TypeScript SDK

@jaina/sdk — typed client for Node and the browser.

Install

Heads up: @jaina/sdk is publishing soon and is not yet on npm. Until it ships, use the REST API directly. The examples below are correct for when the package is live.

npm install @jaina/sdk

Quickstart

import { JainaClient } from '@jaina/sdk';

const jaina = new JainaClient({
  apiKey: process.env.JAINA_API_KEY!,
});

const projects = await jaina.projects.list();
console.log(projects); // Project[]

Resources

The client mirrors the REST API surface:

  • jaina.projects — list, get, create, update, delete
  • jaina.schemas(projectSlug) → list/get/create/update/delete
  • jaina.packages(projectSlug) → list/get/create/update/delete
  • jaina.records: (projectSlug, schemaSlug) → list/listTyped/get/getTyped/create/update/delete
  • jaina.files: upload
  • jaina.actions — define and execute actions
  • jaina.webhooks — register, list, test

Typed records

Use listTyped<T>() for full type safety. The fields of T are flattened onto each record alongside its metadata:

interface Enemy {
  name: string;
  hp: number;
  attack: number;
  sprite: string;
  rarity: 'common' | 'uncommon' | 'rare' | 'mythic';
}

const enemies = await jaina.records.listTyped<Enemy>('my-game', 'enemy', {
  page: 1,
  limit: 50,
});

enemies.data.forEach((e) => {
  // e.name and e.hp are typed; e.id, e.created_at, etc. are also present
});

List options are page, limit, package_slug, and paginate. There is no server-side filter option, so filter the returned data array in your own code.

Generate the interface from your schema with jaina codegen --lang typescript.

Error handling

import { JainaError } from '@jaina/sdk';

try {
  await jaina.records.create('my-game', 'enemy', { /* ... */ });
} catch (err) {
  if (err instanceof JainaError) {
    console.error(err.status, err.code, err.message);
    if (err.code === 'validation_failed') {
      console.error(err.issues);
    }
  } else {
    throw err;
  }
}

Pagination

list and listTyped return a paginated envelope ({ data, total, page, limit, pages }). Walk pages by incrementing page:

let page = 1;
while (true) {
  const result = await jaina.records.list('my-game', 'enemy', { page, limit: 50 });
  for (const record of result.data) {
    /* ... */
  }
  if (page * result.limit >= result.total) break;
  page++;
}

Browser usage

The SDK works in browsers if you wrap it with an authenticated proxy on your backend. Never put jn_live_... tokens in client-side bundles.