@e280/strata 0.0.0-5 → 0.0.0-7

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 (86) hide show
  1. package/README.md +140 -39
  2. package/package.json +9 -2
  3. package/s/index.ts +3 -5
  4. package/s/signals/index.ts +5 -0
  5. package/s/signals/parts/computed.ts +53 -0
  6. package/s/signals/parts/effect.ts +23 -0
  7. package/s/signals/parts/signal.ts +66 -0
  8. package/s/signals/signals.test.ts +181 -0
  9. package/s/tests.test.ts +45 -286
  10. package/s/tracker/index.ts +3 -0
  11. package/s/tracker/tracker.test.ts +40 -0
  12. package/s/tracker/tracker.ts +73 -0
  13. package/s/tree/index.ts +7 -0
  14. package/s/{parts/substrata.ts → tree/parts/branch.ts} +11 -10
  15. package/s/{parts/chronstrata.ts → tree/parts/chronobranch.ts} +8 -8
  16. package/s/{parts/strata.ts → tree/parts/trunk.ts} +14 -13
  17. package/s/{parts → tree/parts}/types.ts +8 -8
  18. package/s/{parts → tree/parts}/utils/setup.ts +9 -9
  19. package/s/tree/tree.test.ts +307 -0
  20. package/x/index.d.ts +3 -5
  21. package/x/index.js +3 -5
  22. package/x/index.js.map +1 -1
  23. package/x/signals/index.d.ts +3 -0
  24. package/x/signals/index.js +4 -0
  25. package/x/signals/index.js.map +1 -0
  26. package/x/signals/parts/computed.d.ts +14 -0
  27. package/x/signals/parts/computed.js +41 -0
  28. package/x/signals/parts/computed.js.map +1 -0
  29. package/x/signals/parts/effect.d.ts +5 -0
  30. package/x/signals/parts/effect.js +17 -0
  31. package/x/signals/parts/effect.js.map +1 -0
  32. package/x/signals/parts/signal.d.ts +18 -0
  33. package/x/signals/parts/signal.js +47 -0
  34. package/x/signals/parts/signal.js.map +1 -0
  35. package/x/signals/signals.test.d.ts +18 -0
  36. package/x/signals/signals.test.js +144 -0
  37. package/x/signals/signals.test.js.map +1 -0
  38. package/x/tests.test.js +46 -265
  39. package/x/tests.test.js.map +1 -1
  40. package/x/tracker/index.d.ts +1 -0
  41. package/x/tracker/index.js +2 -0
  42. package/x/tracker/index.js.map +1 -0
  43. package/x/tracker/tracker.d.ts +29 -0
  44. package/x/tracker/tracker.js +62 -0
  45. package/x/tracker/tracker.js.map +1 -0
  46. package/x/tracker/tracker.test.d.ts +6 -0
  47. package/x/tracker/tracker.test.js +32 -0
  48. package/x/tracker/tracker.test.js.map +1 -0
  49. package/x/tree/index.d.ts +5 -0
  50. package/x/tree/index.js +6 -0
  51. package/x/tree/index.js.map +1 -0
  52. package/x/tree/parts/branch.d.ts +15 -0
  53. package/x/{parts/substrata.js → tree/parts/branch.js} +10 -9
  54. package/x/tree/parts/branch.js.map +1 -0
  55. package/x/{parts/chronstrata.d.ts → tree/parts/chronobranch.d.ts} +6 -6
  56. package/x/{parts/chronstrata.js → tree/parts/chronobranch.js} +6 -6
  57. package/x/tree/parts/chronobranch.js.map +1 -0
  58. package/x/tree/parts/persistence.js.map +1 -0
  59. package/x/tree/parts/trunk.d.ts +17 -0
  60. package/x/{parts/strata.js → tree/parts/trunk.js} +13 -12
  61. package/x/tree/parts/trunk.js.map +1 -0
  62. package/x/{parts → tree/parts}/types.d.ts +8 -8
  63. package/x/{parts → tree/parts}/types.js.map +1 -1
  64. package/x/tree/parts/utils/process-options.js.map +1 -0
  65. package/x/tree/parts/utils/setup.d.ts +8 -0
  66. package/x/{parts → tree/parts}/utils/setup.js +8 -8
  67. package/x/tree/parts/utils/setup.js.map +1 -0
  68. package/x/tree/tree.test.d.ts +37 -0
  69. package/x/tree/tree.test.js +271 -0
  70. package/x/tree/tree.test.js.map +1 -0
  71. package/x/parts/chronstrata.js.map +0 -1
  72. package/x/parts/persistence.js.map +0 -1
  73. package/x/parts/strata.d.ts +0 -17
  74. package/x/parts/strata.js.map +0 -1
  75. package/x/parts/substrata.d.ts +0 -15
  76. package/x/parts/substrata.js.map +0 -1
  77. package/x/parts/utils/process-options.js.map +0 -1
  78. package/x/parts/utils/setup.d.ts +0 -8
  79. package/x/parts/utils/setup.js.map +0 -1
  80. /package/s/{parts → tree/parts}/persistence.ts +0 -0
  81. /package/s/{parts → tree/parts}/utils/process-options.ts +0 -0
  82. /package/x/{parts → tree/parts}/persistence.d.ts +0 -0
  83. /package/x/{parts → tree/parts}/persistence.js +0 -0
  84. /package/x/{parts → tree/parts}/types.js +0 -0
  85. /package/x/{parts → tree/parts}/utils/process-options.d.ts +0 -0
  86. /package/x/{parts → tree/parts}/utils/process-options.js +0 -0
