atom.io 0.40.8 → 0.40.10
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/dist/{chunk-Cl8Af3a2.js → chunk-CTAAG5j7.js} +3 -1
- package/dist/eslint-plugin/index.js +2 -3
- package/dist/eslint-plugin/index.js.map +1 -1
- package/dist/internal/index.d.ts +4 -3
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +1129 -3
- package/dist/internal/index.js.map +1 -1
- package/dist/react-devtools/index.js.map +1 -1
- package/dist/realtime/index.d.ts +29 -5
- package/dist/realtime/index.d.ts.map +1 -1
- package/dist/realtime/index.js +46 -3
- package/dist/realtime/index.js.map +1 -1
- package/dist/realtime-client/index.d.ts +1 -2
- package/dist/realtime-client/index.d.ts.map +1 -1
- package/dist/realtime-client/index.js +1 -2
- package/dist/realtime-client/index.js.map +1 -1
- package/dist/realtime-react/index.d.ts +4 -4
- package/dist/realtime-react/index.d.ts.map +1 -1
- package/dist/realtime-react/index.js +1 -2
- package/dist/realtime-react/index.js.map +1 -1
- package/dist/realtime-server/index.d.ts +5 -16
- package/dist/realtime-server/index.d.ts.map +1 -1
- package/dist/realtime-server/index.js +6 -10
- package/dist/realtime-server/index.js.map +1 -1
- package/dist/realtime-testing/index.d.ts +2 -2
- package/dist/realtime-testing/index.d.ts.map +1 -1
- package/dist/realtime-testing/index.js +2 -2
- package/dist/realtime-testing/index.js.map +1 -1
- package/dist/transceivers/o-list/index.d.ts +77 -0
- package/dist/transceivers/o-list/index.d.ts.map +1 -0
- package/dist/transceivers/o-list/index.js +308 -0
- package/dist/transceivers/o-list/index.js.map +1 -0
- package/dist/transceivers/set-rtx/index.d.ts +1 -1
- package/dist/transceivers/set-rtx/index.d.ts.map +1 -1
- package/dist/transceivers/set-rtx/index.js +2 -2
- package/dist/transceivers/set-rtx/index.js.map +1 -1
- package/dist/transceivers/u-list/index.d.ts +29 -0
- package/dist/transceivers/u-list/index.d.ts.map +1 -0
- package/dist/transceivers/u-list/index.js +87 -0
- package/dist/transceivers/u-list/index.js.map +1 -0
- package/package.json +14 -6
- package/src/internal/mutable/tracker.ts +21 -21
- package/src/internal/mutable/transceiver.ts +4 -4
- package/src/internal/set-state/index.ts +1 -0
- package/src/{realtime-server → realtime}/employ-socket.ts +2 -2
- package/src/realtime/index.ts +2 -0
- package/src/realtime/shared-room-store.ts +12 -11
- package/src/realtime-client/continuity/register-and-attempt-confirmed-update.ts +1 -1
- package/src/realtime-client/push-state.ts +1 -2
- package/src/realtime-react/use-single-effect.ts +1 -1
- package/src/realtime-server/continuity/continuity-store.ts +1 -1
- package/src/realtime-server/continuity/provide-outcomes.ts +2 -2
- package/src/realtime-server/continuity/provide-perspectives.ts +1 -2
- package/src/realtime-server/continuity/provide-startup-payloads.ts +3 -3
- package/src/realtime-server/continuity/receive-action-requests.ts +2 -4
- package/src/realtime-server/continuity/track-acknowledgements.ts +2 -3
- package/src/realtime-server/index.ts +0 -1
- package/src/realtime-server/ipc-sockets/custom-socket.ts +1 -2
- package/src/realtime-server/ipc-sockets/parent-socket.ts +2 -4
- package/src/realtime-server/realtime-family-provider.ts +1 -1
- package/src/realtime-server/realtime-mutable-family-provider.ts +1 -1
- package/src/realtime-server/realtime-mutable-provider.ts +1 -1
- package/src/realtime-server/realtime-server-stores/server-room-external-store.ts +2 -2
- package/src/realtime-server/realtime-server-stores/server-user-store.ts +8 -9
- package/src/realtime-server/realtime-state-provider.ts +1 -1
- package/src/realtime-server/realtime-state-receiver.ts +3 -6
- package/src/realtime-server/server-config.ts +1 -2
- package/src/realtime-testing/setup-realtime-test.tsx +3 -4
- package/src/transceivers/o-list/index.ts +1 -0
- package/src/transceivers/o-list/o-list.ts +412 -0
- package/src/transceivers/set-rtx/set-rtx.ts +3 -3
- package/src/transceivers/u-list/index.ts +1 -0
- package/src/transceivers/u-list/u-list.ts +123 -0
- package/dist/employ-socket-D6wgByWh.js +0 -12
- package/dist/employ-socket-D6wgByWh.js.map +0 -1
- package/dist/has-role-CMlaUlaf.js +0 -1133
- package/dist/has-role-CMlaUlaf.js.map +0 -1
- package/dist/is-fn-DY1wZ-md.js +0 -10
- package/dist/is-fn-DY1wZ-md.js.map +0 -1
- package/dist/mutex-store-CSvxY9i3.js +0 -11
- package/dist/mutex-store-CSvxY9i3.js.map +0 -1
- package/dist/shared-room-store-BfW3nWif.js +0 -31
- package/dist/shared-room-store-BfW3nWif.js.map +0 -1
- package/dist/shared-room-store-D2o4ZLjC.d.ts +0 -15
- package/dist/shared-room-store-D2o4ZLjC.d.ts.map +0 -1
- /package/src/{realtime-server → realtime}/socket-interface.ts +0 -0
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
import type { Fn, Transceiver, TransceiverMode } from "atom.io/internal"
|
|
2
|
+
import { Subject } from "atom.io/internal"
|
|
3
|
+
import type { primitive } from "atom.io/json"
|
|
4
|
+
|
|
5
|
+
type ArrayMutations = Exclude<keyof Array<any>, keyof ReadonlyArray<any>>
|
|
6
|
+
export type ArrayUpdate<P extends primitive> =
|
|
7
|
+
| {
|
|
8
|
+
type: `copyWithin`
|
|
9
|
+
target: number
|
|
10
|
+
start: number
|
|
11
|
+
end?: number
|
|
12
|
+
prev: readonly P[]
|
|
13
|
+
}
|
|
14
|
+
| {
|
|
15
|
+
type: `extend`
|
|
16
|
+
next: number
|
|
17
|
+
prev: number
|
|
18
|
+
}
|
|
19
|
+
| {
|
|
20
|
+
type: `fill`
|
|
21
|
+
value: P
|
|
22
|
+
start?: number
|
|
23
|
+
end?: number
|
|
24
|
+
prev: readonly P[]
|
|
25
|
+
}
|
|
26
|
+
| {
|
|
27
|
+
type: `pop` | `shift`
|
|
28
|
+
value?: P
|
|
29
|
+
}
|
|
30
|
+
| {
|
|
31
|
+
type: `push` | `unshift`
|
|
32
|
+
items: readonly P[]
|
|
33
|
+
}
|
|
34
|
+
| {
|
|
35
|
+
type: `reverse`
|
|
36
|
+
}
|
|
37
|
+
| {
|
|
38
|
+
type: `set`
|
|
39
|
+
next: P
|
|
40
|
+
prev?: P
|
|
41
|
+
index: number
|
|
42
|
+
}
|
|
43
|
+
| {
|
|
44
|
+
type: `sort`
|
|
45
|
+
next: readonly P[]
|
|
46
|
+
prev: readonly P[]
|
|
47
|
+
}
|
|
48
|
+
| {
|
|
49
|
+
type: `splice`
|
|
50
|
+
start: number
|
|
51
|
+
deleteCount?: number
|
|
52
|
+
items?: readonly P[]
|
|
53
|
+
deleted?: readonly P[]
|
|
54
|
+
}
|
|
55
|
+
| {
|
|
56
|
+
type: `truncate`
|
|
57
|
+
length: number
|
|
58
|
+
items: readonly P[]
|
|
59
|
+
}
|
|
60
|
+
export type OListUpdateType = ArrayUpdate<any>[`type`]
|
|
61
|
+
true satisfies ArrayMutations extends OListUpdateType
|
|
62
|
+
? true
|
|
63
|
+
: Exclude<ArrayMutations, OListUpdateType>
|
|
64
|
+
|
|
65
|
+
export type ArrayMutationHandler = {
|
|
66
|
+
[K in Exclude<OListUpdateType, `extend` | `set` | `truncate`>]: Fn
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export class OList<P extends primitive>
|
|
70
|
+
extends Array<P>
|
|
71
|
+
implements
|
|
72
|
+
Transceiver<ReadonlyArray<P>, ArrayUpdate<P>, ReadonlyArray<P>>,
|
|
73
|
+
ArrayMutationHandler
|
|
74
|
+
{
|
|
75
|
+
public mode: TransceiverMode = `record`
|
|
76
|
+
public readonly subject: Subject<ArrayUpdate<P>> = new Subject<
|
|
77
|
+
ArrayUpdate<P>
|
|
78
|
+
>()
|
|
79
|
+
|
|
80
|
+
public readonly READONLY_VIEW: ReadonlyArray<P> = this
|
|
81
|
+
|
|
82
|
+
public constructor(arrayLength?: number)
|
|
83
|
+
public constructor(...items: P[])
|
|
84
|
+
public constructor(...items: P[]) {
|
|
85
|
+
super(...items)
|
|
86
|
+
// biome-ignore lint/correctness/noConstructorReturn: this is chill
|
|
87
|
+
return new Proxy(this, {
|
|
88
|
+
set: (target, prop, value, receiver) => {
|
|
89
|
+
if (
|
|
90
|
+
typeof prop === `string` &&
|
|
91
|
+
!Number.isNaN(Number.parseInt(prop, 10))
|
|
92
|
+
) {
|
|
93
|
+
const index = Number(prop)
|
|
94
|
+
let prev: P | undefined
|
|
95
|
+
if (this.mode === `record`) {
|
|
96
|
+
prev = target[index]
|
|
97
|
+
}
|
|
98
|
+
target[index] = value
|
|
99
|
+
if (prev) {
|
|
100
|
+
this.emit({ type: `set`, index, next: value, prev })
|
|
101
|
+
} else if (this.mode === `record`) {
|
|
102
|
+
this.emit({ type: `set`, index, next: value })
|
|
103
|
+
}
|
|
104
|
+
return true
|
|
105
|
+
}
|
|
106
|
+
if (prop === `length`) {
|
|
107
|
+
if (this.mode === `record`) {
|
|
108
|
+
const prevLength = target.length
|
|
109
|
+
if (prevLength === value) return true
|
|
110
|
+
if (prevLength > value) {
|
|
111
|
+
const dropped = target.slice(value)
|
|
112
|
+
target.length = value
|
|
113
|
+
this.emit({ type: `truncate`, length: value, items: dropped })
|
|
114
|
+
} else {
|
|
115
|
+
target.length = value
|
|
116
|
+
this.emit({ type: `extend`, next: value, prev: prevLength })
|
|
117
|
+
}
|
|
118
|
+
} else {
|
|
119
|
+
target.length = value
|
|
120
|
+
}
|
|
121
|
+
return true
|
|
122
|
+
}
|
|
123
|
+
return Reflect.set(target, prop, value, receiver)
|
|
124
|
+
},
|
|
125
|
+
})
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
public toJSON(): ReadonlyArray<P> {
|
|
129
|
+
return [...this]
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
public static fromJSON<P extends primitive>(json: ReadonlyArray<P>): OList<P> {
|
|
133
|
+
return new OList<P>(...json)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
public push(...items: P[]): number {
|
|
137
|
+
let result: number
|
|
138
|
+
if (this.mode === `record`) {
|
|
139
|
+
this.mode = `playback`
|
|
140
|
+
result = super.push(...items)
|
|
141
|
+
this.mode = `record`
|
|
142
|
+
this.emit({ type: `push`, items })
|
|
143
|
+
} else {
|
|
144
|
+
result = super.push(...items)
|
|
145
|
+
}
|
|
146
|
+
return result
|
|
147
|
+
}
|
|
148
|
+
public pop(): P | undefined {
|
|
149
|
+
let value: P | undefined
|
|
150
|
+
if (this.mode === `record`) {
|
|
151
|
+
this.mode = `playback`
|
|
152
|
+
value = super.pop()
|
|
153
|
+
if (value === undefined) {
|
|
154
|
+
this.emit({ type: `pop` })
|
|
155
|
+
} else {
|
|
156
|
+
this.emit({ type: `pop`, value })
|
|
157
|
+
}
|
|
158
|
+
this.mode = `record`
|
|
159
|
+
} else {
|
|
160
|
+
value = super.pop()
|
|
161
|
+
}
|
|
162
|
+
return value
|
|
163
|
+
}
|
|
164
|
+
public shift(): P | undefined {
|
|
165
|
+
let value: P | undefined
|
|
166
|
+
if (this.mode === `record`) {
|
|
167
|
+
this.mode = `playback`
|
|
168
|
+
value = super.shift()
|
|
169
|
+
if (value === undefined) {
|
|
170
|
+
this.emit({ type: `shift` })
|
|
171
|
+
} else {
|
|
172
|
+
this.emit({ type: `shift`, value })
|
|
173
|
+
}
|
|
174
|
+
this.mode = `record`
|
|
175
|
+
} else {
|
|
176
|
+
value = super.shift()
|
|
177
|
+
}
|
|
178
|
+
return value
|
|
179
|
+
}
|
|
180
|
+
public unshift(...items: P[]): number {
|
|
181
|
+
let result: number
|
|
182
|
+
if (this.mode === `record`) {
|
|
183
|
+
this.mode = `playback`
|
|
184
|
+
result = super.unshift(...items)
|
|
185
|
+
this.emit({ type: `unshift`, items })
|
|
186
|
+
this.mode = `record`
|
|
187
|
+
} else {
|
|
188
|
+
result = super.unshift(...items)
|
|
189
|
+
}
|
|
190
|
+
return result
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
public reverse(): this {
|
|
194
|
+
super.reverse()
|
|
195
|
+
if (this.mode === `record`) {
|
|
196
|
+
this.emit({ type: `reverse` })
|
|
197
|
+
}
|
|
198
|
+
return this
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
public sort(compareFn?: (a: P, b: P) => number): this {
|
|
202
|
+
if (this.mode === `record`) {
|
|
203
|
+
this.mode = `playback`
|
|
204
|
+
const prev = [...this]
|
|
205
|
+
super.sort(compareFn)
|
|
206
|
+
const next = [...this]
|
|
207
|
+
this.emit({ type: `sort`, next, prev })
|
|
208
|
+
this.mode = `record`
|
|
209
|
+
}
|
|
210
|
+
return this
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
public splice(start: number, deleteCount?: number): P[]
|
|
214
|
+
public splice(start: number, deleteCount: number, ...items: P[]): P[]
|
|
215
|
+
public splice(
|
|
216
|
+
...params: [start: number, deleteCount?: number, ...items: P[]]
|
|
217
|
+
): P[] {
|
|
218
|
+
const [start, deleteCount, ...items] = params
|
|
219
|
+
const originalMode = this.mode
|
|
220
|
+
if (originalMode === `record`) this.mode = `playback`
|
|
221
|
+
const deleted = super.splice(...(params as [number, number, ...P[]]))
|
|
222
|
+
if (originalMode === `record`) this.mode = `record`
|
|
223
|
+
if (deleteCount === undefined) {
|
|
224
|
+
this.emit({
|
|
225
|
+
type: `splice`,
|
|
226
|
+
start,
|
|
227
|
+
items,
|
|
228
|
+
deleted,
|
|
229
|
+
deleteCount: deleted.length,
|
|
230
|
+
})
|
|
231
|
+
} else {
|
|
232
|
+
this.emit({ type: `splice`, start, items, deleted, deleteCount })
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return deleted
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
public copyWithin(target: number, start: number, end?: number): this {
|
|
239
|
+
const originalMode = this.mode
|
|
240
|
+
let prev: P[] | undefined
|
|
241
|
+
if (originalMode === `record`) {
|
|
242
|
+
prev = this.slice(target)
|
|
243
|
+
this.mode = `playback`
|
|
244
|
+
}
|
|
245
|
+
super.copyWithin(target, start, end)
|
|
246
|
+
if (originalMode === `record`) this.mode = `record`
|
|
247
|
+
if (prev) {
|
|
248
|
+
if (end === undefined) {
|
|
249
|
+
this.emit({ type: `copyWithin`, prev, target, start })
|
|
250
|
+
} else {
|
|
251
|
+
this.emit({ type: `copyWithin`, prev, target, start, end })
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return this
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
public subscribe(
|
|
258
|
+
key: string,
|
|
259
|
+
fn: (update: ArrayUpdate<P>) => void,
|
|
260
|
+
): () => void {
|
|
261
|
+
return this.subject.subscribe(key, fn)
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
public emit(update: ArrayUpdate<P>): void {
|
|
265
|
+
this.subject.next(update)
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
private doStep(update: ArrayUpdate<P>): void {
|
|
269
|
+
const type = update.type
|
|
270
|
+
switch (type) {
|
|
271
|
+
case `copyWithin`:
|
|
272
|
+
this.copyWithin(update.target, update.start, update.end)
|
|
273
|
+
break
|
|
274
|
+
case `extend`:
|
|
275
|
+
this.length = update.next
|
|
276
|
+
break
|
|
277
|
+
case `fill`:
|
|
278
|
+
this.fill(update.value, update.start, update.end)
|
|
279
|
+
break
|
|
280
|
+
case `pop`:
|
|
281
|
+
this.pop()
|
|
282
|
+
break
|
|
283
|
+
case `push`:
|
|
284
|
+
this.push(...update.items)
|
|
285
|
+
break
|
|
286
|
+
case `reverse`:
|
|
287
|
+
this.reverse()
|
|
288
|
+
break
|
|
289
|
+
case `shift`:
|
|
290
|
+
this.shift()
|
|
291
|
+
break
|
|
292
|
+
case `sort`:
|
|
293
|
+
for (let i = 0; i < update.next.length; i++) {
|
|
294
|
+
this[i] = update.next[i]
|
|
295
|
+
}
|
|
296
|
+
this.length = update.next.length
|
|
297
|
+
break
|
|
298
|
+
case `splice`:
|
|
299
|
+
if (update.deleteCount !== undefined && update.items) {
|
|
300
|
+
this.splice(update.start, update.deleteCount, ...update.items)
|
|
301
|
+
} else {
|
|
302
|
+
this.splice(update.start)
|
|
303
|
+
}
|
|
304
|
+
break
|
|
305
|
+
case `truncate`:
|
|
306
|
+
this.length = update.length
|
|
307
|
+
break
|
|
308
|
+
case `set`:
|
|
309
|
+
this[update.index] = update.next
|
|
310
|
+
break
|
|
311
|
+
case `unshift`:
|
|
312
|
+
this.unshift(...update.items)
|
|
313
|
+
break
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
public do(update: ArrayUpdate<P>): null {
|
|
318
|
+
this.mode = `playback`
|
|
319
|
+
this.doStep(update)
|
|
320
|
+
this.mode = `record`
|
|
321
|
+
return null
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
public undoStep(update: ArrayUpdate<P>): void {
|
|
325
|
+
switch (update.type) {
|
|
326
|
+
case `copyWithin`:
|
|
327
|
+
for (let i = 0; i < update.prev.length; i++) {
|
|
328
|
+
this[i + update.target] = update.prev[i]
|
|
329
|
+
}
|
|
330
|
+
break
|
|
331
|
+
case `extend`:
|
|
332
|
+
this.length = update.prev
|
|
333
|
+
break
|
|
334
|
+
case `fill`:
|
|
335
|
+
{
|
|
336
|
+
const start = update.start ?? 0
|
|
337
|
+
for (let i = 0; i < update.prev.length; i++) {
|
|
338
|
+
this[i + start] = update.prev[i]
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
break
|
|
342
|
+
case `pop`:
|
|
343
|
+
if (update.value) this.push(update.value)
|
|
344
|
+
break
|
|
345
|
+
case `push`:
|
|
346
|
+
{
|
|
347
|
+
let i = update.items.length - 1
|
|
348
|
+
while (i >= 0) {
|
|
349
|
+
this.pop()
|
|
350
|
+
--i
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
break
|
|
354
|
+
case `reverse`:
|
|
355
|
+
this.reverse()
|
|
356
|
+
break
|
|
357
|
+
case `shift`:
|
|
358
|
+
if (update.value) this.unshift(update.value)
|
|
359
|
+
break
|
|
360
|
+
case `sort`:
|
|
361
|
+
for (let i = 0; i < update.prev.length; i++) {
|
|
362
|
+
this[i] = update.prev[i]
|
|
363
|
+
}
|
|
364
|
+
this.length = update.prev.length
|
|
365
|
+
break
|
|
366
|
+
case `set`:
|
|
367
|
+
if (update.prev) {
|
|
368
|
+
this[update.index] = update.prev
|
|
369
|
+
} else {
|
|
370
|
+
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
|
371
|
+
delete this[update.index]
|
|
372
|
+
const firstEmptyIndex = this.findIndex(
|
|
373
|
+
(_, i) => !Object.hasOwn(this, i),
|
|
374
|
+
)
|
|
375
|
+
if (firstEmptyIndex !== -1) {
|
|
376
|
+
this.length = firstEmptyIndex
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
break
|
|
380
|
+
case `splice`:
|
|
381
|
+
if (update.deleted) {
|
|
382
|
+
if (update.items) {
|
|
383
|
+
this.splice(update.start, update.items.length, ...update.deleted)
|
|
384
|
+
} else {
|
|
385
|
+
this.splice(update.start, 0, ...update.deleted)
|
|
386
|
+
}
|
|
387
|
+
} else if (update.items) {
|
|
388
|
+
this.splice(update.start, update.items.length)
|
|
389
|
+
}
|
|
390
|
+
break
|
|
391
|
+
case `truncate`:
|
|
392
|
+
this.push(...update.items)
|
|
393
|
+
break
|
|
394
|
+
case `unshift`:
|
|
395
|
+
{
|
|
396
|
+
let i = update.items.length - 1
|
|
397
|
+
while (i >= 0) {
|
|
398
|
+
this.shift()
|
|
399
|
+
--i
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
break
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
public undo(update: ArrayUpdate<P>): number | null {
|
|
407
|
+
this.mode = `playback`
|
|
408
|
+
this.undoStep(update)
|
|
409
|
+
this.mode = `record`
|
|
410
|
+
return null
|
|
411
|
+
}
|
|
412
|
+
}
|
|
@@ -5,7 +5,7 @@ import { stringifyJson } from "atom.io/json"
|
|
|
5
5
|
|
|
6
6
|
export type SetUpdateType = `add` | `clear` | `del` | `tx`
|
|
7
7
|
export type SetUpdate = `${SetUpdateType}:${string}`
|
|
8
|
-
export type NumberedSetUpdate = `${number}=${SetUpdate}`
|
|
8
|
+
export type NumberedSetUpdate = `${number | `*`}=${SetUpdate}`
|
|
9
9
|
|
|
10
10
|
export interface SetRTXView<P extends primitive> extends ReadonlySet<P> {
|
|
11
11
|
readonly cache: ReadonlyArray<NumberedSetUpdate | null>
|
|
@@ -182,8 +182,8 @@ export class SetRTX<P extends primitive>
|
|
|
182
182
|
const updateNumber = Number(update.substring(0, breakpoint))
|
|
183
183
|
const eventOffset = updateNumber - this.cacheUpdateNumber
|
|
184
184
|
const isFuture = eventOffset > 0
|
|
185
|
-
if (isFuture) {
|
|
186
|
-
if (eventOffset === 1) {
|
|
185
|
+
if (isFuture || Number.isNaN(eventOffset)) {
|
|
186
|
+
if (eventOffset === 1 || Number.isNaN(eventOffset)) {
|
|
187
187
|
this.mode = `playback`
|
|
188
188
|
const innerUpdate = update.substring(breakpoint + 1) as SetUpdate
|
|
189
189
|
this.doStep(innerUpdate)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./u-list"
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import type { Transceiver, TransceiverMode } from "atom.io/internal"
|
|
2
|
+
import { Subject } from "atom.io/internal"
|
|
3
|
+
import type { Json, primitive, stringified } from "atom.io/json"
|
|
4
|
+
import { stringifyJson } from "atom.io/json"
|
|
5
|
+
|
|
6
|
+
export type UListUpdateType = `add` | `clear` | `del`
|
|
7
|
+
export type UListUpdate<P extends primitive> =
|
|
8
|
+
| `${`add` | `del`}:${stringified<P>}`
|
|
9
|
+
| `clear:${stringified<P[]>}`
|
|
10
|
+
|
|
11
|
+
export interface UListJson<P extends primitive> extends Json.Object {
|
|
12
|
+
members: P[]
|
|
13
|
+
}
|
|
14
|
+
export class UList<P extends primitive>
|
|
15
|
+
extends Set<P>
|
|
16
|
+
implements Transceiver<ReadonlySet<P>, UListUpdate<P>, UListJson<P>>
|
|
17
|
+
{
|
|
18
|
+
public mode: TransceiverMode = `record`
|
|
19
|
+
public readonly subject: Subject<UListUpdate<P>> = new Subject<
|
|
20
|
+
UListUpdate<P>
|
|
21
|
+
>()
|
|
22
|
+
|
|
23
|
+
public constructor(values?: Iterable<P>) {
|
|
24
|
+
super(values)
|
|
25
|
+
if (values instanceof UList) {
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public readonly READONLY_VIEW: ReadonlySet<P> = this
|
|
30
|
+
|
|
31
|
+
public toJSON(): UListJson<P> {
|
|
32
|
+
return {
|
|
33
|
+
members: [...this],
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public static fromJSON<P extends primitive>(json: UListJson<P>): UList<P> {
|
|
38
|
+
return new UList<P>(json.members)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public add(value: P): this {
|
|
42
|
+
const result = super.add(value)
|
|
43
|
+
if (this.mode === `record`) {
|
|
44
|
+
this.emit(`add:${stringifyJson<P>(value)}`)
|
|
45
|
+
}
|
|
46
|
+
return result
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public clear(): void {
|
|
50
|
+
const capturedContents = this.mode === `record` ? [...this] : null
|
|
51
|
+
super.clear()
|
|
52
|
+
if (capturedContents) {
|
|
53
|
+
this.emit(`clear:${stringifyJson(capturedContents)}`)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
public delete(value: P): boolean {
|
|
58
|
+
const result = super.delete(value)
|
|
59
|
+
if (this.mode === `record`) {
|
|
60
|
+
this.emit(`del:${stringifyJson<P>(value)}`)
|
|
61
|
+
}
|
|
62
|
+
return result
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
public subscribe(
|
|
66
|
+
key: string,
|
|
67
|
+
fn: (update: UListUpdate<P>) => void,
|
|
68
|
+
): () => void {
|
|
69
|
+
return this.subject.subscribe(key, fn)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
public emit(update: UListUpdate<P>): void {
|
|
73
|
+
this.subject.next(update)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private doStep(update: UListUpdate<P>): void {
|
|
77
|
+
const typeValueBreak = update.indexOf(`:`)
|
|
78
|
+
const type = update.substring(0, typeValueBreak) as UListUpdateType
|
|
79
|
+
const value = update.substring(typeValueBreak + 1)
|
|
80
|
+
switch (type) {
|
|
81
|
+
case `add`:
|
|
82
|
+
this.add(JSON.parse(value))
|
|
83
|
+
break
|
|
84
|
+
case `del`:
|
|
85
|
+
this.delete(JSON.parse(value))
|
|
86
|
+
break
|
|
87
|
+
case `clear`:
|
|
88
|
+
this.clear()
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
public do(update: UListUpdate<P>): null {
|
|
93
|
+
this.mode = `playback`
|
|
94
|
+
this.doStep(update)
|
|
95
|
+
this.mode = `record`
|
|
96
|
+
return null
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public undoStep(update: UListUpdate<P>): void {
|
|
100
|
+
const breakpoint = update.indexOf(`:`)
|
|
101
|
+
const type = update.substring(0, breakpoint) as UListUpdateType
|
|
102
|
+
const value = update.substring(breakpoint + 1)
|
|
103
|
+
switch (type) {
|
|
104
|
+
case `add`:
|
|
105
|
+
this.delete(JSON.parse(value))
|
|
106
|
+
break
|
|
107
|
+
case `del`:
|
|
108
|
+
this.add(JSON.parse(value))
|
|
109
|
+
break
|
|
110
|
+
case `clear`: {
|
|
111
|
+
const values = JSON.parse(value) as P[]
|
|
112
|
+
for (const v of values) this.add(v)
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
public undo(update: UListUpdate<P>): number | null {
|
|
118
|
+
this.mode = `playback`
|
|
119
|
+
this.undoStep(update)
|
|
120
|
+
this.mode = `record`
|
|
121
|
+
return null
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
//#region src/realtime-server/employ-socket.ts
|
|
2
|
-
function employSocket(socket, event, handleEvent) {
|
|
3
|
-
socket.on(event, handleEvent);
|
|
4
|
-
const retireSocket = () => {
|
|
5
|
-
socket.off(event, handleEvent);
|
|
6
|
-
};
|
|
7
|
-
return retireSocket;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
//#endregion
|
|
11
|
-
export { employSocket };
|
|
12
|
-
//# sourceMappingURL=employ-socket-D6wgByWh.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"employ-socket-D6wgByWh.js","names":[],"sources":["../src/realtime-server/employ-socket.ts"],"sourcesContent":["import type { Events } from \"./ipc-sockets\"\nimport type { Socket } from \"./socket-interface\"\n\nexport function employSocket<I extends Events, K extends string & keyof I>(\n\tsocket: Socket,\n\tevent: K,\n\thandleEvent: (...data: I[K]) => void,\n): () => void {\n\tsocket.on(event, handleEvent)\n\tconst retireSocket = () => {\n\t\tsocket.off(event, handleEvent)\n\t}\n\treturn retireSocket\n}\n"],"mappings":";AAGA,SAAgB,aACf,QACA,OACA,aACa;AACb,QAAO,GAAG,OAAO,YAAY;CAC7B,MAAM,qBAAqB;AAC1B,SAAO,IAAI,OAAO,YAAY;;AAE/B,QAAO"}
|