@realiizlabs/admin 0.13.0 → 0.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/media/index.cjs +33 -0
- package/dist/media/index.cjs.map +1 -1
- package/dist/media/index.d.cts +2 -0
- package/dist/media/index.d.ts +2 -0
- package/dist/media/index.js +30 -1
- package/dist/media/index.js.map +1 -1
- package/dist/studio/index.cjs +1 -1
- package/dist/studio/index.cjs.map +1 -1
- package/dist/studio/index.d.cts +3 -41
- package/dist/studio/index.d.ts +3 -41
- package/dist/studio/index.js +1 -1
- package/dist/studio/index.js.map +1 -1
- package/dist/validate-C84Ll1cD.d.cts +41 -0
- package/dist/validate-C84Ll1cD.d.ts +41 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/auth/client.ts","../../src/auth/errors.ts","../../src/auth/session.ts","../../src/auth/types.ts","../../src/auth/roles.ts","../../src/studio/context.ts","../../src/studio/registry.ts","../../src/git/errors.ts","../../src/git/client.ts","../../src/git/pulls.ts","../../src/git/status.ts","../../src/studio/pending.ts","../../src/git/reads.ts","../../src/studio/readers.ts","../../src/git/branch.ts","../../src/git/files.ts","../../src/studio/images.ts","../../src/studio/publish.ts","../../src/git/merge.ts","../../src/studio/merge.ts","../../src/studio/preview.ts","../../src/auth/branding.ts","../../src/auth/profile.ts","../../src/studio/account.ts","../../src/auth/members.ts","../../src/auth/service.ts","../../src/studio/team.ts","../../src/auth/callback.ts","../../src/auth/signout.ts","../../src/studio/handlers.ts","../../src/studio/index.ts"],"names":["createServerClient","redirect","d","matter","getPullRequest","unified","remarkParse","remarkGfm","remarkRehype","rehypeRaw","rehypeSlug","rehypeStringify","createClient"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * createIdentityClient — a Supabase client bound to the request's cookies.\n *\n * Built per request from arguments. A Next 16 route does:\n *\n * const store = await cookies();\n * const client = createIdentityClient({ url, anonKey, cookies: store });\n *\n * No `next` import here. The CookieStore interface accepts either shape a\n * host might hand us: @supabase/ssr's { getAll, setAll }, or Next's\n * cookies() store, which has { getAll, set } — the session cookies are\n * written through whichever exists. (Observed 2026-09-08: with only setAll\n * supported, Next's store silently wrote nothing and every sign-in bounced.)\n */\n\nimport { createServerClient } from \"@supabase/ssr\";\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { IdentityContext } from \"./types\";\n\nexport type IdentityClient = SupabaseClient;\n\ntype CookieToSet = { name: string; value: string; options?: Record<string, unknown> };\n\nexport function createIdentityClient(ctx: IdentityContext): IdentityClient {\n const store = ctx.cookies;\n return createServerClient(ctx.url, ctx.anonKey, {\n cookies: {\n getAll: () => store.getAll(),\n setAll: (list: CookieToSet[]) => {\n // Server Components can't set cookies; @supabase/ssr documents that\n // swallowing the failure there is correct — middleware / route\n // handlers refresh the session instead.\n try {\n if (typeof store.setAll === \"function\") {\n void store.setAll(list);\n } else if (typeof store.set === \"function\") {\n for (const c of list) store.set(c.name, c.value, c.options);\n }\n } catch {\n /* read-only cookie store */\n }\n },\n },\n });\n}\n","/** Typed errors so a route can map them to 401 / 403 without string matching. */\n\nexport class IdentityError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"IdentityError\";\n }\n}\n\n/** No session — send them to sign in. Maps to 401. */\nexport class UnauthenticatedError extends IdentityError {\n constructor() {\n super(\"Not signed in\");\n this.name = \"UnauthenticatedError\";\n }\n}\n\n/** Signed in, but not allowed to do this here. Maps to 403. */\nexport class ForbiddenError extends IdentityError {\n readonly siteId: string;\n readonly required: string;\n readonly actual: string | null;\n\n constructor(siteId: string, required: string, actual: string | null) {\n super(`Requires ${required} on site \"${siteId}\" (you are ${actual ?? \"not a member\"})`);\n this.name = \"ForbiddenError\";\n this.siteId = siteId;\n this.required = required;\n this.actual = actual;\n }\n}\n","/**\n * getCurrentUser — who is signed in, verified against the auth server.\n *\n * `getUser()` round-trips to Supabase and validates the JWT; `getSession()`\n * only decodes the cookie and is not trustworthy on the server. Always this.\n */\n\nimport type { IdentityClient } from \"./client\";\nimport type { IdentityUser } from \"./types\";\n\nexport async function getCurrentUser(client: IdentityClient): Promise<IdentityUser | null> {\n const { data, error } = await client.auth.getUser();\n if (error || !data.user) return null;\n return { id: data.user.id, email: data.user.email ?? null };\n}\n","/**\n * Types for the identity layer. All config arrives as arguments — never env.\n */\n\n/**\n * Either cookie-store shape a host can hand us:\n * - @supabase/ssr's CookieMethodsServer: { getAll, setAll }\n * - Next's `await cookies()` store: { getAll, set }\n * `setAll` is preferred when present; otherwise each cookie goes through `set`.\n */\nexport interface CookieStore {\n getAll(): { name: string; value: string }[] | Promise<{ name: string; value: string }[]>;\n setAll?(cookies: { name: string; value: string; options?: Record<string, unknown> }[]): void | Promise<void>;\n set?(name: string, value: string, options?: Record<string, unknown>): unknown;\n}\n\n/** Enough to read the signed-in user with the anon key + their cookies. */\nexport interface IdentityContext {\n url: string;\n anonKey: string;\n cookies: CookieStore;\n}\n\n/** Server-only. The service-role key bypasses RLS; the module checks roles in code first. */\nexport interface ServiceContext {\n url: string;\n serviceRoleKey: string;\n}\n\nexport type SiteRole = \"staff\" | \"owner\" | \"editor\";\n\nexport const ROLE_RANK: Record<SiteRole, number> = { editor: 1, owner: 2, staff: 3 };\n\nexport interface IdentityUser {\n id: string;\n email: string | null;\n}\n\nexport interface SiteMembership {\n userId: string;\n siteId: string;\n role: \"owner\" | \"editor\";\n}\n","/**\n * Role resolution and the request gate.\n *\n * Two selects on the caller's OWN rows — both permitted by RLS with the anon\n * key, so this never needs the service role. Staff wins over any site role.\n */\n\nimport type { IdentityClient } from \"./client\";\nimport { ForbiddenError, UnauthenticatedError } from \"./errors\";\nimport { getCurrentUser } from \"./session\";\nimport { ROLE_RANK, type IdentityUser, type SiteRole } from \"./types\";\n\nexport async function getSiteRole(client: IdentityClient, siteId: string, userId?: string): Promise<SiteRole | null> {\n const uid = userId ?? (await getCurrentUser(client))?.id;\n if (!uid) return null;\n\n const [staff, member] = await Promise.all([\n client.from(\"staff\").select(\"user_id\").eq(\"user_id\", uid).maybeSingle(),\n client.from(\"site_users\").select(\"role\").eq(\"user_id\", uid).eq(\"site_id\", siteId).maybeSingle(),\n ]);\n\n if (staff.error) throw staff.error;\n if (member.error) throw member.error;\n\n if (staff.data) return \"staff\";\n const role = (member.data as { role?: string } | null)?.role;\n return role === \"owner\" || role === \"editor\" ? role : null;\n}\n\nexport function roleAtLeast(actual: SiteRole | null, minimum: SiteRole): boolean {\n return actual !== null && ROLE_RANK[actual] >= ROLE_RANK[minimum];\n}\n\nexport interface RequireOptions {\n /** Default \"editor\" — any member of the site. */\n minimumRole?: SiteRole;\n}\n\n/**\n * The gate. Throws UnauthenticatedError (→ sign in) or ForbiddenError (→ 403);\n * otherwise returns the user and their effective role for this site.\n */\nexport async function requireSiteUser(\n client: IdentityClient,\n siteId: string,\n opts: RequireOptions = {},\n): Promise<{ user: IdentityUser; role: SiteRole }> {\n const user = await getCurrentUser(client);\n if (!user) throw new UnauthenticatedError();\n\n const minimum = opts.minimumRole ?? \"editor\";\n const role = await getSiteRole(client, siteId, user.id);\n if (!roleAtLeast(role, minimum)) throw new ForbiddenError(siteId, minimum, role);\n\n return { user, role: role as SiteRole };\n}\n","/**\n * Per-request plumbing: the identity client bound to this request's cookies,\n * and the gate every page and action calls first.\n */\n\nimport { redirect } from \"next/navigation\";\nimport { createIdentityClient, type IdentityClient } from \"../auth/client\";\nimport { requireSiteUser } from \"../auth/roles\";\nimport { ForbiddenError, UnauthenticatedError } from \"../auth/errors\";\nimport type { RequireOptions, Session, StudioConfig } from \"./types\";\n\nexport interface RequestContext {\n identityClient: () => Promise<IdentityClient>;\n /**\n * Redirects to /admin/sign-in when nobody is signed in; throws ForbiddenError\n * when the role is too low so the layout can render \"no access\".\n */\n requireAdmin: (opts?: RequireOptions) => Promise<Session>;\n}\n\nexport function makeContext(config: StudioConfig): RequestContext {\n const identityClient = async (): Promise<IdentityClient> => {\n const store = await config.cookies();\n return createIdentityClient({ ...config.env().identity, cookies: store });\n };\n const requireAdmin = async (opts: RequireOptions = {}): Promise<Session> => {\n try {\n return await requireSiteUser(await identityClient(), config.env().siteId, opts);\n } catch (err) {\n if (err instanceof UnauthenticatedError) redirect(\"/admin/sign-in\");\n if (err instanceof ForbiddenError) throw err;\n throw err;\n }\n };\n return { identityClient, requireAdmin };\n}\n","/**\n * Type-aware lookups over the site's registry: which type owns a path, where an\n * item lives on the public site, where its pictures go.\n */\n\nimport type { ContentTypeEntry } from \"../forms/types\";\nimport type { StudioConfig } from \"./types\";\n\nexport interface Located { typeId: string; slug: string; entry: ContentTypeEntry }\n\nexport function makeRegistry(config: Pick<StudioConfig, \"contentTypes\" | \"publicUrls\">) {\n const entries = Object.values(config.contentTypes);\n\n const entry = (typeId: string): ContentTypeEntry | null => config.contentTypes[typeId] ?? null;\n\n /** File name → slug. Blog-style names by default; date-prefixed types supply slugFromFilename. */\n const slugOf = (e: ContentTypeEntry, fileName: string): string | null => {\n if (e.slugFromFilename) return e.slugFromFilename(fileName);\n return fileName.endsWith(\".mdx\") ? fileName.slice(0, -4) : null;\n };\n\n /** content/speaking/x.mdx → { typeId: \"speaking\", slug: \"x\" }. */\n const locate = (path: string): Located | null => {\n for (const e of entries) {\n if (!path.startsWith(`${e.folder}/`)) continue;\n const slug = slugOf(e, path.slice(e.folder.length + 1));\n if (slug) return { typeId: e.id, slug, entry: e };\n }\n return null;\n };\n\n const publicUrlFor = (typeId: string, slug: string): string | null => config.publicUrls?.[typeId]?.(slug) ?? null;\n\n /** Pictures live under public/<last folder segment>/ — content/blog → /blog/. */\n const publicDirFor = (typeId: string): string => {\n const e = entry(typeId);\n return `/${e?.folder.split(\"/\").filter(Boolean).pop() ?? \"images\"}/`;\n };\n\n return { entries, entry, slugOf, locate, publicUrlFor, publicDirFor };\n}\n\nexport type Registry = ReturnType<typeof makeRegistry>;\n","/**\n * Typed errors — so ADMIN-04 can `instanceof` rather than string-match.\n *\n * Each carries enough to log usefully without ever including the token.\n */\n\n/** Any non-2xx from GitHub that is not one of the more specific cases below. */\nexport class GitHubError extends Error {\n readonly status: number;\n readonly path: string;\n readonly body: unknown;\n\n constructor(message: string, opts: { status: number; path: string; body: unknown }) {\n super(message);\n this.name = \"GitHubError\";\n this.status = opts.status;\n this.path = opts.path;\n this.body = opts.body;\n }\n}\n\n/**\n * The pull request cannot merge because `main` moved underneath it in a way\n * that conflicts — someone else edited the same file first.\n *\n * Observed in the probe: a stale base sha does NOT fail the trees write. Tree,\n * commit, ref and PR all succeed; the conflict only shows as\n * `mergeable_state: \"dirty\"` and then a 405 \"Pull Request has merge conflicts\"\n * on merge. So this is raised from mergePullRequest, never from writeFiles.\n * The recovery is the caller's: re-read main, rebuild the change, open a new PR.\n */\nexport class StaleBaseError extends GitHubError {\n readonly pullNumber: number;\n\n constructor(pullNumber: number, opts: { status: number; path: string; body: unknown }) {\n super(`Pull request #${pullNumber} conflicts with the base branch`, opts);\n this.name = \"StaleBaseError\";\n this.pullNumber = pullNumber;\n }\n}\n\n/**\n * The token cannot do what was asked. A 403 from GitHub with a fine-grained PAT\n * almost always means a permission was not granted when the token was made —\n * a setup bug at onboarding, not a runtime condition.\n */\nexport class TokenScopeError extends GitHubError {\n static readonly REQUIRED_PERMISSIONS =\n \"Contents: Read and write, Pull requests: Read and write, Commit statuses: Read-only\";\n\n constructor(opts: { status: number; path: string; body: unknown }) {\n super(\n `GitHub refused ${opts.path} (${opts.status}). The repo token needs these fine-grained permissions: ${TokenScopeError.REQUIRED_PERMISSIONS}`,\n opts,\n );\n this.name = \"TokenScopeError\";\n }\n}\n\n/** mergePullRequest was asked to merge while checks are red. */\nexport class ChecksFailedError extends Error {\n readonly pullNumber: number;\n readonly failingCheck: string | null;\n\n constructor(pullNumber: number, failingCheck: string | null) {\n super(\n `Pull request #${pullNumber} has failing checks${failingCheck ? ` (${failingCheck})` : \"\"}`,\n );\n this.name = \"ChecksFailedError\";\n this.pullNumber = pullNumber;\n this.failingCheck = failingCheck;\n }\n}\n","/**\n * The one place that talks to api.github.com.\n *\n * ── Every call is bounded ────────────────────────────────────────────────────\n * Same pattern as 5degrees-website's HighLevel client: a module constant plus\n * AbortSignal.timeout on every fetch. That fix exists because a slow upstream\n * ran past the serverless function limit and the process was killed before its\n * own error handler could run. A publish is ~10 sequential GitHub calls, so the\n * same failure is available here. Observed probe latency was 200–1400 ms; 10 s\n * is generous, and if GitHub is slower than that we want the error, not the wait.\n *\n * ── No module state ──────────────────────────────────────────────────────────\n * The token arrives in RepoContext on every call. Nothing is read from\n * process.env here or anywhere in src/git (BUILD-ENV law).\n */\n\nimport type { RepoContext } from \"./types\";\nimport { GitHubError, TokenScopeError } from \"./errors\";\n\nconst API = \"https://api.github.com\";\nexport const GITHUB_TIMEOUT_MS = 10_000;\n\nexport interface GitHubResponse<T = unknown> {\n ok: boolean;\n status: number;\n json: T;\n}\n\n/**\n * Low-level request. Returns instead of throwing on non-2xx so callers can\n * inspect the status when a \"failure\" is a meaningful answer (405 on merge,\n * 422 on a duplicate ref). Use `ghFetchOrThrow` when it is not.\n */\nexport async function ghFetch<T = unknown>(\n ctx: RepoContext,\n method: \"GET\" | \"POST\" | \"PATCH\" | \"PUT\" | \"DELETE\",\n path: string,\n body?: unknown,\n): Promise<GitHubResponse<T>> {\n const res = await fetch(API + path, {\n method,\n signal: AbortSignal.timeout(GITHUB_TIMEOUT_MS),\n headers: {\n Authorization: `Bearer ${ctx.token}`,\n Accept: \"application/vnd.github+json\",\n \"X-GitHub-Api-Version\": \"2022-11-28\",\n \"User-Agent\": \"realiizlabs-admin\",\n ...(body !== undefined ? { \"Content-Type\": \"application/json\" } : {}),\n },\n body: body !== undefined ? JSON.stringify(body) : undefined,\n });\n\n const text = await res.text();\n let json: unknown = null;\n if (text) {\n try {\n json = JSON.parse(text);\n } catch {\n json = { raw: text };\n }\n }\n return { ok: res.ok, status: res.status, json: json as T };\n}\n\n/** Same as ghFetch but a non-2xx becomes a typed error. */\nexport async function ghFetchOrThrow<T = unknown>(\n ctx: RepoContext,\n method: \"GET\" | \"POST\" | \"PATCH\" | \"PUT\" | \"DELETE\",\n path: string,\n body?: unknown,\n): Promise<T> {\n const res = await ghFetch<T>(ctx, method, path, body);\n if (!res.ok) throw toError(res, path);\n return res.json;\n}\n\nexport function toError(res: GitHubResponse, path: string): GitHubError {\n const opts = { status: res.status, path, body: res.json };\n if (res.status === 403) return new TokenScopeError(opts);\n const message =\n (res.json as { message?: string } | null)?.message ?? `GitHub ${res.status} on ${path}`;\n return new GitHubError(message, opts);\n}\n\n/** `/repos/{owner}/{repo}` prefix, built per call. */\nexport function repoPath(ctx: RepoContext): string {\n return `/repos/${encodeURIComponent(ctx.owner)}/${encodeURIComponent(ctx.repo)}`;\n}\n\nexport function baseBranch(ctx: RepoContext): string {\n return ctx.baseBranch ?? \"main\";\n}\n","/**\n * openPullRequest — the PR that CI runs on and the client eventually publishes.\n *\n * PR Law (site-starter AGENTS.md): nothing lands on main except through a PR.\n * This module never pushes to the base branch directly.\n */\n\nimport type { PullRequest, RepoContext } from \"./types\";\nimport { baseBranch, ghFetchOrThrow, repoPath } from \"./client\";\n\n/** The subset of GitHub's PR payload this module reads. Observed in the probe. */\nexport interface PullPayload {\n number: number;\n title: string;\n html_url: string;\n state: \"open\" | \"closed\";\n head: { sha: string; ref: string };\n base: { sha: string; ref: string };\n /** null while GitHub is still computing — usually the first ~2 s after creation. */\n mergeable: boolean | null;\n mergeable_state: \"unknown\" | \"clean\" | \"dirty\" | \"blocked\" | \"unstable\" | \"behind\" | \"draft\" | \"has_hooks\";\n merged: boolean;\n /** The description the publish action wrote; the studio reads the file path back out of it. */\n body?: string | null;\n /** Set once merged. */\n merge_commit_sha?: string | null;\n}\n\nexport async function openPullRequest(\n ctx: RepoContext,\n branch: string,\n opts: { title: string; body?: string },\n): Promise<PullRequest> {\n const pr = await ghFetchOrThrow<PullPayload>(ctx, \"POST\", `${repoPath(ctx)}/pulls`, {\n title: opts.title,\n head: branch,\n base: baseBranch(ctx),\n body: opts.body ?? \"\",\n });\n\n return { number: pr.number, html_url: pr.html_url, headSha: pr.head.sha, branch };\n}\n\n/** Live read of a PR — the source of truth for mergeability. */\nexport async function getPullRequest(ctx: RepoContext, number: number): Promise<PullPayload> {\n return ghFetchOrThrow<PullPayload>(ctx, \"GET\", `${repoPath(ctx)}/pulls/${number}`);\n}\n\nexport interface OpenPullRequest extends PullRequest {\n title: string;\n}\n\n/**\n * Open PRs whose head branch starts with `headPrefix` — the dashboard's own\n * in-flight changes (04b names them `admin/{type}/{file}-{stamp}`). One page of\n * 100 is far more than a content site ever has open at once.\n */\nexport async function listOpenPullRequests(ctx: RepoContext, opts: { headPrefix: string }): Promise<OpenPullRequest[]> {\n const prs = await ghFetchOrThrow<PullPayload[]>(ctx, \"GET\", `${repoPath(ctx)}/pulls?state=open&per_page=100`);\n return prs\n .filter((p) => p.head.ref.startsWith(opts.headPrefix))\n .map((p) => ({ number: p.number, title: p.title, html_url: p.html_url, headSha: p.head.sha, branch: p.head.ref }));\n}\n\n/**\n * Close a PR without merging — the client changed their mind. The branch is\n * the caller's to delete (deleteBranch) once the close succeeds; closing first\n * means a failed delete leaves a closed PR, never an open one pointing at nothing.\n */\nexport async function closePullRequest(ctx: RepoContext, number: number): Promise<void> {\n await ghFetchOrThrow<PullPayload>(ctx, \"PATCH\", `${repoPath(ctx)}/pulls/${number}`, { state: \"closed\" });\n}\n","/**\n * getPullRequestStatus — green, red or pending. Nothing else.\n *\n * ── Why not the check-runs endpoint ──────────────────────────────────────────\n * A fine-grained PAT cannot read it. Observed 403 on every probe run, and the\n * token permission picker has no \"Checks\" entry to grant. So status is derived\n * from two things a PAT can always read:\n *\n * 1. the PR's `mergeable_state`, which folds in required checks when branch\n * protection is on;\n * 2. the combined commit status for the head sha, which is where Vercel and\n * any status-based CI report — and the only place a failing check has a\n * name.\n *\n * The accepted limitation: a GitHub Actions failure surfaces only as\n * `blocked`/`unstable`, not by job name. That is red without a name.\n *\n * ── Two traps, both observed ─────────────────────────────────────────────────\n * `mergeable` is null and `mergeable_state` is \"unknown\" for ~2 s after a PR is\n * created. That is pending, never red.\n *\n * The combined status of ZERO statuses has `state: \"pending\"`, not \"success\".\n * A no-CI repo read naively would be pending forever. So `total_count` is\n * checked before `state`.\n */\n\nimport type { PullRequestStatus, RepoContext } from \"./types\";\nimport { ghFetch, ghFetchOrThrow, repoPath } from \"./client\";\nimport { getPullRequest } from \"./pulls\";\n\n/** Observed shape of GET /commits/{sha}/status. */\nexport interface CombinedStatus {\n state: \"success\" | \"failure\" | \"pending\" | \"error\";\n total_count: number;\n statuses: Array<{ context: string; state: string; description: string | null; target_url?: string | null }>;\n}\n\nexport async function getPullRequestStatus(\n ctx: RepoContext,\n number: number,\n log: Pick<Console, \"warn\"> = console,\n): Promise<PullRequestStatus> {\n const pr = await getPullRequest(ctx, number);\n\n if (pr.mergeable === null || pr.mergeable_state === \"unknown\") {\n return { state: \"pending\" };\n }\n\n const combined = await ghFetchOrThrow<CombinedStatus>(\n ctx,\n \"GET\",\n `${repoPath(ctx)}/commits/${pr.head.sha}/status`,\n );\n\n const failing = combined.statuses.find((s) => s.state === \"failure\" || s.state === \"error\");\n\n // dirty is a conflict, not a check failure — mergePullRequest turns it into\n // StaleBaseError. Report it as red here so a poller stops polling.\n if (pr.mergeable_state === \"dirty\") {\n return { state: \"red\", failingCheck: failing?.context ?? \"merge conflict\" };\n }\n\n if (failing || pr.mergeable_state === \"unstable\") {\n return { state: \"red\", failingCheck: failing?.context ?? null };\n }\n\n if (combined.total_count === 0) {\n if (pr.mergeable_state === \"clean\" || pr.mergeable_state === \"behind\") {\n const warning = `[admin/git] ${ctx.owner}/${ctx.repo} has no CI statuses on PR #${number} — treating as green. A client site with no CI is a setup bug.`;\n log.warn(warning);\n return { state: \"green\", warning };\n }\n // blocked with nothing reported yet: required checks have not started.\n return { state: \"pending\" };\n }\n\n if (combined.state === \"success\" && pr.mergeable_state !== \"blocked\") {\n const previewUrl = await previewUrlFor(ctx, pr.head.sha, combined);\n return previewUrl ? { state: \"green\", previewUrl } : { state: \"green\" };\n }\n\n return { state: \"pending\" };\n}\n\n/** Observed shape of GET /deployments and /deployments/{id}/statuses (only what we read). */\ninterface Deployment { id: number; environment: string }\ninterface DeploymentStatus { state: string; environment_url?: string | null }\n\n/** Dashboard pages, not sites — Vercel's commit status points at its inspector, which 404s for anyone else. */\nconst DASHBOARD_HOST = /^https:\\/\\/(www\\.)?(vercel\\.com|app\\.netlify\\.com)\\//i;\n\n/**\n * The preview site's URL, so the client can look before publishing.\n *\n * Preferred source: the GitHub Deployments API, where Vercel/Netlify record the\n * preview hostname as `environment_url`. Needs \"Deployments: read\" on the PAT;\n * a 403 just means no preview link. Fallback: a deploy-ish commit status whose\n * `target_url` is a real site (Vercel's is its dashboard, so it is skipped).\n */\nasync function previewUrlFor(ctx: RepoContext, sha: string, combined: CombinedStatus): Promise<string | null> {\n const deployments = await ghFetch<Deployment[]>(ctx, \"GET\", `${repoPath(ctx)}/deployments?sha=${sha}&per_page=10`);\n if (deployments.ok && Array.isArray(deployments.json)) {\n for (const d of deployments.json.filter((d) => !/^prod/i.test(d.environment))) {\n const statuses = await ghFetch<DeploymentStatus[]>(ctx, \"GET\", `${repoPath(ctx)}/deployments/${d.id}/statuses?per_page=10`);\n if (!statuses.ok || !Array.isArray(statuses.json)) continue;\n const live = statuses.json.find((s) => s.state === \"success\" && s.environment_url && !DASHBOARD_HOST.test(s.environment_url));\n if (live?.environment_url) return live.environment_url;\n }\n }\n const status = combined.statuses.find(\n (s) => s.state === \"success\" && /vercel|netlify|deploy|preview/i.test(s.context) && s.target_url && !DASHBOARD_HOST.test(s.target_url),\n );\n return status?.target_url ?? null;\n}\n","/**\n * The dashboard's own in-flight changes: open PRs on `admin/*` branches, keyed\n * by the file they change. The branch name — `admin/{typeId}/{fileBase}-{stamp}`\n * — is the index, so no extra call per PR is needed. One open change per file;\n * if two ever exist the newest wins here and the older is left alone on GitHub.\n */\n\nimport { getPullRequestStatus } from \"../git/status\";\nimport { listOpenPullRequests } from \"../git/pulls\";\nimport type { RepoConfig, StudioConfig } from \"./types\";\nimport type { Registry } from \"./registry\";\n\nexport type PendingState = \"checking\" | \"ready\" | \"failed\";\n\nexport interface PendingChange {\n number: number;\n branch: string;\n title: string;\n html_url: string;\n path: string;\n typeId: string;\n state: PendingState;\n failingCheck: string | null;\n /** The change removes the item rather than editing it. */\n removal: boolean;\n}\n\nconst BRANCH_RE = /^admin\\/([a-z0-9-]+)\\/(.+)-\\d{8}T\\d{3,6}$/;\n\nexport function makePending(config: StudioConfig, registry: Registry) {\n const repo = (): RepoConfig => config.env().repo;\n\n const listPendingChanges = async (): Promise<Map<string, PendingChange>> => {\n const ctx = repo();\n const prs = await listOpenPullRequests(ctx, { headPrefix: \"admin/\" });\n const out = new Map<string, PendingChange>();\n const resolved = await Promise.all(\n prs.map(async (pr) => {\n const m = BRANCH_RE.exec(pr.branch);\n if (!m) return null;\n const entry = registry.entry(m[1]);\n if (!entry) return null;\n const path = `${entry.folder}/${m[2]}.mdx`;\n const status = await getPullRequestStatus(ctx, pr.number);\n const state: PendingState = status.state === \"green\" ? \"ready\" : status.state === \"red\" ? \"failed\" : \"checking\";\n return {\n number: pr.number,\n branch: pr.branch,\n title: pr.title.replace(/^(Publish|Remove):\\s*/, \"\"),\n removal: pr.title.startsWith(\"Remove: \"),\n html_url: pr.html_url,\n path,\n typeId: entry.id,\n state,\n failingCheck: status.state === \"red\" ? status.failingCheck : null,\n } satisfies PendingChange;\n }),\n );\n for (const p of resolved) {\n if (!p) continue;\n const prev = out.get(p.path);\n if (!prev || p.number > prev.number) out.set(p.path, p);\n }\n return out;\n };\n\n const pendingFor = async (path: string): Promise<PendingChange | null> => (await listPendingChanges()).get(path) ?? null;\n\n return { listPendingChanges, pendingFor };\n}\n\nexport const pendingLabel: Record<PendingState, string> = {\n checking: \"Checking…\",\n ready: \"Ready to publish\",\n failed: \"Needs fixing\",\n};\n\nexport function pendingText(p: PendingChange): string {\n if (p.removal) return p.state === \"ready\" ? \"Removal ready\" : p.state === \"failed\" ? \"Removal needs fixing\" : \"Removing…\";\n return pendingLabel[p.state];\n}\n","/**\n * Read helpers — list a folder, open a file — straight from the repo at call time.\n *\n * The dashboard lists and opens content from `main` via the Contents API, never\n * from the deployed filesystem: Vercel's bundle only contains what the tracer\n * saw, and it is a snapshot of the last deploy rather than of the repo. This\n * is also how hand-written files (github.com, Desktop, Cowork) show up — the\n * dashboard never assumes it authored anything.\n */\n\nimport type { RepoContext } from \"./types\";\nimport { baseBranch, ghFetch, repoPath, toError } from \"./client\";\nimport { GitHubError } from \"./errors\";\n\nexport interface RepoEntry {\n name: string;\n path: string;\n sha: string;\n size: number;\n type: \"file\";\n}\n\nexport interface RepoFile {\n path: string;\n sha: string;\n content: string;\n}\n\nexport class NotFoundError extends GitHubError {\n constructor(path: string) {\n super(`Not found in repo: ${path}`, { status: 404, path, body: null });\n this.name = \"NotFoundError\";\n }\n}\n\ninterface ContentsEntry {\n name: string;\n path: string;\n sha: string;\n size: number;\n type: \"file\" | \"dir\" | \"symlink\" | \"submodule\";\n content?: string;\n encoding?: string;\n}\n\nfunction contentsPath(ctx: RepoContext, path: string, ref?: string): string {\n const clean = path.replace(/^\\/+|\\/+$/g, \"\");\n const encoded = clean.split(\"/\").map(encodeURIComponent).join(\"/\");\n return `${repoPath(ctx)}/contents/${encoded}?ref=${encodeURIComponent(ref ?? baseBranch(ctx))}`;\n}\n\n/** Files directly inside `path`, sorted by name. Missing folder → []. */\nexport async function listDirectory(ctx: RepoContext, path: string, opts: { ref?: string } = {}): Promise<RepoEntry[]> {\n const url = contentsPath(ctx, path, opts.ref);\n const res = await ghFetch<ContentsEntry[] | ContentsEntry>(ctx, \"GET\", url);\n if (res.status === 404) return [];\n if (!res.ok) throw toError(res, url);\n const list = Array.isArray(res.json) ? res.json : [];\n return list\n .filter((e) => e.type === \"file\")\n .map((e) => ({ name: e.name, path: e.path, sha: e.sha, size: e.size, type: \"file\" as const }))\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n\n/** One file, decoded to utf-8. */\nexport async function readFile(ctx: RepoContext, path: string, opts: { ref?: string } = {}): Promise<RepoFile> {\n const url = contentsPath(ctx, path, opts.ref);\n const res = await ghFetch<ContentsEntry>(ctx, \"GET\", url);\n if (res.status === 404) throw new NotFoundError(path);\n if (!res.ok) throw toError(res, url);\n const entry = res.json;\n if (Array.isArray(entry) || entry.type !== \"file\") throw new GitHubError(`${path} is not a file`, { status: res.status, path: url, body: entry });\n if (typeof entry.content !== \"string\") {\n // GitHub omits content for files over 1 MB; MDX never gets near that.\n throw new GitHubError(`${path} is too large to read through the Contents API`, { status: res.status, path: url, body: null });\n }\n const content = decodeBase64Utf8(entry.content);\n return { path: entry.path, sha: entry.sha, content };\n}\n\n/** The Contents API wraps base64 at 60 columns; strip whitespace before decoding. */\nfunction decodeBase64Utf8(b64: string): string {\n const clean = b64.replace(/\\s+/g, \"\");\n const bin = atob(clean);\n const bytes = Uint8Array.from(bin, (c) => c.charCodeAt(0));\n return new TextDecoder(\"utf-8\").decode(bytes);\n}\n","/**\n * Reads come from the repo at request time, never from the deployed filesystem.\n * The dashboard is one of four writers; it lists what is on `main` right now,\n * including files it did not author. Every reader takes a type id, so a second\n * content type needs no new code.\n */\n\nimport matter from \"gray-matter\";\nimport type { ContentTypeEntry } from \"../forms/types\";\nimport { listDirectory, readFile } from \"../git/reads\";\nimport { getPullRequest as ghGetPullRequest } from \"../git/pulls\";\nimport { getPullRequestStatus } from \"../git/status\";\nimport { GitHubError } from \"../git/errors\";\nimport type { StudioConfig } from \"./types\";\nimport type { Registry } from \"./registry\";\nimport type { PendingChange } from \"./pending\";\n\nexport interface ListItem {\n slug: string;\n path: string;\n title: string;\n /** publishedAt, falling back to date — ISO string, or null when the file has neither. */\n date: string | null;\n /** True when the frontmatter did not parse cleanly — still listed, still openable. */\n needsAttention: boolean;\n pending: PendingChange | null;\n /** The file exists only in a pending change — nothing on the live site yet. */\n isNew: boolean;\n}\n\nexport interface PrSummary {\n number: number;\n title: string;\n html_url: string;\n merged: boolean;\n state: \"open\" | \"closed\";\n /** Parsed from the PR body the publish action wrote, when present. */\n postPath: string | null;\n branch: string;\n removal: boolean;\n /** The commit that landed on main when this was published; null until then. */\n mergeCommitSha: string | null;\n}\n\n/** Thrown when no file in the folder maps to the slug — the page turns it into a 404. */\nexport class NotHere extends Error {\n constructor(slug: string) { super(`No item with the web address \"${slug}\".`); this.name = \"NotHere\"; }\n}\n\nconst LIST_CAP = 50;\nconst isItem = (name: string) => name.endsWith(\".mdx\") && !name.startsWith(\"_\");\n\nfunction dateOf(data: Record<string, unknown>): string | null {\n const raw = data.publishedAt ?? data.date;\n if (!raw) return null;\n const d = new Date(raw as string);\n return Number.isNaN(d.getTime()) ? null : d.toISOString();\n}\n\nexport function makeReaders(config: StudioConfig, registry: Registry, pending: { listPendingChanges: () => Promise<Map<string, PendingChange>> }) {\n const repo = () => config.env().repo;\n const need = (typeId: string): ContentTypeEntry => {\n const e = registry.entry(typeId);\n if (!e) throw new Error(`Unknown content type \"${typeId}\"`);\n return e;\n };\n\n /** Slug → repo path; scans the folder when the type names files by date. */\n const pathOf = async (typeId: string, slug: string): Promise<string | null> => {\n const e = need(typeId);\n if (!e.slugFromFilename) return `${e.folder}/${slug}.mdx`;\n const entries = await listDirectory(repo(), e.folder);\n return entries.find((x) => registry.slugOf(e, x.name) === slug)?.path ?? null;\n };\n\n const listItems = async (typeId: string): Promise<ListItem[]> => {\n const e = need(typeId);\n const ctx = repo();\n const [entries, open] = await Promise.all([\n listDirectory(ctx, e.folder).then((all) => all.filter((x) => isItem(x.name))),\n pending.listPendingChanges(),\n ]);\n const describe = async (path: string, ref: string | undefined, extra: Pick<ListItem, \"pending\" | \"isNew\">): Promise<ListItem> => {\n const fileName = path.slice(e.folder.length + 1);\n const slug = registry.slugOf(e, fileName) ?? fileName.replace(/\\.mdx$/, \"\");\n try {\n const file = await readFile(ctx, path, ref ? { ref } : {});\n const { data } = matter(file.content);\n return {\n slug, path,\n title: typeof data.title === \"string\" && data.title ? data.title : slug,\n date: dateOf(data),\n needsAttention: !e.schema.safeParse(data).success,\n ...extra,\n };\n } catch {\n return { slug, path, title: slug, date: null, needsAttention: true, ...extra };\n }\n };\n const live = await Promise.all(entries.slice(0, LIST_CAP).map((x) => describe(x.path, undefined, { pending: open.get(x.path) ?? null, isNew: false })));\n const livePaths = new Set(entries.map((x) => x.path));\n const onlyPending = await Promise.all(\n [...open.values()].filter((p) => p.typeId === e.id && !livePaths.has(p.path)).map((p) => describe(p.path, p.branch, { pending: p, isNew: true })),\n );\n return [...onlyPending, ...live].sort((a, b) => (a.isNew !== b.isNew ? (a.isNew ? -1 : 1) : (b.date ?? \"\").localeCompare(a.date ?? \"\")));\n };\n\n const countItems = async (typeId: string): Promise<number> => {\n const entries = await listDirectory(repo(), need(typeId).folder);\n return entries.filter((x) => isItem(x.name)).length;\n };\n\n const readItem = async (typeId: string, slug: string, opts: { ref?: string } = {}) => {\n const path = await pathOf(typeId, slug);\n if (!path) throw new NotHere(slug);\n const file = await readFile(repo(), path, opts.ref ? { ref: opts.ref } : {});\n const { data, content } = matter(file.content);\n return { frontmatter: data as Record<string, unknown>, body: content.trim(), sha: file.sha, path };\n };\n\n /** The author of the most recent item — the default for a new one; null when the type has no author. */\n const lastAuthor = async (typeId: string): Promise<string | null> => {\n for (const p of await listItems(typeId)) {\n if (p.isNew) continue;\n try {\n const { frontmatter } = await readItem(typeId, p.slug);\n if (typeof frontmatter.author === \"string\" && frontmatter.author) return frontmatter.author;\n } catch { /* try the next one */ }\n }\n return null;\n };\n\n const getPullRequest = async (number: number): Promise<PrSummary | null> => {\n try {\n const pr = await ghGetPullRequest(repo(), number);\n const body = pr.body ?? \"\";\n return {\n number: pr.number, title: pr.title, html_url: pr.html_url, merged: pr.merged, state: pr.state,\n postPath: body.match(/File: `([^`]+)`/)?.[1] ?? null,\n branch: pr.head.ref,\n removal: /^Action: remove$/m.test(body) || pr.title.startsWith(\"Remove: \"),\n mergeCommitSha: pr.merged ? (pr.merge_commit_sha ?? null) : null,\n };\n } catch (err) {\n if (err instanceof GitHubError && err.status === 404) return null;\n throw err;\n }\n };\n\n const prStatus = (number: number) => getPullRequestStatus(repo(), number);\n\n return { pathOf, listItems, countItems, readItem, lastAuthor, getPullRequest, prStatus };\n}\n\nexport type Readers = ReturnType<typeof makeReaders>;\n","/**\n * createBranch — a new branch off the base branch, as it is RIGHT NOW.\n *\n * The base sha is fetched from the refs API on every call and never stored.\n * This module is one of four writers to the same repo (github.com, GitHub\n * Desktop, Cowork are the others), so a ref that was current a minute ago is\n * routinely stale. Branching from a cached sha would silently build on old\n * content.\n */\n\nimport type { CreateBranchResult, RepoContext } from \"./types\";\nimport { baseBranch, ghFetchOrThrow, repoPath } from \"./client\";\n\ninterface RefResponse {\n ref: string;\n object: { sha: string; type: string };\n}\n\n/** Read the current tip of a branch. Always a live call. */\nexport async function getBranchSha(ctx: RepoContext, branch: string): Promise<string> {\n const ref = await ghFetchOrThrow<RefResponse>(\n ctx,\n \"GET\",\n `${repoPath(ctx)}/git/ref/heads/${encodeURIComponent(branch)}`,\n );\n return ref.object.sha;\n}\n\nexport async function createBranch(\n ctx: RepoContext,\n branch: string,\n): Promise<CreateBranchResult> {\n const baseSha = await getBranchSha(ctx, baseBranch(ctx));\n\n await ghFetchOrThrow<RefResponse>(ctx, \"POST\", `${repoPath(ctx)}/git/refs`, {\n ref: `refs/heads/${branch}`,\n sha: baseSha,\n });\n\n return { branch, baseSha };\n}\n\n/**\n * Remove a branch. 204 on success. Used after a squash merge so the client's\n * repo does not accumulate one dead branch per publish.\n */\nexport async function deleteBranch(ctx: RepoContext, branch: string): Promise<void> {\n await ghFetchOrThrow(\n ctx,\n \"DELETE\",\n `${repoPath(ctx)}/git/refs/heads/${encodeURIComponent(branch)}`,\n );\n}\n","/**\n * writeFiles — one or more files in ONE commit on an existing branch.\n *\n * Why the trees API and not the Contents API: a post is an MDX file plus a\n * hero image. Two Contents calls make two commits, and the first triggers a\n * build of a half-finished state. One tree, one commit.\n *\n * Encoding rule, observed in the probe: a tree entry can inline utf-8 text as\n * `content`, but has no `encoding` field — a binary must be uploaded first via\n * POST /git/blobs with `encoding: \"base64\"` and referenced in the tree by sha.\n * So a two-file publish with one image is six calls, not five.\n *\n * `opts.remove` deletes paths in the same commit (tree entry with `sha: null`) —\n * how the dashboard takes a post down: one PR that removes the file.\n */\n\nimport type { FileInput, RepoContext, WriteFilesResult } from \"./types\";\nimport { getBranchSha } from \"./branch\";\nimport { ghFetchOrThrow, repoPath } from \"./client\";\n\ntype TreeEntry =\n | { path: string; mode: \"100644\"; type: \"blob\"; content: string }\n | { path: string; mode: \"100644\"; type: \"blob\"; sha: string }\n /* sha: null in a tree entry deletes the path — GitHub's documented way to remove a file via the trees API. */\n | { path: string; mode: \"100644\"; type: \"blob\"; sha: null };\n\nexport async function writeFiles(\n ctx: RepoContext,\n branch: string,\n files: FileInput[],\n message: string,\n opts: { remove?: string[] } = {},\n): Promise<WriteFilesResult> {\n const remove = opts.remove ?? [];\n if (files.length === 0 && remove.length === 0) throw new Error(\"writeFiles: no files given\");\n\n const base = repoPath(ctx);\n\n // The branch tip as of now — not the sha createBranch returned earlier.\n const parentSha = await getBranchSha(ctx, branch);\n\n // Binary files become blobs first; text is inlined.\n const tree: TreeEntry[] = [];\n for (const file of files) {\n if (file.encoding === \"base64\") {\n const blob = await ghFetchOrThrow<{ sha: string }>(ctx, \"POST\", `${base}/git/blobs`, {\n content: file.content,\n encoding: \"base64\",\n });\n tree.push({ path: file.path, mode: \"100644\", type: \"blob\", sha: blob.sha });\n } else {\n tree.push({ path: file.path, mode: \"100644\", type: \"blob\", content: file.content });\n }\n }\n\n for (const path of remove) tree.push({ path, mode: \"100644\", type: \"blob\", sha: null });\n\n const newTree = await ghFetchOrThrow<{ sha: string }>(ctx, \"POST\", `${base}/git/trees`, {\n base_tree: parentSha,\n tree,\n });\n\n const commit = await ghFetchOrThrow<{ sha: string }>(ctx, \"POST\", `${base}/git/commits`, {\n message,\n tree: newTree.sha,\n parents: [parentSha],\n });\n\n // Fast-forward the branch onto the new commit. `force: false` means a\n // concurrent write to this same branch surfaces as a 422 \"Update is not a\n // fast forward\" rather than being silently overwritten.\n await ghFetchOrThrow(\n ctx,\n \"PATCH\",\n `${base}/git/refs/heads/${encodeURIComponent(branch)}`,\n { sha: commit.sha, force: false },\n );\n\n return { branch, commitSha: commit.sha, treeSha: newTree.sha, fileCount: files.length + remove.length };\n}\n","/**\n * Server-side checks on the pictures a save carries. Pure.\n *\n * The browser already shrank them, but anyone can POST to a server action, so\n * the path, type and size are re-checked before anything is committed: only\n * WebP under the type's public folder, ≤ 800 KB each, ≤ 3.5 MB per save.\n * Frontmatter paths are URL paths (/blog/x.webp); the repo file lives under public/.\n */\n\nexport interface ImagePayload {\n /** URL path as written in the frontmatter or body, e.g. /blog/my-post.webp. */\n path: string;\n /** Base64 of the WebP bytes. */\n base64: string;\n}\n\nexport interface ImageLimits {\n maxEach: number;\n maxTotal: number;\n /** URL prefix pictures must live under. */\n prefix: string;\n}\n\nexport const IMAGE_LIMITS: ImageLimits = { maxEach: 800 * 1024, maxTotal: 3.5 * 1024 * 1024, prefix: \"/blog/\" };\n\nexport const IMAGE_ERRORS = {\n path: \"That image path isn’t allowed.\",\n size: \"That picture is too large to send — try a smaller one.\",\n} as const;\n\nexport type ValidatedImages =\n | { ok: true; files: { path: string; content: string; encoding: \"base64\" }[] }\n | { ok: false; error: string };\n\nconst SAFE_PATH = /^[a-z0-9][a-z0-9/_-]*\\.webp$/;\n\n/** Bytes a base64 string decodes to, without decoding it. */\nexport function decodedSize(b64: string): number {\n const clean = b64.replace(/\\s+/g, \"\");\n const pad = clean.endsWith(\"==\") ? 2 : clean.endsWith(\"=\") ? 1 : 0;\n return Math.floor((clean.length * 3) / 4) - pad;\n}\n\nexport function validateImages(images: ImagePayload[], limits: ImageLimits = IMAGE_LIMITS): ValidatedImages {\n let total = 0;\n const files: { path: string; content: string; encoding: \"base64\" }[] = [];\n for (const img of images) {\n if (typeof img?.path !== \"string\" || typeof img?.base64 !== \"string\") return { ok: false, error: IMAGE_ERRORS.path };\n if (!img.path.startsWith(limits.prefix) || img.path.includes(\"..\")) return { ok: false, error: IMAGE_ERRORS.path };\n const rel = img.path.slice(1);\n if (!SAFE_PATH.test(rel)) return { ok: false, error: IMAGE_ERRORS.path };\n const size = decodedSize(img.base64);\n if (size === 0 || size > limits.maxEach) return { ok: false, error: IMAGE_ERRORS.size };\n total += size;\n if (total > limits.maxTotal) return { ok: false, error: IMAGE_ERRORS.size };\n files.push({ path: `public/${rel}`, content: img.base64.replace(/\\s+/g, \"\"), encoding: \"base64\" });\n }\n return { ok: true, files };\n}\n","/**\n * Publish and remove: validated submission → one commit on a new branch → PR.\n * The branch is cut from `main` as it is at this moment and named with a stamp\n * so two edits of one file never collide. Nothing goes to main directly (PR Law).\n */\n\nimport matter from \"gray-matter\";\nimport { redirect } from \"next/navigation\";\nimport { createBranch } from \"../git/branch\";\nimport { writeFiles } from \"../git/files\";\nimport { openPullRequest } from \"../git/pulls\";\nimport { IMAGE_LIMITS, validateImages, type ImagePayload } from \"./images\";\nimport type { StudioConfig } from \"./types\";\nimport type { Registry } from \"./registry\";\nimport type { RequestContext } from \"./context\";\nimport type { Readers } from \"./readers\";\n\nexport interface PublishInput {\n type: string;\n frontmatter: Record<string, unknown>;\n body: string;\n /** An open change for this file: save onto ITS branch so the same PR picks up the edit. */\n existing?: { number: number; branch: string } | null;\n /** Pictures chosen in this session, already shrunk in the browser; committed with the MDX. */\n images?: ImagePayload[];\n}\n\nexport type PublishResult = { ok: false; error: string };\n\nconst SLUG_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\nconst stamp = () => new Date().toISOString().replace(/[-:]/g, \"\").slice(0, 13);\n\n/** Zod coerced dates to Date; the YAML in the repo uses ISO strings like every hand-written file. */\nfunction serialiseDates(fm: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(fm)) {\n if (v === undefined) continue;\n out[k] = v instanceof Date ? v.toISOString() : v;\n }\n return out;\n}\n\nexport function makePublish(config: StudioConfig, registry: Registry, ctx: RequestContext, readers: Readers) {\n const publishContent = async (input: PublishInput): Promise<PublishResult | never> => {\n const { user } = await ctx.requireAdmin();\n const entry = registry.entry(input.type);\n if (!entry) return { ok: false, error: `Unknown content type \"${input.type}\"` };\n\n const parsed = entry.schema.safeParse(input.frontmatter);\n if (!parsed.success) return { ok: false, error: parsed.error.issues.map((i) => `${i.path.join(\".\")}: ${i.message}`).join(\"; \") };\n\n const fm = serialiseDates(parsed.data as Record<string, unknown>);\n const fileName = entry.filename(fm);\n const path = `${entry.folder}/${fileName}`;\n const content = matter.stringify(`\\n${input.body.trim()}\\n`, fm);\n const title = String(fm.title ?? fileName);\n\n const pictures = validateImages(input.images ?? [], { ...IMAGE_LIMITS, prefix: registry.publicDirFor(entry.id) });\n if (!pictures.ok) return { ok: false, error: pictures.error };\n const files = [{ path, content }, ...pictures.files];\n const repo = config.env().repo;\n\n if (input.existing && (await stillOpen(input.existing.number))) {\n await writeFiles(repo, input.existing.branch, files, `Update: ${title}`);\n redirect(`/admin/pr/${input.existing.number}`);\n }\n const branch = `admin/${entry.id}/${fileName.replace(/\\.mdx$/, \"\")}-${stamp()}`;\n await createBranch(repo, branch);\n await writeFiles(repo, branch, files, `Publish: ${title}`);\n const pr = await openPullRequest(repo, branch, {\n title: `Publish: ${title}`,\n body: `Published from the dashboard by ${user.email ?? user.id}.\\n\\nFile: \\`${path}\\``,\n });\n redirect(`/admin/pr/${pr.number}`);\n };\n\n /** The PR page may be stale: someone could have published or closed the change since it loaded. */\n const stillOpen = async (number: number): Promise<boolean> => {\n try {\n const pr = await readers.getPullRequest(number);\n return Boolean(pr && pr.state === \"open\" && !pr.merged);\n } catch {\n return false;\n }\n };\n\n /** Take an item down: one PR that deletes the file. Nothing disappears until Publish. */\n const removeContent = async (input: { type: string; slug: string }): Promise<PublishResult | never> => {\n const { user } = await ctx.requireAdmin();\n const entry = registry.entry(input.type);\n if (!entry) return { ok: false, error: `Unknown content type \"${input.type}\"` };\n if (!SLUG_RE.test(input.slug)) return { ok: false, error: \"That web address isn't valid.\" };\n const path = (await readers.pathOf(input.type, input.slug)) ?? `${entry.folder}/${input.slug}.mdx`;\n const repo = config.env().repo;\n const branch = `admin/${entry.id}/${input.slug}-${stamp()}`;\n await createBranch(repo, branch);\n await writeFiles(repo, branch, [], `Remove: ${input.slug}`, { remove: [path] });\n const pr = await openPullRequest(repo, branch, {\n title: `Remove: ${input.slug}`,\n body: `Removed from the dashboard by ${user.email ?? user.id}.\\n\\nFile: \\`${path}\\`\\nAction: remove`,\n });\n redirect(`/admin/pr/${pr.number}`);\n };\n\n return { publishContent, removeContent };\n}\n","/**\n * mergePullRequest — publish. Squash, then delete the branch.\n *\n * `requireGreen` defaults to true. The whole point of the PR flow is that CI\n * catches bad frontmatter before it freezes the site; merging red automates the\n * exact failure the flow exists to prevent.\n *\n * Pending is the common case (checks are always pending right after a push),\n * so it is returned for the caller to poll — never thrown.\n */\n\nimport type { MergeResult, RepoContext } from \"./types\";\nimport { deleteBranch } from \"./branch\";\nimport { ghFetch, repoPath, toError } from \"./client\";\nimport { ChecksFailedError, StaleBaseError } from \"./errors\";\nimport { getPullRequest } from \"./pulls\";\nimport { getPullRequestStatus } from \"./status\";\n\ninterface MergeResponse {\n sha: string;\n merged: boolean;\n message: string;\n}\n\nexport interface MergeOptions {\n /** Refuse to merge unless checks are green. Default true. */\n requireGreen?: boolean;\n /** Delete the head branch after a successful merge. Default true. */\n deleteBranch?: boolean;\n /** Squash commit title. Defaults to GitHub's (the PR title + number). */\n commitTitle?: string;\n}\n\nexport async function mergePullRequest(\n ctx: RepoContext,\n number: number,\n opts: MergeOptions = {},\n): Promise<MergeResult> {\n const requireGreen = opts.requireGreen ?? true;\n const path = `${repoPath(ctx)}/pulls/${number}/merge`;\n\n if (requireGreen) {\n const status = await getPullRequestStatus(ctx, number);\n if (status.state === \"pending\") return { merged: false, state: \"pending\" };\n if (status.state === \"red\") {\n // A conflict is not a failed check — it is a stale base. Distinguish it.\n const pr = await getPullRequest(ctx, number);\n if (pr.mergeable_state === \"dirty\") {\n throw new StaleBaseError(number, { status: 0, path, body: pr });\n }\n throw new ChecksFailedError(number, status.failingCheck);\n }\n }\n\n const res = await ghFetch<MergeResponse>(ctx, \"PUT\", path, {\n merge_method: \"squash\",\n ...(opts.commitTitle ? { commit_title: opts.commitTitle } : {}),\n });\n\n if (!res.ok) {\n // Observed: 405 { message: \"Pull Request has merge conflicts\" } for a\n // stale base. Also 405 for \"not mergeable\" generally, and 409 if the head\n // sha moved between read and merge — both are the same recovery for the\n // caller (re-read, rebuild), so both map to StaleBaseError.\n if (res.status === 405 || res.status === 409) {\n throw new StaleBaseError(number, { status: res.status, path, body: res.json });\n }\n throw toError(res, path);\n }\n\n if (opts.deleteBranch ?? true) {\n const pr = await getPullRequest(ctx, number);\n await deleteBranch(ctx, pr.head.ref);\n }\n\n return { merged: true, sha: res.json.sha };\n}\n","/** The Publish button (merge when green, never otherwise) and Discard (close + delete branch). */\n\nimport { mergePullRequest } from \"../git/merge\";\nimport { closePullRequest } from \"../git/pulls\";\nimport { deleteBranch } from \"../git/branch\";\nimport { ChecksFailedError, StaleBaseError } from \"../git/errors\";\nimport type { StudioConfig } from \"./types\";\nimport type { RequestContext } from \"./context\";\nimport type { Readers } from \"./readers\";\n\nexport type MergeOutcome =\n | { state: \"merged\"; sha: string }\n | { state: \"pending\" }\n | { state: \"stale\" }\n | { state: \"red\"; failingCheck: string | null }\n | { state: \"error\"; message: string };\n\nexport type DiscardOutcome =\n | { state: \"discarded\" }\n | { state: \"already-published\" }\n | { state: \"error\"; message: string };\n\nexport function makeMerge(config: StudioConfig, ctx: RequestContext, readers: Readers) {\n const revalidate = config.revalidate ?? (() => {});\n\n const mergeContentPr = async (number: number): Promise<MergeOutcome> => {\n await ctx.requireAdmin();\n try {\n const result = await mergePullRequest(config.env().repo, number, { requireGreen: true });\n revalidate(`/admin/pr/${number}`);\n return result.merged ? { state: \"merged\", sha: result.sha } : { state: \"pending\" };\n } catch (err) {\n if (err instanceof StaleBaseError) return { state: \"stale\" };\n if (err instanceof ChecksFailedError) return { state: \"red\", failingCheck: err.failingCheck };\n return { state: \"error\", message: err instanceof Error ? err.message : String(err) };\n }\n };\n\n const discardChange = async (number: number, branch: string): Promise<DiscardOutcome> => {\n await ctx.requireAdmin();\n const repo = config.env().repo;\n try {\n const pr = await readers.getPullRequest(number);\n if (pr?.merged) return { state: \"already-published\" };\n if (pr && pr.state === \"open\") await closePullRequest(repo, number);\n // Only ever delete the dashboard's own branches; a failed delete leaves a closed PR, which is fine.\n if (branch.startsWith(\"admin/\")) {\n try { await deleteBranch(repo, branch); } catch { /* already gone or protected */ }\n }\n revalidate(\"/admin\");\n const m = /^admin\\/([a-z0-9-]+)\\//.exec(branch);\n if (m) revalidate(`/admin/${m[1]}`);\n return { state: \"discarded\" };\n } catch (err) {\n return { state: \"error\", message: err instanceof Error ? err.message : String(err) };\n }\n };\n\n return { mergeContentPr, discardChange };\n}\n","/**\n * Preview for the editor: the same Markdown machinery the blog's MDX pipeline\n * sits on, returned as HTML. Markdown fidelity, not full MDX — custom components\n * render as their plain contents; headings, lists, links, tables and code are exact.\n */\n\nimport { unified } from \"unified\";\nimport remarkParse from \"remark-parse\";\nimport remarkGfm from \"remark-gfm\";\nimport remarkRehype from \"remark-rehype\";\nimport rehypeRaw from \"rehype-raw\";\nimport rehypeSlug from \"rehype-slug\";\nimport rehypeStringify from \"rehype-stringify\";\nimport type { RequestContext } from \"./context\";\n\nconst MAX_CHARS = 200_000;\n\nconst processor = unified()\n .use(remarkParse)\n .use(remarkGfm)\n .use(remarkRehype, { allowDangerousHtml: true })\n .use(rehypeRaw)\n .use(rehypeSlug)\n .use(rehypeStringify);\n\nexport function makePreview(ctx: RequestContext) {\n const previewBody = async (markdown: string): Promise<{ html: string } | { error: string }> => {\n await ctx.requireAdmin();\n if (markdown.length > MAX_CHARS) return { error: \"That's longer than the preview will render.\" };\n try {\n const source = markdown.replace(/^(import|export)\\s.*$/gm, \"\");\n return { html: String(await processor.process(source)) };\n } catch (err) {\n return { error: err instanceof Error ? err.message.split(\"\\n\")[0] : String(err) };\n }\n };\n return { previewBody };\n}\n","/**\n * Per-site branding — the Business tab. Reads and writes public.sites through\n * the signed-in user's client, so RLS decides who may (members read; owners\n * and staff write). Nothing here needs the service role.\n */\n\nimport type { IdentityClient } from \"./client\";\n\nexport interface SiteBranding {\n name: string;\n logoUrl: string | null;\n faviconUrl: string | null;\n businessEmail: string | null;\n businessPhone: string | null;\n}\n\nexport type BrandingPatch = Partial<SiteBranding> & { name: string };\n\ninterface Row {\n name: string;\n logo_url: string | null;\n favicon_url: string | null;\n business_email: string | null;\n business_phone: string | null;\n}\n\nexport async function getSiteBranding(client: IdentityClient, siteId: string): Promise<SiteBranding | null> {\n const { data, error } = await client.from(\"sites\").select(\"name, logo_url, favicon_url, business_email, business_phone\").eq(\"site_id\", siteId).maybeSingle();\n if (error) throw error;\n if (!data) return null;\n const r = data as Row;\n return { name: r.name, logoUrl: r.logo_url, faviconUrl: r.favicon_url, businessEmail: r.business_email, businessPhone: r.business_phone };\n}\n\n/** Upsert the row. RLS refuses anyone but the site's owners or staff. */\nexport async function updateSiteBranding(client: IdentityClient, siteId: string, patch: BrandingPatch): Promise<void> {\n const row = {\n site_id: siteId,\n name: patch.name.trim(),\n logo_url: patch.logoUrl ?? null,\n favicon_url: patch.faviconUrl ?? null,\n business_email: emptyToNull(patch.businessEmail),\n business_phone: emptyToNull(patch.businessPhone),\n };\n const { error } = await client.from(\"sites\").upsert(row, { onConflict: \"site_id\" });\n if (error) throw error;\n}\n\nfunction emptyToNull(v: string | null | undefined): string | null {\n const s = (v ?? \"\").trim();\n return s === \"\" ? null : s;\n}\n","/**\n * My Profile and Change Password — the signed-in user editing themselves,\n * through their own client (auth.updateUser). Name and photo live in user\n * metadata; the photo file itself is in the avatars bucket (uploaded by the\n * host, path avatars/{uid}/…).\n */\n\nimport type { IdentityClient } from \"./client\";\nimport { IdentityError } from \"./errors\";\n\nexport const MIN_PASSWORD_LENGTH = 10;\nexport const PASSWORD_TOO_SHORT = \"Use at least 10 characters.\";\n\nexport interface ProfilePatch {\n name?: string | null;\n /** The byline — how the name appears on published posts. Blank means \"same as name\". */\n displayName?: string | null;\n avatarUrl?: string | null;\n}\n\nexport interface Profile {\n name: string | null;\n /** Resolved byline: display_name if set, else name. */\n displayName: string | null;\n avatarUrl: string | null;\n}\n\nexport function profileOf(user: { user_metadata?: Record<string, unknown> | null } | null | undefined): Profile {\n const m = user?.user_metadata ?? {};\n const str = (v: unknown) => (typeof v === \"string\" && v.trim() ? v.trim() : null);\n const name = str(m.name);\n const displayName = str(m.display_name) ?? name;\n const avatarUrl = typeof m.avatar_url === \"string\" && m.avatar_url ? m.avatar_url : null;\n return { name, displayName, avatarUrl };\n}\n\nexport async function updateProfile(client: IdentityClient, patch: ProfilePatch): Promise<Profile> {\n const data: Record<string, unknown> = {};\n if (patch.name !== undefined) data.name = (patch.name ?? \"\").trim().slice(0, 80);\n if (patch.displayName !== undefined) data.display_name = (patch.displayName ?? \"\").trim().slice(0, 80);\n if (patch.avatarUrl !== undefined) data.avatar_url = patch.avatarUrl ?? \"\";\n const { data: res, error } = await client.auth.updateUser({ data });\n if (error) throw new IdentityError(error.message);\n return profileOf(res.user);\n}\n\n/** Sets (or replaces) a password. Magic links keep working alongside it. */\nexport async function setPassword(client: IdentityClient, password: string): Promise<void> {\n if (typeof password !== \"string\" || password.length < MIN_PASSWORD_LENGTH) throw new IdentityError(PASSWORD_TOO_SHORT);\n const { error } = await client.auth.updateUser({ password });\n if (error) throw new IdentityError(error.message);\n}\n","/**\n * Account actions for the signed-in person and their site's branding. Everything\n * runs as THE USER through their own identity client, so RLS decides: anyone edits\n * themselves; only owners/staff write branding. No service role in this file.\n * Pictures arrive as base64 (shrunk in the browser) and go to Supabase Storage.\n */\n\nimport { getSiteBranding, updateSiteBranding, type SiteBranding } from \"../auth/branding\";\nimport { profileOf, setPassword, updateProfile } from \"../auth/profile\";\nimport { IdentityError } from \"../auth/errors\";\nimport type { IdentityClient } from \"../auth/client\";\nimport type { ActionResult, StudioConfig } from \"./types\";\nimport type { RequestContext } from \"./context\";\n\nconst MAX_UPLOAD = 800 * 1024;\n\nexport function makeAccount(config: StudioConfig, ctx: RequestContext) {\n const revalidate = config.revalidate ?? (() => {});\n const siteId = () => config.env().siteId;\n const fail = (err: unknown): ActionResult => ({ ok: false, error: err instanceof Error ? err.message : \"Something went wrong. Try again.\" });\n\n const upload = async (client: IdentityClient, bucket: string, path: string, base64: string): Promise<string> => {\n const bytes = Buffer.from(base64.replace(/\\s+/g, \"\"), \"base64\");\n if (bytes.length === 0 || bytes.length > MAX_UPLOAD) throw new IdentityError(\"That picture is too large to send — try a smaller one.\");\n const { error } = await client.storage.from(bucket).upload(path, bytes, { contentType: \"image/webp\", upsert: true, cacheControl: \"60\" });\n if (error) throw new IdentityError(error.message);\n const { data } = client.storage.from(bucket).getPublicUrl(path);\n return `${data.publicUrl}?v=${Date.now()}`;\n };\n\n const saveProfile = async (input: { name: string; displayName: string }): Promise<ActionResult> => {\n await ctx.requireAdmin();\n try {\n await updateProfile(await ctx.identityClient(), { name: input.name, displayName: input.displayName });\n revalidate(\"/admin\", \"layout\");\n return { ok: true, message: \"Saved.\" };\n } catch (err) { return fail(err); }\n };\n\n const saveAvatar = async (input: { base64: string } | null): Promise<ActionResult> => {\n const { user } = await ctx.requireAdmin();\n const client = await ctx.identityClient();\n try {\n if (!input) {\n await updateProfile(client, { avatarUrl: null });\n revalidate(\"/admin\", \"layout\");\n return { ok: true, message: \"Photo removed.\" };\n }\n const url = await upload(client, \"avatars\", `${user.id}/avatar.webp`, input.base64);\n await updateProfile(client, { avatarUrl: url });\n revalidate(\"/admin\", \"layout\");\n return { ok: true, message: \"Photo saved.\" };\n } catch (err) { return fail(err); }\n };\n\n const changePassword = async (input: { password: string; confirm: string }): Promise<ActionResult> => {\n await ctx.requireAdmin();\n if (input.password !== input.confirm) return { ok: false, error: \"Those passwords don’t match.\" };\n try {\n await setPassword(await ctx.identityClient(), input.password);\n return { ok: true, message: \"Password saved. You can sign in with it next time, or keep using email links.\" };\n } catch (err) { return fail(err); }\n };\n\n const loadBranding = async (): Promise<SiteBranding | null> => {\n await ctx.requireAdmin();\n return getSiteBranding(await ctx.identityClient(), siteId());\n };\n\n const saveBranding = async (input: { name: string; businessEmail: string; businessPhone: string }): Promise<ActionResult> => {\n await ctx.requireAdmin({ minimumRole: \"owner\" });\n const client = await ctx.identityClient();\n if (!input.name.trim()) return { ok: false, error: \"Give your business a name.\" };\n try {\n const current = await getSiteBranding(client, siteId());\n await updateSiteBranding(client, siteId(), { name: input.name, businessEmail: input.businessEmail, businessPhone: input.businessPhone, logoUrl: current?.logoUrl ?? null, faviconUrl: current?.faviconUrl ?? null });\n revalidate(\"/admin\", \"layout\");\n return { ok: true, message: \"Saved. Your name now shows at the top of Studio.\" };\n } catch (err) { return fail(err); }\n };\n\n const saveBrandingPicture = async (input: { kind: \"logo\" | \"favicon\"; base64: string | null }): Promise<ActionResult> => {\n await ctx.requireAdmin({ minimumRole: \"owner\" });\n const client = await ctx.identityClient();\n try {\n const current = await getSiteBranding(client, siteId());\n if (!current) return { ok: false, error: \"Save your business name first, then add the pictures.\" };\n const url = input.base64 ? await upload(client, \"branding\", `${siteId()}/${input.kind}.webp`, input.base64) : null;\n await updateSiteBranding(client, siteId(), { ...current, [input.kind === \"logo\" ? \"logoUrl\" : \"faviconUrl\"]: url });\n revalidate(\"/admin\", \"layout\");\n return { ok: true, message: input.base64 ? `${input.kind === \"logo\" ? \"Logo\" : \"Favicon\"} saved.` : \"Removed.\" };\n } catch (err) { return fail(err); }\n };\n\n /** Who am I — for the page header, the profile form and the avatar in the top bar. */\n const loadMe = async () => {\n const { user, role } = await ctx.requireAdmin();\n const { data } = await (await ctx.identityClient()).auth.getUser();\n return { email: user.email ?? \"\", role, ...profileOf(data.user) };\n };\n\n return { saveProfile, saveAvatar, changePassword, loadBranding, saveBranding, saveBrandingPicture, loadMe };\n}\n","/**\n * The Team roster — public.site_members(site_id), a SECURITY DEFINER function\n * that returns rows only to that site's owners or staff (editors get a 42501).\n * Read with the signed-in user's client; writes are in service.ts.\n */\n\nimport type { IdentityClient } from \"./client\";\nimport { ForbiddenError } from \"./errors\";\n\nexport interface SiteMember {\n userId: string;\n email: string;\n name: string | null;\n avatarUrl: string | null;\n role: \"owner\" | \"editor\";\n /** \"invited\" until the person has signed in once. */\n status: \"invited\" | \"active\";\n invitedAt: string;\n}\n\ninterface Row {\n user_id: string;\n email: string;\n name: string | null;\n avatar_url: string | null;\n role: string;\n status: string;\n invited_at: string;\n}\n\nexport async function listSiteMembers(client: IdentityClient, siteId: string): Promise<SiteMember[]> {\n const { data, error } = await client.rpc(\"site_members\", { p_site_id: siteId });\n if (error) {\n if (error.code === \"42501\" || /not allowed/i.test(error.message)) throw new ForbiddenError(siteId, \"owner\", null);\n throw error;\n }\n return ((data ?? []) as Row[]).map((r) => ({\n userId: r.user_id,\n email: r.email,\n name: r.name,\n avatarUrl: r.avatar_url,\n role: r.role === \"owner\" ? \"owner\" : \"editor\",\n status: r.status === \"active\" ? \"active\" : \"invited\",\n invitedAt: r.invited_at,\n }));\n}\n","/**\n * The only file that touches the service-role key. Invite and remove.\n *\n * Authorization is checked HERE, in code, before the privileged client does\n * anything — RLS doesn't apply to the service role, so this is the guard:\n * staff → may grant owner or editor on any site\n * owner → may grant editor on their own site only\n * editor → may not invite\n *\n * `actor` is the caller's already-resolved identity (from requireSiteUser on\n * the anon client). Its role is re-resolved with the service client so a\n * caller can't lie about it.\n */\n\nimport { createClient, type SupabaseClient } from \"@supabase/supabase-js\";\nimport { ForbiddenError, IdentityError } from \"./errors\";\nimport type { ServiceContext, SiteRole } from \"./types\";\n\nexport type ServiceClient = SupabaseClient;\n\nexport function createServiceClient(ctx: ServiceContext): ServiceClient {\n return createClient(ctx.url, ctx.serviceRoleKey, {\n auth: { persistSession: false, autoRefreshToken: false },\n });\n}\n\nexport interface InviteInput {\n email: string;\n siteId: string;\n role: \"owner\" | \"editor\";\n /** The signed-in user performing the invite. */\n actor: { id: string };\n /** Where the invite email's link lands — the site's /admin/auth/callback. */\n redirectTo: string;\n}\n\nexport interface InviteResult {\n userId: string;\n siteId: string;\n role: \"owner\" | \"editor\";\n /** false when the auth user already existed and only the membership was added. */\n invitedByEmail: boolean;\n}\n\nasync function resolveActorRole(svc: ServiceClient, actorId: string, siteId: string): Promise<SiteRole | null> {\n const staff = await svc.from(\"staff\").select(\"user_id\").eq(\"user_id\", actorId).maybeSingle();\n if (staff.error) throw staff.error;\n if (staff.data) return \"staff\";\n const m = await svc.from(\"site_users\").select(\"role\").eq(\"user_id\", actorId).eq(\"site_id\", siteId).maybeSingle();\n if (m.error) throw m.error;\n const role = (m.data as { role?: string } | null)?.role;\n return role === \"owner\" || role === \"editor\" ? role : null;\n}\n\nfunction assertMayGrant(actorRole: SiteRole | null, siteId: string, granting: \"owner\" | \"editor\"): void {\n if (actorRole === \"staff\") return;\n if (actorRole === \"owner\" && granting === \"editor\") return;\n throw new ForbiddenError(siteId, granting === \"owner\" ? \"staff\" : \"owner\", actorRole);\n}\n\nexport async function inviteUser(ctx: ServiceContext, input: InviteInput): Promise<InviteResult> {\n const svc = createServiceClient(ctx);\n const actorRole = await resolveActorRole(svc, input.actor.id, input.siteId);\n assertMayGrant(actorRole, input.siteId, input.role);\n\n const email = input.email.trim().toLowerCase();\n let userId: string | undefined;\n let invitedByEmail = false;\n\n const invite = await svc.auth.admin.inviteUserByEmail(email, {\n redirectTo: input.redirectTo,\n data: { site_id: input.siteId, role: input.role },\n });\n\n if (!invite.error) {\n userId = invite.data.user.id;\n invitedByEmail = true;\n } else if (/already|exists|registered/i.test(invite.error.message)) {\n // Existing auth user (works for another site, or is staff): just add the row.\n userId = await findUserIdByEmail(svc, email);\n if (!userId) throw new IdentityError(`Could not find existing user ${email}`);\n } else {\n throw new IdentityError(`Invite failed: ${invite.error.message}`);\n }\n\n const upsert = await svc\n .from(\"site_users\")\n .upsert({ user_id: userId, site_id: input.siteId, role: input.role, invited_by: input.actor.id }, { onConflict: \"user_id,site_id\" });\n if (upsert.error) throw upsert.error;\n\n return { userId, siteId: input.siteId, role: input.role, invitedByEmail };\n}\n\nasync function findUserIdByEmail(svc: ServiceClient, email: string): Promise<string | undefined> {\n // listUsers is paged; identity holds tens of users, not thousands.\n for (let page = 1; page <= 20; page++) {\n const { data, error } = await svc.auth.admin.listUsers({ page, perPage: 200 });\n if (error) throw error;\n const hit = data.users.find((u) => u.email?.toLowerCase() === email);\n if (hit) return hit.id;\n if (data.users.length < 200) break;\n }\n return undefined;\n}\n\nexport interface RemoveInput {\n userId: string;\n siteId: string;\n actor: { id: string };\n}\n\n/** Removes the membership only. The auth user survives (they may belong to other sites). */\nexport async function removeSiteUser(ctx: ServiceContext, input: RemoveInput): Promise<void> {\n const svc = createServiceClient(ctx);\n const actorRole = await resolveActorRole(svc, input.actor.id, input.siteId);\n\n const target = await svc.from(\"site_users\").select(\"role\").eq(\"user_id\", input.userId).eq(\"site_id\", input.siteId).maybeSingle();\n if (target.error) throw target.error;\n const targetRole = ((target.data as { role?: string } | null)?.role ?? \"editor\") as \"owner\" | \"editor\";\n assertMayGrant(actorRole, input.siteId, targetRole);\n if (targetRole === \"owner\") await assertNotLastOwner(svc, input.siteId);\n\n const del = await svc.from(\"site_users\").delete().eq(\"user_id\", input.userId).eq(\"site_id\", input.siteId);\n if (del.error) throw del.error;\n}\n\nexport interface RoleInput {\n userId: string;\n siteId: string;\n role: \"owner\" | \"editor\";\n actor: { id: string };\n}\n\n/**\n * Change a member's role. Same grant rules as invite (staff anything; an owner\n * may only make people editors on their own site), plus: the last owner of a\n * site can never be demoted, otherwise nobody could manage it.\n */\nexport async function updateSiteRole(ctx: ServiceContext, input: RoleInput): Promise<void> {\n const svc = createServiceClient(ctx);\n const actorRole = await resolveActorRole(svc, input.actor.id, input.siteId);\n assertMayGrant(actorRole, input.siteId, input.role);\n\n const target = await svc.from(\"site_users\").select(\"role\").eq(\"user_id\", input.userId).eq(\"site_id\", input.siteId).maybeSingle();\n if (target.error) throw target.error;\n const current = (target.data as { role?: string } | null)?.role;\n if (!current) throw new IdentityError(\"That person isn't a member of this site.\");\n // Demoting an owner is an owner-level act — an owner may not do it to a peer.\n if (current === \"owner\") assertMayGrant(actorRole, input.siteId, \"owner\");\n if (current === \"owner\" && input.role === \"editor\") await assertNotLastOwner(svc, input.siteId);\n\n const upd = await svc.from(\"site_users\").update({ role: input.role }).eq(\"user_id\", input.userId).eq(\"site_id\", input.siteId);\n if (upd.error) throw upd.error;\n}\n\nexport async function assertNotLastOwner(svc: ServiceClient, siteId: string): Promise<void> {\n const owners = await svc.from(\"site_users\").select(\"user_id\").eq(\"site_id\", siteId).eq(\"role\", \"owner\");\n if (owners.error) throw owners.error;\n if ((owners.data ?? []).length <= 1) throw new IdentityError(\"A site needs at least one owner — make someone else an owner first.\");\n}\n\nexport interface ResendInput {\n email: string;\n siteId: string;\n actor: { id: string };\n redirectTo: string;\n}\n\n/** Send the invite email again. An already-active user gets no email — they can just sign in. */\nexport async function resendInvite(ctx: ServiceContext, input: ResendInput): Promise<{ resent: boolean; message: string }> {\n const svc = createServiceClient(ctx);\n const actorRole = await resolveActorRole(svc, input.actor.id, input.siteId);\n assertMayGrant(actorRole, input.siteId, \"editor\");\n\n const email = input.email.trim().toLowerCase();\n const again = await svc.auth.admin.inviteUserByEmail(email, { redirectTo: input.redirectTo, data: { site_id: input.siteId } });\n if (!again.error) return { resent: true, message: `Invitation sent again to ${email}.` };\n if (/already|exists|registered|confirmed/i.test(again.error.message)) {\n return { resent: false, message: `${email} has already accepted — they can sign in with an email link any time.` };\n }\n throw new IdentityError(`Resend failed: ${again.error.message}`);\n}\n","/**\n * Team actions. Reading the roster uses the signed-in user's client (the\n * site_members() function refuses non-owners). Writes need the service role,\n * which the auth helpers use ONLY after re-checking the actor's role in code.\n */\n\nimport { listSiteMembers, type SiteMember } from \"../auth/members\";\nimport { inviteUser, removeSiteUser, resendInvite, updateSiteRole } from \"../auth/service\";\nimport { ForbiddenError } from \"../auth/errors\";\nimport type { ActionResult, StudioConfig } from \"./types\";\nimport type { RequestContext } from \"./context\";\n\nconst TEAM_NOT_CONFIGURED = \"Inviting people isn’t set up on this deployment yet.\";\nconst OWNER_ONLY = \"Only the site's owner can manage the team.\";\n\nexport type TeamState = { ok: true; members: SiteMember[]; canInvite: boolean } | { ok: false; error: string };\n\nexport function makeTeam(config: StudioConfig, ctx: RequestContext) {\n const revalidate = config.revalidate ?? (() => {});\n const fail = (err: unknown): ActionResult =>\n err instanceof ForbiddenError\n ? { ok: false, error: \"You don’t have permission to do that here.\" }\n : { ok: false, error: err instanceof Error ? err.message : \"Something went wrong. Try again.\" };\n /** No query string: Supabase matches redirect URLs exactly; /admin/auth/accept must be allow-listed per host. */\n const acceptUrl = async () => `${await config.baseUrl()}/admin/auth/accept`;\n\n const loadTeam = async (): Promise<TeamState> => {\n const { role } = await ctx.requireAdmin();\n if (role === \"editor\") return { ok: false, error: OWNER_ONLY };\n try {\n const members = await listSiteMembers(await ctx.identityClient(), config.env().siteId);\n return { ok: true, members, canInvite: config.env().service !== null };\n } catch (err) {\n if (err instanceof ForbiddenError) return { ok: false, error: OWNER_ONLY };\n throw err;\n }\n };\n\n const invite = async (input: { email: string; role: \"owner\" | \"editor\" }): Promise<ActionResult> => {\n const { user } = await ctx.requireAdmin({ minimumRole: \"owner\" });\n const env = config.env();\n if (!env.service) return { ok: false, error: TEAM_NOT_CONFIGURED };\n const email = input.email.trim().toLowerCase();\n if (!/^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$/.test(email)) return { ok: false, error: \"That doesn’t look like an email address.\" };\n try {\n await inviteUser(env.service, { email, siteId: env.siteId, role: input.role, actor: { id: user.id }, redirectTo: await acceptUrl() });\n revalidate(\"/admin/account\");\n return { ok: true, message: `Invitation sent to ${email}.` };\n } catch (err) { return fail(err); }\n };\n\n const changeRole = async (input: { userId: string; role: \"owner\" | \"editor\" }): Promise<ActionResult> => {\n const { user } = await ctx.requireAdmin({ minimumRole: \"owner\" });\n const env = config.env();\n if (!env.service) return { ok: false, error: TEAM_NOT_CONFIGURED };\n try {\n await updateSiteRole(env.service, { userId: input.userId, siteId: env.siteId, role: input.role, actor: { id: user.id } });\n revalidate(\"/admin/account\");\n return { ok: true, message: \"Role updated.\" };\n } catch (err) { return fail(err); }\n };\n\n const resend = async (input: { email: string }): Promise<ActionResult> => {\n const { user } = await ctx.requireAdmin({ minimumRole: \"owner\" });\n const env = config.env();\n if (!env.service) return { ok: false, error: TEAM_NOT_CONFIGURED };\n try {\n const r = await resendInvite(env.service, { email: input.email, siteId: env.siteId, actor: { id: user.id }, redirectTo: await acceptUrl() });\n return { ok: true, message: r.message };\n } catch (err) { return fail(err); }\n };\n\n /** Remove from THIS site (or revoke a pending invite). The person's login survives elsewhere. */\n const remove = async (input: { userId: string }): Promise<ActionResult> => {\n const { user } = await ctx.requireAdmin({ minimumRole: \"owner\" });\n const env = config.env();\n if (!env.service) return { ok: false, error: TEAM_NOT_CONFIGURED };\n if (input.userId === user.id) return { ok: false, error: \"You can’t remove yourself. Ask another owner to do it.\" };\n try {\n await removeSiteUser(env.service, { userId: input.userId, siteId: env.siteId, actor: { id: user.id } });\n revalidate(\"/admin/account\");\n return { ok: true, message: \"Removed.\" };\n } catch (err) { return fail(err); }\n };\n\n return { loadTeam, invite, changeRole, resend, remove };\n}\n","/**\n * handleAuthCallback — the emailed magic link lands here with ?code=…&next=…\n *\n * Exchanges the PKCE code for a session (cookies are written through the\n * adapter the client was built with) and says where to send the user. The\n * `next` parameter is only honoured when it is a plain same-origin path —\n * \"//evil.example\" and \"https://…\" fall back, which closes the open-redirect\n * a naive startsWith(\"/\") check leaves open.\n */\n\nimport type { IdentityClient } from \"./client\";\n\nexport type CallbackResult =\n | { ok: true; redirectTo: string }\n | { ok: false; reason: \"missing_code\" | \"exchange_failed\"; message?: string };\n\nexport interface CallbackOptions {\n /** Where to go when `next` is absent or unsafe. Default \"/admin\". */\n fallbackPath?: string;\n}\n\nexport function safeNextPath(next: string | null | undefined, fallback: string): string {\n if (!next) return fallback;\n // Exactly one leading slash, then not another slash or backslash.\n if (!/^\\/(?![/\\\\])/.test(next)) return fallback;\n // No scheme smuggling or CR/LF.\n if (/[\\r\\n]/.test(next) || /^\\/[^?#]*:\\/\\//.test(next)) return fallback;\n return next;\n}\n\nexport async function handleAuthCallback(\n client: IdentityClient,\n requestUrl: string | URL,\n opts: CallbackOptions = {},\n): Promise<CallbackResult> {\n const fallback = opts.fallbackPath ?? \"/admin\";\n const url = typeof requestUrl === \"string\" ? new URL(requestUrl, \"http://placeholder.invalid\") : requestUrl;\n const code = url.searchParams.get(\"code\");\n if (!code) return { ok: false, reason: \"missing_code\" };\n\n const { error } = await client.auth.exchangeCodeForSession(code);\n if (error) return { ok: false, reason: \"exchange_failed\", message: error.message };\n\n return { ok: true, redirectTo: safeNextPath(url.searchParams.get(\"next\"), fallback) };\n}\n","/** signOut — clears this browser's session. The caller redirects afterwards. */\n\nimport type { IdentityClient } from \"./client\";\n\nexport async function signOut(client: IdentityClient): Promise<void> {\n const { error } = await client.auth.signOut({ scope: \"local\" });\n if (error) throw error;\n}\n","/**\n * Route handlers for the auth round-trips — plain Request → Response so the\n * package never imports next/server. A site re-exports them from route.ts.\n */\n\nimport { handleAuthCallback } from \"../auth/callback\";\nimport { signOut } from \"../auth/signout\";\nimport type { RequestContext } from \"./context\";\n\nexport function makeHandlers(ctx: RequestContext) {\n /** The magic link lands here: ?code=…&next=/admin → session cookies → redirect. */\n const callback = async (request: Request): Promise<Response> => {\n const result = await handleAuthCallback(await ctx.identityClient(), request.url, { fallbackPath: \"/admin\" });\n const target = result.ok ? result.redirectTo : \"/admin/sign-in?error=link\";\n return Response.redirect(new URL(target, request.url), 307);\n };\n\n /** POST only — the sign-out button is a plain form, so this works without JS. */\n const signout = async (request: Request): Promise<Response> => {\n try { await signOut(await ctx.identityClient()); } catch { /* already signed out, or not configured */ }\n return Response.redirect(new URL(\"/admin/sign-in\", request.url), 303);\n };\n\n return { callback, signout };\n}\n","/**\n * @realiizlabs/admin/studio — SERVER-ONLY.\n *\n * The server half of a site's Studio: readers over the repo, the publish /\n * merge / discard / preview / account / team logic, the session gate and the\n * auth route handlers — all built from one createStudio(config) call. Nothing\n * here reads process.env; the site's env.ts does that, lazily.\n */\n\nimport \"server-only\";\n\nimport { makeContext } from \"./context\";\nimport { makeRegistry } from \"./registry\";\nimport { makePending } from \"./pending\";\nimport { makeReaders } from \"./readers\";\nimport { makePublish } from \"./publish\";\nimport { makeMerge } from \"./merge\";\nimport { makePreview } from \"./preview\";\nimport { makeAccount } from \"./account\";\nimport { makeTeam } from \"./team\";\nimport { makeHandlers } from \"./handlers\";\nimport type { StudioConfig } from \"./types\";\n\nexport function createStudio(config: StudioConfig) {\n const ctx = makeContext(config);\n const registry = makeRegistry(config);\n const pending = makePending(config, registry);\n const readers = makeReaders(config, registry, pending);\n const actions = {\n ...makePublish(config, registry, ctx, readers),\n ...makeMerge(config, ctx, readers),\n ...makePreview(ctx),\n ...makeAccount(config, ctx),\n ...makeTeam(config, ctx),\n };\n return {\n config,\n isConfigured: config.isConfigured,\n entry: registry.entry,\n entries: registry.entries,\n requireAdmin: ctx.requireAdmin,\n identityClient: ctx.identityClient,\n readers: { ...readers, ...pending, locate: registry.locate, publicUrlFor: registry.publicUrlFor, publicDirFor: registry.publicDirFor },\n actions,\n authHandlers: makeHandlers(ctx),\n };\n}\n\nexport type Studio = ReturnType<typeof createStudio>;\nexport type StudioActions = Studio[\"actions\"];\nexport type StudioReaders = Studio[\"readers\"];\n\nexport type { StudioConfig, StudioEnv, ActionResult, RepoConfig, IdentityConfig, ServiceConfig, Session } from \"./types\";\nexport type { ListItem, PrSummary } from \"./readers\";\nexport { NotHere } from \"./readers\";\nexport type { PendingChange, PendingState } from \"./pending\";\nexport { pendingLabel, pendingText } from \"./pending\";\nexport type { PublishInput, PublishResult } from \"./publish\";\nexport type { MergeOutcome, DiscardOutcome } from \"./merge\";\nexport type { TeamState } from \"./team\";\nexport type { Located } from \"./registry\";\nexport { validateImages, decodedSize, IMAGE_LIMITS, IMAGE_ERRORS } from \"./images\";\nexport type { ImagePayload, ImageLimits, ValidatedImages } from \"./images\";\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/auth/client.ts","../../src/auth/errors.ts","../../src/auth/session.ts","../../src/auth/types.ts","../../src/auth/roles.ts","../../src/studio/context.ts","../../src/studio/registry.ts","../../src/git/errors.ts","../../src/git/client.ts","../../src/git/pulls.ts","../../src/git/status.ts","../../src/studio/pending.ts","../../src/git/reads.ts","../../src/studio/readers.ts","../../src/git/branch.ts","../../src/git/files.ts","../../src/media/validate.ts","../../src/studio/publish.ts","../../src/git/merge.ts","../../src/studio/merge.ts","../../src/studio/preview.ts","../../src/auth/branding.ts","../../src/auth/profile.ts","../../src/studio/account.ts","../../src/auth/members.ts","../../src/auth/service.ts","../../src/studio/team.ts","../../src/auth/callback.ts","../../src/auth/signout.ts","../../src/studio/handlers.ts","../../src/studio/index.ts"],"names":["createServerClient","redirect","d","matter","getPullRequest","unified","remarkParse","remarkGfm","remarkRehype","rehypeRaw","rehypeSlug","rehypeStringify","createClient"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * createIdentityClient — a Supabase client bound to the request's cookies.\n *\n * Built per request from arguments. A Next 16 route does:\n *\n * const store = await cookies();\n * const client = createIdentityClient({ url, anonKey, cookies: store });\n *\n * No `next` import here. The CookieStore interface accepts either shape a\n * host might hand us: @supabase/ssr's { getAll, setAll }, or Next's\n * cookies() store, which has { getAll, set } — the session cookies are\n * written through whichever exists. (Observed 2026-09-08: with only setAll\n * supported, Next's store silently wrote nothing and every sign-in bounced.)\n */\n\nimport { createServerClient } from \"@supabase/ssr\";\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { IdentityContext } from \"./types\";\n\nexport type IdentityClient = SupabaseClient;\n\ntype CookieToSet = { name: string; value: string; options?: Record<string, unknown> };\n\nexport function createIdentityClient(ctx: IdentityContext): IdentityClient {\n const store = ctx.cookies;\n return createServerClient(ctx.url, ctx.anonKey, {\n cookies: {\n getAll: () => store.getAll(),\n setAll: (list: CookieToSet[]) => {\n // Server Components can't set cookies; @supabase/ssr documents that\n // swallowing the failure there is correct — middleware / route\n // handlers refresh the session instead.\n try {\n if (typeof store.setAll === \"function\") {\n void store.setAll(list);\n } else if (typeof store.set === \"function\") {\n for (const c of list) store.set(c.name, c.value, c.options);\n }\n } catch {\n /* read-only cookie store */\n }\n },\n },\n });\n}\n","/** Typed errors so a route can map them to 401 / 403 without string matching. */\n\nexport class IdentityError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"IdentityError\";\n }\n}\n\n/** No session — send them to sign in. Maps to 401. */\nexport class UnauthenticatedError extends IdentityError {\n constructor() {\n super(\"Not signed in\");\n this.name = \"UnauthenticatedError\";\n }\n}\n\n/** Signed in, but not allowed to do this here. Maps to 403. */\nexport class ForbiddenError extends IdentityError {\n readonly siteId: string;\n readonly required: string;\n readonly actual: string | null;\n\n constructor(siteId: string, required: string, actual: string | null) {\n super(`Requires ${required} on site \"${siteId}\" (you are ${actual ?? \"not a member\"})`);\n this.name = \"ForbiddenError\";\n this.siteId = siteId;\n this.required = required;\n this.actual = actual;\n }\n}\n","/**\n * getCurrentUser — who is signed in, verified against the auth server.\n *\n * `getUser()` round-trips to Supabase and validates the JWT; `getSession()`\n * only decodes the cookie and is not trustworthy on the server. Always this.\n */\n\nimport type { IdentityClient } from \"./client\";\nimport type { IdentityUser } from \"./types\";\n\nexport async function getCurrentUser(client: IdentityClient): Promise<IdentityUser | null> {\n const { data, error } = await client.auth.getUser();\n if (error || !data.user) return null;\n return { id: data.user.id, email: data.user.email ?? null };\n}\n","/**\n * Types for the identity layer. All config arrives as arguments — never env.\n */\n\n/**\n * Either cookie-store shape a host can hand us:\n * - @supabase/ssr's CookieMethodsServer: { getAll, setAll }\n * - Next's `await cookies()` store: { getAll, set }\n * `setAll` is preferred when present; otherwise each cookie goes through `set`.\n */\nexport interface CookieStore {\n getAll(): { name: string; value: string }[] | Promise<{ name: string; value: string }[]>;\n setAll?(cookies: { name: string; value: string; options?: Record<string, unknown> }[]): void | Promise<void>;\n set?(name: string, value: string, options?: Record<string, unknown>): unknown;\n}\n\n/** Enough to read the signed-in user with the anon key + their cookies. */\nexport interface IdentityContext {\n url: string;\n anonKey: string;\n cookies: CookieStore;\n}\n\n/** Server-only. The service-role key bypasses RLS; the module checks roles in code first. */\nexport interface ServiceContext {\n url: string;\n serviceRoleKey: string;\n}\n\nexport type SiteRole = \"staff\" | \"owner\" | \"editor\";\n\nexport const ROLE_RANK: Record<SiteRole, number> = { editor: 1, owner: 2, staff: 3 };\n\nexport interface IdentityUser {\n id: string;\n email: string | null;\n}\n\nexport interface SiteMembership {\n userId: string;\n siteId: string;\n role: \"owner\" | \"editor\";\n}\n","/**\n * Role resolution and the request gate.\n *\n * Two selects on the caller's OWN rows — both permitted by RLS with the anon\n * key, so this never needs the service role. Staff wins over any site role.\n */\n\nimport type { IdentityClient } from \"./client\";\nimport { ForbiddenError, UnauthenticatedError } from \"./errors\";\nimport { getCurrentUser } from \"./session\";\nimport { ROLE_RANK, type IdentityUser, type SiteRole } from \"./types\";\n\nexport async function getSiteRole(client: IdentityClient, siteId: string, userId?: string): Promise<SiteRole | null> {\n const uid = userId ?? (await getCurrentUser(client))?.id;\n if (!uid) return null;\n\n const [staff, member] = await Promise.all([\n client.from(\"staff\").select(\"user_id\").eq(\"user_id\", uid).maybeSingle(),\n client.from(\"site_users\").select(\"role\").eq(\"user_id\", uid).eq(\"site_id\", siteId).maybeSingle(),\n ]);\n\n if (staff.error) throw staff.error;\n if (member.error) throw member.error;\n\n if (staff.data) return \"staff\";\n const role = (member.data as { role?: string } | null)?.role;\n return role === \"owner\" || role === \"editor\" ? role : null;\n}\n\nexport function roleAtLeast(actual: SiteRole | null, minimum: SiteRole): boolean {\n return actual !== null && ROLE_RANK[actual] >= ROLE_RANK[minimum];\n}\n\nexport interface RequireOptions {\n /** Default \"editor\" — any member of the site. */\n minimumRole?: SiteRole;\n}\n\n/**\n * The gate. Throws UnauthenticatedError (→ sign in) or ForbiddenError (→ 403);\n * otherwise returns the user and their effective role for this site.\n */\nexport async function requireSiteUser(\n client: IdentityClient,\n siteId: string,\n opts: RequireOptions = {},\n): Promise<{ user: IdentityUser; role: SiteRole }> {\n const user = await getCurrentUser(client);\n if (!user) throw new UnauthenticatedError();\n\n const minimum = opts.minimumRole ?? \"editor\";\n const role = await getSiteRole(client, siteId, user.id);\n if (!roleAtLeast(role, minimum)) throw new ForbiddenError(siteId, minimum, role);\n\n return { user, role: role as SiteRole };\n}\n","/**\n * Per-request plumbing: the identity client bound to this request's cookies,\n * and the gate every page and action calls first.\n */\n\nimport { redirect } from \"next/navigation\";\nimport { createIdentityClient, type IdentityClient } from \"../auth/client\";\nimport { requireSiteUser } from \"../auth/roles\";\nimport { ForbiddenError, UnauthenticatedError } from \"../auth/errors\";\nimport type { RequireOptions, Session, StudioConfig } from \"./types\";\n\nexport interface RequestContext {\n identityClient: () => Promise<IdentityClient>;\n /**\n * Redirects to /admin/sign-in when nobody is signed in; throws ForbiddenError\n * when the role is too low so the layout can render \"no access\".\n */\n requireAdmin: (opts?: RequireOptions) => Promise<Session>;\n}\n\nexport function makeContext(config: StudioConfig): RequestContext {\n const identityClient = async (): Promise<IdentityClient> => {\n const store = await config.cookies();\n return createIdentityClient({ ...config.env().identity, cookies: store });\n };\n const requireAdmin = async (opts: RequireOptions = {}): Promise<Session> => {\n try {\n return await requireSiteUser(await identityClient(), config.env().siteId, opts);\n } catch (err) {\n if (err instanceof UnauthenticatedError) redirect(\"/admin/sign-in\");\n if (err instanceof ForbiddenError) throw err;\n throw err;\n }\n };\n return { identityClient, requireAdmin };\n}\n","/**\n * Type-aware lookups over the site's registry: which type owns a path, where an\n * item lives on the public site, where its pictures go.\n */\n\nimport type { ContentTypeEntry } from \"../forms/types\";\nimport type { StudioConfig } from \"./types\";\n\nexport interface Located { typeId: string; slug: string; entry: ContentTypeEntry }\n\nexport function makeRegistry(config: Pick<StudioConfig, \"contentTypes\" | \"publicUrls\">) {\n const entries = Object.values(config.contentTypes);\n\n const entry = (typeId: string): ContentTypeEntry | null => config.contentTypes[typeId] ?? null;\n\n /** File name → slug. Blog-style names by default; date-prefixed types supply slugFromFilename. */\n const slugOf = (e: ContentTypeEntry, fileName: string): string | null => {\n if (e.slugFromFilename) return e.slugFromFilename(fileName);\n return fileName.endsWith(\".mdx\") ? fileName.slice(0, -4) : null;\n };\n\n /** content/speaking/x.mdx → { typeId: \"speaking\", slug: \"x\" }. */\n const locate = (path: string): Located | null => {\n for (const e of entries) {\n if (!path.startsWith(`${e.folder}/`)) continue;\n const slug = slugOf(e, path.slice(e.folder.length + 1));\n if (slug) return { typeId: e.id, slug, entry: e };\n }\n return null;\n };\n\n const publicUrlFor = (typeId: string, slug: string): string | null => config.publicUrls?.[typeId]?.(slug) ?? null;\n\n /** Pictures live under public/<last folder segment>/ — content/blog → /blog/. */\n const publicDirFor = (typeId: string): string => {\n const e = entry(typeId);\n return `/${e?.folder.split(\"/\").filter(Boolean).pop() ?? \"images\"}/`;\n };\n\n return { entries, entry, slugOf, locate, publicUrlFor, publicDirFor };\n}\n\nexport type Registry = ReturnType<typeof makeRegistry>;\n","/**\n * Typed errors — so ADMIN-04 can `instanceof` rather than string-match.\n *\n * Each carries enough to log usefully without ever including the token.\n */\n\n/** Any non-2xx from GitHub that is not one of the more specific cases below. */\nexport class GitHubError extends Error {\n readonly status: number;\n readonly path: string;\n readonly body: unknown;\n\n constructor(message: string, opts: { status: number; path: string; body: unknown }) {\n super(message);\n this.name = \"GitHubError\";\n this.status = opts.status;\n this.path = opts.path;\n this.body = opts.body;\n }\n}\n\n/**\n * The pull request cannot merge because `main` moved underneath it in a way\n * that conflicts — someone else edited the same file first.\n *\n * Observed in the probe: a stale base sha does NOT fail the trees write. Tree,\n * commit, ref and PR all succeed; the conflict only shows as\n * `mergeable_state: \"dirty\"` and then a 405 \"Pull Request has merge conflicts\"\n * on merge. So this is raised from mergePullRequest, never from writeFiles.\n * The recovery is the caller's: re-read main, rebuild the change, open a new PR.\n */\nexport class StaleBaseError extends GitHubError {\n readonly pullNumber: number;\n\n constructor(pullNumber: number, opts: { status: number; path: string; body: unknown }) {\n super(`Pull request #${pullNumber} conflicts with the base branch`, opts);\n this.name = \"StaleBaseError\";\n this.pullNumber = pullNumber;\n }\n}\n\n/**\n * The token cannot do what was asked. A 403 from GitHub with a fine-grained PAT\n * almost always means a permission was not granted when the token was made —\n * a setup bug at onboarding, not a runtime condition.\n */\nexport class TokenScopeError extends GitHubError {\n static readonly REQUIRED_PERMISSIONS =\n \"Contents: Read and write, Pull requests: Read and write, Commit statuses: Read-only\";\n\n constructor(opts: { status: number; path: string; body: unknown }) {\n super(\n `GitHub refused ${opts.path} (${opts.status}). The repo token needs these fine-grained permissions: ${TokenScopeError.REQUIRED_PERMISSIONS}`,\n opts,\n );\n this.name = \"TokenScopeError\";\n }\n}\n\n/** mergePullRequest was asked to merge while checks are red. */\nexport class ChecksFailedError extends Error {\n readonly pullNumber: number;\n readonly failingCheck: string | null;\n\n constructor(pullNumber: number, failingCheck: string | null) {\n super(\n `Pull request #${pullNumber} has failing checks${failingCheck ? ` (${failingCheck})` : \"\"}`,\n );\n this.name = \"ChecksFailedError\";\n this.pullNumber = pullNumber;\n this.failingCheck = failingCheck;\n }\n}\n","/**\n * The one place that talks to api.github.com.\n *\n * ── Every call is bounded ────────────────────────────────────────────────────\n * Same pattern as 5degrees-website's HighLevel client: a module constant plus\n * AbortSignal.timeout on every fetch. That fix exists because a slow upstream\n * ran past the serverless function limit and the process was killed before its\n * own error handler could run. A publish is ~10 sequential GitHub calls, so the\n * same failure is available here. Observed probe latency was 200–1400 ms; 10 s\n * is generous, and if GitHub is slower than that we want the error, not the wait.\n *\n * ── No module state ──────────────────────────────────────────────────────────\n * The token arrives in RepoContext on every call. Nothing is read from\n * process.env here or anywhere in src/git (BUILD-ENV law).\n */\n\nimport type { RepoContext } from \"./types\";\nimport { GitHubError, TokenScopeError } from \"./errors\";\n\nconst API = \"https://api.github.com\";\nexport const GITHUB_TIMEOUT_MS = 10_000;\n\nexport interface GitHubResponse<T = unknown> {\n ok: boolean;\n status: number;\n json: T;\n}\n\n/**\n * Low-level request. Returns instead of throwing on non-2xx so callers can\n * inspect the status when a \"failure\" is a meaningful answer (405 on merge,\n * 422 on a duplicate ref). Use `ghFetchOrThrow` when it is not.\n */\nexport async function ghFetch<T = unknown>(\n ctx: RepoContext,\n method: \"GET\" | \"POST\" | \"PATCH\" | \"PUT\" | \"DELETE\",\n path: string,\n body?: unknown,\n): Promise<GitHubResponse<T>> {\n const res = await fetch(API + path, {\n method,\n signal: AbortSignal.timeout(GITHUB_TIMEOUT_MS),\n headers: {\n Authorization: `Bearer ${ctx.token}`,\n Accept: \"application/vnd.github+json\",\n \"X-GitHub-Api-Version\": \"2022-11-28\",\n \"User-Agent\": \"realiizlabs-admin\",\n ...(body !== undefined ? { \"Content-Type\": \"application/json\" } : {}),\n },\n body: body !== undefined ? JSON.stringify(body) : undefined,\n });\n\n const text = await res.text();\n let json: unknown = null;\n if (text) {\n try {\n json = JSON.parse(text);\n } catch {\n json = { raw: text };\n }\n }\n return { ok: res.ok, status: res.status, json: json as T };\n}\n\n/** Same as ghFetch but a non-2xx becomes a typed error. */\nexport async function ghFetchOrThrow<T = unknown>(\n ctx: RepoContext,\n method: \"GET\" | \"POST\" | \"PATCH\" | \"PUT\" | \"DELETE\",\n path: string,\n body?: unknown,\n): Promise<T> {\n const res = await ghFetch<T>(ctx, method, path, body);\n if (!res.ok) throw toError(res, path);\n return res.json;\n}\n\nexport function toError(res: GitHubResponse, path: string): GitHubError {\n const opts = { status: res.status, path, body: res.json };\n if (res.status === 403) return new TokenScopeError(opts);\n const message =\n (res.json as { message?: string } | null)?.message ?? `GitHub ${res.status} on ${path}`;\n return new GitHubError(message, opts);\n}\n\n/** `/repos/{owner}/{repo}` prefix, built per call. */\nexport function repoPath(ctx: RepoContext): string {\n return `/repos/${encodeURIComponent(ctx.owner)}/${encodeURIComponent(ctx.repo)}`;\n}\n\nexport function baseBranch(ctx: RepoContext): string {\n return ctx.baseBranch ?? \"main\";\n}\n","/**\n * openPullRequest — the PR that CI runs on and the client eventually publishes.\n *\n * PR Law (site-starter AGENTS.md): nothing lands on main except through a PR.\n * This module never pushes to the base branch directly.\n */\n\nimport type { PullRequest, RepoContext } from \"./types\";\nimport { baseBranch, ghFetchOrThrow, repoPath } from \"./client\";\n\n/** The subset of GitHub's PR payload this module reads. Observed in the probe. */\nexport interface PullPayload {\n number: number;\n title: string;\n html_url: string;\n state: \"open\" | \"closed\";\n head: { sha: string; ref: string };\n base: { sha: string; ref: string };\n /** null while GitHub is still computing — usually the first ~2 s after creation. */\n mergeable: boolean | null;\n mergeable_state: \"unknown\" | \"clean\" | \"dirty\" | \"blocked\" | \"unstable\" | \"behind\" | \"draft\" | \"has_hooks\";\n merged: boolean;\n /** The description the publish action wrote; the studio reads the file path back out of it. */\n body?: string | null;\n /** Set once merged. */\n merge_commit_sha?: string | null;\n}\n\nexport async function openPullRequest(\n ctx: RepoContext,\n branch: string,\n opts: { title: string; body?: string },\n): Promise<PullRequest> {\n const pr = await ghFetchOrThrow<PullPayload>(ctx, \"POST\", `${repoPath(ctx)}/pulls`, {\n title: opts.title,\n head: branch,\n base: baseBranch(ctx),\n body: opts.body ?? \"\",\n });\n\n return { number: pr.number, html_url: pr.html_url, headSha: pr.head.sha, branch };\n}\n\n/** Live read of a PR — the source of truth for mergeability. */\nexport async function getPullRequest(ctx: RepoContext, number: number): Promise<PullPayload> {\n return ghFetchOrThrow<PullPayload>(ctx, \"GET\", `${repoPath(ctx)}/pulls/${number}`);\n}\n\nexport interface OpenPullRequest extends PullRequest {\n title: string;\n}\n\n/**\n * Open PRs whose head branch starts with `headPrefix` — the dashboard's own\n * in-flight changes (04b names them `admin/{type}/{file}-{stamp}`). One page of\n * 100 is far more than a content site ever has open at once.\n */\nexport async function listOpenPullRequests(ctx: RepoContext, opts: { headPrefix: string }): Promise<OpenPullRequest[]> {\n const prs = await ghFetchOrThrow<PullPayload[]>(ctx, \"GET\", `${repoPath(ctx)}/pulls?state=open&per_page=100`);\n return prs\n .filter((p) => p.head.ref.startsWith(opts.headPrefix))\n .map((p) => ({ number: p.number, title: p.title, html_url: p.html_url, headSha: p.head.sha, branch: p.head.ref }));\n}\n\n/**\n * Close a PR without merging — the client changed their mind. The branch is\n * the caller's to delete (deleteBranch) once the close succeeds; closing first\n * means a failed delete leaves a closed PR, never an open one pointing at nothing.\n */\nexport async function closePullRequest(ctx: RepoContext, number: number): Promise<void> {\n await ghFetchOrThrow<PullPayload>(ctx, \"PATCH\", `${repoPath(ctx)}/pulls/${number}`, { state: \"closed\" });\n}\n","/**\n * getPullRequestStatus — green, red or pending. Nothing else.\n *\n * ── Why not the check-runs endpoint ──────────────────────────────────────────\n * A fine-grained PAT cannot read it. Observed 403 on every probe run, and the\n * token permission picker has no \"Checks\" entry to grant. So status is derived\n * from two things a PAT can always read:\n *\n * 1. the PR's `mergeable_state`, which folds in required checks when branch\n * protection is on;\n * 2. the combined commit status for the head sha, which is where Vercel and\n * any status-based CI report — and the only place a failing check has a\n * name.\n *\n * The accepted limitation: a GitHub Actions failure surfaces only as\n * `blocked`/`unstable`, not by job name. That is red without a name.\n *\n * ── Two traps, both observed ─────────────────────────────────────────────────\n * `mergeable` is null and `mergeable_state` is \"unknown\" for ~2 s after a PR is\n * created. That is pending, never red.\n *\n * The combined status of ZERO statuses has `state: \"pending\"`, not \"success\".\n * A no-CI repo read naively would be pending forever. So `total_count` is\n * checked before `state`.\n */\n\nimport type { PullRequestStatus, RepoContext } from \"./types\";\nimport { ghFetch, ghFetchOrThrow, repoPath } from \"./client\";\nimport { getPullRequest } from \"./pulls\";\n\n/** Observed shape of GET /commits/{sha}/status. */\nexport interface CombinedStatus {\n state: \"success\" | \"failure\" | \"pending\" | \"error\";\n total_count: number;\n statuses: Array<{ context: string; state: string; description: string | null; target_url?: string | null }>;\n}\n\nexport async function getPullRequestStatus(\n ctx: RepoContext,\n number: number,\n log: Pick<Console, \"warn\"> = console,\n): Promise<PullRequestStatus> {\n const pr = await getPullRequest(ctx, number);\n\n if (pr.mergeable === null || pr.mergeable_state === \"unknown\") {\n return { state: \"pending\" };\n }\n\n const combined = await ghFetchOrThrow<CombinedStatus>(\n ctx,\n \"GET\",\n `${repoPath(ctx)}/commits/${pr.head.sha}/status`,\n );\n\n const failing = combined.statuses.find((s) => s.state === \"failure\" || s.state === \"error\");\n\n // dirty is a conflict, not a check failure — mergePullRequest turns it into\n // StaleBaseError. Report it as red here so a poller stops polling.\n if (pr.mergeable_state === \"dirty\") {\n return { state: \"red\", failingCheck: failing?.context ?? \"merge conflict\" };\n }\n\n if (failing || pr.mergeable_state === \"unstable\") {\n return { state: \"red\", failingCheck: failing?.context ?? null };\n }\n\n if (combined.total_count === 0) {\n if (pr.mergeable_state === \"clean\" || pr.mergeable_state === \"behind\") {\n const warning = `[admin/git] ${ctx.owner}/${ctx.repo} has no CI statuses on PR #${number} — treating as green. A client site with no CI is a setup bug.`;\n log.warn(warning);\n return { state: \"green\", warning };\n }\n // blocked with nothing reported yet: required checks have not started.\n return { state: \"pending\" };\n }\n\n if (combined.state === \"success\" && pr.mergeable_state !== \"blocked\") {\n const previewUrl = await previewUrlFor(ctx, pr.head.sha, combined);\n return previewUrl ? { state: \"green\", previewUrl } : { state: \"green\" };\n }\n\n return { state: \"pending\" };\n}\n\n/** Observed shape of GET /deployments and /deployments/{id}/statuses (only what we read). */\ninterface Deployment { id: number; environment: string }\ninterface DeploymentStatus { state: string; environment_url?: string | null }\n\n/** Dashboard pages, not sites — Vercel's commit status points at its inspector, which 404s for anyone else. */\nconst DASHBOARD_HOST = /^https:\\/\\/(www\\.)?(vercel\\.com|app\\.netlify\\.com)\\//i;\n\n/**\n * The preview site's URL, so the client can look before publishing.\n *\n * Preferred source: the GitHub Deployments API, where Vercel/Netlify record the\n * preview hostname as `environment_url`. Needs \"Deployments: read\" on the PAT;\n * a 403 just means no preview link. Fallback: a deploy-ish commit status whose\n * `target_url` is a real site (Vercel's is its dashboard, so it is skipped).\n */\nasync function previewUrlFor(ctx: RepoContext, sha: string, combined: CombinedStatus): Promise<string | null> {\n const deployments = await ghFetch<Deployment[]>(ctx, \"GET\", `${repoPath(ctx)}/deployments?sha=${sha}&per_page=10`);\n if (deployments.ok && Array.isArray(deployments.json)) {\n for (const d of deployments.json.filter((d) => !/^prod/i.test(d.environment))) {\n const statuses = await ghFetch<DeploymentStatus[]>(ctx, \"GET\", `${repoPath(ctx)}/deployments/${d.id}/statuses?per_page=10`);\n if (!statuses.ok || !Array.isArray(statuses.json)) continue;\n const live = statuses.json.find((s) => s.state === \"success\" && s.environment_url && !DASHBOARD_HOST.test(s.environment_url));\n if (live?.environment_url) return live.environment_url;\n }\n }\n const status = combined.statuses.find(\n (s) => s.state === \"success\" && /vercel|netlify|deploy|preview/i.test(s.context) && s.target_url && !DASHBOARD_HOST.test(s.target_url),\n );\n return status?.target_url ?? null;\n}\n","/**\n * The dashboard's own in-flight changes: open PRs on `admin/*` branches, keyed\n * by the file they change. The branch name — `admin/{typeId}/{fileBase}-{stamp}`\n * — is the index, so no extra call per PR is needed. One open change per file;\n * if two ever exist the newest wins here and the older is left alone on GitHub.\n */\n\nimport { getPullRequestStatus } from \"../git/status\";\nimport { listOpenPullRequests } from \"../git/pulls\";\nimport type { RepoConfig, StudioConfig } from \"./types\";\nimport type { Registry } from \"./registry\";\n\nexport type PendingState = \"checking\" | \"ready\" | \"failed\";\n\nexport interface PendingChange {\n number: number;\n branch: string;\n title: string;\n html_url: string;\n path: string;\n typeId: string;\n state: PendingState;\n failingCheck: string | null;\n /** The change removes the item rather than editing it. */\n removal: boolean;\n}\n\nconst BRANCH_RE = /^admin\\/([a-z0-9-]+)\\/(.+)-\\d{8}T\\d{3,6}$/;\n\nexport function makePending(config: StudioConfig, registry: Registry) {\n const repo = (): RepoConfig => config.env().repo;\n\n const listPendingChanges = async (): Promise<Map<string, PendingChange>> => {\n const ctx = repo();\n const prs = await listOpenPullRequests(ctx, { headPrefix: \"admin/\" });\n const out = new Map<string, PendingChange>();\n const resolved = await Promise.all(\n prs.map(async (pr) => {\n const m = BRANCH_RE.exec(pr.branch);\n if (!m) return null;\n const entry = registry.entry(m[1]);\n if (!entry) return null;\n const path = `${entry.folder}/${m[2]}.mdx`;\n const status = await getPullRequestStatus(ctx, pr.number);\n const state: PendingState = status.state === \"green\" ? \"ready\" : status.state === \"red\" ? \"failed\" : \"checking\";\n return {\n number: pr.number,\n branch: pr.branch,\n title: pr.title.replace(/^(Publish|Remove):\\s*/, \"\"),\n removal: pr.title.startsWith(\"Remove: \"),\n html_url: pr.html_url,\n path,\n typeId: entry.id,\n state,\n failingCheck: status.state === \"red\" ? status.failingCheck : null,\n } satisfies PendingChange;\n }),\n );\n for (const p of resolved) {\n if (!p) continue;\n const prev = out.get(p.path);\n if (!prev || p.number > prev.number) out.set(p.path, p);\n }\n return out;\n };\n\n const pendingFor = async (path: string): Promise<PendingChange | null> => (await listPendingChanges()).get(path) ?? null;\n\n return { listPendingChanges, pendingFor };\n}\n\nexport const pendingLabel: Record<PendingState, string> = {\n checking: \"Checking…\",\n ready: \"Ready to publish\",\n failed: \"Needs fixing\",\n};\n\nexport function pendingText(p: PendingChange): string {\n if (p.removal) return p.state === \"ready\" ? \"Removal ready\" : p.state === \"failed\" ? \"Removal needs fixing\" : \"Removing…\";\n return pendingLabel[p.state];\n}\n","/**\n * Read helpers — list a folder, open a file — straight from the repo at call time.\n *\n * The dashboard lists and opens content from `main` via the Contents API, never\n * from the deployed filesystem: Vercel's bundle only contains what the tracer\n * saw, and it is a snapshot of the last deploy rather than of the repo. This\n * is also how hand-written files (github.com, Desktop, Cowork) show up — the\n * dashboard never assumes it authored anything.\n */\n\nimport type { RepoContext } from \"./types\";\nimport { baseBranch, ghFetch, repoPath, toError } from \"./client\";\nimport { GitHubError } from \"./errors\";\n\nexport interface RepoEntry {\n name: string;\n path: string;\n sha: string;\n size: number;\n type: \"file\";\n}\n\nexport interface RepoFile {\n path: string;\n sha: string;\n content: string;\n}\n\nexport class NotFoundError extends GitHubError {\n constructor(path: string) {\n super(`Not found in repo: ${path}`, { status: 404, path, body: null });\n this.name = \"NotFoundError\";\n }\n}\n\ninterface ContentsEntry {\n name: string;\n path: string;\n sha: string;\n size: number;\n type: \"file\" | \"dir\" | \"symlink\" | \"submodule\";\n content?: string;\n encoding?: string;\n}\n\nfunction contentsPath(ctx: RepoContext, path: string, ref?: string): string {\n const clean = path.replace(/^\\/+|\\/+$/g, \"\");\n const encoded = clean.split(\"/\").map(encodeURIComponent).join(\"/\");\n return `${repoPath(ctx)}/contents/${encoded}?ref=${encodeURIComponent(ref ?? baseBranch(ctx))}`;\n}\n\n/** Files directly inside `path`, sorted by name. Missing folder → []. */\nexport async function listDirectory(ctx: RepoContext, path: string, opts: { ref?: string } = {}): Promise<RepoEntry[]> {\n const url = contentsPath(ctx, path, opts.ref);\n const res = await ghFetch<ContentsEntry[] | ContentsEntry>(ctx, \"GET\", url);\n if (res.status === 404) return [];\n if (!res.ok) throw toError(res, url);\n const list = Array.isArray(res.json) ? res.json : [];\n return list\n .filter((e) => e.type === \"file\")\n .map((e) => ({ name: e.name, path: e.path, sha: e.sha, size: e.size, type: \"file\" as const }))\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n\n/** One file, decoded to utf-8. */\nexport async function readFile(ctx: RepoContext, path: string, opts: { ref?: string } = {}): Promise<RepoFile> {\n const url = contentsPath(ctx, path, opts.ref);\n const res = await ghFetch<ContentsEntry>(ctx, \"GET\", url);\n if (res.status === 404) throw new NotFoundError(path);\n if (!res.ok) throw toError(res, url);\n const entry = res.json;\n if (Array.isArray(entry) || entry.type !== \"file\") throw new GitHubError(`${path} is not a file`, { status: res.status, path: url, body: entry });\n if (typeof entry.content !== \"string\") {\n // GitHub omits content for files over 1 MB; MDX never gets near that.\n throw new GitHubError(`${path} is too large to read through the Contents API`, { status: res.status, path: url, body: null });\n }\n const content = decodeBase64Utf8(entry.content);\n return { path: entry.path, sha: entry.sha, content };\n}\n\n/** The Contents API wraps base64 at 60 columns; strip whitespace before decoding. */\nfunction decodeBase64Utf8(b64: string): string {\n const clean = b64.replace(/\\s+/g, \"\");\n const bin = atob(clean);\n const bytes = Uint8Array.from(bin, (c) => c.charCodeAt(0));\n return new TextDecoder(\"utf-8\").decode(bytes);\n}\n","/**\n * Reads come from the repo at request time, never from the deployed filesystem.\n * The dashboard is one of four writers; it lists what is on `main` right now,\n * including files it did not author. Every reader takes a type id, so a second\n * content type needs no new code.\n */\n\nimport matter from \"gray-matter\";\nimport type { ContentTypeEntry } from \"../forms/types\";\nimport { listDirectory, readFile } from \"../git/reads\";\nimport { getPullRequest as ghGetPullRequest } from \"../git/pulls\";\nimport { getPullRequestStatus } from \"../git/status\";\nimport { GitHubError } from \"../git/errors\";\nimport type { StudioConfig } from \"./types\";\nimport type { Registry } from \"./registry\";\nimport type { PendingChange } from \"./pending\";\n\nexport interface ListItem {\n slug: string;\n path: string;\n title: string;\n /** publishedAt, falling back to date — ISO string, or null when the file has neither. */\n date: string | null;\n /** True when the frontmatter did not parse cleanly — still listed, still openable. */\n needsAttention: boolean;\n pending: PendingChange | null;\n /** The file exists only in a pending change — nothing on the live site yet. */\n isNew: boolean;\n}\n\nexport interface PrSummary {\n number: number;\n title: string;\n html_url: string;\n merged: boolean;\n state: \"open\" | \"closed\";\n /** Parsed from the PR body the publish action wrote, when present. */\n postPath: string | null;\n branch: string;\n removal: boolean;\n /** The commit that landed on main when this was published; null until then. */\n mergeCommitSha: string | null;\n}\n\n/** Thrown when no file in the folder maps to the slug — the page turns it into a 404. */\nexport class NotHere extends Error {\n constructor(slug: string) { super(`No item with the web address \"${slug}\".`); this.name = \"NotHere\"; }\n}\n\nconst LIST_CAP = 50;\nconst isItem = (name: string) => name.endsWith(\".mdx\") && !name.startsWith(\"_\");\n\nfunction dateOf(data: Record<string, unknown>): string | null {\n const raw = data.publishedAt ?? data.date;\n if (!raw) return null;\n const d = new Date(raw as string);\n return Number.isNaN(d.getTime()) ? null : d.toISOString();\n}\n\nexport function makeReaders(config: StudioConfig, registry: Registry, pending: { listPendingChanges: () => Promise<Map<string, PendingChange>> }) {\n const repo = () => config.env().repo;\n const need = (typeId: string): ContentTypeEntry => {\n const e = registry.entry(typeId);\n if (!e) throw new Error(`Unknown content type \"${typeId}\"`);\n return e;\n };\n\n /** Slug → repo path; scans the folder when the type names files by date. */\n const pathOf = async (typeId: string, slug: string): Promise<string | null> => {\n const e = need(typeId);\n if (!e.slugFromFilename) return `${e.folder}/${slug}.mdx`;\n const entries = await listDirectory(repo(), e.folder);\n return entries.find((x) => registry.slugOf(e, x.name) === slug)?.path ?? null;\n };\n\n const listItems = async (typeId: string): Promise<ListItem[]> => {\n const e = need(typeId);\n const ctx = repo();\n const [entries, open] = await Promise.all([\n listDirectory(ctx, e.folder).then((all) => all.filter((x) => isItem(x.name))),\n pending.listPendingChanges(),\n ]);\n const describe = async (path: string, ref: string | undefined, extra: Pick<ListItem, \"pending\" | \"isNew\">): Promise<ListItem> => {\n const fileName = path.slice(e.folder.length + 1);\n const slug = registry.slugOf(e, fileName) ?? fileName.replace(/\\.mdx$/, \"\");\n try {\n const file = await readFile(ctx, path, ref ? { ref } : {});\n const { data } = matter(file.content);\n return {\n slug, path,\n title: typeof data.title === \"string\" && data.title ? data.title : slug,\n date: dateOf(data),\n needsAttention: !e.schema.safeParse(data).success,\n ...extra,\n };\n } catch {\n return { slug, path, title: slug, date: null, needsAttention: true, ...extra };\n }\n };\n const live = await Promise.all(entries.slice(0, LIST_CAP).map((x) => describe(x.path, undefined, { pending: open.get(x.path) ?? null, isNew: false })));\n const livePaths = new Set(entries.map((x) => x.path));\n const onlyPending = await Promise.all(\n [...open.values()].filter((p) => p.typeId === e.id && !livePaths.has(p.path)).map((p) => describe(p.path, p.branch, { pending: p, isNew: true })),\n );\n return [...onlyPending, ...live].sort((a, b) => (a.isNew !== b.isNew ? (a.isNew ? -1 : 1) : (b.date ?? \"\").localeCompare(a.date ?? \"\")));\n };\n\n const countItems = async (typeId: string): Promise<number> => {\n const entries = await listDirectory(repo(), need(typeId).folder);\n return entries.filter((x) => isItem(x.name)).length;\n };\n\n const readItem = async (typeId: string, slug: string, opts: { ref?: string } = {}) => {\n const path = await pathOf(typeId, slug);\n if (!path) throw new NotHere(slug);\n const file = await readFile(repo(), path, opts.ref ? { ref: opts.ref } : {});\n const { data, content } = matter(file.content);\n return { frontmatter: data as Record<string, unknown>, body: content.trim(), sha: file.sha, path };\n };\n\n /** The author of the most recent item — the default for a new one; null when the type has no author. */\n const lastAuthor = async (typeId: string): Promise<string | null> => {\n for (const p of await listItems(typeId)) {\n if (p.isNew) continue;\n try {\n const { frontmatter } = await readItem(typeId, p.slug);\n if (typeof frontmatter.author === \"string\" && frontmatter.author) return frontmatter.author;\n } catch { /* try the next one */ }\n }\n return null;\n };\n\n const getPullRequest = async (number: number): Promise<PrSummary | null> => {\n try {\n const pr = await ghGetPullRequest(repo(), number);\n const body = pr.body ?? \"\";\n return {\n number: pr.number, title: pr.title, html_url: pr.html_url, merged: pr.merged, state: pr.state,\n postPath: body.match(/File: `([^`]+)`/)?.[1] ?? null,\n branch: pr.head.ref,\n removal: /^Action: remove$/m.test(body) || pr.title.startsWith(\"Remove: \"),\n mergeCommitSha: pr.merged ? (pr.merge_commit_sha ?? null) : null,\n };\n } catch (err) {\n if (err instanceof GitHubError && err.status === 404) return null;\n throw err;\n }\n };\n\n const prStatus = (number: number) => getPullRequestStatus(repo(), number);\n\n return { pathOf, listItems, countItems, readItem, lastAuthor, getPullRequest, prStatus };\n}\n\nexport type Readers = ReturnType<typeof makeReaders>;\n","/**\n * createBranch — a new branch off the base branch, as it is RIGHT NOW.\n *\n * The base sha is fetched from the refs API on every call and never stored.\n * This module is one of four writers to the same repo (github.com, GitHub\n * Desktop, Cowork are the others), so a ref that was current a minute ago is\n * routinely stale. Branching from a cached sha would silently build on old\n * content.\n */\n\nimport type { CreateBranchResult, RepoContext } from \"./types\";\nimport { baseBranch, ghFetchOrThrow, repoPath } from \"./client\";\n\ninterface RefResponse {\n ref: string;\n object: { sha: string; type: string };\n}\n\n/** Read the current tip of a branch. Always a live call. */\nexport async function getBranchSha(ctx: RepoContext, branch: string): Promise<string> {\n const ref = await ghFetchOrThrow<RefResponse>(\n ctx,\n \"GET\",\n `${repoPath(ctx)}/git/ref/heads/${encodeURIComponent(branch)}`,\n );\n return ref.object.sha;\n}\n\nexport async function createBranch(\n ctx: RepoContext,\n branch: string,\n): Promise<CreateBranchResult> {\n const baseSha = await getBranchSha(ctx, baseBranch(ctx));\n\n await ghFetchOrThrow<RefResponse>(ctx, \"POST\", `${repoPath(ctx)}/git/refs`, {\n ref: `refs/heads/${branch}`,\n sha: baseSha,\n });\n\n return { branch, baseSha };\n}\n\n/**\n * Remove a branch. 204 on success. Used after a squash merge so the client's\n * repo does not accumulate one dead branch per publish.\n */\nexport async function deleteBranch(ctx: RepoContext, branch: string): Promise<void> {\n await ghFetchOrThrow(\n ctx,\n \"DELETE\",\n `${repoPath(ctx)}/git/refs/heads/${encodeURIComponent(branch)}`,\n );\n}\n","/**\n * writeFiles — one or more files in ONE commit on an existing branch.\n *\n * Why the trees API and not the Contents API: a post is an MDX file plus a\n * hero image. Two Contents calls make two commits, and the first triggers a\n * build of a half-finished state. One tree, one commit.\n *\n * Encoding rule, observed in the probe: a tree entry can inline utf-8 text as\n * `content`, but has no `encoding` field — a binary must be uploaded first via\n * POST /git/blobs with `encoding: \"base64\"` and referenced in the tree by sha.\n * So a two-file publish with one image is six calls, not five.\n *\n * `opts.remove` deletes paths in the same commit (tree entry with `sha: null`) —\n * how the dashboard takes a post down: one PR that removes the file.\n */\n\nimport type { FileInput, RepoContext, WriteFilesResult } from \"./types\";\nimport { getBranchSha } from \"./branch\";\nimport { ghFetchOrThrow, repoPath } from \"./client\";\n\ntype TreeEntry =\n | { path: string; mode: \"100644\"; type: \"blob\"; content: string }\n | { path: string; mode: \"100644\"; type: \"blob\"; sha: string }\n /* sha: null in a tree entry deletes the path — GitHub's documented way to remove a file via the trees API. */\n | { path: string; mode: \"100644\"; type: \"blob\"; sha: null };\n\nexport async function writeFiles(\n ctx: RepoContext,\n branch: string,\n files: FileInput[],\n message: string,\n opts: { remove?: string[] } = {},\n): Promise<WriteFilesResult> {\n const remove = opts.remove ?? [];\n if (files.length === 0 && remove.length === 0) throw new Error(\"writeFiles: no files given\");\n\n const base = repoPath(ctx);\n\n // The branch tip as of now — not the sha createBranch returned earlier.\n const parentSha = await getBranchSha(ctx, branch);\n\n // Binary files become blobs first; text is inlined.\n const tree: TreeEntry[] = [];\n for (const file of files) {\n if (file.encoding === \"base64\") {\n const blob = await ghFetchOrThrow<{ sha: string }>(ctx, \"POST\", `${base}/git/blobs`, {\n content: file.content,\n encoding: \"base64\",\n });\n tree.push({ path: file.path, mode: \"100644\", type: \"blob\", sha: blob.sha });\n } else {\n tree.push({ path: file.path, mode: \"100644\", type: \"blob\", content: file.content });\n }\n }\n\n for (const path of remove) tree.push({ path, mode: \"100644\", type: \"blob\", sha: null });\n\n const newTree = await ghFetchOrThrow<{ sha: string }>(ctx, \"POST\", `${base}/git/trees`, {\n base_tree: parentSha,\n tree,\n });\n\n const commit = await ghFetchOrThrow<{ sha: string }>(ctx, \"POST\", `${base}/git/commits`, {\n message,\n tree: newTree.sha,\n parents: [parentSha],\n });\n\n // Fast-forward the branch onto the new commit. `force: false` means a\n // concurrent write to this same branch surfaces as a 422 \"Update is not a\n // fast forward\" rather than being silently overwritten.\n await ghFetchOrThrow(\n ctx,\n \"PATCH\",\n `${base}/git/refs/heads/${encodeURIComponent(branch)}`,\n { sha: commit.sha, force: false },\n );\n\n return { branch, commitSha: commit.sha, treeSha: newTree.sha, fileCount: files.length + remove.length };\n}\n","/**\n * Server-side checks on the pictures a save carries. Pure.\n *\n * The browser already shrank them, but anyone can POST to a server action, so\n * the path, type and size are re-checked before anything is committed: only\n * WebP under the type's public folder, ≤ 800 KB each, ≤ 3.5 MB per save.\n * Frontmatter paths are URL paths (/blog/x.webp); the repo file lives under public/.\n */\n\nexport interface ImagePayload {\n /** URL path as written in the frontmatter or body, e.g. /blog/my-post.webp. */\n path: string;\n /** Base64 of the WebP bytes. */\n base64: string;\n}\n\nexport interface ImageLimits {\n maxEach: number;\n maxTotal: number;\n /** URL prefix pictures must live under. */\n prefix: string;\n}\n\nexport const IMAGE_LIMITS: ImageLimits = { maxEach: 800 * 1024, maxTotal: 3.5 * 1024 * 1024, prefix: \"/blog/\" };\n\nexport const IMAGE_ERRORS = {\n path: \"That image path isn’t allowed.\",\n size: \"That picture is too large to send — try a smaller one.\",\n} as const;\n\nexport type ValidatedImages =\n | { ok: true; files: { path: string; content: string; encoding: \"base64\" }[] }\n | { ok: false; error: string };\n\nconst SAFE_PATH = /^[a-z0-9][a-z0-9/_-]*\\.webp$/;\n\n/** Bytes a base64 string decodes to, without decoding it. */\nexport function decodedSize(b64: string): number {\n const clean = b64.replace(/\\s+/g, \"\");\n const pad = clean.endsWith(\"==\") ? 2 : clean.endsWith(\"=\") ? 1 : 0;\n return Math.floor((clean.length * 3) / 4) - pad;\n}\n\nexport function validateImages(images: ImagePayload[], limits: ImageLimits = IMAGE_LIMITS): ValidatedImages {\n let total = 0;\n const files: { path: string; content: string; encoding: \"base64\" }[] = [];\n for (const img of images) {\n if (typeof img?.path !== \"string\" || typeof img?.base64 !== \"string\") return { ok: false, error: IMAGE_ERRORS.path };\n if (!img.path.startsWith(limits.prefix) || img.path.includes(\"..\")) return { ok: false, error: IMAGE_ERRORS.path };\n const rel = img.path.slice(1);\n if (!SAFE_PATH.test(rel)) return { ok: false, error: IMAGE_ERRORS.path };\n const size = decodedSize(img.base64);\n if (size === 0 || size > limits.maxEach) return { ok: false, error: IMAGE_ERRORS.size };\n total += size;\n if (total > limits.maxTotal) return { ok: false, error: IMAGE_ERRORS.size };\n files.push({ path: `public/${rel}`, content: img.base64.replace(/\\s+/g, \"\"), encoding: \"base64\" });\n }\n return { ok: true, files };\n}\n","/**\n * Publish and remove: validated submission → one commit on a new branch → PR.\n * The branch is cut from `main` as it is at this moment and named with a stamp\n * so two edits of one file never collide. Nothing goes to main directly (PR Law).\n */\n\nimport matter from \"gray-matter\";\nimport { redirect } from \"next/navigation\";\nimport { createBranch } from \"../git/branch\";\nimport { writeFiles } from \"../git/files\";\nimport { openPullRequest } from \"../git/pulls\";\nimport { IMAGE_LIMITS, validateImages, type ImagePayload } from \"./images\";\nimport type { StudioConfig } from \"./types\";\nimport type { Registry } from \"./registry\";\nimport type { RequestContext } from \"./context\";\nimport type { Readers } from \"./readers\";\n\nexport interface PublishInput {\n type: string;\n frontmatter: Record<string, unknown>;\n body: string;\n /** An open change for this file: save onto ITS branch so the same PR picks up the edit. */\n existing?: { number: number; branch: string } | null;\n /** Pictures chosen in this session, already shrunk in the browser; committed with the MDX. */\n images?: ImagePayload[];\n}\n\nexport type PublishResult = { ok: false; error: string };\n\nconst SLUG_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\nconst stamp = () => new Date().toISOString().replace(/[-:]/g, \"\").slice(0, 13);\n\n/** Zod coerced dates to Date; the YAML in the repo uses ISO strings like every hand-written file. */\nfunction serialiseDates(fm: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(fm)) {\n if (v === undefined) continue;\n out[k] = v instanceof Date ? v.toISOString() : v;\n }\n return out;\n}\n\nexport function makePublish(config: StudioConfig, registry: Registry, ctx: RequestContext, readers: Readers) {\n const publishContent = async (input: PublishInput): Promise<PublishResult | never> => {\n const { user } = await ctx.requireAdmin();\n const entry = registry.entry(input.type);\n if (!entry) return { ok: false, error: `Unknown content type \"${input.type}\"` };\n\n const parsed = entry.schema.safeParse(input.frontmatter);\n if (!parsed.success) return { ok: false, error: parsed.error.issues.map((i) => `${i.path.join(\".\")}: ${i.message}`).join(\"; \") };\n\n const fm = serialiseDates(parsed.data as Record<string, unknown>);\n const fileName = entry.filename(fm);\n const path = `${entry.folder}/${fileName}`;\n const content = matter.stringify(`\\n${input.body.trim()}\\n`, fm);\n const title = String(fm.title ?? fileName);\n\n const pictures = validateImages(input.images ?? [], { ...IMAGE_LIMITS, prefix: registry.publicDirFor(entry.id) });\n if (!pictures.ok) return { ok: false, error: pictures.error };\n const files = [{ path, content }, ...pictures.files];\n const repo = config.env().repo;\n\n if (input.existing && (await stillOpen(input.existing.number))) {\n await writeFiles(repo, input.existing.branch, files, `Update: ${title}`);\n redirect(`/admin/pr/${input.existing.number}`);\n }\n const branch = `admin/${entry.id}/${fileName.replace(/\\.mdx$/, \"\")}-${stamp()}`;\n await createBranch(repo, branch);\n await writeFiles(repo, branch, files, `Publish: ${title}`);\n const pr = await openPullRequest(repo, branch, {\n title: `Publish: ${title}`,\n body: `Published from the dashboard by ${user.email ?? user.id}.\\n\\nFile: \\`${path}\\``,\n });\n redirect(`/admin/pr/${pr.number}`);\n };\n\n /** The PR page may be stale: someone could have published or closed the change since it loaded. */\n const stillOpen = async (number: number): Promise<boolean> => {\n try {\n const pr = await readers.getPullRequest(number);\n return Boolean(pr && pr.state === \"open\" && !pr.merged);\n } catch {\n return false;\n }\n };\n\n /** Take an item down: one PR that deletes the file. Nothing disappears until Publish. */\n const removeContent = async (input: { type: string; slug: string }): Promise<PublishResult | never> => {\n const { user } = await ctx.requireAdmin();\n const entry = registry.entry(input.type);\n if (!entry) return { ok: false, error: `Unknown content type \"${input.type}\"` };\n if (!SLUG_RE.test(input.slug)) return { ok: false, error: \"That web address isn't valid.\" };\n const path = (await readers.pathOf(input.type, input.slug)) ?? `${entry.folder}/${input.slug}.mdx`;\n const repo = config.env().repo;\n const branch = `admin/${entry.id}/${input.slug}-${stamp()}`;\n await createBranch(repo, branch);\n await writeFiles(repo, branch, [], `Remove: ${input.slug}`, { remove: [path] });\n const pr = await openPullRequest(repo, branch, {\n title: `Remove: ${input.slug}`,\n body: `Removed from the dashboard by ${user.email ?? user.id}.\\n\\nFile: \\`${path}\\`\\nAction: remove`,\n });\n redirect(`/admin/pr/${pr.number}`);\n };\n\n return { publishContent, removeContent };\n}\n","/**\n * mergePullRequest — publish. Squash, then delete the branch.\n *\n * `requireGreen` defaults to true. The whole point of the PR flow is that CI\n * catches bad frontmatter before it freezes the site; merging red automates the\n * exact failure the flow exists to prevent.\n *\n * Pending is the common case (checks are always pending right after a push),\n * so it is returned for the caller to poll — never thrown.\n */\n\nimport type { MergeResult, RepoContext } from \"./types\";\nimport { deleteBranch } from \"./branch\";\nimport { ghFetch, repoPath, toError } from \"./client\";\nimport { ChecksFailedError, StaleBaseError } from \"./errors\";\nimport { getPullRequest } from \"./pulls\";\nimport { getPullRequestStatus } from \"./status\";\n\ninterface MergeResponse {\n sha: string;\n merged: boolean;\n message: string;\n}\n\nexport interface MergeOptions {\n /** Refuse to merge unless checks are green. Default true. */\n requireGreen?: boolean;\n /** Delete the head branch after a successful merge. Default true. */\n deleteBranch?: boolean;\n /** Squash commit title. Defaults to GitHub's (the PR title + number). */\n commitTitle?: string;\n}\n\nexport async function mergePullRequest(\n ctx: RepoContext,\n number: number,\n opts: MergeOptions = {},\n): Promise<MergeResult> {\n const requireGreen = opts.requireGreen ?? true;\n const path = `${repoPath(ctx)}/pulls/${number}/merge`;\n\n if (requireGreen) {\n const status = await getPullRequestStatus(ctx, number);\n if (status.state === \"pending\") return { merged: false, state: \"pending\" };\n if (status.state === \"red\") {\n // A conflict is not a failed check — it is a stale base. Distinguish it.\n const pr = await getPullRequest(ctx, number);\n if (pr.mergeable_state === \"dirty\") {\n throw new StaleBaseError(number, { status: 0, path, body: pr });\n }\n throw new ChecksFailedError(number, status.failingCheck);\n }\n }\n\n const res = await ghFetch<MergeResponse>(ctx, \"PUT\", path, {\n merge_method: \"squash\",\n ...(opts.commitTitle ? { commit_title: opts.commitTitle } : {}),\n });\n\n if (!res.ok) {\n // Observed: 405 { message: \"Pull Request has merge conflicts\" } for a\n // stale base. Also 405 for \"not mergeable\" generally, and 409 if the head\n // sha moved between read and merge — both are the same recovery for the\n // caller (re-read, rebuild), so both map to StaleBaseError.\n if (res.status === 405 || res.status === 409) {\n throw new StaleBaseError(number, { status: res.status, path, body: res.json });\n }\n throw toError(res, path);\n }\n\n if (opts.deleteBranch ?? true) {\n const pr = await getPullRequest(ctx, number);\n await deleteBranch(ctx, pr.head.ref);\n }\n\n return { merged: true, sha: res.json.sha };\n}\n","/** The Publish button (merge when green, never otherwise) and Discard (close + delete branch). */\n\nimport { mergePullRequest } from \"../git/merge\";\nimport { closePullRequest } from \"../git/pulls\";\nimport { deleteBranch } from \"../git/branch\";\nimport { ChecksFailedError, StaleBaseError } from \"../git/errors\";\nimport type { StudioConfig } from \"./types\";\nimport type { RequestContext } from \"./context\";\nimport type { Readers } from \"./readers\";\n\nexport type MergeOutcome =\n | { state: \"merged\"; sha: string }\n | { state: \"pending\" }\n | { state: \"stale\" }\n | { state: \"red\"; failingCheck: string | null }\n | { state: \"error\"; message: string };\n\nexport type DiscardOutcome =\n | { state: \"discarded\" }\n | { state: \"already-published\" }\n | { state: \"error\"; message: string };\n\nexport function makeMerge(config: StudioConfig, ctx: RequestContext, readers: Readers) {\n const revalidate = config.revalidate ?? (() => {});\n\n const mergeContentPr = async (number: number): Promise<MergeOutcome> => {\n await ctx.requireAdmin();\n try {\n const result = await mergePullRequest(config.env().repo, number, { requireGreen: true });\n revalidate(`/admin/pr/${number}`);\n return result.merged ? { state: \"merged\", sha: result.sha } : { state: \"pending\" };\n } catch (err) {\n if (err instanceof StaleBaseError) return { state: \"stale\" };\n if (err instanceof ChecksFailedError) return { state: \"red\", failingCheck: err.failingCheck };\n return { state: \"error\", message: err instanceof Error ? err.message : String(err) };\n }\n };\n\n const discardChange = async (number: number, branch: string): Promise<DiscardOutcome> => {\n await ctx.requireAdmin();\n const repo = config.env().repo;\n try {\n const pr = await readers.getPullRequest(number);\n if (pr?.merged) return { state: \"already-published\" };\n if (pr && pr.state === \"open\") await closePullRequest(repo, number);\n // Only ever delete the dashboard's own branches; a failed delete leaves a closed PR, which is fine.\n if (branch.startsWith(\"admin/\")) {\n try { await deleteBranch(repo, branch); } catch { /* already gone or protected */ }\n }\n revalidate(\"/admin\");\n const m = /^admin\\/([a-z0-9-]+)\\//.exec(branch);\n if (m) revalidate(`/admin/${m[1]}`);\n return { state: \"discarded\" };\n } catch (err) {\n return { state: \"error\", message: err instanceof Error ? err.message : String(err) };\n }\n };\n\n return { mergeContentPr, discardChange };\n}\n","/**\n * Preview for the editor: the same Markdown machinery the blog's MDX pipeline\n * sits on, returned as HTML. Markdown fidelity, not full MDX — custom components\n * render as their plain contents; headings, lists, links, tables and code are exact.\n */\n\nimport { unified } from \"unified\";\nimport remarkParse from \"remark-parse\";\nimport remarkGfm from \"remark-gfm\";\nimport remarkRehype from \"remark-rehype\";\nimport rehypeRaw from \"rehype-raw\";\nimport rehypeSlug from \"rehype-slug\";\nimport rehypeStringify from \"rehype-stringify\";\nimport type { RequestContext } from \"./context\";\n\nconst MAX_CHARS = 200_000;\n\nconst processor = unified()\n .use(remarkParse)\n .use(remarkGfm)\n .use(remarkRehype, { allowDangerousHtml: true })\n .use(rehypeRaw)\n .use(rehypeSlug)\n .use(rehypeStringify);\n\nexport function makePreview(ctx: RequestContext) {\n const previewBody = async (markdown: string): Promise<{ html: string } | { error: string }> => {\n await ctx.requireAdmin();\n if (markdown.length > MAX_CHARS) return { error: \"That's longer than the preview will render.\" };\n try {\n const source = markdown.replace(/^(import|export)\\s.*$/gm, \"\");\n return { html: String(await processor.process(source)) };\n } catch (err) {\n return { error: err instanceof Error ? err.message.split(\"\\n\")[0] : String(err) };\n }\n };\n return { previewBody };\n}\n","/**\n * Per-site branding — the Business tab. Reads and writes public.sites through\n * the signed-in user's client, so RLS decides who may (members read; owners\n * and staff write). Nothing here needs the service role.\n */\n\nimport type { IdentityClient } from \"./client\";\n\nexport interface SiteBranding {\n name: string;\n logoUrl: string | null;\n faviconUrl: string | null;\n businessEmail: string | null;\n businessPhone: string | null;\n}\n\nexport type BrandingPatch = Partial<SiteBranding> & { name: string };\n\ninterface Row {\n name: string;\n logo_url: string | null;\n favicon_url: string | null;\n business_email: string | null;\n business_phone: string | null;\n}\n\nexport async function getSiteBranding(client: IdentityClient, siteId: string): Promise<SiteBranding | null> {\n const { data, error } = await client.from(\"sites\").select(\"name, logo_url, favicon_url, business_email, business_phone\").eq(\"site_id\", siteId).maybeSingle();\n if (error) throw error;\n if (!data) return null;\n const r = data as Row;\n return { name: r.name, logoUrl: r.logo_url, faviconUrl: r.favicon_url, businessEmail: r.business_email, businessPhone: r.business_phone };\n}\n\n/** Upsert the row. RLS refuses anyone but the site's owners or staff. */\nexport async function updateSiteBranding(client: IdentityClient, siteId: string, patch: BrandingPatch): Promise<void> {\n const row = {\n site_id: siteId,\n name: patch.name.trim(),\n logo_url: patch.logoUrl ?? null,\n favicon_url: patch.faviconUrl ?? null,\n business_email: emptyToNull(patch.businessEmail),\n business_phone: emptyToNull(patch.businessPhone),\n };\n const { error } = await client.from(\"sites\").upsert(row, { onConflict: \"site_id\" });\n if (error) throw error;\n}\n\nfunction emptyToNull(v: string | null | undefined): string | null {\n const s = (v ?? \"\").trim();\n return s === \"\" ? null : s;\n}\n","/**\n * My Profile and Change Password — the signed-in user editing themselves,\n * through their own client (auth.updateUser). Name and photo live in user\n * metadata; the photo file itself is in the avatars bucket (uploaded by the\n * host, path avatars/{uid}/…).\n */\n\nimport type { IdentityClient } from \"./client\";\nimport { IdentityError } from \"./errors\";\n\nexport const MIN_PASSWORD_LENGTH = 10;\nexport const PASSWORD_TOO_SHORT = \"Use at least 10 characters.\";\n\nexport interface ProfilePatch {\n name?: string | null;\n /** The byline — how the name appears on published posts. Blank means \"same as name\". */\n displayName?: string | null;\n avatarUrl?: string | null;\n}\n\nexport interface Profile {\n name: string | null;\n /** Resolved byline: display_name if set, else name. */\n displayName: string | null;\n avatarUrl: string | null;\n}\n\nexport function profileOf(user: { user_metadata?: Record<string, unknown> | null } | null | undefined): Profile {\n const m = user?.user_metadata ?? {};\n const str = (v: unknown) => (typeof v === \"string\" && v.trim() ? v.trim() : null);\n const name = str(m.name);\n const displayName = str(m.display_name) ?? name;\n const avatarUrl = typeof m.avatar_url === \"string\" && m.avatar_url ? m.avatar_url : null;\n return { name, displayName, avatarUrl };\n}\n\nexport async function updateProfile(client: IdentityClient, patch: ProfilePatch): Promise<Profile> {\n const data: Record<string, unknown> = {};\n if (patch.name !== undefined) data.name = (patch.name ?? \"\").trim().slice(0, 80);\n if (patch.displayName !== undefined) data.display_name = (patch.displayName ?? \"\").trim().slice(0, 80);\n if (patch.avatarUrl !== undefined) data.avatar_url = patch.avatarUrl ?? \"\";\n const { data: res, error } = await client.auth.updateUser({ data });\n if (error) throw new IdentityError(error.message);\n return profileOf(res.user);\n}\n\n/** Sets (or replaces) a password. Magic links keep working alongside it. */\nexport async function setPassword(client: IdentityClient, password: string): Promise<void> {\n if (typeof password !== \"string\" || password.length < MIN_PASSWORD_LENGTH) throw new IdentityError(PASSWORD_TOO_SHORT);\n const { error } = await client.auth.updateUser({ password });\n if (error) throw new IdentityError(error.message);\n}\n","/**\n * Account actions for the signed-in person and their site's branding. Everything\n * runs as THE USER through their own identity client, so RLS decides: anyone edits\n * themselves; only owners/staff write branding. No service role in this file.\n * Pictures arrive as base64 (shrunk in the browser) and go to Supabase Storage.\n */\n\nimport { getSiteBranding, updateSiteBranding, type SiteBranding } from \"../auth/branding\";\nimport { profileOf, setPassword, updateProfile } from \"../auth/profile\";\nimport { IdentityError } from \"../auth/errors\";\nimport type { IdentityClient } from \"../auth/client\";\nimport type { ActionResult, StudioConfig } from \"./types\";\nimport type { RequestContext } from \"./context\";\n\nconst MAX_UPLOAD = 800 * 1024;\n\nexport function makeAccount(config: StudioConfig, ctx: RequestContext) {\n const revalidate = config.revalidate ?? (() => {});\n const siteId = () => config.env().siteId;\n const fail = (err: unknown): ActionResult => ({ ok: false, error: err instanceof Error ? err.message : \"Something went wrong. Try again.\" });\n\n const upload = async (client: IdentityClient, bucket: string, path: string, base64: string): Promise<string> => {\n const bytes = Buffer.from(base64.replace(/\\s+/g, \"\"), \"base64\");\n if (bytes.length === 0 || bytes.length > MAX_UPLOAD) throw new IdentityError(\"That picture is too large to send — try a smaller one.\");\n const { error } = await client.storage.from(bucket).upload(path, bytes, { contentType: \"image/webp\", upsert: true, cacheControl: \"60\" });\n if (error) throw new IdentityError(error.message);\n const { data } = client.storage.from(bucket).getPublicUrl(path);\n return `${data.publicUrl}?v=${Date.now()}`;\n };\n\n const saveProfile = async (input: { name: string; displayName: string }): Promise<ActionResult> => {\n await ctx.requireAdmin();\n try {\n await updateProfile(await ctx.identityClient(), { name: input.name, displayName: input.displayName });\n revalidate(\"/admin\", \"layout\");\n return { ok: true, message: \"Saved.\" };\n } catch (err) { return fail(err); }\n };\n\n const saveAvatar = async (input: { base64: string } | null): Promise<ActionResult> => {\n const { user } = await ctx.requireAdmin();\n const client = await ctx.identityClient();\n try {\n if (!input) {\n await updateProfile(client, { avatarUrl: null });\n revalidate(\"/admin\", \"layout\");\n return { ok: true, message: \"Photo removed.\" };\n }\n const url = await upload(client, \"avatars\", `${user.id}/avatar.webp`, input.base64);\n await updateProfile(client, { avatarUrl: url });\n revalidate(\"/admin\", \"layout\");\n return { ok: true, message: \"Photo saved.\" };\n } catch (err) { return fail(err); }\n };\n\n const changePassword = async (input: { password: string; confirm: string }): Promise<ActionResult> => {\n await ctx.requireAdmin();\n if (input.password !== input.confirm) return { ok: false, error: \"Those passwords don’t match.\" };\n try {\n await setPassword(await ctx.identityClient(), input.password);\n return { ok: true, message: \"Password saved. You can sign in with it next time, or keep using email links.\" };\n } catch (err) { return fail(err); }\n };\n\n const loadBranding = async (): Promise<SiteBranding | null> => {\n await ctx.requireAdmin();\n return getSiteBranding(await ctx.identityClient(), siteId());\n };\n\n const saveBranding = async (input: { name: string; businessEmail: string; businessPhone: string }): Promise<ActionResult> => {\n await ctx.requireAdmin({ minimumRole: \"owner\" });\n const client = await ctx.identityClient();\n if (!input.name.trim()) return { ok: false, error: \"Give your business a name.\" };\n try {\n const current = await getSiteBranding(client, siteId());\n await updateSiteBranding(client, siteId(), { name: input.name, businessEmail: input.businessEmail, businessPhone: input.businessPhone, logoUrl: current?.logoUrl ?? null, faviconUrl: current?.faviconUrl ?? null });\n revalidate(\"/admin\", \"layout\");\n return { ok: true, message: \"Saved. Your name now shows at the top of Studio.\" };\n } catch (err) { return fail(err); }\n };\n\n const saveBrandingPicture = async (input: { kind: \"logo\" | \"favicon\"; base64: string | null }): Promise<ActionResult> => {\n await ctx.requireAdmin({ minimumRole: \"owner\" });\n const client = await ctx.identityClient();\n try {\n const current = await getSiteBranding(client, siteId());\n if (!current) return { ok: false, error: \"Save your business name first, then add the pictures.\" };\n const url = input.base64 ? await upload(client, \"branding\", `${siteId()}/${input.kind}.webp`, input.base64) : null;\n await updateSiteBranding(client, siteId(), { ...current, [input.kind === \"logo\" ? \"logoUrl\" : \"faviconUrl\"]: url });\n revalidate(\"/admin\", \"layout\");\n return { ok: true, message: input.base64 ? `${input.kind === \"logo\" ? \"Logo\" : \"Favicon\"} saved.` : \"Removed.\" };\n } catch (err) { return fail(err); }\n };\n\n /** Who am I — for the page header, the profile form and the avatar in the top bar. */\n const loadMe = async () => {\n const { user, role } = await ctx.requireAdmin();\n const { data } = await (await ctx.identityClient()).auth.getUser();\n return { email: user.email ?? \"\", role, ...profileOf(data.user) };\n };\n\n return { saveProfile, saveAvatar, changePassword, loadBranding, saveBranding, saveBrandingPicture, loadMe };\n}\n","/**\n * The Team roster — public.site_members(site_id), a SECURITY DEFINER function\n * that returns rows only to that site's owners or staff (editors get a 42501).\n * Read with the signed-in user's client; writes are in service.ts.\n */\n\nimport type { IdentityClient } from \"./client\";\nimport { ForbiddenError } from \"./errors\";\n\nexport interface SiteMember {\n userId: string;\n email: string;\n name: string | null;\n avatarUrl: string | null;\n role: \"owner\" | \"editor\";\n /** \"invited\" until the person has signed in once. */\n status: \"invited\" | \"active\";\n invitedAt: string;\n}\n\ninterface Row {\n user_id: string;\n email: string;\n name: string | null;\n avatar_url: string | null;\n role: string;\n status: string;\n invited_at: string;\n}\n\nexport async function listSiteMembers(client: IdentityClient, siteId: string): Promise<SiteMember[]> {\n const { data, error } = await client.rpc(\"site_members\", { p_site_id: siteId });\n if (error) {\n if (error.code === \"42501\" || /not allowed/i.test(error.message)) throw new ForbiddenError(siteId, \"owner\", null);\n throw error;\n }\n return ((data ?? []) as Row[]).map((r) => ({\n userId: r.user_id,\n email: r.email,\n name: r.name,\n avatarUrl: r.avatar_url,\n role: r.role === \"owner\" ? \"owner\" : \"editor\",\n status: r.status === \"active\" ? \"active\" : \"invited\",\n invitedAt: r.invited_at,\n }));\n}\n","/**\n * The only file that touches the service-role key. Invite and remove.\n *\n * Authorization is checked HERE, in code, before the privileged client does\n * anything — RLS doesn't apply to the service role, so this is the guard:\n * staff → may grant owner or editor on any site\n * owner → may grant editor on their own site only\n * editor → may not invite\n *\n * `actor` is the caller's already-resolved identity (from requireSiteUser on\n * the anon client). Its role is re-resolved with the service client so a\n * caller can't lie about it.\n */\n\nimport { createClient, type SupabaseClient } from \"@supabase/supabase-js\";\nimport { ForbiddenError, IdentityError } from \"./errors\";\nimport type { ServiceContext, SiteRole } from \"./types\";\n\nexport type ServiceClient = SupabaseClient;\n\nexport function createServiceClient(ctx: ServiceContext): ServiceClient {\n return createClient(ctx.url, ctx.serviceRoleKey, {\n auth: { persistSession: false, autoRefreshToken: false },\n });\n}\n\nexport interface InviteInput {\n email: string;\n siteId: string;\n role: \"owner\" | \"editor\";\n /** The signed-in user performing the invite. */\n actor: { id: string };\n /** Where the invite email's link lands — the site's /admin/auth/callback. */\n redirectTo: string;\n}\n\nexport interface InviteResult {\n userId: string;\n siteId: string;\n role: \"owner\" | \"editor\";\n /** false when the auth user already existed and only the membership was added. */\n invitedByEmail: boolean;\n}\n\nasync function resolveActorRole(svc: ServiceClient, actorId: string, siteId: string): Promise<SiteRole | null> {\n const staff = await svc.from(\"staff\").select(\"user_id\").eq(\"user_id\", actorId).maybeSingle();\n if (staff.error) throw staff.error;\n if (staff.data) return \"staff\";\n const m = await svc.from(\"site_users\").select(\"role\").eq(\"user_id\", actorId).eq(\"site_id\", siteId).maybeSingle();\n if (m.error) throw m.error;\n const role = (m.data as { role?: string } | null)?.role;\n return role === \"owner\" || role === \"editor\" ? role : null;\n}\n\nfunction assertMayGrant(actorRole: SiteRole | null, siteId: string, granting: \"owner\" | \"editor\"): void {\n if (actorRole === \"staff\") return;\n if (actorRole === \"owner\" && granting === \"editor\") return;\n throw new ForbiddenError(siteId, granting === \"owner\" ? \"staff\" : \"owner\", actorRole);\n}\n\nexport async function inviteUser(ctx: ServiceContext, input: InviteInput): Promise<InviteResult> {\n const svc = createServiceClient(ctx);\n const actorRole = await resolveActorRole(svc, input.actor.id, input.siteId);\n assertMayGrant(actorRole, input.siteId, input.role);\n\n const email = input.email.trim().toLowerCase();\n let userId: string | undefined;\n let invitedByEmail = false;\n\n const invite = await svc.auth.admin.inviteUserByEmail(email, {\n redirectTo: input.redirectTo,\n data: { site_id: input.siteId, role: input.role },\n });\n\n if (!invite.error) {\n userId = invite.data.user.id;\n invitedByEmail = true;\n } else if (/already|exists|registered/i.test(invite.error.message)) {\n // Existing auth user (works for another site, or is staff): just add the row.\n userId = await findUserIdByEmail(svc, email);\n if (!userId) throw new IdentityError(`Could not find existing user ${email}`);\n } else {\n throw new IdentityError(`Invite failed: ${invite.error.message}`);\n }\n\n const upsert = await svc\n .from(\"site_users\")\n .upsert({ user_id: userId, site_id: input.siteId, role: input.role, invited_by: input.actor.id }, { onConflict: \"user_id,site_id\" });\n if (upsert.error) throw upsert.error;\n\n return { userId, siteId: input.siteId, role: input.role, invitedByEmail };\n}\n\nasync function findUserIdByEmail(svc: ServiceClient, email: string): Promise<string | undefined> {\n // listUsers is paged; identity holds tens of users, not thousands.\n for (let page = 1; page <= 20; page++) {\n const { data, error } = await svc.auth.admin.listUsers({ page, perPage: 200 });\n if (error) throw error;\n const hit = data.users.find((u) => u.email?.toLowerCase() === email);\n if (hit) return hit.id;\n if (data.users.length < 200) break;\n }\n return undefined;\n}\n\nexport interface RemoveInput {\n userId: string;\n siteId: string;\n actor: { id: string };\n}\n\n/** Removes the membership only. The auth user survives (they may belong to other sites). */\nexport async function removeSiteUser(ctx: ServiceContext, input: RemoveInput): Promise<void> {\n const svc = createServiceClient(ctx);\n const actorRole = await resolveActorRole(svc, input.actor.id, input.siteId);\n\n const target = await svc.from(\"site_users\").select(\"role\").eq(\"user_id\", input.userId).eq(\"site_id\", input.siteId).maybeSingle();\n if (target.error) throw target.error;\n const targetRole = ((target.data as { role?: string } | null)?.role ?? \"editor\") as \"owner\" | \"editor\";\n assertMayGrant(actorRole, input.siteId, targetRole);\n if (targetRole === \"owner\") await assertNotLastOwner(svc, input.siteId);\n\n const del = await svc.from(\"site_users\").delete().eq(\"user_id\", input.userId).eq(\"site_id\", input.siteId);\n if (del.error) throw del.error;\n}\n\nexport interface RoleInput {\n userId: string;\n siteId: string;\n role: \"owner\" | \"editor\";\n actor: { id: string };\n}\n\n/**\n * Change a member's role. Same grant rules as invite (staff anything; an owner\n * may only make people editors on their own site), plus: the last owner of a\n * site can never be demoted, otherwise nobody could manage it.\n */\nexport async function updateSiteRole(ctx: ServiceContext, input: RoleInput): Promise<void> {\n const svc = createServiceClient(ctx);\n const actorRole = await resolveActorRole(svc, input.actor.id, input.siteId);\n assertMayGrant(actorRole, input.siteId, input.role);\n\n const target = await svc.from(\"site_users\").select(\"role\").eq(\"user_id\", input.userId).eq(\"site_id\", input.siteId).maybeSingle();\n if (target.error) throw target.error;\n const current = (target.data as { role?: string } | null)?.role;\n if (!current) throw new IdentityError(\"That person isn't a member of this site.\");\n // Demoting an owner is an owner-level act — an owner may not do it to a peer.\n if (current === \"owner\") assertMayGrant(actorRole, input.siteId, \"owner\");\n if (current === \"owner\" && input.role === \"editor\") await assertNotLastOwner(svc, input.siteId);\n\n const upd = await svc.from(\"site_users\").update({ role: input.role }).eq(\"user_id\", input.userId).eq(\"site_id\", input.siteId);\n if (upd.error) throw upd.error;\n}\n\nexport async function assertNotLastOwner(svc: ServiceClient, siteId: string): Promise<void> {\n const owners = await svc.from(\"site_users\").select(\"user_id\").eq(\"site_id\", siteId).eq(\"role\", \"owner\");\n if (owners.error) throw owners.error;\n if ((owners.data ?? []).length <= 1) throw new IdentityError(\"A site needs at least one owner — make someone else an owner first.\");\n}\n\nexport interface ResendInput {\n email: string;\n siteId: string;\n actor: { id: string };\n redirectTo: string;\n}\n\n/** Send the invite email again. An already-active user gets no email — they can just sign in. */\nexport async function resendInvite(ctx: ServiceContext, input: ResendInput): Promise<{ resent: boolean; message: string }> {\n const svc = createServiceClient(ctx);\n const actorRole = await resolveActorRole(svc, input.actor.id, input.siteId);\n assertMayGrant(actorRole, input.siteId, \"editor\");\n\n const email = input.email.trim().toLowerCase();\n const again = await svc.auth.admin.inviteUserByEmail(email, { redirectTo: input.redirectTo, data: { site_id: input.siteId } });\n if (!again.error) return { resent: true, message: `Invitation sent again to ${email}.` };\n if (/already|exists|registered|confirmed/i.test(again.error.message)) {\n return { resent: false, message: `${email} has already accepted — they can sign in with an email link any time.` };\n }\n throw new IdentityError(`Resend failed: ${again.error.message}`);\n}\n","/**\n * Team actions. Reading the roster uses the signed-in user's client (the\n * site_members() function refuses non-owners). Writes need the service role,\n * which the auth helpers use ONLY after re-checking the actor's role in code.\n */\n\nimport { listSiteMembers, type SiteMember } from \"../auth/members\";\nimport { inviteUser, removeSiteUser, resendInvite, updateSiteRole } from \"../auth/service\";\nimport { ForbiddenError } from \"../auth/errors\";\nimport type { ActionResult, StudioConfig } from \"./types\";\nimport type { RequestContext } from \"./context\";\n\nconst TEAM_NOT_CONFIGURED = \"Inviting people isn’t set up on this deployment yet.\";\nconst OWNER_ONLY = \"Only the site's owner can manage the team.\";\n\nexport type TeamState = { ok: true; members: SiteMember[]; canInvite: boolean } | { ok: false; error: string };\n\nexport function makeTeam(config: StudioConfig, ctx: RequestContext) {\n const revalidate = config.revalidate ?? (() => {});\n const fail = (err: unknown): ActionResult =>\n err instanceof ForbiddenError\n ? { ok: false, error: \"You don’t have permission to do that here.\" }\n : { ok: false, error: err instanceof Error ? err.message : \"Something went wrong. Try again.\" };\n /** No query string: Supabase matches redirect URLs exactly; /admin/auth/accept must be allow-listed per host. */\n const acceptUrl = async () => `${await config.baseUrl()}/admin/auth/accept`;\n\n const loadTeam = async (): Promise<TeamState> => {\n const { role } = await ctx.requireAdmin();\n if (role === \"editor\") return { ok: false, error: OWNER_ONLY };\n try {\n const members = await listSiteMembers(await ctx.identityClient(), config.env().siteId);\n return { ok: true, members, canInvite: config.env().service !== null };\n } catch (err) {\n if (err instanceof ForbiddenError) return { ok: false, error: OWNER_ONLY };\n throw err;\n }\n };\n\n const invite = async (input: { email: string; role: \"owner\" | \"editor\" }): Promise<ActionResult> => {\n const { user } = await ctx.requireAdmin({ minimumRole: \"owner\" });\n const env = config.env();\n if (!env.service) return { ok: false, error: TEAM_NOT_CONFIGURED };\n const email = input.email.trim().toLowerCase();\n if (!/^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$/.test(email)) return { ok: false, error: \"That doesn’t look like an email address.\" };\n try {\n await inviteUser(env.service, { email, siteId: env.siteId, role: input.role, actor: { id: user.id }, redirectTo: await acceptUrl() });\n revalidate(\"/admin/account\");\n return { ok: true, message: `Invitation sent to ${email}.` };\n } catch (err) { return fail(err); }\n };\n\n const changeRole = async (input: { userId: string; role: \"owner\" | \"editor\" }): Promise<ActionResult> => {\n const { user } = await ctx.requireAdmin({ minimumRole: \"owner\" });\n const env = config.env();\n if (!env.service) return { ok: false, error: TEAM_NOT_CONFIGURED };\n try {\n await updateSiteRole(env.service, { userId: input.userId, siteId: env.siteId, role: input.role, actor: { id: user.id } });\n revalidate(\"/admin/account\");\n return { ok: true, message: \"Role updated.\" };\n } catch (err) { return fail(err); }\n };\n\n const resend = async (input: { email: string }): Promise<ActionResult> => {\n const { user } = await ctx.requireAdmin({ minimumRole: \"owner\" });\n const env = config.env();\n if (!env.service) return { ok: false, error: TEAM_NOT_CONFIGURED };\n try {\n const r = await resendInvite(env.service, { email: input.email, siteId: env.siteId, actor: { id: user.id }, redirectTo: await acceptUrl() });\n return { ok: true, message: r.message };\n } catch (err) { return fail(err); }\n };\n\n /** Remove from THIS site (or revoke a pending invite). The person's login survives elsewhere. */\n const remove = async (input: { userId: string }): Promise<ActionResult> => {\n const { user } = await ctx.requireAdmin({ minimumRole: \"owner\" });\n const env = config.env();\n if (!env.service) return { ok: false, error: TEAM_NOT_CONFIGURED };\n if (input.userId === user.id) return { ok: false, error: \"You can’t remove yourself. Ask another owner to do it.\" };\n try {\n await removeSiteUser(env.service, { userId: input.userId, siteId: env.siteId, actor: { id: user.id } });\n revalidate(\"/admin/account\");\n return { ok: true, message: \"Removed.\" };\n } catch (err) { return fail(err); }\n };\n\n return { loadTeam, invite, changeRole, resend, remove };\n}\n","/**\n * handleAuthCallback — the emailed magic link lands here with ?code=…&next=…\n *\n * Exchanges the PKCE code for a session (cookies are written through the\n * adapter the client was built with) and says where to send the user. The\n * `next` parameter is only honoured when it is a plain same-origin path —\n * \"//evil.example\" and \"https://…\" fall back, which closes the open-redirect\n * a naive startsWith(\"/\") check leaves open.\n */\n\nimport type { IdentityClient } from \"./client\";\n\nexport type CallbackResult =\n | { ok: true; redirectTo: string }\n | { ok: false; reason: \"missing_code\" | \"exchange_failed\"; message?: string };\n\nexport interface CallbackOptions {\n /** Where to go when `next` is absent or unsafe. Default \"/admin\". */\n fallbackPath?: string;\n}\n\nexport function safeNextPath(next: string | null | undefined, fallback: string): string {\n if (!next) return fallback;\n // Exactly one leading slash, then not another slash or backslash.\n if (!/^\\/(?![/\\\\])/.test(next)) return fallback;\n // No scheme smuggling or CR/LF.\n if (/[\\r\\n]/.test(next) || /^\\/[^?#]*:\\/\\//.test(next)) return fallback;\n return next;\n}\n\nexport async function handleAuthCallback(\n client: IdentityClient,\n requestUrl: string | URL,\n opts: CallbackOptions = {},\n): Promise<CallbackResult> {\n const fallback = opts.fallbackPath ?? \"/admin\";\n const url = typeof requestUrl === \"string\" ? new URL(requestUrl, \"http://placeholder.invalid\") : requestUrl;\n const code = url.searchParams.get(\"code\");\n if (!code) return { ok: false, reason: \"missing_code\" };\n\n const { error } = await client.auth.exchangeCodeForSession(code);\n if (error) return { ok: false, reason: \"exchange_failed\", message: error.message };\n\n return { ok: true, redirectTo: safeNextPath(url.searchParams.get(\"next\"), fallback) };\n}\n","/** signOut — clears this browser's session. The caller redirects afterwards. */\n\nimport type { IdentityClient } from \"./client\";\n\nexport async function signOut(client: IdentityClient): Promise<void> {\n const { error } = await client.auth.signOut({ scope: \"local\" });\n if (error) throw error;\n}\n","/**\n * Route handlers for the auth round-trips — plain Request → Response so the\n * package never imports next/server. A site re-exports them from route.ts.\n */\n\nimport { handleAuthCallback } from \"../auth/callback\";\nimport { signOut } from \"../auth/signout\";\nimport type { RequestContext } from \"./context\";\n\nexport function makeHandlers(ctx: RequestContext) {\n /** The magic link lands here: ?code=…&next=/admin → session cookies → redirect. */\n const callback = async (request: Request): Promise<Response> => {\n const result = await handleAuthCallback(await ctx.identityClient(), request.url, { fallbackPath: \"/admin\" });\n const target = result.ok ? result.redirectTo : \"/admin/sign-in?error=link\";\n return Response.redirect(new URL(target, request.url), 307);\n };\n\n /** POST only — the sign-out button is a plain form, so this works without JS. */\n const signout = async (request: Request): Promise<Response> => {\n try { await signOut(await ctx.identityClient()); } catch { /* already signed out, or not configured */ }\n return Response.redirect(new URL(\"/admin/sign-in\", request.url), 303);\n };\n\n return { callback, signout };\n}\n","/**\n * @realiizlabs/admin/studio — SERVER-ONLY.\n *\n * The server half of a site's Studio: readers over the repo, the publish /\n * merge / discard / preview / account / team logic, the session gate and the\n * auth route handlers — all built from one createStudio(config) call. Nothing\n * here reads process.env; the site's env.ts does that, lazily.\n */\n\nimport \"server-only\";\n\nimport { makeContext } from \"./context\";\nimport { makeRegistry } from \"./registry\";\nimport { makePending } from \"./pending\";\nimport { makeReaders } from \"./readers\";\nimport { makePublish } from \"./publish\";\nimport { makeMerge } from \"./merge\";\nimport { makePreview } from \"./preview\";\nimport { makeAccount } from \"./account\";\nimport { makeTeam } from \"./team\";\nimport { makeHandlers } from \"./handlers\";\nimport type { StudioConfig } from \"./types\";\n\nexport function createStudio(config: StudioConfig) {\n const ctx = makeContext(config);\n const registry = makeRegistry(config);\n const pending = makePending(config, registry);\n const readers = makeReaders(config, registry, pending);\n const actions = {\n ...makePublish(config, registry, ctx, readers),\n ...makeMerge(config, ctx, readers),\n ...makePreview(ctx),\n ...makeAccount(config, ctx),\n ...makeTeam(config, ctx),\n };\n return {\n config,\n isConfigured: config.isConfigured,\n entry: registry.entry,\n entries: registry.entries,\n requireAdmin: ctx.requireAdmin,\n identityClient: ctx.identityClient,\n readers: { ...readers, ...pending, locate: registry.locate, publicUrlFor: registry.publicUrlFor, publicDirFor: registry.publicDirFor },\n actions,\n authHandlers: makeHandlers(ctx),\n };\n}\n\nexport type Studio = ReturnType<typeof createStudio>;\nexport type StudioActions = Studio[\"actions\"];\nexport type StudioReaders = Studio[\"readers\"];\n\nexport type { StudioConfig, StudioEnv, ActionResult, RepoConfig, IdentityConfig, ServiceConfig, Session } from \"./types\";\nexport type { ListItem, PrSummary } from \"./readers\";\nexport { NotHere } from \"./readers\";\nexport type { PendingChange, PendingState } from \"./pending\";\nexport { pendingLabel, pendingText } from \"./pending\";\nexport type { PublishInput, PublishResult } from \"./publish\";\nexport type { MergeOutcome, DiscardOutcome } from \"./merge\";\nexport type { TeamState } from \"./team\";\nexport type { Located } from \"./registry\";\nexport { validateImages, decodedSize, IMAGE_LIMITS, IMAGE_ERRORS } from \"./images\";\nexport type { ImagePayload, ImageLimits, ValidatedImages } from \"./images\";\n"]}
|