Skip to content

Custom Transport

You can implement custom transport layers for Teleportal by implementing the Transport interface. This guide shows you how.

A transport is a combination of a Source (for reading messages) and a Sink (for writing messages):

interface Transport<Context, Properties = {}> {
readable: ReadableStream<Message<Context>>;
writable: WritableStream<Message<Context>>;
// Optional additional properties
[key: string]: any;
}
import { compose } from "teleportal/transports";
import type { Transport, Source, Sink } from "teleportal/transports";
// Create a source that reads from your transport
function getMyTransportSource(): Source<Context> {
return {
readable: new ReadableStream({
async start(controller) {
// Set up your transport's read mechanism
myTransport.on("message", (data) => {
// Decode message
const message = decodeMessage(data);
controller.enqueue(message);
});
myTransport.on("close", () => {
controller.close();
});
myTransport.on("error", (error) => {
controller.error(error);
});
},
}),
};
}
// Create a sink that writes to your transport
function getMyTransportSink(): Sink<Context> {
return {
writable: new WritableStream({
async write(message) {
// Encode message
const encoded = encodeMessage(message);
// Send via your transport
await myTransport.send(encoded);
},
async close() {
await myTransport.close();
},
}),
};
}
// Compose into a transport
const transport: Transport<Context> = compose(
getMyTransportSource(),
getMyTransportSink()
);

If your transport works with raw binary data, you can use binary transport utilities:

import { toBinaryTransport, fromBinaryTransport } from "teleportal/transports";
// Convert to binary transport
const binaryTransport = toBinaryTransport(transport, context);
// Convert from binary transport
const messageTransport = fromBinaryTransport(binaryTransport, context);

You can compose your custom transport with middleware:

import { withLogger, withRateLimit } from "teleportal/transports";
// Add logging
let transport = withLogger(myTransport);
// Add rate limiting
transport = withRateLimit(transport, {
maxMessages: 100,
windowMs: 1000,
});
  1. Handle Errors: Implement proper error handling for connection failures
  2. Support Cleanup: Implement cleanup logic for closing connections
  3. Message Encoding: Use Teleportal’s encoding/decoding utilities
  4. Stream API: Follow the Web Streams API patterns
  5. Context Injection: Ensure context is properly injected into messages
  • Transport - Learn more about transports
  • Server - See how transports are used in the server