npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@wooshiiltd/assist-canvas-sdk

v1.0.0

Published

SDK for Assist Canvas: real-time state, WebSocket + polling, token handling

Readme

@wooshiiltd/assist-canvas-sdk

SDK for building apps that connect to Assist Canvas: real-time state sync over WebSocket with HTTP polling fallback, token handling, and optional origin checks.

The SDK is generic — it does not assume any state shape. Your app defines its own types and API calls; the SDK handles auth, fetching/streaming state, and reconnection.

Installation

pnpm add @wooshiiltd/assist-canvas-sdk
# or
npm install @wooshiiltd/assist-canvas-sdk
  • React — peer: react (>=18). Import from @wooshiiltd/assist-canvas-sdk/react.
  • Vue — peer: vue (>=3). Import from @wooshiiltd/assist-canvas-sdk/vue.
  • Vanilla / other — import from @wooshiiltd/assist-canvas-sdk and use fetchState, createConnection, and getAuthHeaders.

React

import { useCanvasConnection, getAuthHeaders } from '@wooshiiltd/assist-canvas-sdk/react';

function getToken() {
  return new URLSearchParams(window.location.search).get('assist_token');
}

function App() {
  const { state, outputId, error, loading, connectionMode, refetch } =
    useCanvasConnection<MyState>({
      getToken,
      pollingIntervalMs: 5000,
      pollingBackoffMs: 2000,
    });

  const handleAction = async () => {
    const token = getToken();
    if (!token) return;
    await fetch('/api/...', {
      method: 'PATCH',
      headers: getAuthHeaders(token),
      body: JSON.stringify({ ... }),
    });
  };

  if (loading) return <div>Loading…</div>;
  if (error) return <div>{error} <button onClick={refetch}>Retry</button></div>;
  return <div>{/* render state */}</div>;
}

Vue

<script setup lang="ts">
import { useCanvasConnection, getAuthHeaders } from '@wooshiiltd/assist-canvas-sdk/vue';

function getToken() {
  return new URLSearchParams(window.location.search).get('assist_token');
}

const { state, outputId, error, loading, connectionMode, refetch } =
  useCanvasConnection<MyState>({
    getToken,
    pollingIntervalMs: 5000,
    pollingBackoffMs: 2000,
  });
</script>

<template>
  <div v-if="loading">Loading…</div>
  <div v-else-if="error">{{ error }} <button @click="refetch">Retry</button></div>
  <div v-else><!-- render state --></div>
</template>

In Vue, useCanvasConnection returns refs (state, error, etc.); in templates they auto-unwrap. For TypeScript, the return type is UseCanvasConnectionResultVue<T>.

Config

| Option | Description | |--------|-------------| | getToken | () => string \| null — e.g. from URL query or storage. | | baseUrl | Optional. API base (default: current origin). | | pollingIntervalMs | Interval when using polling (default 5000). | | pollingBackoffMs | Backoff step when polling fails (default 2000). | | maxPollingIntervalMs | Cap for polling interval (default 60000). | | allowedOrigins | Optional. If set, only these origins can fetch/connect (e.g. ['https://app.example.com']). Used by fetchState and createConnection. |

Core API (framework-agnostic)

  • fetchState<T>(token, config?)GET /api/state, returns Promise<{ outputId: string; state: T }>. In the browser, if config.allowedOrigins is set, the current origin is checked first.
  • getAuthHeaders(token){ Authorization: 'Bearer …', 'Content-Type': 'application/json' } for your own fetch calls.
  • createConnection<T>(token, config, callbacks) — Starts WebSocket; on close/error switches to polling. Returns a disconnect function. Callbacks: onState, onError, optional onConnectionMode.

Your app is responsible for any other endpoints (e.g. PATCH for moving a card); use getAuthHeaders(token) when calling them.

Types

  • StateResponse<T>{ outputId: string; state: T }. T is your app’s state type.

Security

  • Origin validation — Set allowedOrigins so the client only runs on trusted domains. Checked in both fetchState and createConnection when running in the browser.
  • IDsoutputId is validated (alphanumeric, _, -, length). Use sanitizeOutputId if you need to validate IDs elsewhere.
  • Tokens are never logged; use getToken() only when needed and avoid putting tokens in URLs beyond the initial load if possible.

Content Security Policy (CSP)

The SDK does not set CSP headers. The page that embeds your canvas app (or the server that serves it) should send a strict Content-Security-Policy so that only your app and the canvas API can be loaded.

Example for a page that embeds the canvas in an iframe and allows the canvas API origin:

Content-Security-Policy: default-src 'self'; connect-src 'self' https://your-canvas-api.example.com wss://your-canvas-api.example.com; frame-src 'self' https://your-canvas-api.example.com; script-src 'self'; style-src 'self' 'unsafe-inline';

Tighten or relax as needed (e.g. add frame-ancestors if the canvas is in an iframe and you want to restrict which parents can embed it).

Building

pnpm install
pnpm build

Output is in dist/ (ESM + types).