synstate 6.0.0 → 6.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 +4 -3
- package/dist/core/class/manager-observable-class.d.mts.map +1 -1
- package/dist/core/class/manager-observable-class.mjs +6 -0
- package/dist/core/class/manager-observable-class.mjs.map +1 -1
- package/dist/core/class/observable-base-class.d.mts +8 -0
- package/dist/core/class/observable-base-class.d.mts.map +1 -1
- package/dist/core/class/observable-base-class.mjs +16 -1
- package/dist/core/class/observable-base-class.mjs.map +1 -1
- package/dist/core/class/propagation-state.d.mts +6 -3
- package/dist/core/class/propagation-state.d.mts.map +1 -1
- package/dist/core/class/propagation-state.mjs +4 -0
- package/dist/core/class/propagation-state.mjs.map +1 -1
- package/dist/core/combine/combine.d.mts.map +1 -1
- package/dist/core/combine/combine.mjs +3 -43
- package/dist/core/combine/combine.mjs.map +1 -1
- package/dist/core/combine/derive.d.mts +63 -0
- package/dist/core/combine/derive.d.mts.map +1 -0
- package/dist/core/combine/derive.mjs +124 -0
- package/dist/core/combine/derive.mjs.map +1 -0
- package/dist/core/combine/index.d.mts +1 -0
- package/dist/core/combine/index.d.mts.map +1 -1
- package/dist/core/combine/index.mjs +1 -0
- package/dist/core/combine/index.mjs.map +1 -1
- package/dist/core/types/id.d.mts +2 -1
- package/dist/core/types/id.d.mts.map +1 -1
- package/dist/core/types/observable-family.d.mts +3 -0
- package/dist/core/types/observable-family.d.mts.map +1 -1
- package/dist/core/types/observable-family.mjs.map +1 -1
- package/dist/core/types/observable.d.mts +2 -1
- package/dist/core/types/observable.d.mts.map +1 -1
- package/dist/core/types/observable.mjs.map +1 -1
- package/dist/core/utils/id-maker.d.mts +7 -0
- package/dist/core/utils/id-maker.d.mts.map +1 -1
- package/dist/core/utils/id-maker.mjs +9 -0
- package/dist/core/utils/id-maker.mjs.map +1 -1
- package/dist/utils/create-reducer.d.mts +2 -2
- package/dist/utils/create-reducer.d.mts.map +1 -1
- package/dist/utils/create-reducer.mjs +4 -16
- package/dist/utils/create-reducer.mjs.map +1 -1
- package/dist/utils/create-state.d.mts +1 -1
- package/dist/utils/create-state.d.mts.map +1 -1
- package/dist/utils/create-state.mjs +10 -13
- package/dist/utils/create-state.mjs.map +1 -1
- package/dist/utils/state-source.d.mts +19 -0
- package/dist/utils/state-source.d.mts.map +1 -0
- package/dist/utils/state-source.mjs +31 -0
- package/dist/utils/state-source.mjs.map +1 -0
- package/package.json +13 -11
- package/src/core/class/manager-observable-class.mts +7 -0
- package/src/core/class/observable-base-class.mts +22 -2
- package/src/core/class/propagation-state.mts +11 -7
- package/src/core/class/unobserved-write.test.mts +194 -0
- package/src/core/combine/combine.mts +7 -72
- package/src/core/combine/derive.mts +172 -0
- package/src/core/combine/derive.test.mts +190 -0
- package/src/core/combine/index.mts +1 -0
- package/src/core/types/id.mts +2 -1
- package/src/core/types/observable-family.mts +18 -0
- package/src/core/types/observable.mts +2 -1
- package/src/core/utils/id-maker.mts +10 -0
- package/src/utils/create-reducer.mts +9 -24
- package/src/utils/create-state.mts +12 -29
- package/src/utils/create-state.test.mts +18 -0
- package/src/utils/state-source.mts +48 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observable.d.mts","sourceRoot":"","sources":["../../../src/core/types/observable.mts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,QAAQ,EACb,KAAK,IAAI,EACV,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAoB,UAAU,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAErE;;;;;;;;;;;;GAYG;AAEH,KAAK,oBAAoB,CAAC,CAAC,EAAE,IAAI,SAAS,cAAc,IAAI,QAAQ,CAAC;IACnE,CAAC,eAAe,CAAC,EAAE,IAAI,CAAC;IAExB,IAAI,EAAE,IAAI,CAAC;IAEX;;;;OAIG;IACH,KAAK,EAAE,IAAI,SAAS,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC;IAExC,WAAW,EAAE,MAAM,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC/B,WAAW,EAAE,OAAO,CAAC;IAErB
|
|
1
|
+
{"version":3,"file":"observable.d.mts","sourceRoot":"","sources":["../../../src/core/types/observable.mts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observable.mjs","sourceRoot":"","sources":["../../../src/core/types/observable.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,MAAM,EACN,QAAQ,GAGT,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"observable.mjs","sourceRoot":"","sources":["../../../src/core/types/observable.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,MAAM,EACN,QAAQ,GAGT,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAsKrD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,KAAc,EAAgC,EAAE,CAC3E,QAAQ,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;AAEpD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,GAAkB,EACW,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,YAAY,CAAC;AAE5D,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,GAAkB,EACQ,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,MAAM,CAAC;AAEnD,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,GAAkB,EACS,EAAE,CAC7B,GAAG,CAAC,IAAI,KAAK,YAAY,IAAI,GAAG,CAAC,IAAI,KAAK,aAAa,CAAC;AAgB1D,sEAAsE;AACtE,uDAAuD;AAEvD,oEAAoE;AACpE,+CAA+C;AAC/C,UAAU,CAYR,GAAG,CAAC,CAAC;AAEP,UAAU,CAGR,GAAG,CAAC,CAAC;AAEP,oEAAoE;AACpE,UAAU,CAGR,KAAK,CAAC,CAAC;AAET,UAAU,CAAsC,GAAG,CAAC,CAAC;AAErD,UAAU,CAAiD,GAAG,CAAC,CAAC;AAEhE,UAAU,CAAgD,GAAG,CAAC,CAAC;AAE/D,UAAU,CAAiD,GAAG,CAAC,CAAC;AAEhE,UAAU,CAA2C,GAAG,CAAC,CAAC;AAE1D,UAAU,CAAuD,GAAG,CAAC,CAAC;AAEtE,UAAU,CAA8C,IAAI,CAAC,CAAC;AAE9D,UAAU,CAA8C,KAAK,CAAC,CAAC;AAE/D,UAAU,CAGR,IAAI,CAAC,CAAC;AAER,UAAU,CAA8C,KAAK,CAAC,CAAC;AAE/D,UAAU,CAGR,IAAI,CAAC,CAAC;AAER,UAAU,CAGR,KAAK,CAAC,CAAC"}
|
|
@@ -5,4 +5,11 @@ import type { UpdateToken } from '../types/index.mjs';
|
|
|
5
5
|
* issues nothing.
|
|
6
6
|
*/
|
|
7
7
|
export declare const notUpdatedYet: UpdateToken;
|
|
8
|
+
/**
|
|
9
|
+
* Issues the token of a write that opens no update, because nothing observes
|
|
10
|
+
* the observable written to (`setNextIfUnobserved`). Nothing is ever queued
|
|
11
|
+
* with it, so it is a token and not a queue, unlike the tokens
|
|
12
|
+
* `openUpdate` issues.
|
|
13
|
+
*/
|
|
14
|
+
export declare const issueUnqueuedToken: () => UpdateToken;
|
|
8
15
|
//# sourceMappingURL=id-maker.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"id-maker.d.mts","sourceRoot":"","sources":["../../../src/core/utils/id-maker.mts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,WAEM,CAAC"}
|
|
1
|
+
{"version":3,"file":"id-maker.d.mts","sourceRoot":"","sources":["../../../src/core/utils/id-maker.mts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,WAEM,CAAC;AAEnC;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,QAAO,WAEjB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"id-maker.mjs","sourceRoot":"","sources":["../../../src/core/utils/id-maker.mts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa;AACxB,4DAA4D;AAC5D,MAAM,CAAC,MAAM,CAAC,EAAE,CAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"id-maker.mjs","sourceRoot":"","sources":["../../../src/core/utils/id-maker.mts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa;AACxB,4DAA4D;AAC5D,MAAM,CAAC,MAAM,CAAC,EAAE,CAAgB,CAAC;AAEnC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAgB,EAAE;AAClD,4DAA4D;AAC5D,CAAC,EAAE,CAAgB,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ReplaceEqualDeepOptions } from 'ts-data-forge';
|
|
2
2
|
import type { Reducer } from 'ts-type-forge';
|
|
3
|
-
import {
|
|
3
|
+
import type { InitializedObservable } from '../core/index.mjs';
|
|
4
4
|
/**
|
|
5
5
|
* Creates a reducer-based state management container following the Redux pattern.
|
|
6
6
|
* Actions are dispatched to update the state according to the reducer function.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-reducer.d.mts","sourceRoot":"","sources":["../../src/utils/create-reducer.mts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"create-reducer.d.mts","sourceRoot":"","sources":["../../src/utils/create-reducer.mts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAG/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4EG;AACH,eAAO,MAAM,aAAa,GAAI,CAAC,EAAE,CAAC,WACvB,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,gBACR,CAAC,YACL,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KACjC,SAAS,CACV,KAAK,EAAE,qBAAqB,CAAC,CAAC,CAAC,EAC/B,QAAQ,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,EAC1B,KAAK,EAAE,QAAQ,CAAC;IACd,WAAW,EAAE,MAAM,CAAC,CAAC;IACrB,YAAY,EAAE,CAAC,CAAC;CACjB,CAAC,CAcH,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,QAAQ,CAAC;IACrC;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC;IAE1C;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,cAAc,CAAC,EAAE,OAAO,GAAG,uBAAuB,CAAC;CACpD,CAAC,CAAC"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { source } from '../core/index.mjs';
|
|
1
|
+
import { createStateSource } from './state-source.mjs';
|
|
3
2
|
|
|
4
3
|
|
|
5
4
|
|
|
@@ -78,22 +77,11 @@ import { source } from '../core/index.mjs';
|
|
|
78
77
|
|
|
79
78
|
|
|
80
79
|
export const createReducer = (reducer, initialState, options) => {
|
|
81
|
-
const state =
|
|
82
|
-
const equals = options?.equals ?? Object.is;
|
|
83
|
-
const keepEqualParts = options?.keepEqualParts ?? false;
|
|
84
|
-
const keepOptions = typeof keepEqualParts === 'boolean' ? undefined : keepEqualParts;
|
|
80
|
+
const { state, getSnapshot, commit } = createStateSource(initialState, options);
|
|
85
81
|
const dispatch = (action) => {
|
|
86
|
-
const currentState =
|
|
87
|
-
|
|
88
|
-
const nextState = keepEqualParts === false
|
|
89
|
-
? reduced
|
|
90
|
-
: replaceEqualDeep(currentState, reduced, keepOptions);
|
|
91
|
-
|
|
92
|
-
return equals(currentState, nextState)
|
|
93
|
-
? currentState
|
|
94
|
-
: state.next(nextState);
|
|
82
|
+
const currentState = getSnapshot();
|
|
83
|
+
return commit(currentState, reducer(currentState, action));
|
|
95
84
|
};
|
|
96
|
-
const getSnapshot = () => state.getSnapshot().value;
|
|
97
85
|
return [state, dispatch, { getSnapshot, initialState }];
|
|
98
86
|
};
|
|
99
87
|
//# sourceMappingURL=create-reducer.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-reducer.mjs","sourceRoot":"","sources":["../../src/utils/create-reducer.mts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"create-reducer.mjs","sourceRoot":"","sources":["../../src/utils/create-reducer.mts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4EG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,OAAsB,EACtB,YAAe,EACf,OAAkC,EAQlC,EAAE;IACF,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,iBAAiB,CACtD,YAAY,EACZ,OAAO,CACR,CAAC;IAEF,MAAM,QAAQ,GAAG,CAAC,MAAS,EAAK,EAAE;QAChC,MAAM,YAAY,GAAG,WAAW,EAAE,CAAC;QAEnC,OAAO,MAAM,CAAC,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7D,CAAC,CAAC;IAEF,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,WAAW,EAAE,YAAY,EAAE,CAAU,CAAC;AACnE,CAAC,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { InitializedObservable } from '../core/index.mjs';
|
|
2
|
-
import {
|
|
2
|
+
import type { StateOptions } from './create-reducer.mjs';
|
|
3
3
|
/**
|
|
4
4
|
* Creates a reactive state container with getter and setter methods.
|
|
5
5
|
* Provides a simple state management solution with observable state.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-state.d.mts","sourceRoot":"","sources":["../../src/utils/create-state.mts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,
|
|
1
|
+
{"version":3,"file":"create-state.d.mts","sourceRoot":"","sources":["../../src/utils/create-state.mts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6HG;AACH,eAAO,MAAM,WAAW,GAAI,CAAC,gBACb,CAAC,YACL,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KACjC,SAAS,CACV,KAAK,EAAE,qBAAqB,CAAC,CAAC,CAAC,EAC/B,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EACrB,KAAK,EAAE,QAAQ,CAAC;IACd,WAAW,EAAE,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC7C,UAAU,EAAE,MAAM,CAAC,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC,CAAC;IACrB,YAAY,EAAE,CAAC,CAAC;CACjB,CAAC,CA6BH,CAAC"}
|
|
@@ -1,12 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
const reducer = (state, action) => {
|
|
3
|
-
switch (action.type) {
|
|
4
|
-
case 'set':
|
|
5
|
-
return action.nextState;
|
|
6
|
-
case 'update':
|
|
7
|
-
return action.updateFn(state);
|
|
8
|
-
}
|
|
9
|
-
};
|
|
1
|
+
import { createStateSource } from './state-source.mjs';
|
|
10
2
|
|
|
11
3
|
|
|
12
4
|
|
|
@@ -134,10 +126,15 @@ const reducer = (state, action) => {
|
|
|
134
126
|
|
|
135
127
|
|
|
136
128
|
export const createState = (initialState, options) => {
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
const
|
|
129
|
+
const { state, getSnapshot, commit } = createStateSource(initialState, options);
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
const updateState = (updateFn) => {
|
|
133
|
+
const currentState = getSnapshot();
|
|
134
|
+
return commit(currentState, updateFn(currentState));
|
|
135
|
+
};
|
|
136
|
+
const setState = (nextState) => commit(getSnapshot(), nextState);
|
|
137
|
+
const resetState = () => commit(getSnapshot(), initialState);
|
|
141
138
|
return [
|
|
142
139
|
state,
|
|
143
140
|
setState,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-state.mjs","sourceRoot":"","sources":["../../src/utils/create-state.mts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"create-state.mjs","sourceRoot":"","sources":["../../src/utils/create-state.mts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6HG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CACzB,YAAe,EACf,OAAkC,EAUlC,EAAE;IACF,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,iBAAiB,CACtD,YAAY,EACZ,OAAO,CACR,CAAC;IAEF,qEAAqE;IACrE,uCAAuC;IACvC,MAAM,WAAW,GAAG,CAAC,QAAwB,EAAK,EAAE;QAClD,MAAM,YAAY,GAAG,WAAW,EAAE,CAAC;QAEnC,OAAO,MAAM,CAAC,YAAY,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC;IACtD,CAAC,CAAC;IAEF,MAAM,QAAQ,GAAG,CAAC,SAAY,EAAK,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,SAAS,CAAC,CAAC;IAEvE,MAAM,UAAU,GAAG,GAAM,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,YAAY,CAAC,CAAC;IAEhE,OAAO;QACL,KAAK;QACL,QAAQ;QACR;YACE,WAAW;YACX,UAAU;YACV,WAAW;YACX,YAAY;SACb;KACO,CAAC;AACb,CAAC,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type InitializedSourceObservable } from '../core/index.mjs';
|
|
2
|
+
import type { StateOptions } from './create-reducer.mjs';
|
|
3
|
+
/**
|
|
4
|
+
* What `createState` and `createReducer` are both built on: the source
|
|
5
|
+
* holding the state, its current value, and `commit`, the one way either
|
|
6
|
+
* writes it. `commit` writes `reduced` unless `equals` finds it the same as
|
|
7
|
+
* `currentState`, after keeping the parts of `currentState` it did not change
|
|
8
|
+
* when `keepEqualParts` asks for that, and returns the state written, or
|
|
9
|
+
* `currentState` when nothing was.
|
|
10
|
+
*
|
|
11
|
+
* Not part of the package's API: `gen:index:src` leaves this file out of the
|
|
12
|
+
* barrel.
|
|
13
|
+
*/
|
|
14
|
+
export declare const createStateSource: <S>(initialState: S, options: StateOptions<S> | undefined) => Readonly<{
|
|
15
|
+
state: InitializedSourceObservable<S>;
|
|
16
|
+
getSnapshot: () => S;
|
|
17
|
+
commit: (currentState: S, reduced: S) => S;
|
|
18
|
+
}>;
|
|
19
|
+
//# sourceMappingURL=state-source.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-source.d.mts","sourceRoot":"","sources":["../../src/utils/state-source.mts"],"names":[],"mappings":"AACA,OAAO,EAAU,KAAK,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AAC7E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,iBAAiB,GAAI,CAAC,gBACnB,CAAC,WACN,YAAY,CAAC,CAAC,CAAC,GAAG,SAAS,KACnC,QAAQ,CAAC;IACV,KAAK,EAAE,2BAA2B,CAAC,CAAC,CAAC,CAAC;IACtC,WAAW,EAAE,MAAM,CAAC,CAAC;IACrB,MAAM,EAAE,CAAC,YAAY,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;CAC5C,CAyBA,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { replaceEqualDeep } from 'ts-data-forge';
|
|
2
|
+
import { source } from '../core/index.mjs';
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
export const createStateSource = (initialState, options) => {
|
|
15
|
+
const state = source(initialState);
|
|
16
|
+
const getSnapshot = () => state.getSnapshot().value;
|
|
17
|
+
const equals = options?.equals ?? Object.is;
|
|
18
|
+
const keepEqualParts = options?.keepEqualParts ?? false;
|
|
19
|
+
const keepOptions = typeof keepEqualParts === 'boolean' ? undefined : keepEqualParts;
|
|
20
|
+
const commit = (currentState, reduced) => {
|
|
21
|
+
const nextState = keepEqualParts === false
|
|
22
|
+
? reduced
|
|
23
|
+
: replaceEqualDeep(currentState, reduced, keepOptions);
|
|
24
|
+
|
|
25
|
+
return equals(currentState, nextState)
|
|
26
|
+
? currentState
|
|
27
|
+
: state.next(nextState);
|
|
28
|
+
};
|
|
29
|
+
return { state, getSnapshot, commit };
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=state-source.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-source.mjs","sourceRoot":"","sources":["../../src/utils/state-source.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,MAAM,EAAoC,MAAM,mBAAmB,CAAC;AAG7E;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,YAAe,EACf,OAAoC,EAKnC,EAAE;IACH,MAAM,KAAK,GAAG,MAAM,CAAI,YAAY,CAAC,CAAC;IAEtC,MAAM,WAAW,GAAG,GAAM,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC;IAEvD,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,MAAM,CAAC,EAAE,CAAC;IAE5C,MAAM,cAAc,GAAG,OAAO,EAAE,cAAc,IAAI,KAAK,CAAC;IAExD,MAAM,WAAW,GACf,OAAO,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC;IAEnE,MAAM,MAAM,GAAG,CAAC,YAAe,EAAE,OAAU,EAAK,EAAE;QAChD,MAAM,SAAS,GACb,cAAc,KAAK,KAAK;YACtB,CAAC,CAAC,OAAO;YACT,CAAC,CAAC,gBAAgB,CAAC,YAAY,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;QAE3D,8DAA8D;QAC9D,OAAO,MAAM,CAAC,YAAY,EAAE,SAAS,CAAC;YACpC,CAAC,CAAC,YAAY;YACd,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC5B,CAAC,CAAC;IAEF,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC;AACxC,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "synstate",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.1.1",
|
|
4
4
|
"description": "Type-safe State Management Library for TypeScript/JavaScript",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -34,31 +34,33 @@
|
|
|
34
34
|
"ts-type-forge": "^9.2.2"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
+
"@preact/signals-core": "1.14.4",
|
|
37
38
|
"@reduxjs/toolkit": "2.13.0",
|
|
38
|
-
"@sumi-lang/cli": "0.1.
|
|
39
|
+
"@sumi-lang/cli": "0.1.3",
|
|
39
40
|
"@types/react": "19.3.0",
|
|
40
41
|
"@vitest/browser-playwright": "5.0.5",
|
|
41
42
|
"argparse": "3.0.3",
|
|
42
|
-
"eslint-config-typed": "
|
|
43
|
-
"eslint-plugin-ts-data-forge": "0.10.
|
|
44
|
-
"eslint-plugin-ts-fortress": "1.3.
|
|
45
|
-
"eslint-plugin-ts-type-forge": "0.8.
|
|
43
|
+
"eslint-config-typed": "7.1.0",
|
|
44
|
+
"eslint-plugin-ts-data-forge": "0.10.5",
|
|
45
|
+
"eslint-plugin-ts-fortress": "1.3.10",
|
|
46
|
+
"eslint-plugin-ts-type-forge": "0.8.15",
|
|
46
47
|
"jotai": "3.0.1",
|
|
47
|
-
"mobx": "7.0
|
|
48
|
+
"mobx": "7.1.0",
|
|
48
49
|
"playwright": "1.64.1",
|
|
49
50
|
"prettier": "3.9.10",
|
|
50
51
|
"prettier-plugin-organize-imports": "4.3.0",
|
|
51
52
|
"prettier-plugin-packagejson": "3.0.2",
|
|
52
53
|
"react": "19.3.1",
|
|
53
54
|
"rxjs": "7.8.2",
|
|
54
|
-
"
|
|
55
|
-
"synstate-react-hooks
|
|
55
|
+
"solid-js": "1.9.17",
|
|
56
|
+
"synstate-react-hooks": "6.1.1",
|
|
57
|
+
"synstate-react-hooks-compat": "6.1.1",
|
|
56
58
|
"ts-repo-utils": "10.7.1",
|
|
57
59
|
"valtio": "2.3.2",
|
|
58
60
|
"zustand": "5.0.15"
|
|
59
61
|
},
|
|
60
62
|
"engines": {
|
|
61
|
-
"node": ">=22.
|
|
63
|
+
"node": ">=22.23.4",
|
|
62
64
|
"pnpm": ">=9.0.0"
|
|
63
65
|
},
|
|
64
66
|
"publishConfig": {
|
|
@@ -83,7 +85,7 @@
|
|
|
83
85
|
"fmt": "pnpm run fix:fmt",
|
|
84
86
|
"gen": "run-s gen:index gen:readme gen:jsdoc gen:sample-diffs",
|
|
85
87
|
"gen:index": "run-s gen:index:src fix:fmt",
|
|
86
|
-
"gen:index:src": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ../../libs/ts-repo-utils/src/cmd/gen-index-ts.mts ./src --index-ext .mts --export-ext .mjs --target-ext .mts --target-ext .tsx --exclude entry-point.mts --exclude \"core/class/**\" --exclude \"core/utils/**\"",
|
|
88
|
+
"gen:index:src": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ../../libs/ts-repo-utils/src/cmd/gen-index-ts.mts ./src --index-ext .mts --export-ext .mjs --target-ext .mts --target-ext .tsx --exclude entry-point.mts --exclude \"core/class/**\" --exclude \"core/utils/**\" --exclude utils/state-source.mts",
|
|
87
89
|
"gen:jsdoc": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ./scripts/cmd/embed-examples-in-jsdoc.mts",
|
|
88
90
|
"gen:readme": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ./scripts/cmd/embed-examples.mts",
|
|
89
91
|
"gen:sample-diffs": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ./scripts/cmd/generate-sample-diffs.mts",
|
|
@@ -26,6 +26,13 @@ export class ManagerObservableClass<
|
|
|
26
26
|
> extends ObservableBaseClass<A, Kind, Depth> {
|
|
27
27
|
/** Emits `nextValue` and propagates it to the descendants. */
|
|
28
28
|
protected startUpdate(nextValue: A): void {
|
|
29
|
+
// Nothing to propagate to (a branch no `switchMap` follows, a state
|
|
30
|
+
// written before anything subscribes): the update is the value alone,
|
|
31
|
+
// and opening one would cost more than storing it.
|
|
32
|
+
if (this.setNextIfUnobserved(nextValue)) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
29
36
|
const updateToken = openUpdate(this.depth);
|
|
30
37
|
|
|
31
38
|
beginPropagation(updateToken);
|
|
@@ -23,6 +23,7 @@ import type {
|
|
|
23
23
|
} from '../types/index.mjs';
|
|
24
24
|
import {
|
|
25
25
|
getCurrentScopeInternals,
|
|
26
|
+
issueUnqueuedToken,
|
|
26
27
|
notUpdatedYet,
|
|
27
28
|
observableBrand,
|
|
28
29
|
toSubscriber,
|
|
@@ -146,7 +147,7 @@ export class ObservableBaseClass<
|
|
|
146
147
|
// A set, not an array: a completed child removes itself, and that has to
|
|
147
148
|
// be O(1) for a UI that creates and completes derived nodes on every mount.
|
|
148
149
|
if (this.#mut_children === undefined) {
|
|
149
|
-
this.#mut_children = new Set([child]);
|
|
150
|
+
this.#mut_children = new Set<ChildNode>([child]);
|
|
150
151
|
} else {
|
|
151
152
|
this.#mut_children.add(child);
|
|
152
153
|
}
|
|
@@ -178,6 +179,25 @@ export class ObservableBaseClass<
|
|
|
178
179
|
}
|
|
179
180
|
}
|
|
180
181
|
|
|
182
|
+
/**
|
|
183
|
+
* Stores `nextValue` and returns `true` when nothing observes this
|
|
184
|
+
* observable — no child to queue and no subscriber to call — so that the
|
|
185
|
+
* caller need not open an update; returns `false`, storing nothing,
|
|
186
|
+
* otherwise. The value still gets a token of its own, so that whoever
|
|
187
|
+
* stored the last one sees that it emitted.
|
|
188
|
+
*/
|
|
189
|
+
protected setNextIfUnobserved(nextValue: A): boolean {
|
|
190
|
+
if (this.hasChild || this.hasSubscriber) {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
this.#mut_updateToken = issueUnqueuedToken();
|
|
195
|
+
|
|
196
|
+
this.#mut_snapshot = Optional.some(nextValue);
|
|
197
|
+
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
|
|
181
201
|
/**
|
|
182
202
|
* Called with the token of every update that reaches this observable; a
|
|
183
203
|
* parent that did not emit in that update has a different `updateToken`.
|
|
@@ -321,7 +341,7 @@ export class ObservableBaseClass<
|
|
|
321
341
|
|
|
322
342
|
const subscriber = toSubscriber(onNext, onComplete);
|
|
323
343
|
|
|
324
|
-
this.#mut_subscribers ??= new Set();
|
|
344
|
+
this.#mut_subscribers ??= new Set<Subscriber<A>>();
|
|
325
345
|
|
|
326
346
|
this.#mut_subscribers.add(subscriber);
|
|
327
347
|
|
|
@@ -18,8 +18,9 @@ import type { UpdateToken } from '../types/index.mjs';
|
|
|
18
18
|
import type { ChildNode } from './observable-node.mjs';
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
|
-
* How many
|
|
22
|
-
*
|
|
21
|
+
* How many updates are propagating, across every observable, and the token
|
|
22
|
+
* of the outermost one. A write nothing observes opens none
|
|
23
|
+
* (`setNextIfUnobserved`).
|
|
23
24
|
*/
|
|
24
25
|
const mut_propagation: {
|
|
25
26
|
depth: number;
|
|
@@ -28,7 +29,7 @@ const mut_propagation: {
|
|
|
28
29
|
|
|
29
30
|
/**
|
|
30
31
|
* Work deferred by {@link runAfterPropagation}, run once the outermost
|
|
31
|
-
*
|
|
32
|
+
* update has reached every descendant.
|
|
32
33
|
*/
|
|
33
34
|
const mut_afterPropagation: (() => void)[] = [];
|
|
34
35
|
|
|
@@ -57,7 +58,10 @@ export const runAfterPropagation = (task: () => void): void => {
|
|
|
57
58
|
}
|
|
58
59
|
};
|
|
59
60
|
|
|
60
|
-
/**
|
|
61
|
+
/**
|
|
62
|
+
* Brackets one update a `startUpdate` opens (a write nothing observes opens
|
|
63
|
+
* none); see {@link endPropagation}.
|
|
64
|
+
*/
|
|
61
65
|
export const beginPropagation = (updateToken: UpdateToken): void => {
|
|
62
66
|
if (mut_propagation.depth === 0) {
|
|
63
67
|
mut_propagation.outermostToken = updateToken;
|
|
@@ -67,8 +71,8 @@ export const beginPropagation = (updateToken: UpdateToken): void => {
|
|
|
67
71
|
};
|
|
68
72
|
|
|
69
73
|
/**
|
|
70
|
-
* Ends one
|
|
71
|
-
*
|
|
74
|
+
* Ends one update, and runs the deferred work once the outermost one has
|
|
75
|
+
* ended.
|
|
72
76
|
*/
|
|
73
77
|
export const endPropagation = (): void => {
|
|
74
78
|
mut_propagation.depth -= 1;
|
|
@@ -251,7 +255,7 @@ class UpdateQueue {
|
|
|
251
255
|
// Another open update has queued `child` and may not have visited
|
|
252
256
|
// it yet: leave its mark alone.
|
|
253
257
|
if (this.#mut_queuedDespiteMark === undefined) {
|
|
254
|
-
this.#mut_queuedDespiteMark = new Set();
|
|
258
|
+
this.#mut_queuedDespiteMark = new Set<ChildNode>();
|
|
255
259
|
} else if (this.#mut_queuedDespiteMark.has(child)) {
|
|
256
260
|
continue;
|
|
257
261
|
}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import type { FixedLengthTuple } from 'ts-type-forge';
|
|
2
|
+
import { createState } from '../../utils/index.mjs';
|
|
3
|
+
import { derive, merge } from '../combine/index.mjs';
|
|
4
|
+
import { source } from '../create/index.mjs';
|
|
5
|
+
import { debounce, map, switchMap } from '../operators/index.mjs';
|
|
6
|
+
import { writeDuringPropagationWarning } from './root-observable-class.mjs';
|
|
7
|
+
|
|
8
|
+
// A write to an observable with no child and no subscriber stores the value
|
|
9
|
+
// without opening an update (`ManagerObservableClass.startUpdate`). These
|
|
10
|
+
// pin what that must not change.
|
|
11
|
+
describe('a write nothing observes', () => {
|
|
12
|
+
test('is held, and a later subscriber receives the last one', () => {
|
|
13
|
+
const s$ = source<number>(0);
|
|
14
|
+
|
|
15
|
+
s$.next(1);
|
|
16
|
+
|
|
17
|
+
s$.next(2);
|
|
18
|
+
|
|
19
|
+
const mut_history: number[] = [];
|
|
20
|
+
|
|
21
|
+
s$.subscribe((v) => {
|
|
22
|
+
mut_history.push(v);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
assert.deepStrictEqual(mut_history, [2]);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('gets a token of its own each time', () => {
|
|
29
|
+
const s$ = source<number>(0);
|
|
30
|
+
|
|
31
|
+
const before = s$.updateToken;
|
|
32
|
+
|
|
33
|
+
s$.next(1);
|
|
34
|
+
|
|
35
|
+
const first = s$.updateToken;
|
|
36
|
+
|
|
37
|
+
s$.next(2);
|
|
38
|
+
|
|
39
|
+
assert.notStrictEqual(first, before);
|
|
40
|
+
|
|
41
|
+
assert.notStrictEqual(s$.updateToken, first);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test('is held after the last subscriber leaves', () => {
|
|
45
|
+
const [s$, setS] = createState(0);
|
|
46
|
+
|
|
47
|
+
const subscription = s$.subscribe(() => {});
|
|
48
|
+
|
|
49
|
+
subscription.unsubscribe();
|
|
50
|
+
|
|
51
|
+
assert.strictEqual(setS(5), 5);
|
|
52
|
+
|
|
53
|
+
const mut_history: number[] = [];
|
|
54
|
+
|
|
55
|
+
s$.subscribe((v) => {
|
|
56
|
+
mut_history.push(v);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
assert.deepStrictEqual(mut_history, [5]);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test('is where a child created later starts, and later writes reach it', () => {
|
|
63
|
+
const s$ = source<number>(0);
|
|
64
|
+
|
|
65
|
+
s$.next(3);
|
|
66
|
+
|
|
67
|
+
const mut_history: number[] = [];
|
|
68
|
+
|
|
69
|
+
s$.pipe(map((x) => x * 10)).subscribe((v) => {
|
|
70
|
+
mut_history.push(v);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
s$.next(4);
|
|
74
|
+
|
|
75
|
+
assert.deepStrictEqual(mut_history, [30, 40]);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test('is not taken for an emission of an update another parent starts', () => {
|
|
79
|
+
const a$ = source<number>(0);
|
|
80
|
+
|
|
81
|
+
const b$ = source<number>(0);
|
|
82
|
+
|
|
83
|
+
a$.next(5);
|
|
84
|
+
|
|
85
|
+
const mut_merged: number[] = [];
|
|
86
|
+
|
|
87
|
+
merge([a$, b$]).subscribe((v) => {
|
|
88
|
+
mut_merged.push(v);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const mut_derived: FixedLengthTuple<2, number>[] = [];
|
|
92
|
+
|
|
93
|
+
derive([a$, b$], (a, b) => [a, b] as const).subscribe((v) => {
|
|
94
|
+
mut_derived.push(v);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
b$.next(1);
|
|
98
|
+
|
|
99
|
+
a$.next(6);
|
|
100
|
+
|
|
101
|
+
// merge passes on the parents that emitted in an update: only b$, then
|
|
102
|
+
// only a$, never the value a$ was given while nothing observed it.
|
|
103
|
+
assert.deepStrictEqual(mut_merged, [1, 6]);
|
|
104
|
+
|
|
105
|
+
assert.deepStrictEqual(mut_derived, [
|
|
106
|
+
[5, 0],
|
|
107
|
+
[5, 1],
|
|
108
|
+
[6, 1],
|
|
109
|
+
]);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
test('by an async child is held, as a root write is', () => {
|
|
113
|
+
vi.useFakeTimers();
|
|
114
|
+
|
|
115
|
+
const s$ = source<number>(0);
|
|
116
|
+
|
|
117
|
+
const debounced$ = s$.pipe(debounce(100));
|
|
118
|
+
|
|
119
|
+
const subscription = debounced$.subscribe(() => {});
|
|
120
|
+
|
|
121
|
+
subscription.unsubscribe();
|
|
122
|
+
|
|
123
|
+
// debounced$ keeps its parent, but has no observer of its own when the
|
|
124
|
+
// timer fires.
|
|
125
|
+
s$.next(1);
|
|
126
|
+
|
|
127
|
+
vi.runAllTimers();
|
|
128
|
+
|
|
129
|
+
const mut_history: number[] = [];
|
|
130
|
+
|
|
131
|
+
debounced$.subscribe((v) => {
|
|
132
|
+
mut_history.push(v);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
s$.next(2);
|
|
136
|
+
|
|
137
|
+
vi.runAllTimers();
|
|
138
|
+
|
|
139
|
+
assert.deepStrictEqual(mut_history, [1, 2]);
|
|
140
|
+
|
|
141
|
+
vi.useRealTimers();
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test('by a switchMap inner after the switchMap lost its observers is held', () => {
|
|
145
|
+
const selector$ = source<number>(0);
|
|
146
|
+
|
|
147
|
+
const branch$ = source<number>(10);
|
|
148
|
+
|
|
149
|
+
const switched$ = selector$.pipe(switchMap(() => branch$));
|
|
150
|
+
|
|
151
|
+
const subscription = switched$.subscribe(() => {});
|
|
152
|
+
|
|
153
|
+
// switchMap follows an inner once the selector emits.
|
|
154
|
+
selector$.next(1);
|
|
155
|
+
|
|
156
|
+
subscription.unsubscribe();
|
|
157
|
+
|
|
158
|
+
branch$.next(11);
|
|
159
|
+
|
|
160
|
+
const mut_history: number[] = [];
|
|
161
|
+
|
|
162
|
+
switched$.pipe(map((x) => x * 2)).subscribe((v) => {
|
|
163
|
+
mut_history.push(v);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
branch$.next(12);
|
|
167
|
+
|
|
168
|
+
assert.deepStrictEqual(mut_history, [22, 24]);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
test('from a subscriber still warns as a write during propagation', () => {
|
|
172
|
+
const [a$, setA] = createState(0);
|
|
173
|
+
|
|
174
|
+
const [, setB] = createState(0);
|
|
175
|
+
|
|
176
|
+
a$.subscribe((a) => {
|
|
177
|
+
setB(a);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
const warn = vi.fn();
|
|
181
|
+
|
|
182
|
+
vi.stubGlobal('console', { ...console, warn });
|
|
183
|
+
|
|
184
|
+
setA(1);
|
|
185
|
+
|
|
186
|
+
// cspell:disable-next-line
|
|
187
|
+
vi.unstubAllGlobals();
|
|
188
|
+
|
|
189
|
+
assert.deepStrictEqual(
|
|
190
|
+
warn.mock.calls.map((args: readonly unknown[]) => args[0]),
|
|
191
|
+
[writeDuringPropagationWarning],
|
|
192
|
+
);
|
|
193
|
+
});
|
|
194
|
+
});
|