@honua/react 0.1.2-beta.0 → 0.1.7-beta.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/contract/discovery.d.ts +34 -0
- package/contract/discovery.d.ts.map +1 -1
- package/contract/index.d.ts +7 -5
- package/contract/index.d.ts.map +1 -1
- package/contract/index.js +3 -2
- package/contract/pmtiles.d.ts +10 -1
- package/contract/pmtiles.d.ts.map +1 -1
- package/contract/pmtiles.js +10 -2
- package/contract/protocol-module.d.ts +84 -9
- package/contract/protocol-module.d.ts.map +1 -1
- package/contract/query-filter-fes.d.ts +18 -0
- package/contract/query-filter-fes.d.ts.map +1 -0
- package/contract/query-filter-fes.js +122 -0
- package/contract/query-filter.d.ts +300 -0
- package/contract/query-filter.d.ts.map +1 -0
- package/contract/query-filter.js +883 -0
- package/contract/schema.d.ts +12 -0
- package/contract/schema.d.ts.map +1 -1
- package/contract/schema.js +34 -0
- package/contract/source-capability-support.d.ts.map +1 -1
- package/contract/source-capability-support.js +15 -3
- package/contract/source.d.ts +45 -25
- package/contract/source.d.ts.map +1 -1
- package/contract/source.js +719 -479
- package/contract/types.d.ts +88 -19
- package/contract/types.d.ts.map +1 -1
- package/contract/types.js +4 -0
- package/contract/widget-source.d.ts.map +1 -1
- package/core/client.d.ts +51 -21
- package/core/client.d.ts.map +1 -1
- package/core/client.js +234 -54
- package/core/error-classifications.d.ts +23 -0
- package/core/error-classifications.d.ts.map +1 -1
- package/core/error-classifications.js +23 -0
- package/core/error-code-registry.d.ts +24 -1
- package/core/error-code-registry.d.ts.map +1 -1
- package/core/error-code-registry.js +23 -0
- package/core/error-envelope.js +2 -0
- package/core/errors.d.ts +2 -2
- package/core/errors.d.ts.map +1 -1
- package/core/errors.js +1 -1
- package/core/geoparquet-sql.d.ts +69 -5
- package/core/geoparquet-sql.d.ts.map +1 -1
- package/core/geoparquet-sql.js +327 -10
- package/core/odata-write-codec.d.ts.map +1 -1
- package/core/odata-write-codec.js +0 -1
- package/core/odata.d.ts +6 -0
- package/core/odata.d.ts.map +1 -1
- package/core/odata.js +6 -1
- package/core/ogc-processes.d.ts +182 -25
- package/core/ogc-processes.d.ts.map +1 -1
- package/core/ogc-processes.js +602 -30
- package/core/process-runner.d.ts +8 -1
- package/core/process-runner.d.ts.map +1 -1
- package/core/process-runner.js +1 -0
- package/core/protocol-transport.d.ts +2 -0
- package/core/protocol-transport.d.ts.map +1 -1
- package/core/stac.d.ts +32 -0
- package/core/stac.d.ts.map +1 -1
- package/core/stac.js +158 -23
- package/core/surfaces.d.ts.map +1 -1
- package/core/surfaces.js +273 -68
- package/core/types.d.ts +138 -11
- package/core/types.d.ts.map +1 -1
- package/core/wfs-axis-order.d.ts +18 -0
- package/core/wfs-axis-order.d.ts.map +1 -0
- package/core/wfs-axis-order.js +108 -0
- package/core/wfs-capabilities.d.ts +65 -24
- package/core/wfs-capabilities.d.ts.map +1 -1
- package/core/wfs-capabilities.js +237 -27
- package/core/wfs-filter.d.ts +26 -3
- package/core/wfs-filter.d.ts.map +1 -1
- package/core/wfs-filter.js +48 -53
- package/core/wfs-protocol-error.d.ts +12 -0
- package/core/wfs-protocol-error.d.ts.map +1 -0
- package/core/wfs-protocol-error.js +13 -0
- package/core/wfs.d.ts +53 -1
- package/core/wfs.d.ts.map +1 -1
- package/core/wfs.js +251 -29
- package/core/wms-feature-info.d.ts +92 -0
- package/core/wms-feature-info.d.ts.map +1 -0
- package/core/wms-feature-info.js +285 -0
- package/core/wms.d.ts +9 -0
- package/core/wms.d.ts.map +1 -1
- package/core/wms.js +17 -5
- package/esri-compat/event-bus.d.ts +20 -0
- package/esri-compat/event-bus.d.ts.map +1 -1
- package/esri-compat/feature-filter.d.ts +46 -1
- package/esri-compat/feature-filter.d.ts.map +1 -1
- package/esri-compat/feature-filter.js +49 -0
- package/esri-compat/geojson-layer.d.ts +4 -2
- package/esri-compat/geojson-layer.d.ts.map +1 -1
- package/esri-compat/geojson-layer.js +4 -2
- package/esri-compat/identity-manager.js +2 -2
- package/esri-compat/imagery-layer.d.ts +2 -1
- package/esri-compat/imagery-layer.d.ts.map +1 -1
- package/esri-compat/imagery-layer.js +2 -1
- package/esri-compat/layer-list.d.ts +8 -1
- package/esri-compat/layer-list.d.ts.map +1 -1
- package/esri-compat/layer-list.js +11 -4
- package/esri-compat/legend.d.ts.map +1 -1
- package/esri-compat/legend.js +1 -1
- package/esri-compat/locator.d.ts +297 -0
- package/esri-compat/locator.d.ts.map +1 -0
- package/esri-compat/locator.js +579 -0
- package/esri-compat/map-image-layer.d.ts.map +1 -1
- package/esri-compat/map-view.d.ts.map +1 -1
- package/esri-compat/map-view.js +1 -1
- package/esri-compat/scene-view.d.ts.map +1 -1
- package/esri-compat/time-slider.d.ts +29 -0
- package/esri-compat/time-slider.d.ts.map +1 -1
- package/esri-compat/time-slider.js +117 -0
- package/esri-compat/wfs-layer.d.ts +2 -1
- package/esri-compat/wfs-layer.d.ts.map +1 -1
- package/esri-compat/wfs-layer.js +2 -1
- package/esri-compat/widget-host.d.ts +42 -6
- package/esri-compat/widget-host.d.ts.map +1 -1
- package/esri-compat/widget-host.js +99 -10
- package/generated-app/projection.d.ts.map +1 -1
- package/generated-app/runtime.d.ts.map +1 -1
- package/interactions/declarative-contract.d.ts +149 -0
- package/interactions/declarative-contract.d.ts.map +1 -0
- package/interactions/declarative-contract.js +293 -0
- package/interactions/declarative.d.ts +198 -0
- package/interactions/declarative.d.ts.map +1 -0
- package/interactions/declarative.js +470 -0
- package/interactions/feature-state.d.ts +7 -0
- package/interactions/feature-state.d.ts.map +1 -1
- package/interactions/feature-state.js +10 -2
- package/map/data-to-map-bridge.d.ts +1 -1
- package/map/data-to-map-bridge.d.ts.map +1 -1
- package/map/data-to-map-bridge.js +1 -2
- package/map/honua-map.d.ts.map +1 -1
- package/map/honua-map.js +1 -1
- package/map/index.d.ts +2 -0
- package/map/index.d.ts.map +1 -1
- package/map/index.js +2 -0
- package/map/maplibre-target.js +1 -1
- package/map/realtime-reconciliation-adapter.d.ts +98 -0
- package/map/realtime-reconciliation-adapter.d.ts.map +1 -0
- package/map/realtime-reconciliation-adapter.js +84 -0
- package/map/temporal-playback.d.ts +25 -0
- package/map/temporal-playback.d.ts.map +1 -1
- package/map/temporal-playback.js +29 -1
- package/package.json +4 -3
- package/query-planner/canonical-filter.d.ts +30 -0
- package/query-planner/canonical-filter.d.ts.map +1 -0
- package/query-planner/canonical-filter.js +30 -0
- package/query-planner/columnar-plan.d.ts +63 -0
- package/query-planner/columnar-plan.d.ts.map +1 -0
- package/query-planner/columnar-plan.js +94 -0
- package/query-planner/diagnostics.d.ts +3 -3
- package/query-planner/diagnostics.d.ts.map +1 -1
- package/query-planner/diagnostics.js +17 -4
- package/query-planner/duckdb.d.ts.map +1 -1
- package/query-planner/duckdb.js +16 -2
- package/query-planner/execution-context.d.ts.map +1 -1
- package/query-planner/execution-context.js +3 -1
- package/query-planner/executor.d.ts.map +1 -1
- package/query-planner/executor.js +7 -1
- package/query-planner/geoservices.d.ts.map +1 -1
- package/query-planner/geoservices.js +24 -5
- package/query-planner/grpc.d.ts.map +1 -1
- package/query-planner/grpc.js +29 -5
- package/query-planner/index.d.ts +20 -5
- package/query-planner/index.d.ts.map +1 -1
- package/query-planner/index.js +16 -3
- package/query-planner/ir.d.ts +6 -1
- package/query-planner/ir.d.ts.map +1 -1
- package/query-planner/ir.js +63 -1
- package/query-planner/odata-protocol-module.d.ts +54 -0
- package/query-planner/odata-protocol-module.d.ts.map +1 -0
- package/query-planner/odata-protocol-module.js +199 -0
- package/query-planner/odata-v1.d.ts +23 -0
- package/query-planner/odata-v1.d.ts.map +1 -0
- package/query-planner/odata-v1.js +202 -0
- package/query-planner/odata.d.ts +0 -3
- package/query-planner/odata.d.ts.map +1 -1
- package/query-planner/odata.js +0 -143
- package/query-planner/ogc-features.d.ts.map +1 -1
- package/query-planner/ogc-features.js +23 -1
- package/query-planner/planner.d.ts +2 -2
- package/query-planner/planner.d.ts.map +1 -1
- package/query-planner/planner.js +146 -27
- package/query-planner/representation.d.ts +59 -0
- package/query-planner/representation.d.ts.map +1 -0
- package/query-planner/representation.js +140 -0
- package/query-planner/types.d.ts +153 -3
- package/query-planner/types.d.ts.map +1 -1
- package/query-planner/wfs-protocol-module.d.ts +57 -0
- package/query-planner/wfs-protocol-module.d.ts.map +1 -0
- package/query-planner/wfs-protocol-module.js +731 -0
- package/query-planner/wfs-v1.d.ts +41 -0
- package/query-planner/wfs-v1.d.ts.map +1 -0
- package/query-planner/wfs-v1.js +366 -0
- package/query-planner/wfs.d.ts +1 -3
- package/query-planner/wfs.d.ts.map +1 -1
- package/query-planner/wfs.js +1 -70
- package/react/honua-map.d.ts +3 -1
- package/react/honua-map.d.ts.map +1 -1
- package/react/honua-map.js +11 -1
- package/react/hooks.d.ts +1 -1
- package/react/hooks.js +1 -1
- package/react/selection.d.ts.map +1 -1
- package/react/selection.js +0 -0
- package/react/use-mounted-source.d.ts +1 -1
- package/react/use-mounted-source.js +1 -1
- package/realtime/checkpoint-store.d.ts +206 -0
- package/realtime/checkpoint-store.d.ts.map +1 -0
- package/realtime/checkpoint-store.js +504 -0
- package/realtime/contract.d.ts +142 -0
- package/realtime/contract.d.ts.map +1 -0
- package/realtime/contract.js +154 -0
- package/realtime/exploration.d.ts +16 -0
- package/realtime/exploration.d.ts.map +1 -0
- package/realtime/exploration.js +32 -0
- package/realtime/honua-server.d.ts +131 -0
- package/realtime/honua-server.d.ts.map +1 -0
- package/realtime/honua-server.js +302 -0
- package/realtime/index.d.ts +39 -0
- package/realtime/index.d.ts.map +1 -0
- package/realtime/index.js +26 -0
- package/realtime/odata-delta.d.ts +114 -0
- package/realtime/odata-delta.d.ts.map +1 -0
- package/realtime/odata-delta.js +483 -0
- package/realtime/projections.d.ts +30 -0
- package/realtime/projections.d.ts.map +1 -0
- package/realtime/projections.js +51 -0
- package/realtime/reconciliation.d.ts +245 -0
- package/realtime/reconciliation.d.ts.map +1 -0
- package/realtime/reconciliation.js +377 -0
- package/realtime/reducer.d.ts +14 -0
- package/realtime/reducer.d.ts.map +1 -0
- package/realtime/reducer.js +351 -0
- package/realtime/resumable-transport.d.ts +111 -0
- package/realtime/resumable-transport.d.ts.map +1 -0
- package/realtime/resumable-transport.js +406 -0
- package/realtime/resumable.d.ts +104 -0
- package/realtime/resumable.d.ts.map +1 -0
- package/realtime/resumable.js +632 -0
- package/realtime/sse.d.ts +23 -0
- package/realtime/sse.d.ts.map +1 -0
- package/realtime/sse.js +153 -0
- package/realtime/store.d.ts +18 -0
- package/realtime/store.d.ts.map +1 -0
- package/realtime/store.js +63 -0
- package/realtime/types.d.ts +190 -0
- package/realtime/types.d.ts.map +1 -0
- package/realtime/types.js +10 -0
- package/realtime/websocket.d.ts +60 -0
- package/realtime/websocket.d.ts.map +1 -0
- package/realtime/websocket.js +157 -0
- package/realtime/wire.d.ts +28 -0
- package/realtime/wire.d.ts.map +1 -0
- package/realtime/wire.js +73 -0
- package/runtime/index.d.ts +6 -2
- package/runtime/index.d.ts.map +1 -1
- package/runtime/index.js +3 -1
- package/runtime/load-package.d.ts +24 -0
- package/runtime/load-package.d.ts.map +1 -1
- package/runtime/load-package.js +45 -1
- package/runtime/maplibre-renderer.d.ts +11 -0
- package/runtime/maplibre-renderer.d.ts.map +1 -1
- package/runtime/maplibre-renderer.js +32 -7
- package/runtime/offline-region-protocol.d.ts +73 -0
- package/runtime/offline-region-protocol.d.ts.map +1 -0
- package/runtime/offline-region-protocol.js +63 -0
- package/runtime/offline-region-style.d.ts +78 -0
- package/runtime/offline-region-style.d.ts.map +1 -0
- package/runtime/offline-region-style.js +147 -0
- package/runtime/pmtiles-protocol.d.ts +7 -8
- package/runtime/pmtiles-protocol.d.ts.map +1 -1
- package/runtime/pmtiles-protocol.js +19 -66
- package/runtime/protocol-registry.d.ts +55 -0
- package/runtime/protocol-registry.d.ts.map +1 -0
- package/runtime/protocol-registry.js +103 -0
- package/runtime/runtime.d.ts +2 -0
- package/runtime/runtime.d.ts.map +1 -1
- package/runtime/runtime.js +6 -1
- package/runtime/style-compose.d.ts.map +1 -1
- package/runtime/style-compose.js +78 -9
- package/studio/index.d.ts +24 -7
- package/studio/index.d.ts.map +1 -1
- package/studio/index.js +21 -7
- package/studio/lifecycle-client.d.ts +164 -0
- package/studio/lifecycle-client.d.ts.map +1 -0
- package/studio/lifecycle-client.js +299 -0
- package/studio/lifecycle-errors.d.ts +91 -0
- package/studio/lifecycle-errors.d.ts.map +1 -0
- package/studio/lifecycle-errors.js +77 -0
- package/studio/lifecycle-types.d.ts +321 -0
- package/studio/lifecycle-types.d.ts.map +1 -0
- package/studio/lifecycle-types.js +22 -0
- package/webmap/convert-label.js +0 -1
- package/webmap/convert-symbol.d.ts.map +1 -1
package/realtime/sse.js
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { decodeDefaultRealtimeEnvelope, normalizeRealtimeErrorEvent, realtimeFailure } from "./wire.js";
|
|
2
|
+
const DEFAULT_EVENT_TYPES = ["snapshot", "upsert", "delete", "delta", "heartbeat", "status", "error"];
|
|
3
|
+
export function createRealtimeServerSentEventsTransport(options) {
|
|
4
|
+
return {
|
|
5
|
+
capabilities: {
|
|
6
|
+
kind: "sse",
|
|
7
|
+
resumeModes: ["cursor", "watermark", "timestamp", "sequence", "delta-token"],
|
|
8
|
+
emitsHeartbeats: true,
|
|
9
|
+
emitsWatermarks: true,
|
|
10
|
+
},
|
|
11
|
+
subscribe(request, observer) {
|
|
12
|
+
// If the caller's signal is already aborted at subscribe time, the
|
|
13
|
+
// "abort" event has already fired and will never fire again, so the
|
|
14
|
+
// listener registered below would never run and the EventSource would
|
|
15
|
+
// leak (open connection + auto-reconnect + attached listeners). Bail
|
|
16
|
+
// out synchronously before constructing anything, mirroring the
|
|
17
|
+
// up-front `signal?.aborted` guard used elsewhere (e.g. core/batch.ts).
|
|
18
|
+
if (request.signal?.aborted) {
|
|
19
|
+
observer.complete();
|
|
20
|
+
return { close: () => { } };
|
|
21
|
+
}
|
|
22
|
+
let source;
|
|
23
|
+
try {
|
|
24
|
+
const url = new URL(options.url, "http://honua.local");
|
|
25
|
+
encodeDefaultRealtimeRequest(url, request);
|
|
26
|
+
options.encodeRequest?.(url, request);
|
|
27
|
+
source = createEventSource(resolveEventSourceUrl(options.url, url), options);
|
|
28
|
+
}
|
|
29
|
+
catch (cause) {
|
|
30
|
+
throw realtimeFailure("delivery-failed", "Unable to initialize the realtime Server-Sent Events transport.", cause);
|
|
31
|
+
}
|
|
32
|
+
let closed = false;
|
|
33
|
+
const listeners = [];
|
|
34
|
+
const emitPayload = (payload) => {
|
|
35
|
+
if (closed || payload.trim() === "")
|
|
36
|
+
return;
|
|
37
|
+
let event;
|
|
38
|
+
try {
|
|
39
|
+
const decoded = (options.decodeEvent ?? (decodeRealtimeServerSentEvent))(JSON.parse(payload));
|
|
40
|
+
event = normalizeRealtimeErrorEvent(decoded);
|
|
41
|
+
}
|
|
42
|
+
catch (cause) {
|
|
43
|
+
observer.error(realtimeFailure("invalid-event", "Realtime Server-Sent Events payload decoding failed.", cause));
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
observer.next(event);
|
|
48
|
+
}
|
|
49
|
+
catch (cause) {
|
|
50
|
+
observer.error(realtimeFailure("consumer-failed", "Realtime event observer rejected delivery.", cause));
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
const messageListener = (event) => emitPayload(event.data);
|
|
54
|
+
source.onopen = () => {
|
|
55
|
+
if (!closed)
|
|
56
|
+
observer.next({ type: "status", status: "live", receivedAt: Date.now() });
|
|
57
|
+
};
|
|
58
|
+
source.onmessage = messageListener;
|
|
59
|
+
source.onerror = (event) => {
|
|
60
|
+
if (!closed)
|
|
61
|
+
observer.next({ type: "status", status: "reconnecting", reason: "sse-error", receivedAt: Date.now() });
|
|
62
|
+
if (isEventSourceClosed(source)) {
|
|
63
|
+
observer.error(realtimeFailure("transport-gap", "Realtime Server-Sent Events transport closed unexpectedly.", event));
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
for (const type of options.eventTypes ?? DEFAULT_EVENT_TYPES) {
|
|
67
|
+
if (!source.addEventListener)
|
|
68
|
+
break;
|
|
69
|
+
const listener = (event) => {
|
|
70
|
+
// EventSource also dispatches its native connection-error Event
|
|
71
|
+
// under the name "error". It has no data payload and must remain
|
|
72
|
+
// the responsibility of `source.onerror` below.
|
|
73
|
+
if (typeof event.data === "string")
|
|
74
|
+
emitPayload(event.data);
|
|
75
|
+
};
|
|
76
|
+
source.addEventListener(type, listener);
|
|
77
|
+
listeners.push([type, listener]);
|
|
78
|
+
}
|
|
79
|
+
const abortListener = () => closeSource();
|
|
80
|
+
request.signal?.addEventListener("abort", abortListener, { once: true });
|
|
81
|
+
function closeSource() {
|
|
82
|
+
if (closed)
|
|
83
|
+
return;
|
|
84
|
+
closed = true;
|
|
85
|
+
request.signal?.removeEventListener("abort", abortListener);
|
|
86
|
+
for (const [type, listener] of listeners)
|
|
87
|
+
source.removeEventListener?.(type, listener);
|
|
88
|
+
source.onopen = null;
|
|
89
|
+
source.onmessage = null;
|
|
90
|
+
source.onerror = null;
|
|
91
|
+
source.close();
|
|
92
|
+
observer.complete();
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
close: closeSource,
|
|
96
|
+
};
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
export function encodeDefaultRealtimeRequest(url, request) {
|
|
101
|
+
url.searchParams.set("sourceId", String(request.sourceId));
|
|
102
|
+
if (request.layerId !== undefined)
|
|
103
|
+
url.searchParams.set("layerId", String(request.layerId));
|
|
104
|
+
if (request.requestId)
|
|
105
|
+
url.searchParams.set("requestId", request.requestId);
|
|
106
|
+
if (request.mode)
|
|
107
|
+
url.searchParams.set("mode", request.mode);
|
|
108
|
+
if (request.where)
|
|
109
|
+
url.searchParams.set("where", request.where);
|
|
110
|
+
if (request.fields?.length)
|
|
111
|
+
url.searchParams.set("fields", request.fields.join(","));
|
|
112
|
+
if (request.cursor ?? request.resumeFrom?.cursor)
|
|
113
|
+
url.searchParams.set("cursor", request.cursor ?? request.resumeFrom?.cursor ?? "");
|
|
114
|
+
if (request.watermark ?? request.resumeFrom?.watermark) {
|
|
115
|
+
url.searchParams.set("watermark", request.watermark ?? request.resumeFrom?.watermark ?? "");
|
|
116
|
+
}
|
|
117
|
+
if (request.timestamp ?? request.resumeFrom?.timestamp) {
|
|
118
|
+
url.searchParams.set("timestamp", request.timestamp ?? request.resumeFrom?.timestamp ?? "");
|
|
119
|
+
}
|
|
120
|
+
if (request.deltaToken ?? request.resumeFrom?.deltaToken) {
|
|
121
|
+
url.searchParams.set("deltaToken", request.deltaToken ?? request.resumeFrom?.deltaToken ?? "");
|
|
122
|
+
}
|
|
123
|
+
if (request.resumeFrom?.sequence !== undefined)
|
|
124
|
+
url.searchParams.set("sequence", String(request.resumeFrom.sequence));
|
|
125
|
+
if (request.spatialFilter !== undefined)
|
|
126
|
+
url.searchParams.set("spatialFilter", JSON.stringify(request.spatialFilter));
|
|
127
|
+
if (request.metadata !== undefined)
|
|
128
|
+
url.searchParams.set("metadata", JSON.stringify(request.metadata));
|
|
129
|
+
return url;
|
|
130
|
+
}
|
|
131
|
+
export function decodeRealtimeServerSentEvent(payload) {
|
|
132
|
+
return decodeDefaultRealtimeEnvelope(payload);
|
|
133
|
+
}
|
|
134
|
+
function createEventSource(url, options) {
|
|
135
|
+
if (options.eventSourceFactory) {
|
|
136
|
+
return options.eventSourceFactory(url, { withCredentials: options.withCredentials });
|
|
137
|
+
}
|
|
138
|
+
// The global `EventSource` is a constructor: calling it as a plain
|
|
139
|
+
// function (`EventSource(url, init)`) throws a TypeError in browsers,
|
|
140
|
+
// so the default path must construct with `new`.
|
|
141
|
+
const EventSourceCtor = globalThis.EventSource;
|
|
142
|
+
if (!EventSourceCtor)
|
|
143
|
+
throw new Error("EventSource is not available; provide eventSourceFactory for this runtime.");
|
|
144
|
+
return new EventSourceCtor(url, { withCredentials: options.withCredentials });
|
|
145
|
+
}
|
|
146
|
+
function resolveEventSourceUrl(input, url) {
|
|
147
|
+
if (input.startsWith("http://") || input.startsWith("https://"))
|
|
148
|
+
return url.toString();
|
|
149
|
+
return `${url.pathname}${url.search}`;
|
|
150
|
+
}
|
|
151
|
+
function isEventSourceClosed(source) {
|
|
152
|
+
return source.readyState === 2;
|
|
153
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Store and transport bridge for realtime feature state.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import type { RealtimeFeatureEvent, RealtimeFeatureState, RealtimeFeatureTransport, RealtimeReducerOptions, RealtimeStalenessOptions, RealtimeStateListener, RealtimeSubscriptionHandle, RealtimeSubscriptionRequest } from "./types.js";
|
|
7
|
+
export interface RealtimeFeatureStore<TFeature = unknown> {
|
|
8
|
+
readonly state: RealtimeFeatureState<TFeature>;
|
|
9
|
+
apply(event: RealtimeFeatureEvent<TFeature>): RealtimeFeatureState<TFeature>;
|
|
10
|
+
checkStale(options: RealtimeStalenessOptions): RealtimeFeatureState<TFeature>;
|
|
11
|
+
subscribe(listener: RealtimeStateListener<TFeature>, options?: {
|
|
12
|
+
readonly fireImmediately?: boolean;
|
|
13
|
+
}): () => void;
|
|
14
|
+
connect(transport: RealtimeFeatureTransport<TFeature>, request: RealtimeSubscriptionRequest): RealtimeSubscriptionHandle;
|
|
15
|
+
close(): void;
|
|
16
|
+
}
|
|
17
|
+
export declare function createRealtimeFeatureStore<TFeature = unknown>(initialState?: RealtimeFeatureState<TFeature>, options?: RealtimeReducerOptions): RealtimeFeatureStore<TFeature>;
|
|
18
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/realtime/store.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EACV,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,EACxB,sBAAsB,EACtB,wBAAwB,EACxB,qBAAqB,EACrB,0BAA0B,EAC1B,2BAA2B,EAC5B,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,oBAAoB,CAAC,QAAQ,GAAG,OAAO;IACtD,QAAQ,CAAC,KAAK,EAAE,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAC/C,KAAK,CAAC,KAAK,EAAE,oBAAoB,CAAC,QAAQ,CAAC,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAC7E,UAAU,CAAC,OAAO,EAAE,wBAAwB,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAC9E,SAAS,CAAC,QAAQ,EAAE,qBAAqB,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,MAAM,IAAI,CAAC;IACnH,OAAO,CACL,SAAS,EAAE,wBAAwB,CAAC,QAAQ,CAAC,EAC7C,OAAO,EAAE,2BAA2B,GACnC,0BAA0B,CAAC;IAC9B,KAAK,IAAI,IAAI,CAAC;CACf;AAED,wBAAgB,0BAA0B,CAAC,QAAQ,GAAG,OAAO,EAC3D,YAAY,GAAE,oBAAoB,CAAC,QAAQ,CAAyC,EACpF,OAAO,GAAE,sBAA2B,GACnC,oBAAoB,CAAC,QAAQ,CAAC,CA2DhC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Store and transport bridge for realtime feature state.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { emptyRealtimeFeatureState, reconcileRealtimeStaleness, reduceRealtimeFeatureState } from "./reducer.js";
|
|
7
|
+
export function createRealtimeFeatureStore(initialState = emptyRealtimeFeatureState(), options = {}) {
|
|
8
|
+
let state = initialState;
|
|
9
|
+
let activeHandle;
|
|
10
|
+
const listeners = new Set();
|
|
11
|
+
function emit(event) {
|
|
12
|
+
for (const listener of [...listeners])
|
|
13
|
+
listener(state, event);
|
|
14
|
+
}
|
|
15
|
+
function setState(next, event) {
|
|
16
|
+
if (Object.is(state, next))
|
|
17
|
+
return state;
|
|
18
|
+
state = next;
|
|
19
|
+
emit(event);
|
|
20
|
+
return state;
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
get state() {
|
|
24
|
+
return state;
|
|
25
|
+
},
|
|
26
|
+
apply(event) {
|
|
27
|
+
return setState(reduceRealtimeFeatureState(state, event, options), event);
|
|
28
|
+
},
|
|
29
|
+
checkStale(stalenessOptions) {
|
|
30
|
+
return setState(reconcileRealtimeStaleness(state, stalenessOptions), undefined);
|
|
31
|
+
},
|
|
32
|
+
subscribe(listener, subscribeOptions = {}) {
|
|
33
|
+
listeners.add(listener);
|
|
34
|
+
if (subscribeOptions.fireImmediately)
|
|
35
|
+
listener(state, undefined);
|
|
36
|
+
return () => {
|
|
37
|
+
listeners.delete(listener);
|
|
38
|
+
};
|
|
39
|
+
},
|
|
40
|
+
connect(transport, request) {
|
|
41
|
+
activeHandle?.close();
|
|
42
|
+
this.apply({ type: "status", status: "connecting" });
|
|
43
|
+
activeHandle = transport.subscribe(request, {
|
|
44
|
+
next: (event) => this.apply(event),
|
|
45
|
+
error: (error) => this.apply({ type: "error", error }),
|
|
46
|
+
complete: () => this.apply({ type: "status", status: "closed" }),
|
|
47
|
+
});
|
|
48
|
+
return {
|
|
49
|
+
close: () => {
|
|
50
|
+
activeHandle?.close();
|
|
51
|
+
activeHandle = undefined;
|
|
52
|
+
this.apply({ type: "status", status: "closed" });
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
},
|
|
56
|
+
close() {
|
|
57
|
+
activeHandle?.close();
|
|
58
|
+
activeHandle = undefined;
|
|
59
|
+
setState({ ...state, status: "closed" }, { type: "status", status: "closed" });
|
|
60
|
+
listeners.clear();
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Realtime operational feature state.
|
|
3
|
+
*
|
|
4
|
+
* These types model live create/update/delete/snapshot delivery without
|
|
5
|
+
* committing app code to SSE, WebSocket, or polling. Transport adapters emit
|
|
6
|
+
* `RealtimeFeatureEvent`s; apps and SDK bindings consume reconciled state.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
import type { FeatureId, SourceId } from "../contract/types.js";
|
|
11
|
+
export type RealtimeConnectionStatus = "idle" | "connecting" | "live" | "reconnecting" | "stale" | "offline" | "closed" | "error";
|
|
12
|
+
export type RealtimeTransportKind = "sse" | "websocket" | "polling" | "mock" | "custom";
|
|
13
|
+
export type RealtimeResumeMode = "none" | "cursor" | "watermark" | "timestamp" | "sequence" | "delta-token";
|
|
14
|
+
export type RealtimeSubscriptionMode = "snapshot" | "snapshot-then-delta" | "delta";
|
|
15
|
+
export interface RealtimeResumeCheckpoint {
|
|
16
|
+
readonly cursor?: string;
|
|
17
|
+
readonly watermark?: string;
|
|
18
|
+
readonly timestamp?: string;
|
|
19
|
+
readonly sequence?: number;
|
|
20
|
+
readonly deltaToken?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface RealtimeFeaturePatch<TFeature = unknown> {
|
|
23
|
+
readonly id: FeatureId;
|
|
24
|
+
readonly sourceId?: SourceId;
|
|
25
|
+
readonly feature: TFeature;
|
|
26
|
+
readonly version?: number;
|
|
27
|
+
readonly updatedAt?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface RealtimeFeatureRecord<TFeature = unknown> extends RealtimeFeaturePatch<TFeature> {
|
|
30
|
+
readonly key: string;
|
|
31
|
+
readonly cursor?: string;
|
|
32
|
+
readonly sequence?: number;
|
|
33
|
+
readonly receivedAt: number;
|
|
34
|
+
}
|
|
35
|
+
export interface RealtimeFeatureTombstone {
|
|
36
|
+
readonly id: FeatureId;
|
|
37
|
+
readonly sourceId?: SourceId;
|
|
38
|
+
readonly key: string;
|
|
39
|
+
readonly cursor?: string;
|
|
40
|
+
readonly sequence?: number;
|
|
41
|
+
readonly version?: number;
|
|
42
|
+
readonly updatedAt?: string;
|
|
43
|
+
readonly deletedAt: number;
|
|
44
|
+
}
|
|
45
|
+
export interface RealtimeFeatureEventBase {
|
|
46
|
+
readonly eventId?: string;
|
|
47
|
+
readonly cursor?: string;
|
|
48
|
+
readonly watermark?: string;
|
|
49
|
+
readonly timestamp?: string;
|
|
50
|
+
readonly deltaToken?: string;
|
|
51
|
+
readonly checkpoint?: RealtimeResumeCheckpoint;
|
|
52
|
+
readonly sequence?: number;
|
|
53
|
+
readonly receivedAt?: number;
|
|
54
|
+
}
|
|
55
|
+
export interface RealtimeSnapshotEvent<TFeature = unknown> extends RealtimeFeatureEventBase {
|
|
56
|
+
readonly type: "snapshot";
|
|
57
|
+
readonly features: ReadonlyArray<RealtimeFeaturePatch<TFeature>>;
|
|
58
|
+
/** Replace the current live set. @default true */
|
|
59
|
+
readonly replace?: boolean;
|
|
60
|
+
}
|
|
61
|
+
export interface RealtimeUpsertEvent<TFeature = unknown> extends RealtimeFeatureEventBase {
|
|
62
|
+
readonly type: "upsert";
|
|
63
|
+
readonly feature: RealtimeFeaturePatch<TFeature>;
|
|
64
|
+
}
|
|
65
|
+
export interface RealtimeDeleteEvent extends RealtimeFeatureEventBase {
|
|
66
|
+
readonly type: "delete";
|
|
67
|
+
readonly id: FeatureId;
|
|
68
|
+
readonly sourceId?: SourceId;
|
|
69
|
+
readonly version?: number;
|
|
70
|
+
readonly updatedAt?: string;
|
|
71
|
+
readonly deletedAt?: number;
|
|
72
|
+
}
|
|
73
|
+
export interface RealtimeDeletePatch {
|
|
74
|
+
readonly id: FeatureId;
|
|
75
|
+
readonly sourceId?: SourceId;
|
|
76
|
+
readonly version?: number;
|
|
77
|
+
readonly updatedAt?: string;
|
|
78
|
+
readonly deletedAt?: number;
|
|
79
|
+
}
|
|
80
|
+
export interface RealtimeDeltaEvent<TFeature = unknown> extends RealtimeFeatureEventBase {
|
|
81
|
+
readonly type: "delta";
|
|
82
|
+
readonly upserts?: ReadonlyArray<RealtimeFeaturePatch<TFeature>>;
|
|
83
|
+
readonly deletes?: ReadonlyArray<RealtimeDeletePatch>;
|
|
84
|
+
}
|
|
85
|
+
export interface RealtimeHeartbeatEvent extends RealtimeFeatureEventBase {
|
|
86
|
+
readonly type: "heartbeat";
|
|
87
|
+
}
|
|
88
|
+
export interface RealtimeStatusEvent extends RealtimeFeatureEventBase {
|
|
89
|
+
readonly type: "status";
|
|
90
|
+
readonly status: RealtimeConnectionStatus;
|
|
91
|
+
readonly staleSince?: number;
|
|
92
|
+
readonly reason?: string;
|
|
93
|
+
readonly retryAfterMs?: number;
|
|
94
|
+
readonly reconnectAttempt?: number;
|
|
95
|
+
}
|
|
96
|
+
export interface RealtimeErrorEvent extends RealtimeFeatureEventBase {
|
|
97
|
+
readonly type: "error";
|
|
98
|
+
readonly error: unknown;
|
|
99
|
+
readonly terminal?: boolean;
|
|
100
|
+
readonly code?: string;
|
|
101
|
+
readonly retryAfterMs?: number;
|
|
102
|
+
}
|
|
103
|
+
export type RealtimeFeatureEvent<TFeature = unknown> = RealtimeSnapshotEvent<TFeature> | RealtimeUpsertEvent<TFeature> | RealtimeDeleteEvent | RealtimeDeltaEvent<TFeature> | RealtimeHeartbeatEvent | RealtimeStatusEvent | RealtimeErrorEvent;
|
|
104
|
+
export interface RealtimeFeatureState<TFeature = unknown> {
|
|
105
|
+
readonly status: RealtimeConnectionStatus;
|
|
106
|
+
readonly records: Readonly<Record<string, RealtimeFeatureRecord<TFeature>>>;
|
|
107
|
+
readonly tombstones: Readonly<Record<string, RealtimeFeatureTombstone>>;
|
|
108
|
+
readonly cursor?: string;
|
|
109
|
+
readonly watermark?: string;
|
|
110
|
+
readonly timestamp?: string;
|
|
111
|
+
readonly deltaToken?: string;
|
|
112
|
+
readonly checkpoint?: RealtimeResumeCheckpoint;
|
|
113
|
+
readonly lastSequence?: number;
|
|
114
|
+
readonly lastEventAt?: number;
|
|
115
|
+
readonly lastStatusAt?: number;
|
|
116
|
+
readonly lastHeartbeatAt?: number;
|
|
117
|
+
readonly staleSince?: number;
|
|
118
|
+
readonly error?: unknown;
|
|
119
|
+
readonly statusReason?: string;
|
|
120
|
+
readonly retryAfterMs?: number;
|
|
121
|
+
readonly reconnectAttempt?: number;
|
|
122
|
+
readonly terminalError?: boolean;
|
|
123
|
+
readonly ignoredEventCount: number;
|
|
124
|
+
readonly seenEventIds: ReadonlyArray<string>;
|
|
125
|
+
}
|
|
126
|
+
export interface RealtimeReducerOptions {
|
|
127
|
+
readonly now?: () => number;
|
|
128
|
+
readonly maxSeenEventIds?: number;
|
|
129
|
+
/**
|
|
130
|
+
* Upper bound on the number of delete tombstones retained in state. Outside a
|
|
131
|
+
* `replace` snapshot, tombstones are never cleared, so a long-lived delta
|
|
132
|
+
* subscription leaks one entry per delete. When the cap is exceeded the
|
|
133
|
+
* oldest tombstones (by `deletedAt`) are evicted, mirroring the
|
|
134
|
+
* {@link maxSeenEventIds} cap. Defaults to 1024; set to `0` to disable the
|
|
135
|
+
* count bound.
|
|
136
|
+
*/
|
|
137
|
+
readonly maxTombstones?: number;
|
|
138
|
+
/**
|
|
139
|
+
* Maximum age, in milliseconds, of a retained tombstone measured from its
|
|
140
|
+
* `deletedAt`. Tombstones older than this are dropped on the next reduce.
|
|
141
|
+
* Disabled (no age bound) when omitted.
|
|
142
|
+
*/
|
|
143
|
+
readonly tombstoneTtlMs?: number;
|
|
144
|
+
}
|
|
145
|
+
export interface RealtimeStalenessOptions {
|
|
146
|
+
readonly staleAfterMs: number;
|
|
147
|
+
readonly now?: number;
|
|
148
|
+
}
|
|
149
|
+
export interface RealtimeSubscriptionIdentity {
|
|
150
|
+
readonly sourceId: SourceId;
|
|
151
|
+
readonly layerId?: string | number;
|
|
152
|
+
readonly where?: string;
|
|
153
|
+
readonly fields?: ReadonlyArray<string>;
|
|
154
|
+
readonly spatialFilter?: unknown;
|
|
155
|
+
/**
|
|
156
|
+
* Optional caller-owned logical subscription id. Use this when a UI needs
|
|
157
|
+
* to reconnect the same source/layer/filter request across page reloads.
|
|
158
|
+
*/
|
|
159
|
+
readonly requestId?: string;
|
|
160
|
+
}
|
|
161
|
+
export interface RealtimeSubscriptionRequest extends RealtimeSubscriptionIdentity {
|
|
162
|
+
readonly mode?: RealtimeSubscriptionMode;
|
|
163
|
+
readonly resumeFrom?: RealtimeResumeCheckpoint;
|
|
164
|
+
readonly cursor?: string;
|
|
165
|
+
readonly watermark?: string;
|
|
166
|
+
readonly timestamp?: string;
|
|
167
|
+
readonly deltaToken?: string;
|
|
168
|
+
readonly signal?: AbortSignal;
|
|
169
|
+
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
170
|
+
}
|
|
171
|
+
export interface RealtimeFeatureObserver<TFeature = unknown> {
|
|
172
|
+
next(event: RealtimeFeatureEvent<TFeature>): void;
|
|
173
|
+
error(error: unknown): void;
|
|
174
|
+
complete(): void;
|
|
175
|
+
}
|
|
176
|
+
export interface RealtimeSubscriptionHandle {
|
|
177
|
+
close(): void;
|
|
178
|
+
}
|
|
179
|
+
export interface RealtimeTransportCapabilities {
|
|
180
|
+
readonly kind: RealtimeTransportKind;
|
|
181
|
+
readonly resumeModes?: ReadonlyArray<RealtimeResumeMode>;
|
|
182
|
+
readonly emitsHeartbeats?: boolean;
|
|
183
|
+
readonly emitsWatermarks?: boolean;
|
|
184
|
+
}
|
|
185
|
+
export interface RealtimeFeatureTransport<TFeature = unknown> {
|
|
186
|
+
readonly capabilities?: RealtimeTransportCapabilities;
|
|
187
|
+
subscribe(request: RealtimeSubscriptionRequest, observer: RealtimeFeatureObserver<TFeature>): RealtimeSubscriptionHandle;
|
|
188
|
+
}
|
|
189
|
+
export type RealtimeStateListener<TFeature = unknown> = (state: RealtimeFeatureState<TFeature>, event: RealtimeFeatureEvent<TFeature> | undefined) => void;
|
|
190
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/realtime/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Realtime operational feature state.
|
|
3
|
+
*
|
|
4
|
+
* These types model live create/update/delete/snapshot delivery without
|
|
5
|
+
* committing app code to SSE, WebSocket, or polling. Transport adapters emit
|
|
6
|
+
* `RealtimeFeatureEvent`s; apps and SDK bindings consume reconciled state.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Raw WebSocket wire transport for `@honua/sdk-js/realtime`. Mirrors
|
|
3
|
+
* `sse.ts`'s adapter shape (subscribe params encoded onto the connection URL,
|
|
4
|
+
* default JSON event decoding, `HonuaRealtimeResumeError` failure tagging)
|
|
5
|
+
* so the two transports are interchangeable everywhere a
|
|
6
|
+
* `RealtimeFeatureTransport` is expected, including
|
|
7
|
+
* {@link "./resumable-transport.js".createResumableRealtimeTransport}.
|
|
8
|
+
*
|
|
9
|
+
* This module opens exactly one socket per `subscribe()` call and never
|
|
10
|
+
* reconnects on its own — reconnect/backoff, bounded queueing, and resume
|
|
11
|
+
* ownership live in `resumable-transport.ts` (#557), matching the resumable
|
|
12
|
+
* delivery gate's explicit non-goal ("the gate never reconnects a
|
|
13
|
+
* transport itself").
|
|
14
|
+
*
|
|
15
|
+
* @module
|
|
16
|
+
*/
|
|
17
|
+
import type { RealtimeFeatureEvent, RealtimeFeatureTransport, RealtimeSubscriptionRequest } from "./types.js";
|
|
18
|
+
/**
|
|
19
|
+
* Minimal WebSocket surface the transport depends on. The global `WebSocket`
|
|
20
|
+
* constructor (browsers, and Node's built-in client since Node 22) already
|
|
21
|
+
* satisfies this; pass `webSocketFactory` to supply a polyfill or a mock in
|
|
22
|
+
* tests without adding a runtime dependency.
|
|
23
|
+
*/
|
|
24
|
+
export interface RealtimeWebSocket {
|
|
25
|
+
readonly readyState?: number;
|
|
26
|
+
onopen: ((event: Event) => void) | null;
|
|
27
|
+
onmessage: ((event: MessageEvent<string>) => void) | null;
|
|
28
|
+
onerror: ((event: Event) => void) | null;
|
|
29
|
+
onclose: ((event: RealtimeWebSocketCloseEvent) => void) | null;
|
|
30
|
+
close(code?: number, reason?: string): void;
|
|
31
|
+
send(data: string): void;
|
|
32
|
+
}
|
|
33
|
+
/** Subset of `CloseEvent` the transport reads; avoids depending on the DOM lib for `wasClean`. */
|
|
34
|
+
export interface RealtimeWebSocketCloseEvent {
|
|
35
|
+
readonly code?: number;
|
|
36
|
+
readonly reason?: string;
|
|
37
|
+
readonly wasClean?: boolean;
|
|
38
|
+
}
|
|
39
|
+
export type RealtimeWebSocketFactory = (url: string, protocols: string | ReadonlyArray<string> | undefined) => RealtimeWebSocket;
|
|
40
|
+
export interface RealtimeWebSocketTransportOptions<TFeature = unknown> {
|
|
41
|
+
readonly url: string;
|
|
42
|
+
readonly protocols?: string | ReadonlyArray<string>;
|
|
43
|
+
readonly webSocketFactory?: RealtimeWebSocketFactory;
|
|
44
|
+
readonly encodeRequest?: (url: URL, request: RealtimeSubscriptionRequest) => void;
|
|
45
|
+
readonly decodeEvent?: (payload: unknown) => RealtimeFeatureEvent<TFeature>;
|
|
46
|
+
/**
|
|
47
|
+
* Sent as a single JSON text frame immediately after the socket opens, for
|
|
48
|
+
* servers that expect an explicit subscribe message instead of (or in
|
|
49
|
+
* addition to) URL query parameters. The default transport never sends a
|
|
50
|
+
* subscribe frame on its own.
|
|
51
|
+
*/
|
|
52
|
+
readonly encodeSubscribeMessage?: (request: RealtimeSubscriptionRequest) => unknown;
|
|
53
|
+
/**
|
|
54
|
+
* WebSocket close codes treated as a normal, non-reconnectable end of the
|
|
55
|
+
* stream rather than a `transport-gap` failure. @default [1000]
|
|
56
|
+
*/
|
|
57
|
+
readonly cleanCloseCodes?: ReadonlyArray<number>;
|
|
58
|
+
}
|
|
59
|
+
export declare function createRealtimeWebSocketTransport<TFeature = unknown>(options: RealtimeWebSocketTransportOptions<TFeature>): RealtimeFeatureTransport<TFeature>;
|
|
60
|
+
//# sourceMappingURL=websocket.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../../../src/realtime/websocket.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EACV,oBAAoB,EACpB,wBAAwB,EAExB,2BAA2B,EAC5B,MAAM,YAAY,CAAC;AAGpB;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IACxC,SAAS,EAAE,CAAC,CAAC,KAAK,EAAE,YAAY,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1D,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IACzC,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,2BAA2B,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IAC/D,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,kGAAkG;AAClG,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,MAAM,wBAAwB,GAAG,CACrC,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,GAAG,SAAS,KAClD,iBAAiB,CAAC;AAEvB,MAAM,WAAW,iCAAiC,CAAC,QAAQ,GAAG,OAAO;IACnE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACpD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,wBAAwB,CAAC;IACrD,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,2BAA2B,KAAK,IAAI,CAAC;IAClF,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAC5E;;;;;OAKG;IACH,QAAQ,CAAC,sBAAsB,CAAC,EAAE,CAAC,OAAO,EAAE,2BAA2B,KAAK,OAAO,CAAC;IACpF;;;OAGG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CAClD;AAID,wBAAgB,gCAAgC,CAAC,QAAQ,GAAG,OAAO,EACjE,OAAO,EAAE,iCAAiC,CAAC,QAAQ,CAAC,GACnD,wBAAwB,CAAC,QAAQ,CAAC,CAwGpC"}
|