@oimdb/react 1.0.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/README.md +496 -0
- package/dist/index.cjs +145 -0
- package/dist/index.d.cts +45 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +109 -0
- package/package.json +48 -0
package/README.md
ADDED
|
@@ -0,0 +1,496 @@
|
|
|
1
|
+
# @oimdb/react
|
|
2
|
+
|
|
3
|
+
React integration for OIMDB - Hooks for selection and subscription with reactive collections and indexes.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
`@oimdb/react` provides React hooks that work with OIMDB reactive objects (`OIMReactiveCollection` and `OIMReactiveIndex`). The library includes both direct hooks for component-level usage and React Context utilities for application-wide data management.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **Reactive Integration**: Hooks work with `OIMReactiveCollection` and `OIMReactiveIndex` from `@oimdb/core`
|
|
12
|
+
- **Automatic Subscription**: Uses `useSyncExternalStore` for optimal React 18+ performance
|
|
13
|
+
- **Event Coalescing**: Leverages OIMDB's built-in event coalescing for efficient updates
|
|
14
|
+
- **Type Safety**: Full TypeScript support with advanced generic type inference
|
|
15
|
+
- **Context Support**: Optional React Context for centralized collection management
|
|
16
|
+
- **Flexible Usage**: Use hooks directly or through context provider pattern
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install @oimdb/react @oimdb/core
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
### Basic Setup
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { OIMEventQueue, OIMRICollection, OIMReactiveIndexManual } from '@oimdb/core';
|
|
30
|
+
import {
|
|
31
|
+
useSelectEntitiesByPks,
|
|
32
|
+
selectEntitiesByIndexKey,
|
|
33
|
+
selectEntityByPk
|
|
34
|
+
} from '@oimdb/react';
|
|
35
|
+
|
|
36
|
+
// Create event queue and reactive collections
|
|
37
|
+
const queue = new OIMEventQueue();
|
|
38
|
+
const userTeamIndex = new OIMReactiveIndexManual<string, string>(queue);
|
|
39
|
+
const usersCollection = new OIMRICollection(queue, {
|
|
40
|
+
collectionOpts: { selectPk: (user: User) => user.id },
|
|
41
|
+
indexes: { byTeam: userTeamIndex },
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Single Entity Selection
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
function UserProfile({ userId }: { userId: string }) {
|
|
49
|
+
const user = selectEntityByPk(usersCollection, userId);
|
|
50
|
+
|
|
51
|
+
if (!user) return <div>Loading...</div>;
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<div>
|
|
55
|
+
<h2>{user.name}</h2>
|
|
56
|
+
<p>Email: {user.email}</p>
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Multiple Entities Selection
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
function UserList({ userIds }: { userIds: string[] }) {
|
|
66
|
+
const users = useSelectEntitiesByPks(usersCollection, userIds);
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<ul>
|
|
70
|
+
{users.map((user, index) => (
|
|
71
|
+
<li key={user?.id || index}>
|
|
72
|
+
{user ? user.name : 'Loading...'}
|
|
73
|
+
</li>
|
|
74
|
+
))}
|
|
75
|
+
</ul>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Index-based Selection
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
function TeamMembers({ teamId }: { teamId: string }) {
|
|
84
|
+
const teamUsers = selectEntitiesByIndexKey(
|
|
85
|
+
usersCollection,
|
|
86
|
+
usersCollection.indexes.byTeam,
|
|
87
|
+
teamId
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<div>
|
|
92
|
+
{teamUsers.map((user, index) => (
|
|
93
|
+
<div key={user?.id || index}>
|
|
94
|
+
{user ? `${user.name} (${user.role})` : 'Loading...'}
|
|
95
|
+
</div>
|
|
96
|
+
))}
|
|
97
|
+
</div>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## React Context Integration
|
|
103
|
+
|
|
104
|
+
For applications with multiple collections, use the React Context pattern for centralized management:
|
|
105
|
+
|
|
106
|
+
### Context Setup
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
import {
|
|
110
|
+
OIMRICollectionsProvider,
|
|
111
|
+
useOIMCollectionsContext,
|
|
112
|
+
StrictCollectionsDictionary
|
|
113
|
+
} from '@oimdb/react';
|
|
114
|
+
|
|
115
|
+
interface User {
|
|
116
|
+
id: string;
|
|
117
|
+
name: string;
|
|
118
|
+
teamId: string;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
interface Team {
|
|
122
|
+
id: string;
|
|
123
|
+
name: string;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function createCollections() {
|
|
127
|
+
const queue = new OIMEventQueue();
|
|
128
|
+
|
|
129
|
+
const userTeamIndex = new OIMReactiveIndexManual<string, string>(queue);
|
|
130
|
+
const usersCollection = new OIMRICollection(queue, {
|
|
131
|
+
collectionOpts: { selectPk: (user: User) => user.id },
|
|
132
|
+
indexes: { byTeam: userTeamIndex },
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
const teamsCollection = new OIMRICollection(queue, {
|
|
136
|
+
collectionOpts: { selectPk: (team: Team) => team.id },
|
|
137
|
+
indexes: {},
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
return { users: usersCollection, teams: teamsCollection } as const;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
type AppCollections = StrictCollectionsDictionary<ReturnType<typeof createCollections>>;
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Provider Setup
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
function App() {
|
|
150
|
+
const collections = React.useMemo(() => createCollections(), []);
|
|
151
|
+
|
|
152
|
+
return (
|
|
153
|
+
<OIMRICollectionsProvider collections={collections}>
|
|
154
|
+
<UserDashboard />
|
|
155
|
+
</OIMRICollectionsProvider>
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Using Context in Components
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
function UserDashboard() {
|
|
164
|
+
const { users, teams } = useOIMCollectionsContext<AppCollections>();
|
|
165
|
+
|
|
166
|
+
// Use collections with hooks
|
|
167
|
+
const allUsers = useSelectEntitiesByPks(users, []);
|
|
168
|
+
const teamMembers = selectEntitiesByIndexKey(
|
|
169
|
+
users,
|
|
170
|
+
users.indexes.byTeam,
|
|
171
|
+
'team1'
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
return (
|
|
175
|
+
<div>
|
|
176
|
+
<h2>All Users: {allUsers.length}</h2>
|
|
177
|
+
<h3>Team 1 Members: {teamMembers.length}</h3>
|
|
178
|
+
</div>
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Custom Context
|
|
184
|
+
|
|
185
|
+
For multiple independent contexts:
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
const UserContext = createOIMCollectionsContext<{ users: typeof usersCollection }>();
|
|
189
|
+
|
|
190
|
+
function UserProvider({ children }: { children: React.ReactNode }) {
|
|
191
|
+
const collections = React.useMemo(() => ({ users: usersCollection }), []);
|
|
192
|
+
|
|
193
|
+
return (
|
|
194
|
+
<OIMRICollectionsProvider collections={collections} context={UserContext}>
|
|
195
|
+
{children}
|
|
196
|
+
</OIMRICollectionsProvider>
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function UserComponent() {
|
|
201
|
+
const { users } = useOIMCollectionsContext(UserContext);
|
|
202
|
+
// Use users collection...
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## API Reference
|
|
207
|
+
|
|
208
|
+
### `selectEntityByPk(reactiveCollection, pk)`
|
|
209
|
+
|
|
210
|
+
Subscribes to a single entity from a reactive collection.
|
|
211
|
+
|
|
212
|
+
**Parameters:**
|
|
213
|
+
- `reactiveCollection: OIMReactiveCollection<TEntity, TPk>` - Reactive collection instance
|
|
214
|
+
- `pk: TPk` - Primary key of the entity
|
|
215
|
+
|
|
216
|
+
**Returns:**
|
|
217
|
+
- `TEntity | undefined` - Entity data or undefined if not found
|
|
218
|
+
|
|
219
|
+
### `useSelectEntitiesByPks(reactiveCollection, pks)`
|
|
220
|
+
|
|
221
|
+
Subscribes to multiple entities from a reactive collection.
|
|
222
|
+
|
|
223
|
+
**Parameters:**
|
|
224
|
+
- `reactiveCollection: OIMReactiveCollection<TEntity, TPk>` - Reactive collection instance
|
|
225
|
+
- `pks: readonly TPk[]` - Array of primary keys
|
|
226
|
+
|
|
227
|
+
**Returns:**
|
|
228
|
+
- `(TEntity | undefined)[]` - Array of entities (undefined for missing entities)
|
|
229
|
+
|
|
230
|
+
### `selectEntitiesByIndexKey(reactiveCollection, reactiveIndex, key)`
|
|
231
|
+
|
|
232
|
+
Subscribes to entities indexed by a specific key.
|
|
233
|
+
|
|
234
|
+
**Parameters:**
|
|
235
|
+
- `reactiveCollection: OIMReactiveCollection<TEntity, TPk>` - Reactive collection instance
|
|
236
|
+
- `reactiveIndex: OIMReactiveIndex<TKey, TPk, TIndex>` - Reactive index instance
|
|
237
|
+
- `key: TKey` - Index key to query
|
|
238
|
+
|
|
239
|
+
**Returns:**
|
|
240
|
+
- `(TEntity | undefined)[]` - Array of entities for the given index key
|
|
241
|
+
|
|
242
|
+
### `selectEntitiesByIndexKeys(reactiveCollection, reactiveIndex, keys)`
|
|
243
|
+
|
|
244
|
+
Subscribes to entities indexed by multiple keys.
|
|
245
|
+
|
|
246
|
+
**Parameters:**
|
|
247
|
+
- `reactiveCollection: OIMReactiveCollection<TEntity, TPk>` - Reactive collection instance
|
|
248
|
+
- `reactiveIndex: OIMReactiveIndex<TKey, TPk, TIndex>` - Reactive index instance
|
|
249
|
+
- `keys: readonly TKey[]` - Array of index keys to query
|
|
250
|
+
|
|
251
|
+
**Returns:**
|
|
252
|
+
- `(TEntity | undefined)[]` - Array of entities for the given index keys
|
|
253
|
+
|
|
254
|
+
### `useSelectPksByIndexKey(reactiveIndex, key)`
|
|
255
|
+
|
|
256
|
+
Subscribes to primary keys indexed by a specific key.
|
|
257
|
+
|
|
258
|
+
**Parameters:**
|
|
259
|
+
- `reactiveIndex: OIMReactiveIndex<TKey, TPk, TIndex>` - Reactive index instance
|
|
260
|
+
- `key: TKey` - Index key to query
|
|
261
|
+
|
|
262
|
+
**Returns:**
|
|
263
|
+
- `TPk[]` - Array of primary keys for the given index key
|
|
264
|
+
|
|
265
|
+
### `useSelectPksByIndexKeys(reactiveIndex, keys)`
|
|
266
|
+
|
|
267
|
+
Subscribes to primary keys indexed by multiple keys.
|
|
268
|
+
|
|
269
|
+
**Parameters:**
|
|
270
|
+
- `reactiveIndex: OIMReactiveIndex<TKey, TPk, TIndex>` - Reactive index instance
|
|
271
|
+
- `keys: readonly TKey[]` - Array of index keys to query
|
|
272
|
+
|
|
273
|
+
**Returns:**
|
|
274
|
+
- `Map<TKey, TPk[]>` - Map of index keys to their corresponding primary keys
|
|
275
|
+
|
|
276
|
+
## Context API Reference
|
|
277
|
+
|
|
278
|
+
### `OIMRICollectionsProvider<T>`
|
|
279
|
+
|
|
280
|
+
Provider component for collections context.
|
|
281
|
+
|
|
282
|
+
**Props:**
|
|
283
|
+
- `collections: T` - Dictionary of reactive collections
|
|
284
|
+
- `children: ReactNode` - React children
|
|
285
|
+
- `context?: React.Context<OIMContextValue<T>>` - Optional custom context
|
|
286
|
+
|
|
287
|
+
### `useOIMCollectionsContext<T>(context?)`
|
|
288
|
+
|
|
289
|
+
Hook to access collections from context.
|
|
290
|
+
|
|
291
|
+
**Parameters:**
|
|
292
|
+
- `context?: React.Context<OIMContextValue<T>>` - Optional custom context
|
|
293
|
+
|
|
294
|
+
**Returns:**
|
|
295
|
+
- `T` - Collections dictionary with full type safety
|
|
296
|
+
|
|
297
|
+
**Throws:**
|
|
298
|
+
- Error if used outside of provider
|
|
299
|
+
|
|
300
|
+
### `createOIMCollectionsContext<T>()`
|
|
301
|
+
|
|
302
|
+
Creates a custom collections context with specific typing.
|
|
303
|
+
|
|
304
|
+
**Returns:**
|
|
305
|
+
- `React.Context<OIMContextValue<T>>` - Typed React context
|
|
306
|
+
|
|
307
|
+
### Type Utilities
|
|
308
|
+
|
|
309
|
+
#### `StrictCollectionsDictionary<T>`
|
|
310
|
+
|
|
311
|
+
Ensures collections dictionary maintains exact types.
|
|
312
|
+
|
|
313
|
+
#### `CollectionsDictionary`
|
|
314
|
+
|
|
315
|
+
Base type for any collections dictionary.
|
|
316
|
+
|
|
317
|
+
#### `ExtractEntityType<T>`, `ExtractPkType<T>`, etc.
|
|
318
|
+
|
|
319
|
+
Type utilities for extracting specific types from collections.
|
|
320
|
+
|
|
321
|
+
## Architecture
|
|
322
|
+
|
|
323
|
+
### Reactive Collections Integration
|
|
324
|
+
|
|
325
|
+
The hooks work directly with OIMDB reactive objects:
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
// Use reactive collections and indexes directly
|
|
329
|
+
const user = selectEntityByPk(reactiveCollection, 'user123');
|
|
330
|
+
const posts = selectEntitiesByIndexKey(reactiveCollection, reactiveIndex, 'tech');
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Event Subscription
|
|
334
|
+
|
|
335
|
+
Hooks automatically subscribe to OIMDB reactive events using `useSyncExternalStore`:
|
|
336
|
+
|
|
337
|
+
- **Collection updates**: Subscribe to `reactiveCollection.updateEventEmitter`
|
|
338
|
+
- **Index updates**: Subscribe to `reactiveIndex.updateEventEmitter`
|
|
339
|
+
- **Optimized subscriptions**: Subscribe only to specific keys for efficient updates
|
|
340
|
+
- **Automatic cleanup**: Unsubscribe when component unmounts
|
|
341
|
+
|
|
342
|
+
### Performance
|
|
343
|
+
|
|
344
|
+
- **React 18+ Integration**: Uses `useSyncExternalStore` for optimal performance
|
|
345
|
+
- **Event Coalescing**: OIMDB's built-in event coalescing reduces unnecessary re-renders
|
|
346
|
+
- **Key-specific subscriptions**: Only listen to changes for relevant data
|
|
347
|
+
- **Memory Management**: Automatic cleanup prevents memory leaks
|
|
348
|
+
- **Efficient batching**: Updates are batched through React's concurrent features
|
|
349
|
+
|
|
350
|
+
## Examples
|
|
351
|
+
|
|
352
|
+
### Complete Example
|
|
353
|
+
|
|
354
|
+
```typescript
|
|
355
|
+
import React from 'react';
|
|
356
|
+
import { OIMEventQueue, OIMRICollection, OIMReactiveIndexManual } from '@oimdb/core';
|
|
357
|
+
import { selectEntityByPk, useSelectEntitiesByPks, selectEntitiesByIndexKey } from '@oimdb/react';
|
|
358
|
+
|
|
359
|
+
interface User {
|
|
360
|
+
id: string;
|
|
361
|
+
name: string;
|
|
362
|
+
email: string;
|
|
363
|
+
teamId: string;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// Setup
|
|
367
|
+
function createUserCollection() {
|
|
368
|
+
const queue = new OIMEventQueue();
|
|
369
|
+
const teamIndex = new OIMReactiveIndexManual<string, string>(queue);
|
|
370
|
+
|
|
371
|
+
return new OIMRICollection(queue, {
|
|
372
|
+
collectionOpts: { selectPk: (user: User) => user.id },
|
|
373
|
+
indexes: { byTeam: teamIndex },
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
const usersCollection = createUserCollection();
|
|
378
|
+
|
|
379
|
+
// Component
|
|
380
|
+
function UserProfile({ userId }: { userId: string }) {
|
|
381
|
+
const user = selectEntityByPk(usersCollection, userId);
|
|
382
|
+
|
|
383
|
+
if (!user) return <div>Loading...</div>;
|
|
384
|
+
|
|
385
|
+
return <h2>{user.name}</h2>;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
function TeamDashboard({ teamId }: { teamId: string }) {
|
|
389
|
+
const teamMembers = selectEntitiesByIndexKey(
|
|
390
|
+
usersCollection,
|
|
391
|
+
usersCollection.indexes.byTeam,
|
|
392
|
+
teamId
|
|
393
|
+
);
|
|
394
|
+
|
|
395
|
+
return (
|
|
396
|
+
<div>
|
|
397
|
+
<h3>Team Members ({teamMembers.length})</h3>
|
|
398
|
+
{teamMembers.map(user => (
|
|
399
|
+
<div key={user.id}>{user.name}</div>
|
|
400
|
+
))}
|
|
401
|
+
</div>
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
### With Context Provider
|
|
407
|
+
|
|
408
|
+
```typescript
|
|
409
|
+
import {
|
|
410
|
+
OIMRICollectionsProvider,
|
|
411
|
+
useOIMCollectionsContext
|
|
412
|
+
} from '@oimdb/react';
|
|
413
|
+
|
|
414
|
+
function App() {
|
|
415
|
+
const collections = React.useMemo(() => ({
|
|
416
|
+
users: createUserCollection(),
|
|
417
|
+
// ... other collections
|
|
418
|
+
}), []);
|
|
419
|
+
|
|
420
|
+
return (
|
|
421
|
+
<OIMRICollectionsProvider collections={collections}>
|
|
422
|
+
<Dashboard />
|
|
423
|
+
</OIMRICollectionsProvider>
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
function Dashboard() {
|
|
428
|
+
const { users } = useOIMCollectionsContext();
|
|
429
|
+
const allUsers = useSelectEntitiesByPks(users, []);
|
|
430
|
+
|
|
431
|
+
return <div>Total Users: {allUsers.length}</div>;
|
|
432
|
+
}
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
## Migration from v0.x
|
|
436
|
+
|
|
437
|
+
The v1.x API has changed significantly to work with reactive collections:
|
|
438
|
+
|
|
439
|
+
### Hook Name Changes
|
|
440
|
+
|
|
441
|
+
```typescript
|
|
442
|
+
// v0.x - Abstract storage interfaces
|
|
443
|
+
const user = useEntity(userStorage, 'user123');
|
|
444
|
+
const users = useEntities(userStorage, userIds);
|
|
445
|
+
const posts = useIndex(postStorage, categoryIndex, 'tech');
|
|
446
|
+
|
|
447
|
+
// v1.x - Reactive collections
|
|
448
|
+
const user = selectEntityByPk(reactiveCollection, 'user123');
|
|
449
|
+
const users = useSelectEntitiesByPks(reactiveCollection, userIds);
|
|
450
|
+
const posts = selectEntitiesByIndexKey(reactiveCollection, reactiveIndex, 'tech');
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
### Collection Creation
|
|
454
|
+
|
|
455
|
+
```typescript
|
|
456
|
+
// v0.x - With DX layer
|
|
457
|
+
const db = createDb({ scheduler: 'microtask' });
|
|
458
|
+
const users = db.createCollection<User>();
|
|
459
|
+
const user = useEntity(users.advanced.collection, userId);
|
|
460
|
+
|
|
461
|
+
// v1.x - Direct reactive collections
|
|
462
|
+
const queue = new OIMEventQueue();
|
|
463
|
+
const usersCollection = new OIMRICollection(queue, {
|
|
464
|
+
collectionOpts: { selectPk: (user: User) => user.id },
|
|
465
|
+
indexes: {},
|
|
466
|
+
});
|
|
467
|
+
const user = selectEntityByPk(usersCollection, userId);
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
### Context API
|
|
471
|
+
|
|
472
|
+
```typescript
|
|
473
|
+
// v0.x - No context support
|
|
474
|
+
|
|
475
|
+
// v1.x - Full context support
|
|
476
|
+
const collections = { users: usersCollection };
|
|
477
|
+
<OIMRICollectionsProvider collections={collections}>
|
|
478
|
+
<App />
|
|
479
|
+
</OIMRICollectionsProvider>
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
### Key Changes
|
|
483
|
+
|
|
484
|
+
- **Hook naming**: More explicit names like `selectEntityByPk` vs `useEntity`
|
|
485
|
+
- **Parameters**: Direct reactive collection objects instead of storage abstractions
|
|
486
|
+
- **Context**: New context API for centralized collection management
|
|
487
|
+
- **Type safety**: Enhanced TypeScript support with better inference
|
|
488
|
+
|
|
489
|
+
## Dependencies
|
|
490
|
+
|
|
491
|
+
- `@oimdb/core` - Core OIMDB functionality
|
|
492
|
+
- `react` - React hooks and components
|
|
493
|
+
|
|
494
|
+
## License
|
|
495
|
+
|
|
496
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
OIMRICollectionsContext: () => OIMRICollectionsContext,
|
|
24
|
+
OIMRICollectionsProvider: () => OIMRICollectionsProvider,
|
|
25
|
+
createOIMCollectionsContext: () => createOIMCollectionsContext,
|
|
26
|
+
selectEntitiesByIndexKey: () => selectEntitiesByIndexKey,
|
|
27
|
+
selectEntitiesByIndexKeys: () => selectEntitiesByIndexKeys,
|
|
28
|
+
selectEntityByPk: () => selectEntityByPk,
|
|
29
|
+
useOIMCollectionsContext: () => useOIMCollectionsContext,
|
|
30
|
+
useSelectEntitiesByPks: () => useSelectEntitiesByPks,
|
|
31
|
+
useSelectPksByIndexKey: () => useSelectPksByIndexKey,
|
|
32
|
+
useSelectPksByIndexKeys: () => useSelectPksByIndexKeys
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(index_exports);
|
|
35
|
+
|
|
36
|
+
// src/hooks/index.ts
|
|
37
|
+
var import_react = require("react");
|
|
38
|
+
var import_react2 = require("react");
|
|
39
|
+
var useSelectPksByIndexKeys = (reactiveIndex, keys) => {
|
|
40
|
+
const subscribe = (0, import_react.useMemo)(() => {
|
|
41
|
+
return (onStoreChange) => reactiveIndex.updateEventEmitter.subscribeOnKeys(
|
|
42
|
+
keys,
|
|
43
|
+
onStoreChange
|
|
44
|
+
);
|
|
45
|
+
}, [keys, reactiveIndex.updateEventEmitter]);
|
|
46
|
+
const getSnapshot = (0, import_react.useMemo)(
|
|
47
|
+
() => () => keys.map((key) => reactiveIndex.getPksByKey(key)),
|
|
48
|
+
[keys, reactiveIndex]
|
|
49
|
+
);
|
|
50
|
+
const snapshot = (0, import_react2.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
51
|
+
return snapshot;
|
|
52
|
+
};
|
|
53
|
+
var useSelectPksByIndexKey = (reactiveIndex, key) => {
|
|
54
|
+
const subscribe = (0, import_react.useMemo)(() => {
|
|
55
|
+
return (onStoreChange) => reactiveIndex.updateEventEmitter.subscribeOnKey(key, onStoreChange);
|
|
56
|
+
}, [key, reactiveIndex.updateEventEmitter]);
|
|
57
|
+
const getSnapshot = (0, import_react.useMemo)(
|
|
58
|
+
() => () => reactiveIndex.getPksByKey(key),
|
|
59
|
+
[key, reactiveIndex]
|
|
60
|
+
);
|
|
61
|
+
const snapshot = (0, import_react2.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
62
|
+
return snapshot;
|
|
63
|
+
};
|
|
64
|
+
var selectEntityByPk = (reactiveCollection, pk) => {
|
|
65
|
+
const subscribe = (0, import_react.useMemo)(() => {
|
|
66
|
+
return (onStoreChange) => reactiveCollection.updateEventEmitter.subscribeOnKey(
|
|
67
|
+
pk,
|
|
68
|
+
onStoreChange
|
|
69
|
+
);
|
|
70
|
+
}, [pk, reactiveCollection.updateEventEmitter]);
|
|
71
|
+
const getSnapshot = (0, import_react.useMemo)(
|
|
72
|
+
() => () => reactiveCollection.getOneByPk(pk),
|
|
73
|
+
[pk, reactiveCollection]
|
|
74
|
+
);
|
|
75
|
+
const snapshot = (0, import_react2.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
76
|
+
return snapshot;
|
|
77
|
+
};
|
|
78
|
+
var useSelectEntitiesByPks = (reactiveCollection, pks) => {
|
|
79
|
+
const subscribe = (0, import_react.useMemo)(() => {
|
|
80
|
+
return (onStoreChange) => reactiveCollection.updateEventEmitter.subscribeOnKeys(
|
|
81
|
+
pks,
|
|
82
|
+
onStoreChange
|
|
83
|
+
);
|
|
84
|
+
}, [pks, reactiveCollection.updateEventEmitter]);
|
|
85
|
+
const getSnapshot = (0, import_react.useMemo)(
|
|
86
|
+
() => () => pks.map((pk) => reactiveCollection.getOneByPk(pk)),
|
|
87
|
+
[pks, reactiveCollection]
|
|
88
|
+
);
|
|
89
|
+
const snapshot = (0, import_react2.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
90
|
+
return snapshot;
|
|
91
|
+
};
|
|
92
|
+
var selectEntitiesByIndexKey = (reactiveCollection, reactiveIndex, key) => {
|
|
93
|
+
const pks = useSelectPksByIndexKey(reactiveIndex, key);
|
|
94
|
+
return useSelectEntitiesByPks(reactiveCollection, pks);
|
|
95
|
+
};
|
|
96
|
+
var unique = (array) => {
|
|
97
|
+
return Array.from(new Set(array));
|
|
98
|
+
};
|
|
99
|
+
var selectEntitiesByIndexKeys = (reactiveCollection, reactiveIndex, keys) => {
|
|
100
|
+
const pks = useSelectPksByIndexKeys(reactiveIndex, keys);
|
|
101
|
+
const pksArray = (0, import_react.useMemo)(
|
|
102
|
+
() => unique(Array.from(pks.values()).flat()),
|
|
103
|
+
[pks]
|
|
104
|
+
);
|
|
105
|
+
return useSelectEntitiesByPks(reactiveCollection, pksArray);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
// src/context/index.tsx
|
|
109
|
+
var import_react3 = require("react");
|
|
110
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
111
|
+
var OIMRICollectionsContext = (0, import_react3.createContext)(null);
|
|
112
|
+
function createOIMCollectionsContext() {
|
|
113
|
+
return (0, import_react3.createContext)(null);
|
|
114
|
+
}
|
|
115
|
+
function OIMRICollectionsProvider({
|
|
116
|
+
collections,
|
|
117
|
+
children,
|
|
118
|
+
context = OIMRICollectionsContext
|
|
119
|
+
}) {
|
|
120
|
+
const Provider = context.Provider;
|
|
121
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Provider, { value: collections, children });
|
|
122
|
+
}
|
|
123
|
+
function useOIMCollectionsContext(context) {
|
|
124
|
+
const contextToUse = context || OIMRICollectionsContext;
|
|
125
|
+
const collections = (0, import_react3.useContext)(contextToUse);
|
|
126
|
+
if (!collections) {
|
|
127
|
+
throw new Error(
|
|
128
|
+
"useOIMCollectionsContext must be used within an OIMRICollectionsProvider"
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
return collections;
|
|
132
|
+
}
|
|
133
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
134
|
+
0 && (module.exports = {
|
|
135
|
+
OIMRICollectionsContext,
|
|
136
|
+
OIMRICollectionsProvider,
|
|
137
|
+
createOIMCollectionsContext,
|
|
138
|
+
selectEntitiesByIndexKey,
|
|
139
|
+
selectEntitiesByIndexKeys,
|
|
140
|
+
selectEntityByPk,
|
|
141
|
+
useOIMCollectionsContext,
|
|
142
|
+
useSelectEntitiesByPks,
|
|
143
|
+
useSelectPksByIndexKey,
|
|
144
|
+
useSelectPksByIndexKeys
|
|
145
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { TOIMPk, OIMIndex, OIMReactiveIndex, OIMReactiveCollection, OIMRICollection } from '@oimdb/core';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { ReactNode } from 'react';
|
|
5
|
+
|
|
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[])[];
|
|
7
|
+
declare const useSelectPksByIndexKey: <TPk extends TOIMPk, TKey extends TOIMPk, TIndex extends OIMIndex<TKey, TPk>>(reactiveIndex: OIMReactiveIndex<TKey, TPk, TIndex>, key: TKey) => readonly TPk[];
|
|
8
|
+
declare const selectEntityByPk: <TEntity extends object, TPk extends TOIMPk>(reactiveCollection: OIMReactiveCollection<TEntity, TPk>, pk: TPk) => TEntity | undefined;
|
|
9
|
+
declare const useSelectEntitiesByPks: <TEntity extends object, TPk extends TOIMPk>(reactiveCollection: OIMReactiveCollection<TEntity, TPk>, pks: readonly TPk[]) => (TEntity | undefined)[];
|
|
10
|
+
declare const selectEntitiesByIndexKey: <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) => (TEntity | undefined)[];
|
|
11
|
+
declare const selectEntitiesByIndexKeys: <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[]) => (TEntity | undefined)[];
|
|
12
|
+
|
|
13
|
+
type AnyOIMRICollection = OIMRICollection<object, TOIMPk, string, TOIMPk, any, any>;
|
|
14
|
+
type CollectionsDictionary = Record<string, AnyOIMRICollection>;
|
|
15
|
+
type TypedCollectionsDictionary<T extends CollectionsDictionary> = T;
|
|
16
|
+
type OIMContextValue<T extends CollectionsDictionary = CollectionsDictionary> = T | null;
|
|
17
|
+
declare const OIMRICollectionsContext: React.Context<OIMContextValue<CollectionsDictionary>>;
|
|
18
|
+
declare function createOIMCollectionsContext<T extends CollectionsDictionary>(): React.Context<OIMContextValue<T>>;
|
|
19
|
+
interface OIMRICollectionsProviderProps<T extends CollectionsDictionary> {
|
|
20
|
+
collections: T;
|
|
21
|
+
children: ReactNode;
|
|
22
|
+
context?: React.Context<OIMContextValue<T>>;
|
|
23
|
+
}
|
|
24
|
+
declare function OIMRICollectionsProvider<T extends CollectionsDictionary>({ collections, children, context, }: OIMRICollectionsProviderProps<T>): react_jsx_runtime.JSX.Element;
|
|
25
|
+
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
|
+
|
|
45
|
+
export { type AnyOIMRICollection, type CollectionsDictionary, type CreateCollectionsDictionary, type ExtractCollectionSignature, type ExtractEntityType, type ExtractIndexKeyType, type ExtractIndexNameType, type ExtractPkType, type OIMContextValue, OIMRICollectionsContext, OIMRICollectionsProvider, type OIMRICollectionsProviderProps, type StrictCollectionsDictionary, type TypedCollectionsDictionary, createOIMCollectionsContext, selectEntitiesByIndexKey, selectEntitiesByIndexKeys, selectEntityByPk, useOIMCollectionsContext, useSelectEntitiesByPks, useSelectPksByIndexKey, useSelectPksByIndexKeys };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { TOIMPk, OIMIndex, OIMReactiveIndex, OIMReactiveCollection, OIMRICollection } from '@oimdb/core';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { ReactNode } from 'react';
|
|
5
|
+
|
|
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[])[];
|
|
7
|
+
declare const useSelectPksByIndexKey: <TPk extends TOIMPk, TKey extends TOIMPk, TIndex extends OIMIndex<TKey, TPk>>(reactiveIndex: OIMReactiveIndex<TKey, TPk, TIndex>, key: TKey) => readonly TPk[];
|
|
8
|
+
declare const selectEntityByPk: <TEntity extends object, TPk extends TOIMPk>(reactiveCollection: OIMReactiveCollection<TEntity, TPk>, pk: TPk) => TEntity | undefined;
|
|
9
|
+
declare const useSelectEntitiesByPks: <TEntity extends object, TPk extends TOIMPk>(reactiveCollection: OIMReactiveCollection<TEntity, TPk>, pks: readonly TPk[]) => (TEntity | undefined)[];
|
|
10
|
+
declare const selectEntitiesByIndexKey: <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) => (TEntity | undefined)[];
|
|
11
|
+
declare const selectEntitiesByIndexKeys: <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[]) => (TEntity | undefined)[];
|
|
12
|
+
|
|
13
|
+
type AnyOIMRICollection = OIMRICollection<object, TOIMPk, string, TOIMPk, any, any>;
|
|
14
|
+
type CollectionsDictionary = Record<string, AnyOIMRICollection>;
|
|
15
|
+
type TypedCollectionsDictionary<T extends CollectionsDictionary> = T;
|
|
16
|
+
type OIMContextValue<T extends CollectionsDictionary = CollectionsDictionary> = T | null;
|
|
17
|
+
declare const OIMRICollectionsContext: React.Context<OIMContextValue<CollectionsDictionary>>;
|
|
18
|
+
declare function createOIMCollectionsContext<T extends CollectionsDictionary>(): React.Context<OIMContextValue<T>>;
|
|
19
|
+
interface OIMRICollectionsProviderProps<T extends CollectionsDictionary> {
|
|
20
|
+
collections: T;
|
|
21
|
+
children: ReactNode;
|
|
22
|
+
context?: React.Context<OIMContextValue<T>>;
|
|
23
|
+
}
|
|
24
|
+
declare function OIMRICollectionsProvider<T extends CollectionsDictionary>({ collections, children, context, }: OIMRICollectionsProviderProps<T>): react_jsx_runtime.JSX.Element;
|
|
25
|
+
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
|
+
|
|
45
|
+
export { type AnyOIMRICollection, type CollectionsDictionary, type CreateCollectionsDictionary, type ExtractCollectionSignature, type ExtractEntityType, type ExtractIndexKeyType, type ExtractIndexNameType, type ExtractPkType, type OIMContextValue, OIMRICollectionsContext, OIMRICollectionsProvider, type OIMRICollectionsProviderProps, type StrictCollectionsDictionary, type TypedCollectionsDictionary, createOIMCollectionsContext, selectEntitiesByIndexKey, selectEntitiesByIndexKeys, selectEntityByPk, useOIMCollectionsContext, useSelectEntitiesByPks, useSelectPksByIndexKey, useSelectPksByIndexKeys };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// src/hooks/index.ts
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
import { useSyncExternalStore } from "react";
|
|
4
|
+
var useSelectPksByIndexKeys = (reactiveIndex, keys) => {
|
|
5
|
+
const subscribe = useMemo(() => {
|
|
6
|
+
return (onStoreChange) => reactiveIndex.updateEventEmitter.subscribeOnKeys(
|
|
7
|
+
keys,
|
|
8
|
+
onStoreChange
|
|
9
|
+
);
|
|
10
|
+
}, [keys, reactiveIndex.updateEventEmitter]);
|
|
11
|
+
const getSnapshot = useMemo(
|
|
12
|
+
() => () => keys.map((key) => reactiveIndex.getPksByKey(key)),
|
|
13
|
+
[keys, reactiveIndex]
|
|
14
|
+
);
|
|
15
|
+
const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
16
|
+
return snapshot;
|
|
17
|
+
};
|
|
18
|
+
var useSelectPksByIndexKey = (reactiveIndex, key) => {
|
|
19
|
+
const subscribe = useMemo(() => {
|
|
20
|
+
return (onStoreChange) => reactiveIndex.updateEventEmitter.subscribeOnKey(key, onStoreChange);
|
|
21
|
+
}, [key, reactiveIndex.updateEventEmitter]);
|
|
22
|
+
const getSnapshot = useMemo(
|
|
23
|
+
() => () => reactiveIndex.getPksByKey(key),
|
|
24
|
+
[key, reactiveIndex]
|
|
25
|
+
);
|
|
26
|
+
const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
27
|
+
return snapshot;
|
|
28
|
+
};
|
|
29
|
+
var selectEntityByPk = (reactiveCollection, pk) => {
|
|
30
|
+
const subscribe = useMemo(() => {
|
|
31
|
+
return (onStoreChange) => reactiveCollection.updateEventEmitter.subscribeOnKey(
|
|
32
|
+
pk,
|
|
33
|
+
onStoreChange
|
|
34
|
+
);
|
|
35
|
+
}, [pk, reactiveCollection.updateEventEmitter]);
|
|
36
|
+
const getSnapshot = useMemo(
|
|
37
|
+
() => () => reactiveCollection.getOneByPk(pk),
|
|
38
|
+
[pk, reactiveCollection]
|
|
39
|
+
);
|
|
40
|
+
const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
41
|
+
return snapshot;
|
|
42
|
+
};
|
|
43
|
+
var useSelectEntitiesByPks = (reactiveCollection, pks) => {
|
|
44
|
+
const subscribe = useMemo(() => {
|
|
45
|
+
return (onStoreChange) => reactiveCollection.updateEventEmitter.subscribeOnKeys(
|
|
46
|
+
pks,
|
|
47
|
+
onStoreChange
|
|
48
|
+
);
|
|
49
|
+
}, [pks, reactiveCollection.updateEventEmitter]);
|
|
50
|
+
const getSnapshot = useMemo(
|
|
51
|
+
() => () => pks.map((pk) => reactiveCollection.getOneByPk(pk)),
|
|
52
|
+
[pks, reactiveCollection]
|
|
53
|
+
);
|
|
54
|
+
const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
55
|
+
return snapshot;
|
|
56
|
+
};
|
|
57
|
+
var selectEntitiesByIndexKey = (reactiveCollection, reactiveIndex, key) => {
|
|
58
|
+
const pks = useSelectPksByIndexKey(reactiveIndex, key);
|
|
59
|
+
return useSelectEntitiesByPks(reactiveCollection, pks);
|
|
60
|
+
};
|
|
61
|
+
var unique = (array) => {
|
|
62
|
+
return Array.from(new Set(array));
|
|
63
|
+
};
|
|
64
|
+
var selectEntitiesByIndexKeys = (reactiveCollection, reactiveIndex, keys) => {
|
|
65
|
+
const pks = useSelectPksByIndexKeys(reactiveIndex, keys);
|
|
66
|
+
const pksArray = useMemo(
|
|
67
|
+
() => unique(Array.from(pks.values()).flat()),
|
|
68
|
+
[pks]
|
|
69
|
+
);
|
|
70
|
+
return useSelectEntitiesByPks(reactiveCollection, pksArray);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
// src/context/index.tsx
|
|
74
|
+
import { createContext, useContext } from "react";
|
|
75
|
+
import { jsx } from "react/jsx-runtime";
|
|
76
|
+
var OIMRICollectionsContext = createContext(null);
|
|
77
|
+
function createOIMCollectionsContext() {
|
|
78
|
+
return createContext(null);
|
|
79
|
+
}
|
|
80
|
+
function OIMRICollectionsProvider({
|
|
81
|
+
collections,
|
|
82
|
+
children,
|
|
83
|
+
context = OIMRICollectionsContext
|
|
84
|
+
}) {
|
|
85
|
+
const Provider = context.Provider;
|
|
86
|
+
return /* @__PURE__ */ jsx(Provider, { value: collections, children });
|
|
87
|
+
}
|
|
88
|
+
function useOIMCollectionsContext(context) {
|
|
89
|
+
const contextToUse = context || OIMRICollectionsContext;
|
|
90
|
+
const collections = useContext(contextToUse);
|
|
91
|
+
if (!collections) {
|
|
92
|
+
throw new Error(
|
|
93
|
+
"useOIMCollectionsContext must be used within an OIMRICollectionsProvider"
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
return collections;
|
|
97
|
+
}
|
|
98
|
+
export {
|
|
99
|
+
OIMRICollectionsContext,
|
|
100
|
+
OIMRICollectionsProvider,
|
|
101
|
+
createOIMCollectionsContext,
|
|
102
|
+
selectEntitiesByIndexKey,
|
|
103
|
+
selectEntitiesByIndexKeys,
|
|
104
|
+
selectEntityByPk,
|
|
105
|
+
useOIMCollectionsContext,
|
|
106
|
+
useSelectEntitiesByPks,
|
|
107
|
+
useSelectPksByIndexKey,
|
|
108
|
+
useSelectPksByIndexKeys
|
|
109
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@oimdb/react",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "React integration for OIMDB - Hooks for selection and subscription with external storage",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"sideEffects": false,
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/abaikov/oimdb.git"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/abaikov/oimdb/issues"
|
|
16
|
+
},
|
|
17
|
+
"homepage": "https://github.com/abaikov/oimdb#readme",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"import": "./dist/index.js",
|
|
22
|
+
"require": "./dist/index.cjs"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsup src/index.ts --dts --format esm,cjs",
|
|
27
|
+
"clean": "rimraf dist"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist"
|
|
31
|
+
],
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@oimdb/core": "^1.0.0"
|
|
34
|
+
},
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"@oimdb/core": "^1.0.0",
|
|
37
|
+
"react": "^18.0.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"tsup": "^8.5.0",
|
|
41
|
+
"typescript": "^5.2.2",
|
|
42
|
+
"rimraf": "^5.0.5",
|
|
43
|
+
"react": "^18.0.0",
|
|
44
|
+
"@types/react": "^18.0.0"
|
|
45
|
+
},
|
|
46
|
+
"author": "Andrei Baikov",
|
|
47
|
+
"license": "MIT"
|
|
48
|
+
}
|