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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@instantdb/platform

v0.22.96

Published

Instant's platform package for managing Instant apps.

Readme

Welcome to Instant's platform SDK.

The Platform SDK allows you to manage apps on behalf of an Instant user.

Usage

OAuth flow

You'll need an OAuth access token to make request on the Instant user's behalf. The platform SDK includes helpers for performing the OAuth flow in the OAuthHandler class.

Go to the OAuth Apps page of the dashboard to create a new OAuth client id.

First you'll need to create a page that you can redirect to complete the OAuth flow. It should live on the same domain as the page where you're originating the OAuth flow:

// oauth/instant/redirect.tsx
import { OAuthHandler } from '@instantdb/platform';
import { useEffect } from 'react';

const oauthHandler = new OAuthHandler({
  // https://www.instantdb.com/dash?s=main&t=oauth-apps
  clientId: 'YOUR_CLIENT_ID',
  // Be sure the redirectUri matches one of the authorized redirect uris
  // in your OAuth App client config on the Instant dashboard.
  redirectUri: 'https://example.com/oauth/instant/redirect',
});

export default function Page() {
  useEffect(() => {
    // This will send the oauth code to the originating window,
    // then close the window.
    return oauthHandler.handleClientRedirect();
  });

  return <div>Loading...</div>;
}

On the page where you want the user to connect:

// ConnectPage.tsx
import { OAuthHandler } from '@instantdb/platform';

// Available scopes are: apps-read, apps-write,
//                       data-read, data-write,
//                       storage-read, storage-write
const scopes = ['apps-write'];

const handler = new OAuthHandler({
  // https://www.instantdb.com/dash?s=main&t=oauth-apps
  clientId: 'YOUR_CLIENT_ID',
  // Be sure the redirectUri matches one of the authorized redirect uris
  // in your OAuth App client config on the Instant dashboard.
  redirectUri: 'https://example.com/oauth/instant/redirect',
});

export default function Page() {
  const handleConnect = async () => {
    try {
      // This will open a new window where the user will complete the OAuth flow
      const token = await oauthHandler.startClientOnlyFlow(scopes);
      // doSomethingWith(token)
    } catch (e) {
      alert(e.message);
    }
  };

  return (
    <button onClick={handleConnect}>Connect to your Instant Account</button>
  );
}

The client-only flow described here uses PKCE and does not support refresh tokens. For a server-based flow that supports refresh tokens, see the Platform OAuth docs.

Making API requests

Once you have your token, you can perform actions on the user's behalf with the PlatformApi class.

Setup:

import { PlatformApi } from '@instantdb/platform';

const api = new PlatformApi({ auth: { token: 'OAUTH_ACCESS_TOKEN' } });

getApps

Requires the apps-read or apps-write scope.

Get all of the user's apps, optionally fetching the schema and permissions:

const { apps } = await api.getApps({ includeSchema: true, includePerms: true });

getApp

Requires the apps-read or apps-write scope.

Get an app by its id, optionally fetching the schema and permissions:

const { app } = await api.getApp(YOUR_APP_ID, {
  includeSchema: true,
  includePerms: true,
});

getSchema

Requires the apps-read or apps-write scope.

Get the schema for an app by its id:

const { schema } = await api.getSchema(YOUR_APP_ID);

The Platform SDK includes a helper for generating the instant.schema.ts file from the schema returned by the API.

import { generateSchemaTypescriptFile } from '@instantdb/platform';

// Generate the instant.schema.ts file with:
const schemaTs = generateSchemaTypescriptFile(null, schema, '@instantdb/react');

getPerms

Requires the apps-read or apps-write scope.

Get the permissions for an app by its id:

const { perms } = await api.getPerms(YOUR_APP_ID);

The Platform SDK includes a helper for generating the instant.perms.ts file from the perms returned by the API.

import { generatePermsTypescriptFile } from '@instantdb/platform';

// Generate the instant.schema.ts file with:
const permsTs = generatePermsTypescriptFile(perms, '@instantdb/react');

createApp

Requires the apps-write scope.

Create a new app in the authenticated user's account:

const { app } = await api.createApp({ title: 'Great new app' });

createApp takes optional schema and perms arguments.

Create an app with permissions:

import type { InstantRules } from '@instantdb/platform';

const perms: InstantRules = {
  $default: {
    allow: {
      $default: false,
    },
  },
  todos: {
    allow: {
      view: 'true',
      create: 'isOwner',
      update: 'isOwner',
      delete: 'isOwner',
    },
    bind: ['isOwner', 'auth.id != null && auth.id == data.creatorId'],
  },
};

const { app } = await api.createApp({
  title: 'My app with permissions',
  perms: perms,
});

Create an app with a schema:

import { i } from '@instantdb/platform';

const schema = i.schema({
  entities: {
    todos: i.entity({
      title: i.string(),
      done: i.boolean(),
    }),
  },
});

const { app } = await api.createApp({
  title: 'Todo app',
  schema: schema,
});

updateApp

