Source
This app’s code and revision history are public. Download a copy or explore the files below.
Public
The app’s code and revision history are public.
Run it yourself
Take the whole tree and run it on your own machine. The download needs no account. Cloning needs a sign-in.
Download .zip
bounded clone a8c677472ab5691741798a3d
A copy you download is not bounded. The guarantees this app runs under - declared egress, proven invariants, writes that fail closed - live in the runtime serving this page, not in the files. What you get is auditable source you can read and run, with no runtime guarantees attached.
src/lib/bounded.ts
// The guest account: created on first use, no sign-up. It keeps a copy of the person's practice
// days (seconds and sessions per day), so progress is stored for the account as well as on the
// device. Moods never leave the device. The SDK loads only when it is needed.
import { APP_ID } from "../../functions/lib/config";
/** The app this page is served for: the host injects it, so a preview talks to its own data. Local dev falls back to config. */
export const SERVED_APP_ID =
(typeof document !== "undefined" && document.getElementById("__bounded-first-live-bridge")?.getAttribute("data-app-id")) || APP_ID;
type Sdk = typeof import("@bounded-sh/client");
let session: Promise<{ sdk: Sdk; id: string }> | null = null;
/** Resolves to the SDK and this browser's guest user id, signing in once. */
export function me(): Promise<{ sdk: Sdk; id: string }> {
session ??= (async () => {
if (!SERVED_APP_ID) throw new Error("No app id.");
const sdk = await import("@bounded-sh/client");
await sdk.init({ appId: SERVED_APP_ID });
const user = sdk.getCurrentUser() || (await sdk.signInAnonymously());
if (!user?.id) throw new Error("Could not start a guest session.");
return { sdk, id: user.id as string };
})().catch((err) => {
session = null;
throw err;
});
return session;
}
export type DayTotals = { seconds: number; sessions: number };
/** The account's practice days, by YYYY-MM-DD. */
export async function remoteDays(): Promise<Record<string, DayTotals>> {
const { sdk, id } = await me();
const out: Record<string, DayTotals> = {};
let cursor: string | undefined;
do {
const page = (await sdk.get(`practice/${id}/days`, { limit: 1000, cursor })) as { data: { id: string; seconds?: number; sessions?: number }[]; nextCursor?: string | null };
for (const r of page.data ?? []) out[r.id] = { seconds: r.seconds ?? 0, sessions: r.sessions ?? 0 };
cursor = page.nextCursor ?? undefined;
} while (cursor);
return out;
}
export async function saveDay(day: string, totals: DayTotals) {
const { sdk, id } = await me();
await sdk.set(`practice/${id}/days/${day}`, { seconds: Math.round(totals.seconds), sessions: totals.sessions });
}
export async function deleteDays(days: string[]) {
const { sdk, id } = await me();
for (let i = 0; i < days.length; i += 50) {
await sdk.setMany(days.slice(i, i + 50).map((d) => ({ path: `practice/${id}/days/${d}`, document: null })));
}
}
Change history
Link to OpenApps pages and add a contribution strip
Bind the agent address in the policy
Add favicon.ico so browsers that ask for it stop getting a 404
Bounded source sync
Bounded source sync
Bounded source sync
Bounded source sync