@nice-code/state 0.7.0 → 0.9.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.
Files changed (37) hide show
  1. package/build/Store-B65MojT2.d.ts +201 -0
  2. package/build/Store-CI9N0P6I.js +366 -0
  3. package/build/Store-CI9N0P6I.js.map +1 -0
  4. package/build/Store-PjfFkZ2I.js +349 -0
  5. package/build/Store-PjfFkZ2I.js.map +1 -0
  6. package/build/devtools/browser/index.d.ts +120 -0
  7. package/build/devtools/browser/index.js +2750 -2357
  8. package/build/devtools/browser/index.js.map +1 -0
  9. package/build/index.d.ts +2 -0
  10. package/build/index.js +2 -244
  11. package/build/react/index.d.ts +58 -0
  12. package/build/react/index.js +59 -308
  13. package/build/react/index.js.map +1 -0
  14. package/package.json +29 -26
  15. package/build/types/core/Store.d.ts +0 -136
  16. package/build/types/core/index.d.ts +0 -1
  17. package/build/types/devtools/browser/NiceStateDevtools.d.ts +0 -10
  18. package/build/types/devtools/browser/components/ChangeDetailPanel.d.ts +0 -12
  19. package/build/types/devtools/browser/components/ChangeList.d.ts +0 -9
  20. package/build/types/devtools/browser/components/DiffView.d.ts +0 -13
  21. package/build/types/devtools/browser/components/JsonDiffView.d.ts +0 -24
  22. package/build/types/devtools/browser/components/JsonView.d.ts +0 -7
  23. package/build/types/devtools/browser/components/PanelChrome.d.ts +0 -54
  24. package/build/types/devtools/browser/components/SectionLabel.d.ts +0 -4
  25. package/build/types/devtools/browser/components/StateInspector.d.ts +0 -16
  26. package/build/types/devtools/browser/components/StoreTabs.d.ts +0 -12
  27. package/build/types/devtools/browser/components/utils.d.ts +0 -98
  28. package/build/types/devtools/browser/devtools_dock.d.ts +0 -54
  29. package/build/types/devtools/browser/index.d.ts +0 -3
  30. package/build/types/devtools/core/StateDevtools.types.d.ts +0 -43
  31. package/build/types/devtools/core/StateDevtoolsCore.d.ts +0 -56
  32. package/build/types/devtools/core/devtools_colors.d.ts +0 -26
  33. package/build/types/index.d.ts +0 -1
  34. package/build/types/react/InjectStoreState.d.ts +0 -18
  35. package/build/types/react/index.d.ts +0 -3
  36. package/build/types/react/useLocalStore.d.ts +0 -8
  37. package/build/types/react/useStoreState.d.ts +0 -23
