@zeix/cause-effect 0.16.0 → 0.16.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 +1 -1
- package/index.dev.js +167 -162
- package/index.js +1 -1
- package/index.ts +3 -2
- package/package.json +1 -1
- package/src/computed.ts +15 -16
- package/src/diff.ts +24 -21
- package/src/state.ts +34 -45
- package/src/store.ts +170 -221
- package/src/util.ts +2 -6
- package/test/batch.test.ts +1 -1
- package/test/benchmark.test.ts +1 -1
- package/test/computed.test.ts +1 -1
- package/test/effect.test.ts +1 -1
- package/test/match.test.ts +1 -1
- package/test/resolve.test.ts +1 -1
- package/test/signal.test.ts +2 -2
- package/test/state.test.ts +1 -1
- package/test/store.test.ts +859 -1502
- package/types/index.d.ts +3 -3
- package/types/src/diff.d.ts +7 -7
- package/types/src/store.d.ts +6 -7
package/src/diff.ts
CHANGED
|
@@ -5,16 +5,20 @@ import { isRecord, isRecordOrArray, UNSET } from './util'
|
|
|
5
5
|
|
|
6
6
|
type UnknownRecord = Record<string, unknown & {}>
|
|
7
7
|
type UnknownArray = ReadonlyArray<unknown & {}>
|
|
8
|
+
|
|
8
9
|
type ArrayToRecord<T extends UnknownArray> = {
|
|
9
10
|
[key: string]: T extends Array<infer U extends {}> ? U : never
|
|
10
11
|
}
|
|
11
|
-
type UnknownRecordOrArray = UnknownRecord | ArrayToRecord<UnknownArray>
|
|
12
12
|
|
|
13
|
-
type
|
|
13
|
+
type PartialRecord<T> = T extends UnknownArray
|
|
14
|
+
? Partial<ArrayToRecord<T>>
|
|
15
|
+
: Partial<T>
|
|
16
|
+
|
|
17
|
+
type DiffResult<T extends UnknownRecord | UnknownArray = UnknownRecord> = {
|
|
14
18
|
changed: boolean
|
|
15
|
-
add:
|
|
16
|
-
change:
|
|
17
|
-
remove:
|
|
19
|
+
add: PartialRecord<T>
|
|
20
|
+
change: PartialRecord<T>
|
|
21
|
+
remove: PartialRecord<T>
|
|
18
22
|
}
|
|
19
23
|
|
|
20
24
|
/* === Functions === */
|
|
@@ -88,9 +92,9 @@ const isEqual = <T>(a: T, b: T, visited?: WeakSet<object>): boolean => {
|
|
|
88
92
|
* @param {T} newObj - The new record to compare
|
|
89
93
|
* @returns {DiffResult<T>} The result of the comparison
|
|
90
94
|
*/
|
|
91
|
-
const diff = <T extends
|
|
92
|
-
oldObj: T,
|
|
93
|
-
newObj: T,
|
|
95
|
+
const diff = <T extends UnknownRecord | UnknownArray>(
|
|
96
|
+
oldObj: T extends UnknownArray ? ArrayToRecord<T> : T,
|
|
97
|
+
newObj: T extends UnknownArray ? ArrayToRecord<T> : T,
|
|
94
98
|
): DiffResult<T> => {
|
|
95
99
|
// Guard against non-objects that can't be diffed properly with Object.keys and 'in' operator
|
|
96
100
|
const oldValid = isRecordOrArray(oldObj)
|
|
@@ -100,17 +104,17 @@ const diff = <T extends UnknownRecordOrArray>(
|
|
|
100
104
|
const changed = !Object.is(oldObj, newObj)
|
|
101
105
|
return {
|
|
102
106
|
changed,
|
|
103
|
-
add: changed && newValid ? newObj : {},
|
|
104
|
-
change: {}
|
|
105
|
-
remove: changed && oldValid ? oldObj : {},
|
|
107
|
+
add: changed && newValid ? newObj : ({} as PartialRecord<T>),
|
|
108
|
+
change: {} as PartialRecord<T>,
|
|
109
|
+
remove: changed && oldValid ? oldObj : ({} as PartialRecord<T>),
|
|
106
110
|
}
|
|
107
111
|
}
|
|
108
112
|
|
|
109
113
|
const visited = new WeakSet()
|
|
110
114
|
|
|
111
|
-
const add
|
|
112
|
-
const change
|
|
113
|
-
const remove
|
|
115
|
+
const add = {} as PartialRecord<T>
|
|
116
|
+
const change = {} as PartialRecord<T>
|
|
117
|
+
const remove = {} as PartialRecord<T>
|
|
114
118
|
|
|
115
119
|
const oldKeys = Object.keys(oldObj)
|
|
116
120
|
const newKeys = Object.keys(newObj)
|
|
@@ -121,18 +125,17 @@ const diff = <T extends UnknownRecordOrArray>(
|
|
|
121
125
|
const newHas = key in newObj
|
|
122
126
|
|
|
123
127
|
if (!oldHas && newHas) {
|
|
124
|
-
add[key
|
|
128
|
+
add[key] = newObj[key]
|
|
125
129
|
continue
|
|
126
130
|
} else if (oldHas && !newHas) {
|
|
127
|
-
remove[key
|
|
131
|
+
remove[key] = UNSET
|
|
128
132
|
continue
|
|
129
133
|
}
|
|
130
134
|
|
|
131
|
-
const oldValue = oldObj[key]
|
|
132
|
-
const newValue = newObj[key]
|
|
135
|
+
const oldValue = oldObj[key]
|
|
136
|
+
const newValue = newObj[key]
|
|
133
137
|
|
|
134
|
-
if (!isEqual(oldValue, newValue, visited))
|
|
135
|
-
change[key as keyof T] = newValue
|
|
138
|
+
if (!isEqual(oldValue, newValue, visited)) change[key] = newValue
|
|
136
139
|
}
|
|
137
140
|
|
|
138
141
|
const changed =
|
|
@@ -157,5 +160,5 @@ export {
|
|
|
157
160
|
isEqual,
|
|
158
161
|
type UnknownRecord,
|
|
159
162
|
type UnknownArray,
|
|
160
|
-
type
|
|
163
|
+
type PartialRecord,
|
|
161
164
|
}
|
package/src/state.ts
CHANGED
|
@@ -31,55 +31,44 @@ const createState = /*#__PURE__*/ <T extends {}>(initialValue: T): State<T> => {
|
|
|
31
31
|
const watchers: Set<Watcher> = new Set()
|
|
32
32
|
let value: T = initialValue
|
|
33
33
|
|
|
34
|
-
const
|
|
35
|
-
|
|
34
|
+
const setValue = (newValue: T) => {
|
|
35
|
+
if (newValue == null) throw new NullishSignalValueError('state')
|
|
36
|
+
if (isEqual(value, newValue)) return
|
|
37
|
+
value = newValue
|
|
38
|
+
notify(watchers)
|
|
39
|
+
|
|
40
|
+
// Setting to UNSET clears the watchers so the signal can be garbage collected
|
|
41
|
+
if (UNSET === value) watchers.clear()
|
|
42
|
+
}
|
|
36
43
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
* @returns {T} - Current value of the state
|
|
42
|
-
*/
|
|
43
|
-
get: (): T => {
|
|
44
|
-
subscribe(watchers)
|
|
45
|
-
return value
|
|
44
|
+
const state: Record<PropertyKey, unknown> = {}
|
|
45
|
+
Object.defineProperties(state, {
|
|
46
|
+
[Symbol.toStringTag]: {
|
|
47
|
+
value: TYPE_STATE,
|
|
46
48
|
},
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
* @param {T} newValue - New value of the state
|
|
53
|
-
* @returns {void}
|
|
54
|
-
*/
|
|
55
|
-
set: (newValue: T): void => {
|
|
56
|
-
if (newValue == null) throw new NullishSignalValueError('state')
|
|
57
|
-
if (isEqual(value, newValue)) return
|
|
58
|
-
value = newValue
|
|
59
|
-
notify(watchers)
|
|
60
|
-
|
|
61
|
-
// Setting to UNSET clears the watchers so the signal can be garbage collected
|
|
62
|
-
if (UNSET === value) watchers.clear()
|
|
49
|
+
get: {
|
|
50
|
+
value: () => {
|
|
51
|
+
subscribe(watchers)
|
|
52
|
+
return value
|
|
53
|
+
},
|
|
63
54
|
},
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
* @since 0.10.0
|
|
69
|
-
* @param {(v: T) => T} updater - Function to update the state
|
|
70
|
-
* @returns {void}
|
|
71
|
-
*/
|
|
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))
|
|
55
|
+
set: {
|
|
56
|
+
value: (newValue: T) => {
|
|
57
|
+
setValue(newValue)
|
|
58
|
+
},
|
|
79
59
|
},
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
60
|
+
update: {
|
|
61
|
+
value: (updater: (oldValue: T) => T) => {
|
|
62
|
+
if (!isFunction(updater))
|
|
63
|
+
throw new InvalidCallbackError(
|
|
64
|
+
'state update',
|
|
65
|
+
valueString(updater),
|
|
66
|
+
)
|
|
67
|
+
setValue(updater(value))
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
})
|
|
71
|
+
return state as State<T>
|
|
83
72
|
}
|
|
84
73
|
|
|
85
74
|
/**
|