@oimdb/core 3.0.0 → 3.1.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.cjs +405 -364
- package/dist/index.d.cts +110 -68
- package/dist/index.d.ts +110 -68
- package/dist/index.js +405 -364
- package/llms.txt +30 -2
- package/package.json +1 -1
package/llms.txt
CHANGED
|
@@ -11,7 +11,7 @@ OIMDB is a TypeScript in-memory reactive database. It stores entities in typed c
|
|
|
11
11
|
| Package | Purpose |
|
|
12
12
|
|---|---|
|
|
13
13
|
| `@oimdb/core` | Collections, indexes, event queue, reactive primitives |
|
|
14
|
-
| `@oimdb/persist` |
|
|
14
|
+
| `@oimdb/persist` | Storage-agnostic persist/hydrate engine (source adapters, resources, versioned codec). Backends ship separately: `@oimdb/persist-memory`, `-localstorage`, `-idb`, `-async-kv`, `-json` |
|
|
15
15
|
| `@oimdb/react` | React hooks for collections and selectors |
|
|
16
16
|
| `@oimdb/async` | Async-aware reactive collection and index variants |
|
|
17
17
|
| `@oimdb/devtools` | Debug registry: name collections/indexes/computeds, inspect runtime state |
|
|
@@ -78,6 +78,12 @@ byRole.subscribeOnKey('admin', () => {
|
|
|
78
78
|
queue.flush(); // delivers subscription
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
+
Membership writes are incremental (touch only the changed pks):
|
|
82
|
+
- `addPks(key, pks)` / `removePks(key, pks)` — **set-based**: O(1) per pk for both. **array-based**: `addPks` O(1), `removePks` O(bucket) (ordered, must scan).
|
|
83
|
+
- For frequently changing membership (e.g. a **virtual/windowed list** indexing the on-screen rows, adding/removing on scroll) prefer **set-based**.
|
|
84
|
+
- `setPks` / `addPks` resolve each pk → slot (O(1) lookup); if you already hold slots (`collection.upsertMany` returns them) use `setSlots` / `appendSlots` to skip the lookup.
|
|
85
|
+
- `getEntitiesByKey(key)` returns `(TEntity | undefined)[]` — positional holes for not-yet-loaded pks, aligned with `getPksByKey` (not dropped), so you can render a loading state.
|
|
86
|
+
|
|
81
87
|
### DX Layer — Collection Model
|
|
82
88
|
|
|
83
89
|
`createOIMCollectionKit` wires queue + collection + index factory + selectors together.
|
|
@@ -210,10 +216,32 @@ const { users } = useOIMCollectionsContext<AppCollections>();
|
|
|
210
216
|
| `useSelectValueByObjectKey(object, key)` | One key from `OIMReactiveObject` |
|
|
211
217
|
| `useSelectValuesByObjectKeys(object, keys)` | Multiple keys from `OIMReactiveObject` |
|
|
212
218
|
|
|
219
|
+
All hooks above use `useSyncExternalStore` (Concurrent-safe; detect change by `Object.is` reference).
|
|
220
|
+
|
|
221
|
+
### Mutable mode + signal hooks (advanced, opt-in)
|
|
222
|
+
|
|
223
|
+
For update-heavy / fine-grained UIs, run a collection **in place** (no per-update object copy) and bind with the lighter **signal hooks** (re-render on the keyed notification, no `useSyncExternalStore`, no `Object.is`):
|
|
224
|
+
|
|
225
|
+
```ts
|
|
226
|
+
import { OIMReactiveCollection, createInPlaceEntityUpdater } from '@oimdb/core';
|
|
227
|
+
import { useSelectEntityByPkSignal, useSelectPksByIndexKeyArrayBasedSignal } from '@oimdb/react';
|
|
228
|
+
|
|
229
|
+
const cards = new OIMReactiveCollection(queue, {
|
|
230
|
+
selectPk: c => c.id,
|
|
231
|
+
updateEntity: createInPlaceEntityUpdater(), // mutate in place, no allocation
|
|
232
|
+
});
|
|
233
|
+
const card = useSelectEntityByPkSignal(cards, id); // sees in-place mutations (uSES would miss them)
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Signal hooks: `useSelectEntityByPkSignal(collection, pk)`, `useSelectPksByIndexKeyArrayBasedSignal(index, key)`, `useSelectPksByIndexKeySetBasedSignal(index, key)`. Use the fine-grained pattern (parent reads pks by index key; each row reads its own entity by pk).
|
|
237
|
+
|
|
238
|
+
Trade-offs (use only when every reader is subscription-driven): NOT Concurrent-safe; the entity reference is stable across changes, so `React.memo` on entities, prev/next diffing, time-travel, and the default uSES hooks on the same collection won't see updates. Default to the standard immutable hooks; reach for this only when a profile shows the data layer is the bottleneck.
|
|
239
|
+
|
|
213
240
|
## Persist (`@oimdb/persist`)
|
|
214
241
|
|
|
215
242
|
```ts
|
|
216
|
-
|
|
243
|
+
// Backends are separate packages: @oimdb/persist-localstorage / -idb / -memory / -async-kv / -json
|
|
244
|
+
import { createLocalStoragePersistor } from '@oimdb/persist-localstorage';
|
|
217
245
|
|
|
218
246
|
const persistor = createLocalStoragePersistor({});
|
|
219
247
|
|