coaction 2.1.0 → 3.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.
@@ -0,0 +1,468 @@
1
+ import { Transport } from "data-transport";
2
+ import { Draft, Patches } from "mutative";
3
+
4
+ //#region packages/core/src/interface.d.ts
5
+ /**
6
+ * Generic object shape used by stores and slices.
7
+ */
8
+ type ISlices<T = any> = Record<PropertyKey, T>;
9
+ /**
10
+ * Recursive partial object accepted by {@link Store.setState} when merging a
11
+ * plain object payload into the current state tree.
12
+ */
13
+ type DeepPartial<T> = { [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K] };
14
+ /**
15
+ * Subscription callback invoked after the store publishes a state change.
16
+ */
17
+ type Listener = () => void;
18
+ /**
19
+ * Patch pair exposed to middleware compatibility hooks.
20
+ */
21
+ interface PatchTransform {
22
+ patches: Patches;
23
+ inversePatches: Patches;
24
+ }
25
+ /**
26
+ * Trace envelope emitted before and after a store method executes.
27
+ */
28
+ interface StoreTraceEvent {
29
+ /**
30
+ * The id of the method.
31
+ */
32
+ id: string;
33
+ /**
34
+ * The method name.
35
+ */
36
+ method: string;
37
+ /**
38
+ * The slice key.
39
+ */
40
+ sliceKey?: PropertyKey;
41
+ /**
42
+ * The parameters of the method.
43
+ */
44
+ parameters?: any[];
45
+ /**
46
+ * The result of the method.
47
+ */
48
+ result?: any;
49
+ }
50
+ /**
51
+ * Runtime store contract returned by {@link create} before framework-specific
52
+ * wrappers add selectors or reactivity helpers.
53
+ *
54
+ * @remarks
55
+ * `getState()` returns methods and getters alongside plain data. Methods
56
+ * extracted from the returned object keep the correct `this` binding when they
57
+ * are later invoked.
58
+ */
59
+ interface Store<T extends ISlices = ISlices> {
60
+ /**
61
+ * The name of the store.
62
+ */
63
+ name: string;
64
+ /**
65
+ * Mutate the current state.
66
+ *
67
+ * @remarks
68
+ * Pass a deep-partial object to merge fields, or pass an updater to edit a
69
+ * Mutative draft. Passing `null` is a no-op. Client-side shared stores intentionally reject direct
70
+ * `setState()` calls; trigger a store method instead.
71
+ */
72
+ setState: (
73
+ /**
74
+ * The next partial state, or an updater that mutates a draft.
75
+ */
76
+
77
+ next: DeepPartial<T> | ((draft: Draft<T>) => any) | null,
78
+ /**
79
+ * Low-level updater hook used by transports and middleware integrations.
80
+ */
81
+
82
+ updater?: (next: DeepPartial<T> | ((draft: Draft<T>) => any) | null) => [] | [T, Patches, Patches]) => void;
83
+ /**
84
+ * Read the current state object.
85
+ *
86
+ * @remarks
87
+ * The returned object includes methods and getters. Methods destructured from
88
+ * this object continue to execute against the latest store state.
89
+ */
90
+ getState: () => T;
91
+ /**
92
+ * Subscribe to state changes.
93
+ *
94
+ * @returns A function that removes the listener.
95
+ */
96
+ subscribe: (listener: Listener) => () => void;
97
+ /**
98
+ * Tear down the store.
99
+ *
100
+ * @remarks
101
+ * `destroy()` is idempotent. It clears subscriptions and disposes any
102
+ * attached transport.
103
+ */
104
+ destroy: () => void;
105
+ /**
106
+ * Indicates whether the store is local, the main shared store, or a client
107
+ * mirror of a shared store.
108
+ */
109
+ share?: 'main' | 'client' | false;
110
+ /**
111
+ * Transport used to synchronize a shared store between processes or threads.
112
+ */
113
+ transport?: Transport;
114
+ /**
115
+ * Whether `createState` was interpreted as a slices object.
116
+ */
117
+ isSliceStore: boolean;
118
+ /**
119
+ * Apply patches to the current state.
120
+ *
121
+ * @remarks
122
+ * This is a low-level hook used by transports and middleware. Application
123
+ * code should generally prefer store methods or `setState()`. Client-side
124
+ * shared-store mirrors reject direct `apply()` calls.
125
+ */
126
+ apply: (state?: T, patches?: Patches) => void;
127
+ /**
128
+ * Return the current state without methods or getters.
129
+ *
130
+ * @remarks
131
+ * Useful for serialization, inspection, or tests that only care about raw
132
+ * data.
133
+ */
134
+ getPureState: () => T;
135
+ /**
136
+ * Return the state produced during initialization before later mutations.
137
+ */
138
+ getInitialState: () => T;
139
+ /**
140
+ * @deprecated Middleware compatibility hook. Prefer typing middleware stores
141
+ * with `MiddlewareStore`.
142
+ */
143
+ patch?: (option: PatchTransform) => PatchTransform;
144
+ /**
145
+ * @deprecated Middleware compatibility hook. Prefer typing middleware stores
146
+ * with `MiddlewareStore`.
147
+ */
148
+ trace?: (options: StoreTraceEvent) => void;
149
+ }
150
+ /**
151
+ * Semantic alias for middleware-facing stores.
152
+ *
153
+ * @remarks
154
+ * Middleware implementations should type their `store` parameter as
155
+ * `MiddlewareStore` instead of relying on deprecated `patch` or `trace` hooks.
156
+ */
157
+ interface MiddlewareStore<T extends ISlices = ISlices> extends Store<T> {}
158
+ /**
159
+ * Helper passed into {@link Slice} and {@link Slices} factories.
160
+ *
161
+ * @remarks
162
+ * Call it with no arguments to read the current store state. Call it with a
163
+ * dependency selector pair to define a computed value.
164
+ */
165
+ interface Getter<T extends ISlices> {
166
+ <P extends any[], R>(getDeps: (store: T) => readonly [...P] | [...P], selector: (...args: P) => R): R;
167
+ (): T;
168
+ }
169
+ /**
170
+ * Factory for a single store object.
171
+ *
172
+ * @remarks
173
+ * Return a plain object containing state, getters, and methods. Methods and
174
+ * getters may use `this` to access the live store state.
175
+ */
176
+ type Slice<T extends ISlices> = (
177
+ /**
178
+ * The setState is used to update the state.
179
+ */
180
+ set: Store<T>['setState'],
181
+ /**
182
+ * The getState is used to get the state.
183
+ */
184
+ get: Getter<T>,
185
+ /**
186
+ * The store is used to store the state.
187
+ */
188
+ store: Store<T>) => T;
189
+ /**
190
+ * Store enhancer invoked during store creation.
191
+ *
192
+ * @remarks
193
+ * Middleware may mutate the received store in place or return a replacement
194
+ * store object, but it must preserve the {@link Store} contract.
195
+ */
196
+ type Middleware<T extends CreateState> = (store: MiddlewareStore<T>) => MiddlewareStore<T>;
197
+ /**
198
+ * Callable store returned by {@link create} in local or main/shared mode.
199
+ */
200
+ type StoreReturn<T extends object> = Store<T> & ((...args: any[]) => T);
201
+ /**
202
+ * Accepted `create()` input shape.
203
+ *
204
+ * @remarks
205
+ * This can be either a single store factory/object or a map of slice
206
+ * factories.
207
+ */
208
+ type CreateState = ISlices | Record<PropertyKey, Slice<any>>;
209
+ //#endregion
210
+ //#region packages/core/src/internal.d.ts
211
+ type MutationOperation = 'setState' | 'apply';
212
+ type StoreOperation = MutationOperation | 'subscribe' | 'store initialization' | `action ${string}`;
213
+ type SignalSlot = {
214
+ refresh: () => void;
215
+ };
216
+ type StateSchema = {
217
+ rootKeys: Set<PropertyKey>;
218
+ sliceKeys?: Map<PropertyKey, Set<PropertyKey>>;
219
+ };
220
+ interface Internal<T extends CreateState = CreateState> {
221
+ /**
222
+ * The store module.
223
+ */
224
+ module: T;
225
+ /**
226
+ * The root state.
227
+ */
228
+ rootState: T | Draft<T>;
229
+ /**
230
+ * The backup state.
231
+ */
232
+ backupState: T | Draft<T>;
233
+ /**
234
+ * Finalize the draft.
235
+ */
236
+ finalizeDraft: () => [T, Patches, Patches];
237
+ /**
238
+ * The mutable instance.
239
+ */
240
+ mutableInstance: any;
241
+ /**
242
+ * The sequence number.
243
+ */
244
+ sequence: number;
245
+ /** Identifies the lifetime of the current shared authority. */
246
+ transportEpoch?: string;
247
+ /** Action paths declared when the authoritative store was initialized. */
248
+ sharedActionPaths?: Set<string>;
249
+ /**
250
+ * Whether the batch is running.
251
+ */
252
+ isBatching: boolean;
253
+ /** Depth of a cached getter/computed evaluation over immutable state. */
254
+ computedReadDepth?: number;
255
+ /** Frozen snapshots keyed by immutable state object identity. */
256
+ computedSnapshotCache?: WeakMap<object, unknown>;
257
+ /** Immutable state sources keyed by frozen computed snapshot identity. */
258
+ computedSnapshotSources?: WeakMap<object, object>;
259
+ /** Whether a computed getter has returned a state snapshot object. */
260
+ computedIdentityRequired?: boolean;
261
+ /**
262
+ * The listeners.
263
+ */
264
+ listeners: Set<Listener>;
265
+ /** Cleanup callbacks owned by transport and integration layers. */
266
+ destroyCallbacks?: Set<() => void>;
267
+ /**
268
+ * Publish an externally-owned immutable state change to signal slots and
269
+ * store subscribers.
270
+ */
271
+ notifyStateChange: () => void;
272
+ /**
273
+ * Reactive state slots used by computed getters/selectors.
274
+ */
275
+ signalSlots?: Set<SignalSlot>;
276
+ /**
277
+ * State keys that are allowed after initialization.
278
+ */
279
+ stateSchema?: StateSchema;
280
+ /**
281
+ * The act is used to run the function in the action for mutable state.
282
+ */
283
+ actMutable?: <T extends () => any>(fn: T) => ReturnType<T>;
284
+ /**
285
+ * Get the mutable raw instance via the initial state.
286
+ */
287
+ toMutableRaw?: (key: any) => any;
288
+ /**
289
+ * The update immutable function.
290
+ */
291
+ updateImmutable?: (state: T) => void;
292
+ /**
293
+ * Adapter-level authority check for low-level mutations.
294
+ */
295
+ assertMutationAllowed?: (operation: MutationOperation) => void;
296
+ /**
297
+ * Store lifecycle guard.
298
+ */
299
+ assertAlive?: (operation: StoreOperation) => void;
300
+ /**
301
+ * Authorized client-mirror state application used by transports.
302
+ */
303
+ applyClientState?: (state?: T, patches?: Patches) => void;
304
+ /** Request an authoritative full sync for a client mirror. */
305
+ syncClientState?: (expectedEpoch?: string, minimumSequence?: number) => Promise<void>;
306
+ /** Cancel a transport promise when the client mirror is destroyed. */
307
+ awaitClientTransport?: <R>(value: PromiseLike<R> | R) => Promise<R>;
308
+ /** Validate committed state when a runtime capability requires it. */
309
+ validateState?: (state: unknown) => void;
310
+ /** Validate outbound patches before normalization or commit. */
311
+ validatePatches?: (patches: Patches) => void;
312
+ /** Validate an adapter replacement source before reading its values. */
313
+ validateReplacementSource?: (state: unknown) => void;
314
+ /** Commit patches already checked by the native updater. */
315
+ applyValidatedPatches?: (state: T, patches: Patches, skipFinalValidation: boolean) => boolean;
316
+ /** Publish patches when a shared authority transport is attached. */
317
+ emitPatches?: (patches: Patches) => void;
318
+ /** Return the plain state exposed at the JSON transport boundary. */
319
+ getTransportState?: () => unknown;
320
+ }
321
+ //#endregion
322
+ //#region packages/core/src/binder.d.ts
323
+ type ExternalStoreAdapterOptions<F = (...args: any[]) => any> = {
324
+ /**
325
+ * Normalize a third-party store instance into a raw state object plus the
326
+ * binding hook used during initialization.
327
+ */
328
+ handleState: <T extends object = object>(state: T) => {
329
+ /**
330
+ * Copy of the incoming state object that Coaction should consume.
331
+ */
332
+ copyState: T;
333
+ /**
334
+ * Optional nested key when the adapter exposes a single child object from
335
+ * the third-party store.
336
+ */
337
+ key?: keyof T;
338
+ /**
339
+ * Convert the external state object into the raw state shape used by
340
+ * Coaction.
341
+ */
342
+ bind: (state: T) => T;
343
+ };
344
+ /**
345
+ * Wire Coaction's store lifecycle to the external store implementation.
346
+ */
347
+ handleStore: (
348
+ /**
349
+ * Coaction store wrapper.
350
+ */
351
+
352
+ store: Store<object>,
353
+ /**
354
+ * Raw state object returned from `bind`.
355
+ */
356
+
357
+ rawState: object,
358
+ /**
359
+ * Original external store state object.
360
+ */
361
+
362
+ state: object,
363
+ /**
364
+ * Low-level Coaction adapter hooks used by official bindings.
365
+ */
366
+
367
+ internal: Internal<object>,
368
+ /**
369
+ * Optional nested key returned by `handleState`.
370
+ */
371
+
372
+ key?: PropertyKey) => void;
373
+ };
374
+ /**
375
+ * Build an adapter helper for bridging an external store implementation into
376
+ * Coaction.
377
+ *
378
+ * @remarks
379
+ * Import this compatibility helper from `coaction/adapter`.
380
+ *
381
+ * Official bindings use this to integrate stores such as Redux, Jotai, Pinia,
382
+ * Zustand, MobX, and Valtio. Binder-backed integrations are whole-store
383
+ * adapters; they are not compatible with Coaction slices mode.
384
+ */
385
+ declare function createBinder<F = (...args: any[]) => any>({
386
+ handleState,
387
+ handleStore
388
+ }: ExternalStoreAdapterOptions<F>): F;
389
+ /**
390
+ * Define a whole-store adapter for integrating an external state runtime with
391
+ * Coaction.
392
+ *
393
+ * @remarks
394
+ * Import this helper from `coaction/adapter`. `createBinder()` remains as a
395
+ * compatibility alias for existing official and community integrations.
396
+ */
397
+ declare function defineExternalStoreAdapter<F = (...args: any[]) => any>(options: ExternalStoreAdapterOptions<F>): F;
398
+ //#endregion
399
+ //#region packages/core/src/externalMutableAdapterUtils.d.ts
400
+ declare const getMutableAdapterOwnEnumerableKeys: (value: object) => (string | symbol)[];
401
+ declare const isMutableAdapterUnsafeKey: (key: PropertyKey) => key is "__proto__" | "prototype" | "constructor";
402
+ declare const replaceMutableAdapterState: (rawState: Record<PropertyKey, unknown>, mutableState: Record<PropertyKey, unknown>, publicState: Record<PropertyKey, unknown>, source: Record<PropertyKey, unknown>) => void;
403
+ declare const applyMutableAdapterPatches: (baseState: unknown, patches: Patches, rawState: Record<PropertyKey, unknown>, mutableState: Record<PropertyKey, unknown>, publicState: Record<PropertyKey, unknown>, validateState?: (state: unknown) => void) => void;
404
+ declare const toMutableAdapterSnapshot: (value: unknown, visited?: WeakMap<object, unknown>) => unknown;
405
+ declare const snapshotMutableAdapterPureState: (store: Store<object>) => Record<PropertyKey, unknown>;
406
+ declare const isEqualMutableAdapterSnapshot: (left: unknown, right: unknown, visited?: WeakMap<object, WeakSet<object>>) => boolean;
407
+ //#endregion
408
+ //#region packages/core/src/reactiveTracker.d.ts
409
+ type ReactiveTracker = {
410
+ getSnapshot: () => number;
411
+ subscribe: (listener: () => void) => () => void;
412
+ track: <T>(fn: () => T) => T;
413
+ dispose: () => void;
414
+ };
415
+ /**
416
+ * Create a low-level signal dependency tracker for framework adapters.
417
+ *
418
+ * @remarks
419
+ * Adapter and framework authors import this helper from `coaction/adapter`.
420
+ */
421
+ declare const createReactiveTracker: () => ReactiveTracker;
422
+ //#endregion
423
+ //#region packages/core/src/lifecycle.d.ts
424
+ declare const onStoreReady: <T extends CreateState>(store: Store<T>, callback: () => void) => () => void;
425
+ //#endregion
426
+ //#region packages/core/src/replaceExternalStoreState.d.ts
427
+ type ReplaceExternalStoreStateOptions = {
428
+ syncImmutable?: boolean;
429
+ };
430
+ declare const replaceExternalStoreState: <T extends CreateState>(store: MiddlewareStore<T>, internal: Internal<T>, source: Record<PropertyKey, unknown>, {
431
+ syncImmutable
432
+ }?: ReplaceExternalStoreStateOptions) => void;
433
+ //#endregion
434
+ //#region packages/core/src/utils.d.ts
435
+ declare class StateSchemaError extends Error {
436
+ name: string;
437
+ }
438
+ declare const isStateSchemaError: (error: unknown) => error is StateSchemaError;
439
+ type RootReplacementPatch = {
440
+ op: 'add' | 'remove' | 'replace';
441
+ path: PropertyKey[];
442
+ value?: unknown;
443
+ };
444
+ declare const createRootReplacementPatches: (currentState: Record<PropertyKey, unknown>, nextState: Record<PropertyKey, unknown>) => {
445
+ patches: RootReplacementPatch[];
446
+ inversePatches: RootReplacementPatch[];
447
+ };
448
+ declare const applyRootReplacementWithPatches: <T extends object>(store: MiddlewareStore<T>, nextState: Record<PropertyKey, unknown>, options?: {
449
+ applyExactReplacement?: (state: T) => void;
450
+ }) => [T, Patches, Patches];
451
+ declare const replaceOwnEnumerable: (target: Record<PropertyKey, unknown>, source: Record<PropertyKey, unknown>) => void;
452
+ declare const sanitizeReplacementState: <T>(source: T, seen?: WeakMap<object, unknown>) => T;
453
+ declare const sanitizeInitialStateValue: <T>(source: T, seen?: WeakMap<object, unknown>) => T;
454
+ //#endregion
455
+ //#region packages/core/src/wrapStore.d.ts
456
+ /**
457
+ * Convert a store object into Coaction's callable store shape.
458
+ *
459
+ * @remarks
460
+ * Framework bindings use this to attach selector-aware readers while
461
+ * preserving the underlying store API on the returned function object. Most
462
+ * applications should use a public `create` entry instead of calling
463
+ * `wrapStore()` directly. Framework authors import this helper from
464
+ * `coaction/local` or `coaction/adapter`.
465
+ */
466
+ declare const wrapStore: <T extends object>(store: Store<T>, getState?: (...args: unknown[]) => T) => StoreReturn<T>;
467
+ //#endregion
468
+ export { type CreateState, type ExternalStoreAdapterOptions, type Middleware, type MiddlewareStore, type PatchTransform, type ReactiveTracker, StateSchemaError, type Store, type StoreTraceEvent, applyMutableAdapterPatches, applyRootReplacementWithPatches, createBinder, createReactiveTracker, createRootReplacementPatches, defineExternalStoreAdapter, getMutableAdapterOwnEnumerableKeys, isEqualMutableAdapterSnapshot, isMutableAdapterUnsafeKey, isStateSchemaError, onStoreReady, replaceExternalStoreState, replaceMutableAdapterState, replaceOwnEnumerable, sanitizeInitialStateValue, sanitizeReplacementState, snapshotMutableAdapterPureState, toMutableAdapterSnapshot, wrapStore };