Browser client

Every Sluurp server serves its client, and every app's import map already names it: import { Sluurp } from "sluurp". Nothing to install. It speaks the REST API and keeps the sign-in.

app.ts
import { Sluurp } from "sluurp";

const sluurp = new Sluurp();
const todos = sluurp.collection("todos");

const { items } = await todos.list({ filter: "done = false", sort: "-created" });
const todo = await todos.create({ title: "Milk" });
await todos.update(todo.id, { done: true }, { reason: "bought" });

new Sluurp() talks to the server that served the page. Give it an origin, new Sluurp("https://school.example.com"), to talk to another, and { project } to address a project other than the default.

Collections

sluurp.collection(name) has:

list({ page, perPage, sort, filter, asOf })A page: { items, page, perPage, totalItems, totalPages }
listAll(options)Every page, as one array
getOne(id), getFirst(filter)One record
create(data), update(id, data), delete(id)Writes. Each takes { reason }, kept with the change
history(id), version(id, seq), restore(id, seq)A record’s past, for a collection that keeps it
changes(since)Every change after one, in order

Files

upload(id, field, file)Put a File or Blob in a record’s field
createWithFile(data, field, file)Make the record and upload in one step
fileUrl(id, field, { w, h, fit, format })An address for an <img>, resized as asked
srcset(id, field, [400, 800, 1200])The srcset for the same, at those widths
fileObjectUrl(id, field), fileText(id, field)A protected file, fetched with the sign-in

Signing in

On the collection that holds people, usually users:

app.ts
const users = sluurp.collection("users");
await users.authWithPassword(email, password);

sluurp.authStore.isValid;   // signed in
sluurp.authStore.record;    // who
sluurp.logout();

There are also signUp, requestPasswordReset, requestSigninLink (a link by mail), verifyTwoFactor, authRefresh, and oauthUrl("google") for a provider, with captureOAuthToken(sluurp) on the page it comes back to. The sign-in is kept in localStorage, shared by every page of the site. sluurp.onAuthFailure is called when the server stops accepting it.

What may I do?

app.ts
const may = await sluurp.permissions();
may.can("grades", "update");        // for some rows at least
may.certainly("grades", "delete");  // for every row

The collections’ own rules, asked in advance, to show only the buttons that will work.

Errors

A failed call throws a SluurpError with status, message (the server’s sentence), body, and isAuthError (401) and isForbidden (403) to tell them apart.

Live

sluurp.socket({ subscribe: ["messages"] }) opens one WebSocket, with every change to those collections as it happens, read as you. on(type, listener) listens; join(topic) and leave(topic) for presence; emit(topic, event, data) says something without keeping it. For a list that stays current by itself, use Sync.

And the rest

sluurp.conversation(id) and sluurp.conversations for chat, sluurp.pages for Pages, sluurp.payments and sluurp.billing for Payments, sluurp.ai for the models, sluurp.social for a feed. And sluurp.send(path, { method, body, query }) for any endpoint, with the sign-in and the app attached.