Skip to main content
Version: v0.1.0

Transport adapters

The WebSocket, SSE, and ROS adapters share a similar shape: you pass a connection URL, a chunk callback, and optionally an error handler, and get back a stop function. The quantized adapter takes a WebSocket instance and a schema instead. Call the stop function to disconnect.

import {
createWebSocketAdapter,
createSSEAdapter,
createRosbridgeAdapter,
createQuantizedAdapter,
mergeChunkStreams,
withSourceTag,
} from "pointflow";

createWebSocketAdapter

Connects to a WebSocket and calls onChunk for each message that parses as a valid PointChunk.

const stop = createWebSocketAdapter(
url: string,
onChunk: (chunk: PointChunk) => void,
onError?: (event: Event) => void,
): () => void;

Non-chunk messages (JSON that doesn't match the PointChunk shape, or non-JSON frames) are silently ignored.


createSSEAdapter

Connects to a Server-Sent Events endpoint. Each data: event should carry a JSON-encoded PointChunk.

const stop = createSSEAdapter(
url: string,
onChunk: (chunk: PointChunk) => void,
onError?: (error: Error) => void,
): () => void;

createRosbridgeAdapter

Subscribes to a ROS topic via rosbridge v2 WebSocket protocol and translates sensor_msgs/PointCloud2 messages.

const stop = createRosbridgeAdapter(
wsUrl: string,
topic: string,
options: {
fields?: Record<string, string>; // ROS field name → PointFlow attribute key
onChunk: (chunk: PointChunk) => void;
onError?: (event: Event) => void;
},
): () => void;

x, y, z are always extracted. Other fields need to be listed in fields.


createQuantizedAdapter

Decodes compact binary WebSocket messages. Each point is 6 bytes (3 × uint16 XYZ) vs 12 bytes for float32.

const stop = createQuantizedAdapter(
ws: WebSocket,
schema: {
attributes: Array<{
key: string;
min: number;
max: number;
}>;
},
onChunk: (chunk: PointChunk) => void,
): () => void;

The attributes array must match the server's channel order. Each attribute is dequantized with value = min + (uint16 / 65535) × (max - min).

Calling stop() detaches the listener. It does NOT close the WebSocket — you're responsible for that.


mergeChunkStreams

Fans in multiple chunk sources into one emit callback:

import { mergeChunkStreams } from "pointflow";

const stop = mergeChunkStreams([sourceA, sourceB], emit);
// call stop() to disconnect all sources

sources is an array of ChunkSourceFactory functions (each takes an emit callback and returns an unsubscribe). emit is the ChunkEmitter you want all sources to feed into. Returns an unsubscribe that stops all sources at once.


withSourceTag

Wraps an emit callback to stamp a sourceId onto each chunk it receives:

import { withSourceTag } from "pointflow";

const taggedEmit = withSourceTag("lidar-front", emit);
adapter.connect(taggedEmit);

The first argument is the source ID string. The second is the ChunkEmitter to wrap. Returns a new ChunkEmitter that forwards chunks with sourceId set (won't overwrite an existing sourceId).


detectWebGPUSupport

Asynchronous WebGPU capability check:

import { detectWebGPUSupport } from "pointflow";

const available: boolean = await detectWebGPUSupport();

detectWebGPUSync

Synchronous check (less accurate — prefer detectWebGPUSupport when you can await):

import { detectWebGPUSync } from "pointflow";

const available = detectWebGPUSync();

detectSabSupport

Checks SharedArrayBuffer availability (needed for some high-perf transfer paths):

import { detectSabSupport } from "pointflow";

const { available, crossOriginIsolated, message } = detectSabSupport();
// available: boolean
// crossOriginIsolated: boolean — whether COOP/COEP headers are set
// message: string — human-readable explanation