@volynets/reflex-store 0.0.1 → 0.0.2
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 +23 -25
- package/dist/advanced.d.ts +0 -1
- package/dist/advanced.js +6 -5
- package/dist/chunks/collections-yHy0wH0f.js +268 -0
- package/dist/chunks/{compiler-CW_P8WsZ.js → compiler-Dsb3E2ck.js} +1 -11
- package/dist/chunks/{hydrate-Bdtl9XyA.js → hydrate-DMnHCI5q.js} +3 -2
- package/dist/chunks/{keyed-C-QvvUv4.js → keyed-CQKtL8a7.js} +6 -270
- package/dist/chunks/{names-BF36AyM3.js → names-Cx4YcvsH.js} +1 -1
- package/dist/chunks/{shared-BHHficW8.js → values-DCB6zyMz.js} +1 -61
- package/dist/compiled-store.js +1 -1
- package/dist/index.js +6 -5
- package/dist/runtime/internal.js +1 -1
- package/dist/runtime.d.ts +9 -5
- package/dist/runtime.js +18 -8
- package/dist/selectors/index.js +6 -5
- package/dist/selectors/shared.js +63 -1
- package/dist/store.js +1 -1
- package/dist/vite.d.ts +1 -1
- package/dist/vite.js +1 -1
- package/examples/task-board/src/reactivity.ts +33 -0
- package/examples/task-board/src/task-board.ts +1 -1
- package/package.json +4 -10
- package/dist/runtime/types.d.ts +0 -45
- package/dist/runtime/types.js +0 -1
package/README.md
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
# Reflex Store
|
|
2
2
|
|
|
3
3
|
Structured state, derived views and keyed collections with a compiler for static
|
|
4
|
-
store shapes. The library distribution
|
|
5
|
-
|
|
4
|
+
store shapes. The library distribution uses the shared reactive kernel and
|
|
5
|
+
lifecycle primitives. `@volynets/reflex-runtime` and
|
|
6
6
|
`@volynets/reflex-framework` are peer dependencies. Framework supplies the
|
|
7
7
|
shared lifecycle primitives, while Store, DOM and Async share the application's
|
|
8
8
|
kernel module identity.
|
|
9
9
|
The distribution includes the portable SWC WebAssembly compiler and Vite plugin.
|
|
10
10
|
|
|
11
11
|
```sh
|
|
12
|
-
pnpm add @volynets/reflex-store @volynets/reflex
|
|
12
|
+
pnpm add @volynets/reflex-store @volynets/reflex-runtime@^1.0.1 @volynets/reflex-framework
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
Requires Node.js 20.19 or newer for the compiler and Vite plugin. Published
|
|
@@ -23,7 +23,6 @@ Start with `createStore`, `derive`, `selector`, `reactiveMap`, `action` and
|
|
|
23
23
|
restoring compiled data.
|
|
24
24
|
|
|
25
25
|
```ts
|
|
26
|
-
import { createRuntime, effect } from "@volynets/reflex-store/runtime";
|
|
27
26
|
import {
|
|
28
27
|
createStore,
|
|
29
28
|
leaf,
|
|
@@ -35,8 +34,6 @@ import {
|
|
|
35
34
|
hydrate,
|
|
36
35
|
} from "@volynets/reflex-store";
|
|
37
36
|
|
|
38
|
-
createRuntime({ effectStrategy: "flush" });
|
|
39
|
-
|
|
40
37
|
export function createBoard() {
|
|
41
38
|
const board = createStore(
|
|
42
39
|
{
|
|
@@ -108,9 +105,10 @@ export default defineConfig({
|
|
|
108
105
|
```
|
|
109
106
|
|
|
110
107
|
The plugin transforms stores while preserving application package resolution.
|
|
111
|
-
|
|
112
|
-
`/runtime/core` and `/runtime/internal` re-export the shared
|
|
113
|
-
|
|
108
|
+
`@volynets/reflex-store/runtime` exports the compiler's cell, scope and owned
|
|
109
|
+
computed primitives. `/runtime/core` and `/runtime/internal` re-export the shared
|
|
110
|
+
kernel. Application runtime setup and effect scheduling belong to the consumer;
|
|
111
|
+
the task-board example includes explicit kernel/scheduler wiring.
|
|
114
112
|
|
|
115
113
|
The standalone compiler is exported from `@volynets/reflex-store/store`.
|
|
116
114
|
It includes its portable WASM asset; installing a platform-specific native SWC
|
|
@@ -129,27 +127,27 @@ and exposes disposal through `dispose()` and `Symbol.dispose`. Cells are created
|
|
|
129
127
|
and owned during setup; a failed initializer disposes earlier cells before
|
|
130
128
|
rethrowing its original error. Computed getter resources share the same lifetime.
|
|
131
129
|
|
|
132
|
-
Store compilation uses
|
|
133
|
-
optional way for application code to own a store alongside other resources.
|
|
130
|
+
Store compilation uses store scopes for ownership and disposal.
|
|
134
131
|
|
|
135
|
-
Use
|
|
132
|
+
Use a store scope to dispose resources together:
|
|
136
133
|
|
|
137
134
|
```ts
|
|
138
|
-
import {
|
|
135
|
+
import {
|
|
136
|
+
createStoreScope,
|
|
137
|
+
createStoreCell,
|
|
138
|
+
} from "@volynets/reflex-store/runtime";
|
|
139
139
|
import { derive, reactiveMap, selector } from "@volynets/reflex-store";
|
|
140
140
|
|
|
141
|
-
const createPanel =
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
ctx,
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
};
|
|
152
|
-
});
|
|
141
|
+
const createPanel = () =>
|
|
142
|
+
createStoreScope((ctx) => {
|
|
143
|
+
const tasks = ctx.own(reactiveMap<string, { done: boolean }>());
|
|
144
|
+
const selectedId = ctx.own(createStoreCell(""));
|
|
145
|
+
return {
|
|
146
|
+
tasks,
|
|
147
|
+
selected: ctx.own(selector(selectedId)),
|
|
148
|
+
summary: ctx.own(derive(() => ({ total: tasks.size }))),
|
|
149
|
+
};
|
|
150
|
+
});
|
|
153
151
|
```
|
|
154
152
|
|
|
155
153
|
Maps, sets, selectors, keyed projections, structured views and compiled stores
|
package/dist/advanced.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
/// <reference lib="esnext.disposable" />
|
|
2
|
-
import type { Destructor, Accessor } from "./runtime/types.js";
|
|
3
2
|
export { C as CompiledStore, S as StoreData, a as StoreOptions, b as StoreShape, c as createStore, l as leaf } from './types/createStore-BJ66-pfq.js';
|
|
4
3
|
export { action, derive, hydrate } from './index.js';
|
|
5
4
|
export { A as Accessor, D as Destructor, a as DisposableAccessor, S as StoreDisposable, c as createKeyedProjection, b as createSelector, b as selector } from './types/keyed-CdSYzIOc.js';
|
package/dist/advanced.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
export { createProjection } from './selectors/index.js';
|
|
2
|
-
export { R as ReactiveMap,
|
|
3
|
-
export { g as getStoreName } from './chunks/names-
|
|
4
|
-
export { c as collectStore, d as deep, a as disposeStore, o as opaque, r as raw, b as ref, e as shallow, s as snapshot } from './chunks/
|
|
2
|
+
export { R as ReactiveMap, a as ReactiveSet, c as createReactiveMap, c as reactiveMap, r as reactiveSet, t as transaction } from './chunks/collections-yHy0wH0f.js';
|
|
3
|
+
export { g as getStoreName } from './chunks/names-Cx4YcvsH.js';
|
|
4
|
+
export { c as collectStore, d as deep, a as disposeStore, o as opaque, r as raw, b as ref, e as shallow, s as snapshot } from './chunks/values-DCB6zyMz.js';
|
|
5
5
|
export { createStoreCell } from './runtime/internal.js';
|
|
6
|
-
export { a as action, d as derive, h as hydrate, l as leaf } from './chunks/hydrate-
|
|
6
|
+
export { a as action, d as derive, h as hydrate, l as leaf } from './chunks/hydrate-DMnHCI5q.js';
|
|
7
|
+
export { a as createKeyedProjection, c as createSelector, b as createStoreProjection, c as selector } from './chunks/keyed-CQKtL8a7.js';
|
|
7
8
|
export { c as createStore } from './chunks/createStore-DHj16Ehk.js';
|
|
8
9
|
import '@volynets/reflex-runtime/internal';
|
|
9
|
-
import '
|
|
10
|
+
import './selectors/shared.js';
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { untracked, currentConsumer, readProducer, createProducer, disposeNode, getActiveRuntimeContext, enterReactiveBatch, leaveReactiveBatch, writeProducer } from '@volynets/reflex-runtime/internal';
|
|
2
|
+
import { g as storeControls } from './values-DCB6zyMz.js';
|
|
3
|
+
import { s as setStoreName } from './names-Cx4YcvsH.js';
|
|
4
|
+
|
|
5
|
+
let transactionContext;
|
|
6
|
+
/** Publish a synchronous logical action at one runtime batch boundary. */ function transaction(action) {
|
|
7
|
+
if (transactionContext !== undefined && transactionContext === getActiveRuntimeContext()) return action();
|
|
8
|
+
const previous = transactionContext;
|
|
9
|
+
transactionContext = getActiveRuntimeContext();
|
|
10
|
+
enterReactiveBatch();
|
|
11
|
+
try {
|
|
12
|
+
return action();
|
|
13
|
+
} finally{
|
|
14
|
+
transactionContext = previous;
|
|
15
|
+
leaveReactiveBatch();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
class Cells {
|
|
19
|
+
read(key, value) {
|
|
20
|
+
if (currentConsumer === null) return value;
|
|
21
|
+
let entry = this.nodes.get(key);
|
|
22
|
+
if (!entry) {
|
|
23
|
+
entry = {
|
|
24
|
+
node: createProducer(0),
|
|
25
|
+
value
|
|
26
|
+
};
|
|
27
|
+
this.nodes.set(key, entry);
|
|
28
|
+
}
|
|
29
|
+
readProducer(entry.node);
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
write(key, value) {
|
|
33
|
+
const entry = this.nodes.get(key);
|
|
34
|
+
if (!entry || Object.is(entry.value, value)) return;
|
|
35
|
+
entry.value = value;
|
|
36
|
+
writeProducer(entry.node, entry.node.payload + 1);
|
|
37
|
+
}
|
|
38
|
+
clear(value) {
|
|
39
|
+
for (const entry of this.nodes.values()){
|
|
40
|
+
if (Object.is(entry.value, value)) continue;
|
|
41
|
+
entry.value = value;
|
|
42
|
+
writeProducer(entry.node, entry.node.payload + 1);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
collect() {
|
|
46
|
+
for (const [key, { node }] of this.nodes){
|
|
47
|
+
if (node.firstOut !== null) continue;
|
|
48
|
+
this.nodes.delete(key);
|
|
49
|
+
disposeNode(node);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
dispose() {
|
|
53
|
+
for (const { node } of this.nodes.values())disposeNode(node);
|
|
54
|
+
this.nodes.clear();
|
|
55
|
+
}
|
|
56
|
+
constructor(){
|
|
57
|
+
// Values live outside producer payloads so foreign objects remain valid even
|
|
58
|
+
// when runtime dev validation accepts only primitive/plain payloads.
|
|
59
|
+
this.nodes = new Map();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
class ReactiveMap {
|
|
63
|
+
constructor(initial, options = {}){
|
|
64
|
+
this.initial = initial;
|
|
65
|
+
this.options = options;
|
|
66
|
+
this.disposed = false;
|
|
67
|
+
this.valuesByKey = new Cells();
|
|
68
|
+
this.existsByKey = new Cells();
|
|
69
|
+
setStoreName(this, options.name);
|
|
70
|
+
storeControls.set(this, {
|
|
71
|
+
raw: ()=>this.backing(),
|
|
72
|
+
collect: ()=>this.collect(),
|
|
73
|
+
dispose: ()=>this.dispose()
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
backing() {
|
|
77
|
+
if (this.disposed) throw new Error("Cannot use a disposed reactive map");
|
|
78
|
+
if (!this.data) {
|
|
79
|
+
this.data = untracked(()=>new Map(typeof this.initial === "function" ? this.initial() : this.initial));
|
|
80
|
+
this.initial = undefined;
|
|
81
|
+
}
|
|
82
|
+
return this.data;
|
|
83
|
+
}
|
|
84
|
+
get size() {
|
|
85
|
+
const size = this.backing().size;
|
|
86
|
+
if (currentConsumer !== null) readProducer(this.sizeNode ??= createProducer(size));
|
|
87
|
+
return size;
|
|
88
|
+
}
|
|
89
|
+
get [Symbol.toStringTag]() {
|
|
90
|
+
return "ReactiveMap";
|
|
91
|
+
}
|
|
92
|
+
get(key) {
|
|
93
|
+
return this.valuesByKey.read(key, this.backing().get(key));
|
|
94
|
+
}
|
|
95
|
+
has(key) {
|
|
96
|
+
return this.existsByKey.read(key, this.backing().has(key));
|
|
97
|
+
}
|
|
98
|
+
set(key, value) {
|
|
99
|
+
const data = this.backing();
|
|
100
|
+
const previous = data.get(key);
|
|
101
|
+
const existed = previous !== undefined || data.has(key);
|
|
102
|
+
if (existed) {
|
|
103
|
+
const equals = this.options.equals;
|
|
104
|
+
if (equals == null || equals === Object.is ? Object.is(previous, value) : untracked(()=>equals(previous, value))) return this;
|
|
105
|
+
}
|
|
106
|
+
this.commitSet(data, key, value, existed);
|
|
107
|
+
return this;
|
|
108
|
+
}
|
|
109
|
+
commitSet(data, key, value, existed) {
|
|
110
|
+
transaction(()=>{
|
|
111
|
+
data.set(key, value);
|
|
112
|
+
this.valuesByKey.write(key, value);
|
|
113
|
+
if (!existed) {
|
|
114
|
+
this.existsByKey.write(key, true);
|
|
115
|
+
if (this.sizeNode) writeProducer(this.sizeNode, data.size);
|
|
116
|
+
if (this.keysNode) writeProducer(this.keysNode, this.keysNode.payload + 1);
|
|
117
|
+
}
|
|
118
|
+
if (this.valuesNode) writeProducer(this.valuesNode, this.valuesNode.payload + 1);
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
delete(key) {
|
|
122
|
+
const data = this.backing();
|
|
123
|
+
if (!data.has(key)) return false;
|
|
124
|
+
transaction(()=>{
|
|
125
|
+
data.delete(key);
|
|
126
|
+
this.valuesByKey.write(key, undefined);
|
|
127
|
+
this.existsByKey.write(key, false);
|
|
128
|
+
if (this.sizeNode) writeProducer(this.sizeNode, data.size);
|
|
129
|
+
if (this.keysNode) writeProducer(this.keysNode, this.keysNode.payload + 1);
|
|
130
|
+
if (this.valuesNode) writeProducer(this.valuesNode, this.valuesNode.payload + 1);
|
|
131
|
+
});
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
clear() {
|
|
135
|
+
const data = this.backing();
|
|
136
|
+
if (data.size === 0) return;
|
|
137
|
+
transaction(()=>{
|
|
138
|
+
data.clear();
|
|
139
|
+
// Only materialized semantic locations need invalidation, even for a large map.
|
|
140
|
+
this.valuesByKey.clear(undefined);
|
|
141
|
+
this.existsByKey.clear(false);
|
|
142
|
+
if (this.sizeNode) writeProducer(this.sizeNode, 0);
|
|
143
|
+
if (this.keysNode) writeProducer(this.keysNode, this.keysNode.payload + 1);
|
|
144
|
+
if (this.valuesNode) writeProducer(this.valuesNode, this.valuesNode.payload + 1);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
keys() {
|
|
148
|
+
const data = this.backing();
|
|
149
|
+
if (currentConsumer !== null) readProducer(this.keysNode ??= createProducer(0));
|
|
150
|
+
return data.keys();
|
|
151
|
+
}
|
|
152
|
+
values() {
|
|
153
|
+
const data = this.backing();
|
|
154
|
+
if (currentConsumer !== null) readProducer(this.valuesNode ??= createProducer(0));
|
|
155
|
+
return data.values();
|
|
156
|
+
}
|
|
157
|
+
entries() {
|
|
158
|
+
const data = this.backing();
|
|
159
|
+
if (currentConsumer !== null) readProducer(this.valuesNode ??= createProducer(0));
|
|
160
|
+
return data.entries();
|
|
161
|
+
}
|
|
162
|
+
[Symbol.iterator]() {
|
|
163
|
+
return this.entries();
|
|
164
|
+
}
|
|
165
|
+
forEach(callback, thisArg) {
|
|
166
|
+
const data = this.backing();
|
|
167
|
+
if (currentConsumer !== null) readProducer(this.valuesNode ??= createProducer(0));
|
|
168
|
+
data.forEach((value, key)=>callback.call(thisArg, value, key, this));
|
|
169
|
+
}
|
|
170
|
+
collect() {
|
|
171
|
+
this.valuesByKey.collect();
|
|
172
|
+
this.existsByKey.collect();
|
|
173
|
+
if (this.sizeNode?.firstOut === null) {
|
|
174
|
+
disposeNode(this.sizeNode);
|
|
175
|
+
this.sizeNode = undefined;
|
|
176
|
+
}
|
|
177
|
+
if (this.keysNode?.firstOut === null) {
|
|
178
|
+
disposeNode(this.keysNode);
|
|
179
|
+
this.keysNode = undefined;
|
|
180
|
+
}
|
|
181
|
+
if (this.valuesNode?.firstOut === null) {
|
|
182
|
+
disposeNode(this.valuesNode);
|
|
183
|
+
this.valuesNode = undefined;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
[Symbol.dispose]() {
|
|
187
|
+
this.dispose();
|
|
188
|
+
}
|
|
189
|
+
dispose() {
|
|
190
|
+
this.disposed = true;
|
|
191
|
+
this.valuesByKey.dispose();
|
|
192
|
+
this.existsByKey.dispose();
|
|
193
|
+
if (this.sizeNode) disposeNode(this.sizeNode);
|
|
194
|
+
if (this.keysNode) disposeNode(this.keysNode);
|
|
195
|
+
if (this.valuesNode) disposeNode(this.valuesNode);
|
|
196
|
+
this.sizeNode = this.keysNode = this.valuesNode = undefined;
|
|
197
|
+
this.data = undefined;
|
|
198
|
+
this.initial = undefined;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
/** A native Set-shaped membership collection over keyed reactive observations. */ class ReactiveSet {
|
|
202
|
+
constructor(initial, options = {}){
|
|
203
|
+
this.members = new ReactiveMap(()=>Array.from(typeof initial === "function" ? initial() : initial ?? [], (value)=>[
|
|
204
|
+
value,
|
|
205
|
+
true
|
|
206
|
+
]));
|
|
207
|
+
setStoreName(this, options.name);
|
|
208
|
+
storeControls.set(this, {
|
|
209
|
+
raw: ()=>new Set(this.members.keys()),
|
|
210
|
+
collect: ()=>this.collect(),
|
|
211
|
+
dispose: ()=>this.dispose()
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
get size() {
|
|
215
|
+
return this.members.size;
|
|
216
|
+
}
|
|
217
|
+
get [Symbol.toStringTag]() {
|
|
218
|
+
return "ReactiveSet";
|
|
219
|
+
}
|
|
220
|
+
has(value) {
|
|
221
|
+
return this.members.has(value);
|
|
222
|
+
}
|
|
223
|
+
add(value) {
|
|
224
|
+
this.members.set(value, true);
|
|
225
|
+
return this;
|
|
226
|
+
}
|
|
227
|
+
delete(value) {
|
|
228
|
+
return this.members.delete(value);
|
|
229
|
+
}
|
|
230
|
+
clear() {
|
|
231
|
+
this.members.clear();
|
|
232
|
+
}
|
|
233
|
+
values() {
|
|
234
|
+
return this.members.keys();
|
|
235
|
+
}
|
|
236
|
+
keys() {
|
|
237
|
+
return this.values();
|
|
238
|
+
}
|
|
239
|
+
*entries() {
|
|
240
|
+
for (const value of this.values())yield [
|
|
241
|
+
value,
|
|
242
|
+
value
|
|
243
|
+
];
|
|
244
|
+
}
|
|
245
|
+
[Symbol.iterator]() {
|
|
246
|
+
return this.values();
|
|
247
|
+
}
|
|
248
|
+
forEach(callback, thisArg) {
|
|
249
|
+
for (const value of this.values())callback.call(thisArg, value, value, this);
|
|
250
|
+
}
|
|
251
|
+
collect() {
|
|
252
|
+
this.members.collect();
|
|
253
|
+
}
|
|
254
|
+
dispose() {
|
|
255
|
+
this.members.dispose();
|
|
256
|
+
}
|
|
257
|
+
[Symbol.dispose]() {
|
|
258
|
+
this.dispose();
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
function reactiveSet(initial, options) {
|
|
262
|
+
return new ReactiveSet(initial, options);
|
|
263
|
+
}
|
|
264
|
+
function createReactiveMap(initial, options) {
|
|
265
|
+
return new ReactiveMap(initial, options);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export { ReactiveMap as R, ReactiveSet as a, createReactiveMap as c, reactiveSet as r, transaction as t };
|
|
@@ -1160,10 +1160,7 @@ function scanUnsupportedStoreSyntax(program, state) {
|
|
|
1160
1160
|
}
|
|
1161
1161
|
const intrinsicNames = new Map();
|
|
1162
1162
|
for (const item of program.body){
|
|
1163
|
-
if (item.type !== "ImportDeclaration" || !STORE_MODULES$1.has(item.source.value)
|
|
1164
|
-
"@volynets/reflex",
|
|
1165
|
-
"@volynets/reflex-store/runtime"
|
|
1166
|
-
].includes(item.source.value)) continue;
|
|
1163
|
+
if (item.type !== "ImportDeclaration" || !STORE_MODULES$1.has(item.source.value)) continue;
|
|
1167
1164
|
for (const specifier of item.specifiers){
|
|
1168
1165
|
if (specifier.type !== "ImportSpecifier" || specifier.isTypeOnly) continue;
|
|
1169
1166
|
const imported = specifier.imported?.value ?? specifier.local.value;
|
|
@@ -1175,13 +1172,6 @@ function scanUnsupportedStoreSyntax(program, state) {
|
|
|
1175
1172
|
arity: imported === "hydrate" ? 2 : 1,
|
|
1176
1173
|
rootIndex: 0
|
|
1177
1174
|
});
|
|
1178
|
-
if (imported === "own" && [
|
|
1179
|
-
"@volynets/reflex",
|
|
1180
|
-
"@volynets/reflex-store/runtime"
|
|
1181
|
-
].includes(item.source.value)) intrinsicNames.set(bindingKey(specifier.local), {
|
|
1182
|
-
arity: 2,
|
|
1183
|
-
rootIndex: 1
|
|
1184
|
-
});
|
|
1185
1175
|
}
|
|
1186
1176
|
}
|
|
1187
1177
|
const returnRoots = new Set();
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { i as isPlain,
|
|
1
|
+
import { d as createDerivedProjection } from './keyed-CQKtL8a7.js';
|
|
2
|
+
import { i as isPlain, h as getStoreControl, j as depthOf } from './values-DCB6zyMz.js';
|
|
3
3
|
import { untracked } from '@volynets/reflex-runtime/internal';
|
|
4
|
+
import { t as transaction } from './collections-yHy0wH0f.js';
|
|
4
5
|
|
|
5
6
|
/** Marks one compiled store value as a replaceable leaf. */ function leaf(value) {
|
|
6
7
|
return value;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { setCurrentConsumer, currentConsumer, createConsumer, readConsumerLazy, disposeNode, untracked, unlinkAllSources, CONSUMER_INITIAL_STATE, createProducer,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { setCurrentConsumer, currentConsumer, createConsumer, readConsumerLazy, disposeNode, untracked, unlinkAllSources, CONSUMER_INITIAL_STATE, createProducer, disposeWatcher, createWatcher, runWatcher, Both, readProducer, writeProducer } from '@volynets/reflex-runtime/internal';
|
|
2
|
+
import { f as cloneValue, g as storeControls, j as depthOf, k as isStructural } from './values-DCB6zyMz.js';
|
|
3
|
+
import { a as storeName, s as setStoreName } from './names-Cx4YcvsH.js';
|
|
4
|
+
import { readProjectionPath } from '../selectors/shared.js';
|
|
5
|
+
import { t as transaction } from './collections-yHy0wH0f.js';
|
|
5
6
|
|
|
6
7
|
/** A memo with owner-controlled suspension; no node exists until its first read. */ class Demand {
|
|
7
8
|
constructor(compute){
|
|
@@ -265,271 +266,6 @@ function createSignalNode(payload) {
|
|
|
265
266
|
return createProducer(payload);
|
|
266
267
|
}
|
|
267
268
|
|
|
268
|
-
let transactionContext;
|
|
269
|
-
/** Publish a synchronous logical action at one runtime batch boundary. */ function transaction(action) {
|
|
270
|
-
if (transactionContext !== undefined && transactionContext === getActiveRuntimeContext()) return action();
|
|
271
|
-
return batch(()=>{
|
|
272
|
-
const previous = transactionContext;
|
|
273
|
-
transactionContext = getActiveRuntimeContext();
|
|
274
|
-
enterReactiveBatch();
|
|
275
|
-
try {
|
|
276
|
-
return action();
|
|
277
|
-
} finally{
|
|
278
|
-
transactionContext = previous;
|
|
279
|
-
leaveReactiveBatch();
|
|
280
|
-
}
|
|
281
|
-
});
|
|
282
|
-
}
|
|
283
|
-
class Cells {
|
|
284
|
-
read(key, value) {
|
|
285
|
-
if (currentConsumer === null) return value;
|
|
286
|
-
let entry = this.nodes.get(key);
|
|
287
|
-
if (!entry) {
|
|
288
|
-
entry = {
|
|
289
|
-
node: createProducer(0),
|
|
290
|
-
value
|
|
291
|
-
};
|
|
292
|
-
this.nodes.set(key, entry);
|
|
293
|
-
}
|
|
294
|
-
readProducer(entry.node);
|
|
295
|
-
return value;
|
|
296
|
-
}
|
|
297
|
-
write(key, value) {
|
|
298
|
-
const entry = this.nodes.get(key);
|
|
299
|
-
if (!entry || Object.is(entry.value, value)) return;
|
|
300
|
-
entry.value = value;
|
|
301
|
-
writeProducer(entry.node, entry.node.payload + 1);
|
|
302
|
-
}
|
|
303
|
-
clear(value) {
|
|
304
|
-
for (const entry of this.nodes.values()){
|
|
305
|
-
if (Object.is(entry.value, value)) continue;
|
|
306
|
-
entry.value = value;
|
|
307
|
-
writeProducer(entry.node, entry.node.payload + 1);
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
collect() {
|
|
311
|
-
for (const [key, { node }] of this.nodes){
|
|
312
|
-
if (node.firstOut !== null) continue;
|
|
313
|
-
this.nodes.delete(key);
|
|
314
|
-
disposeNode(node);
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
dispose() {
|
|
318
|
-
for (const { node } of this.nodes.values())disposeNode(node);
|
|
319
|
-
this.nodes.clear();
|
|
320
|
-
}
|
|
321
|
-
constructor(){
|
|
322
|
-
// Values live outside producer payloads so foreign objects remain valid even
|
|
323
|
-
// when runtime dev validation accepts only primitive/plain payloads.
|
|
324
|
-
this.nodes = new Map();
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
class ReactiveMap {
|
|
328
|
-
constructor(initial, options = {}){
|
|
329
|
-
this.initial = initial;
|
|
330
|
-
this.options = options;
|
|
331
|
-
this.disposed = false;
|
|
332
|
-
this.valuesByKey = new Cells();
|
|
333
|
-
this.existsByKey = new Cells();
|
|
334
|
-
setStoreName(this, options.name);
|
|
335
|
-
storeControls.set(this, {
|
|
336
|
-
raw: ()=>this.backing(),
|
|
337
|
-
collect: ()=>this.collect(),
|
|
338
|
-
dispose: ()=>this.dispose()
|
|
339
|
-
});
|
|
340
|
-
}
|
|
341
|
-
backing() {
|
|
342
|
-
if (this.disposed) throw new Error("Cannot use a disposed reactive map");
|
|
343
|
-
if (!this.data) {
|
|
344
|
-
this.data = untracked(()=>new Map(typeof this.initial === "function" ? this.initial() : this.initial));
|
|
345
|
-
this.initial = undefined;
|
|
346
|
-
}
|
|
347
|
-
return this.data;
|
|
348
|
-
}
|
|
349
|
-
get size() {
|
|
350
|
-
const size = this.backing().size;
|
|
351
|
-
if (currentConsumer !== null) readProducer(this.sizeNode ??= createProducer(size));
|
|
352
|
-
return size;
|
|
353
|
-
}
|
|
354
|
-
get [Symbol.toStringTag]() {
|
|
355
|
-
return "ReactiveMap";
|
|
356
|
-
}
|
|
357
|
-
get(key) {
|
|
358
|
-
return this.valuesByKey.read(key, this.backing().get(key));
|
|
359
|
-
}
|
|
360
|
-
has(key) {
|
|
361
|
-
return this.existsByKey.read(key, this.backing().has(key));
|
|
362
|
-
}
|
|
363
|
-
set(key, value) {
|
|
364
|
-
const data = this.backing();
|
|
365
|
-
const previous = data.get(key);
|
|
366
|
-
const existed = previous !== undefined || data.has(key);
|
|
367
|
-
if (existed) {
|
|
368
|
-
const equals = this.options.equals;
|
|
369
|
-
if (equals == null || equals === Object.is ? Object.is(previous, value) : untracked(()=>equals(previous, value))) return this;
|
|
370
|
-
}
|
|
371
|
-
this.commitSet(data, key, value, existed);
|
|
372
|
-
return this;
|
|
373
|
-
}
|
|
374
|
-
commitSet(data, key, value, existed) {
|
|
375
|
-
transaction(()=>{
|
|
376
|
-
data.set(key, value);
|
|
377
|
-
this.valuesByKey.write(key, value);
|
|
378
|
-
if (!existed) {
|
|
379
|
-
this.existsByKey.write(key, true);
|
|
380
|
-
if (this.sizeNode) writeProducer(this.sizeNode, data.size);
|
|
381
|
-
if (this.keysNode) writeProducer(this.keysNode, this.keysNode.payload + 1);
|
|
382
|
-
}
|
|
383
|
-
if (this.valuesNode) writeProducer(this.valuesNode, this.valuesNode.payload + 1);
|
|
384
|
-
});
|
|
385
|
-
}
|
|
386
|
-
delete(key) {
|
|
387
|
-
const data = this.backing();
|
|
388
|
-
if (!data.has(key)) return false;
|
|
389
|
-
transaction(()=>{
|
|
390
|
-
data.delete(key);
|
|
391
|
-
this.valuesByKey.write(key, undefined);
|
|
392
|
-
this.existsByKey.write(key, false);
|
|
393
|
-
if (this.sizeNode) writeProducer(this.sizeNode, data.size);
|
|
394
|
-
if (this.keysNode) writeProducer(this.keysNode, this.keysNode.payload + 1);
|
|
395
|
-
if (this.valuesNode) writeProducer(this.valuesNode, this.valuesNode.payload + 1);
|
|
396
|
-
});
|
|
397
|
-
return true;
|
|
398
|
-
}
|
|
399
|
-
clear() {
|
|
400
|
-
const data = this.backing();
|
|
401
|
-
if (data.size === 0) return;
|
|
402
|
-
transaction(()=>{
|
|
403
|
-
data.clear();
|
|
404
|
-
// Only materialized semantic locations need invalidation, even for a large map.
|
|
405
|
-
this.valuesByKey.clear(undefined);
|
|
406
|
-
this.existsByKey.clear(false);
|
|
407
|
-
if (this.sizeNode) writeProducer(this.sizeNode, 0);
|
|
408
|
-
if (this.keysNode) writeProducer(this.keysNode, this.keysNode.payload + 1);
|
|
409
|
-
if (this.valuesNode) writeProducer(this.valuesNode, this.valuesNode.payload + 1);
|
|
410
|
-
});
|
|
411
|
-
}
|
|
412
|
-
keys() {
|
|
413
|
-
const data = this.backing();
|
|
414
|
-
if (currentConsumer !== null) readProducer(this.keysNode ??= createProducer(0));
|
|
415
|
-
return data.keys();
|
|
416
|
-
}
|
|
417
|
-
values() {
|
|
418
|
-
const data = this.backing();
|
|
419
|
-
if (currentConsumer !== null) readProducer(this.valuesNode ??= createProducer(0));
|
|
420
|
-
return data.values();
|
|
421
|
-
}
|
|
422
|
-
entries() {
|
|
423
|
-
const data = this.backing();
|
|
424
|
-
if (currentConsumer !== null) readProducer(this.valuesNode ??= createProducer(0));
|
|
425
|
-
return data.entries();
|
|
426
|
-
}
|
|
427
|
-
[Symbol.iterator]() {
|
|
428
|
-
return this.entries();
|
|
429
|
-
}
|
|
430
|
-
forEach(callback, thisArg) {
|
|
431
|
-
const data = this.backing();
|
|
432
|
-
if (currentConsumer !== null) readProducer(this.valuesNode ??= createProducer(0));
|
|
433
|
-
data.forEach((value, key)=>callback.call(thisArg, value, key, this));
|
|
434
|
-
}
|
|
435
|
-
collect() {
|
|
436
|
-
this.valuesByKey.collect();
|
|
437
|
-
this.existsByKey.collect();
|
|
438
|
-
if (this.sizeNode?.firstOut === null) {
|
|
439
|
-
disposeNode(this.sizeNode);
|
|
440
|
-
this.sizeNode = undefined;
|
|
441
|
-
}
|
|
442
|
-
if (this.keysNode?.firstOut === null) {
|
|
443
|
-
disposeNode(this.keysNode);
|
|
444
|
-
this.keysNode = undefined;
|
|
445
|
-
}
|
|
446
|
-
if (this.valuesNode?.firstOut === null) {
|
|
447
|
-
disposeNode(this.valuesNode);
|
|
448
|
-
this.valuesNode = undefined;
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
[Symbol.dispose]() {
|
|
452
|
-
this.dispose();
|
|
453
|
-
}
|
|
454
|
-
dispose() {
|
|
455
|
-
this.disposed = true;
|
|
456
|
-
this.valuesByKey.dispose();
|
|
457
|
-
this.existsByKey.dispose();
|
|
458
|
-
if (this.sizeNode) disposeNode(this.sizeNode);
|
|
459
|
-
if (this.keysNode) disposeNode(this.keysNode);
|
|
460
|
-
if (this.valuesNode) disposeNode(this.valuesNode);
|
|
461
|
-
this.sizeNode = this.keysNode = this.valuesNode = undefined;
|
|
462
|
-
this.data = undefined;
|
|
463
|
-
this.initial = undefined;
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
/** A native Set-shaped membership collection over keyed reactive observations. */ class ReactiveSet {
|
|
467
|
-
constructor(initial, options = {}){
|
|
468
|
-
this.members = new ReactiveMap(()=>Array.from(typeof initial === "function" ? initial() : initial ?? [], (value)=>[
|
|
469
|
-
value,
|
|
470
|
-
true
|
|
471
|
-
]));
|
|
472
|
-
setStoreName(this, options.name);
|
|
473
|
-
storeControls.set(this, {
|
|
474
|
-
raw: ()=>new Set(this.members.keys()),
|
|
475
|
-
collect: ()=>this.collect(),
|
|
476
|
-
dispose: ()=>this.dispose()
|
|
477
|
-
});
|
|
478
|
-
}
|
|
479
|
-
get size() {
|
|
480
|
-
return this.members.size;
|
|
481
|
-
}
|
|
482
|
-
get [Symbol.toStringTag]() {
|
|
483
|
-
return "ReactiveSet";
|
|
484
|
-
}
|
|
485
|
-
has(value) {
|
|
486
|
-
return this.members.has(value);
|
|
487
|
-
}
|
|
488
|
-
add(value) {
|
|
489
|
-
this.members.set(value, true);
|
|
490
|
-
return this;
|
|
491
|
-
}
|
|
492
|
-
delete(value) {
|
|
493
|
-
return this.members.delete(value);
|
|
494
|
-
}
|
|
495
|
-
clear() {
|
|
496
|
-
this.members.clear();
|
|
497
|
-
}
|
|
498
|
-
values() {
|
|
499
|
-
return this.members.keys();
|
|
500
|
-
}
|
|
501
|
-
keys() {
|
|
502
|
-
return this.values();
|
|
503
|
-
}
|
|
504
|
-
*entries() {
|
|
505
|
-
for (const value of this.values())yield [
|
|
506
|
-
value,
|
|
507
|
-
value
|
|
508
|
-
];
|
|
509
|
-
}
|
|
510
|
-
[Symbol.iterator]() {
|
|
511
|
-
return this.values();
|
|
512
|
-
}
|
|
513
|
-
forEach(callback, thisArg) {
|
|
514
|
-
for (const value of this.values())callback.call(thisArg, value, value, this);
|
|
515
|
-
}
|
|
516
|
-
collect() {
|
|
517
|
-
this.members.collect();
|
|
518
|
-
}
|
|
519
|
-
dispose() {
|
|
520
|
-
this.members.dispose();
|
|
521
|
-
}
|
|
522
|
-
[Symbol.dispose]() {
|
|
523
|
-
this.dispose();
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
function reactiveSet(initial, options) {
|
|
527
|
-
return new ReactiveSet(initial, options);
|
|
528
|
-
}
|
|
529
|
-
function createReactiveMap(initial, options) {
|
|
530
|
-
return new ReactiveMap(initial, options);
|
|
531
|
-
}
|
|
532
|
-
|
|
533
269
|
/// <reference lib="esnext.disposable" />
|
|
534
270
|
function withDispose(resource, name) {
|
|
535
271
|
setStoreName(resource, name);
|
|
@@ -644,4 +380,4 @@ function createKeyedProjection(source, keyOf, project, options = {}) {
|
|
|
644
380
|
}), options.name);
|
|
645
381
|
}
|
|
646
382
|
|
|
647
|
-
export {
|
|
383
|
+
export { createKeyedProjection as a, createStoreProjection as b, createSelector as c, createDerivedProjection as d };
|
|
@@ -139,64 +139,4 @@ function disposeStore(store) {
|
|
|
139
139
|
control.collect();
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
-
|
|
143
|
-
function sameValue(prev, next) {
|
|
144
|
-
return Object.is(prev, next);
|
|
145
|
-
}
|
|
146
|
-
function getMissing() {
|
|
147
|
-
return MISSING;
|
|
148
|
-
}
|
|
149
|
-
function isObject(value) {
|
|
150
|
-
return typeof value === "object" && value !== null;
|
|
151
|
-
}
|
|
152
|
-
function readProjectionPath(value, path) {
|
|
153
|
-
let current = value;
|
|
154
|
-
for(let index = 0; index < path.length; ++index){
|
|
155
|
-
if (!isObject(current)) return undefined;
|
|
156
|
-
current = current[path[index]];
|
|
157
|
-
}
|
|
158
|
-
return current;
|
|
159
|
-
}
|
|
160
|
-
function createStoreReaderProxy(readState, path = []) {
|
|
161
|
-
return new Proxy(Object.create(null), {
|
|
162
|
-
get (_target, prop) {
|
|
163
|
-
if (prop === Symbol.toStringTag) return "ProjectionStore";
|
|
164
|
-
const value = readProjectionPath(readState(), [
|
|
165
|
-
...path,
|
|
166
|
-
prop
|
|
167
|
-
]);
|
|
168
|
-
return isObject(value) ? createStoreReaderProxy(readState, [
|
|
169
|
-
...path,
|
|
170
|
-
prop
|
|
171
|
-
]) : value;
|
|
172
|
-
},
|
|
173
|
-
has (_target, prop) {
|
|
174
|
-
const parent = readProjectionPath(readState(), path);
|
|
175
|
-
return isObject(parent) && prop in parent;
|
|
176
|
-
},
|
|
177
|
-
ownKeys () {
|
|
178
|
-
const value = readProjectionPath(readState(), path);
|
|
179
|
-
return isObject(value) ? Reflect.ownKeys(value) : [];
|
|
180
|
-
},
|
|
181
|
-
getOwnPropertyDescriptor (_target, prop) {
|
|
182
|
-
const parent = readProjectionPath(readState(), path);
|
|
183
|
-
if (!isObject(parent) || !(prop in parent)) {
|
|
184
|
-
return undefined;
|
|
185
|
-
}
|
|
186
|
-
return {
|
|
187
|
-
configurable: true,
|
|
188
|
-
enumerable: true,
|
|
189
|
-
value: parent[prop],
|
|
190
|
-
writable: false
|
|
191
|
-
};
|
|
192
|
-
},
|
|
193
|
-
set () {
|
|
194
|
-
return false;
|
|
195
|
-
},
|
|
196
|
-
deleteProperty () {
|
|
197
|
-
return false;
|
|
198
|
-
}
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
export { disposeStore as a, ref as b, collectStore as c, deep as d, shallow as e, depthOf as f, getStoreControl as g, cloneValue as h, isPlain as i, readProjectionPath as j, storeControls as k, isStructural as l, createStoreReaderProxy as m, getMissing as n, opaque as o, isObject as p, sameValue as q, raw as r, snapshot as s };
|
|
142
|
+
export { disposeStore as a, ref as b, collectStore as c, deep as d, shallow as e, cloneValue as f, storeControls as g, getStoreControl as h, isPlain as i, depthOf as j, isStructural as k, opaque as o, raw as r, snapshot as s };
|
package/dist/compiled-store.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { c as createStore } from './chunks/createStore-DHj16Ehk.js';
|
|
2
|
-
export { C as CompiledStoreTransformError, c as compileStore, t as transformCompiledStore } from './chunks/compiler-
|
|
2
|
+
export { C as CompiledStoreTransformError, c as compileStore, t as transformCompiledStore } from './chunks/compiler-Dsb3E2ck.js';
|
|
3
3
|
import 'util';
|
|
4
4
|
import 'fs';
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export { c as createStore } from './chunks/createStore-DHj16Ehk.js';
|
|
2
|
-
export { a as action, d as derive, h as hydrate, l as leaf } from './chunks/hydrate-
|
|
3
|
-
export { c as
|
|
4
|
-
export {
|
|
2
|
+
export { a as action, d as derive, h as hydrate, l as leaf } from './chunks/hydrate-DMnHCI5q.js';
|
|
3
|
+
export { c as selector } from './chunks/keyed-CQKtL8a7.js';
|
|
4
|
+
export { c as reactiveMap } from './chunks/collections-yHy0wH0f.js';
|
|
5
|
+
export { o as opaque, s as snapshot } from './chunks/values-DCB6zyMz.js';
|
|
5
6
|
import '@volynets/reflex-runtime/internal';
|
|
6
|
-
import './chunks/names-
|
|
7
|
-
import '
|
|
7
|
+
import './chunks/names-Cx4YcvsH.js';
|
|
8
|
+
import './selectors/shared.js';
|
package/dist/runtime/internal.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { currentConsumer, readProducer, createProducer, writeProducer, disposeNode } from '@volynets/reflex-runtime/internal';
|
|
2
2
|
export * from '@volynets/reflex-runtime/internal';
|
|
3
|
-
import {
|
|
3
|
+
import { s as setStoreName } from '../chunks/names-Cx4YcvsH.js';
|
|
4
4
|
|
|
5
5
|
/** Compiler target: a direct leaf address, materialized only by a tracked read. */ function createStoreCell(initial, options) {
|
|
6
6
|
let value = initial;
|
package/dist/runtime.d.ts
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
/// <reference lib="esnext.disposable" />
|
|
2
|
-
import type { Destructor, Accessor, AnyFn, EffectFn, EffectOptions, DirectValue, Updater, SetInput, Setter, ValueReadable, Writable, Disposable, SymbolDisposable, Readable, WritableReadable, Signal, Computed, Memo, Derived, Effect, Scan, Realtime, Stream, ReadableLike, WritableLike, ValueOf } from "./runtime/types.js";
|
|
3
|
-
export * from '@volynets/reflex';
|
|
4
|
-
export { Accessor, AnyFn, Computed, Derived, Destructor, DirectValue, Disposable, Effect, EffectFn, EffectOptions, Memo, Readable, ReadableLike, Realtime, Scan, SetInput, Setter, Signal, Stream, SymbolDisposable, Updater, ValueOf, ValueReadable, Writable, WritableLike, WritableReadable } from './runtime/types.js';
|
|
5
2
|
import { S as StoreCell } from './types/internal-BIzJSPwN.js';
|
|
6
3
|
export { c as createStoreCell } from './types/internal-BIzJSPwN.js';
|
|
7
4
|
import { DisposableResource, Synchronous } from '@volynets/reflex-framework';
|
|
8
5
|
import '@volynets/reflex-runtime/internal';
|
|
9
6
|
|
|
7
|
+
interface DisposableComputed<T> {
|
|
8
|
+
readonly read: () => T;
|
|
9
|
+
dispose(): void;
|
|
10
|
+
}
|
|
11
|
+
/** Owned lazy getter used by the store compiler. */
|
|
12
|
+
declare function createDisposableComputed<T>(fn: () => T): DisposableComputed<T>;
|
|
13
|
+
|
|
10
14
|
type AnyFunction = (...args: never[]) => unknown;
|
|
11
15
|
interface StoreScope {
|
|
12
16
|
readonly disposed: boolean;
|
|
@@ -21,5 +25,5 @@ type StoreScopeValue<T extends object> = T & DisposableResource & {
|
|
|
21
25
|
/** Compiler lifetime and mutation boundary over the shared framework lifecycle. */
|
|
22
26
|
declare function createStoreScope<T extends object>(setup: (scope: StoreScope) => T): StoreScopeValue<T>;
|
|
23
27
|
|
|
24
|
-
export { createStoreScope };
|
|
25
|
-
export type { StoreScope, StoreScopeValue };
|
|
28
|
+
export { createDisposableComputed, createStoreScope };
|
|
29
|
+
export type { DisposableComputed, StoreScope, StoreScopeValue };
|
package/dist/runtime.js
CHANGED
|
@@ -1,12 +1,22 @@
|
|
|
1
|
-
import { batch } from '@volynets/reflex';
|
|
2
|
-
export * from '@volynets/reflex';
|
|
3
1
|
export { createStoreCell } from './runtime/internal.js';
|
|
2
|
+
import { createConsumer, disposeNode, readConsumerLazy, untracked, setCurrentConsumer, currentConsumer } from '@volynets/reflex-runtime/internal';
|
|
4
3
|
import { LifecycleScope } from '@volynets/reflex-framework';
|
|
5
|
-
import {
|
|
6
|
-
import './chunks/names-
|
|
4
|
+
import { t as transaction } from './chunks/collections-yHy0wH0f.js';
|
|
5
|
+
import './chunks/names-Cx4YcvsH.js';
|
|
6
|
+
import './chunks/values-DCB6zyMz.js';
|
|
7
|
+
|
|
8
|
+
/** Owned lazy getter used by the store compiler. */ function createDisposableComputed(fn) {
|
|
9
|
+
const node = createConsumer(fn);
|
|
10
|
+
return {
|
|
11
|
+
read: readConsumerLazy.bind(node),
|
|
12
|
+
dispose () {
|
|
13
|
+
disposeNode(node);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
}
|
|
7
17
|
|
|
8
18
|
/** Compiler lifetime and mutation boundary over the shared framework lifecycle. */ function createStoreScope(setup) {
|
|
9
|
-
const lifecycle = new LifecycleScope((fn)=>
|
|
19
|
+
const lifecycle = new LifecycleScope((fn)=>transaction(()=>untracked(fn)));
|
|
10
20
|
const assertOpen = ()=>{
|
|
11
21
|
if (lifecycle.disposed) throw new Error("Cannot use a disposed compiled store scope");
|
|
12
22
|
};
|
|
@@ -39,7 +49,7 @@ import './chunks/names-BF36AyM3.js';
|
|
|
39
49
|
const previous = pending;
|
|
40
50
|
pending = value;
|
|
41
51
|
try {
|
|
42
|
-
|
|
52
|
+
transaction(commit);
|
|
43
53
|
return value;
|
|
44
54
|
} finally{
|
|
45
55
|
pending = previous;
|
|
@@ -51,7 +61,7 @@ import './chunks/names-BF36AyM3.js';
|
|
|
51
61
|
if (Object.prototype.toString.call(callback) === "[object AsyncFunction]") throw new TypeError("Store actions require a synchronous callback");
|
|
52
62
|
return function(...args) {
|
|
53
63
|
assertOpen();
|
|
54
|
-
return
|
|
64
|
+
return transaction(()=>untracked(()=>{
|
|
55
65
|
const result = Reflect.apply(callback, this, args);
|
|
56
66
|
if (result !== null && (typeof result === "object" || typeof result === "function") && typeof Reflect.get(result, "then") === "function") throw new TypeError("Store actions cannot return a promise");
|
|
57
67
|
return result;
|
|
@@ -75,4 +85,4 @@ import './chunks/names-BF36AyM3.js';
|
|
|
75
85
|
}
|
|
76
86
|
}
|
|
77
87
|
|
|
78
|
-
export { createStoreScope };
|
|
88
|
+
export { createDisposableComputed, createStoreScope };
|
package/dist/selectors/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
1
|
+
import { a as createKeyedProjection, b as createStoreProjection } from '../chunks/keyed-CQKtL8a7.js';
|
|
2
|
+
export { c as createSelector } from '../chunks/keyed-CQKtL8a7.js';
|
|
3
3
|
import '@volynets/reflex-runtime/internal';
|
|
4
|
-
import '../chunks/
|
|
5
|
-
import '../chunks/names-
|
|
6
|
-
import '
|
|
4
|
+
import '../chunks/values-DCB6zyMz.js';
|
|
5
|
+
import '../chunks/names-Cx4YcvsH.js';
|
|
6
|
+
import './shared.js';
|
|
7
|
+
import '../chunks/collections-yHy0wH0f.js';
|
|
7
8
|
|
|
8
9
|
function createProjection(sourceOrProject, keyOrSeed, projectOrOptions, options) {
|
|
9
10
|
if (typeof keyOrSeed === "function" && typeof projectOrOptions === "function") {
|
package/dist/selectors/shared.js
CHANGED
|
@@ -1,2 +1,64 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { f as cloneProjectionValue } from '../chunks/values-DCB6zyMz.js';
|
|
2
2
|
import '@volynets/reflex-runtime/internal';
|
|
3
|
+
|
|
4
|
+
const MISSING = Symbol("selector.missing");
|
|
5
|
+
function sameValue(prev, next) {
|
|
6
|
+
return Object.is(prev, next);
|
|
7
|
+
}
|
|
8
|
+
function getMissing() {
|
|
9
|
+
return MISSING;
|
|
10
|
+
}
|
|
11
|
+
function isObject(value) {
|
|
12
|
+
return typeof value === "object" && value !== null;
|
|
13
|
+
}
|
|
14
|
+
function readProjectionPath(value, path) {
|
|
15
|
+
let current = value;
|
|
16
|
+
for(let index = 0; index < path.length; ++index){
|
|
17
|
+
if (!isObject(current)) return undefined;
|
|
18
|
+
current = current[path[index]];
|
|
19
|
+
}
|
|
20
|
+
return current;
|
|
21
|
+
}
|
|
22
|
+
function createStoreReaderProxy(readState, path = []) {
|
|
23
|
+
return new Proxy(Object.create(null), {
|
|
24
|
+
get (_target, prop) {
|
|
25
|
+
if (prop === Symbol.toStringTag) return "ProjectionStore";
|
|
26
|
+
const value = readProjectionPath(readState(), [
|
|
27
|
+
...path,
|
|
28
|
+
prop
|
|
29
|
+
]);
|
|
30
|
+
return isObject(value) ? createStoreReaderProxy(readState, [
|
|
31
|
+
...path,
|
|
32
|
+
prop
|
|
33
|
+
]) : value;
|
|
34
|
+
},
|
|
35
|
+
has (_target, prop) {
|
|
36
|
+
const parent = readProjectionPath(readState(), path);
|
|
37
|
+
return isObject(parent) && prop in parent;
|
|
38
|
+
},
|
|
39
|
+
ownKeys () {
|
|
40
|
+
const value = readProjectionPath(readState(), path);
|
|
41
|
+
return isObject(value) ? Reflect.ownKeys(value) : [];
|
|
42
|
+
},
|
|
43
|
+
getOwnPropertyDescriptor (_target, prop) {
|
|
44
|
+
const parent = readProjectionPath(readState(), path);
|
|
45
|
+
if (!isObject(parent) || !(prop in parent)) {
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
configurable: true,
|
|
50
|
+
enumerable: true,
|
|
51
|
+
value: parent[prop],
|
|
52
|
+
writable: false
|
|
53
|
+
};
|
|
54
|
+
},
|
|
55
|
+
set () {
|
|
56
|
+
return false;
|
|
57
|
+
},
|
|
58
|
+
deleteProperty () {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export { createStoreReaderProxy, getMissing, isObject, readProjectionPath, sameValue };
|
package/dist/store.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { c as createStore } from './chunks/createStore-DHj16Ehk.js';
|
|
2
|
-
export { C as CompiledStoreTransformError, c as compileStore, t as transformCompiledStore } from './chunks/compiler-
|
|
2
|
+
export { C as CompiledStoreTransformError, c as compileStore, t as transformCompiledStore } from './chunks/compiler-Dsb3E2ck.js';
|
|
3
3
|
import 'util';
|
|
4
4
|
import 'fs';
|
package/dist/vite.d.ts
CHANGED
package/dist/vite.js
CHANGED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Application wiring for this example; the store does not own a host runtime.
|
|
2
|
+
import {
|
|
3
|
+
createRuntimeContext,
|
|
4
|
+
createWatcher,
|
|
5
|
+
disposeWatcher,
|
|
6
|
+
runWatcher,
|
|
7
|
+
switchRuntimeContext,
|
|
8
|
+
} from "@volynets/reflex-runtime/internal";
|
|
9
|
+
import {
|
|
10
|
+
createRuntimeSchedulerBinding,
|
|
11
|
+
resolveEffectSchedulerMode,
|
|
12
|
+
type EffectStrategy,
|
|
13
|
+
} from "@volynets/reflex-scheduler";
|
|
14
|
+
|
|
15
|
+
export function createRuntime({
|
|
16
|
+
effectStrategy = "eager",
|
|
17
|
+
}: { effectStrategy?: EffectStrategy } = {}) {
|
|
18
|
+
const context = createRuntimeContext();
|
|
19
|
+
const scheduler = createRuntimeSchedulerBinding(
|
|
20
|
+
resolveEffectSchedulerMode(effectStrategy),
|
|
21
|
+
context,
|
|
22
|
+
);
|
|
23
|
+
context.nodeInvalidatedHook = scheduler.onNodeInvalidated;
|
|
24
|
+
context.hostFlushHook = scheduler.onHostFlush;
|
|
25
|
+
switchRuntimeContext(context);
|
|
26
|
+
return { flush: scheduler.flush };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function effect(callback: () => void | (() => void)): () => void {
|
|
30
|
+
const node = createWatcher(callback);
|
|
31
|
+
runWatcher(node);
|
|
32
|
+
return () => disposeWatcher(node);
|
|
33
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volynets/reflex-store",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "State management primitives for Reflex",
|
|
6
6
|
"license": "MIT",
|
|
@@ -47,10 +47,6 @@
|
|
|
47
47
|
"./runtime/core": {
|
|
48
48
|
"types": "./dist/runtime/core.d.ts",
|
|
49
49
|
"import": "./dist/runtime/core.js"
|
|
50
|
-
},
|
|
51
|
-
"./runtime/types": {
|
|
52
|
-
"types": "./dist/runtime/types.d.ts",
|
|
53
|
-
"import": "./dist/runtime/types.js"
|
|
54
50
|
}
|
|
55
51
|
},
|
|
56
52
|
"files": [
|
|
@@ -79,7 +75,7 @@
|
|
|
79
75
|
"test:dev": "vitest run --config vite.dev.config.ts",
|
|
80
76
|
"test:differential": "vitest run --config vite.config.ts tests/compiler.differential.test.ts tests/runtime.differential.test.ts",
|
|
81
77
|
"test:integration": "vitest run --config vite.config.ts tests/store.integration.test.ts tests/vite-user-dx.test.ts tests/task-board",
|
|
82
|
-
"test:packed-runtime": "pnpm
|
|
78
|
+
"test:packed-runtime": "pnpm build:all && node scripts/packed-runtime-identity.mjs",
|
|
83
79
|
"build:all": "node ../../tooling/build/run.mjs @volynets/reflex-store",
|
|
84
80
|
"check:artifacts": "node ../../tooling/build/verify-artifacts.mjs --directory .",
|
|
85
81
|
"prepack": "pnpm build && pnpm check:artifacts"
|
|
@@ -92,7 +88,6 @@
|
|
|
92
88
|
"@swc/core": "^1.15.18",
|
|
93
89
|
"@swc/wasm": "^1.16.13",
|
|
94
90
|
"@types/node": "^26.1.2",
|
|
95
|
-
"@volynets/reflex": "workspace:^",
|
|
96
91
|
"@volynets/reflex-runtime": "workspace:*",
|
|
97
92
|
"@volynets/reflex-scheduler": "workspace:^",
|
|
98
93
|
"rollup": "^4.54.0",
|
|
@@ -119,9 +114,8 @@
|
|
|
119
114
|
"node": ">=20.19.0"
|
|
120
115
|
},
|
|
121
116
|
"peerDependencies": {
|
|
122
|
-
"@volynets/reflex": "^1.0.
|
|
123
|
-
"@volynets/reflex-
|
|
124
|
-
"@volynets/reflex-framework": "^0.1.3"
|
|
117
|
+
"@volynets/reflex-runtime": "^1.0.1",
|
|
118
|
+
"@volynets/reflex-framework": "^0.1.4"
|
|
125
119
|
},
|
|
126
120
|
"private": false
|
|
127
121
|
}
|
package/dist/runtime/types.d.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
type Destructor = () => void;
|
|
2
|
-
type Accessor<T> = () => T;
|
|
3
|
-
type AnyFn = (...args: never[]) => unknown;
|
|
4
|
-
type EffectFn = () => void | Destructor;
|
|
5
|
-
interface EffectOptions {
|
|
6
|
-
priority?: number;
|
|
7
|
-
}
|
|
8
|
-
type DirectValue<T> = T extends AnyFn ? never : T;
|
|
9
|
-
type Updater<T> = (previous: T) => T;
|
|
10
|
-
type SetInput<T> = DirectValue<T> | Updater<T>;
|
|
11
|
-
type Setter<T> = undefined extends T ? {
|
|
12
|
-
(): T;
|
|
13
|
-
(input: SetInput<T>): T;
|
|
14
|
-
} : {
|
|
15
|
-
(input: SetInput<T>): T;
|
|
16
|
-
};
|
|
17
|
-
interface ValueReadable<T> {
|
|
18
|
-
readonly value: T;
|
|
19
|
-
}
|
|
20
|
-
interface Writable<T> {
|
|
21
|
-
set: Setter<T>;
|
|
22
|
-
}
|
|
23
|
-
interface Disposable {
|
|
24
|
-
(): void;
|
|
25
|
-
}
|
|
26
|
-
interface SymbolDisposable {
|
|
27
|
-
[Symbol.dispose](): void;
|
|
28
|
-
}
|
|
29
|
-
type Readable<T> = Accessor<T> & ValueReadable<T>;
|
|
30
|
-
type WritableReadable<T> = Readable<T> & Writable<T>;
|
|
31
|
-
type Signal<T> = Accessor<T> & Writable<T>;
|
|
32
|
-
type Computed<T> = Readable<T>;
|
|
33
|
-
type Memo<T> = Readable<T>;
|
|
34
|
-
type Derived<T> = Readable<T>;
|
|
35
|
-
type Effect<T = void> = Readable<T> & Disposable & Partial<SymbolDisposable>;
|
|
36
|
-
type Scan<T> = Readable<T> & Disposable & Partial<SymbolDisposable>;
|
|
37
|
-
type Realtime<T> = WritableReadable<T> & {
|
|
38
|
-
subscribe(callback: () => void): () => void;
|
|
39
|
-
};
|
|
40
|
-
type Stream<T> = WritableReadable<T> & AsyncIterable<T>;
|
|
41
|
-
type ReadableLike<T> = Signal<T> | Computed<T> | Memo<T> | Derived<T> | Realtime<T> | Stream<T>;
|
|
42
|
-
type WritableLike<T> = Signal<T> | Realtime<T> | Stream<T>;
|
|
43
|
-
type ValueOf<T> = T extends Accessor<infer V> ? V : T extends ValueReadable<infer V> ? V : never;
|
|
44
|
-
|
|
45
|
-
export type { Accessor, AnyFn, Computed, Derived, Destructor, DirectValue, Disposable, Effect, EffectFn, EffectOptions, Memo, Readable, ReadableLike, Realtime, Scan, SetInput, Setter, Signal, Stream, SymbolDisposable, Updater, ValueOf, ValueReadable, Writable, WritableLike, WritableReadable };
|
package/dist/runtime/types.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
|