@zeix/cause-effect 0.17.1 → 0.17.3
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 +13 -0
- package/.github/copilot-instructions.md +4 -0
- package/.zed/settings.json +3 -0
- package/CLAUDE.md +41 -7
- package/README.md +48 -25
- package/archive/benchmark.ts +0 -5
- package/archive/collection.ts +6 -65
- package/archive/composite.ts +85 -0
- package/archive/computed.ts +18 -20
- package/archive/list.ts +7 -75
- package/archive/memo.ts +15 -15
- package/archive/state.ts +2 -1
- package/archive/store.ts +8 -78
- package/archive/task.ts +20 -25
- package/index.dev.js +508 -526
- package/index.js +1 -1
- package/index.ts +9 -11
- package/package.json +6 -6
- package/src/classes/collection.ts +70 -107
- package/src/classes/computed.ts +165 -149
- package/src/classes/list.ts +145 -107
- package/src/classes/ref.ts +19 -17
- package/src/classes/state.ts +21 -17
- package/src/classes/store.ts +125 -73
- package/src/diff.ts +2 -1
- package/src/effect.ts +17 -10
- package/src/errors.ts +14 -1
- package/src/resolve.ts +1 -1
- package/src/signal.ts +3 -2
- package/src/system.ts +159 -61
- package/src/util.ts +0 -6
- package/test/batch.test.ts +4 -11
- package/test/benchmark.test.ts +4 -2
- package/test/collection.test.ts +106 -107
- package/test/computed.test.ts +351 -112
- package/test/effect.test.ts +2 -2
- package/test/list.test.ts +62 -102
- package/test/ref.test.ts +128 -2
- package/test/state.test.ts +16 -22
- package/test/store.test.ts +101 -108
- package/test/util/dependency-graph.ts +2 -2
- package/tsconfig.build.json +11 -0
- package/tsconfig.json +5 -7
- package/types/index.d.ts +3 -3
- package/types/src/classes/collection.d.ts +9 -10
- package/types/src/classes/computed.d.ts +17 -20
- package/types/src/classes/list.d.ts +8 -6
- package/types/src/classes/ref.d.ts +8 -12
- package/types/src/classes/state.d.ts +5 -8
- package/types/src/classes/store.d.ts +14 -13
- package/types/src/effect.d.ts +1 -2
- package/types/src/errors.d.ts +2 -1
- package/types/src/signal.d.ts +3 -2
- package/types/src/system.d.ts +47 -34
- package/types/src/util.d.ts +1 -2
- package/src/classes/composite.ts +0 -176
- package/types/src/classes/composite.d.ts +0 -15
package/src/classes/composite.ts
DELETED
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
import type { DiffResult, UnknownRecord } from '../diff'
|
|
2
|
-
import { guardMutableSignal } from '../errors'
|
|
3
|
-
import type { Signal } from '../signal'
|
|
4
|
-
import {
|
|
5
|
-
batchSignalWrites,
|
|
6
|
-
type Cleanup,
|
|
7
|
-
createWatcher,
|
|
8
|
-
emitNotification,
|
|
9
|
-
type Listener,
|
|
10
|
-
type Listeners,
|
|
11
|
-
trackSignalReads,
|
|
12
|
-
type Watcher,
|
|
13
|
-
} from '../system'
|
|
14
|
-
|
|
15
|
-
/* === Types === */
|
|
16
|
-
|
|
17
|
-
type CompositeListeners = Pick<Listeners, 'add' | 'change' | 'remove'>
|
|
18
|
-
|
|
19
|
-
/* === Class Definitions === */
|
|
20
|
-
|
|
21
|
-
class Composite<T extends UnknownRecord, S extends Signal<T[keyof T] & {}>> {
|
|
22
|
-
signals = new Map<string, S>()
|
|
23
|
-
#validate: <K extends keyof T & string>(
|
|
24
|
-
key: K,
|
|
25
|
-
value: unknown,
|
|
26
|
-
) => value is T[K] & {}
|
|
27
|
-
#create: <V extends T[keyof T] & {}>(value: V) => S
|
|
28
|
-
#watchers = new Map<string, Watcher>()
|
|
29
|
-
#listeners: CompositeListeners = {
|
|
30
|
-
add: new Set<Listener<'add'>>(),
|
|
31
|
-
change: new Set<Listener<'change'>>(),
|
|
32
|
-
remove: new Set<Listener<'remove'>>(),
|
|
33
|
-
}
|
|
34
|
-
#batching = false
|
|
35
|
-
|
|
36
|
-
constructor(
|
|
37
|
-
values: T,
|
|
38
|
-
validate: <K extends keyof T & string>(
|
|
39
|
-
key: K,
|
|
40
|
-
value: unknown,
|
|
41
|
-
) => value is T[K] & {},
|
|
42
|
-
create: <V extends T[keyof T] & {}>(value: V) => S,
|
|
43
|
-
) {
|
|
44
|
-
this.#validate = validate
|
|
45
|
-
this.#create = create
|
|
46
|
-
this.change(
|
|
47
|
-
{
|
|
48
|
-
add: values,
|
|
49
|
-
change: {},
|
|
50
|
-
remove: {},
|
|
51
|
-
changed: true,
|
|
52
|
-
},
|
|
53
|
-
true,
|
|
54
|
-
)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
#addWatcher(key: string): void {
|
|
58
|
-
const watcher = createWatcher(() => {
|
|
59
|
-
trackSignalReads(watcher, () => {
|
|
60
|
-
this.signals.get(key)?.get() // Subscribe to the signal
|
|
61
|
-
if (!this.#batching)
|
|
62
|
-
emitNotification(this.#listeners.change, [key])
|
|
63
|
-
})
|
|
64
|
-
})
|
|
65
|
-
this.#watchers.set(key, watcher)
|
|
66
|
-
watcher()
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
add<K extends keyof T & string>(key: K, value: T[K]): boolean {
|
|
70
|
-
if (!this.#validate(key, value)) return false
|
|
71
|
-
|
|
72
|
-
this.signals.set(key, this.#create(value))
|
|
73
|
-
if (this.#listeners.change.size) this.#addWatcher(key)
|
|
74
|
-
|
|
75
|
-
if (!this.#batching) emitNotification(this.#listeners.add, [key])
|
|
76
|
-
return true
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
remove<K extends keyof T & string>(key: K): boolean {
|
|
80
|
-
const ok = this.signals.delete(key)
|
|
81
|
-
if (!ok) return false
|
|
82
|
-
|
|
83
|
-
const watcher = this.#watchers.get(key)
|
|
84
|
-
if (watcher) {
|
|
85
|
-
watcher.stop()
|
|
86
|
-
this.#watchers.delete(key)
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
if (!this.#batching) emitNotification(this.#listeners.remove, [key])
|
|
90
|
-
return true
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
change(changes: DiffResult, initialRun?: boolean): boolean {
|
|
94
|
-
this.#batching = true
|
|
95
|
-
|
|
96
|
-
// Additions
|
|
97
|
-
if (Object.keys(changes.add).length) {
|
|
98
|
-
for (const key in changes.add)
|
|
99
|
-
this.add(
|
|
100
|
-
key as Extract<keyof T, string>,
|
|
101
|
-
changes.add[key] as T[Extract<keyof T, string>] & {},
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
// Queue initial additions event to allow listeners to be added first
|
|
105
|
-
const notify = () =>
|
|
106
|
-
emitNotification(this.#listeners.add, Object.keys(changes.add))
|
|
107
|
-
if (initialRun) setTimeout(notify, 0)
|
|
108
|
-
else notify()
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// Changes
|
|
112
|
-
if (Object.keys(changes.change).length) {
|
|
113
|
-
batchSignalWrites(() => {
|
|
114
|
-
for (const key in changes.change) {
|
|
115
|
-
const value = changes.change[key]
|
|
116
|
-
if (!this.#validate(key as keyof T & string, value))
|
|
117
|
-
continue
|
|
118
|
-
|
|
119
|
-
const signal = this.signals.get(key)
|
|
120
|
-
if (guardMutableSignal(`list item "${key}"`, value, signal))
|
|
121
|
-
signal.set(value)
|
|
122
|
-
}
|
|
123
|
-
})
|
|
124
|
-
emitNotification(
|
|
125
|
-
this.#listeners.change,
|
|
126
|
-
Object.keys(changes.change),
|
|
127
|
-
)
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// Removals
|
|
131
|
-
if (Object.keys(changes.remove).length) {
|
|
132
|
-
for (const key in changes.remove)
|
|
133
|
-
this.remove(key as keyof T & string)
|
|
134
|
-
emitNotification(
|
|
135
|
-
this.#listeners.remove,
|
|
136
|
-
Object.keys(changes.remove),
|
|
137
|
-
)
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
this.#batching = false
|
|
141
|
-
return changes.changed
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
clear(): boolean {
|
|
145
|
-
const keys = Array.from(this.signals.keys())
|
|
146
|
-
this.signals.clear()
|
|
147
|
-
this.#watchers.clear()
|
|
148
|
-
emitNotification(this.#listeners.remove, keys)
|
|
149
|
-
return true
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
on<K extends keyof CompositeListeners>(
|
|
153
|
-
type: K,
|
|
154
|
-
listener: Listener<K>,
|
|
155
|
-
): Cleanup {
|
|
156
|
-
this.#listeners[type].add(listener)
|
|
157
|
-
if (type === 'change' && !this.#watchers.size) {
|
|
158
|
-
this.#batching = true
|
|
159
|
-
for (const key of this.signals.keys()) this.#addWatcher(key)
|
|
160
|
-
this.#batching = false
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return () => {
|
|
164
|
-
this.#listeners[type].delete(listener)
|
|
165
|
-
if (type === 'change' && !this.#listeners.change.size) {
|
|
166
|
-
if (this.#watchers.size) {
|
|
167
|
-
for (const watcher of this.#watchers.values())
|
|
168
|
-
watcher.stop()
|
|
169
|
-
this.#watchers.clear()
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
export { Composite, type CompositeListeners }
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { DiffResult, UnknownRecord } from '../diff';
|
|
2
|
-
import type { Signal } from '../signal';
|
|
3
|
-
import { type Cleanup, type Listener, type Listeners } from '../system';
|
|
4
|
-
type CompositeListeners = Pick<Listeners, 'add' | 'change' | 'remove'>;
|
|
5
|
-
declare class Composite<T extends UnknownRecord, S extends Signal<T[keyof T] & {}>> {
|
|
6
|
-
#private;
|
|
7
|
-
signals: Map<string, S>;
|
|
8
|
-
constructor(values: T, validate: <K extends keyof T & string>(key: K, value: unknown) => value is T[K] & {}, create: <V extends T[keyof T] & {}>(value: V) => S);
|
|
9
|
-
add<K extends keyof T & string>(key: K, value: T[K]): boolean;
|
|
10
|
-
remove<K extends keyof T & string>(key: K): boolean;
|
|
11
|
-
change(changes: DiffResult, initialRun?: boolean): boolean;
|
|
12
|
-
clear(): boolean;
|
|
13
|
-
on<K extends keyof CompositeListeners>(type: K, listener: Listener<K>): Cleanup;
|
|
14
|
-
}
|
|
15
|
-
export { Composite, type CompositeListeners };
|