@synnaxlabs/client 0.56.2 → 0.57.1
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-DDACDVZ-.js +14505 -0
- package/dist/client-DDACDVZ-.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 +91 -0
- package/dist/src/framer/cache/dynamic.d.ts.map +1 -0
- package/dist/src/framer/cache/reader.d.ts +57 -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 +39 -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 +39 -16
- 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 +340 -0
- package/src/framer/cache/reader.ts +231 -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 +108 -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 +19 -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,273 @@
|
|
|
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
|
+
type FileTransport,
|
|
12
|
+
type UnaryClient,
|
|
13
|
+
type UploadBody,
|
|
14
|
+
} from "@synnaxlabs/freighter";
|
|
15
|
+
import {
|
|
16
|
+
array,
|
|
17
|
+
caseconv,
|
|
18
|
+
type destructor,
|
|
19
|
+
primitive,
|
|
20
|
+
record,
|
|
21
|
+
zod,
|
|
22
|
+
} from "@synnaxlabs/x";
|
|
23
|
+
import { z } from "zod";
|
|
24
|
+
|
|
25
|
+
import { imex } from "@/imex";
|
|
26
|
+
import { type ontology } from "@/ontology";
|
|
27
|
+
import {
|
|
28
|
+
type Key,
|
|
29
|
+
keyZ,
|
|
30
|
+
type New,
|
|
31
|
+
ontologyID,
|
|
32
|
+
type Project,
|
|
33
|
+
projectZ,
|
|
34
|
+
} from "@/project/types.gen";
|
|
35
|
+
import { query } from "@/query";
|
|
36
|
+
|
|
37
|
+
export const SET_CHANNEL_NAME = "sy_project_set";
|
|
38
|
+
export const DELETE_CHANNEL_NAME = "sy_project_delete";
|
|
39
|
+
|
|
40
|
+
const retrieveReqZ = z.object({
|
|
41
|
+
keys: keyZ.array().optional(),
|
|
42
|
+
searchTerm: z.string().optional(),
|
|
43
|
+
offset: z.int().optional(),
|
|
44
|
+
limit: z.int().optional(),
|
|
45
|
+
ignoreNotFoundError: z.boolean().optional(),
|
|
46
|
+
});
|
|
47
|
+
const retrieveMultiParamsZ = retrieveReqZ.or(query.keyListZ(keyZ));
|
|
48
|
+
export interface RetrieveRequest extends z.infer<typeof retrieveReqZ> {}
|
|
49
|
+
const createReqZ = z.object({ projects: projectZ.array() });
|
|
50
|
+
const renameReqZ = z.object({ key: keyZ, name: z.string() });
|
|
51
|
+
const setLayoutReqZ = z.object({
|
|
52
|
+
key: keyZ,
|
|
53
|
+
layout: caseconv.preserveCase(record.unknownZ()),
|
|
54
|
+
});
|
|
55
|
+
const deleteReqZ = z.object({ keys: keyZ.array() });
|
|
56
|
+
const exportReqZ = z.object({ key: keyZ, encoding: imex.encodingZ });
|
|
57
|
+
|
|
58
|
+
const importParamsZ = z.object({ fileName: z.string().min(1) });
|
|
59
|
+
|
|
60
|
+
const retrieveResZ = z.object({ projects: projectZ.array().default(() => []) });
|
|
61
|
+
const createResZ = z.object({ projects: projectZ.array() });
|
|
62
|
+
const importResZ = z.object({ project: projectZ });
|
|
63
|
+
const emptyResZ = z.object({});
|
|
64
|
+
|
|
65
|
+
/** Options for a project import call. */
|
|
66
|
+
export interface ImportOptions {
|
|
67
|
+
/**
|
|
68
|
+
* The name of the uploaded archive or picked directory. Its extension-stripped form
|
|
69
|
+
* names the project when the bundle carries no name.
|
|
70
|
+
*/
|
|
71
|
+
fileName: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface SetLayoutParams extends z.input<typeof setLayoutReqZ> {}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Client-side matching for a request: key sets. Server-computed shapes
|
|
78
|
+
* (search, limit/offset) never reach this filter; they refetch instead.
|
|
79
|
+
*/
|
|
80
|
+
const requestFilter = (req: RetrieveRequest): ((p: Project) => boolean) => {
|
|
81
|
+
const keySet = primitive.isNonZero(req.keys) ? new Set(req.keys) : undefined;
|
|
82
|
+
return (p) => keySet == null || keySet.has(p.key);
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export interface ClientConfig {
|
|
86
|
+
unary: UnaryClient;
|
|
87
|
+
file: FileTransport;
|
|
88
|
+
cache: query.Cache;
|
|
89
|
+
ontology: ontology.Client;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export class Client extends query.Retriever<typeof retrieveMultiParamsZ, Key, Project> {
|
|
93
|
+
private readonly cfg: ClientConfig;
|
|
94
|
+
private readonly store: query.Table<Key, Project>;
|
|
95
|
+
|
|
96
|
+
constructor(cfg: ClientConfig) {
|
|
97
|
+
const { cache } = cfg;
|
|
98
|
+
const store = cache.createTable<Key, Project>({
|
|
99
|
+
name: "projects",
|
|
100
|
+
fetch: async (keys) => await this.execRetrieve({ keys }),
|
|
101
|
+
listen: [
|
|
102
|
+
query.createSetListener(SET_CHANNEL_NAME, projectZ),
|
|
103
|
+
query.createDeleteListener(DELETE_CHANNEL_NAME, keyZ),
|
|
104
|
+
],
|
|
105
|
+
});
|
|
106
|
+
super(cache, {
|
|
107
|
+
name: "project",
|
|
108
|
+
table: store,
|
|
109
|
+
request: {
|
|
110
|
+
schema: retrieveMultiParamsZ,
|
|
111
|
+
fetch: async (req) => await this.execRetrieve(req),
|
|
112
|
+
matches: (project, req) => requestFilter(req)(project),
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
this.cfg = cfg;
|
|
116
|
+
this.store = store;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async create(project: New, opts?: query.WriteOptions<Project[]>): Promise<Project>;
|
|
120
|
+
async create(
|
|
121
|
+
projects: New[],
|
|
122
|
+
opts?: query.WriteOptions<Project[]>,
|
|
123
|
+
): Promise<Project[]>;
|
|
124
|
+
async create(
|
|
125
|
+
projects: New | New[],
|
|
126
|
+
opts: query.WriteOptions<Project[]> = {},
|
|
127
|
+
): Promise<Project | Project[]> {
|
|
128
|
+
const isMany = Array.isArray(projects);
|
|
129
|
+
const optimistic = array
|
|
130
|
+
.toArray(projects)
|
|
131
|
+
.map((p) => zod.parse(projectZ, p, { label: "project" }));
|
|
132
|
+
const res = await query.optimistic({
|
|
133
|
+
rollbacks: [this.store.set(optimistic)],
|
|
134
|
+
onOptimistic: () => opts.onOptimistic?.(optimistic),
|
|
135
|
+
commit: async () =>
|
|
136
|
+
await this.cfg.unary.send(
|
|
137
|
+
"/project/create",
|
|
138
|
+
{ projects: optimistic },
|
|
139
|
+
createReqZ,
|
|
140
|
+
createResZ,
|
|
141
|
+
),
|
|
142
|
+
});
|
|
143
|
+
this.store.set(res.projects);
|
|
144
|
+
return isMany ? res.projects : res.projects[0];
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async rename(key: Key, name: string, opts: query.WriteOptions = {}): Promise<void> {
|
|
148
|
+
const rename = () => [
|
|
149
|
+
query.partialUpdate(this.store, key, { name }),
|
|
150
|
+
this.cfg.ontology.cache.renameResource(ontologyID(key), name),
|
|
151
|
+
];
|
|
152
|
+
await query.optimistic({
|
|
153
|
+
rollbacks: rename(),
|
|
154
|
+
onOptimistic: opts.onOptimistic,
|
|
155
|
+
commit: async () =>
|
|
156
|
+
await this.cfg.unary.send(
|
|
157
|
+
"/project/rename",
|
|
158
|
+
{ key, name },
|
|
159
|
+
renameReqZ,
|
|
160
|
+
emptyResZ,
|
|
161
|
+
),
|
|
162
|
+
});
|
|
163
|
+
rename();
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
async setLayout(
|
|
167
|
+
key: Key,
|
|
168
|
+
layout: record.Unknown,
|
|
169
|
+
opts: query.WriteOptions = {},
|
|
170
|
+
): Promise<void> {
|
|
171
|
+
await query.optimistic({
|
|
172
|
+
rollbacks: [query.partialUpdate(this.store, key, { layout })],
|
|
173
|
+
onOptimistic: opts.onOptimistic,
|
|
174
|
+
commit: async () =>
|
|
175
|
+
await this.cfg.unary.send(
|
|
176
|
+
"/project/set-layout",
|
|
177
|
+
{ key, layout },
|
|
178
|
+
setLayoutReqZ,
|
|
179
|
+
emptyResZ,
|
|
180
|
+
),
|
|
181
|
+
});
|
|
182
|
+
this.mergeThrough(key, { layout });
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async delete(key: Key, opts?: query.WriteOptions): Promise<void>;
|
|
186
|
+
async delete(keys: Key[], opts?: query.WriteOptions): Promise<void>;
|
|
187
|
+
async delete(keys: Key | Key[], opts: query.WriteOptions = {}): Promise<void> {
|
|
188
|
+
const keysArr = array.toArray(keys);
|
|
189
|
+
const drop = () => [
|
|
190
|
+
this.cfg.ontology.cache.deleteResources(ontologyID(keysArr)),
|
|
191
|
+
this.store.delete(keysArr),
|
|
192
|
+
];
|
|
193
|
+
await query.optimistic({
|
|
194
|
+
rollbacks: drop(),
|
|
195
|
+
onOptimistic: opts.onOptimistic,
|
|
196
|
+
commit: async () =>
|
|
197
|
+
await this.cfg.unary.send(
|
|
198
|
+
"/project/delete",
|
|
199
|
+
{ keys: keysArr },
|
|
200
|
+
deleteReqZ,
|
|
201
|
+
emptyResZ,
|
|
202
|
+
),
|
|
203
|
+
});
|
|
204
|
+
drop();
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Exports the project and its contents as a bundle: a zip archive holding one JSON
|
|
209
|
+
* file per document and panel, group children as directories, and a manifest.json
|
|
210
|
+
* naming the project. Two members of one directory that take the same file name keep
|
|
211
|
+
* distinct names through a numeric suffix. The caller pipes the stream wherever it
|
|
212
|
+
* likes without the client buffering the whole archive.
|
|
213
|
+
* @param options - the export options, including the serialization member files are
|
|
214
|
+
* written in.
|
|
215
|
+
* @returns the bundle as a stream of zip bytes.
|
|
216
|
+
*/
|
|
217
|
+
async export(key: Key, options: imex.Options): Promise<ReadableStream<Uint8Array>> {
|
|
218
|
+
return await this.cfg.file.download(
|
|
219
|
+
"/project/export",
|
|
220
|
+
{ key, encoding: options.encoding },
|
|
221
|
+
exportReqZ,
|
|
222
|
+
{ encoding: "ZIP" },
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Imports a project bundle: a zip archive holding one JSON envelope per document and
|
|
228
|
+
* panel, group children as directories, and a manifest.json naming the project. The
|
|
229
|
+
* Core creates a fresh project and imports every member in a single transaction, so a
|
|
230
|
+
* failure leaves nothing behind. Legacy project directories (a root LAYOUT.json with
|
|
231
|
+
* no manifest) import through the same call.
|
|
232
|
+
*
|
|
233
|
+
* @param data - the bundle as zip bytes.
|
|
234
|
+
* @param options - the import options, including the source file's name.
|
|
235
|
+
* @returns the created project.
|
|
236
|
+
* @throws {ValidationError} if the manifest is missing, malformed, or of another
|
|
237
|
+
* bundle kind, if two member names collide, or if a member cannot be imported.
|
|
238
|
+
*/
|
|
239
|
+
async import(data: UploadBody, options: ImportOptions): Promise<Project> {
|
|
240
|
+
const res = await this.cfg.file.upload(
|
|
241
|
+
"/project/import",
|
|
242
|
+
data,
|
|
243
|
+
{ encoding: "ZIP", params: options, paramsSchema: importParamsZ },
|
|
244
|
+
importResZ,
|
|
245
|
+
);
|
|
246
|
+
this.store.set(res.project);
|
|
247
|
+
return res.project;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/** Subscribes to every project delete delivered to the cache. */
|
|
251
|
+
onDelete(handler: (key: Key) => void): destructor.Destructor {
|
|
252
|
+
return this.store.subscribe((event) => {
|
|
253
|
+
if (event.variant === "delete") handler(event.key);
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Undefined fields are dropped: the server keeps prior values for them.
|
|
258
|
+
private mergeThrough(key: Key, changes: Partial<Project>): void {
|
|
259
|
+
const prev = this.store.get(key);
|
|
260
|
+
if (prev != null)
|
|
261
|
+
this.store.set(key, { ...prev, ...record.purgeUndefined(changes) });
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
private async execRetrieve(req: RetrieveRequest): Promise<Project[]> {
|
|
265
|
+
const res = await this.cfg.unary.send(
|
|
266
|
+
"/project/retrieve",
|
|
267
|
+
req,
|
|
268
|
+
retrieveReqZ,
|
|
269
|
+
retrieveResZ,
|
|
270
|
+
);
|
|
271
|
+
return res.projects;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
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
|
+
export * from "@/project/client";
|
|
11
|
+
export * from "@/project/types.gen";
|
|
@@ -0,0 +1,10 @@
|
|
|
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
|
+
export * as project from "@/project/external";
|
|
@@ -0,0 +1,40 @@
|
|
|
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
|
+
// Code generated by Oracle. DO NOT EDIT.
|
|
11
|
+
|
|
12
|
+
import { caseconv, record, uuid } from "@synnaxlabs/x";
|
|
13
|
+
import { z } from "zod";
|
|
14
|
+
|
|
15
|
+
import { ontology } from "@/ontology";
|
|
16
|
+
|
|
17
|
+
export const keyZ = z.uuid();
|
|
18
|
+
export type Key = z.infer<typeof keyZ>;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Project is a named, persistable container that stores the layout and organization of
|
|
22
|
+
* the Console application. Projects allow users to save and restore custom arrangements
|
|
23
|
+
* of visualizations, tabs, and window configurations.
|
|
24
|
+
*/
|
|
25
|
+
export const projectZ = z.object({
|
|
26
|
+
/** key is the unique identifier for this project. */
|
|
27
|
+
key: keyZ.default(uuid.create),
|
|
28
|
+
/** name is a human-readable name for the project. */
|
|
29
|
+
name: z.string().min(1, "name is required"),
|
|
30
|
+
/**
|
|
31
|
+
* layout is the mosaic tree structure that defines how visualizations are arranged.
|
|
32
|
+
* Contains tab layout, split configurations, and window positions.
|
|
33
|
+
*/
|
|
34
|
+
layout: caseconv.preserveCase(record.unknownZ().default(() => ({}))),
|
|
35
|
+
});
|
|
36
|
+
export interface Project extends z.infer<typeof projectZ> {}
|
|
37
|
+
export interface New extends z.input<typeof projectZ> {}
|
|
38
|
+
|
|
39
|
+
export const ontologyID = ontology.createIDFactory<Key>("project");
|
|
40
|
+
export const TYPE_ONTOLOGY_ID = ontologyID("");
|
|
@@ -0,0 +1,326 @@
|
|
|
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
|
+
type breaker,
|
|
12
|
+
type destructor,
|
|
13
|
+
errors,
|
|
14
|
+
observe,
|
|
15
|
+
type record,
|
|
16
|
+
type state,
|
|
17
|
+
} from "@synnaxlabs/x";
|
|
18
|
+
import type z from "zod";
|
|
19
|
+
|
|
20
|
+
import { AccessDeniedError, isConnectionError } from "@/errors";
|
|
21
|
+
import { type framer } from "@/framer";
|
|
22
|
+
import { bindDerived, type DeriveParams } from "@/query/derived";
|
|
23
|
+
import { type Retrieves, Space, type SpaceConfig } from "@/query/query";
|
|
24
|
+
import { createStreamer, type Listener, type Streamer } from "@/query/streamer";
|
|
25
|
+
import { type Keyed, type ListenerSpec, Table, type TableParams } from "@/query/table";
|
|
26
|
+
import { type Data, type Params } from "@/query/types";
|
|
27
|
+
|
|
28
|
+
export interface CacheParams {
|
|
29
|
+
/**
|
|
30
|
+
* Opens the raw frame streamer used to receive change signals; reconnect hardening is
|
|
31
|
+
* applied internally. Null constructs a detached cache: purely local tables and no
|
|
32
|
+
* change stream. Used for clients constructed with `cache: false`.
|
|
33
|
+
*/
|
|
34
|
+
openStreamer: framer.StreamOpener | null;
|
|
35
|
+
/** Retry behavior for change-stream reconnect attempts. */
|
|
36
|
+
breaker?: breaker.Config;
|
|
37
|
+
/** Called whenever the change stream goes live, before reconciliation begins. */
|
|
38
|
+
onStreamLive?: () => void;
|
|
39
|
+
/** Called when the change stream fails and reconnection begins. */
|
|
40
|
+
onStreamDrop?: (error: Error) => void;
|
|
41
|
+
/**
|
|
42
|
+
* Called when the change stream is refused because the caller lacks access to
|
|
43
|
+
* the mirrored channels. Only a policy change lifts a denial.
|
|
44
|
+
*/
|
|
45
|
+
onStreamDenied?: (error: Error) => void;
|
|
46
|
+
/**
|
|
47
|
+
* Receives errors that have no caller to throw to: listener fan-out, streamer frame
|
|
48
|
+
* handling, and background reconciliation. Defaults to console logging.
|
|
49
|
+
*/
|
|
50
|
+
onError?: (error: Error) => void;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Configuration for a derived table owned by a {@link Cache}. */
|
|
54
|
+
export interface DerivedConfig<
|
|
55
|
+
Key extends record.Key,
|
|
56
|
+
Value extends Keyed<Key>,
|
|
57
|
+
Composed extends Keyed<Key>,
|
|
58
|
+
> extends DeriveParams<Key, Value, Composed> {
|
|
59
|
+
/** Names the table in diagnostics. */
|
|
60
|
+
name: string;
|
|
61
|
+
/** Overrides the deep-equality default used to silence redundant sets. */
|
|
62
|
+
equal?: (a: Composed, b: Composed, key: Key) => boolean;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Configuration for a table owned by a {@link Cache}. */
|
|
66
|
+
export interface TableConfig<
|
|
67
|
+
Key extends record.Key = record.Key,
|
|
68
|
+
Value extends state.State = state.State,
|
|
69
|
+
> extends Omit<TableParams<Key, Value>, "onError"> {
|
|
70
|
+
/** Names the table in diagnostics (reconciliation errors). */
|
|
71
|
+
name: string;
|
|
72
|
+
/** Mirror listeners keeping this table current from stream channels. */
|
|
73
|
+
listen?: Array<ListenerSpec<Key, Value>>;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
interface RegisteredTable {
|
|
77
|
+
name: string;
|
|
78
|
+
listeners: Listener[];
|
|
79
|
+
reconcile?: () => Promise<void>;
|
|
80
|
+
reset: () => void;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** The cache-facing lifecycle of an answer space, generics erased. */
|
|
84
|
+
interface SpaceLifecycle {
|
|
85
|
+
close: () => void;
|
|
86
|
+
reset: () => void;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* The client's local mirror of cluster state: keyed tables, the change-stream loop,
|
|
91
|
+
* connection epochs, and reconciliation. Holds zero domain knowledge — domain clients
|
|
92
|
+
* create their tables here and expose typed query spaces. Always present on a client; a
|
|
93
|
+
* null {@link CacheParams.openStreamer} stands in for "disabled" or "not yet connected"
|
|
94
|
+
* rather than a null cache. The change stream opens lazily: nothing touches the network
|
|
95
|
+
* until the first {@link ensureStreaming} call. All tables and listeners must be
|
|
96
|
+
* declared before streaming starts.
|
|
97
|
+
*/
|
|
98
|
+
export class Cache {
|
|
99
|
+
private readonly tables: RegisteredTable[] = [];
|
|
100
|
+
private readonly reactions: Listener[] = [];
|
|
101
|
+
private readonly spaces: SpaceLifecycle[] = [];
|
|
102
|
+
private readonly detachers: destructor.Destructor[] = [];
|
|
103
|
+
private readonly epochObserver = new observe.Observer<number>();
|
|
104
|
+
private readonly params: CacheParams;
|
|
105
|
+
private streamer: Streamer | null = null;
|
|
106
|
+
private epochCount = 0;
|
|
107
|
+
private unmaintained = false;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Stable error sink for machinery built on this cache (dispatch
|
|
111
|
+
* controllers, answer spaces).
|
|
112
|
+
*/
|
|
113
|
+
readonly onError: (error: Error) => void;
|
|
114
|
+
|
|
115
|
+
constructor(params: CacheParams) {
|
|
116
|
+
this.params = params;
|
|
117
|
+
this.onError = params.onError ?? console.error;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Creates a table owned by this cache and returns it, binding its declared mirror
|
|
122
|
+
* listeners. Must be called before streaming starts; creating after {@link
|
|
123
|
+
* ensureStreaming} throws, as the new table's channels would never be streamed.
|
|
124
|
+
*/
|
|
125
|
+
createTable<Key extends record.Key, Value extends state.State>(
|
|
126
|
+
config: TableConfig<Key, Value>,
|
|
127
|
+
): Table<Key, Value> {
|
|
128
|
+
if (this.streamer != null)
|
|
129
|
+
throw new Error(`cannot create table ${config.name} after streaming has started`);
|
|
130
|
+
const { name, listen, ...params } = config;
|
|
131
|
+
const table = new Table<Key, Value>({ ...params, onError: this.onError });
|
|
132
|
+
this.tables.push({
|
|
133
|
+
name,
|
|
134
|
+
listeners: (listen ?? []).map((spec) => spec.bind(table)),
|
|
135
|
+
reconcile: config.fetch == null ? undefined : async () => await table.reconcile(),
|
|
136
|
+
reset: () => table.reset(),
|
|
137
|
+
});
|
|
138
|
+
return table;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Creates a table materialized from another table owned by this cache. Composed
|
|
143
|
+
* entries are replaced on source and watch events, so entry identity changes exactly
|
|
144
|
+
* when composition changes; misses on read fetch through the source. Resets with the
|
|
145
|
+
* cache. No stream listeners of its own, so it may be created at any time.
|
|
146
|
+
*/
|
|
147
|
+
derive<Key extends record.Key, Value extends Keyed<Key>, Composed extends Keyed<Key>>(
|
|
148
|
+
config: DerivedConfig<Key, Value, Composed>,
|
|
149
|
+
): Table<Key, Composed> {
|
|
150
|
+
const { name, source, compose, watch, equal } = config;
|
|
151
|
+
const table = new Table<Key, Composed>({
|
|
152
|
+
onError: this.onError,
|
|
153
|
+
equal,
|
|
154
|
+
fetch: async (keys) => (await source.retrieve(keys)).map(compose),
|
|
155
|
+
});
|
|
156
|
+
this.detachers.push(bindDerived(table, { source, compose, watch }));
|
|
157
|
+
this.tables.push({ name, listeners: [], reset: () => table.reset() });
|
|
158
|
+
return table;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Registers a channel reaction: a listener that is not a table mirror
|
|
163
|
+
* (dispatch wires, cross-table side effects). Same pre-streaming
|
|
164
|
+
* constraint as {@link createTable}.
|
|
165
|
+
*/
|
|
166
|
+
listen<Z extends z.ZodType>(listener: Listener<Z>): void {
|
|
167
|
+
if (this.streamer != null)
|
|
168
|
+
throw new Error(
|
|
169
|
+
`cannot listen to ${listener.channel} after streaming has started`,
|
|
170
|
+
);
|
|
171
|
+
this.reactions.push(listener);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Constructs an answer space wired to this cache: reads open the change
|
|
176
|
+
* stream, maintained answers refetch on epoch bumps, maintenance errors
|
|
177
|
+
* report to the cache's error sink, and the space closes with the cache.
|
|
178
|
+
*/
|
|
179
|
+
queries<
|
|
180
|
+
Q extends Params,
|
|
181
|
+
D extends Data,
|
|
182
|
+
K extends record.Key = record.Key,
|
|
183
|
+
V extends state.State = state.State,
|
|
184
|
+
>(config: SpaceConfig<Q, D, K, V>): Retrieves<Q, D> {
|
|
185
|
+
const space = new Space(config, {
|
|
186
|
+
ensureStreaming: async () => await this.ensureStreaming(),
|
|
187
|
+
onEpoch: (callback) => this.onEpoch(callback),
|
|
188
|
+
maintained: () => !this.unmaintained && this.params.openStreamer != null,
|
|
189
|
+
onError: this.onError,
|
|
190
|
+
});
|
|
191
|
+
this.spaces.push(space);
|
|
192
|
+
return space;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Ensures the change stream is open, opening it on first call. Callers that
|
|
197
|
+
* populate or read tables await this first so no change is missed between a
|
|
198
|
+
* fetch and the stream opening.
|
|
199
|
+
* @throws {AccessDeniedError} if the caller cannot stream the mirrored
|
|
200
|
+
* channels. Answers stop being maintained until a later call succeeds.
|
|
201
|
+
*/
|
|
202
|
+
async ensureStreaming(): Promise<void> {
|
|
203
|
+
const { openStreamer, breaker, onStreamLive, onStreamDrop, onStreamDenied } =
|
|
204
|
+
this.params;
|
|
205
|
+
if (openStreamer == null) return;
|
|
206
|
+
if (this.streamer == null) {
|
|
207
|
+
// A reset can retire the streamer while its open is in flight; a
|
|
208
|
+
// retired streamer's lifecycle callbacks must not touch the epoch.
|
|
209
|
+
const streamer = createStreamer({
|
|
210
|
+
openStreamer,
|
|
211
|
+
breaker,
|
|
212
|
+
listeners: [
|
|
213
|
+
...this.tables.flatMap(({ listeners }) => listeners),
|
|
214
|
+
...this.reactions,
|
|
215
|
+
],
|
|
216
|
+
onError: this.onError,
|
|
217
|
+
onLive: onStreamLive,
|
|
218
|
+
onDrop: onStreamDrop,
|
|
219
|
+
onOpen: () => {
|
|
220
|
+
if (this.streamer !== streamer) return;
|
|
221
|
+
this.unmaintained = false;
|
|
222
|
+
this.epochCount = 1;
|
|
223
|
+
this.epochObserver.notify(this.epochCount);
|
|
224
|
+
},
|
|
225
|
+
onReopen: () => {
|
|
226
|
+
if (this.streamer !== streamer) return;
|
|
227
|
+
this.bumpEpoch();
|
|
228
|
+
},
|
|
229
|
+
onDead: (error) => {
|
|
230
|
+
if (this.streamer !== streamer) return;
|
|
231
|
+
this.unmaintained = true;
|
|
232
|
+
if (AccessDeniedError.matches(error)) onStreamDenied?.(error);
|
|
233
|
+
},
|
|
234
|
+
});
|
|
235
|
+
this.streamer = streamer;
|
|
236
|
+
}
|
|
237
|
+
try {
|
|
238
|
+
await this.streamer.demand();
|
|
239
|
+
} catch (exc) {
|
|
240
|
+
this.unmaintained = true;
|
|
241
|
+
const error = errors.fromUnknown(exc);
|
|
242
|
+
// The first open never reaches onDead: the stream dies before there is
|
|
243
|
+
// one to observe.
|
|
244
|
+
if (AccessDeniedError.matches(error)) onStreamDenied?.(error);
|
|
245
|
+
throw error;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* The connection epoch: 0 before streaming starts, 1 once live, incremented
|
|
251
|
+
* on every reconnect. Changes may have been missed between epochs.
|
|
252
|
+
*/
|
|
253
|
+
get epoch(): number {
|
|
254
|
+
return this.epochCount;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/** Subscribes to epoch changes. Returns a destructor that unsubscribes. */
|
|
258
|
+
onEpoch(callback: (epoch: number) => void): destructor.Destructor {
|
|
259
|
+
return this.epochObserver.onChange(callback);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Re-checks every cached entry against the cluster: refreshes entries that
|
|
264
|
+
* still exist and tombstones entries that vanished. Runs after every
|
|
265
|
+
* reconnect for tables that declare a fetch.
|
|
266
|
+
*/
|
|
267
|
+
private async reconcile(): Promise<void> {
|
|
268
|
+
await Promise.all(
|
|
269
|
+
this.tables.map(async ({ name, reconcile }) => {
|
|
270
|
+
if (reconcile == null) return;
|
|
271
|
+
try {
|
|
272
|
+
await reconcile();
|
|
273
|
+
} catch (exc) {
|
|
274
|
+
// The next reopen reconciles again, so an unreachable cluster is churn.
|
|
275
|
+
if (isConnectionError(exc)) return;
|
|
276
|
+
this.onError(new Error(`failed to reconcile ${name} cache`, { cause: exc }));
|
|
277
|
+
}
|
|
278
|
+
}),
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Discards every cached entry, tombstone, and answer, closes the change
|
|
284
|
+
* stream so it reopens fresh, and returns the epoch to 0. Called when the
|
|
285
|
+
* cluster behind the connection is replaced: no cached record, corpse, or
|
|
286
|
+
* answer remains meaningful, so nothing is tombstoned or diffed.
|
|
287
|
+
*/
|
|
288
|
+
async reset(): Promise<void> {
|
|
289
|
+
const { streamer } = this;
|
|
290
|
+
this.streamer = null;
|
|
291
|
+
// Drain the retired stream first so a late frame cannot repopulate the
|
|
292
|
+
// tables cleared below. A close failure must not block the reset: the
|
|
293
|
+
// stream is retired either way.
|
|
294
|
+
try {
|
|
295
|
+
await streamer?.close();
|
|
296
|
+
} catch (exc) {
|
|
297
|
+
console.error("failed to close retired stream", exc);
|
|
298
|
+
}
|
|
299
|
+
this.tables.forEach(({ reset }) => reset());
|
|
300
|
+
this.spaces.forEach((space) => space.reset());
|
|
301
|
+
this.unmaintained = false;
|
|
302
|
+
this.epochCount = 0;
|
|
303
|
+
this.epochObserver.notify(0);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
private bumpEpoch(): void {
|
|
307
|
+
this.epochCount++;
|
|
308
|
+
this.epochObserver.notify(this.epochCount);
|
|
309
|
+
this.reconcile().catch((exc: unknown) =>
|
|
310
|
+
this.onError(
|
|
311
|
+
new Error("failed to reconcile caches after reconnect", { cause: exc }),
|
|
312
|
+
),
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Closes the change stream and every answer space this cache constructed.
|
|
318
|
+
* A no-op for the stream when streaming never started.
|
|
319
|
+
*/
|
|
320
|
+
async close(): Promise<void> {
|
|
321
|
+
this.detachers.forEach((detach) => detach());
|
|
322
|
+
this.spaces.forEach((space) => space.close());
|
|
323
|
+
if (this.streamer == null) return;
|
|
324
|
+
await this.streamer.close();
|
|
325
|
+
}
|
|
326
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
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 TimeStamp } from "@synnaxlabs/x";
|
|
11
|
+
|
|
12
|
+
// Brands instances through the global symbol registry so matches() holds across
|
|
13
|
+
// duplicated module instances (dual CJS/ESM builds), where instanceof does not.
|
|
14
|
+
const BRAND = Symbol.for("synnaxlabs.client.query.deleted");
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The last value of a deleted record, delivered wherever a cached answer would be, so
|
|
18
|
+
* deletion can never be mistaken for live data. One instance exists per deletion:
|
|
19
|
+
* repeated reads of a deleted answer return the same reference.
|
|
20
|
+
*/
|
|
21
|
+
export class Deleted<D = unknown> {
|
|
22
|
+
/** The record's value at the moment it was deleted. */
|
|
23
|
+
readonly corpse: D;
|
|
24
|
+
/** When the deletion was applied. */
|
|
25
|
+
readonly deletedAt: TimeStamp;
|
|
26
|
+
protected readonly [BRAND] = true;
|
|
27
|
+
|
|
28
|
+
constructor(corpse: D, deletedAt: TimeStamp) {
|
|
29
|
+
this.corpse = corpse;
|
|
30
|
+
this.deletedAt = deletedAt;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Narrows a cached answer to the deleted case, carrying its record type
|
|
34
|
+
* onto the corpse. */
|
|
35
|
+
static matches<D>(value: D | Deleted<D> | undefined): value is Deleted<D> {
|
|
36
|
+
return typeof value === "object" && value !== null && BRAND in value;
|
|
37
|
+
}
|
|
38
|
+
}
|