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

@jsm-mit/rabbit-motoko-package

v0.12.0

Published

Wrapper TypeScript package for Rabbit Motoko Canister.

Readme

Rabbit Motoko Package

A TypeScript library for interacting with the rabbit-motoko task-queue canister on the Internet Computer. The wrapper is the only sanctioned way to talk to the canister: it hides HttpAgent/idlFactory wiring, unwraps the canister's Framework.Result<T> into "resolves with T or throws a known Error", and converts candid opt/variant/ Principal shapes into idiomatic TypeScript.

Installation

npm install @jsm-mit/rabbit-motoko-package

Usage

Initialization

import { TasksActor, AdminActor, ChannelsActor } from '@jsm-mit/rabbit-motoko-package';

const canisterId = 'your-canister-id';
const tasksActor = new TasksActor(canisterId, identity);   // identity optional
const adminActor = new AdminActor(canisterId, identity);
const channelsActor = new ChannelsActor(canisterId, identity);

In a browser bundle import from @jsm-mit/rabbit-motoko-package/browser: the same API without RabbitTaskWorker, whose pigeon dependency pulls in Node-only modules.

Permissions model

A fresh canister has no admins — the first caller of adminActor.registerAsAdminAsyncUnsafe() claims the role. Task permissions are per channel: an admin creates a channel (createChannelAsyncUnsafe) and opens its 10-minute signup window (openChannelForSignupAsyncUnsafe); during the window any principal enrolls itself via signUpForChannelAsyncUnsafe, choosing canAddTasks (create tasks) and/or canWorkOnTasks (poll + claim + complete). Admins can also grant/revoke levels directly and audit members (getChannelMembersAsyncUnsafe).

Adding a task

const taskId = await tasksActor.addTaskAsyncUnsafe({
  channel: 'my-channel',
  commonId: 'operation-42',
  payload: 'task payload data',
  parentIds: [12n],            // optional — task waits until every parent completes
});

Polling, claiming and completing

const availableIds = await tasksActor.getAvailableTaskIdsAsyncUnsafe('my-channel');

const task = await tasksActor.claimTaskAsyncUnsafe({
  id: availableIds[0],
  timeoutNanos: BigInt(5 * 60 * 1_000_000_000),
});

// Only the principal that claimed the task may complete it
await tasksActor.completeTaskAsyncUnsafe({
  id: task.id,
  message: 'task completed successfully',
});

Background worker

import { RabbitTaskWorker } from '@jsm-mit/rabbit-motoko-package';

const worker = new RabbitTaskWorker('my-channel', 15_000, tasksActor);
worker.tasks$.subscribe(task => { /* process claimed TaskView */ });
worker.run();

Error model

Every ...AsyncUnsafe method throws one of exactly three errors — switch on error.message, details are always on error.cause:

  • CanisterError — the canister returned a business #err; cause = { errorKey, errorMessage, logs } (e.g. errorKey: "NotAuthorized", "NotFound", "InvalidData", "ForcedUpdate").
  • CriticalCanisterError — transport failure or a canister trap; cause = { logs, rawError }.
  • CallRefusedAtInspectionStage — the canister's inspect gate refused the call before execution (oversized payload or anonymous caller).

...AsyncSafe variants never throw and resolve with a documented fallback value.

API

  • TasksActor — task-queue domain: addTaskAsyncUnsafe, getAvailableTaskIdsAsyncUnsafe, claimTaskAsyncUnsafe, completeTaskAsyncUnsafe, getTasksAsyncUnsafe, getTasksLast24hAsyncUnsafe, getTasksByCommonIdAsyncUnsafe, getTasksByChannelAndCommonIdAsyncUnsafe, getTaskAsyncUnsafe, getTaskAsyncSafe.
  • AdminActor — admin allowlist and diagnostics: registerAsAdminAsyncUnsafe, addAdminAsyncUnsafe, removeAdminAsyncUnsafe, getAdminsAsyncUnsafe, setLoggingEnabledAsyncUnsafe, whoAmIAsyncUnsafe, getLogsAsyncUnsafe, clearLogsAsyncUnsafe.
  • ChannelsActor — channel registry and permissions: createChannelAsyncUnsafe, openChannelForSignupAsyncUnsafe, signUpForChannelAsyncUnsafe, grantChannelPermissionsAsyncUnsafe, revokeChannelPermissionsAsyncUnsafe, getChannelMembersAsyncUnsafe, getChannelsAsyncUnsafe.
  • RabbitTaskWorker — interval-based polling worker emitting claimed tasks on tasks$.
  • Task data is returned as TaskView (opts flattened to optionals, principals as text, status as "Available" | "Claimed" | "Completed" | "Expired"); raw candid types remain available from . and ./declarations/* exports.

Development

See CLAUDE.md for the canister-change workflow (declarations sync, wrapper updates) and the integration-test policy. The scripts below deploy to mainnet and spend cycles — human-run only; Claude never runs them.

  • npm run test-suite / npm run test-access-restrictions / npm run test-smoke — always on short-living, the crafting table's short-lived test canister: scripts/run-tests.sh reinstalls the current ../rabbit-motoko build there (npm run craft:deploy -- short-living --lease 3 in that repo, no prompt), then runs the entry point with CANISTER_ID set to the short-living id from ~/motoko-crafting-table/canister_ids.json. No .env: every identity is generated per run. A longer lease: npm run test-suite -- --lease 10.
  • npm run redeploy -- [slot] [reinstall|upgrade] [--lease <min>] [--force] — deploys without tests through craft:deploy / craft:upgrade in ../rabbit-motoko. Defaults: short-living, reinstall. No .env, no prompt.

Requirements

  • Node.js 18+
  • TypeScript 5+

License

ISC

Author

@jsm-mit

Publishing

Bump the version in package.json by hand, then npm run publish-public. scripts/publish-public.sh refuses unless this repo is on master equal to origin/master with nothing uncommitted but the bump, the version is new on the registry, and ../rabbit-motoko is on a clean master equal to its origin/master. It then reinstalls that master into short-living (npm run craft:deploy -- short-living --lease 2) and refuses unless dfx canister metadata <short-living id> candid:service equals the committed declarations/rabbit-motoko-backend/rabbit-motoko-backend.did (trailing whitespace ignored) and the smoke test (tests/test-smoke.ts: setup, then one write and one read per domain) passes against that same deploy. Next scripts/stamp-canister-commit.sh checks the canister repo again, rebuilds the canister, regenerates the declarations and refuses if that changes what is committed here; only then it writes rabbitMotoko.{repo, repoUrl, commit} into package.json. Last: build, publish, and commit and push Version bump to <version> (when nothing is left to commit, that is not a failure). A failed publish takes the stamp out.