Skip to content

Latest commit

 

History

4 Commits

Folders and files

Repository files navigation

@snapbase/client-sdk

TypeScript client SDK for Snapbase.

Install

npm install @snapbase/client-sdk

Usage

import { SnapbaseClient } from "@snapbase/client-sdk";

const client = new SnapbaseClient({
  baseUrl: "http://localhost:7070",
  onAuthExpired: () => {
    // Token expired — redirect to login, show a modal, etc.
    window.location.href = "/login";
  },
});

Client singleton

Create a single SnapbaseClient instance and import it across your app — just like PocketBase. The authStore (token, userId, isValid) lives on this instance and stays in sync everywhere.

// lib/snapbase.ts
import { SnapbaseClient } from "@snapbase/client-sdk";

export const sb = new SnapbaseClient({
  baseUrl: "http://localhost:7070",
  onAuthExpired: () => window.location.href = "/login",
});
// any component / file
import { sb } from "@/lib/snapbase";

sb.authStore.isValid; // true | false
sb.authStore.token;   // "eyJ..."
sb.authStore.userId;  // user id | null

React: sb.authStore.isValid is not reactive on its own — React only re-renders on state changes. Sync it manually after login() / logout():

const [loggedIn, setLoggedIn] = useState(sb.authStore.isValid);

await sb.login(email, password);
setLoggedIn(sb.authStore.isValid);

Solid.js: works out of the box. Fine-grained reactivity tracks property reads automatically — no syncing or context needed.

Auth

// User signup
await client.signup("Alice", "alice@test.com", "password");

// User login — token and userId are stored automatically
await client.login("alice@test.com", "password");

console.log(client.authStore.isValid); // true
console.log(client.authStore.token);   // "eyJ..."
console.log(client.authStore.userId);  // "yad87ap3j52peu4" | null

// Logout
client.logout();

All subsequent requests automatically include Authorization: Bearer <token>.

Token expiry

When a request returns 401 (expired/invalid token), the SDK automatically clears the token and fires onAuthExpired. A 403 response (valid token but insufficient role) does not trigger the callback — the error bubbles to your app code so you can handle it gracefully.

// 401 — calls onAuthExpired, clears token
const users = await client.collection("users").getList();

// 403 — returns normally, token stays, caller decides what to do
const response = await client.collection("admin-only").getList();
if (response.status === "error") {
  showToast("You don't have access to this resource");
}

Collections

// Get a collection handle
const posts = client.collection("posts");

// Insert a record
await posts.create({ title: "Hello", body: "World" });

// Query records
await posts.getList({
  filter: { title: "~Hello" },
  sort: { created_at: "DESC" },
  limit: 10,
});

// Update records by filter
await posts.update(
  { title: "Updated" },
  { filter: { title: "=Hello" } }
);
// Response: { status: "success", data: { updated: 1 } }

// Delete records by filter
await posts.delete({ filter: { title: "~spam" } });

Typed collections with Model<T>

Wrap a collection in a Model to get compile-time type safety on records, field names, and filter keys.

import { SnapbaseClient, Model } from "@snapbase/client-sdk";

type User = {
  id: string;
  email: string;
  name: string;
  age: number;
};

const client = new SnapbaseClient();
const Users = new Model<User>(client.collection("users"));

// getList returns typed records
const allUsers = await Users.getList();
// allUsers: User[]

// Filter/sort keys are autocompleted
const adults = await Users.getList({
  filter: { age: ">=18" },
  sort: { name: "ASC" },
});

// create is type-checked
await Users.create({ email: "bob@test.com", name: "Bob", age: 25 });

// update with typed filter keys
await Users.update(
  { age: 31 },
  { filter: { email: "=bob@test.com" } }
);

// delete with typed filter keys
await Users.delete({ filter: { age: "<18" } });

Define your type once and get autocomplete for field names everywhere — no more guessing or typos.

API

new SnapbaseClient(config?)

Option Type Default Description
baseUrl string "http://localhost:7070" Snapbase backend URL
onAuthExpired () => void — Called when a 401 response is received

SnapbaseClient

Method Returns Description
login(email, password) Promise<ApiResponse> Authenticate user, stores token in authStore
signup(name, email, password) Promise<ApiResponse> Register a new user
logout() void Clears the stored auth token
collection(name) CollectionService Get a collection handle

CollectionService

Method Returns Description
getList(params?) Promise<ApiResponse> Query records with filters, sorting, and pagination
create(data) Promise<ApiResponse> Insert a record
update(data, filter) Promise<ApiResponse> Update records by filter
delete(params?) Promise<ApiResponse> Delete records by filter

Model<T>

Method Returns Description
getList(params?) Promise<T[]> Query records with typed filter/sort keys
create(data) Promise<ApiResponse> Insert a record (type-checked Partial<T>)
update(data, params) Promise<ApiResponse> Update records with typed filter keys
delete(params?) Promise<ApiResponse> Delete records with typed filter keys

Filter operators

Operator Example Description
= "=alice@test.com" Equal
!= "!=spam" Not equal
> ">18" Greater than
< "<100" Less than
>= ">=18" Greater than or equal
<= "<=100" Less than or equal
~ "~john" Contains / like
!~ "!~test" Does not contain

Development (local testing with npm link)

# 1. Build the SDK
npm run build

# 2. Register it globally
npm link

# 3. Link into your test project
cd ../your-test-project
npm link @snapbase/client-sdk

# 4. (Optional) Start watch mode for live edits
cd ../snapbase-client-sdk
npm run dev

The test project's node_modules/@snapbase/client-sdk will be a symlink to this directory. Changes to src/ rebuild automatically with npm run dev.

To unlink:

cd ../your-test-project
npm unlink @snapbase/client-sdk

cd ../snapbase-client-sdk
npm unlink -g

Releases

Packages

Contributors

Languages