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

@orbiocloud/client

v0.2.0

Published

TypeScript SDK for the OrbioCloud platform API

Readme

@orbiocloud/client

TypeScript SDK for the OrbioCloud platform API. Auth, collections, storage, billing, webhooks and realtime tokens behind one typed client.

Works in Node 18+ and modern browsers. No runtime dependencies — it uses the global fetch.

Install

npm install @orbiocloud/client

Quick start

import { OrbioClient } from '@orbiocloud/client';

const orbio = new OrbioClient({ apiKey: process.env.ORBIO_API_KEY! });

await orbio.auth.signIn({ email: '[email protected]', password: '...' });

const { items: posts } = await orbio.collections.documents('posts').list({ limit: 20 });

apiKey is required. baseUrl defaults to https://api.orbiocloud.com and only needs setting if you are pointed at another environment.

Keep your API key server-side. It authenticates as your tenant. In a browser app, call your own backend and let it hold the key.

Auth

await orbio.auth.signUp({ email, password, metadata: { plan: 'free' } });
await orbio.auth.signIn({ email, password });
await orbio.auth.signOut();

orbio.auth.getSession();       // current session or null
orbio.auth.getAccessToken();   // raw token or null
await orbio.auth.getUser();
await orbio.auth.refreshSession();
await orbio.auth.resetPassword(email);   // note: a plain string, not an object

const unsubscribe = orbio.auth.onAuthStateChange((event, session) => {
  if (event === 'SIGNED_OUT') redirectToLogin();
});

After signIn, the access token is attached to subsequent requests automatically.

Signup rate limits

signUp accepts an optional turnstile_token. Supplying a valid one raises your budget from 1 signup/hour/IP to 3/hour/IP. An invalid token is rejected with 403, so send a real one or omit the field.

await orbio.auth.signUp({ email, password, turnstile_token: tokenFromWidget });

Collections

// Collections themselves
const { items, total, has_more } = await orbio.collections.list({ page: 1, limit: 20 });
await orbio.collections.create({ slug: 'posts', name: 'Posts' });
await orbio.collections.get('posts');
await orbio.collections.update('posts', { name: 'Blog posts' });
await orbio.collections.delete('posts');

// Documents inside a collection
const posts = orbio.collections.documents<{ title: string }>('posts');
await posts.list({ page: 1, limit: 20, filter: { published: true } });
await posts.create({ title: 'Hello' });
await posts.get(id);
await posts.update(id, { title: 'Updated' });
await posts.delete(id);

List endpoints return { items, page, limit, total, has_more }.

Storage

await orbio.storage.upload(file, { filename: 'avatar.png' });  // File or Blob
await orbio.storage.list();
await orbio.storage.get(fileId);
await orbio.storage.delete(fileId);

Billing

await orbio.billing.createCheckout({
  price_id: 'price_123',
  success_url: 'https://example.com/done',
  cancel_url: 'https://example.com/cancel',
});
await orbio.billing.getSubscription();
await orbio.billing.createPortalSession();

Webhooks

await orbio.webhooks.createEndpoint({ url, events: ['user.created'] });
await orbio.webhooks.listEndpoints();
await orbio.webhooks.getEndpoint(id);
await orbio.webhooks.updateEndpoint(id, { events: [...] });
await orbio.webhooks.deleteEndpoint(id);
await orbio.webhooks.listDeliveries({ endpoint_id: id });

Realtime

const { token, expires_in } = await orbio.getRealtimeToken();

Returns a short-lived token for a realtime connection. Mint a fresh one per session rather than caching it.

Error handling

Every failure throws an OrbioError carrying the real HTTP status.

import { OrbioError } from '@orbiocloud/client';

try {
  await orbio.auth.signIn({ email, password });
} catch (err) {
  if (err instanceof OrbioError) {
    if (err.isRateLimited) {
      // Back off. err.retryAfter is seconds, when the server said.
      await wait((err.retryAfter ?? 60) * 1000);
    } else if (err.status === 401) {
      showInvalidCredentials();
    }
  }
}

| Property | Meaning | | --- | --- | | status | HTTP status as returned by the server | | message | Server-supplied error message | | code | Machine-readable code, when the server sends one | | retryAfter | Seconds to wait, on 429 — from Retry-After or retry_after | | isRateLimited | true when status === 429 |

Do not retry a 429 with different credentials

Logins are throttled per account as well as per IP, so you can be rate limited while using entirely valid credentials. Treating 429 as an auth failure and retrying makes it worse. Branch on isRateLimited before you branch on anything else.

Versions before 0.2.0 reported a hardcoded 400/401 on every error regardless of what the server returned, so a 429 was indistinguishable from bad credentials. If you are pinned below 0.2.0, upgrade before relying on status.

Security model

Sessions are held in memory only. This client never writes to localStorage, sessionStorage or cookies. That is deliberate: a token in localStorage is readable by any script on the page, so one XSS becomes a stolen session. The trade-off is that a session does not survive a page reload — if you need persistence in a browser app, store the session yourself somewhere you have decided is appropriate (an httpOnly cookie set by your own backend is the usual answer), rather than expecting the SDK to do it for you.

Your API key authenticates as your whole tenant. Keep it on a server. If a browser needs data, call your own backend and let that hold the key. Shipping the key to a client bundle exposes every tenant operation this SDK can perform.

Zero runtime dependencies. The package has no dependencies, only the global fetch, so installing it adds no transitive supply-chain surface.

Node 18+ is required for global fetch.

License

MIT