@zeix/cause-effect 0.15.1 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.ai-context.md +254 -0
- package/.cursorrules +54 -0
- package/.github/copilot-instructions.md +132 -0
- package/CLAUDE.md +319 -0
- package/README.md +167 -159
- package/eslint.config.js +1 -1
- package/index.dev.js +528 -407
- package/index.js +1 -1
- package/index.ts +36 -25
- package/package.json +1 -1
- package/src/computed.ts +41 -30
- package/src/diff.ts +57 -44
- package/src/effect.ts +15 -16
- package/src/errors.ts +64 -0
- package/src/match.ts +2 -2
- package/src/resolve.ts +2 -2
- package/src/signal.ts +27 -49
- package/src/state.ts +27 -19
- package/src/store.ts +410 -209
- package/src/system.ts +122 -0
- package/src/util.ts +45 -6
- package/test/batch.test.ts +18 -11
- package/test/benchmark.test.ts +4 -4
- package/test/computed.test.ts +508 -72
- package/test/diff.test.ts +321 -4
- package/test/effect.test.ts +61 -61
- package/test/match.test.ts +38 -28
- package/test/resolve.test.ts +16 -16
- package/test/signal.test.ts +19 -147
- package/test/state.test.ts +212 -25
- package/test/store.test.ts +1370 -134
- package/test/util/dependency-graph.ts +1 -1
- package/types/index.d.ts +10 -9
- package/types/src/collection.d.ts +26 -0
- package/types/src/computed.d.ts +9 -9
- package/types/src/diff.d.ts +5 -3
- package/types/src/effect.d.ts +3 -3
- package/types/src/errors.d.ts +22 -0
- package/types/src/match.d.ts +1 -1
- package/types/src/resolve.d.ts +1 -1
- package/types/src/signal.d.ts +12 -19
- package/types/src/state.d.ts +5 -5
- package/types/src/store.d.ts +40 -36
- package/types/src/system.d.ts +44 -0
- package/types/src/util.d.ts +7 -5
- package/index.d.ts +0 -36
- package/src/scheduler.ts +0 -172
- package/types/test-new-effect.d.ts +0 -1
package/src/signal.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type Computed,
|
|
3
3
|
type ComputedCallback,
|
|
4
|
-
|
|
4
|
+
createComputed,
|
|
5
5
|
isComputed,
|
|
6
6
|
isComputedCallback,
|
|
7
7
|
} from './computed'
|
|
8
|
-
import { isState, type State
|
|
9
|
-
import { isStore, type Store
|
|
8
|
+
import { createState, isState, type State } from './state'
|
|
9
|
+
import { createStore, isStore, type Store } from './store'
|
|
10
10
|
import { isRecord } from './util'
|
|
11
11
|
|
|
12
12
|
/* === Types === */
|
|
@@ -14,7 +14,6 @@ import { isRecord } from './util'
|
|
|
14
14
|
type Signal<T extends {}> = {
|
|
15
15
|
get(): T
|
|
16
16
|
}
|
|
17
|
-
type MaybeSignal<T extends {}> = T | Signal<T> | ComputedCallback<T>
|
|
18
17
|
|
|
19
18
|
type UnknownSignalRecord = Record<string, Signal<unknown & {}>>
|
|
20
19
|
|
|
@@ -22,15 +21,10 @@ type SignalValues<S extends UnknownSignalRecord> = {
|
|
|
22
21
|
[K in keyof S]: S[K] extends Signal<infer T> ? T : never
|
|
23
22
|
}
|
|
24
23
|
|
|
25
|
-
/* === Constants === */
|
|
26
|
-
|
|
27
|
-
// biome-ignore lint/suspicious/noExplicitAny: Deliberately using any to be used as a placeholder value in any signal
|
|
28
|
-
const UNSET: any = Symbol()
|
|
29
|
-
|
|
30
24
|
/* === Functions === */
|
|
31
25
|
|
|
32
26
|
/**
|
|
33
|
-
* Check whether a value is a Signal
|
|
27
|
+
* Check whether a value is a Signal
|
|
34
28
|
*
|
|
35
29
|
* @since 0.9.0
|
|
36
30
|
* @param {unknown} value - value to check
|
|
@@ -40,6 +34,17 @@ const isSignal = /*#__PURE__*/ <T extends {}>(
|
|
|
40
34
|
value: unknown,
|
|
41
35
|
): value is Signal<T> => isState(value) || isComputed(value) || isStore(value)
|
|
42
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Check whether a value is a State or Store
|
|
39
|
+
*
|
|
40
|
+
* @since 0.15.2
|
|
41
|
+
* @param {unknown} value - value to check
|
|
42
|
+
* @returns {boolean} - true if value is a State or Store, false otherwise
|
|
43
|
+
*/
|
|
44
|
+
const isMutableSignal = /*#__PURE__*/ <T extends {}>(
|
|
45
|
+
value: unknown,
|
|
46
|
+
): value is State<T> | Store<T> => isState(value) || isStore(value)
|
|
47
|
+
|
|
43
48
|
/**
|
|
44
49
|
* Convert a value to a Signal if it's not already a Signal
|
|
45
50
|
*
|
|
@@ -47,10 +52,6 @@ const isSignal = /*#__PURE__*/ <T extends {}>(
|
|
|
47
52
|
* @param {T} value - value to convert
|
|
48
53
|
* @returns {Signal<T>} - Signal instance
|
|
49
54
|
*/
|
|
50
|
-
function toSignal<T extends {}>(value: T[]): Store<Record<string, T>>
|
|
51
|
-
function toSignal<T extends {}>(
|
|
52
|
-
value: (() => T) | ((abort: AbortSignal) => Promise<T>),
|
|
53
|
-
): Computed<T>
|
|
54
55
|
function toSignal<T extends {}>(
|
|
55
56
|
value: T,
|
|
56
57
|
): T extends Store<infer U>
|
|
@@ -61,50 +62,27 @@ function toSignal<T extends {}>(
|
|
|
61
62
|
? Computed<U>
|
|
62
63
|
: T extends Signal<infer U>
|
|
63
64
|
? Signal<U>
|
|
64
|
-
: T extends
|
|
65
|
-
? Store<
|
|
66
|
-
:
|
|
67
|
-
|
|
65
|
+
: T extends ReadonlyArray<infer U extends {}>
|
|
66
|
+
? Store<U[]>
|
|
67
|
+
: T extends Record<string, unknown & {}>
|
|
68
|
+
? Store<{ [K in keyof T]: T[K] }>
|
|
69
|
+
: T extends ComputedCallback<infer U extends {}>
|
|
70
|
+
? Computed<U>
|
|
71
|
+
: State<T>
|
|
72
|
+
function toSignal<T extends {}>(value: T) {
|
|
68
73
|
if (isSignal<T>(value)) return value
|
|
69
|
-
if (isComputedCallback(value)) return
|
|
70
|
-
if (Array.isArray(value)) return
|
|
71
|
-
|
|
72
|
-
return state(value)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Convert a value to a mutable Signal if it's not already a Signal
|
|
77
|
-
*
|
|
78
|
-
* @since 0.15.0
|
|
79
|
-
* @param {T} value - value to convert
|
|
80
|
-
* @returns {State<T> | Store<T>} - Signal instance
|
|
81
|
-
*/
|
|
82
|
-
function toMutableSignal<T extends {}>(value: T[]): Store<Record<string, T>>
|
|
83
|
-
function toMutableSignal<T extends {}>(
|
|
84
|
-
value: T,
|
|
85
|
-
): T extends Store<infer U>
|
|
86
|
-
? Store<U>
|
|
87
|
-
: T extends State<infer U>
|
|
88
|
-
? State<U>
|
|
89
|
-
: T extends Record<string, unknown & {}>
|
|
90
|
-
? Store<{ [K in keyof T]: T[K] }>
|
|
91
|
-
: State<T>
|
|
92
|
-
function toMutableSignal<T extends {}>(value: T): State<T> | Store<T> {
|
|
93
|
-
if (isState<T>(value) || isStore<T>(value)) return value
|
|
94
|
-
if (Array.isArray(value)) return store(value as T)
|
|
95
|
-
if (isRecord(value)) return store(value)
|
|
96
|
-
return state(value)
|
|
74
|
+
if (isComputedCallback(value)) return createComputed(value)
|
|
75
|
+
if (Array.isArray(value) || isRecord(value)) return createStore(value)
|
|
76
|
+
return createState(value)
|
|
97
77
|
}
|
|
98
78
|
|
|
99
79
|
/* === Exports === */
|
|
100
80
|
|
|
101
81
|
export {
|
|
102
82
|
type Signal,
|
|
103
|
-
type MaybeSignal,
|
|
104
83
|
type UnknownSignalRecord,
|
|
105
84
|
type SignalValues,
|
|
106
|
-
UNSET,
|
|
107
85
|
isSignal,
|
|
86
|
+
isMutableSignal,
|
|
108
87
|
toSignal,
|
|
109
|
-
toMutableSignal,
|
|
110
88
|
}
|
package/src/state.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { isEqual } from './diff'
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { isObjectOfType } from './util'
|
|
2
|
+
import { InvalidCallbackError, NullishSignalValueError } from './errors'
|
|
3
|
+
import { notify, subscribe, type Watcher } from './system'
|
|
4
|
+
import { isFunction, isObjectOfType, UNSET, valueString } from './util'
|
|
5
5
|
|
|
6
6
|
/* === Types === */
|
|
7
7
|
|
|
8
8
|
type State<T extends {}> = {
|
|
9
|
-
[Symbol.toStringTag]: 'State'
|
|
9
|
+
readonly [Symbol.toStringTag]: 'State'
|
|
10
10
|
get(): T
|
|
11
|
-
set(
|
|
12
|
-
update(
|
|
11
|
+
set(newValue: T): void
|
|
12
|
+
update(updater: (oldValue: T) => T): void
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
/* === Constants === */
|
|
@@ -25,18 +25,20 @@ const TYPE_STATE = 'State'
|
|
|
25
25
|
* @param {T} initialValue - initial value of the state
|
|
26
26
|
* @returns {State<T>} - new state signal
|
|
27
27
|
*/
|
|
28
|
-
const
|
|
28
|
+
const createState = /*#__PURE__*/ <T extends {}>(initialValue: T): State<T> => {
|
|
29
|
+
if (initialValue == null) throw new NullishSignalValueError('state')
|
|
30
|
+
|
|
29
31
|
const watchers: Set<Watcher> = new Set()
|
|
30
32
|
let value: T = initialValue
|
|
31
33
|
|
|
32
|
-
const
|
|
34
|
+
const state: State<T> = {
|
|
33
35
|
[Symbol.toStringTag]: TYPE_STATE,
|
|
34
36
|
|
|
35
37
|
/**
|
|
36
38
|
* Get the current value of the state
|
|
37
39
|
*
|
|
38
40
|
* @since 0.9.0
|
|
39
|
-
* @returns {T} -
|
|
41
|
+
* @returns {T} - Current value of the state
|
|
40
42
|
*/
|
|
41
43
|
get: (): T => {
|
|
42
44
|
subscribe(watchers)
|
|
@@ -47,12 +49,13 @@ const state = /*#__PURE__*/ <T extends {}>(initialValue: T): State<T> => {
|
|
|
47
49
|
* Set a new value of the state
|
|
48
50
|
*
|
|
49
51
|
* @since 0.9.0
|
|
50
|
-
* @param {T}
|
|
52
|
+
* @param {T} newValue - New value of the state
|
|
51
53
|
* @returns {void}
|
|
52
54
|
*/
|
|
53
|
-
set: (
|
|
54
|
-
if (
|
|
55
|
-
value
|
|
55
|
+
set: (newValue: T): void => {
|
|
56
|
+
if (newValue == null) throw new NullishSignalValueError('state')
|
|
57
|
+
if (isEqual(value, newValue)) return
|
|
58
|
+
value = newValue
|
|
56
59
|
notify(watchers)
|
|
57
60
|
|
|
58
61
|
// Setting to UNSET clears the watchers so the signal can be garbage collected
|
|
@@ -63,15 +66,20 @@ const state = /*#__PURE__*/ <T extends {}>(initialValue: T): State<T> => {
|
|
|
63
66
|
* Update the state with a new value using a function
|
|
64
67
|
*
|
|
65
68
|
* @since 0.10.0
|
|
66
|
-
* @param {(v: T) => T}
|
|
67
|
-
* @returns {void}
|
|
69
|
+
* @param {(v: T) => T} updater - Function to update the state
|
|
70
|
+
* @returns {void}
|
|
68
71
|
*/
|
|
69
|
-
update: (
|
|
70
|
-
|
|
72
|
+
update: (updater: (oldValue: T) => T): void => {
|
|
73
|
+
if (!isFunction(updater))
|
|
74
|
+
throw new InvalidCallbackError(
|
|
75
|
+
'state update',
|
|
76
|
+
valueString(updater),
|
|
77
|
+
)
|
|
78
|
+
state.set(updater(value))
|
|
71
79
|
},
|
|
72
80
|
}
|
|
73
81
|
|
|
74
|
-
return
|
|
82
|
+
return state
|
|
75
83
|
}
|
|
76
84
|
|
|
77
85
|
/**
|
|
@@ -87,4 +95,4 @@ const isState = /*#__PURE__*/ <T extends {}>(
|
|
|
87
95
|
|
|
88
96
|
/* === Exports === */
|
|
89
97
|
|
|
90
|
-
export { TYPE_STATE, isState,
|
|
98
|
+
export { TYPE_STATE, isState, createState, type State }
|