CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-types--phoenix

TypeScript definitions for Phoenix JavaScript client library enabling real-time WebSocket communication with Phoenix Framework applications

Overview
Eval results
Files

push.mddocs/

Push Operations

Push mechanism for sending messages to channels with delivery status tracking and timeout handling, enabling reliable message delivery confirmation.

Capabilities

Push Constructor

Creates a new Push instance for sending messages with status tracking.

/**
 * Creates a new Push instance for sending messages with status tracking
 * @param channel - Channel to send message through
 * @param event - Event name for the message
 * @param payload - Message payload object
 * @param timeout - Timeout in milliseconds for the push operation
 */
constructor(channel: Channel, event: string, payload: object, timeout: number);

Note: Push instances are typically created through channel.push() rather than directly constructing them.

Message Sending

Send and resend push messages.

/**
 * Send the push message
 */
send(): void;

/**
 * Resend the push message with a new timeout
 * @param timeout - New timeout value in milliseconds
 */
resend(timeout: number): void;

Usage Example:

import { Channel, Socket } from "phoenix";

const socket = new Socket("/socket");
const channel = socket.channel("room:lobby");

// Create push through channel (recommended)
const push = channel.push("new_message", {
  body: "Hello, Phoenix!",
  user_id: 123
}, 5000);

// Send immediately (usually not needed as channel.push() sends automatically)
push.send();

// Resend with longer timeout if needed
push.resend(10000);

Status Handling

Register callbacks for different push response statuses.

/**
 * Register callback for specific push status
 * @param status - Push status to handle ("ok", "error", or "timeout")
 * @param callback - Function to call when status is received
 * @returns Push instance for chaining
 */
receive(status: PushStatus, callback: (response?: any) => any): this;

type PushStatus = "ok" | "error" | "timeout";

Usage Example:

// Chain status handlers
channel.push("create_post", {
  title: "My Post",
  content: "Post content here..."
})
.receive("ok", (response) => {
  console.log("Post created successfully:", response.post);
  // Navigate to new post
  window.location.href = `/posts/${response.post.id}`;
})
.receive("error", (errors) => {
  console.error("Failed to create post:", errors);
  // Show validation errors to user
  displayErrors(errors);
})
.receive("timeout", () => {
  console.warn("Post creation timed out");
  // Show retry option to user
  showRetryDialog();
});

Advanced Usage Patterns

Error Handling with Retry Logic

function sendMessageWithRetry(channel: Channel, event: string, payload: object, maxRetries = 3) {
  let attempts = 0;

  function attempt(): Promise<any> {
    return new Promise((resolve, reject) => {
      attempts++;

      channel.push(event, payload, 5000)
        .receive("ok", resolve)
        .receive("error", (errors) => {
          if (attempts < maxRetries) {
            console.log(`Attempt ${attempts} failed, retrying...`);
            setTimeout(() => {
              attempt().then(resolve).catch(reject);
            }, 1000 * attempts); // Exponential backoff
          } else {
            reject(new Error(`Failed after ${maxRetries} attempts: ${JSON.stringify(errors)}`));
          }
        })
        .receive("timeout", () => {
          if (attempts < maxRetries) {
            console.log(`Attempt ${attempts} timed out, retrying...`);
            setTimeout(() => {
              attempt().then(resolve).catch(reject);
            }, 1000 * attempts);
          } else {
            reject(new Error(`Timed out after ${maxRetries} attempts`));
          }
        });
    });
  }

  return attempt();
}

// Usage
sendMessageWithRetry(channel, "important_action", { data: "critical" })
  .then(result => console.log("Success:", result))
  .catch(error => console.error("Final failure:", error));

Status-based Flow Control