Requires the apps-write scope.

Update an app's title by its id:

const { app } = await api.updateApp(YOUR_APP_ID, { title: 'New app title' });

deleteApp

Requires the apps-write scope.

Delete an app by its id:

const { app } = await api.deleteApp(YOUR_APP_ID);

pushPerms

Requires the apps-write scope.

Update the permissions for an app by its id. This will completely replace the current set of permissions.

import type { InstantRules } from '@instantdb/platform';

const perms: InstantRules = {
  $default: {
    allow: {
      $default: false,
    },
  },
  todos: {
    allow: {
      view: 'true',
      create: 'isOwner',
      update: 'isOwner',
      delete: 'isOwner',
    },
    bind: ['isOwner', 'auth.id != null && auth.id == data.creatorId'],
  },
};

const { app } = await api.pushPerms(YOUR_APP_ID, {
  perms: perms,
});

planSchemaPush

Requires the apps-read or apps-write scope.

Performs a dry-run of schemaPush, returning the steps that would be taken.

import { i } from '@instantdb/platform';

const schema = i.schema({
  entities: {
    todos: i.entity({
      title: i.string().indexed(),
      done: i.boolean(),
      completedAt: i.date().optional(),
    }),
  },
});

const { steps } = await api.planSchemaPush(YOUR_APP_ID, { schema: schema });

// steps
// [
//   { type: 'index', friendlyDescription: 'Add index to todos.title.' },
//   {
//     type: 'add-attr',
//     friendlyDescription: 'Add attribute todos.completedAt.',
//     attr: {...},
//   },
// ];

schemaPush

Requires the apps-write scope.

Push a new schema to an app.

Some schema updates, like adding an index to an attribute with existing data, kick off a process that completes in the background. The schemaPush method will wait for all of the background processes to finish before it returns.

You can subscribe to progress updates to display feedback to the user.

import { i } from '@instantdb/platform';

const schema = i.schema({
  entities: {
    todos: i.entity({
      title: i.string().indexed(),
      done: i.boolean(),
      completedAt: i.date().optional(),
    }),
  },
});

const pushPromise = api.schemaPush(YOUR_APP_ID, { schema: schema });

pushPromise.subscribe({
  next(status) {
    console.log(status.friendlyDescription);
  },
});

const { steps } = await pushPromise;

Note that the promise will return the steps without throwing even if some of the background steps failed. For example, if an attribute was marked unique, but there were multiple entities with the same value. In the case of failure, the step will have a backgroundJob field where error is set to a string.

Here is an example of a failed step to make the title attribute unique because mulitple entities had the same Write docs value.

// steps
[
  {
    type: 'unique',
    friendlyDescription: 'Ensure that todos.title is unique.',
    attrId: '07145112-59b6-4617-9abc-544a3c3e146c',
    forwardIdentity: ['24c6c019-97ef-4915-aef5-7f4f09b372e1', 'todos', 'title'],
    backgroundJob: {
      id: '1a5941ad-542b-4d0a-bce8-81ced3eaed1a',
      createdAt: '2025-05-30T23:26:54.000Z',
      updatedAt: '2025-05-30T23:26:54.000Z',
      status: 'errored',
      workEstimate: 2,
      workCompleted: null,
      error: 'triple-not-unique-error',
      invalidTriplesSample: [
        {
          entityId: 'b59b3be0-9d76-419f-8f95-e28830d12a40',
          value: 'Write docs',
          jsonType: 'string',
        },
        {
          entityId: 'eb57dbc8-5e09-4978-b255-1b81ff46b63e',
          value: 'Write docs',
          jsonType: 'string',
        },
      ],
      type: 'unique',
      invalidUniqueValue: 'Write docs',
    },
  },
];

Some failed steps will include an invalidTriplesSample in the background job, which show some of the triples that caused the error.

Managing schemas

The platform package includes helpers for generating the instant.schema.ts and instant.perms.ts config files from the schema and perms data returned from the API.

import {
  generateSchemaTypescriptFile,
  generatePermsTypescriptFile,
} from '@instantdb/platform';

console.log(
  generateSchemaTypescriptFile(null, shemaFromApi, '@instantdb/core'),
);

console.log(generatePermsTypescriptFile(permsFromApi, '@instantdb/core'));

Use schemaTypescriptFileToInstantSchema to recover an InstantSchemaDef from the typescript file:

import {
  i,
  generateSchemaTypescriptFile,
  schemaTypescriptFileToInstantSchema,
} from '@instantdb/platform';

// Example schema
const schema = i.schema({
  entities: {
    books: i.entity({
      title: i.string().unique(),
    }),
  },
});

// Example of the typescript file that was generated for a schema
const code = generateTypescriptFile(null, schema, '@instantdb/core');

const recoveredSchema = schemaTypescriptFileToInstantSchema(code);

schema == recoveredSchema;

This is useful when parsing a schema that the user manually edited or pulled with npx instant-cli pull.

Questions?

If you have any questions, feel free to drop us a line on our Discord