### Teleportal Server Setup (TypeScript) Source: https://teleportal.tools/getting-started Sets up a basic Teleportal server using crossws for WebSocket handling and Teleportal's server and storage modules. It initializes an in-memory storage and configures WebSocket handlers with user context extraction. ```typescript import { serve } from "crossws/server"; import { Server } from "teleportal/server"; import { YDocStorage } from "teleportal/storage"; import { getWebsocketHandlers } from "teleportal/websocket-server"; // Create a Teleportal server with in-memory storage const server = new Server({ storage: new YDocStorage(), }); // Set up WebSocket handlers serve({ websocket: getWebsocketHandlers({ server, onUpgrade: async () => { // Extract user context from the request // In production, you'd verify authentication here return { context: { userId: "user-123", room: "workspace-1" }, }; }, }), fetch: () => new Response("Not found", { status: 404 }), }); ``` -------------------------------- ### Configure SQLite Storage with unstorage Source: https://teleportal.tools/guides/persistent-storage Demonstrates setting up unstorage to use SQLite for persistent storage. This example initializes createStorage with the SQLite driver, specifying the path to the database file. ```javascript import sqliteDriver from "unstorage/drivers/sqlite"; const storage = createStorage({ driver: sqliteDriver({ db: "./teleportal.db", }), }); ``` -------------------------------- ### Teleportal Client Setup with Fallback Connection Source: https://teleportal.tools/guides/fallback-connection Demonstrates the client-side setup using Teleportal's Provider, which automatically attempts a WebSocket connection and falls back to HTTP if the WebSocket connection fails. It shows how to create the provider instance and check the active connection type. ```typescript import { Provider } from "teleportal/providers"; // Provider automatically tries WebSocket first, falls back to HTTP const provider = await Provider.create({ url: "wss://example.com", // Tries WebSocket first document: "my-document", }); // Check which connection type is active console.log(provider.connectionType); // "websocket" | "http" | null await provider.synced; ``` -------------------------------- ### UnencryptedDocumentStorage Implementation Example Source: https://teleportal.tools/advanced/custom-storage An example demonstrating how to extend `UnencryptedDocumentStorage` to implement a custom storage solution. ```APIDOC ## Example: Custom DocumentStorage ### Description This example shows how to create a custom document storage implementation by extending the `UnencryptedDocumentStorage` class. It demonstrates overriding methods to interact with a hypothetical backend (`myBackend`). ### Class Definition ```typescript import type { DocumentStorage, Document, DocumentMetadata, Update, } from "teleportal/storage"; import { UnencryptedDocumentStorage } from "teleportal/storage/unencrypted"; import { mergeUpdates, getStateVectorFromUpdate } from "teleportal/storage"; // Assume myBackend is an existing module for interacting with your storage // declare const myBackend: any; export class MyCustomDocumentStorage extends UnencryptedDocumentStorage { readonly type = "document-storage" as const; storageType: "unencrypted" = "unencrypted"; async handleUpdate(documentId: string, update: Update): Promise { // Store update in your backend const existing = await this.getDocument(documentId); if (existing) { const merged = mergeUpdates([existing.content.update, update]); await myBackend.storeUpdate(documentId, merged); } else { await myBackend.storeUpdate(documentId, update); } } async getDocument(documentId: string): Promise { // Retrieve from your backend const update = await myBackend.getUpdate(documentId); if (!update) return null; // Build document from your storage return { id: documentId, metadata: await this.getDocumentMetadata(documentId), content: { update, stateVector: getStateVectorFromUpdate(update), }, }; } async writeDocumentMetadata( documentId: string, metadata: DocumentMetadata ): Promise { await myBackend.storeMetadata(documentId, metadata); } async getDocumentMetadata(documentId: string): Promise { return (await myBackend.getMetadata(documentId)) ?? { files: [], milestones: [], createdAt: Date.now(), updatedAt: Date.now(), }; } async deleteDocument(documentId: string): Promise { await myBackend.deleteDocument(documentId); } async transaction( documentId: string, cb: () => Promise ): Promise { // Implement transaction logic for your backend return await myBackend.transaction(documentId, cb); } } ``` ``` -------------------------------- ### Teleportal Server Setup with WebSocket and HTTP Source: https://teleportal.tools/guides/fallback-connection Sets up a Teleportal server to handle both WebSocket and HTTP transports. It initializes the server, defines WebSocket handlers with an upgrade callback, and HTTP handlers with a connection callback, then starts the server to listen for incoming connections. ```typescript import { serve } from "crossws/server"; import { Server } from "teleportal/server"; import { getWebsocketHandlers } from "teleportal/websocket-server"; import { getHttpHandlers } from "teleportal/http"; const server = new Server({ getStorage: async (ctx) => { // Your storage implementation return documentStorage; }, }); // WebSocket handlers const wsHandlers = getWebsocketHandlers({ server, onUpgrade: async () => { return { context: { userId: "user-123" }, }; }, }); // HTTP handlers const httpHandlers = getHttpHandlers({ server, onConnect: async (request) => { return { context: { userId: "user-123" }, }; }, }); serve({ websocket: wsHandlers, fetch: httpHandlers, }); ``` -------------------------------- ### Custom DocumentStorage Implementation Example Source: https://teleportal.tools/advanced/custom-storage An example of a custom `DocumentStorage` implementation extending `UnencryptedDocumentStorage`. It demonstrates how to integrate a custom backend for storing and retrieving document updates, metadata, and handling transactions. This example assumes the existence of a `myBackend` object for persistence. ```typescript import type { DocumentStorage, Document, DocumentMetadata, Update, } from "teleportal/storage"; import { UnencryptedDocumentStorage } from "teleportal/storage/unencrypted"; import { mergeUpdates, getStateVectorFromUpdate } from "teleportal/storage"; export class MyCustomDocumentStorage extends UnencryptedDocumentStorage { readonly type = "document-storage" as const; storageType: "unencrypted" = "unencrypted"; async handleUpdate(documentId: string, update: Update): Promise { // Store update in your backend // You might want to merge with existing updates const existing = await this.getDocument(documentId); if (existing) { const merged = mergeUpdates([existing.content.update, update]); await myBackend.storeUpdate(documentId, merged); } else { await myBackend.storeUpdate(documentId, update); } } async getDocument(documentId: string): Promise { // Retrieve from your backend const update = await myBackend.getUpdate(documentId); if (!update) return null; // Build document from your storage return { id: documentId, metadata: await this.getDocumentMetadata(documentId), content: { update, stateVector: getStateVectorFromUpdate(update), }, }; } async writeDocumentMetadata( documentId: string, metadata: DocumentMetadata ): Promise { await myBackend.storeMetadata(documentId, metadata); } async getDocumentMetadata(documentId: string): Promise { return (await myBackend.getMetadata(documentId)) ?? { files: [], milestones: [], createdAt: Date.now(), updatedAt: Date.now(), }; } async deleteDocument(documentId: string): Promise { await myBackend.deleteDocument(documentId); } async transaction( documentId: string, cb: () => Promise ): Promise { // Implement transaction logic for your backend // This might use database transactions, distributed locks, etc. return await myBackend.transaction(documentId, cb); } } ``` -------------------------------- ### Implement Custom Authentication for Teleportal Source: https://teleportal.tools/integration Provides an example of implementing custom authentication logic within Teleportal's `onUpgrade` handler. This allows integration with existing authentication systems. ```javascript // Custom auth const handlers = getWebsocketHandlers({ server, onUpgrade: async (request) => { const user = await verifySession(request); if (!user) throw new Response("Unauthorized", { status: 401 }); return { context: { userId: user.id } }; }, }); ``` -------------------------------- ### Teleportal Client Connection and Y.js Sync (TypeScript) Source: https://teleportal.tools/getting-started Connects a Teleportal client to a server, synchronizes a Y.js document, and allows for real-time updates. It demonstrates creating a provider, accessing the Y.js document, and listening for changes. ```typescript import { Provider } from "teleportal/providers"; import * as Y from "yjs"; // Create a provider that connects to the server const provider = await Provider.create({ url: "ws://localhost:3000", document: "my-document", }); // Wait for the document to sync await provider.synced; // Access the Y.js document const ydoc = provider.doc; // Create a Y.js text type and insert content const ytext = ydoc.getText("content"); ytext.insert(0, "Hello, world!"); // Listen for updates from other clients ydoc.on("update", () => { console.log("Document updated:", ytext.toString()); }); ``` -------------------------------- ### Teleportal Client Setup with HTTP Transport (JavaScript) Source: https://teleportal.tools/guides/http-transport Demonstrates setting up a Teleportal client using the `Provider` API. The `Provider` automatically utilizes HTTP transport with Server-Sent Events if WebSocket connections are unavailable. It connects to a specified URL and document, then waits for synchronization. ```javascript import { Provider } from "teleportal/providers"; // Provider will automatically use HTTP/SSE if WebSocket fails const provider = await Provider.create({ url: "https://example.com", document: "my-document", }); await provider.synced; ``` -------------------------------- ### Teleportal Server Setup with HTTP Transport (JavaScript) Source: https://teleportal.tools/guides/http-transport Sets up a Teleportal server using HTTP transport. It initializes the server and defines HTTP handlers using `getHttpHandlers` from the 'teleportal/http' module. The `onConnect` function extracts context from the incoming request. ```javascript import { Server } from "teleportal/server"; import { getHttpHandlers } from "teleportal/http"; const server = new Server({ getStorage: async (ctx) => { // Your storage implementation return documentStorage; }, }); // HTTP handlers const handlers = getHttpHandlers({ server, onConnect: async (request) => { // Extract context from request return { context: { userId: "user-123" }, }; }, }); ``` -------------------------------- ### Transport Composition Example with Teleportal Source: https://teleportal.tools/core-concepts/transport Demonstrates layering multiple transport middleware functions onto a base transport. This example shows how to add encryption, rate limiting, logging, and message validation sequentially. ```javascript // Base transport let transport = getBaseTransport(); // Add encryption transport = getEncryptedTransport(handler); // Add rate limiting transport = withRateLimit(transport, options); // Add logging transport = withLogger(transport); // Add message validation transport = withMessageValidator(transport, { isAuthorized: async (message, type) => { // Authorization logic return true; }, }); ``` -------------------------------- ### Client Setup: JWT Token Generation and Connection with Teleportal Source: https://teleportal.tools/guides/authentication This snippet illustrates how to set up JWT token authentication on the client-side using Teleportal. It shows how to create a token manager (matching the server's secret), generate a JWT token with specific user and document permissions, and then use this token to establish a secure connection to a Teleportal provider. ```typescript import { Provider } from "teleportal/providers"; import { createTokenManager } from "teleportal/token"; // Create token manager (should match server secret) const tokenManager = createTokenManager({ secret: "your-secret-key", }); // Generate token const token = await tokenManager.createToken("user-123", "org-456", [ { pattern: "user-123/*", permissions: ["read", "write"] }, ]); // Connect with token const provider = await Provider.create({ url: `wss://example.com?token=${token}`, document: "user-123/my-document", }); await provider.synced; ``` -------------------------------- ### Implement Custom Monitoring for Teleportal Server Events Source: https://teleportal.tools/integration Demonstrates how to integrate custom monitoring by subscribing to Teleportal server events, such as client connections. This allows sending event data to external monitoring systems. ```javascript // Custom monitoring server.on("client-connect", (data) => { // Send to your monitoring system }); ``` -------------------------------- ### Monitoring Teleportal Deployment Metrics Source: https://teleportal.tools/advanced/scaling Provides code examples for monitoring Teleportal deployments. It shows how to retrieve per-node metrics from a server instance and how to aggregate metrics across multiple nodes for a comprehensive overview of the system's performance. ```javascript // Per-node metrics const metrics = await server.getMetrics(); // Aggregate metrics across nodes const aggregatedMetrics = await aggregateMetrics(allNodes); ``` -------------------------------- ### Document Pattern Matching Examples Source: https://teleportal.tools/core-concepts/authentication Demonstrates various methods for matching document patterns when defining token permissions. Supports exact, prefix, wildcard, and suffix matching. ```json { "exact_match": { "pattern": "document1" // Matches: "document1" }, "prefix_match": { "pattern": "user/*" // Matches: "user/doc1", "user/doc2", "user/project/doc3" }, "wildcard_match": { "pattern": "*" // Matches: any document name }, "suffix_match": { "pattern": "*.md" // Matches: "readme.md", "document.md" } } ``` -------------------------------- ### Configure PostgreSQL Storage with unstorage Source: https://teleportal.tools/guides/persistent-storage Shows how to configure unstorage to use PostgreSQL as a persistent storage backend. This involves importing the PostgreSQL driver and initializing createStorage with the necessary connection string. ```javascript import postgresDriver from "unstorage/drivers/postgres"; const storage = createStorage({ driver: postgresDriver({ connectionString: "postgresql://user:password@localhost/db", }), }); ``` -------------------------------- ### Single-Node Teleportal Server Setup Source: https://teleportal.tools/advanced/scaling Sets up a basic Teleportal server for single-node deployments. It requires a storage backend to be provided via the getStorage function. This is suitable for small to medium applications with in-memory or local storage. ```javascript const server = new Server({ getStorage: async (ctx) => { // Your storage }, }); ``` -------------------------------- ### Configure Redis Storage and Teleportal Server Source: https://teleportal.tools/guides/persistent-storage Demonstrates setting up a Teleportal server with persistent document storage using the unstorage abstraction layer and the Redis driver. It initializes unstorage with Redis and configures the server to use this storage for documents and files. ```javascript import { createStorage } from "unstorage"; import { createUnstorage } from "teleportal/storage"; import redisDriver from "unstorage/drivers/redis"; import { Server } from "teleportal/server"; // Create unstorage instance with Redis driver const storage = createStorage({ driver: redisDriver({ base: "teleportal:", url: "redis://localhost:6379", }), }); const server = new Server({ getStorage: async (ctx) => { const { documentStorage } = createUnstorage(storage, { documentKeyPrefix: "doc", fileKeyPrefix: "file", encrypted: ctx.encrypted, }); return documentStorage; }, }); ``` -------------------------------- ### Separating Storage Types in Teleportal Source: https://teleportal.tools/advanced/scaling Demonstrates how to configure different storage backends for various data types within a Teleportal application. This example shows separate configurations for documents (PostgreSQL), files (S3), and milestones (Redis), allowing for optimized storage solutions for each. ```javascript // PostgreSQL for documents const documentStorage = new PostgresDocumentStorage(db); // S3 for files const fileStorage = new S3FileStorage(s3Client); // Redis for milestones const milestoneStorage = new RedisMilestoneStorage(redisClient); ``` -------------------------------- ### Server Setup: JWT Token Authentication with Teleportal Source: https://teleportal.tools/guides/authentication This snippet demonstrates setting up JWT token authentication on the server-side using Teleportal. It configures a token manager with a secret key and expiration, and integrates it into the server's permission checking logic. The `onUpgrade` function extracts and verifies the token from incoming WebSocket requests. ```typescript import { serve } from "crossws/server"; import { Server } from "teleportal/server"; import { createTokenManager } from "teleportal/token"; import { getWebsocketHandlers } from "teleportal/websocket-server"; const tokenManager = createTokenManager({ secret: "your-secret-key", expiresIn: 3600, }); const server = new Server({ getStorage: async (ctx) => { // Your storage implementation return documentStorage; }, checkPermission: async ({ context, documentId, message, type }) => { const token = (context as any).token; if (!token) return false; const result = await tokenManager.verifyToken(token); if (!result.valid || !result.payload) return false; const payload = result.payload; const requiredPermission = type === "read" ? "read" : "write"; return tokenManager.hasDocumentPermission( payload, documentId!, requiredPermission ); }, }); serve({ websocket: getWebsocketHandlers({ server, onUpgrade: async (request) => { // Extract token from request const url = new URL(request.url); const token = url.searchParams.get("token") || request.headers.get("authorization")?.replace("Bearer ", ""); if (!token) { throw new Response("No token provided", { status: 401 }); } const result = await tokenManager.verifyToken(token); if (!result.valid || !result.payload) { throw new Response("Invalid token", { status: 401 }); } return { context: { userId: result.payload.userId, room: result.payload.room, token, }, }; }, }), fetch: () => new Response("Not found", { status: 404 }), }); ``` -------------------------------- ### Setup Teleportal Server with Observability Endpoints (TypeScript) Source: https://teleportal.tools/guides/observability Demonstrates how to set up a Teleportal server and expose observability endpoints for metrics, health checks, and status. Requires the 'teleportal/server' and 'teleportal/monitoring' modules. ```typescript import { Server } from "teleportal/server"; import { getMetricsHandler, getHealthHandler, getStatusHandler } from "teleportal/monitoring"; const server = new Server({ getStorage: async (ctx) => { // Your storage implementation return documentStorage; }, }); // Expose observability endpoints app.get("/metrics", getMetricsHandler(server)); app.get("/health", getHealthHandler(server)); app.get("/status", getStatusHandler(server)); ``` -------------------------------- ### Configure Server Rate Limiting with Unstorage Source: https://teleportal.tools/guides/rate-limiting Demonstrates how to configure rate limiting rules on the Teleportal server using Unstorage for persistent storage. It shows how to define rules for tracking limits by user, document, or user-document pair, and how to handle exceeded rate limits and message sizes. ```typescript import { Server } from "teleportal/server"; import { createStorage } from "unstorage"; import { UnstorageDocumentStorage, UnstorageRateLimitStorage } from "teleportal/storage"; const storage = createStorage(); const server = new Server({ storage: new UnstorageDocumentStorage(storage), rateLimitConfig: { // Multiple rate limit rules rules: [ // Track by user (across all documents) { id: "per-user", maxMessages: 100, // 100 messages per window windowMs: 1000, // 1 second window trackBy: "user", }, // Track by document (across all users) { id: "per-document", maxMessages: 500, // 500 messages per window per document windowMs: 10000, // 10 second window trackBy: "document", }, // Track by user-document pair { id: "user-document", maxMessages: 100, windowMs: 1000, trackBy: "user-document", }, ], // Use persistent storage for multi-node deployments rateLimitStorage: new UnstorageRateLimitStorage(storage), // Callback when rate limit is exceeded onRateLimitExceeded: (details) => { console.warn("Rate limit exceeded", details); }, // Maximum message size maxMessageSize: 10 * 1024 * 1024, // 10MB // Callback when message size is exceeded onMessageSizeExceeded: (details) => { console.warn("Message size exceeded", details); }, }, }); ``` -------------------------------- ### Configure Unstorage for Production Teleportal Source: https://teleportal.tools/integration Sets up Unstorage with Redis as the backend for Teleportal's document and file storage. This configuration is recommended for production environments. ```javascript // Unstorage (production) import { createStorage } from "unstorage"; import { createUnstorage } from "teleportal/storage"; import redisDriver from "unstorage/drivers/redis"; const storage = createStorage({ driver: redisDriver({ base: "teleportal:" }), }); const server = new Server({ getStorage: async (ctx) => { const { documentStorage } = createUnstorage(storage, { documentKeyPrefix: "doc", fileKeyPrefix: "file", }); return documentStorage; }, }); ``` -------------------------------- ### Configure Multi-Node Teleportal with Redis Pub/Sub Source: https://teleportal.tools/integration Sets up a multi-node Teleportal deployment using Redis for Pub/Sub message coordination. This ensures proper message handling across multiple server instances. ```javascript // Multi-node with PubSub import { RedisPubSub } from "teleportal/pubsub/redis"; const server = new Server({ getStorage: async (ctx) => { // Shared storage }, pubSub: new RedisPubSub({ url: "redis://localhost:6379", }), nodeId: process.env.NODE_ID, }); ``` -------------------------------- ### Teleportal Server Setup with HTTP Load Balancer Source: https://teleportal.tools/advanced/scaling Sets up a Teleportal server instance intended to be used behind an HTTP load balancer. This configuration omits Pub/Sub and relies on shared storage and sticky sessions for scaling. It's a simpler approach for scaling without direct inter-node communication. ```javascript // Each server instance const server = new Server({ getStorage: async (ctx) => { // Shared storage return documentStorage; }, // No pubSub - relies on sticky sessions }); ``` -------------------------------- ### Send Webhooks on Document Load with Node.js Source: https://teleportal.tools/core-concepts/server This code example shows how to handle the 'document-load' event. When a document is loaded, it triggers an asynchronous function that sends a webhook notification. The webhook includes event details like the document ID and the user ID from the context, enabling external systems to react to document openings. ```javascript server.on("document-load", async (data) => { await sendWebhook({ event: "document.opened", documentId: data.documentId, userId: data.context.userId, }); }); ``` -------------------------------- ### Teleportal Server Setup with Redis Pub/Sub Source: https://teleportal.tools/guides/pub-sub Sets up a Teleportal server instance utilizing Redis for Pub/Sub communication and a shared storage backend. It configures the server with a unique nodeId and a RedisPubSub instance pointing to the Redis server. ```typescript import { Server } from "teleportal/server"; import { RedisPubSub } from "teleportal/pubsub/redis"; import { createUnstorage } from "teleportal/storage"; const server = new Server({ getStorage: async (ctx) => { // Shared storage backend return documentStorage; }, pubSub: new RedisPubSub({ url: "redis://localhost:6379", }), nodeId: process.env.NODE_ID || `node-${uuidv4()}`, }); ``` -------------------------------- ### Configure S3 Storage with unstorage Source: https://teleportal.tools/guides/persistent-storage Illustrates how to configure unstorage to use Amazon S3 as a persistent storage backend. This involves importing the S3 driver and providing the bucket name and region to createStorage. ```javascript import s3Driver from "unstorage/drivers/s3"; const storage = createStorage({ driver: s3Driver({ bucket: "my-bucket", region: "us-east-1", }), }); ``` -------------------------------- ### Connection State Source: https://teleportal.tools/core-concepts/provider This section details how to monitor the connection state of the Teleportal provider. It provides examples of checking the current connection type and handling connection errors, as well as waiting for the provider to be fully synced. ```APIDOC ## Connection State ### Description Monitors and reacts to the connection state of the provider. ### Method Provider.state ### Endpoint N/A (Client-side access) ### Parameters None ### Request Example ```javascript // Get current connection state const connection = provider.state; if (connection.type === "connected") { console.log("Connected!"); } else if (connection.type === "errored") { console.error("Connection error:", connection.error); } // Wait for connection try { await provider.synced; console.log("Fully synced!"); } catch (error) { console.error("Sync failed:", error); } ``` ### Response #### Success Response (200) Connection state object. #### Response Example ```json { "type": "connected" | "disconnected" | "errored", "error": Error | null } ``` ``` -------------------------------- ### Configure Automatic Backups with Server Triggers Source: https://teleportal.tools/core-concepts/milestones Configures automatic backups for a server using milestone triggers. This example sets up a default time-based trigger to create a milestone every hour. It requires the `Server` class and a configuration object for `milestoneTriggerConfig`. ```javascript const server = new Server({ milestoneTriggerConfig: { defaultTriggers: [ { type: "time-based", interval: 3600000, // Every hour }, ], }, }); ``` -------------------------------- ### Server Setup with Encrypted Storage - Teleportal Source: https://teleportal.tools/guides/encryption-at-rest Sets up a Teleportal server with encrypted storage using unstorage and a Redis driver. It configures the storage to enable encryption based on the context provided to the server. Dependencies include 'teleportal/server', 'teleportal/storage', 'unstorage', and 'unstorage/drivers/redis'. ```typescript import { Server } from "teleportal/server"; import { createUnstorage } from "teleportal/storage"; import { createStorage } from "unstorage"; import redisDriver from "unstorage/drivers/redis"; const storage = createStorage({ driver: redisDriver({ base: "teleportal:", url: "redis://localhost:6379", }), }); const server = new Server({ getStorage: async (ctx) => { const { documentStorage } = createUnstorage(storage, { documentKeyPrefix: "doc", encrypted: ctx.encrypted, // Enable encryption based on context }); return documentStorage; }, }); ``` -------------------------------- ### Configure Multi-Node Rate Limiting with Redis Source: https://teleportal.tools/guides/rate-limiting Shows how to configure persistent rate limit storage for multi-node Teleportal deployments using Redis. This ensures rate limits are shared across multiple server instances. ```typescript import { RedisRateLimitStorage } from "teleportal/transports/redis"; const rateLimitStorage = new RedisRateLimitStorage(redisClient); const server = new Server({ // ... other options rateLimitConfig: { rateLimitStorage, // Shared across server instances // ... other options }, }); ``` -------------------------------- ### Connect Teleportal Client via WebSocket Source: https://teleportal.tools/guides/websocket-only Establishes a WebSocket connection to a Teleportal server using the Provider API. It connects to a specified document, waits for synchronization, inserts initial text, and logs the document content. It also sets up an update listener to log any changes to the document's text. ```typescript import { Provider } from "teleportal/providers"; const provider = await Provider.create({ url: `ws://localhost:3000`, document: "test", }); await provider.synced; provider.doc.getText("test").insert(0, "Hello, world!"); console.log(provider.doc.getText("test").toString()); provider.doc.on("update", () => { console.log(provider.doc.getText("test").toString()); }); ``` -------------------------------- ### Create Provider with Automatic Connection (JavaScript) Source: https://teleportal.tools/core-concepts/provider Demonstrates the basic usage of creating a Provider instance with automatic connection establishment. It shows how to access the Yjs document, make changes, and listen to connection state updates. This method automatically handles connection fallback. ```javascript import { Provider } from "teleportal/providers"; // Create a provider with automatic connection const provider = await Provider.create({ url: "wss://example.com", document: "my-document-id", }); // Wait for document to be synced await provider.synced; // Access the Yjs document const ymap = provider.doc.getMap("data"); ymap.set("key", "value"); // Listen to connection state provider.on("update", (state) => { console.log("Connection state:", state.type); }); ``` -------------------------------- ### Listen to Client Connections with Node.js Source: https://teleportal.tools/core-concepts/server This snippet demonstrates how to use the `server.on` method to listen for the 'client-connect' event. It asynchronously creates a new record in a 'clients' table in a database, storing the client's ID and connection timestamp. This is useful for tracking user activity and managing client sessions. ```javascript server.on("client-connect", async (data) => { await db.clients.create({ clientId: data.clientId, connectedAt: new Date(), }); }); ``` -------------------------------- ### GET /health Source: https://teleportal.tools/guides/observability Checks the overall health status of the Teleportal server. ```APIDOC ## GET /health ### Description This endpoint provides a quick health check of the Teleportal server, indicating if it is operational. ### Method GET ### Endpoint /health ### Parameters None ### Request Example ```bash curl http://localhost:3000/health ``` ### Response #### Success Response (200) - **status** (string) - The health status of the server (e.g., "healthy"). - **timestamp** (string) - The timestamp when the health check was performed. - **checks** (object) - An object containing results of internal health checks (details omitted). - **uptime** (number) - The server's uptime in seconds. #### Response Example ```json { "status": "healthy", "timestamp": "2024-01-01T00:00:00.000Z", "checks": { ... }, "uptime": 3600 } ``` ``` -------------------------------- ### GET /status Source: https://teleportal.tools/guides/observability Retrieves detailed operational status information for the Teleportal server. ```APIDOC ## GET /status ### Description This endpoint returns detailed operational status information for the Teleportal server, including client and session counts, message statistics, and uptime. ### Method GET ### Endpoint /status ### Parameters None ### Request Example ```bash curl http://localhost:3000/status ``` ### Response #### Success Response (200) - **nodeId** (string) - The unique identifier for the server node. - **activeClients** (number) - The current number of active clients connected to the server. - **activeSessions** (number) - The current number of active sessions. - **totalMessagesProcessed** (number) - The total number of messages processed by the server. - **totalDocumentsOpened** (number) - The total number of documents opened. - **messageTypeBreakdown** (object) - An object detailing the breakdown of processed message types. - **doc** (number) - Number of document-related messages. - **awareness** (number) - Number of awareness-related messages. - **file** (number) - Number of file-related messages. - **uptime** (number) - The server's uptime in seconds. #### Response Example ```json { "nodeId": "node-123", "activeClients": 10, "activeSessions": 5, "totalMessagesProcessed": 1000, "totalDocumentsOpened": 50, "messageTypeBreakdown": { "doc": 500, "awareness": 300, "file": 200 }, "uptime": 3600 } ``` ``` -------------------------------- ### GET /metrics Source: https://teleportal.tools/guides/observability Exposes Prometheus-compatible metrics for monitoring server performance and activity. ```APIDOC ## GET /metrics ### Description This endpoint provides Prometheus-formatted metrics about the Teleportal server's operational status, including active sessions, clients, and processed messages. ### Method GET ### Endpoint /metrics ### Parameters None ### Request Example ```bash curl http://localhost:3000/metrics ``` ### Response #### Success Response (200) - **teleportal_sessions_active** (gauge) - Current number of active sessions - **teleportal_clients_active** (gauge) - Current number of active clients - **teleportal_documents_opened_total** (counter) - Total documents opened - **teleportal_messages_processed_total** (counter) - Total messages processed - **teleportal_message_duration_seconds** (histogram) - Message processing duration #### Response Example ``` # HELP teleportal_sessions_active Current number of active sessions # TYPE teleportal_sessions_active gauge teleportal_sessions_active 5 # HELP teleportal_clients_active Current number of active clients # TYPE teleportal_clients_active gauge teleportal_clients_active 10 # HELP teleportal_documents_opened_total Total documents opened # TYPE teleportal_documents_opened_total counter teleportal_documents_opened_total 50 # HELP teleportal_messages_processed_total Total messages processed # TYPE teleportal_messages_processed_total counter teleportal_messages_processed_total 1000 # HELP teleportal_message_duration_seconds Message processing duration # TYPE teleportal_message_duration_seconds histogram teleportal_message_duration_seconds_bucket{le="0.005"} 0 teleportal_message_duration_seconds_bucket{le="0.01"} 0 # ... other buckets ... teleportal_message_duration_seconds_count 1000 teleportal_message_duration_seconds_sum 10.5 ``` ``` -------------------------------- ### Implement WebSocket Transport for Teleportal Source: https://teleportal.tools/integration Configures Teleportal to use WebSocket for bidirectional communication. This is the default and recommended transport for low-latency interactions. ```javascript // WebSocket import { getWebsocketHandlers } from "teleportal/websocket-server"; const handlers = getWebsocketHandlers({ server, onUpgrade: async (request) => { return { context: { userId: "user-123" } }; }, }); ``` -------------------------------- ### Create Milestones on Save/Publish - JavaScript Source: https://teleportal.tools/core-concepts/milestones Example use cases for creating milestones at significant document events like saving or publishing. ```javascript // Create milestone when user clicks "Save" await provider.createMilestone("Save point 1"); // Create milestone when document is published await provider.createMilestone("Published v1.0"); ``` -------------------------------- ### Enable Milestone Synchronization in Teleportal Source: https://teleportal.tools/integration Configures Teleportal to include milestone synchronization functionality. This requires providing a milestone storage instance to the RPC handlers. ```javascript // Milestone sync (optional) import { getMilestoneRpcHandlers } from "teleportal/protocols/milestone"; const server = new Server({ rpcHandlers: { ...getMilestoneRpcHandlers(milestoneStorage), }, }); ``` -------------------------------- ### Enable File Synchronization in Teleportal Source: https://teleportal.tools/integration Configures Teleportal to include file synchronization functionality. This requires providing a file storage instance to the RPC handlers. ```javascript // File sync (optional) import { getFileRpcHandlers } from "teleportal/protocols/file"; const server = new Server({ rpcHandlers: { ...getFileRpcHandlers(fileStorage), }, }); ``` -------------------------------- ### Implement HTTP/SSE Transport for Teleportal Source: https://teleportal.tools/integration Configures Teleportal to use HTTP with Server-Sent Events (SSE) for communication. This is a fallback option for environments where WebSockets are blocked. ```javascript // HTTP/SSE import { getHttpHandlers } from "teleportal/http"; const handlers = getHttpHandlers({ server, onConnect: async (request) => { return { context: { userId: "user-123" } }; }, }); ``` -------------------------------- ### Expose Teleportal Metrics and Health Checks Source: https://teleportal.tools/integration Configures HTTP endpoints for Prometheus metrics and health checks for a Teleportal server. This allows for monitoring the server's status and performance. ```javascript // Metrics & health import { getMetricsHandler, getHealthHandler } from "teleportal/monitoring"; app.get("/metrics", getMetricsHandler(server)); app.get("/health", getHealthHandler(server)); ``` -------------------------------- ### Configure Built-in JWT Authentication for Teleportal Source: https://teleportal.tools/integration Sets up Teleportal's built-in JSON Web Token (JWT) manager for authentication. This includes creating tokens with specific permissions. ```javascript // JWT (built-in) import { createTokenManager } from "teleportal/token"; const tokenManager = createTokenManager({ secret: "your-secret-key", expiresIn: 3600, }); const token = await tokenManager.createToken("user-123", "org-456", [ { pattern: "user-123/*", permissions: ["read", "write"] }, ]); ``` -------------------------------- ### Enable Offline Persistence with IndexedDB Source: https://teleportal.tools/core-concepts/provider Demonstrates how to enable and configure offline persistence using IndexedDB. The provider defaults to enabling this feature and allows for a custom IndexedDB prefix. It shows how to wait for local data to load and synchronization with the server. ```javascript const provider = await Provider.create({ url: "wss://example.com", document: "my-document-id", enableOfflinePersistence: true, // default indexedDBPrefix: "my-app-", // custom prefix }); // Document will be loaded from IndexedDB if available await provider.loaded; // Resolves when local data is loaded await provider.synced; // Resolves when synced with server ``` -------------------------------- ### Configure Unstorage for Indexed Keys or Key Scanning Source: https://teleportal.tools/advanced/performance Sets up an unstorage-based document storage, allowing configuration between using indexed keys (recommended for Redis, Memcached) or key scanning (recommended for PostgreSQL, MySQL) for better performance. ```javascript const { documentStorage } = createUnstorage(storage, { scanKeys: false, // Use indexed keys (better for Redis, Memcached) // or scanKeys: true, // Use key scanning (better for PostgreSQL, MySQL) }); ``` -------------------------------- ### Manage Awareness State (JavaScript) Source: https://teleportal.tools/core-concepts/provider Shows how to utilize the Provider's Awareness instance for managing user presence and cursor information. It covers setting local user state and listening for updates when other users' awareness information changes. This is crucial for collaborative features. ```javascript // Access awareness const awareness = provider.awareness; // Set local state awareness.setLocalStateField("user", { name: "John Doe", color: "#ff0000", }); // Listen to awareness updates awareness.on("update", ({ added, updated, removed }) => { console.log("Users changed:", { added, updated, removed }); }); ``` -------------------------------- ### Configure In-Memory Storage for Development Teleportal Source: https://teleportal.tools/integration Sets up in-memory storage for Teleportal, suitable for development and testing purposes. This provides a simple and fast storage solution without external dependencies. ```javascript // In-memory (development) import { createInMemory } from "teleportal/storage"; const server = new Server({ getStorage: async (ctx) => { const { documentStorage } = createInMemory(); return documentStorage; }, }); ``` -------------------------------- ### Set Up Teleportal Server with Token Authentication (TypeScript) Source: https://teleportal.tools/index This snippet demonstrates how to set up a Teleportal server using TypeScript. It configures a token manager for JWT authentication and integrates it with both WebSocket and HTTP handlers. The server uses an in-memory storage and enforces permission checks based on the provided token. ```typescript import { serve } from "crossws/server"; import { createTokenManager } from "teleportal/token"; import { tokenAuthenticatedWebsocketHandler } from "teleportal/websocket-server"; import { tokenAuthenticatedHTTPHandler } from "teleportal/http"; import { checkPermissionWithTokenManager, Server } from "teleportal/server"; import { YDocStorage } from "teleportal/storage"; // token manager is a JWT token verifier and manager. const tokenManager = createTokenManager({ secret: "your-secret-key-here", expiresIn: 3600, // 1 hour issuer: "teleportal.tools", }); // Create a Teleportal server instance const server = new Server({ // you can use any storage backend you want, this one is in-memory storage: new YDocStorage(), // every message is verified against the token's permissions to the document checkPermission: checkPermissionWithTokenManager(tokenManager), }); // Serve the Teleportal server with crossws (for multi-runtime support) serve({ // websocket upgrades are denied if the token is invalid websocket: tokenAuthenticatedWebsocketHandler({ server, tokenManager }), // HTTP requests are denied if the token is invalid fetch: tokenAuthenticatedHTTPHandler({ server, tokenManager }), }); ``` -------------------------------- ### Provider with WebSocket Connection (JavaScript) Source: https://teleportal.tools/core-concepts/provider Illustrates how to explicitly create a Provider using a WebSocketConnection. This is the default and most common connection type for real-time synchronization. It requires importing the WebSocketConnection class. ```javascript import { WebSocketConnection } from "teleportal/providers/websocket"; const connection = new WebSocketConnection({ url: "wss://example.com", }); const provider = new Provider({ client: connection, document: "my-document", }); ``` -------------------------------- ### Create Custom Transport Sink Source: https://teleportal.tools/advanced/custom-transport This example shows how to create a custom `Sink` for a Teleportal transport. It uses `WritableStream` to write outgoing messages to a custom transport mechanism after encoding them and handles transport closure. ```typescript import { compose } from "teleportal/transports"; import type { Transport, Source, Sink } from "teleportal/transports"; // Create a sink that writes to your transport function getMyTransportSink(): Sink { 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(); }, }), }; } ``` -------------------------------- ### Running Multiple Teleportal Server Instances Source: https://teleportal.tools/advanced/scaling Demonstrates how to run multiple Teleportal server instances concurrently. Each instance is assigned a unique NODE_ID and PORT, allowing them to operate as separate nodes in a distributed system. This is typically used in conjunction with a Pub/Sub mechanism for coordination. ```bash # Instance 1 NODE_ID=node-1 PORT=3000 node server.js # Instance 2 NODE_ID=node-2 PORT=3001 node server.js # Instance 3 NODE_ID=node-3 PORT=3002 node server.js ``` -------------------------------- ### Switch Documents Efficiently (JavaScript) Source: https://teleportal.tools/core-concepts/provider Explains the `switchDocument` method, which allows changing the active Yjs document on an existing connection without re-establishing network communication. This improves efficiency when dealing with multiple documents. The old provider is destroyed, and the new one is returned. ```javascript // Switch to a new document (reuses connection) const newProvider = provider.switchDocument({ document: "new-document-id", }); // Old provider is destroyed, new provider is ready await newProvider.synced; ```