@mitway/sdk
v0.10.0
Published
TypeScript/JavaScript client for MITWAY-BaaS — auth + database for end-user apps
Readme
@mitway/sdk
TypeScript/JavaScript client for the MITWAY-BaaS backend. Lets end-user apps sign up, sign in, refresh tokens, run PostgREST queries, subscribe to realtime events, and manage storage against a per-tenant MITWAY-BaaS deployment.
Status
v0.5.0
| Module | Status | Notes |
|---|---|---|
| auth | Working | signUp, signInWithPassword, signOut, refreshSession, getSession, getUser, getCurrentUser, getProfile, setProfile, onAuthStateChange |
| database | Working | PostgREST query builder via @supabase/postgrest-js |
| realtime | Working | Socket.IO transport with channels (postgres_changes, broadcast, presence) |
| storage | Working | Bucket admin + object operations (upload, download, signed URLs, public URLs) |
| functions | MCP only | Backend routes + MCP tools working. No SDK module |
| email | Not yet | Backend has no /api/email/* routes |
| ai | Not yet | Backend has no /api/ai/* routes |
Install
pnpm add @mitway/sdkQuick start
import { createClient } from '@mitway/sdk';
const client = createClient({
baseUrl: 'https://acme.api.dev.nttmitway.com',
anonKey: 'eyJhbGciOiJIUzI1NiIs...',
});
// Sign up
const { data: signUpResult, error: signUpError } = await client.auth.signUp({
email: '[email protected]',
password: 'a-strong-password',
name: 'Alice',
});
// Sign in
const { data: session, error } = await client.auth.signInWithPassword({
email: '[email protected]',
password: 'a-strong-password',
});
// Database query (PostgREST query builder)
const { data: posts, error: dbError } = await client.database
.from('posts')
.select('*, author:users(*)')
.eq('user_id', session.user.id)
.order('created_at', { ascending: false })
.limit(10);
// Insert
const { data: newPost } = await client.database
.from('posts')
.insert({ title: 'Hello', content: 'World' })
.select()
.single();
// RPC (stored function)
const { data: stats } = await client.database
.rpc('get_user_stats', { user_id: session.user.id });
// Upload a file
const { data: uploaded, error: upErr } = await client.storage
.from('avatars')
.upload('user-123/avatar.png', file, { contentType: 'image/png' });
// Share a link that expires in an hour
const { data: signed } = await client.storage
.from('private-docs')
.createSignedUrl('contract.pdf', { expiresIn: 3600 });
console.log(signed?.url);
// Public download URL (for public buckets)
const { data: pub } = client.storage
.from('avatars')
.getPublicUrl('user-123/avatar.png');
// Realtime subscription
const channel = client.realtime
.channel('posts-feed')
.on('postgres_changes', { event: 'INSERT', schema: 'public', table: 'posts' }, (payload) => {
console.log('New post:', payload);
})
.subscribe();
// Sign out
await client.auth.signOut();Configuration
interface MitwayBaasConfig {
baseUrl?: string; // default 'http://localhost:7130'
anonKey?: string; // optional fallback bearer for unauthenticated requests
fetch?: typeof fetch; // override (Node < 18, tests, etc.)
headers?: Record<string, string>;
debug?: boolean | ((msg: string, ...args: any[]) => void);
timeout?: number; // default 30000 ms (0 disables)
retryCount?: number; // default 3 (0 disables)
retryDelay?: number; // default 500 ms (exponential backoff with jitter)
autoRefreshToken?: boolean;// default true (refreshes on 401 INVALID_TOKEN)
persistSession?: boolean; // default true (session survives F5)
storageKey?: string; // default 'mitway_baas_session'
storage?: StorageAdapter; // default browser localStorage — pluggable
multiTab?: boolean; // default true (sync session across tabs via `storage` event)
realtime?: RealtimeOptions;
}
interface StorageAdapter {
getItem(key: string): string | null;
setItem(key: string, value: string): void;
removeItem(key: string): void;
}Reactive auth — onAuthStateChange
Subscribe to session transitions (sign-in, sign-out, token refresh,
cross-tab sync, profile update) without polling getSession(). Returns
a Subscription; call .unsubscribe() to stop.
const sub = client.auth.onAuthStateChange((event, session) => {
// event: 'INITIAL_SESSION' | 'SIGNED_IN' | 'SIGNED_OUT'
// | 'TOKEN_REFRESHED' | 'USER_UPDATED'
if (event === 'SIGNED_OUT') router.push('/login');
});
// later
sub.unsubscribe();Custom storage (e.g., cross-subdomain cookie)
Pass a storage adapter to back the session with something other than
the default localStorage — cookies, a native secure store, an
in-memory stub for tests. The adapter is called on every session
mutation (sign-in, refresh, logout), so anything layered on top of it
sees a complete session lifecycle.
import { createClient, createLocalStorageAdapter } from '@mitway/sdk';
import type { StorageAdapter } from '@mitway/sdk';
const localAdapter = createLocalStorageAdapter();
const dualStorage: StorageAdapter = {
getItem: (k) => localAdapter.getItem(k) ?? readFromCookie(k),
setItem: (k, v) => { localAdapter.setItem(k, v); writeCookie(k, v); },
removeItem: (k) => { localAdapter.removeItem(k); clearCookie(k); },
};
const client = createClient({
baseUrl: 'https://…',
storage: dualStorage,
});baseUrl is the only URL consumers need. Auth, database, storage, and realtime
all route through the same backend.
Releasing a new version
Releases are automated via GitHub Actions with OIDC provenance.
Steps:
- Bump the version in
package.json:
pnpm version patch # or minor / major- Push the commit and tag:
git push --follow-tags- Create a Release on GitHub pointing to the new tag (e.g.
v0.5.1).
The workflow (.github/workflows/publish.yml) triggers on the release event, runs typecheck, test, build, and publishes to npm with provenance attestation. Requires an NPM_TOKEN secret configured in the repository.
Auth flow
| Method | Backend route |
|---|---|
| signUp(...) | POST /api/auth/register |
| signInWithPassword(...) | POST /api/auth/login |
| signOut() | POST /api/auth/logout |
| refreshSession() (also automatic on 401) | POST /api/auth/refresh |
The HttpClient automatically calls refreshSession() and retries the
original request when it receives a 401 INVALID_TOKEN response.
Database flow
The database module is a thin wrapper around
@supabase/postgrest-js.
The full PostgREST query builder API is available: select, insert, update,
upsert, delete, rpc, filters, modifiers, and foreign-key joins.
Authorization is read from the TokenManager on every request, so a sign-in/sign-out
is picked up automatically.
Origin
Forked structurally from
InsForge/InsForge-sdk-js.
Kept the lib/ infrastructure (http-client, token-manager, logger)
with rebranding. Rewrote auth and database for the MITWAY-BaaS routes.
