atom.io 0.6.4 → 0.6.6
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 +32 -78
- package/dist/index.d.mts +4 -35
- package/dist/index.d.ts +4 -35
- package/dist/index.js +17 -129
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +17 -129
- package/dist/index.mjs.map +1 -1
- package/introspection/dist/index.js +312 -0
- package/introspection/dist/index.js.map +1 -0
- package/introspection/dist/index.mjs +289 -0
- package/introspection/dist/index.mjs.map +1 -0
- package/introspection/package.json +15 -0
- package/package.json +17 -8
- package/react-devtools/dist/index.css +22 -5
- package/react-devtools/dist/index.css.map +1 -1
- package/react-devtools/dist/index.d.mts +347 -8
- package/react-devtools/dist/index.d.ts +347 -8
- package/react-devtools/dist/index.js +2722 -674
- package/react-devtools/dist/index.js.map +1 -1
- package/react-devtools/dist/index.mjs +2669 -630
- package/react-devtools/dist/index.mjs.map +1 -1
- package/src/internal/index.ts +0 -1
- package/src/internal/operation.ts +1 -0
- package/src/internal/store.ts +3 -2
- package/src/internal/time-travel-internal.ts +2 -0
- package/src/internal/timeline/add-atom-to-timeline.ts +11 -12
- package/src/internal/timeline-internal.ts +5 -1
- package/src/introspection/attach-atom-index.ts +73 -0
- package/src/introspection/attach-introspection-states.ts +42 -0
- package/src/introspection/attach-selector-index.ts +77 -0
- package/src/introspection/attach-timeline-family.ts +49 -0
- package/src/introspection/attach-timeline-index.ts +36 -0
- package/src/introspection/attach-transaction-index.ts +38 -0
- package/src/introspection/attach-transaction-logs.ts +40 -0
- package/src/introspection/index.ts +20 -0
- package/src/react-devtools/AtomIODevtools.tsx +97 -96
- package/src/react-devtools/Button.tsx +24 -0
- package/src/react-devtools/StateEditor.tsx +14 -16
- package/src/react-devtools/StateIndex.tsx +153 -0
- package/src/react-devtools/TimelineIndex.tsx +92 -0
- package/src/react-devtools/TransactionIndex.tsx +70 -0
- package/src/react-devtools/Updates.tsx +145 -0
- package/src/react-devtools/devtools.scss +196 -15
- package/src/react-devtools/index.ts +71 -0
- package/src/react-explorer/AtomIOExplorer.tsx +0 -1
- package/src/react-explorer/explorer-effects.ts +3 -3
- package/src/react-explorer/explorer-states.ts +1 -1
- package/src/react-explorer/space-states.ts +6 -4
- package/src/react-explorer/view-states.ts +0 -2
- package/realtime-testing/dist/index.d.mts +0 -49
- package/realtime-testing/dist/index.d.ts +0 -49
- package/realtime-testing/dist/index.js +0 -165
- package/realtime-testing/dist/index.js.map +0 -1
- package/realtime-testing/dist/index.mjs +0 -129
- package/realtime-testing/dist/index.mjs.map +0 -1
- package/src/internal/meta/attach-meta.ts +0 -17
- package/src/internal/meta/index.ts +0 -4
- package/src/internal/meta/meta-state.ts +0 -135
- package/src/internal/meta/meta-timelines.ts +0 -1
- package/src/internal/meta/meta-transactions.ts +0 -1
- package/src/react-devtools/TokenList.tsx +0 -61
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import type { ƒn } from "~/packages/anvl/src/function"
|
|
2
|
+
import { discoverType } from "~/packages/anvl/src/refinement/refinery"
|
|
3
|
+
|
|
4
|
+
import { prettyJson } from "."
|
|
5
|
+
import type { KeyedStateUpdate } from "../subscribe"
|
|
6
|
+
import type { TimelineUpdate } from "../timeline"
|
|
7
|
+
import type { TransactionUpdate } from "../transaction"
|
|
8
|
+
|
|
9
|
+
const AtomUpdateFC: React.FC<{
|
|
10
|
+
serialNumber: number
|
|
11
|
+
atomUpdate: KeyedStateUpdate<unknown>
|
|
12
|
+
}> = ({ atomUpdate }) => {
|
|
13
|
+
return (
|
|
14
|
+
<article
|
|
15
|
+
key={atomUpdate.key}
|
|
16
|
+
className="node atom_update"
|
|
17
|
+
onClick={() => console.log(atomUpdate)}
|
|
18
|
+
onKeyUp={() => console.log(atomUpdate)}
|
|
19
|
+
>
|
|
20
|
+
<span className="detail">{atomUpdate.key}: </span>
|
|
21
|
+
<span>
|
|
22
|
+
<span className="summary">
|
|
23
|
+
{prettyJson.diff(atomUpdate.oldValue, atomUpdate.newValue).summary}
|
|
24
|
+
</span>
|
|
25
|
+
</span>
|
|
26
|
+
</article>
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const TransactionUpdateFC: React.FC<{
|
|
31
|
+
serialNumber: number
|
|
32
|
+
transactionUpdate: TransactionUpdate<ƒn>
|
|
33
|
+
}> = ({ serialNumber, transactionUpdate }) => {
|
|
34
|
+
return (
|
|
35
|
+
<article className="node transaction_update">
|
|
36
|
+
<header>
|
|
37
|
+
<h4>{serialNumber}</h4>
|
|
38
|
+
</header>
|
|
39
|
+
<main>
|
|
40
|
+
<section className="transaction_params">
|
|
41
|
+
<span className="detail">params: </span>
|
|
42
|
+
{transactionUpdate.params.map((param, index) => {
|
|
43
|
+
return (
|
|
44
|
+
<article
|
|
45
|
+
key={`param` + index}
|
|
46
|
+
className="node transaction_param"
|
|
47
|
+
onClick={() => console.log(transactionUpdate)}
|
|
48
|
+
onKeyUp={() => console.log(transactionUpdate)}
|
|
49
|
+
>
|
|
50
|
+
<span className="detail">{discoverType(param)}: </span>
|
|
51
|
+
<span className="summary">
|
|
52
|
+
{typeof param === `object` &&
|
|
53
|
+
`type` in param &&
|
|
54
|
+
`target` in param ? (
|
|
55
|
+
<>{JSON.stringify(param.type)}</>
|
|
56
|
+
) : (
|
|
57
|
+
<>{JSON.stringify(param)}</>
|
|
58
|
+
)}
|
|
59
|
+
</span>
|
|
60
|
+
</article>
|
|
61
|
+
)
|
|
62
|
+
})}
|
|
63
|
+
</section>
|
|
64
|
+
<section className="node transaction_output">
|
|
65
|
+
<span className="detail">output: </span>
|
|
66
|
+
<span className="detail">
|
|
67
|
+
{discoverType(transactionUpdate.output)}
|
|
68
|
+
</span>
|
|
69
|
+
{transactionUpdate.output ? (
|
|
70
|
+
<span className="summary">
|
|
71
|
+
: {JSON.stringify(transactionUpdate.output)}
|
|
72
|
+
</span>
|
|
73
|
+
) : null}
|
|
74
|
+
</section>
|
|
75
|
+
<section className="transaction_impact">
|
|
76
|
+
<span className="detail">impact: </span>
|
|
77
|
+
{transactionUpdate.atomUpdates
|
|
78
|
+
.filter((token) => !token.key.startsWith(`👁🗨`))
|
|
79
|
+
.map((atomUpdate, index) => {
|
|
80
|
+
return (
|
|
81
|
+
<article.AtomUpdate
|
|
82
|
+
key={`${transactionUpdate.key}:${index}:${atomUpdate.key}`}
|
|
83
|
+
serialNumber={index}
|
|
84
|
+
atomUpdate={atomUpdate}
|
|
85
|
+
/>
|
|
86
|
+
)
|
|
87
|
+
})}
|
|
88
|
+
</section>
|
|
89
|
+
</main>
|
|
90
|
+
</article>
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export const TimelineUpdateFC: React.FC<{
|
|
95
|
+
timelineUpdate: TimelineUpdate
|
|
96
|
+
}> = ({ timelineUpdate }) => {
|
|
97
|
+
return (
|
|
98
|
+
<article className="node timeline_update">
|
|
99
|
+
<header>
|
|
100
|
+
<h4>
|
|
101
|
+
{timelineUpdate.timestamp}: {timelineUpdate.type} ({timelineUpdate.key}
|
|
102
|
+
)
|
|
103
|
+
</h4>
|
|
104
|
+
</header>
|
|
105
|
+
<main>
|
|
106
|
+
{timelineUpdate.type === `transaction_update` ? (
|
|
107
|
+
timelineUpdate.atomUpdates
|
|
108
|
+
.filter((token) => !token.key.startsWith(`👁🗨`))
|
|
109
|
+
.map((atomUpdate, index) => {
|
|
110
|
+
return (
|
|
111
|
+
<article.AtomUpdate
|
|
112
|
+
key={`${timelineUpdate.key}:${index}:${atomUpdate.key}`}
|
|
113
|
+
serialNumber={index}
|
|
114
|
+
atomUpdate={atomUpdate}
|
|
115
|
+
/>
|
|
116
|
+
)
|
|
117
|
+
})
|
|
118
|
+
) : timelineUpdate.type === `selector_update` ? (
|
|
119
|
+
timelineUpdate.atomUpdates
|
|
120
|
+
.filter((token) => !token.key.startsWith(`👁🗨`))
|
|
121
|
+
.map((atomUpdate, index) => {
|
|
122
|
+
return (
|
|
123
|
+
<article.AtomUpdate
|
|
124
|
+
key={`${timelineUpdate.key}:${index}:${atomUpdate.key}`}
|
|
125
|
+
serialNumber={index}
|
|
126
|
+
atomUpdate={atomUpdate}
|
|
127
|
+
/>
|
|
128
|
+
)
|
|
129
|
+
})
|
|
130
|
+
) : timelineUpdate.type === `atom_update` ? (
|
|
131
|
+
<article.AtomUpdate
|
|
132
|
+
serialNumber={timelineUpdate.timestamp}
|
|
133
|
+
atomUpdate={timelineUpdate}
|
|
134
|
+
/>
|
|
135
|
+
) : null}
|
|
136
|
+
</main>
|
|
137
|
+
</article>
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export const article = {
|
|
142
|
+
AtomUpdate: AtomUpdateFC,
|
|
143
|
+
TransactionUpdate: TransactionUpdateFC,
|
|
144
|
+
TimelineUpdate: TimelineUpdateFC,
|
|
145
|
+
}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
main.atom_io_devtools {
|
|
2
2
|
--fg-color: #eee;
|
|
3
3
|
--bg-color: #111;
|
|
4
|
+
--bg-tint1: #222;
|
|
5
|
+
--fg-border: 1px solid var(--fg-color);
|
|
4
6
|
@media (prefers-color-scheme: light) {
|
|
5
|
-
--fg-color: #
|
|
6
|
-
--bg-color: #
|
|
7
|
+
--fg-color: #444;
|
|
8
|
+
--bg-color: #ddd;
|
|
9
|
+
--bg-tint1: #e3e3e3;
|
|
7
10
|
}
|
|
8
11
|
box-sizing: border-box;
|
|
9
12
|
color: var(--fg-color);
|
|
@@ -17,31 +20,208 @@ main.atom_io_devtools {
|
|
|
17
20
|
flex-flow: column;
|
|
18
21
|
max-height: 800px;
|
|
19
22
|
width: 100%;
|
|
20
|
-
max-width:
|
|
23
|
+
max-width: 500px;
|
|
21
24
|
overflow-y: scroll;
|
|
22
|
-
|
|
23
|
-
|
|
25
|
+
* {
|
|
26
|
+
font-size: 16px;
|
|
27
|
+
font-family: theia, monospace;
|
|
28
|
+
}
|
|
29
|
+
> header {
|
|
30
|
+
padding: 5px;
|
|
31
|
+
padding-left: 10px;
|
|
32
|
+
padding-bottom: 0;
|
|
24
33
|
display: flex;
|
|
25
34
|
justify-content: space-between;
|
|
26
35
|
h1 {
|
|
27
36
|
font-size: inherit;
|
|
28
37
|
margin: 0;
|
|
38
|
+
font-size: 24px;
|
|
39
|
+
font-family: charter;
|
|
40
|
+
}
|
|
41
|
+
nav {
|
|
42
|
+
display: flex;
|
|
43
|
+
flex-flow: row nowrap;
|
|
44
|
+
button {
|
|
45
|
+
cursor: pointer;
|
|
46
|
+
background: none;
|
|
47
|
+
border: none;
|
|
48
|
+
padding: none;
|
|
49
|
+
margin-bottom: -2px;
|
|
50
|
+
z-index: 1000;
|
|
51
|
+
&:disabled {
|
|
52
|
+
cursor: default;
|
|
53
|
+
background-color: var(--bg-tint1);
|
|
54
|
+
color: var(--fg-color);
|
|
55
|
+
border: var(--fg-border);
|
|
56
|
+
border-bottom: none;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
29
59
|
}
|
|
30
60
|
}
|
|
61
|
+
> main {
|
|
62
|
+
background: var(--bg-tint1);
|
|
63
|
+
}
|
|
31
64
|
main {
|
|
32
65
|
overflow-y: scroll;
|
|
33
66
|
flex-grow: 1;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
67
|
+
display: flex;
|
|
68
|
+
flex-flow: column;
|
|
69
|
+
gap: 0;
|
|
70
|
+
article.index {
|
|
71
|
+
.node .node {
|
|
72
|
+
border-right: var(--fg-border);
|
|
73
|
+
padding-right: 0;
|
|
74
|
+
background: #fff3;
|
|
75
|
+
}
|
|
76
|
+
.node > .node {
|
|
77
|
+
margin: 5px 0;
|
|
78
|
+
margin-left: 12px;
|
|
79
|
+
border-left: var(--fg-border);
|
|
39
80
|
}
|
|
40
81
|
.node {
|
|
41
|
-
border:
|
|
42
|
-
padding: 5px;
|
|
43
|
-
margin: 5px;
|
|
82
|
+
border-top: var(--fg-border);
|
|
44
83
|
overflow-x: scroll;
|
|
84
|
+
padding: 5px;
|
|
85
|
+
&:last-of-type {
|
|
86
|
+
border-bottom: var(--fg-border);
|
|
87
|
+
}
|
|
88
|
+
&.transaction_update {
|
|
89
|
+
padding: 0;
|
|
90
|
+
}
|
|
91
|
+
header {
|
|
92
|
+
display: flex;
|
|
93
|
+
flex-flow: row;
|
|
94
|
+
gap: 5px;
|
|
95
|
+
position: sticky;
|
|
96
|
+
z-index: 999;
|
|
97
|
+
top: 0;
|
|
98
|
+
button.carat {
|
|
99
|
+
cursor: pointer;
|
|
100
|
+
background: none;
|
|
101
|
+
border: none;
|
|
102
|
+
width: 20px;
|
|
103
|
+
&.open {
|
|
104
|
+
transform: rotate(90deg);
|
|
105
|
+
}
|
|
106
|
+
&:disabled {
|
|
107
|
+
cursor: default;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
label {
|
|
111
|
+
display: flex;
|
|
112
|
+
flex-flow: row;
|
|
113
|
+
gap: 5px;
|
|
114
|
+
cursor: help;
|
|
115
|
+
h2 {
|
|
116
|
+
display: inline-block;
|
|
117
|
+
margin: 0;
|
|
118
|
+
}
|
|
119
|
+
.detail {
|
|
120
|
+
color: #777;
|
|
121
|
+
@media (prefers-color-scheme: light) {
|
|
122
|
+
color: #999;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
main {
|
|
128
|
+
margin-left: 15px;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
section.transaction_log {
|
|
132
|
+
margin-top: 0;
|
|
133
|
+
header: {
|
|
134
|
+
padding: 5px;
|
|
135
|
+
}
|
|
136
|
+
main {
|
|
137
|
+
display: flex;
|
|
138
|
+
flex-flow: row wrap;
|
|
139
|
+
gap: 5px;
|
|
140
|
+
.transaction_update {
|
|
141
|
+
width: 100%;
|
|
142
|
+
display: flex;
|
|
143
|
+
flex-flow: row;
|
|
144
|
+
align-items: flex-start;
|
|
145
|
+
justify-content: flex-start;
|
|
146
|
+
justify-items: flex-start;
|
|
147
|
+
align-content: flex-start;
|
|
148
|
+
border-left: var(--fg-border);
|
|
149
|
+
border-top: var(--fg-border);
|
|
150
|
+
header {
|
|
151
|
+
padding: 5px;
|
|
152
|
+
h4 {
|
|
153
|
+
margin: 0;
|
|
154
|
+
padding: 0;
|
|
155
|
+
font-size: inherit;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
main {
|
|
159
|
+
margin-left: 0;
|
|
160
|
+
display: flex;
|
|
161
|
+
flex-flow: column;
|
|
162
|
+
gap: 0px;
|
|
163
|
+
border-left: 1px solid #333;
|
|
164
|
+
section ~ section {
|
|
165
|
+
border-top: 1px solid #333;
|
|
166
|
+
}
|
|
167
|
+
section {
|
|
168
|
+
padding: 5px;
|
|
169
|
+
&.transaction_output {
|
|
170
|
+
border-right: none;
|
|
171
|
+
}
|
|
172
|
+
&.transaction_impact {
|
|
173
|
+
padding: 5px;
|
|
174
|
+
}
|
|
175
|
+
margin: 0;
|
|
176
|
+
article {
|
|
177
|
+
border-left: var(--fg-border);
|
|
178
|
+
border-right: var(--fg-border);
|
|
179
|
+
.summary {
|
|
180
|
+
white-space: nowrap;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
section.timeline_log {
|
|
189
|
+
header {
|
|
190
|
+
display: flex;
|
|
191
|
+
label {
|
|
192
|
+
display: flex;
|
|
193
|
+
width: 100%;
|
|
194
|
+
flex-grow: 1;
|
|
195
|
+
.gap {
|
|
196
|
+
flex-grow: 1;
|
|
197
|
+
}
|
|
198
|
+
nav {
|
|
199
|
+
display: flex;
|
|
200
|
+
flex-flow: row nowrap;
|
|
201
|
+
gap: 5px;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
.timeline_update {
|
|
206
|
+
padding: 5px;
|
|
207
|
+
border-left: var(--fg-border);
|
|
208
|
+
h4 {
|
|
209
|
+
margin: 0;
|
|
210
|
+
padding: 0;
|
|
211
|
+
font-size: inherit;
|
|
212
|
+
}
|
|
213
|
+
main {
|
|
214
|
+
margin: 0;
|
|
215
|
+
.node.atom_update {
|
|
216
|
+
border-left: var(--fg-border);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
.you_are_here {
|
|
221
|
+
background: var(--fg-color);
|
|
222
|
+
color: var(--bg-color);
|
|
223
|
+
text-align: center;
|
|
224
|
+
}
|
|
45
225
|
}
|
|
46
226
|
}
|
|
47
227
|
}
|
|
@@ -61,7 +241,7 @@ main.atom_io_devtools {
|
|
|
61
241
|
|
|
62
242
|
.json_editor {
|
|
63
243
|
input {
|
|
64
|
-
font-size: 20px;
|
|
244
|
+
// font-size: 20px;
|
|
65
245
|
font-family: theia;
|
|
66
246
|
border: none;
|
|
67
247
|
border-bottom: 1px solid;
|
|
@@ -106,6 +286,7 @@ main.atom_io_devtools {
|
|
|
106
286
|
background-color: #f055;
|
|
107
287
|
}
|
|
108
288
|
.json_editor_key {
|
|
289
|
+
padding-right: 10px;
|
|
109
290
|
input {
|
|
110
291
|
color: #999;
|
|
111
292
|
@media (prefers-color-scheme: light) {
|
|
@@ -121,7 +302,7 @@ main.atom_io_devtools {
|
|
|
121
302
|
}
|
|
122
303
|
.json_editor_properties {
|
|
123
304
|
> * {
|
|
124
|
-
border-bottom:
|
|
305
|
+
border-bottom: var(--fg-border);
|
|
125
306
|
margin-bottom: 2px;
|
|
126
307
|
}
|
|
127
308
|
}
|
|
@@ -1 +1,72 @@
|
|
|
1
|
+
import { isPlainObject } from "~/packages/anvl/src/object"
|
|
2
|
+
import { Refinery } from "~/packages/anvl/src/refinement/refinery"
|
|
3
|
+
import {
|
|
4
|
+
diffArray,
|
|
5
|
+
diffBoolean,
|
|
6
|
+
diffNumber,
|
|
7
|
+
diffObject,
|
|
8
|
+
diffString,
|
|
9
|
+
Differ,
|
|
10
|
+
} from "~/packages/anvl/src/tree/differ"
|
|
11
|
+
|
|
12
|
+
import { atom, atomFamily } from ".."
|
|
13
|
+
import { attachIntrospectionStates } from "../introspection"
|
|
14
|
+
import { lazyLocalStorageEffect } from "../web-effects"
|
|
15
|
+
|
|
1
16
|
export * from "./AtomIODevtools"
|
|
17
|
+
|
|
18
|
+
export const {
|
|
19
|
+
atomIndex,
|
|
20
|
+
selectorIndex,
|
|
21
|
+
transactionIndex,
|
|
22
|
+
findTransactionLogState,
|
|
23
|
+
timelineIndex,
|
|
24
|
+
findTimelineState,
|
|
25
|
+
} = attachIntrospectionStates()
|
|
26
|
+
|
|
27
|
+
export const devtoolsAreOpenState = atom<boolean>({
|
|
28
|
+
key: `👁🗨 Devtools Are Open`,
|
|
29
|
+
default: true,
|
|
30
|
+
effects: [lazyLocalStorageEffect(`👁🗨 Devtools Are Open`)],
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
type DevtoolsView = `atoms` | `selectors` | `timelines` | `transactions`
|
|
34
|
+
|
|
35
|
+
export const devtoolsViewSelectionState = atom<DevtoolsView>({
|
|
36
|
+
key: `👁🗨 Devtools View Selection`,
|
|
37
|
+
default: `atoms`,
|
|
38
|
+
effects: [lazyLocalStorageEffect(`👁🗨 Devtools View`)],
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
export const devtoolsViewOptionsState = atom<DevtoolsView[]>({
|
|
42
|
+
key: `👁🗨 Devtools View Options`,
|
|
43
|
+
default: [`atoms`, `selectors`, `transactions`, `timelines`],
|
|
44
|
+
effects: [lazyLocalStorageEffect(`👁🗨 Devtools View Options`)],
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
export const findViewIsOpenState = atomFamily<boolean, string>({
|
|
48
|
+
key: `👁🗨 Devtools View Is Open`,
|
|
49
|
+
default: false,
|
|
50
|
+
effects: (key) => [lazyLocalStorageEffect(key + `:view-is-open`)],
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
export const primitiveRefinery = new Refinery({
|
|
54
|
+
number: (input: unknown): input is number => typeof input === `number`,
|
|
55
|
+
string: (input: unknown): input is string => typeof input === `string`,
|
|
56
|
+
boolean: (input: unknown): input is boolean => typeof input === `boolean`,
|
|
57
|
+
null: (input: unknown): input is null => input === null,
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
export const jsonTreeRefinery = new Refinery({
|
|
61
|
+
object: isPlainObject,
|
|
62
|
+
array: (input: unknown): input is unknown[] => Array.isArray(input),
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
export const prettyJson = new Differ(primitiveRefinery, jsonTreeRefinery, {
|
|
66
|
+
number: diffNumber,
|
|
67
|
+
string: diffString,
|
|
68
|
+
boolean: diffBoolean,
|
|
69
|
+
null: () => ({ summary: `No Change` }),
|
|
70
|
+
object: diffObject,
|
|
71
|
+
array: diffArray,
|
|
72
|
+
})
|
|
@@ -151,7 +151,6 @@ export const composeExplorer = ({
|
|
|
151
151
|
const spaceLayout = useO(findSpaceLayoutNode(spaceId))
|
|
152
152
|
const viewIds = useO(findSpaceViewsState(spaceId))
|
|
153
153
|
const focusedViewId = useO(findSpaceFocusedViewState(spaceId))
|
|
154
|
-
console.log({ spaceLayout, viewIds, focusedViewId })
|
|
155
154
|
return (
|
|
156
155
|
<div className="spaces">
|
|
157
156
|
{spaceLayout.childSpaceIds.length === 0 ? (
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { isString } from "fp-ts/lib/string"
|
|
2
|
-
|
|
3
1
|
import { isArray } from "~/packages/anvl/src/array"
|
|
4
2
|
import { parseJson, stringifyJson } from "~/packages/anvl/src/json"
|
|
5
3
|
|
|
@@ -10,7 +8,9 @@ export const persistStringSetAtom = persistAtom<Set<string>>(localStorage)({
|
|
|
10
8
|
parse: (string) => {
|
|
11
9
|
try {
|
|
12
10
|
const json = parseJson(string)
|
|
13
|
-
const array = isArray(
|
|
11
|
+
const array = isArray((v): v is string => typeof v === `string`)(json)
|
|
12
|
+
? json
|
|
13
|
+
: []
|
|
14
14
|
return new Set(array)
|
|
15
15
|
} catch (thrown) {
|
|
16
16
|
console.error(`Error parsing spaceIndexState from localStorage`)
|
|
@@ -31,7 +31,7 @@ export const makeViewsPerSpaceState = (
|
|
|
31
31
|
): AtomToken<Join<null, `viewId`, `spaceId`>> =>
|
|
32
32
|
atom<Join<null, `viewId`, `spaceId`>>({
|
|
33
33
|
key: `${key}:views_per_space`,
|
|
34
|
-
default: new Join({ relationType: `1:n` }),
|
|
34
|
+
default: new Join({ relationType: `1:n` }).from(`viewId`).to(`spaceId`),
|
|
35
35
|
effects: [
|
|
36
36
|
persistAtom<Join<null, `viewId`, `spaceId`>>(localStorage)({
|
|
37
37
|
stringify: (index) => JSON.stringify(index.toJSON()),
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { isNumber } from "fp-ts/lib/number"
|
|
2
|
-
|
|
3
1
|
import { Join } from "~/packages/anvl/src/join"
|
|
4
2
|
import { parseJson, stringifyJson } from "~/packages/anvl/src/json"
|
|
5
3
|
import { hasExactProperties } from "~/packages/anvl/src/object"
|
|
@@ -23,7 +21,9 @@ export const makeSpaceLayoutState = (
|
|
|
23
21
|
): AtomToken<Join<{ size: number }, `parent`, `child`>> =>
|
|
24
22
|
atom({
|
|
25
23
|
key: `${key}:space_layout`,
|
|
26
|
-
default: new Join({ relationType: `1:n` })
|
|
24
|
+
default: new Join<{ size: number }>({ relationType: `1:n` })
|
|
25
|
+
.from(`parent`)
|
|
26
|
+
.to(`child`),
|
|
27
27
|
effects: [
|
|
28
28
|
persistAtom<Join<{ size: number }, `parent`, `child`>>(localStorage)({
|
|
29
29
|
stringify: (join) => stringifyJson(join.toJSON()),
|
|
@@ -31,7 +31,9 @@ export const makeSpaceLayoutState = (
|
|
|
31
31
|
try {
|
|
32
32
|
const json = parseJson(string)
|
|
33
33
|
const join = Join.fromJSON(json, {
|
|
34
|
-
isContent: hasExactProperties({
|
|
34
|
+
isContent: hasExactProperties({
|
|
35
|
+
size: (v): v is number => typeof v === `number`,
|
|
36
|
+
}),
|
|
35
37
|
from: `parent`,
|
|
36
38
|
to: `child`,
|
|
37
39
|
})
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { RenderResult } from '@testing-library/react';
|
|
2
|
-
import * as AtomIO from 'atom.io';
|
|
3
|
-
import * as React from 'react';
|
|
4
|
-
import * as SocketIO from 'socket.io';
|
|
5
|
-
|
|
6
|
-
type TestSetupOptions = {
|
|
7
|
-
server: (tools: {
|
|
8
|
-
socket: SocketIO.Socket;
|
|
9
|
-
silo: AtomIO.Silo;
|
|
10
|
-
}) => void;
|
|
11
|
-
};
|
|
12
|
-
type TestSetupOptions__SingleClient = TestSetupOptions & {
|
|
13
|
-
client: React.FC;
|
|
14
|
-
};
|
|
15
|
-
type TestSetupOptions__MultiClient<ClientNames extends string> = TestSetupOptions & {
|
|
16
|
-
clients: {
|
|
17
|
-
[K in ClientNames]: React.FC;
|
|
18
|
-
};
|
|
19
|
-
};
|
|
20
|
-
type RealtimeTestTools = {
|
|
21
|
-
name: string;
|
|
22
|
-
silo: AtomIO.Silo;
|
|
23
|
-
dispose: () => void;
|
|
24
|
-
};
|
|
25
|
-
type RealtimeTestClient = RealtimeTestTools & {
|
|
26
|
-
renderResult: RenderResult;
|
|
27
|
-
prettyPrint: () => void;
|
|
28
|
-
reconnect: () => void;
|
|
29
|
-
disconnect: () => void;
|
|
30
|
-
};
|
|
31
|
-
type RealtimeTestServer = RealtimeTestTools & {
|
|
32
|
-
port: number;
|
|
33
|
-
};
|
|
34
|
-
type RealtimeTestAPI = {
|
|
35
|
-
server: RealtimeTestServer;
|
|
36
|
-
teardown: () => void;
|
|
37
|
-
};
|
|
38
|
-
type RealtimeTestAPI__SingleClient = RealtimeTestAPI & {
|
|
39
|
-
client: RealtimeTestClient;
|
|
40
|
-
};
|
|
41
|
-
type RealtimeTestAPI__MultiClient<ClientNames extends string> = RealtimeTestAPI & {
|
|
42
|
-
clients: Record<ClientNames, RealtimeTestClient>;
|
|
43
|
-
};
|
|
44
|
-
declare const setupRealtimeTestServer: (options: TestSetupOptions) => RealtimeTestServer;
|
|
45
|
-
declare const setupRealtimeTestClient: (options: TestSetupOptions__SingleClient, name: string, port: number) => RealtimeTestClient;
|
|
46
|
-
declare const singleClient: (options: TestSetupOptions__SingleClient) => RealtimeTestAPI__SingleClient;
|
|
47
|
-
declare const multiClient: <ClientNames extends string>(options: TestSetupOptions__MultiClient<ClientNames>) => RealtimeTestAPI__MultiClient<ClientNames>;
|
|
48
|
-
|
|
49
|
-
export { RealtimeTestAPI, RealtimeTestAPI__MultiClient, RealtimeTestAPI__SingleClient, RealtimeTestClient, RealtimeTestServer, RealtimeTestTools, TestSetupOptions, TestSetupOptions__MultiClient, TestSetupOptions__SingleClient, multiClient, setupRealtimeTestClient, setupRealtimeTestServer, singleClient };
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { RenderResult } from '@testing-library/react';
|
|
2
|
-
import * as AtomIO from 'atom.io';
|
|
3
|
-
import * as React from 'react';
|
|
4
|
-
import * as SocketIO from 'socket.io';
|
|
5
|
-
|
|
6
|
-
type TestSetupOptions = {
|
|
7
|
-
server: (tools: {
|
|
8
|
-
socket: SocketIO.Socket;
|
|
9
|
-
silo: AtomIO.Silo;
|
|
10
|
-
}) => void;
|
|
11
|
-
};
|
|
12
|
-
type TestSetupOptions__SingleClient = TestSetupOptions & {
|
|
13
|
-
client: React.FC;
|
|
14
|
-
};
|
|
15
|
-
type TestSetupOptions__MultiClient<ClientNames extends string> = TestSetupOptions & {
|
|
16
|
-
clients: {
|
|
17
|
-
[K in ClientNames]: React.FC;
|
|
18
|
-
};
|
|
19
|
-
};
|
|
20
|
-
type RealtimeTestTools = {
|
|
21
|
-
name: string;
|
|
22
|
-
silo: AtomIO.Silo;
|
|
23
|
-
dispose: () => void;
|
|
24
|
-
};
|
|
25
|
-
type RealtimeTestClient = RealtimeTestTools & {
|
|
26
|
-
renderResult: RenderResult;
|
|
27
|
-
prettyPrint: () => void;
|
|
28
|
-
reconnect: () => void;
|
|
29
|
-
disconnect: () => void;
|
|
30
|
-
};
|
|
31
|
-
type RealtimeTestServer = RealtimeTestTools & {
|
|
32
|
-
port: number;
|
|
33
|
-
};
|
|
34
|
-
type RealtimeTestAPI = {
|
|
35
|
-
server: RealtimeTestServer;
|
|
36
|
-
teardown: () => void;
|
|
37
|
-
};
|
|
38
|
-
type RealtimeTestAPI__SingleClient = RealtimeTestAPI & {
|
|
39
|
-
client: RealtimeTestClient;
|
|
40
|
-
};
|
|
41
|
-
type RealtimeTestAPI__MultiClient<ClientNames extends string> = RealtimeTestAPI & {
|
|
42
|
-
clients: Record<ClientNames, RealtimeTestClient>;
|
|
43
|
-
};
|
|
44
|
-
declare const setupRealtimeTestServer: (options: TestSetupOptions) => RealtimeTestServer;
|
|
45
|
-
declare const setupRealtimeTestClient: (options: TestSetupOptions__SingleClient, name: string, port: number) => RealtimeTestClient;
|
|
46
|
-
declare const singleClient: (options: TestSetupOptions__SingleClient) => RealtimeTestAPI__SingleClient;
|
|
47
|
-
declare const multiClient: <ClientNames extends string>(options: TestSetupOptions__MultiClient<ClientNames>) => RealtimeTestAPI__MultiClient<ClientNames>;
|
|
48
|
-
|
|
49
|
-
export { RealtimeTestAPI, RealtimeTestAPI__MultiClient, RealtimeTestAPI__SingleClient, RealtimeTestClient, RealtimeTestServer, RealtimeTestTools, TestSetupOptions, TestSetupOptions__MultiClient, TestSetupOptions__SingleClient, multiClient, setupRealtimeTestClient, setupRealtimeTestServer, singleClient };
|