@zakkster/lite-signal-decorators 1.1.0 → 1.1.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/CHANGELOG.md +55 -0
- package/README.md +18 -13
- package/SignalDecorators.js +3 -3
- package/llms.txt +7 -4
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,61 @@ All notable changes to `@zakkster/lite-signal-decorators` are documented here.
|
|
|
4
4
|
The format follows Keep a Changelog; this project adheres to Semantic
|
|
5
5
|
Versioning.
|
|
6
6
|
|
|
7
|
+
## [1.1.1] - 2026-08-30
|
|
8
|
+
|
|
9
|
+
A docs-accuracy patch. No runtime, fixture, or emit-matrix byte changed; the
|
|
10
|
+
accessor canon and every export are byte-identical to 1.1.0. The only test
|
|
11
|
+
changes are `test/15`'s cookbook ground-truth recount for wave 2 and two
|
|
12
|
+
comment-only lines in the gate's step description -- no budget moved anywhere.
|
|
13
|
+
Surface stays at 18 exports; pack stays the same 7-file set.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- Standards phrasing pass across README, llms.txt, package.json, the main-file
|
|
18
|
+
header, and the catalog card. TC39 lists the decorators proposal (and
|
|
19
|
+
Decorator Metadata) at Stage 2.7 since the 2026-05 plenary, down from Stage 3;
|
|
20
|
+
the emitters are unchanged -- TypeScript 5.x standard emit and Babel `2023-11`
|
|
21
|
+
remain the only real-world paths, no native engine ships decorators. Each doc
|
|
22
|
+
now names the fact once and refers to the protocol by its emitters everywhere
|
|
23
|
+
else, since stage labels drift and emitter names do not. Only the stage LABEL
|
|
24
|
+
moved: the emit matrix, the committed TS/Babel fixtures, and every test are
|
|
25
|
+
byte-untouched by this pass. Recorded in `research/feature-gap-2026-08-30.md` section 1 and
|
|
26
|
+
the `decisions/0011` addendum. Three-place version sync to 1.1.1
|
|
27
|
+
(`package.json`, the `VERSION` const, `llms.txt`).
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
|
|
31
|
+
- Cookbook wave 2: six recipes appended, `r12`..`r17`.
|
|
32
|
+
- `r12` -- Wait for a condition, as a Promise.
|
|
33
|
+
- `r13` -- React to a computed value, not every write (GATED).
|
|
34
|
+
- `r14` -- Tie teardown to an AbortSignal.
|
|
35
|
+
- `r15` -- Async state without async in the graph.
|
|
36
|
+
- `r16` -- Read without subscribing.
|
|
37
|
+
- `r17` -- Start the resource when someone is watching (GATED).
|
|
38
|
+
- Cookbook gated set grows 6 -> 8 (adds `r13`, `r17`).
|
|
39
|
+
- Publications refresh (P3): the outward drafts restamped to the 1.1.x story;
|
|
40
|
+
files stay git-untracked.
|
|
41
|
+
- Bench chart artifact (closes ROADMAP open question 5): `bench/chart.mjs`
|
|
42
|
+
renders `bench/results-chart.svg` -- the CHURN lane (ops/s + heapMed per
|
|
43
|
+
adapter) parsed verbatim from the stamped `bench/results.txt`, deterministic
|
|
44
|
+
and dev-side only (never in `files[]`); wired into the README numbers section.
|
|
45
|
+
|
|
46
|
+
### Gate output (section-10 chain, archived verbatim)
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
fixtures OK exit 0 -- emit fixtures regenerated
|
|
50
|
+
test OK exit 0 -- 257 pass / 0 fail
|
|
51
|
+
test:gc OK exit 0 -- 257 pass / 0 fail
|
|
52
|
+
torture OK exit 0 -- 14 passed, 2 skipped, 0 warned, 0 failed in 33.1s
|
|
53
|
+
torture:controls OK exit 0 -- 16 passed, 0 skipped, 0 warned, 0 failed in 2.0s
|
|
54
|
+
torture:peer-preview REPORTED NON-BLOCKING -- lane completed (exit 0) [preview 1.9.0-preview.6 SUITE-GREEN 16 passed, 0 skipped, 0 warned, 0 failed; canary 1.9.0-canary.1 SUITE-GREEN 16 passed, 0 skipped, 0 warned, 0 failed]
|
|
55
|
+
bench:selftest OK exit 0 -- ALL PASS -- 22 passed, 0 failed
|
|
56
|
+
cookbook OK exit 0/0 -- corpus 18/18 companions ok in 2.1s; controls 8/8 controls fail correctly in 5.0s
|
|
57
|
+
pack OK exit 0 -- 7/7 files, exact 7-name set, no demo/ no Publications/
|
|
58
|
+
----------------------------------------------------------------------
|
|
59
|
+
GATE PASS -- 8 blocking steps + 1 non-blocking (peer-preview)
|
|
60
|
+
```
|
|
61
|
+
|
|
7
62
|
## [1.1.0] - 2026-08-30
|
|
8
63
|
|
|
9
64
|
The pooled-lifetime release: an instance is no longer single-lifetime. The
|
package/README.md
CHANGED
|
@@ -10,9 +10,10 @@
|
|
|
10
10
|

|
|
11
11
|
[](https://opensource.org/licenses/MIT)
|
|
12
12
|
|
|
13
|
-
>
|
|
14
|
-
>
|
|
15
|
-
>
|
|
13
|
+
> Standard decorators (TC39 decorators proposal, Stage 2.7 since 2026-05; TS
|
|
14
|
+
> 5.x / Babel 2023-11 emit unchanged) that turn a plain class into a reactive
|
|
15
|
+
> view-model with a measured per-property cost, one deterministic teardown, and
|
|
16
|
+
> poison-on-dispose safety -- built on @zakkster/lite-signal.
|
|
16
17
|
|
|
17
18
|
**`@reactive accessor` fields, `@derived` getters, `@reactiveEffect` methods, `@batched` actions, one `@reactiveHost` wiring site -- and `disposeReactive()` tears the whole instance down in one call, every time, with nothing left dangling. A decorated read costs ~1.0x a hand-written instance-field signal read. An instance costs exactly P + D + E + 1 pool nodes and gives all of them back on dispose. A buildless twin, `defineReactive()`, delivers the identical feature set with zero transpiler.**
|
|
18
19
|
|
|
@@ -70,7 +71,7 @@ npm i @zakkster/lite-signal-decorators @zakkster/lite-signal
|
|
|
70
71
|
|
|
71
72
|
`@zakkster/lite-signal` (`>=1.5.0 <2.0.0`) is a **peer dependency**, and that is a correctness requirement, not a formality: your decorated instances, your raw signals, and the engine's node pool must live in ONE reactive graph. A second nested copy of the engine would silently split that graph. Install both at the top level.
|
|
72
73
|
|
|
73
|
-
ESM-only. Ships TypeScript definitions. Node >= 18. The `@` syntax needs a
|
|
74
|
+
ESM-only. Ships TypeScript definitions. Node >= 18. The `@` syntax needs a standard-decorators toolchain (TypeScript 5 or Babel `2023-11` -- see [Compatibility](#compatibility)); [`defineReactive`](#definereactiveclass-spec---class) needs nothing.
|
|
74
75
|
|
|
75
76
|
### Quick start
|
|
76
77
|
|
|
@@ -259,7 +260,7 @@ With labels and audit off, the zero-GC budgets are byte-identical to 0.3.0 -- th
|
|
|
259
260
|
| Export | Value |
|
|
260
261
|
|---|---|
|
|
261
262
|
| `ReactiveDisposedError` | `extends Error`; `name: "ReactiveDisposedError"`; fields `className`, `key`. Thrown on ANY touch of a disposed instance's surface. |
|
|
262
|
-
| `VERSION` | `"1.1.
|
|
263
|
+
| `VERSION` | `"1.1.1"` |
|
|
263
264
|
|
|
264
265
|
### The rejection matrix
|
|
265
266
|
|
|
@@ -376,7 +377,7 @@ The ~7 ns over raw batch is the guarded thunk + rest-array the decorator allocat
|
|
|
376
377
|
| `disposeReactive(vm)` | none | allocation-free success path; poison handles are prebuilt per member at decoration time |
|
|
377
378
|
| `boxOf` / `rootOf` / any throw | cold path | introspection and failure paths may allocate; never on the hot path |
|
|
378
379
|
|
|
379
|
-
The gates that hold it (run on every change, all green at 1.1.
|
|
380
|
+
The gates that hold it (run on every change, all green at 1.1.1):
|
|
380
381
|
|
|
381
382
|
- `npm test` / `npm run test:gc` -- **257/257** on both lanes.
|
|
382
383
|
- Suite gate (lite-leak + lite-gc-profiler): `leak=size 0/0 findings=0 warnings=0 | gc major=0 minor=0 maxMs=0.00 | ok`.
|
|
@@ -385,6 +386,10 @@ The gates that hold it (run on every change, all green at 1.1.0):
|
|
|
385
386
|
|
|
386
387
|
The cross-framework matrix lives in `bench/` (private, never shipped): six engines -- both our tiers, the hand-written `lite-raw-boxes` baseline, MobX 7, signal-utils/signal-polyfill, and a hand-rolled alien-signals class -- across eight class-shaped scenarios (including the `churn-reuse` acquire/release lane, where the lite tiers pool with zero retained growth and MobX/signal-utils/alien-class are structurally `unsupported` -- no disposable instance lifecycle to pool), checksum-verified for identical work, stamped into `bench/results.txt`. The formal verdicts are in [`decisions/0006-kill-criteria.md`](decisions/0006-kill-criteria.md): the decorated path measured **0.94x** the hand-written baseline on vm-write and **1.10x** on a 10k-instance fleet read (the 2.0x kill line cleared with margin), and **0 major + 0 minor GC over 4096 construct/use/dispose cycles** with pools at floor -- while emitting ~12.6x less transient garbage per churn run than the hand-rolled class it replaces.
|
|
387
388
|
|
|
389
|
+

|
|
390
|
+
|
|
391
|
+
The chart above is generated from the stamped `bench/results.txt` by `bench/chart.mjs` (`node bench/chart.mjs`) -- it plots the CHURN lane for every adapter at full scale, including `alien-class`, the hand-rolled reference that has no disposable instance lifecycle to pool.
|
|
392
|
+
|
|
388
393
|
</details>
|
|
389
394
|
|
|
390
395
|
---
|
|
@@ -412,11 +417,11 @@ npm run test:gc # the same 257 with --expose-gc (enables the allocation asse
|
|
|
412
417
|
npm run gate # the full pre-publish chain (section 10): fixtures -> test -> test:gc -> torture -> controls -> peer-preview (non-blocking) -> bench selftest -> cookbook -> pack
|
|
413
418
|
```
|
|
414
419
|
|
|
415
|
-
**257 tests** across sixteen files, all green at 1.1.
|
|
420
|
+
**257 tests** across sixteen files, all green at 1.1.1. The decorator protocol is tested three times over: against a mock standard-decorators emitter *and* against committed real TypeScript 5 and Babel `2023-11` emits, so both toolchains' codegen is pinned, not assumed.
|
|
416
421
|
|
|
417
422
|
| File | Tests | Covers |
|
|
418
423
|
|---|---:|---|
|
|
419
|
-
| `01-protocol-mock` | 30 | Decorator protocol on the mock
|
|
424
|
+
| `01-protocol-mock` | 30 | Decorator protocol on the mock standard-decorators emitter: wiring, values, options, rejection matrix |
|
|
420
425
|
| `02-fixtures-ts` | 19 | The same laws on real TypeScript 5 emit (committed fixtures) |
|
|
421
426
|
| `03-fixtures-babel` | 19 | The same laws on real Babel `2023-11` emit |
|
|
422
427
|
| `04-fixture-freshness` | 2 | Fixture hashes match the sources (stale-emit guard) + the README emit-matrix block matches its generator |
|
|
@@ -435,7 +440,7 @@ npm run gate # the full pre-publish chain (section 10): fixtures -> test
|
|
|
435
440
|
|
|
436
441
|
### Emit-support matrix
|
|
437
442
|
|
|
438
|
-
Three fixture sources, two
|
|
443
|
+
Three fixture sources, two standard-decorators emitters, both emit lanes -- every cell below is a committed, hash-pinned fixture (the `04-fixture-freshness` guard above). The table is generated from the fixture manifest, so a re-emit that changes a byte is loud, not silent:
|
|
439
444
|
|
|
440
445
|
<!-- EMIT-MATRIX:START -->
|
|
441
446
|
Generated by `node test/fixtures/emit-matrix.mjs` from `test/fixtures/hashes.json` -- do not hand-edit. Toolchain pinned by the committed fixtures: **TypeScript 5.9.3**, **@babel/core 7.29.7** + **@babel/plugin-proposal-decorators 7.29.7** (`version: 2023-11`). Each `sha256` is the first 12 hex of the committed emit; `npm run fixtures` regenerates and `test/04-fixture-freshness` fails loudly on any drift.
|
|
@@ -496,7 +501,7 @@ The `demo/` directory is dev-only -- it never enters `package.json` `files[]` an
|
|
|
496
501
|
|
|
497
502
|
| Path | Requirement |
|
|
498
503
|
|---|---|
|
|
499
|
-
| `@` decorator syntax | A
|
|
504
|
+
| `@` decorator syntax | A standard-decorators (2023-11) toolchain: **TypeScript >= 5.0** (standard decorators -- leave `experimentalDecorators` unset/false) or **Babel** with `["@babel/plugin-proposal-decorators", { "version": "2023-11" }]`. Both emits are first-class: the suite pins each with committed fixtures. |
|
|
500
505
|
| `defineReactive` | Nothing. Any ESM runtime. |
|
|
501
506
|
| Runtime | Node >= 18 (ESM-only, `sideEffects: false`); browsers via any ESM bundler or native modules. No DOM dependency anywhere in the package. |
|
|
502
507
|
| Peer | `@zakkster/lite-signal` `>=1.5.0 <2.0.0`, installed at the top level (one engine instance, one graph). |
|
|
@@ -529,7 +534,7 @@ Verified against the installed `signal-utils@0.21.1`: `@signal` (on accessors or
|
|
|
529
534
|
| `@signal accessor x` (or `@signal get x`) | `@reactive accessor x` |
|
|
530
535
|
| `@cached get y()` | `@derived get y()` |
|
|
531
536
|
| no disposal API at all | `disposeReactive(vm)` -- **and it disposes**: cascade teardown, poison swap, node-exact conservation |
|
|
532
|
-
|
|
|
537
|
+
| Standard-decorators build required | `defineReactive(Class, spec)` -- the buildless door signal-utils has no equivalent for |
|
|
533
538
|
|
|
534
539
|
The cross-framework numbers behind this table are stamped in [`decisions/0006-kill-criteria.md`](decisions/0006-kill-criteria.md) (both engines measured through their documented class APIs at checksum-identical work).
|
|
535
540
|
|
|
@@ -561,14 +566,14 @@ The cross-framework numbers behind this table are stamped in [`decisions/0006-ki
|
|
|
561
566
|
|
|
562
567
|
### The cookbook
|
|
563
568
|
|
|
564
|
-
[`COOKBOOK.md`](https://github.com/PeshoVurtoleta/lite-signal-decorators/blob/main/COOKBOOK.md) collects
|
|
569
|
+
[`COOKBOOK.md`](https://github.com/PeshoVurtoleta/lite-signal-decorators/blob/main/COOKBOOK.md) collects eighteen composition recipes over the frozen 18-export surface -- how to build the things this package deliberately does not ship a decorator for, by composing the ones it does. Its headline is the **MobX-parity-by-composition matrix**, mapping each remaining MobX construct (`observable.array`, `observable.map`, `observable.deep`, `toJS`, `when`, `runInAction`, `observe`/`intercept`) to a decorator, a suite member, or a recipe -- extending the migration tables above to the rest of MobX with the honest note per row. It walks the **two-plane fleet** (a sim plane of arena columns written raw per frame beside a reactive plane of a handful of committed members), the reactive-collection-without-a-node-per-element pattern, and the **lite-store boundary** where document state meets class state -- stated plainly as the one path that is *not* zero-GC, and why. Every code block is byte-verified against a runnable, GC-gated companion in `cookbook/` (`npm run cookbook`), so a quoted recipe cannot drift from working code. It is delivered GitHub-only -- the installed tarball stays the lean 7-file runtime surface (decisions/0009).
|
|
565
570
|
|
|
566
571
|
---
|
|
567
572
|
|
|
568
573
|
## FAQ
|
|
569
574
|
|
|
570
575
|
**Why the `accessor` keyword?**
|
|
571
|
-
It is the
|
|
576
|
+
It is the standard-decorators protocol mechanism that gives a decorator both an `init` hook (create the box during field initialization -- eagerly, so the getter carries no `if (!box)` lazy branch) and replaceable get/set bodies, without per-instance `defineProperty` calls or a base class. `@reactive` on a plain field is a named throw pointing you to `accessor`.
|
|
572
577
|
|
|
573
578
|
**How is this different from MobX's `@observable`?**
|
|
574
579
|
Philosophy: MobX trades allocation and administration overhead for maximal transparency; this package trades a little syntax (`accessor`, explicit dispose) for zero hot-path allocation, a node-exact instance cost, and a teardown you can prove. There is no proxy, no administration object per instance, and nothing is left for the GC to find "eventually" -- which is precisely what makes 10k-instance fleets and long sessions flat.
|
package/SignalDecorators.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @zakkster/lite-signal-decorators v1.1.
|
|
2
|
+
* @zakkster/lite-signal-decorators v1.1.1
|
|
3
3
|
* --------------------
|
|
4
|
-
*
|
|
4
|
+
* Standard-decorators layer over @zakkster/lite-signal. Turns a plain class into
|
|
5
5
|
* a reactive view-model with measured per-instance cost and deterministic
|
|
6
6
|
* teardown:
|
|
7
7
|
* - `@reactive accessor x = v` -- a per-instance signal box, stored in a
|
|
@@ -1944,4 +1944,4 @@ export function auditReactive(on) {
|
|
|
1944
1944
|
// --- Version ------------------------------------------------------------------
|
|
1945
1945
|
|
|
1946
1946
|
/** Package version. Kept in lockstep with package.json and llms.txt. */
|
|
1947
|
-
export const VERSION = "1.1.
|
|
1947
|
+
export const VERSION = "1.1.1";
|
package/llms.txt
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# @zakkster/lite-signal-decorators
|
|
2
2
|
|
|
3
|
-
VERSION 1.1.
|
|
3
|
+
VERSION 1.1.1
|
|
4
4
|
|
|
5
|
-
>
|
|
5
|
+
> Standard-decorators layer over @zakkster/lite-signal, built on the TC39
|
|
6
|
+
> decorators proposal (Stage 2.7 since 2026-05; TS 5.x / Babel 2023-11 emit
|
|
7
|
+
> unchanged). Turns a plain class into a
|
|
6
8
|
> reactive view-model where each instance has a measured per-property cost, a
|
|
7
9
|
> single deterministic teardown, and poison-on-dispose safety. ESM-only, zero
|
|
8
10
|
> runtime dependencies beyond the peer. The accessor read/write bodies carry one
|
|
@@ -80,7 +82,7 @@ slot for a poison handle, so any later read/write throws a named
|
|
|
80
82
|
`FinalizationRegistry` reports any instance GC'd without `disposeReactive`.
|
|
81
83
|
- `ReactiveDisposedError` -- `extends Error`, `name` `"ReactiveDisposedError"`,
|
|
82
84
|
fields `className` and `key`.
|
|
83
|
-
- `VERSION` -- `"1.1.
|
|
85
|
+
- `VERSION` -- `"1.1.1"`.
|
|
84
86
|
|
|
85
87
|
## Registry law (one registry per host chain)
|
|
86
88
|
|
|
@@ -123,7 +125,8 @@ no node leaks, on the decorator path (init-phase) and the buildless path alike.
|
|
|
123
125
|
|
|
124
126
|
## Buildless contract (defineReactive)
|
|
125
127
|
|
|
126
|
-
`defineReactive(Class, spec)` is for consumers without a
|
|
128
|
+
`defineReactive(Class, spec)` is for consumers without a standard-decorators
|
|
129
|
+
(2023-11) transpiler. The
|
|
127
130
|
spec normalizes (fail closed; `Reflect.ownKeys`, so symbol keys work):
|
|
128
131
|
|
|
129
132
|
- `signals`: an array of keys (each initial `undefined`) OR a map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zakkster/lite-signal-decorators",
|
|
3
|
-
"version": "1.1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.1.1",
|
|
4
|
+
"description": "Standard-decorators layer over @zakkster/lite-signal (TC39 decorators proposal, Stage 2.7 since 2026-05; TS 5.x / Babel 2023-11 emit unchanged). The reactive class layer where an instance has a measured cost, deterministic teardown, and a churn benchmark.",
|
|
5
5
|
"author": "Zahary Shinikchiev <shinikchiev@yahoo.com>",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"type": "module",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"reactive",
|
|
40
40
|
"reactivity",
|
|
41
41
|
"decorators",
|
|
42
|
-
"
|
|
42
|
+
"standard-decorators",
|
|
43
43
|
"computed",
|
|
44
44
|
"derived",
|
|
45
45
|
"class",
|