package/s/tests.test.ts CHANGED
@@ -1,307 +1,66 @@
1
1
 
2
- import {expect, Science} from "@e280/science"
3
- import {Strata} from "./parts/strata.js"
2
+ import {expect, Science, test} from "@e280/science"
4
3
 
5
- await Science.run({
6
- "strata": Science.suite({
7
- "get state": Science.test(async() => {
8
- const strata = new Strata({count: 0})
9
- expect(strata.state.count).is(0)
10
- }),
11
-
12
- "state is immutable": Science.test(async() => {
13
- const strata = new Strata({count: 0})
14
- expect(() => strata.state.count++).throws()
15
- }),
16
-
17
- "run a proper mutation": Science.test(async() => {
18
- const strata = new Strata({count: 0})
19
- expect(strata.state.count).is(0)
20
- await strata.mutate(state => state.count++)
21
- expect(strata.state.count).is(1)
22
- await strata.mutate(state => state.count++)
23
- expect(strata.state.count).is(2)
24
- }),
4
+ import tree from "./tree/tree.test.js"
5
+ import signals from "./signals/signals.test.js"
6
+ import tracker from "./tracker/tracker.test.js"
25
7
 
26
- "forbidden mutation nesting": Science.test(async() => {
27
- const strata = new Strata({count: 0})
28
- await expect(async() => {
29
- let promise!: Promise<any>
30
- await strata.mutate(() => {
31
- promise = strata.mutate(() => {})
32
- })
33
- await promise
34
- }).throwsAsync()
35
- }),
8
+ import {Trunk} from "./tree/parts/trunk.js"
9
+ import {effect} from "./signals/parts/effect.js"
10
+ import {signal} from "./signals/parts/signal.js"
36
11
 
37
- "state after mutation is frozen": Science.test(async () => {
38
- const strata = new Strata({x: 1})
39
- await strata.mutate(s => { s.x = 2 })
40
- expect(() => strata.state.x = 3).throws()
41
- }),
12
+ await Science.run({
13
+ tree,
14
+ signals,
15
+ tracker,
42
16
 
43
- "watch is published": Science.test(async() => {
44
- const strata = new Strata({count: 0})
45
- let mutationCount = 0
46
- strata.watch.sub(() => {mutationCount++})
47
- await strata.mutate(state => state.count++)
48
- expect(mutationCount).is(1)
49
- }),
17
+ interop: Science.suite({
18
+ "effect responds to trunk change": test(async() => {
19
+ const trunk = new Trunk({count: 1})
50
20
 
51
- "watch is debounced": Science.test(async() => {
52
- const strata = new Strata({count: 0})
53
- let mutationCount = 0
54
- strata.watch.sub(() => {mutationCount++})
55
- const promise = strata.mutate(state => state.count++)
56
- expect(mutationCount).is(0)
57
- await promise
58
- expect(mutationCount).is(1)
59
- }),
21
+ let copy = 0
22
+ expect(copy).is(0)
60
23
 
61
- "watch is fired when array item is pushed": Science.test(async() => {
62
- const strata = new Strata({items: ["hello", "world"]})
63
- let mutationCount = 0
64
- strata.watch.sub(() => {mutationCount++})
65
- await strata.mutate(state => state.items.push("lol"))
66
- expect(mutationCount).is(1)
67
- expect(strata.state.items.length).is(3)
68
- }),
24
+ effect(() => copy = trunk.state.count)
25
+ expect(copy).is(1)
69
26
 
70
- "prevent mutation loops": Science.test(async() => {
71
- const strata = new Strata({count: 0})
72
- let mutationCount = 0
73
- strata.watch.sub(async() => {
74
- mutationCount++
75
- if (mutationCount > 100)
76
- return
77
- await strata.mutate(s => s.count++)
78
- })
79
- await expect(async() => {
80
- await strata.mutate(state => state.count++)
81
- }).throwsAsync()
82
- expect(mutationCount).is(1)
27
+ await trunk.mutate(s => s.count++)
28
+ expect(copy).is(2)
83
29
  }),
84
- }),
85
30
 
86
- "substrata": Science.suite({
87
- "get state": Science.test(async() => {
88
- const strata = new Strata({count: 0, sub: {rofls: 0}})
89
- const substrata = strata.substrata(s => s.sub)
90
- expect(substrata.state.rofls).is(0)
91
- }),
31
+ "signal.set participates in flush": test(async() => {
32
+ let order: string[] = []
33
+ const count = signal(0)
92
34
 
93
- "nullable selector": Science.test(async () => {
94
- const strata = new Strata({
95
- a: {b: 0} as (null | {b: number}),
35
+ effect(() => {
36
+ if (count.value)
37
+ order.push("effect")
96
38
  })
97
- const a = strata.substrata(s => s.a)
98
- expect(strata.state.a?.b).is(0)
99
- expect(a.state?.b).is(0)
100
- await a.mutate(a => { a!.b = 1 })
101
- expect(strata.state.a?.b).is(1)
102
- expect(a.state?.b).is(1)
103
- await strata.mutate(s => s.a = null)
104
- expect(strata.state.a?.b).is(undefined)
105
- expect(a.state?.b).is(undefined)
106
- }),
107
39
 
108
- "composition": Science.test(async () => {
109
- const strata = new Strata({a: {b: {c: 0}}})
110
- const a = strata.substrata(s => s.a)
111
- const b = a.substrata(s => s.b)
112
- expect(strata.state.a.b.c).is(0)
113
- expect(b.state.c).is(0)
114
- }),
40
+ order.push("before")
41
+ await count.set(1)
42
+ order.push("after")
115
43
 
116
- "deep mutations": Science.test(async () => {
117
- const strata = new Strata({a: {b: {c: 0}}})
118
- const a = strata.substrata(s => s.a)
119
- const b = a.substrata(s => s.b)
120
- await b.mutate(b => { b.c = 101 })
121
- expect(strata.state.a.b.c).is(101)
122
- expect(a.state.b.c).is(101)
123
- expect(b.state.c).is(101)
124
- await a.mutate(a => { a.b = {c: 102} })
125
- expect(strata.state.a.b.c).is(102)
126
- expect(a.state.b.c).is(102)
127
- expect(b.state.c).is(102)
128
- await strata.mutate(s => { s.a = {b: {c: 103}} })
129
- expect(strata.state.a.b.c).is(103)
130
- expect(a.state.b.c).is(103)
131
- expect(b.state.c).is(103)
44
+ expect(order.length).is(3)
45
+ expect(order[0]).is("before")
46
+ expect(order[1]).is("effect")
47
+ expect(order[2]).is("after")
132
48
  }),
133
49
 
134
- "watch ignores outside mutations": Science.test(async() => {
135
- const strata = new Strata({a: {x: 0}, b: {x: 0}})
136
- const a = strata.substrata(s => s.a)
137
- const b = strata.substrata(s => s.b)
138
- let counted = 0
139
- b.watch.sub(() => {counted++})
140
- await a.mutate(a => a.x = 1)
141
- expect(counted).is(0)
142
- }),
143
-
144
- "forbid submutation in mutation": Science.test(async() => {
145
- const strata = new Strata({a: {b: 0}})
146
- const a = strata.substrata(s => s.a)
147
- await expect(async() => {
148
- let promise!: Promise<any>
149
- await strata.mutate(() => {
150
- promise = a.mutate(() => {})
151
- })
152
- await promise
153
- }).throwsAsync()
154
- }),
50
+ "branch can include signal value": test.skip(async() => {
51
+ const bingus = signal(101)
52
+ const trunk = new Trunk({count: 1})
53
+ const branch = trunk.branch(s => ({
54
+ count: s.count,
55
+ bingus: bingus.value,
56
+ }))
57
+ expect(branch.state.count).is(1)
58
+ expect(branch.state.bingus).is(101)
155
59
 
156
- "forbid mutation in submutation": Science.test(async() => {
157
- const strata = new Strata({a: {b: 0}})
158
- const a = strata.substrata(s => s.a)
159
- await expect(async() => {
160
- let promise!: Promise<any>
161
- await a.mutate(() => {
162
- promise = strata.mutate(() => {})
163
- })
164
- await promise
165
- }).throwsAsync()
60
+ await bingus.set(102)
61
+ expect(branch.state.count).is(1)
62
+ expect(branch.state.bingus).is(102)
166
63
  }),
167
64
  }),
168
-
169
- "chronstrata": (() => {
170
- const setup = () => {
171
- const strata = new Strata({
172
- chron: Strata.chronicle({count: 0}),
173
- })
174
- const chron = strata.chronstrata(64, s => s.chron)
175
- return {strata, chron}
176
- }
177
-
178
- return Science.suite({
179
- "get state": Science.test(async() => {
180
- const {chron} = setup()
181
- expect(chron.state.count).is(0)
182
- }),
183
-
184
- "mutate": Science.test(async() => {
185
- const {chron} = setup()
186
- expect(chron.state.count).is(0)
187
- await chron.mutate(s => s.count++)
188
- expect(chron.state.count).is(1)
189
- await chron.mutate(s => s.count++)
190
- expect(chron.state.count).is(2)
191
- }),
192
-
193
- "undoable/redoable": Science.test(async() => {
194
- const {chron} = setup()
195
- expect(chron.undoable).is(0)
196
- expect(chron.redoable).is(0)
197
- expect(chron.state.count).is(0)
198
- await chron.mutate(s => s.count++)
199
- expect(chron.undoable).is(1)
200
- await chron.mutate(s => s.count++)
201
- expect(chron.undoable).is(2)
202
- await chron.undo()
203
- expect(chron.undoable).is(1)
204
- expect(chron.redoable).is(1)
205
- await chron.undo()
206
- expect(chron.undoable).is(0)
207
- expect(chron.redoable).is(2)
208
- await chron.redo()
209
- expect(chron.undoable).is(1)
210
- expect(chron.redoable).is(1)
211
- }),
212
-
213
- "undo": Science.test(async() => {
214
- const {chron} = setup()
215
- await chron.mutate(s => s.count++)
216
- await chron.undo()
217
- expect(chron.state.count).is(0)
218
- }),
219
-
220
- "redo": Science.test(async() => {
221
- const {chron} = setup()
222
- await chron.mutate(s => s.count++)
223
- await chron.undo()
224
- expect(chron.state.count).is(0)
225
- await chron.redo()
226
- expect(chron.state.count).is(1)
227
- }),
228
-
229
- "undo/redo well ordered": Science.test(async() => {
230
- const {chron} = setup()
231
- await chron.mutate(s => s.count++)
232
- await chron.mutate(s => s.count++)
233
- await chron.mutate(s => s.count++)
234
- expect(chron.state.count).is(3)
235
-
236
- await chron.undo()
237
- expect(chron.state.count).is(2)
238
-
239
- await chron.undo()
240
- expect(chron.state.count).is(1)
241
-
242
- await chron.redo()
243
- expect(chron.state.count).is(2)
244
-
245
- await chron.redo()
246
- expect(chron.state.count).is(3)
247
-
248
- await chron.undo()
249
- expect(chron.state.count).is(2)
250
-
251
- await chron.undo()
252
- expect(chron.state.count).is(1)
253
-
254
- await chron.undo()
255
- expect(chron.state.count).is(0)
256
- }),
257
-
258
- "undo nothing does nothing": Science.test(async() => {
259
- const {chron} = setup()
260
- await chron.undo()
261
- expect(chron.state.count).is(0)
262
- }),
263
-
264
- "redo nothing does nothing": Science.test(async() => {
265
- const {chron} = setup()
266
- await chron.redo()
267
- expect(chron.state.count).is(0)
268
- }),
269
-
270
- "undo 2x": Science.test(async() => {
271
- const {chron} = setup()
272
- await chron.mutate(s => s.count++)
273
- await chron.mutate(s => s.count++)
274
- expect(chron.state.count).is(2)
275
- await chron.undo(2)
276
- expect(chron.state.count).is(0)
277
- }),
278
-
279
- "redo 2x": Science.test(async() => {
280
- const {chron} = setup()
281
- await chron.mutate(s => s.count++)
282
- await chron.mutate(s => s.count++)
283
- expect(chron.state.count).is(2)
284
- await chron.undo(2)
285
- expect(chron.state.count).is(0)
286
- await chron.redo(2)
287
- expect(chron.state.count).is(2)
288
- }),
289
-
290
- "substrata mutations are tracked": Science.test(async() => {
291
- const strata = new Strata({
292
- chron: Strata.chronicle({
293
- group: {count: 0},
294
- }),
295
- })
296
- const chron = strata.chronstrata(64, s => s.chron)
297
- const group = chron.substrata(s => s.group)
298
- expect(group.state.count).is(0)
299
- await group.mutate(g => g.count = 101)
300
- expect(group.state.count).is(101)
301
- await chron.undo()
302
- expect(group.state.count).is(0)
303
- }),
304
- })
305
- })(),
306
65
  })
307
66
 
@@ -0,0 +1,3 @@
1
+
2
+ export * from "./tracker.js"
3
+
@@ -0,0 +1,40 @@
1
+
2
+ import {Science, test, expect} from "@e280/science"
3
+ import {Tracker} from "./tracker.js"
4
+
5
+ export default Science.suite({
6
+ "change waits for downstream effects to settle": test(async() => {
7
+ const tracker = new Tracker()
8
+ let order: string[] = []
9
+
10
+ const item = {}
11
+ tracker.changed(item, async () => {
12
+ await Promise.resolve()
13
+ order.push("effect")
14
+ })
15
+
16
+ order.push("before")
17
+ await tracker.change(item)
18
+ order.push("after")
19
+
20
+ expect(order.length).is(3)
21
+ expect(order[0]).is("before")
22
+ expect(order[1]).is("effect")
23
+ expect(order[2]).is("after")
24
+ }),
25
+
26
+ "circularity forbidden": test(async() => {
27
+ const tracker = new Tracker()
28
+ const item = {}
29
+
30
+ // effect re-publishes the same change, creating a cycle
31
+ tracker.changed(item, async() => {
32
+ await tracker.change(item)
33
+ })
34
+
35
+ expect(async() => {
36
+ await tracker.change(item)
37
+ }).throwsAsync()
38
+ }),
39
+ })
40
+
@@ -0,0 +1,73 @@
1
+
2
+ import {sub, Sub} from "@e280/stz"
3
+
4
+ export type TrackableItem = object | symbol
5
+
6
+ /**
7
+ * tracking system for state management
8
+ * - it tracks when items are seen or changed
9
+ *
10
+ * for state item integration (like you're integrating a new kind of state object)
11
+ * - items can call `tracker.see(this)` when they are accessed
12
+ * - items can call `tracker.change(this)` when they are reassigned
13
+ *
14
+ * for reactivity integration (like you're integrating a new view library that reacts to state changes)
15
+ * - run `tracker.seen(renderFn)`, collecting a set of seen items
16
+ * - loop over each seen item, attach a changed handler `tracker.changed(item, handlerFn)`
17
+ */
18
+ export class Tracker<Item extends TrackableItem = any> {
19
+ #seeables: Set<Item>[] = []
20
+ #changeables = new WeakMap<Item, Sub>()
21
+ #changeStack: Set<Promise<void>>[] = []
22
+ #busy = new Set<Item>()
23
+
24
+ /** indicate item was accessed */
25
+ see(item: Item) {
26
+ this.#seeables.at(-1)?.add(item)
27
+ }
28
+
29
+ /** collect which items were seen during fn */
30
+ seen<R>(fn: () => R) {
31
+ this.#seeables.push(new Set())
32
+ const result = fn()
33
+ const seen = this.#seeables.pop()!
34
+ return {seen, result}
35
+ }
36
+
37
+ /** indicate item was changed */
38
+ async change(item: Item) {
39
+ if (this.#busy.has(item))
40
+ throw new Error("circularity forbidden")
41
+ const prom = this.#guaranteeChangeable(item).pub()
42
+ this.#changeStack.at(-1)?.add(prom)
43
+ return prom
44
+ }
45
+
46
+ /** respond to changes by calling fn */
47
+ changed(item: Item, fn: () => Promise<void>) {
48
+ return this.#guaranteeChangeable(item)(async() => {
49
+ const collected = new Set<Promise<void>>()
50
+ this.#changeStack.push(collected)
51
+ this.#busy.add(item)
52
+ collected.add(fn())
53
+ this.#busy.delete(item)
54
+ await Promise.all(collected)
55
+ this.#changeStack.pop()
56
+ })
57
+ }
58
+
59
+ #guaranteeChangeable(item: Item) {
60
+ let on = this.#changeables.get(item)
61
+ if (!on) {
62
+ on = sub()
63
+ this.#changeables.set(item, on)
64
+ }
65
+ return on
66
+ }
67
+ }
68
+
69
+ const key = Symbol.for("e280.tracker.v2")
70
+
71
+ /** standard global tracker for integrations */
72
+ export const tracker: Tracker = (globalThis as any)[key] ??= new Tracker()
73
+
@@ -0,0 +1,7 @@
1
+
2
+ export * from "./parts/chronobranch.js"
3
+ export * from "./parts/persistence.js"
4
+ export * from "./parts/trunk.js"
5
+ export * from "./parts/branch.js"
6
+ export * from "./parts/types.js"
7
+
@@ -1,21 +1,22 @@
1
1
 
2
- import {debounce, deep, sub, tracker} from "@e280/stz"
2
+ import {debounce, deep, sub} from "@e280/stz"
3
3
 
4
- import {Chronstrata} from "./chronstrata.js"
5
- import {Chronicle, Mutator, Options, Selector, Stratum, Substate} from "./types.js"
4
+ import {Chronobranch} from "./chronobranch.js"
5
+ import {tracker} from "../../tracker/tracker.js"
6
+ import {Chronicle, Mutator, Options, Selector, Tree, Branchstate} from "./types.js"
6
7
 
7
- export class Substrata<S extends Substate, ParentState extends Substate = any> implements Stratum<S> {
8
+ export class Branch<S extends Branchstate, ParentState extends Branchstate = any> implements Tree<S> {
8
9
  dispose: () => void
9
10
  watch = sub<[state: S]>()
10
11
 
11
12
  #immutable: S
12
13
  #dispatchMutation = debounce(0, async(state: S) => {
13
14
  await this.watch.pub(state)
14
- tracker.change(this)
15
+ await tracker.change(this)
15
16
  })
16
17
 
17
18
  constructor(
18
- private parent: Stratum<ParentState>,
19
+ private parent: Tree<ParentState>,
19
20
  private selector: Selector<S, ParentState>,
20
21
  private options: Options,
21
22
  ) {
@@ -49,15 +50,15 @@ export class Substrata<S extends Substate, ParentState extends Substate = any> i
49
50
  return this.#immutable
50
51
  }
51
52
 
52
- substrata<Sub extends Substate>(selector: Selector<Sub, S>): Substrata<Sub, S> {
53
- return new Substrata(this, selector, this.options)
53
+ branch<Sub extends Branchstate>(selector: Selector<Sub, S>): Branch<Sub, S> {
54
+ return new Branch(this, selector, this.options)
54
55
  }
55
56
 
56
- chronstrata<Sub extends Substate>(
57
+ chronobranch<Sub extends Branchstate>(
57
58
  limit: number,
58
59
  selector: Selector<Chronicle<Sub>, S>,
59
60
  ) {
60
- return new Chronstrata(limit, this, selector, this.options)
61
+ return new Chronobranch(limit, this, selector, this.options)
61
62
  }
62
63
  }
63
64
 
@@ -1,17 +1,17 @@
1
1
 
2
- import {Substrata} from "./substrata.js"
3
- import {Chronicle, Mutator, Options, Selector, Stratum, Substate} from "./types.js"
2
+ import {Branch} from "./branch.js"
3
+ import {Chronicle, Mutator, Options, Selector, Tree, Branchstate} from "./types.js"
4
4
 
5
- export class Chronstrata<S extends Substate, ParentState extends Substate = any> implements Stratum<S> {
6
- #substrata: Substrata<Chronicle<S>, ParentState>
5
+ export class Chronobranch<S extends Branchstate, ParentState extends Branchstate = any> implements Tree<S> {
6
+ #substrata: Branch<Chronicle<S>, ParentState>
7
7
 
8
8
  constructor(
9
9
  public limit: number,
10
- public parent: Stratum<ParentState>,
10
+ public parent: Tree<ParentState>,
11
11
  public selector: Selector<Chronicle<S>, ParentState>,
12
12
  public options: Options,
13
13
  ) {
14
- this.#substrata = parent.substrata(selector)
14
+ this.#substrata = parent.branch(selector)
15
15
  }
16
16
 
17
17
  get state() {
@@ -77,8 +77,8 @@ export class Chronstrata<S extends Substate, ParentState extends Substate = any>
77
77
  })
78
78
  }
79
79
 
80
- substrata<Sub extends Substate>(selector: Selector<Sub, S>): Substrata<Sub, S> {
81
- return new Substrata(this, selector, this.options)
80
+ branch<Sub extends Branchstate>(selector: Selector<Sub, S>): Branch<Sub, S> {
81
+ return new Branch(this, selector, this.options)
82
82
  }
83
83
  }
84
84
 
@@ -1,15 +1,16 @@
1
1
 
2
- import {debounce, deep, sub, tracker} from "@e280/stz"
2
+ import {debounce, deep, sub} from "@e280/stz"
3
3
 
4
- import {Substrata} from "./substrata.js"
5
- import {strataSetup} from "./utils/setup.js"
6
- import {Chronstrata} from "./chronstrata.js"
4
+ import {Branch} from "./branch.js"
5
+ import {trunkSetup} from "./utils/setup.js"
6
+ import {Chronobranch} from "./chronobranch.js"
7
+ import {tracker} from "../../tracker/tracker.js"
7
8
  import {processOptions} from "./utils/process-options.js"
8
- import {Chronicle, Mutator, Options, Selector, State, Stratum, Substate} from "./types.js"
9
+ import {Chronicle, Mutator, Options, Selector, Treestate, Tree, Branchstate} from "./types.js"
9
10
 
10
- export class Strata<S extends State> implements Stratum<S> {
11
- static setup = strataSetup
12
- static chronicle = <S extends Substate>(state: S): Chronicle<S> => ({
11
+ export class Trunk<S extends Treestate> implements Tree<S> {
12
+ static setup = trunkSetup
13
+ static chronicle = <S extends Branchstate>(state: S): Chronicle<S> => ({
13
14
  present: state,
14
15
  past: [],
15
16
  future: [],
@@ -52,22 +53,22 @@ export class Strata<S extends State> implements Stratum<S> {
52
53
  await this.#dispatchMutation()
53
54
  }
54
55
 
55
- substrata<Sub extends Substate>(selector: Selector<Sub, S>): Substrata<Sub, S> {
56
- return new Substrata(this, selector, this.options)
56
+ branch<Sub extends Branchstate>(selector: Selector<Sub, S>): Branch<Sub, S> {
57
+ return new Branch(this, selector, this.options)
57
58
  }
58
59
 
59
- chronstrata<Sub extends Substate>(
60
+ chronobranch<Sub extends Branchstate>(
60
61
  limit: number,
61
62
  selector: Selector<Chronicle<Sub>, S>,
62
63
  ) {
63
- return new Chronstrata(limit, this, selector, this.options)
64
+ return new Chronobranch(limit, this, selector, this.options)
64
65
  }
65
66
 
66
67
  #dispatchMutation = debounce(0, async() => {
67
68
  this.#mutationLock++
68
69
  try { await this.watch.pub(this.#immutable) }
69
70
  finally { this.#mutationLock-- }
70
- tracker.change(this)
71
+ await tracker.change(this)
71
72
  })
72
73
  }
73
74
 
@@ -1,5 +1,5 @@
1
1
 
2
- import {Substrata} from "./substrata.js"
2
+ import {Branch} from "./branch.js"
3
3
 
4
4
  export type Options = {
5
5
  clone: <X>(x: X) => X
@@ -8,29 +8,29 @@ export type Options = {
8
8
  export type Selector<Sub, S> = (state: S) => Sub
9
9
  export type Mutator<S> = (state: S) => void
10
10
 
11
- export type State = {}
12
- export type Substate = {} | null | undefined
11
+ export type Treestate = {}
12
+ export type Branchstate = {} | null | undefined
13
13
 
14
- export type Versioned<S extends State> = {
14
+ export type Versioned<S extends Treestate> = {
15
15
  state: S
16
16
  version: number
17
17
  }
18
18
 
19
- export type Stratum<S extends Substate> = {
19
+ export type Tree<S extends Branchstate> = {
20
20
  readonly state: S
21
21
  watch(fn: (s: S) => void): () => void
22
22
  mutate(mutator: Mutator<S>): Promise<S>
23
- substrata<Sub extends Substate>(selector: Selector<Sub, S>): Substrata<Sub, S>
23
+ branch<Sub extends Branchstate>(selector: Selector<Sub, S>): Branch<Sub, S>
24
24
  }
25
25
 
26
- export type SetupOptions<S extends State> = {
26
+ export type SetupOptions<S extends Treestate> = {
27
27
  version: number
28
28
  initialState: S
29
29
  saveDebounceTime?: number
30
30
  persistence?: Persistence<Versioned<S>>
31
31
  }
32
32
 
33
- export type Chronicle<S extends Substate> = {
33
+ export type Chronicle<S extends Branchstate> = {
34
34
  // [abc] d [efg]
35
35
  // \ \ \
36
36
  // \ \ future