function handleFormSubmission(channel: Channel, formData: object) {
  const submitButton = document.getElementById("submit-btn") as HTMLButtonElement;
  const errorDiv = document.getElementById("errors") as HTMLDivElement;
  const successDiv = document.getElementById("success") as HTMLDivElement;

  // Disable submit button during request
  submitButton.disabled = true;
  submitButton.textContent = "Submitting...";

  channel.push("form_submit", formData, 10000)
    .receive("ok", (response) => {
      // Success handling
      successDiv.style.display = "block";
      successDiv.textContent = "Form submitted successfully!";
      errorDiv.style.display = "none";

      // Reset form
      (document.getElementById("form") as HTMLFormElement).reset();
    })
    .receive("error", (errors) => {
      // Error handling
      errorDiv.style.display = "block";
      errorDiv.innerHTML = "";

      // Display validation errors
      Object.entries(errors).forEach(([field, messages]) => {
        const errorItem = document.createElement("div");
        errorItem.textContent = `${field}: ${(messages as string[]).join(", ")}`;
        errorDiv.appendChild(errorItem);
      });

      successDiv.style.display = "none";
    })
    .receive("timeout", () => {
      // Timeout handling
      errorDiv.style.display = "block";
      errorDiv.textContent = "Request timed out. Please try again.";
      successDiv.style.display = "none";
    });

  // Always re-enable submit button
  setTimeout(() => {
    submitButton.disabled = false;
    submitButton.textContent = "Submit";
  }, 1000);
}

Promise-based Push Wrapper

function pushPromise(channel: Channel, event: string, payload: object, timeout = 5000): Promise<any> {
  return new Promise((resolve, reject) => {
    channel.push(event, payload, timeout)
      .receive("ok", resolve)
      .receive("error", reject)
      .receive("timeout", () => reject(new Error("Push operation timed out")));
  });
}

// Usage with async/await
async function createUser(channel: Channel, userData: object) {
  try {
    const response = await pushPromise(channel, "create_user", userData, 8000);
    console.log("User created:", response.user);
    return response.user;
  } catch (error) {
    console.error("Failed to create user:", error);
    throw error;
  }
}

Batch Operations with Status Tracking

async function batchOperations(channel: Channel, operations: Array<{event: string, payload: object}>) {
  const results = [];
  const errors = [];

  for (const [index, operation] of operations.entries()) {
    try {
      const result = await new Promise((resolve, reject) => {
        channel.push(operation.event, operation.payload, 5000)
          .receive("ok", resolve)
          .receive("error", reject)
          .receive("timeout", () => reject(new Error("Timeout")));
      });

      results.push({ index, result });
    } catch (error) {
      errors.push({ index, error, operation });
    }
  }

  return { results, errors };
}

// Usage
const operations = [
  { event: "create_post", payload: { title: "Post 1" } },
  { event: "create_post", payload: { title: "Post 2" } },
  { event: "update_user", payload: { name: "Updated Name" } }
];

batchOperations(channel, operations)
  .then(({ results, errors }) => {
    console.log(`Completed ${results.length} operations successfully`);
    if (errors.length > 0) {
      console.error(`${errors.length} operations failed:`, errors);
    }
  });

Push Status Monitoring

class PushMonitor {
  private activePushes: Map<string, { push: Push, startTime: number }> = new Map();

  track(id: string, channel: Channel, event: string, payload: object, timeout = 5000) {
    const startTime = Date.now();
    const push = channel.push(event, payload, timeout);

    this.activePushes.set(id, { push, startTime });

    push
      .receive("ok", (response) => {
        this.complete(id, "ok", response);
      })
      .receive("error", (errors) => {
        this.complete(id, "error", errors);
      })
      .receive("timeout", () => {
        this.complete(id, "timeout", null);
      });

    return push;
  }

  private complete(id: string, status: PushStatus, response: any) {
    const entry = this.activePushes.get(id);
    if (entry) {
      const duration = Date.now() - entry.startTime;
      console.log(`Push ${id} completed with status ${status} in ${duration}ms`);
      this.activePushes.delete(id);
    }
  }

  getActivePushes(): string[] {
    return Array.from(this.activePushes.keys());
  }

  getActivePushCount(): number {
    return this.activePushes.size;
  }
}

// Usage
const monitor = new PushMonitor();

monitor.track("post-creation", channel, "create_post", {
  title: "My New Post",
  content: "Post content..."
});

console.log("Active pushes:", monitor.getActivePushCount());

Install with Tessl CLI

npx tessl i tessl/npm-types--phoenix

docs

channel.md

index.md

presence.md

push.md

socket.md

utilities.md

tile.json