atom.io 0.6.8 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/README.md +21 -2
  2. package/dist/index.d.mts +42 -461
  3. package/dist/index.d.ts +42 -461
  4. package/dist/index.js +128 -1792
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +75 -1742
  7. package/dist/index.mjs.map +1 -1
  8. package/internal/dist/index.d.mts +342 -0
  9. package/internal/dist/index.d.ts +342 -0
  10. package/internal/dist/index.js +1873 -0
  11. package/internal/dist/index.js.map +1 -0
  12. package/internal/dist/index.mjs +1798 -0
  13. package/internal/dist/index.mjs.map +1 -0
  14. package/internal/package.json +15 -0
  15. package/internal/src/atom/create-atom.ts +75 -0
  16. package/internal/src/atom/delete-atom.ts +10 -0
  17. package/internal/src/atom/index.ts +3 -0
  18. package/{src/internal → internal/src/atom}/is-default.ts +4 -2
  19. package/internal/src/caching.ts +21 -0
  20. package/internal/src/families/create-atom-family.ts +59 -0
  21. package/internal/src/families/create-readonly-selector-family.ts +45 -0
  22. package/internal/src/families/create-selector-family.ts +67 -0
  23. package/internal/src/families/index.ts +3 -0
  24. package/internal/src/get-state-internal.ts +23 -0
  25. package/internal/src/index.ts +13 -0
  26. package/internal/src/mutable/create-mutable-atom-family.ts +25 -0
  27. package/internal/src/mutable/create-mutable-atom.ts +49 -0
  28. package/internal/src/mutable/get-json-token.ts +22 -0
  29. package/internal/src/mutable/get-update-token.ts +20 -0
  30. package/internal/src/mutable/index.ts +17 -0
  31. package/internal/src/mutable/is-atom-token-mutable.ts +7 -0
  32. package/internal/src/mutable/tracker-family.ts +61 -0
  33. package/internal/src/mutable/tracker.ts +164 -0
  34. package/internal/src/mutable/transceiver.ts +110 -0
  35. package/internal/src/operation.ts +68 -0
  36. package/{src/internal → internal/src}/selector/create-read-write-selector.ts +10 -13
  37. package/{src/internal → internal/src}/selector/create-readonly-selector.ts +9 -8
  38. package/internal/src/selector/create-selector.ts +65 -0
  39. package/{src/internal → internal/src}/selector/index.ts +1 -0
  40. package/internal/src/selector/lookup-selector-sources.ts +20 -0
  41. package/{src/internal → internal/src}/selector/register-selector.ts +13 -9
  42. package/{src/internal → internal/src}/selector/trace-selector-atoms.ts +4 -2
  43. package/{src/internal → internal/src}/selector/update-selector-atoms.ts +4 -3
  44. package/internal/src/set-state/become.ts +10 -0
  45. package/internal/src/set-state/copy-mutable-if-needed.ts +23 -0
  46. package/internal/src/set-state/copy-mutable-in-transaction.ts +59 -0
  47. package/internal/src/set-state/copy-mutable-into-new-store.ts +34 -0
  48. package/internal/src/set-state/emit-update.ts +23 -0
  49. package/internal/src/set-state/evict-downstream.ts +39 -0
  50. package/internal/src/set-state/index.ts +2 -0
  51. package/internal/src/set-state/set-atom-state.ts +38 -0
  52. package/internal/src/set-state/set-selector-state.ts +19 -0
  53. package/internal/src/set-state/set-state-internal.ts +18 -0
  54. package/internal/src/set-state/stow-update.ts +42 -0
  55. package/internal/src/store/deposit.ts +43 -0
  56. package/internal/src/store/index.ts +5 -0
  57. package/internal/src/store/lookup.ts +26 -0
  58. package/internal/src/store/store.ts +154 -0
  59. package/internal/src/store/withdraw-new-family-member.ts +53 -0
  60. package/internal/src/store/withdraw.ts +113 -0
  61. package/internal/src/subject.ts +21 -0
  62. package/internal/src/subscribe/index.ts +1 -0
  63. package/internal/src/subscribe/recall-state.ts +19 -0
  64. package/internal/src/subscribe/subscribe-to-root-atoms.ts +47 -0
  65. package/{src/internal → internal/src}/timeline/add-atom-to-timeline.ts +50 -29
  66. package/internal/src/timeline/index.ts +3 -0
  67. package/{src/internal → internal/src/timeline}/time-travel-internal.ts +6 -6
  68. package/{src/internal → internal/src/timeline}/timeline-internal.ts +20 -12
  69. package/{src/internal → internal/src}/transaction/abort-transaction.ts +1 -1
  70. package/{src/internal → internal/src}/transaction/apply-transaction.ts +25 -18
  71. package/{src/internal → internal/src}/transaction/build-transaction.ts +12 -6
  72. package/{src/internal → internal/src}/transaction/index.ts +3 -2
  73. package/{src/internal → internal/src}/transaction/redo-transaction.ts +4 -5
  74. package/{src/internal → internal/src/transaction}/transaction-internal.ts +16 -13
  75. package/{src/internal → internal/src}/transaction/undo-transaction.ts +4 -5
  76. package/introspection/dist/index.d.mts +12 -260
  77. package/introspection/dist/index.d.ts +12 -260
  78. package/introspection/dist/index.js +125 -140
  79. package/introspection/dist/index.js.map +1 -1
  80. package/introspection/dist/index.mjs +103 -116
  81. package/introspection/dist/index.mjs.map +1 -1
  82. package/{src/introspection → introspection/src}/attach-atom-index.ts +41 -30
  83. package/{src/introspection → introspection/src}/attach-introspection-states.ts +6 -10
  84. package/introspection/src/attach-selector-index.ts +90 -0
  85. package/{src/introspection → introspection/src}/attach-timeline-family.ts +16 -16
  86. package/introspection/src/attach-timeline-index.ts +38 -0
  87. package/introspection/src/attach-transaction-index.ts +40 -0
  88. package/{src/introspection → introspection/src}/attach-transaction-logs.ts +11 -8
  89. package/json/dist/index.d.mts +41 -2
  90. package/json/dist/index.d.ts +41 -2
  91. package/json/dist/index.js +88 -48
  92. package/json/dist/index.js.map +1 -1
  93. package/json/dist/index.mjs +76 -13
  94. package/json/dist/index.mjs.map +1 -1
  95. package/json/src/index.ts +5 -0
  96. package/json/src/select-json-family.ts +35 -0
  97. package/json/src/select-json.ts +22 -0
  98. package/package.json +105 -57
  99. package/react/dist/index.d.mts +9 -17
  100. package/react/dist/index.d.ts +9 -17
  101. package/react/dist/index.js +45 -77
  102. package/react/dist/index.js.map +1 -1
  103. package/react/dist/index.mjs +18 -34
  104. package/react/dist/index.mjs.map +1 -1
  105. package/react/src/store-context.tsx +12 -0
  106. package/react/src/store-hooks.ts +36 -0
  107. package/react-devtools/dist/index.css +1 -1
  108. package/react-devtools/dist/index.css.map +1 -1
  109. package/react-devtools/dist/index.d.mts +199 -230
  110. package/react-devtools/dist/index.d.ts +199 -230
  111. package/react-devtools/dist/index.js +610 -2466
  112. package/react-devtools/dist/index.js.map +1 -1
  113. package/react-devtools/dist/index.mjs +543 -2401
  114. package/react-devtools/dist/index.mjs.map +1 -1
  115. package/{src/react-devtools → react-devtools/src}/AtomIODevtools.tsx +5 -3
  116. package/{src/react-devtools → react-devtools/src}/Button.tsx +2 -3
  117. package/{src/react-devtools → react-devtools/src}/StateEditor.tsx +3 -2
  118. package/{src/react-devtools → react-devtools/src}/StateIndex.tsx +7 -4
  119. package/{src/react-devtools → react-devtools/src}/TimelineIndex.tsx +7 -11
  120. package/{src/react-devtools → react-devtools/src}/TransactionIndex.tsx +4 -4
  121. package/{src/react-devtools → react-devtools/src}/Updates.tsx +9 -4
  122. package/{src/react-devtools → react-devtools/src}/index.ts +5 -5
  123. package/realtime-react/dist/index.d.mts +9 -25
  124. package/realtime-react/dist/index.d.ts +9 -25
  125. package/realtime-react/dist/index.js +75 -193
  126. package/realtime-react/dist/index.js.map +1 -1
  127. package/realtime-react/dist/index.mjs +44 -148
  128. package/realtime-react/dist/index.mjs.map +1 -1
  129. package/realtime-react/src/index.ts +7 -0
  130. package/{src/realtime-react → realtime-react/src}/realtime-context.tsx +3 -4
  131. package/realtime-react/src/use-pull-family-member.ts +15 -0
  132. package/realtime-react/src/use-pull-mutable-family-member.ts +20 -0
  133. package/realtime-react/src/use-pull-mutable.ts +17 -0
  134. package/realtime-react/src/use-pull.ts +15 -0
  135. package/realtime-react/src/use-push.ts +19 -0
  136. package/realtime-react/src/use-server-action.ts +18 -0
  137. package/realtime-testing/dist/index.d.mts +49 -0
  138. package/realtime-testing/dist/index.d.ts +49 -0
  139. package/realtime-testing/dist/index.js +147 -0
  140. package/realtime-testing/dist/index.js.map +1 -0
  141. package/realtime-testing/dist/index.mjs +116 -0
  142. package/realtime-testing/dist/index.mjs.map +1 -0
  143. package/{src/realtime-testing → realtime-testing/src}/setup-realtime-test.tsx +10 -8
  144. package/src/atom.ts +64 -8
  145. package/src/index.ts +36 -29
  146. package/src/logger.ts +7 -7
  147. package/src/selector.ts +5 -5
  148. package/src/silo.ts +49 -43
  149. package/src/subscribe.ts +27 -22
  150. package/src/timeline.ts +9 -4
  151. package/src/transaction.ts +3 -4
  152. package/transceivers/set-rtx/dist/index.d.mts +39 -0
  153. package/transceivers/set-rtx/dist/index.d.ts +39 -0
  154. package/transceivers/set-rtx/dist/index.js +213 -0
  155. package/transceivers/set-rtx/dist/index.js.map +1 -0
  156. package/transceivers/set-rtx/dist/index.mjs +211 -0
  157. package/transceivers/set-rtx/dist/index.mjs.map +1 -0
  158. package/{realtime → transceivers/set-rtx}/package.json +1 -1
  159. package/transceivers/set-rtx/src/index.ts +1 -0
  160. package/transceivers/set-rtx/src/set-rtx.ts +242 -0
  161. package/realtime/dist/index.d.mts +0 -25
  162. package/realtime/dist/index.d.ts +0 -25
  163. package/realtime/dist/index.js +0 -190
  164. package/realtime/dist/index.js.map +0 -1
  165. package/realtime/dist/index.mjs +0 -151
  166. package/realtime/dist/index.mjs.map +0 -1
  167. package/src/internal/atom-internal.ts +0 -54
  168. package/src/internal/families-internal.ts +0 -144
  169. package/src/internal/get.ts +0 -129
  170. package/src/internal/index.ts +0 -15
  171. package/src/internal/operation.ts +0 -139
  172. package/src/internal/selector/lookup-selector-sources.ts +0 -16
  173. package/src/internal/selector-internal.ts +0 -58
  174. package/src/internal/set.ts +0 -99
  175. package/src/internal/store.ts +0 -151
  176. package/src/internal/subscribe-internal.ts +0 -88
  177. package/src/internal/timeline/index.ts +0 -1
  178. package/src/introspection/attach-selector-index.ts +0 -77
  179. package/src/introspection/attach-timeline-index.ts +0 -36
  180. package/src/introspection/attach-transaction-index.ts +0 -38
  181. package/src/json/index.ts +0 -1
  182. package/src/json/select-json.ts +0 -18
  183. package/src/react/store-context.tsx +0 -13
  184. package/src/react/store-hooks.ts +0 -47
  185. package/src/react-explorer/AtomIOExplorer.tsx +0 -218
  186. package/src/react-explorer/explorer-effects.ts +0 -20
  187. package/src/react-explorer/explorer-states.ts +0 -217
  188. package/src/react-explorer/index.ts +0 -23
  189. package/src/react-explorer/space-states.ts +0 -72
  190. package/src/react-explorer/view-states.ts +0 -41
  191. package/src/realtime/README.md +0 -33
  192. package/src/realtime/hook-composition/expose-family.ts +0 -101
  193. package/src/realtime/hook-composition/expose-single.ts +0 -38
  194. package/src/realtime/hook-composition/expose-timeline.ts +0 -60
  195. package/src/realtime/hook-composition/index.ts +0 -12
  196. package/src/realtime/hook-composition/receive-state.ts +0 -29
  197. package/src/realtime/hook-composition/receive-transaction.ts +0 -18
  198. package/src/realtime/index.ts +0 -1
  199. package/src/realtime-react/index.ts +0 -3
  200. package/src/realtime-react/realtime-hooks.ts +0 -39
  201. package/src/realtime-react/realtime-state.ts +0 -10
  202. package/src/realtime-react/use-pull-family-member.ts +0 -26
  203. package/src/realtime-react/use-pull-family.ts +0 -24
  204. package/src/realtime-react/use-pull.ts +0 -24
  205. package/src/realtime-react/use-push.ts +0 -27
  206. package/src/realtime-react/use-server-action.ts +0 -33
  207. package/src/tracker/index.ts +0 -3
  208. package/src/tracker/tracker.ts +0 -61
  209. package/src/web-effects/index.ts +0 -1
  210. package/src/web-effects/storage.ts +0 -30
  211. /package/{src/introspection → introspection/src}/index.ts +0 -0
  212. /package/{src/react → react/src}/index.ts +0 -0
  213. /package/{src/react-devtools → react-devtools/src}/devtools.scss +0 -0
  214. /package/{src/realtime-testing → realtime-testing/src}/index.ts +0 -0
