still-free.openapps.xyz

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.
Owned app · rev 0fa0e84d537b
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.
← All files
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
0fa0e84d53 · 19 hours ago
Bind the agent address in the policy
6f3baa1c72 · 1 day ago
Add favicon.ico so browsers that ask for it stop getting a 404
1a004fe0e3 · 1 day ago
Bounded source sync
afe642fe50 · 2 days ago
Bounded source sync
2c581f55ea · 2 days ago
Bounded source sync
375934c28b · 2 days ago
Bounded source sync
74ff37d51a · 2 days ago