@vielzeug/ripple 1.3.0 → 2.0.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/README.md +33 -72
- package/dist/_async.cjs +2 -0
- package/dist/_async.cjs.map +1 -0
- package/dist/_async.d.ts +40 -0
- package/dist/_async.d.ts.map +1 -0
- package/dist/_async.js +75 -0
- package/dist/_async.js.map +1 -0
- package/dist/_store.cjs +2 -0
- package/dist/_store.cjs.map +1 -0
- package/dist/_store.d.ts +20 -0
- package/dist/_store.d.ts.map +1 -0
- package/dist/_store.js +24 -0
- package/dist/_store.js.map +1 -0
- package/dist/_watch.cjs +2 -0
- package/dist/_watch.cjs.map +1 -0
- package/dist/_watch.d.ts +15 -0
- package/dist/_watch.d.ts.map +1 -0
- package/dist/_watch.js +18 -0
- package/dist/_watch.js.map +1 -0
- package/dist/async.cjs +1 -0
- package/dist/async.d.ts +3 -0
- package/dist/async.d.ts.map +1 -0
- package/dist/async.js +2 -0
- package/dist/errors.cjs +1 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.ts +2 -15
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +2 -2
- package/dist/errors.js.map +1 -1
- package/dist/index.cjs +2 -1
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +34 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -11
- package/dist/index.js.map +1 -0
- package/dist/ripple.cjs +1 -1
- package/dist/ripple.cjs.map +1 -1
- package/dist/ripple.iife.js +1 -1
- package/dist/ripple.iife.js.map +1 -1
- package/dist/ripple.js +1 -1
- package/dist/ripple.js.map +1 -1
- package/dist/runtime.cjs +2 -0
- package/dist/runtime.cjs.map +1 -0
- package/dist/runtime.d.ts +98 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +340 -0
- package/dist/runtime.js.map +1 -0
- package/dist/store.cjs +1 -2
- package/dist/store.d.ts +2 -57
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +2 -207
- package/dist/types.d.ts +37 -301
- package/dist/types.d.ts.map +1 -1
- package/dist/watch.cjs +1 -0
- package/dist/watch.d.ts +3 -0
- package/dist/watch.d.ts.map +1 -0
- package/dist/watch.js +2 -0
- package/package.json +22 -21
- package/dist/_dev.cjs +0 -2
- package/dist/_dev.cjs.map +0 -1
- package/dist/_dev.d.ts +0 -2
- package/dist/_dev.d.ts.map +0 -1
- package/dist/_dev.js +0 -9
- package/dist/_dev.js.map +0 -1
- package/dist/_error-utils.cjs +0 -2
- package/dist/_error-utils.cjs.map +0 -1
- package/dist/_error-utils.d.ts +0 -24
- package/dist/_error-utils.d.ts.map +0 -1
- package/dist/_error-utils.js +0 -20
- package/dist/_error-utils.js.map +0 -1
- package/dist/_virtual/_rolldown/runtime.js +0 -7
- package/dist/async-computed.cjs +0 -2
- package/dist/async-computed.cjs.map +0 -1
- package/dist/async-computed.d.ts +0 -36
- package/dist/async-computed.d.ts.map +0 -1
- package/dist/async-computed.js +0 -62
- package/dist/async-computed.js.map +0 -1
- package/dist/computed.cjs +0 -2
- package/dist/computed.cjs.map +0 -1
- package/dist/computed.d.ts +0 -26
- package/dist/computed.d.ts.map +0 -1
- package/dist/computed.js +0 -113
- package/dist/computed.js.map +0 -1
- package/dist/devtools-hook.cjs +0 -2
- package/dist/devtools-hook.cjs.map +0 -1
- package/dist/devtools-hook.d.ts +0 -4
- package/dist/devtools-hook.d.ts.map +0 -1
- package/dist/devtools-hook.js +0 -8
- package/dist/devtools-hook.js.map +0 -1
- package/dist/devtools.d.ts +0 -50
- package/dist/devtools.d.ts.map +0 -1
- package/dist/effect.cjs +0 -2
- package/dist/effect.cjs.map +0 -1
- package/dist/effect.d.ts +0 -104
- package/dist/effect.d.ts.map +0 -1
- package/dist/effect.js +0 -174
- package/dist/effect.js.map +0 -1
- package/dist/execution-context.cjs +0 -2
- package/dist/execution-context.cjs.map +0 -1
- package/dist/execution-context.d.ts +0 -49
- package/dist/execution-context.d.ts.map +0 -1
- package/dist/execution-context.js +0 -32
- package/dist/execution-context.js.map +0 -1
- package/dist/history.d.ts +0 -56
- package/dist/history.d.ts.map +0 -1
- package/dist/reactive-base.cjs +0 -2
- package/dist/reactive-base.cjs.map +0 -1
- package/dist/reactive-base.d.ts +0 -60
- package/dist/reactive-base.d.ts.map +0 -1
- package/dist/reactive-base.js +0 -56
- package/dist/reactive-base.js.map +0 -1
- package/dist/scheduling.cjs +0 -2
- package/dist/scheduling.cjs.map +0 -1
- package/dist/scheduling.d.ts +0 -5
- package/dist/scheduling.d.ts.map +0 -1
- package/dist/scheduling.js +0 -57
- package/dist/scheduling.js.map +0 -1
- package/dist/signal.cjs +0 -2
- package/dist/signal.cjs.map +0 -1
- package/dist/signal.d.ts +0 -24
- package/dist/signal.d.ts.map +0 -1
- package/dist/signal.js +0 -54
- package/dist/signal.js.map +0 -1
- package/dist/src/devtools.cjs +0 -2
- package/dist/src/devtools.cjs.map +0 -1
- package/dist/src/devtools.js +0 -36
- package/dist/src/devtools.js.map +0 -1
- package/dist/src/history.cjs +0 -2
- package/dist/src/history.cjs.map +0 -1
- package/dist/src/history.js +0 -60
- package/dist/src/history.js.map +0 -1
- package/dist/src/ssr/index.cjs +0 -2
- package/dist/src/ssr/index.cjs.map +0 -1
- package/dist/src/ssr/index.js +0 -38
- package/dist/src/ssr/index.js.map +0 -1
- package/dist/ssr/index.d.ts +0 -56
- package/dist/ssr/index.d.ts.map +0 -1
- package/dist/store.cjs.map +0 -1
- package/dist/store.js.map +0 -1
- package/dist/subscription.cjs +0 -2
- package/dist/subscription.cjs.map +0 -1
- package/dist/subscription.d.ts +0 -22
- package/dist/subscription.d.ts.map +0 -1
- package/dist/subscription.js +0 -47
- package/dist/subscription.js.map +0 -1
- package/dist/symbols.cjs +0 -2
- package/dist/symbols.cjs.map +0 -1
- package/dist/symbols.d.ts +0 -6
- package/dist/symbols.d.ts.map +0 -1
- package/dist/symbols.js +0 -6
- package/dist/symbols.js.map +0 -1
- package/dist/tracking.cjs +0 -2
- package/dist/tracking.cjs.map +0 -1
- package/dist/tracking.d.ts +0 -51
- package/dist/tracking.d.ts.map +0 -1
- package/dist/tracking.js +0 -28
- package/dist/tracking.js.map +0 -1
- package/dist/utilities.cjs +0 -2
- package/dist/utilities.cjs.map +0 -1
- package/dist/utilities.d.ts +0 -56
- package/dist/utilities.d.ts.map +0 -1
- package/dist/utilities.js +0 -25
- package/dist/utilities.js.map +0 -1
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
import { RippleComputedCycleError as e, RippleDisposedScopeError as t, RippleInfiniteLoopError as n } from "./errors.js";
|
|
2
|
+
//#region src/runtime.ts
|
|
3
|
+
var r = Symbol("ripple.reactive"), i = Symbol("ripple.signal"), a = Symbol("ripple.computed"), o = 100, s = Symbol("ripple.unset"), c = class {
|
|
4
|
+
[r] = !0;
|
|
5
|
+
dependents = /* @__PURE__ */ new Set();
|
|
6
|
+
name;
|
|
7
|
+
runtime;
|
|
8
|
+
constructor(e, t) {
|
|
9
|
+
this.runtime = e, this.name = t;
|
|
10
|
+
}
|
|
11
|
+
subscribe(e) {
|
|
12
|
+
this.peek();
|
|
13
|
+
let t = {
|
|
14
|
+
dependencies: /* @__PURE__ */ new Set(),
|
|
15
|
+
onDependencyChanged: () => this.runtime.enqueueListener(e)
|
|
16
|
+
};
|
|
17
|
+
return this.dependents.add(t), () => this.dependents.delete(t);
|
|
18
|
+
}
|
|
19
|
+
notify() {
|
|
20
|
+
for (let e of [...this.dependents]) e.onDependencyChanged();
|
|
21
|
+
}
|
|
22
|
+
}, l = class extends c {
|
|
23
|
+
[i] = !0;
|
|
24
|
+
current;
|
|
25
|
+
equals;
|
|
26
|
+
constructor(e, t, n) {
|
|
27
|
+
super(e, n?.name), this.current = t, this.equals = n?.equals ?? Object.is;
|
|
28
|
+
}
|
|
29
|
+
get value() {
|
|
30
|
+
return this.runtime.track(this), this.current;
|
|
31
|
+
}
|
|
32
|
+
set value(e) {
|
|
33
|
+
if (this.equals(this.current, e)) return;
|
|
34
|
+
let t = this.current;
|
|
35
|
+
this.current = e, this.runtime.emit({
|
|
36
|
+
kind: "write",
|
|
37
|
+
name: this.name,
|
|
38
|
+
next: e,
|
|
39
|
+
previous: t
|
|
40
|
+
}), this.runtime.propagate(() => this.notify());
|
|
41
|
+
}
|
|
42
|
+
peek() {
|
|
43
|
+
return this.current;
|
|
44
|
+
}
|
|
45
|
+
}, u = class extends c {
|
|
46
|
+
[a] = !0;
|
|
47
|
+
dependencies = /* @__PURE__ */ new Set();
|
|
48
|
+
computing = !1;
|
|
49
|
+
disposed = !1;
|
|
50
|
+
dirty = !0;
|
|
51
|
+
current = s;
|
|
52
|
+
derive;
|
|
53
|
+
equals;
|
|
54
|
+
constructor(e, t, n) {
|
|
55
|
+
super(e, n?.name), this.derive = t, this.equals = n?.equals ?? Object.is;
|
|
56
|
+
}
|
|
57
|
+
get value() {
|
|
58
|
+
return this.refresh(), this.runtime.track(this), this.current;
|
|
59
|
+
}
|
|
60
|
+
peek() {
|
|
61
|
+
return this.refresh(), this.current;
|
|
62
|
+
}
|
|
63
|
+
onDependencyChanged() {
|
|
64
|
+
this.disposed || (this.dirty ||= !0, this.dependents.size > 0 && this.refresh() && this.notify());
|
|
65
|
+
}
|
|
66
|
+
dispose() {
|
|
67
|
+
this.disposed || (this.disposed = !0, this.runtime.clearDependencies(this), this.dependents.clear());
|
|
68
|
+
}
|
|
69
|
+
refresh() {
|
|
70
|
+
if (!this.dirty || this.disposed) return !1;
|
|
71
|
+
if (this.computing) {
|
|
72
|
+
let t = this.name === void 0 ? "" : ` "${this.name}"`;
|
|
73
|
+
throw new e(`computed cycle detected${t}`);
|
|
74
|
+
}
|
|
75
|
+
this.computing = !0, this.runtime.emit({
|
|
76
|
+
kind: "compute",
|
|
77
|
+
name: this.name
|
|
78
|
+
});
|
|
79
|
+
try {
|
|
80
|
+
let e = this.runtime.collect(this, this.derive), t = this.current === s || !this.equals(this.current, e);
|
|
81
|
+
return this.current = e, this.dirty = !1, t;
|
|
82
|
+
} finally {
|
|
83
|
+
this.computing = !1;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}, d = class {
|
|
87
|
+
disposalController = new AbortController();
|
|
88
|
+
owned = /* @__PURE__ */ new Set();
|
|
89
|
+
name;
|
|
90
|
+
isDisposed = !1;
|
|
91
|
+
runtime;
|
|
92
|
+
constructor(e, t) {
|
|
93
|
+
this.runtime = e, this.name = t;
|
|
94
|
+
}
|
|
95
|
+
get disposed() {
|
|
96
|
+
return this.isDisposed;
|
|
97
|
+
}
|
|
98
|
+
get disposalSignal() {
|
|
99
|
+
return this.disposalController.signal;
|
|
100
|
+
}
|
|
101
|
+
run(e) {
|
|
102
|
+
if (this.isDisposed) throw new t("Cannot run a disposed scope.");
|
|
103
|
+
return this.runtime.withScope(this, e);
|
|
104
|
+
}
|
|
105
|
+
dispose() {
|
|
106
|
+
if (!this.isDisposed) {
|
|
107
|
+
this.isDisposed = !0;
|
|
108
|
+
for (let e of [...this.owned].reverse()) e.dispose();
|
|
109
|
+
this.owned.clear(), this.disposalController.abort(), this.runtime.emit({
|
|
110
|
+
kind: "dispose",
|
|
111
|
+
name: this.name,
|
|
112
|
+
node: "scope"
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
[Symbol.dispose]() {
|
|
117
|
+
this.dispose();
|
|
118
|
+
}
|
|
119
|
+
}, f = class {
|
|
120
|
+
dependencies = /* @__PURE__ */ new Set();
|
|
121
|
+
disposalController = new AbortController();
|
|
122
|
+
cleanup;
|
|
123
|
+
isDisposed = !1;
|
|
124
|
+
owner;
|
|
125
|
+
scheduled = !1;
|
|
126
|
+
callback;
|
|
127
|
+
options;
|
|
128
|
+
runtime;
|
|
129
|
+
constructor(e, t, n) {
|
|
130
|
+
this.runtime = e, this.callback = t, this.options = n;
|
|
131
|
+
}
|
|
132
|
+
get disposed() {
|
|
133
|
+
return this.isDisposed;
|
|
134
|
+
}
|
|
135
|
+
get disposalSignal() {
|
|
136
|
+
return this.disposalController.signal;
|
|
137
|
+
}
|
|
138
|
+
onDependencyChanged() {
|
|
139
|
+
if (!this.isDisposed) {
|
|
140
|
+
if (this.options?.scheduler === "microtask") {
|
|
141
|
+
if (this.scheduled) return;
|
|
142
|
+
this.scheduled = !0, queueMicrotask(() => {
|
|
143
|
+
this.scheduled = !1, this.isDisposed || this.runtime.enqueue(this);
|
|
144
|
+
});
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
this.runtime.enqueue(this);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
run() {
|
|
151
|
+
if (this.isDisposed) return;
|
|
152
|
+
this.owner?.dispose(), this.owner = void 0, this.runCleanup(), this.runtime.emit({
|
|
153
|
+
kind: "effect",
|
|
154
|
+
name: this.options?.name
|
|
155
|
+
});
|
|
156
|
+
let e = new d(this.runtime);
|
|
157
|
+
try {
|
|
158
|
+
let t = this.runtime.withEffectScope(e, () => this.runtime.collectEffect(this, this.callback));
|
|
159
|
+
this.owner = e, this.cleanup = typeof t == "function" ? t : void 0;
|
|
160
|
+
} catch (t) {
|
|
161
|
+
e.dispose(), this.runtime.report(t, {
|
|
162
|
+
kind: "effect",
|
|
163
|
+
name: this.options?.name
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
dispose() {
|
|
168
|
+
this.isDisposed || (this.isDisposed = !0, this.owner?.dispose(), this.owner = void 0, this.runtime.clearDependencies(this), this.runCleanup(), this.disposalController.abort(), this.runtime.emit({
|
|
169
|
+
kind: "dispose",
|
|
170
|
+
name: this.options?.name,
|
|
171
|
+
node: "effect"
|
|
172
|
+
}));
|
|
173
|
+
}
|
|
174
|
+
[Symbol.dispose]() {
|
|
175
|
+
this.dispose();
|
|
176
|
+
}
|
|
177
|
+
runCleanup() {
|
|
178
|
+
let e = this.cleanup;
|
|
179
|
+
if (this.cleanup = void 0, e !== void 0) try {
|
|
180
|
+
e();
|
|
181
|
+
} catch (e) {
|
|
182
|
+
this.runtime.report(e, {
|
|
183
|
+
kind: "cleanup",
|
|
184
|
+
name: this.options?.name
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}, p = class {
|
|
189
|
+
activeEffectScope;
|
|
190
|
+
activeObserver;
|
|
191
|
+
activeScope;
|
|
192
|
+
flushDepth = 0;
|
|
193
|
+
flushing = !1;
|
|
194
|
+
pending = /* @__PURE__ */ new Set();
|
|
195
|
+
listeners = /* @__PURE__ */ new Set();
|
|
196
|
+
rootScope;
|
|
197
|
+
observer;
|
|
198
|
+
onError;
|
|
199
|
+
constructor(e) {
|
|
200
|
+
this.observer = e?.observer, this.onError = e?.onError ?? ((e) => {
|
|
201
|
+
queueMicrotask(() => {
|
|
202
|
+
throw e;
|
|
203
|
+
});
|
|
204
|
+
}), this.rootScope = new d(this, "runtime"), this.activeScope = this.rootScope;
|
|
205
|
+
}
|
|
206
|
+
signal = (e, t) => new l(this, e, t);
|
|
207
|
+
computed = (e, t) => {
|
|
208
|
+
let n = new u(this, e, t);
|
|
209
|
+
return (this.activeEffectScope ?? this.activeScope).owned.add(n), n;
|
|
210
|
+
};
|
|
211
|
+
effect = (e, t) => {
|
|
212
|
+
let n = new f(this, e, t);
|
|
213
|
+
return (this.activeEffectScope ?? this.activeScope).owned.add(n), n.run(), n;
|
|
214
|
+
};
|
|
215
|
+
createScope = (e) => {
|
|
216
|
+
let t = new d(this, e);
|
|
217
|
+
return this.activeScope.owned.add(t), t;
|
|
218
|
+
};
|
|
219
|
+
batch = (e) => this.propagate(e);
|
|
220
|
+
untrack = (e) => this.withObserver(void 0, e);
|
|
221
|
+
dispose() {
|
|
222
|
+
this.rootScope.dispose();
|
|
223
|
+
}
|
|
224
|
+
track(e) {
|
|
225
|
+
let t = this.activeObserver;
|
|
226
|
+
t?.collecting !== void 0 && t.collecting.add(e);
|
|
227
|
+
}
|
|
228
|
+
clearDependencies(e) {
|
|
229
|
+
for (let t of e.dependencies) t.dependents.delete(e);
|
|
230
|
+
e.dependencies.clear();
|
|
231
|
+
}
|
|
232
|
+
collect(e, t) {
|
|
233
|
+
return this.collectWith(e, t, !1);
|
|
234
|
+
}
|
|
235
|
+
collectEffect(e, t) {
|
|
236
|
+
return this.collectWith(e, t, !0);
|
|
237
|
+
}
|
|
238
|
+
withEffectScope(e, t) {
|
|
239
|
+
let n = this.activeEffectScope;
|
|
240
|
+
this.activeEffectScope = e;
|
|
241
|
+
try {
|
|
242
|
+
return t();
|
|
243
|
+
} finally {
|
|
244
|
+
this.activeEffectScope = n;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
withObserver(e, t) {
|
|
248
|
+
let n = this.activeObserver;
|
|
249
|
+
this.activeObserver = e;
|
|
250
|
+
try {
|
|
251
|
+
return t();
|
|
252
|
+
} finally {
|
|
253
|
+
this.activeObserver = n;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
withScope(e, t) {
|
|
257
|
+
let n = this.activeEffectScope, r = this.activeScope;
|
|
258
|
+
this.activeEffectScope = void 0, this.activeScope = e;
|
|
259
|
+
try {
|
|
260
|
+
return t();
|
|
261
|
+
} finally {
|
|
262
|
+
this.activeEffectScope = n, this.activeScope = r;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
enqueue(e) {
|
|
266
|
+
this.pending.add(e), this.flushDepth === 0 && this.flush();
|
|
267
|
+
}
|
|
268
|
+
enqueueListener(e) {
|
|
269
|
+
this.listeners.add(e), this.flushDepth === 0 && this.flush();
|
|
270
|
+
}
|
|
271
|
+
propagate(e) {
|
|
272
|
+
this.flushDepth++;
|
|
273
|
+
try {
|
|
274
|
+
return e();
|
|
275
|
+
} finally {
|
|
276
|
+
this.flushDepth--, this.flushDepth === 0 && this.flush();
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
emit(e) {
|
|
280
|
+
try {
|
|
281
|
+
this.observer?.(e);
|
|
282
|
+
} catch (t) {
|
|
283
|
+
this.report(t, {
|
|
284
|
+
kind: "observer",
|
|
285
|
+
name: e.name
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
report(e, t) {
|
|
290
|
+
try {
|
|
291
|
+
this.onError(e, t);
|
|
292
|
+
} catch (e) {
|
|
293
|
+
queueMicrotask(() => {
|
|
294
|
+
throw e;
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
collectWith(e, t, n) {
|
|
299
|
+
let r = this.activeObserver, i = /* @__PURE__ */ new Set();
|
|
300
|
+
e.collecting = i, this.activeObserver = e;
|
|
301
|
+
try {
|
|
302
|
+
let n = t();
|
|
303
|
+
return this.commitDependencies(e, i), n;
|
|
304
|
+
} catch (t) {
|
|
305
|
+
throw n && this.commitDependencies(e, i), t;
|
|
306
|
+
} finally {
|
|
307
|
+
e.collecting = void 0, this.activeObserver = r;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
commitDependencies(e, t) {
|
|
311
|
+
for (let n of e.dependencies) t.has(n) || n.dependents.delete(e);
|
|
312
|
+
for (let n of t) e.dependencies.has(n) || n.dependents.add(e);
|
|
313
|
+
e.dependencies.clear();
|
|
314
|
+
for (let n of t) e.dependencies.add(n);
|
|
315
|
+
}
|
|
316
|
+
flush() {
|
|
317
|
+
if (this.flushing) return;
|
|
318
|
+
this.flushing = !0;
|
|
319
|
+
let e = 0;
|
|
320
|
+
try {
|
|
321
|
+
for (; this.pending.size > 0 || this.listeners.size > 0;) {
|
|
322
|
+
if (++e > o) throw new n(`infinite reactive flush (>${o} iterations)`);
|
|
323
|
+
let t = [...this.pending], r = [...this.listeners];
|
|
324
|
+
this.pending.clear(), this.listeners.clear();
|
|
325
|
+
for (let e of t) e.run();
|
|
326
|
+
for (let e of r) try {
|
|
327
|
+
e();
|
|
328
|
+
} catch (e) {
|
|
329
|
+
this.report(e, { kind: "listener" });
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
} finally {
|
|
333
|
+
this.flushing = !1;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}, m = (e) => typeof e == "object" && !!e && r in e;
|
|
337
|
+
//#endregion
|
|
338
|
+
export { p as ReactiveRuntime, m as isReactive };
|
|
339
|
+
|
|
340
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","names":[],"sources":["../src/runtime.ts"],"sourcesContent":["import type {\n Cleanup,\n ComputedOptions,\n EffectHandle,\n EffectOptions,\n ReactiveErrorContext,\n ReactiveObserver,\n Readable,\n RippleOptions,\n Scope,\n Signal,\n SignalOptions,\n Unsubscribe,\n} from './types';\n\nimport { RippleComputedCycleError, RippleDisposedScopeError, RippleInfiniteLoopError } from './errors';\n\nconst REACTIVE = Symbol('ripple.reactive');\nconst SIGNAL = Symbol('ripple.signal');\nconst COMPUTED = Symbol('ripple.computed');\nconst MAX_FLUSH_ITERATIONS = 100;\nconst UNSET = Symbol('ripple.unset');\n\ntype Dependency = ReactiveNode<unknown>;\n\ntype ObserverNode = {\n collecting?: Set<Dependency>;\n readonly dependencies: Set<Dependency>;\n onDependencyChanged(): void;\n};\n\ntype Owned = {\n dispose(): void;\n};\n\nabstract class ReactiveNode<T> {\n readonly [REACTIVE] = true;\n readonly dependents = new Set<ObserverNode>();\n readonly name: string | undefined;\n protected readonly runtime: ReactiveRuntime;\n\n protected constructor(runtime: ReactiveRuntime, name?: string) {\n this.runtime = runtime;\n this.name = name;\n }\n\n abstract peek(): T;\n abstract get value(): T;\n\n subscribe(listener: () => void): Unsubscribe {\n this.peek();\n\n const observer: ObserverNode = {\n dependencies: new Set(),\n onDependencyChanged: () => this.runtime.enqueueListener(listener),\n };\n\n this.dependents.add(observer);\n\n return () => this.dependents.delete(observer);\n }\n\n protected notify(): void {\n for (const dependent of [...this.dependents]) dependent.onDependencyChanged();\n }\n}\n\nclass SignalNode<T> extends ReactiveNode<T> implements Signal<T> {\n readonly [SIGNAL] = true;\n private current: T;\n private readonly equals: (previous: T, next: T) => boolean;\n\n constructor(runtime: ReactiveRuntime, initial: T, options?: SignalOptions<T>) {\n super(runtime, options?.name);\n this.current = initial;\n this.equals = options?.equals ?? Object.is;\n }\n\n get value(): T {\n this.runtime.track(this);\n\n return this.current;\n }\n\n set value(next: T) {\n if (this.equals(this.current, next)) return;\n\n const previous = this.current;\n\n this.current = next;\n this.runtime.emit({ kind: 'write', name: this.name, next, previous });\n this.runtime.propagate(() => this.notify());\n }\n\n peek(): T {\n return this.current;\n }\n}\n\nclass ComputedNode<T> extends ReactiveNode<T> implements ObserverNode, Owned {\n readonly [COMPUTED] = true;\n readonly dependencies = new Set<Dependency>();\n private computing = false;\n private disposed = false;\n private dirty = true;\n private current: T | typeof UNSET = UNSET;\n private readonly derive: () => T;\n private readonly equals: (previous: T, next: T) => boolean;\n\n constructor(runtime: ReactiveRuntime, derive: () => T, options?: ComputedOptions<T>) {\n super(runtime, options?.name);\n this.derive = derive;\n this.equals = options?.equals ?? Object.is;\n }\n\n get value(): T {\n this.refresh();\n this.runtime.track(this);\n\n return this.current as T;\n }\n\n peek(): T {\n this.refresh();\n\n return this.current as T;\n }\n\n onDependencyChanged(): void {\n if (this.disposed) return;\n\n if (!this.dirty) this.dirty = true;\n\n if (this.dependents.size > 0 && this.refresh()) this.notify();\n }\n\n dispose(): void {\n if (this.disposed) return;\n\n this.disposed = true;\n this.runtime.clearDependencies(this);\n this.dependents.clear();\n }\n\n private refresh(): boolean {\n if (!this.dirty || this.disposed) return false;\n\n if (this.computing) {\n const label = this.name === undefined ? '' : ` \"${this.name}\"`;\n\n throw new RippleComputedCycleError(`computed cycle detected${label}`);\n }\n\n this.computing = true;\n this.runtime.emit({ kind: 'compute', name: this.name });\n\n try {\n const next = this.runtime.collect(this, this.derive);\n const changed = this.current === UNSET || !this.equals(this.current as T, next);\n\n this.current = next;\n this.dirty = false;\n\n return changed;\n } finally {\n this.computing = false;\n }\n }\n}\n\nclass ScopeNode implements Scope {\n readonly disposalController = new AbortController();\n readonly owned = new Set<Owned>();\n readonly name: string | undefined;\n private isDisposed = false;\n private readonly runtime: ReactiveRuntime;\n\n constructor(runtime: ReactiveRuntime, name?: string) {\n this.runtime = runtime;\n this.name = name;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n get disposalSignal(): AbortSignal {\n return this.disposalController.signal;\n }\n\n run<T>(fn: () => T): T {\n if (this.isDisposed) throw new RippleDisposedScopeError('Cannot run a disposed scope.');\n\n return this.runtime.withScope(this, fn);\n }\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n for (const owned of [...this.owned].reverse()) owned.dispose();\n this.owned.clear();\n this.disposalController.abort();\n this.runtime.emit({ kind: 'dispose', name: this.name, node: 'scope' });\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n}\n\nclass EffectNode implements ObserverNode, EffectHandle {\n readonly dependencies = new Set<Dependency>();\n readonly disposalController = new AbortController();\n private cleanup: Cleanup | undefined;\n private isDisposed = false;\n private owner: ScopeNode | undefined;\n private scheduled = false;\n private readonly callback: () => Cleanup | void;\n private readonly options: EffectOptions | undefined;\n private readonly runtime: ReactiveRuntime;\n\n constructor(runtime: ReactiveRuntime, callback: () => Cleanup | void, options?: EffectOptions) {\n this.runtime = runtime;\n this.callback = callback;\n this.options = options;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n get disposalSignal(): AbortSignal {\n return this.disposalController.signal;\n }\n\n onDependencyChanged(): void {\n if (this.isDisposed) return;\n\n if (this.options?.scheduler === 'microtask') {\n if (this.scheduled) return;\n\n this.scheduled = true;\n queueMicrotask(() => {\n this.scheduled = false;\n\n if (!this.isDisposed) this.runtime.enqueue(this);\n });\n\n return;\n }\n\n this.runtime.enqueue(this);\n }\n\n run(): void {\n if (this.isDisposed) return;\n\n this.owner?.dispose();\n this.owner = undefined;\n this.runCleanup();\n this.runtime.emit({ kind: 'effect', name: this.options?.name });\n\n const owner = new ScopeNode(this.runtime);\n\n try {\n const cleanup = this.runtime.withEffectScope(owner, () => this.runtime.collectEffect(this, this.callback));\n\n this.owner = owner;\n this.cleanup = typeof cleanup === 'function' ? cleanup : undefined;\n } catch (error) {\n owner.dispose();\n this.runtime.report(error, { kind: 'effect', name: this.options?.name });\n }\n }\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n this.owner?.dispose();\n this.owner = undefined;\n this.runtime.clearDependencies(this);\n this.runCleanup();\n this.disposalController.abort();\n this.runtime.emit({ kind: 'dispose', name: this.options?.name, node: 'effect' });\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n private runCleanup(): void {\n const cleanup = this.cleanup;\n\n this.cleanup = undefined;\n\n if (cleanup === undefined) return;\n\n try {\n cleanup();\n } catch (error) {\n this.runtime.report(error, { kind: 'cleanup', name: this.options?.name });\n }\n }\n}\n\n/**\n * A runtime owns reactive graph state and lifetime. Separate instances isolate\n * applications and SSR requests without process-wide mutable hooks.\n */\nexport class ReactiveRuntime {\n private activeEffectScope: ScopeNode | undefined;\n private activeObserver: ObserverNode | undefined;\n private activeScope: ScopeNode;\n private flushDepth = 0;\n private flushing = false;\n private readonly pending = new Set<EffectNode>();\n private readonly listeners = new Set<() => void>();\n private readonly rootScope: ScopeNode;\n private readonly observer: ReactiveObserver | undefined;\n private readonly onError: (error: unknown, context: ReactiveErrorContext) => void;\n\n constructor(options?: RippleOptions) {\n this.observer = options?.observer;\n this.onError =\n options?.onError ??\n ((error) => {\n queueMicrotask(() => {\n throw error;\n });\n });\n this.rootScope = new ScopeNode(this, 'runtime');\n this.activeScope = this.rootScope;\n }\n\n readonly signal = <T>(initial: T, options?: SignalOptions<T>): Signal<T> => new SignalNode(this, initial, options);\n\n readonly computed = <T>(derive: () => T, options?: ComputedOptions<T>): Readable<T> => {\n const node = new ComputedNode(this, derive, options);\n\n (this.activeEffectScope ?? this.activeScope).owned.add(node);\n\n return node;\n };\n\n readonly effect = (callback: () => Cleanup | void, options?: EffectOptions): EffectHandle => {\n const node = new EffectNode(this, callback, options);\n\n (this.activeEffectScope ?? this.activeScope).owned.add(node);\n node.run();\n\n return node;\n };\n\n readonly createScope = (name?: string): Scope => {\n const scope = new ScopeNode(this, name);\n\n this.activeScope.owned.add(scope);\n\n return scope;\n };\n\n readonly batch = <T>(fn: () => T): T => this.propagate(fn);\n\n readonly untrack = <T>(fn: () => T): T => this.withObserver(undefined, fn);\n\n dispose(): void {\n this.rootScope.dispose();\n }\n\n track(node: Dependency): void {\n const observer = this.activeObserver;\n\n if (observer?.collecting === undefined) return;\n\n observer.collecting.add(node);\n }\n\n clearDependencies(observer: ObserverNode): void {\n for (const dependency of observer.dependencies) dependency.dependents.delete(observer);\n observer.dependencies.clear();\n }\n\n collect<T>(observer: ObserverNode, fn: () => T): T {\n return this.collectWith(observer, fn, false);\n }\n\n collectEffect<T>(observer: ObserverNode, fn: () => T): T {\n return this.collectWith(observer, fn, true);\n }\n\n withEffectScope<T>(scope: ScopeNode, fn: () => T): T {\n const previous = this.activeEffectScope;\n\n this.activeEffectScope = scope;\n\n try {\n return fn();\n } finally {\n this.activeEffectScope = previous;\n }\n }\n\n withObserver<T>(observer: ObserverNode | undefined, fn: () => T): T {\n const previous = this.activeObserver;\n\n this.activeObserver = observer;\n\n try {\n return fn();\n } finally {\n this.activeObserver = previous;\n }\n }\n\n withScope<T>(scope: ScopeNode, fn: () => T): T {\n const previousEffectScope = this.activeEffectScope;\n const previousScope = this.activeScope;\n\n this.activeEffectScope = undefined;\n this.activeScope = scope;\n\n try {\n return fn();\n } finally {\n this.activeEffectScope = previousEffectScope;\n this.activeScope = previousScope;\n }\n }\n\n enqueue(effect: EffectNode): void {\n this.pending.add(effect);\n\n if (this.flushDepth === 0) this.flush();\n }\n\n enqueueListener(listener: () => void): void {\n this.listeners.add(listener);\n\n if (this.flushDepth === 0) this.flush();\n }\n\n propagate<T>(fn: () => T): T {\n this.flushDepth++;\n\n try {\n return fn();\n } finally {\n this.flushDepth--;\n\n if (this.flushDepth === 0) this.flush();\n }\n }\n\n emit(event: Parameters<ReactiveObserver>[0]): void {\n try {\n this.observer?.(event);\n } catch (error) {\n this.report(error, { kind: 'observer', name: event.name });\n }\n }\n\n report(error: unknown, context: ReactiveErrorContext): void {\n try {\n this.onError(error, context);\n } catch (reporterError) {\n queueMicrotask(() => {\n throw reporterError;\n });\n }\n }\n\n private collectWith<T>(observer: ObserverNode, fn: () => T, commitOnError: boolean): T {\n const previousObserver = this.activeObserver;\n const dependencies = new Set<Dependency>();\n\n observer.collecting = dependencies;\n this.activeObserver = observer;\n\n try {\n const result = fn();\n\n this.commitDependencies(observer, dependencies);\n\n return result;\n } catch (error) {\n if (commitOnError) this.commitDependencies(observer, dependencies);\n\n throw error;\n } finally {\n observer.collecting = undefined;\n this.activeObserver = previousObserver;\n }\n }\n\n private commitDependencies(observer: ObserverNode, next: Set<Dependency>): void {\n for (const dependency of observer.dependencies) {\n if (!next.has(dependency)) dependency.dependents.delete(observer);\n }\n\n for (const dependency of next) {\n if (!observer.dependencies.has(dependency)) dependency.dependents.add(observer);\n }\n\n observer.dependencies.clear();\n for (const dependency of next) observer.dependencies.add(dependency);\n }\n\n private flush(): void {\n if (this.flushing) return;\n\n this.flushing = true;\n\n let iterations = 0;\n\n try {\n while (this.pending.size > 0 || this.listeners.size > 0) {\n if (++iterations > MAX_FLUSH_ITERATIONS) {\n throw new RippleInfiniteLoopError(`infinite reactive flush (>${MAX_FLUSH_ITERATIONS} iterations)`);\n }\n\n const effects = [...this.pending];\n const listeners = [...this.listeners];\n\n this.pending.clear();\n this.listeners.clear();\n\n for (const effect of effects) effect.run();\n\n for (const listener of listeners) {\n try {\n listener();\n } catch (error) {\n this.report(error, { kind: 'listener' });\n }\n }\n }\n } finally {\n this.flushing = false;\n }\n }\n}\n\nexport const isReactive = <T>(value: T | Readable<T>): value is Readable<T> =>\n typeof value === 'object' && value !== null && REACTIVE in value;\n\nexport const isSignal = <T>(value: unknown): value is Signal<T> =>\n typeof value === 'object' && value !== null && SIGNAL in value;\n\nexport const isComputed = (value: unknown): value is Readable<unknown> =>\n typeof value === 'object' && value !== null && COMPUTED in value;\n"],"mappings":";;AAiBA,IAAM,IAAW,OAAO,iBAAiB,GACnC,IAAS,OAAO,eAAe,GAC/B,IAAW,OAAO,iBAAiB,GACnC,IAAuB,KACvB,IAAQ,OAAO,cAAc,GAcpB,IAAf,MAA+B;CAC7B,CAAU,KAAY;CACtB,6BAAsB,IAAI,IAAkB;CAC5C;CACA;CAEA,YAAsB,GAA0B,GAAe;EAE7D,AADA,KAAK,UAAU,GACf,KAAK,OAAO;CACd;CAKA,UAAU,GAAmC;EAC3C,KAAK,KAAK;EAEV,IAAM,IAAyB;GAC7B,8BAAc,IAAI,IAAI;GACtB,2BAA2B,KAAK,QAAQ,gBAAgB,CAAQ;EAClE;EAIA,OAFA,KAAK,WAAW,IAAI,CAAQ,SAEf,KAAK,WAAW,OAAO,CAAQ;CAC9C;CAEA,SAAyB;EACvB,KAAK,IAAM,KAAa,CAAC,GAAG,KAAK,UAAU,GAAG,EAAU,oBAAoB;CAC9E;AACF,GAEM,IAAN,cAA4B,EAAqC;CAC/D,CAAU,KAAU;CACpB;CACA;CAEA,YAAY,GAA0B,GAAY,GAA4B;EAG5E,AAFA,MAAM,GAAS,GAAS,IAAI,GAC5B,KAAK,UAAU,GACf,KAAK,SAAS,GAAS,UAAU,OAAO;CAC1C;CAEA,IAAI,QAAW;EAGb,OAFA,KAAK,QAAQ,MAAM,IAAI,GAEhB,KAAK;CACd;CAEA,IAAI,MAAM,GAAS;EACjB,IAAI,KAAK,OAAO,KAAK,SAAS,CAAI,GAAG;EAErC,IAAM,IAAW,KAAK;EAItB,AAFA,KAAK,UAAU,GACf,KAAK,QAAQ,KAAK;GAAE,MAAM;GAAS,MAAM,KAAK;GAAM;GAAM;EAAS,CAAC,GACpE,KAAK,QAAQ,gBAAgB,KAAK,OAAO,CAAC;CAC5C;CAEA,OAAU;EACR,OAAO,KAAK;CACd;AACF,GAEM,IAAN,cAA8B,EAA+C;CAC3E,CAAU,KAAY;CACtB,+BAAwB,IAAI,IAAgB;CAC5C,YAAoB;CACpB,WAAmB;CACnB,QAAgB;CAChB,UAAoC;CACpC;CACA;CAEA,YAAY,GAA0B,GAAiB,GAA8B;EAGnF,AAFA,MAAM,GAAS,GAAS,IAAI,GAC5B,KAAK,SAAS,GACd,KAAK,SAAS,GAAS,UAAU,OAAO;CAC1C;CAEA,IAAI,QAAW;EAIb,OAHA,KAAK,QAAQ,GACb,KAAK,QAAQ,MAAM,IAAI,GAEhB,KAAK;CACd;CAEA,OAAU;EAGR,OAFA,KAAK,QAAQ,GAEN,KAAK;CACd;CAEA,sBAA4B;EACtB,KAAK,aAET,AAAiB,KAAK,UAAQ,IAE1B,KAAK,WAAW,OAAO,KAAK,KAAK,QAAQ,KAAG,KAAK,OAAO;CAC9D;CAEA,UAAgB;EACV,KAAK,aAET,KAAK,WAAW,IAChB,KAAK,QAAQ,kBAAkB,IAAI,GACnC,KAAK,WAAW,MAAM;CACxB;CAEA,UAA2B;EACzB,IAAI,CAAC,KAAK,SAAS,KAAK,UAAU,OAAO;EAEzC,IAAI,KAAK,WAAW;GAClB,IAAM,IAAQ,KAAK,SAAS,KAAA,IAAY,KAAK,KAAK,KAAK,KAAK;GAE5D,MAAM,IAAI,EAAyB,0BAA0B,GAAO;EACtE;EAGA,AADA,KAAK,YAAY,IACjB,KAAK,QAAQ,KAAK;GAAE,MAAM;GAAW,MAAM,KAAK;EAAK,CAAC;EAEtD,IAAI;GACF,IAAM,IAAO,KAAK,QAAQ,QAAQ,MAAM,KAAK,MAAM,GAC7C,IAAU,KAAK,YAAY,KAAS,CAAC,KAAK,OAAO,KAAK,SAAc,CAAI;GAK9E,OAHA,KAAK,UAAU,GACf,KAAK,QAAQ,IAEN;EACT,UAAU;GACR,KAAK,YAAY;EACnB;CACF;AACF,GAEM,IAAN,MAAiC;CAC/B,qBAA8B,IAAI,gBAAgB;CAClD,wBAAiB,IAAI,IAAW;CAChC;CACA,aAAqB;CACrB;CAEA,YAAY,GAA0B,GAAe;EAEnD,AADA,KAAK,UAAU,GACf,KAAK,OAAO;CACd;CAEA,IAAI,WAAoB;EACtB,OAAO,KAAK;CACd;CAEA,IAAI,iBAA8B;EAChC,OAAO,KAAK,mBAAmB;CACjC;CAEA,IAAO,GAAgB;EACrB,IAAI,KAAK,YAAY,MAAM,IAAI,EAAyB,8BAA8B;EAEtF,OAAO,KAAK,QAAQ,UAAU,MAAM,CAAE;CACxC;CAEA,UAAgB;EACV,UAAK,YAET;QAAK,aAAa;GAClB,KAAK,IAAM,KAAS,CAAC,GAAG,KAAK,KAAK,CAAC,CAAC,QAAQ,GAAG,EAAM,QAAQ;GAG7D,AAFA,KAAK,MAAM,MAAM,GACjB,KAAK,mBAAmB,MAAM,GAC9B,KAAK,QAAQ,KAAK;IAAE,MAAM;IAAW,MAAM,KAAK;IAAM,MAAM;GAAQ,CAAC;EAJnD;CAKpB;CAEA,CAAC,OAAO,WAAiB;EACvB,KAAK,QAAQ;CACf;AACF,GAEM,IAAN,MAAuD;CACrD,+BAAwB,IAAI,IAAgB;CAC5C,qBAA8B,IAAI,gBAAgB;CAClD;CACA,aAAqB;CACrB;CACA,YAAoB;CACpB;CACA;CACA;CAEA,YAAY,GAA0B,GAAgC,GAAyB;EAG7F,AAFA,KAAK,UAAU,GACf,KAAK,WAAW,GAChB,KAAK,UAAU;CACjB;CAEA,IAAI,WAAoB;EACtB,OAAO,KAAK;CACd;CAEA,IAAI,iBAA8B;EAChC,OAAO,KAAK,mBAAmB;CACjC;CAEA,sBAA4B;EACtB,UAAK,YAET;OAAI,KAAK,SAAS,cAAc,aAAa;IAC3C,IAAI,KAAK,WAAW;IAGpB,AADA,KAAK,YAAY,IACjB,qBAAqB;KAGnB,AAFA,KAAK,YAAY,IAEZ,KAAK,cAAY,KAAK,QAAQ,QAAQ,IAAI;IACjD,CAAC;IAED;GACF;GAEA,KAAK,QAAQ,QAAQ,IAAI;EAFzB;CAGF;CAEA,MAAY;EACV,IAAI,KAAK,YAAY;EAKrB,AAHA,KAAK,OAAO,QAAQ,GACpB,KAAK,QAAQ,KAAA,GACb,KAAK,WAAW,GAChB,KAAK,QAAQ,KAAK;GAAE,MAAM;GAAU,MAAM,KAAK,SAAS;EAAK,CAAC;EAE9D,IAAM,IAAQ,IAAI,EAAU,KAAK,OAAO;EAExC,IAAI;GACF,IAAM,IAAU,KAAK,QAAQ,gBAAgB,SAAa,KAAK,QAAQ,cAAc,MAAM,KAAK,QAAQ,CAAC;GAGzG,AADA,KAAK,QAAQ,GACb,KAAK,UAAU,OAAO,KAAY,aAAa,IAAU,KAAA;EAC3D,SAAS,GAAO;GAEd,AADA,EAAM,QAAQ,GACd,KAAK,QAAQ,OAAO,GAAO;IAAE,MAAM;IAAU,MAAM,KAAK,SAAS;GAAK,CAAC;EACzE;CACF;CAEA,UAAgB;EACV,KAAK,eAET,KAAK,aAAa,IAClB,KAAK,OAAO,QAAQ,GACpB,KAAK,QAAQ,KAAA,GACb,KAAK,QAAQ,kBAAkB,IAAI,GACnC,KAAK,WAAW,GAChB,KAAK,mBAAmB,MAAM,GAC9B,KAAK,QAAQ,KAAK;GAAE,MAAM;GAAW,MAAM,KAAK,SAAS;GAAM,MAAM;EAAS,CAAC;CACjF;CAEA,CAAC,OAAO,WAAiB;EACvB,KAAK,QAAQ;CACf;CAEA,aAA2B;EACzB,IAAM,IAAU,KAAK;EAErB,SAAK,UAAU,KAAA,GAEX,MAAY,KAAA,GAEhB,IAAI;GACF,EAAQ;EACV,SAAS,GAAO;GACd,KAAK,QAAQ,OAAO,GAAO;IAAE,MAAM;IAAW,MAAM,KAAK,SAAS;GAAK,CAAC;EAC1E;CACF;AACF,GAMa,IAAb,MAA6B;CAC3B;CACA;CACA;CACA,aAAqB;CACrB,WAAmB;CACnB,0BAA2B,IAAI,IAAgB;CAC/C,4BAA6B,IAAI,IAAgB;CACjD;CACA;CACA;CAEA,YAAY,GAAyB;EAUnC,AATA,KAAK,WAAW,GAAS,UACzB,KAAK,UACH,GAAS,aACP,MAAU;GACV,qBAAqB;IACnB,MAAM;GACR,CAAC;EACH,IACF,KAAK,YAAY,IAAI,EAAU,MAAM,SAAS,GAC9C,KAAK,cAAc,KAAK;CAC1B;CAEA,UAAsB,GAAY,MAA0C,IAAI,EAAW,MAAM,GAAS,CAAO;CAEjH,YAAwB,GAAiB,MAA8C;EACrF,IAAM,IAAO,IAAI,EAAa,MAAM,GAAQ,CAAO;EAInD,QAFC,KAAK,qBAAqB,KAAK,YAAA,CAAa,MAAM,IAAI,CAAI,GAEpD;CACT;CAEA,UAAmB,GAAgC,MAA0C;EAC3F,IAAM,IAAO,IAAI,EAAW,MAAM,GAAU,CAAO;EAKnD,QAHC,KAAK,qBAAqB,KAAK,YAAA,CAAa,MAAM,IAAI,CAAI,GAC3D,EAAK,IAAI,GAEF;CACT;CAEA,eAAwB,MAAyB;EAC/C,IAAM,IAAQ,IAAI,EAAU,MAAM,CAAI;EAItC,OAFA,KAAK,YAAY,MAAM,IAAI,CAAK,GAEzB;CACT;CAEA,SAAqB,MAAmB,KAAK,UAAU,CAAE;CAEzD,WAAuB,MAAmB,KAAK,aAAa,KAAA,GAAW,CAAE;CAEzE,UAAgB;EACd,KAAK,UAAU,QAAQ;CACzB;CAEA,MAAM,GAAwB;EAC5B,IAAM,IAAW,KAAK;EAElB,GAAU,eAAe,KAAA,KAE7B,EAAS,WAAW,IAAI,CAAI;CAC9B;CAEA,kBAAkB,GAA8B;EAC9C,KAAK,IAAM,KAAc,EAAS,cAAc,EAAW,WAAW,OAAO,CAAQ;EACrF,EAAS,aAAa,MAAM;CAC9B;CAEA,QAAW,GAAwB,GAAgB;EACjD,OAAO,KAAK,YAAY,GAAU,GAAI,EAAK;CAC7C;CAEA,cAAiB,GAAwB,GAAgB;EACvD,OAAO,KAAK,YAAY,GAAU,GAAI,EAAI;CAC5C;CAEA,gBAAmB,GAAkB,GAAgB;EACnD,IAAM,IAAW,KAAK;EAEtB,KAAK,oBAAoB;EAEzB,IAAI;GACF,OAAO,EAAG;EACZ,UAAU;GACR,KAAK,oBAAoB;EAC3B;CACF;CAEA,aAAgB,GAAoC,GAAgB;EAClE,IAAM,IAAW,KAAK;EAEtB,KAAK,iBAAiB;EAEtB,IAAI;GACF,OAAO,EAAG;EACZ,UAAU;GACR,KAAK,iBAAiB;EACxB;CACF;CAEA,UAAa,GAAkB,GAAgB;EAC7C,IAAM,IAAsB,KAAK,mBAC3B,IAAgB,KAAK;EAG3B,AADA,KAAK,oBAAoB,KAAA,GACzB,KAAK,cAAc;EAEnB,IAAI;GACF,OAAO,EAAG;EACZ,UAAU;GAER,AADA,KAAK,oBAAoB,GACzB,KAAK,cAAc;EACrB;CACF;CAEA,QAAQ,GAA0B;EAGhC,AAFA,KAAK,QAAQ,IAAI,CAAM,GAEnB,KAAK,eAAe,KAAG,KAAK,MAAM;CACxC;CAEA,gBAAgB,GAA4B;EAG1C,AAFA,KAAK,UAAU,IAAI,CAAQ,GAEvB,KAAK,eAAe,KAAG,KAAK,MAAM;CACxC;CAEA,UAAa,GAAgB;EAC3B,KAAK;EAEL,IAAI;GACF,OAAO,EAAG;EACZ,UAAU;GAGR,AAFA,KAAK,cAED,KAAK,eAAe,KAAG,KAAK,MAAM;EACxC;CACF;CAEA,KAAK,GAA8C;EACjD,IAAI;GACF,KAAK,WAAW,CAAK;EACvB,SAAS,GAAO;GACd,KAAK,OAAO,GAAO;IAAE,MAAM;IAAY,MAAM,EAAM;GAAK,CAAC;EAC3D;CACF;CAEA,OAAO,GAAgB,GAAqC;EAC1D,IAAI;GACF,KAAK,QAAQ,GAAO,CAAO;EAC7B,SAAS,GAAe;GACtB,qBAAqB;IACnB,MAAM;GACR,CAAC;EACH;CACF;CAEA,YAAuB,GAAwB,GAAa,GAA2B;EACrF,IAAM,IAAmB,KAAK,gBACxB,oBAAe,IAAI,IAAgB;EAGzC,AADA,EAAS,aAAa,GACtB,KAAK,iBAAiB;EAEtB,IAAI;GACF,IAAM,IAAS,EAAG;GAIlB,OAFA,KAAK,mBAAmB,GAAU,CAAY,GAEvC;EACT,SAAS,GAAO;GAGd,MAFI,KAAe,KAAK,mBAAmB,GAAU,CAAY,GAE3D;EACR,UAAU;GAER,AADA,EAAS,aAAa,KAAA,GACtB,KAAK,iBAAiB;EACxB;CACF;CAEA,mBAA2B,GAAwB,GAA6B;EAC9E,KAAK,IAAM,KAAc,EAAS,cAChC,AAAK,EAAK,IAAI,CAAU,KAAG,EAAW,WAAW,OAAO,CAAQ;EAGlE,KAAK,IAAM,KAAc,GACvB,AAAK,EAAS,aAAa,IAAI,CAAU,KAAG,EAAW,WAAW,IAAI,CAAQ;EAGhF,EAAS,aAAa,MAAM;EAC5B,KAAK,IAAM,KAAc,GAAM,EAAS,aAAa,IAAI,CAAU;CACrE;CAEA,QAAsB;EACpB,IAAI,KAAK,UAAU;EAEnB,KAAK,WAAW;EAEhB,IAAI,IAAa;EAEjB,IAAI;GACF,OAAO,KAAK,QAAQ,OAAO,KAAK,KAAK,UAAU,OAAO,IAAG;IACvD,IAAI,EAAE,IAAa,GACjB,MAAM,IAAI,EAAwB,6BAA6B,EAAqB,aAAa;IAGnG,IAAM,IAAU,CAAC,GAAG,KAAK,OAAO,GAC1B,IAAY,CAAC,GAAG,KAAK,SAAS;IAGpC,AADA,KAAK,QAAQ,MAAM,GACnB,KAAK,UAAU,MAAM;IAErB,KAAK,IAAM,KAAU,GAAS,EAAO,IAAI;IAEzC,KAAK,IAAM,KAAY,GACrB,IAAI;KACF,EAAS;IACX,SAAS,GAAO;KACd,KAAK,OAAO,GAAO,EAAE,MAAM,WAAW,CAAC;IACzC;GAEJ;EACF,UAAU;GACR,KAAK,WAAW;EAClB;CACF;AACF,GAEa,KAAiB,MAC5B,OAAO,KAAU,cAAY,KAAkB,KAAY"}
|
package/dist/store.cjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
//# sourceMappingURL=store.cjs.map
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./index.cjs");exports.createStore=e.createStore;
|
package/dist/store.d.ts
CHANGED
|
@@ -1,58 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { IS_SIGNAL, IS_STORE } from './symbols';
|
|
4
|
-
export declare class StoreImpl<T extends object> implements Store<T> {
|
|
5
|
-
[IS_SIGNAL]: true;
|
|
6
|
-
[IS_STORE]: true;
|
|
7
|
-
readonly name: string | undefined;
|
|
8
|
-
private current_;
|
|
9
|
-
private disposed_;
|
|
10
|
-
private readonly initial_;
|
|
11
|
-
private readonly lensCache_;
|
|
12
|
-
private readonly propSignals_;
|
|
13
|
-
private readonly readonlyProxy_;
|
|
14
|
-
private readonly version_;
|
|
15
|
-
constructor(initial: T, name?: string);
|
|
16
|
-
/** Returns (or lazily creates) the per-property signal for a top-level key. */
|
|
17
|
-
propSignalFor_(key: string): SignalImpl<unknown>;
|
|
18
|
-
/**
|
|
19
|
-
* Returns the current state as a tracked read — registers the store as a dependency
|
|
20
|
-
* inside `effect()` / `computed()`. Any mutation re-runs the subscriber.
|
|
21
|
-
* For untracked one-off reads, use `peek()` instead.
|
|
22
|
-
*/
|
|
23
|
-
get value(): Readonly<T>;
|
|
24
|
-
/**
|
|
25
|
-
* Returns a frozen deep snapshot of the current state.
|
|
26
|
-
* The returned object reflects state at call time — it does not update as the store mutates.
|
|
27
|
-
* Nested objects are cloned (not aliased), so mutating nested properties on the snapshot
|
|
28
|
-
* does not affect the live store state.
|
|
29
|
-
* Use for serialization or one-off reads outside reactive contexts.
|
|
30
|
-
* For reactive reads, use `store.lens(path)` instead.
|
|
31
|
-
*/
|
|
32
|
-
peek(): Readonly<T>;
|
|
33
|
-
readonly subscribe: (listener: () => void) => Subscription;
|
|
34
|
-
patch(partial: Partial<T>): void;
|
|
35
|
-
replace(fn: (state: Readonly<T>) => T): void;
|
|
36
|
-
reset(): void;
|
|
37
|
-
/**
|
|
38
|
-
* Top-level lens: backed directly by the per-property signal — no extra graph node.
|
|
39
|
-
* The store owns propSig's lifecycle, so this lens has no `disposeSource`.
|
|
40
|
-
*/
|
|
41
|
-
private topLevelLens_;
|
|
42
|
-
/**
|
|
43
|
-
* Nested lens: backed by a derived `computed()` over the root property signal — the
|
|
44
|
-
* lens owns that computed (disposeSource) since nothing else references it.
|
|
45
|
-
* Write path batches the update so a nested lens write remains atomic.
|
|
46
|
-
*/
|
|
47
|
-
private nestedLens_;
|
|
48
|
-
/** Splits `path` on `.` and rejects empty/unsafe/too-deep segments before any lens is built. */
|
|
49
|
-
private validatedLensParts_;
|
|
50
|
-
lens<P extends string>(path: P): Signal<PathValue<T, P>>;
|
|
51
|
-
get disposed(): boolean;
|
|
52
|
-
dispose(): void;
|
|
53
|
-
[Symbol.dispose](): void;
|
|
54
|
-
}
|
|
55
|
-
export declare const store: <T extends object>(initial: T, options?: {
|
|
56
|
-
name?: string;
|
|
57
|
-
}) => Store<T>;
|
|
1
|
+
export type { Store, StoreOptions } from './_store';
|
|
2
|
+
export { createStore } from './index';
|
|
58
3
|
//# sourceMappingURL=store.d.ts.map
|
package/dist/store.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC"}
|
package/dist/store.js
CHANGED
|
@@ -1,207 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { batch as n } from "./scheduling.js";
|
|
4
|
-
import { IS_SIGNAL as r, IS_STORE as i } from "./symbols.js";
|
|
5
|
-
import { SignalImpl as a } from "./signal.js";
|
|
6
|
-
import { computed as o } from "./computed.js";
|
|
7
|
-
//#region src/store.ts
|
|
8
|
-
var s = (e) => {
|
|
9
|
-
if (e === "__proto__" || e === "constructor" || e === "prototype") throw new t(`Unsafe key "${e}" rejected to prevent prototype pollution.`);
|
|
10
|
-
}, c = (e, t) => {
|
|
11
|
-
let n = e;
|
|
12
|
-
for (let e of t) {
|
|
13
|
-
if (typeof n != "object" || !n) return;
|
|
14
|
-
n = n[e];
|
|
15
|
-
}
|
|
16
|
-
return n;
|
|
17
|
-
}, l = (e, n, r) => {
|
|
18
|
-
if (n.length === 0) return r;
|
|
19
|
-
if (typeof e != "object" || !e) throw new t("Cannot write to a nested path through a null or non-object intermediate value.");
|
|
20
|
-
let [i, ...a] = n, o = e;
|
|
21
|
-
return {
|
|
22
|
-
...o,
|
|
23
|
-
[i]: l(o[i], a, r)
|
|
24
|
-
};
|
|
25
|
-
}, u = class {
|
|
26
|
-
[r] = !0;
|
|
27
|
-
source_;
|
|
28
|
-
write_;
|
|
29
|
-
evict_;
|
|
30
|
-
disposeSource_;
|
|
31
|
-
name_;
|
|
32
|
-
disposed_ = !1;
|
|
33
|
-
get name() {
|
|
34
|
-
return this.name_ ?? this.source_.name;
|
|
35
|
-
}
|
|
36
|
-
constructor(e) {
|
|
37
|
-
this.source_ = e.source, this.write_ = e.write, this.evict_ = e.evict, this.disposeSource_ = e.disposeSource, this.name_ = e.name;
|
|
38
|
-
}
|
|
39
|
-
get value() {
|
|
40
|
-
return this.source_.value;
|
|
41
|
-
}
|
|
42
|
-
set value(e) {
|
|
43
|
-
this.write_(e);
|
|
44
|
-
}
|
|
45
|
-
peek() {
|
|
46
|
-
return this.source_.peek();
|
|
47
|
-
}
|
|
48
|
-
subscribe(e) {
|
|
49
|
-
return this.source_.subscribe(e);
|
|
50
|
-
}
|
|
51
|
-
get disposed() {
|
|
52
|
-
return this.disposed_ || this.source_.disposed;
|
|
53
|
-
}
|
|
54
|
-
dispose() {
|
|
55
|
-
this.disposed_ = !0, this.evict_(), this.disposeSource_?.();
|
|
56
|
-
}
|
|
57
|
-
[Symbol.dispose]() {
|
|
58
|
-
this.dispose();
|
|
59
|
-
}
|
|
60
|
-
}, d = class {
|
|
61
|
-
[r] = !0;
|
|
62
|
-
[i] = !0;
|
|
63
|
-
name;
|
|
64
|
-
current_;
|
|
65
|
-
disposed_;
|
|
66
|
-
initial_;
|
|
67
|
-
lensCache_;
|
|
68
|
-
propSignals_;
|
|
69
|
-
readonlyProxy_;
|
|
70
|
-
version_;
|
|
71
|
-
constructor(e, n) {
|
|
72
|
-
this.name = n, this.current_ = structuredClone(e), this.disposed_ = !1, this.initial_ = structuredClone(e), this.lensCache_ = /* @__PURE__ */ new Map(), this.propSignals_ = /* @__PURE__ */ new Map(), this.version_ = new a(0, void 0, n ? `${n}.version` : void 0), this.readonlyProxy_ = new Proxy(this.current_, {
|
|
73
|
-
deleteProperty(e, n) {
|
|
74
|
-
throw new t(`Direct deletion from store.value is not allowed. Use store.patch() or store.lens(). (key: "${String(n)}")`);
|
|
75
|
-
},
|
|
76
|
-
set(e, n) {
|
|
77
|
-
throw new t(`Direct mutation of store.value is not allowed. Use store.patch(), store.lens(), or store.replace(). (key: "${String(n)}")`);
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
propSignalFor_(e) {
|
|
82
|
-
let t = this.propSignals_.get(e);
|
|
83
|
-
return t === void 0 && (t = new a(this.current_[e], void 0, this.name === void 0 ? e : `${this.name}.${e}`), this.propSignals_.set(e, t)), t;
|
|
84
|
-
}
|
|
85
|
-
setPath_(e, t) {
|
|
86
|
-
let [n, ...r] = e, i = this.current_[n], a = l(i, r, t);
|
|
87
|
-
this.applyTopLevelChange_(n, a);
|
|
88
|
-
}
|
|
89
|
-
applyTopLevelChange_(e, t) {
|
|
90
|
-
s(e);
|
|
91
|
-
let n = this.current_[e];
|
|
92
|
-
Object.is(n, t) || (this.current_[e] = t, this.propSignalFor_(e).value = t, this.version_.value = this.version_.peek() + 1);
|
|
93
|
-
}
|
|
94
|
-
deleteTopLevelKey_(e) {
|
|
95
|
-
Object.hasOwn(this.current_, e) && (delete this.current_[e], this.propSignalFor_(e).value = void 0, this.version_.value = this.version_.peek() + 1);
|
|
96
|
-
}
|
|
97
|
-
applyFullState_(e) {
|
|
98
|
-
let t = this.current_, r = /* @__PURE__ */ new Set([...Object.keys(t), ...Object.keys(e)]);
|
|
99
|
-
for (let e of r) s(e);
|
|
100
|
-
n(() => {
|
|
101
|
-
for (let t of r) Object.hasOwn(e, t) ? this.applyTopLevelChange_(t, e[t]) : this.deleteTopLevelKey_(t);
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
get value() {
|
|
105
|
-
return this.version_.value, this.readonlyProxy_;
|
|
106
|
-
}
|
|
107
|
-
peek() {
|
|
108
|
-
return Object.freeze(structuredClone(this.current_));
|
|
109
|
-
}
|
|
110
|
-
subscribe = (e) => this.version_.subscribe(e);
|
|
111
|
-
patch(r) {
|
|
112
|
-
if (typeof r != "object" || !r || Array.isArray(r)) throw new t("store.patch() requires a plain object partial.");
|
|
113
|
-
let i = Object.keys(r);
|
|
114
|
-
if (i.length !== 0) {
|
|
115
|
-
for (let e of i) s(e);
|
|
116
|
-
n(() => {
|
|
117
|
-
for (let e of i) this.applyTopLevelChange_(e, r[e]);
|
|
118
|
-
}), e()?.mutate?.({
|
|
119
|
-
kind: "patch",
|
|
120
|
-
name: this.name
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
replace(t) {
|
|
125
|
-
let n = structuredClone(this.current_), r = t(n);
|
|
126
|
-
r !== n && (this.applyFullState_(r), e()?.mutate?.({
|
|
127
|
-
kind: "replace",
|
|
128
|
-
name: this.name
|
|
129
|
-
}));
|
|
130
|
-
}
|
|
131
|
-
reset() {
|
|
132
|
-
this.applyFullState_(this.initial_), e()?.mutate?.({
|
|
133
|
-
kind: "reset",
|
|
134
|
-
name: this.name
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
topLevelLens_(t, r) {
|
|
138
|
-
return new u({
|
|
139
|
-
evict: () => this.lensCache_.delete(r),
|
|
140
|
-
source: this.propSignalFor_(t),
|
|
141
|
-
write: (i) => {
|
|
142
|
-
n(() => this.applyTopLevelChange_(t, i)), e()?.mutate?.({
|
|
143
|
-
kind: "lens",
|
|
144
|
-
name: this.name,
|
|
145
|
-
path: r
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
nestedLens_(t, r) {
|
|
151
|
-
let i = o(() => c(this.propSignalFor_(t[0]).value, t.slice(1)));
|
|
152
|
-
return new u({
|
|
153
|
-
disposeSource: () => i.dispose(),
|
|
154
|
-
evict: () => this.lensCache_.delete(r),
|
|
155
|
-
name: this.name ? `${this.name}.${r}` : r,
|
|
156
|
-
source: i,
|
|
157
|
-
write: (a) => {
|
|
158
|
-
Object.is(i.peek(), a) || (n(() => this.setPath_(t, a)), e()?.mutate?.({
|
|
159
|
-
kind: "lens",
|
|
160
|
-
name: this.name,
|
|
161
|
-
path: r
|
|
162
|
-
}));
|
|
163
|
-
}
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
validatedLensParts_(e) {
|
|
167
|
-
let n = e.split(".");
|
|
168
|
-
if (n.length > 32) throw new t(`Lens path exceeds maximum depth of 32 segments: "${e}".`);
|
|
169
|
-
for (let r of n) {
|
|
170
|
-
if (r === "") throw new t(`Empty path segment in lens path "${e}". Check for consecutive dots.`);
|
|
171
|
-
if (r === "__proto__" || r === "constructor" || r === "prototype") throw new t(`Unsafe path segment "${r}" in lens path "${e}".`);
|
|
172
|
-
}
|
|
173
|
-
return n;
|
|
174
|
-
}
|
|
175
|
-
lens(e) {
|
|
176
|
-
let t = this.lensCache_.get(e);
|
|
177
|
-
if (t !== void 0) return t;
|
|
178
|
-
let n = this.validatedLensParts_(e), r = n.length === 1 ? this.topLevelLens_(n[0], e) : this.nestedLens_(n, e);
|
|
179
|
-
return this.lensCache_.set(e, r), r;
|
|
180
|
-
}
|
|
181
|
-
get disposed() {
|
|
182
|
-
return this.disposed_;
|
|
183
|
-
}
|
|
184
|
-
dispose() {
|
|
185
|
-
if (!this.disposed_) {
|
|
186
|
-
this.disposed_ = !0;
|
|
187
|
-
for (let e of [...this.lensCache_.values()]) e.dispose();
|
|
188
|
-
this.lensCache_.clear();
|
|
189
|
-
for (let e of this.propSignals_.values()) e.dispose();
|
|
190
|
-
this.propSignals_.clear(), this.version_.dispose(), e()?.dispose?.({
|
|
191
|
-
kind: "store",
|
|
192
|
-
name: this.name
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
[Symbol.dispose]() {
|
|
197
|
-
this.dispose();
|
|
198
|
-
}
|
|
199
|
-
}, f = (e, n) => {
|
|
200
|
-
if (typeof e != "object" || !e || Array.isArray(e)) throw new t("store() requires a plain object initial state.");
|
|
201
|
-
for (let t of Object.keys(e)) s(t);
|
|
202
|
-
return new d(e, n?.name);
|
|
203
|
-
};
|
|
204
|
-
//#endregion
|
|
205
|
-
export { d as StoreImpl, f as store };
|
|
206
|
-
|
|
207
|
-
//# sourceMappingURL=store.js.map
|
|
1
|
+
import { createStore as e } from "./index.js";
|
|
2
|
+
export { e as createStore };
|