SDKs
TypeScript SDK
Official TypeScript/JavaScript SDK for FastCMS with full type safety, auto token refresh, batch operations, real-time subscriptions, and OTP authentication.
TypeScript SDK
The official TypeScript SDK for FastCMS provides a fully-typed client for all API operations with automatic token refresh and real-time support.
Installation
npm install @fastcms/sdk
# or
yarn add @fastcms/sdkQuick Start
import { FastCMS } from '@fastcms/sdk';
const client = new FastCMS({
baseUrl: 'http://localhost:8000',
});
// Sign in
const { user, tokens } = await client.auth.signInWithEmail(
'admin@example.com',
'password123'
);
// Query records
const posts = await client.collection('posts').list({
sort: '-created',
filter: 'published=true',
perPage: 20,
});Authentication
Email & Password
// Register
const { user } = await client.auth.signUpWithEmail(
'user@example.com',
'SecurePass123',
'John Doe' // optional name
);
// Login
const { user, tokens } = await client.auth.signInWithEmail(
'user@example.com',
'SecurePass123'
);
// Refresh token
const newTokens = await client.auth.refreshToken(tokens.refreshToken);
// Get current user
const me = await client.auth.getCurrentUser();
// Change password
await client.auth.changePassword('oldPass', 'newPass');OTP (Passwordless)
// Step 1: Request OTP
await client.auth.requestOTP('user@example.com');
// Step 2: Authenticate with the code from email
const { user, tokens } = await client.auth.authWithOTP(
'user@example.com',
'483921'
);Email Management
// Request email change (sends verification to new address)
await client.auth.requestEmailChange('new@example.com', 'currentPassword');
// Confirm email change (token from the verification email)
await client.auth.confirmEmailChange('verification-token');
// Verify email address
await client.auth.verifyEmail('verification-token');Session Management
// List all active sessions
const sessions = await client.auth.getSessions();
// Revoke a specific session
await client.auth.revokeSession(sessionId);
// Logout all devices
await client.auth.logoutAll();Collections
CRUD Operations
const col = client.collection('products');
// List with filtering, sorting, pagination
const result = await col.list({
page: 1,
perPage: 30,
sort: '-created',
filter: 'price>=100&&active=true',
search: 'laptop',
});
// result.items, result.total, result.page, result.perPage
// Get one record
const product = await col.getOne('record-id');
// Create
const created = await col.create({ name: 'Laptop', price: 999 });
// Update
const updated = await col.update('record-id', { price: 899 });
// Delete
await col.delete('record-id');Batch Operations
Process multiple records in a single request:
// Bulk create
const created = await client.batch.createMany('products', [
{ name: 'Product A', price: 10 },
{ name: 'Product B', price: 20 },
]);
// Bulk upsert
const { created, updated } = await client.batch.upsertMany(
'products',
records,
['sku'] // upsert key field(s)
);
// Bulk delete
const { deleted } = await client.batch.deleteMany('products', ['id1', 'id2', 'id3']);
// Raw batch (custom requests)
const results = await client.batch.execute([
{ method: 'POST', url: '/api/v1/collections/posts/records', body: { title: 'A' } },
{ method: 'PATCH', url: '/api/v1/collections/posts/records/xyz', body: { title: 'B' } },
]);Files
// Upload
const file = await client.files.upload(fileBlob, {
collectionName: 'products',
recordId: 'record-id',
fieldName: 'image',
});
// Get download URL
const url = client.files.getDownloadUrl(file.id);
// Thumbnail — WxH with optional modifier
// Modifiers: (none)=center-crop, f=fit/letterbox, t=top-crop, b=bottom-crop
// Use 0xH or Wx0 for proportional resize
const thumb = client.files.getDownloadUrl(file.id, '300x200'); // center crop
const fit = client.files.getDownloadUrl(file.id, '300x200f'); // fit + pad
const topCrop = client.files.getDownloadUrl(file.id, '300x200t'); // crop from top
const propHeight = client.files.getDownloadUrl(file.id, '0x150'); // prop. to 150px tall
// Protected file — get a short-lived token (2 min)
const { token } = await client.files.getToken(file.id);
const protectedUrl = client.files.getDownloadUrl(file.id, undefined, token);
// Set file as protected
await client.files.setProtected(file.id, true);
// Delete
await client.files.delete(file.id);Real-time Subscriptions
const rt = client.realtime.connect(tokens.accessToken);
// Subscribe to a collection
rt.subscribe('posts', { published: true });
// Listen to events
rt.on('posts:record.created', (data) => {
console.log('New post:', data);
});
rt.on('posts:record.updated', (data) => {
console.log('Post updated:', data);
});
// Unsubscribe
rt.unsubscribe('posts');
// Disconnect
rt.disconnect();API Keys
// Use an API key instead of a user token
const client = new FastCMS({
baseUrl: 'http://localhost:8000',
apiKey: 'fk_live_your_key_here',
});Auto Token Refresh
The SDK automatically refreshes the access token on 401 responses using the stored refresh token. No manual handling required.
// Set tokens after login
client.setTokens(tokens.accessToken, tokens.refreshToken);
// Tokens are refreshed silently in the background
const data = await client.collection('posts').list();TypeScript Types
import type { FastCMS, CollectionRecord, AuthTokens, FileRecord } from '@fastcms/sdk';
interface Post extends CollectionRecord {
title: string;
content: string;
published: boolean;
}
const posts = await client.collection<Post>('posts').list();
// posts.items is Post[]