@mmstack/primitives 22.5.0 → 22.5.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 +30 -1
- package/fesm2022/mmstack-primitives.mjs +206 -24
- package/fesm2022/mmstack-primitives.mjs.map +1 -1
- package/package.json +1 -1
- package/types/mmstack-primitives.d.ts +112 -3
package/package.json
CHANGED
|
@@ -3024,6 +3024,32 @@ declare function mutableStore<T extends AnyRecord>(value: T, opt?: CreateSignalO
|
|
|
3024
3024
|
*/
|
|
3025
3025
|
noUnionLeaves?: boolean;
|
|
3026
3026
|
}): MutableSignalStore<T>;
|
|
3027
|
+
/**
|
|
3028
|
+
* Builds a DI-less store context — the shared proxy-cache and cleanup registry that {@link toStore}
|
|
3029
|
+
* normally resolves from the injector — so a `store`/`toStore`/`opLog` graph can run with NO Angular
|
|
3030
|
+
* injection context. Spread the result into the options:
|
|
3031
|
+
*
|
|
3032
|
+
* ```ts
|
|
3033
|
+
* import { microtaskOpLogDriver } from '@mmstack/worker/host';
|
|
3034
|
+
* const ctx = createStoreContext();
|
|
3035
|
+
* const s = store({ todos: [] }, ctx);
|
|
3036
|
+
* const log = opLog(s, { driver: microtaskOpLogDriver(), origin: 'worker' }); // no injector anywhere
|
|
3037
|
+
* ```
|
|
3038
|
+
*
|
|
3039
|
+
* **This is a worker-only fallback — do NOT use it on the main thread.** DI is the default and
|
|
3040
|
+
* correct path in an app: the injector scopes the proxy-cache/cleanup singletons per app instance,
|
|
3041
|
+
* which on the SERVER keeps one request's store identity from bleeding into another's (the exact
|
|
3042
|
+
* hazard a module-scope singleton would reintroduce). A Web Worker is safe because it is a single
|
|
3043
|
+
* store graph per thread and never runs during SSR (spawn is a `PLATFORM_ID === 'server'` no-op),
|
|
3044
|
+
* so there is no cross-request scope to contaminate. Never hoist a `createStoreContext()` to module
|
|
3045
|
+
* scope on a shared/main thread.
|
|
3046
|
+
*
|
|
3047
|
+
* **Share ONE context across every store in a worker** — the same way `providedIn: 'root'` shares
|
|
3048
|
+
* one cache across all of an app's stores. `@mmstack/worker/host` memoizes this per worker
|
|
3049
|
+
* (`workerStoreContext()`); reach for `createStoreContext()` directly only in a bare
|
|
3050
|
+
* (non-worker-host) DI-less setup, and hold the single instance yourself.
|
|
3051
|
+
*/
|
|
3052
|
+
declare function createStoreContext(): toStoreOptions;
|
|
3027
3053
|
|
|
3028
3054
|
/**
|
|
3029
3055
|
* A 3-way merge of a forked value against a changed base: given the common `ancestor` (the base
|
|
@@ -3117,11 +3143,28 @@ type OpBatch = {
|
|
|
3117
3143
|
readonly version: number;
|
|
3118
3144
|
readonly ops: readonly StoreOp[];
|
|
3119
3145
|
};
|
|
3146
|
+
/**
|
|
3147
|
+
* Drives an {@link opLog}'s emission reaction. Given the `run` closure (which reads the source in
|
|
3148
|
+
* a tracking context and flushes the delta), a driver arranges for `run` to execute now and again
|
|
3149
|
+
* on every subsequent change, returning a handle that stops it. The default driver is an Angular
|
|
3150
|
+
* `effect` (needs an injector). Supply a custom driver to run an opLog with NO injector; a
|
|
3151
|
+
* renderer-independent one built on `@angular/core/primitives/signals` `createWatch` ships as
|
|
3152
|
+
* `microtaskOpLogDriver` from `@mmstack/worker/host` (the Web Worker seam).
|
|
3153
|
+
*/
|
|
3154
|
+
type OpLogDriver = (run: () => void) => {
|
|
3155
|
+
destroy(): void;
|
|
3156
|
+
};
|
|
3120
3157
|
type CreateOpLogOptions = {
|
|
3121
3158
|
/** Transport identity for emitted batches. Defaults to a random id. */
|
|
3122
3159
|
readonly origin?: string;
|
|
3123
|
-
/** Injection context for the
|
|
3160
|
+
/** Injection context for the default effect-based driver (required outside one). */
|
|
3124
3161
|
readonly injector?: Injector;
|
|
3162
|
+
/**
|
|
3163
|
+
* Replaces the default Angular-`effect` emission driver. Supply a custom driver (e.g.
|
|
3164
|
+
* `microtaskOpLogDriver` from `@mmstack/worker/host`) to run an opLog with NO injector. When
|
|
3165
|
+
* given, `injector` is ignored and no injection context is required.
|
|
3166
|
+
*/
|
|
3167
|
+
readonly driver?: OpLogDriver;
|
|
3125
3168
|
};
|
|
3126
3169
|
type OpLog<T extends object> = {
|
|
3127
3170
|
/**
|
|
@@ -3131,6 +3174,15 @@ type OpLog<T extends object> = {
|
|
|
3131
3174
|
subscribe(cb: (batch: OpBatch) => void): () => void;
|
|
3132
3175
|
/** The most recent batch — a lossy sampling view (devtools); use `subscribe` for transport. */
|
|
3133
3176
|
readonly latest: Signal<OpBatch | null>;
|
|
3177
|
+
/**
|
|
3178
|
+
* Synchronously diff the source and emit any pending change NOW, rather than waiting for the
|
|
3179
|
+
* driver's scheduled run (an app tick, or a custom driver's microtask). Idempotent
|
|
3180
|
+
* and coalescing: writes since the last emission compose into one batch, and a `flush()` with
|
|
3181
|
+
* nothing pending is a no-op. Use it to make emission deterministic — the worker host calls it
|
|
3182
|
+
* to settle its mirror synchronously (tests), and it underpins the flush-before-apply honesty of
|
|
3183
|
+
* {@link OpLog.apply}. Independent of the driver: a later scheduled run simply finds no diff.
|
|
3184
|
+
*/
|
|
3185
|
+
flush(): void;
|
|
3134
3186
|
/**
|
|
3135
3187
|
* Applies ops (a remote batch, a persisted journal entry, an {@link invertBatch} result)
|
|
3136
3188
|
* atomically: ONE `set`, one notification wave. Also advances this log's diff baseline in
|
|
@@ -3142,6 +3194,21 @@ type OpLog<T extends object> = {
|
|
|
3142
3194
|
/** Stops observing and drops subscribers. Also happens when the injection context dies. */
|
|
3143
3195
|
destroy(): void;
|
|
3144
3196
|
};
|
|
3197
|
+
/**
|
|
3198
|
+
* Pure, store-free application of ops onto a plain root value, returning the next immutable root
|
|
3199
|
+
* (structural-sharing along op paths, missing containers vivified `'auto'`-style). This is the
|
|
3200
|
+
* same transform {@link OpLog.apply} runs, extracted so a replica can fold a received batch into
|
|
3201
|
+
* a value WITHOUT owning a diffing {@link opLog} — e.g. the worker-graph read-replica seam.
|
|
3202
|
+
* Accepts a batch or a bare op list.
|
|
3203
|
+
*/
|
|
3204
|
+
declare function applyOps<T>(root: T, ops: OpBatch | readonly StoreOp[]): T;
|
|
3205
|
+
/**
|
|
3206
|
+
* Pure reference-pruned structural diff of two roots into minimal ops (the emission core of
|
|
3207
|
+
* {@link opLog}, exported so code outside a log can produce a batch — e.g. diffing a scratch
|
|
3208
|
+
* draft against a replica's current value to route a write to its owner). Trusts the
|
|
3209
|
+
* copy-on-write contract: an untouched subtree that kept its reference is skipped.
|
|
3210
|
+
*/
|
|
3211
|
+
declare function diffOps(prev: unknown, next: unknown): StoreOp[];
|
|
3145
3212
|
/**
|
|
3146
3213
|
* Inverts a batch for undo: reversed order, `set`↔its own inverse (an add — a `set` with no
|
|
3147
3214
|
* `prev` — inverts to a `delete`; a `delete` inverts to a `set` restoring `prev`). Feed the
|
|
@@ -3174,6 +3241,48 @@ declare function invertBatch(batch: OpBatch | readonly StoreOp[]): StoreOp[];
|
|
|
3174
3241
|
*/
|
|
3175
3242
|
declare function opLog<T extends object>(source: WritableSignal<T>, opt?: CreateOpLogOptions): OpLog<T>;
|
|
3176
3243
|
|
|
3244
|
+
/** Identity selector for keyed array reconciliation: a property name, or a function per item. */
|
|
3245
|
+
type ReconcileKey = string | ((item: any) => unknown);
|
|
3246
|
+
/**
|
|
3247
|
+
* Produces a value equal to `next` but sharing as much of `prev`'s reference structure as possible:
|
|
3248
|
+
* an object subtree that did not change keeps its `prev` reference, and array items are matched by
|
|
3249
|
+
* `key` so a surviving item keeps its identity across a reorder/insert/remove (only added items are
|
|
3250
|
+
* new, only removed items are dropped). This is what lets a derived store recompute without tearing
|
|
3251
|
+
* down every downstream `computed` that reads an unchanged part of it.
|
|
3252
|
+
*/
|
|
3253
|
+
declare function reconcile<T>(prev: T, next: T, key?: ReconcileKey): T;
|
|
3254
|
+
type ProjectionOptions = toStoreOptions & {
|
|
3255
|
+
/** Identity key for reconciling array items (default `'id'`). */
|
|
3256
|
+
readonly key?: ReconcileKey;
|
|
3257
|
+
};
|
|
3258
|
+
/**
|
|
3259
|
+
* A derived STORE, the store-shaped counterpart to `computed`. `fn` receives a mutable draft seeded
|
|
3260
|
+
* with the current value and either mutates it in place or returns a new value; whichever it does,
|
|
3261
|
+
* the result is reconciled against the previous value (see {@link reconcile}) so unchanged subtrees
|
|
3262
|
+
* keep reference identity and keyed array items keep their proxy identity. Reading through the
|
|
3263
|
+
* returned store is fine-grained: a `computed` over one field only recomputes when that field
|
|
3264
|
+
* actually changes, even though the whole projection re-ran.
|
|
3265
|
+
*
|
|
3266
|
+
* Recompute is pull-based, exactly like `computed`: the projection is memoized and re-runs on the
|
|
3267
|
+
* first read after a signal `fn` depends on changes, so reads are always coherent (no waiting on an
|
|
3268
|
+
* effect flush) and nothing recomputes while nobody reads. `fn` must be pure, it runs inside the
|
|
3269
|
+
* reactive computation. Prefer `computed` for a plain value; reach for `projection` when you want
|
|
3270
|
+
* the per-property tracking of a store on top of a derivation.
|
|
3271
|
+
*
|
|
3272
|
+
* ```ts
|
|
3273
|
+
* const active = projection<User[]>(() => users().filter((u) => u.active), [], { key: 'id' });
|
|
3274
|
+
* // active[0].name(); — surviving users keep identity across recomputes
|
|
3275
|
+
* ```
|
|
3276
|
+
*
|
|
3277
|
+
* Needs an injection context (or an explicit `injector`) for the store layer's cleanup on the main
|
|
3278
|
+
* thread; with an explicit store context (`createStoreContext()`) it is injector-free, so it also
|
|
3279
|
+
* runs on a worker host.
|
|
3280
|
+
*
|
|
3281
|
+
* @param fn receives the current draft; mutate it, or return new data.
|
|
3282
|
+
* @param seed the initial value, held before the first run.
|
|
3283
|
+
*/
|
|
3284
|
+
declare function projection<T extends object>(fn: (draft: T) => void | T, seed: T, opt?: ProjectionOptions): SignalStore<T>;
|
|
3285
|
+
|
|
3177
3286
|
/**
|
|
3178
3287
|
* Interface for storage mechanisms compatible with the `stored` signal.
|
|
3179
3288
|
* Matches the essential parts of the `Storage` interface (`localStorage`, `sessionStorage`).
|
|
@@ -3632,5 +3741,5 @@ type CreateHistoryOptions<T> = Omit<CreateSignalOptions<T[]>, 'equal'> & {
|
|
|
3632
3741
|
*/
|
|
3633
3742
|
declare function withHistory<T>(sourceOrValue: WritableSignal<T> | T, opt?: CreateHistoryOptions<T>): SignalWithHistory<T>;
|
|
3634
3743
|
|
|
3635
|
-
export { MmActivity, MmTransition, MmViewTransitionName, PAUSABLE_OPTIONS, SuspenseBoundary, SuspenseBoundaryBase, UnscopedSuspenseBoundary, activeTransaction, batteryStatus, bridgeScopeToPendingTasks, chunked, clipboard, combineWith, createAttributedPending, createForwardingScope, createTransaction, createTransitionScope, debounce, debounced, deferredValue, derived, distinct, elementSize, elementVisibility, extendStore, filter, filterWith, focusWithin, forkStore, geolocation, getTransitionScope, holdUntilReady, idle, indexArray, injectPaused, injectRegisterResource, injectStartTransaction, injectStartTransition, injectTransitionScope, invertBatch, isDerivation, isLeaf, isMutable, isOpaque, isStore, keepPrevious, keyArray, latest, map, mapArray, mapObject, mediaQuery, merge3, mousePosition, mutable, mutableStore, nestedEffect, networkStatus, opLog, opaque, orientation, pageVisibility, pairwise, pausableComputed, pausableEffect, pausableSignal, pipeable, piped, pointerDrag, pooled, pooledArray, pooledMap, pooledSet, prefersDarkMode, prefersReducedMotion, provideForwardingTransitionScope, providePausableOptions, providePaused, provideTransitionScope, registerResource, resolvePause, scan, scrollPosition, select, sensor, sensors, signalFromEvent, startWith, store, stored, tabSync, tap, throttle, throttled, toFakeDerivation, toFakeSignalDerivation, toStore, toWritable, until, use, windowSize, withHistory };
|
|
3636
|
-
export type { BatteryStatus, ClipboardSignal, Computation, CreateChunkedOptions, CreateDebouncedOptions, CreateHistoryOptions, CreateLatestOptions, CreateOpLogOptions, CreatePooledOptions, CreateProvidedPooledOptions, CreateStoredOptions, CreateThrottledOptions, DebouncedSignal, DeferStrategy, DeferredSignal, DeferredValueOptions, DerivedSignal, ElementSize, ElementSizeOptions, ElementSizeSignal, ElementVisibilityOptions, ElementVisibilitySignal, ExtendStoreOptions, Fork, ForkStoreOptions, ForkStrategy, ForwardingTransitionScope, Frame, GeolocationOptions, GeolocationSignal, IdleOptions, IdleSignal, LatestSignal, MmTransitionContext, MousePositionOptions, MousePositionSignal, MutableSignal, MutableSignalStore, NetworkStatusSignal, OpBatch, OpLog, Opaque, PausableOptions, PauseOption, PipeableSignal, PointerDragOptions, PointerDragSignal, PointerDragState, PointerModifiers, PointerPoint, ReconcileFn, RegisterOptions, ResourceLike, ScreenOrientation, ScreenOrientationState, ScrollPosition, ScrollPositionOptions, ScrollPositionSignal, SensorRunOptions, SignalFromEventOptions, SignalStore, SignalWithHistory, StoreOp, StoreOptions, StoredSignal, SuspendType, ThrottledSignal, Transaction, TransactionRef, TransitionRef, TransitionScope, UntilOptions, UseSource, Vivify, WindowSize, WindowSizeOptions, WindowSizeSignal, WithVivify, WritableSignalStore, toStoreOptions };
|
|
3744
|
+
export { MmActivity, MmTransition, MmViewTransitionName, PAUSABLE_OPTIONS, SuspenseBoundary, SuspenseBoundaryBase, UnscopedSuspenseBoundary, activeTransaction, applyOps, batteryStatus, bridgeScopeToPendingTasks, chunked, clipboard, combineWith, createAttributedPending, createForwardingScope, createStoreContext, createTransaction, createTransitionScope, debounce, debounced, deferredValue, derived, diffOps, distinct, elementSize, elementVisibility, extendStore, filter, filterWith, focusWithin, forkStore, geolocation, getTransitionScope, holdUntilReady, idle, indexArray, injectPaused, injectRegisterResource, injectStartTransaction, injectStartTransition, injectTransitionScope, invertBatch, isDerivation, isLeaf, isMutable, isOpaque, isStore, keepPrevious, keyArray, latest, map, mapArray, mapObject, mediaQuery, merge3, mousePosition, mutable, mutableStore, nestedEffect, networkStatus, opLog, opaque, orientation, pageVisibility, pairwise, pausableComputed, pausableEffect, pausableSignal, pipeable, piped, pointerDrag, pooled, pooledArray, pooledMap, pooledSet, prefersDarkMode, prefersReducedMotion, projection, provideForwardingTransitionScope, providePausableOptions, providePaused, provideTransitionScope, reconcile, registerResource, resolvePause, scan, scrollPosition, select, sensor, sensors, signalFromEvent, startWith, store, stored, tabSync, tap, throttle, throttled, toFakeDerivation, toFakeSignalDerivation, toStore, toWritable, until, use, windowSize, withHistory };
|
|
3745
|
+
export type { BatteryStatus, ClipboardSignal, Computation, CreateChunkedOptions, CreateDebouncedOptions, CreateHistoryOptions, CreateLatestOptions, CreateOpLogOptions, CreatePooledOptions, CreateProvidedPooledOptions, CreateStoredOptions, CreateThrottledOptions, DebouncedSignal, DeferStrategy, DeferredSignal, DeferredValueOptions, DerivedSignal, ElementSize, ElementSizeOptions, ElementSizeSignal, ElementVisibilityOptions, ElementVisibilitySignal, ExtendStoreOptions, Fork, ForkStoreOptions, ForkStrategy, ForwardingTransitionScope, Frame, GeolocationOptions, GeolocationSignal, IdleOptions, IdleSignal, LatestSignal, MmTransitionContext, MousePositionOptions, MousePositionSignal, MutableSignal, MutableSignalStore, NetworkStatusSignal, OpBatch, OpLog, OpLogDriver, Opaque, PausableOptions, PauseOption, PipeableSignal, PointerDragOptions, PointerDragSignal, PointerDragState, PointerModifiers, PointerPoint, ProjectionOptions, ReconcileFn, ReconcileKey, RegisterOptions, ResourceLike, ScreenOrientation, ScreenOrientationState, ScrollPosition, ScrollPositionOptions, ScrollPositionSignal, SensorRunOptions, SignalFromEventOptions, SignalStore, SignalWithHistory, StoreOp, StoreOptions, StoredSignal, SuspendType, ThrottledSignal, Transaction, TransactionRef, TransitionRef, TransitionScope, UntilOptions, UseSource, Vivify, WindowSize, WindowSizeOptions, WindowSizeSignal, WithVivify, WritableSignalStore, toStoreOptions };
|