@e280/strata 0.2.0-1 → 0.2.0-11

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.
Files changed (99) hide show
  1. package/README.md +95 -57
  2. package/package.json +4 -4
  3. package/s/signals/core/derived.ts +65 -0
  4. package/s/signals/{effect.ts → core/effect.ts} +1 -1
  5. package/s/signals/{lazy.ts → core/lazy.ts} +34 -3
  6. package/s/signals/{parts → core/parts}/readable.ts +1 -1
  7. package/s/signals/core/signal.ts +97 -0
  8. package/s/signals/index.ts +11 -8
  9. package/s/signals/porcelain.ts +30 -0
  10. package/s/signals/r/map.ts +63 -0
  11. package/s/signals/r/set.ts +43 -0
  12. package/s/signals/signals.test.ts +5 -6
  13. package/s/signals/tests/{derive.test.ts → derived.test.ts} +28 -6
  14. package/s/signals/tests/effect.test.ts +2 -2
  15. package/s/signals/tests/lazy.test.ts +16 -1
  16. package/s/signals/tests/signal.test.ts +53 -1
  17. package/s/signals/types.ts +16 -5
  18. package/s/tests.test.ts +2 -2
  19. package/s/tree/parts/branch.ts +4 -4
  20. package/s/tree/parts/trunk.ts +5 -5
  21. package/s/tree/tree.test.ts +1 -1
  22. package/x/signals/core/derived.d.ts +10 -0
  23. package/x/signals/core/derived.js +52 -0
  24. package/x/signals/core/derived.js.map +1 -0
  25. package/x/signals/{effect.js → core/effect.js} +1 -1
  26. package/x/signals/core/effect.js.map +1 -0
  27. package/x/signals/{lazy.d.ts → core/lazy.d.ts} +4 -1
  28. package/x/signals/{lazy.js → core/lazy.js} +25 -2
  29. package/x/signals/core/lazy.js.map +1 -0
  30. package/x/signals/core/parts/reactive.js.map +1 -0
  31. package/x/signals/{parts → core/parts}/readable.js +1 -1
  32. package/x/signals/core/parts/readable.js.map +1 -0
  33. package/x/signals/{signal.d.ts → core/signal.d.ts} +5 -3
  34. package/x/signals/core/signal.js +76 -0
  35. package/x/signals/core/signal.js.map +1 -0
  36. package/x/signals/index.d.ts +9 -7
  37. package/x/signals/index.js +9 -7
  38. package/x/signals/index.js.map +1 -1
  39. package/x/signals/porcelain.d.ts +8 -0
  40. package/x/signals/porcelain.js +15 -0
  41. package/x/signals/porcelain.js.map +1 -0
  42. package/x/signals/r/map.d.ts +14 -0
  43. package/x/signals/r/map.js +52 -0
  44. package/x/signals/r/map.js.map +1 -0
  45. package/x/signals/r/set.d.ts +10 -0
  46. package/x/signals/r/set.js +36 -0
  47. package/x/signals/r/set.js.map +1 -0
  48. package/x/signals/signals.test.d.ts +26 -17
  49. package/x/signals/signals.test.js +4 -6
  50. package/x/signals/signals.test.js.map +1 -1
  51. package/x/signals/tests/{derive.test.d.ts → derived.test.d.ts} +4 -0
  52. package/x/signals/tests/{derive.test.js → derived.test.js} +25 -7
  53. package/x/signals/tests/derived.test.js.map +1 -0
  54. package/x/signals/tests/effect.test.js +2 -2
  55. package/x/signals/tests/effect.test.js.map +1 -1
  56. package/x/signals/tests/lazy.test.d.ts +3 -0
  57. package/x/signals/tests/lazy.test.js +13 -1
  58. package/x/signals/tests/lazy.test.js.map +1 -1
  59. package/x/signals/tests/signal.test.d.ts +6 -0
  60. package/x/signals/tests/signal.test.js +41 -1
  61. package/x/signals/tests/signal.test.js.map +1 -1
  62. package/x/signals/types.d.ts +14 -5
  63. package/x/tests.test.js +2 -2
  64. package/x/tests.test.js.map +1 -1
  65. package/x/tree/parts/branch.js +2 -2
  66. package/x/tree/parts/branch.js.map +1 -1
  67. package/x/tree/parts/trunk.js +2 -2
  68. package/x/tree/parts/trunk.js.map +1 -1
  69. package/x/tree/tree.test.js +1 -1
  70. package/x/tree/tree.test.js.map +1 -1
  71. package/s/signals/derive.ts +0 -33
  72. package/s/signals/fns.ts +0 -31
  73. package/s/signals/signal.ts +0 -55
  74. package/s/signals/tests/signal-fn.test.ts +0 -28
  75. package/s/signals/utils/hipster.ts +0 -40
  76. package/x/signals/derive.d.ts +0 -7
  77. package/x/signals/derive.js +0 -28
  78. package/x/signals/derive.js.map +0 -1
  79. package/x/signals/effect.js.map +0 -1
  80. package/x/signals/fns.d.ts +0 -12
  81. package/x/signals/fns.js +0 -16
  82. package/x/signals/fns.js.map +0 -1
  83. package/x/signals/lazy.js.map +0 -1
  84. package/x/signals/parts/reactive.js.map +0 -1
  85. package/x/signals/parts/readable.js.map +0 -1
  86. package/x/signals/signal.js +0 -46
  87. package/x/signals/signal.js.map +0 -1
  88. package/x/signals/tests/derive.test.js.map +0 -1
  89. package/x/signals/tests/signal-fn.test.d.ts +0 -6
  90. package/x/signals/tests/signal-fn.test.js +0 -22
  91. package/x/signals/tests/signal-fn.test.js.map +0 -1
  92. package/x/signals/utils/hipster.d.ts +0 -3
  93. package/x/signals/utils/hipster.js +0 -28
  94. package/x/signals/utils/hipster.js.map +0 -1
  95. /package/s/signals/{parts → core/parts}/reactive.ts +0 -0
  96. /package/x/signals/{effect.d.ts → core/effect.d.ts} +0 -0
  97. /package/x/signals/{parts → core/parts}/reactive.d.ts +0 -0
  98. /package/x/signals/{parts → core/parts}/reactive.js +0 -0
  99. /package/x/signals/{parts → core/parts}/readable.d.ts +0 -0
