@signal-tree/vue 15.3.0 → 15.4.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 +26 -0
- package/llms.txt +136 -12
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -94,3 +94,29 @@ rely on component unmount hooks for request cleanup or share a module-level tree
|
|
|
94
94
|
between requests. With streaming rendering, wait for completion or abort before
|
|
95
95
|
destroying the request owner. Construct the client tree from the same initial
|
|
96
96
|
state used for the server output before hydration.
|
|
97
|
+
|
|
98
|
+
## Transaction failures
|
|
99
|
+
|
|
100
|
+
Read [Transaction failure policy and the 15.3.1 failure inventory](https://github.com/JBorgia/signal-tree/blob/v15.3.1/docs/guides/transaction-failures-v15.md)
|
|
101
|
+
before combining transactions, undo, or persistence. Explicit rollback refusal
|
|
102
|
+
leaves state unchanged and the handle pending but releases consequences in v15. The
|
|
103
|
+
15.3.1 release commits surviving writes on automatic refusal
|
|
104
|
+
before a handle returns and still throws. An error does not guarantee undo;
|
|
105
|
+
never blindly retry the entire operation.
|
|
106
|
+
|
|
107
|
+
15.3.1 containment applies to deferred write subscribers and transaction
|
|
108
|
+
turn listeners, not all Vue effects. Vue rethrows watcher errors in development
|
|
109
|
+
but logs them in production, so only the former can trigger automatic rollback
|
|
110
|
+
at transaction closure.
|
|
111
|
+
|
|
112
|
+
## Independent editors and connections
|
|
113
|
+
|
|
114
|
+
Keep shared records in an owned tree. Give each independently closable editor or
|
|
115
|
+
connection its own lifetime; native local form state may be enough for a draft.
|
|
116
|
+
A declared EntityMap supports dynamic data membership, not runtime installation
|
|
117
|
+
of composite slices. Separate trees do not share transactions or undo history.
|
|
118
|
+
Destroy directly created trees at their ownership boundary.
|
|
119
|
+
|
|
120
|
+
See the [owned sessions guide](../../docs/guides/owned-sessions.md) for the Angular
|
|
121
|
+
reference demo, stale-save policy, same-ID replacement and cleanup tests. Use this
|
|
122
|
+
package’s own reactive/lifecycle integration when applying the pattern.
|
package/llms.txt
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
# SignalTree
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
This reference describes the 15.4.0 package version, with explicitly marked
|
|
4
|
+
15.3.1 comparisons. Consult the [npm package page](https://www.npmjs.com/package/@signal-tree/kernel?activeTab=versions)
|
|
5
|
+
for published versions.
|
|
6
|
+
|
|
7
|
+
SignalTree keeps nested state, entity identity, transactions, undo, external
|
|
8
|
+
updates and reactive publication consistent across frameworks. The v15 construction model is
|
|
5
9
|
`signalTree(initialState, { derived, enhancers })`; state is read through
|
|
6
10
|
`tree.$`.
|
|
7
11
|
|
|
@@ -23,11 +27,13 @@ SignalTree is FOR. Describe SignalTree by its primary job (consequential state
|
|
|
23
27
|
with a causal model an application can trust), not by one thing that model
|
|
24
28
|
happens to make easy.
|
|
25
29
|
|
|
26
|
-
|
|
30
|
+
The Angular facade supports Angular 20, 21, or 22.
|
|
31
|
+
|
|
32
|
+
v15 ships five packages under the hyphenated `@signal-tree/*` scope. The
|
|
27
33
|
no-hyphen `@signaltree/*` scope is the separate v14 line: still maintained for
|
|
28
|
-
bug and security fixes (
|
|
34
|
+
bug and security fixes (check the [registry](https://www.npmjs.com/package/@signaltree/core) for the current patch), frozen on features, and not an
|
|
29
35
|
alias for anything under `@signal-tree/*`. Generate `@signal-tree/*` names for
|
|
30
|
-
new v15 code
|
|
36
|
+
new v15 code. The canonical package set is `scripts/release-plan.mjs`:
|
|
31
37
|
|
|
32
38
|
- `@signal-tree/kernel` — framework-neutral tree, `entityMap()`, causal turns,
|
|
33
39
|
links, and the `restoration()` / `transactions()` / `batching()` / `devTools()`
|
|
@@ -43,6 +49,8 @@ new v15 code:
|
|
|
43
49
|
- `@signal-tree/vue` — the complete Vue application facade. **Vue code imports
|
|
44
50
|
`signalTree` and all other SignalTree APIs from here**. Terminal state leaves
|
|
45
51
|
are native `Ref<T>` values and derived leaves are `ComputedRef<T>` values.
|
|
52
|
+
- `@signal-tree/solid` — the complete Solid application facade. Read terminal
|
|
53
|
+
leaves with `leaf()` and write with `leaf.set(value)`.
|
|
46
54
|
|
|
47
55
|
Use `@signal-tree/kernel` directly only for framework-neutral TypeScript,
|
|
48
56
|
including reusable domain libraries. Framework facades forward the neutral
|
|
@@ -53,19 +61,34 @@ kernel surface by canonical identity; they do not duplicate semantic authority.
|
|
|
53
61
|
The neutral kernel exposes callable locations:
|
|
54
62
|
|
|
55
63
|
```typescript
|
|
64
|
+
import { signalTree } from '@signal-tree/kernel';
|
|
65
|
+
const location = signalTree({ count: 0 }).$.count;
|
|
56
66
|
location(); // read
|
|
57
|
-
location(
|
|
58
|
-
location((current) =>
|
|
67
|
+
location(5); // replace the complete value
|
|
68
|
+
location((current) => current + 1); // derive the next complete value
|
|
59
69
|
```
|
|
60
70
|
|
|
61
71
|
The root (`tree.$`) and object branches keep this callable whole-value grammar
|
|
62
72
|
in every facade. Terminal values use the framework's native carrier:
|
|
63
73
|
|
|
64
74
|
```typescript
|
|
75
|
+
import { signalTree } from '@signal-tree/angular';
|
|
76
|
+
const angularTree = signalTree({ count: 0 });
|
|
65
77
|
angularTree.$.count();
|
|
66
78
|
angularTree.$.count.set(5);
|
|
67
79
|
angularTree.$.count.update((count) => count + 1);
|
|
80
|
+
```
|
|
68
81
|
|
|
82
|
+
```typescript
|
|
83
|
+
import { signalTree } from '@signal-tree/solid';
|
|
84
|
+
const solidTree = signalTree({ count: 0 });
|
|
85
|
+
solidTree.$.count();
|
|
86
|
+
solidTree.$.count.set(5);
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
import { signalTree } from '@signal-tree/vue';
|
|
91
|
+
const vueTree = signalTree({ count: 0 });
|
|
69
92
|
vueTree.$.count.value;
|
|
70
93
|
vueTree.$.count.value = 5;
|
|
71
94
|
```
|
|
@@ -75,18 +98,25 @@ locations and observes selected state through `useSignalTree(owner, selector)`.
|
|
|
75
98
|
EntityMap query and field leaves follow the same carrier rule; EntityMap command
|
|
76
99
|
methods such as `setAll()` and `updateOne()` do not change.
|
|
77
100
|
|
|
101
|
+
Replace atomic values through their location. In-place mutation of a returned
|
|
102
|
+
object, array, Map or Set is not a recorded write; restoration does not provide
|
|
103
|
+
deep-copy isolation for mutable payloads.
|
|
104
|
+
|
|
78
105
|
Plain objects normally become traversable branches. `leaf(value)` explicitly
|
|
79
|
-
ends topology so an object remains one atomic location.
|
|
80
|
-
|
|
106
|
+
ends topology so an object remains one atomic location. Declare function-valued
|
|
107
|
+
fields with `leaf(fn)`. At a callable write boundary, use `leaf(fn)` to distinguish
|
|
108
|
+
a stored function from an updater. Native Angular `.set(fn)` assigns the function
|
|
109
|
+
directly, as shown below:
|
|
81
110
|
|
|
82
111
|
```typescript
|
|
83
|
-
|
|
112
|
+
import { signalTree, leaf } from '@signal-tree/angular';
|
|
113
|
+
const angularTree = signalTree({
|
|
84
114
|
range: leaf({ start: 0, end: 10 }),
|
|
85
115
|
callback: leaf((value: number) => console.log(value)),
|
|
86
116
|
});
|
|
87
117
|
|
|
88
118
|
angularTree.$.range.set({ start: 5, end: 15 });
|
|
89
|
-
angularTree.$.callback.set((value) =>
|
|
119
|
+
angularTree.$.callback.set((value) => console.log(value));
|
|
90
120
|
```
|
|
91
121
|
|
|
92
122
|
The wrapper is consumed at construction or invocation and never enters state,
|
|
@@ -169,12 +199,106 @@ of the same model.
|
|
|
169
199
|
## Canonical Sources
|
|
170
200
|
|
|
171
201
|
- `AGENTS.md` — contributor and consumer rules
|
|
172
|
-
- `RELEASE-
|
|
202
|
+
- `RELEASE-CURRENT.md` — active candidate, current release work and blockers
|
|
203
|
+
- `RELEASE-1.0.md` — historical derivations, failures and prior checkpoints
|
|
173
204
|
- `README.md` — public package overview
|
|
174
205
|
- `packages/kernel/README.md` — kernel API and examples
|
|
175
206
|
- `packages/angular/README.md` — Angular realization
|
|
176
207
|
- `packages/react/README.md` — React observation
|
|
208
|
+
- `packages/vue/README.md` — Vue realization
|
|
209
|
+
- `packages/solid/README.md` — Solid realization
|
|
177
210
|
- `docs/guides/composition-recipes.md` — patterns built from existing primitives, no new API
|
|
178
211
|
- `docs/guides/persistence-guide.md` — the `link()`-as-storage recipe
|
|
179
212
|
- `docs/guides/migration-v14-v15.md` — `@signaltree/*` → `@signal-tree/*` migration (rename, consolidation, removed APIs)
|
|
180
213
|
- `docs/migration/post-rc1-workstream.md` — greenfield-first post-RC program
|
|
214
|
+
|
|
215
|
+
## Transaction failure guidance
|
|
216
|
+
|
|
217
|
+
The failure behavior in this section describes published SignalTree 15.3.1.
|
|
218
|
+
The release-tag link below is fixed to 15.3.1 to preserve that historical
|
|
219
|
+
comparison; it is not a list of defects in 15.4.0. Check versioned changes against
|
|
220
|
+
the installed version; source changes do not update an existing tarball.
|
|
221
|
+
|
|
222
|
+
Read [Transaction failures and limitations in 15.3.1](https://github.com/JBorgia/signal-tree/blob/v15.3.1/docs/guides/transaction-failures-v15.md)
|
|
223
|
+
before generating optimistic writes or persistence. Explicit `pending.rollback()`
|
|
224
|
+
refusal leaves state unchanged and the handle pending, but releases consequences
|
|
225
|
+
in existing v15. In 15.3.1, automatic refusal before a
|
|
226
|
+
handle returns records surviving writes as committed, retains eligible undo
|
|
227
|
+
history, releases consequences, and still throws. Successful automatic rollback
|
|
228
|
+
reverses recorded writes. Error does not guarantee undo: never blindly retry the
|
|
229
|
+
whole operation or use `undo()`/`jumpTo()` for request reconciliation. Removing a
|
|
230
|
+
pending-created row after a confirmed edit does not necessarily clear its
|
|
231
|
+
rollback dependency. Recoverable pending refusal is a v16 target, not v15 API.
|
|
232
|
+
|
|
233
|
+
15.3.1 containment covers deferred write subscribers and transaction turn
|
|
234
|
+
listeners, not all framework effects. Vue watcher failures differ between
|
|
235
|
+
development and production; an enclosing Solid `batch()` can defer errors until
|
|
236
|
+
after a handle returns. The guide lists the Link, branch-key, coalesce, pending undo, ordering,
|
|
237
|
+
notification, and retention failures documented for 15.3.1.
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
## Collection identity and independent store instances
|
|
241
|
+
|
|
242
|
+
Declare the store structure and enhancers at construction. `entityMap()` supports
|
|
243
|
+
dynamic entity membership; it is not an API for installing new composite slices
|
|
244
|
+
with nested marker/enhancer lifecycles. Component/dialog-owned trees are valid:
|
|
245
|
+
create one per independent editing session, and call `destroy()` at its owner’s
|
|
246
|
+
teardown. A repeated entity ID is not an editing-session ID.
|
|
247
|
+
|
|
248
|
+
`setAll()` is replacement by key. Repeated incoming keys collapse to the last
|
|
249
|
+
value for that key, not distinct rows. Use a required stable ID where available;
|
|
250
|
+
validate missing IDs at ingress rather than assigning a shared fallback. Numeric
|
|
251
|
+
and string keys remain distinct. Do not depend on a development warning to reject
|
|
252
|
+
invalid input. Version 15.3.1 does not warn for non-null duplicate incoming keys.
|
|
253
|
+
|
|
254
|
+
Version 15.4.0 checks `setAll()` staging after user callbacks.
|
|
255
|
+
If an interceptor or ID selector changes collection membership, keys or order,
|
|
256
|
+
the outer replacement refuses before applying its staged writes. The callback's
|
|
257
|
+
already-completed writes remain. Field-only callback writes do not trigger this
|
|
258
|
+
structural refusal. Prefer interceptors that validate or transform input instead
|
|
259
|
+
of changing the same collection's topology.
|
|
260
|
+
|
|
261
|
+
In published 15.3.1, calling Link `settled()` immediately after a write can return
|
|
262
|
+
before the newly queued send finishes. Version 15.4.0 repairs this same-turn race:
|
|
263
|
+
`settled()` waits for the send queued by the preceding write. It is still not proof
|
|
264
|
+
of backend durability, and one generic delay is not a universal synchronization
|
|
265
|
+
barrier. The repair does not change the published 15.3.1 artifact.
|
|
266
|
+
|
|
267
|
+
## Choosing ownership for editors and devices
|
|
268
|
+
|
|
269
|
+
See `docs/guides/owned-sessions.md` and the demo `/owned-sessions`. Keep shared
|
|
270
|
+
entities in one owned tree. Give each independent editor a unique session ID and
|
|
271
|
+
a local draft (native form state or a separate tree); do not key drafts only by
|
|
272
|
+
entity ID. Validate against the current application revision and entity lifetime
|
|
273
|
+
before applying. Refuse stale saves while keeping the draft, and never silently
|
|
274
|
+
retarget it to a replacement record. These are application policies, not kernel
|
|
275
|
+
MVCC or remote concurrency protection. A backend must enforce its own version
|
|
276
|
+
check. The demo's Apply locally does not acknowledge a server write.
|
|
277
|
+
|
|
278
|
+
Each connection owns its subscription and tree. Register cleanup and guard late
|
|
279
|
+
callbacks. Destroy that session when closed and all remaining sessions at owner
|
|
280
|
+
teardown. Keep resources out of serializable rows. Combine display with computed
|
|
281
|
+
reads over a registry, not copied state, root grafting or Link mirroring.
|
|
282
|
+
|
|
283
|
+
Do not invent dynamic slice APIs, draft/fork primitives, or cross-tree settlement.
|
|
284
|
+
Use one framework import root. Angular and Solid write `leaf.set(value)`, Vue
|
|
285
|
+
writes `leaf.value = value`, and React/neutral write `leaf(value)`. The demo is
|
|
286
|
+
Angular-specific evidence, not a cross-framework lifecycle proof.
|
|
287
|
+
|
|
288
|
+
## Runtime observation (15.4.0)
|
|
289
|
+
|
|
290
|
+
Tooling can use `transactionLifecycleReader`, `restorationReader`,
|
|
291
|
+
`entityMembershipReader`, and `linkStateReader` from
|
|
292
|
+
`@signal-tree/kernel/internals`. Each reader exposes a current `snapshot()` and
|
|
293
|
+
`subscribe(listener)` for subsequent events. `stateLocationReader(tree).locate()`
|
|
294
|
+
maps an effect's or write's position, entity lifetime and `fieldSegments` to its
|
|
295
|
+
current structured location, or `undefined` when no longer reachable. Missing capability is not empty
|
|
296
|
+
history. These readers do not install enhancers or retain terminal history.
|
|
297
|
+
|
|
298
|
+
Use actual tree + collection + entity lifetime identity and typed keys; displayed
|
|
299
|
+
paths are labels and must never be split into addressing segments. Confirmation
|
|
300
|
+
means local settlement, never server acceptance. Link queued jobs are reconciliation
|
|
301
|
+
work, not a FIFO of application values. A tool recording these events owns its
|
|
302
|
+
bounded retention and must show interruptions, omissions and unsupported sources.
|
|
303
|
+
Unsubscribe on view teardown and destroy bounded-lifetime trees. See
|
|
304
|
+
[Runtime observation in 15.4.0](https://github.com/JBorgia/signal-tree/blob/v15.4.0/docs/guides/runtime-observation.md) for contracts and examples.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@signal-tree/vue",
|
|
3
|
-
"version": "15.
|
|
3
|
+
"version": "15.4.0",
|
|
4
4
|
"description": "Vue observation for SignalTree.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"llms.txt"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@signal-tree/kernel": "15.
|
|
28
|
+
"@signal-tree/kernel": "15.4.0"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
31
|
"tslib": "^2.0.0",
|