feedback-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 4a4c54cd95c6
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 54b9c9d7fdc2b68029ce2e57
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
// One Bounded session per tab: a guest account created on first use, or the person's own account once
// they sign in with email to keep their votes and posts on every device. No sign-up to start, ever.
import { init, getCurrentUser, getLoginReturnError, signInAnonymously, loginWithRedirect, logout } from "@bounded-sh/client";
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;

export interface Me { id: string; email: string | null; guest: boolean }

let session: Promise<Me> | null = null;
let loginError: string | null = null;

/** Resolves to this browser's person: the signed-in account, or a guest created once. */
export function me(): Promise<Me> {
  session ??= (async () => {
    await init({ appId: SERVED_APP_ID });
    const err = getLoginReturnError();
    if (err) loginError = explain(err);
    const user = getCurrentUser() || (await signInAnonymously());
    if (!user?.id) throw new Error("Could not start a session.");
    return { id: user.id as string, email: (user.email as string | null) ?? null, guest: Boolean(user.isAnonymous) };
  })().catch((err) => {
    session = null;
    throw err;
  });
  return session;
}

/** A hosted sign-in that came back with an error, once. */
export function takeLoginError(): string | null {
  const e = loginError;
  loginError = null;
  return e;
}

/** Hosted email sign-in. The page leaves and comes back here, signed in. */
export async function signIn(): Promise<void> {
  await loginWithRedirect({ methods: ["email"] });
}

/** Signs out and reloads, so the page starts again as a new guest. */
export async function signOut(): Promise<void> {
  await logout();
  location.reload();
}

/** A sentence a person can read for a failed write or read. */
export function explain(err: unknown): string {
  const e = err as { message?: string; decline?: { message?: string } };
  if (e?.decline?.message) return e.decline.message;
  const msg = String(e?.message || err || "");
  if (/network|fetch|Failed to fetch/i.test(msg)) return "You seem to be offline. Try again in a moment.";
  if (/denied|403|forbidden|constraint|policy/i.test(msg)) return "That change was not allowed.";
  return msg || "Something went wrong. Try again.";
}

Change history

Point store links to openapps.free
4a4c54cd95 · 18 hours ago
Release with preview
1d0728818d · 19 hours ago
Retry release
1abc843b3f · 19 hours ago
Bind app agent address in policy
00eb15f50d · 19 hours ago
Use OpenApps service URLs and add contribution strip
347a7b8ca0 · 19 hours ago
Bounded source sync
a0aaceae63 · 1 day ago
Bounded source sync
3125b8113f · 1 day ago
Bounded source sync
882a76ba95 · 1 day ago
Bounded source sync
852d9782ee · 1 day ago
Bounded source sync
a8ee705109 · 1 day ago