@synnaxlabs/client 0.56.1 → 0.57.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/dist/client-B08VDLSA.js +14463 -0
- package/dist/client-B08VDLSA.js.map +1 -0
- package/dist/client.js +1128 -14876
- package/dist/client.js.map +1 -0
- package/dist/src/access/client.d.ts +10 -1
- package/dist/src/access/client.d.ts.map +1 -1
- package/dist/src/access/enforce.d.ts.map +1 -1
- package/dist/src/access/external.d.ts +1 -0
- package/dist/src/access/external.d.ts.map +1 -1
- package/dist/src/access/granted.d.ts +39 -0
- package/dist/src/access/granted.d.ts.map +1 -0
- package/dist/src/access/policy/client.d.ts +136 -147
- package/dist/src/access/policy/client.d.ts.map +1 -1
- package/dist/src/access/policy/types.gen.d.ts +15 -68
- package/dist/src/access/policy/types.gen.d.ts.map +1 -1
- package/dist/src/access/role/client.d.ts +77 -58
- package/dist/src/access/role/client.d.ts.map +1 -1
- package/dist/src/access/role/types.gen.d.ts +8 -14
- package/dist/src/access/role/types.gen.d.ts.map +1 -1
- package/dist/src/actions/actions.d.ts +5 -6
- package/dist/src/actions/actions.d.ts.map +1 -1
- package/dist/src/actions/controller.d.ts +194 -0
- package/dist/src/actions/controller.d.ts.map +1 -0
- package/dist/src/actions/external.d.ts +1 -0
- package/dist/src/actions/external.d.ts.map +1 -1
- package/dist/src/arc/actions.d.ts +575 -0
- package/dist/src/arc/actions.d.ts.map +1 -0
- package/dist/src/arc/actions.gen.d.ts +1439 -0
- package/dist/src/arc/actions.gen.d.ts.map +1 -0
- package/dist/src/arc/client.d.ts +97 -13
- package/dist/src/arc/client.d.ts.map +1 -1
- package/dist/src/arc/compiler/types.gen.d.ts +3 -3
- package/dist/src/arc/compiler/types.gen.d.ts.map +1 -1
- package/dist/src/arc/external.d.ts +2 -0
- package/dist/src/arc/external.d.ts.map +1 -1
- package/dist/src/arc/graph/types.gen.d.ts +45 -597
- package/dist/src/arc/graph/types.gen.d.ts.map +1 -1
- package/dist/src/arc/ir/index.d.ts +1 -1
- package/dist/src/arc/ir/index.d.ts.map +1 -1
- package/dist/src/arc/ir/ir.d.ts +2 -0
- package/dist/src/arc/ir/ir.d.ts.map +1 -0
- package/dist/src/arc/ir/types.gen.d.ts +58 -2807
- package/dist/src/arc/ir/types.gen.d.ts.map +1 -1
- package/dist/src/arc/module/types.gen.d.ts +18 -1090
- package/dist/src/arc/module/types.gen.d.ts.map +1 -1
- package/dist/src/arc/program/types.gen.d.ts +18 -1090
- package/dist/src/arc/program/types.gen.d.ts.map +1 -1
- package/dist/src/arc/text/types.gen.d.ts +54 -1
- package/dist/src/arc/text/types.gen.d.ts.map +1 -1
- package/dist/src/arc/types/types.gen.d.ts +35 -153
- package/dist/src/arc/types/types.gen.d.ts.map +1 -1
- package/dist/src/arc/types.gen.d.ts +98 -2278
- package/dist/src/arc/types.gen.d.ts.map +1 -1
- package/dist/src/auth/auth.d.ts +14 -2
- package/dist/src/auth/auth.d.ts.map +1 -1
- package/dist/src/channel/client.d.ts +113 -75
- package/dist/src/channel/client.d.ts.map +1 -1
- package/dist/src/channel/external.d.ts +0 -1
- package/dist/src/channel/external.d.ts.map +1 -1
- package/dist/src/channel/payload.d.ts +65 -56
- package/dist/src/channel/payload.d.ts.map +1 -1
- package/dist/src/channel/types.gen.d.ts +26 -73
- package/dist/src/channel/types.gen.d.ts.map +1 -1
- package/dist/src/channel/writer.d.ts +1 -3
- package/dist/src/channel/writer.d.ts.map +1 -1
- package/dist/src/client.d.ts +55 -27
- package/dist/src/client.d.ts.map +1 -1
- package/dist/src/connection/client.d.ts +146 -0
- package/dist/src/connection/client.d.ts.map +1 -0
- package/dist/src/connection/external.d.ts +3 -0
- package/dist/src/connection/external.d.ts.map +1 -0
- package/dist/src/connection/index.d.ts +1 -1
- package/dist/src/connection/index.d.ts.map +1 -1
- package/dist/src/connection/status.d.ts +252 -0
- package/dist/src/connection/status.d.ts.map +1 -0
- package/dist/src/control/client.d.ts +31 -7
- package/dist/src/control/client.d.ts.map +1 -1
- package/dist/src/control/state.d.ts +47 -16
- package/dist/src/control/state.d.ts.map +1 -1
- package/dist/src/device/client.d.ts +59 -17
- package/dist/src/device/client.d.ts.map +1 -1
- package/dist/src/device/types.gen.d.ts +17 -67
- package/dist/src/device/types.gen.d.ts.map +1 -1
- package/dist/src/errors.d.ts +17 -20
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/ethercat/external.d.ts +2 -0
- package/dist/src/ethercat/external.d.ts.map +1 -0
- package/dist/src/ethercat/index.d.ts +2 -0
- package/dist/src/ethercat/index.d.ts.map +1 -0
- package/dist/src/ethercat/types.gen.d.ts +243 -0
- package/dist/src/ethercat/types.gen.d.ts.map +1 -0
- package/dist/src/framer/adapter.d.ts +8 -5
- package/dist/src/framer/adapter.d.ts.map +1 -1
- package/dist/src/framer/benchutil.d.ts +19 -0
- package/dist/src/framer/benchutil.d.ts.map +1 -0
- package/dist/src/framer/cache/cache.d.ts +38 -0
- package/dist/src/framer/cache/cache.d.ts.map +1 -0
- package/dist/src/framer/cache/dynamic.d.ts +71 -0
- package/dist/src/framer/cache/dynamic.d.ts.map +1 -0
- package/dist/src/framer/cache/reader.d.ts +43 -0
- package/dist/src/framer/cache/reader.d.ts.map +1 -0
- package/dist/src/framer/cache/static.d.ts +66 -0
- package/dist/src/framer/cache/static.d.ts.map +1 -0
- package/dist/src/framer/cache/streamer.d.ts +86 -0
- package/dist/src/framer/cache/streamer.d.ts.map +1 -0
- package/dist/src/framer/cache/transform.d.ts +18 -0
- package/dist/src/framer/cache/transform.d.ts.map +1 -0
- package/dist/src/framer/cache/unary.d.ts +37 -0
- package/dist/src/framer/cache/unary.d.ts.map +1 -0
- package/dist/src/framer/client.d.ts +35 -14
- package/dist/src/framer/client.d.ts.map +1 -1
- package/dist/src/framer/codec.d.ts.map +1 -1
- package/dist/src/framer/deleter.d.ts +3 -2
- package/dist/src/framer/deleter.d.ts.map +1 -1
- package/dist/src/framer/external.d.ts +6 -0
- package/dist/src/framer/external.d.ts.map +1 -1
- package/dist/src/framer/feed.d.ts +40 -0
- package/dist/src/framer/feed.d.ts.map +1 -0
- package/dist/src/framer/frame.d.ts +16 -20
- package/dist/src/framer/frame.d.ts.map +1 -1
- package/dist/src/framer/hardened.d.ts +70 -0
- package/dist/src/framer/hardened.d.ts.map +1 -0
- package/dist/src/framer/iterator.d.ts +36 -43
- package/dist/src/framer/iterator.d.ts.map +1 -1
- package/dist/src/framer/reader.d.ts +3 -2
- package/dist/src/framer/reader.d.ts.map +1 -1
- package/dist/src/framer/streamer.d.ts +132 -205
- package/dist/src/framer/streamer.d.ts.map +1 -1
- package/dist/src/framer/writer.d.ts +130 -161
- package/dist/src/framer/writer.d.ts.map +1 -1
- package/dist/src/group/client.d.ts +66 -9
- package/dist/src/group/client.d.ts.map +1 -1
- package/dist/src/group/types.gen.d.ts +2 -2
- package/dist/src/http/external.d.ts +2 -0
- package/dist/src/http/external.d.ts.map +1 -0
- package/dist/src/http/index.d.ts +2 -0
- package/dist/src/http/index.d.ts.map +1 -0
- package/dist/src/http/types.gen.d.ts +451 -0
- package/dist/src/http/types.gen.d.ts.map +1 -0
- package/dist/src/imex/client.d.ts +88 -0
- package/dist/src/imex/client.d.ts.map +1 -0
- package/dist/src/imex/index.d.ts +2 -0
- package/dist/src/imex/index.d.ts.map +1 -0
- package/dist/src/index.d.ts +18 -5
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/label/client.d.ts +55 -36
- package/dist/src/label/client.d.ts.map +1 -1
- package/dist/src/label/external.d.ts +2 -0
- package/dist/src/label/external.d.ts.map +1 -1
- package/dist/src/label/payload.d.ts +4 -46
- package/dist/src/label/payload.d.ts.map +1 -1
- package/dist/src/label/store.d.ts +8 -0
- package/dist/src/label/store.d.ts.map +1 -0
- package/dist/src/label/types.gen.d.ts +45 -0
- package/dist/src/label/types.gen.d.ts.map +1 -0
- package/dist/src/labjack/external.d.ts +2 -0
- package/dist/src/labjack/external.d.ts.map +1 -0
- package/dist/src/labjack/index.d.ts +2 -0
- package/dist/src/labjack/index.d.ts.map +1 -0
- package/dist/src/labjack/types.gen.d.ts +442 -0
- package/dist/src/labjack/types.gen.d.ts.map +1 -0
- package/dist/src/lineplot/actions.d.ts +914 -0
- package/dist/src/lineplot/actions.d.ts.map +1 -0
- package/dist/src/lineplot/actions.gen.d.ts +4208 -0
- package/dist/src/lineplot/actions.gen.d.ts.map +1 -0
- package/dist/src/lineplot/client.d.ts +66 -16
- package/dist/src/lineplot/client.d.ts.map +1 -1
- package/dist/src/lineplot/external.d.ts +3 -0
- package/dist/src/lineplot/external.d.ts.map +1 -1
- package/dist/src/lineplot/line.d.ts +16 -0
- package/dist/src/lineplot/line.d.ts.map +1 -0
- package/dist/src/lineplot/types.gen.d.ts +837 -14
- package/dist/src/lineplot/types.gen.d.ts.map +1 -1
- package/dist/src/log/actions.d.ts +271 -0
- package/dist/src/log/actions.d.ts.map +1 -0
- package/dist/src/log/actions.gen.d.ts +1529 -0
- package/dist/src/log/actions.gen.d.ts.map +1 -0
- package/dist/src/log/client.d.ts +66 -16
- package/dist/src/log/client.d.ts.map +1 -1
- package/dist/src/log/external.d.ts +2 -0
- package/dist/src/log/external.d.ts.map +1 -1
- package/dist/src/log/types.gen.d.ts +139 -14
- package/dist/src/log/types.gen.d.ts.map +1 -1
- package/dist/src/modbus/external.d.ts +2 -0
- package/dist/src/modbus/external.d.ts.map +1 -0
- package/dist/src/modbus/index.d.ts +2 -0
- package/dist/src/modbus/index.d.ts.map +1 -0
- package/dist/src/modbus/types.gen.d.ts +280 -0
- package/dist/src/modbus/types.gen.d.ts.map +1 -0
- package/dist/src/ni/external.d.ts +2 -0
- package/dist/src/ni/external.d.ts.map +1 -0
- package/dist/src/ni/index.d.ts +2 -0
- package/dist/src/ni/index.d.ts.map +1 -0
- package/dist/src/ni/types.gen.d.ts +21029 -0
- package/dist/src/ni/types.gen.d.ts.map +1 -0
- package/dist/src/node/index.d.ts +2 -0
- package/dist/src/node/index.d.ts.map +1 -0
- package/dist/src/node/types.gen.d.ts +4 -0
- package/dist/src/node/types.gen.d.ts.map +1 -0
- package/dist/src/ontology/client.d.ts +314 -67
- package/dist/src/ontology/client.d.ts.map +1 -1
- package/dist/src/ontology/external.d.ts +1 -0
- package/dist/src/ontology/external.d.ts.map +1 -1
- package/dist/src/ontology/payload.d.ts +60 -18
- package/dist/src/ontology/payload.d.ts.map +1 -1
- package/dist/src/ontology/store.d.ts +32 -0
- package/dist/src/ontology/store.d.ts.map +1 -0
- package/dist/src/ontology/types.gen.d.ts +3 -2
- package/dist/src/ontology/types.gen.d.ts.map +1 -1
- package/dist/src/ontology/writer.d.ts +16 -10
- package/dist/src/ontology/writer.d.ts.map +1 -1
- package/dist/src/opcua/external.d.ts +2 -0
- package/dist/src/opcua/external.d.ts.map +1 -0
- package/dist/src/opcua/index.d.ts +2 -0
- package/dist/src/opcua/index.d.ts.map +1 -0
- package/dist/src/opcua/types.gen.d.ts +82 -0
- package/dist/src/opcua/types.gen.d.ts.map +1 -0
- package/dist/src/pagerduty/external.d.ts +2 -0
- package/dist/src/pagerduty/external.d.ts.map +1 -0
- package/dist/src/pagerduty/index.d.ts +2 -0
- package/dist/src/pagerduty/index.d.ts.map +1 -0
- package/dist/src/pagerduty/types.gen.d.ts +30 -0
- package/dist/src/pagerduty/types.gen.d.ts.map +1 -0
- package/dist/src/panel/actions.d.ts +273 -0
- package/dist/src/panel/actions.d.ts.map +1 -0
- package/dist/src/panel/actions.gen.d.ts +1255 -0
- package/dist/src/panel/actions.gen.d.ts.map +1 -0
- package/dist/src/panel/client.d.ts +148 -0
- package/dist/src/panel/client.d.ts.map +1 -0
- package/dist/src/panel/external.d.ts +6 -0
- package/dist/src/panel/external.d.ts.map +1 -0
- package/dist/src/panel/index.d.ts +2 -0
- package/dist/src/panel/index.d.ts.map +1 -0
- package/dist/src/panel/tree.d.ts +50 -0
- package/dist/src/panel/tree.d.ts.map +1 -0
- package/dist/src/panel/types.gen.d.ts +370 -0
- package/dist/src/panel/types.gen.d.ts.map +1 -0
- package/dist/src/project/client.d.ts +89 -0
- package/dist/src/project/client.d.ts.map +1 -0
- package/dist/src/project/external.d.ts.map +1 -0
- package/dist/src/project/index.d.ts +2 -0
- package/dist/src/project/index.d.ts.map +1 -0
- package/dist/src/project/types.gen.d.ts +27 -0
- package/dist/src/project/types.gen.d.ts.map +1 -0
- package/dist/src/query/cache.d.ts +132 -0
- package/dist/src/query/cache.d.ts.map +1 -0
- package/dist/src/query/deleted.d.ts +20 -0
- package/dist/src/query/deleted.d.ts.map +1 -0
- package/dist/src/query/derived.d.ts +33 -0
- package/dist/src/query/derived.d.ts.map +1 -0
- package/dist/src/query/external.d.ts +10 -0
- package/dist/src/query/external.d.ts.map +1 -0
- package/dist/src/query/index.d.ts +2 -0
- package/dist/src/query/index.d.ts.map +1 -0
- package/dist/src/query/query.d.ts +235 -0
- package/dist/src/query/query.d.ts.map +1 -0
- package/dist/src/query/retriever.d.ts +135 -0
- package/dist/src/query/retriever.d.ts.map +1 -0
- package/dist/src/query/streamer.d.ts +67 -0
- package/dist/src/query/streamer.d.ts.map +1 -0
- package/dist/src/query/table.d.ts +219 -0
- package/dist/src/query/table.d.ts.map +1 -0
- package/dist/src/query/types.d.ts +35 -0
- package/dist/src/query/types.d.ts.map +1 -0
- package/dist/src/query/write.d.ts +21 -0
- package/dist/src/query/write.d.ts.map +1 -0
- package/dist/src/rack/client.d.ts +58 -20
- package/dist/src/rack/client.d.ts.map +1 -1
- package/dist/src/rack/types.gen.d.ts +11 -12
- package/dist/src/rack/types.gen.d.ts.map +1 -1
- package/dist/src/range/alias/types.gen.d.ts +2 -3
- package/dist/src/range/alias/types.gen.d.ts.map +1 -1
- package/dist/src/ranger/client.d.ts +138 -27
- package/dist/src/ranger/client.d.ts.map +1 -1
- package/dist/src/ranger/kv/client.d.ts +7 -4
- package/dist/src/ranger/kv/client.d.ts.map +1 -1
- package/dist/src/ranger/payload.d.ts +3 -0
- package/dist/src/ranger/payload.d.ts.map +1 -1
- package/dist/src/ranger/types.gen.d.ts +45 -101
- package/dist/src/ranger/types.gen.d.ts.map +1 -1
- package/dist/src/ranger/writer.d.ts +2 -74
- package/dist/src/ranger/writer.d.ts.map +1 -1
- package/dist/src/schematic/actions.d.ts +90 -33
- package/dist/src/schematic/actions.d.ts.map +1 -1
- package/dist/src/schematic/actions.gen.d.ts +207 -114
- package/dist/src/schematic/actions.gen.d.ts.map +1 -1
- package/dist/src/schematic/client.d.ts +70 -68
- package/dist/src/schematic/client.d.ts.map +1 -1
- package/dist/src/schematic/symbol/client.d.ts +133 -27
- package/dist/src/schematic/symbol/client.d.ts.map +1 -1
- package/dist/src/schematic/symbol/types.gen.d.ts +258 -153
- package/dist/src/schematic/symbol/types.gen.d.ts.map +1 -1
- package/dist/src/schematic/types.gen.d.ts +17 -96
- package/dist/src/schematic/types.gen.d.ts.map +1 -1
- package/dist/src/status/client.d.ts +69 -14
- package/dist/src/status/client.d.ts.map +1 -1
- package/dist/src/status/external.d.ts +2 -0
- package/dist/src/status/external.d.ts.map +1 -1
- package/dist/src/status/payload.d.ts +2 -36
- package/dist/src/status/payload.d.ts.map +1 -1
- package/dist/src/status/status.d.ts +65 -0
- package/dist/src/status/status.d.ts.map +1 -0
- package/dist/src/status/types.gen.d.ts +58 -0
- package/dist/src/status/types.gen.d.ts.map +1 -0
- package/dist/src/table/actions.d.ts +72 -13
- package/dist/src/table/actions.d.ts.map +1 -1
- package/dist/src/table/actions.gen.d.ts +221 -137
- package/dist/src/table/actions.gen.d.ts.map +1 -1
- package/dist/src/table/client.d.ts +64 -40
- package/dist/src/table/client.d.ts.map +1 -1
- package/dist/src/table/types.gen.d.ts +20 -55
- package/dist/src/table/types.gen.d.ts.map +1 -1
- package/dist/src/task/client.d.ts +149 -28
- package/dist/src/task/client.d.ts.map +1 -1
- package/dist/src/task/types.gen.d.ts +71 -89
- package/dist/src/task/types.gen.d.ts.map +1 -1
- package/dist/src/testutil/access.d.ts +27 -1
- package/dist/src/testutil/access.d.ts.map +1 -1
- package/dist/src/testutil/channels.d.ts +2 -0
- package/dist/src/testutil/channels.d.ts.map +1 -1
- package/dist/src/testutil/client.d.ts +5 -0
- package/dist/src/testutil/client.d.ts.map +1 -1
- package/dist/src/testutil/connection.d.ts +10 -0
- package/dist/src/testutil/connection.d.ts.map +1 -0
- package/dist/src/testutil/index.d.ts +9 -0
- package/dist/src/testutil/index.d.ts.map +1 -0
- package/dist/src/testutil/panels.d.ts +8 -0
- package/dist/src/testutil/panels.d.ts.map +1 -0
- package/dist/src/testutil/proxy.d.ts +29 -0
- package/dist/src/testutil/proxy.d.ts.map +1 -0
- package/dist/src/testutil/query.d.ts +7 -0
- package/dist/src/testutil/query.d.ts.map +1 -0
- package/dist/src/testutil/telem.d.ts +4 -0
- package/dist/src/testutil/telem.d.ts.map +1 -1
- package/dist/src/transport.d.ts +10 -4
- package/dist/src/transport.d.ts.map +1 -1
- package/dist/src/user/client.d.ts +29 -28
- package/dist/src/user/client.d.ts.map +1 -1
- package/dist/src/user/external.d.ts +1 -1
- package/dist/src/user/external.d.ts.map +1 -1
- package/dist/src/user/types.gen.d.ts +4 -4
- package/dist/src/util/retrieve.d.ts +2 -2
- package/dist/src/util/retrieve.d.ts.map +1 -1
- package/dist/src/util/telem.d.ts.map +1 -1
- package/dist/src/view/client.d.ts +30 -14
- package/dist/src/view/client.d.ts.map +1 -1
- package/dist/src/view/types.gen.d.ts +7 -15
- package/dist/src/view/types.gen.d.ts.map +1 -1
- package/dist/testutil.js +189 -0
- package/dist/testutil.js.map +1 -0
- package/package.json +40 -17
- package/src/access/client.ts +14 -3
- package/src/access/enforce.ts +0 -3
- package/src/access/external.ts +1 -0
- package/src/access/granted.ts +114 -0
- package/src/access/policy/client.ts +135 -43
- package/src/access/policy/types.gen.ts +9 -11
- package/src/access/role/client.ts +160 -38
- package/src/access/role/types.gen.ts +8 -12
- package/src/actions/actions.ts +5 -6
- package/src/actions/controller.ts +626 -0
- package/src/actions/external.ts +11 -0
- package/src/arc/actions.gen.ts +313 -0
- package/src/arc/actions.ts +192 -0
- package/src/arc/client.ts +424 -41
- package/src/arc/compiler/types.gen.ts +5 -6
- package/src/arc/external.ts +2 -0
- package/src/arc/graph/types.gen.ts +24 -22
- package/src/arc/ir/index.ts +1 -1
- package/{eslint.config.ts → src/arc/ir/ir.ts} +1 -4
- package/src/arc/ir/types.gen.ts +42 -41
- package/src/arc/text/types.gen.ts +21 -2
- package/src/arc/types/types.gen.ts +40 -32
- package/src/arc/types.gen.ts +31 -29
- package/src/auth/auth.ts +40 -8
- package/src/channel/client.ts +529 -132
- package/src/channel/external.ts +0 -1
- package/src/channel/payload.ts +30 -3
- package/src/channel/types.gen.ts +37 -48
- package/src/channel/writer.ts +2 -11
- package/src/client.ts +215 -91
- package/src/connection/client.ts +495 -0
- package/src/connection/external.ts +34 -0
- package/src/connection/index.ts +1 -1
- package/src/connection/status.ts +442 -0
- package/src/control/client.ts +84 -12
- package/src/control/state.ts +17 -36
- package/src/device/client.ts +293 -41
- package/src/device/types.gen.ts +15 -26
- package/src/errors.ts +45 -22
- package/src/{workspace → ethercat}/external.ts +1 -2
- package/src/{workspace → ethercat}/index.ts +1 -1
- package/src/ethercat/types.gen.ts +151 -0
- package/src/framer/adapter.ts +60 -37
- package/src/framer/benchutil.ts +67 -0
- package/src/framer/cache/cache.ts +115 -0
- package/src/framer/cache/dynamic.ts +279 -0
- package/src/framer/cache/reader.ts +160 -0
- package/src/framer/cache/static.ts +215 -0
- package/src/framer/cache/streamer.ts +391 -0
- package/src/framer/cache/transform.ts +31 -0
- package/src/framer/cache/unary.ts +104 -0
- package/src/framer/client.ts +71 -43
- package/src/framer/codec.ts +55 -18
- package/src/framer/deleter.ts +4 -6
- package/src/framer/external.ts +10 -0
- package/src/framer/feed.ts +108 -0
- package/src/framer/frame.ts +13 -23
- package/src/framer/hardened.ts +283 -0
- package/src/framer/iterator.ts +31 -42
- package/src/framer/reader.ts +11 -11
- package/src/framer/streamer.ts +18 -178
- package/src/framer/writer.ts +39 -59
- package/src/group/client.ts +158 -23
- package/src/http/external.ts +10 -0
- package/src/{cluster → http}/index.ts +1 -1
- package/src/http/types.gen.ts +245 -0
- package/src/imex/client.ts +125 -0
- package/src/imex/index.ts +10 -0
- package/src/index.ts +18 -6
- package/src/label/client.ts +193 -54
- package/src/label/external.ts +2 -0
- package/src/label/payload.ts +4 -9
- package/src/label/store.ts +28 -0
- package/src/label/types.gen.ts +31 -0
- package/src/labjack/external.ts +10 -0
- package/src/labjack/index.ts +10 -0
- package/src/labjack/types.gen.ts +251 -0
- package/src/lineplot/actions.gen.ts +880 -0
- package/src/lineplot/actions.ts +535 -0
- package/src/lineplot/client.ts +224 -52
- package/src/lineplot/external.ts +3 -0
- package/src/lineplot/line.ts +80 -0
- package/src/lineplot/types.gen.ts +225 -12
- package/src/log/actions.gen.ts +474 -0
- package/src/log/actions.ts +242 -0
- package/src/log/client.ts +223 -52
- package/src/log/external.ts +2 -0
- package/src/log/types.gen.ts +45 -14
- package/src/modbus/external.ts +10 -0
- package/src/modbus/index.ts +10 -0
- package/src/modbus/types.gen.ts +185 -0
- package/src/ni/external.ts +10 -0
- package/src/ni/index.ts +10 -0
- package/src/ni/types.gen.ts +1632 -0
- package/src/node/index.ts +10 -0
- package/src/{cluster → node}/types.gen.ts +2 -2
- package/src/ontology/client.ts +408 -99
- package/src/ontology/external.ts +7 -0
- package/src/ontology/payload.ts +48 -7
- package/src/ontology/store.ts +83 -0
- package/src/ontology/types.gen.ts +2 -1
- package/src/ontology/writer.ts +1 -0
- package/src/opcua/external.ts +10 -0
- package/src/opcua/index.ts +10 -0
- package/src/opcua/types.gen.ts +65 -0
- package/src/pagerduty/external.ts +10 -0
- package/src/pagerduty/index.ts +10 -0
- package/src/pagerduty/types.gen.ts +41 -0
- package/src/panel/actions.gen.ts +267 -0
- package/src/panel/actions.ts +357 -0
- package/src/panel/client.ts +327 -0
- package/src/panel/external.ts +14 -0
- package/src/panel/index.ts +10 -0
- package/src/panel/tree.ts +163 -0
- package/src/panel/types.gen.ts +164 -0
- package/src/project/client.ts +273 -0
- package/src/project/external.ts +11 -0
- package/src/project/index.ts +10 -0
- package/src/project/types.gen.ts +40 -0
- package/src/query/cache.ts +326 -0
- package/src/query/deleted.ts +38 -0
- package/src/query/derived.ts +101 -0
- package/src/query/external.ts +51 -0
- package/src/query/index.ts +10 -0
- package/src/query/query.ts +865 -0
- package/src/query/retriever.ts +308 -0
- package/src/query/streamer.ts +207 -0
- package/src/query/table.ts +625 -0
- package/src/query/types.ts +54 -0
- package/src/query/write.ts +42 -0
- package/src/rack/client.ts +233 -45
- package/src/rack/types.gen.ts +15 -16
- package/src/range/alias/types.gen.ts +2 -3
- package/src/ranger/client.ts +581 -70
- package/src/ranger/kv/client.ts +52 -21
- package/src/ranger/payload.ts +3 -0
- package/src/ranger/types.gen.ts +21 -23
- package/src/ranger/writer.ts +4 -8
- package/src/schematic/actions.gen.ts +62 -53
- package/src/schematic/actions.ts +44 -42
- package/src/schematic/client.ts +226 -70
- package/src/schematic/symbol/client.ts +277 -48
- package/src/schematic/symbol/types.gen.ts +22 -34
- package/src/schematic/types.gen.ts +22 -29
- package/src/status/client.ts +321 -44
- package/src/status/external.ts +2 -0
- package/src/status/payload.ts +1 -23
- package/src/status/status.ts +241 -0
- package/src/status/types.gen.ts +108 -0
- package/src/table/actions.gen.ts +96 -63
- package/src/table/actions.ts +44 -19
- package/src/table/client.ts +220 -56
- package/src/table/types.gen.ts +24 -31
- package/src/task/client.ts +580 -101
- package/src/task/types.gen.ts +68 -75
- package/src/testutil/access.ts +102 -6
- package/src/testutil/channels.ts +29 -0
- package/src/testutil/client.ts +27 -2
- package/src/testutil/connection.ts +47 -0
- package/src/testutil/index.ts +17 -0
- package/src/testutil/panels.ts +26 -0
- package/src/testutil/proxy.ts +106 -0
- package/src/testutil/query.ts +28 -0
- package/src/testutil/telem.ts +17 -1
- package/src/transport.ts +18 -7
- package/src/user/client.ts +165 -64
- package/src/user/external.ts +1 -1
- package/src/user/types.gen.ts +5 -5
- package/src/util/retrieve.ts +4 -4
- package/src/util/telem.ts +0 -1
- package/src/view/client.ts +120 -37
- package/src/view/types.gen.ts +8 -11
- package/.turbo/turbo-build.log +0 -20
- package/.vscode/settings.json +0 -3
- package/CONTRIBUTING.md +0 -47
- package/dist/client.cjs +0 -118
- package/dist/eslint.config.d.ts +0 -4
- package/dist/eslint.config.d.ts.map +0 -1
- package/dist/src/access/enforce.spec.d.ts +0 -2
- package/dist/src/access/enforce.spec.d.ts.map +0 -1
- package/dist/src/access/policy/access.spec.d.ts +0 -2
- package/dist/src/access/policy/access.spec.d.ts.map +0 -1
- package/dist/src/access/role/role.spec.d.ts +0 -2
- package/dist/src/access/role/role.spec.d.ts.map +0 -1
- package/dist/src/actions/actions.spec.d.ts +0 -2
- package/dist/src/actions/actions.spec.d.ts.map +0 -1
- package/dist/src/arc/access.spec.d.ts +0 -2
- package/dist/src/arc/access.spec.d.ts.map +0 -1
- package/dist/src/arc/arc.spec.d.ts +0 -2
- package/dist/src/arc/arc.spec.d.ts.map +0 -1
- package/dist/src/arc/lsp.spec.d.ts +0 -2
- package/dist/src/arc/lsp.spec.d.ts.map +0 -1
- package/dist/src/auth/auth.spec.d.ts +0 -2
- package/dist/src/auth/auth.spec.d.ts.map +0 -1
- package/dist/src/channel/access.spec.d.ts +0 -2
- package/dist/src/channel/access.spec.d.ts.map +0 -1
- package/dist/src/channel/batchRetriever.spec.d.ts +0 -2
- package/dist/src/channel/batchRetriever.spec.d.ts.map +0 -1
- package/dist/src/channel/channel.spec.d.ts +0 -2
- package/dist/src/channel/channel.spec.d.ts.map +0 -1
- package/dist/src/channel/payload.spec.d.ts +0 -2
- package/dist/src/channel/payload.spec.d.ts.map +0 -1
- package/dist/src/channel/retriever.d.ts +0 -64
- package/dist/src/channel/retriever.d.ts.map +0 -1
- package/dist/src/cluster/index.d.ts +0 -2
- package/dist/src/cluster/index.d.ts.map +0 -1
- package/dist/src/cluster/types.gen.d.ts +0 -4
- package/dist/src/cluster/types.gen.d.ts.map +0 -1
- package/dist/src/connection/checker.d.ts +0 -86
- package/dist/src/connection/checker.d.ts.map +0 -1
- package/dist/src/connection/connection.spec.d.ts +0 -2
- package/dist/src/connection/connection.spec.d.ts.map +0 -1
- package/dist/src/connection.spec.d.ts +0 -2
- package/dist/src/connection.spec.d.ts.map +0 -1
- package/dist/src/control/state.spec.d.ts +0 -2
- package/dist/src/control/state.spec.d.ts.map +0 -1
- package/dist/src/device/access.spec.d.ts +0 -2
- package/dist/src/device/access.spec.d.ts.map +0 -1
- package/dist/src/device/device.spec.d.ts +0 -2
- package/dist/src/device/device.spec.d.ts.map +0 -1
- package/dist/src/device/payload.spec.d.ts +0 -2
- package/dist/src/device/payload.spec.d.ts.map +0 -1
- package/dist/src/errors.spec.d.ts +0 -2
- package/dist/src/errors.spec.d.ts.map +0 -1
- package/dist/src/framer/adapter.spec.d.ts +0 -2
- package/dist/src/framer/adapter.spec.d.ts.map +0 -1
- package/dist/src/framer/client.spec.d.ts +0 -2
- package/dist/src/framer/client.spec.d.ts.map +0 -1
- package/dist/src/framer/codec.spec.d.ts +0 -2
- package/dist/src/framer/codec.spec.d.ts.map +0 -1
- package/dist/src/framer/deleter.spec.d.ts +0 -2
- package/dist/src/framer/deleter.spec.d.ts.map +0 -1
- package/dist/src/framer/frame.spec.d.ts +0 -2
- package/dist/src/framer/frame.spec.d.ts.map +0 -1
- package/dist/src/framer/iterator.spec.d.ts +0 -2
- package/dist/src/framer/iterator.spec.d.ts.map +0 -1
- package/dist/src/framer/reader.spec.d.ts +0 -2
- package/dist/src/framer/reader.spec.d.ts.map +0 -1
- package/dist/src/framer/streamer.spec.d.ts +0 -2
- package/dist/src/framer/streamer.spec.d.ts.map +0 -1
- package/dist/src/framer/writer.spec.d.ts +0 -2
- package/dist/src/framer/writer.spec.d.ts.map +0 -1
- package/dist/src/group/access.spec.d.ts +0 -2
- package/dist/src/group/access.spec.d.ts.map +0 -1
- package/dist/src/group/group.spec.d.ts +0 -2
- package/dist/src/group/group.spec.d.ts.map +0 -1
- package/dist/src/label/access.spec.d.ts +0 -2
- package/dist/src/label/access.spec.d.ts.map +0 -1
- package/dist/src/label/label.spec.d.ts +0 -2
- package/dist/src/label/label.spec.d.ts.map +0 -1
- package/dist/src/lineplot/access.spec.d.ts +0 -2
- package/dist/src/lineplot/access.spec.d.ts.map +0 -1
- package/dist/src/lineplot/lineplot.spec.d.ts +0 -2
- package/dist/src/lineplot/lineplot.spec.d.ts.map +0 -1
- package/dist/src/log/access.spec.d.ts +0 -2
- package/dist/src/log/access.spec.d.ts.map +0 -1
- package/dist/src/log/log.spec.d.ts +0 -2
- package/dist/src/log/log.spec.d.ts.map +0 -1
- package/dist/src/ontology/ontology.spec.d.ts +0 -2
- package/dist/src/ontology/ontology.spec.d.ts.map +0 -1
- package/dist/src/rack/access.spec.d.ts +0 -2
- package/dist/src/rack/access.spec.d.ts.map +0 -1
- package/dist/src/rack/rack.spec.d.ts +0 -2
- package/dist/src/rack/rack.spec.d.ts.map +0 -1
- package/dist/src/ranger/access.spec.d.ts +0 -2
- package/dist/src/ranger/access.spec.d.ts.map +0 -1
- package/dist/src/ranger/alias/payload.spec.d.ts +0 -2
- package/dist/src/ranger/alias/payload.spec.d.ts.map +0 -1
- package/dist/src/ranger/ranger.spec.d.ts +0 -2
- package/dist/src/ranger/ranger.spec.d.ts.map +0 -1
- package/dist/src/schematic/access.spec.d.ts +0 -2
- package/dist/src/schematic/access.spec.d.ts.map +0 -1
- package/dist/src/schematic/actions.spec.d.ts +0 -2
- package/dist/src/schematic/actions.spec.d.ts.map +0 -1
- package/dist/src/schematic/schematic.spec.d.ts +0 -2
- package/dist/src/schematic/schematic.spec.d.ts.map +0 -1
- package/dist/src/schematic/symbol/access.spec.d.ts +0 -2
- package/dist/src/schematic/symbol/access.spec.d.ts.map +0 -1
- package/dist/src/schematic/symbol/client.spec.d.ts +0 -2
- package/dist/src/schematic/symbol/client.spec.d.ts.map +0 -1
- package/dist/src/status/access.spec.d.ts +0 -2
- package/dist/src/status/access.spec.d.ts.map +0 -1
- package/dist/src/status/status.spec.d.ts +0 -2
- package/dist/src/status/status.spec.d.ts.map +0 -1
- package/dist/src/table/access.spec.d.ts +0 -2
- package/dist/src/table/access.spec.d.ts.map +0 -1
- package/dist/src/table/table.spec.d.ts +0 -2
- package/dist/src/table/table.spec.d.ts.map +0 -1
- package/dist/src/task/access.spec.d.ts +0 -2
- package/dist/src/task/access.spec.d.ts.map +0 -1
- package/dist/src/task/payload.spec.d.ts +0 -2
- package/dist/src/task/payload.spec.d.ts.map +0 -1
- package/dist/src/task/task.spec.d.ts +0 -2
- package/dist/src/task/task.spec.d.ts.map +0 -1
- package/dist/src/user/access.spec.d.ts +0 -2
- package/dist/src/user/access.spec.d.ts.map +0 -1
- package/dist/src/user/user.spec.d.ts +0 -2
- package/dist/src/user/user.spec.d.ts.map +0 -1
- package/dist/src/util/retrieve.spec.d.ts +0 -2
- package/dist/src/util/retrieve.spec.d.ts.map +0 -1
- package/dist/src/view/view.spec.d.ts +0 -2
- package/dist/src/view/view.spec.d.ts.map +0 -1
- package/dist/src/workspace/access.spec.d.ts +0 -2
- package/dist/src/workspace/access.spec.d.ts.map +0 -1
- package/dist/src/workspace/client.d.ts +0 -36
- package/dist/src/workspace/client.d.ts.map +0 -1
- package/dist/src/workspace/external.d.ts.map +0 -1
- package/dist/src/workspace/index.d.ts +0 -2
- package/dist/src/workspace/index.d.ts.map +0 -1
- package/dist/src/workspace/types.gen.d.ts +0 -34
- package/dist/src/workspace/types.gen.d.ts.map +0 -1
- package/dist/src/workspace/workspace.spec.d.ts +0 -2
- package/dist/src/workspace/workspace.spec.d.ts.map +0 -1
- package/examples/node/basicReadWrite.js +0 -86
- package/examples/node/createChannels.js +0 -50
- package/examples/node/createRange.js +0 -67
- package/examples/node/package-lock.json +0 -133
- package/examples/node/package.json +0 -17
- package/examples/node/readLatest.js +0 -76
- package/examples/node/seriesAndFrames.js +0 -173
- package/examples/node/streamRead.js +0 -50
- package/examples/node/streamWrite.js +0 -87
- package/src/access/enforce.spec.ts +0 -188
- package/src/access/policy/access.spec.ts +0 -147
- package/src/access/role/role.spec.ts +0 -95
- package/src/actions/actions.spec.ts +0 -229
- package/src/arc/access.spec.ts +0 -149
- package/src/arc/arc.spec.ts +0 -44
- package/src/arc/lsp.spec.ts +0 -717
- package/src/auth/auth.spec.ts +0 -101
- package/src/channel/access.spec.ts +0 -116
- package/src/channel/batchRetriever.spec.ts +0 -115
- package/src/channel/channel.spec.ts +0 -352
- package/src/channel/payload.spec.ts +0 -117
- package/src/channel/retriever.ts +0 -252
- package/src/connection/checker.ts +0 -203
- package/src/connection/connection.spec.ts +0 -152
- package/src/connection.spec.ts +0 -145
- package/src/control/state.spec.ts +0 -22
- package/src/device/access.spec.ts +0 -159
- package/src/device/device.spec.ts +0 -461
- package/src/device/payload.spec.ts +0 -142
- package/src/errors.spec.ts +0 -71
- package/src/framer/adapter.spec.ts +0 -620
- package/src/framer/client.spec.ts +0 -180
- package/src/framer/codec.spec.ts +0 -383
- package/src/framer/deleter.spec.ts +0 -103
- package/src/framer/frame.spec.ts +0 -973
- package/src/framer/iterator.spec.ts +0 -169
- package/src/framer/reader.spec.ts +0 -865
- package/src/framer/streamer.spec.ts +0 -871
- package/src/framer/writer.spec.ts +0 -486
- package/src/group/access.spec.ts +0 -77
- package/src/group/group.spec.ts +0 -65
- package/src/label/access.spec.ts +0 -109
- package/src/label/label.spec.ts +0 -83
- package/src/lineplot/access.spec.ts +0 -134
- package/src/lineplot/lineplot.spec.ts +0 -120
- package/src/log/access.spec.ts +0 -132
- package/src/log/log.spec.ts +0 -106
- package/src/ontology/ontology.spec.ts +0 -521
- package/src/rack/access.spec.ts +0 -102
- package/src/rack/rack.spec.ts +0 -171
- package/src/ranger/access.spec.ts +0 -115
- package/src/ranger/alias/payload.spec.ts +0 -52
- package/src/ranger/ranger.spec.ts +0 -343
- package/src/schematic/access.spec.ts +0 -134
- package/src/schematic/actions.spec.ts +0 -699
- package/src/schematic/schematic.spec.ts +0 -340
- package/src/schematic/symbol/access.spec.ts +0 -172
- package/src/schematic/symbol/client.spec.ts +0 -160
- package/src/status/access.spec.ts +0 -129
- package/src/status/status.spec.ts +0 -448
- package/src/table/access.spec.ts +0 -128
- package/src/table/table.spec.ts +0 -651
- package/src/task/access.spec.ts +0 -131
- package/src/task/payload.spec.ts +0 -113
- package/src/task/task.spec.ts +0 -657
- package/src/user/access.spec.ts +0 -107
- package/src/user/user.spec.ts +0 -290
- package/src/util/retrieve.spec.ts +0 -49
- package/src/view/view.spec.ts +0 -165
- package/src/workspace/access.spec.ts +0 -108
- package/src/workspace/client.ts +0 -112
- package/src/workspace/types.gen.ts +0 -46
- package/src/workspace/workspace.spec.ts +0 -111
- package/tsconfig.json +0 -5
- package/tsconfig.vite.json +0 -4
- package/vite.config.ts +0 -29
- /package/dist/src/{workspace → project}/external.d.ts +0 -0
|
@@ -0,0 +1,625 @@
|
|
|
1
|
+
// Copyright 2026 Synnax Labs, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Use of this software is governed by the Business Source License included in the file
|
|
4
|
+
// licenses/BSL.txt.
|
|
5
|
+
//
|
|
6
|
+
// As of the Change Date specified in that file, in accordance with the Business Source
|
|
7
|
+
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
|
+
// included in the file licenses/APL.txt.
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
array,
|
|
12
|
+
type CrudeTimeSpan,
|
|
13
|
+
debounce,
|
|
14
|
+
deep,
|
|
15
|
+
destructor,
|
|
16
|
+
errors,
|
|
17
|
+
type record,
|
|
18
|
+
state,
|
|
19
|
+
TimeSpan,
|
|
20
|
+
TimeStamp,
|
|
21
|
+
} from "@synnaxlabs/x";
|
|
22
|
+
import type z from "zod";
|
|
23
|
+
|
|
24
|
+
import { NotFoundError } from "@/errors";
|
|
25
|
+
import { Deleted } from "@/query/deleted";
|
|
26
|
+
import { type Listener } from "@/query/streamer";
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Presence of a key in a table: "present" when a live entry exists, "tombstoned"
|
|
30
|
+
* when the entry was deleted and its corpse is retained, "unknown" when the
|
|
31
|
+
* table has never seen the key or the corpse was cleared.
|
|
32
|
+
*/
|
|
33
|
+
export type EntryStatus = "present" | "tombstoned" | "unknown";
|
|
34
|
+
|
|
35
|
+
/** A change to a single entry of a {@link Table}. */
|
|
36
|
+
export type TableEvent<
|
|
37
|
+
Key extends record.Key = record.Key,
|
|
38
|
+
Value extends state.State = state.State,
|
|
39
|
+
> = { variant: "set"; key: Key; value: Value } | { variant: "delete"; key: Key };
|
|
40
|
+
|
|
41
|
+
/** Receives {@link TableEvent}s. Must be synchronous; thrown errors are
|
|
42
|
+
* reported to the table's error sink and do not stop delivery. */
|
|
43
|
+
export interface TableSubscriber<
|
|
44
|
+
Key extends record.Key = record.Key,
|
|
45
|
+
Value extends state.State = state.State,
|
|
46
|
+
> {
|
|
47
|
+
(event: TableEvent<Key, Value>): void;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Receives every event of a batched write as one call, in event order. A single write
|
|
52
|
+
* delivers a batch of one. Same synchrony and error contract as
|
|
53
|
+
* {@link TableSubscriber}.
|
|
54
|
+
*/
|
|
55
|
+
export interface BatchSubscriber<
|
|
56
|
+
Key extends record.Key = record.Key,
|
|
57
|
+
Value extends state.State = state.State,
|
|
58
|
+
> {
|
|
59
|
+
(events: TableEvent<Key, Value>[]): void;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* How fetched records hydrate a table: "set" overwrites entries, "if-absent"
|
|
64
|
+
* preserves existing entries.
|
|
65
|
+
*/
|
|
66
|
+
export type HydrateMode = "set" | "if-absent";
|
|
67
|
+
|
|
68
|
+
/** A table value carrying its entry key, so batch writes and fetches can derive
|
|
69
|
+
* each entry's key from the record itself. */
|
|
70
|
+
export type Keyed<
|
|
71
|
+
Key extends record.Key = record.Key,
|
|
72
|
+
Value extends state.State = state.State,
|
|
73
|
+
> = Value & record.Keyed<Key>;
|
|
74
|
+
|
|
75
|
+
/** Construction arguments for a {@link Table}. */
|
|
76
|
+
export interface TableParams<
|
|
77
|
+
Key extends record.Key = record.Key,
|
|
78
|
+
Value extends state.State = state.State,
|
|
79
|
+
> {
|
|
80
|
+
/** Receives subscriber and fetch errors that have no caller to throw to. */
|
|
81
|
+
onError: (error: Error) => void;
|
|
82
|
+
/** Overrides the deep-equality default used to silence redundant sets. */
|
|
83
|
+
equal?: (a: Value, b: Value, key: Key) => boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Fetches the current records for the given keys from the cluster,
|
|
86
|
+
* returning only the entries that still exist. Powers {@link Table.retrieve},
|
|
87
|
+
* key-announce listeners, and reconciliation. Omit for tables with no
|
|
88
|
+
* server backing (they are skipped by all three).
|
|
89
|
+
*/
|
|
90
|
+
fetch?: (keys: Key[]) => Promise<Array<Keyed<Key, Value>>>;
|
|
91
|
+
/**
|
|
92
|
+
* Hydration mode, "set" by default. Dispatch-backed document tables use
|
|
93
|
+
* "if-absent" so fetches never clobber locally replayed edits.
|
|
94
|
+
*/
|
|
95
|
+
hydrate?: HydrateMode;
|
|
96
|
+
/**
|
|
97
|
+
* Window for coalescing concurrent miss fetches into one fetch call.
|
|
98
|
+
* @default TimeSpan.milliseconds(10)
|
|
99
|
+
*/
|
|
100
|
+
fetchDebounce?: CrudeTimeSpan;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Retrieves by key are strict: a batch containing any vanished key rejects
|
|
105
|
+
* with NotFound instead of returning the survivors. Falls back to probing
|
|
106
|
+
* keys one at a time so survivors are still distinguishable.
|
|
107
|
+
*/
|
|
108
|
+
const fetchSurvivors = async <Key extends record.Key, Value extends state.State>(
|
|
109
|
+
fetch: NonNullable<TableParams<Key, Value>["fetch"]>,
|
|
110
|
+
keys: Key[],
|
|
111
|
+
): Promise<Array<Keyed<Key, Value>>> => {
|
|
112
|
+
try {
|
|
113
|
+
return await fetch(keys);
|
|
114
|
+
} catch (exc) {
|
|
115
|
+
if (!NotFoundError.matches(exc)) throw errors.fromUnknown(exc);
|
|
116
|
+
}
|
|
117
|
+
if (keys.length === 1) return [];
|
|
118
|
+
const probed = await Promise.all(
|
|
119
|
+
keys.map(async (key) => {
|
|
120
|
+
try {
|
|
121
|
+
return await fetch([key]);
|
|
122
|
+
} catch (exc) {
|
|
123
|
+
if (NotFoundError.matches(exc)) return [];
|
|
124
|
+
throw errors.fromUnknown(exc);
|
|
125
|
+
}
|
|
126
|
+
}),
|
|
127
|
+
);
|
|
128
|
+
return probed.flat();
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const DEFAULT_FETCH_DEBOUNCE = TimeSpan.milliseconds(10);
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* The sole owner of one resource's record content and tombstones. Everything else in
|
|
135
|
+
* the cache holds keys into it: answers store key lists, dispatch bookkeeping rides
|
|
136
|
+
* entry deletion, and consumers assemble content at read time. An equal-value set
|
|
137
|
+
* announces nothing: writers echoing state the table already holds (server echoes of
|
|
138
|
+
* optimistic writes, idempotent backfills) are silenced by the equality check rather
|
|
139
|
+
* than by writer identity.
|
|
140
|
+
*/
|
|
141
|
+
export class Table<
|
|
142
|
+
Key extends record.Key = record.Key,
|
|
143
|
+
Value extends state.State = state.State,
|
|
144
|
+
> {
|
|
145
|
+
private readonly entries = new Map<Key, Value>();
|
|
146
|
+
private readonly tombstones = new Map<Key, Deleted<Value>>();
|
|
147
|
+
private readonly broadSubscribers = new Set<TableSubscriber<Key, Value>>();
|
|
148
|
+
private readonly batchSubscribers = new Set<BatchSubscriber<Key, Value>>();
|
|
149
|
+
private readonly keyedSubscribers = new Map<Key, Set<TableSubscriber<Key, Value>>>();
|
|
150
|
+
private batching: TableEvent<Key, Value>[] | null = null;
|
|
151
|
+
private readonly onError: (error: Error) => void;
|
|
152
|
+
private readonly equal: (a: Value, b: Value, key: Key) => boolean;
|
|
153
|
+
private readonly fetchEntries?: (keys: Key[]) => Promise<Array<Keyed<Key, Value>>>;
|
|
154
|
+
private readonly hydrateMode: HydrateMode;
|
|
155
|
+
private readonly fetchBatcher: debounce.Batcher<
|
|
156
|
+
Key[],
|
|
157
|
+
Array<Keyed<Key, Value>>
|
|
158
|
+
> | null;
|
|
159
|
+
private gen = 0;
|
|
160
|
+
|
|
161
|
+
constructor({
|
|
162
|
+
onError,
|
|
163
|
+
equal = deep.equal,
|
|
164
|
+
fetch,
|
|
165
|
+
hydrate = "set",
|
|
166
|
+
fetchDebounce = DEFAULT_FETCH_DEBOUNCE,
|
|
167
|
+
}: TableParams<Key, Value>) {
|
|
168
|
+
this.onError = onError;
|
|
169
|
+
this.equal = equal;
|
|
170
|
+
this.fetchEntries = fetch;
|
|
171
|
+
this.hydrateMode = hydrate;
|
|
172
|
+
this.fetchBatcher =
|
|
173
|
+
fetch == null
|
|
174
|
+
? null
|
|
175
|
+
: new debounce.Batcher({
|
|
176
|
+
interval: fetchDebounce,
|
|
177
|
+
exec: async (requests) => {
|
|
178
|
+
const keys = new Set<Key>();
|
|
179
|
+
requests.forEach(({ req }) => req.forEach((key) => keys.add(key)));
|
|
180
|
+
const fetched = await fetch(Array.from(keys));
|
|
181
|
+
// The window's fetch carries other callers' keys too; each caller
|
|
182
|
+
// hydrates only the entries it asked for.
|
|
183
|
+
requests.forEach(({ req, resolve }) => {
|
|
184
|
+
const mine = new Set(req);
|
|
185
|
+
resolve(fetched.filter(({ key }) => mine.has(key)));
|
|
186
|
+
});
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
private setOne(
|
|
192
|
+
key: Key,
|
|
193
|
+
value: state.SetArg<Value | undefined>,
|
|
194
|
+
): destructor.Destructor | undefined {
|
|
195
|
+
const prev = this.entries.get(key);
|
|
196
|
+
const next = state.executeSetter(value, prev);
|
|
197
|
+
if (next == null || (prev != null && this.equal(next, prev, key))) return undefined;
|
|
198
|
+
const prevTombstone = this.tombstones.get(key);
|
|
199
|
+
this.tombstones.delete(key);
|
|
200
|
+
this.entries.set(key, next);
|
|
201
|
+
this.notify({ variant: "set", key, value: next });
|
|
202
|
+
|
|
203
|
+
return () => {
|
|
204
|
+
if (prev === undefined) {
|
|
205
|
+
this.entries.delete(key);
|
|
206
|
+
if (prevTombstone != null) this.tombstones.set(key, prevTombstone);
|
|
207
|
+
this.notify({ variant: "delete", key });
|
|
208
|
+
} else {
|
|
209
|
+
this.entries.set(key, prev);
|
|
210
|
+
this.notify({ variant: "set", key, value: prev });
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Sets the value for the given key, or applies a setter to the previous value. A
|
|
217
|
+
* setter producing null/undefined, or a value equal to the current one, is a no-op.
|
|
218
|
+
* @returns A rollback that undoes the set.
|
|
219
|
+
*/
|
|
220
|
+
set(key: Key, value: state.SetArg<Value | undefined>): destructor.Destructor;
|
|
221
|
+
/**
|
|
222
|
+
* Sets every given keyed value, keying each entry by its key property.
|
|
223
|
+
* @returns A rollback that undoes the inserted values in reverse order.
|
|
224
|
+
*/
|
|
225
|
+
set(values: Keyed<Key, Value> | Array<Keyed<Key, Value>>): destructor.Destructor;
|
|
226
|
+
set(
|
|
227
|
+
keyOrValues: Key | Keyed<Key, Value> | Array<Keyed<Key, Value>>,
|
|
228
|
+
value?: state.SetArg<Value | undefined>,
|
|
229
|
+
): destructor.Destructor {
|
|
230
|
+
if (typeof keyOrValues !== "object")
|
|
231
|
+
return this.setOne(keyOrValues as Key, value) ?? destructor.NOOP;
|
|
232
|
+
const rollbacks: destructor.Destructor[] = [];
|
|
233
|
+
this.batch(() =>
|
|
234
|
+
array.toArray(keyOrValues).forEach((val) => {
|
|
235
|
+
const rollback = this.setOne(val.key, val);
|
|
236
|
+
if (rollback != null) rollbacks.push(rollback);
|
|
237
|
+
}),
|
|
238
|
+
);
|
|
239
|
+
return () => this.batch(() => rollbacks.reverse().forEach((r) => r()));
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
private setIfAbsent(values: Array<Keyed<Key, Value>>): destructor.Destructor {
|
|
243
|
+
const rollbacks: destructor.Destructor[] = [];
|
|
244
|
+
this.batch(() =>
|
|
245
|
+
values.forEach((val) => {
|
|
246
|
+
if (this.entries.has(val.key)) return;
|
|
247
|
+
const rollback = this.setOne(val.key, val);
|
|
248
|
+
if (rollback != null) rollbacks.push(rollback);
|
|
249
|
+
}),
|
|
250
|
+
);
|
|
251
|
+
return () => this.batch(() => rollbacks.reverse().forEach((r) => r()));
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Writes fetched records into the table under its declared hydrate mode:
|
|
256
|
+
* "set" overwrites entries, "if-absent" leaves existing entries untouched.
|
|
257
|
+
* @returns A rollback that undoes the entries this call wrote.
|
|
258
|
+
*/
|
|
259
|
+
ingest(values: Keyed<Key, Value> | Array<Keyed<Key, Value>>): destructor.Destructor {
|
|
260
|
+
const arr = array.toArray(values);
|
|
261
|
+
if (this.hydrateMode === "if-absent") return this.setIfAbsent(arr);
|
|
262
|
+
return this.set(arr);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/** Returns every entry in the table. */
|
|
266
|
+
get(): Value[];
|
|
267
|
+
get(key: Key): Value | undefined;
|
|
268
|
+
get(keys: Key[]): Value[];
|
|
269
|
+
get(filter: (value: Value) => boolean): Value[];
|
|
270
|
+
get(keys?: Key | Key[] | ((value: Value) => boolean)): Value | Value[] | undefined {
|
|
271
|
+
if (keys === undefined) return Array.from(this.entries.values());
|
|
272
|
+
if (typeof keys === "function")
|
|
273
|
+
return Array.from(this.entries.values()).filter(keys);
|
|
274
|
+
if (Array.isArray(keys))
|
|
275
|
+
return keys
|
|
276
|
+
.map((key) => this.entries.get(key))
|
|
277
|
+
.filter((e): e is Value => e != null);
|
|
278
|
+
return this.entries.get(keys);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
has(key: Key): boolean {
|
|
282
|
+
return this.entries.has(key);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/** Returns the key of every live entry. */
|
|
286
|
+
keys(): Key[] {
|
|
287
|
+
return Array.from(this.entries.keys());
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Returns the presence of the given key: present, tombstoned, or unknown.
|
|
292
|
+
* Cache-internal surface: consumed by the query machinery, not domain code.
|
|
293
|
+
*/
|
|
294
|
+
status(key: Key): EntryStatus {
|
|
295
|
+
if (this.entries.has(key)) return "present";
|
|
296
|
+
if (this.tombstones.has(key)) return "tombstoned";
|
|
297
|
+
return "unknown";
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Returns the tombstone for the given key, or undefined if none exists.
|
|
302
|
+
* Cache-internal surface: consumed by the query machinery, not domain code.
|
|
303
|
+
*/
|
|
304
|
+
getTombstone(key: Key): Deleted<Value> | undefined {
|
|
305
|
+
return this.tombstones.get(key);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Resolves the given keys to records: serves cached entries and fetches the misses
|
|
310
|
+
* through the table's fetch, hydrating results under the declared mode. With refresh,
|
|
311
|
+
* every key is fetched regardless of presence. Returns the table's entries for the
|
|
312
|
+
* found keys in input order, deduplicated; keys the cluster no longer has are
|
|
313
|
+
* omitted. Tables without a fetch serve cached entries only.
|
|
314
|
+
*/
|
|
315
|
+
async retrieve(keys: Key[], opts: { refresh?: boolean } = {}): Promise<Value[]> {
|
|
316
|
+
if (this.fetchBatcher != null) {
|
|
317
|
+
const misses =
|
|
318
|
+
opts.refresh === true ? keys : keys.filter((key) => !this.entries.has(key));
|
|
319
|
+
if (misses.length > 0) {
|
|
320
|
+
const gen = this.gen;
|
|
321
|
+
const fetched = await this.fetchBatcher.enqueue(misses);
|
|
322
|
+
if (gen === this.gen && fetched.length > 0)
|
|
323
|
+
if (opts.refresh === true) this.set(fetched);
|
|
324
|
+
else this.ingest(fetched);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
const seen = new Set<Key>();
|
|
328
|
+
const results: Value[] = [];
|
|
329
|
+
for (const key of keys) {
|
|
330
|
+
if (seen.has(key)) continue;
|
|
331
|
+
seen.add(key);
|
|
332
|
+
const entry = this.entries.get(key);
|
|
333
|
+
if (entry != null) results.push(entry);
|
|
334
|
+
}
|
|
335
|
+
return results;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Deletes entries and notifies subscribers. Deleted values are retained as
|
|
340
|
+
* tombstones until a subsequent set for the key.
|
|
341
|
+
* @param key - The key(s) to delete or a filter function
|
|
342
|
+
* @returns A rollback that restores the deleted entries
|
|
343
|
+
*/
|
|
344
|
+
delete(
|
|
345
|
+
key: Key | Key[] | ((value: Value, key: Key) => boolean),
|
|
346
|
+
): destructor.Destructor {
|
|
347
|
+
return this.remove(key, true);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Removes entries and notifies subscribers, retaining no corpses: the undo of a write
|
|
352
|
+
* the record never survived, not a deletion. A reader finds the key unknown rather
|
|
353
|
+
* than deleted.
|
|
354
|
+
* @returns A rollback that restores the removed entries
|
|
355
|
+
*/
|
|
356
|
+
evict(key: Key | Key[]): destructor.Destructor {
|
|
357
|
+
return this.remove(key, false);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
private remove(
|
|
361
|
+
key: Key | Key[] | ((value: Value, key: Key) => boolean),
|
|
362
|
+
tombstone: boolean,
|
|
363
|
+
): destructor.Destructor {
|
|
364
|
+
const toDelete: Array<{ key: Key; value?: Value }> = [];
|
|
365
|
+
|
|
366
|
+
if (typeof key === "function")
|
|
367
|
+
this.entries.forEach((value, k) => {
|
|
368
|
+
if (key(value, k)) toDelete.push({ key: k, value });
|
|
369
|
+
});
|
|
370
|
+
else
|
|
371
|
+
array.toArray(key).forEach((k) => {
|
|
372
|
+
const value = this.entries.get(k);
|
|
373
|
+
toDelete.push({ key: k, value });
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
this.batch(() =>
|
|
377
|
+
toDelete.forEach(({ key: k, value }) => {
|
|
378
|
+
this.entries.delete(k);
|
|
379
|
+
if (tombstone && value != null)
|
|
380
|
+
this.tombstones.set(k, new Deleted(value, TimeStamp.now()));
|
|
381
|
+
this.notify({ variant: "delete", key: k });
|
|
382
|
+
}),
|
|
383
|
+
);
|
|
384
|
+
|
|
385
|
+
return () =>
|
|
386
|
+
this.batch(() =>
|
|
387
|
+
toDelete.forEach(({ key: k, value }) => {
|
|
388
|
+
if (value == null) return;
|
|
389
|
+
this.tombstones.delete(k);
|
|
390
|
+
this.entries.set(k, value);
|
|
391
|
+
this.notify({ variant: "set", key: k, value });
|
|
392
|
+
}),
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Re-checks every cached entry against the cluster through the table's
|
|
398
|
+
* fetch: refreshes entries that still exist and tombstones entries that
|
|
399
|
+
* vanished. A no-op for empty tables and tables without a fetch.
|
|
400
|
+
*/
|
|
401
|
+
async reconcile(): Promise<void> {
|
|
402
|
+
const { fetchEntries } = this;
|
|
403
|
+
if (fetchEntries == null) return;
|
|
404
|
+
const keys = this.keys();
|
|
405
|
+
if (keys.length === 0) return;
|
|
406
|
+
const gen = this.gen;
|
|
407
|
+
const values = await fetchSurvivors(fetchEntries, keys);
|
|
408
|
+
// A reset mid-fetch means the cluster was replaced: writing the fetched
|
|
409
|
+
// entries would repopulate the cleared table with old-cluster records.
|
|
410
|
+
if (gen !== this.gen) return;
|
|
411
|
+
const present = new Set<Key>(values.map(({ key }) => key));
|
|
412
|
+
const vanished = keys.filter((k) => !present.has(k));
|
|
413
|
+
this.batch(() => {
|
|
414
|
+
if (vanished.length > 0) this.delete(vanished);
|
|
415
|
+
if (values.length > 0) this.set(values);
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Discards every entry and tombstone without notifying subscribers. Called
|
|
421
|
+
* only by the cache's reset, which resets the answer spaces itself:
|
|
422
|
+
* per-entry delete events would masquerade as deletions of live records.
|
|
423
|
+
* Fetches in flight when the reset runs discard their results.
|
|
424
|
+
*/
|
|
425
|
+
reset(): void {
|
|
426
|
+
this.gen++;
|
|
427
|
+
this.entries.clear();
|
|
428
|
+
this.tombstones.clear();
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Subscribes to entry changes delivered per batched write: one call carrying every
|
|
433
|
+
* event of the batch, in order, after all of the batch's entries have applied.
|
|
434
|
+
* Cache-internal surface: consumed by the query machinery, not domain code;
|
|
435
|
+
* per-record consumers use {@link subscribe}.
|
|
436
|
+
* @returns A destructor that unsubscribes.
|
|
437
|
+
*/
|
|
438
|
+
subscribeBatch(subscriber: BatchSubscriber<Key, Value>): destructor.Destructor {
|
|
439
|
+
this.batchSubscribers.add(subscriber);
|
|
440
|
+
return () => this.batchSubscribers.delete(subscriber);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Subscribes to entry changes. With a key, only changes to that entry fire.
|
|
445
|
+
* @returns A destructor that unsubscribes.
|
|
446
|
+
*/
|
|
447
|
+
subscribe(subscriber: TableSubscriber<Key, Value>, key?: Key): destructor.Destructor {
|
|
448
|
+
if (key == null) {
|
|
449
|
+
this.broadSubscribers.add(subscriber);
|
|
450
|
+
return () => this.broadSubscribers.delete(subscriber);
|
|
451
|
+
}
|
|
452
|
+
let held = this.keyedSubscribers.get(key);
|
|
453
|
+
if (held == null) {
|
|
454
|
+
held = new Set();
|
|
455
|
+
this.keyedSubscribers.set(key, held);
|
|
456
|
+
}
|
|
457
|
+
held.add(subscriber);
|
|
458
|
+
return () => {
|
|
459
|
+
held.delete(subscriber);
|
|
460
|
+
// Guarded on identity so a stale destructor cannot drop a set a later
|
|
461
|
+
// subscription re-created under the same key.
|
|
462
|
+
if (held.size === 0 && this.keyedSubscribers.get(key) === held)
|
|
463
|
+
this.keyedSubscribers.delete(key);
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* Runs fn with event delivery deferred: writes apply to entries immediately, and
|
|
469
|
+
* every event they produce is delivered as one batch when the outermost batch
|
|
470
|
+
* exits. Delivery stays synchronous, inside this call. Nested batches join the
|
|
471
|
+
* outermost one. Events flush even when fn throws, since the entries they describe
|
|
472
|
+
* were already applied.
|
|
473
|
+
*/
|
|
474
|
+
batch<T>(fn: () => T): T {
|
|
475
|
+
if (this.batching != null) return fn();
|
|
476
|
+
const events: TableEvent<Key, Value>[] = [];
|
|
477
|
+
this.batching = events;
|
|
478
|
+
try {
|
|
479
|
+
return fn();
|
|
480
|
+
} finally {
|
|
481
|
+
this.batching = null;
|
|
482
|
+
if (events.length > 0) this.flush(events);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
private notify(event: TableEvent<Key, Value>) {
|
|
487
|
+
if (this.batching != null) {
|
|
488
|
+
this.batching.push(event);
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
this.flush([event]);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
private flush(events: TableEvent<Key, Value>[]) {
|
|
495
|
+
for (const event of events) {
|
|
496
|
+
this.deliver(this.keyedSubscribers.get(event.key), event);
|
|
497
|
+
this.deliver(this.broadSubscribers, event);
|
|
498
|
+
}
|
|
499
|
+
for (const subscriber of this.batchSubscribers)
|
|
500
|
+
try {
|
|
501
|
+
subscriber(events);
|
|
502
|
+
} catch (exc) {
|
|
503
|
+
this.onError(new Error("failed to notify table subscriber", { cause: exc }));
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
private deliver(
|
|
508
|
+
subscribers: Iterable<TableSubscriber<Key, Value>> | undefined,
|
|
509
|
+
event: TableEvent<Key, Value>,
|
|
510
|
+
) {
|
|
511
|
+
if (subscribers == null) return;
|
|
512
|
+
for (const subscriber of subscribers)
|
|
513
|
+
try {
|
|
514
|
+
subscriber(event);
|
|
515
|
+
} catch (exc) {
|
|
516
|
+
this.onError(new Error("failed to notify table subscriber", { cause: exc }));
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
* A mirror listener declaration: keeps the owning table current from one stream
|
|
523
|
+
* channel. Built with {@link createSetListener}, {@link createDeleteListener}, or
|
|
524
|
+
* {@link createFetchListener}; bound to its table by the cache.
|
|
525
|
+
*/
|
|
526
|
+
export interface ListenerSpec<
|
|
527
|
+
Key extends record.Key = record.Key,
|
|
528
|
+
Value extends state.State = state.State,
|
|
529
|
+
> {
|
|
530
|
+
/** Binds the declaration to the owning table as a raw channel listener. */
|
|
531
|
+
bind: (table: Table<Key, Value>) => Listener;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* Declares that the channel broadcasts records to mirror into the table.
|
|
536
|
+
* By default the parsed record keys itself (`changed.key`) and is stored
|
|
537
|
+
* as-is; `key` derives the entry key, `value` transforms the record and may
|
|
538
|
+
* merge with the previous entry (return null/undefined to skip the write).
|
|
539
|
+
*/
|
|
540
|
+
export const createSetListener = <
|
|
541
|
+
Z extends z.ZodType,
|
|
542
|
+
Key extends record.Key = record.Key,
|
|
543
|
+
Value extends state.State = state.State,
|
|
544
|
+
>(
|
|
545
|
+
channel: string,
|
|
546
|
+
schema: Z,
|
|
547
|
+
opts: {
|
|
548
|
+
key?: (changed: z.output<Z>) => Key;
|
|
549
|
+
value?: (changed: z.output<Z>, prev: Value | undefined) => Value | null | undefined;
|
|
550
|
+
} = {},
|
|
551
|
+
): ListenerSpec<Key, Value> => {
|
|
552
|
+
const {
|
|
553
|
+
key = (changed) => (changed as record.Keyed<Key>).key,
|
|
554
|
+
value = (changed) => changed as Value,
|
|
555
|
+
} = opts;
|
|
556
|
+
return {
|
|
557
|
+
bind: (table): Listener<Z> => ({
|
|
558
|
+
channel,
|
|
559
|
+
schema,
|
|
560
|
+
onChange: (changed) => {
|
|
561
|
+
table.batch(() =>
|
|
562
|
+
changed.forEach((c) =>
|
|
563
|
+
table.set(key(c), (prev) => value(c, prev) ?? undefined),
|
|
564
|
+
),
|
|
565
|
+
);
|
|
566
|
+
},
|
|
567
|
+
}),
|
|
568
|
+
};
|
|
569
|
+
};
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* Declares that the channel broadcasts deletions to mirror into the table.
|
|
573
|
+
* By default the parsed value is the entry key; `key` derives it instead.
|
|
574
|
+
*/
|
|
575
|
+
export const createDeleteListener = <
|
|
576
|
+
Z extends z.ZodType,
|
|
577
|
+
Key extends record.Key = record.Key,
|
|
578
|
+
Value extends state.State = state.State,
|
|
579
|
+
>(
|
|
580
|
+
channel: string,
|
|
581
|
+
schema: Z,
|
|
582
|
+
opts: { key?: (changed: z.output<Z>) => Key } = {},
|
|
583
|
+
): ListenerSpec<Key, Value> => {
|
|
584
|
+
const { key = (changed) => changed as Key } = opts;
|
|
585
|
+
return {
|
|
586
|
+
bind: (table): Listener<Z> => ({
|
|
587
|
+
channel,
|
|
588
|
+
schema,
|
|
589
|
+
onChange: (changed) => {
|
|
590
|
+
table.delete(changed.map((c) => key(c)));
|
|
591
|
+
},
|
|
592
|
+
}),
|
|
593
|
+
};
|
|
594
|
+
};
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Declares that the channel announces keys whose records changed. Announced
|
|
598
|
+
* keys are refetched through the table's fetch and overwrite their entries.
|
|
599
|
+
*/
|
|
600
|
+
export const createFetchListener = <
|
|
601
|
+
Z extends z.ZodType<Key | Key[]>,
|
|
602
|
+
Key extends record.Key = record.Key,
|
|
603
|
+
Value extends state.State = state.State,
|
|
604
|
+
>(
|
|
605
|
+
channel: string,
|
|
606
|
+
schema: Z,
|
|
607
|
+
): ListenerSpec<Key, Value> => ({
|
|
608
|
+
bind: (table): Listener<Z> => ({
|
|
609
|
+
channel,
|
|
610
|
+
schema,
|
|
611
|
+
onChange: async (changed) => {
|
|
612
|
+
await table.retrieve(
|
|
613
|
+
changed.flatMap((c) => array.toArray(c)),
|
|
614
|
+
{ refresh: true },
|
|
615
|
+
);
|
|
616
|
+
},
|
|
617
|
+
}),
|
|
618
|
+
});
|
|
619
|
+
|
|
620
|
+
export const partialUpdate = <Key extends record.Key, Value extends object>(
|
|
621
|
+
table: Table<Key, Value>,
|
|
622
|
+
key: Key,
|
|
623
|
+
value: Partial<Value>,
|
|
624
|
+
): destructor.Destructor =>
|
|
625
|
+
table.set(key, (p) => (p == null ? undefined : { ...p, ...value }));
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Copyright 2026 Synnax Labs, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Use of this software is governed by the Business Source License included in the file
|
|
4
|
+
// licenses/BSL.txt.
|
|
5
|
+
//
|
|
6
|
+
// As of the Change Date specified in that file, in accordance with the Business Source
|
|
7
|
+
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
|
+
// included in the file licenses/APL.txt.
|
|
9
|
+
|
|
10
|
+
import { type primitive, type state } from "@synnaxlabs/x";
|
|
11
|
+
|
|
12
|
+
/** Options to control async operations. */
|
|
13
|
+
export interface FetchOptions {
|
|
14
|
+
/** Optional AbortSignal to cancel the operation */
|
|
15
|
+
signal?: AbortSignal;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Options for write methods that apply the change locally before the send. */
|
|
19
|
+
export interface WriteOptions<T = void> {
|
|
20
|
+
/**
|
|
21
|
+
* Called after the optimistic cache apply and before the network send, with
|
|
22
|
+
* the optimistically applied value. UI layers use it to react to a write
|
|
23
|
+
* (e.g. open a tab) without waiting on the server.
|
|
24
|
+
*/
|
|
25
|
+
onOptimistic?: (value: T) => Promise<void> | void;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Plain-data shape used to address a record in the cache query system. Queries are
|
|
30
|
+
* hashed by {@link hash} to produce stable cache keys, so they must be primitives,
|
|
31
|
+
* arrays of queries, plain string-keyed objects of queries, or class instances
|
|
32
|
+
* implementing {@link primitive.Hashable}. Maps, Sets, Dates, and non-Hashable class
|
|
33
|
+
* instances are rejected at compile time because their fields don't recursively reduce
|
|
34
|
+
* to {@link Params}. Consumer query types must be declared with `type` aliases, not
|
|
35
|
+
* `interface`, because TypeScript interfaces lack an implicit string index signature
|
|
36
|
+
* and fail the `{ readonly [k: string]: Params }` branch.
|
|
37
|
+
*/
|
|
38
|
+
export type Params =
|
|
39
|
+
| string
|
|
40
|
+
| number
|
|
41
|
+
| bigint
|
|
42
|
+
| boolean
|
|
43
|
+
| null
|
|
44
|
+
| undefined
|
|
45
|
+
| primitive.Hashable
|
|
46
|
+
| readonly Params[]
|
|
47
|
+
| { readonly [key: string]: Params };
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Shape of values returned and stored by the cache query system. Unlike
|
|
51
|
+
* {@link Params}, data values do not need to be hashable — they may carry
|
|
52
|
+
* arbitrary state including class instances or non-serializable references.
|
|
53
|
+
*/
|
|
54
|
+
export type Data = state.State;
|