package/README.md CHANGED
@@ -1,7 +1,9 @@
1
1
 
2
2
  ![](https://i.imgur.com/h7FohWa.jpeg)
3
3
 
4
- <br/>
4
+
5
+
6
+ <br/><br/>
5
7
 
6
8
  # ⛏️ strata
7
9
 
@@ -9,14 +11,16 @@
9
11
  📦 `npm install @e280/strata`
10
12
  🧙‍♂️ probably my tenth state management library, lol
11
13
  💁 it's all about rerendering ui when data changes
12
- 🦝 used by our view library [@e280/sly](https://github.com/e280/sly)
14
+ 🦝 powers reactivity in our view library [@e280/sly](https://github.com/e280/sly)
13
15
  🧑‍💻 a project by https://e280.org/
14
16
 
15
17
  🚦 **signals** — ephemeral view-level state
16
18
  🌳 **tree** — persistent app-level state
17
19
  🪄 **tracker** — reactivity integration hub
18
20
 
19
- <br/>
21
+
22
+
23
+ <br/><br/>
20
24
 
21
25
  ## 🚦 strata signals
22
26
  > *ephemeral view-level state*
@@ -26,95 +30,125 @@ import {signal, effect} from "@e280/strata"
26
30
  ```
27
31
 
28
32
  ### 🚦 each signal holds a value
29
- - **create a signal**
33
+ - **make signal**
30
34
  ```ts
31
- const count = signal(0)
35
+ const $count = signal(0)
32
36
  ```
33
- - **read a signal**
37
+ > *maybe you like the `$` prefix convention for signals?*
38
+ - **read signal**
34
39
  ```ts
35
- count.get() // 0
40
+ $count() // 0
36
41
  ```
37
- - **set a signal**
42
+ - **write signal**
38
43
  ```ts
39
- count.set(1)
44
+ $count(1)
40
45
  ```
41
- - **set a signal, and await effect propagation**
46
+ - **write signal *(and await all downstream effects)***
42
47
  ```ts
43
- await count.set(2)
48
+ await $count(2)
44
49
  ```
50
+ > *this is supposed to impress you*
45
51
 
46
52
  ### 🚦 pick your poison
53
+ - **signal hipster-fn syntax**
54
+ ```ts
55
+ $count() // read
56
+ await $count(2) // write
57
+ ```
47
58
  - **signal get/set syntax**
48
59
  ```ts
49
- count.get() // get
50
- await count.set(2) // set
60
+ $count.get() // read
61
+ await $count.set(2) // write
51
62
  ```
52
63
  - **signal .value accessor syntax**
53
64
  ```ts
54
- count.value // get
55
- count.value = 2 // set
65
+ $count.value // read
66
+ $count.value = 2 // write
56
67
  ```
57
- value pattern is nice for these vibes
68
+ value pattern is super nice for these vibes
58
69
  ```ts
59
- count.value++
60
- count.value += 1
70
+ $count.value++
71
+ $count.value += 1
61
72
  ```
62
- - **signal hipster fn syntax**
63
- - turn a signal into a hipster fn
64
- ```ts
65
- const count = signal.fn(1)
66
- ```
67
- - now you can directly invoke it
68
- ```ts
69
- count() // get
70
- await count(2) // set
71
- ```
72
- - it has all the stuff that a signal has
73
- ```ts
74
- count.get()
75
- await count.publish(5)
76
- count.on(x => console.log(x))
77
- ```
78
- - mint a fresh new signal fn
79
- ```ts
80
- const count = signal.fn(1)
81
- ```
82
73
 
83
74
  ### 🚦 effects
84
75
  - **effects run when the relevant signals change**
85
76
  ```ts
86
- effect(() => console.log(count.get()))
77
+ effect(() => console.log($count()))
87
78
  // 1
88
- // the system detects 'count' is relevant
79
+ // the system detects '$count' is relevant
89
80
 
90
- count.value++
81
+ $count.value++
91
82
  // 2
92
- // when count is changed, the effect fn is run
83
+ // when $count is changed, the effect fn is run
93
84
  ```
94
85
 
95
- ### 🚦 `signal.derive` and `signal.lazy` are computed signals
96
- - **signal.derive**
97
- is for combining signals
86
+ ### 🚦 `signal.derived` and `signal.lazy` are computed signals
87
+ - **signal.derived**
88
+ is for combining signals, like a formula
98
89
  ```ts
99
- const a = signal(1)
100
- const b = signal(10)
101
- const product = signal.derive(() => a.get() * b.get())
90
+ const $a = signal(1)
91
+ const $b = signal(10)
92
+ const $product = signal.derived(() => $a() * $b())
102
93
 
103
- product.get() // 10
94
+ $product() // 10
104
95
 
105
96
  // change a dependency,
106
97
  // and the derived signal is automatically updated
107
- await a.set(2)
98
+ await $a(2)
108
99
 
109
- product.get() // 20
100
+ $product() // 20
110
101
  ```
111
102
  - **signal.lazy**
112
103
  is for making special optimizations.
113
- it's like derive, except it cannot trigger effects,
114
- because it's so lazy it only computes the value on read, and only when necessary.
104
+ it's like derived, except it cannot trigger effects,
105
+ because it's so damned lazy, it only computes the value on read, and only when necessary.
115
106
  > *i repeat: lazy signals cannot trigger effects!*
116
107
 
117
- <br/>
108
+ ### 🚦 core primitive classes
109
+ - **the hipster-fn syntax has a slight performance cost**
110
+ - **you can instead use the core primitive classes**
111
+ ```ts
112
+ const $count = new Signal(1)
113
+ ```
114
+ core signals work mostly the same
115
+ ```ts
116
+ // ✅ legal
117
+ $count.get()
118
+ $count.set(2)
119
+ ```
120
+ except you cannot directly invoke them
121
+ ```ts
122
+ // ⛔ illegal on core primitives
123
+ $count()
124
+ $count(2)
125
+ ```
126
+ - **same thing for derived/lazy**
127
+ ```ts
128
+ const $product = new Derived(() => $a() * $b())
129
+ ```
130
+ ```ts
131
+ const $product = new Lazy(() => $a() * $b())
132
+ ```
133
+ - **conversions**
134
+ - all core primitives (signal/derived/lazy) have a convert-to-hipster-fn method
135
+ ```ts
136
+ new Signal(1).fn() // SignalFn<number>, hipster-fn
137
+ ```
138
+ - and all hipster fns (signal/derived/lazy) have a `.core` property to get the primitive
139
+ ```ts
140
+ signal(0).core // Signal<number>, primitive instance
141
+ ```
142
+
143
+ ### 🚦 types
144
+ - **`Signaly<V>`** — can be `Signal<V>` or `Derived<V>` or `Lazy<V>`
145
+ - these are types for the core primitive classes
146
+ - **`SignalyFn<V>`** — can be `SignalFn<V>` or `DerivedFn<V>` or `LazyFn<V>`
147
+ - these `*Fn` types are for the hipster-fn-syntax enabled variants
148
+
149
+
150
+
151
+ <br/><br/>
118
152
 
119
153
  ## 🌳 strata trees
120
154
  > *persistent app-level state*
@@ -249,7 +283,9 @@ import {Trunk} from "@e280/strata"
249
283
  - chronobranch can have its own branches — all their mutations advance history
250
284
  - plz pinky-swear right now, that you won't create a chronobranch under a branch under another chronobranch 💀
251
285
 
252
- <br/>
286
+
287
+
288
+ <br/><br/>
253
289
 
254
290
  ## 🪄 strata tracker
255
291
  > *reactivity integration hub*
@@ -324,9 +360,11 @@ note, the *items* that the tracker tracks can be any object, or symbol.. the tra
324
360
  }
325
361
  ```
326
362
 
327
- <br/>
328
363
 
329
- ## 🧑‍💻 an e280 project
364
+
365
+ <br/><br/>
366
+
367
+ ## 🧑‍💻 strata is by e280
330
368
  free and open source by https://e280.org/
331
369
  join us if you're cool and good at dev
332
370
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@e280/strata",
3
- "version": "0.2.0-1",
3
+ "version": "0.2.0-11",
4
4
  "description": "state management",
5
5
  "license": "MIT",
6
6
  "author": "Chase Moskal <chasemoskal@gmail.com>",
@@ -29,11 +29,11 @@
29
29
  "_tscw": "tsc -w"
30
30
  },
31
31
  "dependencies": {
32
- "@e280/stz": "^0.2.0"
32
+ "@e280/stz": "^0.2.3"
33
33
  },
34
34
  "devDependencies": {
35
- "@e280/science": "^0.1.1",
36
- "@types/node": "^24.3.0",
35
+ "@e280/science": "^0.1.2",
36
+ "@types/node": "^24.3.1",
37
37
  "npm-run-all": "^4.1.5",
38
38
  "typescript": "^5.9.2"
39
39
  },
@@ -0,0 +1,65 @@
1
+
2
+ import {collectorEffect} from "./effect.js"
3
+ import {Reactive} from "./parts/reactive.js"
4
+ import {tracker} from "../../tracker/tracker.js"
5
+ import {DerivedFn, SignalOptions} from "../types.js"
6
+ import {defaultCompare} from "../utils/default-compare.js"
7
+
8
+ export class Derived<V> extends Reactive<V> {
9
+ #dispose: () => void
10
+
11
+ constructor(formula: () => V, options?: Partial<SignalOptions>) {
12
+ const compare = options?.compare ?? defaultCompare
13
+ const {result, dispose} = collectorEffect(formula, async() => {
14
+ const value = formula()
15
+ const isChanged = !compare(this.sneak, value)
16
+ if (isChanged) {
17
+ this.sneak = value
18
+ await Promise.all([
19
+ tracker.notifyWrite(this),
20
+ this.on.pub(value),
21
+ ])
22
+ }
23
+ })
24
+ super(result)
25
+ this.#dispose = dispose
26
+ }
27
+
28
+ toString() {
29
+ return `(derived "${String(this.get())}")`
30
+ }
31
+
32
+ dispose() {
33
+ super.dispose()
34
+ this.#dispose()
35
+ }
36
+
37
+ get core() {
38
+ return this
39
+ }
40
+
41
+ fn() {
42
+ const that = this as Derived<V>
43
+
44
+ function f(): V {
45
+ return that.get()
46
+ }
47
+
48
+ f.core = that
49
+ f.get = that.get.bind(that)
50
+ f.on = that.on
51
+ f.dispose = that.dispose.bind(that)
52
+ f.fn = that.fn.bind(that)
53
+
54
+ Object.defineProperty(f, "value", {
55
+ get: () => that.value,
56
+ })
57
+
58
+ Object.defineProperty(f, "sneak", {
59
+ get: () => that.sneak,
60
+ })
61
+
62
+ return f as DerivedFn<V>
63
+ }
64
+ }
65
+
@@ -1,6 +1,6 @@
1
1
 
2
2
  import {debounce} from "@e280/stz"
3
- import {tracker} from "../tracker/tracker.js"
3
+ import {tracker} from "../../tracker/tracker.js"
4
4
 
5
5
  export function effect(
6
6
  collector: () => void,
@@ -1,9 +1,9 @@
1
1
 
2
- import {SignalOptions} from "./types.js"
3
2
  import {collectorEffect} from "./effect.js"
4
3
  import {Readable} from "./parts/readable.js"
5
- import {tracker} from "../tracker/tracker.js"
6
- import {defaultCompare} from "./utils/default-compare.js"
4
+ import {tracker} from "../../tracker/tracker.js"
5
+ import {LazyFn, SignalOptions} from "../types.js"
6
+ import {defaultCompare} from "../utils/default-compare.js"
7
7
 
8
8
  export class Lazy<V> extends Readable<V> {
9
9
  #formula: () => V
@@ -17,6 +17,10 @@ export class Lazy<V> extends Readable<V> {
17
17
  this.#compare = options?.compare ?? defaultCompare
18
18
  }
19
19
 
20
+ toString() {
21
+ return `($lazy "${String(this.get())}")`
22
+ }
23
+
20
24
  get() {
21
25
  if (!this.#effect) {
22
26
  const {result, dispose} = collectorEffect(
@@ -43,5 +47,32 @@ export class Lazy<V> extends Readable<V> {
43
47
  if (this.#effect)
44
48
  this.#effect()
45
49
  }
50
+
51
+ get core() {
52
+ return this
53
+ }
54
+
55
+ fn() {
56
+ const that = this as Lazy<V>
57
+
58
+ function f(): V {
59
+ return that.get()
60
+ }
61
+
62
+ f.core = that
63
+ f.get = that.get.bind(that)
64
+ f.dispose = that.dispose.bind(that)
65
+ f.fn = that.fn.bind(that)
66
+
67
+ Object.defineProperty(f, "value", {
68
+ get: () => that.value,
69
+ })
70
+
71
+ Object.defineProperty(f, "sneak", {
72
+ get: () => that.sneak,
73
+ })
74
+
75
+ return f as LazyFn<V>
76
+ }
46
77
  }
47
78
 
@@ -1,5 +1,5 @@
1
1
 
2
- import {tracker} from "../../tracker/tracker.js"
2
+ import {tracker} from "../../../tracker/tracker.js"
3
3
 
4
4
  export class Readable<V> {
5
5
  constructor(public sneak: V) {}
@@ -0,0 +1,97 @@
1
+
2
+ import {Reactive} from "./parts/reactive.js"
3
+ import {tracker} from "../../tracker/tracker.js"
4
+ import {SignalFn, SignalOptions} from "../types.js"
5
+ import {defaultCompare} from "../utils/default-compare.js"
6
+
7
+ export class Signal<V> extends Reactive<V> {
8
+ #lock = false
9
+ #compare: (a: any, b: any) => boolean
10
+
11
+ constructor(value: V, options?: Partial<SignalOptions>) {
12
+ super(value)
13
+ this.#compare = options?.compare ?? defaultCompare
14
+ }
15
+
16
+ toString() {
17
+ return `($signal "${String(this.get())}")`
18
+ }
19
+
20
+ async set(v: V) {
21
+ const isChanged = !this.#compare(this.sneak, v)
22
+ if (isChanged) await this.publish(v)
23
+ return v
24
+ }
25
+
26
+ get value() {
27
+ return this.get()
28
+ }
29
+
30
+ set value(v: V) {
31
+ void this.set(v)
32
+ }
33
+
34
+ async publish(v: V) {
35
+ // only wizards are allowed beyond this point.
36
+ // - the implementation is subtle
37
+ // - it looks wrong, but it's right
38
+ // - tarnished alchemists, take heed: lock engages only for sync activity of the async fns (think of the value setter!)
39
+
40
+ if (this.#lock)
41
+ throw new Error("forbid circularity")
42
+
43
+ let promise: Promise<any> = Promise.resolve()
44
+
45
+ try {
46
+ this.#lock = true
47
+ this.sneak = v
48
+ promise = Promise.all([
49
+ tracker.notifyWrite(this),
50
+ this.on.publish(v),
51
+ ])
52
+ }
53
+ finally {
54
+ this.#lock = false
55
+ }
56
+
57
+ await promise
58
+ return v
59
+ }
60
+
61
+ get core() {
62
+ return this
63
+ }
64
+
65
+ fn() {
66
+ const that = this as Signal<V>
67
+
68
+ function f(): V
69
+ function f(v: V): Promise<V>
70
+ function f(_v?: V): V | Promise<V> {
71
+ return (arguments.length === 0)
72
+ ? that.get()
73
+ : that.set(arguments[0])
74
+ }
75
+
76
+ f.core = that
77
+ f.get = that.get.bind(that)
78
+ f.set = that.set.bind(that)
79
+ f.on = that.on
80
+ f.dispose = that.dispose.bind(that)
81
+ f.publish = that.publish.bind(that)
82
+ f.fn = that.fn.bind(that)
83
+
84
+ Object.defineProperty(f, "value", {
85
+ get: () => that.value,
86
+ set: (v) => that.value = v,
87
+ })
88
+
89
+ Object.defineProperty(f, "sneak", {
90
+ get: () => that.sneak,
91
+ set: (v) => that.sneak = v,
92
+ })
93
+
94
+ return f as SignalFn<V>
95
+ }
96
+ }
97
+
@@ -1,11 +1,14 @@
1
1
 
2
- export * from "./parts/reactive.js"
3
- export * from "./parts/readable.js"
4
-
5
- export * from "./derive.js"
6
- export * from "./effect.js"
7
- export * from "./fns.js"
8
- export * from "./lazy.js"
9
- export * from "./signal.js"
2
+ export * from "./core/parts/reactive.js"
3
+ export * from "./core/parts/readable.js"
4
+ export * from "./core/derived.js"
5
+ export * from "./core/effect.js"
6
+ export * from "./core/lazy.js"
7
+ export * from "./core/signal.js"
8
+
9
+ export * from "./r/map.js"
10
+ export * from "./r/set.js"
11
+
12
+ export * from "./porcelain.js"
10
13
  export * from "./types.js"
11
14
 
@@ -0,0 +1,30 @@
1
+
2
+ import {SignalOptions} from "./types.js"
3
+ import {Lazy} from "./core/lazy.js"
4
+ import {Signal} from "./core/signal.js"
5
+ import {Derived} from "./core/derived.js"
6
+
7
+ export function lazy<V>(
8
+ formula: () => V,
9
+ options?: Partial<SignalOptions>,
10
+ ) {
11
+ return new Lazy<V>(formula, options).fn()
12
+ }
13
+
14
+ export function derived<V>(
15
+ formula: () => V,
16
+ options?: Partial<SignalOptions>,
17
+ ) {
18
+ return new Derived<V>(formula, options).fn()
19
+ }
20
+
21
+ export function signal<V>(
22
+ value: V,
23
+ options?: Partial<SignalOptions>,
24
+ ) {
25
+ return new Signal<V>(value, options).fn()
26
+ }
27
+
28
+ signal.lazy = lazy
29
+ signal.derived = derived
30
+
@@ -0,0 +1,63 @@
1
+
2
+ import {MapG} from "@e280/stz"
3
+ import {tracker} from "../../tracker/tracker.js"
4
+
5
+ export class RMap<K, V> extends MapG<K, V> {
6
+ get size() {
7
+ tracker.notifyRead(this)
8
+ return super.size
9
+ }
10
+
11
+ ;[Symbol.iterator]() {
12
+ tracker.notifyRead(this)
13
+ return super[Symbol.iterator]()
14
+ }
15
+
16
+ keys() {
17
+ tracker.notifyRead(this)
18
+ return super.keys()
19
+ }
20
+
21
+ values() {
22
+ tracker.notifyRead(this)
23
+ return super.values()
24
+ }
25
+
26
+ entries() {
27
+ tracker.notifyRead(this)
28
+ return super.entries()
29
+ }
30
+
31
+ forEach(callbackFn: (value: V, key: K, map: Map<K, V>) => void) {
32
+ tracker.notifyRead(this)
33
+ return super.forEach(callbackFn)
34
+ }
35
+
36
+ has(key: K) {
37
+ tracker.notifyRead(this)
38
+ return super.has(key)
39
+ }
40
+
41
+ get(key: K) {
42
+ tracker.notifyRead(this)
43
+ return super.get(key)
44
+ }
45
+
46
+ set(key: K, value: V) {
47
+ const r = super.set(key, value)
48
+ tracker.notifyWrite(this)
49
+ return r
50
+ }
51
+
52
+ delete(key: K) {
53
+ const r = super.delete(key)
54
+ tracker.notifyWrite(this)
55
+ return r
56
+ }
57
+
58
+ clear() {
59
+ super.clear()
60
+ tracker.notifyWrite(this)
61
+ }
62
+ }
63
+
@@ -0,0 +1,43 @@
1
+
2
+ import {SetG} from "@e280/stz"
3
+ import {tracker} from "../../tracker/tracker.js"
4
+
5
+ export class RSet<T> extends SetG<T> {
6
+ get size() {
7
+ tracker.notifyRead(this)
8
+ return super.size
9
+ }
10
+
11
+ ;[Symbol.iterator]() {
12
+ tracker.notifyRead(this)
13
+ return super[Symbol.iterator]()
14
+ }
15
+
16
+ values() {
17
+ tracker.notifyRead(this)
18
+ return super.values()
19
+ }
20
+
21
+ has(item: T) {
22
+ tracker.notifyRead(this)
23
+ return super.has(item)
24
+ }
25
+
26
+ add(item: T) {
27
+ super.add(item)
28
+ tracker.notifyWrite(this)
29
+ return this
30
+ }
31
+
32
+ delete(item: T) {
33
+ const r = super.delete(item)
34
+ tracker.notifyWrite(this)
35
+ return r
36
+ }
37
+
38
+ clear() {
39
+ super.clear()
40
+ tracker.notifyWrite(this)
41
+ }
42
+ }
43
+
@@ -1,16 +1,15 @@
1
1
 
2
2
  import {Science} from "@e280/science"
3
- import signalTest from "./tests/signal.test.js"
4
- import signalFnTest from "./tests/signal-fn.test.js"
3
+
5
4
  import effectTest from "./tests/effect.test.js"
5
+ import signalTest from "./tests/signal.test.js"
6
+ import derivedTest from "./tests/derived.test.js"
6
7
  import lazyTest from "./tests/lazy.test.js"
7
- import deriveTest from "./tests/derive.test.js"
8
8
 
9
9
  export default Science.suite({
10
- "signal": signalTest,
11
- "signal.fn": signalFnTest,
12
10
  "effect": effectTest,
11
+ "signal": signalTest,
12
+ "derived": derivedTest,
13
13
  "lazy": lazyTest,
14
- "derive": deriveTest,
15
14
  })
16
15