atom.io 0.6.9 → 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.
- package/README.md +21 -2
- package/dist/index.d.mts +34 -421
- package/dist/index.d.ts +34 -421
- package/dist/index.js +248 -23
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +209 -4
- package/dist/index.mjs.map +1 -1
- package/internal/dist/index.d.mts +342 -0
- package/internal/dist/index.d.ts +342 -0
- package/internal/dist/index.js +1873 -0
- package/internal/dist/index.js.map +1 -0
- package/internal/dist/index.mjs +1798 -0
- package/internal/dist/index.mjs.map +1 -0
- package/internal/package.json +15 -0
- package/internal/src/atom/create-atom.ts +75 -0
- package/internal/src/atom/delete-atom.ts +10 -0
- package/internal/src/atom/index.ts +3 -0
- package/internal/src/atom/is-default.ts +37 -0
- package/internal/src/caching.ts +21 -0
- package/internal/src/families/create-atom-family.ts +59 -0
- package/internal/src/families/create-readonly-selector-family.ts +45 -0
- package/internal/src/families/create-selector-family.ts +67 -0
- package/internal/src/families/index.ts +3 -0
- package/internal/src/get-state-internal.ts +23 -0
- package/internal/src/index.ts +13 -0
- package/internal/src/mutable/create-mutable-atom-family.ts +25 -0
- package/internal/src/mutable/create-mutable-atom.ts +49 -0
- package/internal/src/mutable/get-json-token.ts +22 -0
- package/internal/src/mutable/get-update-token.ts +20 -0
- package/internal/src/mutable/index.ts +17 -0
- package/internal/src/mutable/is-atom-token-mutable.ts +7 -0
- package/internal/src/mutable/tracker-family.ts +61 -0
- package/internal/src/mutable/tracker.ts +164 -0
- package/internal/src/mutable/transceiver.ts +110 -0
- package/internal/src/operation.ts +68 -0
- package/internal/src/selector/create-read-write-selector.ts +65 -0
- package/internal/src/selector/create-readonly-selector.ts +49 -0
- package/internal/src/selector/create-selector.ts +65 -0
- package/internal/src/selector/index.ts +5 -0
- package/internal/src/selector/lookup-selector-sources.ts +20 -0
- package/internal/src/selector/register-selector.ts +61 -0
- package/internal/src/selector/trace-selector-atoms.ts +45 -0
- package/internal/src/selector/update-selector-atoms.ts +34 -0
- package/internal/src/set-state/become.ts +10 -0
- package/internal/src/set-state/copy-mutable-if-needed.ts +23 -0
- package/internal/src/set-state/copy-mutable-in-transaction.ts +59 -0
- package/internal/src/set-state/copy-mutable-into-new-store.ts +34 -0
- package/internal/src/set-state/emit-update.ts +23 -0
- package/internal/src/set-state/evict-downstream.ts +39 -0
- package/internal/src/set-state/index.ts +2 -0
- package/internal/src/set-state/set-atom-state.ts +38 -0
- package/internal/src/set-state/set-selector-state.ts +19 -0
- package/internal/src/set-state/set-state-internal.ts +18 -0
- package/internal/src/set-state/stow-update.ts +42 -0
- package/internal/src/store/deposit.ts +43 -0
- package/internal/src/store/index.ts +5 -0
- package/internal/src/store/lookup.ts +26 -0
- package/internal/src/store/store.ts +154 -0
- package/internal/src/store/withdraw-new-family-member.ts +53 -0
- package/internal/src/store/withdraw.ts +113 -0
- package/internal/src/subject.ts +21 -0
- package/internal/src/subscribe/index.ts +1 -0
- package/internal/src/subscribe/recall-state.ts +19 -0
- package/internal/src/subscribe/subscribe-to-root-atoms.ts +47 -0
- package/internal/src/timeline/add-atom-to-timeline.ts +189 -0
- package/internal/src/timeline/index.ts +3 -0
- package/internal/src/timeline/time-travel-internal.ts +91 -0
- package/internal/src/timeline/timeline-internal.ts +115 -0
- package/internal/src/transaction/abort-transaction.ts +12 -0
- package/internal/src/transaction/apply-transaction.ts +64 -0
- package/internal/src/transaction/build-transaction.ts +39 -0
- package/internal/src/transaction/index.ts +26 -0
- package/internal/src/transaction/redo-transaction.ts +22 -0
- package/internal/src/transaction/transaction-internal.ts +64 -0
- package/internal/src/transaction/undo-transaction.ts +22 -0
- package/introspection/dist/index.d.mts +3 -197
- package/introspection/dist/index.d.ts +3 -197
- package/introspection/dist/index.js +329 -4
- package/introspection/dist/index.js.map +1 -1
- package/introspection/dist/index.mjs +310 -4
- package/introspection/dist/index.mjs.map +1 -1
- package/introspection/src/attach-atom-index.ts +84 -0
- package/introspection/src/attach-introspection-states.ts +38 -0
- package/introspection/src/attach-selector-index.ts +90 -0
- package/introspection/src/attach-timeline-family.ts +59 -0
- package/introspection/src/attach-timeline-index.ts +38 -0
- package/introspection/src/attach-transaction-index.ts +40 -0
- package/introspection/src/attach-transaction-logs.ts +43 -0
- package/introspection/src/index.ts +20 -0
- package/json/dist/index.d.mts +10 -2
- package/json/dist/index.d.ts +10 -2
- package/json/dist/index.js +83 -26
- package/json/dist/index.js.map +1 -1
- package/json/dist/index.mjs +74 -3
- package/json/dist/index.mjs.map +1 -1
- package/json/src/index.ts +5 -0
- package/json/src/select-json-family.ts +35 -0
- package/json/src/select-json.ts +22 -0
- package/package.json +103 -63
- package/react/dist/index.d.mts +9 -17
- package/react/dist/index.d.ts +9 -17
- package/react/dist/index.js +44 -27
- package/react/dist/index.js.map +1 -1
- package/react/dist/index.mjs +24 -4
- package/react/dist/index.mjs.map +1 -1
- package/react/src/index.ts +2 -0
- package/react/src/store-context.tsx +12 -0
- package/react/src/store-hooks.ts +36 -0
- package/react-devtools/dist/index.css +50 -1
- package/react-devtools/dist/index.css.map +1 -1
- package/react-devtools/dist/index.d.mts +104 -71
- package/react-devtools/dist/index.d.ts +104 -71
- package/react-devtools/dist/index.js +2806 -44
- package/react-devtools/dist/index.js.map +1 -1
- package/react-devtools/dist/index.mjs +2775 -10
- package/react-devtools/dist/index.mjs.map +1 -1
- package/react-devtools/src/AtomIODevtools.tsx +109 -0
- package/react-devtools/src/Button.tsx +23 -0
- package/react-devtools/src/StateEditor.tsx +75 -0
- package/react-devtools/src/StateIndex.tsx +159 -0
- package/react-devtools/src/TimelineIndex.tsx +88 -0
- package/react-devtools/src/TransactionIndex.tsx +70 -0
- package/react-devtools/src/Updates.tsx +150 -0
- package/react-devtools/src/devtools.scss +310 -0
- package/react-devtools/src/index.ts +72 -0
- package/realtime-react/dist/index.d.mts +8 -22
- package/realtime-react/dist/index.d.ts +8 -22
- package/realtime-react/dist/index.js +87 -32
- package/realtime-react/dist/index.js.map +1 -1
- package/realtime-react/dist/index.mjs +62 -6
- package/realtime-react/dist/index.mjs.map +1 -1
- package/realtime-react/src/index.ts +7 -0
- package/realtime-react/src/realtime-context.tsx +29 -0
- package/realtime-react/src/use-pull-family-member.ts +15 -0
- package/realtime-react/src/use-pull-mutable-family-member.ts +20 -0
- package/realtime-react/src/use-pull-mutable.ts +17 -0
- package/realtime-react/src/use-pull.ts +15 -0
- package/realtime-react/src/use-push.ts +19 -0
- package/realtime-react/src/use-server-action.ts +18 -0
- package/realtime-testing/dist/index.d.mts +49 -0
- package/realtime-testing/dist/index.d.ts +49 -0
- package/realtime-testing/dist/index.js +147 -0
- package/realtime-testing/dist/index.js.map +1 -0
- package/realtime-testing/dist/index.mjs +116 -0
- package/realtime-testing/dist/index.mjs.map +1 -0
- package/realtime-testing/src/index.ts +1 -0
- package/realtime-testing/src/setup-realtime-test.tsx +161 -0
- package/src/atom.ts +64 -9
- package/src/index.ts +36 -32
- package/src/logger.ts +3 -3
- package/src/selector.ts +3 -3
- package/src/silo.ts +29 -20
- package/src/subscribe.ts +3 -3
- package/src/timeline.ts +2 -2
- package/transceivers/set-rtx/dist/index.d.mts +39 -0
- package/transceivers/set-rtx/dist/index.d.ts +39 -0
- package/transceivers/set-rtx/dist/index.js +213 -0
- package/transceivers/set-rtx/dist/index.js.map +1 -0
- package/transceivers/set-rtx/dist/index.mjs +211 -0
- package/transceivers/set-rtx/dist/index.mjs.map +1 -0
- package/{realtime → transceivers/set-rtx}/package.json +1 -1
- package/transceivers/set-rtx/src/index.ts +1 -0
- package/transceivers/set-rtx/src/set-rtx.ts +242 -0
- package/realtime/dist/index.d.mts +0 -23
- package/realtime/dist/index.d.ts +0 -23
- package/realtime/dist/index.js +0 -32
- package/realtime/dist/index.js.map +0 -1
- package/realtime/dist/index.mjs +0 -7
- package/realtime/dist/index.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/setup-realtime-test.tsx","../../../anvl/src/object/entries.ts"],"names":["clients"],"mappings":"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","sourcesContent":["import * as http from \"http\"\n\nimport { type RenderResult, prettyDOM, render } from \"@testing-library/react\"\nimport * as AtomIO from \"atom.io\"\nimport * as Internal from \"atom.io/internal\"\nimport * as AR from \"atom.io/react\"\nimport * as RTC from \"atom.io/realtime-react\"\nimport * as Happy from \"happy-dom\"\nimport * as React from \"react\"\nimport * as SocketIO from \"socket.io\"\nimport type { Socket as ClientSocket } from \"socket.io-client\"\nimport { io } from \"socket.io-client\"\n\nimport { recordToEntries } from \"~/packages/anvl/src/object\"\n\nexport type TestSetupOptions = {\n\tserver: (tools: { socket: SocketIO.Socket; silo: AtomIO.Silo }) => void\n}\nexport type TestSetupOptions__SingleClient = TestSetupOptions & {\n\tclient: React.FC\n}\nexport type TestSetupOptions__MultiClient<ClientNames extends string> =\n\tTestSetupOptions & {\n\t\tclients: {\n\t\t\t[K in ClientNames]: React.FC\n\t\t}\n\t}\n\nexport type RealtimeTestTools = {\n\tname: string\n\tsilo: AtomIO.Silo\n\tdispose: () => void\n}\nexport type RealtimeTestClient = RealtimeTestTools & {\n\trenderResult: RenderResult\n\tprettyPrint: () => void\n\treconnect: () => void\n\tdisconnect: () => void\n}\nexport type RealtimeTestServer = RealtimeTestTools & {\n\tport: number\n}\n\nexport type RealtimeTestAPI = {\n\tserver: RealtimeTestServer\n\tteardown: () => void\n}\nexport type RealtimeTestAPI__SingleClient = RealtimeTestAPI & {\n\tclient: RealtimeTestClient\n}\nexport type RealtimeTestAPI__MultiClient<ClientNames extends string> =\n\tRealtimeTestAPI & {\n\t\tclients: Record<ClientNames, RealtimeTestClient>\n\t}\n\nexport const setupRealtimeTestServer = (\n\toptions: TestSetupOptions,\n): RealtimeTestServer => {\n\tconst httpServer = http.createServer((_, res) => res.end(`Hello World!`))\n\tconst address = httpServer.listen().address()\n\tconst port =\n\t\ttypeof address === `string` ? 80 : address === null ? null : address.port\n\tif (port === null) throw new Error(`Could not determine port for test server`)\n\tconst server = new SocketIO.Server(httpServer)\n\tconst silo = new AtomIO.Silo(`SERVER`, Internal.IMPLICIT.STORE)\n\n\tserver.on(`connection`, (socket: SocketIO.Socket) => {\n\t\toptions.server({ socket, silo })\n\t})\n\n\tconst dispose = () => {\n\t\tserver.close()\n\t\tInternal.clearStore(silo.store)\n\t}\n\n\treturn {\n\t\tname: `SERVER`,\n\t\tsilo,\n\t\tdispose,\n\t\tport,\n\t}\n}\nexport const setupRealtimeTestClient = (\n\toptions: TestSetupOptions__SingleClient,\n\tname: string,\n\tport: number,\n): RealtimeTestClient => {\n\tconst socket: ClientSocket = io(`http://localhost:${port}/`)\n\tconst silo = new AtomIO.Silo(name, Internal.IMPLICIT.STORE)\n\n\tconst { document } = new Happy.Window()\n\tdocument.body.innerHTML = `<div id=\"app\"></div>`\n\tconst renderResult = render(\n\t\t<AR.StoreProvider store={silo.store}>\n\t\t\t<RTC.RealtimeProvider socket={socket}>\n\t\t\t\t<options.client />\n\t\t\t</RTC.RealtimeProvider>\n\t\t</AR.StoreProvider>,\n\t\t{\n\t\t\tcontainer: document.querySelector(`#app`) as unknown as HTMLElement,\n\t\t},\n\t)\n\n\tconst prettyPrint = () => console.log(prettyDOM(renderResult.container))\n\n\tconst disconnect = () => socket.disconnect()\n\tconst reconnect = () => socket.connect()\n\n\tconst dispose = () => {\n\t\tsocket.disconnect()\n\t\tInternal.clearStore(silo.store)\n\t}\n\n\treturn {\n\t\tname,\n\t\tsilo,\n\t\trenderResult,\n\t\tprettyPrint,\n\t\tdisconnect,\n\t\treconnect,\n\t\tdispose,\n\t}\n}\n\nexport const singleClient = (\n\toptions: TestSetupOptions__SingleClient,\n): RealtimeTestAPI__SingleClient => {\n\tconst server = setupRealtimeTestServer(options)\n\tconst client = setupRealtimeTestClient(options, `CLIENT`, server.port)\n\n\treturn {\n\t\tclient,\n\t\tserver,\n\t\tteardown: () => {\n\t\t\tclient.dispose()\n\t\t\tserver.dispose()\n\t\t},\n\t}\n}\n\nexport const multiClient = <ClientNames extends string>(\n\toptions: TestSetupOptions__MultiClient<ClientNames>,\n): RealtimeTestAPI__MultiClient<ClientNames> => {\n\tconst server = setupRealtimeTestServer(options)\n\tconst clients = recordToEntries(options.clients).reduce(\n\t\t(clients, [name, client]) => ({\n\t\t\t...clients,\n\t\t\t[name]: setupRealtimeTestClient({ ...options, client }, name, server.port),\n\t\t}),\n\t\t{} as Record<ClientNames, RealtimeTestClient>,\n\t)\n\n\treturn {\n\t\tclients,\n\t\tserver,\n\t\tteardown: () => {\n\t\t\trecordToEntries(clients).forEach(([, client]) => client.dispose())\n\t\t\tserver.dispose()\n\t\t},\n\t}\n}\n","export type Entries<K extends keyof any, V> = [key: K, value: V][]\n\nexport const recordToEntries = <K extends keyof any, V>(\n\tobj: Record<K, V>,\n): Entries<K, V> => Object.entries(obj) as Entries<K, V>\n\nexport const entriesToRecord = <K extends keyof any, V>(\n\tentries: Entries<K, V>,\n): Record<K, V> => Object.fromEntries(entries) as Record<K, V>\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./setup-realtime-test"
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import * as http from "http"
|
|
2
|
+
|
|
3
|
+
import { type RenderResult, prettyDOM, render } from "@testing-library/react"
|
|
4
|
+
import * as AtomIO from "atom.io"
|
|
5
|
+
import * as Internal from "atom.io/internal"
|
|
6
|
+
import * as AR from "atom.io/react"
|
|
7
|
+
import * as RTC from "atom.io/realtime-react"
|
|
8
|
+
import * as Happy from "happy-dom"
|
|
9
|
+
import * as React from "react"
|
|
10
|
+
import * as SocketIO from "socket.io"
|
|
11
|
+
import type { Socket as ClientSocket } from "socket.io-client"
|
|
12
|
+
import { io } from "socket.io-client"
|
|
13
|
+
|
|
14
|
+
import { recordToEntries } from "~/packages/anvl/src/object"
|
|
15
|
+
|
|
16
|
+
export type TestSetupOptions = {
|
|
17
|
+
server: (tools: { socket: SocketIO.Socket; silo: AtomIO.Silo }) => void
|
|
18
|
+
}
|
|
19
|
+
export type TestSetupOptions__SingleClient = TestSetupOptions & {
|
|
20
|
+
client: React.FC
|
|
21
|
+
}
|
|
22
|
+
export type TestSetupOptions__MultiClient<ClientNames extends string> =
|
|
23
|
+
TestSetupOptions & {
|
|
24
|
+
clients: {
|
|
25
|
+
[K in ClientNames]: React.FC
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type RealtimeTestTools = {
|
|
30
|
+
name: string
|
|
31
|
+
silo: AtomIO.Silo
|
|
32
|
+
dispose: () => void
|
|
33
|
+
}
|
|
34
|
+
export type RealtimeTestClient = RealtimeTestTools & {
|
|
35
|
+
renderResult: RenderResult
|
|
36
|
+
prettyPrint: () => void
|
|
37
|
+
reconnect: () => void
|
|
38
|
+
disconnect: () => void
|
|
39
|
+
}
|
|
40
|
+
export type RealtimeTestServer = RealtimeTestTools & {
|
|
41
|
+
port: number
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export type RealtimeTestAPI = {
|
|
45
|
+
server: RealtimeTestServer
|
|
46
|
+
teardown: () => void
|
|
47
|
+
}
|
|
48
|
+
export type RealtimeTestAPI__SingleClient = RealtimeTestAPI & {
|
|
49
|
+
client: RealtimeTestClient
|
|
50
|
+
}
|
|
51
|
+
export type RealtimeTestAPI__MultiClient<ClientNames extends string> =
|
|
52
|
+
RealtimeTestAPI & {
|
|
53
|
+
clients: Record<ClientNames, RealtimeTestClient>
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export const setupRealtimeTestServer = (
|
|
57
|
+
options: TestSetupOptions,
|
|
58
|
+
): RealtimeTestServer => {
|
|
59
|
+
const httpServer = http.createServer((_, res) => res.end(`Hello World!`))
|
|
60
|
+
const address = httpServer.listen().address()
|
|
61
|
+
const port =
|
|
62
|
+
typeof address === `string` ? 80 : address === null ? null : address.port
|
|
63
|
+
if (port === null) throw new Error(`Could not determine port for test server`)
|
|
64
|
+
const server = new SocketIO.Server(httpServer)
|
|
65
|
+
const silo = new AtomIO.Silo(`SERVER`, Internal.IMPLICIT.STORE)
|
|
66
|
+
|
|
67
|
+
server.on(`connection`, (socket: SocketIO.Socket) => {
|
|
68
|
+
options.server({ socket, silo })
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
const dispose = () => {
|
|
72
|
+
server.close()
|
|
73
|
+
Internal.clearStore(silo.store)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
name: `SERVER`,
|
|
78
|
+
silo,
|
|
79
|
+
dispose,
|
|
80
|
+
port,
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export const setupRealtimeTestClient = (
|
|
84
|
+
options: TestSetupOptions__SingleClient,
|
|
85
|
+
name: string,
|
|
86
|
+
port: number,
|
|
87
|
+
): RealtimeTestClient => {
|
|
88
|
+
const socket: ClientSocket = io(`http://localhost:${port}/`)
|
|
89
|
+
const silo = new AtomIO.Silo(name, Internal.IMPLICIT.STORE)
|
|
90
|
+
|
|
91
|
+
const { document } = new Happy.Window()
|
|
92
|
+
document.body.innerHTML = `<div id="app"></div>`
|
|
93
|
+
const renderResult = render(
|
|
94
|
+
<AR.StoreProvider store={silo.store}>
|
|
95
|
+
<RTC.RealtimeProvider socket={socket}>
|
|
96
|
+
<options.client />
|
|
97
|
+
</RTC.RealtimeProvider>
|
|
98
|
+
</AR.StoreProvider>,
|
|
99
|
+
{
|
|
100
|
+
container: document.querySelector(`#app`) as unknown as HTMLElement,
|
|
101
|
+
},
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
const prettyPrint = () => console.log(prettyDOM(renderResult.container))
|
|
105
|
+
|
|
106
|
+
const disconnect = () => socket.disconnect()
|
|
107
|
+
const reconnect = () => socket.connect()
|
|
108
|
+
|
|
109
|
+
const dispose = () => {
|
|
110
|
+
socket.disconnect()
|
|
111
|
+
Internal.clearStore(silo.store)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
name,
|
|
116
|
+
silo,
|
|
117
|
+
renderResult,
|
|
118
|
+
prettyPrint,
|
|
119
|
+
disconnect,
|
|
120
|
+
reconnect,
|
|
121
|
+
dispose,
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export const singleClient = (
|
|
126
|
+
options: TestSetupOptions__SingleClient,
|
|
127
|
+
): RealtimeTestAPI__SingleClient => {
|
|
128
|
+
const server = setupRealtimeTestServer(options)
|
|
129
|
+
const client = setupRealtimeTestClient(options, `CLIENT`, server.port)
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
client,
|
|
133
|
+
server,
|
|
134
|
+
teardown: () => {
|
|
135
|
+
client.dispose()
|
|
136
|
+
server.dispose()
|
|
137
|
+
},
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export const multiClient = <ClientNames extends string>(
|
|
142
|
+
options: TestSetupOptions__MultiClient<ClientNames>,
|
|
143
|
+
): RealtimeTestAPI__MultiClient<ClientNames> => {
|
|
144
|
+
const server = setupRealtimeTestServer(options)
|
|
145
|
+
const clients = recordToEntries(options.clients).reduce(
|
|
146
|
+
(clients, [name, client]) => ({
|
|
147
|
+
...clients,
|
|
148
|
+
[name]: setupRealtimeTestClient({ ...options, client }, name, server.port),
|
|
149
|
+
}),
|
|
150
|
+
{} as Record<ClientNames, RealtimeTestClient>,
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
return {
|
|
154
|
+
clients,
|
|
155
|
+
server,
|
|
156
|
+
teardown: () => {
|
|
157
|
+
recordToEntries(clients).forEach(([, client]) => client.dispose())
|
|
158
|
+
server.dispose()
|
|
159
|
+
},
|
|
160
|
+
}
|
|
161
|
+
}
|
package/src/atom.ts
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
import type { Subject } from "atom.io/internal"
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import type { Subject, Transceiver } from "atom.io/internal"
|
|
2
|
+
import {
|
|
3
|
+
createAtom,
|
|
4
|
+
createAtomFamily,
|
|
5
|
+
createMutableAtom,
|
|
6
|
+
createMutableAtomFamily,
|
|
7
|
+
} from "atom.io/internal"
|
|
8
|
+
import type { Json, JsonInterface } from "atom.io/json"
|
|
4
9
|
|
|
5
|
-
import type { AtomToken } from "."
|
|
10
|
+
import type { AtomToken, MutableAtomToken } from "."
|
|
6
11
|
|
|
7
12
|
export type Effectors<T> = {
|
|
8
13
|
setSelf: <V extends T>(next: V | ((oldValue: T) => V)) => void
|
|
@@ -15,11 +20,27 @@ export type AtomOptions<T> = {
|
|
|
15
20
|
key: string
|
|
16
21
|
default: T | (() => T)
|
|
17
22
|
effects?: AtomEffect<T>[]
|
|
18
|
-
mutable?: boolean
|
|
19
23
|
}
|
|
24
|
+
// biome-ignore format: complex intersection
|
|
25
|
+
export type MutableAtomOptions<T extends Transceiver<any>, J extends Json.Serializable> =
|
|
26
|
+
& JsonInterface<T, J>
|
|
27
|
+
& Omit<AtomOptions<T>, `default`>
|
|
28
|
+
& {
|
|
29
|
+
default: () => T
|
|
30
|
+
mutable: true
|
|
31
|
+
}
|
|
20
32
|
|
|
21
|
-
export function atom<T
|
|
22
|
-
|
|
33
|
+
export function atom<T extends Transceiver<any>, J extends Json.Serializable>(
|
|
34
|
+
options: MutableAtomOptions<T, J>,
|
|
35
|
+
): MutableAtomToken<T, J>
|
|
36
|
+
export function atom<T>(options: AtomOptions<T>): AtomToken<T>
|
|
37
|
+
export function atom<T>(
|
|
38
|
+
options: AtomOptions<any> | MutableAtomOptions<any, any>,
|
|
39
|
+
): AtomToken<any> {
|
|
40
|
+
if (`mutable` in options) {
|
|
41
|
+
return createMutableAtom(options)
|
|
42
|
+
}
|
|
43
|
+
return createAtom<T>(options)
|
|
23
44
|
}
|
|
24
45
|
|
|
25
46
|
export type AtomFamilyOptions<T, K extends Json.Serializable> = {
|
|
@@ -35,9 +56,43 @@ export type AtomFamily<T, K extends Json.Serializable = Json.Serializable> = ((
|
|
|
35
56
|
type: `atom_family`
|
|
36
57
|
subject: Subject<AtomToken<T>>
|
|
37
58
|
}
|
|
59
|
+
// biome-ignore format: intersection
|
|
60
|
+
export type MutableAtomFamilyOptions<
|
|
61
|
+
T extends Transceiver<any>,
|
|
62
|
+
J extends Json.Serializable,
|
|
63
|
+
K extends Json.Serializable,
|
|
64
|
+
> =
|
|
65
|
+
& AtomFamilyOptions<T, K>
|
|
66
|
+
& JsonInterface<T, J>
|
|
67
|
+
& { mutable: true }
|
|
38
68
|
|
|
69
|
+
// biome-ignore format: intersection
|
|
70
|
+
export type MutableAtomFamily<
|
|
71
|
+
Core extends Transceiver<any>,
|
|
72
|
+
SerializableCore extends Json.Serializable,
|
|
73
|
+
Key extends Json.Serializable,
|
|
74
|
+
> =
|
|
75
|
+
& JsonInterface<Core, SerializableCore>
|
|
76
|
+
& ((key: Key) => MutableAtomToken<Core, SerializableCore>)
|
|
77
|
+
& {
|
|
78
|
+
key: `${string}::mutable`
|
|
79
|
+
type: `atom_family`
|
|
80
|
+
subject: Subject<MutableAtomToken<Core, SerializableCore>>
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function atomFamily<
|
|
84
|
+
T extends Transceiver<any>,
|
|
85
|
+
J extends Json.Serializable,
|
|
86
|
+
K extends Json.Serializable,
|
|
87
|
+
>(options: MutableAtomFamilyOptions<T, J, K>): MutableAtomFamily<T, J, K>
|
|
39
88
|
export function atomFamily<T, K extends Json.Serializable>(
|
|
40
89
|
options: AtomFamilyOptions<T, K>,
|
|
41
|
-
): AtomFamily<T, K>
|
|
42
|
-
|
|
90
|
+
): AtomFamily<T, K>
|
|
91
|
+
export function atomFamily<T, K extends Json.Serializable>(
|
|
92
|
+
options: AtomFamilyOptions<T, K> | MutableAtomFamilyOptions<any, any, any>,
|
|
93
|
+
): AtomFamily<T, K> | MutableAtomFamily<any, any, any> {
|
|
94
|
+
if (`mutable` in options) {
|
|
95
|
+
return createMutableAtomFamily(options)
|
|
96
|
+
}
|
|
97
|
+
return createAtomFamily<T, K>(options)
|
|
43
98
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,31 +1,23 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
getState__INTERNAL,
|
|
5
|
-
isAtomDefault,
|
|
6
|
-
isSelectorDefault,
|
|
7
|
-
openOperation,
|
|
8
|
-
setState__INTERNAL,
|
|
9
|
-
withdraw,
|
|
10
|
-
} from "atom.io/internal"
|
|
11
|
-
import * as __INTERNAL__ from "atom.io/internal"
|
|
12
|
-
import type { Store } from "atom.io/internal"
|
|
13
|
-
|
|
14
|
-
import type { ƒn } from "~/packages/anvl/src/function"
|
|
15
|
-
import { capitalize } from "~/packages/anvl/src/string/capitalize"
|
|
16
|
-
|
|
17
|
-
export { ƒn }
|
|
1
|
+
import * as IO from "atom.io/internal"
|
|
2
|
+
import type { Store, Transceiver } from "atom.io/internal"
|
|
3
|
+
import type { Json } from "atom.io/json"
|
|
18
4
|
|
|
19
5
|
export * from "./atom"
|
|
20
6
|
export * from "./logger"
|
|
21
7
|
export * from "./selector"
|
|
22
8
|
export * from "./silo"
|
|
23
|
-
export
|
|
9
|
+
export {
|
|
10
|
+
subscribe,
|
|
11
|
+
subscribeToTimeline,
|
|
12
|
+
subscribeToTransaction,
|
|
13
|
+
KeyedStateUpdate,
|
|
14
|
+
StateUpdate,
|
|
15
|
+
UpdateHandler,
|
|
16
|
+
} from "./subscribe"
|
|
24
17
|
export * from "./timeline"
|
|
25
18
|
export * from "./transaction"
|
|
26
|
-
|
|
27
|
-
export type
|
|
28
|
-
export type { Json } from "atom.io/json"
|
|
19
|
+
|
|
20
|
+
export type ƒn = (...parameters: any[]) => any
|
|
29
21
|
|
|
30
22
|
export type AtomToken<_> = {
|
|
31
23
|
key: string
|
|
@@ -33,6 +25,13 @@ export type AtomToken<_> = {
|
|
|
33
25
|
family?: FamilyMetadata
|
|
34
26
|
__brand?: _
|
|
35
27
|
}
|
|
28
|
+
export interface MutableAtomToken<
|
|
29
|
+
T extends Transceiver<any>,
|
|
30
|
+
J extends Json.Serializable,
|
|
31
|
+
> extends AtomToken<T> {
|
|
32
|
+
__asJSON?: J
|
|
33
|
+
__update?: T extends Transceiver<infer Update> ? Update : never
|
|
34
|
+
}
|
|
36
35
|
export type SelectorToken<_> = {
|
|
37
36
|
key: string
|
|
38
37
|
type: `selector`
|
|
@@ -53,11 +52,15 @@ export type FamilyMetadata = {
|
|
|
53
52
|
subKey: string
|
|
54
53
|
}
|
|
55
54
|
|
|
55
|
+
export const capitalize = (str: string): string =>
|
|
56
|
+
str[0].toUpperCase() + str.slice(1)
|
|
57
|
+
|
|
56
58
|
export const getState = <T>(
|
|
57
59
|
token: ReadonlySelectorToken<T> | StateToken<T>,
|
|
58
|
-
store: Store = IMPLICIT.STORE,
|
|
60
|
+
store: Store = IO.IMPLICIT.STORE,
|
|
59
61
|
): T => {
|
|
60
|
-
const state =
|
|
62
|
+
const state =
|
|
63
|
+
IO.withdraw(token, store) ?? IO.withdrawNewFamilyMember(token, store)
|
|
61
64
|
if (state === null) {
|
|
62
65
|
throw new Error(
|
|
63
66
|
`${capitalize(token.type)} "${token.key}" not found in store "${
|
|
@@ -65,23 +68,24 @@ export const getState = <T>(
|
|
|
65
68
|
}".`,
|
|
66
69
|
)
|
|
67
70
|
}
|
|
68
|
-
return getState__INTERNAL(state, store)
|
|
71
|
+
return IO.getState__INTERNAL(state, store)
|
|
69
72
|
}
|
|
70
73
|
|
|
71
74
|
export const setState = <T, New extends T>(
|
|
72
75
|
token: StateToken<T>,
|
|
73
76
|
value: New | ((oldValue: T) => New),
|
|
74
|
-
store: Store = IMPLICIT.STORE,
|
|
77
|
+
store: Store = IO.IMPLICIT.STORE,
|
|
75
78
|
): void => {
|
|
76
79
|
try {
|
|
77
|
-
openOperation(token, store)
|
|
80
|
+
IO.openOperation(token, store)
|
|
78
81
|
} catch (thrown) {
|
|
79
82
|
if (!(typeof thrown === `symbol`)) {
|
|
80
83
|
throw thrown
|
|
81
84
|
}
|
|
82
85
|
return
|
|
83
86
|
}
|
|
84
|
-
const state =
|
|
87
|
+
const state =
|
|
88
|
+
IO.withdraw(token, store) ?? IO.withdrawNewFamilyMember(token, store)
|
|
85
89
|
if (state === null) {
|
|
86
90
|
throw new Error(
|
|
87
91
|
`${capitalize(token.type)} "${token.key}" not found in store "${
|
|
@@ -89,14 +93,14 @@ export const setState = <T, New extends T>(
|
|
|
89
93
|
}".`,
|
|
90
94
|
)
|
|
91
95
|
}
|
|
92
|
-
setState__INTERNAL(state, value, store)
|
|
93
|
-
closeOperation(store)
|
|
96
|
+
IO.setState__INTERNAL(state, value, store)
|
|
97
|
+
IO.closeOperation(store)
|
|
94
98
|
}
|
|
95
99
|
|
|
96
100
|
export const isDefault = (
|
|
97
101
|
token: ReadonlySelectorToken<unknown> | StateToken<unknown>,
|
|
98
|
-
store: Store = IMPLICIT.STORE,
|
|
102
|
+
store: Store = IO.IMPLICIT.STORE,
|
|
99
103
|
): boolean =>
|
|
100
104
|
token.type === `atom`
|
|
101
|
-
? isAtomDefault(token.key, store)
|
|
102
|
-
: isSelectorDefault(token.key, store)
|
|
105
|
+
? IO.isAtomDefault(token.key, store)
|
|
106
|
+
: IO.isSelectorDefault(token.key, store)
|
package/src/logger.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { IMPLICIT } from "atom.io/internal"
|
|
2
2
|
import type { Store } from "atom.io/internal"
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
export const NO_OP = (): void => undefined
|
|
5
5
|
|
|
6
6
|
export type Logger = Pick<Console, `error` | `info` | `warn`>
|
|
7
7
|
export const LOG_LEVELS: ReadonlyArray<keyof Logger> = [
|
|
@@ -22,7 +22,7 @@ export const setLogLevel = (
|
|
|
22
22
|
LOG_LEVELS.forEach((logLevel) => {
|
|
23
23
|
if (LOG_LEVELS.indexOf(logLevel) < LOG_LEVELS.indexOf(preferredLevel)) {
|
|
24
24
|
// biome-ignore lint/style/noNonNullAssertion: we just set it
|
|
25
|
-
store.config.logger![logLevel] =
|
|
25
|
+
store.config.logger![logLevel] = NO_OP
|
|
26
26
|
} else {
|
|
27
27
|
// biome-ignore lint/style/noNonNullAssertion: we just set it
|
|
28
28
|
store.config.logger![logLevel] = logger__INTERNAL[logLevel]
|
|
@@ -39,7 +39,7 @@ export const useLogger = (
|
|
|
39
39
|
store.config.logger === null
|
|
40
40
|
? null
|
|
41
41
|
: LOG_LEVELS.find(
|
|
42
|
-
(logLevel) => store.config.logger?.[logLevel] !==
|
|
42
|
+
(logLevel) => store.config.logger?.[logLevel] !== NO_OP,
|
|
43
43
|
) ?? null
|
|
44
44
|
store.config.logger__INTERNAL = { ...logger }
|
|
45
45
|
setLogLevel(currentLogLevel, store)
|
package/src/selector.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Subject } from "atom.io/internal"
|
|
2
|
-
import {
|
|
2
|
+
import { createSelector, createSelectorFamily } from "atom.io/internal"
|
|
3
3
|
import type { Json } from "atom.io/json"
|
|
4
4
|
|
|
5
5
|
import type { ReadonlySelectorToken, SelectorToken } from "."
|
|
@@ -22,7 +22,7 @@ export function selector<T>(
|
|
|
22
22
|
export function selector<T>(
|
|
23
23
|
options: ReadonlySelectorOptions<T> | SelectorOptions<T>,
|
|
24
24
|
): ReadonlySelectorToken<T> | SelectorToken<T> {
|
|
25
|
-
return
|
|
25
|
+
return createSelector(options)
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
export type SelectorFamilyOptions<T, K extends Json.Serializable> = {
|
|
@@ -62,5 +62,5 @@ export function selectorFamily<T, K extends Json.Serializable>(
|
|
|
62
62
|
export function selectorFamily<T, K extends Json.Serializable>(
|
|
63
63
|
options: ReadonlySelectorFamilyOptions<T, K> | SelectorFamilyOptions<T, K>,
|
|
64
64
|
): ReadonlySelectorFamily<T, K> | SelectorFamily<T, K> {
|
|
65
|
-
return
|
|
65
|
+
return createSelectorFamily(options)
|
|
66
66
|
}
|
package/src/silo.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Store,
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
createAtom,
|
|
4
|
+
createAtomFamily,
|
|
5
|
+
createMutableAtom,
|
|
6
|
+
createMutableAtomFamily,
|
|
7
|
+
createSelector,
|
|
8
|
+
createSelectorFamily,
|
|
5
9
|
redo__INTERNAL,
|
|
6
|
-
selectorFamily__INTERNAL,
|
|
7
|
-
selector__INTERNAL,
|
|
8
10
|
timeline__INTERNAL,
|
|
9
11
|
transaction__INTERNAL,
|
|
10
12
|
undo__INTERNAL,
|
|
@@ -30,21 +32,28 @@ export class Silo {
|
|
|
30
32
|
public undo: typeof undo
|
|
31
33
|
public redo: typeof redo
|
|
32
34
|
public constructor(name: string, fromStore: Store | null = null) {
|
|
33
|
-
const
|
|
34
|
-
this.store =
|
|
35
|
-
this.atom = (options) =>
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
this.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
this.
|
|
35
|
+
const s = new Store(name, fromStore)
|
|
36
|
+
this.store = s
|
|
37
|
+
this.atom = (options) => {
|
|
38
|
+
if (`mutable` in options) {
|
|
39
|
+
return createMutableAtom(options, s)
|
|
40
|
+
}
|
|
41
|
+
return createAtom(options, undefined, s)
|
|
42
|
+
}
|
|
43
|
+
this.atomFamily = (options) => {
|
|
44
|
+
if (`mutable` in options) {
|
|
45
|
+
return createMutableAtomFamily(options, s) as any
|
|
46
|
+
}
|
|
47
|
+
return createAtomFamily(options, s)
|
|
48
|
+
}
|
|
49
|
+
this.selector = (options) => createSelector(options, undefined, s) as any
|
|
50
|
+
this.selectorFamily = (options) => createSelectorFamily(options, s) as any
|
|
51
|
+
this.transaction = (options) => transaction__INTERNAL(options, s)
|
|
52
|
+
this.timeline = (options) => timeline__INTERNAL(options, s)
|
|
53
|
+
this.getState = (token) => getState(token, s)
|
|
54
|
+
this.setState = (token, newValue) => setState(token, newValue, s)
|
|
55
|
+
this.subscribe = (token, handler, key) => subscribe(token, handler, key, s)
|
|
56
|
+
this.undo = (token) => undo__INTERNAL(token, s)
|
|
57
|
+
this.redo = (token) => redo__INTERNAL(token, s)
|
|
49
58
|
}
|
|
50
59
|
}
|
package/src/subscribe.ts
CHANGED
|
@@ -19,12 +19,12 @@ export type KeyedStateUpdate<T> = StateUpdate<T> & {
|
|
|
19
19
|
}
|
|
20
20
|
export type UpdateHandler<T> = (update: StateUpdate<T>) => void
|
|
21
21
|
|
|
22
|
-
export
|
|
22
|
+
export function subscribe<T>(
|
|
23
23
|
token: ReadonlySelectorToken<T> | StateToken<T>,
|
|
24
24
|
handleUpdate: UpdateHandler<T>,
|
|
25
25
|
key: string = Math.random().toString(36).slice(2),
|
|
26
26
|
store: Store = IMPLICIT.STORE,
|
|
27
|
-
): (
|
|
27
|
+
): () => void {
|
|
28
28
|
const state = withdraw<T>(token, store)
|
|
29
29
|
if (state === null) {
|
|
30
30
|
throw new Error(
|
|
@@ -32,7 +32,7 @@ export const subscribe = <T>(
|
|
|
32
32
|
)
|
|
33
33
|
}
|
|
34
34
|
const unsubFunction = state.subject.subscribe(key, handleUpdate)
|
|
35
|
-
store.config.logger?.info(`👀
|
|
35
|
+
store.config.logger?.info(`👀 adding subscription "${key}" to "${state.key}"`)
|
|
36
36
|
const dependencyUnsubFunctions =
|
|
37
37
|
state.type !== `atom` ? subscribeToRootAtoms(state, store) : null
|
|
38
38
|
|
package/src/timeline.ts
CHANGED
|
@@ -3,12 +3,12 @@ import type {
|
|
|
3
3
|
TimelineSelectorUpdate,
|
|
4
4
|
TimelineTransactionUpdate,
|
|
5
5
|
} from "atom.io/internal"
|
|
6
|
-
import { IMPLICIT } from "atom.io/internal"
|
|
7
6
|
import {
|
|
7
|
+
IMPLICIT,
|
|
8
8
|
redo__INTERNAL,
|
|
9
9
|
timeline__INTERNAL,
|
|
10
10
|
undo__INTERNAL,
|
|
11
|
-
} from "atom.io/internal
|
|
11
|
+
} from "atom.io/internal"
|
|
12
12
|
|
|
13
13
|
import type { AtomFamily, AtomToken } from "."
|
|
14
14
|
|
|
@@ -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 };
|