atom.io 0.15.3 → 0.15.5
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/data/dist/index.cjs +29 -16
- package/data/dist/index.cjs.map +1 -1
- package/data/dist/index.js +30 -17
- package/data/dist/index.js.map +1 -1
- package/data/src/join.ts +15 -2
- package/dist/index.cjs +32 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +153 -85
- package/dist/index.js +157 -1
- package/dist/index.js.map +1 -1
- package/internal/dist/index.cjs +98 -159
- package/internal/dist/index.cjs.map +1 -1
- package/internal/dist/index.d.ts +44 -32
- package/internal/dist/index.js +89 -105
- package/internal/dist/index.js.map +1 -1
- package/internal/src/atom/create-regular-atom.ts +1 -1
- package/internal/src/get-environment-data.ts +18 -0
- package/internal/src/index.ts +2 -0
- package/internal/src/ingest-updates/index.ts +3 -0
- package/internal/src/ingest-updates/ingest-atom-update.ts +14 -0
- package/internal/src/ingest-updates/ingest-selector-update.ts +17 -0
- package/internal/src/ingest-updates/ingest-transaction-update.ts +22 -0
- package/internal/src/mutable/tracker.ts +4 -4
- package/internal/src/not-found-error.ts +3 -8
- package/internal/src/operation.ts +4 -4
- package/internal/src/selector/create-read-write-selector.ts +6 -4
- package/internal/src/selector/create-readonly-selector.ts +3 -3
- package/internal/src/selector/register-selector.ts +6 -4
- package/internal/src/selector/update-selector-atoms.ts +2 -2
- package/internal/src/store/deposit.ts +5 -5
- package/internal/src/store/store.ts +4 -4
- package/internal/src/store/withdraw-new-family-member.ts +8 -11
- package/internal/src/store/withdraw.ts +11 -12
- package/internal/src/subscribe/subscribe-to-state.ts +2 -2
- package/internal/src/subscribe/subscribe-to-timeline.ts +4 -4
- package/internal/src/timeline/add-atom-to-timeline.ts +7 -7
- package/internal/src/timeline/create-timeline.ts +29 -21
- package/internal/src/timeline/time-travel.ts +19 -45
- package/internal/src/transaction/apply-transaction.ts +5 -51
- package/internal/src/transaction/build-transaction.ts +9 -2
- package/internal/src/transaction/create-transaction.ts +4 -4
- package/internal/src/transaction/index.ts +2 -2
- package/introspection/dist/index.cjs +9 -9
- package/introspection/dist/index.cjs.map +1 -1
- package/introspection/dist/index.d.ts +6 -6
- package/introspection/dist/index.js +9 -9
- package/introspection/dist/index.js.map +1 -1
- package/introspection/src/attach-atom-index.ts +4 -4
- package/introspection/src/attach-introspection-states.ts +2 -2
- package/introspection/src/attach-selector-index.ts +4 -4
- package/introspection/src/attach-timeline-family.ts +6 -6
- package/introspection/src/attach-timeline-index.ts +6 -4
- package/introspection/src/attach-transaction-index.ts +1 -1
- package/introspection/src/index.ts +1 -1
- package/package.json +11 -12
- package/react/dist/index.cjs.map +1 -1
- package/react/dist/index.d.ts +4 -4
- package/react/dist/index.js.map +1 -1
- package/react/src/store-hooks.ts +5 -5
- package/react-devtools/dist/index.cjs +7 -9
- package/react-devtools/dist/index.cjs.map +1 -1
- package/react-devtools/dist/index.d.ts +10 -265
- package/react-devtools/dist/index.js +7 -9
- package/react-devtools/dist/index.js.map +1 -1
- package/react-devtools/src/StateEditor.tsx +3 -3
- package/react-devtools/src/StateIndex.tsx +3 -3
- package/react-devtools/src/TimelineIndex.tsx +2 -2
- package/react-devtools/src/Updates.tsx +1 -1
- package/realtime-client/dist/index.cjs +68 -66
- package/realtime-client/dist/index.cjs.map +1 -1
- package/realtime-client/dist/index.d.ts +8 -7
- package/realtime-client/dist/index.js +63 -62
- package/realtime-client/dist/index.js.map +1 -1
- package/realtime-client/src/pull-family-member.ts +1 -1
- package/realtime-client/src/pull.ts +1 -1
- package/realtime-client/src/push.ts +2 -3
- package/realtime-client/src/realtime-state.ts +11 -3
- package/realtime-client/src/server-action.ts +65 -65
- package/realtime-react/dist/index.cjs +90 -56
- package/realtime-react/dist/index.cjs.map +1 -1
- package/realtime-react/dist/index.d.ts +11 -6
- package/realtime-react/dist/index.js +89 -55
- package/realtime-react/dist/index.js.map +1 -1
- package/realtime-react/src/on-mount.ts +23 -0
- package/realtime-react/src/realtime-context.tsx +14 -6
- package/realtime-react/src/use-pull-family-member.ts +5 -8
- package/realtime-react/src/use-pull-mutable-family-member.ts +4 -7
- package/realtime-react/src/use-pull-mutable.ts +4 -7
- package/realtime-react/src/use-pull.ts +5 -8
- package/realtime-react/src/use-push.ts +5 -9
- package/realtime-react/src/use-realtime-service.ts +30 -0
- package/realtime-react/src/use-server-action.ts +8 -8
- package/realtime-server/dist/index.cjs +109 -40
- package/realtime-server/dist/index.cjs.map +1 -1
- package/realtime-server/dist/index.d.ts +7 -6
- package/realtime-server/dist/index.js +90 -39
- package/realtime-server/dist/index.js.map +1 -1
- package/realtime-server/src/hook-composition/expose-family.ts +2 -2
- package/realtime-server/src/hook-composition/expose-mutable-family.ts +1 -1
- package/realtime-server/src/hook-composition/expose-single.ts +1 -1
- package/realtime-server/src/hook-composition/index.ts +2 -1
- package/realtime-server/src/hook-composition/receive-state.ts +2 -2
- package/realtime-server/src/hook-composition/receive-transaction.ts +13 -32
- package/realtime-server/src/hook-composition/sync-transaction.ts +92 -0
- package/realtime-testing/dist/index.cjs +3 -3
- package/realtime-testing/dist/index.cjs.map +1 -1
- package/realtime-testing/dist/index.js +2 -2
- package/realtime-testing/dist/index.js.map +1 -1
- package/realtime-testing/src/setup-realtime-test.tsx +4 -3
- package/src/atom.ts +30 -7
- package/src/dispose.ts +2 -2
- package/src/find-state.ts +64 -0
- package/src/get-state.ts +2 -2
- package/src/index.ts +23 -0
- package/src/logger.ts +1 -0
- package/src/selector.ts +16 -0
- package/src/set-state.ts +2 -2
- package/src/silo.ts +2 -2
- package/src/subscribe.ts +7 -11
- package/src/timeline.ts +20 -12
- package/src/transaction.ts +31 -12
- package/src/validators.ts +74 -0
- package/dist/chunk-K22LR3V6.js +0 -138
- package/dist/chunk-K22LR3V6.js.map +0 -1
- package/internal/src/set-state/copy-mutable-into-new-store.ts +0 -34
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import * as AtomIO from "atom.io"
|
|
2
|
+
import * as Internal from "atom.io/internal"
|
|
3
|
+
|
|
4
|
+
import type { ServerConfig } from "."
|
|
5
|
+
|
|
6
|
+
const completeUpdateAtoms = AtomIO.atomFamily<
|
|
7
|
+
AtomIO.TransactionUpdate<any> | null,
|
|
8
|
+
string
|
|
9
|
+
>({
|
|
10
|
+
key: `completeUpdate`,
|
|
11
|
+
default: null,
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
const transactionRedactorAtoms = AtomIO.atomFamily<
|
|
15
|
+
{
|
|
16
|
+
filter: (
|
|
17
|
+
updates: AtomIO.TransactionUpdateContent[],
|
|
18
|
+
) => AtomIO.TransactionUpdateContent[]
|
|
19
|
+
},
|
|
20
|
+
string
|
|
21
|
+
>({
|
|
22
|
+
key: `transactionRedactor`,
|
|
23
|
+
default: { filter: (updates) => updates },
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
const redactedUpdateSelectors = AtomIO.selectorFamily<
|
|
27
|
+
AtomIO.TransactionUpdate<any> | null,
|
|
28
|
+
[transactionKey: string, updateId: string]
|
|
29
|
+
>({
|
|
30
|
+
key: `redactedUpdate`,
|
|
31
|
+
get:
|
|
32
|
+
([transactionKey, updateId]) =>
|
|
33
|
+
({ get, find }) => {
|
|
34
|
+
const update = get(find(completeUpdateAtoms, updateId))
|
|
35
|
+
const { filter } = get(find(transactionRedactorAtoms, transactionKey))
|
|
36
|
+
|
|
37
|
+
if (update && filter) {
|
|
38
|
+
return { ...update, updates: filter(update.updates) }
|
|
39
|
+
}
|
|
40
|
+
return null
|
|
41
|
+
},
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
export function useSyncTransaction({
|
|
45
|
+
socket,
|
|
46
|
+
store = Internal.IMPLICIT.STORE,
|
|
47
|
+
}: ServerConfig) {
|
|
48
|
+
return function syncTransaction<ƒ extends AtomIO.ƒn>(
|
|
49
|
+
tx: AtomIO.TransactionToken<ƒ>,
|
|
50
|
+
filter?: (
|
|
51
|
+
update: AtomIO.TransactionUpdateContent[],
|
|
52
|
+
) => AtomIO.TransactionUpdateContent[],
|
|
53
|
+
): () => void {
|
|
54
|
+
if (filter) {
|
|
55
|
+
AtomIO.setState(
|
|
56
|
+
AtomIO.findState(transactionRedactorAtoms, tx.key),
|
|
57
|
+
{ filter },
|
|
58
|
+
store,
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
const fillTransactionRequest = (update: AtomIO.TransactionUpdate<ƒ>) => {
|
|
62
|
+
AtomIO.runTransaction<ƒ>(tx, store, update.id)(...update.params)
|
|
63
|
+
}
|
|
64
|
+
socket.on(`tx-run:${tx.key}`, fillTransactionRequest)
|
|
65
|
+
|
|
66
|
+
const fillTransactionSubscriptionRequest = () => {
|
|
67
|
+
const unsubscribe = Internal.subscribeToTransaction(
|
|
68
|
+
tx,
|
|
69
|
+
(update) => {
|
|
70
|
+
unsubscribe()
|
|
71
|
+
const updateState = AtomIO.findState(completeUpdateAtoms, update.id)
|
|
72
|
+
AtomIO.setState(updateState, update, store)
|
|
73
|
+
const toEmit = filter
|
|
74
|
+
? AtomIO.getState(
|
|
75
|
+
AtomIO.findState(redactedUpdateSelectors, [tx.key, update.id]),
|
|
76
|
+
store,
|
|
77
|
+
)
|
|
78
|
+
: update
|
|
79
|
+
socket.emit(`tx-new:${tx.key}`, toEmit)
|
|
80
|
+
},
|
|
81
|
+
`tx-sub:${tx.key}:${socket.id}`,
|
|
82
|
+
store,
|
|
83
|
+
)
|
|
84
|
+
socket.on(`tx-unsub:${tx.key}`, unsubscribe)
|
|
85
|
+
}
|
|
86
|
+
socket.on(`tx-sub:${tx.key}`, fillTransactionSubscriptionRequest)
|
|
87
|
+
|
|
88
|
+
return () => {
|
|
89
|
+
socket.off(`tx-run:${tx.key}`, fillTransactionRequest)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -5,7 +5,7 @@ var react = require('@testing-library/react');
|
|
|
5
5
|
var AtomIO = require('atom.io');
|
|
6
6
|
var Internal = require('atom.io/internal');
|
|
7
7
|
var AR = require('atom.io/react');
|
|
8
|
-
var
|
|
8
|
+
var RTR = require('atom.io/realtime-react');
|
|
9
9
|
var Happy = require('happy-dom');
|
|
10
10
|
var SocketIO = require('socket.io');
|
|
11
11
|
var socket_ioClient = require('socket.io-client');
|
|
@@ -33,7 +33,7 @@ var http__namespace = /*#__PURE__*/_interopNamespace(http);
|
|
|
33
33
|
var AtomIO__namespace = /*#__PURE__*/_interopNamespace(AtomIO);
|
|
34
34
|
var Internal__namespace = /*#__PURE__*/_interopNamespace(Internal);
|
|
35
35
|
var AR__namespace = /*#__PURE__*/_interopNamespace(AR);
|
|
36
|
-
var
|
|
36
|
+
var RTR__namespace = /*#__PURE__*/_interopNamespace(RTR);
|
|
37
37
|
var Happy__namespace = /*#__PURE__*/_interopNamespace(Happy);
|
|
38
38
|
var SocketIO__namespace = /*#__PURE__*/_interopNamespace(SocketIO);
|
|
39
39
|
|
|
@@ -87,7 +87,7 @@ var setupRealtimeTestClient = (options, name, port) => {
|
|
|
87
87
|
const { document } = new Happy__namespace.Window();
|
|
88
88
|
document.body.innerHTML = `<div id="app"></div>`;
|
|
89
89
|
const renderResult = react.render(
|
|
90
|
-
/* @__PURE__ */ jsxRuntime.jsx(AR__namespace.StoreProvider, { store: silo.store, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
90
|
+
/* @__PURE__ */ jsxRuntime.jsx(AR__namespace.StoreProvider, { store: silo.store, children: /* @__PURE__ */ jsxRuntime.jsx(RTR__namespace.RealtimeProvider, { socket, children: /* @__PURE__ */ jsxRuntime.jsx(options.client, {}) }) }),
|
|
91
91
|
{
|
|
92
92
|
container: document.querySelector(`#app`)
|
|
93
93
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/setup-realtime-test.tsx","../../../anvl/src/object/entries.ts"],"names":["clients"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA,YAAY,UAAU;AAEtB,SAA4B,WAAW,cAAc;AACrD,YAAY,YAAY;AACxB,YAAY,cAAc;AAC1B,YAAY,QAAQ;AACpB,YAAY,SAAS;AACrB,YAAY,WAAW;AAEvB,YAAY,cAAc;AAE1B,SAAS,UAAU;;;ACTZ,IAAM,kBAAkB,CAC9B,QACmB,OAAO,QAAQ,GAAG;;;
|
|
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 RTR 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\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<RTR.RealtimeProvider socket={socket}>\n\t\t\t\t<options.client />\n\t\t\t</RTR.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\tclients[name] = setupRealtimeTestClient(\n\t\t\t\t{ ...options, client },\n\t\t\t\tname,\n\t\t\t\tserver.port,\n\t\t\t)\n\t\t\treturn clients\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\tfor (const [, client] of recordToEntries(clients)) {\n\t\t\t\tclient.dispose()\n\t\t\t}\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"]}
|
|
@@ -5,7 +5,7 @@ import { render, prettyDOM } from '@testing-library/react';
|
|
|
5
5
|
import * as AtomIO from 'atom.io';
|
|
6
6
|
import * as Internal from 'atom.io/internal';
|
|
7
7
|
import * as AR from 'atom.io/react';
|
|
8
|
-
import * as
|
|
8
|
+
import * as RTR from 'atom.io/realtime-react';
|
|
9
9
|
import * as Happy from 'happy-dom';
|
|
10
10
|
import * as SocketIO from 'socket.io';
|
|
11
11
|
import { io } from 'socket.io-client';
|
|
@@ -39,7 +39,7 @@ var setupRealtimeTestClient = (options, name, port) => {
|
|
|
39
39
|
const { document } = new Happy.Window();
|
|
40
40
|
document.body.innerHTML = `<div id="app"></div>`;
|
|
41
41
|
const renderResult = render(
|
|
42
|
-
/* @__PURE__ */ jsx(AR.StoreProvider, { store: silo.store, children: /* @__PURE__ */ jsx(
|
|
42
|
+
/* @__PURE__ */ jsx(AR.StoreProvider, { store: silo.store, children: /* @__PURE__ */ jsx(RTR.RealtimeProvider, { socket, children: /* @__PURE__ */ jsx(options.client, {}) }) }),
|
|
43
43
|
{
|
|
44
44
|
container: document.querySelector(`#app`)
|
|
45
45
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/setup-realtime-test.tsx"],"names":["clients"],"mappings":";;;;;;;;;AAAA,YAAY,UAAU;AAEtB,SAA4B,WAAW,cAAc;AACrD,YAAY,YAAY;AACxB,YAAY,cAAc;AAC1B,YAAY,QAAQ;AACpB,YAAY,SAAS;AACrB,YAAY,WAAW;AAEvB,YAAY,cAAc;AAE1B,SAAS,UAAU;
|
|
1
|
+
{"version":3,"sources":["../src/setup-realtime-test.tsx"],"names":["clients"],"mappings":";;;;;;;;;AAAA,YAAY,UAAU;AAEtB,SAA4B,WAAW,cAAc;AACrD,YAAY,YAAY;AACxB,YAAY,cAAc;AAC1B,YAAY,QAAQ;AACpB,YAAY,SAAS;AACrB,YAAY,WAAW;AAEvB,YAAY,cAAc;AAE1B,SAAS,UAAU;AAqFf;AAzCG,IAAM,0BAA0B,CACtC,YACwB;AACxB,QAAM,aAAkB,kBAAa,CAAC,GAAG,QAAQ,IAAI,IAAI,cAAc,CAAC;AACxE,QAAM,UAAU,WAAW,OAAO,EAAE,QAAQ;AAC5C,QAAM,OACL,OAAO,YAAY,WAAW,KAAK,YAAY,OAAO,OAAO,QAAQ;AACtE,MAAI,SAAS;AAAM,UAAM,IAAI,MAAM,0CAA0C;AAC7E,QAAM,SAAS,IAAa,gBAAO,UAAU;AAE7C,QAAM,OAAO,IAAW,YAAK,UAAmB,kBAAS,KAAK;AAE9D,SAAO,GAAG,cAAc,CAAC,WAA4B;AACpD,YAAQ,OAAO,EAAE,QAAQ,KAAK,CAAC;AAAA,EAChC,CAAC;AAED,QAAM,UAAU,MAAM;AACrB,WAAO,MAAM;AACb,IAAS,oBAAW,KAAK,KAAK;AAAA,EAC/B;AAEA,SAAO;AAAA,IACN,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACD;AACO,IAAM,0BAA0B,CACtC,SACA,MACA,SACwB;AACxB,QAAM,SAAuB,GAAG,oBAAoB,IAAI,GAAG;AAC3D,QAAM,OAAO,IAAW,YAAK,MAAe,kBAAS,KAAK;AAE1D,QAAM,EAAE,SAAS,IAAI,IAAU,aAAO;AACtC,WAAS,KAAK,YAAY;AAC1B,QAAM,eAAe;AAAA,IACpB,oBAAI,kBAAH,EAAiB,OAAO,KAAK,OAC7B,8BAAK,sBAAJ,EAAqB,QACrB,8BAAC,QAAQ,QAAR,EAAe,GACjB,GACD;AAAA,IACA;AAAA,MACC,WAAW,SAAS,cAAc,MAAM;AAAA,IACzC;AAAA,EACD;AAEA,QAAM,cAAc,MAAM,QAAQ,IAAI,UAAU,aAAa,SAAS,CAAC;AAEvE,QAAM,aAAa,MAAM,OAAO,WAAW;AAC3C,QAAM,YAAY,MAAM,OAAO,QAAQ;AAEvC,QAAM,UAAU,MAAM;AACrB,WAAO,WAAW;AAClB,IAAS,oBAAW,KAAK,KAAK;AAAA,EAC/B;AAEA,SAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACD;AAEO,IAAM,eAAe,CAC3B,YACmC;AACnC,QAAM,SAAS,wBAAwB,OAAO;AAC9C,QAAM,SAAS,wBAAwB,SAAS,UAAU,OAAO,IAAI;AAErE,SAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA,UAAU,MAAM;AACf,aAAO,QAAQ;AACf,aAAO,QAAQ;AAAA,IAChB;AAAA,EACD;AACD;AAEO,IAAM,cAAc,CAC1B,YAC+C;AAC/C,QAAM,SAAS,wBAAwB,OAAO;AAC9C,QAAM,UAAU,gBAAgB,QAAQ,OAAO,EAAE;AAAA,IAChD,CAACA,UAAS,CAAC,MAAM,MAAM,MAAM;AAC5B,MAAAA,SAAQ,IAAI,IAAI;AAAA,QACf,iCAAK,UAAL,EAAc,OAAO;AAAA,QACrB;AAAA,QACA,OAAO;AAAA,MACR;AACA,aAAOA;AAAA,IACR;AAAA,IACA,CAAC;AAAA,EACF;AAEA,SAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA,UAAU,MAAM;AACf,iBAAW,CAAC,EAAE,MAAM,KAAK,gBAAgB,OAAO,GAAG;AAClD,eAAO,QAAQ;AAAA,MAChB;AACA,aAAO,QAAQ;AAAA,IAChB;AAAA,EACD;AACD","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 RTR 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\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<RTR.RealtimeProvider socket={socket}>\n\t\t\t\t<options.client />\n\t\t\t</RTR.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\tclients[name] = setupRealtimeTestClient(\n\t\t\t\t{ ...options, client },\n\t\t\t\tname,\n\t\t\t\tserver.port,\n\t\t\t)\n\t\t\treturn clients\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\tfor (const [, client] of recordToEntries(clients)) {\n\t\t\t\tclient.dispose()\n\t\t\t}\n\t\t\tserver.dispose()\n\t\t},\n\t}\n}\n"]}
|
|
@@ -4,7 +4,7 @@ import { type RenderResult, prettyDOM, render } from "@testing-library/react"
|
|
|
4
4
|
import * as AtomIO from "atom.io"
|
|
5
5
|
import * as Internal from "atom.io/internal"
|
|
6
6
|
import * as AR from "atom.io/react"
|
|
7
|
-
import * as
|
|
7
|
+
import * as RTR from "atom.io/realtime-react"
|
|
8
8
|
import * as Happy from "happy-dom"
|
|
9
9
|
import * as React from "react"
|
|
10
10
|
import * as SocketIO from "socket.io"
|
|
@@ -62,6 +62,7 @@ export const setupRealtimeTestServer = (
|
|
|
62
62
|
typeof address === `string` ? 80 : address === null ? null : address.port
|
|
63
63
|
if (port === null) throw new Error(`Could not determine port for test server`)
|
|
64
64
|
const server = new SocketIO.Server(httpServer)
|
|
65
|
+
|
|
65
66
|
const silo = new AtomIO.Silo(`SERVER`, Internal.IMPLICIT.STORE)
|
|
66
67
|
|
|
67
68
|
server.on(`connection`, (socket: SocketIO.Socket) => {
|
|
@@ -92,9 +93,9 @@ export const setupRealtimeTestClient = (
|
|
|
92
93
|
document.body.innerHTML = `<div id="app"></div>`
|
|
93
94
|
const renderResult = render(
|
|
94
95
|
<AR.StoreProvider store={silo.store}>
|
|
95
|
-
<
|
|
96
|
+
<RTR.RealtimeProvider socket={socket}>
|
|
96
97
|
<options.client />
|
|
97
|
-
</
|
|
98
|
+
</RTR.RealtimeProvider>
|
|
98
99
|
</AR.StoreProvider>,
|
|
99
100
|
{
|
|
100
101
|
container: document.querySelector(`#app`) as unknown as HTMLElement,
|
package/src/atom.ts
CHANGED
|
@@ -49,6 +49,14 @@ export type AtomFamily<T, K extends Json.Serializable = Json.Serializable> = ((
|
|
|
49
49
|
subject: Subject<AtomToken<T>>
|
|
50
50
|
mutable?: boolean
|
|
51
51
|
install: (store: Store) => void
|
|
52
|
+
__T?: T
|
|
53
|
+
__K?: K
|
|
54
|
+
}
|
|
55
|
+
export type AtomFamilyToken<T, K extends Json.Serializable> = {
|
|
56
|
+
key: string
|
|
57
|
+
type: `atom_family`
|
|
58
|
+
__T?: T
|
|
59
|
+
__K?: K
|
|
52
60
|
}
|
|
53
61
|
|
|
54
62
|
// biome-ignore format: intersection
|
|
@@ -63,19 +71,34 @@ export type MutableAtomFamilyOptions<
|
|
|
63
71
|
|
|
64
72
|
// biome-ignore format: intersection
|
|
65
73
|
export type MutableAtomFamily<
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
74
|
+
T extends Transceiver<any>,
|
|
75
|
+
J extends Json.Serializable,
|
|
76
|
+
K extends Json.Serializable,
|
|
69
77
|
> =
|
|
70
|
-
& JsonInterface<
|
|
71
|
-
& ((key:
|
|
78
|
+
& JsonInterface<T, J>
|
|
79
|
+
& ((key: K) => MutableAtomToken<T, J>)
|
|
72
80
|
& {
|
|
73
|
-
key:
|
|
81
|
+
key: string
|
|
74
82
|
type: `atom_family`
|
|
75
|
-
subject: Subject<MutableAtomToken<
|
|
83
|
+
subject: Subject<MutableAtomToken<T, J>>
|
|
76
84
|
mutable: true
|
|
77
85
|
install: (store: Store) => void
|
|
86
|
+
__T?: T
|
|
87
|
+
__J?: J
|
|
88
|
+
__K?: K
|
|
78
89
|
}
|
|
90
|
+
export type MutableAtomFamilyToken<
|
|
91
|
+
T extends Transceiver<any>,
|
|
92
|
+
J extends Json.Serializable,
|
|
93
|
+
K extends Json.Serializable,
|
|
94
|
+
> = {
|
|
95
|
+
key: string
|
|
96
|
+
type: `atom_family`
|
|
97
|
+
mutable: true
|
|
98
|
+
__T?: T
|
|
99
|
+
__J?: J
|
|
100
|
+
__K?: K
|
|
101
|
+
}
|
|
79
102
|
|
|
80
103
|
export function atomFamily<
|
|
81
104
|
T extends Transceiver<any>,
|
package/src/dispose.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as Internal from "atom.io/internal"
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type { ReadableToken } from "."
|
|
4
4
|
|
|
5
5
|
export function dispose(
|
|
6
|
-
token:
|
|
6
|
+
token: ReadableToken<any>,
|
|
7
7
|
store: Internal.Store = Internal.IMPLICIT.STORE,
|
|
8
8
|
): void {
|
|
9
9
|
switch (token.type) {
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AtomFamilyToken,
|
|
3
|
+
AtomToken,
|
|
4
|
+
MutableAtomFamilyToken,
|
|
5
|
+
MutableAtomToken,
|
|
6
|
+
ReadableFamilyToken,
|
|
7
|
+
ReadableToken,
|
|
8
|
+
ReadonlySelectorFamilyToken,
|
|
9
|
+
ReadonlySelectorToken,
|
|
10
|
+
SelectorFamilyToken,
|
|
11
|
+
SelectorToken,
|
|
12
|
+
WritableFamilyToken,
|
|
13
|
+
WritableToken,
|
|
14
|
+
} from "atom.io"
|
|
15
|
+
import type { Store, Transceiver } from "atom.io/internal"
|
|
16
|
+
import { IMPLICIT } from "atom.io/internal"
|
|
17
|
+
import type { Json } from "atom.io/json"
|
|
18
|
+
|
|
19
|
+
export function findInStore(
|
|
20
|
+
token: ReadableFamilyToken<any, any>,
|
|
21
|
+
key: Json.Serializable,
|
|
22
|
+
store: Store,
|
|
23
|
+
): ReadableToken<any> {
|
|
24
|
+
const familyKey = token.key
|
|
25
|
+
const family = store.families.get(familyKey)
|
|
26
|
+
if (family === undefined) {
|
|
27
|
+
throw new Error(`Family ${familyKey} not found`)
|
|
28
|
+
}
|
|
29
|
+
const state = family(key)
|
|
30
|
+
return state
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function findState<
|
|
34
|
+
T extends Transceiver<any>,
|
|
35
|
+
J extends Json.Serializable,
|
|
36
|
+
K extends Json.Serializable,
|
|
37
|
+
>(token: MutableAtomFamilyToken<T, J, K>, key: K): MutableAtomToken<T, J>
|
|
38
|
+
export function findState<T, K extends Json.Serializable>(
|
|
39
|
+
token: AtomFamilyToken<T, K>,
|
|
40
|
+
key: K,
|
|
41
|
+
): AtomToken<T>
|
|
42
|
+
export function findState<T, K extends Json.Serializable>(
|
|
43
|
+
token: SelectorFamilyToken<T, K>,
|
|
44
|
+
key: K,
|
|
45
|
+
): SelectorToken<T>
|
|
46
|
+
export function findState<T, K extends Json.Serializable>(
|
|
47
|
+
token: ReadonlySelectorFamilyToken<T, K>,
|
|
48
|
+
key: K,
|
|
49
|
+
): ReadonlySelectorToken<T>
|
|
50
|
+
export function findState<T, K extends Json.Serializable>(
|
|
51
|
+
token: WritableFamilyToken<T, K>,
|
|
52
|
+
key: K,
|
|
53
|
+
): WritableToken<T>
|
|
54
|
+
export function findState<T, K extends Json.Serializable>(
|
|
55
|
+
token: ReadableFamilyToken<T, K>,
|
|
56
|
+
key: K,
|
|
57
|
+
): ReadableToken<T>
|
|
58
|
+
export function findState(
|
|
59
|
+
token: ReadableFamilyToken<any, any>,
|
|
60
|
+
key: Json.Serializable,
|
|
61
|
+
): ReadableToken<any> {
|
|
62
|
+
const state = findInStore(token, key, IMPLICIT.STORE)
|
|
63
|
+
return state
|
|
64
|
+
}
|
package/src/get-state.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as Internal from "atom.io/internal"
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type { ReadableToken } from "."
|
|
4
4
|
|
|
5
5
|
export function getState<T>(
|
|
6
|
-
token:
|
|
6
|
+
token: ReadableToken<T>,
|
|
7
7
|
store: Internal.Store = Internal.IMPLICIT.STORE,
|
|
8
8
|
): T {
|
|
9
9
|
const state =
|
package/src/index.ts
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import type { Transceiver } from "atom.io/internal"
|
|
2
2
|
import type { Json } from "atom.io/json"
|
|
3
|
+
import type { AtomFamily, AtomFamilyToken } from "./atom"
|
|
4
|
+
import type {
|
|
5
|
+
ReadonlySelectorFamily,
|
|
6
|
+
ReadonlySelectorFamilyToken,
|
|
7
|
+
SelectorFamily,
|
|
8
|
+
SelectorFamilyToken,
|
|
9
|
+
} from "./selector"
|
|
3
10
|
|
|
4
11
|
export * from "./atom"
|
|
5
12
|
export * from "./dispose"
|
|
13
|
+
export * from "./find-state"
|
|
6
14
|
export * from "./get-state"
|
|
7
15
|
export * from "./logger"
|
|
8
16
|
export * from "./selector"
|
|
@@ -11,6 +19,7 @@ export * from "./silo"
|
|
|
11
19
|
export * from "./subscribe"
|
|
12
20
|
export * from "./timeline"
|
|
13
21
|
export * from "./transaction"
|
|
22
|
+
export * from "./validators"
|
|
14
23
|
|
|
15
24
|
export type ƒn = (...parameters: any[]) => any
|
|
16
25
|
|
|
@@ -40,6 +49,20 @@ export type StateToken<T> = AtomToken<T> | SelectorToken<T>
|
|
|
40
49
|
export type WritableToken<T> = AtomToken<T> | SelectorToken<T>
|
|
41
50
|
export type ReadableToken<T> = ReadonlySelectorToken<T> | WritableToken<T>
|
|
42
51
|
|
|
52
|
+
export type WritableFamily<T, K extends Json.Serializable> =
|
|
53
|
+
| AtomFamily<T, K>
|
|
54
|
+
| SelectorFamily<T, K>
|
|
55
|
+
export type ReadableFamily<T, K extends Json.Serializable> =
|
|
56
|
+
| ReadonlySelectorFamily<T, K>
|
|
57
|
+
| WritableFamily<T, K>
|
|
58
|
+
|
|
59
|
+
export type WritableFamilyToken<T, K extends Json.Serializable> =
|
|
60
|
+
| AtomFamilyToken<T, K>
|
|
61
|
+
| SelectorFamilyToken<T, K>
|
|
62
|
+
export type ReadableFamilyToken<T, K extends Json.Serializable> =
|
|
63
|
+
| ReadonlySelectorFamilyToken<T, K>
|
|
64
|
+
| WritableFamilyToken<T, K>
|
|
65
|
+
|
|
43
66
|
export type ReadonlySelectorToken<_> = {
|
|
44
67
|
key: string
|
|
45
68
|
type: `readonly_selector`
|
package/src/logger.ts
CHANGED
package/src/selector.ts
CHANGED
|
@@ -43,6 +43,14 @@ export type SelectorFamily<
|
|
|
43
43
|
type: `selector_family`
|
|
44
44
|
subject: Subject<SelectorToken<T>>
|
|
45
45
|
install: (store: Store) => void
|
|
46
|
+
__T?: T
|
|
47
|
+
__K?: K
|
|
48
|
+
}
|
|
49
|
+
export type SelectorFamilyToken<T, K extends Json.Serializable> = {
|
|
50
|
+
key: string
|
|
51
|
+
type: `selector_family`
|
|
52
|
+
__T?: T
|
|
53
|
+
__K?: K
|
|
46
54
|
}
|
|
47
55
|
|
|
48
56
|
export type ReadonlySelectorFamily<
|
|
@@ -53,6 +61,14 @@ export type ReadonlySelectorFamily<
|
|
|
53
61
|
type: `readonly_selector_family`
|
|
54
62
|
subject: Subject<ReadonlySelectorToken<T>>
|
|
55
63
|
install: (store: Store) => void
|
|
64
|
+
__T?: T
|
|
65
|
+
__K?: K
|
|
66
|
+
}
|
|
67
|
+
export type ReadonlySelectorFamilyToken<T, K extends Json.Serializable> = {
|
|
68
|
+
key: string
|
|
69
|
+
type: `readonly_selector_family`
|
|
70
|
+
__T?: T
|
|
71
|
+
__K?: K
|
|
56
72
|
}
|
|
57
73
|
|
|
58
74
|
export function selectorFamily<T, K extends Json.Serializable>(
|
package/src/set-state.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as Internal from "atom.io/internal"
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type { WritableToken } from "."
|
|
4
4
|
|
|
5
5
|
export function setState<T, New extends T>(
|
|
6
|
-
token:
|
|
6
|
+
token: WritableToken<T>,
|
|
7
7
|
value: New | ((oldValue: T) => New),
|
|
8
8
|
store: Internal.Store = Internal.IMPLICIT.STORE,
|
|
9
9
|
): void {
|
package/src/silo.ts
CHANGED
|
@@ -40,7 +40,7 @@ export class Silo {
|
|
|
40
40
|
this.getState = (token) => getState(token, s)
|
|
41
41
|
this.setState = (token, newValue) => setState(token, newValue, s)
|
|
42
42
|
this.subscribe = (token, handler, key) => subscribe(token, handler, key, s)
|
|
43
|
-
this.undo = (token) => timeTravel(`
|
|
44
|
-
this.redo = (token) => timeTravel(`
|
|
43
|
+
this.undo = (token) => timeTravel(`undo`, token, s)
|
|
44
|
+
this.redo = (token) => timeTravel(`redo`, token, s)
|
|
45
45
|
}
|
|
46
46
|
}
|
package/src/subscribe.ts
CHANGED
|
@@ -8,8 +8,8 @@ import {
|
|
|
8
8
|
|
|
9
9
|
import type {
|
|
10
10
|
FamilyMetadata,
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
ReadableToken,
|
|
12
|
+
TimelineManageable,
|
|
13
13
|
TimelineToken,
|
|
14
14
|
TimelineUpdate,
|
|
15
15
|
TransactionToken,
|
|
@@ -29,7 +29,7 @@ export type TransactionUpdateHandler<ƒ extends ƒn> = (
|
|
|
29
29
|
) => void
|
|
30
30
|
|
|
31
31
|
export function subscribe<T>(
|
|
32
|
-
token:
|
|
32
|
+
token: ReadableToken<T>,
|
|
33
33
|
handleUpdate: UpdateHandler<T>,
|
|
34
34
|
key?: string,
|
|
35
35
|
store?: Store,
|
|
@@ -40,18 +40,14 @@ export function subscribe<ƒ extends ƒn>(
|
|
|
40
40
|
key?: string,
|
|
41
41
|
store?: Store,
|
|
42
42
|
): () => void
|
|
43
|
-
export function subscribe(
|
|
44
|
-
token: TimelineToken
|
|
45
|
-
handleUpdate: (update: TimelineUpdate | `redo` | `undo`) => void,
|
|
43
|
+
export function subscribe<M extends TimelineManageable>(
|
|
44
|
+
token: TimelineToken<M>,
|
|
45
|
+
handleUpdate: (update: TimelineUpdate<M> | `redo` | `undo`) => void,
|
|
46
46
|
key?: string,
|
|
47
47
|
store?: Store,
|
|
48
48
|
): () => void
|
|
49
49
|
export function subscribe(
|
|
50
|
-
token:
|
|
51
|
-
| ReadonlySelectorToken<any>
|
|
52
|
-
| StateToken<any>
|
|
53
|
-
| TimelineToken
|
|
54
|
-
| TransactionToken<any>,
|
|
50
|
+
token: ReadableToken<any> | TimelineToken<any> | TransactionToken<any>,
|
|
55
51
|
handleUpdate: (update: any) => void,
|
|
56
52
|
key: string = Math.random().toString(36).slice(2),
|
|
57
53
|
store = IMPLICIT.STORE,
|
package/src/timeline.ts
CHANGED
|
@@ -8,30 +8,38 @@ import { IMPLICIT, createTimeline, timeTravel } from "atom.io/internal"
|
|
|
8
8
|
|
|
9
9
|
import type { AtomFamily, AtomToken } from "."
|
|
10
10
|
|
|
11
|
-
export type
|
|
11
|
+
export type TimelineManageable = AtomFamily<any, any> | AtomToken<any>
|
|
12
|
+
|
|
13
|
+
export type TimelineToken<_> = {
|
|
12
14
|
key: string
|
|
13
15
|
type: `timeline`
|
|
16
|
+
__brand?: _
|
|
14
17
|
}
|
|
15
18
|
|
|
16
|
-
export type TimelineOptions = {
|
|
19
|
+
export type TimelineOptions<ManagedAtom extends TimelineManageable> = {
|
|
17
20
|
key: string
|
|
18
|
-
atoms:
|
|
19
|
-
shouldCapture?: (
|
|
21
|
+
atoms: ManagedAtom[]
|
|
22
|
+
shouldCapture?: (
|
|
23
|
+
update: TimelineUpdate<ManagedAtom>,
|
|
24
|
+
timeline: Timeline<TimelineManageable>,
|
|
25
|
+
) => boolean
|
|
20
26
|
}
|
|
21
27
|
|
|
22
|
-
export type TimelineUpdate =
|
|
23
|
-
| TimelineAtomUpdate
|
|
24
|
-
| TimelineSelectorUpdate
|
|
28
|
+
export type TimelineUpdate<ManagedAtom extends TimelineManageable> =
|
|
29
|
+
| TimelineAtomUpdate<ManagedAtom>
|
|
30
|
+
| TimelineSelectorUpdate<ManagedAtom>
|
|
25
31
|
| TimelineTransactionUpdate
|
|
26
32
|
|
|
27
|
-
export const timeline =
|
|
33
|
+
export const timeline = <ManagedAtom extends TimelineManageable>(
|
|
34
|
+
options: TimelineOptions<ManagedAtom>,
|
|
35
|
+
): TimelineToken<ManagedAtom> => {
|
|
28
36
|
return createTimeline(options, IMPLICIT.STORE)
|
|
29
37
|
}
|
|
30
38
|
|
|
31
|
-
export const redo = (timeline: TimelineToken): void => {
|
|
32
|
-
timeTravel(`
|
|
39
|
+
export const redo = (timeline: TimelineToken<any>): void => {
|
|
40
|
+
timeTravel(`redo`, timeline, IMPLICIT.STORE)
|
|
33
41
|
}
|
|
34
42
|
|
|
35
|
-
export const undo = (timeline: TimelineToken): void => {
|
|
36
|
-
timeTravel(`
|
|
43
|
+
export const undo = (timeline: TimelineToken<any>): void => {
|
|
44
|
+
timeTravel(`undo`, timeline, IMPLICIT.STORE)
|
|
37
45
|
}
|