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

directus-sdk-live

v0.1.0

Published

Experimental realtime query client for Directus with live subscriptions, caching, and framework integrations

Readme

directus-sdk-live

Experimental — This package is under active development and not yet stable. APIs may change without notice. Use at your own risk.

Realtime query client for Directus with live subscriptions, caching, and framework integrations.

Install

pnpm add directus-sdk-live @directus/sdk

Quick Start

Create a typed client:

import { createLiveClient } from "directus-sdk-live";

const client = createLiveClient<MySchema>("http://localhost:8055", {
  auth: { mode: "session" },
});

Use it in a React component — data updates automatically when records change in Directus:

import { useLiveQuery } from "directus-sdk-live/react";

function Posts() {
  const { data, isPending, error } = useLiveQuery(client.posts, {
    fields: ["id", "title", "status"],
    filter: { status: { _eq: "published" } },
    sort: ["-date_created"],
    limit: 10,
  });

  if (isPending) return <p>Loading...</p>;
  return data?.map((post) => <div key={post.id}>{post.title}</div>);
}

Or in Vue / Nuxt:

<script setup>
const client = useDirectus();
const { data, isPending } = useLiveQuery(client.posts, {
  fields: ["id", "title"],
  sort: ["-date_created"],
  limit: 10,
});
</script>

Don't need live updates? Use useQuery instead — same API, REST only, no WebSocket overhead.

Authentication

Four auth modes: session, cookie, memory, static. See Auth Modes for details.

// Login / logout / refresh
await client.auth.login({ email: "[email protected]", password: "secret" });
await client.auth.refresh();
await client.auth.logout();

// Current user — supports field selection
const user = await client.auth.me();
const userWithRole = await client.auth.me({ fields: ["id", "email", "role.*"] });

me() results are cached for 30 seconds per unique query. Cache clears on login, logout, and token changes.

useLiveQuery

Subscribe to real-time collection changes via WebSocket. When records are created, updated, or deleted, the result set updates automatically.

React:

import { useLiveQuery } from "directus-sdk-live/react";

const { data, isPending, error, refresh, liveActive } = useLiveQuery(client.posts, {
  fields: ["id", "title", "status"],
  filter: { status: { _eq: "published" } },
  sort: ["-date_created"],
  limit: 10,
});

Vue:

import { useLiveQuery } from "directus-sdk-live/vue";

const { data, isPending, error, isReady, isEmpty, status, refresh } = useLiveQuery(client.posts, {
  fields: ["id", "title"],
  limit: 10,
});

Options:

| Option | Type | Default | Description | | --------- | --------- | ------- | ------------------------------------------- | | enabled | boolean | true | Disable the query without removing the hook | | live | boolean | true | Set false for REST-only (no WebSocket) |

Return values:

| Field | Description | | ------------ | -------------------------------------------- | | data | The current result set | | isPending | true during initial fetch | | error | Error object if the query failed | | refresh() | Manually re-fetch | | liveActive | true when WebSocket subscription is active | | meta | Query metadata (total count, etc.) |

Singletons work the same way:

const { data: settings } = useLiveQuery(client.directus_settings);

useQuery

Same API as useLiveQuery but without WebSocket subscriptions. Use when you don't need live updates.

React:

import { useQuery } from "directus-sdk-live/react";

const { data, isPending, error, refresh } = useQuery(client.posts, {
  fields: ["id", "title"],
  limit: 10,
});

Vue:

import { useQuery } from "directus-sdk-live/vue";

const { data, isPending, error, isReady, isEmpty, status, refresh } = useQuery(client.posts, {
  fields: ["id", "title"],
  limit: 10,
});

Queries re-fetch automatically when the query object changes. Call refresh() to manually re-fetch.

SSR Prefetch (React / Next.js)

Prefetch data on the server, then hydrate on the client without a double-fetch.

// Server component
import { createLiveClient, prefetchQuery, dehydrateClient } from "directus-sdk-live";

const client = createLiveClient<MySchema>("http://localhost:8055");

await prefetchQuery(() => client.posts.readItems({ fields: ["id", "title"] }));

