@e280/strata 0.0.0-0 → 0.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/README.md +72 -16
- package/package.json +1 -1
- package/s/index.ts +4 -3
- package/s/parts/chronstrata.ts +84 -0
- package/s/parts/strata.ts +36 -13
- package/s/parts/substrata.ts +19 -16
- package/s/parts/types.ts +20 -0
- package/s/tests.test.ts +188 -0
- package/x/index.d.ts +4 -3
- package/x/index.js +4 -2
- package/x/index.js.map +1 -1
- package/x/parts/chronstrata.d.ts +23 -0
- package/x/parts/chronstrata.js +74 -0
- package/x/parts/chronstrata.js.map +1 -0
- package/x/parts/strata.d.ts +7 -3
- package/x/parts/strata.js +36 -10
- package/x/parts/strata.js.map +1 -1
- package/x/parts/substrata.d.ts +8 -6
- package/x/parts/substrata.js +15 -12
- package/x/parts/substrata.js.map +1 -1
- package/x/parts/types.d.ts +12 -0
- package/x/tests.test.js +165 -0
- package/x/tests.test.js.map +1 -1
package/README.md
CHANGED
|
@@ -1,72 +1,128 @@
|
|
|
1
1
|
|
|
2
|
+

|
|
3
|
+
|
|
2
4
|
# ⛏️ strata
|
|
3
5
|
|
|
4
6
|
**my 10th state management library, probably**
|
|
5
7
|
- 📦 `npm install @e280/strata`
|
|
6
8
|
- single-source-of-truth state tree
|
|
7
9
|
- immutable except for `mutate(fn)` calls
|
|
10
|
+
- no spooky-dookie proxy magic — just god's honest javascript
|
|
8
11
|
- undo/redo history, cross-tab sync, localStorage persistence
|
|
9
12
|
|
|
10
|
-
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
## get in loser, we're managing state
|
|
11
16
|
|
|
12
|
-
###
|
|
17
|
+
### `Strata` is your app's state tree root
|
|
13
18
|
- better stick to json-friendly serializable data
|
|
14
19
|
```ts
|
|
15
20
|
import {Strata} from "@e280/strata"
|
|
16
21
|
|
|
17
22
|
const strata = new Strata({
|
|
18
23
|
count: 0,
|
|
19
|
-
|
|
24
|
+
snacks: {
|
|
20
25
|
peanuts: 8,
|
|
21
|
-
|
|
26
|
+
bag: ["popcorn", "butter"],
|
|
22
27
|
},
|
|
23
28
|
})
|
|
24
29
|
|
|
25
30
|
strata.state.count // 0
|
|
26
|
-
strata.state.
|
|
31
|
+
strata.state.snacks.peanuts // 8
|
|
27
32
|
```
|
|
28
33
|
|
|
29
|
-
###
|
|
34
|
+
### formal mutations to change state
|
|
30
35
|
- ⛔ informal mutations are denied
|
|
31
36
|
```ts
|
|
32
37
|
strata.state.count++ // error is thrown
|
|
33
38
|
```
|
|
34
|
-
- ✅ formal
|
|
39
|
+
- ✅ formal mutations are allowed
|
|
35
40
|
```ts
|
|
36
41
|
await strata.mutate(s => s.count++)
|
|
37
42
|
```
|
|
38
43
|
|
|
39
|
-
###
|
|
40
|
-
- a
|
|
44
|
+
### `Substrata` is a view into a subtree
|
|
45
|
+
- it's a lens, make lots of them, pass 'em around your app
|
|
41
46
|
```ts
|
|
42
|
-
const
|
|
47
|
+
const snacks = strata.substrata(s => s.snacks)
|
|
43
48
|
```
|
|
44
49
|
- run substrata mutations
|
|
45
50
|
```ts
|
|
46
|
-
await
|
|
51
|
+
await snacks.mutate(s => s.peanuts++)
|
|
47
52
|
```
|
|
48
|
-
- array mutations are
|
|
53
|
+
- array mutations are unironically based, actually
|
|
49
54
|
```ts
|
|
50
|
-
await
|
|
55
|
+
await snacks.mutate(s => s.bag.push("salt"))
|
|
51
56
|
```
|
|
57
|
+
- you can make a substrata of another substrata
|
|
52
58
|
|
|
53
59
|
### onMutation events
|
|
54
60
|
- you can listen to global mutations on the strata
|
|
55
61
|
```ts
|
|
56
62
|
strata.onMutation(s => console.log(s.count))
|
|
57
63
|
```
|
|
58
|
-
|
|
59
64
|
- substrata listeners don't care about outside changes
|
|
60
65
|
```ts
|
|
61
|
-
|
|
66
|
+
snacks.onMutation(s => console.log(s.peanuts))
|
|
62
67
|
```
|
|
63
|
-
|
|
64
68
|
- onMutation returns a fn to stop listening
|
|
65
69
|
```ts
|
|
66
70
|
const stop = strata.onMutation(s => console.log(s.count))
|
|
67
71
|
stop() // stop listening
|
|
68
72
|
```
|
|
69
73
|
|
|
74
|
+
<br/>
|
|
75
|
+
|
|
76
|
+
## only high-class discerning aristocrats permitted beyond this point
|
|
77
|
+
|
|
78
|
+
### `Chronstrata` for undo/redo history
|
|
79
|
+
- first, put a `Chronicle` into your state tree
|
|
80
|
+
```ts
|
|
81
|
+
const strata = new Strata({
|
|
82
|
+
count: 0,
|
|
83
|
+
snacks: Strata.chronicle({
|
|
84
|
+
peanuts: 8,
|
|
85
|
+
bag: ["popcorn", "butter"],
|
|
86
|
+
}),
|
|
87
|
+
})
|
|
88
|
+
```
|
|
89
|
+
- *big-brain moment:* the whole chronicle *itself* is stored in the state.. serializable.. think persistence — user can close their project, reopen, and their undo/redo history is still chillin' — *brat girl summer*
|
|
90
|
+
- second, make a `Chronstrata` which is like a substrata
|
|
91
|
+
```ts
|
|
92
|
+
const snacks = strata.chronstrata(64, s => s.snacks)
|
|
93
|
+
// \
|
|
94
|
+
// how many past snapshots to store
|
|
95
|
+
```
|
|
96
|
+
- mutations will advance history (undoable/redoable)
|
|
97
|
+
```ts
|
|
98
|
+
await snacks.mutate(s => s.peanuts = 101)
|
|
99
|
+
|
|
100
|
+
await snacks.undo()
|
|
101
|
+
// back to 8 peanuts
|
|
102
|
+
|
|
103
|
+
await snacks.redo()
|
|
104
|
+
// forward to 101 peanuts
|
|
105
|
+
```
|
|
106
|
+
- you can check how many undoable or redoable steps are available
|
|
107
|
+
```ts
|
|
108
|
+
snacks.undoable // 0
|
|
109
|
+
|
|
110
|
+
await snacks.mutate(s => s.peanuts = 101)
|
|
111
|
+
await snacks.mutate(s => s.peanuts = 102)
|
|
112
|
+
await snacks.mutate(s => s.peanuts = 103)
|
|
113
|
+
|
|
114
|
+
snacks.undoable // 3
|
|
115
|
+
|
|
116
|
+
await snacks.undo()
|
|
117
|
+
|
|
118
|
+
snacks.undoable // 2
|
|
119
|
+
snacks.redoable // 1
|
|
120
|
+
```
|
|
121
|
+
- chronstrata can have its own substrata — all their mutations advance history
|
|
122
|
+
- plz pinky-swear right now, that you won't create a chronstrata under a substrata under a chronstrata
|
|
123
|
+
|
|
124
|
+
<br/>
|
|
125
|
+
|
|
70
126
|
## a buildercore e280 project
|
|
71
127
|
free and open source by https://e280.org/
|
|
72
128
|
join us if you're cool and good at dev
|
package/package.json
CHANGED
package/s/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
2
|
+
export * from "./parts/chronstrata.js"
|
|
3
|
+
export * from "./parts/strata.js"
|
|
4
|
+
export * from "./parts/substrata.js"
|
|
5
|
+
export * from "./parts/types.js"
|
|
5
6
|
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
|
|
2
|
+
import {Substrata} from "./substrata.js"
|
|
3
|
+
import {Chronicle, Mutator, Options, Selector, Stratum, Substate} from "./types.js"
|
|
4
|
+
|
|
5
|
+
export class Chronstrata<ParentState extends Substate, S extends Substate> implements Stratum<S> {
|
|
6
|
+
#substrata: Substrata<ParentState, Chronicle<S>>
|
|
7
|
+
|
|
8
|
+
constructor(
|
|
9
|
+
public limit: number,
|
|
10
|
+
public parent: Stratum<ParentState>,
|
|
11
|
+
public selector: Selector<ParentState, Chronicle<S>>,
|
|
12
|
+
public options: Options,
|
|
13
|
+
) {
|
|
14
|
+
this.#substrata = parent.substrata(selector)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
get state() {
|
|
18
|
+
return this.#substrata.state.present
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
get undoable() {
|
|
22
|
+
return this.#substrata.state.past.length
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
get redoable() {
|
|
26
|
+
return this.#substrata.state.future.length
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
onMutation(fn: (state: S) => void) {
|
|
30
|
+
return this.#substrata.onMutation(chronicle => fn(chronicle.present))
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** progress forwards in history */
|
|
34
|
+
async mutate(mutator: Mutator<S>) {
|
|
35
|
+
const limit = Math.max(0, this.limit)
|
|
36
|
+
const snapshot = this.options.clone(this.#substrata.state.present)
|
|
37
|
+
await this.#substrata.mutate(chronicle => {
|
|
38
|
+
mutator(chronicle.present)
|
|
39
|
+
chronicle.past.push(snapshot)
|
|
40
|
+
chronicle.past = chronicle.past.slice(-limit)
|
|
41
|
+
chronicle.future = []
|
|
42
|
+
})
|
|
43
|
+
return this.state
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** step backwards into the past, by n steps */
|
|
47
|
+
async undo(n = 1) {
|
|
48
|
+
await this.#substrata.mutate(chronicle => {
|
|
49
|
+
const snapshots = chronicle.past.slice(-n)
|
|
50
|
+
if (snapshots.length >= n) {
|
|
51
|
+
const oldPresent = chronicle.present
|
|
52
|
+
chronicle.present = snapshots.shift()!
|
|
53
|
+
chronicle.past = chronicle.past.slice(0, -n)
|
|
54
|
+
chronicle.future.unshift(oldPresent, ...snapshots)
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** step forwards into the future, by n steps */
|
|
60
|
+
async redo(n = 1) {
|
|
61
|
+
await this.#substrata.mutate(chronicle => {
|
|
62
|
+
const snapshots = chronicle.future.slice(0, n)
|
|
63
|
+
if (snapshots.length >= n) {
|
|
64
|
+
const oldPresent = chronicle.present
|
|
65
|
+
chronicle.present = snapshots.shift()!
|
|
66
|
+
chronicle.past.push(oldPresent, ...snapshots)
|
|
67
|
+
chronicle.future = chronicle.future.slice(n)
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** wipe past and future snapshots */
|
|
73
|
+
async wipe() {
|
|
74
|
+
await this.#substrata.mutate(chronicle => {
|
|
75
|
+
chronicle.past = []
|
|
76
|
+
chronicle.future = []
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
substrata<Sub extends Substate>(selector: Selector<S, Sub>): Substrata<S, Sub> {
|
|
81
|
+
return new Substrata(this, selector, this.options)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
package/s/parts/strata.ts
CHANGED
|
@@ -2,39 +2,51 @@
|
|
|
2
2
|
import {debounce, deep, sub} from "@e280/stz"
|
|
3
3
|
|
|
4
4
|
import {Substrata} from "./substrata.js"
|
|
5
|
+
import {Chronstrata} from "./chronstrata.js"
|
|
5
6
|
import {processOptions} from "./utils/process-options.js"
|
|
6
|
-
import {Mutator, Options, Selector, State, Substate} from "./types.js"
|
|
7
|
+
import {Chronicle, Mutator, Options, Selector, State, Stratum, Substate} from "./types.js"
|
|
7
8
|
|
|
8
|
-
export class Strata<S extends State> {
|
|
9
|
+
export class Strata<S extends State> implements Stratum<S> {
|
|
10
|
+
static chronicle = <S extends Substate>(state: S): Chronicle<S> => ({
|
|
11
|
+
present: state,
|
|
12
|
+
past: [],
|
|
13
|
+
future: [],
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
options: Options
|
|
9
17
|
onMutation = sub<[state: S]>()
|
|
10
18
|
|
|
11
|
-
#options: Options
|
|
12
19
|
#mutable: S
|
|
13
20
|
#immutable: S
|
|
14
|
-
#
|
|
21
|
+
#mutationLock = 0
|
|
22
|
+
#dispatchMutation = debounce(0, async(state: S) => {
|
|
23
|
+
this.#mutationLock++
|
|
24
|
+
try { await this.onMutation.pub(state) }
|
|
25
|
+
finally { this.#mutationLock-- }
|
|
26
|
+
})
|
|
15
27
|
|
|
16
28
|
constructor(state: S, options: Partial<Options> = {}) {
|
|
17
|
-
this
|
|
29
|
+
this.options = processOptions(options)
|
|
18
30
|
this.#mutable = state
|
|
19
|
-
this.#immutable = deep.freeze(this
|
|
31
|
+
this.#immutable = deep.freeze(this.options.clone(state))
|
|
20
32
|
}
|
|
21
33
|
|
|
22
34
|
#updateState(state: S) {
|
|
23
35
|
this.#mutable = state
|
|
24
|
-
this.#immutable = deep.freeze(this
|
|
36
|
+
this.#immutable = deep.freeze(this.options.clone(state))
|
|
25
37
|
}
|
|
26
38
|
|
|
27
39
|
get state() {
|
|
28
40
|
return this.#immutable
|
|
29
41
|
}
|
|
30
42
|
|
|
31
|
-
substrata<Sub extends Substate>(selector: Selector<S, Sub>) {
|
|
32
|
-
return new Substrata(this, selector, this.#options)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
43
|
async mutate(mutator: Mutator<S>) {
|
|
36
|
-
const oldState = this
|
|
37
|
-
|
|
44
|
+
const oldState = this.options.clone(this.#mutable)
|
|
45
|
+
if (this.#mutationLock > 0)
|
|
46
|
+
throw new Error("nested mutations are forbidden")
|
|
47
|
+
this.#mutationLock++
|
|
48
|
+
try { mutator(this.#mutable) }
|
|
49
|
+
finally { this.#mutationLock-- }
|
|
38
50
|
const newState = this.#mutable
|
|
39
51
|
const isChanged = !deep.equal(newState, oldState)
|
|
40
52
|
if (isChanged) {
|
|
@@ -44,5 +56,16 @@ export class Strata<S extends State> {
|
|
|
44
56
|
}
|
|
45
57
|
return this.#immutable
|
|
46
58
|
}
|
|
59
|
+
|
|
60
|
+
substrata<Sub extends Substate>(selector: Selector<S, Sub>): Substrata<S, Sub> {
|
|
61
|
+
return new Substrata(this, selector, this.options)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
chronstrata<Sub extends Substate>(
|
|
65
|
+
limit: number,
|
|
66
|
+
selector: Selector<S, Chronicle<Sub>>,
|
|
67
|
+
) {
|
|
68
|
+
return new Chronstrata(limit, this, selector, this.options)
|
|
69
|
+
}
|
|
47
70
|
}
|
|
48
71
|
|
package/s/parts/substrata.ts
CHANGED
|
@@ -1,29 +1,25 @@
|
|
|
1
1
|
|
|
2
2
|
import {debounce, deep, sub} from "@e280/stz"
|
|
3
|
+
import {Chronstrata} from "./chronstrata.js"
|
|
4
|
+
import {Chronicle, Mutator, Options, Selector, Stratum, Substate} from "./types.js"
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
import {processOptions} from "./utils/process-options.js"
|
|
6
|
-
import {Mutator, Options, Selector, State, Substate} from "./types.js"
|
|
7
|
-
|
|
8
|
-
export class Substrata<ParentState extends State, S extends Substate> {
|
|
6
|
+
export class Substrata<ParentState extends Substate, S extends Substate> implements Stratum<S> {
|
|
9
7
|
dispose: () => void
|
|
10
8
|
onMutation = sub<[state: S]>()
|
|
11
9
|
|
|
12
|
-
#options: Options
|
|
13
10
|
#immutable: S
|
|
14
11
|
#dispatchMutation = debounce(0, (state: S) => this.onMutation.pub(state))
|
|
15
12
|
|
|
16
13
|
constructor(
|
|
17
|
-
private
|
|
14
|
+
private parent: Stratum<ParentState>,
|
|
18
15
|
private selector: Selector<ParentState, S>,
|
|
19
|
-
options:
|
|
16
|
+
private options: Options,
|
|
20
17
|
) {
|
|
21
18
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
this.#immutable = deep.freeze(this.#options.clone(state))
|
|
19
|
+
const state = this.selector(this.parent.state)
|
|
20
|
+
this.#immutable = deep.freeze(this.options.clone(state))
|
|
25
21
|
|
|
26
|
-
this.dispose = this.
|
|
22
|
+
this.dispose = this.parent.onMutation(async parentState => {
|
|
27
23
|
const oldState = this.#immutable
|
|
28
24
|
const newState = this.selector(parentState)
|
|
29
25
|
const isChanged = !deep.equal(newState, oldState)
|
|
@@ -36,7 +32,7 @@ export class Substrata<ParentState extends State, S extends Substate> {
|
|
|
36
32
|
}
|
|
37
33
|
|
|
38
34
|
#updateState(state: S) {
|
|
39
|
-
this.#immutable = deep.freeze(this
|
|
35
|
+
this.#immutable = deep.freeze(this.options.clone(state))
|
|
40
36
|
}
|
|
41
37
|
|
|
42
38
|
get state(): S {
|
|
@@ -44,12 +40,19 @@ export class Substrata<ParentState extends State, S extends Substate> {
|
|
|
44
40
|
}
|
|
45
41
|
|
|
46
42
|
async mutate(mutator: Mutator<S>) {
|
|
47
|
-
await this.
|
|
43
|
+
await this.parent.mutate(parentState => mutator(this.selector(parentState)))
|
|
48
44
|
return this.#immutable
|
|
49
45
|
}
|
|
50
46
|
|
|
51
|
-
substrata<Sub extends Substate>(selector: Selector<S, Sub>) {
|
|
52
|
-
return this
|
|
47
|
+
substrata<Sub extends Substate>(selector: Selector<S, Sub>): Substrata<S, Sub> {
|
|
48
|
+
return new Substrata(this, selector, this.options)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
chronstrata<Sub extends Substate>(
|
|
52
|
+
limit: number,
|
|
53
|
+
selector: Selector<S, Chronicle<Sub>>,
|
|
54
|
+
) {
|
|
55
|
+
return new Chronstrata(limit, this, selector, this.options)
|
|
53
56
|
}
|
|
54
57
|
}
|
|
55
58
|
|
package/s/parts/types.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
|
|
2
|
+
import {Substrata} from "./substrata.js"
|
|
3
|
+
|
|
2
4
|
export type Options = {
|
|
3
5
|
clone: <X>(x: X) => X
|
|
4
6
|
}
|
|
@@ -9,3 +11,21 @@ export type Mutator<S> = (state: S) => void
|
|
|
9
11
|
export type State = {}
|
|
10
12
|
export type Substate = {} | null | undefined
|
|
11
13
|
|
|
14
|
+
export type Stratum<S extends Substate> = {
|
|
15
|
+
readonly state: S
|
|
16
|
+
onMutation(fn: (s: S) => void): () => void
|
|
17
|
+
mutate(mutator: Mutator<S>): Promise<S>
|
|
18
|
+
substrata<Sub extends Substate>(selector: Selector<S, Sub>): Substrata<S, Sub>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type Chronicle<S extends Substate> = {
|
|
22
|
+
// [abc] d [efg]
|
|
23
|
+
// \ \ \
|
|
24
|
+
// \ \ future
|
|
25
|
+
// \ present
|
|
26
|
+
// past
|
|
27
|
+
past: S[]
|
|
28
|
+
present: S
|
|
29
|
+
future: S[]
|
|
30
|
+
}
|
|
31
|
+
|
package/s/tests.test.ts
CHANGED
|
@@ -23,6 +23,17 @@ await Science.run({
|
|
|
23
23
|
expect(strata.state.count).is(2)
|
|
24
24
|
}),
|
|
25
25
|
|
|
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
|
+
}),
|
|
36
|
+
|
|
26
37
|
"state after mutation is frozen": Science.test(async () => {
|
|
27
38
|
const strata = new Strata({x: 1})
|
|
28
39
|
await strata.mutate(s => { s.x = 2 })
|
|
@@ -55,6 +66,21 @@ await Science.run({
|
|
|
55
66
|
expect(mutationCount).is(1)
|
|
56
67
|
expect(strata.state.items.length).is(3)
|
|
57
68
|
}),
|
|
69
|
+
|
|
70
|
+
"prevent mutation loops": Science.test(async() => {
|
|
71
|
+
const strata = new Strata({count: 0})
|
|
72
|
+
let mutationCount = 0
|
|
73
|
+
strata.onMutation.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)
|
|
83
|
+
}),
|
|
58
84
|
}),
|
|
59
85
|
|
|
60
86
|
"substrata": Science.suite({
|
|
@@ -114,6 +140,168 @@ await Science.run({
|
|
|
114
140
|
await a.mutate(a => a.x = 1)
|
|
115
141
|
expect(counted).is(0)
|
|
116
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
|
+
}),
|
|
155
|
+
|
|
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()
|
|
166
|
+
}),
|
|
117
167
|
}),
|
|
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
|
+
})(),
|
|
118
306
|
})
|
|
119
307
|
|
package/x/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
1
|
+
export * from "./parts/chronstrata.js";
|
|
2
|
+
export * from "./parts/strata.js";
|
|
3
|
+
export * from "./parts/substrata.js";
|
|
4
|
+
export * from "./parts/types.js";
|
package/x/index.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
1
|
+
export * from "./parts/chronstrata.js";
|
|
2
|
+
export * from "./parts/strata.js";
|
|
3
|
+
export * from "./parts/substrata.js";
|
|
4
|
+
export * from "./parts/types.js";
|
|
3
5
|
//# sourceMappingURL=index.js.map
|
package/x/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../s/index.ts"],"names":[],"mappings":"AACA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../s/index.ts"],"names":[],"mappings":"AACA,cAAc,wBAAwB,CAAA;AACtC,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA;AACpC,cAAc,kBAAkB,CAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Substrata } from "./substrata.js";
|
|
2
|
+
import { Chronicle, Mutator, Options, Selector, Stratum, Substate } from "./types.js";
|
|
3
|
+
export declare class Chronstrata<ParentState extends Substate, S extends Substate> implements Stratum<S> {
|
|
4
|
+
#private;
|
|
5
|
+
limit: number;
|
|
6
|
+
parent: Stratum<ParentState>;
|
|
7
|
+
selector: Selector<ParentState, Chronicle<S>>;
|
|
8
|
+
options: Options;
|
|
9
|
+
constructor(limit: number, parent: Stratum<ParentState>, selector: Selector<ParentState, Chronicle<S>>, options: Options);
|
|
10
|
+
get state(): S;
|
|
11
|
+
get undoable(): number;
|
|
12
|
+
get redoable(): number;
|
|
13
|
+
onMutation(fn: (state: S) => void): () => void;
|
|
14
|
+
/** progress forwards in history */
|
|
15
|
+
mutate(mutator: Mutator<S>): Promise<S>;
|
|
16
|
+
/** step backwards into the past, by n steps */
|
|
17
|
+
undo(n?: number): Promise<void>;
|
|
18
|
+
/** step forwards into the future, by n steps */
|
|
19
|
+
redo(n?: number): Promise<void>;
|
|
20
|
+
/** wipe past and future snapshots */
|
|
21
|
+
wipe(): Promise<void>;
|
|
22
|
+
substrata<Sub extends Substate>(selector: Selector<S, Sub>): Substrata<S, Sub>;
|
|
23
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Substrata } from "./substrata.js";
|
|
2
|
+
export class Chronstrata {
|
|
3
|
+
limit;
|
|
4
|
+
parent;
|
|
5
|
+
selector;
|
|
6
|
+
options;
|
|
7
|
+
#substrata;
|
|
8
|
+
constructor(limit, parent, selector, options) {
|
|
9
|
+
this.limit = limit;
|
|
10
|
+
this.parent = parent;
|
|
11
|
+
this.selector = selector;
|
|
12
|
+
this.options = options;
|
|
13
|
+
this.#substrata = parent.substrata(selector);
|
|
14
|
+
}
|
|
15
|
+
get state() {
|
|
16
|
+
return this.#substrata.state.present;
|
|
17
|
+
}
|
|
18
|
+
get undoable() {
|
|
19
|
+
return this.#substrata.state.past.length;
|
|
20
|
+
}
|
|
21
|
+
get redoable() {
|
|
22
|
+
return this.#substrata.state.future.length;
|
|
23
|
+
}
|
|
24
|
+
onMutation(fn) {
|
|
25
|
+
return this.#substrata.onMutation(chronicle => fn(chronicle.present));
|
|
26
|
+
}
|
|
27
|
+
/** progress forwards in history */
|
|
28
|
+
async mutate(mutator) {
|
|
29
|
+
const limit = Math.max(0, this.limit);
|
|
30
|
+
const snapshot = this.options.clone(this.#substrata.state.present);
|
|
31
|
+
await this.#substrata.mutate(chronicle => {
|
|
32
|
+
mutator(chronicle.present);
|
|
33
|
+
chronicle.past.push(snapshot);
|
|
34
|
+
chronicle.past = chronicle.past.slice(-limit);
|
|
35
|
+
chronicle.future = [];
|
|
36
|
+
});
|
|
37
|
+
return this.state;
|
|
38
|
+
}
|
|
39
|
+
/** step backwards into the past, by n steps */
|
|
40
|
+
async undo(n = 1) {
|
|
41
|
+
await this.#substrata.mutate(chronicle => {
|
|
42
|
+
const snapshots = chronicle.past.slice(-n);
|
|
43
|
+
if (snapshots.length >= n) {
|
|
44
|
+
const oldPresent = chronicle.present;
|
|
45
|
+
chronicle.present = snapshots.shift();
|
|
46
|
+
chronicle.past = chronicle.past.slice(0, -n);
|
|
47
|
+
chronicle.future.unshift(oldPresent, ...snapshots);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/** step forwards into the future, by n steps */
|
|
52
|
+
async redo(n = 1) {
|
|
53
|
+
await this.#substrata.mutate(chronicle => {
|
|
54
|
+
const snapshots = chronicle.future.slice(0, n);
|
|
55
|
+
if (snapshots.length >= n) {
|
|
56
|
+
const oldPresent = chronicle.present;
|
|
57
|
+
chronicle.present = snapshots.shift();
|
|
58
|
+
chronicle.past.push(oldPresent, ...snapshots);
|
|
59
|
+
chronicle.future = chronicle.future.slice(n);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
/** wipe past and future snapshots */
|
|
64
|
+
async wipe() {
|
|
65
|
+
await this.#substrata.mutate(chronicle => {
|
|
66
|
+
chronicle.past = [];
|
|
67
|
+
chronicle.future = [];
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
substrata(selector) {
|
|
71
|
+
return new Substrata(this, selector, this.options);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=chronstrata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chronstrata.js","sourceRoot":"","sources":["../../s/parts/chronstrata.ts"],"names":[],"mappings":"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"}
|
package/x/parts/strata.d.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { Substrata } from "./substrata.js";
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { Chronstrata } from "./chronstrata.js";
|
|
3
|
+
import { Chronicle, Mutator, Options, Selector, State, Stratum, Substate } from "./types.js";
|
|
4
|
+
export declare class Strata<S extends State> implements Stratum<S> {
|
|
4
5
|
#private;
|
|
6
|
+
static chronicle: <S_1 extends Substate>(state: S_1) => Chronicle<S_1>;
|
|
7
|
+
options: Options;
|
|
5
8
|
onMutation: import("@e280/stz").Sub<[state: S]>;
|
|
6
9
|
constructor(state: S, options?: Partial<Options>);
|
|
7
10
|
get state(): S;
|
|
8
|
-
substrata<Sub extends Substate>(selector: Selector<S, Sub>): Substrata<S, Sub>;
|
|
9
11
|
mutate(mutator: Mutator<S>): Promise<S>;
|
|
12
|
+
substrata<Sub extends Substate>(selector: Selector<S, Sub>): Substrata<S, Sub>;
|
|
13
|
+
chronstrata<Sub extends Substate>(limit: number, selector: Selector<S, Chronicle<Sub>>): Chronstrata<S, Sub>;
|
|
10
14
|
}
|
package/x/parts/strata.js
CHANGED
|
@@ -1,30 +1,50 @@
|
|
|
1
1
|
import { debounce, deep, sub } from "@e280/stz";
|
|
2
2
|
import { Substrata } from "./substrata.js";
|
|
3
|
+
import { Chronstrata } from "./chronstrata.js";
|
|
3
4
|
import { processOptions } from "./utils/process-options.js";
|
|
4
5
|
export class Strata {
|
|
6
|
+
static chronicle = (state) => ({
|
|
7
|
+
present: state,
|
|
8
|
+
past: [],
|
|
9
|
+
future: [],
|
|
10
|
+
});
|
|
11
|
+
options;
|
|
5
12
|
onMutation = sub();
|
|
6
|
-
#options;
|
|
7
13
|
#mutable;
|
|
8
14
|
#immutable;
|
|
9
|
-
#
|
|
15
|
+
#mutationLock = 0;
|
|
16
|
+
#dispatchMutation = debounce(0, async (state) => {
|
|
17
|
+
this.#mutationLock++;
|
|
18
|
+
try {
|
|
19
|
+
await this.onMutation.pub(state);
|
|
20
|
+
}
|
|
21
|
+
finally {
|
|
22
|
+
this.#mutationLock--;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
10
25
|
constructor(state, options = {}) {
|
|
11
|
-
this
|
|
26
|
+
this.options = processOptions(options);
|
|
12
27
|
this.#mutable = state;
|
|
13
|
-
this.#immutable = deep.freeze(this
|
|
28
|
+
this.#immutable = deep.freeze(this.options.clone(state));
|
|
14
29
|
}
|
|
15
30
|
#updateState(state) {
|
|
16
31
|
this.#mutable = state;
|
|
17
|
-
this.#immutable = deep.freeze(this
|
|
32
|
+
this.#immutable = deep.freeze(this.options.clone(state));
|
|
18
33
|
}
|
|
19
34
|
get state() {
|
|
20
35
|
return this.#immutable;
|
|
21
36
|
}
|
|
22
|
-
substrata(selector) {
|
|
23
|
-
return new Substrata(this, selector, this.#options);
|
|
24
|
-
}
|
|
25
37
|
async mutate(mutator) {
|
|
26
|
-
const oldState = this
|
|
27
|
-
|
|
38
|
+
const oldState = this.options.clone(this.#mutable);
|
|
39
|
+
if (this.#mutationLock > 0)
|
|
40
|
+
throw new Error("nested mutations are forbidden");
|
|
41
|
+
this.#mutationLock++;
|
|
42
|
+
try {
|
|
43
|
+
mutator(this.#mutable);
|
|
44
|
+
}
|
|
45
|
+
finally {
|
|
46
|
+
this.#mutationLock--;
|
|
47
|
+
}
|
|
28
48
|
const newState = this.#mutable;
|
|
29
49
|
const isChanged = !deep.equal(newState, oldState);
|
|
30
50
|
if (isChanged) {
|
|
@@ -34,5 +54,11 @@ export class Strata {
|
|
|
34
54
|
}
|
|
35
55
|
return this.#immutable;
|
|
36
56
|
}
|
|
57
|
+
substrata(selector) {
|
|
58
|
+
return new Substrata(this, selector, this.options);
|
|
59
|
+
}
|
|
60
|
+
chronstrata(limit, selector) {
|
|
61
|
+
return new Chronstrata(limit, this, selector, this.options);
|
|
62
|
+
}
|
|
37
63
|
}
|
|
38
64
|
//# sourceMappingURL=strata.js.map
|
package/x/parts/strata.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"strata.js","sourceRoot":"","sources":["../../s/parts/strata.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAC,MAAM,WAAW,CAAA;AAE7C,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAA;AACxC,OAAO,EAAC,cAAc,EAAC,MAAM,4BAA4B,CAAA;AAGzD,MAAM,OAAO,MAAM;IAClB,UAAU,GAAG,GAAG,EAAc,CAAA;IAE9B,QAAQ,
|
|
1
|
+
{"version":3,"file":"strata.js","sourceRoot":"","sources":["../../s/parts/strata.ts"],"names":[],"mappings":"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"}
|
package/x/parts/substrata.d.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Mutator, Options, Selector,
|
|
3
|
-
export declare class Substrata<ParentState extends
|
|
1
|
+
import { Chronstrata } from "./chronstrata.js";
|
|
2
|
+
import { Chronicle, Mutator, Options, Selector, Stratum, Substate } from "./types.js";
|
|
3
|
+
export declare class Substrata<ParentState extends Substate, S extends Substate> implements Stratum<S> {
|
|
4
4
|
#private;
|
|
5
|
-
private
|
|
5
|
+
private parent;
|
|
6
6
|
private selector;
|
|
7
|
+
private options;
|
|
7
8
|
dispose: () => void;
|
|
8
9
|
onMutation: import("@e280/stz").Sub<[state: S]>;
|
|
9
|
-
constructor(
|
|
10
|
+
constructor(parent: Stratum<ParentState>, selector: Selector<ParentState, S>, options: Options);
|
|
10
11
|
get state(): S;
|
|
11
12
|
mutate(mutator: Mutator<S>): Promise<S>;
|
|
12
|
-
substrata<Sub extends Substate>(selector: Selector<S, Sub>): Substrata<
|
|
13
|
+
substrata<Sub extends Substate>(selector: Selector<S, Sub>): Substrata<S, Sub>;
|
|
14
|
+
chronstrata<Sub extends Substate>(limit: number, selector: Selector<S, Chronicle<Sub>>): Chronstrata<S, Sub>;
|
|
13
15
|
}
|
package/x/parts/substrata.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { debounce, deep, sub } from "@e280/stz";
|
|
2
|
-
import {
|
|
2
|
+
import { Chronstrata } from "./chronstrata.js";
|
|
3
3
|
export class Substrata {
|
|
4
|
-
|
|
4
|
+
parent;
|
|
5
5
|
selector;
|
|
6
|
+
options;
|
|
6
7
|
dispose;
|
|
7
8
|
onMutation = sub();
|
|
8
|
-
#options;
|
|
9
9
|
#immutable;
|
|
10
10
|
#dispatchMutation = debounce(0, (state) => this.onMutation.pub(state));
|
|
11
|
-
constructor(
|
|
12
|
-
this.
|
|
11
|
+
constructor(parent, selector, options) {
|
|
12
|
+
this.parent = parent;
|
|
13
13
|
this.selector = selector;
|
|
14
|
-
this
|
|
15
|
-
const state = this.selector(this.
|
|
16
|
-
this.#immutable = deep.freeze(this
|
|
17
|
-
this.dispose = this.
|
|
14
|
+
this.options = options;
|
|
15
|
+
const state = this.selector(this.parent.state);
|
|
16
|
+
this.#immutable = deep.freeze(this.options.clone(state));
|
|
17
|
+
this.dispose = this.parent.onMutation(async (parentState) => {
|
|
18
18
|
const oldState = this.#immutable;
|
|
19
19
|
const newState = this.selector(parentState);
|
|
20
20
|
const isChanged = !deep.equal(newState, oldState);
|
|
@@ -26,17 +26,20 @@ export class Substrata {
|
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
28
|
#updateState(state) {
|
|
29
|
-
this.#immutable = deep.freeze(this
|
|
29
|
+
this.#immutable = deep.freeze(this.options.clone(state));
|
|
30
30
|
}
|
|
31
31
|
get state() {
|
|
32
32
|
return this.#immutable;
|
|
33
33
|
}
|
|
34
34
|
async mutate(mutator) {
|
|
35
|
-
await this.
|
|
35
|
+
await this.parent.mutate(parentState => mutator(this.selector(parentState)));
|
|
36
36
|
return this.#immutable;
|
|
37
37
|
}
|
|
38
38
|
substrata(selector) {
|
|
39
|
-
return this
|
|
39
|
+
return new Substrata(this, selector, this.options);
|
|
40
|
+
}
|
|
41
|
+
chronstrata(limit, selector) {
|
|
42
|
+
return new Chronstrata(limit, this, selector, this.options);
|
|
40
43
|
}
|
|
41
44
|
}
|
|
42
45
|
//# sourceMappingURL=substrata.js.map
|
package/x/parts/substrata.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"substrata.js","sourceRoot":"","sources":["../../s/parts/substrata.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAC,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"substrata.js","sourceRoot":"","sources":["../../s/parts/substrata.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAC,MAAM,WAAW,CAAA;AAC7C,OAAO,EAAC,WAAW,EAAC,MAAM,kBAAkB,CAAA;AAG5C,MAAM,OAAO,SAAS;IAQX;IACA;IACA;IATV,OAAO,CAAY;IACnB,UAAU,GAAG,GAAG,EAAc,CAAA;IAE9B,UAAU,CAAG;IACb,iBAAiB,GAAG,QAAQ,CAAC,CAAC,EAAE,CAAC,KAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAA;IAEzE,YACU,MAA4B,EAC5B,QAAkC,EAClC,OAAgB;QAFhB,WAAM,GAAN,MAAM,CAAsB;QAC5B,aAAQ,GAAR,QAAQ,CAA0B;QAClC,YAAO,GAAP,OAAO,CAAS;QAGzB,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAC9C,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAA;QAExD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,EAAC,WAAW,EAAC,EAAE;YACzD,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAA;YAChC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;YAC3C,MAAM,SAAS,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;YACjD,IAAI,SAAS,EAAE,CAAC;gBACf,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAA;gBAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAA;gBAC5B,MAAM,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAA;YACxC,CAAC;QACF,CAAC,CAAC,CAAA;IACH,CAAC;IAED,YAAY,CAAC,KAAQ;QACpB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAA;IACzD,CAAC;IAED,IAAI,KAAK;QACR,OAAO,IAAI,CAAC,UAAU,CAAA;IACvB,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,OAAmB;QAC/B,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAA;QAC5E,OAAO,IAAI,CAAC,UAAU,CAAA;IACvB,CAAC;IAED,SAAS,CAAuB,QAA0B;QACzD,OAAO,IAAI,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;IACnD,CAAC;IAED,WAAW,CACT,KAAa,EACb,QAAqC;QAEtC,OAAO,IAAI,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;IAC5D,CAAC;CACD"}
|
package/x/parts/types.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Substrata } from "./substrata.js";
|
|
1
2
|
export type Options = {
|
|
2
3
|
clone: <X>(x: X) => X;
|
|
3
4
|
};
|
|
@@ -5,3 +6,14 @@ export type Selector<S, Sub> = (state: S) => Sub;
|
|
|
5
6
|
export type Mutator<S> = (state: S) => void;
|
|
6
7
|
export type State = {};
|
|
7
8
|
export type Substate = {} | null | undefined;
|
|
9
|
+
export type Stratum<S extends Substate> = {
|
|
10
|
+
readonly state: S;
|
|
11
|
+
onMutation(fn: (s: S) => void): () => void;
|
|
12
|
+
mutate(mutator: Mutator<S>): Promise<S>;
|
|
13
|
+
substrata<Sub extends Substate>(selector: Selector<S, Sub>): Substrata<S, Sub>;
|
|
14
|
+
};
|
|
15
|
+
export type Chronicle<S extends Substate> = {
|
|
16
|
+
past: S[];
|
|
17
|
+
present: S;
|
|
18
|
+
future: S[];
|
|
19
|
+
};
|
package/x/tests.test.js
CHANGED
|
@@ -18,6 +18,16 @@ await Science.run({
|
|
|
18
18
|
await strata.mutate(state => state.count++);
|
|
19
19
|
expect(strata.state.count).is(2);
|
|
20
20
|
}),
|
|
21
|
+
"forbidden mutation nesting": Science.test(async () => {
|
|
22
|
+
const strata = new Strata({ count: 0 });
|
|
23
|
+
await expect(async () => {
|
|
24
|
+
let promise;
|
|
25
|
+
await strata.mutate(() => {
|
|
26
|
+
promise = strata.mutate(() => { });
|
|
27
|
+
});
|
|
28
|
+
await promise;
|
|
29
|
+
}).throwsAsync();
|
|
30
|
+
}),
|
|
21
31
|
"state after mutation is frozen": Science.test(async () => {
|
|
22
32
|
const strata = new Strata({ x: 1 });
|
|
23
33
|
await strata.mutate(s => { s.x = 2; });
|
|
@@ -47,6 +57,20 @@ await Science.run({
|
|
|
47
57
|
expect(mutationCount).is(1);
|
|
48
58
|
expect(strata.state.items.length).is(3);
|
|
49
59
|
}),
|
|
60
|
+
"prevent mutation loops": Science.test(async () => {
|
|
61
|
+
const strata = new Strata({ count: 0 });
|
|
62
|
+
let mutationCount = 0;
|
|
63
|
+
strata.onMutation.sub(async () => {
|
|
64
|
+
mutationCount++;
|
|
65
|
+
if (mutationCount > 100)
|
|
66
|
+
return;
|
|
67
|
+
await strata.mutate(s => s.count++);
|
|
68
|
+
});
|
|
69
|
+
await expect(async () => {
|
|
70
|
+
await strata.mutate(state => state.count++);
|
|
71
|
+
}).throwsAsync();
|
|
72
|
+
expect(mutationCount).is(1);
|
|
73
|
+
}),
|
|
50
74
|
}),
|
|
51
75
|
"substrata": Science.suite({
|
|
52
76
|
"get state": Science.test(async () => {
|
|
@@ -101,6 +125,147 @@ await Science.run({
|
|
|
101
125
|
await a.mutate(a => a.x = 1);
|
|
102
126
|
expect(counted).is(0);
|
|
103
127
|
}),
|
|
128
|
+
"forbid submutation in mutation": Science.test(async () => {
|
|
129
|
+
const strata = new Strata({ a: { b: 0 } });
|
|
130
|
+
const a = strata.substrata(s => s.a);
|
|
131
|
+
await expect(async () => {
|
|
132
|
+
let promise;
|
|
133
|
+
await strata.mutate(() => {
|
|
134
|
+
promise = a.mutate(() => { });
|
|
135
|
+
});
|
|
136
|
+
await promise;
|
|
137
|
+
}).throwsAsync();
|
|
138
|
+
}),
|
|
139
|
+
"forbid mutation in submutation": Science.test(async () => {
|
|
140
|
+
const strata = new Strata({ a: { b: 0 } });
|
|
141
|
+
const a = strata.substrata(s => s.a);
|
|
142
|
+
await expect(async () => {
|
|
143
|
+
let promise;
|
|
144
|
+
await a.mutate(() => {
|
|
145
|
+
promise = strata.mutate(() => { });
|
|
146
|
+
});
|
|
147
|
+
await promise;
|
|
148
|
+
}).throwsAsync();
|
|
149
|
+
}),
|
|
104
150
|
}),
|
|
151
|
+
"chronstrata": (() => {
|
|
152
|
+
const setup = () => {
|
|
153
|
+
const strata = new Strata({
|
|
154
|
+
chron: Strata.chronicle({ count: 0 }),
|
|
155
|
+
});
|
|
156
|
+
const chron = strata.chronstrata(64, s => s.chron);
|
|
157
|
+
return { strata, chron };
|
|
158
|
+
};
|
|
159
|
+
return Science.suite({
|
|
160
|
+
"get state": Science.test(async () => {
|
|
161
|
+
const { chron } = setup();
|
|
162
|
+
expect(chron.state.count).is(0);
|
|
163
|
+
}),
|
|
164
|
+
"mutate": Science.test(async () => {
|
|
165
|
+
const { chron } = setup();
|
|
166
|
+
expect(chron.state.count).is(0);
|
|
167
|
+
await chron.mutate(s => s.count++);
|
|
168
|
+
expect(chron.state.count).is(1);
|
|
169
|
+
await chron.mutate(s => s.count++);
|
|
170
|
+
expect(chron.state.count).is(2);
|
|
171
|
+
}),
|
|
172
|
+
"undoable/redoable": Science.test(async () => {
|
|
173
|
+
const { chron } = setup();
|
|
174
|
+
expect(chron.undoable).is(0);
|
|
175
|
+
expect(chron.redoable).is(0);
|
|
176
|
+
expect(chron.state.count).is(0);
|
|
177
|
+
await chron.mutate(s => s.count++);
|
|
178
|
+
expect(chron.undoable).is(1);
|
|
179
|
+
await chron.mutate(s => s.count++);
|
|
180
|
+
expect(chron.undoable).is(2);
|
|
181
|
+
await chron.undo();
|
|
182
|
+
expect(chron.undoable).is(1);
|
|
183
|
+
expect(chron.redoable).is(1);
|
|
184
|
+
await chron.undo();
|
|
185
|
+
expect(chron.undoable).is(0);
|
|
186
|
+
expect(chron.redoable).is(2);
|
|
187
|
+
await chron.redo();
|
|
188
|
+
expect(chron.undoable).is(1);
|
|
189
|
+
expect(chron.redoable).is(1);
|
|
190
|
+
}),
|
|
191
|
+
"undo": Science.test(async () => {
|
|
192
|
+
const { chron } = setup();
|
|
193
|
+
await chron.mutate(s => s.count++);
|
|
194
|
+
await chron.undo();
|
|
195
|
+
expect(chron.state.count).is(0);
|
|
196
|
+
}),
|
|
197
|
+
"redo": Science.test(async () => {
|
|
198
|
+
const { chron } = setup();
|
|
199
|
+
await chron.mutate(s => s.count++);
|
|
200
|
+
await chron.undo();
|
|
201
|
+
expect(chron.state.count).is(0);
|
|
202
|
+
await chron.redo();
|
|
203
|
+
expect(chron.state.count).is(1);
|
|
204
|
+
}),
|
|
205
|
+
"undo/redo well ordered": Science.test(async () => {
|
|
206
|
+
const { chron } = setup();
|
|
207
|
+
await chron.mutate(s => s.count++);
|
|
208
|
+
await chron.mutate(s => s.count++);
|
|
209
|
+
await chron.mutate(s => s.count++);
|
|
210
|
+
expect(chron.state.count).is(3);
|
|
211
|
+
await chron.undo();
|
|
212
|
+
expect(chron.state.count).is(2);
|
|
213
|
+
await chron.undo();
|
|
214
|
+
expect(chron.state.count).is(1);
|
|
215
|
+
await chron.redo();
|
|
216
|
+
expect(chron.state.count).is(2);
|
|
217
|
+
await chron.redo();
|
|
218
|
+
expect(chron.state.count).is(3);
|
|
219
|
+
await chron.undo();
|
|
220
|
+
expect(chron.state.count).is(2);
|
|
221
|
+
await chron.undo();
|
|
222
|
+
expect(chron.state.count).is(1);
|
|
223
|
+
await chron.undo();
|
|
224
|
+
expect(chron.state.count).is(0);
|
|
225
|
+
}),
|
|
226
|
+
"undo nothing does nothing": Science.test(async () => {
|
|
227
|
+
const { chron } = setup();
|
|
228
|
+
await chron.undo();
|
|
229
|
+
expect(chron.state.count).is(0);
|
|
230
|
+
}),
|
|
231
|
+
"redo nothing does nothing": Science.test(async () => {
|
|
232
|
+
const { chron } = setup();
|
|
233
|
+
await chron.redo();
|
|
234
|
+
expect(chron.state.count).is(0);
|
|
235
|
+
}),
|
|
236
|
+
"undo 2x": Science.test(async () => {
|
|
237
|
+
const { chron } = setup();
|
|
238
|
+
await chron.mutate(s => s.count++);
|
|
239
|
+
await chron.mutate(s => s.count++);
|
|
240
|
+
expect(chron.state.count).is(2);
|
|
241
|
+
await chron.undo(2);
|
|
242
|
+
expect(chron.state.count).is(0);
|
|
243
|
+
}),
|
|
244
|
+
"redo 2x": Science.test(async () => {
|
|
245
|
+
const { chron } = setup();
|
|
246
|
+
await chron.mutate(s => s.count++);
|
|
247
|
+
await chron.mutate(s => s.count++);
|
|
248
|
+
expect(chron.state.count).is(2);
|
|
249
|
+
await chron.undo(2);
|
|
250
|
+
expect(chron.state.count).is(0);
|
|
251
|
+
await chron.redo(2);
|
|
252
|
+
expect(chron.state.count).is(2);
|
|
253
|
+
}),
|
|
254
|
+
"substrata mutations are tracked": Science.test(async () => {
|
|
255
|
+
const strata = new Strata({
|
|
256
|
+
chron: Strata.chronicle({
|
|
257
|
+
group: { count: 0 },
|
|
258
|
+
}),
|
|
259
|
+
});
|
|
260
|
+
const chron = strata.chronstrata(64, s => s.chron);
|
|
261
|
+
const group = chron.substrata(s => s.group);
|
|
262
|
+
expect(group.state.count).is(0);
|
|
263
|
+
await group.mutate(g => g.count = 101);
|
|
264
|
+
expect(group.state.count).is(101);
|
|
265
|
+
await chron.undo();
|
|
266
|
+
expect(group.state.count).is(0);
|
|
267
|
+
}),
|
|
268
|
+
});
|
|
269
|
+
})(),
|
|
105
270
|
});
|
|
106
271
|
//# sourceMappingURL=tests.test.js.map
|
package/x/tests.test.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tests.test.js","sourceRoot":"","sources":["../s/tests.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tests.test.js","sourceRoot":"","sources":["../s/tests.test.ts"],"names":[],"mappings":"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"}
|