@@ -0,0 +1,349 @@
1
+ import { deepEqual } from "fast-equals";
2
+ import { applyPatches, enablePatches, produce, produceWithPatches } from "immer";
3
+ //#region src/core/Store.ts
4
+ enablePatches();
5
+ /**
6
+ * @internal
7
+ *
8
+ * Builds the per-emission runner for a selector subscription.
9
+ *
10
+ * Change detection follows the "Fast-Path" rule: Immer's structural sharing
11
+ * means an untouched branch keeps its exact reference, so a strict `===` check
12
+ * resolves the overwhelmingly common "nothing changed" case in 0ms. Only when
13
+ * the reference actually changes do we pay for a `deepEqual` traversal to
14
+ * confirm the change is structural and not just a new-but-equal reference.
15
+ */
16
+ function makeSubscriptionFunction(store, watch, listener) {
17
+ let lastWatchState = watch(store.getRawState());
18
+ return () => {
19
+ const currentState = store.getRawState();
20
+ const nextWatchState = watch(currentState);
21
+ if (nextWatchState === lastWatchState) return;
22
+ if (deepEqual(nextWatchState, lastWatchState)) {
23
+ lastWatchState = nextWatchState;
24
+ return;
25
+ }
26
+ const previousWatched = lastWatchState;
27
+ lastWatchState = nextWatchState;
28
+ listener(nextWatchState, currentState, previousWatched);
29
+ };
30
+ }
31
+ /**
32
+ * @internal
33
+ *
34
+ * Builds a reaction creator. Reactions follow the same Fast-Path rule as
35
+ * subscriptions, then run their recipe inside Immer to derive further state.
36
+ */
37
+ function makeReactionFunctionCreator(watch, reaction) {
38
+ return (store) => {
39
+ let lastWatchState = watch(store.getRawState());
40
+ return (forceRun = false) => {
41
+ const currentState = store.getRawState();
42
+ const nextWatchState = watch(currentState);
43
+ if (!forceRun) {
44
+ if (nextWatchState === lastWatchState) return;
45
+ if (deepEqual(nextWatchState, lastWatchState)) {
46
+ lastWatchState = nextWatchState;
47
+ return;
48
+ }
49
+ }
50
+ const previousWatched = lastWatchState;
51
+ lastWatchState = nextWatchState;
52
+ if (store._hasPatchListeners()) {
53
+ const [nextState, patches, inversePatches] = produceWithPatches(currentState, (draft) => {
54
+ reaction(nextWatchState, draft, currentState, previousWatched);
55
+ });
56
+ store._updateStateWithoutReaction(nextState);
57
+ if (patches.length > 0) store._emitPatches(patches, inversePatches);
58
+ } else {
59
+ const nextState = produce(currentState, (draft) => {
60
+ reaction(nextWatchState, draft, currentState, previousWatched);
61
+ });
62
+ store._updateStateWithoutReaction(nextState);
63
+ }
64
+ };
65
+ };
66
+ }
67
+ /**
68
+ * A framework-agnostic, Immer-backed state container.
69
+ *
70
+ * The store owns a single immutable state value and a `Set` of plain
71
+ * listeners. Every mutation runs through Immer's `produce`, and listeners are
72
+ * only notified when the resulting root reference actually changes — making
73
+ * "no-op" updates genuinely free for subscribers.
74
+ *
75
+ * @typeParam S Your store's state interface.
76
+ */
77
+ var Store = class {
78
+ currentState;
79
+ createInitialState;
80
+ ssr = false;
81
+ /** Plain pub/sub listeners — a Set both dedupes and dispatches fast. */
82
+ listeners = /* @__PURE__ */ new Set();
83
+ reactionCreators = [];
84
+ reactions = [];
85
+ clientSubscriptions = [];
86
+ /**
87
+ * @internal
88
+ */
89
+ _patchListeners = [];
90
+ constructor(initialState) {
91
+ if (initialState instanceof Function) {
92
+ this.createInitialState = initialState;
93
+ this.currentState = initialState();
94
+ } else {
95
+ this.createInitialState = () => initialState;
96
+ this.currentState = initialState;
97
+ }
98
+ }
99
+ get state() {
100
+ return Object.freeze(this.currentState);
101
+ }
102
+ /**
103
+ * @internal
104
+ */
105
+ _setInternalOptions({ ssr, reactionCreators = [] }) {
106
+ this.ssr = ssr;
107
+ this.reactionCreators = reactionCreators;
108
+ this.reactions = reactionCreators.map((rc) => rc(this));
109
+ }
110
+ /**
111
+ * @internal
112
+ */
113
+ _getReactionCreators() {
114
+ return this.reactionCreators;
115
+ }
116
+ /**
117
+ * @internal
118
+ */
119
+ _instantiateReactions() {
120
+ this.reactions = this.reactionCreators.map((rc) => rc(this));
121
+ }
122
+ /**
123
+ * @internal
124
+ */
125
+ _getInitialState() {
126
+ return this.createInitialState();
127
+ }
128
+ /**
129
+ * @internal
130
+ */
131
+ _hasPatchListeners() {
132
+ return this._patchListeners.length > 0;
133
+ }
134
+ /**
135
+ * @internal
136
+ */
137
+ _emitPatches(patches, inversePatches) {
138
+ for (const listener of this._patchListeners) listener(patches, inversePatches);
139
+ }
140
+ /**
141
+ * @internal
142
+ *
143
+ * Writes a new state value without running reactions. Used by reactions
144
+ * themselves to avoid re-entrancy.
145
+ */
146
+ _updateStateWithoutReaction(nextState) {
147
+ this.currentState = nextState;
148
+ }
149
+ /**
150
+ * @internal
151
+ *
152
+ * Commits a new root state, runs reactions, then dispatches to all
153
+ * subscribers. Callers are responsible for the `nextState !== currentState`
154
+ * reference guard before invoking this.
155
+ */
156
+ _updateState(nextState) {
157
+ this.currentState = nextState;
158
+ for (const runReaction of this.reactions) runReaction();
159
+ if (this.ssr) return;
160
+ for (const runSubscription of this.clientSubscriptions) runSubscription();
161
+ for (const listener of this.listeners) listener();
162
+ }
163
+ /**
164
+ * Returns the raw state object contained within this store at this moment.
165
+ *
166
+ * ---
167
+ * ** WARNING **
168
+ *
169
+ * Most of the time, if you're using this in your app, there's probably a
170
+ * better way to do it (a selector subscription or the React adapter).
171
+ * ---
172
+ */
173
+ getRawState() {
174
+ return this.currentState;
175
+ }
176
+ /**
177
+ * Subscribe a plain listener to store mutations. The listener fires once per
178
+ * committed update (root reference change) and receives no arguments — read
179
+ * the latest value with {@link getRawState}.
180
+ *
181
+ * This is the low-level primitive that vanilla code and framework adapters
182
+ * (e.g. React's `useSyncExternalStore`) build upon.
183
+ *
184
+ * @returns An unsubscribe function.
185
+ */
186
+ subscribe(listener) {
187
+ this.listeners.add(listener);
188
+ return () => {
189
+ this.listeners.delete(listener);
190
+ };
191
+ }
192
+ /**
193
+ * Subscribe to a derived slice of state. The `listener` only fires when the
194
+ * watched value changes structurally (per the Fast-Path rule).
195
+ *
196
+ * @returns An unsubscribe function.
197
+ */
198
+ watch(watch, listener) {
199
+ if (this.ssr) return () => {
200
+ console.warn(`@nice-code/state: Subscriptions made on the server side are not registered, so this unsubscribe call does nothing.`);
201
+ };
202
+ const run = makeSubscriptionFunction(this, watch, listener);
203
+ this.clientSubscriptions.push(run);
204
+ return () => {
205
+ this.clientSubscriptions = this.clientSubscriptions.filter((f) => f !== run);
206
+ };
207
+ }
208
+ /**
209
+ * Register a reaction: when the watched slice changes, the `reaction` recipe
210
+ * runs inside Immer to derive further state on the same store.
211
+ *
212
+ * @returns A function that removes the reaction.
213
+ */
214
+ createReaction(watch, reaction, { runNow = false, runNowWithSideEffects = false } = {}) {
215
+ const creator = makeReactionFunctionCreator(watch, reaction);
216
+ this.reactionCreators.push(creator);
217
+ const run = creator(this);
218
+ this.reactions.push(run);
219
+ if (runNow || runNowWithSideEffects) {
220
+ run(true);
221
+ if (runNowWithSideEffects && !this.ssr) this._updateState(this.currentState);
222
+ }
223
+ return () => {
224
+ this.reactions = this.reactions.filter((f) => f !== run);
225
+ this.reactionCreators = this.reactionCreators.filter((f) => f !== creator);
226
+ };
227
+ }
228
+ /**
229
+ * Subscribe to the Immer patches produced by each update.
230
+ *
231
+ * @returns An unsubscribe function.
232
+ */
233
+ listenToPatches(patchListener) {
234
+ this._patchListeners.push(patchListener);
235
+ return () => {
236
+ this._patchListeners = this._patchListeners.filter((f) => f !== patchListener);
237
+ };
238
+ }
239
+ /**
240
+ * Mutate the store via one or more Immer update functions.
241
+ *
242
+ * @param updater A single update function, or an array applied in order.
243
+ * @param patchesCallback Optional callback receiving the patches for this update.
244
+ */
245
+ update(updater, patchesCallback) {
246
+ update(this, updater, patchesCallback);
247
+ }
248
+ /**
249
+ * Replace the store's state entirely with a new state value.
250
+ */
251
+ replace(newState) {
252
+ if (newState !== this.currentState) this._updateState(newState);
253
+ }
254
+ /**
255
+ * Replace the store's state by mapping from the current state.
256
+ */
257
+ replaceFromCurrent(replacer) {
258
+ const nextState = replacer(this.currentState);
259
+ if (nextState !== this.currentState) this._updateState(nextState);
260
+ }
261
+ /**
262
+ * Apply a set of Immer patches to the store.
263
+ */
264
+ applyPatches(patches) {
265
+ applyPatchesToStore(this, patches);
266
+ }
267
+ };
268
+ /**
269
+ * Apply Immer patches to a store, committing only if the root reference changes.
270
+ */
271
+ function applyPatchesToStore(store, patches) {
272
+ const currentState = store.getRawState();
273
+ const nextState = applyPatches(currentState, patches);
274
+ if (nextState !== currentState) store._updateState(nextState);
275
+ }
276
+ /**
277
+ * @internal
278
+ *
279
+ * Runs an updater (or array of updaters) through Immer, collecting patches.
280
+ */
281
+ function applyUpdaterWithPatches(currentState, updater) {
282
+ if (typeof updater === "function") {
283
+ const [next, patches, inversePatches] = produceWithPatches(currentState, (draft) => {
284
+ updater(draft, currentState);
285
+ });
286
+ return [
287
+ next,
288
+ patches,
289
+ inversePatches
290
+ ];
291
+ }
292
+ let state = currentState;
293
+ const patches = [];
294
+ const inversePatches = [];
295
+ for (const single of updater) {
296
+ const [next, p, ip] = produceWithPatches(state, (draft) => {
297
+ single(draft, state);
298
+ });
299
+ state = next;
300
+ patches.push(...p);
301
+ inversePatches.push(...ip);
302
+ }
303
+ return [
304
+ state,
305
+ patches,
306
+ inversePatches
307
+ ];
308
+ }
309
+ /**
310
+ * @internal
311
+ *
312
+ * Runs an updater (or array of updaters) through Immer without tracking patches.
313
+ */
314
+ function applyUpdater(currentState, updater) {
315
+ if (typeof updater === "function") return produce(currentState, (draft) => {
316
+ updater(draft, currentState);
317
+ });
318
+ return updater.reduce((previousState, single) => produce(previousState, (draft) => {
319
+ single(draft, previousState);
320
+ }), currentState);
321
+ }
322
+ /**
323
+ * Mutate a store via one or more Immer update functions.
324
+ *
325
+ * Patches are only computed when there's a consumer for them (a registered
326
+ * patch listener or a `patchesCallback`), keeping the common path allocation-free.
327
+ * Listeners are notified only when the root reference actually changes.
328
+ *
329
+ * @param store The store to update.
330
+ * @param updater A single update function, or an array applied in order.
331
+ * @param patchesCallback Optional callback receiving the patches for this update.
332
+ */
333
+ function update(store, updater, patchesCallback) {
334
+ const currentState = store.getRawState();
335
+ let nextState;
336
+ if (store._hasPatchListeners() || patchesCallback != null) {
337
+ const [next, patches, inversePatches] = applyUpdaterWithPatches(currentState, updater);
338
+ if (patches.length > 0) {
339
+ if (patchesCallback != null) patchesCallback(patches, inversePatches);
340
+ store._emitPatches(patches, inversePatches);
341
+ }
342
+ nextState = next;
343
+ } else nextState = applyUpdater(currentState, updater);
344
+ if (nextState !== currentState) store._updateState(nextState);
345
+ }
346
+ //#endregion
347
+ export { applyPatchesToStore as n, update as r, Store as t };
348
+
349
+ //# sourceMappingURL=Store-PjfFkZ2I.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Store-PjfFkZ2I.js","names":[],"sources":["../src/core/Store.ts"],"sourcesContent":["import { deepEqual } from \"fast-equals\";\r\nimport {\r\n applyPatches,\r\n type Draft,\r\n enablePatches,\r\n type Patch,\r\n type PatchListener,\r\n produce,\r\n produceWithPatches,\r\n} from \"immer\";\r\n\r\n// Immer emits JSON patches for `produceWithPatches`, which the store exposes via\r\n// `listenToPatches`. This must run once, before any patch-producing update.\r\nenablePatches();\r\n\r\n/**\r\n * A plain pub/sub listener. Fired (in the order added) every time the store's\r\n * root state reference changes. This is the vanilla integration point that any\r\n * ecosystem — including the React adapter's `useSyncExternalStore` — builds on.\r\n */\r\nexport type TUpdateListener = () => void;\r\n\r\n/**\r\n * @typeParam S The store's state\r\n * @param draft The mutable draft to change during this update (Immer proxy).\r\n * @param original A readonly snapshot of the state as it was before this update.\r\n */\r\nexport type TUpdateFunction<S> = (draft: Draft<S>, original: S) => void;\r\n\r\n/**\r\n * A selector that derives a watched slice `T` from the full store state `S`.\r\n */\r\nexport type TStoreWatch<S extends object, T> = (state: S) => T;\r\n\r\n/**\r\n * Fired by {@link Store.watch} whenever the watched slice changes structurally.\r\n */\r\nexport type TStoreSubscriptionListener<S extends object, T> = (\r\n watched: T,\r\n allState: S,\r\n previousWatched: T,\r\n) => void;\r\n\r\n/**\r\n * Runs inside an Immer `produce` whenever a watched slice changes, letting the\r\n * store derive further state from its own mutations.\r\n */\r\nexport type TReactionFunction<S extends object, T> = (\r\n watched: T,\r\n draft: Draft<S>,\r\n original: S,\r\n previousWatched: T,\r\n) => void;\r\n\r\nexport type TStoreActionUpdate<S extends object> = (\r\n updater: TUpdateFunction<S> | TUpdateFunction<S>[],\r\n patchesCallback?: TPatchesCallback,\r\n) => void;\r\n\r\nexport type TStoreAction<S extends object> = (update: TStoreActionUpdate<S>) => void;\r\n\r\nexport type TPatchesCallback = (patches: Patch[], inversePatches: Patch[]) => void;\r\n\r\n/**\r\n * @internal\r\n * Drives a registered reaction. `forceRun` bypasses the change-detection\r\n * fast-path (used when a reaction is created with `runNow`).\r\n */\r\ntype TRunReactionFunction = (forceRun?: boolean) => void;\r\n\r\n/**\r\n * @internal\r\n * Drives a registered selector subscription on every store emission.\r\n */\r\ntype TRunSubscriptionFunction = () => void;\r\n\r\n/**\r\n * @internal\r\n * Binds a reaction definition to a concrete store instance.\r\n */\r\ntype TReactionCreator<S extends object> = (store: Store<S>) => TRunReactionFunction;\r\n\r\nexport interface IStoreInternalOptions<S extends object> {\r\n ssr: boolean;\r\n reactionCreators?: TReactionCreator<S>[];\r\n}\r\n\r\nexport interface ICreateReactionOptions {\r\n runNow?: boolean;\r\n runNowWithSideEffects?: boolean;\r\n}\r\n\r\n/**\r\n * @internal\r\n *\r\n * Builds the per-emission runner for a selector subscription.\r\n *\r\n * Change detection follows the \"Fast-Path\" rule: Immer's structural sharing\r\n * means an untouched branch keeps its exact reference, so a strict `===` check\r\n * resolves the overwhelmingly common \"nothing changed\" case in 0ms. Only when\r\n * the reference actually changes do we pay for a `deepEqual` traversal to\r\n * confirm the change is structural and not just a new-but-equal reference.\r\n */\r\nfunction makeSubscriptionFunction<S extends object, T>(\r\n store: Store<S>,\r\n watch: TStoreWatch<S, T>,\r\n listener: TStoreSubscriptionListener<S, T>,\r\n): TRunSubscriptionFunction {\r\n let lastWatchState: T = watch(store.getRawState());\r\n\r\n return () => {\r\n const currentState = store.getRawState();\r\n const nextWatchState = watch(currentState);\r\n\r\n // Fast-path: reference is identical → the watched branch was never touched.\r\n if (nextWatchState === lastWatchState) {\r\n return;\r\n }\r\n\r\n // Reference changed — fall back to deep equality to confirm real change.\r\n if (deepEqual(nextWatchState, lastWatchState)) {\r\n // Structurally equal: adopt the new reference so the fast-path stays hot,\r\n // but do not notify — nothing the watcher cares about actually changed.\r\n lastWatchState = nextWatchState;\r\n return;\r\n }\r\n\r\n const previousWatched = lastWatchState;\r\n lastWatchState = nextWatchState;\r\n listener(nextWatchState, currentState, previousWatched);\r\n };\r\n}\r\n\r\n/**\r\n * @internal\r\n *\r\n * Builds a reaction creator. Reactions follow the same Fast-Path rule as\r\n * subscriptions, then run their recipe inside Immer to derive further state.\r\n */\r\nfunction makeReactionFunctionCreator<S extends object, T>(\r\n watch: TStoreWatch<S, T>,\r\n reaction: TReactionFunction<S, T>,\r\n): TReactionCreator<S> {\r\n return (store) => {\r\n let lastWatchState: T = watch(store.getRawState());\r\n\r\n return (forceRun = false) => {\r\n const currentState = store.getRawState();\r\n const nextWatchState = watch(currentState);\r\n\r\n if (!forceRun) {\r\n // Fast-path: identical reference → skip entirely.\r\n if (nextWatchState === lastWatchState) {\r\n return;\r\n }\r\n\r\n // New reference but structurally equal → adopt and skip the recipe.\r\n if (deepEqual(nextWatchState, lastWatchState)) {\r\n lastWatchState = nextWatchState;\r\n return;\r\n }\r\n }\r\n\r\n const previousWatched = lastWatchState;\r\n lastWatchState = nextWatchState;\r\n\r\n // Reactions mutate via Immer but must not re-enter the reaction loop, so\r\n // they write back through the no-reaction update path.\r\n if (store._hasPatchListeners()) {\r\n const [nextState, patches, inversePatches] = produceWithPatches(\r\n currentState,\r\n (draft: Draft<S>) => {\r\n reaction(nextWatchState, draft, currentState, previousWatched);\r\n },\r\n );\r\n\r\n store._updateStateWithoutReaction(nextState);\r\n\r\n if (patches.length > 0) {\r\n store._emitPatches(patches, inversePatches);\r\n }\r\n } else {\r\n const nextState = produce(currentState, (draft: Draft<S>) => {\r\n reaction(nextWatchState, draft, currentState, previousWatched);\r\n });\r\n store._updateStateWithoutReaction(nextState);\r\n }\r\n };\r\n };\r\n}\r\n\r\n/**\r\n * A framework-agnostic, Immer-backed state container.\r\n *\r\n * The store owns a single immutable state value and a `Set` of plain\r\n * listeners. Every mutation runs through Immer's `produce`, and listeners are\r\n * only notified when the resulting root reference actually changes — making\r\n * \"no-op\" updates genuinely free for subscribers.\r\n *\r\n * @typeParam S Your store's state interface.\r\n */\r\nexport class Store<S extends object = object> {\r\n private currentState: S;\r\n private readonly createInitialState: () => S;\r\n private ssr = false;\r\n\r\n /** Plain pub/sub listeners — a Set both dedupes and dispatches fast. */\r\n private readonly listeners = new Set<TUpdateListener>();\r\n\r\n private reactionCreators: TReactionCreator<S>[] = [];\r\n private reactions: TRunReactionFunction[] = [];\r\n private clientSubscriptions: TRunSubscriptionFunction[] = [];\r\n\r\n /**\r\n * @internal\r\n */\r\n public _patchListeners: PatchListener[] = [];\r\n\r\n constructor(initialState: S | (() => S)) {\r\n if (initialState instanceof Function) {\r\n this.createInitialState = initialState;\r\n this.currentState = initialState();\r\n } else {\r\n this.createInitialState = () => initialState;\r\n this.currentState = initialState;\r\n }\r\n }\r\n\r\n get state(): S {\r\n return Object.freeze(this.currentState);\r\n }\r\n\r\n /**\r\n * @internal\r\n */\r\n _setInternalOptions({ ssr, reactionCreators = [] }: IStoreInternalOptions<S>) {\r\n this.ssr = ssr;\r\n this.reactionCreators = reactionCreators;\r\n this.reactions = reactionCreators.map((rc) => rc(this));\r\n }\r\n\r\n /**\r\n * @internal\r\n */\r\n _getReactionCreators(): TReactionCreator<S>[] {\r\n return this.reactionCreators;\r\n }\r\n\r\n /**\r\n * @internal\r\n */\r\n _instantiateReactions() {\r\n this.reactions = this.reactionCreators.map((rc) => rc(this));\r\n }\r\n\r\n /**\r\n * @internal\r\n */\r\n _getInitialState(): S {\r\n return this.createInitialState();\r\n }\r\n\r\n /**\r\n * @internal\r\n */\r\n _hasPatchListeners(): boolean {\r\n return this._patchListeners.length > 0;\r\n }\r\n\r\n /**\r\n * @internal\r\n */\r\n _emitPatches(patches: Patch[], inversePatches: Patch[]) {\r\n for (const listener of this._patchListeners) {\r\n listener(patches, inversePatches);\r\n }\r\n }\r\n\r\n /**\r\n * @internal\r\n *\r\n * Writes a new state value without running reactions. Used by reactions\r\n * themselves to avoid re-entrancy.\r\n */\r\n _updateStateWithoutReaction(nextState: S) {\r\n this.currentState = nextState;\r\n }\r\n\r\n /**\r\n * @internal\r\n *\r\n * Commits a new root state, runs reactions, then dispatches to all\r\n * subscribers. Callers are responsible for the `nextState !== currentState`\r\n * reference guard before invoking this.\r\n */\r\n _updateState(nextState: S) {\r\n this.currentState = nextState;\r\n\r\n // Reactions run first and may derive further state (without re-triggering).\r\n for (const runReaction of this.reactions) {\r\n runReaction();\r\n }\r\n\r\n if (this.ssr) {\r\n return;\r\n }\r\n\r\n for (const runSubscription of this.clientSubscriptions) {\r\n runSubscription();\r\n }\r\n\r\n for (const listener of this.listeners) {\r\n listener();\r\n }\r\n }\r\n\r\n /**\r\n * Returns the raw state object contained within this store at this moment.\r\n *\r\n * ---\r\n * ** WARNING **\r\n *\r\n * Most of the time, if you're using this in your app, there's probably a\r\n * better way to do it (a selector subscription or the React adapter).\r\n * ---\r\n */\r\n getRawState(): S {\r\n return this.currentState;\r\n }\r\n\r\n /**\r\n * Subscribe a plain listener to store mutations. The listener fires once per\r\n * committed update (root reference change) and receives no arguments — read\r\n * the latest value with {@link getRawState}.\r\n *\r\n * This is the low-level primitive that vanilla code and framework adapters\r\n * (e.g. React's `useSyncExternalStore`) build upon.\r\n *\r\n * @returns An unsubscribe function.\r\n */\r\n subscribe(listener: TUpdateListener): () => void {\r\n this.listeners.add(listener);\r\n return () => {\r\n this.listeners.delete(listener);\r\n };\r\n }\r\n\r\n /**\r\n * Subscribe to a derived slice of state. The `listener` only fires when the\r\n * watched value changes structurally (per the Fast-Path rule).\r\n *\r\n * @returns An unsubscribe function.\r\n */\r\n watch<T>(watch: TStoreWatch<S, T>, listener: TStoreSubscriptionListener<S, T>): () => void {\r\n if (this.ssr) {\r\n return () => {\r\n console.warn(\r\n `@nice-code/state: Subscriptions made on the server side are not registered, so this unsubscribe call does nothing.`,\r\n );\r\n };\r\n }\r\n\r\n const run = makeSubscriptionFunction(this, watch, listener);\r\n this.clientSubscriptions.push(run);\r\n\r\n return () => {\r\n this.clientSubscriptions = this.clientSubscriptions.filter((f) => f !== run);\r\n };\r\n }\r\n\r\n /**\r\n * Register a reaction: when the watched slice changes, the `reaction` recipe\r\n * runs inside Immer to derive further state on the same store.\r\n *\r\n * @returns A function that removes the reaction.\r\n */\r\n createReaction<T>(\r\n watch: TStoreWatch<S, T>,\r\n reaction: TReactionFunction<S, T>,\r\n { runNow = false, runNowWithSideEffects = false }: ICreateReactionOptions = {},\r\n ): () => void {\r\n const creator = makeReactionFunctionCreator(watch, reaction);\r\n this.reactionCreators.push(creator);\r\n\r\n const run = creator(this);\r\n this.reactions.push(run);\r\n\r\n if (runNow || runNowWithSideEffects) {\r\n run(true);\r\n\r\n if (runNowWithSideEffects && !this.ssr) {\r\n this._updateState(this.currentState);\r\n }\r\n }\r\n\r\n return () => {\r\n this.reactions = this.reactions.filter((f) => f !== run);\r\n this.reactionCreators = this.reactionCreators.filter((f) => f !== creator);\r\n };\r\n }\r\n\r\n /**\r\n * Subscribe to the Immer patches produced by each update.\r\n *\r\n * @returns An unsubscribe function.\r\n */\r\n listenToPatches(patchListener: PatchListener): () => void {\r\n this._patchListeners.push(patchListener);\r\n return () => {\r\n this._patchListeners = this._patchListeners.filter((f) => f !== patchListener);\r\n };\r\n }\r\n\r\n /**\r\n * Mutate the store via one or more Immer update functions.\r\n *\r\n * @param updater A single update function, or an array applied in order.\r\n * @param patchesCallback Optional callback receiving the patches for this update.\r\n */\r\n update(updater: TUpdateFunction<S> | TUpdateFunction<S>[], patchesCallback?: TPatchesCallback) {\r\n update(this, updater, patchesCallback);\r\n }\r\n\r\n /**\r\n * Replace the store's state entirely with a new state value.\r\n */\r\n replace(newState: S) {\r\n if (newState !== this.currentState) {\r\n this._updateState(newState);\r\n }\r\n }\r\n\r\n /**\r\n * Replace the store's state by mapping from the current state.\r\n */\r\n replaceFromCurrent(replacer: (state: S) => S) {\r\n const nextState = replacer(this.currentState);\r\n if (nextState !== this.currentState) {\r\n this._updateState(nextState);\r\n }\r\n }\r\n\r\n /**\r\n * Apply a set of Immer patches to the store.\r\n */\r\n applyPatches(patches: Patch[]) {\r\n applyPatchesToStore(this, patches);\r\n }\r\n}\r\n\r\n/**\r\n * Apply Immer patches to a store, committing only if the root reference changes.\r\n */\r\nexport function applyPatchesToStore<S extends object = object>(store: Store<S>, patches: Patch[]) {\r\n const currentState = store.getRawState();\r\n const nextState = applyPatches(currentState, patches);\r\n if (nextState !== currentState) {\r\n store._updateState(nextState);\r\n }\r\n}\r\n\r\n/**\r\n * @internal\r\n *\r\n * Runs an updater (or array of updaters) through Immer, collecting patches.\r\n */\r\nfunction applyUpdaterWithPatches<S extends object>(\r\n currentState: S,\r\n updater: TUpdateFunction<S> | TUpdateFunction<S>[],\r\n): [S, Patch[], Patch[]] {\r\n if (typeof updater === \"function\") {\r\n const [next, patches, inversePatches] = produceWithPatches(currentState, (draft: Draft<S>) => {\r\n updater(draft, currentState);\r\n });\r\n return [next, patches, inversePatches];\r\n }\r\n\r\n let state = currentState;\r\n const patches: Patch[] = [];\r\n const inversePatches: Patch[] = [];\r\n\r\n for (const single of updater) {\r\n const [next, p, ip] = produceWithPatches(state, (draft: Draft<S>) => {\r\n single(draft, state);\r\n });\r\n state = next;\r\n patches.push(...p);\r\n inversePatches.push(...ip);\r\n }\r\n\r\n return [state, patches, inversePatches];\r\n}\r\n\r\n/**\r\n * @internal\r\n *\r\n * Runs an updater (or array of updaters) through Immer without tracking patches.\r\n */\r\nfunction applyUpdater<S extends object>(\r\n currentState: S,\r\n updater: TUpdateFunction<S> | TUpdateFunction<S>[],\r\n): S {\r\n if (typeof updater === \"function\") {\r\n return produce(currentState, (draft: Draft<S>) => {\r\n updater(draft, currentState);\r\n });\r\n }\r\n\r\n return updater.reduce<S>(\r\n (previousState, single) =>\r\n produce(previousState, (draft: Draft<S>) => {\r\n single(draft, previousState);\r\n }),\r\n currentState,\r\n );\r\n}\r\n\r\n/**\r\n * Mutate a store via one or more Immer update functions.\r\n *\r\n * Patches are only computed when there's a consumer for them (a registered\r\n * patch listener or a `patchesCallback`), keeping the common path allocation-free.\r\n * Listeners are notified only when the root reference actually changes.\r\n *\r\n * @param store The store to update.\r\n * @param updater A single update function, or an array applied in order.\r\n * @param patchesCallback Optional callback receiving the patches for this update.\r\n */\r\nexport function update<S extends object = object>(\r\n store: Store<S>,\r\n updater: TUpdateFunction<S> | TUpdateFunction<S>[],\r\n patchesCallback?: TPatchesCallback,\r\n) {\r\n const currentState = store.getRawState();\r\n\r\n let nextState: S;\r\n\r\n if (store._hasPatchListeners() || patchesCallback != null) {\r\n const [next, patches, inversePatches] = applyUpdaterWithPatches(currentState, updater);\r\n\r\n if (patches.length > 0) {\r\n if (patchesCallback != null) {\r\n patchesCallback(patches, inversePatches);\r\n }\r\n store._emitPatches(patches, inversePatches);\r\n }\r\n\r\n nextState = next;\r\n } else {\r\n nextState = applyUpdater(currentState, updater);\r\n }\r\n\r\n // Reference guard: an updater that mutated nothing yields the same reference,\r\n // so we skip the dispatch entirely.\r\n if (nextState !== currentState) {\r\n store._updateState(nextState);\r\n }\r\n}\r\n"],"mappings":"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"}
@@ -0,0 +1,120 @@
1
+ import { r as Store } from "../../Store-B65MojT2.js";
2
+ import { Patch } from "immer";
3
+ //#region ../nice-devtools-shared/src/components/PanelChrome.d.ts
4
+ /** Where a devtools panel is docked. */
5
+ type TDevtoolsPosition = "dock-bottom" | "dock-top" | "dock-left" | "dock-right";
6
+ //#endregion
7
+ //#region src/devtools/core/StateDevtools.types.d.ts
8
+ /**
9
+ * How a recorded change came to be. `update` is the normal Immer-patch path,
10
+ * `replace` is a whole-state swap with no patches, and the two `devtools-*`
11
+ * sources are writes the devtools itself made (manual edits / reverts) so they
12
+ * can be visually distinguished from real app traffic.
13
+ */
14
+ type TStateChangeSource = "update" | "replace" | "devtools-edit" | "devtools-revert";
15
+ /**
16
+ * A single committed mutation of a registered store. Captures both the Immer
17
+ * patches (when available) and full before/after snapshots so the panel can
18
+ * render a precise diff and offer a one-click revert.
19
+ */
20
+ interface IDevtoolsStateChange {
21
+ cuid: string;
22
+ storeId: string;
23
+ storeLabel: string;
24
+ timestamp: number;
25
+ patches: Patch[];
26
+ inversePatches: Patch[];
27
+ prevSnapshot: unknown;
28
+ snapshot: unknown;
29
+ source: TStateChangeSource;
30
+ }
31
+ /**
32
+ * Live summary of a registered store, refreshed on every commit so the panel's
33
+ * tabs and state inspector always reflect the current value.
34
+ */
35
+ interface IDevtoolsStoreInfo {
36
+ id: string;
37
+ label: string;
38
+ currentState: unknown;
39
+ changeCount: number;
40
+ lastChangeTime?: number;
41
+ }
42
+ interface IStateDevtoolsSnapshot {
43
+ stores: IDevtoolsStoreInfo[];
44
+ /** Most-recent-first across all registered stores. */
45
+ changes: IDevtoolsStateChange[];
46
+ paused: boolean;
47
+ }
48
+ type TStateDevtoolsListener = (snapshot: IStateDevtoolsSnapshot) => void;
49
+ //#endregion
50
+ //#region src/devtools/core/StateDevtoolsCore.d.ts
51
+ interface IStateDevtoolsCoreOptions {
52
+ /** Cap on retained changes across all stores (oldest dropped first). */
53
+ maxChanges?: number;
54
+ }
55
+ /**
56
+ * Framework-agnostic collector for nice-state stores.
57
+ *
58
+ * Register any {@link Store} and the core hooks its patch + update streams,
59
+ * pairing the two so each committed mutation becomes a single
60
+ * {@link IDevtoolsStateChange} with patches and full before/after snapshots.
61
+ * The browser panel ({@link NiceStateDevtools}) renders whatever this exposes.
62
+ *
63
+ * Registering a store attaches a patch listener, which makes Immer compute
64
+ * patches for that store's updates — a negligible dev-time cost. Keep this out
65
+ * of production bundles (the panel is dev-gated, but the core is not).
66
+ */
67
+ declare class StateDevtoolsCore {
68
+ private readonly _stores;
69
+ private _changes;
70
+ private readonly _listeners;
71
+ private readonly _maxChanges;
72
+ private _paused;
73
+ private _cuidCounter;
74
+ private _sourceOverride;
75
+ constructor(options?: IStateDevtoolsCoreOptions);
76
+ /**
77
+ * Start observing a store under a human-readable label. Returns an
78
+ * unregister function. If the label collides with an existing store, a numeric
79
+ * suffix is appended to keep ids unique.
80
+ */
81
+ registerStore(label: string, store: Store<any>): () => void;
82
+ unregisterStore(id: string): void;
83
+ /**
84
+ * Replace a registered store's state wholesale — the primary "edit directly
85
+ * for testing" entry point. The resulting change is tagged `devtools-edit`.
86
+ */
87
+ applyEdit(storeId: string, newState: unknown): void;
88
+ /**
89
+ * Undo a change by applying its inverse patches. Cleanest for the most recent
90
+ * change of a store; older reverts may not apply if later changes touched the
91
+ * same paths. The resulting change is tagged `devtools-revert`.
92
+ */
93
+ revertChange(change: IDevtoolsStateChange): void;
94
+ setPaused(paused: boolean): void;
95
+ togglePaused(): void;
96
+ /** Drop the recorded timeline; registered stores and their state remain. */
97
+ clear(): void;
98
+ getSnapshot(): IStateDevtoolsSnapshot;
99
+ subscribe(listener: TStateDevtoolsListener): () => void;
100
+ private _recordChange;
101
+ private _uniqueId;
102
+ private _buildSnapshot;
103
+ private _notify;
104
+ }
105
+ //#endregion
106
+ //#region src/devtools/browser/NiceStateDevtools.d.ts
107
+ interface INiceStateDevtoolsProps {
108
+ core: StateDevtoolsCore;
109
+ position?: TDevtoolsPosition;
110
+ initialOpen?: boolean;
111
+ /** Show the panel even when NODE_ENV is not "development". */
112
+ forceEnable?: boolean;
113
+ }
114
+ declare function NiceStateDevtools({
115
+ forceEnable,
116
+ ...props
117
+ }: INiceStateDevtoolsProps): import("react/jsx-runtime").JSX.Element | null;
118
+ //#endregion
119
+ export { type IDevtoolsStateChange, type IDevtoolsStoreInfo, type INiceStateDevtoolsProps, type IStateDevtoolsCoreOptions, type IStateDevtoolsSnapshot, NiceStateDevtools, StateDevtoolsCore, type TDevtoolsPosition, type TStateChangeSource, type TStateDevtoolsListener };
120
+ //# sourceMappingURL=index.d.ts.map