TypeScript SDK

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

Install

Available now via direct download. @jaina/sdk is not on npm yet, but you can install the real build today:

npm install https://jaina.dev/downloads/npm/jaina-sdk-0.2.0.tgz

See all downloads. The npm install @jaina/sdk command below is correct for when the package goes live on npm.

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.