@oimdb/react 1.1.0 → 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 CHANGED
@@ -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 = StrictCollectionsDictionary<ReturnType<typeof createCollections>>;
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
@@ -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
 
package/dist/index.d.cts CHANGED
@@ -10,9 +10,7 @@ declare const useSelectEntitiesByPks: <TEntity extends object, TPk extends TOIMP
10
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
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 AnyOIMRICollection = OIMRICollection<object, TOIMPk, string, TOIMPk, any, any>;
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 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, useOIMCollectionsContext, useSelectEntitiesByIndexKey, useSelectEntitiesByIndexKeys, useSelectEntitiesByPks, useSelectEntityByPk, useSelectPksByIndexKey, useSelectPksByIndexKeys };
25
+ export { type CollectionsDictionary, type OIMContextValue, OIMRICollectionsContext, OIMRICollectionsProvider, type OIMRICollectionsProviderProps, createOIMCollectionsContext, useOIMCollectionsContext, useSelectEntitiesByIndexKey, useSelectEntitiesByIndexKeys, useSelectEntitiesByPks, useSelectEntityByPk, useSelectPksByIndexKey, useSelectPksByIndexKeys };
package/dist/index.d.ts CHANGED
@@ -10,9 +10,7 @@ declare const useSelectEntitiesByPks: <TEntity extends object, TPk extends TOIMP
10
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
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 AnyOIMRICollection = OIMRICollection<object, TOIMPk, string, TOIMPk, any, any>;
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 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, useOIMCollectionsContext, useSelectEntitiesByIndexKey, useSelectEntitiesByIndexKeys, useSelectEntitiesByPks, useSelectEntityByPk, useSelectPksByIndexKey, useSelectPksByIndexKeys };
25
+ export { type CollectionsDictionary, type OIMContextValue, OIMRICollectionsContext, OIMRICollectionsProvider, type OIMRICollectionsProviderProps, createOIMCollectionsContext, useOIMCollectionsContext, useSelectEntitiesByIndexKey, useSelectEntitiesByIndexKeys, useSelectEntitiesByPks, useSelectEntityByPk, useSelectPksByIndexKey, useSelectPksByIndexKeys };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oimdb/react",
3
- "version": "1.1.0",
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.6",
36
+ "@oimdb/core": "^1.1.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
+ "@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
- "@types/react": "^18.0.0"
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"