const dehydratedState = dehydrateClient(client);

// Pass dehydratedState to LiveQueryProvider
// Client component
import { LiveQueryProvider } from "directus-sdk-live/react";

<LiveQueryProvider client={client} dehydratedState={dehydratedState}>
  <Posts />
</LiveQueryProvider>;

prefetchQuery silently swallows auth errors (FORBIDDEN, UNAUTHORIZED, TOKEN_EXPIRED) so unauthenticated server renders don't crash.

React

import {
  LiveQueryProvider,
  useDirectus,
  useDirectusAuth,
  useLiveQuery,
  useQuery,
  useMutation,
} from "directus-sdk-live/react";

function App() {
  return (
    <LiveQueryProvider client={client}>
      <Posts />
    </LiveQueryProvider>
  );
}

useDirectus() returns the typed client. useDirectusAuth() provides reactive auth state (authenticated | anonymous) plus login, logout, and refresh methods.

Vue

import { useLiveQuery, useQuery, useMutation } from "directus-sdk-live/vue";

Vue composables accept reactive refs for query arguments — the query re-subscribes automatically when refs change.

Nuxt Module

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ["directus-sdk-live/nuxt"],
  directus: {
    url: "http://localhost:8055",
    auth: {
      mode: "session",
      middleware: "global",
      loginRoute: "/login",
      forbiddenRoute: "/",
    },
    devtools: true,
  },
});

Auto-imported composables

| Composable | Description | | --------------------------- | ------------------------------------------------ | | useDirectus() | Access the typed LiveClient | | useDirectusAuth() | Auth state, login, logout, refresh | | useDirectusUser(options?) | Reactive current user with SSR support | | useLiveQuery(ref, query) | Reactive live query with WebSocket subscriptions | | useQuery(ref, query) | Reactive query via REST (no WebSocket) | | useMutation(ref) | Create, update, delete mutations |

Auth Middleware

The module registers a directus-auth route middleware. Use it per-page or globally.

Per-page:

<script setup>
definePageMeta({ middleware: "directus-auth" });
</script>

Global mode — set auth.middleware: 'global' in the module config. Opt out per-page:

<script setup>
definePageMeta({ directusAuth: false });
</script>

Role / policy validation:

<script setup>
definePageMeta({
  middleware: "directus-auth",
  directusAuth: {
    fields: ["id", "role.*"],
    validate: (user) => user.role?.name === "Administrator",
  },
});
</script>

useDirectusUser

Reactive wrapper around client.auth.me() with SSR hydration via useAsyncData.

<script setup>
const { user, loading, error, refresh } = useDirectusUser({
  fields: ["id", "email", "first_name", "role.*", "policies.*"],
});
</script>

In Nuxt, useQuery and useLiveQuery integrate with useAsyncData — data fetched on the server is transferred to the client without a double-fetch.

Codegen

Generate TypeScript types from your Directus schema:

npx directus-sdk-live generate --url http://localhost:8055 --token YOUR_TOKEN --output ./app/.generated/directus.ts

Flags:

| Flag | Description | | ----------------- | ----------------------------------------- | | --url | Directus instance URL | | --token | Admin access token | | --output | Output file path (single-file mode) | | --types-output | Types output path (split mode) | | --client-output | Client factory output path (split mode) | | --zod | Generate Zod schemas | | --zod-output | Zod output path | | --singleton | Mark collection as singleton (repeatable) | | --watch | Watch for schema changes | | --nuxt | Nuxt-compatible output | | --env | Load env file for token/url |

Devtools

Visual debug panel showing subscriptions, cache state, and live events.

Standalone:

import { mountDevtools } from "directus-sdk-live/devtools";
const unmount = mountDevtools(client);

Nuxt: Set devtools: true in the module config — panel mounts automatically in dev mode.

Development Hooks

Dev-only event bus for instrumentation (resolves to undefined in production):

import { __devBus } from "directus-sdk-live";

const stop = __devBus?.subscribe((event) => {
  console.debug(event.type, event);
});

Events: subscription:open, subscription:close, subscription:event, subscription:malformed, cache:update.

Docs

License

MIT