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

@arealtimetech/adk-js

v0.0.24

Published

JavaScript ADK to interact with the A Realtime Tech Platform.

Readme

JavaScript ADK

The official JavaScript SDK for the A Realtime Tech (ART) platform.

Website · Documentation · About ART


About ART

A Realtime Tech (ART) is a realtime application platform that powers low-latency messaging, presence, and collaborative state for modern apps. Build chat, live dashboards, multiplayer experiences, IoT control planes, and CRDT-backed shared documents on a single managed backbone — without standing up your own websocket, presence, or sync infrastructure. Learn more at arealtimetech.com.

About the JavaScript ADK

The JavaScript ADK (ART Development Kit) gives your application the tools it needs to talk to ART services. It ships only the runtime needed to connect, subscribe, send, receive, and synchronise state — no separate dev/prod build is required, so you can drop the same package directly into production.

Note — installing the package is not enough on its own. The ADK must also be authenticated using credentials issued by ART (see Configuration below).


Installation

npm install @arealtimetech/adk-js

Configuration

The ADK supports two ways to provide credentials. Pick whichever fits your app.

Option 1 — Load credentials from a JSON file (AutoLoadCredsFromJSON)

Set AutoLoadCredsFromJSON: true and the ADK will automatically fetch credentials from a JSON file at the configured path. This is the simplest setup and where you can place adk-services.json in the root of the project.

import Adk from '@arealtimetech/adk-js';

const adk = new Adk({
  Uri: "",                       // ART service URL
  AutoLoadCredsFromJSON: true,   // load credentials from JSON
});

adk.connect();

JSON file shape (served at the configured config path):

{
  "Client-ID":     "your-client-id",
  "Client-Secret": "your-client-secret",
  "Org-Title":     "your-org",
  "Environment":   "your-environment",
  "ProjectKey":    "your-project-key"
}

Option 2 — Set credentials programmatically (setCredentials)

When AutoLoadCredsFromJSON is off (or omitted), you supply credentials in code via setCredentials(). Use this when credentials come from your own auth flow, an active user session, or any other runtime source.

import Adk from '@arealtimetech/adk-js';

const adk = new Adk({
  Uri: "",   // ART service URL
});

adk.setCredentials({
  ClientID:     "your-client-id",
  ClientSecret: "your-client-secret",
  OrgTitle:     "your-org",
  Environment:  "your-environment",
  ProjectKey:   "your-project-key"
});

adk.connect();

| Field | Type | Required | Description | | -------------- | ------ | -------- | ------------------------------------ | | ClientID | string | yes | Client identifier issued by ART | | ClientSecret | string | yes | Client secret paired with ClientID | | OrgTitle | string | yes | Your organisation / tenant title | | Environment | string | yes | Target environment name | | ProjectKey | string | yes | Project key inside the environment |


Usage

Establish and manage the connection

import Adk from '@arealtimetech/adk-js';

const adk = new Adk({
  Uri: "",                      // service URL
  AuthToken: "",                // passcode generated by your server for the user
});

// Open the connection
adk.connect();

// Connection lifecycle
adk.on("open", async (event) => {
  console.log("ADK connection opened", event);
});

adk.on("close", () => {
  console.log("ADK connection closed");
});

// Tear down
adk.disconnect();

Subscribe to a channel

subscribe() joins a specific channel. Once subscribed, the channel is a real-time stream where you can send, receive, listen to events, and observe user presence.

const sub = await adk.subscribe("YOUR_CHANNEL_NAME");

Track presence

fetchPresence() returns the list of users currently active in the channel.

sub.fetchPresence((users) => {
  console.log("Active users:", users);
});

Listen to all events

listen() is a catch-all — every payload published to the channel is delivered to your callback.

sub.listen((data) => {
  console.log("Received:", data);
});

Listen to a specific event

bind() filters by event name; the callback only fires for matching events.

sub.bind("EVENT", (data) => {
  console.log("Event received:", data);
});

Send messages

push() publishes an event to the channel. Pass to to deliver only to specific users.

const payload = { message: "Hello!" };

sub.push("EVENT", payload, {
  to: ["username1", "username2"],   // optional — target specific users
});

Threads on an orchestrator-enabled channel

On a channel that has orchestrator enabled, you can spin up isolated threads from a subscription. Each thread has its own id and only receives messages tagged with that id.

