TypeScript SDK

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

Install

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.items);

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/get/create/update/delete
  • jaina.files(projectSlug) → upload/get/delete
  • jaina.actions — define and execute actions
  • jaina.webhooks — register, list, test

Typed records

Pass a type parameter for full type safety on data:

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

const enemies = await jaina.records.list<Enemy>('my-game', 'enemy', {
  filter: { 'data.hp': { gte: 50 } },
});

enemies.items.forEach((e) => {
  // e.data.name, e.data.hp are typed
});

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 helper

for await (const page of jaina.records.paginate('my-game', 'enemy')) {
  for (const record of page.items) {
    /* ... */
  }
}

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.