@volynets/reflex-store 0.0.0-stage → 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +239 -2
- package/SPECIFICATION.md +137 -0
- package/dist/advanced.d.ts +13 -0
- package/dist/advanced.js +9 -0
- package/dist/chunks/compiler-CW_P8WsZ.js +2526 -0
- package/dist/chunks/createStore-DHj16Ehk.js +12 -0
- package/dist/chunks/hydrate-Bdtl9XyA.js +137 -0
- package/dist/chunks/keyed-C-QvvUv4.js +647 -0
- package/dist/chunks/names-BF36AyM3.js +11 -0
- package/dist/chunks/shared-BHHficW8.js +202 -0
- package/dist/compiled-store.d.ts +4 -0
- package/dist/compiled-store.js +4 -0
- package/dist/compiler/swc.wasm +0 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +7 -0
- package/dist/licenses/NOTICE.txt +1 -0
- package/dist/licenses/SWC-APACHE-2.0.txt +202 -0
- package/dist/runtime/core.d.ts +2 -0
- package/dist/runtime/core.js +1 -0
- package/dist/runtime/internal.d.ts +3 -0
- package/dist/runtime/internal.js +41 -0
- package/dist/runtime/types.d.ts +45 -0
- package/dist/runtime/types.js +1 -0
- package/dist/runtime.d.ts +25 -0
- package/dist/runtime.js +78 -0
- package/dist/selectors/index.d.ts +13 -0
- package/dist/selectors/index.js +15 -0
- package/dist/selectors/shared.d.ts +3 -0
- package/dist/selectors/shared.js +2 -0
- package/dist/store.d.ts +9 -0
- package/dist/store.js +4 -0
- package/dist/types/contracts-BCsRPdQb.d.ts +78 -0
- package/dist/types/createStore-BJ66-pfq.d.ts +43 -0
- package/dist/types/internal-BIzJSPwN.d.ts +18 -0
- package/dist/types/keyed-CdSYzIOc.d.ts +18 -0
- package/dist/types/shared-CdTKzvLe.d.ts +114 -0
- package/dist/vite.d.ts +68 -0
- package/dist/vite.js +87 -0
- package/examples/task-board/README.md +15 -0
- package/examples/task-board/src/task-board.ts +159 -0
- package/examples/task-board/vite.config.ts +6 -0
- package/package.json +125 -4
- package/src/store/README.md +59 -0
- package/src/store/TRANSFORM_SPEC.md +85 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-present Andrii Volynets
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,240 @@
|
|
|
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 keeps the Reflex host and reactive kernel
|
|
5
|
+
as external imports. `@volynets/reflex`, `@volynets/reflex-runtime` and
|
|
6
|
+
`@volynets/reflex-framework` are peer dependencies. Framework supplies the
|
|
7
|
+
shared lifecycle primitives, while Store, DOM and Async share the application's
|
|
8
|
+
kernel module identity.
|
|
9
|
+
The distribution includes the portable SWC WebAssembly compiler and Vite plugin.
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
pnpm add @volynets/reflex-store @volynets/reflex @volynets/reflex-runtime @volynets/reflex-framework
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Requires Node.js 20.19 or newer for the compiler and Vite plugin. Published
|
|
16
|
+
entrypoints use ES modules. The compiler and its SWC WASM asset are included;
|
|
17
|
+
consumers do not need to install SWC separately.
|
|
18
|
+
|
|
19
|
+
## Application API
|
|
20
|
+
|
|
21
|
+
Start with `createStore`, `derive`, `selector`, `reactiveMap`, `action` and
|
|
22
|
+
`snapshot`. Use `leaf`/`opaque` for reference boundaries and `hydrate` for
|
|
23
|
+
restoring compiled data.
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { createRuntime, effect } from "@volynets/reflex-store/runtime";
|
|
27
|
+
import {
|
|
28
|
+
createStore,
|
|
29
|
+
leaf,
|
|
30
|
+
derive,
|
|
31
|
+
selector,
|
|
32
|
+
reactiveMap,
|
|
33
|
+
action,
|
|
34
|
+
snapshot,
|
|
35
|
+
hydrate,
|
|
36
|
+
} from "@volynets/reflex-store";
|
|
37
|
+
|
|
38
|
+
createRuntime({ effectStrategy: "flush" });
|
|
39
|
+
|
|
40
|
+
export function createBoard() {
|
|
41
|
+
const board = createStore(
|
|
42
|
+
{
|
|
43
|
+
filter: { status: "all", query: "" },
|
|
44
|
+
selection: { taskId: "T-101" },
|
|
45
|
+
pinned: leaf<readonly string[]>([]),
|
|
46
|
+
|
|
47
|
+
get filterLabel() {
|
|
48
|
+
const query = this.filter.query.trim().toLowerCase();
|
|
49
|
+
return query ? this.filter.status + ":" + query : this.filter.status;
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
setFilter(status: string, query = "") {
|
|
53
|
+
this.filter.status = status;
|
|
54
|
+
this.filter.query = query;
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
{ name: "Board" },
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
return board;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const board = createBoard();
|
|
64
|
+
const tasks = reactiveMap<string, { title: string; done: boolean }>();
|
|
65
|
+
const isSelected = selector(() => board.selection.taskId);
|
|
66
|
+
const summary = derive(
|
|
67
|
+
() => ({
|
|
68
|
+
total: tasks.size,
|
|
69
|
+
completed: [...tasks.values()].filter((task) => task.done).length,
|
|
70
|
+
}),
|
|
71
|
+
{ name: "Summary" },
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
const addTasks = action(() => {
|
|
75
|
+
tasks.set("T-101", { title: "Design checkout", done: false });
|
|
76
|
+
tasks.set("T-102", { title: "Add audit log", done: true });
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
addTasks();
|
|
80
|
+
console.log(summary.completed); // 1; pulls current data immediately
|
|
81
|
+
const saved = snapshot(board); // frozen data; excludes methods and getters
|
|
82
|
+
hydrate(board, saved); // validates the entire shape, then writes in one action
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Every factory call creates independent state. Root methods become bound,
|
|
86
|
+
synchronous actions; getters become owned lazy computeds. Static data reads and
|
|
87
|
+
writes lower to direct cell calls. Getters must be pure and synchronous.
|
|
88
|
+
|
|
89
|
+
`derive` accepts a pure callback returning a plain object. Its property views
|
|
90
|
+
are read-only. Dynamic entity IDs belong in `reactiveMap`; map values are
|
|
91
|
+
reference boundaries, so replace an entry to publish an entity change.
|
|
92
|
+
|
|
93
|
+
`action` preserves callback parameters, return value and receiver. Related
|
|
94
|
+
writes run untracked inside one scheduler/runtime batch. Direct reads see writes
|
|
95
|
+
so far. Exceptions keep completed writes and close the batch; there is no rollback.
|
|
96
|
+
|
|
97
|
+
## Compiler and Vite
|
|
98
|
+
|
|
99
|
+
`createStore` requires the transform. The runtime stub throws if it executes.
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
import { defineConfig } from "vite";
|
|
103
|
+
import reflexStore from "@volynets/reflex-store/vite";
|
|
104
|
+
|
|
105
|
+
export default defineConfig({
|
|
106
|
+
plugins: [reflexStore({ eraseFacade: true })],
|
|
107
|
+
});
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The plugin transforms stores while preserving application package resolution.
|
|
111
|
+
It does not redirect host or kernel imports. `@volynets/reflex-store/runtime`,
|
|
112
|
+
`/runtime/core` and `/runtime/internal` re-export the shared peer APIs; they do not
|
|
113
|
+
contain a private host or kernel.
|
|
114
|
+
|
|
115
|
+
The standalone compiler is exported from `@volynets/reflex-store/store`.
|
|
116
|
+
It includes its portable WASM asset; installing a platform-specific native SWC
|
|
117
|
+
package is unnecessary. `eraseFacade` removes the object only when every use
|
|
118
|
+
lowers to data cells. Factories, methods, getters, disposal and data extraction
|
|
119
|
+
retain the required facade.
|
|
120
|
+
|
|
121
|
+
See [compiler rules](./src/store/TRANSFORM_SPEC.md).
|
|
122
|
+
|
|
123
|
+
## Ownership
|
|
124
|
+
|
|
125
|
+
Compiled stores use `createStoreScope()` from `/runtime`. This thin compiler
|
|
126
|
+
target delegates ownership, cancellation and rollback to Framework's
|
|
127
|
+
`LifecycleScope`. It adds synchronous, untracked actions inside the host batch
|
|
128
|
+
and exposes disposal through `dispose()` and `Symbol.dispose`. Cells are created
|
|
129
|
+
and owned during setup; a failed initializer disposes earlier cells before
|
|
130
|
+
rethrowing its original error. Computed getter resources share the same lifetime.
|
|
131
|
+
|
|
132
|
+
Store compilation uses neither `createModel` nor `defineModel`. Models remain an
|
|
133
|
+
optional way for application code to own a store alongside other resources.
|
|
134
|
+
|
|
135
|
+
Use the shared host's model ownership to dispose resources together:
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
import { createModel, own, signal } from "@volynets/reflex-store/runtime";
|
|
139
|
+
import { derive, reactiveMap, selector } from "@volynets/reflex-store";
|
|
140
|
+
|
|
141
|
+
const createPanel = createModel((ctx) => {
|
|
142
|
+
const tasks = own(ctx, reactiveMap<string, { done: boolean }>());
|
|
143
|
+
const selectedId = signal("");
|
|
144
|
+
return {
|
|
145
|
+
tasks,
|
|
146
|
+
selected: own(ctx, selector(selectedId)),
|
|
147
|
+
summary: own(
|
|
148
|
+
ctx,
|
|
149
|
+
derive(() => ({ total: tasks.size })),
|
|
150
|
+
),
|
|
151
|
+
};
|
|
152
|
+
});
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Maps, sets, selectors, keyed projections, structured views and compiled stores
|
|
156
|
+
implement `Symbol.dispose`. They also support explicit terminal disposal. Compiled reads, methods, writes and
|
|
157
|
+
restoration reject use after disposal.
|
|
158
|
+
`collect` is available in the advanced API for long-lived structures with many
|
|
159
|
+
previously observed keys.
|
|
160
|
+
|
|
161
|
+
## Reference and data boundaries
|
|
162
|
+
|
|
163
|
+
An object literal is a structural branch. `leaf(value)` is one replaceable
|
|
164
|
+
location. `opaque(resource)` retains an external reference.
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
const state = createStore({
|
|
168
|
+
items: leaf<readonly Task[]>([]),
|
|
169
|
+
engine: opaque(new Engine()),
|
|
170
|
+
});
|
|
171
|
+
state.items = [...state.items, task];
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Compiled arrays use replacement semantics. Array mutation does not publish
|
|
175
|
+
fine-grained changes.
|
|
176
|
+
|
|
177
|
+
Snapshots copy and freeze plain structural data, preserving cycles and shared
|
|
178
|
+
references. Map/Set keys preserve identity. Opaque and foreign objects remain
|
|
179
|
+
external references. Applications define encoding/exclusion for JSON, SSR
|
|
180
|
+
persistence and external resources.
|
|
181
|
+
|
|
182
|
+
Compiled hydration requires the full exact data shape, including empty branches.
|
|
183
|
+
It rejects missing/extra fields and accessor properties before the first write,
|
|
184
|
+
clones structural leaf data, and restores all fields in one action. Schema
|
|
185
|
+
validation is structural; validate untrusted input value types in the application.
|
|
186
|
+
|
|
187
|
+
## Advanced API
|
|
188
|
+
|
|
189
|
+
`@volynets/reflex-store/advanced` preserves projection controls, depth markers,
|
|
190
|
+
`raw`, `transaction`, lifecycle helpers and `createStoreCell`. It also exports:
|
|
191
|
+
|
|
192
|
+
```ts
|
|
193
|
+
import { reactiveSet, getStoreName } from "@volynets/reflex-store/advanced";
|
|
194
|
+
|
|
195
|
+
const selectedIds = reactiveSet<string>([], { name: "Selected IDs" });
|
|
196
|
+
selectedIds.add("T-101");
|
|
197
|
+
console.log(getStoreName(selectedIds));
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
`ReactiveSet` follows native Set membership and iteration semantics.
|
|
201
|
+
Resource names are optional store metadata and do not add runtime kernel hooks.
|
|
202
|
+
The existing draft and keyed projection APIs remain available here.
|
|
203
|
+
|
|
204
|
+
The [task board](./examples/task-board/README.md) demonstrates the basic API.
|
|
205
|
+
The normative contract is in [SPECIFICATION.md](./SPECIFICATION.md).
|
|
206
|
+
|
|
207
|
+
## Checks
|
|
208
|
+
|
|
209
|
+
```sh
|
|
210
|
+
pnpm --filter @volynets/reflex-store test
|
|
211
|
+
pnpm --filter @volynets/reflex-store test:dev
|
|
212
|
+
pnpm --filter @volynets/reflex-store typecheck
|
|
213
|
+
pnpm --filter @volynets/reflex-store lint
|
|
214
|
+
pnpm --filter @volynets/reflex-store test:packed-runtime
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
The packed test installs the Store and its Reflex peer tarballs in an empty
|
|
218
|
+
offline project. It checks all published imports, WASM loading, one shared graph across entrypoints,
|
|
219
|
+
the Vite plugin, factory isolation, batching, snapshots/hydration and consumer
|
|
220
|
+
declarations with `skipLibCheck=false`.
|
|
221
|
+
|
|
222
|
+
## Release preparation
|
|
223
|
+
|
|
224
|
+
Run from the repository root with workspace dependencies installed:
|
|
225
|
+
|
|
226
|
+
```sh
|
|
227
|
+
pnpm --filter @volynets/reflex-store check:release
|
|
228
|
+
pnpm --dir packages/reflex-store pack --pack-destination ../../artifacts/npm
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
`check:release` builds Store and its workspace dependencies, runs lint, production
|
|
232
|
+
and development tests, checks types and artifacts, and verifies an isolated
|
|
233
|
+
installation of the packed packages. `prepublishOnly` runs the same checks.
|
|
234
|
+
`prepack` rebuilds Store and checks its output before creating a tarball.
|
|
235
|
+
|
|
236
|
+
The package contains the MIT license and the Apache-2.0 license for the bundled
|
|
237
|
+
SWC compiler. Publish compatible versions of the required Reflex peers before
|
|
238
|
+
releasing Store. The repository release workflow uses `pnpm release:qualify`
|
|
239
|
+
and publishes the verified tarballs through `pnpm release:publish` with the
|
|
240
|
+
qualification and quality-summary paths required by that command.
|
package/SPECIFICATION.md
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Reflex Store Specification
|
|
2
|
+
|
|
3
|
+
**Revision:** 2026-10-07
|
|
4
|
+
**Scope:** compiled static state and runtime structured views/collections.
|
|
5
|
+
|
|
6
|
+
## Package boundary
|
|
7
|
+
|
|
8
|
+
The published package MUST declare no dependencies, peer dependencies or optional
|
|
9
|
+
dependencies. Runtime, host, scheduler, compiler and WASM assets MUST be included.
|
|
10
|
+
All runtime entrypoints MUST share the same kernel and host bindings.
|
|
11
|
+
|
|
12
|
+
The basic root exports createStore, derive, selector, reactiveMap, action,
|
|
13
|
+
snapshot, leaf, opaque and hydrate. Advanced projections, Set, lifecycle controls,
|
|
14
|
+
names and compiler primitives belong to /advanced. Headless host APIs belong to
|
|
15
|
+
/runtime; compiler and Vite entrypoints belong to /store and /vite.
|
|
16
|
+
|
|
17
|
+
Kernel read/write/link/unlink code MUST remain independent from store ownership,
|
|
18
|
+
names and compiler metadata. This package makes no kernel source changes.
|
|
19
|
+
|
|
20
|
+
## Static stores
|
|
21
|
+
|
|
22
|
+
createStore is compile-only and MUST throw if its source stub executes.
|
|
23
|
+
Declarations may appear at module scope or inside lexical function/block bodies.
|
|
24
|
+
Binding identity MUST distinguish aliases, shadowing and separate factory calls.
|
|
25
|
+
Loop-header declarations and arbitrary inline factories remain unsupported.
|
|
26
|
+
|
|
27
|
+
A literal object property defines a structural branch. Other accepted initial
|
|
28
|
+
values define leaves. leaf(value) forces one replaceable leaf. opaque(value)
|
|
29
|
+
retains an external resource/reference boundary. Marker aliases MUST resolve by
|
|
30
|
+
import binding identity.
|
|
31
|
+
|
|
32
|
+
Root methods become synchronous bound actions. Their this references to the
|
|
33
|
+
store are lowered to the same static locations; nested ordinary functions
|
|
34
|
+
retain their own this. Async/generator store methods are rejected.
|
|
35
|
+
Root getters become lazy disposable computeds. They MUST be pure, synchronous,
|
|
36
|
+
memoize clean reads and validate dependencies on pull. Store writes in getters
|
|
37
|
+
are rejected. Setters and nested methods/getters remain unsupported.
|
|
38
|
+
|
|
39
|
+
Static leaf reads/writes lower to callable cells and action writers. Data cells
|
|
40
|
+
create their producer only on the first tracked read. Initializers MUST run once
|
|
41
|
+
per declaration execution. Compound assignment and update lowering MUST preserve
|
|
42
|
+
JavaScript evaluation order, single RHS evaluation, ToNumeric and exceptions.
|
|
43
|
+
|
|
44
|
+
Dynamic root paths, branch aliases, structural replacement, delete, optional
|
|
45
|
+
chaining and general root reflection are diagnosed. Returning a facade from a
|
|
46
|
+
factory and snapshot/hydrate data intrinsics are supported escape boundaries.
|
|
47
|
+
|
|
48
|
+
Optional static name options label the store and its cells. Optional eraseFacade
|
|
49
|
+
may remove a facade only when every use lowers directly to declared data leaves.
|
|
50
|
+
Escapes, methods, getters and lifecycle references MUST keep it.
|
|
51
|
+
|
|
52
|
+
## Collections
|
|
53
|
+
|
|
54
|
+
ReactiveMap uses native SameValueZero keys and Object.is value equality by
|
|
55
|
+
default. get, has, size, key iteration and value iteration observe different
|
|
56
|
+
semantic locations. Replacing an existing value MUST not invalidate key-only
|
|
57
|
+
consumers. Untracked lookups MUST not allocate key observation producers.
|
|
58
|
+
|
|
59
|
+
ReactiveSet follows native Set membership, insertion order, deletion, clear,
|
|
60
|
+
iteration and forEach semantics. It uses keyed membership observations.
|
|
61
|
+
No-op add/delete operations MUST not notify consumers.
|
|
62
|
+
|
|
63
|
+
Collection values are reference boundaries. In-place mutation of an entity or
|
|
64
|
+
array is not a reactive publication. Optional initializers materialize backing
|
|
65
|
+
data lazily. Reads after terminal disposal MUST fail.
|
|
66
|
+
|
|
67
|
+
## Derivations and selectors
|
|
68
|
+
|
|
69
|
+
derive accepts a pure-return callback producing a plain object. Structured
|
|
70
|
+
projections use lazy Demand and semantic path observations; compatible plain
|
|
71
|
+
objects and arrays are traversed by default. Foreign/ref/opaque values retain
|
|
72
|
+
reference semantics. Returned structured views are read-only.
|
|
73
|
+
|
|
74
|
+
Selectors route old/new semantic keys with configurable equality and preserve
|
|
75
|
+
Object.is behavior for signed zero/NaN. Keyed projections represent the active
|
|
76
|
+
source key; they are not arbitrary entity lookup. ReactiveMap provides that lookup.
|
|
77
|
+
|
|
78
|
+
Advanced draft projections, clone/equality/depth controls and keyed projections
|
|
79
|
+
remain available. Clean reads MUST memoize and dirty reads MUST pull fresh data
|
|
80
|
+
without waiting for an effect flush. Equal projected results MUST cut off
|
|
81
|
+
downstream user computation.
|
|
82
|
+
|
|
83
|
+
## Actions and delivery
|
|
84
|
+
|
|
85
|
+
action runs the synchronous callback untracked within one scheduler and reactive
|
|
86
|
+
batch. Nested actions compose. The callback receiver, arguments and return value
|
|
87
|
+
MUST be preserved. Reads inside an action see writes so far. Completed writes
|
|
88
|
+
survive exceptions; all batch boundaries MUST close.
|
|
89
|
+
|
|
90
|
+
The active host controls flush/eager/SAB delivery. Runtime and scheduler batching
|
|
91
|
+
MUST compose so one logical multi-write action never publishes an intermediate
|
|
92
|
+
state to eager effects.
|
|
93
|
+
|
|
94
|
+
## Extraction, hydration and SSR
|
|
95
|
+
|
|
96
|
+
snapshot is untracked. Compiled stores expose statically generated data extraction
|
|
97
|
+
callbacks, including nested/empty branches and excluding methods/getters.
|
|
98
|
+
Plain snapshots MUST be independent and frozen, preserving cycles, shared
|
|
99
|
+
references, symbols, enumerable descriptors and sparse array structure.
|
|
100
|
+
Map and Set representations preserve key identity and disable public mutators.
|
|
101
|
+
|
|
102
|
+
Opaque/foreign values remain external references. No arbitrary JSON or
|
|
103
|
+
structured-clone guarantee is made. Applications define serialization policies
|
|
104
|
+
for cycles, BigInt, symbols, functions, external resources and Map/Set keys.
|
|
105
|
+
|
|
106
|
+
hydrate requires a complete compiled data schema. It MUST validate all structural
|
|
107
|
+
fields before writing: exact branch keys, required fields and own data-property
|
|
108
|
+
descriptors. Structural values MUST be cloned with shared references preserved.
|
|
109
|
+
All writes MUST occur in one logical batch. Field value types are checked by
|
|
110
|
+
TypeScript/application validation, not inferred from initial primitive values.
|
|
111
|
+
|
|
112
|
+
Each SSR request creates its own store factory instance. Snapshot/restore operate
|
|
113
|
+
on those instances and never require module-global application state.
|
|
114
|
+
|
|
115
|
+
## Ownership and diagnostic names
|
|
116
|
+
|
|
117
|
+
Maps, Sets, selectors, keyed projections, structured projection views and compiled
|
|
118
|
+
stores MUST implement Symbol.dispose and work with own(ctx, resource).
|
|
119
|
+
Disposal is terminal and idempotent. Compiled data reads/writes, getters, methods,
|
|
120
|
+
extraction and hydration MUST reject use after disposal. Collecting unused observations MUST preserve
|
|
121
|
+
nodes that still have outgoing consumer links. Owners stop consumers before
|
|
122
|
+
collection and collect derived layers from downstream to upstream.
|
|
123
|
+
|
|
124
|
+
Names are optional resource metadata exposed through getStoreName. Looking up a
|
|
125
|
+
name MUST not compute a lazy projection or create reactive observations. Names
|
|
126
|
+
MUST not add metadata or hooks to runtime kernel hot paths.
|
|
127
|
+
|
|
128
|
+
## Conformance evidence
|
|
129
|
+
|
|
130
|
+
Tests cover native collection differential behavior, compiler/JavaScript
|
|
131
|
+
differential behavior, all scheduler strategies, getter caching, coherent methods
|
|
132
|
+
and hydration, factory isolation, ownership and erasure safety.
|
|
133
|
+
|
|
134
|
+
The packed-install check MUST install only the local tarball in a clean offline
|
|
135
|
+
project, reject external package imports in JS/declarations, load WASM, validate
|
|
136
|
+
shared graph behavior and Vite integration, and typecheck a consumer without
|
|
137
|
+
skipLibCheck. Build-only tooling belongs in devDependencies.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/// <reference lib="esnext.disposable" />
|
|
2
|
+
import type { Destructor, Accessor } from "./runtime/types.js";
|
|
3
|
+
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
|
+
export { action, derive, hydrate } from './index.js';
|
|
5
|
+
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';
|
|
6
|
+
export { D as Depth, K as KeyedOptions, P as ProjectionOptions, R as ReactiveMap, a as ReactiveMapOptions, b as ReactiveSet, S as Snapshot, c as StoreProjectionOptions, d as collectStore, e as createReactiveMap, f as deep, g as disposeStore, o as opaque, r as raw, e as reactiveMap, h as reactiveSet, i as ref, s as shallow, j as snapshot, t as transaction } from './types/shared-CdTKzvLe.js';
|
|
7
|
+
export { createProjection, createStoreProjection } from './selectors/index.js';
|
|
8
|
+
export { S as StoreCell, c as createStoreCell } from './types/internal-BIzJSPwN.js';
|
|
9
|
+
import '@volynets/reflex-runtime/internal';
|
|
10
|
+
|
|
11
|
+
declare function getStoreName(resource: object): string | undefined;
|
|
12
|
+
|
|
13
|
+
export { getStoreName };
|
package/dist/advanced.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { createProjection } from './selectors/index.js';
|
|
2
|
+
export { R as ReactiveMap, b as ReactiveSet, d as createKeyedProjection, c as createReactiveMap, a as createSelector, e as createStoreProjection, c as reactiveMap, r as reactiveSet, a as selector, t as transaction } from './chunks/keyed-C-QvvUv4.js';
|
|
3
|
+
export { g as getStoreName } from './chunks/names-BF36AyM3.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/shared-BHHficW8.js';
|
|
5
|
+
export { createStoreCell } from './runtime/internal.js';
|
|
6
|
+
export { a as action, d as derive, h as hydrate, l as leaf } from './chunks/hydrate-Bdtl9XyA.js';
|
|
7
|
+
export { c as createStore } from './chunks/createStore-DHj16Ehk.js';
|
|
8
|
+
import '@volynets/reflex-runtime/internal';
|
|
9
|
+
import '@volynets/reflex';
|