const sub = await adk.subscribe("YOUR_CHANNEL");

const thread = sub.thread();
console.log(thread.threadId);

Pass an existing id to attach to a known thread (for example, one created by the server):

const thread = sub.thread("thread_xxxxx");

Listen to all events on the thread

thread.listen((msg) => {
  console.log(msg.event, msg.content);
});

Listen to a specific event

thread.bind("status_update", (content) => {
  console.log(content);
});

Send a message

The thread_id is attached automatically.

await thread.push("user_input", { message: "hello" }, {
  to: ["username"],
});

Stop listening

thread.remove("status_update");          // remove all callbacks for the event
thread.remove("status_update", myFn);    // remove a single callback

Close the thread

thread.dispose();

Orchestrator

adk.orchestrator(id) connects directly to an orchestrator. The SDK subscribes to the orchestrator, so you can go straight to threads.

const orch = adk.orchestrator("your-orchestrator-id").connect();

const thread = await orch.thread();

thread.listen((msg) => {
  console.log(msg.event, msg.content);
});

await thread.push("user_input", { message: "hi" }, {
  to: ["username"],
});

Reuse an existing thread by id:

const thread = await orch.thread("thread_xxxxx");

Agent

adk.agent(id) connects directly to an agent. The SDK subscribes to the agent's.

const agent = adk.agent("your-agent-id").connect();

const thread = agent.thread();

thread.listen((evt) => {
  console.log(evt.event, evt.content);
});

// Start a run with user input
const run = await thread.run("Hello agent");

// Await the final output
const output = await run.done();
console.log(output);

Reply to a follow-up question from the agent:

await run.sendFeedback("yes, proceed");

Shared Object Channel

A Shared Object Channel is a real-time, collaborative data structure backed by a CRDT. Multiple clients can update the same JSON tree concurrently and converge to a consistent state.

// Subscribe like any other channel
const sub = await adk.subscribe("YOUR_SO_CHANNEL_NAME");

Reading

Listen for live updates

Listen at a path inside the shared object — your callback receives plain JSON whenever that subtree changes.

// path examples: "", "user", "user.profile", "todos"
const unsubscribe = await sub.query("user.profile").listen((data) => {
  console.log("profile updated:", data);
});

// later
unsubscribe();

Path rules

  • "" (empty) or "index" → whole document
  • Use dot paths for objects (e.g. user.profile.name)
  • For arrays, listen at the array path (e.g. "todos"). Item keys are internal; per-item paths are not stable.

Fetch once (no subscription)

Retrieve the current value at a path without subscribing for ongoing updates.

const profile = await sub.query("user.profile").execute();

Writing

sub.state() returns a live proxy. Mutate it like normal JavaScript — changes are batched and merged using CRDT rules. The proxy:

  • Auto-creates missing parent objects/arrays on write
  • Deletes safely (deleting a missing key is a no-op)
  • Emits ops optimistically (UI updates immediately) and ships a compacted batch to the server
// Get the live state proxy once and reuse it
const state = sub.state();

/* ---------- Objects ---------- */
state.user.profile.name = "Jane Doe";

// Safe delete (no error if the key doesn't exist)
delete state.settings.theme;

/* ---------- Arrays ---------- */
state.todos.push({ text: "one" }, { text: "two" });

// Mutate newly added items immediately
state.todos[0].text = "ONE";

// Replace item at index 1
state.todos.splice(1, 1, { text: "two-ish" });

// Pop last item (returns the removed value)
const last = state.todos.pop();

/* ---------- Flushing ---------- */
// The client batches & compacts ops automatically.
// Call flush() to force-send the current batch now.
await sub.flush();

Array API (on any array path)

  • push(...items) / pop() / unshift(...items)
  • splice(start, deleteCount?, ...insert)
  • insertAt(index, item)
  • move(fromIndex, toIndex)
  • Numeric index get/set (state.todos[0] = {...})
  • delete state.todos[i] (remove at index)

Notes

  • You cannot create sparse indices by assignment (e.g. todos[5] = ... when length is 1). Use insertAt / splice.
  • For newly pushed items you can mutate them immediately (optimistic local state).

Documentation

Full API reference and guides: docs.arealtimetech.com

Learn more


Made with care by A Realtime Tech.