package/src/subscribe.ts CHANGED
@@ -1,49 +1,54 @@
1
- import type { ƒn } from "~/packages/anvl/src/function"
1
+ import type { Store } from "atom.io/internal"
2
+ import { IMPLICIT, subscribeToRootAtoms, withdraw } from "atom.io/internal"
2
3
 
3
4
  import type {
5
+ FamilyMetadata,
4
6
  ReadonlySelectorToken,
5
7
  StateToken,
6
8
  TimelineToken,
7
9
  TimelineUpdate,
8
10
  TransactionToken,
9
11
  TransactionUpdate,
12
+ ƒn,
10
13
  } from "."
11
- import type { Store } from "./internal"
12
- import { IMPLICIT, subscribeToRootAtoms, withdraw } from "./internal"
13
14
 
14
15
  export type StateUpdate<T> = { newValue: T; oldValue: T }
15
- export type KeyedStateUpdate<T> = StateUpdate<T> & { key: string }
16
+ export type KeyedStateUpdate<T> = StateUpdate<T> & {
17
+ key: string
18
+ family?: FamilyMetadata
19
+ }
16
20
  export type UpdateHandler<T> = (update: StateUpdate<T>) => void
17
21
 
18
- export const subscribe = <T>(
22
+ export function subscribe<T>(
19
23
  token: ReadonlySelectorToken<T> | StateToken<T>,
20
24
  handleUpdate: UpdateHandler<T>,
25
+ key: string = Math.random().toString(36).slice(2),
21
26
  store: Store = IMPLICIT.STORE,
22
- ): (() => void) => {
27
+ ): () => void {
23
28
  const state = withdraw<T>(token, store)
24
29
  if (state === null) {
25
30
  throw new Error(
26
31
  `State "${token.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`,
27
32
  )
28
33
  }
29
- const subscription = state.subject.subscribe(handleUpdate)
30
- store.config.logger?.info(`👀 subscribe to "${state.key}"`)
31
- const dependencySubscriptions =
34
+ const unsubFunction = state.subject.subscribe(key, handleUpdate)
35
+ store.config.logger?.info(`👀 adding subscription "${key}" to "${state.key}"`)
36
+ const dependencyUnsubFunctions =
32
37
  state.type !== `atom` ? subscribeToRootAtoms(state, store) : null
33
38
 
34
39
  const unsubscribe =
35
- dependencySubscriptions === null
40
+ dependencyUnsubFunctions === null
36
41
  ? () => {
37
42
  store.config.logger?.info(`🙈 unsubscribe from "${state.key}"`)
38
- subscription.unsubscribe()
43
+ unsubFunction()
39
44
  }
40
45
  : () => {
41
46
  store.config.logger?.info(
42
47
  `🙈 unsubscribe from "${state.key}" and its dependencies`,
43
48
  )
44
- subscription.unsubscribe()
45
- for (const dependencySubscription of dependencySubscriptions) {
46
- dependencySubscription.unsubscribe()
49
+ unsubFunction()
50
+ for (const unsubFromDependency of dependencyUnsubFunctions) {
51
+ unsubFromDependency()
47
52
  }
48
53
  }
49
54
 
@@ -57,6 +62,7 @@ export type TransactionUpdateHandler<ƒ extends ƒn> = (
57
62
  export const subscribeToTransaction = <ƒ extends ƒn>(
58
63
  token: TransactionToken<ƒ>,
59
64
  handleUpdate: TransactionUpdateHandler<ƒ>,
65
+ key: string = Math.random().toString(36).slice(2),
60
66
  store = IMPLICIT.STORE,
61
67
  ): (() => void) => {
62
68
  const tx = withdraw(token, store)
@@ -66,17 +72,17 @@ export const subscribeToTransaction = <ƒ extends ƒn>(
66
72
  )
67
73
  }
68
74
  store.config.logger?.info(`👀 subscribe to transaction "${token.key}"`)
69
- const subscription = tx.subject.subscribe(handleUpdate)
70
- const unsubscribe = () => {
75
+ const unsubscribe = tx.subject.subscribe(key, handleUpdate)
76
+ return () => {
71
77
  store.config.logger?.info(`🙈 unsubscribe from transaction "${token.key}"`)
72
- subscription.unsubscribe()
78
+ unsubscribe()
73
79
  }
74
- return unsubscribe
75
80
  }
76
81
 
77
82
  export const subscribeToTimeline = (
78
83
  token: TimelineToken,
79
84
  handleUpdate: (update: TimelineUpdate | `redo` | `undo`) => void,
85
+ key: string = Math.random().toString(36).slice(2),
80
86
  store = IMPLICIT.STORE,
81
87
  ): (() => void) => {
82
88
  const tl = withdraw(token, store)
@@ -86,10 +92,9 @@ export const subscribeToTimeline = (
86
92
  )
87
93
  }
88
94
  store.config.logger?.info(`👀 subscribe to timeline "${token.key}"`)
89
- const subscription = tl.subject.subscribe(handleUpdate)
90
- const unsubscribe = () => {
95
+ const unsubscribe = tl.subject.subscribe(key, handleUpdate)
96
+ return () => {
91
97
  store.config.logger?.info(`🙈 unsubscribe from timeline "${token.key}"`)
92
- subscription.unsubscribe()
98
+ unsubscribe()
93
99
  }
94
- return unsubscribe
95
100
  }
package/src/timeline.ts CHANGED
@@ -1,11 +1,16 @@
1
- import type { AtomFamily, AtomToken } from "."
2
1
  import type {
3
2
  TimelineAtomUpdate,
4
3
  TimelineSelectorUpdate,
5
4
  TimelineTransactionUpdate,
6
- } from "./internal"
7
- import { IMPLICIT } from "./internal"
8
- import { redo__INTERNAL, timeline__INTERNAL, undo__INTERNAL } from "./internal/"
5
+ } from "atom.io/internal"
6
+ import {
7
+ IMPLICIT,
8
+ redo__INTERNAL,
9
+ timeline__INTERNAL,
10
+ undo__INTERNAL,
11
+ } from "atom.io/internal"
12
+
13
+ import type { AtomFamily, AtomToken } from "."
9
14
 
10
15
  export type TimelineToken = {
11
16
  key: string
@@ -1,8 +1,7 @@
1
- import type { ƒn } from "~/packages/anvl/src/function"
1
+ import type { Store } from "atom.io/internal"
2
+ import { IMPLICIT, transaction__INTERNAL, withdraw } from "atom.io/internal"
2
3
 
3
- import type { KeyedStateUpdate, ReadonlySelectorToken, StateToken } from "."
4
- import type { Store } from "./internal"
5
- import { IMPLICIT, transaction__INTERNAL, withdraw } from "./internal"
4
+ import type { KeyedStateUpdate, ReadonlySelectorToken, StateToken, ƒn } from "."
6
5
 
7
6
  export type TransactionToken<_> = {
8
7
  key: string
@@ -0,0 +1,39 @@
1
+ import { Transceiver, TransceiverMode, Subject } from 'atom.io/internal';
2
+ import { primitive, Json } from 'atom.io/json';
3
+
4
+ type SetUpdate = `add:${string}` | `clear:${string}` | `del:${string}` | `tx:${string}`;
5
+ type NumberedSetUpdate = `${number}=${SetUpdate}`;
6
+ interface SetRTXJson<P extends primitive> extends Json.Object {
7
+ members: P[];
8
+ cache: (NumberedSetUpdate | null)[];
9
+ cacheLimit: number;
10
+ cacheIdx: number;
11
+ cacheUpdateNumber: number;
12
+ }
13
+ declare class SetRTX<P extends primitive> extends Set<P> implements Transceiver<NumberedSetUpdate> {
14
+ mode: TransceiverMode;
15
+ readonly subject: Subject<SetUpdate>;
16
+ cacheLimit: number;
17
+ cache: (NumberedSetUpdate | null)[];
18
+ cacheIdx: number;
19
+ cacheUpdateNumber: number;
20
+ constructor(values?: Set<P> | readonly P[] | null, cacheLimit?: number);
21
+ toJSON(): SetRTXJson<P>;
22
+ static fromJSON<P extends primitive>(json: SetRTXJson<P>): SetRTX<P>;
23
+ add(value: P): this;
24
+ clear(): void;
25
+ delete(value: P): boolean;
26
+ readonly parent: SetRTX<P> | null;
27
+ child: SetRTX<P> | null;
28
+ transactionUpdates: SetUpdate[] | null;
29
+ transaction(run: (child: SetRTX<P>) => boolean): void;
30
+ protected _subscribe(key: string, fn: (update: SetUpdate) => void): () => void;
31
+ subscribe(key: string, fn: (update: NumberedSetUpdate) => void): () => void;
32
+ emit(update: SetUpdate): void;
33
+ private doStep;
34
+ do(update: NumberedSetUpdate): number | `OUT_OF_RANGE` | null;
35
+ undoStep(update: SetUpdate): void;
36
+ undo(update: NumberedSetUpdate): number | null;
37
+ }
38
+
39
+ export { NumberedSetUpdate, SetRTX, SetRTXJson, SetUpdate };
@@ -0,0 +1,39 @@
1
+ import { Transceiver, TransceiverMode, Subject } from 'atom.io/internal';
2
+ import { primitive, Json } from 'atom.io/json';
3
+
4
+ type SetUpdate = `add:${string}` | `clear:${string}` | `del:${string}` | `tx:${string}`;
5
+ type NumberedSetUpdate = `${number}=${SetUpdate}`;
6
+ interface SetRTXJson<P extends primitive> extends Json.Object {
7
+ members: P[];
8
+ cache: (NumberedSetUpdate | null)[];
9
+ cacheLimit: number;
10
+ cacheIdx: number;
11
+ cacheUpdateNumber: number;
12
+ }
13
+ declare class SetRTX<P extends primitive> extends Set<P> implements Transceiver<NumberedSetUpdate> {
14
+ mode: TransceiverMode;
15
+ readonly subject: Subject<SetUpdate>;
16
+ cacheLimit: number;
17
+ cache: (NumberedSetUpdate | null)[];
18
+ cacheIdx: number;
19
+ cacheUpdateNumber: number;
20
+ constructor(values?: Set<P> | readonly P[] | null, cacheLimit?: number);
21
+ toJSON(): SetRTXJson<P>;
22
+ static fromJSON<P extends primitive>(json: SetRTXJson<P>): SetRTX<P>;
23
+ add(value: P): this;
24
+ clear(): void;
25
+ delete(value: P): boolean;
26
+ readonly parent: SetRTX<P> | null;
27
+ child: SetRTX<P> | null;
28
+ transactionUpdates: SetUpdate[] | null;
29
+ transaction(run: (child: SetRTX<P>) => boolean): void;
30
+ protected _subscribe(key: string, fn: (update: SetUpdate) => void): () => void;
31
+ subscribe(key: string, fn: (update: NumberedSetUpdate) => void): () => void;
32
+ emit(update: SetUpdate): void;
33
+ private doStep;
34
+ do(update: NumberedSetUpdate): number | `OUT_OF_RANGE` | null;
35
+ undoStep(update: SetUpdate): void;
36
+ undo(update: NumberedSetUpdate): number | null;
37
+ }
38
+
39
+ export { NumberedSetUpdate, SetRTX, SetRTXJson, SetUpdate };
@@ -0,0 +1,213 @@
1
+ 'use strict';
2
+
3
+ var internal = require('atom.io/internal');
4
+ var json = require('atom.io/json');
5
+
6
+ // src/set-rtx.ts
7
+ var SetRTX = class _SetRTX extends Set {
8
+ constructor(values, cacheLimit = 0) {
9
+ super(values);
10
+ this.mode = `record`;
11
+ this.subject = new internal.Subject();
12
+ this.cacheLimit = 0;
13
+ this.cache = [];
14
+ this.cacheIdx = -1;
15
+ this.cacheUpdateNumber = -1;
16
+ this.child = null;
17
+ this.transactionUpdates = null;
18
+ if (values instanceof _SetRTX) {
19
+ this.parent = values;
20
+ this.cacheUpdateNumber = values.cacheUpdateNumber;
21
+ }
22
+ if (cacheLimit) {
23
+ this.cacheLimit = cacheLimit;
24
+ this.cache = new Array(cacheLimit);
25
+ this.subscribe(`auto cache`, (update) => {
26
+ this.cacheIdx++;
27
+ this.cacheIdx %= this.cacheLimit;
28
+ this.cache[this.cacheIdx] = update;
29
+ });
30
+ }
31
+ }
32
+ toJSON() {
33
+ return {
34
+ members: [...this],
35
+ cache: this.cache,
36
+ cacheLimit: this.cacheLimit,
37
+ cacheIdx: this.cacheIdx,
38
+ cacheUpdateNumber: this.cacheUpdateNumber
39
+ };
40
+ }
41
+ static fromJSON(json) {
42
+ const set = new _SetRTX(json.members, json.cacheLimit);
43
+ set.cache = json.cache;
44
+ set.cacheIdx = json.cacheIdx;
45
+ set.cacheUpdateNumber = json.cacheUpdateNumber;
46
+ return set;
47
+ }
48
+ add(value) {
49
+ if (this.mode === `record`) {
50
+ this.cacheUpdateNumber++;
51
+ this.emit(`add:${json.stringifyJson(value)}`);
52
+ }
53
+ return super.add(value);
54
+ }
55
+ clear() {
56
+ if (this.mode === `record`) {
57
+ this.cacheUpdateNumber++;
58
+ this.emit(`clear:${JSON.stringify([...this])}`);
59
+ }
60
+ super.clear();
61
+ }
62
+ delete(value) {
63
+ if (this.mode === `record`) {
64
+ this.cacheUpdateNumber++;
65
+ this.emit(`del:${json.stringifyJson(value)}`);
66
+ }
67
+ return super.delete(value);
68
+ }
69
+ transaction(run) {
70
+ this.mode = `transaction`;
71
+ this.transactionUpdates = [];
72
+ this.child = new _SetRTX(this);
73
+ const unsubscribe = this.child._subscribe(`transaction`, (update) => {
74
+ var _a;
75
+ (_a = this.transactionUpdates) == null ? void 0 : _a.push(update);
76
+ });
77
+ try {
78
+ const shouldCommit = run(this.child);
79
+ if (shouldCommit) {
80
+ this.cacheUpdateNumber++;
81
+ this.emit(`tx:${this.transactionUpdates.join(`;`)}`);
82
+ for (const update of this.transactionUpdates) {
83
+ this.doStep(update);
84
+ }
85
+ }
86
+ } catch (thrown) {
87
+ console.error(`Failed to apply transaction: ${thrown}`);
88
+ } finally {
89
+ unsubscribe();
90
+ this.child = null;
91
+ this.transactionUpdates = null;
92
+ this.mode = `record`;
93
+ }
94
+ }
95
+ _subscribe(key, fn) {
96
+ return this.subject.subscribe(key, fn);
97
+ }
98
+ subscribe(key, fn) {
99
+ return this.subject.subscribe(
100
+ key,
101
+ (update) => fn(`${this.cacheUpdateNumber}=${update}`)
102
+ );
103
+ }
104
+ emit(update) {
105
+ this.subject.next(update);
106
+ }
107
+ doStep(update) {
108
+ const typeValueBreak = update.indexOf(`:`);
109
+ const type = update.substring(0, typeValueBreak);
110
+ const value = update.substring(typeValueBreak + 1);
111
+ switch (type) {
112
+ case `add`:
113
+ this.add(json.parseJson(value));
114
+ break;
115
+ case `clear`:
116
+ this.clear();
117
+ break;
118
+ case `del`:
119
+ this.delete(json.parseJson(value));
120
+ break;
121
+ case `tx`:
122
+ for (const update2 of value.split(`;`)) {
123
+ this.doStep(update2);
124
+ }
125
+ }
126
+ }
127
+ do(update) {
128
+ const breakpoint = update.indexOf(`=`);
129
+ const updateNumber = Number(update.substring(0, breakpoint));
130
+ const eventOffset = updateNumber - this.cacheUpdateNumber;
131
+ const isFuture = eventOffset > 0;
132
+ if (isFuture) {
133
+ if (eventOffset === 1) {
134
+ this.mode = `playback`;
135
+ const innerUpdate = update.substring(breakpoint + 1);
136
+ this.doStep(innerUpdate);
137
+ this.mode = `record`;
138
+ this.cacheUpdateNumber = updateNumber;
139
+ return null;
140
+ }
141
+ return this.cacheUpdateNumber + 1;
142
+ } else {
143
+ if (Math.abs(eventOffset) < this.cacheLimit) {
144
+ const eventIdx = this.cacheIdx + eventOffset;
145
+ const cachedUpdate = this.cache[eventIdx];
146
+ if (cachedUpdate === update) {
147
+ return null;
148
+ }
149
+ this.mode = `playback`;
150
+ let done = false;
151
+ while (!done) {
152
+ this.cacheIdx %= this.cacheLimit;
153
+ const update2 = this.cache[this.cacheIdx];
154
+ this.cacheIdx--;
155
+ if (!update2) {
156
+ return `OUT_OF_RANGE`;
157
+ }
158
+ this.undo(update2);
159
+ done = this.cacheIdx === eventIdx - 1;
160
+ }
161
+ const innerUpdate = update.substring(breakpoint + 1);
162
+ this.doStep(innerUpdate);
163
+ this.mode = `record`;
164
+ this.cacheUpdateNumber = updateNumber;
165
+ return null;
166
+ } else {
167
+ return `OUT_OF_RANGE`;
168
+ }
169
+ }
170
+ }
171
+ undoStep(update) {
172
+ const breakpoint = update.indexOf(`:`);
173
+ const type = update.substring(0, breakpoint);
174
+ const value = update.substring(breakpoint + 1);
175
+ switch (type) {
176
+ case `add`:
177
+ this.delete(json.parseJson(value));
178
+ break;
179
+ case `del`:
180
+ this.add(json.parseJson(value));
181
+ break;
182
+ case `clear`: {
183
+ const values = JSON.parse(value);
184
+ for (const value2 of values)
185
+ this.add(value2);
186
+ break;
187
+ }
188
+ case `tx`: {
189
+ const updates = value.split(`;`);
190
+ for (let i = updates.length - 1; i >= 0; i--) {
191
+ this.undoStep(updates[i]);
192
+ }
193
+ }
194
+ }
195
+ }
196
+ undo(update) {
197
+ const breakpoint = update.indexOf(`=`);
198
+ const updateNumber = Number(update.substring(0, breakpoint));
199
+ if (updateNumber === this.cacheUpdateNumber) {
200
+ this.mode = `playback`;
201
+ const innerUpdate = update.substring(breakpoint + 1);
202
+ this.undoStep(innerUpdate);
203
+ this.mode = `record`;
204
+ this.cacheUpdateNumber--;
205
+ return null;
206
+ }
207
+ return this.cacheUpdateNumber;
208
+ }
209
+ };
210
+
211
+ exports.SetRTX = SetRTX;
212
+ //# sourceMappingURL=out.js.map
213
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/set-rtx.ts"],"names":["update","value"],"mappings":"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","sourcesContent":["import type { Transceiver, TransceiverMode } from \"atom.io/internal\"\nimport { Subject } from \"atom.io/internal\"\nimport type { Json, Stringified, primitive } from \"atom.io/json\"\nimport { parseJson, stringifyJson } from \"atom.io/json\"\n\nexport type SetUpdate =\n\t| `add:${string}`\n\t| `clear:${string}`\n\t| `del:${string}`\n\t| `tx:${string}`\nexport type NumberedSetUpdate = `${number}=${SetUpdate}`\n\nexport interface SetRTXJson<P extends primitive> extends Json.Object {\n\tmembers: P[]\n\tcache: (NumberedSetUpdate | null)[]\n\tcacheLimit: number\n\tcacheIdx: number\n\tcacheUpdateNumber: number\n}\nexport class SetRTX<P extends primitive>\n\textends Set<P>\n\timplements Transceiver<NumberedSetUpdate>\n{\n\tpublic mode: TransceiverMode = `record`\n\tpublic readonly subject = new Subject<SetUpdate>()\n\tpublic cacheLimit = 0\n\tpublic cache: (NumberedSetUpdate | null)[] = []\n\tpublic cacheIdx = -1\n\tpublic cacheUpdateNumber = -1\n\n\tpublic constructor(values?: Set<P> | readonly P[] | null, cacheLimit = 0) {\n\t\tsuper(values)\n\t\tif (values instanceof SetRTX) {\n\t\t\tthis.parent = values\n\t\t\tthis.cacheUpdateNumber = values.cacheUpdateNumber\n\t\t}\n\t\tif (cacheLimit) {\n\t\t\tthis.cacheLimit = cacheLimit\n\t\t\tthis.cache = new Array(cacheLimit)\n\t\t\tthis.subscribe(`auto cache`, (update) => {\n\t\t\t\tthis.cacheIdx++\n\t\t\t\tthis.cacheIdx %= this.cacheLimit\n\t\t\t\tthis.cache[this.cacheIdx] = update\n\t\t\t})\n\t\t}\n\t}\n\n\tpublic toJSON(): SetRTXJson<P> {\n\t\treturn {\n\t\t\tmembers: [...this],\n\t\t\tcache: this.cache,\n\t\t\tcacheLimit: this.cacheLimit,\n\t\t\tcacheIdx: this.cacheIdx,\n\t\t\tcacheUpdateNumber: this.cacheUpdateNumber,\n\t\t}\n\t}\n\n\tpublic static fromJSON<P extends primitive>(json: SetRTXJson<P>): SetRTX<P> {\n\t\tconst set = new SetRTX<P>(json.members, json.cacheLimit)\n\t\tset.cache = json.cache\n\t\tset.cacheIdx = json.cacheIdx\n\t\tset.cacheUpdateNumber = json.cacheUpdateNumber\n\t\treturn set\n\t}\n\n\tpublic add(value: P): this {\n\t\tif (this.mode === `record`) {\n\t\t\tthis.cacheUpdateNumber++\n\t\t\tthis.emit(`add:${stringifyJson<P>(value)}`)\n\t\t}\n\t\treturn super.add(value)\n\t}\n\n\tpublic clear(): void {\n\t\tif (this.mode === `record`) {\n\t\t\tthis.cacheUpdateNumber++\n\t\t\tthis.emit(`clear:${JSON.stringify([...this])}`)\n\t\t}\n\t\tsuper.clear()\n\t}\n\n\tpublic delete(value: P): boolean {\n\t\tif (this.mode === `record`) {\n\t\t\tthis.cacheUpdateNumber++\n\t\t\tthis.emit(`del:${stringifyJson<P>(value)}`)\n\t\t}\n\t\treturn super.delete(value)\n\t}\n\n\tpublic readonly parent: SetRTX<P> | null\n\tpublic child: SetRTX<P> | null = null\n\tpublic transactionUpdates: SetUpdate[] | null = null\n\tpublic transaction(run: (child: SetRTX<P>) => boolean): void {\n\t\tthis.mode = `transaction`\n\t\tthis.transactionUpdates = []\n\t\tthis.child = new SetRTX(this)\n\t\tconst unsubscribe = this.child._subscribe(`transaction`, (update) => {\n\t\t\tthis.transactionUpdates?.push(update)\n\t\t})\n\t\ttry {\n\t\t\tconst shouldCommit = run(this.child)\n\t\t\tif (shouldCommit) {\n\t\t\t\tthis.cacheUpdateNumber++\n\t\t\t\tthis.emit(`tx:${this.transactionUpdates.join(`;`)}`)\n\t\t\t\tfor (const update of this.transactionUpdates) {\n\t\t\t\t\tthis.doStep(update)\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (thrown) {\n\t\t\tconsole.error(`Failed to apply transaction: ${thrown}`)\n\t\t} finally {\n\t\t\tunsubscribe()\n\t\t\tthis.child = null\n\t\t\tthis.transactionUpdates = null\n\t\t\tthis.mode = `record`\n\t\t}\n\t}\n\n\tprotected _subscribe(\n\t\tkey: string,\n\t\tfn: (update: SetUpdate) => void,\n\t): () => void {\n\t\treturn this.subject.subscribe(key, fn)\n\t}\n\tpublic subscribe(\n\t\tkey: string,\n\t\tfn: (update: NumberedSetUpdate) => void,\n\t): () => void {\n\t\treturn this.subject.subscribe(key, (update) =>\n\t\t\tfn(`${this.cacheUpdateNumber}=${update}`),\n\t\t)\n\t}\n\n\tpublic emit(update: SetUpdate): void {\n\t\tthis.subject.next(update)\n\t}\n\n\tprivate doStep(update: SetUpdate): void {\n\t\tconst typeValueBreak = update.indexOf(`:`)\n\t\tconst type = update.substring(0, typeValueBreak)\n\t\tconst value = update.substring(typeValueBreak + 1)\n\t\tswitch (type) {\n\t\t\tcase `add`:\n\t\t\t\tthis.add(parseJson(value as Stringified<P>))\n\t\t\t\tbreak\n\t\t\tcase `clear`:\n\t\t\t\tthis.clear()\n\t\t\t\tbreak\n\t\t\tcase `del`:\n\t\t\t\tthis.delete(parseJson(value as Stringified<P>))\n\t\t\t\tbreak\n\t\t\tcase `tx`:\n\t\t\t\tfor (const update of value.split(`;`)) {\n\t\t\t\t\tthis.doStep(update as SetUpdate)\n\t\t\t\t}\n\t\t}\n\t}\n\n\tpublic do(update: NumberedSetUpdate): number | `OUT_OF_RANGE` | null {\n\t\tconst breakpoint = update.indexOf(`=`)\n\t\tconst updateNumber = Number(update.substring(0, breakpoint))\n\t\tconst eventOffset = updateNumber - this.cacheUpdateNumber\n\t\tconst isFuture = eventOffset > 0\n\t\tif (isFuture) {\n\t\t\tif (eventOffset === 1) {\n\t\t\t\tthis.mode = `playback`\n\t\t\t\tconst innerUpdate = update.substring(breakpoint + 1) as SetUpdate\n\t\t\t\tthis.doStep(innerUpdate)\n\t\t\t\tthis.mode = `record`\n\t\t\t\tthis.cacheUpdateNumber = updateNumber\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn this.cacheUpdateNumber + 1\n\t\t} else {\n\t\t\tif (Math.abs(eventOffset) < this.cacheLimit) {\n\t\t\t\tconst eventIdx = this.cacheIdx + eventOffset\n\t\t\t\tconst cachedUpdate = this.cache[eventIdx]\n\t\t\t\tif (cachedUpdate === update) {\n\t\t\t\t\treturn null\n\t\t\t\t}\n\t\t\t\tthis.mode = `playback`\n\t\t\t\tlet done = false\n\t\t\t\twhile (!done) {\n\t\t\t\t\tthis.cacheIdx %= this.cacheLimit\n\t\t\t\t\tconst update = this.cache[this.cacheIdx]\n\t\t\t\t\tthis.cacheIdx--\n\t\t\t\t\tif (!update) {\n\t\t\t\t\t\treturn `OUT_OF_RANGE`\n\t\t\t\t\t}\n\t\t\t\t\tconst undoRes = this.undo(update)\n\t\t\t\t\tdone = this.cacheIdx === eventIdx - 1\n\t\t\t\t}\n\t\t\t\tconst innerUpdate = update.substring(breakpoint + 1) as SetUpdate\n\t\t\t\tthis.doStep(innerUpdate)\n\t\t\t\tthis.mode = `record`\n\t\t\t\tthis.cacheUpdateNumber = updateNumber\n\t\t\t\treturn null\n\t\t\t} else {\n\t\t\t\treturn `OUT_OF_RANGE`\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic undoStep(update: SetUpdate): void {\n\t\tconst breakpoint = update.indexOf(`:`)\n\t\tconst type = update.substring(0, breakpoint)\n\t\tconst value = update.substring(breakpoint + 1)\n\t\tswitch (type) {\n\t\t\tcase `add`:\n\t\t\t\tthis.delete(parseJson(value as Stringified<P>))\n\t\t\t\tbreak\n\t\t\tcase `del`:\n\t\t\t\tthis.add(parseJson(value as Stringified<P>))\n\t\t\t\tbreak\n\t\t\tcase `clear`: {\n\t\t\t\tconst values = JSON.parse(value) as P[]\n\t\t\t\tfor (const value of values) this.add(value)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase `tx`: {\n\t\t\t\tconst updates = value.split(`;`) as SetUpdate[]\n\t\t\t\tfor (let i = updates.length - 1; i >= 0; i--) {\n\t\t\t\t\tthis.undoStep(updates[i])\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic undo(update: NumberedSetUpdate): number | null {\n\t\tconst breakpoint = update.indexOf(`=`)\n\t\tconst updateNumber = Number(update.substring(0, breakpoint))\n\t\tif (updateNumber === this.cacheUpdateNumber) {\n\t\t\tthis.mode = `playback`\n\t\t\tconst innerUpdate = update.substring(breakpoint + 1) as SetUpdate\n\t\t\tthis.undoStep(innerUpdate)\n\t\t\tthis.mode = `record`\n\t\t\tthis.cacheUpdateNumber--\n\t\t\treturn null\n\t\t}\n\t\treturn this.cacheUpdateNumber\n\t}\n}\n"]}
@@ -0,0 +1,211 @@
1
+ import { Subject } from 'atom.io/internal';
2
+ import { stringifyJson, parseJson } from 'atom.io/json';
3
+
4
+ // src/set-rtx.ts
5
+ var SetRTX = class _SetRTX extends Set {
6
+ constructor(values, cacheLimit = 0) {
7
+ super(values);
8
+ this.mode = `record`;
9
+ this.subject = new Subject();
10
+ this.cacheLimit = 0;
11
+ this.cache = [];
12
+ this.cacheIdx = -1;
13
+ this.cacheUpdateNumber = -1;
14
+ this.child = null;
15
+ this.transactionUpdates = null;
16
+ if (values instanceof _SetRTX) {
17
+ this.parent = values;
18
+ this.cacheUpdateNumber = values.cacheUpdateNumber;
19
+ }
20
+ if (cacheLimit) {
21
+ this.cacheLimit = cacheLimit;
22
+ this.cache = new Array(cacheLimit);
23
+ this.subscribe(`auto cache`, (update) => {
24
+ this.cacheIdx++;
25
+ this.cacheIdx %= this.cacheLimit;
26
+ this.cache[this.cacheIdx] = update;
27
+ });
28
+ }
29
+ }
30
+ toJSON() {
31
+ return {
32
+ members: [...this],
33
+ cache: this.cache,
34
+ cacheLimit: this.cacheLimit,
35
+ cacheIdx: this.cacheIdx,
36
+ cacheUpdateNumber: this.cacheUpdateNumber
37
+ };
38
+ }
39
+ static fromJSON(json) {
40
+ const set = new _SetRTX(json.members, json.cacheLimit);
41
+ set.cache = json.cache;
42
+ set.cacheIdx = json.cacheIdx;
43
+ set.cacheUpdateNumber = json.cacheUpdateNumber;
44
+ return set;
45
+ }
46
+ add(value) {
47
+ if (this.mode === `record`) {
48
+ this.cacheUpdateNumber++;
49
+ this.emit(`add:${stringifyJson(value)}`);
50
+ }
51
+ return super.add(value);
52
+ }
53
+ clear() {
54
+ if (this.mode === `record`) {
55
+ this.cacheUpdateNumber++;
56
+ this.emit(`clear:${JSON.stringify([...this])}`);
57
+ }
58
+ super.clear();
59
+ }
60
+ delete(value) {
61
+ if (this.mode === `record`) {
62
+ this.cacheUpdateNumber++;
63
+ this.emit(`del:${stringifyJson(value)}`);
64
+ }
65
+ return super.delete(value);
66
+ }
67
+ transaction(run) {
68
+ this.mode = `transaction`;
69
+ this.transactionUpdates = [];
70
+ this.child = new _SetRTX(this);
71
+ const unsubscribe = this.child._subscribe(`transaction`, (update) => {
72
+ var _a;
73
+ (_a = this.transactionUpdates) == null ? void 0 : _a.push(update);
74
+ });
75
+ try {
76
+ const shouldCommit = run(this.child);
77
+ if (shouldCommit) {
78
+ this.cacheUpdateNumber++;
79
+ this.emit(`tx:${this.transactionUpdates.join(`;`)}`);
80
+ for (const update of this.transactionUpdates) {
81
+ this.doStep(update);
82
+ }
83
+ }
84
+ } catch (thrown) {
85
+ console.error(`Failed to apply transaction: ${thrown}`);
86
+ } finally {
87
+ unsubscribe();
88
+ this.child = null;
89
+ this.transactionUpdates = null;
90
+ this.mode = `record`;
91
+ }
92
+ }
93
+ _subscribe(key, fn) {
94
+ return this.subject.subscribe(key, fn);
95
+ }
96
+ subscribe(key, fn) {
97
+ return this.subject.subscribe(
98
+ key,
99
+ (update) => fn(`${this.cacheUpdateNumber}=${update}`)
100
+ );
101
+ }
102
+ emit(update) {
103
+ this.subject.next(update);
104
+ }
105
+ doStep(update) {
106
+ const typeValueBreak = update.indexOf(`:`);
107
+ const type = update.substring(0, typeValueBreak);
108
+ const value = update.substring(typeValueBreak + 1);
109
+ switch (type) {
110
+ case `add`:
111
+ this.add(parseJson(value));
112
+ break;
113
+ case `clear`:
114
+ this.clear();
115
+ break;
116
+ case `del`:
117
+ this.delete(parseJson(value));
118
+ break;
119
+ case `tx`:
120
+ for (const update2 of value.split(`;`)) {
121
+ this.doStep(update2);
122
+ }
123
+ }
124
+ }
125
+ do(update) {
126
+ const breakpoint = update.indexOf(`=`);
127
+ const updateNumber = Number(update.substring(0, breakpoint));
128
+ const eventOffset = updateNumber - this.cacheUpdateNumber;
129
+ const isFuture = eventOffset > 0;
130
+ if (isFuture) {
131
+ if (eventOffset === 1) {
132
+ this.mode = `playback`;
133
+ const innerUpdate = update.substring(breakpoint + 1);
134
+ this.doStep(innerUpdate);
135
+ this.mode = `record`;
136
+ this.cacheUpdateNumber = updateNumber;
137
+ return null;
138
+ }
139
+ return this.cacheUpdateNumber + 1;
140
+ } else {
141
+ if (Math.abs(eventOffset) < this.cacheLimit) {
142
+ const eventIdx = this.cacheIdx + eventOffset;
143
+ const cachedUpdate = this.cache[eventIdx];
144
+ if (cachedUpdate === update) {
145
+ return null;
146
+ }
147
+ this.mode = `playback`;
148
+ let done = false;
149
+ while (!done) {
150
+ this.cacheIdx %= this.cacheLimit;
151
+ const update2 = this.cache[this.cacheIdx];
152
+ this.cacheIdx--;
153
+ if (!update2) {
154
+ return `OUT_OF_RANGE`;
155
+ }
156
+ this.undo(update2);
157
+ done = this.cacheIdx === eventIdx - 1;
158
+ }
159
+ const innerUpdate = update.substring(breakpoint + 1);
160
+ this.doStep(innerUpdate);
161
+ this.mode = `record`;
162
+ this.cacheUpdateNumber = updateNumber;
163
+ return null;
164
+ } else {
165
+ return `OUT_OF_RANGE`;
166
+ }
167
+ }
168
+ }
169
+ undoStep(update) {
170
+ const breakpoint = update.indexOf(`:`);
171
+ const type = update.substring(0, breakpoint);
172
+ const value = update.substring(breakpoint + 1);
173
+ switch (type) {
174
+ case `add`:
175
+ this.delete(parseJson(value));
176
+ break;
177
+ case `del`:
178
+ this.add(parseJson(value));
179
+ break;
180
+ case `clear`: {
181
+ const values = JSON.parse(value);
182
+ for (const value2 of values)
183
+ this.add(value2);
184
+ break;
185
+ }
186
+ case `tx`: {
187
+ const updates = value.split(`;`);
188
+ for (let i = updates.length - 1; i >= 0; i--) {
189
+ this.undoStep(updates[i]);
190
+ }
191
+ }
192
+ }
193
+ }
194
+ undo(update) {
195
+ const breakpoint = update.indexOf(`=`);
196
+ const updateNumber = Number(update.substring(0, breakpoint));
197
+ if (updateNumber === this.cacheUpdateNumber) {
198
+ this.mode = `playback`;
199
+ const innerUpdate = update.substring(breakpoint + 1);
200
+ this.undoStep(innerUpdate);
201
+ this.mode = `record`;
202
+ this.cacheUpdateNumber--;
203
+ return null;
204
+ }
205
+ return this.cacheUpdateNumber;
206
+ }
207
+ };
208
+
209
+ export { SetRTX };
210
+ //# sourceMappingURL=out.js.map
211
+ //# sourceMappingURL=index.mjs.map