@mortar-ai/client
v0.3.0
Published
TypeScript client for Mortar — Backend-as-a-Service for mainland-China-friendly mobile + web apps
Maintainers
Readme
@mortar-ai/client
TypeScript / JavaScript client for Mortar — a mainland-China-friendly Backend-as-a-Service.
Works in Node 20+, modern browsers, Cloudflare Workers, Deno, Bun,
React Native — anywhere fetch exists.
Install
npm install @mortar-ai/client
# or pnpm / yarn / bun addProject-scope client
Use this from your app code (mobile / web / server) to call Mortar's
data APIs. Authenticated by your project's API key (created via
the Mortar dashboard or POST /v1/{tenant}/_admin/keys).
import { createClient } from '@mortar-ai/client';
const mortar = createClient({
// The tenant lives in the host subdomain (Supabase's `<ref>.supabase.co`
// shape) — there is no separate `tenant` option.
url: 'https://project-uuid.api.mortar.appunvs.com',
apiKey: process.env.MORTAR_API_KEY!,
});
// Database
const todos = await mortar.from('todos').select({ limit: 50 });
const row = await mortar.from('todos').insert({ title: 'buy milk' });
await mortar.from('todos').update(row.id, { title: 'buy milk + eggs' });
await mortar.from('todos').delete(row.id);
// End-user auth
const { token, user } = await mortar.auth.signIn({
email: '[email protected]',
password: '...',
});
// Re-create the client with the user's token attached so RLS
// can key off them:
const userScoped = mortar.withUserToken(token);
// Storage
await userScoped.storage.upload({
bucket: 'avatars',
key: 'alice.jpg',
body: file, // Blob, ArrayBuffer, Uint8Array, Node stream
contentType: 'image/jpeg',
});
const bytes = await userScoped.storage.downloadAsBytes({ bucket: 'avatars', key: 'alice.jpg' });
// Realtime — SSE subscription to row changes
const sub = mortar.realtime.subscribe(
{ table: 'todos' },
(ev) => console.log(ev.op, ev.id, ev.data),
(err) => console.error('realtime error:', err),
);
// later: sub.unsubscribe();
// Usage / credit dashboard
const usage = await mortar.usage.me();
console.log(`balance: ¥${usage.credit.balance_yuan}`);Account-scope client
Use this from your control-plane code (CI scripts, admin tools,
the mortar CLI itself) to manage your own Mortar account + projects.
import { createAccountClient } from '@mortar-ai/client/account';
const account = createAccountClient({ url: 'https://api.mortar.appunvs.com' });
// First-time
await account.signUp({ email: '[email protected]', password: 'hunter2' });
// or returning user
const { token } = await account.signIn({ email: '[email protected]', password: '...' });
// Projects
const projects = await account.projects.list();
const created = await account.projects.create({
name: 'my-app-prod',
tier: 'small',
credit_mode: 'hard_budget',
});
await account.projects.update(created.id, { tier: 'medium' });
await account.projects.delete(created.id);Errors
Every method throws MortarApiError on non-2xx responses. The
error carries the HTTP status + the parsed JSON body.
import { MortarApiError } from '@mortar-ai/client';
try {
await mortar.from('todos').insert({ title: 'x' });
} catch (e) {
if (e instanceof MortarApiError && e.status === 402 && (e.body as any).error === 'credit_exhausted') {
// Time to top up or wait for next billing period
}
}License
Apache-2.0 — see Mortar's main LICENSE.
