@nearform/fling 0.6.0 → 0.7.0
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/README.md +115 -18
- package/dist/cli.js +2256 -525
- package/package.json +3 -4
- package/CHANGELOG.md +0 -109
- package/dist/cli.js.map +0 -7
package/dist/cli.js.map
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../packages/shared/src/api.ts", "../../../packages/shared/src/audience.ts", "../../../packages/shared/src/manifest.ts", "../../../packages/shared/src/limits.ts", "../../../packages/shared/src/secrets.ts", "../../../packages/shared/src/comments.ts", "../../../packages/shared/src/distribution.ts", "../../../packages/shared/src/groups.ts", "../../../packages/shared/src/site-labels.ts", "../../../packages/shared/src/hosts.ts", "../../../packages/shared/src/instance.ts", "../../../packages/shared/src/kvs.ts", "../../../packages/shared/src/route-keys.ts", "../../../packages/shared/src/listing.ts", "../../../packages/shared/src/mcp-tools.ts", "../../../packages/shared/src/site-sort.ts", "../../../packages/shared/src/ready.ts", "../../../packages/shared/src/review-bridge.ts", "../../../packages/shared/src/review-live.ts", "../src/cli.ts", "../src/commands/auth.ts", "../src/auth.ts", "../src/errors.ts", "../package.json", "../src/package-info.ts", "../src/api.ts", "../src/config.ts", "../src/instance.ts", "../src/context.ts", "../src/ready.ts", "../src/utils/logger.ts", "../src/ui/theme.ts", "../src/utils/output.ts", "../src/sites.ts", "../src/commands/comments.ts", "../src/commands/deploy.ts", "../src/deploy.ts", "../src/manifest.ts", "../src/gitignore.ts", "../src/naming.ts", "../src/inputs.ts", "../src/commands/groups.ts", "../src/commands/setup.ts", "../src/claude.ts", "../src/commands/sites.ts", "../src/mcp.ts", "../src/locate.ts", "../src/mcp-servers.ts", "../src/route.ts"],
|
|
4
|
-
"sourcesContent": ["import { z } from 'zod'\nimport { AudienceInputSchema, AudienceSchema } from './audience.ts'\nimport { ManifestSchema } from './manifest.ts'\n\n// Request/response contracts for the Fling HTTP API. All JSON. Auth is either the\n// `__Host-fling_session` cookie (web UI) or `Authorization: Bearer <api key>` (CLI/MCP).\n\nexport const VisibilitySchema = z.enum(['private', 'public'])\nexport type Visibility = z.infer<typeof VisibilitySchema>\n\nexport const MeSchema = z.object({\n email: z.string(),\n name: z.string(),\n picture: z.string().nullable(),\n userSlug: z.string(),\n /** one of the instance's admins (servers from before admins don't say: false) */\n admin: z.boolean().default(false),\n /** while an admin impersonates this user: the admin (browser sessions only) */\n impersonator: z.string().optional(),\n /** \u2026and when the impersonation lapses */\n impersonationEndsAt: z.string().optional(),\n})\nexport type Me = z.infer<typeof MeSchema>\n\nexport const SiteSchema = z.object({\n name: z.string(),\n url: z.string(),\n visibility: VisibilitySchema,\n spa: z.boolean(),\n archived: z.boolean(),\n currentVersionId: z.string().nullable(),\n shareUrl: z.string().nullable(),\n /** private with an audience: only the owner and the people in it can open it */\n restricted: z.boolean().default(false),\n /** how many addresses and groups the audience names (kept, and ignored, while public) */\n audienceSize: z.number().default(0),\n /** how many of those are groups */\n audienceGroups: z.number().default(0),\n createdAt: z.string(),\n updatedAt: z.string(),\n})\nexport type Site = z.infer<typeof SiteSchema>\n\n/** A site with its audience, for its owner (`audiences` capability; older servers omit it). */\nexport const SiteWithAudienceSchema = SiteSchema.extend({ audience: AudienceSchema.optional() })\nexport type SiteWithAudience = z.infer<typeof SiteWithAudienceSchema>\n\nexport const VersionSchema = z.object({\n id: z.string(),\n fileCount: z.number(),\n totalBytes: z.number(),\n createdAt: z.string(),\n})\nexport type Version = z.infer<typeof VersionSchema>\n\nexport const SiteDetailSchema = SiteWithAudienceSchema.extend({ versions: z.array(VersionSchema) })\nexport type SiteDetail = z.infer<typeof SiteDetailSchema>\n\nexport const SiteListSchema = z.object({ sites: z.array(SiteSchema) })\n\n/**\n * A restricted site someone else owns that the caller may see, because its audience names them or\n * a group they are in (GET /api/shared, `audiences` capability). What a viewer needs to open it and\n * nothing of the owner's: no versions, share link or audience.\n */\nexport const SharedSiteSchema = z.object({\n name: z.string(),\n url: z.string(),\n /** the site's review page (`comments` capability) */\n reviewUrl: z.string().optional(),\n owner: z.string(),\n /** how the caller is in the audience: by address, and through which of their groups (slugs) */\n via: z.object({ direct: z.boolean(), groups: z.array(z.string()) }),\n createdAt: z.string(),\n updatedAt: z.string(),\n})\nexport type SharedSite = z.infer<typeof SharedSiteSchema>\n\nexport const SharedSiteListSchema = z.object({ sites: z.array(SharedSiteSchema) })\n\n/**\n * GET /api/sites/:name/versions/:versionId/files \u2014 the files in one version (owner only; 404 for\n * an unknown site or version). Paths are sorted. `generatedIndex` is true when the root\n * index.html is the \"List HTML files\" page Fling generated (it carries the `fling-listing`\n * generator marker).\n */\nexport const SiteFileSchema = z.object({\n path: z.string(),\n size: z.number(),\n contentType: z.string(),\n})\nexport type SiteFile = z.infer<typeof SiteFileSchema>\n\nexport const VersionFilesSchema = z.object({\n versionId: z.string(),\n files: z.array(SiteFileSchema),\n totalBytes: z.number(),\n generatedIndex: z.boolean(),\n})\nexport type VersionFiles = z.infer<typeof VersionFilesSchema>\n\n/**\n * GET /api/names/:name \u2014 can the caller fling to this name?\n * - available: nobody has it - yours: the caller's existing site (a fling updates it)\n * - taken: someone else's - invalid: fails isValidSiteName (incl. reserved)\n * `suggestions` (free names from nameSuggestions(): `<name>-<initials>`, `<name>-<initials>2`, \u2026)\n * is filled for taken/invalid.\n * A deploy to a name someone else owns fails 409 with error code `name_taken`.\n */\nexport const NameCheckSchema = z.object({\n name: z.string(),\n status: z.enum(['available', 'yours', 'taken', 'invalid']),\n suggestions: z.array(z.string()),\n})\nexport type NameCheck = z.infer<typeof NameCheckSchema>\n\n/** POST /api/sites/:name/deploys */\nexport const DeployRequestSchema = z.object({\n manifest: ManifestSchema,\n spa: z.boolean().optional(),\n visibility: VisibilitySchema.optional(),\n})\nexport type DeployRequest = z.infer<typeof DeployRequestSchema>\n\nexport const UploadSchema = z.object({\n path: z.string(),\n url: z.string(),\n /** headers the client must send with the PUT (they are part of the signature) */\n headers: z.record(z.string(), z.string()),\n})\n\nexport const DeployResponseSchema = z.discriminatedUnion('status', [\n /** content identical to the current version \u2014 nothing happened */\n z.object({ status: z.literal('unchanged'), versionId: z.string(), site: SiteSchema }),\n /** this content was deployed before \u2014 site now points at that version again */\n z.object({ status: z.literal('repointed'), versionId: z.string(), site: SiteSchema }),\n /** new content \u2014 PUT every upload, then POST /api/sites/:name/deploys/:versionId/finalize */\n z.object({\n status: z.literal('upload'),\n versionId: z.string(),\n uploads: z.array(UploadSchema),\n }),\n])\nexport type DeployResponse = z.infer<typeof DeployResponseSchema>\n\n/** POST /api/sites/:name/deploys/:versionId/finalize */\nexport const FinalizeResponseSchema = z.object({\n status: z.literal('live'),\n versionId: z.string(),\n site: SiteSchema,\n})\n\n/** POST /api/sites/:name/current { versionId } */\nexport const RollbackRequestSchema = z.object({ versionId: z.string() })\n\n/**\n * PATCH /api/sites/:name { visibility?, spa?, audience? } \u2192 SiteWithAudienceSchema (the audience\n * when the patch set one). An address the instance wouldn't let sign in is a 400\n * `email_not_allowed`.\n */\nexport const UpdateSiteRequestSchema = z.object({\n visibility: VisibilitySchema.optional(),\n spa: z.boolean().optional(),\n audience: AudienceInputSchema.optional(),\n})\n\nexport const ApiKeySchema = z.object({\n id: z.string(),\n name: z.string(),\n createdAt: z.string(),\n lastUsedAt: z.string().nullable(),\n})\nexport const ApiKeyListSchema = z.object({ keys: z.array(ApiKeySchema) })\n\nexport const ErrorEnvelopeSchema = z.object({\n error: z.object({ code: z.string(), message: z.string() }),\n})\nexport type ErrorEnvelope = z.infer<typeof ErrorEnvelopeSchema>\n\n/** POST /api/sites/:name/share \u2014 creates or rotates the share link */\nexport const ShareResponseSchema = z.object({ shareUrl: z.string() })\nexport type ShareResponse = z.infer<typeof ShareResponseSchema>\n\n/**\n * PATCH /api/sites/:name, POST \u2026/current, \u2026/archive, \u2026/unarchive all respond with\n * SiteSchema (the updated site). DELETE /api/sites/:name and DELETE \u2026/share respond 204.\n */\nexport const SiteResponseSchema = SiteSchema\n\n/**\n * GET /api/connections \u2014 apps connected through OAuth (e.g. the Claude connector). Revoking one\n * (DELETE /api/connections/:id) kills its refresh token and, at once, its access tokens.\n */\nexport const ConnectionSchema = z.object({\n id: z.string(),\n clientName: z.string(),\n /** host the client identifies as (CIMD client_id host or redirect URI host) */\n clientHost: z.string().nullable(),\n createdAt: z.string(),\n lastUsedAt: z.string().nullable(),\n})\nexport type Connection = z.infer<typeof ConnectionSchema>\nexport const ConnectionListSchema = z.object({ connections: z.array(ConnectionSchema) })\n\n/** GET /api/oauth/requests/:id \u2014 what the consent page shows. */\nexport const OAuthRequestInfoSchema = z.object({\n clientName: z.string(),\n clientUri: z.string().nullable(),\n /** host of the CIMD client_id URL, when the client identified itself that way */\n clientIdHost: z.string().nullable(),\n redirectHost: z.string(),\n /** true when the code goes to a loopback address (any local program could be asking) */\n loopback: z.boolean(),\n scopes: z.array(z.string()),\n email: z.string(),\n})\nexport type OAuthRequestInfo = z.infer<typeof OAuthRequestInfoSchema>\n\n/** POST /api/oauth/requests/:id/approve | /deny \u2192 where to send the browser. */\nexport const OAuthDecisionSchema = z.object({ redirectUrl: z.string() })\n\n// --- admin (ADMIN_EMAILS only; anyone else gets 404s) ---\n\n/** GET /api/admin/users?q=<email prefix>&cursor=&limit= \u2014 one page, by email. */\nexport const AdminUserSchema = z.object({\n email: z.string(),\n name: z.string(),\n picture: z.string().nullable(),\n userSlug: z.string(),\n createdAt: z.string().nullable(),\n lastSignInAt: z.string().nullable(),\n /** sites the user holds, archived ones included */\n siteCount: z.number(),\n admin: z.boolean(),\n})\nexport type AdminUser = z.infer<typeof AdminUserSchema>\nexport const AdminUserListSchema = z.object({\n users: z.array(AdminUserSchema),\n /** pass back as `cursor` for the next page; null: no more */\n cursor: z.string().nullable(),\n})\nexport type AdminUserList = z.infer<typeof AdminUserListSchema>\n\n/** GET /api/admin/audit \u2014 the latest admin actions, newest first. */\nexport const AuditEntrySchema = z.object({\n id: z.string(),\n at: z.string(),\n action: z.enum(['impersonation.start', 'impersonation.stop']),\n actor: z.string(),\n target: z.string(),\n until: z.string().optional(),\n lapsed: z.boolean().optional(),\n})\nexport type AuditEntry = z.infer<typeof AuditEntrySchema>\nexport const AuditListSchema = z.object({ entries: z.array(AuditEntrySchema) })\n\n/**\n * POST /api/admin/impersonate { email } (browser session, an admin) \u2192 the new Me; POST\n * /api/admin/impersonate/stop \u2192 the admin's own Me again.\n */\nexport const ImpersonateRequestSchema = z.object({ email: z.string().trim().toLowerCase().min(3) })\n", "// A site's audience: who, besides its owner, may see it while it is private. Empty means every\n// signed-in member; a private site with an audience is restricted. The contract, the edits every\n// client makes (`fling access`, both servers' `fling_set_audience`, the web's Access section) and\n// the words the CLI and both MCP servers describe it (and the sites shared with someone) with.\n// Browser-safe (zod only).\n\nimport { z } from 'zod'\n\n/** The most addresses an audience holds. */\nexport const AUDIENCE_EMAILS_MAX = 100\n/** The most groups an audience names. */\nexport const AUDIENCE_GROUPS_MAX = 10\n\n/** An address in an audience; `known` once it has signed in to the instance. */\nexport const AudienceEmailSchema = z.object({ email: z.string(), known: z.boolean() })\nexport type AudienceEmail = z.infer<typeof AudienceEmailSchema>\n\n/**\n * A group in an audience (groups.ts), by its slug; `size`: how many members it has. A group that\n * has been deleted while it was the audience's only entry stays in it, letting nobody in, so the\n * site stays restricted to its owner: it is `deleted`, and its `slug` is a reference\n * (`deletedGroupRef`) the owner passes back to keep it, or leaves out to remove it.\n */\nexport const AudienceGroupSchema = z.object({\n slug: z.string(),\n name: z.string(),\n size: z.number(),\n deleted: z.boolean().optional(),\n})\nexport type AudienceGroup = z.infer<typeof AudienceGroupSchema>\n\n/** How an audience names a deleted group (`#<id>`): never a slug, which has no `#`. */\nexport const deletedGroupRef = (id: string) => `#${id}`\n/** The id in a deleted group's reference, or null for a slug. */\nexport const deletedGroupId = (ref: string) => (ref.startsWith('#') ? ref.slice(1) : null)\n\n/** As the API reports it to the owner. */\nexport const AudienceSchema = z.object({\n emails: z.array(AudienceEmailSchema),\n groups: z.array(AudienceGroupSchema).default([]),\n})\nexport type Audience = z.infer<typeof AudienceSchema>\n\n/**\n * PATCH /api/sites/:name { audience }: the whole new audience. Each address must be one the\n * instance lets sign in, and each group (by slug) one that exists (else a 400 naming it).\n */\nexport const AudienceInputSchema = z.object({\n emails: z\n .array(z.string().trim().toLowerCase().min(3).max(254))\n .max(AUDIENCE_EMAILS_MAX, `An audience holds at most ${AUDIENCE_EMAILS_MAX} addresses`),\n groups: z\n .array(z.string().trim().toLowerCase().min(1).max(100))\n .max(AUDIENCE_GROUPS_MAX, `An audience names at most ${AUDIENCE_GROUPS_MAX} groups`)\n .default([]),\n})\nexport type AudienceInput = z.input<typeof AudienceInputSchema>\n\n/**\n * A change to an audience: its addresses (`set`, `add`, `remove`) and its groups by slug\n * (`setGroups`, `addGroups`, `removeGroups`), each cleared or replaced first, then added to, then\n * removed from. `clear` empties both.\n */\nexport interface AudienceChange {\n set?: readonly string[]\n add?: readonly string[]\n remove?: readonly string[]\n setGroups?: readonly string[]\n addGroups?: readonly string[]\n removeGroups?: readonly string[]\n clear?: boolean\n}\n\nexport const normaliseEmail = (email: string) => email.trim().toLowerCase()\n\n/** `a@x.test, b@x.test` (or several such values) \u2192 the addresses, normalised. */\nexport function splitEmails(values: string | readonly string[]): string[] {\n const all = typeof values === 'string' ? [values] : values\n return all\n .flatMap(v => v.split(/[\\s,;]+/))\n .map(normaliseEmail)\n .filter(Boolean)\n}\n\n/** The addresses after `change`, normalised, each once, in the order they were first given. */\nexport function editAudience(current: readonly string[], change: AudienceChange): string[] {\n let emails = change.clear ? [] : change.set ? [...change.set] : [...current]\n emails = [...emails, ...(change.add ?? [])].map(normaliseEmail)\n const removed = new Set((change.remove ?? []).map(normaliseEmail))\n return [...new Set(emails)].filter(e => e && !removed.has(e))\n}\n\n/** The group slugs after `change`, normalised, each once, in the order they were first given. */\nexport function editAudienceGroups(current: readonly string[], change: AudienceChange): string[] {\n const norm = (s: string) => s.trim().toLowerCase()\n let groups = change.clear ? [] : change.setGroups ? [...change.setGroups] : [...current]\n groups = [...groups, ...(change.addGroups ?? [])].map(norm)\n const removed = new Set((change.removeGroups ?? []).map(norm))\n return [...new Set(groups)].filter(g => g && !removed.has(g))\n}\n\n/** The whole new audience after `change`, as PATCH takes it (groups by slug). */\nexport function editAudienceInput(\n current: { emails: readonly AudienceEmail[]; groups: readonly AudienceGroup[] },\n change: AudienceChange\n): { emails: string[]; groups: string[] } {\n return {\n emails: editAudience(\n current.emails.map(e => e.email),\n change\n ),\n groups: editAudienceGroups(\n current.groups.map(g => g.slug),\n change\n ),\n }\n}\n\n/** Whether a change edits anything. */\nexport const changesAudience = (change: AudienceChange) =>\n Boolean(\n change.clear ||\n change.set ||\n change.add?.length ||\n change.remove?.length ||\n change.setGroups ||\n change.addGroups?.length ||\n change.removeGroups?.length\n )\n\nconst people = (n: number) => `${n} ${n === 1 ? 'person' : 'people'}`\n\n/** `design (Design team, 4 people)`; a deleted one: `a deleted group (#<id>)`. */\nexport const groupLabel = (g: Pick<AudienceGroup, 'slug' | 'name' | 'size' | 'deleted'>) =>\n g.deleted\n ? `a deleted group (${g.slug})`\n : `${g.slug} (${g.name !== g.slug ? `${g.name}, ` : ''}${people(g.size)})`\n\n/**\n * `3 people`, `the group design (\u2026)`, `a deleted group (#\u2026)`: who an audience names, as parts of a\n * sentence.\n */\nfunction whoIn(emails: readonly AudienceEmail[], groups: readonly AudienceGroup[]): string[] {\n const live = groups.filter(g => !g.deleted)\n return [\n emails.length ? people(emails.length) : '',\n live.length\n ? `${live.length === 1 ? 'the group' : 'the groups'} ${live.map(groupLabel).join(', ')}`\n : '',\n ...groups.filter(g => g.deleted).map(groupLabel),\n ].filter(Boolean)\n}\n\n/** `a`, `a and b`, `a, b and c`. */\nconst and = (parts: readonly string[]) =>\n parts.length > 1 ? `${parts.slice(0, -1).join(', ')} and ${parts.at(-1)}` : (parts[0] ?? '')\n\n/** `a@x.test, b@x.test (hasn't signed in yet)`. */\nexport const audienceList = (emails: readonly AudienceEmail[]) =>\n emails.map(e => (e.known ? e.email : `${e.email} (hasn't signed in yet)`)).join(', ')\n\n/**\n * Who can open the site, for the CLI and both MCP servers: public, every member\n * (`privateAudience`), or the listed people; plus a warning when a share link still opens a\n * restricted site to anyone.\n */\nexport function describeAudience(\n site: {\n visibility: 'public' | 'private'\n audience?: Audience\n shareUrl: string | null\n },\n privateAudience: string\n): string {\n const emails = site.audience?.emails ?? []\n const groups = site.audience?.groups ?? []\n const empty = emails.length + groups.length === 0\n const list = emails.length ? `: ${audienceList(emails)}` : ''\n if (site.visibility === 'public') {\n return empty\n ? 'Public: anyone can open the site; reviewing it still needs sign-in.'\n : `Public: anyone can open the site; reviewing it still needs sign-in. Its audience (${and(whoIn(emails, groups))}${list}) applies when it is private again.`\n }\n if (empty) return `Private: ${privateAudience} can open it.`\n const share = site.shareUrl\n ? ` A share link is active: anyone with it can still open the site (${site.shareUrl}).`\n : ''\n if (emails.length === 0 && groups.every(g => g.deleted)) {\n const refs = groups.map(g => g.slug).join(', ')\n return `Restricted: only you can open it. Its audience names only ${groups.length === 1 ? 'a deleted group' : 'deleted groups'} (${refs}), which let nobody in: add people or groups, or clear it.${share}`\n }\n return `Restricted: only ${and(['you', ...whoIn(emails, groups)])} can open it${list}.${share}`\n}\n\n/** What says how a shared site reached someone (`SharedSite`, api.ts). */\ninterface SharedVia {\n via: { direct: boolean; groups: readonly string[] }\n}\n\n/** `your address`, `group design`, `your address and groups design, ops`: how a site was shared. */\nexport function sharedVia(site: SharedVia): string {\n const { direct, groups } = site.via\n return and([\n ...(direct ? ['your address'] : []),\n ...(groups.length ? [`${groups.length === 1 ? 'group' : 'groups'} ${groups.join(', ')}`] : []),\n ])\n}\n\n/**\n * One site shared with the user, for the CLI and both MCP servers:\n * `- q3-report: https://\u2026 (shared by ann@x.test, through group design; review: https://\u2026)`.\n */\nexport const describeSharedSite = (\n site: SharedVia & { name: string; url: string; owner: string; reviewUrl?: string }\n) =>\n `- ${site.name}: ${site.url} (shared by ${site.owner}, through ${sharedVia(site)}` +\n `${site.reviewUrl ? `; review: ${site.reviewUrl}` : ''})`\n", "import { z } from 'zod'\nimport { MAX_DEPLOY_BYTES, MAX_FILE_BYTES, MAX_FILES, MAX_PATH_LENGTH } from './limits.ts'\nimport { isSecretPath } from './secrets.ts'\n\n/**\n * A site-relative POSIX path: no leading slash, no backslashes, no empty segments, and no segment\n * starting with `.` \u2014 so no `.`/`..`, and never a dotfile or dot-directory (`.env`, `.dev.vars`,\n * `.git/\u2026`, `.well-known/\u2026`). Fling never publishes dotfiles; there is no override.\n */\nexport function isValidSitePath(path: string): boolean {\n if (!path || path.length > MAX_PATH_LENGTH) return false\n if (path.startsWith('/') || path.includes('\\\\') || path.includes('\\0')) return false\n return path.split('/').every(seg => seg !== '' && !seg.startsWith('.'))\n}\n\nexport const ManifestFileSchema = z.object({\n path: z\n .string()\n .refine(isValidSitePath, 'invalid path (dotfiles are never published)')\n .refine(p => !isSecretPath(p), 'secret file (keys, certificates, credentials) never published'),\n sha256: z.string().regex(/^[a-f0-9]{64}$/),\n size: z.number().int().min(0).max(MAX_FILE_BYTES),\n contentType: z.string().min(1).max(255),\n})\nexport type ManifestFile = z.infer<typeof ManifestFileSchema>\n\nexport const ManifestSchema = z\n .object({ files: z.array(ManifestFileSchema).min(1).max(MAX_FILES) })\n .refine(m => new Set(m.files.map(f => f.path)).size === m.files.length, 'duplicate paths')\n .refine(m => m.files.reduce((n, f) => n + f.size, 0) <= MAX_DEPLOY_BYTES, 'deploy too large')\nexport type Manifest = z.infer<typeof ManifestSchema>\n\n/**\n * The canonical string a version id is hashed from: one `path\\0sha256\\n` line per\n * file, sorted by path. Content type is deliberately excluded so the same bytes\n * always map to the same version.\n */\nexport function canonicalManifest(files: readonly Pick<ManifestFile, 'path' | 'sha256'>[]): string {\n return [...files]\n .sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0))\n .map(f => `${f.path}\\0${f.sha256}\\n`)\n .join('')\n}\n\nexport const VERSION_ID_LENGTH = 16\n", "export const MAX_DEPLOY_BYTES = 100 * 1024 * 1024\nexport const MAX_FILE_BYTES = 25 * 1024 * 1024\nexport const MAX_FILES = 5000\nexport const MAX_PATH_LENGTH = 1024\n", "/**\n * Secrets guard (browser-safe, dependency-free) \u2014 used by the CLI, the local MCP server and the\n * API, so every way of flinging applies the same rules:\n *\n * - `isSecretPath(path)`: file names that are secrets by nature (private keys, keystores,\n * credentials files, Terraform state\u2026). Always refused; there is no override.\n * - `scanForSecrets(text, path)`: well-known, high-precision token / key patterns in file\n * contents. Any finding refuses the deploy; there is no override.\n *\n * Findings carry only the path, the line and the rule \u2014 never the matched value \u2014 so error\n * messages and logs can't leak the secret they are reporting.\n *\n * Deliberately not detected (too noisy for a hard error with no override): browser API keys that\n * are public by design (e.g. Google Maps / Firebase `AIza\u2026` keys), JWTs, generic \"password =\"\n * assignments and high-entropy strings.\n */\n\nimport { MAX_FILE_BYTES } from './limits.ts'\n\n/** Files bigger than this are not scanned: the per-file deploy limit, so every text file is. */\nexport const SECRET_SCAN_MAX_FILE_BYTES = MAX_FILE_BYTES\n/** A NUL byte in the first this-many bytes marks a file as binary (not scanned). */\nexport const BINARY_SNIFF_BYTES = 8192\n\n// ---- secret file names --------------------------------------------------------------------\n\nconst SECRET_EXTENSIONS = [\n '.pem',\n '.key',\n '.p12',\n '.pfx',\n '.jks',\n '.keystore',\n '.tfstate',\n '.tfstate.backup',\n '.tfvars',\n '.tfvars.json',\n '.kdbx',\n]\nconst SECRET_NAMES = new Set([\n 'credentials',\n 'credentials.json',\n 'secrets.json',\n 'secrets.yml',\n 'secrets.yaml',\n 'wp-config.php',\n '.htpasswd',\n])\nconst SSH_KEY_RE = /^id_(?:rsa|dsa|ecdsa|ed25519)(?:[._-]|$)/\n\n/**\n * Is this a file that holds secrets by its very name (case-insensitive, on the file name)?\n * SSH public keys (`id_rsa.pub`) are allowed. Directory names are not matched, so a docs page at\n * `credentials/index.html` is fine.\n */\nexport function isSecretPath(path: string): boolean {\n const name = (path.split(/[\\\\/]/).at(-1) ?? '').toLowerCase()\n if (!name) return false\n if (SECRET_NAMES.has(name)) return true\n if (SECRET_EXTENSIONS.some(ext => name.endsWith(ext) && name.length > ext.length)) return true\n if (/service[-_]account.*\\.json$/.test(name)) return true\n if (SSH_KEY_RE.test(name) && !name.endsWith('.pub')) return true\n return false\n}\n\n// ---- secret contents ----------------------------------------------------------------------\n\nexport interface SecretFinding {\n path: string\n /** 1-based */\n line: number\n /** rule id (see SECRET_RULE_LABELS) */\n rule: string\n}\n\ninterface Rule {\n id: string\n label: string\n re: RegExp\n /** The match is a placeholder / documentation example (not a secret). */\n allow?: (match: RegExpExecArray) => boolean\n}\n\nconst PLACEHOLDER_RE = /example|xxxx/i\nconst isPlaceholder = (m: RegExpExecArray) => PLACEHOLDER_RE.test(m[0])\n\nconst DB_PASSWORD_PLACEHOLDER =\n /^(?:password|passw(?:or)?d|pass|pwd|secret|changeme|example|test|admin|root|postgres|mysql|redis|guest|user|\\*+|x+|\\.+)$/i\nconst LOCAL_HOST = /^(?:localhost|127\\.0\\.0\\.1|0\\.0\\.0\\.0|\\[::1\\]|db|host|hostname)(?::\\d+)?$/i\n\nconst RULES: Rule[] = [\n {\n id: 'private-key',\n label: 'private key',\n // The header, optional RFC 1421 headers (Proc-Type, DEK-Info, Version), then key material.\n re: /-----BEGIN (?:RSA |EC |DSA |OPENSSH |ENCRYPTED |PGP )?PRIVATE KEY(?: BLOCK)?-----[ \\t]*\\r?\\n(?:[A-Za-z-]+:[^\\n]*\\r?\\n)*(?:[ \\t]*\\r?\\n)?[ \\t]*[A-Za-z0-9+/=]{40,}/g,\n },\n {\n id: 'aws-access-key-id',\n label: 'AWS access key ID',\n re: /\\b(?:AKIA|ASIA)[0-9A-Z]{16}\\b/g,\n allow: isPlaceholder,\n },\n {\n id: 'aws-secret-access-key',\n label: 'AWS secret access key',\n re: /\\b(?:aws_?)?secret_?access_?key[\"']?\\s*[:=]\\s*[\"']?[A-Za-z0-9/+=]{40}(?![A-Za-z0-9/+=])/gi,\n allow: isPlaceholder,\n },\n {\n id: 'github-token',\n label: 'GitHub token',\n re: /\\b(?:gh[pousr]_[A-Za-z0-9]{36,}|github_pat_[A-Za-z0-9_]{80,})/g,\n allow: isPlaceholder,\n },\n { id: 'npm-token', label: 'npm token', re: /\\bnpm_[A-Za-z0-9]{36}\\b/g, allow: isPlaceholder },\n {\n id: 'slack-token',\n label: 'Slack token',\n re: /\\bxox[abposr]-[0-9]{6,}-[A-Za-z0-9-]{10,}/g,\n allow: isPlaceholder,\n },\n {\n id: 'slack-webhook',\n label: 'Slack webhook URL',\n re: /https:\\/\\/hooks\\.slack\\.com\\/services\\/T[A-Z0-9]{6,}\\/B[A-Z0-9]{6,}\\/[A-Za-z0-9]{20,}/g,\n allow: isPlaceholder,\n },\n {\n id: 'stripe-live-key',\n label: 'Stripe live key',\n re: /\\b[sr]k_live_[0-9a-zA-Z]{24,}\\b/g,\n allow: isPlaceholder,\n },\n {\n id: 'google-oauth-client-secret',\n label: 'Google OAuth client secret',\n re: /\\bGOCSPX-[A-Za-z0-9_-]{28}(?![A-Za-z0-9_-])/g,\n allow: isPlaceholder,\n },\n {\n id: 'openai-api-key',\n label: 'OpenAI API key',\n re: /\\bsk-(?:(?:proj|svcacct|admin)-[A-Za-z0-9_-]{40,}|[A-Za-z0-9]{20}T3BlbkFJ[A-Za-z0-9]{20})/g,\n allow: isPlaceholder,\n },\n {\n id: 'anthropic-api-key',\n label: 'Anthropic API key',\n re: /\\bsk-ant-[A-Za-z0-9_-]{80,}/g,\n allow: isPlaceholder,\n },\n {\n id: 'sendgrid-api-key',\n label: 'SendGrid API key',\n re: /\\bSG\\.[A-Za-z0-9_-]{22}\\.[A-Za-z0-9_-]{43}(?![A-Za-z0-9_-])/g,\n allow: isPlaceholder,\n },\n {\n id: 'azure-storage-key',\n label: 'Azure storage account key',\n re: /\\bAccountKey=[A-Za-z0-9+/]{80,}={0,2}/g,\n allow: isPlaceholder,\n },\n {\n id: 'database-url-password',\n label: 'database URL with a password',\n re: /\\b(?:postgres(?:ql)?|mysql|mariadb|mongodb(?:\\+srv)?|rediss?|amqps?):\\/\\/[^:\\s/@\"'`<>]+:([^@\\s/\"'`<>]{3,})@([^\\s/?#\"'`<>]+)/g,\n allow: m => {\n const password = m[1] ?? ''\n const host = m[2] ?? ''\n return (\n DB_PASSWORD_PLACEHOLDER.test(password) ||\n /[${}%]/.test(password) ||\n PLACEHOLDER_RE.test(password) ||\n LOCAL_HOST.test(host) ||\n /(?:^|\\.)example(?:\\.[a-z]+)?(?::\\d+)?$/i.test(host)\n )\n },\n },\n]\n\n/** rule id \u2192 what it is, for messages. */\nexport const SECRET_RULE_LABELS: Record<string, string> = Object.fromEntries(\n RULES.map(r => [r.id, r.label])\n)\n\n/** 1-based line of `index` in a text whose line starts are `starts`. */\nfunction lineAt(starts: number[], index: number): number {\n let lo = 0\n let hi = starts.length - 1\n while (lo < hi) {\n const mid = (lo + hi + 1) >> 1\n if ((starts[mid] as number) <= index) lo = mid\n else hi = mid - 1\n }\n return lo + 1\n}\n\n/** Secrets in a text file: one finding per rule and line, sorted by line. Never the value. */\nexport function scanForSecrets(text: string, path: string): SecretFinding[] {\n let starts: number[] | undefined\n const findings: SecretFinding[] = []\n const seen = new Set<string>()\n for (const rule of RULES) {\n rule.re.lastIndex = 0\n for (let m = rule.re.exec(text); m !== null; m = rule.re.exec(text)) {\n if (m[0].length === 0) rule.re.lastIndex++\n if (rule.allow?.(m)) continue\n if (!starts) {\n starts = [0]\n for (let i = text.indexOf('\\n'); i !== -1; i = text.indexOf('\\n', i + 1)) starts.push(i + 1)\n }\n const line = lineAt(starts, m.index)\n const key = `${rule.id}:${line}`\n if (seen.has(key)) continue\n seen.add(key)\n findings.push({ path, line, rule: rule.id })\n }\n }\n return findings.sort((a, b) => a.line - b.line || a.rule.localeCompare(b.rule))\n}\n\nconst BINARY_EXTENSIONS = new Set(\n (\n 'png jpg jpeg gif webp avif ico bmp tif tiff heic psd ' +\n 'woff woff2 ttf otf eot ' +\n 'mp3 mp4 m4a m4v mov webm ogg oga ogv wav flac aac avi mkv ' +\n 'zip gz tgz br zst bz2 xz 7z rar ' +\n 'wasm pdf glb gltf-binary bin dat'\n )\n .split(/\\s+/)\n .filter(Boolean)\n)\n\n/** Worth reading to scan? (Everything except well-known binary formats.) */\nexport function isScannablePath(path: string): boolean {\n const name = path.split('/').at(-1) ?? ''\n const dot = name.lastIndexOf('.')\n return dot <= 0 || !BINARY_EXTENSIONS.has(name.slice(dot + 1).toLowerCase())\n}\n\n/** A NUL byte near the start \u2192 binary. */\nexport function looksBinary(bytes: Uint8Array): boolean {\n const end = Math.min(bytes.length, BINARY_SNIFF_BYTES)\n for (let i = 0; i < end; i++) if (bytes[i] === 0) return true\n return false\n}\n\n/**\n * Scan a file's bytes: skipped (no findings) when the path is a binary format, it is bigger than\n * SECRET_SCAN_MAX_FILE_BYTES, or it looks binary; otherwise decoded as UTF-8 and scanned.\n */\nexport function scanBytesForSecrets(bytes: Uint8Array, path: string): SecretFinding[] {\n if (!isScannablePath(path) || bytes.length > SECRET_SCAN_MAX_FILE_BYTES || looksBinary(bytes))\n return []\n return scanForSecrets(new TextDecoder('utf-8').decode(bytes), path)\n}\n\n/** `config.js line 12: AWS access key ID` \u2014 one per finding, at most `max` (then \"\u2026 and N more\"). */\nexport function describeSecretFindings(findings: readonly SecretFinding[], max = 20): string[] {\n const lines = findings\n .slice(0, max)\n .map(f => `${f.path} line ${f.line}: ${SECRET_RULE_LABELS[f.rule] ?? f.rule}`)\n if (findings.length > max) lines.push(`\u2026 and ${findings.length - max} more`)\n return lines\n}\n\n/** Why a path can never be published (dotfile or secret file name), or null if it can. */\nexport function forbiddenPathReason(path: string): 'dotfile' | 'secret_file' | null {\n if (path.split('/').some(seg => seg.startsWith('.') && seg !== '.' && seg !== '..'))\n return 'dotfile'\n if (isSecretPath(path)) return 'secret_file'\n return null\n}\n\nexport const NEVER_PUBLISHED_NOTE =\n 'Fling never publishes dotfiles, gitignored files, secret files (keys, certificates, credentials) or files that contain secrets.'\n", "// Comments on a site: the API contract (`/api/sites/:name/comments`), the page-path rule every\n// client and the API agree on, and the threading the web, the CLI and the MCP servers show.\n// Browser-safe (zod only).\n//\n// A comment is made in review mode: an app-origin page that frames the review shell, a page on the\n// site's own origin that frames the site and reports what it sees (review-bridge.ts). A comment\n// attaches to `{ path, versionId }`, the page the frame was showing and the version being served\n// when it was made. An optional `anchor` is the spot the reviewer pinned (a point, a box they drew\n// or text they selected), with enough context (element, document point, scroll, viewport, SPA hash\n// route, the quoted text) to find it again on another screen.\n\nimport { z } from 'zod'\n\n/** Characters in one comment. */\nexport const COMMENT_MAX_CHARS = 4000\n/** Comments (threads and replies) one site may hold. */\nexport const COMMENTS_PER_SITE_MAX = 1000\n/** Characters in a page path. */\nexport const COMMENT_PATH_MAX = 1024\n\n/**\n * Who wrote a comment: a signed-in user, or (later) a guest who opened a share link and gave a\n * name (`guest`: a signed per-site cookie, not built yet; the API never creates one today).\n */\nexport const CommentAuthorSchema = z.discriminatedUnion('kind', [\n z.object({ kind: z.literal('user'), email: z.string() }),\n z.object({ kind: z.literal('guest'), name: z.string() }),\n])\nexport type CommentAuthor = z.infer<typeof CommentAuthorSchema>\n\n/** Characters in an anchor's CSS selector. */\nexport const ANCHOR_SELECTOR_MAX = 512\n/** Characters of selected text an anchor quotes. */\nexport const ANCHOR_QUOTE_MAX = 500\n\nconst px = z.number().finite().min(-1e7).max(1e7)\nconst percent = z.number().min(0).max(100)\n\n/**\n * A spot on a page. `x`/`y` (percentages of the frame's viewport) are always there and are the last\n * resort; the review shell finds the spot again by, in order: `selector` plus `ex`/`ey` (the\n * element and the point inside it, as percentages of its box), then `docX`/`docY` (document\n * pixels), then `x`/`y`. `scrollX`/`scrollY` and `vw`/`vh` record the scroll and viewport the pin\n * was placed with; `hash` is the page's fragment, the route of a hash-routed single-page app.\n *\n * An area (a box the reviewer drew, or text they selected) has the spot as its top-left corner and\n * a size: `ew`/`eh` (percentages of the element's box) and `docW`/`docH` (document pixels). Selected\n * text also has its `quote`, which the shell finds again inside the element before falling back to\n * the box.\n */\nexport const CommentAnchorSchema = z.object({\n x: percent,\n y: percent,\n selector: z.string().min(1).max(ANCHOR_SELECTOR_MAX).optional(),\n ex: percent.optional(),\n ey: percent.optional(),\n docX: px.optional(),\n docY: px.optional(),\n scrollX: px.optional(),\n scrollY: px.optional(),\n vw: z.number().finite().min(0).max(1e5).optional(),\n vh: z.number().finite().min(0).max(1e5).optional(),\n hash: z.string().max(COMMENT_PATH_MAX).optional(),\n ew: percent.optional(),\n eh: percent.optional(),\n docW: z.number().finite().min(0).max(1e7).optional(),\n docH: z.number().finite().min(0).max(1e7).optional(),\n quote: z.string().min(1).max(ANCHOR_QUOTE_MAX).optional(),\n})\nexport type CommentAnchor = z.infer<typeof CommentAnchorSchema>\n\nexport const CommentSchema = z.object({\n id: z.string(),\n /** the thread this replies to; null for the comment that starts a thread */\n parentId: z.string().nullable(),\n /** the page, as normalizeCommentPath() writes it ('/', '/docs/', '/about.html') */\n path: z.string(),\n /** the version the site was serving when the comment was made (null: none was) */\n versionId: z.string().nullable(),\n anchor: CommentAnchorSchema.nullable(),\n body: z.string(),\n author: CommentAuthorSchema,\n createdAt: z.string(),\n /** threads only: when and by whom it was resolved (null: open) */\n resolvedAt: z.string().nullable(),\n resolvedBy: CommentAuthorSchema.nullable(),\n /** whether the caller may delete it (policy's answer, so clients don't guess) */\n canDelete: z.boolean(),\n})\nexport type Comment = z.infer<typeof CommentSchema>\n\n/**\n * GET /api/sites/:name/comments[?path=] \u2014 the site (as much as a reviewer needs: members can't\n * read the site itself), its comments oldest first, and what the caller may do. 404 when the\n * caller may not read comments on the site, or the instance has comments turned off.\n */\nexport const CommentListSchema = z.object({\n site: z.object({\n name: z.string(),\n url: z.string(),\n currentVersionId: z.string().nullable(),\n }),\n comments: z.array(CommentSchema),\n can: z.object({\n create: z.boolean(),\n resolve: z.boolean(),\n /** delete anyone's comment (everyone may delete their own) */\n deleteAny: z.boolean(),\n }),\n})\nexport type CommentList = z.infer<typeof CommentListSchema>\n\n/** POST /api/sites/:name/comments \u2192 CommentSchema (201). A reply takes its thread's path. */\nexport const CreateCommentRequestSchema = z.object({\n body: z.string().trim().min(1).max(COMMENT_MAX_CHARS),\n path: z.string().max(COMMENT_PATH_MAX).optional(),\n parentId: z.string().min(1).max(100).optional(),\n anchor: CommentAnchorSchema.optional(),\n})\nexport type CreateCommentRequest = z.infer<typeof CreateCommentRequestSchema>\n\n/** PATCH /api/sites/:name/comments/:id { resolved } \u2192 CommentSchema. Threads only. */\nexport const UpdateCommentRequestSchema = z.object({ resolved: z.boolean() })\n\n/**\n * A page path as comments store it: site-relative with a leading slash, without the query or\n * fragment, `index.html` folded into its folder (`/docs/index.html` \u2192 `/docs/`). Accepts a full\n * URL (its path is used) and a bare relative path (`about.html` \u2192 `/about.html`). Null when it is\n * not a path.\n */\nexport function normalizeCommentPath(input: string | undefined | null): string | null {\n let path = (input ?? '').trim()\n if (path === '') return '/'\n if (/^[a-z][a-z0-9+.-]*:\\/\\//i.test(path)) {\n try {\n path = new URL(path).pathname\n } catch {\n return null\n }\n }\n path = path.replace(/[?#].*$/, '')\n if (!path.startsWith('/')) path = `/${path}`\n path = path.replace(/\\/{2,}/g, '/').replace(/(^|\\/)index\\.html$/, '$1')\n if (path.length > COMMENT_PATH_MAX || /\\s/.test(path)) return null\n if (path.split('/').some(s => s === '.' || s === '..')) return null\n return path\n}\n\n/** A thread: the comment that starts it and its replies, oldest first. */\nexport interface CommentThread {\n comment: Comment\n replies: Comment[]\n}\n\n/**\n * Comments (oldest first, as the API lists them) grouped into threads, oldest thread first.\n * Replies whose thread is gone are dropped.\n */\nexport function commentThreads(comments: readonly Comment[]): CommentThread[] {\n const threads = new Map<string, CommentThread>()\n for (const c of comments) {\n if (c.parentId === null) threads.set(c.id, { comment: c, replies: [] })\n }\n for (const c of comments) {\n if (c.parentId !== null) threads.get(c.parentId)?.replies.push(c)\n }\n return [...threads.values()]\n}\n\n/** How an author is shown: their email, or a guest's name marked as such. */\nexport function authorLabel(author: CommentAuthor): string {\n return author.kind === 'user' ? author.email : `${author.name} (guest)`\n}\n\n/** The review page of a site on the app: `https://fling.example.test/review/<name>[?path=\u2026]`. */\nexport function reviewUrl(appOrigin: string, name: string, path?: string): string {\n const base = `${appOrigin.replace(/\\/+$/, '')}/review/${name === '<name>' ? name : encodeURIComponent(name)}`\n return path && path !== '/' ? `${base}?path=${encodeURIComponent(path)}` : base\n}\n", "// Where Fling itself is published: the npm package of the CLI (apps/cli/package.json `name`, kept\n// in step by a test) and the GitHub repository, which is also the Claude Code plugin marketplace.\n// The one place code names either; everything else imports these.\n\nexport const CLI_PACKAGE = '@nearform/fling'\nexport const REPO_SLUG = 'nearform/fling'\n\n/** The command an instance's metadata advertises unless it configures its own. */\nexport const DEFAULT_INSTALL_COMMAND = `npm install -g ${CLI_PACKAGE}`\n", "// Groups: a named, reusable list of people (a team) that a site's audience can name. Any member of\n// the instance lists them, sees who is in one and uses it in an audience; only its owner, who made\n// it, renames it, changes its members or deletes it. Clients name a group by its slug, unique on\n// the instance. The contract, and the words the CLI and both MCP servers describe groups with.\n// Browser-safe (zod only).\n\nimport { z } from 'zod'\nimport { type AudienceEmail, AudienceEmailSchema, audienceList, groupLabel } from './audience.ts'\n\n/** The most members a group holds. */\nexport const GROUP_MEMBERS_MAX = 500\nexport const GROUP_SLUG_MAX = 50\nexport const GROUP_NAME_MAX = 100\n\nconst GROUP_SLUG_RE = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/\n\n/** 1-50 lowercase letters, digits and single hyphens, like a site name (without the reserved list). */\nexport function isValidGroupSlug(slug: string): boolean {\n return slug.length <= GROUP_SLUG_MAX && GROUP_SLUG_RE.test(slug) && !slug.includes('--')\n}\n\nexport const GROUP_SLUG_RULES = `1-${GROUP_SLUG_MAX} lowercase letters, digits and single hyphens`\n\nexport const GroupSlugSchema = z\n .string()\n .trim()\n .toLowerCase()\n .refine(isValidGroupSlug, `A group's slug is ${GROUP_SLUG_RULES}`)\n\nexport const GroupNameSchema = z.string().trim().min(1).max(GROUP_NAME_MAX)\n\nconst memberEmails = z\n .array(z.string().trim().toLowerCase().min(3).max(254))\n .max(GROUP_MEMBERS_MAX, `A group holds at most ${GROUP_MEMBERS_MAX} people`)\n\n/** A group as lists show it. `size`: how many members it has. */\nexport const GroupSummarySchema = z.object({\n slug: z.string(),\n name: z.string(),\n /** the email of the user who made it, the only one who may change it */\n owner: z.string(),\n size: z.number(),\n createdAt: z.string(),\n updatedAt: z.string(),\n})\nexport type GroupSummary = z.infer<typeof GroupSummarySchema>\n\n/**\n * GET /api/groups[?mine=1][&members=a@x,b@y]: every group on the instance (or the caller's own),\n * by slug. With `members`, only the groups whose members are exactly those addresses.\n */\nexport const GroupListSchema = z.object({ groups: z.array(GroupSummarySchema) })\n\n/** GET /api/groups/:slug: the group with its members; `canManage` when the caller owns it. */\nexport const GroupDetailSchema = GroupSummarySchema.extend({\n members: z.array(AudienceEmailSchema),\n canManage: z.boolean(),\n})\nexport type GroupDetail = z.infer<typeof GroupDetailSchema>\n\n/**\n * POST /api/groups { slug, name, members? } \u2192 GroupDetailSchema (201). A slug in use is a 409\n * `group_taken`; a member the instance wouldn't let sign in is a 400 `email_not_allowed`.\n */\nexport const CreateGroupRequestSchema = z.object({\n slug: GroupSlugSchema,\n name: GroupNameSchema,\n members: memberEmails.optional(),\n})\nexport type CreateGroupRequest = z.input<typeof CreateGroupRequestSchema>\n\n/** PATCH /api/groups/:slug { name } \u2192 GroupDetailSchema. The owner only (else 403). */\nexport const UpdateGroupRequestSchema = z.object({ name: GroupNameSchema })\n\n/**\n * POST /api/groups/:slug/members { add?, remove? } \u2192 GroupDetailSchema: adds, then removes. The\n * owner only (else 403); DELETE /api/groups/:slug (204) likewise, and takes the group out of every\n * audience that names it.\n */\nexport const GroupMembersRequestSchema = z.object({\n add: memberEmails.optional(),\n remove: memberEmails.optional(),\n})\nexport type GroupMembersRequest = z.input<typeof GroupMembersRequestSchema>\n\n/** `a, b` (or several such values) \u2192 the group slugs, normalised. */\nexport function splitGroups(values: string | readonly string[]): string[] {\n const all = typeof values === 'string' ? [values] : values\n return all\n .flatMap(v => v.split(/[\\s,;]+/))\n .map(s => s.trim().toLowerCase())\n .filter(Boolean)\n}\n\n/** One line per group, for the CLI and both MCP servers. */\nexport function describeGroups(groups: readonly GroupSummary[], me?: string): string {\n if (groups.length === 0) return 'No groups yet.'\n return groups\n .map(g => `- ${groupLabel(g)}, owned by ${g.owner === me ? 'you' : g.owner}`)\n .join('\\n')\n}\n\n/** A group and its members, for the CLI and both MCP servers. */\nexport function describeGroup(group: GroupDetail): string {\n const members: readonly AudienceEmail[] = group.members\n const who = group.canManage\n ? 'you (you can change it)'\n : `${group.owner} (only they can change it)`\n return [\n `${groupLabel(group)}, owned by ${who}.`,\n members.length ? `Members: ${audienceList(members)}.` : 'No members yet.',\n ].join('\\n')\n}\n", "// Which first labels of a sites host are sites (`<name>`) or share links (`s--<token>`).\n// Dependency-free and in the CloudFront Functions syntax subset (see site-routing.ts): the edge\n// bundles it.\n\nexport const SITE_NAME_MAX = 50\nexport const SHARE_TOKEN_LENGTH = 20\n\n/** Names that would be confusing or that we may want for ourselves. */\nexport const RESERVED_SITE_NAMES: readonly string[] = [\n 'admin',\n 'api',\n 'app',\n 'assets',\n 'auth',\n 'cdn',\n 'docs-fling',\n 'fling',\n 'help',\n 'login',\n 'mail',\n 'static',\n 'status',\n 'www',\n]\n\nconst SLUG_RE = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/\nconst SHARE_TOKEN_RE = new RegExp(`^[a-z0-9]{${SHARE_TOKEN_LENGTH}}$`)\n\nexport function isValidSiteName(name: string): boolean {\n return (\n name.length <= SITE_NAME_MAX &&\n SLUG_RE.test(name) &&\n !name.includes('--') &&\n !RESERVED_SITE_NAMES.includes(name)\n )\n}\n\nexport type ParsedLabel = { kind: 'site'; name: string } | { kind: 'share'; token: string }\n\n/** Parse the first DNS label of a sites-domain host. Returns null for anything malformed. */\nexport function parseLabel(label: string): ParsedLabel | null {\n const parts = label.split('--')\n if (parts.length === 1) return isValidSiteName(label) ? { kind: 'site', name: label } : null\n if (parts.length === 2 && parts[0] === 's' && SHARE_TOKEN_RE.test(parts[1] || '')) {\n return { kind: 'share', token: parts[1] as string }\n }\n return null\n}\n", "// Naming rules for sites and the hostnames they are served on.\n//\n// Site names are one global namespace (first come, first served): a site lives at\n// `<name>.<sitesDomain>`. A share link lives at `s--<token>.<sitesDomain>`. Site\n// names may not contain `--`, so the two can never collide.\n\nexport {\n isValidSiteName,\n type ParsedLabel,\n parseLabel,\n RESERVED_SITE_NAMES,\n SHARE_TOKEN_LENGTH,\n SITE_NAME_MAX,\n} from './site-labels.ts'\n\nimport { SITE_NAME_MAX } from './site-labels.ts'\n\nexport const USER_SLUG_MAX = 20\n\nexport function slugify(input: string, max = SITE_NAME_MAX): string {\n return input\n .normalize('NFKD')\n .replace(/[\u0300-\u036F]/g, '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, max)\n .replace(/-+$/g, '')\n}\n\nexport function userSlugFromEmail(email: string): string {\n const local = email.split('@')[0] ?? ''\n return slugify(local, USER_SLUG_MAX) || 'user'\n}\n\n/** `clifton.cunningham@\u2026` \u2192 `cc`; a single-word local part gives its first two letters. */\nexport function initialsFromEmail(email: string): string {\n const words = slugify(email.split('@')[0] ?? '', 64)\n .split('-')\n .filter(Boolean)\n if (words.length === 0) return 'x'\n if (words.length === 1) return (words[0] as string).slice(0, 2)\n return words\n .map(w => w[0])\n .join('')\n .slice(0, 4)\n}\n\n/**\n * Free-name candidates when `name` belongs to someone else: `<name>-<initials>`,\n * `<name>-<initials>2`, \u2026 (the base is trimmed so each stays within SITE_NAME_MAX).\n */\nexport function nameSuggestions(name: string, initials: string, count: number): string[] {\n const out: string[] = []\n for (let i = 1; out.length < count; i++) {\n const suffix = `-${initials}${i === 1 ? '' : i}`\n const base = name.slice(0, SITE_NAME_MAX - suffix.length).replace(/-+$/, '')\n out.push(`${base}${suffix}`)\n }\n return out\n}\n\n/** The DNS label a site is served on \u2014 just its name. */\nexport function siteLabel(name: string): string {\n return name\n}\n\nexport function shareLabel(token: string): string {\n return `s--${token}`\n}\n\nexport function siteUrl(label: string, sitesDomain: string, protocol = 'https:'): string {\n return `${protocol}//${label}.${sitesDomain}/`\n}\n", "// Instance metadata: what a Fling deployment says about itself at `GET /.well-known/fling` on its\n// app origin. Published artifacts (the CLI, the MCP servers, the web build) carry no instance\n// values; they read these instead. Browser-safe (zod only).\n//\n// Versioned for evolution: `version` only goes up for a change old clients cannot read, every\n// object is loose (unknown fields are kept, never rejected), and new fields are optional. A client\n// accepts any document that has the fields it needs.\n\nimport { z } from 'zod'\n\nexport const INSTANCE_METADATA_PATH = '/.well-known/fling'\nexport const INSTANCE_METADATA_VERSION = 1\n/** `Cache-Control` max-age of the metadata, in seconds. */\nexport const INSTANCE_METADATA_MAX_AGE = 300\n\n/** `#rgb` or `#rrggbb`: the only colour syntax brand config accepts (it ends up in CSS). */\nexport const HEX_COLOR_RE = /^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i\n\nconst color = z.string().regex(HEX_COLOR_RE)\n\n/**\n * How people sign in. `kind` names the method: `oidc` (the instance's OpenID Connect `issuer`) or\n * `dev` (local dev login); clients show `displayName` (\"Sign in with \u2026\") and must tolerate kinds\n * they don't know. A verified email gets in if its domain is in `emailDomains`, or if it is one of\n * the instance's invited addresses (`invitedEmails`: there are some; the addresses themselves are\n * never published).\n */\nexport const InstanceAuthSchema = z.looseObject({\n kind: z.string().min(1),\n displayName: z.string().min(1),\n issuer: z.string().optional(),\n emailDomains: z.array(z.string()).default([]),\n invitedEmails: z.boolean().optional(),\n})\nexport type InstanceAuth = z.infer<typeof InstanceAuthSchema>\n\n/**\n * The colours a deployment may set; the web derives every shade from these. `primary` backs\n * primary buttons and active states (with `primaryContent` on it), `accent` is links and focus,\n * `ink` is text and the dark chrome, `highlight` a decorative third colour.\n */\nexport const BrandColorsSchema = z.looseObject({\n primary: color.optional(),\n primaryContent: color.optional(),\n accent: color.optional(),\n ink: color.optional(),\n highlight: color.optional(),\n})\nexport type BrandColors = z.infer<typeof BrandColorsSchema>\n\n/** Looks. Every field is optional: without them the web's neutral default theme applies. */\nexport const InstanceBrandSchema = z.looseObject({\n /** https: or data: URL of the logo mark shown before the name (light theme). */\n logoUrl: z.string().optional(),\n /** The same for the dark theme; defaults to `logoUrl`. */\n logoDarkUrl: z.string().optional(),\n faviconUrl: z.string().optional(),\n colors: BrandColorsSchema.default({}),\n})\nexport type InstanceBrand = z.infer<typeof InstanceBrandSchema>\n\nexport const InstanceMetadataSchema = z.looseObject({\n version: z.number().int().min(1),\n /** Display name, e.g. \"Fling\". */\n name: z.string().min(1),\n /** e.g. `https://fling.example.test` (no trailing slash) */\n appOrigin: z.string().url(),\n /** host[:port] sites hang off: a site is `<name>.<sitesDomain>` */\n sitesDomain: z.string().min(1),\n siteScheme: z.enum(['http', 'https']),\n auth: InstanceAuthSchema,\n brand: InstanceBrandSchema.default({ colors: {} }),\n /** Feature flags: a client hides what is missing or false. */\n capabilities: z.record(z.string(), z.boolean()).default({}),\n /** How to install the CLI, e.g. `npm install -g <package>`. */\n installCommand: z.string().min(1),\n})\nexport type InstanceMetadata = z.infer<typeof InstanceMetadataSchema>\n\n/**\n * What every instance has. Features an instance can turn off are added by its config (`comments`,\n * COMMENTS); missing means unsupported.\n */\nexport const CORE_CAPABILITIES = {\n /** the remote MCP connector at `/mcp` */\n remoteMcp: true,\n shareLinks: true,\n publicSites: true,\n archive: true,\n rollback: true,\n /** a private site can be limited to listed people (its audience) */\n audiences: true,\n /** named lists of people (groups.ts) that any member can use in an audience */\n groups: true,\n} as const\n\n/** `https://<name>.sites.example.test/` \u2014 a site's URL on an instance. */\nexport function instanceSiteUrl(\n instance: Pick<InstanceMetadata, 'sitesDomain' | 'siteScheme'>,\n label: string\n): string {\n return `${instance.siteScheme}://${label}.${instance.sitesDomain}/`\n}\n\n/** `https://<name>.sites.example.test`, for copy. */\nexport function instanceSitesPattern(\n instance: Pick<InstanceMetadata, 'sitesDomain' | 'siteScheme'>\n) {\n return `${instance.siteScheme}://<name>.${instance.sitesDomain}`\n}\n\n/** `@example.test` / `@a.test or @b.test`, or null when any verified email may sign in. */\nexport function emailDomainsPhrase(auth: Pick<InstanceAuth, 'emailDomains'>): string | null {\n const domains = auth.emailDomains.map(d => `@${d}`)\n if (domains.length === 0) return null\n return domains.length === 1\n ? (domains[0] as string)\n : `${domains.slice(0, -1).join(', ')} or ${domains.at(-1)}`\n}\n\n/**\n * The accounts that may sign in, for copy: `@example.test accounts`, `invited accounts`,\n * `@example.test accounts and invited accounts`, or null when any verified email may sign in.\n */\nexport function allowedAccountsPhrase(\n auth: Pick<InstanceAuth, 'emailDomains' | 'invitedEmails'>\n): string | null {\n const domains = emailDomainsPhrase(auth)\n const parts = [domains && `${domains} accounts`, auth.invitedEmails && 'invited accounts']\n return parts.filter(Boolean).join(' and ') || null\n}\n\n/**\n * Who may open a private site, for copy: \"anyone signed in to Fling (@example.test accounts)\".\n */\nexport function privateAudience(instance: Pick<InstanceMetadata, 'name' | 'auth'>): string {\n const accounts = allowedAccountsPhrase(instance.auth)\n return `anyone signed in to ${instance.name}${accounts ? ` (${accounts})` : ''}`\n}\n\n/** The metadata URL of the instance at `serverUrl`. */\nexport function instanceMetadataUrl(serverUrl: string): string {\n return `${serverUrl.replace(/\\/+$/, '')}${INSTANCE_METADATA_PATH}`\n}\n", "import { z } from 'zod'\n\n// The route table contract between the API (writer) and the edge (reader: the shared routing\n// function in site-routing.ts, run by the CloudFront Function and the Worker). Values must stay\n// under 1 KB (CloudFront KeyValueStore). The keys live in route-keys.ts, which has no\n// dependencies, so the CloudFront Function bundle stays small.\n\nexport * from './route-keys.ts'\n\nexport const KvsSiteValueSchema = z.object({\n /** siteId \u2014 S3 prefix is `sites/<id>/<v>/` */\n id: z.string(),\n /** current versionId */\n v: z.string(),\n vis: z.enum(['private', 'public']),\n /** serve /index.html for unknown extensionless paths */\n spa: z.boolean(),\n /** present when the site is restricted (private with an audience): the edge wants a site pass */\n r: z.literal(1).optional(),\n})\nexport type KvsSiteValue = z.infer<typeof KvsSiteValueSchema>\n\nexport const siteObjectKey = (siteId: string, versionId: string, path: string) =>\n `sites/${siteId}/${versionId}/${path}`\nexport const siteVersionPrefix = (siteId: string, versionId: string) =>\n `sites/${siteId}/${versionId}/`\nexport const sitePrefix = (siteId: string) => `sites/${siteId}/`\n", "// Route table keys and the edge's special paths. Dependency-free: the CloudFront Function bundles\n// this (see site-routing.ts for the syntax it may use).\n\n/** `site:<name>` \u2192 routing for a live (non-archived) site. */\nexport const siteKvsKey = (label: string) => `site:${label}`\n/** `share:<token>` \u2192 routing for a share link; served without auth. */\nexport const shareKvsKey = (token: string) => `share:${token}`\n/** HMAC key the edge uses to verify the `fling_site` cookie. */\nexport const SITE_HMAC_KVS_KEY = 'cfg:site-hmac'\n\n/** Object key that never exists; the edge rewrites unknown hosts here so S3 404s into the error page. */\nexport const MISSING_KEY = '/_fling/missing'\nexport const NOT_FOUND_PAGE = '/_fling/404.html'\n/** The review shell (review-bridge.ts): a static page on every sites host that frames the site. */\nexport const REVIEW_SHELL = '/_fling/review.html'\n/** Every sites host's `/robots.txt` (site-routing.ts): `Disallow: /`, so no site is indexed. */\nexport const ROBOTS_TXT = '/_fling/robots.txt'\n/**\n * Where a restricted site's host turns a pass handoff into a site pass:\n * `/_fling-pass?t=<handoff>&r=<path>` (site-cookie.ts, site-routing.ts). Not under `/_fling/`:\n * on AWS that path is served from the bucket without the site router (the error page's behaviour).\n */\nexport const SITE_PASS_PATH = '/_fling-pass'\n/** The site pass cookie (host-only, on a restricted site's host). */\nexport const SITE_PASS_COOKIE_NAME = 'fling_pass'\n/** How long a site pass lasts: the most a removed viewer keeps seeing the site. */\nexport const SITE_PASS_TTL_SECONDS = 5 * 60\n/**\n * How long a `fling_pass` that says the site refused this browser lasts: the site answers 404\n * until then, and someone added to its audience waits at most this long to get in.\n */\nexport const SITE_DENIED_TTL_SECONDS = 10\n", "// \"List HTML files\": when a fling has no root index.html, the CLI / MCP servers can generate one\n// that links every HTML page in the site. Browser-safe and dependency-free so the CLI, the local\n// MCP server and the remote connector all render the same page.\n\nexport const LISTING_GENERATOR_META = 'fling-listing'\n\nexport type ListingEntry = {\n /** site-relative POSIX path, e.g. `reports/q3.html` */\n path: string\n /** the page's <title>, if it has one */\n title?: string | null\n}\n\nconst escapeHtml = (s: string) =>\n s.replace(\n /[&<>\"']/g,\n c => ({ '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''' })[c] as string\n )\n\n/** Percent-encode each path segment so names with spaces etc. still link correctly. */\nconst hrefFor = (path: string) => path.split('/').map(encodeURIComponent).join('/')\n\n/** Does this HTML carry the generator marker renderHtmlListing() writes? (Checks the <head> only.) */\nexport function isGeneratedListing(html: string): boolean {\n return new RegExp(\n `<meta\\\\s+name=[\"']generator[\"']\\\\s+content=[\"']${LISTING_GENERATOR_META}[\"']`,\n 'i'\n ).test(html.slice(0, 4096))\n}\n\nexport function isHtmlPath(path: string): boolean {\n return /\\.html?$/i.test(path)\n}\n\n/** Pull the <title> text out of an HTML document (first 64 KB is plenty). */\nexport function extractHtmlTitle(html: string): string | null {\n const match = /<title[^>]*>([\\s\\S]*?)<\\/title>/i.exec(html.slice(0, 65536))\n const title = match?.[1]\n ?.replace(/<[^>]*>/g, '')\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/\\s+/g, ' ')\n .trim()\n return title ? title : null\n}\n\n/**\n * Render the listing page. Entries are grouped by folder (root first) and sorted by path;\n * non-HTML paths are ignored, as is a root `index.html` (there isn't one \u2014 that's why we're here).\n */\nexport function renderHtmlListing(siteName: string, entries: readonly ListingEntry[]): string {\n const pages = entries\n .filter(e => isHtmlPath(e.path) && e.path.toLowerCase() !== 'index.html')\n .sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0))\n\n const groups = new Map<string, ListingEntry[]>()\n for (const page of pages) {\n const slash = page.path.lastIndexOf('/')\n const folder = slash === -1 ? '' : page.path.slice(0, slash)\n groups.set(folder, [...(groups.get(folder) ?? []), page])\n }\n\n const sections = [...groups.entries()]\n .sort(([a], [b]) => (a === '' ? -1 : b === '' ? 1 : a < b ? -1 : 1))\n .map(([folder, items]) => {\n const heading = folder ? `<h2>${escapeHtml(folder)}/</h2>` : ''\n const rows = items\n .map(item => {\n const file = item.path.slice(item.path.lastIndexOf('/') + 1)\n const label = item.title ? escapeHtml(item.title) : escapeHtml(file)\n const sub = item.title ? `<span class=\"file\">${escapeHtml(file)}</span>` : ''\n return `<li><a href=\"${hrefFor(item.path)}\">${label}</a>${sub}</li>`\n })\n .join('\\n')\n return `${heading}<ul>\\n${rows}\\n</ul>`\n })\n .join('\\n')\n\n const body = pages.length ? sections : '<p class=\"empty\">No HTML pages in this fling.</p>'\n const count = `${pages.length} page${pages.length === 1 ? '' : 's'}`\n\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<meta name=\"generator\" content=\"${LISTING_GENERATOR_META}\">\n<title>${escapeHtml(siteName)}</title>\n<style>\n :root { color-scheme: light dark; --fg: #000e38; --muted: #5b6480; --bg: #f7f8fb; --card: #fff;\n --line: #e3e6ef; --accent: #166bff; --green: #00e5a4; }\n @media (prefers-color-scheme: dark) { :root { --fg: #eef1f8; --muted: #9aa3bd; --bg: #000e38;\n --card: #0b1a4a; --line: #1d2c5e; --accent: #6ea2ff; } }\n * { box-sizing: border-box; }\n body { margin: 0; font: 16px/1.5 Inter, ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", sans-serif;\n color: var(--fg); background: var(--bg); }\n main { max-width: 760px; margin: 0 auto; padding: 48px 20px 64px; }\n header { border-left: 4px solid var(--green); padding-left: 14px; margin-bottom: 28px; }\n h1 { margin: 0; font-size: 1.6rem; }\n header p, .file, footer { color: var(--muted); font-size: .875rem; }\n header p { margin: 4px 0 0; }\n h2 { font-size: .95rem; margin: 28px 0 8px; color: var(--muted); font-weight: 600; }\n ul { list-style: none; margin: 0; padding: 0; background: var(--card); border: 1px solid var(--line);\n border-radius: 10px; overflow: hidden; }\n li { padding: 12px 16px; border-top: 1px solid var(--line); display: flex; gap: 12px;\n justify-content: space-between; align-items: baseline; flex-wrap: wrap; }\n li:first-child { border-top: 0; }\n a { color: var(--accent); text-decoration: none; font-weight: 500; }\n a:hover { text-decoration: underline; }\n .empty { color: var(--muted); }\n footer { margin-top: 40px; }\n</style>\n</head>\n<body>\n<main>\n<header><h1>${escapeHtml(siteName)}</h1><p>${count}</p></header>\n${body}\n<footer>Flung with Fling</footer>\n</main>\n</body>\n</html>\n`\n}\n", "/**\n * The Fling MCP tool catalogue: names, titles, descriptions and zod input shapes shared by the\n * local server (`fling mcp`, apps/cli) and the remote connector (`POST /mcp`, apps/api), so both\n * describe the same operations the same way. Browser-safe (zod only).\n *\n * The local server reads files from disk (`fling_deploy {path}`); the remote one can't, so it takes\n * content inline (`fling_publish`, or the chunked `fling_upload_*` trio for bigger sites).\n *\n * Descriptions are templates: they name the instance, where its sites live and who can open a\n * private site. Each server renders them with `mcpToolsFor(mcpWording(instance))` \u2014 the remote one\n * from its config, the local one from the instance the CLI is logged in to.\n */\nimport { z } from 'zod'\nimport type { VersionFiles } from './api.ts'\nimport { AUDIENCE_EMAILS_MAX, AUDIENCE_GROUPS_MAX } from './audience.ts'\nimport {\n authorLabel,\n COMMENT_MAX_CHARS,\n type CommentList,\n commentThreads,\n reviewUrl,\n} from './comments.ts'\nimport { GROUP_MEMBERS_MAX, GROUP_NAME_MAX, GROUP_SLUG_RULES } from './groups.ts'\nimport { SITE_NAME_MAX } from './hosts.ts'\nimport { type InstanceMetadata, instanceSitesPattern, privateAudience } from './instance.ts'\nimport { MAX_FILES } from './limits.ts'\nimport { SITE_SORTS } from './site-sort.ts'\n\n/** fling_publish: total decoded bytes per call (fits a ~6 MB request once base64-encoded). */\nexport const MCP_PUBLISH_MAX_BYTES = 4 * 1024 * 1024\n/** fling_upload_file: max `content` length (characters, as sent) per call. */\nexport const MCP_UPLOAD_CHUNK_MAX_CHARS = 4 * 1024 * 1024\n/** Chunked uploads expire this long after fling_upload_begin. */\nexport const MCP_UPLOAD_TTL_SECONDS = 60 * 60\n/** Files per chunked upload. */\nexport const MCP_UPLOAD_MAX_FILES = 1000\n\nexport interface McpToolAnnotations {\n readOnlyHint?: boolean\n destructiveHint?: boolean\n idempotentHint?: boolean\n openWorldHint?: boolean\n}\n\nexport interface McpToolDef<S extends z.ZodRawShape = z.ZodRawShape> {\n name: string\n title: string\n description: string\n inputSchema: S\n annotations: McpToolAnnotations\n}\n\nconst tool = <S extends z.ZodRawShape>(def: McpToolDef<S>) => def\n\n/** The instance-specific words in the descriptions. */\nexport interface McpWording {\n /** The instance's display name, e.g. \"Fling\". */\n name: string\n /** `https://<name>.sites.example.test` */\n sitesPattern: string\n /** Who can open a private site: \"anyone signed in to Fling (@example.test accounts)\". */\n privateAudience: string\n /** How the user signs in: \"their Example SSO account\". */\n signIn: string\n /** Where people review a site in the browser: `https://fling.example.test/review/<name>`. */\n reviewPattern: string\n}\n\nconst GENERIC_REVIEW = \"the site's review page in the Fling web app (/review/<name>)\"\n\n/** Wording for an instance; without one (not logged in yet) it stays generic. */\nexport function mcpWording(\n instance?:\n | (Pick<InstanceMetadata, 'name' | 'sitesDomain' | 'siteScheme' | 'auth'> &\n Partial<Pick<InstanceMetadata, 'appOrigin'>>)\n | null\n): McpWording {\n if (!instance) {\n return {\n name: 'Fling',\n sitesPattern: 'https://<name>.<sites domain>',\n privateAudience: 'people signed in to this Fling',\n signIn: 'the Fling sign-in page',\n reviewPattern: GENERIC_REVIEW,\n }\n }\n return {\n name: instance.name,\n sitesPattern: instanceSitesPattern(instance),\n privateAudience: privateAudience(instance),\n signIn: `their ${instance.auth.displayName} account`,\n reviewPattern: instance.appOrigin ? reviewUrl(instance.appOrigin, '<name>') : GENERIC_REVIEW,\n }\n}\n\n// --- shared wording -----------------------------------------------------------------------------\n\nconst NAME_REQUIRED =\n 'Publishing needs a name: if the user did not give one, propose a short descriptive one (e.g. \"q3-report\") ' +\n 'and confirm it with them first (fling_check_name tells you whether it is free). If the name is taken by someone ' +\n 'else the call fails with free suggestions \u2014 offer those to the user and retry with the one they pick.'\n\nconst INLINE_ONLY =\n 'If you created the content in this conversation, pass it directly \u2014 never pass file paths from your ' +\n 'sandbox (this server cannot read them) and never try to curl/upload from your sandbox.'\n\n/** Shown to Claude wherever files are sent (no override exists, so don't let it look for one). */\nexport const NEVER_PUBLISHED =\n 'Fling never publishes dotfiles, gitignored files, secret files (keys, certs, credentials) or files that contain ' +\n 'secrets (API keys, tokens, private keys, passwords in database URLs); it stops and tells you which file and line. ' +\n 'Remove the secret (or leave the file out) and retry \u2014 there is no way to override this.'\n\nconst ENCODING =\n '`encoding` is \"utf8\" (default, for text: HTML, CSS, JS, SVG, JSON, Markdown\u2026) or \"base64\" (binary: images, fonts, PDFs).'\n\nconst LIST_HTML =\n 'If the files have no root index.html but do include HTML pages, the call does not publish: it reports how ' +\n 'many HTML pages there are and asks you to check with the user. Ask them whether to generate an index.html ' +\n 'listing those pages (retry with `listHtml: true`) or to publish without one (`listHtml: false` \u2014 the site root ' +\n 'will 404, the pages still work at their own paths), then retry.'\n\nconst listHtml = z\n .boolean()\n .optional()\n .describe(\n 'Only matters when there is no root index.html: true \u2192 generate an index.html linking every HTML page; false \u2192 publish without one (root 404s). Omit until the user has decided'\n )\n\nconst siteName = z.string().min(1).max(200).describe('Site name, e.g. \"q3-report\"')\n\nconst sitePath = z\n .string()\n .min(1)\n .max(1024)\n .describe(\n 'Site-relative path with forward slashes, e.g. \"index.html\", \"css/app.css\", \"img/logo.png\". The root page must be \"index.html\". No dotfiles (\".env\", \".well-known/\u2026\")'\n )\n\nconst emails = z.array(z.string().min(3).max(254)).max(AUDIENCE_EMAILS_MAX)\nconst groupSlugs = z.array(z.string().min(1).max(100)).max(AUDIENCE_GROUPS_MAX)\nconst groupSlug = z.string().min(1).max(100).describe('The group\\'s slug, e.g. \"design\"')\nconst members = z.array(z.string().min(3).max(254)).max(GROUP_MEMBERS_MAX)\nconst groupName = z.string().min(1).max(GROUP_NAME_MAX)\n\nconst commentPath = z.string().max(1024)\nconst commentId = z.string().min(1).max(100)\n\nconst encoding = z\n .enum(['utf8', 'base64'])\n .optional()\n .describe('How `content` is encoded: \"utf8\" (default) for text, \"base64\" for binary files')\n\nconst spa = z\n .boolean()\n .optional()\n .describe(\n 'Single-page app: serve index.html for unknown paths (client-side routing). Omit to keep the current setting'\n )\n\n// --- tools --------------------------------------------------------------------------------------\n\n/** The catalogue, its descriptions rendered with `w`. */\nexport function mcpToolsFor(w: McpWording) {\n const NAME_RULES =\n `Site names are 1-${SITE_NAME_MAX} chars of lowercase letters, digits and single hyphens, and are ` +\n `one global namespace (first come, first served): the site is served at ${w.sitesPattern}.`\n\n const VISIBILITY =\n `Sites are private by default (only ${w.privateAudience} can open them); pass \\`public: true\\` only if ` +\n 'the user asks for a public site. Share links (fling_share) are public to anyone who has them.'\n\n const isPublic = z\n .boolean()\n .optional()\n .describe(\n `true \u2192 anyone can view; false \u2192 only ${w.privateAudience}. Omit to keep the current setting (new sites are private)`\n )\n\n return {\n whoami: tool({\n name: 'fling_whoami',\n title: 'Who am I',\n description: `Show the signed-in user that ${w.name} acts as.`,\n inputSchema: {},\n annotations: { readOnlyHint: true, openWorldHint: false },\n }),\n\n list: tool({\n name: 'fling_list',\n title: 'List sites',\n description:\n \"List the user's Fling sites with URL, visibility and share link. With `shared: true`, list instead \" +\n \"the restricted sites other people have shared with the user (by address or through a group they're in), \" +\n 'with URL, review link and owner.',\n inputSchema: {\n archived: z.boolean().optional().describe('List archived sites instead of live ones'),\n shared: z\n .boolean()\n .optional()\n .describe(\"List the sites others have shared with the user instead of the user's own\"),\n sort: z\n .enum(SITE_SORTS)\n .optional()\n .describe(\n 'Order: updated (last updated, newest first; the default), created (newest first) or name (A\u2013Z)'\n ),\n },\n annotations: { readOnlyHint: true, openWorldHint: false },\n }),\n\n info: tool({\n name: 'fling_info',\n title: 'Site details',\n description:\n 'Show one site: URL, visibility, share link, current version and version history (ids for fling_rollback).',\n inputSchema: { name: siteName },\n annotations: { readOnlyHint: true, openWorldHint: false },\n }),\n\n files: tool({\n name: 'fling_files',\n title: 'List site files',\n description:\n \"List the files in a site's current version (or in `versionId`, from fling_info): path, size and content \" +\n 'type, sorted by path. Use it to check what was actually published \u2014 e.g. when the user sees a 404, confirm ' +\n 'the page exists at that path and that there is a root index.html (without one the site root 404s).',\n inputSchema: {\n name: siteName,\n versionId: z\n .string()\n .min(1)\n .max(100)\n .optional()\n .describe('Version id (from fling_info); omit for the version being served'),\n },\n annotations: { readOnlyHint: true, openWorldHint: false },\n }),\n\n checkName: tool({\n name: 'fling_check_name',\n title: 'Check a site name',\n description:\n 'Check whether a site name can be used before publishing: `available` (a new site), `yours` (publishing ' +\n \"updates the user's existing site), `taken` (someone else's \u2014 free `suggestions` are returned) or `invalid`. \" +\n NAME_RULES,\n inputSchema: { name: z.string().min(1).max(200).describe('Site name to check') },\n annotations: { readOnlyHint: true, openWorldHint: false },\n }),\n\n publish: tool({\n name: 'fling_publish',\n title: 'Publish a site',\n description:\n 'Publish a static site to Fling in one call and get back its URL. Pass every file of the site inline in ' +\n `\\`files\\` (whole site, up to ${MCP_PUBLISH_MAX_BYTES / 1024 / 1024} MB decoded in total; bigger sites: ` +\n `fling_upload_begin / fling_upload_file / fling_upload_finish). ${INLINE_ONLY} ${ENCODING} ` +\n 'Publishing replaces the whole site with exactly these files (it is not a patch: include unchanged files too); ' +\n 'publishing identical content again is a no-op. ' +\n `${NAME_REQUIRED} ${NAME_RULES} ${VISIBILITY} ${LIST_HTML} ${NEVER_PUBLISHED} ` +\n 'The result includes `warnings`. Share the returned URL with the user; fling_files shows exactly which files ' +\n 'the site has.',\n inputSchema: {\n name: siteName,\n files: z\n .array(\n z.object({\n path: sitePath,\n content: z.string().describe('The file content, encoded as `encoding` says'),\n encoding,\n })\n )\n .min(1)\n .max(MAX_FILES)\n .describe('Every file of the site'),\n spa,\n public: isPublic,\n listHtml,\n },\n annotations: { destructiveHint: false, idempotentHint: true, openWorldHint: true },\n }),\n\n uploadBegin: tool({\n name: 'fling_upload_begin',\n title: 'Start a chunked upload',\n description:\n `Start publishing a site too big for one fling_publish call (over ${MCP_PUBLISH_MAX_BYTES / 1024 / 1024} MB, ` +\n 'or large binary files). Returns an `uploadId`; then send each file with fling_upload_file and finish with ' +\n `fling_upload_finish within ${MCP_UPLOAD_TTL_SECONDS / 60} minutes. ${INLINE_ONLY} ` +\n `${NAME_REQUIRED} ${VISIBILITY}`,\n inputSchema: { name: siteName, spa, public: isPublic },\n annotations: { destructiveHint: false, openWorldHint: false },\n }),\n\n uploadFile: tool({\n name: 'fling_upload_file',\n title: 'Upload a file (chunked)',\n description:\n 'Add one file to a chunked upload started with fling_upload_begin. Sending the same path again replaces it. ' +\n `A file larger than ${MCP_UPLOAD_CHUNK_MAX_CHARS / 1024 / 1024} MB of content can span calls: send the first ` +\n 'part normally, then the following parts in order with `append: true` (same path and encoding; send appends ' +\n `one at a time, not in parallel). ${ENCODING} ${NEVER_PUBLISHED}`,\n inputSchema: {\n uploadId: z.string().min(1).max(100).describe('From fling_upload_begin'),\n path: sitePath,\n content: z\n .string()\n .max(MCP_UPLOAD_CHUNK_MAX_CHARS)\n .describe('The file content (or the next part of it, with `append`)'),\n encoding,\n append: z\n .boolean()\n .optional()\n .describe('Append this content to the file sent earlier with the same path'),\n },\n annotations: { destructiveHint: false, openWorldHint: false },\n }),\n\n uploadFinish: tool({\n name: 'fling_upload_finish',\n title: 'Finish a chunked upload',\n description:\n 'Publish everything sent with fling_upload_file as the new version of the site and return its URL. The site ' +\n `becomes exactly the uploaded files. ${LIST_HTML} The upload stays open, so just call fling_upload_finish ` +\n 'again with `listHtml`. The result includes `warnings`.',\n inputSchema: {\n uploadId: z.string().min(1).max(100).describe('From fling_upload_begin'),\n listHtml,\n },\n annotations: { destructiveHint: false, openWorldHint: true },\n }),\n\n share: tool({\n name: 'fling_share',\n title: 'Share link',\n description:\n 'Get or create a public share link for a site: anyone with the link can view it without signing in (use it to ' +\n 'show a private site to someone who cannot sign in). `refresh` replaces the link (the old one stops working); ' +\n '`revoke` removes it.',\n inputSchema: {\n name: siteName,\n refresh: z.boolean().optional().describe('Rotate the link'),\n revoke: z.boolean().optional().describe('Remove the link'),\n },\n annotations: { destructiveHint: false, openWorldHint: true },\n }),\n\n setVisibility: tool({\n name: 'fling_set_visibility',\n title: 'Set visibility',\n description: `Make a site private (open to ${w.privateAudience}) or public (anyone can open the site; its review page and comments still need sign-in).`,\n inputSchema: { name: siteName, visibility: z.enum(['private', 'public']) },\n annotations: { idempotentHint: true, openWorldHint: true },\n }),\n\n setAudience: tool({\n name: 'fling_set_audience',\n title: 'Set who can see a private site',\n description:\n `Limit a private site to listed people and groups (its audience), or open it again to ${w.privateAudience}. ` +\n '`add` and `remove` change the addresses and `set` replaces them; `addGroups`, `removeGroups` and ' +\n '`setGroups` do the same for groups, by slug (fling_groups lists them); `clear` empties both (then every ' +\n 'signed-in member can see it again). The owner always sees the site. Each address must be one that can ' +\n `sign in to ${w.name}. The audience only applies while the site is private (fling_set_visibility); share ` +\n 'links still open it to anyone. Removing someone takes up to 5 minutes to shut them out. fling_info shows ' +\n 'the audience.',\n inputSchema: {\n name: siteName,\n add: emails.optional().describe('Addresses to let in'),\n remove: emails.optional().describe('Addresses to take out'),\n set: emails.optional().describe('Replace the addresses with exactly these'),\n addGroups: groupSlugs.optional().describe('Groups (slugs) to let in'),\n removeGroups: groupSlugs.optional().describe('Groups (slugs) to take out'),\n setGroups: groupSlugs.optional().describe('Replace the groups with exactly these slugs'),\n clear: z\n .boolean()\n .optional()\n .describe('Empty the audience (addresses and groups): every signed-in member sees it'),\n },\n annotations: { idempotentHint: true, openWorldHint: false },\n }),\n\n groups: tool({\n name: 'fling_groups',\n title: 'List groups',\n description:\n `List the groups on ${w.name}: named lists of people (a team) that any member can use in a site's ` +\n 'audience (fling_set_audience `addGroups`). Each has a slug, a name, a size and an owner; `mine` lists only ' +\n \"the user's own. `members` lists only the groups of exactly those people: use it before making a group, \" +\n 'or to swap a list of addresses in an audience for a group that already holds them.',\n inputSchema: {\n mine: z.boolean().optional().describe('Only the groups the user owns'),\n members: members\n .optional()\n .describe('Only the groups whose members are exactly these addresses'),\n },\n annotations: { readOnlyHint: true, openWorldHint: false },\n }),\n\n groupShow: tool({\n name: 'fling_group_show',\n title: 'Show a group',\n description:\n 'Show a group and its members (each marked when they have not signed in yet), and whether the user owns ' +\n 'it (only the owner can change it).',\n inputSchema: { slug: groupSlug },\n annotations: { readOnlyHint: true, openWorldHint: false },\n }),\n\n groupCreate: tool({\n name: 'fling_group_create',\n title: 'Create a group',\n description:\n `Create a group the user owns: a named list of people that anyone signed in to ${w.name} can see and use ` +\n `in a site's audience, but only the user can change. The slug is ${GROUP_SLUG_RULES}, unique on ` +\n `${w.name}; each member must be an address that can sign in (at most ${GROUP_MEMBERS_MAX}).`,\n inputSchema: {\n slug: groupSlug,\n name: groupName.describe('Its display name, e.g. \"Design team\"'),\n members: members.optional().describe('Addresses to put in it'),\n },\n annotations: { destructiveHint: false, openWorldHint: false },\n }),\n\n groupMembers: tool({\n name: 'fling_group_members',\n title: 'Change who is in a group',\n description:\n 'Add people to a group the user owns, or take them out. Every site whose audience names the group follows: someone taken out is shut out within 5 minutes.',\n inputSchema: {\n slug: groupSlug,\n add: members.optional().describe('Addresses to add'),\n remove: members.optional().describe('Addresses to take out'),\n },\n annotations: { idempotentHint: true, openWorldHint: false },\n }),\n\n groupRename: tool({\n name: 'fling_group_rename',\n title: 'Rename a group',\n description: 'Change the display name of a group the user owns (the slug stays).',\n inputSchema: { slug: groupSlug, name: groupName.describe('The new display name') },\n annotations: { idempotentHint: true, openWorldHint: false },\n }),\n\n groupDelete: tool({\n name: 'fling_group_delete',\n title: 'Delete a group',\n description:\n 'Permanently delete a group the user owns. Sites whose audience names it keep their restriction, and anyone ' +\n 'it let in loses access (a site limited to it alone is left to its owner). Cannot be undone \u2014 confirm with the user ' +\n 'first and pass `confirm: true`.',\n inputSchema: {\n slug: groupSlug,\n confirm: z.literal(true).describe('Must be true: the user has confirmed the deletion'),\n },\n annotations: { destructiveHint: true, openWorldHint: false },\n }),\n\n archive: tool({\n name: 'fling_archive',\n title: 'Archive or restore a site',\n description:\n 'Archive a site (it stops being served and is hidden from lists, but its name, files and versions are kept) ' +\n 'or, with `unarchive`, bring it back. Prefer this over deleting.',\n inputSchema: {\n name: siteName,\n unarchive: z.boolean().optional().describe('Restore an archived site'),\n },\n annotations: { idempotentHint: true, openWorldHint: false },\n }),\n\n delete: tool({\n name: 'fling_delete',\n title: 'Delete a site',\n description:\n 'Permanently delete a site and every version of it, freeing its name. Cannot be undone \u2014 confirm with the user ' +\n 'first and pass `confirm: true`. Consider fling_archive instead.',\n inputSchema: {\n name: siteName,\n confirm: z.literal(true).describe('Must be true: the user has confirmed the deletion'),\n },\n annotations: { destructiveHint: true, openWorldHint: false },\n }),\n\n commentsList: tool({\n name: 'fling_comments_list',\n title: 'List comments',\n description:\n `List the comments people left on a site while reviewing it (${w.reviewPattern}), as threads: each ` +\n 'has the page path it is about, the version the site was serving when it was written, its replies, and ' +\n `whether it is resolved. Anyone signed in to ${w.name} can comment on a site they can open. Resolved threads ` +\n 'are left out unless `includeResolved`. Use it to act on feedback: fix the site, republish, then resolve ' +\n 'the threads with fling_comment_resolve.',\n inputSchema: {\n name: siteName,\n path: commentPath.optional().describe('Only this page, e.g. \"/\" or \"/docs/\"'),\n includeResolved: z.boolean().optional().describe('Include resolved threads'),\n },\n annotations: { readOnlyHint: true, openWorldHint: false },\n }),\n\n commentAdd: tool({\n name: 'fling_comment_add',\n title: 'Add a comment',\n description:\n `Comment on a page of a site (shown on its review page, ${w.reviewPattern}), or reply to a thread ` +\n \"(`replyTo`: a thread id from fling_comments_list). Comments are signed with the user's name, so only \" +\n 'write one the user asked for.',\n inputSchema: {\n name: siteName,\n body: z.string().min(1).max(COMMENT_MAX_CHARS).describe('The comment (plain text)'),\n path: commentPath\n .optional()\n .describe('The page it is about (default \"/\"); ignored for a reply'),\n replyTo: commentId.optional().describe('Reply to this thread instead of starting one'),\n },\n annotations: { destructiveHint: false, openWorldHint: true },\n }),\n\n commentResolve: tool({\n name: 'fling_comment_resolve',\n title: 'Resolve a comment thread',\n description:\n 'Mark a comment thread resolved (e.g. after fixing what it asks for), or reopen it with `reopen: true`. ' +\n 'Thread ids come from fling_comments_list.',\n inputSchema: {\n name: siteName,\n id: commentId.describe('The thread id'),\n reopen: z.boolean().optional().describe('Reopen a resolved thread'),\n },\n annotations: { idempotentHint: true, openWorldHint: false },\n }),\n\n commentDelete: tool({\n name: 'fling_comment_delete',\n title: 'Delete a comment',\n description:\n 'Delete a comment; deleting a thread deletes its replies. People can delete their own comments, and ' +\n \"a site's owner anyone's. Cannot be undone: prefer fling_comment_resolve, and confirm with the user first.\",\n inputSchema: { name: siteName, id: commentId.describe('The comment id') },\n annotations: { destructiveHint: true, openWorldHint: false },\n }),\n\n rollback: tool({\n name: 'fling_rollback',\n title: 'Roll back',\n description:\n 'Point a site at an earlier version (ids from fling_info). Instant; nothing is uploaded.',\n inputSchema: {\n name: siteName,\n versionId: z.string().min(1).max(100).describe('Version id to serve'),\n },\n annotations: { idempotentHint: true, openWorldHint: false },\n }),\n } as const\n}\n\nexport type McpTools = ReturnType<typeof mcpToolsFor>\n\n/**\n * The catalogue with generic wording: for tool names and input schemas. Servers register\n * `mcpToolsFor(mcpWording(instance))` so the descriptions name the instance.\n */\nexport const mcpTools: McpTools = mcpToolsFor(mcpWording())\n\n/** Sent at `initialize` by the remote server. */\nexport const mcpRemoteInstructions = (w: McpWording, opts: { comments?: boolean } = {}) =>\n [\n `${w.name} publishes static sites (HTML/CSS/JS, images, documents) at ${w.sitesPattern}.`,\n 'To publish content you created in this conversation (an HTML page, a report, a small app): call fling_publish with ' +\n 'every file inline (text as utf8, binary as base64). This server cannot read files in your sandbox and your sandbox ' +\n 'cannot reach Fling, so never pass sandbox file paths and never curl or upload from the sandbox. Make the site ' +\n 'self-contained: an index.html at the root, relative links between files.',\n 'Every site needs a name. If the user did not give one, propose a short descriptive name and confirm it before ' +\n 'publishing (fling_check_name shows whether it is free). Names are global and first come, first served; when a ' +\n 'name is taken, offer the returned suggestions.',\n `Sites are private (open to ${w.privateAudience}) by default. Only make one public if asked; to show a private ` +\n 'site to someone who cannot sign in, create a share link with fling_share.',\n 'If a site has HTML pages but no root index.html, fling_publish / fling_upload_finish stop and ask: check with ' +\n 'the user whether to generate an index.html listing the pages (`listHtml: true`) or publish without one ' +\n '(`listHtml: false`, the root URL will 404), then retry.',\n NEVER_PUBLISHED,\n `For sites over ${MCP_PUBLISH_MAX_BYTES / 1024 / 1024} MB use fling_upload_begin, fling_upload_file (repeat, ` +\n '`append` for big files) and fling_upload_finish.',\n (opts.comments\n ? 'Always give the user the links that come back: the review link first, as the one to share for feedback, then the site URL. '\n : 'Always give the user the URL that comes back. ') +\n 'Use fling_list / fling_info to find existing sites, fling_rollback ' +\n 'to restore a version, fling_archive rather than fling_delete unless the user insists. Use fling_files to see ' +\n 'exactly which files a site has (e.g. when the user reports a 404).',\n ...(opts.comments ? [COMMENTS_NOTE(w)] : []),\n ].join('\\n\\n')\n\n/** What the servers say about comments, when the instance has them. */\nexport const COMMENTS_NOTE = (w: McpWording) =>\n `People review sites at ${w.reviewPattern} and leave comments on its pages. Publishing returns this review link ` +\n '(`reviewUrl`): it is the one to share when the user wants feedback; reviewers sign in to use it. ' +\n 'fling_comments_list shows the comments; ' +\n 'after acting on feedback, resolve the threads with fling_comment_resolve. Only post (fling_comment_add) or ' +\n 'delete (fling_comment_delete) comments when the user asks.'\n\n/**\n * The line a publish result leads with when the instance has comments (both servers): the review\n * page is the link to share for feedback, and reviewers sign in to use it.\n */\nexport const shareForFeedback = (reviewPage: string, instanceName: string) =>\n `Share for feedback: ${reviewPage} (reviewers sign in to ${instanceName} to see the site and comment).`\n\n/** Max files listed in a fling_files text result (structured data always has them all). */\nexport const MCP_FILES_LISTED = 200\n\n/**\n * The text of a fling_files result (both servers): a header, a root-404 warning when there is no\n * index.html, then one `path (size, type)` line per file.\n */\nexport function describeVersionFiles(\n name: string,\n files: VersionFiles,\n opts: { current: boolean; url?: string | null }\n): string {\n const kb = (n: number) =>\n n < 1024\n ? `${n} B`\n : n < 1024 * 1024\n ? `${(n / 1024).toFixed(1)} KB`\n : `${(n / 1024 / 1024).toFixed(1)} MB`\n const n = files.files.length\n const which = opts.current ? 'current version' : 'version'\n const lines = [\n `${name} ${which} ${files.versionId}: ${n} file${n === 1 ? '' : 's'}, ${kb(files.totalBytes)}` +\n (opts.current && opts.url ? ` \u2014 served at ${opts.url}` : '') +\n (opts.current ? '' : ' (not the version being served)'),\n ]\n if (!files.files.some(f => f.path === 'index.html')) {\n lines.push(\n 'Warning: there is no index.html at the root, so the site root URL returns 404 (each file still works at its own path).'\n )\n } else if (files.generatedIndex) {\n lines.push('index.html is a generated page listing the HTML pages.')\n }\n for (const f of files.files.slice(0, MCP_FILES_LISTED)) {\n lines.push(`- ${f.path} (${kb(f.size)}, ${f.contentType})`)\n }\n if (n > MCP_FILES_LISTED) lines.push(`\u2026 and ${n - MCP_FILES_LISTED} more`)\n return lines.join('\\n')\n}\n\nexport type McpToolName = (typeof mcpTools)[keyof typeof mcpTools]['name']\n\n/**\n * The text of a fling_comments_list result (both servers): one block per thread \u2014 id, state, page,\n * version, author and body, then its replies indented.\n */\nexport function describeComments(\n list: CommentList,\n opts: { includeResolved?: boolean; reviewUrl?: string } = {}\n): string {\n const all = commentThreads(list.comments)\n const threads = opts.includeResolved ? all : all.filter(t => t.comment.resolvedAt === null)\n const hidden = all.length - threads.length\n const name = list.site.name\n const version = (id: string | null) =>\n id === null ? '' : id === list.site.currentVersionId ? ', current version' : `, version ${id}`\n const head =\n `${threads.length} ${opts.includeResolved ? '' : 'open '}thread${threads.length === 1 ? '' : 's'} on ${name}` +\n (hidden ? ` (${hidden} resolved not shown)` : '') +\n (opts.reviewUrl ? `. Review page: ${opts.reviewUrl}` : '')\n const blocks = threads.map(({ comment: c, replies }) =>\n [\n `- [${c.id}] ${c.resolvedAt ? 'RESOLVED ' : ''}${c.path}${version(c.versionId)} \u2014 ${authorLabel(c.author)}, ${c.createdAt}:`,\n ` ${c.body.replace(/\\n/g, '\\n ')}`,\n ...replies.map(\n r =>\n ` - [${r.id}] ${authorLabel(r.author)}, ${r.createdAt}: ${r.body.replace(/\\n/g, '\\n ')}`\n ),\n ].join('\\n')\n )\n return [head, ...blocks].join('\\n')\n}\n", "// The order sites are listed in, the same in every client (web list, `fling list`, both MCP\n// servers' fling_list). Lists are fetched whole, so sorting happens on the client.\n\nexport const SITE_SORTS = ['updated', 'created', 'name'] as const\n/** `updated`: last updated, newest first; `created`: newest first; `name`: A\u2013Z. */\nexport type SiteSort = (typeof SITE_SORTS)[number]\nexport const DEFAULT_SITE_SORT: SiteSort = 'updated'\n\ntype Sortable = { name: string; createdAt: string; updatedAt: string }\n\nexport function isSiteSort(value: unknown): value is SiteSort {\n return typeof value === 'string' && (SITE_SORTS as readonly string[]).includes(value)\n}\n\nconst byName = (a: Sortable, b: Sortable) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0)\n\n/** A new array in `sort` order; ties (same timestamp) fall back to the name, A\u2013Z. */\nexport function sortSites<T extends Sortable>(\n sites: readonly T[],\n sort: SiteSort = DEFAULT_SITE_SORT\n): T[] {\n const newest = (key: 'createdAt' | 'updatedAt') => (a: T, b: T) =>\n Date.parse(b[key]) - Date.parse(a[key]) || byName(a, b)\n const compare = sort === 'name' ? byName : newest(sort === 'created' ? 'createdAt' : 'updatedAt')\n return [...sites].sort(compare)\n}\n", "/**\n * Readiness wait after a site (or share link) goes live. A new site reaches CloudFront's\n * KeyValueStore at every edge within seconds, not instantly; a browser that opens the link in that\n * window sees the 404 page. So after a deploy that went live (`live`/`repointed`) or a new/rotated\n * share link, the CLI and both MCP servers poll the URL until the edge routes it.\n *\n * Used by apps/cli (CLI commands + local MCP) and apps/api (remote MCP). Browser-safe: `fetch`,\n * `sleep` and `now` are injectable so tests never touch the network or the clock.\n */\n\nexport interface ReachableResult {\n /** the edge routes the URL (2xx, 3xx \u2014 e.g. the sign-in redirect of a private site \u2014 401, 403) */\n ready: boolean\n waitedMs: number\n}\n\nexport interface WaitOptions {\n timeoutMs?: number\n fetch?: (url: string, init: RequestInit) => Promise<Response>\n sleep?: (ms: number) => Promise<void>\n now?: () => number\n /** first delay between polls (default 750 ms); grows by 1.25\u00D7 up to 2 s */\n intervalMs?: number\n /** called once, when the first poll says \"not yet\" (the CLI starts its spinner) */\n onWaiting?: () => void\n}\n\nexport const READY_TIMEOUT_MS = 15_000\n/** The remote MCP runs in a Lambda behind a ~10 s connector timeout. */\nexport const READY_TIMEOUT_LAMBDA_MS = 8_000\n\n/** Shown when the wait timed out (CLI line and MCP result text). */\nexport const NOT_READY_NOTE =\n 'it can take a few more seconds to appear everywhere; reload if you see a 404'\n\nexport const isReachableStatus = (status: number) =>\n (status >= 200 && status < 400) || status === 401 || status === 403\n\nconst defaultSleep = (ms: number) => new Promise<void>(resolve => setTimeout(resolve, ms))\n\nexport async function waitUntilReachable(\n url: string,\n opts: WaitOptions = {}\n): Promise<ReachableResult> {\n const timeoutMs = opts.timeoutMs ?? READY_TIMEOUT_MS\n const doFetch = opts.fetch ?? ((u: string, init: RequestInit) => fetch(u, init))\n const sleep = opts.sleep ?? defaultSleep\n const now = opts.now ?? (() => Date.now())\n const start = now()\n let interval = opts.intervalMs ?? 750\n let announced = false\n\n for (;;) {\n const remaining = timeoutMs - (now() - start)\n try {\n const res = await doFetch(url, {\n method: 'GET',\n redirect: 'manual',\n cache: 'no-store',\n signal: AbortSignal.timeout(Math.max(250, Math.min(remaining, 5_000))),\n })\n await res.body?.cancel().catch(() => {})\n if (isReachableStatus(res.status)) return { ready: true, waitedMs: now() - start }\n } catch {\n // network hiccup or per-request timeout: treat as \"not yet\"\n }\n if (!announced) {\n announced = true\n opts.onWaiting?.()\n }\n const left = timeoutMs - (now() - start)\n if (left <= 0) return { ready: false, waitedMs: now() - start }\n await sleep(Math.min(interval, left))\n interval = Math.min(interval * 1.25, 2_000)\n }\n}\n\n/**\n * Which URL to poll for a site served at `siteUrl` with these files: the root when there is an\n * index.html, else one of its files (the root of a site without index.html 404s for good, which\n * would look like \"not routed yet\").\n */\nexport function probeUrl(siteUrl: string, paths: readonly string[]): string {\n const base = siteUrl.endsWith('/') ? siteUrl : `${siteUrl}/`\n if (paths.length === 0 || paths.includes('index.html')) return base\n const pick = paths.find(p => /\\.html?$/i.test(p)) ?? paths[0]\n return base + (pick as string).split('/').map(encodeURIComponent).join('/')\n}\n\n/** `FLING_NO_WAIT=1` skips the wait; so do test runs (VITEST / NODE_ENV=test) by default. */\nexport function readinessWaitDisabled(env: Record<string, string | undefined>): boolean {\n return env.FLING_NO_WAIT === '1' || env.VITEST === 'true' || env.NODE_ENV === 'test'\n}\n", "// The review bridge: the postMessage protocol between the review page (app origin) and the review\n// shell (`/_fling/review.html` on the site's own origin). The shell frames the site same-origin,\n// so it sees what the review page can't: the page and hash route the frame is on, its scroll, the\n// element under a click, the text the reviewer selects. It keeps the frame on the site, places and draws pins and cursors, and\n// reports to the page. The page owns the data (comments, the live room) and tells the shell what\n// to draw. Browser-safe (zod only).\n//\n// Each side accepts a message only from the other's origin (the shell: the app origin its meta\n// names; the page: the site URL's origin) and parses it with these schemas; anything else is\n// ignored. Messages carry `fling: 'review'` so other postMessage traffic is told apart.\n\nimport { z } from 'zod'\nimport { COMMENT_PATH_MAX, CommentAnchorSchema } from './comments.ts'\nimport { REVIEW_SHELL } from './route-keys.ts'\n\n/** Where the shell serves itself on every site host. */\nexport const REVIEW_SHELL_PATH = REVIEW_SHELL\n\nconst tag = { fling: z.literal('review') }\nconst path = z.string().max(COMMENT_PATH_MAX)\nconst hash = z.string().max(COMMENT_PATH_MAX)\n\n/** A pin as the shell draws it: the thread's number in the list and where it is. */\nexport const BridgePinSchema = z.object({\n id: z.string(),\n n: z.number().int().min(1),\n anchor: CommentAnchorSchema,\n selected: z.boolean(),\n resolved: z.boolean(),\n})\nexport type BridgePin = z.infer<typeof BridgePinSchema>\n\n/** Another reviewer's pointer on the same page. */\nexport const BridgeCursorSchema = z.object({\n id: z.string(),\n name: z.string().max(100),\n colour: z.string().max(32),\n anchor: CommentAnchorSchema,\n})\nexport type BridgeCursor = z.infer<typeof BridgeCursorSchema>\n\n/** shell \u2192 page */\nexport const ShellMessageSchema = z.discriminatedUnion('type', [\n z.object({ ...tag, type: z.literal('ready') }),\n /** the frame is on `path` (normalised, see normalizeCommentPath) with fragment `hash` ('' or '#\u2026') */\n z.object({ ...tag, type: z.literal('location'), path, hash, title: z.string().max(300) }),\n /** a pin placed while placing: a click (a spot) or a drag (a box) */\n z.object({ ...tag, type: z.literal('pinPlaced'), anchor: CommentAnchorSchema }),\n /** the reviewer selected text in the page: an anchor on it, with its quote */\n z.object({ ...tag, type: z.literal('textSelected'), anchor: CommentAnchorSchema }),\n z.object({ ...tag, type: z.literal('pinCancelled') }),\n z.object({ ...tag, type: z.literal('pinClicked'), id: z.string() }),\n /** this reviewer's pointer on the page; null when it left the frame */\n z.object({ ...tag, type: z.literal('cursor'), anchor: CommentAnchorSchema.nullable() }),\n /** a link or form to another origin, stopped: the frame stays on the site */\n z.object({ ...tag, type: z.literal('blocked'), href: z.string().max(2048) }),\n z.object({ ...tag, type: z.literal('escape') }),\n])\nexport type ShellMessage = z.infer<typeof ShellMessageSchema>\n\n/** page \u2192 shell */\nexport const PageMessageSchema = z.discriminatedUnion('type', [\n /** load `path` (site-relative, may carry `?query` and `#hash`) in the frame */\n z.object({ ...tag, type: z.literal('navigate'), path: z.string().max(COMMENT_PATH_MAX * 2) }),\n z.object({ ...tag, type: z.literal('reload') }),\n z.object({ ...tag, type: z.literal('placing'), on: z.boolean() }),\n /** the pins on the frame's current page */\n z.object({ ...tag, type: z.literal('pins'), pins: z.array(BridgePinSchema) }),\n /** scroll the pin into view and draw attention to it */\n z.object({ ...tag, type: z.literal('focusPin'), id: z.string() }),\n z.object({ ...tag, type: z.literal('cursors'), cursors: z.array(BridgeCursorSchema) }),\n])\nexport type PageMessage = z.infer<typeof PageMessageSchema>\n\ntype Untagged<T> = T extends unknown ? Omit<T, 'fling'> : never\n\nexport function shellMessage(m: Untagged<ShellMessage>): ShellMessage {\n return { fling: 'review', ...m } as ShellMessage\n}\n\nexport function pageMessage(m: Untagged<PageMessage>): PageMessage {\n return { fling: 'review', ...m } as PageMessage\n}\n\n/** The shell's URL on a site, framing `path` (site-relative, may carry query and hash). */\nexport function reviewShellUrl(siteUrl: string, path = '/'): string {\n const url = new URL(REVIEW_SHELL_PATH, siteUrl)\n url.searchParams.set('path', path.startsWith('/') ? path : `/${path}`)\n return url.toString()\n}\n", "// The live room: one per site, where everyone with the site's review page open sees each other's\n// pointers and hears that comments changed. The protocol is plain JSON over one WebSocket, the\n// same on every platform (a Durable Object on Cloudflare, API Gateway WebSockets on AWS, an\n// in-process hub locally); clients learn the socket URL from `POST /api/sites/:name/live`, never\n// from which cloud they are on. Browser-safe (zod only).\n//\n// A comment change carries no comment: clients refetch the list, which applies policy.\n\nimport { z } from 'zod'\nimport { COMMENT_PATH_MAX, CommentAnchorSchema } from './comments.ts'\n\n/** Bytes in one client message; larger ones are dropped. */\nexport const LIVE_MESSAGE_MAX_BYTES = 4096\n/** How often a client sends its pointer, at most. */\nexport const LIVE_CURSOR_INTERVAL_MS = 80\n\n/** Characters in a peer's picture URL; a longer one is left out. */\nexport const LIVE_PICTURE_MAX = 1024\n\n/** Someone in the room. `id` is per connection: the same person in two tabs is two peers. */\nexport const LivePeerSchema = z.object({\n id: z.string(),\n name: z.string().max(100),\n colour: z.string().max(32),\n /** their profile picture (https), when sign-in gave one; else clients show initials */\n picture: z.string().max(LIVE_PICTURE_MAX).optional(),\n})\nexport type LivePeer = z.infer<typeof LivePeerSchema>\n\n/** POST /api/sites/:name/live \u2192 where to connect: `${url}?ticket=${ticket}`. */\nexport const LiveTicketSchema = z.object({\n url: z.string(),\n ticket: z.string(),\n /** seconds the ticket is good for: connect before then */\n expiresIn: z.number().int(),\n})\nexport type LiveTicket = z.infer<typeof LiveTicketSchema>\n\nconst path = z.string().max(COMMENT_PATH_MAX)\nconst hash = z.string().max(COMMENT_PATH_MAX)\n\n/**\n * client \u2192 room. A client sends `hello` as soon as the socket opens and the room answers with\n * `welcome`: a room on API Gateway cannot send anything while the connection is being accepted,\n * so on every platform the welcome is the answer to `hello`, never sent unasked.\n */\nexport const LiveClientMessageSchema = z.discriminatedUnion('type', [\n z.object({ type: z.literal('hello') }),\n /** where this peer's pointer is; `anchor` null when it left the page */\n z.object({\n type: z.literal('cursor'),\n path,\n hash,\n anchor: CommentAnchorSchema.nullable(),\n }),\n z.object({ type: z.literal('ping') }),\n])\nexport type LiveClientMessage = z.infer<typeof LiveClientMessageSchema>\n\n/** room \u2192 client */\nexport const LiveServerMessageSchema = z.discriminatedUnion('type', [\n /** the answer to `hello`: who this connection is, and who else is in the room */\n z.object({ type: z.literal('welcome'), you: LivePeerSchema, peers: z.array(LivePeerSchema) }),\n z.object({ type: z.literal('join'), peer: LivePeerSchema }),\n z.object({ type: z.literal('leave'), peerId: z.string() }),\n z.object({\n type: z.literal('cursor'),\n peerId: z.string(),\n path,\n hash,\n anchor: CommentAnchorSchema.nullable(),\n }),\n /** the site's comments changed: refetch them */\n z.object({ type: z.literal('comments') }),\n z.object({ type: z.literal('pong') }),\n])\nexport type LiveServerMessage = z.infer<typeof LiveServerMessageSchema>\n\n/** A stable colour for a person, from their email. */\nexport function peerColour(email: string): string {\n let h = 0\n for (let i = 0; i < email.length; i++) h = (h * 31 + email.charCodeAt(i)) >>> 0\n return `hsl(${h % 360} 75% 45%)`\n}\n\n/** A person's display name: their profile name, else their email's local part. */\nexport function peerName(email: string, name?: string | null): string {\n const n = name?.trim()\n return (n || email.split('@')[0] || email).slice(0, 100)\n}\n\n/** A profile picture a peer may show: an https URL of at most LIVE_PICTURE_MAX characters. */\nexport function peerPicture(picture?: string | null): string | undefined {\n if (!picture || picture.length > LIVE_PICTURE_MAX) return undefined\n try {\n return new URL(picture).protocol === 'https:' ? picture : undefined\n } catch {\n return undefined\n }\n}\n", "/**\n * CLI entry point. Wires commander to the thin command modules; the ONE place that maps errors to\n * exit codes (0 ok \u00B7 1 error \u00B7 2 not logged in \u00B7 3 forbidden) and prints them. Global `--server`\n * and `--json` apply to every command. Bare `fling` prints help; `fling <path>` deploys when the\n * path exists (route.ts).\n */\nimport { DEFAULT_SITE_SORT, SITE_SORTS, type SiteSort } from '@fling/shared'\nimport chalk from 'chalk'\nimport { Command, Option } from 'commander'\nimport { runLogin, runLogout, runUse, runWhoami } from './commands/auth.ts'\nimport { runComment, runComments, runResolve, runUncomment } from './commands/comments.ts'\nimport { runDeploy } from './commands/deploy.ts'\nimport {\n runGroupCreate,\n runGroupDelete,\n runGroupMembers,\n runGroupRename,\n runGroupShow,\n runGroups,\n} from './commands/groups.ts'\nimport { runSetup } from './commands/setup.ts'\nimport {\n runAccess,\n runArchive,\n runFiles,\n runInfo,\n runList,\n runListShared,\n runRemove,\n runRollback,\n runShare,\n runVersions,\n runVisibility,\n} from './commands/sites.ts'\nimport { ENV } from './config.ts'\nimport { type CommandContext, createContext } from './context.ts'\nimport { CliError, exitCodeFor } from './errors.ts'\nimport { runMcpServer } from './mcp.ts'\nimport { BIN_NAME, VERSION } from './package-info.ts'\nimport { routeArgs, routeOptionsFor } from './route.ts'\nimport { brand, logo } from './ui/theme.ts'\nimport { createLogger } from './utils/logger.ts'\nimport { formatJson } from './utils/output.ts'\n\ninterface GlobalOptions {\n server?: string\n json?: boolean\n}\n\nconst program = new Command()\nprogram\n .name(BIN_NAME)\n .description('Fling a folder of static files at Fling and get a link back')\n .version(VERSION)\n .option(\n '--server <url>',\n `server for this command: a URL, or the host of one you signed in to (default: $${ENV.url}, else the current one)`\n )\n .option('--json', 'print JSON instead of human output', false)\n .showHelpAfterError()\n .configureHelp({\n sortSubcommands: false,\n styleTitle: title => chalk.bold(brand.primary(title)),\n styleCommandText: text => chalk.bold(text),\n styleSubcommandText: text => brand.accent(text),\n styleOptionText: text => brand.accent(text),\n styleArgumentText: text => chalk.dim(text),\n })\n .addHelpText('before', () =>\n process.stdout.isTTY ? logo({ columns: process.stdout.columns }) : ''\n )\n .addHelpText(\n 'after',\n () => `\n${chalk.bold(brand.primary('Examples:'))}\n $ ${BIN_NAME} login https://fling.example.com sign in to your Fling (once; there is no default)\n $ ${BIN_NAME} setup sign in and add Fling to Claude Code / Claude Desktop\n $ ${BIN_NAME} use list the Flings you signed in to; \\`use <url>\\` switches\n $ ${BIN_NAME} deploy ./dist --name my-app \u2192 https://my-app.<your sites domain>\n $ ${BIN_NAME} ./dist the same: an existing path deploys\n $ ${BIN_NAME} ./dist --yes no prompts (CI): use the generated name, fail if it is taken\n $ ${BIN_NAME} \"Pitch Deck.html\" a single page\n $ ${BIN_NAME} site.zip a zip of a site\n $ ${BIN_NAME} share my-app public link for people who can't sign in\n\n${chalk.dim(`Exit codes: 0 ok \u00B7 1 error \u00B7 2 not logged in \u00B7 3 forbidden\nEnv: ${ENV.apiKey} \u00B7 ${ENV.url} \u00B7 ${ENV.configDir} \u00B7 ${ENV.debug}`)}`\n )\n\n/** Run a command with a context built from the global options; print + exit-code any error. */\nfunction action<A extends unknown[]>(handler: (ctx: CommandContext, ...args: A) => Promise<void>) {\n return async (...args: unknown[]) => {\n const command = args.at(-1) as Command\n const globals = command.optsWithGlobals<GlobalOptions>()\n let ctx: CommandContext | undefined\n try {\n ctx = await createContext({ server: globals.server, json: globals.json })\n await handler(ctx, ...(args.slice(0, -1) as A))\n } catch (error) {\n report(error, ctx)\n process.exitCode = exitCodeFor(error)\n }\n }\n}\n\nfunction report(error: unknown, ctx: CommandContext | undefined): void {\n const log = ctx?.log ?? createLogger()\n const message = error instanceof Error ? error.message : String(error)\n log.error(message)\n if (error instanceof CliError && error.hint) log.hint(error.hint)\n if (ctx?.config.debug && error instanceof Error && error.stack) log.hint(error.stack)\n if (ctx?.json) {\n const { code, findings, paths } = error as {\n code?: unknown\n findings?: unknown\n paths?: unknown\n }\n process.stdout.write(\n `${formatJson({\n error: {\n message,\n exitCode: exitCodeFor(error),\n ...(typeof code === 'string' ? { code } : {}),\n ...(Array.isArray(findings) ? { findings } : {}),\n ...(Array.isArray(paths) ? { paths } : {}),\n },\n })}\\n`\n )\n }\n}\n\n// ---- deploy --------------------------------------------------------------------------------\n\nprogram\n .command('deploy [path]')\n .helpGroup('Deploy:')\n .description(\n 'deploy a folder (default: .), a single .html file, a .zip or any file. `fling <path>` is short for it'\n )\n .option(\n '-n, --name <name>',\n 'site name \u2014 names are global, first come first served (default: generated from the project and folder, e.g. rocketpod-docs; you confirm it on a terminal)'\n )\n .option('--spa', 'single-page app: serve index.html for unknown paths')\n .option(\n '--public',\n 'make the site public: anyone can open it, reviewing still needs sign-in (default: sign-in required)'\n )\n .option(\n '-y, --yes',\n 'never prompt: accept the generated name; without index.html, list the HTML pages (or fling anyway if there are none)'\n )\n .option('--list-html', 'no index.html at the root: generate one listing the HTML pages')\n .option('--no-list-html', 'no index.html at the root: fling anyway (the root will 404)')\n .action(\n action(\n (\n ctx,\n path: string | undefined,\n opts: { name?: string; spa?: boolean; public?: boolean; yes?: boolean; listHtml?: boolean }\n ) => runDeploy(ctx, path, opts)\n )\n )\n\n// ---- setup and auth ------------------------------------------------------------------------\n\nprogram\n .command('setup [url]')\n .helpGroup('Setup:')\n .description(\n 'sign in (to the Fling at url, which becomes current), then add the Fling plugin to Claude Code and the extension to Claude Desktop'\n )\n .option('-y, --yes', 'do every step without asking')\n .option('-s, --scope <scope>', 'Claude Code plugin scope: user, project or local', 'user')\n .action(\n action((ctx, url: string | undefined, opts: { yes?: boolean; scope?: string }) =>\n runSetup(ctx, { ...opts, url })\n )\n )\nprogram\n .command('login [url]')\n .helpGroup('Setup:')\n .description(\n 'sign in through the browser to the Fling at url and store an API key; it becomes the current server (default: the current one)'\n )\n .action(\n action(async (ctx, url: string | undefined) => {\n await runLogin(ctx, url)\n ctx.log.hint(`Next: \\`${BIN_NAME} setup\\` adds Fling to Claude Code and Claude Desktop.`)\n })\n )\nprogram\n .command('use [url]')\n .helpGroup('Setup:')\n .description(\n 'switch to another Fling you signed in to (a URL or its host); without url, list them'\n )\n .action(action((ctx, url: string | undefined) => runUse(ctx, url)))\nprogram\n .command('logout [url]')\n .helpGroup('Setup:')\n .description(\n \"remove a server's API key (default: the current server's, which stays current); any other server is forgotten\"\n )\n .action(action((ctx, url: string | undefined) => runLogout(ctx, url)))\nprogram\n .command('whoami')\n .helpGroup('Setup:')\n .description('show the signed-in user and the current server')\n .action(action(ctx => runWhoami(ctx)))\n// `help` sits with the setup commands instead of under its own \"Commands:\" heading.\nprogram.commandsGroup('Setup:').helpCommand('help [command]', 'show help for a command')\n\n// ---- sites ---------------------------------------------------------------------------------\n\nprogram\n .command('ls')\n .helpGroup('Sites:')\n .alias('list')\n .description('list your sites')\n .option('--archived', 'list archived sites')\n .addOption(\n new Option(\n '--shared',\n 'list the sites others have shared with you instead of your own'\n ).conflicts('archived')\n )\n .addOption(\n new Option('--sort <order>', 'updated (newest first), created (newest first) or name (A\u2013Z)')\n .choices(SITE_SORTS)\n .default(DEFAULT_SITE_SORT)\n )\n .action(\n action((ctx, opts: { archived?: boolean; shared?: boolean; sort?: SiteSort }) =>\n opts.shared ? runListShared(ctx, opts) : runList(ctx, opts)\n )\n )\nprogram\n .command('info <name>')\n .helpGroup('Sites:')\n .description('show a site')\n .action(action((ctx, name: string) => runInfo(ctx, name)))\nprogram\n .command('versions <name>')\n .helpGroup('Sites:')\n .description(\"list a site's versions (* = live)\")\n .action(action((ctx, name: string) => runVersions(ctx, name)))\nprogram\n .command('files <name> [versionId]')\n .helpGroup('Sites:')\n .description(\"list the files in a site's live version (or in versionId)\")\n .action(\n action((ctx, name: string, versionId: string | undefined) => runFiles(ctx, name, versionId))\n )\nprogram\n .command('rollback <name> <versionId>')\n .helpGroup('Sites:')\n .description('serve an earlier version again')\n .action(action((ctx, name: string, versionId: string) => runRollback(ctx, name, versionId)))\nprogram\n .command('share <name>')\n .helpGroup('Sites:')\n .description('print (or create) a public share link \u2014 anyone with it can view the site')\n .option('--refresh', 'replace the link; the old one stops working')\n .option('--revoke', 'remove the link')\n .action(\n action((ctx, name: string, opts: { refresh?: boolean; revoke?: boolean }) =>\n runShare(ctx, name, opts)\n )\n )\nprogram\n .command('visibility <name> <visibility>')\n .helpGroup('Sites:')\n .description(\n 'private (sign-in required) or public (anyone can open the site; reviewing it still needs sign-in)'\n )\n .action(action((ctx, name: string, visibility: string) => runVisibility(ctx, name, visibility)))\nprogram\n .command('access <name>')\n .helpGroup('Sites:')\n .description('show who can open a private site, or limit it to listed people and groups')\n .option('--add <emails...>', 'let these addresses in (comma-separated or repeated)')\n .option('--remove <emails...>', 'take these addresses out')\n .option('--group <slugs...>', 'let these groups in (see `fling groups`)')\n .option('--remove-group <slugs...>', 'take these groups out')\n .option('--clear', 'empty the audience: everyone signed in can open it again')\n .action(\n action(\n (\n ctx,\n name: string,\n opts: {\n add?: string[]\n remove?: string[]\n group?: string[]\n removeGroup?: string[]\n clear?: boolean\n }\n ) => runAccess(ctx, name, opts)\n )\n )\nprogram\n .command('archive <name>')\n .helpGroup('Sites:')\n .description('take a site offline (404) but keep its files; undo with unarchive')\n .action(action((ctx, name: string) => runArchive(ctx, name)))\nprogram\n .command('unarchive <name>')\n .helpGroup('Sites:')\n .description('bring an archived site back')\n .action(action((ctx, name: string) => runArchive(ctx, name, true)))\nprogram\n .command('rm <name>')\n .helpGroup('Sites:')\n .alias('delete')\n .description('delete a site and all its versions (asks first unless --yes)')\n .option('-y, --yes', 'do not ask for confirmation')\n .action(action((ctx, name: string, opts: { yes?: boolean }) => runRemove(ctx, name, opts)))\n\n// ---- groups --------------------------------------------------------------------------------\n\nconst groups = program\n .command('groups')\n .helpGroup('Groups:')\n .description(\n 'named lists of people anyone can use in an audience; only the owner changes one (default: list)'\n )\ngroups\n .command('list', { isDefault: true })\n .alias('ls')\n .description('list the groups on this Fling')\n .option('--mine', 'only the groups you own')\n .option('--members <emails...>', 'only the groups of exactly these people (a,b or a b)')\n .action(action((ctx, opts: { mine?: boolean; members?: string[] }) => runGroups(ctx, opts)))\ngroups\n .command('create <slug>')\n .description('create a group you own (slug: lowercase letters, digits and single hyphens)')\n .option('--name <name>', 'its display name (default: the slug)')\n .option('--add <emails...>', 'put these addresses in it')\n .action(\n action((ctx, slug: string, opts: { name?: string; add?: string[] }) =>\n runGroupCreate(ctx, slug, opts)\n )\n )\ngroups\n .command('show <slug>')\n .description('show a group and its members')\n .action(action((ctx, slug: string) => runGroupShow(ctx, slug)))\ngroups\n .command('add <slug> <emails...>')\n .description('add people to a group you own')\n .action(\n action((ctx, slug: string, emails: string[]) => runGroupMembers(ctx, slug, emails, 'add'))\n )\ngroups\n .command('remove <slug> <emails...>')\n .description('take people out of a group you own')\n .action(\n action((ctx, slug: string, emails: string[]) => runGroupMembers(ctx, slug, emails, 'remove'))\n )\ngroups\n .command('rename <slug> <name>')\n .description('change the display name of a group you own')\n .action(action((ctx, slug: string, name: string) => runGroupRename(ctx, slug, name)))\ngroups\n .command('delete <slug>')\n .alias('rm')\n .description(\n 'delete a group you own; anyone it let into a site loses access (asks first unless --yes)'\n )\n .option('-y, --yes', 'do not ask for confirmation')\n .action(action((ctx, slug: string, opts: { yes?: boolean }) => runGroupDelete(ctx, slug, opts)))\n\n// ---- comments ------------------------------------------------------------------------------\n\nprogram\n .command('comments <name>')\n .helpGroup('Comments:')\n .description(\"list a site's open comment threads (people leave them on its review page)\")\n .option('-p, --path <path>', 'only this page, e.g. / or /docs/')\n .option('-a, --all', 'include resolved threads')\n .action(\n action((ctx, name: string, opts: { path?: string; all?: boolean }) =>\n runComments(ctx, name, opts)\n )\n )\nprogram\n .command('comment <name> <text>')\n .helpGroup('Comments:')\n .description('comment on a page of a site (default: its home page), or reply to a thread')\n .option('-p, --path <path>', 'the page, e.g. /docs/ or about.html')\n .option('-r, --reply <id>', 'reply to this thread')\n .action(\n action((ctx, name: string, text: string, opts: { path?: string; reply?: string }) =>\n runComment(ctx, name, text, opts)\n )\n )\nprogram\n .command('resolve <name> <id>')\n .helpGroup('Comments:')\n .description('mark a comment thread resolved')\n .option('--reopen', 'reopen it instead')\n .action(\n action((ctx, name: string, id: string, opts: { reopen?: boolean }) =>\n runResolve(ctx, name, id, opts)\n )\n )\nprogram\n .command('uncomment <name> <id>')\n .helpGroup('Comments:')\n .alias('delete-comment')\n .description('delete a comment (a thread goes with its replies; asks first unless --yes)')\n .option('-y, --yes', 'do not ask for confirmation')\n .action(\n action((ctx, name: string, id: string, opts: { yes?: boolean }) =>\n runUncomment(ctx, name, id, opts)\n )\n )\n\n// ---- agents --------------------------------------------------------------------------------\n\nprogram\n .command('mcp')\n .helpGroup('Agents:')\n .description('run the MCP server on stdio (used by the Claude Code plugin)')\n .action(async (_opts: unknown, command: Command) => {\n const globals = command.optsWithGlobals<GlobalOptions>()\n await runMcpServer({ server: globals.server })\n })\n\nasync function main(): Promise<void> {\n const route = await routeArgs(process.argv.slice(2), routeOptionsFor(program))\n if (route.kind === 'help') {\n program.outputHelp()\n return\n }\n if (route.kind === 'unknown') {\n const log = createLogger()\n log.error(`\"${route.arg}\" is not a command, file or folder`)\n log.hint(\n `Run \\`${BIN_NAME} --help\\` for the commands, or \\`${BIN_NAME} deploy <path>\\` to deploy.`\n )\n process.exitCode = 1\n return\n }\n await program.parseAsync(route.args, { from: 'user' })\n}\n\nawait main()\n", "/**\n * `fling login [url] | use [url] | logout [url] | whoami`. The CLI remembers every server it signs\n * in to (config.ts); one is current, and `--server` / FLING_URL pick another for one command.\n */\nimport chalk from 'chalk'\nimport { loginFlow } from '../auth.ts'\nimport { matchServer, redactKey } from '../config.ts'\nimport { type CommandContext, requireClient, requireServer } from '../context.ts'\nimport { CliError } from '../errors.ts'\nimport { loadInstance } from '../instance.ts'\nimport { sitesBaseOf, sitesPattern, whoami } from '../sites.ts'\n\n/**\n * `fling login <url>` \u2192 that server (a remembered one may be named by its host); bare\n * `fling login` \u2192 --server, FLING_URL or the current one.\n */\nexport async function loginServer(ctx: CommandContext, url: string | undefined): Promise<string> {\n if (url === undefined) return requireServer(ctx)\n const { servers } = await ctx.store.load()\n return matchServer(Object.keys(servers), url).url\n}\n\n/** Sign in to a server and make it current; the other servers' logins are kept. */\nexport async function runLogin(ctx: CommandContext, url?: string): Promise<void> {\n const result = await loginFlow({\n serverUrl: await loginServer(ctx, url),\n store: ctx.store,\n log: ctx.log,\n open: ctx.open,\n fetch: ctx.fetch,\n makeCurrent: true,\n })\n if (ctx.json) ctx.out.data(result, () => '')\n}\n\n/** `fling use <url>` makes a remembered server current; bare `fling use` lists them. */\nexport async function runUse(ctx: CommandContext, url?: string): Promise<void> {\n const config = await ctx.store.load()\n const urls = Object.keys(config.servers)\n const overridden =\n ctx.config.serverUrlSource === 'env' || ctx.config.serverUrlSource === 'flag'\n ? ctx.config.serverUrl\n : undefined\n const overrideHint = () => {\n if (overridden)\n ctx.log.hint(\n `${ctx.config.serverUrlSource === 'env' ? 'FLING_URL' : '--server'} is set: commands run with it use ${overridden}.`\n )\n }\n\n if (url === undefined) {\n const servers = urls.map(server => {\n const entry = config.servers[server] ?? {}\n return {\n url: server,\n current: server === config.current,\n instance: entry.instance?.name ?? null,\n email: entry.apiKey ? (entry.user?.email ?? null) : null,\n signedIn: Boolean(entry.apiKey),\n }\n })\n if (servers.length === 0 && !ctx.json) {\n ctx.log.info('No Fling servers yet')\n ctx.log.hint(`Run \\`${ctx.binName} login <url>\\` with your Fling's address.`)\n return\n }\n const width = Math.max(...servers.map(s => s.url.length))\n ctx.out.data({ current: config.current ?? null, servers }, () =>\n servers\n .map(s =>\n [\n s.current ? chalk.bold('*') : ' ',\n s.current ? chalk.bold(s.url.padEnd(width)) : s.url.padEnd(width),\n s.instance ?? chalk.dim('(unknown)'),\n s.signedIn ? (s.email ?? chalk.dim('(signed in)')) : chalk.dim('(signed out)'),\n ].join(' ')\n )\n .join('\\n')\n )\n if (!ctx.json) {\n ctx.log.hint(`* = current. Switch with \\`${ctx.binName} use <url>\\`.`)\n overrideHint()\n }\n return\n }\n\n const match = matchServer(urls, url, { loose: true })\n if (!match.remembered)\n throw new CliError(`Not signed in to ${match.url} on this computer`, {\n hint: `Run \\`${ctx.binName} login ${match.url}\\` to add it, or \\`${ctx.binName} use\\` to list your servers.`,\n })\n await ctx.store.setCurrent(match.url)\n const entry = config.servers[match.url] ?? {}\n const name = entry.instance?.name\n const email = entry.apiKey ? entry.user?.email : undefined\n ctx.out.data(\n { current: match.url, instance: name ?? null, email: email ?? null },\n () => `Now using ${chalk.bold(match.url)}${name ? chalk.dim(` (${name})`) : ''}`\n )\n if (!ctx.json) {\n if (entry.apiKey) ctx.log.hint(`Signed in as ${email ?? 'an unknown user'}.`)\n else ctx.log.hint(`Signed out there: run \\`${ctx.binName} login\\` to sign in.`)\n overrideHint()\n }\n}\n\n/**\n * Remove a server's API key from this computer (default: the server this command uses). The\n * current server is kept, so a bare `fling login` signs in to it again; any other is forgotten.\n */\nexport async function runLogout(ctx: CommandContext, url?: string): Promise<void> {\n const config = await ctx.store.load()\n const target =\n url === undefined\n ? ctx.config.serverUrl\n : matchServer(Object.keys(config.servers), url, { loose: true }).url\n const entry = target === undefined ? undefined : config.servers[target]\n if (target === undefined || entry === undefined) {\n ctx.log.info(`Not logged in${target ? ` to ${target}` : ''} \u2014 nothing to do`)\n return\n }\n if (target === config.current) {\n if (!entry.apiKey) {\n ctx.log.info('Not logged in \u2014 nothing to do')\n return\n }\n await ctx.store.clearCredentials(target)\n ctx.log.success('Logged out; API key removed from this machine')\n } else {\n await ctx.store.removeServer(target)\n ctx.log.success(\n entry.apiKey\n ? `Logged out of ${target}; API key and server removed from this machine`\n : `Removed ${target} from this machine`\n )\n }\n if (entry.apiKey) ctx.log.hint(`Revoke it on the server under Connections at ${target}`)\n}\n\nexport async function runWhoami(ctx: CommandContext): Promise<void> {\n const client = requireClient(ctx)\n const me = await whoami(client)\n const instance = await loadInstance(ctx.store, ctx.config, ctx.fetch)\n const { serverUrl, current } = ctx.config\n const others = Object.keys((await ctx.store.load()).servers).filter(s => s !== serverUrl)\n ctx.out.data(\n {\n ...me,\n serverUrl,\n serverUrlSource: ctx.config.serverUrlSource,\n current: current ?? null,\n instance: instance?.name ?? null,\n apiKey: redactKey(ctx.config.apiKey),\n apiKeySource: ctx.config.apiKeySource,\n },\n () =>\n [\n `${chalk.bold('User:')} ${me.name} <${me.email}>`,\n `${chalk.bold('Sites:')} ${sitesPattern(sitesBaseOf(instance))} ${chalk.dim('(names are first come, first served)')}`,\n `${chalk.bold('Server:')} ${serverUrl}${instance ? chalk.dim(` (${instance.name})`) : ''} ${chalk.dim(\n serverUrl === current\n ? '(current)'\n : `(from ${ctx.config.serverUrlSource === 'env' ? 'FLING_URL' : '--server'}; current: ${current ?? 'none'})`\n )}`,\n `${chalk.bold('API key:')} ${redactKey(ctx.config.apiKey)} ${chalk.dim(`(from ${ctx.config.apiKeySource})`)}`,\n ...(others.length > 0\n ? [\n chalk.dim(\n `${others.length} other server${others.length === 1 ? '' : 's'} on this computer: \\`${ctx.binName} use\\` lists them`\n ),\n ]\n : []),\n ].join('\\n')\n )\n}\n", "/**\n * Login handoff. First `<server>/.well-known/fling` is fetched: it proves the URL is a Fling and is\n * stored as the instance. Then the CLI listens on the first free port in 8765\u20138770 at\n * `http://127.0.0.1:<port>/callback`, opens\n * `<server>/auth/cli?redirect_uri=<callback>&hostname=<host>&state=<random>` in the browser, and the\n * server \u2014 after sign-in \u2014 redirects back with `?key=<api key>` (or `?error=<code>`). If the\n * server echoes `state`, it must match. The callback answers a tiny self-closing page, the CLI\n * verifies the key with `GET /api/me`, and stores it in that server's entry of the config (other\n * servers' entries are kept). Five-minute timeout. The key is never\n * printed in full.\n */\nimport { randomBytes } from 'node:crypto'\nimport { createServer, type IncomingMessage, type Server, type ServerResponse } from 'node:http'\nimport { hostname as osHostname } from 'node:os'\nimport { type InstanceMetadata, type Me, MeSchema } from '@fling/shared'\nimport { createApiClient, type FetchLike } from './api.ts'\nimport { type ConfigStore, redactKey } from './config.ts'\nimport type { OpenLike } from './context.ts'\nimport { CliError } from './errors.ts'\nimport { fetchInstance } from './instance.ts'\nimport { BIN_NAME } from './package-info.ts'\nimport type { Logger } from './utils/logger.ts'\n\nexport const CALLBACK_PORT_START = 8765\nexport const CALLBACK_PORT_END = 8770\nexport const LOGIN_TIMEOUT_MS = 5 * 60 * 1000\nexport const CALLBACK_PATH = '/callback'\n/** Server route that starts the browser side of the handoff. */\nexport const AUTH_CLI_PATH = '/auth/cli'\n\nexport interface LoginOptions {\n serverUrl: string\n store: ConfigStore\n log: Logger\n open: OpenLike\n fetch?: FetchLike\n timeoutMs?: number\n hostname?: string\n /** Called with the sign-in URL before the browser is opened (the MCP server reports it). */\n onAuthUrl?: (url: string) => void\n /** Make the server current once signed in (default: yes). */\n makeCurrent?: boolean\n}\n\nexport interface LoginResult {\n serverUrl: string\n keyPrefix: string\n user: Me\n instance: InstanceMetadata\n}\n\nexport async function loginFlow(options: LoginOptions): Promise<LoginResult> {\n const { serverUrl, store, log } = options\n const instance = await fetchInstance(serverUrl, options.fetch ?? fetch)\n const state = randomBytes(16).toString('hex')\n const callback = await startCallbackServer({ state, timeoutMs: options.timeoutMs })\n try {\n const authUrl = buildAuthUrl(serverUrl, callback.url, options.hostname ?? osHostname(), state)\n options.onAuthUrl?.(authUrl)\n log.info(`Opening your browser to sign in to ${instance.name} at ${serverUrl}`)\n log.hint(`If it does not open, visit: ${authUrl}`)\n try {\n await options.open(authUrl)\n } catch (error) {\n log.warn(`Could not open a browser (${(error as Error).message}); open the URL above.`)\n }\n log.info('Waiting for the browser to complete sign-in (5-minute timeout)\u2026')\n\n const { key } = await callback.result\n const client = createApiClient({ serverUrl, apiKey: key, fetch: options.fetch })\n const user = await client.request('GET', '/api/me', { schema: MeSchema })\n\n await store.putServer(\n serverUrl,\n {\n instance,\n apiKey: key,\n user: { email: user.email, name: user.name, userSlug: user.userSlug },\n },\n { makeCurrent: options.makeCurrent ?? true }\n )\n const keyPrefix = redactKey(key)\n log.success(`Signed in as ${user.email}`)\n log.hint(`Server: ${serverUrl}`)\n log.hint(`API key: ${keyPrefix} (stored in ${store.file})`)\n return { serverUrl, keyPrefix, user, instance }\n } finally {\n callback.close()\n }\n}\n\nexport function buildAuthUrl(\n serverUrl: string,\n callbackUrl: string,\n hostname: string,\n state: string\n): string {\n const url = new URL(AUTH_CLI_PATH, `${serverUrl.replace(/\\/+$/, '')}/`)\n url.searchParams.set('redirect_uri', callbackUrl)\n url.searchParams.set('hostname', hostname)\n url.searchParams.set('state', state)\n return url.toString()\n}\n\n// ---- Loopback callback server ------------------------------------------------------------\n\nexport interface CallbackData {\n key: string\n}\n\nexport interface CallbackServer {\n port: number\n url: string\n /** Resolves with the key, rejects on `?error=`, a missing key, a wrong state, or timeout. */\n result: Promise<CallbackData>\n close(): void\n}\n\ntype Settle = { resolve: (d: CallbackData) => void; reject: (e: Error) => void }\n\n/** Pure parse of a callback URL \u2014 the part of the handoff worth unit-testing on its own. */\nexport function parseCallback(\n url: URL,\n expectedState: string | undefined\n): { ok: true; key: string } | { ok: false; message: string } {\n const error = url.searchParams.get('error')\n if (error) return { ok: false, message: `Sign-in failed: ${error}` }\n const state = url.searchParams.get('state')\n if (state !== null && expectedState !== undefined && state !== expectedState) {\n return {\n ok: false,\n message: 'Sign-in failed: state mismatch (the callback was not for this login)',\n }\n }\n const key = url.searchParams.get('key')\n if (!key) return { ok: false, message: 'Callback missing required parameter: key' }\n return { ok: true, key }\n}\n\nexport async function startCallbackServer(\n options: { state?: string; timeoutMs?: number } = {}\n): Promise<CallbackServer> {\n const timeoutMs = options.timeoutMs ?? LOGIN_TIMEOUT_MS\n let settle: Settle | undefined\n let timer: NodeJS.Timeout | undefined\n const result = new Promise<CallbackData>((resolve, reject) => {\n settle = { resolve, reject }\n }).finally(() => clearTimeout(timer))\n // Mark handled: the browser may hit the callback before the caller awaits `result`.\n result.catch(() => {})\n\n const server = createServer((req, res) => handleCallback(req, res, port, options.state, settle))\n const port = await listenOnFreePort(server)\n timer = setTimeout(() => {\n settle?.reject(\n new CliError(\n `Timed out after ${Math.round(timeoutMs / 60_000) || 1} minute(s) waiting for the browser`,\n { hint: `Run \\`${BIN_NAME} login\\` again and finish signing in within 5 minutes.` }\n )\n )\n }, timeoutMs)\n\n return {\n port,\n url: `http://127.0.0.1:${port}${CALLBACK_PATH}`,\n result,\n close: () => {\n clearTimeout(timer)\n server.close()\n server.closeAllConnections?.()\n },\n }\n}\n\nfunction handleCallback(\n req: IncomingMessage,\n res: ServerResponse,\n port: number,\n expectedState: string | undefined,\n settle: Settle | undefined\n): void {\n const url = new URL(req.url ?? '/', `http://127.0.0.1:${port}`)\n if (url.pathname !== CALLBACK_PATH) {\n res.writeHead(404, { 'Content-Type': 'text/plain' }).end('Not found')\n return\n }\n const parsed = parseCallback(url, expectedState)\n if (!parsed.ok) {\n respondHtml(\n res,\n 400,\n 'Sign-in failed',\n `${escapeHtml(parsed.message)}. Return to the terminal and try again.`\n )\n settle?.reject(\n new CliError(parsed.message, { hint: `Run \\`${BIN_NAME} login\\` to try again.` })\n )\n return\n }\n respondHtml(res, 200, 'Signed in', 'You can close this tab and return to the terminal.', true)\n settle?.resolve({ key: parsed.key })\n}\n\nfunction respondHtml(\n res: ServerResponse,\n status: number,\n title: string,\n body: string,\n close = false\n) {\n const html = `<!doctype html><html><head><meta charset=\"utf-8\"><title>Fling \u2014 ${title}</title></head>\n<body style=\"font-family:system-ui,sans-serif;padding:48px;text-align:center;color:#111\">\n<h1 style=\"font-size:1.5rem\">${title}</h1><p>${body}</p>\n${close ? '<script>setTimeout(function(){window.close()},800)</script>' : ''}\n</body></html>`\n res.writeHead(status, {\n 'Content-Type': 'text/html; charset=utf-8',\n 'Cache-Control': 'no-store',\n Connection: 'close',\n })\n res.end(html)\n}\n\nfunction listenOnFreePort(server: Server): Promise<number> {\n return new Promise((resolve, reject) => {\n let port = CALLBACK_PORT_START\n const tryNext = () => {\n if (port > CALLBACK_PORT_END) {\n reject(\n new CliError(\n `No free port in ${CALLBACK_PORT_START}\u2013${CALLBACK_PORT_END} for the login callback`,\n {\n hint: 'Another login may be in progress; close it or free one of those ports.',\n }\n )\n )\n return\n }\n server.once('error', (error: NodeJS.ErrnoException) => {\n if (error.code === 'EADDRINUSE' || error.code === 'EACCES') {\n port += 1\n tryNext()\n } else reject(error)\n })\n server.listen(port, '127.0.0.1', () => {\n server.removeAllListeners('error')\n resolve(port)\n })\n }\n tryNext()\n })\n}\n\nfunction escapeHtml(text: string): string {\n return text.replace(/[&<>\"']/g, ch => `&#${ch.charCodeAt(0)};`)\n}\n", "/**\n * CLI error types and the exit-code mapping: 0 ok \u00B7 1 error \u00B7 2 not logged in \u00B7 3 forbidden.\n * Commands throw; `cli.ts` catches once, prints once, and sets `process.exitCode`.\n */\n\nexport const EXIT_OK = 0\nexport const EXIT_ERROR = 1\nexport const EXIT_NOT_LOGGED_IN = 2\nexport const EXIT_FORBIDDEN = 3\n\nexport class CliError extends Error {\n readonly exitCode: number\n /** Extra dimmed line printed under the error (e.g. \"run `fling login`\"). */\n readonly hint?: string\n\n constructor(\n message: string,\n options: { exitCode?: number; hint?: string; cause?: unknown } = {}\n ) {\n super(message, options.cause === undefined ? undefined : { cause: options.cause })\n this.name = 'CliError'\n this.exitCode = options.exitCode ?? EXIT_ERROR\n this.hint = options.hint\n }\n}\n\nexport class NotLoggedInError extends CliError {\n constructor(binName: string) {\n super('Not logged in', {\n exitCode: EXIT_NOT_LOGGED_IN,\n hint: `Run \\`${binName} login\\` first.`,\n })\n this.name = 'NotLoggedInError'\n }\n}\n\n/** No server to talk to: a fresh install, or a 0.2 config from before the server was stored. */\nexport class NoServerError extends CliError {\n constructor(binName: string) {\n super(`No Fling server set \u2014 run \\`${binName} login <url>\\` with your Fling's address`, {\n exitCode: EXIT_NOT_LOGGED_IN,\n })\n this.name = 'NoServerError'\n }\n}\n\n/** Exit code for anything a command may throw. Unknown errors \u2192 1. */\nexport function exitCodeFor(error: unknown): number {\n return error instanceof CliError ? error.exitCode : EXIT_ERROR\n}\n", "{\n \"name\": \"@nearform/fling\",\n \"version\": \"0.6.0\",\n \"license\": \"MIT\",\n \"description\": \"Fling a folder of static files at a Fling server and get a link back. CLI + MCP server.\",\n \"type\": \"module\",\n \"bin\": {\n \"fling\": \"./dist/cli.js\"\n },\n \"files\": [\n \"dist/cli.js\",\n \"dist/cli.js.map\",\n \"README.md\",\n \"CHANGELOG.md\"\n ],\n \"engines\": {\n \"node\": \">=22\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/nearform/fling.git\",\n \"directory\": \"apps/cli\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"scripts\": {\n \"dev\": \"tsx src/cli.ts\",\n \"build\": \"node scripts/build.mjs\",\n \"build:mcpb\": \"node scripts/build.mjs && node scripts/build-mcpb.mjs\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run\"\n },\n \"dependencies\": {\n \"@clack/prompts\": \"^1.8.1\",\n \"@modelcontextprotocol/sdk\": \"^1.20.0\",\n \"chalk\": \"^5.6.2\",\n \"commander\": \"^15.0.0\",\n \"fflate\": \"^0.8.3\",\n \"ignore\": \"^7.0.5\",\n \"mime\": \"^4.1.0\",\n \"open\": \"^11.0.0\",\n \"zod\": \"^4.6.7\"\n },\n \"devDependencies\": {\n \"@fling/shared\": \"workspace:*\",\n \"@types/node\": \"^24.0.0\",\n \"esbuild\": \"^0.25.12\",\n \"tsx\": \"^4.23.13\",\n \"typescript\": \"^5.9.3\",\n \"vitest\": \"^3.2.7\"\n }\n}\n", "/** Package metadata \u2014 bin name and version come from package.json (esbuild inlines it). */\nimport pkg from '../package.json'\n\nexport const PACKAGE_NAME: string = pkg.name\nexport const VERSION: string = pkg.version\nexport const BIN_NAME: string = Object.keys(pkg.bin)[0] ?? 'fling'\n/** How a user without a global install runs the CLI \u2014 used in hints shown to agents. */\nexport const NPX_COMMAND = `npx ${pkg.name}`\n", "/**\n * HTTP client for the Fling API \u2014 the only place `fetch` is called. Sends `Authorization: Bearer\n * <key>`, turns the error envelope `{ error: { code, message } }` into `CliApiError` (401 \u2192 exit 2,\n * 403 \u2192 exit 3) and validates success bodies with the zod contracts from `@fling/shared`. Network\n * failures are a `CliApiError` with `status: 0` so callers only ever handle one error type.\n *\n * `putUpload` is the one unauthenticated call: a PUT of file bytes to a presigned S3 URL.\n */\nimport { ErrorEnvelopeSchema } from '@fling/shared'\nimport type { z } from 'zod'\nimport { CliError, EXIT_ERROR, EXIT_FORBIDDEN, EXIT_NOT_LOGGED_IN } from './errors.ts'\nimport { BIN_NAME, PACKAGE_NAME, VERSION } from './package-info.ts'\n\nexport type FetchLike = (input: string, init?: RequestInit) => Promise<Response>\nexport type Method = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE'\n\nexport interface ApiClientOptions {\n serverUrl: string\n apiKey?: string\n fetch?: FetchLike\n timeoutMs?: number\n}\n\nexport type QueryValue = string | number | boolean | undefined | null\n\nexport interface RequestOptions<T> {\n schema?: z.ZodType<T>\n query?: Record<string, QueryValue>\n body?: unknown\n}\n\nexport class CliApiError extends CliError {\n readonly status: number\n readonly code?: string\n readonly body?: unknown\n\n constructor(options: {\n status: number\n message: string\n code?: string\n body?: unknown\n hint?: string\n cause?: unknown\n }) {\n super(options.message, {\n exitCode: exitCodeForStatus(options.status),\n hint: options.hint ?? defaultHint(options.status),\n cause: options.cause,\n })\n this.name = 'CliApiError'\n this.status = options.status\n this.code = options.code\n this.body = options.body\n }\n}\n\nexport function exitCodeForStatus(status: number): number {\n if (status === 401) return EXIT_NOT_LOGGED_IN\n if (status === 403) return EXIT_FORBIDDEN\n return EXIT_ERROR\n}\n\nfunction defaultHint(status: number): string | undefined {\n if (status === 401) return `Run \\`${BIN_NAME} login\\` to authenticate.`\n if (status === 403) return 'You are not allowed to do that.'\n return undefined\n}\n\nexport interface ApiClient {\n readonly serverUrl: string\n request<T = unknown>(method: Method, path: string, options?: RequestOptions<T>): Promise<T>\n}\n\nexport function buildUrl(serverUrl: string, path: string, query?: Record<string, QueryValue>) {\n const url = new URL(`${serverUrl.replace(/\\/+$/, '')}${path.startsWith('/') ? path : `/${path}`}`)\n for (const [key, value] of Object.entries(query ?? {})) {\n if (value !== undefined && value !== null) url.searchParams.set(key, String(value))\n }\n return url.toString()\n}\n\nexport function createApiClient(options: ApiClientOptions): ApiClient {\n const serverUrl = options.serverUrl.replace(/\\/+$/, '')\n const fetchImpl: FetchLike = options.fetch ?? ((input, init) => fetch(input, init))\n const timeoutMs = options.timeoutMs ?? 60_000\n\n async function request<T>(\n method: Method,\n path: string,\n reqOptions: RequestOptions<T> = {}\n ): Promise<T> {\n const url = buildUrl(serverUrl, path, reqOptions.query)\n const headers: Record<string, string> = {\n Accept: 'application/json',\n 'User-Agent': `${BIN_NAME}-cli/${VERSION}`,\n }\n if (options.apiKey) headers.Authorization = `Bearer ${options.apiKey}`\n if (reqOptions.body !== undefined) headers['Content-Type'] = 'application/json'\n\n let response: Response\n try {\n response = await fetchImpl(url, {\n method,\n headers,\n body: reqOptions.body === undefined ? undefined : JSON.stringify(reqOptions.body),\n signal: AbortSignal.timeout(timeoutMs),\n })\n } catch (cause) {\n throw new CliApiError({\n status: 0,\n code: 'network_error',\n message: `Could not reach ${serverUrl} (${describeCause(cause)})`,\n hint: 'Check your connection, or the URL given by `--server` / `FLING_URL`.',\n cause,\n })\n }\n\n const raw = await readBody(response)\n if (!response.ok) throw errorFromResponse(response.status, raw, method, path)\n if (!reqOptions.schema) return raw as T\n\n const parsed = reqOptions.schema.safeParse(raw)\n if (!parsed.success) {\n const issue = parsed.error.issues[0]\n const where = issue?.path.length ? ` at ${issue.path.join('.')}` : ''\n throw new CliApiError({\n status: response.status,\n code: 'invalid_response',\n body: raw,\n message: `Unexpected response from ${method} ${path}${where}: ${issue?.message ?? 'invalid'}`,\n hint: `Your ${BIN_NAME} CLI may be out of date \u2014 try \\`npm i -g ${PACKAGE_NAME}@latest\\`.`,\n })\n }\n return parsed.data\n }\n\n return { serverUrl, request }\n}\n\n/** Thrown by `putUpload`; `retryable` says whether trying again could help. */\nexport class UploadError extends Error {\n constructor(\n message: string,\n readonly retryable: boolean\n ) {\n super(message)\n this.name = 'UploadError'\n }\n}\n\n/** PUT bytes to a presigned URL with exactly the headers the server signed. */\nexport async function putUpload(\n fetchImpl: FetchLike,\n url: string,\n headers: Record<string, string>,\n body: Uint8Array,\n timeoutMs = 5 * 60_000\n): Promise<void> {\n let response: Response\n try {\n response = await fetchImpl(url, {\n method: 'PUT',\n headers,\n body: body as unknown as RequestInit['body'],\n signal: AbortSignal.timeout(timeoutMs),\n })\n } catch (cause) {\n throw new UploadError(`network error (${describeCause(cause)})`, true)\n }\n // Drain the body so the connection can be reused.\n await response.text().catch(() => '')\n if (response.ok) return\n const retryable = response.status >= 500 || response.status === 408 || response.status === 429\n throw new UploadError(`HTTP ${response.status}`, retryable)\n}\n\nasync function readBody(response: Response): Promise<unknown> {\n if (response.status === 204) return undefined\n const text = await response.text()\n if (text === '') return undefined\n try {\n return JSON.parse(text)\n } catch {\n return text\n }\n}\n\nfunction errorFromResponse(status: number, body: unknown, method: string, path: string) {\n const envelope = ErrorEnvelopeSchema.safeParse(body)\n if (envelope.success) {\n const { code } = envelope.data.error\n const error = new CliApiError({\n status,\n code,\n body,\n message: envelope.data.error.message,\n hint: code ? NEVER_PUBLISHED_HINTS[code] : undefined,\n })\n // The server's secret checks (the guarantee behind the CLI's own): keep the details for --json.\n const extra = (body as { error?: { findings?: unknown; paths?: unknown } }).error\n if (Array.isArray(extra?.findings)) Object.assign(error, { findings: extra.findings })\n if (Array.isArray(extra?.paths)) Object.assign(error, { paths: extra.paths })\n return error\n }\n return new CliApiError({ status, body, message: `${method} ${path} failed with HTTP ${status}` })\n}\n\n/** Hints for the server refusing dotfiles, secret files and secrets (no override exists). */\nconst NEVER_PUBLISHED_HINTS: Record<string, string> = {\n secret_detected:\n 'Remove the secret from the file (and rotate it if it was ever shared), or add the file to .flingignore if the site does not need it.',\n secret_file:\n 'Move the secret files out of the folder, or add them to .flingignore if the site does not need them.',\n dotfile: `Dotfiles are never flung. Update the CLI (\\`npm i -g ${PACKAGE_NAME}@latest\\`), which skips them.`,\n}\n\nfunction describeCause(cause: unknown): string {\n if (cause instanceof Error) {\n const inner = (cause as { cause?: unknown }).cause\n if (inner instanceof Error && 'code' in inner) return String((inner as { code: unknown }).code)\n if (cause.name === 'TimeoutError') return 'timed out'\n return cause.message\n }\n return String(cause)\n}\n", "/**\n * CLI config: `~/.fling/config.json` (dir 0700, file 0600) remembering every Fling server signed in\n * to, keyed by its normalised address, and which one is current:\n *\n * { \"current\": \"https://fling.example.com\",\n * \"servers\": { \"https://fling.example.com\": { \"instance\": {\u2026}, \"apiKey\": \"\u2026\", \"user\": {\u2026} } } }\n *\n * Each entry holds what the server said about itself at login (`/.well-known/fling`), its API key\n * and the signed-in user. There is no default server: `fling login <url>` adds one and makes it\n * current, `fling use <url>` switches. A single-server file (`serverUrl`, `instance`, `apiKey` and\n * `user` at the top level, written by 0.3) reads as one entry, which is current; the next save\n * writes the shape above. Entries it cannot read are left out, never fatal.\n *\n * Env overrides (for CI): `FLING_URL` picks a server for one run (a remembered one brings its key),\n * `FLING_API_KEY` overrides the key, `FLING_CONFIG_DIR` relocates the directory. `FLING_DEBUG`\n * enables debug lines. `FLING_ADD_SERVER` (the Claude Desktop extension a Fling serves sets it to\n * that Fling's address) is a server for the local MCP server to remember when it starts. This is the\n * only module that reads `process.env`.\n */\nimport { chmod, mkdir, readFile, stat, writeFile } from 'node:fs/promises'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport { type InstanceMetadata, InstanceMetadataSchema } from '@fling/shared'\nimport { z } from 'zod'\nimport { CliError } from './errors.ts'\n\nexport const CONFIG_DIR_NAME = '.fling'\nexport const CONFIG_FILE_NAME = 'config.json'\n\nexport const ENV = {\n apiKey: 'FLING_API_KEY',\n url: 'FLING_URL',\n configDir: 'FLING_CONFIG_DIR',\n debug: 'FLING_DEBUG',\n /** Where to look for files given by name (the .mcpb extension sets it from its settings). */\n downloadsDir: 'FLING_DOWNLOADS_DIR',\n /** A server the local MCP server adds to the remembered ones on start (the .mcpb bakes it in). */\n addServer: 'FLING_ADD_SERVER',\n} as const\n\n/** One remembered server. Each field is read on its own: one this CLI can't read is dropped. */\nexport const serverEntrySchema = z.object({\n /** What the server said about itself at login. A copy this CLI can't read is just refetched. */\n instance: InstanceMetadataSchema.optional().catch(undefined),\n apiKey: z.string().min(1).optional().catch(undefined),\n user: z\n .object({\n email: z.string().optional(),\n name: z.string().optional(),\n userSlug: z.string().optional(),\n })\n .optional()\n .catch(undefined),\n})\nexport type ServerEntry = z.infer<typeof serverEntrySchema>\n\nexport interface CliConfig {\n /** The server commands use unless `--server` or `FLING_URL` picks another. */\n current?: string\n /** Keyed by normalised server address (`normalizeServerUrl`). */\n servers: Record<string, ServerEntry>\n}\n\nexport type Env = Record<string, string | undefined>\n\n/** The real machine, for looking files up by name (locate.ts). */\nexport function systemLocateOptions(env: Env = process.env) {\n return { cwd: process.cwd(), home: homedir(), platform: process.platform, env }\n}\n\n/** An env value, ignoring blanks and unsubstituted `${user_config.\u2026}` placeholders (.mcpb). */\nfunction fromEnv(value: string | undefined): string | undefined {\n const v = value?.trim()\n return v && !v.startsWith('${') ? v : undefined\n}\n\n/** The server `FLING_ADD_SERVER` names, if any (an unsubstituted placeholder counts as none). */\nexport function serverToAdd(env: Env = process.env): string | undefined {\n return fromEnv(env[ENV.addServer])\n}\n\nexport function resolveConfigDir(env: Env = process.env): string {\n return env[ENV.configDir] ?? join(env.HOME ?? homedir(), CONFIG_DIR_NAME)\n}\n\nexport interface ResolvedConfig {\n /** Unset until `fling login <url>` (or FLING_URL / --server). */\n serverUrl?: string\n serverUrlSource: 'flag' | 'env' | 'config' | 'none'\n /** The current server; `serverUrl` differs from it when `--server` or FLING_URL picks another. */\n current?: string\n /** Whether `serverUrl` has an entry in the config. */\n remembered: boolean\n /** The stored metadata of `serverUrl`. */\n instance?: InstanceMetadata\n apiKey?: string\n apiKeySource: 'env' | 'config' | 'none'\n user?: ServerEntry['user']\n debug: boolean\n}\n\nexport interface ConfigStore {\n readonly dir: string\n readonly file: string\n load(): Promise<CliConfig>\n save(config: CliConfig): Promise<void>\n /**\n * Add a server, or merge `patch` into its entry. It becomes current when `makeCurrent` says so\n * or, by default, when no server is current.\n */\n putServer(\n serverUrl: string,\n patch: ServerEntry,\n options?: { makeCurrent?: boolean }\n ): Promise<CliConfig>\n /** Make a server current (with an empty entry if it has none). */\n setCurrent(serverUrl: string): Promise<void>\n /** Remove a server's key and user; keep the server and its instance. */\n clearCredentials(serverUrl: string): Promise<void>\n /** Forget a server. Forgetting the current one leaves no server current. */\n removeServer(serverUrl: string): Promise<void>\n /** Merge file + env + an optional `--server` flag into what a command should use. */\n resolve(overrides?: { serverUrl?: string }): Promise<ResolvedConfig>\n}\n\nfunction safeNormalize(input: unknown): string | undefined {\n if (typeof input !== 'string') return undefined\n try {\n return normalizeServerUrl(input)\n } catch {\n return undefined\n }\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n/** A config file's JSON, in either shape. Throws only when it is not a JSON object. */\nexport function parseConfig(json: unknown): CliConfig {\n if (!isObject(json)) throw new Error('expected a JSON object')\n const servers: Record<string, ServerEntry> = {}\n let current: string | undefined\n if ('servers' in json) {\n if (isObject(json.servers)) {\n for (const [key, value] of Object.entries(json.servers)) {\n const url = safeNormalize(key)\n const entry = isObject(value) ? serverEntrySchema.safeParse(value) : undefined\n if (url && entry?.success) servers[url] = { ...servers[url], ...entry.data }\n }\n }\n current = safeNormalize(json.current)\n } else {\n // The single-server shape: its server is the one entry, and current.\n current = safeNormalize(json.serverUrl)\n if (current) servers[current] = serverEntrySchema.parse(json)\n }\n if (current && !servers[current]) servers[current] = {}\n return current ? { current, servers } : { servers }\n}\n\nexport function createConfigStore(options: { dir?: string; env?: Env } = {}): ConfigStore {\n const env = options.env ?? process.env\n const dir = options.dir ?? resolveConfigDir(env)\n const file = join(dir, CONFIG_FILE_NAME)\n\n async function load(): Promise<CliConfig> {\n let raw: string\n try {\n raw = await readFile(file, 'utf8')\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return { servers: {} }\n throw error\n }\n let json: unknown\n try {\n json = JSON.parse(raw)\n } catch {\n throw new Error(`Config file ${file} is not valid JSON`)\n }\n try {\n return parseConfig(json)\n } catch (error) {\n throw new Error(`Config file ${file} is invalid: ${(error as Error).message}`)\n }\n }\n\n async function save(config: CliConfig): Promise<void> {\n await mkdir(dir, { recursive: true, mode: 0o700 })\n await chmod(dir, 0o700).catch(() => {})\n const body = { current: config.current, servers: config.servers }\n await writeFile(file, `${JSON.stringify(body, null, 2)}\\n`, { mode: 0o600 })\n // `mode` only applies on creation; tighten an existing file too.\n await chmod(file, 0o600)\n }\n\n async function edit(change: (config: CliConfig) => void): Promise<CliConfig> {\n const config = await load()\n change(config)\n await save(config)\n return config\n }\n\n return {\n dir,\n file,\n load,\n save,\n putServer(serverUrl, patch, opts = {}) {\n const url = normalizeServerUrl(serverUrl)\n return edit(config => {\n config.servers[url] = { ...config.servers[url], ...patch }\n if (opts.makeCurrent ?? !config.current) config.current = url\n })\n },\n async setCurrent(serverUrl) {\n const url = normalizeServerUrl(serverUrl)\n await edit(config => {\n config.servers[url] ??= {}\n config.current = url\n })\n },\n async clearCredentials(serverUrl) {\n const url = normalizeServerUrl(serverUrl)\n await edit(config => {\n const entry = config.servers[url]\n if (entry) config.servers[url] = entry.instance ? { instance: entry.instance } : {}\n })\n },\n async removeServer(serverUrl) {\n const url = normalizeServerUrl(serverUrl)\n await edit(config => {\n delete config.servers[url]\n if (config.current === url) config.current = undefined\n })\n },\n async resolve(overrides = {}) {\n const config = await load()\n const envUrl = fromEnv(env[ENV.url])\n const envKey = fromEnv(env[ENV.apiKey])\n const [rawUrl, serverUrlSource]: [string | undefined, ResolvedConfig['serverUrlSource']] =\n overrides.serverUrl\n ? [overrides.serverUrl, 'flag']\n : envUrl\n ? [envUrl, 'env']\n : config.current\n ? [config.current, 'config']\n : [undefined, 'none']\n const serverUrl =\n rawUrl === undefined\n ? undefined\n : matchServer(Object.keys(config.servers), rawUrl, { loose: true }).url\n const entry = serverUrl === undefined ? undefined : config.servers[serverUrl]\n const [apiKey, apiKeySource]: [string | undefined, ResolvedConfig['apiKeySource']] = envKey\n ? [envKey, 'env']\n : entry?.apiKey\n ? [entry.apiKey, 'config']\n : [undefined, 'none']\n return {\n serverUrl,\n serverUrlSource,\n current: config.current,\n remembered: entry !== undefined,\n instance: entry?.instance,\n apiKey,\n apiKeySource,\n user: entry?.user,\n debug: Boolean(env[ENV.debug]),\n }\n },\n }\n}\n\nconst HAS_SCHEME = /^[a-z][a-z0-9+.-]*:\\/\\//i\n\n/**\n * Which server `input` names, given the remembered ones. An address that normalises to a\n * remembered one is that one. Without a scheme, `input` may also name one by host\n * (`localhost:47101`, whatever its scheme) and, when `loose`, by the start of its address or a\n * parent domain (`example.com` for `https://fling.example.com`), as long as only one matches.\n * Anything else is the address as given, not remembered. Throws when `input` is not an address or\n * matches several servers.\n */\nexport function matchServer(\n remembered: readonly string[],\n input: string,\n options: { loose?: boolean } = {}\n): { url: string; remembered: boolean } {\n const trimmed = input.trim()\n const normalized = safeNormalize(trimmed)\n if (normalized && remembered.includes(normalized)) return { url: normalized, remembered: true }\n if (!HAS_SCHEME.test(trimmed)) {\n const bare = trimmed.replace(/\\/+$/, '').toLowerCase()\n const parts = remembered.map(url => {\n const u = new URL(url)\n return { url, host: u.host, hostname: u.hostname, address: `${u.host}${u.pathname}` }\n })\n const tiers = [\n parts.filter(p => p.host === bare || p.address === bare),\n options.loose && bare\n ? parts.filter(p => p.address.startsWith(bare) || p.hostname.endsWith(`.${bare}`))\n : [],\n ]\n for (const found of tiers) {\n const [only] = found\n if (only && found.length === 1) return { url: only.url, remembered: true }\n if (found.length > 1)\n throw new CliError(`\"${input}\" matches more than one server you have signed in to`, {\n hint: `Use the full address: ${found.map(p => p.url).join(', ')}`,\n })\n }\n }\n if (!normalized)\n throw new CliError(`\"${input}\" is not a server address`, {\n hint: \"Use your Fling's address, e.g. https://fling.example.com.\",\n })\n return { url: normalized, remembered: false }\n}\n\n/**\n * `fling.example.test` \u2192 `https://fling.example.test`; trailing slashes go. Anything after the host\n * is kept (a server may live under a path). Throws on something that isn't a URL.\n */\nexport function normalizeServerUrl(input: string): string {\n const trimmed = input.trim()\n const withScheme = HAS_SCHEME.test(trimmed) ? trimmed : `https://${trimmed}`\n const url = new URL(withScheme)\n if (url.protocol !== 'https:' && url.protocol !== 'http:') {\n throw new Error(`Not an http(s) URL: ${input}`)\n }\n return `${url.origin}${url.pathname}`.replace(/\\/+$/, '')\n}\n\n/** File mode bits (e.g. `0o600`) or null when the path does not exist. */\nexport async function fileMode(path: string): Promise<number | null> {\n try {\n return (await stat(path)).mode & 0o777\n } catch {\n return null\n }\n}\n\nconst REDACTED_KEY_CHARS = 10\n\n/** Show only the key prefix \u2014 never the full secret. `fling_ab12\u2026` */\nexport function redactKey(key: string | undefined): string {\n if (!key) return '-'\n return key.length <= REDACTED_KEY_CHARS + 8 ? '****' : `${key.slice(0, REDACTED_KEY_CHARS)}\u2026`\n}\n", "/**\n * The instance the CLI talks to, from its `/.well-known/fling`: fetched (and so checked to be a\n * Fling) by `fling login <url>`, stored in the config, and read from there by every later command\n * and by the local MCP server. A config written before metadata existed (0.2) gets it fetched and\n * stored on first use.\n */\nimport { type InstanceMetadata, InstanceMetadataSchema, instanceMetadataUrl } from '@fling/shared'\nimport type { FetchLike } from './api.ts'\nimport type { ConfigStore, ResolvedConfig } from './config.ts'\nimport { CliError } from './errors.ts'\n\n/** GET `<server>/.well-known/fling`, validated. Throws a CliError saying what is wrong. */\nexport async function fetchInstance(\n serverUrl: string,\n fetch: FetchLike\n): Promise<InstanceMetadata> {\n const url = instanceMetadataUrl(serverUrl)\n let response: Response\n try {\n response = await fetch(url, { headers: { Accept: 'application/json' } })\n } catch (cause) {\n throw new CliError(`Could not reach ${serverUrl} (${(cause as Error).message ?? cause})`, {\n hint: 'Check the address and your connection.',\n cause,\n })\n }\n const notFling = () =>\n new CliError(`${serverUrl} does not look like a Fling server (no valid ${url})`, {\n hint: 'Use the address of your Fling, e.g. https://fling.example.com.',\n })\n if (!response.ok) throw notFling()\n const parsed = InstanceMetadataSchema.safeParse(await response.json().catch(() => null))\n if (!parsed.success) throw notFling()\n return parsed.data\n}\n\n/**\n * The instance for `config`: the stored copy, else fetched \u2014 and stored when `serverUrl` is a\n * remembered server (not a one-off `--server` / FLING_URL address). Null when it can't be had;\n * never throws.\n */\nexport async function loadInstance(\n store: ConfigStore,\n config: Pick<ResolvedConfig, 'serverUrl' | 'remembered' | 'instance'>,\n fetch: FetchLike\n): Promise<InstanceMetadata | null> {\n if (config.instance) return config.instance\n if (!config.serverUrl) return null\n try {\n const instance = await fetchInstance(config.serverUrl, fetch)\n if (config.remembered)\n await store.putServer(config.serverUrl, { instance }, { makeCurrent: false })\n return instance\n } catch {\n return null\n }\n}\n", "/**\n * Per-invocation command context: resolved config, logger (stderr), output (stdout) and the\n * injectable seams tests use (`fetch`, `open`, `confirm`, TTY). Commands receive a context and\n * return; they never touch `process` directly.\n */\nimport { confirm, isCancel, text } from '@clack/prompts'\nimport { type ApiClient, createApiClient, type FetchLike } from './api.ts'\nimport { type ConfigStore, createConfigStore, type Env, type ResolvedConfig } from './config.ts'\nimport { CliError, NoServerError, NotLoggedInError } from './errors.ts'\nimport { BIN_NAME } from './package-info.ts'\nimport { createReadyWaiter, type ReadyWaiter } from './ready.ts'\nimport { createLogger, type Logger } from './utils/logger.ts'\nimport { createOutput, type Output } from './utils/output.ts'\n\nexport type OpenLike = (url: string) => Promise<unknown>\nexport type ConfirmLike = (question: string) => Promise<boolean>\n/** Ask a free-text question on the terminal; resolves to the raw answer (untrimmed). */\nexport type PromptLike = (question: string) => Promise<string>\n\nexport interface CommandContext {\n store: ConfigStore\n /** Config merged with env and `--server` \u2014 what the command should use. */\n config: ResolvedConfig\n json: boolean\n log: Logger\n out: Output\n fetch: FetchLike\n open: OpenLike\n /** Whether stdin/stderr are an interactive terminal (prompts, progress line). */\n interactive: boolean\n confirm: ConfirmLike\n prompt: PromptLike\n /** Rewrites a single status line on stderr (TTY only); `null` clears it. */\n progress: (line: string | null) => void\n binName: string\n /** Waits for a new site / share link to reach the edge; absent \u2192 no wait (tests). */\n waitReady?: ReadyWaiter\n}\n\nexport interface ContextOptions {\n /** `--server <url>` */\n server?: string\n json?: boolean\n store?: ConfigStore\n env?: Env\n log?: Logger\n out?: Output\n fetch?: FetchLike\n open?: OpenLike\n}\n\nexport async function createContext(options: ContextOptions = {}): Promise<CommandContext> {\n const store = options.store ?? createConfigStore({ env: options.env })\n const json = options.json ?? false\n const config = await store.resolve({ serverUrl: options.server })\n const interactive = Boolean(process.stdin.isTTY && process.stderr.isTTY)\n return {\n store,\n config,\n json,\n log: options.log ?? createLogger({ debug: config.debug }),\n out: options.out ?? createOutput({ json }),\n fetch: options.fetch ?? ((input, init) => fetch(input, init)),\n open: options.open ?? (async url => (await import('open')).default(url)),\n interactive,\n confirm: ttyConfirm,\n prompt: ttyPrompt,\n progress: interactive ? ttyProgress : () => {},\n binName: BIN_NAME,\n waitReady: createReadyWaiter({ env: options.env }),\n }\n}\n\n// Prompts draw on stderr so stdout stays clean for pipes and --json. Ctrl-C / Esc cancels.\nasync function ttyConfirm(question: string): Promise<boolean> {\n const answer = await confirm({ message: question, initialValue: false, output: process.stderr })\n if (isCancel(answer)) throw new CliError('Cancelled')\n return answer\n}\n\nasync function ttyPrompt(question: string): Promise<string> {\n const answer = await text({ message: question.trim(), output: process.stderr })\n if (isCancel(answer)) throw new CliError('Cancelled')\n return answer ?? ''\n}\n\nfunction ttyProgress(line: string | null): void {\n process.stderr.write(`\\r\\x1b[2K${line ?? ''}`)\n}\n\n/** The server to talk to, or `NoServerError` (exit 2): there is no default server. */\nexport function requireServer(ctx: Pick<CommandContext, 'config' | 'binName'>): string {\n if (!ctx.config.serverUrl) throw new NoServerError(ctx.binName)\n return ctx.config.serverUrl\n}\n\n/** An authenticated client, or `NoServerError` / `NotLoggedInError` (exit 2). */\nexport function requireClient(\n ctx: Pick<CommandContext, 'config' | 'fetch' | 'binName'>\n): ApiClient {\n const serverUrl = requireServer(ctx)\n if (!ctx.config.apiKey) throw new NotLoggedInError(ctx.binName)\n return createApiClient({\n serverUrl,\n apiKey: ctx.config.apiKey,\n fetch: ctx.fetch,\n })\n}\n", "/**\n * After a deploy goes live or a share link is created, wait until the edge routes the URL (the\n * shared `waitUntilReachable`), so the link we print doesn't 404 for the first few seconds.\n * `FLING_NO_WAIT=1` (and test runs) skip it.\n */\nimport {\n NOT_READY_NOTE,\n probeUrl,\n type ReachableResult,\n readinessWaitDisabled,\n waitUntilReachable,\n} from '@fling/shared'\nimport chalk from 'chalk'\nimport type { FetchLike } from './api.ts'\nimport type { Env } from './config.ts'\n\nexport interface ReadyResult extends ReachableResult {\n /** the wait was skipped (FLING_NO_WAIT / tests): `ready` is assumed */\n skipped?: boolean\n}\n\n/** Poll `url` (a site or share URL) whose served version has `paths`. */\nexport type ReadyWaiter = (\n url: string,\n paths: readonly string[],\n opts?: { onWaiting?: () => void }\n) => Promise<ReadyResult>\n\nexport const skipWait: ReadyWaiter = async () => ({ ready: true, waitedMs: 0, skipped: true })\n\nexport function createReadyWaiter(\n options: { env?: Env; fetch?: FetchLike; timeoutMs?: number } = {}\n): ReadyWaiter {\n if (readinessWaitDisabled(options.env ?? process.env)) return skipWait\n return (url, paths, opts) =>\n waitUntilReachable(probeUrl(url, paths), {\n timeoutMs: options.timeoutMs,\n fetch: options.fetch,\n onWaiting: opts?.onWaiting,\n })\n}\n\nconst SPINNER = ['\u280B', '\u2819', '\u2839', '\u2838', '\u283C', '\u2834', '\u2826', '\u2827', '\u2807', '\u280F']\n\n/**\n * Wait with a spinner line (\"Waiting for the edge\u2026\") on a terminal; on timeout, warn with the\n * URL and the \"reload if you see a 404\" note. Never throws.\n */\nexport async function waitWithSpinner(\n waiter: ReadyWaiter | undefined,\n url: string,\n paths: readonly string[],\n io: { progress: (line: string | null) => void; warn: (message: string) => void }\n): Promise<ReadyResult> {\n if (!waiter) return { ready: true, waitedMs: 0, skipped: true }\n let frame = 0\n let timer: ReturnType<typeof setInterval> | undefined\n const draw = () =>\n io.progress(`${chalk.cyan(SPINNER[frame++ % SPINNER.length])} Waiting for the edge\u2026`)\n try {\n const result = await waiter(url, paths, {\n onWaiting: () => {\n draw()\n timer = setInterval(draw, 100)\n timer.unref?.()\n },\n }).catch(() => ({ ready: false, waitedMs: 0 }))\n if (timer) io.progress(null)\n if (!result.ready) io.warn(`${url} \u2014 ${NOT_READY_NOTE}`)\n return result\n } finally {\n if (timer) clearInterval(timer)\n }\n}\n", "/**\n * Status logger. Everything here goes to STDERR so `--json` stdout stays pipe-clean (and so the MCP\n * server's stdout carries only protocol). `debug` lines appear only when `FLING_DEBUG` is set.\n */\nimport chalk from 'chalk'\nimport { symbols } from '../ui/theme.ts'\n\nexport interface Logger {\n info(message: string): void\n success(message: string): void\n warn(message: string): void\n error(message: string): void\n /** Secondary guidance under an info/error line, dimmed. */\n hint(message: string): void\n debug(message: string): void\n}\n\nexport interface LoggerOptions {\n write?: (line: string) => void\n debug?: boolean\n}\n\nexport function createLogger(options: LoggerOptions = {}): Logger {\n const write = options.write ?? ((line: string) => process.stderr.write(`${line}\\n`))\n const debugEnabled = options.debug ?? false\n return {\n info: message => write(`${symbols.info} ${message}`),\n success: message => write(`${symbols.success} ${message}`),\n warn: message => write(`${symbols.warn} ${chalk.yellow(message)}`),\n error: message => write(`${symbols.error} ${chalk.red(message)}`),\n hint: message => write(chalk.dim(` ${message}`)),\n debug: message => {\n if (debugEnabled) write(chalk.dim(`[debug] ${message}`))\n },\n }\n}\n\n/** A logger that records lines instead of printing \u2014 for tests. */\nexport function createMemoryLogger(debug = false): Logger & { lines: string[] } {\n const lines: string[] = []\n const logger = createLogger({ write: line => lines.push(line), debug })\n return Object.assign(logger, { lines })\n}\n\n/** A logger that prints nothing (the MCP server). */\nexport const silentLogger: Logger = {\n info: () => {},\n success: () => {},\n warn: () => {},\n error: () => {},\n hint: () => {},\n debug: () => {},\n}\n", "/**\n * The CLI's look: the FLING logo (a left-to-right gradient with motion trails), brand colours,\n * symbols and a box for the URL a deploy hands back. Everything degrades to plain text when chalk\n * has no colour (NO_COLOR, pipes).\n */\nimport chalk from 'chalk'\n\n/** Gradient stops, left to right: cyan \u2192 violet \u2192 pink. */\nconst STOPS: readonly [number, number, number][] = [\n [0x00, 0xe5, 0xff],\n [0x7c, 0x4d, 0xff],\n [0xff, 0x4e, 0xcd],\n]\n\nconst WORDMARK = [\n '\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ',\n '\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D ',\n '\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2557',\n '\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551',\n '\u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D',\n '\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D ',\n]\n\n/** Speed lines to the left of the wordmark: it has just been flung. */\nconst TRAILS = [' ', ' \u2501\u2501\u2501 ', ' \u2501\u2501\u2501\u2501 ', ' \u2501\u2501 ', ' ', ' ']\n\nconst LOGO_WIDTH = TRAILS[0].length + WORDMARK[0].length\n\nexport const brand = {\n primary: chalk.hex('#7C4DFF'),\n accent: chalk.hex('#00E5FF'),\n url: (url: string) => chalk.bold.hex('#00E5FF')(url),\n}\n\nexport const symbols = {\n info: chalk.hex('#7C4DFF')('\u25C6'),\n success: chalk.green('\u2714'),\n warn: chalk.yellow('\u25B2'),\n error: chalk.red('\u2716'),\n step: chalk.dim('\u2502'),\n}\n\nfunction colourAt(t: number): [number, number, number] {\n const scaled = Math.min(Math.max(t, 0), 1) * (STOPS.length - 1)\n const i = Math.min(Math.floor(scaled), STOPS.length - 2)\n const f = scaled - i\n const a = STOPS[i] as [number, number, number]\n const b = STOPS[i + 1] as [number, number, number]\n return [0, 1, 2].map(k => Math.round(a[k] + (b[k] - a[k]) * f)) as [number, number, number]\n}\n\n/** Colour each character of `text` along the gradient (position `offset` of `width`). */\nexport function gradient(text: string, width = text.length, offset = 0): string {\n if (chalk.level === 0) return text\n return [...text]\n .map((ch, i) => (ch === ' ' ? ch : chalk.rgb(...colourAt((offset + i) / (width - 1)))(ch)))\n .join('')\n}\n\n/**\n * The logo with a tagline, or a one-line wordmark when the terminal is too narrow for the big one.\n */\nexport function logo(options: { columns?: number; tagline?: string } = {}): string {\n const columns = options.columns || process.stderr.columns || 80\n const tagline = options.tagline ?? 'throw static files at the web, get a link back'\n if (columns < LOGO_WIDTH + 2) return `${gradient('\u25B6\u25B6 fling')} ${chalk.dim(tagline)}`\n const lines = WORDMARK.map(\n (row, i) => chalk.dim(TRAILS[i] ?? '') + gradient(row, WORDMARK[0].length)\n )\n return ['', ...lines, `${' '.repeat(TRAILS[0].length)}${chalk.dim(tagline)}`, ''].join('\\n')\n}\n\n// biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI escapes\nconst ANSI = /\\x1b\\[[0-9;]*m/g\nconst visibleLength = (s: string) => s.replace(ANSI, '').length\n\n/** A rounded box around `lines`, with an optional title in the top border. */\nexport function box(lines: readonly string[], title?: string): string {\n const width = Math.max(...lines.map(visibleLength), title ? visibleLength(title) + 2 : 0)\n const border = chalk.dim\n const top = title\n ? `${border('\u256D\u2500')} ${title} ${border(`${'\u2500'.repeat(width - visibleLength(title) - 1)}\u256E`)}`\n : border(`\u256D${'\u2500'.repeat(width + 2)}\u256E`)\n const body = lines.map(\n line => `${border('\u2502')} ${line}${' '.repeat(width - visibleLength(line))} ${border('\u2502')}`\n )\n return [top, ...body, border(`\u2570${'\u2500'.repeat(width + 2)}\u256F`)].join('\\n')\n}\n", "/**\n * Data output. `Output.data(raw, human)` prints `raw` as JSON under `--json` or the human rendering\n * otherwise \u2014 both to STDOUT. Tables are plain text so they diff and grep well.\n */\nimport chalk from 'chalk'\n\nexport interface Output {\n readonly json: boolean\n /** stdout is a terminal (not a pipe): human output may be decorated (boxes, logo). */\n readonly tty: boolean\n /** Print `raw` as JSON under `--json`, otherwise the result of `human()`. */\n data(raw: unknown, human: () => string): void\n /** Print a human-only line (skipped under `--json`). */\n text(line: string): void\n}\n\nexport interface OutputOptions {\n json?: boolean\n tty?: boolean\n write?: (chunk: string) => void\n}\n\nexport function createOutput(options: OutputOptions = {}): Output {\n const json = options.json ?? false\n const write = options.write ?? ((chunk: string) => process.stdout.write(chunk))\n return {\n json,\n tty: options.tty ?? (options.write ? false : Boolean(process.stdout.isTTY)),\n data: (raw, human) => write(`${json ? formatJson(raw) : human()}\\n`),\n text: line => {\n if (!json) write(`${line}\\n`)\n },\n }\n}\n\n/** An output that records what was written \u2014 for tests. */\nexport function createMemoryOutput(json = false): Output & { chunks: string[]; content(): string } {\n const chunks: string[] = []\n const output = createOutput({ json, write: chunk => chunks.push(chunk) })\n return Object.assign(output, { chunks, content: () => chunks.join('') })\n}\n\nexport function formatJson(value: unknown): string {\n return JSON.stringify(value, null, 2)\n}\n\nexport interface Column<Row> {\n header: string\n value: (row: Row) => unknown\n}\n\n/** Left-aligned columns separated by two spaces; header in bold; `-` for null/undefined. */\nexport function renderTable<Row>(rows: readonly Row[], columns: readonly Column<Row>[]): string {\n if (rows.length === 0) return chalk.dim('(no results)')\n const cells = rows.map(row => columns.map(column => formatCell(column.value(row))))\n const widths = columns.map((column, i) =>\n Math.max(column.header.length, ...cells.map(line => line[i]?.length ?? 0))\n )\n const pad = (text: string, i: number) =>\n i === columns.length - 1 ? text : text.padEnd(widths[i] ?? 0)\n const header = columns.map((column, i) => pad(column.header, i)).join(' ')\n const body = cells.map(line => line.map(pad).join(' '))\n return [chalk.bold(header), ...body].join('\\n')\n}\n\nexport function formatCell(value: unknown): string {\n if (value === null || value === undefined || value === '') return '-'\n if (typeof value === 'object') return JSON.stringify(value)\n return String(value)\n}\n\n/** `2026-09-01 07:54` in local time, or `-` for null. */\nexport function formatDate(value: string | null | undefined): string {\n if (!value) return '-'\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return String(value)\n const pad = (n: number) => String(n).padStart(2, '0')\n return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`\n}\n\n/** `1.2 MB` */\nexport function formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`\n const units = ['KB', 'MB', 'GB']\n let value = bytes / 1024\n let unit = 0\n while (value >= 1024 && unit < units.length - 1) {\n value /= 1024\n unit++\n }\n return `${value.toFixed(value < 10 ? 1 : 0)} ${units[unit]}`\n}\n", "/**\n * The site operations, as plain functions over an `ApiClient` that return data. The CLI commands\n * print what these return; the MCP tools serialise it. Nothing here prints.\n */\nimport {\n type AudienceChange,\n type Comment,\n type CommentList,\n CommentListSchema,\n CommentSchema,\n type CreateGroupRequest,\n editAudienceInput,\n type GroupDetail,\n GroupDetailSchema,\n GroupListSchema,\n type GroupMembersRequest,\n type GroupSummary,\n type InstanceMetadata,\n type Me,\n MeSchema,\n type NameCheck,\n NameCheckSchema,\n type SharedSite,\n SharedSiteListSchema,\n type Site,\n type SiteDetail,\n SiteDetailSchema,\n SiteListSchema,\n SiteSchema,\n type SiteSort,\n type SiteWithAudience,\n SiteWithAudienceSchema,\n siteUrl,\n sortSites,\n splitEmails,\n type VersionFiles,\n VersionFilesSchema,\n type Visibility,\n} from '@fling/shared'\nimport { z } from 'zod'\nimport type { ApiClient } from './api.ts'\nimport { CliError } from './errors.ts'\n\n/**\n * Response of `POST /api/sites/:name/share`. Not (yet) in `@fling/shared/api.ts`, so it lives here;\n * tolerant of the server returning the whole site alongside.\n */\nexport const ShareResponseSchema = z.looseObject({ shareUrl: z.string() })\n\nconst sitePath = (name: string) => `/api/sites/${encodeURIComponent(name)}`\n\nexport function whoami(client: ApiClient): Promise<Me> {\n return client.request('GET', '/api/me', { schema: MeSchema })\n}\n\n/** GET /api/names/:name \u2014 available, yours, taken (with free suggestions) or invalid. */\nexport function checkName(client: ApiClient, name: string): Promise<NameCheck> {\n return client.request('GET', `/api/names/${encodeURIComponent(name)}`, {\n schema: NameCheckSchema,\n })\n}\n\n/** Where sites are served: `https:` + `sites.example.test` (a site is `<name>.<domain>`). */\nexport interface SitesBase {\n protocol: string\n /** host, including any port */\n domain: string\n}\n\n/** From the instance metadata (`sitesDomain`, `siteScheme`); null when there is none. */\nexport function sitesBaseOf(\n instance: Pick<InstanceMetadata, 'sitesDomain' | 'siteScheme'> | null | undefined\n): SitesBase | null {\n return instance ? { protocol: `${instance.siteScheme}:`, domain: instance.sitesDomain } : null\n}\n\nexport function siteUrlFor(name: string, base: SitesBase): string {\n return siteUrl(name, base.domain, base.protocol)\n}\n\n/** `https://<name>.sites.example.test/` for display. */\nexport function sitesPattern(base: SitesBase | null): string {\n return base ? siteUrlFor('<name>', base) : '<name>.<sites domain>'\n}\n\nexport async function listSites(\n client: ApiClient,\n opts: { archived?: boolean; sort?: SiteSort } = {}\n): Promise<Site[]> {\n const res = await client.request('GET', '/api/sites', {\n schema: SiteListSchema,\n query: { archived: opts.archived ? 1 : undefined },\n })\n return sortSites(res.sites, opts.sort)\n}\n\n/** The restricted sites others have shared with the caller, in `sort` order (default updated). */\nexport async function listShared(\n client: ApiClient,\n opts: { sort?: SiteSort } = {}\n): Promise<SharedSite[]> {\n const res = await client.request('GET', '/api/shared', { schema: SharedSiteListSchema })\n return sortSites(res.sites, opts.sort)\n}\n\nexport function getSite(client: ApiClient, name: string): Promise<SiteDetail> {\n return client.request('GET', sitePath(name), { schema: SiteDetailSchema })\n}\n\nexport interface SiteFiles extends VersionFiles {\n name: string\n url: string\n /** the version being served */\n current: boolean\n}\n\n/** The files in `versionId`, or in the version being served when omitted. */\nexport async function versionFiles(\n client: ApiClient,\n name: string,\n versionId?: string\n): Promise<SiteFiles> {\n const site = await getSite(client, name)\n const id = versionId ?? site.currentVersionId\n if (!id) throw new CliError(`${name} has no published version yet`)\n const files = await client.request(\n 'GET',\n `${sitePath(name)}/versions/${encodeURIComponent(id)}/files`,\n { schema: VersionFilesSchema }\n )\n return { name: site.name, url: site.url, current: id === site.currentVersionId, ...files }\n}\n\n/**\n * Mutations whose response body the contract does not pin down: use it when it is a site, else\n * read the site back.\n */\nasync function siteAfter(client: ApiClient, name: string, raw: unknown): Promise<Site> {\n const parsed = SiteSchema.safeParse(raw)\n if (parsed.success) return parsed.data\n const nested = SiteSchema.safeParse((raw as { site?: unknown } | undefined)?.site)\n if (nested.success) return nested.data\n return getSite(client, name)\n}\n\nexport async function rollback(client: ApiClient, name: string, versionId: string): Promise<Site> {\n const raw = await client.request('POST', `${sitePath(name)}/current`, { body: { versionId } })\n return siteAfter(client, name, raw)\n}\n\nexport async function setVisibility(\n client: ApiClient,\n name: string,\n visibility: Visibility\n): Promise<Site> {\n const raw = await client.request('PATCH', sitePath(name), { body: { visibility } })\n return siteAfter(client, name, raw)\n}\n\n/** The site with its audience; a server without audiences fails (it reports none). */\nexport async function getAudience(client: ApiClient, name: string): Promise<SiteDetail> {\n const site = await getSite(client, name)\n if (!site.audience) throw noAudiences()\n return site\n}\n\nconst noAudiences = () =>\n new CliError('This Fling does not support limiting a site to listed people', {\n hint: 'Ask its operator to update it.',\n })\n\n/**\n * Change who can see a private site (addresses and groups, as `editAudienceInput`): PATCH the\n * whole new audience. Returns the site with its audience.\n */\nexport async function setAudience(\n client: ApiClient,\n name: string,\n change: AudienceChange\n): Promise<SiteWithAudience & { audience: NonNullable<SiteWithAudience['audience']> }> {\n const current = await getAudience(client, name)\n const audience = current.audience as NonNullable<SiteDetail['audience']>\n const site = await client.request('PATCH', sitePath(name), {\n schema: SiteWithAudienceSchema,\n body: { audience: editAudienceInput(audience, change) },\n })\n if (!site.audience) throw noAudiences()\n return site as typeof site & { audience: NonNullable<typeof site.audience> }\n}\n\n/**\n * Warnings about who can still open a site, or why its audience doesn't apply: a share link on a\n * restricted site, or an audience on a public one.\n */\nexport function audienceWarnings(site: SiteWithAudience): string[] {\n const n = site.audience\n ? site.audience.emails.length + site.audience.groups.length\n : site.audienceSize\n if (site.visibility === 'public' && n > 0) {\n return [\n `${site.name} is public, so its audience doesn't apply yet; it does once the site is private: fling visibility ${site.name} private`,\n ]\n }\n if (site.restricted && site.shareUrl) {\n return [`${site.name} has a share link: anyone with it can still open the site`]\n }\n return []\n}\n\n/**\n * Whether the instance can limit sites to listed people, by its stored metadata: its `audiences`\n * capability, or \u2014 when the stored copy predates the flag \u2014 yes, and the server decides. No\n * instance at all: no.\n */\nexport function audiencesEnabled(\n instance: Pick<InstanceMetadata, 'capabilities'> | null | undefined\n): boolean {\n if (!instance) return false\n return instance.capabilities.audiences ?? true\n}\n\n// --- groups ---\n\nconst groupPath = (slug: string) => `/api/groups/${encodeURIComponent(slug)}`\n\n/**\n * Every group on the Fling, or (`mine`) the caller's own; by slug. With `members`, only the groups\n * whose members are exactly those addresses.\n */\nexport async function listGroups(\n client: ApiClient,\n opts: { mine?: boolean; members?: readonly string[] } = {}\n): Promise<GroupSummary[]> {\n const res = await client.request('GET', '/api/groups', {\n schema: GroupListSchema,\n query: {\n mine: opts.mine ? 1 : undefined,\n members: opts.members ? splitEmails(opts.members).join(',') : undefined,\n },\n })\n return res.groups\n}\n\nexport function getGroup(client: ApiClient, slug: string): Promise<GroupDetail> {\n return client.request('GET', groupPath(slug), { schema: GroupDetailSchema })\n}\n\nexport function createGroup(client: ApiClient, input: CreateGroupRequest): Promise<GroupDetail> {\n return client.request('POST', '/api/groups', { schema: GroupDetailSchema, body: input })\n}\n\n/** Add people to a group the caller owns, then take people out. */\nexport function changeGroupMembers(\n client: ApiClient,\n slug: string,\n change: GroupMembersRequest\n): Promise<GroupDetail> {\n return client.request('POST', `${groupPath(slug)}/members`, {\n schema: GroupDetailSchema,\n body: change,\n })\n}\n\nexport function renameGroup(client: ApiClient, slug: string, name: string): Promise<GroupDetail> {\n return client.request('PATCH', groupPath(slug), { schema: GroupDetailSchema, body: { name } })\n}\n\nexport async function deleteGroup(\n client: ApiClient,\n slug: string\n): Promise<{ slug: string; deleted: true }> {\n await client.request('DELETE', groupPath(slug))\n return { slug, deleted: true }\n}\n\n/**\n * Whether the instance has groups, by its stored metadata: its `groups` capability, or \u2014 when the\n * stored copy predates the flag \u2014 yes, and the server decides. No instance at all: no.\n */\nexport function groupsEnabled(\n instance: Pick<InstanceMetadata, 'capabilities'> | null | undefined\n): boolean {\n if (!instance) return false\n return instance.capabilities.groups ?? true\n}\n\nexport async function archiveSite(\n client: ApiClient,\n name: string,\n opts: { unarchive?: boolean } = {}\n): Promise<Site> {\n const raw = await client.request(\n 'POST',\n `${sitePath(name)}/${opts.unarchive ? 'unarchive' : 'archive'}`\n )\n return siteAfter(client, name, raw)\n}\n\nexport async function deleteSite(\n client: ApiClient,\n name: string\n): Promise<{ name: string; deleted: true }> {\n await client.request('DELETE', sitePath(name))\n return { name, deleted: true }\n}\n\nexport type ShareResult =\n | { name: string; action: 'existing' | 'created' | 'refreshed'; shareUrl: string }\n | { name: string; action: 'revoked'; shareUrl: null }\n\n/**\n * Share link management. Without flags: return the current link, or create one. `refresh` rotates\n * (the old link stops working); `revoke` removes it.\n */\nexport async function share(\n client: ApiClient,\n name: string,\n opts: { refresh?: boolean; revoke?: boolean } = {}\n): Promise<ShareResult> {\n if (opts.revoke) {\n await client.request('DELETE', `${sitePath(name)}/share`)\n return { name, action: 'revoked', shareUrl: null }\n }\n let hadLink = false\n if (!opts.refresh) {\n const site = await getSite(client, name)\n if (site.shareUrl) return { name, action: 'existing', shareUrl: site.shareUrl }\n } else hadLink = true\n const res = await client.request('POST', `${sitePath(name)}/share`, {\n schema: ShareResponseSchema,\n })\n return { name, action: hadLink ? 'refreshed' : 'created', shareUrl: res.shareUrl }\n}\n\n// --- comments ---\n\n/** GET \u2026/comments \u2014 the site's comments (oldest first), optionally one page's. */\nexport function listComments(\n client: ApiClient,\n name: string,\n opts: { path?: string } = {}\n): Promise<CommentList> {\n return client.request('GET', `${sitePath(name)}/comments`, {\n schema: CommentListSchema,\n query: { path: opts.path },\n })\n}\n\n/** Start a thread on a page, or reply to one. */\nexport function addComment(\n client: ApiClient,\n name: string,\n input: { body: string; path?: string; parentId?: string }\n): Promise<Comment> {\n return client.request('POST', `${sitePath(name)}/comments`, {\n schema: CommentSchema,\n body: input,\n })\n}\n\n/** Resolve a thread, or reopen it. */\nexport function resolveComment(\n client: ApiClient,\n name: string,\n id: string,\n resolved: boolean\n): Promise<Comment> {\n return client.request('PATCH', `${sitePath(name)}/comments/${encodeURIComponent(id)}`, {\n schema: CommentSchema,\n body: { resolved },\n })\n}\n\nexport async function deleteComment(\n client: ApiClient,\n name: string,\n id: string\n): Promise<{ name: string; id: string; deleted: true }> {\n await client.request('DELETE', `${sitePath(name)}/comments/${encodeURIComponent(id)}`)\n return { name, id, deleted: true }\n}\n\n/**\n * Whether the instance has comments, by its stored metadata: its `comments` capability, or \u2014 when\n * the stored copy predates the flag (fetched by an older login) \u2014 yes, and the server decides.\n * No instance at all: no.\n */\nexport function commentsEnabled(\n instance: Pick<InstanceMetadata, 'capabilities'> | null | undefined\n): boolean {\n if (!instance) return false\n return instance.capabilities.comments ?? true\n}\n", "/** Comments on a site: comments (list), comment (add or reply), resolve (or reopen), uncomment. */\nimport { authorLabel, type Comment, commentThreads, reviewUrl } from '@fling/shared'\nimport chalk from 'chalk'\nimport { type CommandContext, requireClient } from '../context.ts'\nimport { CliError } from '../errors.ts'\nimport {\n addComment,\n commentsEnabled,\n deleteComment,\n listComments,\n resolveComment,\n} from '../sites.ts'\nimport { formatDate } from '../utils/output.ts'\n\n/** The client, unless the stored instance says it has comments turned off. */\nfunction commentsClient(ctx: CommandContext) {\n const instance = ctx.config.instance\n if (instance && !commentsEnabled(instance)) {\n throw new CliError(`${instance.name} has comments turned off`)\n }\n return requireClient(ctx)\n}\n\nconst reviewPage = (ctx: CommandContext, name: string, path?: string) =>\n reviewUrl(ctx.config.instance?.appOrigin ?? ctx.config.serverUrl ?? '', name, path)\n\nfunction describe(c: Comment, currentVersionId: string | null): string {\n const version =\n c.versionId === null\n ? ''\n : c.versionId === currentVersionId\n ? ''\n : chalk.dim(` (on version ${c.versionId})`)\n return `${chalk.bold(authorLabel(c.author))} ${chalk.dim(formatDate(c.createdAt))}${version}`\n}\n\nexport async function runComments(\n ctx: CommandContext,\n name: string,\n opts: { path?: string; all?: boolean }\n): Promise<void> {\n const list = await listComments(commentsClient(ctx), name, { path: opts.path })\n const all = commentThreads(list.comments)\n const threads = opts.all ? all : all.filter(t => t.comment.resolvedAt === null)\n const hidden = all.length - threads.length\n ctx.out.data({ ...list, reviewUrl: reviewPage(ctx, name) }, () => {\n const lines: string[] = []\n let lastPath: string | null = null\n for (const { comment: c, replies } of threads.sort((a, b) =>\n a.comment.path.localeCompare(b.comment.path)\n )) {\n if (c.path !== lastPath) {\n lines.push('', chalk.bold.underline(c.path))\n lastPath = c.path\n }\n const state = c.resolvedAt ? chalk.green(' \u2713 resolved') : ''\n lines.push(`${chalk.dim(c.id)}${state} ${describe(c, list.site.currentVersionId)}`)\n if (c.anchor?.quote) lines.push(chalk.dim(` > ${c.anchor.quote}`))\n lines.push(...c.body.split('\\n').map(l => ` ${l}`))\n for (const r of replies) {\n lines.push(` ${chalk.dim('\u21B3')} ${describe(r, list.site.currentVersionId)}`)\n lines.push(...r.body.split('\\n').map(l => ` ${l}`))\n }\n }\n const summary = chalk.dim(\n `${threads.length} ${opts.all ? '' : 'open '}thread${threads.length === 1 ? '' : 's'}` +\n (hidden ? ` (${hidden} resolved \u2014 \\`--all\\` shows them)` : '') +\n ` \u00B7 review: ${reviewPage(ctx, name)}`\n )\n return [...lines, '', summary].join('\\n').replace(/^\\n/, '')\n })\n}\n\nexport async function runComment(\n ctx: CommandContext,\n name: string,\n text: string,\n opts: { path?: string; reply?: string }\n): Promise<void> {\n if (!text.trim()) throw new CliError('The comment is empty')\n const comment = await addComment(commentsClient(ctx), name, {\n body: text,\n path: opts.path,\n parentId: opts.reply,\n })\n ctx.log.success(\n comment.parentId\n ? `Replied to ${comment.parentId} on ${name}`\n : `Comment added on ${name} ${comment.path}`\n )\n ctx.out.data(comment, () => reviewPage(ctx, name, comment.path))\n}\n\nexport async function runResolve(\n ctx: CommandContext,\n name: string,\n id: string,\n opts: { reopen?: boolean }\n): Promise<void> {\n const comment = await resolveComment(commentsClient(ctx), name, id, !opts.reopen)\n ctx.log.success(opts.reopen ? `Thread ${id} reopened` : `Thread ${id} resolved`)\n if (ctx.json) ctx.out.data(comment, () => '')\n}\n\nexport async function runUncomment(\n ctx: CommandContext,\n name: string,\n id: string,\n opts: { yes?: boolean }\n): Promise<void> {\n if (!opts.yes) {\n if (!ctx.interactive) {\n throw new CliError(`Refusing to delete comment ${id} without confirmation`, {\n hint: 'Pass --yes to delete.',\n })\n }\n const ok = await ctx.confirm(`Delete comment ${id} (and its replies)? This cannot be undone.`)\n if (!ok) throw new CliError('Cancelled')\n }\n const result = await deleteComment(commentsClient(ctx), name, id)\n ctx.log.success(`Comment ${id} deleted`)\n if (ctx.json) ctx.out.data(result, () => '')\n}\n", "/**\n * `fling [path] [--name x] [--spa] [--public] [--yes] [--[no-]list-html]` \u2014 the default command.\n *\n * `path` is a folder, a single .html file, a .zip or any other file (inputs.ts). It must exist as\n * given: the CLI never goes looking for it elsewhere (the MCP server does, see locate.ts).\n *\n * On a terminal (and without `--yes`) it asks before flinging: it confirms the generated site name\n * (checked against GET /api/names/:name; a taken name defaults to the first free suggestion) and,\n * when there is no root index.html, whether to list the HTML pages on a generated index page,\n * fling anyway or abort. Without a terminal (CI, agents) or with `--yes` it never asks: with no\n * index.html it generates the listing when there are HTML pages (else warns), and a taken name\n * fails with suggestions (it never silently picks another name). `--list-html` / `--no-list-html`\n * decide the listing up front.\n *\n * Dotfiles, gitignored files, secret files and files containing secrets are never flung (see\n * manifest.ts); there is no flag to include them. Skipped files are listed (`skipped` in --json).\n */\n\nimport { stat } from 'node:fs/promises'\nimport { resolve } from 'node:path'\nimport {\n type InstanceMetadata,\n isValidSiteName,\n privateAudience,\n reviewUrl,\n SITE_NAME_MAX,\n} from '@fling/shared'\nimport chalk from 'chalk'\nimport type { ApiClient } from '../api.ts'\nimport { type CommandContext, requireClient } from '../context.ts'\nimport { deploy, resolveSiteName } from '../deploy.ts'\nimport { CliError } from '../errors.ts'\nimport { type PreparedInput, prepareInput } from '../inputs.ts'\nimport { loadInstance } from '../instance.ts'\nimport {\n buildManifest,\n describeSkipped,\n hasRootIndex,\n htmlPages,\n NO_INDEX_WARNING,\n withHtmlListing,\n} from '../manifest.ts'\nimport { waitWithSpinner } from '../ready.ts'\nimport { checkName, commentsEnabled, type SitesBase, sitesBaseOf, siteUrlFor } from '../sites.ts'\nimport { box, brand } from '../ui/theme.ts'\nimport { formatBytes } from '../utils/output.ts'\n\nexport interface DeployCommandOptions {\n name?: string\n spa?: boolean\n public?: boolean\n /** never prompt */\n yes?: boolean\n /** No root index.html: true \u2192 generate a listing of the HTML pages; false \u2192 fling anyway. */\n listHtml?: boolean\n}\n\nexport type NoIndexChoice = 'list' | 'fling'\n\nexport async function runDeploy(\n ctx: CommandContext,\n input: string | undefined,\n opts: DeployCommandOptions\n): Promise<void> {\n const client = requireClient(ctx)\n const ask = ctx.interactive && !opts.yes\n // Where the site will be served and who can see it: from the instance stored at login.\n const instance = await loadInstance(ctx.store, ctx.config, ctx.fetch)\n const base = sitesBaseOf(instance)\n\n const path = resolve(input ?? '.')\n if (!(await stat(path).catch(() => null)))\n throw new CliError(`No such file or folder: ${input ?? '.'}`, {\n hint: `Give the path to a folder, .html, .zip or other file, e.g. \\`${ctx.binName} deploy ./dist\\`.`,\n })\n const prepared = await prepareInput(path)\n try {\n await deployPrepared(ctx, client, instance, base, prepared, opts, ask)\n } finally {\n await prepared.cleanup()\n }\n}\n\nasync function deployPrepared(\n ctx: CommandContext,\n client: ApiClient,\n instance: InstanceMetadata | null,\n base: SitesBase | null,\n prepared: PreparedInput,\n opts: DeployCommandOptions,\n ask: boolean\n): Promise<void> {\n let local = await buildManifest(prepared.dir)\n local.skipped.dotfiles.unshift(...prepared.skippedDotfiles)\n // Never flung, whatever the flags: say so, so nobody wonders where .env went.\n for (const line of describeSkipped(local.skipped)) ctx.log.info(line)\n let name =\n opts.name !== undefined ? resolveSiteName(prepared.dir, opts.name) : prepared.defaultName\n if (opts.name === undefined && ask) name = await confirmSiteName(ctx, client, name, base)\n\n if (!hasRootIndex(local)) {\n const pages = htmlPages(local).length\n const root = base ? siteUrlFor(name, base) : 'the site root'\n const warning = `No index.html at the root \u2014 ${root} will show a 404.`\n const choice: NoIndexChoice =\n opts.listHtml === true\n ? 'list'\n : opts.listHtml === false\n ? 'fling'\n : ask\n ? await askNoIndex(ctx, pages)\n : pages > 0\n ? 'list'\n : 'fling'\n if (choice === 'list') {\n local = await withHtmlListing(local, name)\n ctx.log.info(`Generated index.html listing ${pages} HTML page${pages === 1 ? '' : 's'}`)\n } else ctx.log.warn(warning)\n }\n\n let progressShown = false\n const result = await deploy(\n { client, fetch: ctx.fetch },\n {\n dir: prepared.dir,\n name,\n manifest: local,\n spa: opts.spa ? true : undefined,\n public: opts.public,\n onProgress: p => {\n if (p.total === 0) return\n progressShown = true\n ctx.progress(\n `${progressBar(p.totalBytes ? p.bytes / p.totalBytes : p.uploaded / p.total)} uploading ${p.uploaded}/${p.total} files \u00B7 ${formatBytes(p.bytes)}/${formatBytes(p.totalBytes)}`\n )\n },\n }\n ).finally(() => {\n if (progressShown) ctx.progress(null)\n })\n\n for (const warning of result.warnings) if (warning !== NO_INDEX_WARNING) ctx.log.warn(warning)\n const summary = `${result.fileCount} files, ${formatBytes(result.totalBytes)}`\n if (result.status === 'unchanged') ctx.log.info(`Unchanged ${chalk.dim(`(${summary})`)}`)\n else if (result.status === 'repointed')\n ctx.log.success(`Restored version ${result.versionId} ${chalk.dim(`(${summary})`)}`)\n else\n ctx.log.success(\n `Deployed ${result.name} ${chalk.dim(`(${summary}; uploaded ${result.uploaded}, version ${result.versionId})`)}`\n )\n\n // A new or re-pointed version takes a few seconds to reach every edge: don't hand out a URL\n // that 404s. (`unchanged` was already live.)\n const ready =\n result.status === 'unchanged'\n ? true\n : (\n await waitWithSpinner(\n ctx.waitReady,\n result.url,\n local.files.map(f => f.path),\n { progress: ctx.progress, warn: m => ctx.log.warn(m) }\n )\n ).ready\n\n const who = instance ? `${privateAudience(instance)} can open it` : 'sign-in required'\n const privateNote = `Private: ${who}. Share publicly with \\`${ctx.binName} share ${result.name}\\`.`\n // With comments on, the review page is the link to share for feedback; the site URL follows.\n const review =\n instance && commentsEnabled(instance) ? reviewUrl(instance.appOrigin, result.name) : undefined\n const reviewNote = instance\n ? `Share for feedback (reviewers sign in to ${instance.name}):`\n : 'Share for feedback:'\n const data = {\n status: result.status,\n site: result.site,\n ...(review ? { reviewUrl: review } : {}),\n ready,\n skipped: local.skipped,\n }\n ctx.out.data(data, () => {\n const isPrivate = result.site.visibility === 'private'\n // On a terminal the URLs get a box; piped, the site URL stays the first line on its own so\n // `fling deploy \u2026 | pbcopy` works.\n if (ctx.out.tty)\n return box(\n [\n ...(review ? [chalk.dim(reviewNote), brand.url(review), '', chalk.dim('Site:')] : []),\n brand.url(result.url),\n ...(isPrivate ? [chalk.dim(privateNote)] : []),\n ],\n isPrivate ? chalk.bold('flung \u00B7 private') : chalk.bold('flung \u00B7 public')\n )\n const lines = [chalk.bold(result.url)]\n if (review) lines.push(chalk.dim(`${reviewNote} ${review}`))\n if (isPrivate) lines.push(chalk.dim(privateNote))\n return lines.join('\\n')\n })\n}\n\nconst BAR_WIDTH = 20\n\n/** `\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2500\u2500\u2500\u2500\u2500\u2500` for a fraction 0\u20261. */\nfunction progressBar(fraction: number): string {\n const done = Math.round(Math.min(Math.max(fraction, 0), 1) * BAR_WIDTH)\n return brand.primary('\u2501'.repeat(done)) + chalk.dim('\u2500'.repeat(BAR_WIDTH - done))\n}\n\n/**\n * No root index.html, on a terminal: list the HTML pages on a generated index (the default when\n * there are any), fling anyway, or abort (the default when there are none).\n */\nexport async function askNoIndex(ctx: CommandContext, pages: number): Promise<NoIndexChoice> {\n const question =\n pages > 0\n ? 'No index.html at the root. [L]ist the HTML pages on a generated index page / [f]ling anyway (the root will 404) / [a]bort '\n : 'No index.html at the root (and no HTML pages to list). [f]ling anyway (the root will 404) / [A]bort '\n for (;;) {\n const answer = (await ctx.prompt(question)).trim().toLowerCase()\n if (pages > 0 && (answer === '' || answer === 'l' || answer === 'list')) return 'list'\n if (answer === 'f' || answer === 'fling') return 'fling'\n if (answer === 'a' || answer === 'abort' || answer === 'n' || answer === 'no' || answer === '')\n throw new CliError('Not flung: no index.html at the root', {\n hint: 'Fling the folder that contains index.html (your build output, e.g. ./dist), or pass --list-html / --no-list-html.',\n })\n }\n}\n\n/**\n * Show the generated name (and whether it is new, yours or taken) and let the user accept it,\n * type another, or abort. Loops until a usable name is accepted.\n */\nexport async function confirmSiteName(\n ctx: CommandContext,\n client: ApiClient,\n generated: string,\n base: SitesBase | null\n): Promise<string> {\n const where = (n: string) => (base ? ` \u2192 ${siteUrlFor(n, base)}` : '')\n const describe = (n: string, note: string) =>\n ctx.log.info(`Site name: ${chalk.bold(n)}${where(n)} ${chalk.dim(`(${note})`)}`)\n\n let candidate = generated\n for (;;) {\n const check = await checkName(client, candidate)\n let proposal: string | undefined\n if (check.status === 'available' || check.status === 'yours') {\n proposal = candidate\n describe(candidate, check.status === 'yours' ? 'updates your existing site' : 'new')\n } else {\n const why = check.status === 'taken' ? 'is taken' : 'is not a valid site name'\n const alternatives = check.suggestions.length\n ? ` Suggestions: ${check.suggestions.join(', ')}`\n : ''\n ctx.log.warn(`${candidate} ${why}.${alternatives}`)\n proposal = check.suggestions[0]\n if (proposal) describe(proposal, 'new')\n }\n\n for (;;) {\n const question = proposal\n ? `Use \"${proposal}\"? [Y/n or type another name] `\n : 'Type a site name (or n to abort): '\n const answer = (await ctx.prompt(question)).trim()\n if (proposal && (answer === '' || /^y(es)?$/i.test(answer))) return proposal\n if (/^no?$/i.test(answer))\n throw new CliError('Aborted \u2014 nothing was flung', {\n hint: 'Pass --name <name> to choose the site name up front.',\n })\n if (answer === '') continue\n if (!isValidSiteName(answer)) {\n ctx.log.warn(\n `\"${answer}\" is not a valid site name: use lowercase letters, digits and single hyphens (max ${SITE_NAME_MAX}); some names are reserved.`\n )\n continue\n }\n candidate = answer\n break\n }\n }\n}\n", "/**\n * Deploy a folder: build the manifest, ask the API what to do, upload only what it asks for\n * straight to S3 (presigned PUTs, 8 at a time, 3 retries with backoff), then finalize.\n */\nimport { readFile } from 'node:fs/promises'\nimport {\n DeployResponseSchema,\n FinalizeResponseSchema,\n isValidSiteName,\n SITE_NAME_MAX,\n type Site,\n slugify,\n} from '@fling/shared'\nimport { type ApiClient, CliApiError, type FetchLike, putUpload, UploadError } from './api.ts'\nimport { CliError } from './errors.ts'\nimport {\n buildManifest,\n type LocalFile,\n type LocalManifest,\n mapLimit,\n toManifest,\n} from './manifest.ts'\nimport { defaultSiteName } from './naming.ts'\nimport { checkName } from './sites.ts'\n\nexport { defaultSiteName }\n\n/** The name belongs to someone else (409 `name_taken`, or a name check said `taken`). */\nexport class NameTakenError extends CliError {\n readonly code = 'name_taken'\n constructor(\n readonly siteName: string,\n readonly suggestions: string[],\n hint?: string\n ) {\n super(\n `The site name \"${siteName}\" is taken by someone else` +\n (suggestions.length ? `. Free alternatives: ${suggestions.join(', ')}` : ''),\n {\n hint:\n hint ??\n `Pass --name <name> to choose another${suggestions[0] ? `, e.g. --name ${suggestions[0]}` : ''}.`,\n }\n )\n this.name = 'NameTakenError'\n }\n}\n\n/** Suggestions from a 409 body (`error.suggestions`), else asked of GET /api/names/:name. */\nasync function nameTakenError(client: ApiClient, name: string, body: unknown) {\n const raw = (body as { error?: { suggestions?: unknown } } | undefined)?.error?.suggestions\n let suggestions = Array.isArray(raw) ? raw.filter((s): s is string => typeof s === 'string') : []\n if (suggestions.length === 0) {\n suggestions = await checkName(client, name)\n .then(c => c.suggestions)\n .catch(() => [])\n }\n return new NameTakenError(name, suggestions)\n}\n\nexport const UPLOAD_CONCURRENCY = 8\nexport const UPLOAD_RETRIES = 3\n\nexport function resolveSiteName(dir: string, name?: string): string {\n if (name !== undefined) {\n if (!isValidSiteName(name)) {\n throw new CliError(`Invalid site name \"${name}\"`, {\n hint: `Use lowercase letters, digits and single hyphens, up to ${SITE_NAME_MAX} characters (e.g. \"${slugify(name) || 'my-site'}\").`,\n })\n }\n return name\n }\n const derived = defaultSiteName(dir)\n if (!isValidSiteName(derived)) {\n throw new CliError(`Could not derive a site name from \"${dir}\"`, {\n hint: 'Pass --name <name>.',\n })\n }\n return derived\n}\n\nexport interface DeployOptions {\n dir: string\n name?: string\n spa?: boolean\n public?: boolean\n /** A manifest already built from `dir` (so the caller can inspect it before deploying). */\n manifest?: LocalManifest\n onProgress?: (event: {\n uploaded: number\n total: number\n bytes: number\n totalBytes: number\n }) => void\n}\n\nexport interface DeployDeps {\n client: ApiClient\n /** For the presigned PUTs (no auth header). */\n fetch: FetchLike\n sleep?: (ms: number) => Promise<void>\n}\n\nexport interface DeployResult {\n status: 'unchanged' | 'repointed' | 'live'\n name: string\n url: string\n versionId: string\n site: Site\n fileCount: number\n totalBytes: number\n /** files actually uploaded (0 unless status is `live`) */\n uploaded: number\n warnings: string[]\n}\n\nconst defaultSleep = (ms: number) => new Promise<void>(r => setTimeout(r, ms))\n\nexport async function deploy(deps: DeployDeps, opts: DeployOptions): Promise<DeployResult> {\n const name = resolveSiteName(opts.dir, opts.name)\n const local = opts.manifest ?? (await buildManifest(opts.dir))\n const base = {\n name,\n fileCount: local.files.length,\n totalBytes: local.totalBytes,\n warnings: local.warnings,\n }\n const path = `/api/sites/${encodeURIComponent(name)}/deploys`\n const res = await deps.client\n .request('POST', path, {\n schema: DeployResponseSchema,\n body: {\n manifest: toManifest(local),\n ...(opts.spa !== undefined ? { spa: opts.spa } : {}),\n ...(opts.public ? { visibility: 'public' as const } : {}),\n },\n })\n .catch(async (error: unknown) => {\n if (error instanceof CliApiError && error.status === 409 && error.code === 'name_taken')\n throw await nameTakenError(deps.client, name, error.body)\n throw error\n })\n if (res.status !== 'upload') {\n return {\n ...base,\n status: res.status,\n url: res.site.url,\n versionId: res.versionId,\n site: res.site,\n uploaded: 0,\n }\n }\n\n const byPath = new Map(local.files.map(f => [f.path, f]))\n const uploads = res.uploads.map(u => {\n const file = byPath.get(u.path)\n if (!file) throw new CliError(`Server asked for a file that is not in the manifest: ${u.path}`)\n return { ...u, file }\n })\n const totalBytes = uploads.reduce((n, u) => n + u.file.size, 0)\n let done = 0\n let bytes = 0\n opts.onProgress?.({ uploaded: 0, total: uploads.length, bytes: 0, totalBytes })\n await mapLimit(uploads, UPLOAD_CONCURRENCY, async u => {\n await uploadWithRetry(deps, u.file, u.url, u.headers)\n done++\n bytes += u.file.size\n opts.onProgress?.({ uploaded: done, total: uploads.length, bytes, totalBytes })\n })\n\n const fin = await deps.client.request(\n 'POST',\n `${path}/${encodeURIComponent(res.versionId)}/finalize`,\n { schema: FinalizeResponseSchema }\n )\n return {\n ...base,\n status: 'live',\n url: fin.site.url,\n versionId: fin.versionId,\n site: fin.site,\n uploaded: uploads.length,\n }\n}\n\nasync function uploadWithRetry(\n deps: DeployDeps,\n file: LocalFile,\n url: string,\n headers: Record<string, string>\n): Promise<void> {\n const sleep = deps.sleep ?? defaultSleep\n const body = file.content ?? (await readFile(file.absPath))\n for (let attempt = 0; ; attempt++) {\n try {\n await putUpload(deps.fetch, url, headers, body)\n return\n } catch (error) {\n const retryable = error instanceof UploadError && error.retryable\n if (!retryable || attempt >= UPLOAD_RETRIES) {\n throw new CliError(`Upload of ${file.path} failed: ${(error as Error).message}`, {\n hint: retryable ? 'Check your connection and run the deploy again.' : undefined,\n })\n }\n await sleep(500 * 2 ** attempt)\n }\n }\n}\n", "/**\n * Build a deploy manifest from a folder: walk it, hash every file (sha256, streamed), guess content\n * types, and enforce the shared limits before anything is sent to the server.\n *\n * Never flung (no flag or option changes this): dotfiles and dot-directories, gitignored files\n * (see gitignore.ts), and `node_modules`; anything matched by a root `.flingignore` (gitignore\n * syntax) is skipped too. Skipped dotfiles and gitignored files are reported in `skipped`.\n *\n * Refused outright (a CliError, nothing is uploaded): secret files by name (`server.key`,\n * `id_rsa`, `credentials.json`\u2026 \u2014 isSecretPath) and files whose contents contain secrets\n * (scanForSecrets: private keys, cloud / API tokens\u2026). The API checks the same again \u2014 this is the\n * early, friendly half; the server is the guarantee.\n *\n * Symlinks are followed only when their real target is inside the folder; a link pointing outside\n * is skipped with a warning (and directory cycles are never re-entered).\n */\nimport { createHash } from 'node:crypto'\nimport { createReadStream } from 'node:fs'\nimport { readdir, readFile, realpath, stat } from 'node:fs/promises'\nimport { join, relative, sep } from 'node:path'\nimport {\n describeSecretFindings,\n extractHtmlTitle,\n isHtmlPath,\n isScannablePath,\n isSecretPath,\n isValidSitePath,\n MAX_DEPLOY_BYTES,\n MAX_FILE_BYTES,\n MAX_FILES,\n MAX_PATH_LENGTH,\n type Manifest,\n NEVER_PUBLISHED_NOTE,\n renderHtmlListing,\n SECRET_SCAN_MAX_FILE_BYTES,\n type SecretFinding,\n scanBytesForSecrets,\n} from '@fling/shared'\nimport ignore, { type Ignore } from 'ignore'\nimport mime from 'mime'\nimport { CliError } from './errors.ts'\nimport { loadGitIgnore } from './gitignore.ts'\nimport { formatBytes } from './utils/output.ts'\n\nexport const IGNORE_FILE = '.flingignore'\nexport const NO_INDEX_WARNING = 'No index.html at the top of the folder \u2014 the site root will 404.'\nconst ALWAYS_SKIP = new Set(['node_modules'])\n/** Dot entries skipped without being reported (nobody expects them on a site). */\nconst QUIET_DOT_ENTRIES = new Set(['.git', '.DS_Store'])\n/** How many skipped names to show in messages. */\nexport const SKIPPED_SHOWN = 5\nconst CHARSET_TYPES = new Set([\n 'application/javascript',\n 'application/json',\n 'application/manifest+json',\n 'application/xml',\n 'image/svg+xml',\n])\n\nexport interface LocalFile {\n /** site-relative POSIX path */\n path: string\n /** absolute path on disk ('' for generated files, which carry `content`) */\n absPath: string\n /** Generated in memory (e.g. the HTML listing): uploaded from here, never written to disk. */\n content?: Buffer\n sha256: string\n size: number\n contentType: string\n}\n\nexport interface Skipped {\n /** dotfiles and dot-directories (directories end with `/`) */\n dotfiles: string[]\n /** gitignored files and directories (directories end with `/`) */\n gitignored: string[]\n}\n\nexport interface LocalManifest {\n root: string\n files: LocalFile[]\n totalBytes: number\n warnings: string[]\n skipped: Skipped\n}\n\n/** Secret files (by name) in the folder: never flung. */\nexport class SecretFilesError extends CliError {\n readonly code = 'secret_file'\n constructor(readonly paths: string[]) {\n const shown = paths.slice(0, 20)\n super(\n `Not flung: ${paths.length === 1 ? 'this is a secret file' : `these are ${paths.length} secret files`} (keys, certificates, credentials): ` +\n `${shown.join(', ')}${paths.length > shown.length ? ` (+${paths.length - shown.length} more)` : ''}. ${NEVER_PUBLISHED_NOTE}`,\n {\n hint: `Move ${paths.length === 1 ? 'it' : 'them'} out of the folder, or add ${paths.length === 1 ? 'it' : 'them'} to ${IGNORE_FILE} if the site does not need ${paths.length === 1 ? 'it' : 'them'}.`,\n }\n )\n this.name = 'SecretFilesError'\n }\n}\n\n/** Files that contain secrets: never flung. The message names file, line and kind \u2014 never the value. */\nexport class SecretsFoundError extends CliError {\n readonly code = 'secret_detected'\n constructor(readonly findings: SecretFinding[]) {\n const files = new Set(findings.map(f => f.path)).size\n super(\n `Not flung: found secrets in ${files} file${files === 1 ? '' : 's'}:\\n ${describeSecretFindings(findings).join('\\n ')}\\n${NEVER_PUBLISHED_NOTE}`,\n {\n hint: `Remove the secret (and rotate it if it was ever shared), or add the file to ${IGNORE_FILE} if the site does not need it.`,\n }\n )\n this.name = 'SecretsFoundError'\n }\n}\n\n/** \"Skipped 3 dotfiles (.env, .npmrc, .vscode/)\" lines for what the walker left out; [] if none. */\nexport function describeSkipped(skipped: Skipped): string[] {\n const line = (n: number, what: string, names: string[]) =>\n `Skipped ${n} ${what}${n === 1 ? '' : 's'} (${names.slice(0, SKIPPED_SHOWN).join(', ')}${n > SKIPPED_SHOWN ? ', \u2026' : ''}) \u2014 ${what}s are never flung`\n const lines: string[] = []\n if (skipped.dotfiles.length)\n lines.push(line(skipped.dotfiles.length, 'dotfile', skipped.dotfiles))\n if (skipped.gitignored.length)\n lines.push(line(skipped.gitignored.length, 'gitignored file', skipped.gitignored))\n return lines\n}\n\nexport function contentTypeFor(path: string): string {\n const type = mime.getType(path) ?? 'application/octet-stream'\n return type.startsWith('text/') || CHARSET_TYPES.has(type) ? `${type}; charset=utf-8` : type\n}\n\nexport async function sha256File(path: string): Promise<string> {\n const hash = createHash('sha256')\n for await (const chunk of createReadStream(path)) hash.update(chunk as Buffer)\n return hash.digest('hex')\n}\n\n/** The manifest body the API expects (no local paths). */\nexport function toManifest(local: LocalManifest): Manifest {\n return {\n files: local.files.map(({ path, sha256, size, contentType }) => ({\n path,\n sha256,\n size,\n contentType,\n })),\n }\n}\n\nexport async function buildManifest(dir: string): Promise<LocalManifest> {\n let root: string\n try {\n root = await realpath(dir)\n } catch {\n throw new CliError(`Folder not found: ${dir}`)\n }\n if (!(await stat(root)).isDirectory()) throw new CliError(`Not a folder: ${dir}`)\n\n const ig = await loadIgnore(root)\n const gitIgnore = await loadGitIgnore(root)\n const warnings: string[] = []\n const skipped: Skipped = { dotfiles: [], gitignored: [] }\n const secretFiles: string[] = []\n const found: { path: string; absPath: string; size: number }[] = []\n const visitedDirs = new Set<string>([root])\n\n const inside = (real: string) => real === root || real.startsWith(root + sep)\n\n async function walk(realDir: string, relDir: string): Promise<void> {\n await gitIgnore.enterDir(realDir, relDir)\n const entries = await readdir(realDir, { withFileTypes: true })\n entries.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0))\n for (const entry of entries) {\n const rel = relDir ? `${relDir}/${entry.name}` : entry.name\n if (entry.name.startsWith('.')) {\n if (!QUIET_DOT_ENTRIES.has(entry.name))\n skipped.dotfiles.push(entry.isDirectory() ? `${rel}/` : rel)\n continue\n }\n if (ALWAYS_SKIP.has(entry.name)) continue\n let abs = join(realDir, entry.name)\n let isDir = entry.isDirectory()\n let isFile = entry.isFile()\n if (entry.isSymbolicLink()) {\n let target: string\n try {\n target = await realpath(abs)\n } catch {\n warnings.push(`Skipped broken symlink: ${rel}`)\n continue\n }\n if (!inside(target)) {\n warnings.push(`Skipped symlink pointing outside the folder: ${rel}`)\n continue\n }\n const info = await stat(target)\n // A link must not smuggle in what is never flung under another name.\n const targetRel = relative(root, target).split(sep).join('/')\n if (targetRel.split('/').some(seg => seg.startsWith('.'))) {\n skipped.dotfiles.push(rel)\n continue\n }\n if (targetRel && gitIgnore.ignores(targetRel, info.isDirectory())) {\n skipped.gitignored.push(rel)\n continue\n }\n abs = target\n isDir = info.isDirectory()\n isFile = info.isFile()\n }\n if (isDir) {\n if (gitIgnore.ignores(rel, true)) {\n skipped.gitignored.push(`${rel}/`)\n continue\n }\n if (ig.ignores(`${rel}/`)) continue\n if (visitedDirs.has(abs)) continue\n visitedDirs.add(abs)\n await walk(abs, rel)\n } else if (isFile) {\n if (gitIgnore.ignores(rel, false)) {\n skipped.gitignored.push(rel)\n continue\n }\n if (ig.ignores(rel)) continue\n if (isSecretPath(rel)) {\n secretFiles.push(rel)\n continue\n }\n const { size } = await stat(abs)\n found.push({ path: rel, absPath: abs, size })\n if (found.length > MAX_FILES) {\n throw new CliError(`Too many files: more than ${MAX_FILES} in ${dir}`, {\n hint: `Add a ${IGNORE_FILE} to skip what the site does not need.`,\n })\n }\n }\n }\n }\n await walk(root, '')\n\n if (secretFiles.length > 0) throw new SecretFilesError(secretFiles)\n if (found.length === 0) {\n throw new CliError(\n `Nothing to deploy: ${dir} has no files (dotfiles, gitignored files and node_modules are skipped)`\n )\n }\n checkLimits(found, dir)\n if (!found.some(f => f.path === 'index.html')) {\n warnings.push(NO_INDEX_WARNING)\n }\n\n const findings: SecretFinding[] = []\n const files = await mapLimit(found, 16, async f => {\n let sha256: string\n if (f.size <= SECRET_SCAN_MAX_FILE_BYTES && isScannablePath(f.path)) {\n // Small enough to read whole: hash and scan for secrets in one read.\n const bytes = await readFile(f.absPath)\n sha256 = createHash('sha256').update(bytes).digest('hex')\n findings.push(...scanBytesForSecrets(bytes, f.path))\n } else sha256 = await sha256File(f.absPath)\n return { ...f, sha256, contentType: contentTypeFor(f.path) }\n })\n if (findings.length > 0) {\n throw new SecretsFoundError(\n findings.sort((a, b) =>\n a.path < b.path ? -1 : a.path > b.path ? 1 : a.line - b.line || a.rule.localeCompare(b.rule)\n )\n )\n }\n return { root, files, totalBytes: files.reduce((n, f) => n + f.size, 0), warnings, skipped }\n}\n\nfunction checkLimits(files: { path: string; size: number }[], dir: string): void {\n for (const f of files) {\n if (f.path.length > MAX_PATH_LENGTH) {\n throw new CliError(\n `Path too long (max ${MAX_PATH_LENGTH} characters): ${f.path.slice(0, 80)}\u2026`\n )\n }\n if (!isValidSitePath(f.path)) throw new CliError(`Unsupported file path: ${f.path}`)\n if (f.size > MAX_FILE_BYTES) {\n throw new CliError(\n `${f.path} is ${formatBytes(f.size)}; the limit is ${formatBytes(MAX_FILE_BYTES)} per file`,\n { hint: `Add it to ${IGNORE_FILE} if the site does not need it.` }\n )\n }\n }\n const total = files.reduce((n, f) => n + f.size, 0)\n if (total > MAX_DEPLOY_BYTES) {\n throw new CliError(\n `${dir} is ${formatBytes(total)}; the limit is ${formatBytes(MAX_DEPLOY_BYTES)} per deploy`,\n { hint: `Add a ${IGNORE_FILE} to skip what the site does not need.` }\n )\n }\n}\n\nexport const hasRootIndex = (local: Pick<LocalManifest, 'files'>) =>\n local.files.some(f => f.path === 'index.html')\n\nexport const htmlPages = (local: Pick<LocalManifest, 'files'>) =>\n local.files.filter(f => isHtmlPath(f.path) && f.path !== 'index.html')\n\nconst TITLE_BYTES = 65536\n\nasync function readHead(file: LocalFile): Promise<string> {\n if (file.content) return file.content.subarray(0, TITLE_BYTES).toString('utf8')\n const chunks: Buffer[] = []\n let size = 0\n for await (const chunk of createReadStream(file.absPath, { end: TITLE_BYTES - 1 })) {\n chunks.push(chunk as Buffer)\n size += (chunk as Buffer).length\n }\n return Buffer.concat(chunks, size).toString('utf8')\n}\n\n/**\n * Add a generated `index.html` listing every HTML page (titles from their `<title>`), built in\n * memory: the user's folder is never written to. Same pages and titles \u2192 same bytes, so a\n * re-deploy stays `unchanged`.\n */\nexport async function withHtmlListing(\n local: LocalManifest,\n siteName: string\n): Promise<LocalManifest> {\n const pages = htmlPages(local)\n const entries = await mapLimit(pages, 16, async f => ({\n path: f.path,\n title: extractHtmlTitle(await readHead(f)),\n }))\n const content = Buffer.from(renderHtmlListing(siteName, entries), 'utf8')\n const index: LocalFile = {\n path: 'index.html',\n absPath: '',\n content,\n sha256: createHash('sha256').update(content).digest('hex'),\n size: content.length,\n contentType: contentTypeFor('index.html'),\n }\n const files = [...local.files.filter(f => f.path !== 'index.html'), index].sort((a, b) =>\n a.path < b.path ? -1 : a.path > b.path ? 1 : 0\n )\n return {\n ...local,\n files,\n totalBytes: files.reduce((n, f) => n + f.size, 0),\n warnings: local.warnings.filter(w => w !== NO_INDEX_WARNING),\n }\n}\n\nasync function loadIgnore(root: string): Promise<Ignore> {\n const ig = ignore()\n try {\n ig.add(await readFile(join(root, IGNORE_FILE), 'utf8'))\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error\n }\n return ig\n}\n\n/** `Promise.all(items.map(fn))` with at most `limit` in flight; keeps order. */\nexport async function mapLimit<T, R>(\n items: readonly T[],\n limit: number,\n fn: (item: T, index: number) => Promise<R>\n): Promise<R[]> {\n const results = new Array<R>(items.length)\n let next = 0\n const worker = async () => {\n while (next < items.length) {\n const i = next++\n results[i] = await fn(items[i] as T, i)\n }\n }\n await Promise.all(Array.from({ length: Math.min(limit, items.length) }, worker))\n return results\n}\n", "/**\n * Which files in a folder are gitignored, so the walker (manifest.ts) never flings them.\n *\n * - The folder is inside a git work tree and is itself tracked (neither it nor an ancestor up to\n * the repo root is ignored): git decides \u2014 every file `git ls-files --others --ignored\n * --exclude-standard --directory` reports is skipped (all .gitignore levels, .git/info/exclude\n * and the global excludes file).\n * - The folder is ignored itself (the usual case for build output such as dist/ or build/): asking\n * git would mark everything as ignored, so instead only the `.gitignore` files *inside* the\n * folder apply.\n * - No git (not installed, not a repo, or git fails): the `.gitignore` files inside the folder\n * apply, as above.\n */\nimport { execFile } from 'node:child_process'\nimport { readFile, realpath } from 'node:fs/promises'\nimport { join, relative, sep } from 'node:path'\nimport ignore, { type Ignore } from 'ignore'\n\nexport type GitIgnoreMode = 'git' | 'nested'\n\nexport interface GitIgnore {\n mode: GitIgnoreMode\n /**\n * Is `rel` (site-relative POSIX path) ignored? Directories are passed with `isDir`. In `nested`\n * mode the walker must call `enterDir` for each directory before asking about its entries.\n */\n ignores(rel: string, isDir: boolean): boolean\n /** Load `<dir>/.gitignore` (nested mode; no-op otherwise). */\n enterDir(absDir: string, relDir: string): Promise<void>\n}\n\nconst GIT_TIMEOUT_MS = 20_000\n\nfunction git(cwd: string, args: string[], input?: string): Promise<string | null> {\n return new Promise(resolve => {\n try {\n const child = execFile(\n 'git',\n ['-C', cwd, ...args],\n { timeout: GIT_TIMEOUT_MS, maxBuffer: 256 * 1024 * 1024, encoding: 'utf8' },\n (error, stdout) => {\n // check-ignore exits 1 when nothing is ignored: that's an answer, not a failure.\n const code = (error as { code?: unknown } | null)?.code\n if (error && !(args[0] === 'check-ignore' && code === 1)) resolve(null)\n else resolve(stdout)\n }\n )\n child.on('error', () => resolve(null))\n if (input !== undefined) child.stdin?.end(input)\n } catch {\n resolve(null)\n }\n })\n}\n\n/** Is `root` (a realpath) itself ignored by the repo it is in? */\nasync function rootIsIgnored(top: string, root: string): Promise<boolean> {\n const rel = relative(top, root)\n if (!rel || rel.startsWith('..')) return false\n const segments = rel.split(sep)\n // The folder and each ancestor up to (not including) the repo root.\n const candidates = segments.map((_, i) => `${segments.slice(0, i + 1).join('/')}/`)\n const out = await git(top, ['check-ignore', '--stdin', '-z'], `${candidates.join('\\0')}\\0`)\n return out !== null && out.split('\\0').some(Boolean)\n}\n\nfunction gitMode(entries: string[]): GitIgnore {\n const files = new Set<string>()\n const dirs: string[] = []\n for (const e of entries) {\n if (!e) continue\n if (e.endsWith('/')) dirs.push(e)\n else files.add(e)\n }\n const dirSet = new Set(dirs)\n return {\n mode: 'git',\n ignores(rel, isDir) {\n if (isDir ? dirSet.has(`${rel}/`) : files.has(rel)) return true\n let i = rel.indexOf('/')\n while (i !== -1) {\n if (dirSet.has(rel.slice(0, i + 1))) return true\n i = rel.indexOf('/', i + 1)\n }\n return false\n },\n async enterDir() {},\n }\n}\n\nfunction nestedMode(): GitIgnore {\n const levels: { base: string; ig: Ignore }[] = []\n return {\n mode: 'nested',\n ignores(rel, isDir) {\n for (const { base, ig } of levels) {\n if (base && !rel.startsWith(`${base}/`)) continue\n const sub = base ? rel.slice(base.length + 1) : rel\n if (sub && ig.ignores(isDir ? `${sub}/` : sub)) return true\n }\n return false\n },\n async enterDir(absDir, relDir) {\n let text: string\n try {\n text = await readFile(join(absDir, '.gitignore'), 'utf8')\n } catch {\n return\n }\n levels.push({ base: relDir, ig: ignore().add(text) })\n },\n }\n}\n\n/** How to tell gitignored files in `root` (a realpath'd folder). */\nexport async function loadGitIgnore(root: string): Promise<GitIgnore> {\n const topOut = await git(root, ['rev-parse', '--show-toplevel'])\n const topRaw = topOut?.trim()\n if (!topRaw) return nestedMode()\n const top = await realpath(topRaw).catch(() => topRaw)\n if (await rootIsIgnored(top, root)) return nestedMode()\n const listed = await git(root, [\n 'ls-files',\n '--others',\n '--ignored',\n '--exclude-standard',\n '--directory',\n '-z',\n ])\n if (listed === null) return nestedMode()\n return gitMode(listed.split('\\0'))\n}\n", "/**\n * The default site name for a folder. Site names are one global namespace, so the name should say\n * which project the folder belongs to \u2014 `~/work/rocketpod/docs` is `rocketpod-docs`, not `docs` \u2014\n * and never include the user's name.\n *\n * 1. Project root: the nearest ancestor (the folder itself included) containing `.git`; failing\n * that, the nearest containing a package manifest (PROJECT_MARKERS). The search stops below the\n * home directory and the filesystem root, which are never a project root.\n * 2. With a root: the root's folder name, then each path segment from the root down to the folder,\n * skipping BUILD_OUTPUT_DIRS, CONTAINER_DIRS, dot-directories (`.vitepress`, `.next`\u2026) and\n * repeats (a segment equal to the root name or the previous kept segment). A build-suffix\n * (`storybook-static`, `docs-dist`\u2026) is trimmed off a segment (`storybook`).\n * Without a root: just the deepest segment below home that is not a build-output / dot dir\n * (`~/Downloads/report/dist` \u2192 `report`).\n * 3. Slugify each part and join with `-`. Over SITE_NAME_MAX: drop middle parts (keeping the\n * first and last), then truncate; never ends in `-`. A reserved or otherwise invalid result\n * gets `-site` appended (`api` \u2192 `api-site`).\n *\n * Pure apart from the injectable `exists` check (tests pass a fake filesystem).\n */\nimport { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { basename, dirname, isAbsolute, relative, resolve, sep } from 'node:path'\nimport { isValidSiteName, SITE_NAME_MAX, slugify } from '@fling/shared'\n\n/** Files that mark a project root when there is no `.git` above the folder. */\nexport const PROJECT_MARKERS = ['package.json', 'pyproject.toml', 'Cargo.toml', 'go.mod'] as const\n\n/** Build-output folder names: they say nothing about what the site is. */\nexport const BUILD_OUTPUT_DIRS: ReadonlySet<string> = new Set([\n 'dist',\n 'build',\n 'out',\n 'output',\n 'public',\n 'www',\n '_site',\n 'site',\n 'html',\n 'static',\n 'export',\n 'target',\n])\n\n/** Monorepo / source container folders: the interesting name is the one below them. */\nexport const CONTAINER_DIRS: ReadonlySet<string> = new Set([\n 'apps',\n 'packages',\n 'src',\n 'sites',\n 'libs',\n 'projects',\n 'services',\n])\n\n/** Trimmed off the end of a segment: `storybook-static` \u2192 `storybook`, `docs-dist` \u2192 `docs`. */\nconst BUILD_SUFFIX_RE = /[-_.](static|dist|build|out|output)$/i\n\nconst FALLBACK_NAME = 'my-site'\n\nexport interface NamingEnv {\n /** Does this absolute path exist (file or directory)? */\n exists?: (path: string) => boolean\n /** Home directory: the root search stops below it. */\n home?: string\n}\n\n/** Nearest ancestor with `.git`, else with a PROJECT_MARKERS file; null when there is none. */\nexport function findProjectRoot(dir: string, env: NamingEnv = {}): string | null {\n const exists = env.exists ?? existsSync\n const home = resolve(env.home ?? homedir())\n const candidates: string[] = []\n for (let d = resolve(dir); d !== home && dirname(d) !== d; d = dirname(d)) candidates.push(d)\n return (\n candidates.find(d => exists(`${d}${sep}.git`)) ??\n candidates.find(d => PROJECT_MARKERS.some(m => exists(`${d}${sep}${m}`))) ??\n null\n )\n}\n\nconst isGeneric = (segment: string) =>\n segment.startsWith('.') || BUILD_OUTPUT_DIRS.has(segment.toLowerCase())\n\n/** The name parts for a folder, before slugifying and fitting (see the module comment). */\nexport function nameParts(dir: string, env: NamingEnv = {}): string[] {\n const abs = resolve(dir)\n const root = findProjectRoot(abs, env)\n if (!root) {\n // Only segments below home, so the home folder (often the user's name) never leaks in.\n const fromHome = relative(resolve(env.home ?? homedir()), abs)\n if (fromHome === '') return []\n const underHome = fromHome && !fromHome.startsWith('..') && !isAbsolute(fromHome)\n const segments = (underHome ? fromHome : abs).split(sep).filter(Boolean)\n const pick = [...segments].reverse().find(s => !isGeneric(s)) ?? segments.at(-1)\n return pick ? [pick] : []\n }\n const parts = [basename(root)]\n const rel = relative(root, abs)\n for (const raw of rel ? rel.split(sep) : []) {\n if (isGeneric(raw) || CONTAINER_DIRS.has(raw.toLowerCase())) continue\n const segment = raw.replace(BUILD_SUFFIX_RE, '')\n const slug = slugify(segment, 200)\n if (!slug || slug === slugify(parts[0] ?? '', 200)) continue\n if (slug === slugify(parts.at(-1) ?? '', 200)) continue\n parts.push(segment)\n }\n return parts\n}\n\n/** Join slugified parts within SITE_NAME_MAX: drop middle parts first, then truncate. */\nexport function fitName(parts: string[]): string {\n const slugs = parts.map(p => slugify(p, 200)).filter(Boolean)\n while (slugs.length > 2 && slugs.join('-').length > SITE_NAME_MAX) slugs.splice(1, 1)\n let name = slugify(slugs.join('-'))\n if (!name) return FALLBACK_NAME\n if (!isValidSiteName(name)) {\n name = `${name.slice(0, SITE_NAME_MAX - 5).replace(/-+$/, '')}-site`\n }\n return isValidSiteName(name) ? name : FALLBACK_NAME\n}\n\n/** Default site name for a folder, e.g. `~/work/rocketpod/docs` \u2192 `rocketpod-docs`. */\nexport function defaultSiteName(dir: string, env: NamingEnv = {}): string {\n return fitName(nameParts(dir, env))\n}\n", "/**\n * What can be flung, turned into a folder to deploy:\n *\n * - a folder: as is;\n * - a single .html/.htm file: copied to a temp folder as `index.html`;\n * - a .zip: extracted to a temp folder (zip-slip safe, within the shared size limits), skipping\n * `__MACOSX/`, OS junk and dotfiles (reported in `skippedDotfiles`, except `.DS_Store` / `._*`),\n * and unwrapping a single top-level folder;\n * - any other single file (.svg, .pdf, .png, .md\u2026): copied to a temp folder next to a generated\n * minimal `index.html` that shows or links it.\n *\n * A single file whose name starts with `.` (`.env`) or is a secret file (`server.key`) is refused:\n * Fling never publishes those.\n *\n * Default site names: a folder uses the folder naming algorithm (naming.ts); a file uses its own\n * name without the extension or a browser's \" (1)\" duplicate suffix (\"Pitch Deck (1).html\" \u2192\n * `pitch-deck`).\n */\nimport { copyFile, mkdir, mkdtemp, readFile, rm, stat, writeFile } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { basename, extname, join, resolve, sep } from 'node:path'\nimport {\n isSecretPath,\n MAX_DEPLOY_BYTES,\n MAX_FILE_BYTES,\n MAX_FILES,\n NEVER_PUBLISHED_NOTE,\n} from '@fling/shared'\nimport { unzipSync } from 'fflate'\nimport { CliError } from './errors.ts'\nimport { SecretFilesError } from './manifest.ts'\nimport { defaultSiteName, fitName } from './naming.ts'\nimport { formatBytes } from './utils/output.ts'\n\nexport type InputKind = 'folder' | 'html' | 'zip' | 'file'\n\nexport interface PreparedInput {\n kind: InputKind\n /** What the user pointed at. */\n source: string\n /** The folder to deploy (a temp folder unless `kind` is `folder`). */\n dir: string\n defaultName: string\n /** Dotfiles left out of a zip (reported to the user; never flung). */\n skippedDotfiles: string[]\n /** Remove the temp folder (no-op for folders). */\n cleanup(): Promise<void>\n}\n\nexport function inputKind(path: string, isDirectory: boolean): InputKind {\n if (isDirectory) return 'folder'\n const ext = extname(path).toLowerCase()\n if (ext === '.html' || ext === '.htm') return 'html'\n if (ext === '.zip') return 'zip'\n return 'file'\n}\n\n/** Default site name for a single file: its name without extension or \" (1)\", slugified. */\nexport function fileSiteName(path: string): string {\n const file = basename(path.replace(/\\\\/g, '/'))\n const stem = file.slice(0, file.length - extname(file).length) || file\n return fitName([stem.replace(/\\s*\\(\\d+\\)$/, '')])\n}\n\nexport function defaultNameFor(path: string, isDirectory: boolean): string {\n return isDirectory ? defaultSiteName(path) : fileSiteName(path)\n}\n\nasync function tempFolder(): Promise<{ dir: string; cleanup: () => Promise<void> }> {\n const dir = await mkdtemp(join(tmpdir(), 'fling-'))\n return { dir, cleanup: () => rm(dir, { recursive: true, force: true }) }\n}\n\nexport async function prepareInput(path: string): Promise<PreparedInput> {\n let info: Awaited<ReturnType<typeof stat>>\n try {\n info = await stat(path)\n } catch {\n throw new CliError(`Not found: ${path}`)\n }\n const kind = inputKind(path, info.isDirectory())\n const defaultName = defaultNameFor(path, info.isDirectory())\n if (kind === 'folder')\n return {\n kind,\n source: path,\n dir: path,\n defaultName,\n skippedDotfiles: [],\n cleanup: async () => {},\n }\n const file = basename(path)\n if (file.startsWith('.'))\n throw new CliError(`Not flung: ${file} is a dotfile. ${NEVER_PUBLISHED_NOTE}`)\n if (kind === 'file' && isSecretPath(file)) throw new SecretFilesError([file])\n\n if (info.size > MAX_DEPLOY_BYTES)\n throw new CliError(\n `${basename(path)} is ${formatBytes(info.size)}; the limit is ${formatBytes(MAX_DEPLOY_BYTES)}`\n )\n const tmp = await tempFolder()\n const skippedDotfiles: string[] = []\n try {\n if (kind === 'html') {\n if (info.size > MAX_FILE_BYTES)\n throw new CliError(\n `${basename(path)} is ${formatBytes(info.size)}; the limit is ${formatBytes(MAX_FILE_BYTES)} per file`\n )\n await copyFile(path, join(tmp.dir, 'index.html'))\n } else if (kind === 'zip') {\n await extractZip(await readFile(path), tmp.dir, skippedDotfiles)\n } else {\n const name = basename(path)\n await copyFile(path, join(tmp.dir, name))\n await writeFile(join(tmp.dir, 'index.html'), wrapperPage(name))\n }\n } catch (error) {\n await tmp.cleanup()\n throw error\n }\n return { kind, source: path, dir: tmp.dir, defaultName, skippedDotfiles, cleanup: tmp.cleanup }\n}\n\n// ---- zip -----------------------------------------------------------------------------------\n\nconst JUNK_FILES = new Set(['thumbs.db', 'desktop.ini'])\n\n/**\n * The site path for a zip entry name, `null` to skip it (folders, `__MACOSX/`, dotfiles, OS junk),\n * or `'unsafe'` for names that would escape the folder (absolute, drive letters, `..`).\n */\nexport function zipEntryPath(name: string): string | null | 'unsafe' {\n const normalised = name.replace(/\\\\/g, '/')\n if (normalised.includes('\\0')) return 'unsafe'\n if (normalised.startsWith('/') || /^[a-zA-Z]:/.test(normalised)) return 'unsafe'\n const segments = normalised.split('/').filter(s => s !== '' && s !== '.')\n if (segments.includes('..')) return 'unsafe'\n if (normalised.endsWith('/') || segments.length === 0) return null\n if (segments[0] === '__MACOSX') return null\n if (segments.some(s => s.startsWith('.'))) return null\n if (JUNK_FILES.has((segments.at(-1) ?? '').toLowerCase())) return null\n return segments.join('/')\n}\n\n/** Drop a single top-level folder shared by every path (repeatedly: `a/b/index.html` \u2192 `index.html`). */\nexport function unwrapSingleFolder(paths: string[]): string[] {\n let current = paths\n for (;;) {\n const first = current[0]?.split('/')[0]\n if (!first || !current.every(p => p.includes('/') && p.split('/')[0] === first)) return current\n current = current.map(p => p.slice(first.length + 1))\n }\n}\n\n/**\n * A dot entry in a zip worth telling the user about (`.env`, `site/.npmrc`, `.vscode/`), or null.\n * `.git/` and macOS junk (`.DS_Store`, `._*`, anything under `__MACOSX/`) are skipped silently.\n */\nexport function zipDotEntry(name: string): string | null {\n const segments = name\n .replace(/\\\\/g, '/')\n .split('/')\n .filter(s => s !== '' && s !== '.')\n if (segments[0] === '__MACOSX') return null\n const i = segments.findIndex(s => s.startsWith('.'))\n if (i === -1) return null\n const seg = segments[i] as string\n if (seg === '.DS_Store' || seg === '.git' || seg.startsWith('._')) return null\n return i < segments.length - 1 ? `${segments.slice(0, i + 1).join('/')}/` : segments.join('/')\n}\n\n/**\n * Extract a zip into `dest` (see the module comment). Throws on unsafe names or over-limit sizes.\n * Dot entries that were left out are added to `skippedDotfiles` (once per file / dot-directory).\n */\nexport async function extractZip(\n data: Uint8Array,\n dest: string,\n skippedDotfiles: string[] = []\n): Promise<string[]> {\n const unsafe: string[] = []\n let declared = 0\n let count = 0\n let entries: Record<string, Uint8Array>\n try {\n entries = unzipSync(data, {\n filter: file => {\n const path = zipEntryPath(file.name)\n if (path === 'unsafe') {\n unsafe.push(file.name)\n return false\n }\n if (path === null) {\n const dot = zipDotEntry(file.name)\n if (dot && !skippedDotfiles.includes(dot)) skippedDotfiles.push(dot)\n return false\n }\n count++\n declared += file.originalSize\n if (file.originalSize > MAX_FILE_BYTES)\n throw new CliError(\n `${path} in the zip is ${formatBytes(file.originalSize)}; the limit is ${formatBytes(MAX_FILE_BYTES)} per file`\n )\n if (declared > MAX_DEPLOY_BYTES)\n throw new CliError(\n `The zip expands to more than ${formatBytes(MAX_DEPLOY_BYTES)}, the limit per deploy`\n )\n if (count > MAX_FILES) throw new CliError(`The zip has more than ${MAX_FILES} files`)\n return true\n },\n })\n } catch (error) {\n if (error instanceof CliError) throw error\n throw new CliError(`Could not read the zip: ${(error as Error).message}`)\n }\n if (unsafe.length)\n throw new CliError(\n `Refusing to extract the zip: it has paths that escape its folder (${unsafe.slice(0, 3).join(', ')})`\n )\n\n const names = Object.keys(entries)\n const paths = new Map<string, string>()\n const kept = names.map(n => zipEntryPath(n) as string)\n const unwrapped = unwrapSingleFolder(kept)\n names.forEach((n, i) => {\n paths.set(n, unwrapped[i] as string)\n })\n if (names.length === 0) throw new CliError('The zip has no files to fling')\n\n const root = resolve(dest)\n let total = 0\n const written: string[] = []\n for (const name of names) {\n const content = entries[name] as Uint8Array\n total += content.length\n if (content.length > MAX_FILE_BYTES || total > MAX_DEPLOY_BYTES)\n throw new CliError(`The zip expands to more than the limits allow`)\n const rel = paths.get(name) as string\n const target = resolve(root, ...rel.split('/'))\n if (!target.startsWith(root + sep)) throw new CliError(`Unsafe path in the zip: ${name}`)\n await mkdir(join(target, '..'), { recursive: true })\n await writeFile(target, content)\n written.push(rel)\n }\n return written.sort()\n}\n\n// ---- wrapper page for other single files -------------------------------------------------\n\nconst escapeHtml = (s: string) => s.replace(/[&<>\"']/g, c => `&#${c.charCodeAt(0)};`)\n\n/** A minimal index.html that shows (images, PDF, video, audio) or links the file. */\nexport function wrapperPage(file: string): string {\n const href = escapeHtml(encodeURIComponent(file))\n const title = escapeHtml(file)\n const ext = extname(file).toLowerCase()\n let body: string\n if (/^\\.(png|jpe?g|gif|webp|avif|svg|bmp|ico)$/.test(ext))\n body = `<img src=\"${href}\" alt=\"${title}\">`\n else if (ext === '.pdf') body = `<iframe src=\"${href}\" title=\"${title}\"></iframe>`\n else if (/^\\.(mp4|webm|mov|m4v)$/.test(ext)) body = `<video src=\"${href}\" controls></video>`\n else if (/^\\.(mp3|wav|ogg|m4a|flac)$/.test(ext)) body = `<audio src=\"${href}\" controls></audio>`\n else body = ''\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>${title}</title>\n<style>\n body { margin: 0; font: 16px/1.5 system-ui, sans-serif; display: flex; flex-direction: column; min-height: 100vh; }\n header { padding: 12px 20px; border-bottom: 1px solid #ddd; display: flex; gap: 16px; align-items: baseline; }\n main { flex: 1; display: flex; justify-content: center; align-items: center; padding: 20px; }\n img, video { max-width: 100%; max-height: 85vh; }\n iframe { width: 100%; height: 85vh; border: 0; }\n</style>\n</head>\n<body>\n<header><strong>${title}</strong> <a href=\"${href}\" download>Download</a> <a href=\"${href}\">Open</a></header>\n<main>${body}</main>\n</body>\n</html>\n`\n}\n", "/**\n * `fling groups \u2026`: named lists of people that any member can use in a site's audience\n * (`fling access <site> --group <slug>`). Anyone lists and shows them; only a group's owner adds\n * or removes people, renames it or deletes it (the server refuses anyone else).\n */\nimport { describeGroup, describeGroups, splitEmails } from '@fling/shared'\nimport chalk from 'chalk'\nimport { type CommandContext, requireClient } from '../context.ts'\nimport { CliError } from '../errors.ts'\nimport {\n changeGroupMembers,\n createGroup,\n deleteGroup,\n getGroup,\n groupsEnabled,\n listGroups,\n renameGroup,\n whoami,\n} from '../sites.ts'\nimport { renderTable } from '../utils/output.ts'\n\nfunction requireGroups(ctx: CommandContext) {\n const instance = ctx.config.instance\n if (instance && !groupsEnabled(instance)) throw new CliError(`${instance.name} has no groups`)\n return requireClient(ctx)\n}\n\n/** `--members a,b`: only the groups of exactly those people (none: say so, not \"no groups yet\"). */\nexport async function runGroups(\n ctx: CommandContext,\n opts: { mine?: boolean; members?: string[] }\n): Promise<void> {\n const client = requireGroups(ctx)\n const members = opts.members ? splitEmails(opts.members) : undefined\n if (members && members.length === 0) throw new CliError('Name at least one address')\n const [groups, me] = await Promise.all([\n listGroups(client, { mine: opts.mine, members }),\n whoami(client),\n ])\n ctx.out.data({ groups }, () =>\n groups.length\n ? renderTable(groups, [\n { header: 'SLUG', value: g => g.slug },\n { header: 'NAME', value: g => g.name },\n { header: 'PEOPLE', value: g => g.size },\n { header: 'OWNER', value: g => (g.owner === me.email ? 'you' : g.owner) },\n ])\n : chalk.dim(members ? 'No group has exactly those people.' : describeGroups([]))\n )\n}\n\nexport async function runGroupShow(ctx: CommandContext, slug: string): Promise<void> {\n const group = await getGroup(requireGroups(ctx), slug)\n ctx.out.data(group, () => describeGroup(group))\n}\n\nexport async function runGroupCreate(\n ctx: CommandContext,\n slug: string,\n opts: { name?: string; add?: string[] }\n): Promise<void> {\n const group = await createGroup(requireGroups(ctx), {\n slug,\n name: opts.name ?? slug,\n members: splitEmails(opts.add ?? []),\n })\n ctx.log.success(`Group ${group.slug} created`)\n ctx.out.data(group, () => describeGroup(group))\n}\n\nexport async function runGroupMembers(\n ctx: CommandContext,\n slug: string,\n emails: string[],\n how: 'add' | 'remove'\n): Promise<void> {\n const list = splitEmails(emails)\n if (list.length === 0) throw new CliError('Name at least one address')\n const group = await changeGroupMembers(requireGroups(ctx), slug, { [how]: list })\n ctx.out.data(group, () => describeGroup(group))\n}\n\nexport async function runGroupRename(ctx: CommandContext, slug: string, name: string) {\n const group = await renameGroup(requireGroups(ctx), slug, name)\n ctx.log.success(`Group ${group.slug} is now called ${group.name}`)\n ctx.out.data(group, () => describeGroup(group))\n}\n\nexport async function runGroupDelete(\n ctx: CommandContext,\n slug: string,\n opts: { yes?: boolean }\n): Promise<void> {\n const client = requireGroups(ctx)\n if (!opts.yes) {\n if (!ctx.interactive) {\n throw new CliError(`Refusing to delete group ${slug} without confirmation`, {\n hint: 'Pass --yes to delete.',\n })\n }\n const ok = await ctx.confirm(\n `Delete group ${slug}? Sites whose audience names it keep their restriction, and anyone it let in loses access. This cannot be undone.`\n )\n if (!ok) throw new CliError('Cancelled')\n }\n const result = await deleteGroup(client, slug)\n ctx.log.success(`Group ${slug} deleted`)\n if (ctx.json) ctx.out.data(result, () => '')\n}\n", "/**\n * `fling setup [url] [--yes] [--scope user|project|local]` \u2014 get a machine ready in one go:\n *\n * 1. Sign in, to the Fling at `url` (needed the first time: there is no default server); skipped\n * when the stored key for that server still works. Either way it becomes the current server,\n * and the logins to other servers are kept.\n * 2. Claude Code: install the Fling plugin (skill + MCP server) through the `claude` CLI, or\n * update it when it is already installed. Skipped, with a hint, when `claude` is missing.\n * 3. Claude Desktop (macOS / Windows, when it is installed): download fling.mcpb and open it;\n * Desktop then asks the user to confirm the install.\n *\n * On a terminal it asks before steps 2 and 3; with `--yes` or without a terminal it does them all.\n * Steps report and carry on: one failing doesn't stop the others; the exit code is 1 if any did.\n */\nimport { intro, outro, spinner } from '@clack/prompts'\nimport chalk from 'chalk'\nimport {\n claudeCodeStatus,\n downloadExtension,\n findClaudeDesktop,\n installPlugin,\n MARKETPLACE_SOURCE,\n PLUGIN_ID,\n PLUGIN_NAME,\n type PluginScope,\n type RunClaude,\n runClaude,\n updatePlugin,\n} from '../claude.ts'\nimport { type CommandContext, requireClient, requireServer } from '../context.ts'\nimport { CliError, exitCodeFor } from '../errors.ts'\nimport { whoami } from '../sites.ts'\nimport { logo } from '../ui/theme.ts'\nimport { createLogger } from '../utils/logger.ts'\nimport { loginServer, runLogin } from './auth.ts'\n\nexport interface SetupOptions {\n yes?: boolean\n scope?: string\n /** The Fling to sign in to; default: the current one. */\n url?: string\n}\n\nexport interface SetupDeps {\n runClaude?: RunClaude\n findClaudeDesktop?: () => Promise<string | null>\n downloadExtension?: (serverUrl: string) => Promise<string>\n}\n\ntype StepResult = 'done' | 'updated' | 'already' | 'skipped' | 'missing' | 'failed'\n\nconst SCOPES: readonly PluginScope[] = ['user', 'project', 'local']\n\nexport async function runSetup(\n baseCtx: CommandContext,\n opts: SetupOptions,\n deps: SetupDeps = {}\n): Promise<void> {\n const scope = (opts.scope ?? 'user') as PluginScope\n if (!SCOPES.includes(scope))\n throw new CliError(`--scope must be one of ${SCOPES.join(', ')}, not \"${opts.scope}\"`)\n const run = deps.runClaude ?? runClaude\n const ask = baseCtx.interactive && !opts.yes\n const fancy = baseCtx.interactive && !baseCtx.json\n // Inside clack's intro/outro frame, keep log lines on its \u2502 gutter.\n const ctx: CommandContext = fancy\n ? {\n ...baseCtx,\n log: createLogger({\n debug: baseCtx.config.debug,\n write: line => process.stderr.write(`${chalk.gray('\u2502')} ${line}\\n`),\n }),\n }\n : baseCtx\n\n if (fancy) {\n process.stderr.write(`${logo()}\\n`)\n intro(chalk.bold(' fling setup '), { output: process.stderr })\n }\n\n const login = await stepLogin(ctx, opts.url)\n const results: Record<'login' | 'claudeCode' | 'claudeDesktop', StepResult> = {\n login: login.result,\n claudeCode: 'skipped',\n claudeDesktop: 'skipped',\n }\n // The later steps use the server signed in to, with what the login stored.\n const after: CommandContext = login.serverUrl\n ? { ...ctx, config: await ctx.store.resolve({ serverUrl: login.serverUrl }) }\n : ctx\n results.claudeCode = await stepClaudeCode(after, run, scope, ask, fancy)\n results.claudeDesktop = await stepClaudeDesktop(after, deps, ask, fancy)\n\n const failed = Object.values(results).includes('failed')\n if (fancy)\n outro(\n failed\n ? chalk.yellow('Setup finished with problems \u2014 see above, then run `fling setup` again.')\n : `You're set. Try ${chalk.bold(`${ctx.binName} deploy ./dist`)}, or ask Claude to \u201Cfling this\u201D.`,\n { output: process.stderr }\n )\n ctx.out.data(results, () => '')\n if (failed) process.exitCode = 1\n}\n\n/**\n * Sign in to `url` (default: the server this command uses) unless its stored key still works.\n * Either way the server becomes current. Returns the server, when there is one.\n */\nasync function stepLogin(\n ctx: CommandContext,\n url: string | undefined\n): Promise<{ result: StepResult; serverUrl?: string }> {\n let serverUrl: string\n let target: CommandContext\n try {\n serverUrl = await loginServer(ctx, url)\n target = { ...ctx, config: await ctx.store.resolve({ serverUrl }) }\n } catch (error) {\n ctx.log.error(error instanceof Error ? error.message : String(error))\n return { result: 'failed' }\n }\n return { result: await signIn(target, serverUrl), serverUrl }\n}\n\nasync function signIn(ctx: CommandContext, serverUrl: string): Promise<StepResult> {\n if (ctx.config.apiKey) {\n try {\n const me = await whoami(requireClient(ctx))\n if (ctx.config.remembered) await ctx.store.setCurrent(serverUrl)\n ctx.log.success(`Signed in as ${chalk.bold(me.name)} ${chalk.dim(`<${me.email}>`)}`)\n return 'already'\n } catch (error) {\n if (exitCodeFor(error) !== 2) {\n ctx.log.error(error instanceof Error ? error.message : String(error))\n return 'failed'\n }\n ctx.log.warn('The stored API key no longer works \u2014 signing in again')\n }\n }\n try {\n // runLogin prints JSON under --json; setup prints one summary instead.\n await runLogin({ ...ctx, json: false }, serverUrl)\n return 'done'\n } catch (error) {\n ctx.log.error(error instanceof Error ? error.message : String(error))\n return 'failed'\n }\n}\n\nasync function stepClaudeCode(\n ctx: CommandContext,\n run: RunClaude,\n scope: PluginScope,\n ask: boolean,\n fancy: boolean\n): Promise<StepResult> {\n const status = await claudeCodeStatus(run)\n if (status.claude === 'missing') {\n ctx.log.info(`Claude Code not found ${chalk.dim('(no `claude` on your PATH) \u2014 skipped')}`)\n ctx.log.hint(\n `Once it is installed, run \\`${ctx.binName} setup\\` again, or in Claude Code: /plugin marketplace add ${MARKETPLACE_SOURCE} then /plugin install ${PLUGIN_ID}`\n )\n return 'missing'\n }\n\n const installed = 'installed' in status && status.installed\n const question = installed\n ? `The Fling plugin is installed in Claude Code${status.version ? ` (${status.version})` : ''}. Update it to the latest?`\n : 'Install the Fling plugin (skill + MCP server) into Claude Code?'\n if (ask && !(await ctx.confirm(question))) {\n ctx.log.info(chalk.dim('Claude Code plugin: skipped'))\n return installed ? 'already' : 'skipped'\n }\n\n const s = fancy ? spinner({ output: process.stderr }) : null\n s?.start(installed ? 'Updating the Claude Code plugin' : 'Installing the Claude Code plugin')\n try {\n if (installed) await updatePlugin(run, status.scope)\n else await installPlugin(run, scope)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n if (s) s.error(message)\n else ctx.log.error(message)\n return 'failed'\n }\n const done = installed\n ? `Claude Code plugin ${PLUGIN_NAME} is up to date`\n : `Claude Code plugin ${PLUGIN_NAME} installed ${chalk.dim(`(${scope} scope)`)}`\n if (s) s.stop(done)\n else ctx.log.success(done)\n ctx.log.hint('Restart Claude Code (or run /reload-plugins) to pick it up.')\n return installed ? 'updated' : 'done'\n}\n\nasync function stepClaudeDesktop(\n ctx: CommandContext,\n deps: SetupDeps,\n ask: boolean,\n fancy: boolean\n): Promise<StepResult> {\n const app = await (deps.findClaudeDesktop ?? findClaudeDesktop)()\n if (!app) return 'missing'\n if (ask && !(await ctx.confirm('Add the Fling extension to Claude Desktop too?'))) {\n ctx.log.info(chalk.dim('Claude Desktop extension: skipped'))\n return 'skipped'\n }\n const s = fancy ? spinner({ output: process.stderr }) : null\n s?.start('Downloading the Claude Desktop extension')\n try {\n const file = await (\n deps.downloadExtension ?? (serverUrl => downloadExtension(serverUrl, ctx.fetch))\n )(requireServer(ctx))\n await ctx.open(file)\n const done = 'Opened fling.mcpb in Claude Desktop \u2014 click Install there to finish'\n if (s) s.stop(done)\n else ctx.log.success(done)\n return 'done'\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n if (s) s.error(message)\n else ctx.log.error(message)\n return 'failed'\n }\n}\n", "/**\n * Installing Fling into Claude: the Claude Code plugin (skill + MCP server), through the `claude`\n * CLI, and the Claude Desktop extension (fling.mcpb), which Desktop installs when the file is\n * opened. `runClaude` is the seam tests replace.\n */\nimport { execFile } from 'node:child_process'\nimport { access, mkdtemp, writeFile } from 'node:fs/promises'\nimport { homedir, tmpdir } from 'node:os'\nimport { join } from 'node:path'\nimport { REPO_SLUG } from '@fling/shared'\nimport type { FetchLike } from './api.ts'\n\n/** The marketplace (this repo) and the plugin in it. */\nexport const MARKETPLACE_SOURCE = REPO_SLUG\nexport const MARKETPLACE_NAME = 'fling'\nexport const PLUGIN_NAME = 'fling'\nexport const PLUGIN_ID = `${PLUGIN_NAME}@${MARKETPLACE_NAME}`\nexport const MCPB_PATH = '/downloads/fling.mcpb'\n\nexport type PluginScope = 'user' | 'project' | 'local'\n\nexport interface ClaudeResult {\n code: number\n stdout: string\n stderr: string\n}\n\n/** Run `claude <args>`; `code` is -1 when `claude` is not installed. Never throws. */\nexport type RunClaude = (args: readonly string[]) => Promise<ClaudeResult>\n\nexport const runClaude: RunClaude = args =>\n new Promise(resolve => {\n execFile(\n 'claude',\n [...args],\n { timeout: 120_000, maxBuffer: 16 * 1024 * 1024, shell: process.platform === 'win32' },\n (error, stdout, stderr) => {\n const missing = (error as NodeJS.ErrnoException | null)?.code === 'ENOENT'\n const code = !error ? 0 : missing ? -1 : typeof error.code === 'number' ? error.code : 1\n resolve({ code, stdout: String(stdout), stderr: String(stderr) })\n }\n )\n })\n\nexport type PluginStatus =\n | { claude: 'missing' }\n | { claude: string; installed: false }\n | { claude: string; installed: true; version?: string; scope?: string; enabled?: boolean }\n\n/** Is Claude Code installed, and is the Fling plugin? */\nexport async function claudeCodeStatus(run: RunClaude): Promise<PluginStatus> {\n const version = await run(['--version'])\n if (version.code !== 0) return { claude: 'missing' }\n const claude = version.stdout.trim().split(/\\s+/)[0] ?? 'unknown'\n const list = await run(['plugin', 'list', '--json'])\n let plugins: { id?: string; version?: string; scope?: string; enabled?: boolean }[] = []\n try {\n plugins = JSON.parse(list.stdout)\n } catch {\n // an older `claude` without --json: treat as not installed; install will say if it is\n }\n const fling = Array.isArray(plugins) ? plugins.find(p => p.id === PLUGIN_ID) : undefined\n if (!fling) return { claude, installed: false }\n return {\n claude,\n installed: true,\n version: fling.version,\n scope: fling.scope,\n enabled: fling.enabled,\n }\n}\n\n/** Add the marketplace (if needed) and install the plugin. Throws with claude's own message. */\nexport async function installPlugin(run: RunClaude, scope: PluginScope): Promise<void> {\n check(\n await run(['plugin', 'install', PLUGIN_NAME, '--marketplace', MARKETPLACE_SOURCE, '-s', scope]),\n 'install the Fling plugin'\n )\n}\n\n/** Refresh the marketplace and update the installed plugin to its latest version. */\nexport async function updatePlugin(run: RunClaude, scope?: string): Promise<void> {\n check(await run(['plugin', 'marketplace', 'update', MARKETPLACE_NAME]), 'update the marketplace')\n check(\n await run(['plugin', 'update', PLUGIN_ID, ...(scope ? ['-s', scope] : [])]),\n 'update the Fling plugin'\n )\n}\n\nfunction check(result: ClaudeResult, what: string): void {\n if (result.code === 0) return\n const detail = (result.stderr || result.stdout).trim().split('\\n').at(-1)\n throw new Error(`Could not ${what}${detail ? `: ${detail}` : ''}`)\n}\n\n/** Where Claude Desktop lives on this machine, or null (Linux has no Claude Desktop). */\nexport async function findClaudeDesktop(\n platform: NodeJS.Platform = process.platform,\n env: Record<string, string | undefined> = process.env,\n exists: (path: string) => Promise<boolean> = path =>\n access(path).then(\n () => true,\n () => false\n )\n): Promise<string | null> {\n const candidates =\n platform === 'darwin'\n ? ['/Applications/Claude.app', join(homedir(), 'Applications', 'Claude.app')]\n : platform === 'win32' && env.LOCALAPPDATA\n ? [join(env.LOCALAPPDATA, 'AnthropicClaude'), join(env.LOCALAPPDATA, 'Programs', 'Claude')]\n : []\n for (const path of candidates) if (await exists(path)) return path\n return null\n}\n\n/** Download fling.mcpb from the server into a temp folder; returns its path. */\nexport async function downloadExtension(serverUrl: string, fetch: FetchLike): Promise<string> {\n const url = new URL(MCPB_PATH, serverUrl).toString()\n const response = await fetch(url)\n if (!response.ok) throw new Error(`Could not download ${url} (HTTP ${response.status})`)\n const dir = await mkdtemp(join(tmpdir(), 'fling-mcpb-'))\n const file = join(dir, 'fling.mcpb')\n await writeFile(file, Buffer.from(await response.arrayBuffer()))\n return file\n}\n", "/** Site management: ls, info, versions, rollback, share, visibility, access, archive/unarchive, rm. */\nimport {\n changesAudience,\n describeAudience,\n privateAudience,\n type Site,\n type SiteDetail,\n type SiteSort,\n sharedVia,\n splitEmails,\n splitGroups,\n type Visibility,\n} from '@fling/shared'\nimport chalk from 'chalk'\nimport { type CommandContext, requireClient } from '../context.ts'\nimport { CliError } from '../errors.ts'\nimport { waitWithSpinner } from '../ready.ts'\nimport {\n archiveSite,\n audiencesEnabled,\n audienceWarnings,\n deleteSite,\n getAudience,\n getSite,\n groupsEnabled,\n listShared,\n listSites,\n rollback,\n setAudience,\n setVisibility,\n share,\n versionFiles,\n} from '../sites.ts'\nimport { formatBytes, formatDate, renderTable } from '../utils/output.ts'\n\nexport async function runList(\n ctx: CommandContext,\n opts: { archived?: boolean; sort?: SiteSort }\n): Promise<void> {\n const sites = await listSites(requireClient(ctx), opts)\n ctx.out.data({ sites }, () =>\n renderTable(sites, [\n { header: 'NAME', value: s => s.name },\n { header: 'URL', value: s => s.url },\n {\n header: 'VISIBILITY',\n value: s => (s.archived ? `${s.visibility} (archived)` : s.visibility),\n },\n { header: 'SHARE', value: s => s.shareUrl },\n { header: 'UPDATED', value: s => formatDate(s.updatedAt) },\n ])\n )\n}\n\n/** `ls --shared`: the restricted sites others have shared with the caller. */\nexport async function runListShared(ctx: CommandContext, opts: { sort?: SiteSort }): Promise<void> {\n const instance = ctx.config.instance\n if (instance && !audiencesEnabled(instance)) {\n throw new CliError(`${instance.name} can't limit a site to listed people, so nothing is shared`)\n }\n const sites = await listShared(requireClient(ctx), opts)\n ctx.out.data({ sites }, () =>\n renderTable(sites, [\n { header: 'NAME', value: s => s.name },\n { header: 'URL', value: s => s.url },\n { header: 'OWNER', value: s => s.owner },\n { header: 'VIA', value: s => sharedVia(s) },\n { header: 'UPDATED', value: s => formatDate(s.updatedAt) },\n ])\n )\n}\n\nfunction describeSite(site: Site & { versions?: SiteDetail['versions'] }): string[] {\n const row = (label: string, value: string) => `${chalk.bold(`${label}:`.padEnd(12))}${value}`\n return [\n row('Name', site.name),\n row('URL', site.url),\n row('Visibility', site.visibility + (site.archived ? chalk.yellow(' (archived)') : '')),\n row('SPA', site.spa ? 'yes' : 'no'),\n row('Share link', site.shareUrl ?? '-'),\n row('Version', site.currentVersionId ?? '-'),\n ...filesRow(site, row),\n row('Created', formatDate(site.createdAt)),\n row('Updated', formatDate(site.updatedAt)),\n ]\n}\n\nfunction filesRow(\n site: Site & { versions?: SiteDetail['versions'] },\n row: (label: string, value: string) => string\n): string[] {\n const current = site.versions?.find(v => v.id === site.currentVersionId)\n if (!current) return []\n const n = current.fileCount\n return [row('Files', `${n} file${n === 1 ? '' : 's'}, ${formatBytes(current.totalBytes)}`)]\n}\n\n/** Who may open a private site, for copy: the instance's members, or a generic phrase. */\nconst membersOf = (ctx: CommandContext) =>\n ctx.config.instance ? privateAudience(ctx.config.instance) : 'anyone signed in to this Fling'\n\nexport async function runInfo(ctx: CommandContext, name: string): Promise<void> {\n const site = await getSite(requireClient(ctx), name)\n const access =\n site.audience && audiencesEnabled(ctx.config.instance)\n ? [`${chalk.bold('Access:'.padEnd(12))}${describeAudience(site, membersOf(ctx))}`]\n : []\n ctx.out.data(site, () =>\n [\n ...describeSite(site),\n ...access,\n '',\n chalk.dim(\n `${site.versions.length} version(s) \u2014 \\`fling versions ${name}\\`; files \u2014 \\`fling files ${name}\\``\n ),\n ].join('\\n')\n )\n}\n\nexport async function runVersions(ctx: CommandContext, name: string): Promise<void> {\n const site = await getSite(requireClient(ctx), name)\n ctx.out.data(\n { name: site.name, currentVersionId: site.currentVersionId, versions: site.versions },\n () =>\n renderTable(site.versions, [\n { header: '', value: v => (v.id === site.currentVersionId ? '*' : ' ') },\n { header: 'VERSION', value: v => v.id },\n { header: 'FILES', value: v => v.fileCount },\n { header: 'SIZE', value: v => formatBytes(v.totalBytes) },\n { header: 'CREATED', value: v => formatDate(v.createdAt) },\n ])\n )\n}\n\nexport async function runFiles(\n ctx: CommandContext,\n name: string,\n versionId?: string\n): Promise<void> {\n const result = await versionFiles(requireClient(ctx), name, versionId)\n if (!result.files.some(f => f.path === 'index.html')) {\n ctx.log.warn('No index.html at the root \u2014 the site root URL will 404')\n }\n ctx.out.data(result, () => {\n const n = result.files.length\n const header = chalk.dim(\n `${result.versionId}${result.current ? ' (current)' : ' (not served)'} \u2014 ${n} file${n === 1 ? '' : 's'}, ` +\n `${formatBytes(result.totalBytes)}${result.generatedIndex ? ', generated index.html' : ''}`\n )\n const table = renderTable(result.files, [\n { header: 'PATH', value: f => f.path },\n { header: 'SIZE', value: f => formatBytes(f.size) },\n { header: 'TYPE', value: f => f.contentType },\n ])\n return `${header}\\n${table}`\n })\n}\n\nexport async function runRollback(\n ctx: CommandContext,\n name: string,\n versionId: string\n): Promise<void> {\n const site = await rollback(requireClient(ctx), name, versionId)\n ctx.log.success(`${name} now serves version ${site.currentVersionId ?? versionId}`)\n ctx.out.data(site, () => site.url)\n}\n\nexport async function runShare(\n ctx: CommandContext,\n name: string,\n opts: { refresh?: boolean; revoke?: boolean }\n): Promise<void> {\n if (opts.refresh && opts.revoke) throw new CliError('Use either --refresh or --revoke, not both')\n const client = requireClient(ctx)\n const result = await share(client, name, opts)\n let ready: boolean | undefined\n if (result.action === 'created' || result.action === 'refreshed') {\n // a new share label takes a few seconds to reach every edge\n const files = ctx.waitReady ? await versionFiles(client, name).catch(() => null) : null\n ready = (\n await waitWithSpinner(ctx.waitReady, result.shareUrl, files?.files.map(f => f.path) ?? [], {\n progress: ctx.progress,\n warn: m => ctx.log.warn(m),\n })\n ).ready\n }\n if (result.action === 'revoked') ctx.log.success(`Share link for ${name} revoked`)\n else if (result.action === 'refreshed')\n ctx.log.success('New share link \u2014 the old one no longer works')\n else if (result.action === 'created')\n ctx.log.success('Share link created \u2014 anyone with it can view the site')\n ctx.out.data(ready === undefined ? result : { ...result, ready }, () =>\n result.shareUrl ? result.shareUrl : chalk.dim('(no share link)')\n )\n}\n\nexport async function runVisibility(\n ctx: CommandContext,\n name: string,\n visibility: string\n): Promise<void> {\n if (visibility !== 'private' && visibility !== 'public') {\n throw new CliError(`Visibility must be \"private\" or \"public\", not \"${visibility}\"`)\n }\n const site = await setVisibility(requireClient(ctx), name, visibility as Visibility)\n ctx.log.success(\n site.visibility === 'public'\n ? `${name} is public \u2014 no sign-in needed`\n : `${name} is private \u2014 sign-in required`\n )\n ctx.out.data(site, () => site.url)\n}\n\n/**\n * `fling access <name> [--add \u2026] [--remove \u2026] [--group \u2026] [--remove-group \u2026] [--clear]`: show who\n * can open a site or, with options, change its audience (the addresses and groups besides the\n * owner who may open it while private).\n */\nexport async function runAccess(\n ctx: CommandContext,\n name: string,\n opts: {\n add?: string[]\n remove?: string[]\n group?: string[]\n removeGroup?: string[]\n clear?: boolean\n }\n): Promise<void> {\n const instance = ctx.config.instance\n if (instance && !audiencesEnabled(instance)) {\n throw new CliError(`${instance.name} can't limit a site to listed people`)\n }\n const change = {\n add: splitEmails(opts.add ?? []),\n remove: splitEmails(opts.remove ?? []),\n addGroups: splitGroups(opts.group ?? []),\n removeGroups: splitGroups(opts.removeGroup ?? []),\n clear: opts.clear,\n }\n if (instance && (change.addGroups.length || change.removeGroups.length)) {\n if (!groupsEnabled(instance)) throw new CliError(`${instance.name} has no groups`)\n }\n const client = requireClient(ctx)\n const site = changesAudience(change)\n ? await setAudience(client, name, change)\n : await getAudience(client, name)\n const warnings = audienceWarnings(site)\n for (const w of warnings) ctx.log.warn(w)\n ctx.out.data({ ...site, warnings }, () => describeAudience(site, membersOf(ctx)))\n}\n\nexport async function runArchive(\n ctx: CommandContext,\n name: string,\n unarchive = false\n): Promise<void> {\n const site = await archiveSite(requireClient(ctx), name, { unarchive })\n ctx.log.success(\n unarchive ? `${name} restored` : `${name} archived \u2014 it 404s until \\`fling unarchive ${name}\\``\n )\n if (ctx.json) ctx.out.data(site, () => '')\n else if (unarchive) ctx.out.text(site.url)\n}\n\nexport async function runRemove(\n ctx: CommandContext,\n name: string,\n opts: { yes?: boolean }\n): Promise<void> {\n if (!opts.yes) {\n if (!ctx.interactive) {\n throw new CliError(`Refusing to delete ${name} without confirmation`, {\n hint: 'Pass --yes to delete.',\n })\n }\n const ok = await ctx.confirm(`Delete ${name} and every version of it? This cannot be undone.`)\n if (!ok) throw new CliError('Cancelled')\n }\n const result = await deleteSite(requireClient(ctx), name)\n ctx.log.success(`${name} deleted`)\n if (ctx.json) ctx.out.data(result, () => '')\n}\n", "/**\n * `fling mcp` (and the Claude Desktop extension, mcp-entry.ts) \u2014 a stdio MCP server exposing the\n * same operations as the CLI, for agents. It knows every Fling the CLI remembers\n * (`~/.fling/config.json`), re-read on every call so a `fling login` or `fling use` in another\n * terminal takes effect without a restart. Each call goes to the Fling its `server` argument names,\n * with that Fling's stored key; mcp-servers.ts decides what happens without one (the only Fling, the\n * pinned one, or, with several, a request to settle which). `fling_servers` lists them and switches\n * the current one; `fling_login` signs in to a known or new Fling.\n *\n * Tools shared with the remote connector (fling_publish, fling_list, \u2026) take their names,\n * descriptions and schemas from `@fling/shared` mcp-tools, plus `server`. Descriptions and\n * instructions are written when the server starts: with one Fling they name it (its stored\n * `/.well-known/fling`), with none they stay generic, and with several they list them by host.\n * Local extras: fling_deploy (a file, zip or folder on this computer, found by name in Downloads\n * etc. \u2014 see locate.ts / inputs.ts), fling_find_files, fling_servers and fling_login. Never relies\n * on Claude's sandbox paths or network.\n *\n * stdout carries only the MCP protocol: nothing here logs, and errors become tool results.\n */\nimport { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { basename, dirname, join } from 'node:path'\nimport {\n COMMENTS_NOTE,\n changesAudience,\n describeAudience,\n describeComments,\n describeGroup,\n describeGroups,\n describeSharedSite,\n describeVersionFiles,\n type InstanceMetadata,\n isSecretPath,\n isValidSitePath,\n MAX_DEPLOY_BYTES,\n type McpToolDef,\n type McpWording,\n mcpToolsFor,\n mcpWording,\n NEVER_PUBLISHED,\n NOT_READY_NOTE,\n privateAudience,\n reviewUrl,\n shareForFeedback,\n} from '@fling/shared'\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport { z } from 'zod'\nimport { type ApiClient, CliApiError, createApiClient, type FetchLike } from './api.ts'\nimport { type LoginResult, loginFlow } from './auth.ts'\nimport {\n type ConfigStore,\n createConfigStore,\n matchServer,\n type ResolvedConfig,\n serverToAdd,\n systemLocateOptions,\n} from './config.ts'\nimport type { OpenLike } from './context.ts'\nimport { deploy, NameTakenError, resolveSiteName } from './deploy.ts'\nimport { CliError, EXIT_NOT_LOGGED_IN, NoServerError } from './errors.ts'\nimport { defaultNameFor, prepareInput } from './inputs.ts'\nimport { loadInstance } from './instance.ts'\nimport {\n FOUND_AS_GIVEN,\n findFiles,\n type LocateOptions,\n type Resolved,\n resolveInput,\n} from './locate.ts'\nimport {\n buildManifest,\n describeSkipped,\n hasRootIndex,\n htmlPages,\n SecretFilesError,\n withHtmlListing,\n} from './manifest.ts'\nimport {\n addServerOnStart,\n describeServer,\n isPinned,\n type KnownServer,\n knownServers,\n knownServersOf,\n rememberedServer,\n ServerNeededError,\n serverArgDescription,\n serverLabel,\n serversInstructions,\n serverToolNote,\n} from './mcp-servers.ts'\nimport { NPX_COMMAND, VERSION } from './package-info.ts'\nimport { createReadyWaiter, type ReadyWaiter } from './ready.ts'\nimport {\n addComment,\n archiveSite,\n audiencesEnabled,\n changeGroupMembers,\n checkName,\n commentsEnabled,\n createGroup,\n deleteComment,\n deleteGroup,\n deleteSite,\n getGroup,\n getSite,\n groupsEnabled,\n listComments,\n listGroups,\n listShared,\n listSites,\n renameGroup,\n resolveComment,\n rollback,\n setAudience,\n setVisibility,\n share,\n sitesBaseOf,\n sitesPattern,\n siteUrlFor,\n versionFiles,\n whoami,\n} from './sites.ts'\nimport { silentLogger } from './utils/logger.ts'\nimport { formatBytes } from './utils/output.ts'\n\nexport interface McpDeps {\n store?: ConfigStore\n fetch?: FetchLike\n /** Base for relative `path` arguments (default: process.cwd()). */\n cwd?: string\n /** `--server` given to `fling mcp`. */\n server?: string\n /** Where file names are looked up (default: this machine, with `cwd`). */\n locate?: LocateOptions\n /** Opens the sign-in page (default: the `open` package). */\n open?: OpenLike\n /** How long fling_login waits for the browser before returning (default 30 s). */\n loginWaitMs?: number\n /** How long the login listener stays up in the background (default 5 min). */\n loginTimeoutMs?: number\n /** Waits for a new site / share link to reach the edge (default: real polling, skipped by FLING_NO_WAIT and in tests). */\n waitReady?: ReadyWaiter\n /**\n * The Flings the descriptions name (runMcpServer reads them at start): one \u2192 its instance, none \u2192\n * generic wording, several \u2192 listed by host.\n */\n servers?: KnownServer[]\n}\n\nexport const LOGIN_HINT = `Not logged in to Fling. Call fling_login (it opens the browser to sign in), or ask the user to run \\`${NPX_COMMAND} login\\` in a terminal (in Claude Code: \\`! ${NPX_COMMAND} login\\`), then try again.`\n\n/** No server configured: only the user knows their Fling's address. */\nexport const NO_SERVER_HINT = `No Fling server is set up on this computer. Ask the user for their Fling's address, then call fling_login with it as \\`server\\` (or ask them to run \\`${NPX_COMMAND} login <url>\\` in a terminal; in Claude Code: \\`! ${NPX_COMMAND} login <url>\\`), then try again.`\n\n/** Sent at `initialize`: how to use this (local) server. */\nexport const mcpLocalInstructions = (\n w: McpWording,\n opts: { comments?: boolean; servers?: readonly KnownServer[] } = {}\n) =>\n [\n `${w.name} publishes static sites (HTML/CSS/JS, images, documents) at ${w.sitesPattern}. This server runs on the user's computer.`,\n ...[serversInstructions(opts.servers ?? [])].filter(p => p !== undefined),\n 'Content you created in this conversation (an HTML page, a report, a small app): call fling_publish with every file inline (text as utf8, binary as base64). ' +\n 'Never pass file paths from your sandbox (e.g. /mnt/user-data/outputs/\u2026, /sessions/\u2026) \u2014 this computer cannot see them \u2014 and never curl or upload from the sandbox.',\n 'A file or folder the user has on this computer (a downloaded .html, a .zip, a build folder): call fling_deploy with its path, or just its file name (e.g. \"Pitch Deck.html\") \u2014 ' +\n 'it is looked up in Downloads, Desktop, Documents/Claude and Claude Desktop output folders. Use fling_find_files to see recent candidates when unsure which file the user means.',\n 'Confirm the site name with the user before publishing (fling_check_name shows whether it is free and, for a path, the generated name). Names are global, first come first served; when one is taken, offer the suggestions.',\n 'When there is no index.html but there are HTML pages, fling_deploy and fling_publish do not publish: ask the user whether to generate an index page listing the pages (`listHtml: true`) or publish without one (`listHtml: false`, the root URL 404s), then retry.',\n NEVER_PUBLISHED,\n 'Not logged in? Call fling_login, let the user finish signing in in the browser, then retry.',\n `Sites are private (open to ${w.privateAudience}) by default; only make one public if asked. Use fling_share for a link people who cannot sign in can open. ${opts.comments ? 'Always give the user the links that come back: the review link first, as the one to share for feedback, then the site URL.' : 'Always give the user the URL that comes back.'}`,\n ...(opts.comments ? [COMMENTS_NOTE(w)] : []),\n ].join('\\n\\n')\n\ntype DeployOutcome =\n | { kind: 'needs_decision'; summary: string; data: unknown }\n | { kind: 'deployed'; summary: string; data: unknown }\n\n/** The Fling a call goes to. */\ninterface Target {\n client: ApiClient\n url: string\n config: ResolvedConfig\n /** Its `/.well-known/fling` (stored; fetched once if missing). Null when it can't be had. */\n instance(): Promise<InstanceMetadata | null>\n}\n\n/** The line a result naming URLs ends with: which Fling it went to. */\nconst onFling = (url: string, instance: InstanceMetadata | null) =>\n `\\nFling: ${serverLabel(url)}${instance ? ` (${instance.name})` : ''}`\n\nexport function createMcpServer(deps: McpDeps = {}): McpServer {\n const store = deps.store ?? createConfigStore()\n const fetchImpl: FetchLike = deps.fetch ?? ((input, init) => fetch(input, init))\n const cwd = deps.cwd ?? process.cwd()\n const locate: LocateOptions = deps.locate ?? { ...systemLocateOptions(), cwd }\n const waitReady: ReadyWaiter = deps.waitReady ?? createReadyWaiter()\n const servers = deps.servers ?? []\n const several = servers.length > 1\n const wording = mcpWording(several ? null : servers[0]?.instance)\n const mcpTools = mcpToolsFor(wording)\n const serverArg = z.string().min(1).max(500).optional().describe(serverArgDescription(servers))\n const note = serverToolNote(servers)\n\n /** A shared tool definition, with `server` and the note on choosing one. */\n const serverTool = <S extends z.ZodRawShape>(\n def: McpToolDef<S>,\n description = def.description\n ) => ({\n title: def.title,\n description: `${description}${note}`,\n inputSchema: { ...def.inputSchema, server: serverArg },\n annotations: def.annotations,\n })\n\n /** Wait for the edge; never throws. `ready: false` \u2192 append the \"reload\" note. */\n async function edgeReady(url: string, paths: readonly string[]) {\n const r = await waitReady(url, paths).catch(() => ({ ready: false, waitedMs: 0 }))\n return {\n ready: r.ready,\n note: r.ready ? '' : `\\nNot reachable yet at ${url}: ${NOT_READY_NOTE}.`,\n }\n }\n\n /**\n * The resolved config for a call: the Fling `server` names, else the pinned one, else the only\n * one. With several and no `server`, the call is refused with the list (ServerNeededError).\n */\n async function choose(server: string | undefined, tool: string): Promise<ResolvedConfig> {\n if (server !== undefined)\n return store.resolve({ serverUrl: rememberedServer(await store.load(), server) })\n const resolved = await store.resolve({ serverUrl: deps.server })\n if (isPinned(resolved)) return resolved\n const config = await store.load()\n const known = knownServersOf(config)\n if (known.length > 1) throw new ServerNeededError(known, tool)\n const only = known[0]\n return !resolved.serverUrl && only ? store.resolve({ serverUrl: only.url }) : resolved\n }\n\n async function target(server: string | undefined, tool: string): Promise<Target> {\n const config = await choose(server, tool)\n if (!config.serverUrl) throw new NoServerError('fling')\n if (!config.apiKey) throw new CliError('Not logged in', { exitCode: EXIT_NOT_LOGGED_IN })\n const url = config.serverUrl\n let instance: Promise<InstanceMetadata | null> | undefined\n return {\n client: createApiClient({ serverUrl: url, apiKey: config.apiKey, fetch: fetchImpl }),\n url,\n config,\n instance: () => {\n instance ??= loadInstance(store, config, fetchImpl)\n return instance\n },\n }\n }\n\n /** Run an operation on the Fling the call chose, and shape its outcome as a tool result. */\n async function run(\n tool: string,\n server: string | undefined,\n op: (t: Target) => Promise<{ summary: string; data: unknown }>\n ): Promise<CallToolResult> {\n try {\n const { summary, data } = await op(await target(server, tool))\n return textResult(`${summary}\\n\\n${JSON.stringify(data, null, 2)}`)\n } catch (error) {\n return failure(error)\n }\n }\n\n /** Deploy a prepared folder: the listing decision, the deploy, and the name-taken message. */\n async function deployFolder(\n t: Target,\n dir: string,\n opts: {\n name: string\n nameGiven: boolean\n /** e.g. \"the folder\" \u2014 what a generated name came from. */\n nameFrom?: string\n spa?: boolean\n public?: boolean\n listHtml?: boolean\n retryWith: string\n /** Dotfiles already left out (from a zip or the inline files). */\n skippedDotfiles?: string[]\n }\n ): Promise<DeployOutcome> {\n let local = await buildManifest(dir)\n local.skipped.dotfiles.unshift(...(opts.skippedDotfiles ?? []))\n const skippedNote = describeSkipped(local.skipped)\n .map(l => `\\n${l}.`)\n .join('')\n let generatedIndex = false\n if (!hasRootIndex(local)) {\n const pages = htmlPages(local).map(f => f.path)\n if (pages.length > 0 && opts.listHtml === undefined) {\n const shown = pages.slice(0, 20)\n return {\n kind: 'needs_decision',\n summary:\n `Not published yet: there is no index.html at the root, but there ${pages.length === 1 ? 'is 1 HTML page' : `are ${pages.length} HTML pages`}. ` +\n 'Ask the user whether to generate an index.html listing them (call again with `listHtml: true`) or to publish ' +\n `without one (\\`listHtml: false\\` \u2014 the root URL will 404, the pages still work at their own paths). Then call ${opts.retryWith} again with the same arguments plus \\`listHtml\\`.`,\n data: {\n status: 'needs_decision',\n htmlPages: shown,\n ...(pages.length > shown.length ? { moreHtmlPages: pages.length - shown.length } : {}),\n fileCount: local.files.length,\n },\n }\n }\n if (opts.listHtml) {\n local = await withHtmlListing(local, opts.name)\n generatedIndex = true\n }\n }\n const result = await deploy(\n { client: t.client, fetch: fetchImpl },\n { dir, name: opts.name, manifest: local, spa: opts.spa, public: opts.public }\n ).catch((error: unknown) => {\n if (!(error instanceof NameTakenError)) throw error\n const how = opts.nameGiven ? '' : ` (generated from ${opts.nameFrom ?? 'the folder'})`\n const pick = error.suggestions.length\n ? ` Free alternatives: ${error.suggestions.join(', ')}.`\n : ''\n throw new CliError(\n `Not deployed: the site name \"${error.siteName}\"${how} is taken by someone else on ${serverLabel(t.url)}.${pick} ` +\n `Ask the user which name to use (one of these or their own), then call ${opts.retryWith} again with \\`name\\`.`\n )\n })\n const what =\n result.status === 'unchanged'\n ? 'Unchanged \u2014 already live'\n : result.status === 'repointed'\n ? `Restored version ${result.versionId}`\n : `Deployed ${result.fileCount} files (uploaded ${result.uploaded})`\n const warnings = result.warnings.length ? `\\nWarnings:\\n- ${result.warnings.join('\\n- ')}` : ''\n const edge =\n result.status === 'unchanged'\n ? { ready: true, note: '' }\n : await edgeReady(\n result.url,\n local.files.map(f => f.path)\n )\n const instance = await t.instance()\n const review =\n instance && commentsEnabled(instance) ? reviewUrl(instance.appOrigin, result.name) : undefined\n const listing = generatedIndex ? ' \u2014 with a generated index.html listing the HTML pages' : ''\n const head = review\n ? `${what}${listing}.\\n${shareForFeedback(review, instance?.name ?? 'Fling')}\\nSite: ${result.url} (${result.site.visibility})`\n : `${what}: ${result.url} (${result.site.visibility})${listing}`\n return {\n kind: 'deployed',\n summary:\n `${head}${warnings}${skippedNote}${edge.note}${onFling(t.url, instance)}` +\n `\\nTo check exactly which files the site has, call fling_files with name \"${result.name}\".`,\n data: {\n status: result.status,\n ready: edge.ready,\n server: t.url,\n name: result.name,\n nameGenerated: !opts.nameGiven,\n versionId: result.versionId,\n site: result.site,\n ...(review ? { reviewUrl: review } : {}),\n generatedIndex,\n warnings: result.warnings,\n skipped: local.skipped,\n },\n }\n }\n\n const server = new McpServer(\n { name: 'fling', version: VERSION },\n {\n instructions: mcpLocalInstructions(wording, {\n comments: servers.some(s => commentsEnabled(s.instance)),\n servers,\n }),\n }\n )\n const { listHtml, spa, public: isPublic } = mcpTools.publish.inputSchema\n\n server.registerTool(\n 'fling_deploy',\n {\n title: 'Deploy a file or folder from this computer',\n description:\n `Fling something that is on the user's computer and return its stable URL (${wording.sitesPattern}): ` +\n \"a folder of static files (e.g. a build output like dist/), a single .html file (served as the site's index.html), \" +\n 'a .zip of a site (extracted; a single top-level folder is unwrapped), or any other single file (.pdf, .svg, .png\u2026, ' +\n 'served next to a generated page that shows it). `path` can be absolute, relative to the working directory, or just ' +\n 'a file name (\"Pitch Deck.html\"): names are looked up, newest first, in Downloads, Desktop, Documents/Claude and ' +\n 'Claude Desktop output folders, and the result says where the file was found. Never pass paths from your own ' +\n 'sandbox (/mnt/user-data/\u2026, /sessions/\u2026): for content you created, use fling_publish. ' +\n 'Without `name`, a name is generated: from the file name for files (\"Pitch Deck (1).html\" \u2192 pitch-deck), from the ' +\n 'project and folder for folders (~/work/rocketpod/docs \u2192 rocketpod-docs). Site names are one global namespace, first ' +\n 'come first served \u2014 confirm the name with the user first (fling_check_name with `path` shows the generated one). ' +\n 'If the name is taken it fails with free suggestions \u2014 ask the user to pick one, then retry with `name`. ' +\n 'If there is no index.html but there are HTML pages, it does not deploy: ask the user whether to generate an index ' +\n 'page listing them (`listHtml: true`) or deploy without one (`listHtml: false`), then retry. ' +\n `Re-deploying identical content is a no-op. Sites are private (open to ${wording.privateAudience}) unless \\`public\\` is set. ` +\n `${NEVER_PUBLISHED}${note}`,\n inputSchema: {\n path: z\n .string()\n .min(1)\n .describe(\n 'File or folder on this computer: absolute, relative to the working directory, or just its name (looked up in Downloads, Desktop and Claude output folders)'\n ),\n name: z\n .string()\n .optional()\n .describe(\n 'Site name (lowercase letters, digits, single hyphens; max 50). Defaults to a name generated from the file or folder'\n ),\n spa,\n public: isPublic,\n listHtml,\n server: serverArg,\n },\n annotations: { destructiveHint: false, idempotentHint: true, openWorldHint: true },\n },\n args =>\n run('fling_deploy', args.server, async t => {\n const located = await resolveInput(args.path, locate)\n const prepared = await prepareInput(located.path)\n try {\n const name =\n args.name !== undefined\n ? resolveSiteName(prepared.dir, args.name)\n : prepared.defaultName\n const outcome = await deployFolder(t, prepared.dir, {\n name,\n nameGiven: args.name !== undefined,\n nameFrom: prepared.kind === 'folder' ? 'the folder' : 'the file name',\n spa: args.spa,\n public: args.public,\n listHtml: args.listHtml,\n retryWith: 'fling_deploy',\n skippedDotfiles: prepared.skippedDotfiles,\n })\n const where =\n located.foundIn === FOUND_AS_GIVEN\n ? ''\n : `Found \"${basename(located.path)}\" in ${located.foundIn}: ${located.path}\\n`\n return {\n summary: `${where}${outcome.summary}`,\n data: {\n ...(outcome.data as object),\n source: {\n path: located.path,\n foundIn: located.foundIn,\n kind: prepared.kind,\n ...(located.alternatives.length ? { alternatives: located.alternatives } : {}),\n },\n },\n }\n } finally {\n await prepared.cleanup()\n }\n })\n )\n\n server.registerTool(\n 'fling_find_files',\n {\n title: 'Find files to fling',\n description:\n 'List recent things on this computer that could be flung, newest first: .html/.htm and .zip files, and folders ' +\n 'containing an index.html, from the working directory, Downloads, Desktop, Documents/Claude, ~/Claude and Claude ' +\n 'Desktop output folders. Each has its path, where it was found, size and modified time. Use it when the user ' +\n 'refers to a file they downloaded or that Claude Desktop saved, then pass the chosen path (or name) to fling_deploy.',\n inputSchema: {\n query: z\n .string()\n .optional()\n .describe('Only names containing this text (case-insensitive), e.g. \"deck\"'),\n limit: z.number().int().min(1).max(100).optional().describe('Max results (default 20)'),\n days: z\n .number()\n .int()\n .min(1)\n .max(3650)\n .optional()\n .describe('Only things modified in the last N days (default 14)'),\n },\n annotations: { readOnlyHint: true, openWorldHint: false },\n },\n async args => {\n try {\n const { files, searched, complete } = await findFiles(locate, args)\n const lines = files.map(\n f =>\n `- ${f.path} (${f.kind}, ${f.foundIn}, ${formatBytes(f.size)}, modified ${f.modified})`\n )\n const summary = files.length\n ? `${files.length} recent item(s), newest first:\\n${lines.join('\\n')}`\n : `Nothing found from the last ${args.days ?? 14} days${args.query ? ` matching \"${args.query}\"` : ''}.`\n const data = {\n files,\n searched: searched.map(r => ({ label: r.label, path: r.path })),\n ...(complete ? {} : { truncated: true }),\n }\n return textResult(`${summary}\\n\\n${JSON.stringify(data, null, 2)}`)\n } catch (error) {\n return failure(error)\n }\n }\n )\n\n const publishDef = mcpTools.publish\n server.registerTool(\n publishDef.name,\n serverTool(\n publishDef,\n // This server has no chunked upload tools; big sites go through fling_deploy instead.\n publishDef.description.replace(\n /\\(whole site, up to [^;]*; bigger sites: fling_upload_begin \\/ fling_upload_file \\/ fling_upload_finish\\)/,\n '(whole site; for a big site that is already on this computer, use fling_deploy with its folder)'\n )\n ),\n args =>\n run(publishDef.name, args.server, async t => {\n const name = resolveSiteName('.', args.name)\n const tmp = await mkdtemp(join(tmpdir(), 'fling-publish-'))\n try {\n const { skippedDotfiles } = await writeInlineFiles(tmp, args.files)\n return await deployFolder(t, tmp, {\n skippedDotfiles,\n name,\n nameGiven: true,\n spa: args.spa,\n public: args.public,\n listHtml: args.listHtml,\n retryWith: 'fling_publish',\n })\n } finally {\n await rm(tmp, { recursive: true, force: true })\n }\n })\n )\n\n server.registerTool(\n 'fling_check_name',\n {\n ...serverTool(mcpTools.checkName),\n description:\n `${mcpTools.checkName.description} Pass \\`path\\` instead of \\`name\\` to see the name fling_deploy would ` +\n `generate for a file or folder on this computer (same lookup as fling_deploy), so you can confirm it with the user.${note}`,\n inputSchema: {\n name: z.string().min(1).max(200).optional().describe('Site name to check'),\n path: z\n .string()\n .optional()\n .describe('File or folder whose generated default name to check (path or file name)'),\n server: serverArg,\n },\n },\n args =>\n run('fling_check_name', args.server, async t => {\n if (args.name === undefined && args.path === undefined)\n throw new CliError('Pass `name` or `path`')\n let name = args.name\n let source: Resolved | undefined\n if (name === undefined) {\n source = await resolveInput(args.path as string, locate)\n name = defaultNameFor(source.path, source.isDirectory)\n }\n const check = await checkName(t.client, name)\n const base = check.status === 'invalid' ? null : sitesBaseOf(await t.instance())\n const url = base ? siteUrlFor(name, base) : null\n const suggestions = check.suggestions.length\n ? ` Suggestions: ${check.suggestions.join(', ')}.`\n : ''\n const summary = {\n available: `\"${name}\" is available${url ? ` \u2192 ${url}` : ''}.`,\n yours: `\"${name}\" is the user's existing site${url ? ` (${url})` : ''} \u2014 deploying updates it.`,\n taken: `\"${name}\" is taken by someone else.${suggestions}`,\n invalid: `\"${name}\" is not a valid site name.${suggestions}`,\n }[check.status]\n return {\n summary,\n data: {\n ...check,\n url,\n server: t.url,\n ...(source\n ? { generated: true, source: { path: source.path, foundIn: source.foundIn } }\n : {}),\n },\n }\n })\n )\n\n /** Sign-ins waiting for the browser, by server. */\n const pendingLogins = new Map<string, { url?: string; done: Promise<LoginResult> }>()\n\n server.registerTool(\n 'fling_login',\n {\n title: 'Sign in to Fling',\n description:\n `Sign the user in to ${several ? 'a Fling' : wording.name}: opens their browser to sign in with ${wording.signIn} and stores ` +\n 'the key on this computer (shared with the fling CLI). Waits up to ~30 seconds; if sign-in is not finished by ' +\n 'then, it keeps waiting in the background for up to 5 minutes \u2014 tell the user to finish signing in in the ' +\n 'browser, then retry what you were doing. Call it when another tool says the user is not logged in. ' +\n 'Pass `server` (its address) to sign in to another Fling, including one not set up on this computer yet: it is ' +\n 'remembered, and becomes the current one only when none is.' +\n note,\n inputSchema: {\n server: z\n .string()\n .min(1)\n .max(500)\n .optional()\n .describe(\n `The Fling to sign in to: its address (e.g. \"https://fling.example.com\"), or the host of one set up on this computer. ${\n several\n ? `Required while several Flings are set up (${servers.map(s => serverLabel(s.url)).join(', ')})`\n : `Omit it to use ${servers[0] ? serverLabel(servers[0].url) : 'the one this computer knows'}`\n }`\n ),\n },\n annotations: { readOnlyHint: false, openWorldHint: true },\n },\n async args => {\n try {\n let serverUrl: string | undefined\n if (args.server !== undefined) {\n const config = await store.load()\n try {\n serverUrl = matchServer(Object.keys(config.servers), args.server, { loose: true }).url\n } catch (error) {\n const known = knownServersOf(config).map(s => `- ${describeServer(s)}`)\n throw new CliError((error as Error).message, {\n hint: known.length ? `The Flings set up on this computer:\\n${known.join('\\n')}` : '',\n })\n }\n } else {\n serverUrl = (await choose(undefined, 'fling_login')).serverUrl\n }\n if (!serverUrl) throw new NoServerError('fling')\n const config = await store.resolve({ serverUrl })\n let login = pendingLogins.get(serverUrl)\n if (config.apiKey && !login) {\n const me = await whoami(\n createApiClient({ serverUrl, apiKey: config.apiKey, fetch: fetchImpl })\n ).catch(() => null)\n if (me) return textResult(`Already signed in to ${serverUrl} as ${me.email}.`)\n }\n if (!login) {\n const started: { url?: string; done: Promise<LoginResult> } = {\n done: Promise.resolve() as unknown as Promise<LoginResult>,\n }\n started.done = loginFlow({\n serverUrl,\n store,\n log: silentLogger,\n open: deps.open ?? (async url => (await import('open')).default(url)),\n fetch: fetchImpl,\n timeoutMs: deps.loginTimeoutMs,\n // Signing in to another Fling leaves the CLI's current server as it is.\n makeCurrent: !config.current || config.current === serverUrl,\n onAuthUrl: url => {\n started.url = url\n },\n })\n const key = serverUrl\n started.done\n .catch(() => {})\n .finally(() => {\n if (pendingLogins.get(key) === started) pendingLogins.delete(key)\n })\n pendingLogins.set(serverUrl, started)\n login = started\n }\n const current = login\n const waited = await Promise.race([\n current.done.then(\n r => ({ ok: true as const, r }),\n (e: unknown) => ({ ok: false as const, e })\n ),\n new Promise<null>(r => setTimeout(() => r(null), deps.loginWaitMs ?? 30_000).unref?.()),\n ])\n if (waited === null)\n return textResult(\n 'Finish signing in in your browser, then try again. ' +\n `(The sign-in page is open; if it did not open, visit: ${current.url ?? 'the Fling site'} \u2014 this stays valid for 5 minutes.)`\n )\n if (!waited.ok) throw waited.e\n return textResult(\n `Signed in as ${waited.r.user.email} (${waited.r.serverUrl}, ${waited.r.instance.name}).`\n )\n } catch (error) {\n return failure(error)\n }\n }\n )\n\n server.registerTool(\n 'fling_servers',\n {\n title: 'List the Flings on this computer',\n description:\n 'List the Flings set up on this computer, read now: each one\\'s address, name, who is signed in (or \"signed ' +\n 'out\") and which is current, the user\\'s usual one. Call it when unsure which Fling the user means or which ' +\n 'exist; the list may have changed since this conversation started. Pass `use` to make one the current Fling, the ' +\n `same as running \\`${NPX_COMMAND} use <server>\\`: it changes the default of the fling CLI too, so only do it when ` +\n 'the user asks. It does not replace passing `server` to the other tools while several Flings are set up.',\n inputSchema: {\n use: z\n .string()\n .min(1)\n .max(500)\n .optional()\n .describe(\n 'Make this Fling current (address, host or unique part of it), like `fling use`'\n ),\n },\n annotations: { readOnlyHint: false, idempotentHint: true, openWorldHint: false },\n },\n async args => {\n try {\n let switched = ''\n if (args.use !== undefined) {\n const url = rememberedServer(await store.load(), args.use)\n await store.setCurrent(url)\n switched = `Now using ${serverLabel(url)} as the current Fling (as \\`fling use\\` does).\\n`\n }\n const config = await store.load()\n const known = knownServersOf(config)\n const pinned = await store.resolve({ serverUrl: deps.server })\n const summary = known.length\n ? `${switched}${known.length} Fling(s) set up on this computer:\\n${known.map(s => `- ${describeServer(s)}`).join('\\n')}` +\n (isPinned(pinned) && pinned.serverUrl\n ? `\\nCalls without \\`server\\` go to ${serverLabel(pinned.serverUrl)} (set by this server's configuration).`\n : known.length > 1\n ? '\\nPass `server` on every call: the Fling settled on for this conversation.'\n : '')\n : NO_SERVER_HINT\n const data = {\n current: config.current ?? null,\n servers: known.map(s => ({\n url: s.url,\n host: serverLabel(s.url),\n instance: s.instance?.name ?? null,\n signedIn: s.signedIn,\n email: s.email ?? null,\n current: s.current,\n })),\n }\n return textResult(`${summary}\\n\\n${JSON.stringify(data, null, 2)}`)\n } catch (error) {\n return failure(error)\n }\n }\n )\n\n const t = mcpTools\n server.registerTool(t.list.name, serverTool(t.list), args =>\n run(t.list.name, args.server, async target => {\n const { client, url } = target\n if (args.shared) {\n const instance = await target.instance()\n if (instance && !audiencesEnabled(instance)) {\n throw new CliError(\n `${instance.name} (${serverLabel(url)}) can't limit a site to listed people, so nothing is shared`\n )\n }\n const sites = await listShared(client, { sort: args.sort })\n const lines = sites.map(describeSharedSite).join('\\n')\n return {\n summary: `${sites.length} site(s) shared with you on ${serverLabel(url)}${lines ? `:\\n${lines}` : ''}`,\n data: { sites },\n }\n }\n const sites = await listSites(client, { archived: args.archived, sort: args.sort })\n return { summary: `${sites.length} site(s) on ${serverLabel(url)}`, data: { sites } }\n })\n )\n\n /** Who may open a private site on the call's Fling, for copy. */\n const membersOn = async (target: Target) => {\n const instance = await target.instance()\n return instance ? privateAudience(instance) : 'anyone signed in to this Fling'\n }\n\n server.registerTool(t.info.name, serverTool(t.info), args =>\n run(t.info.name, args.server, async target => {\n const site = await getSite(target.client, args.name)\n const access = site.audience ? `\\n${describeAudience(site, await membersOn(target))}` : ''\n return { summary: `${site.name}: ${site.url}${access}`, data: site }\n })\n )\n\n server.registerTool(t.files.name, serverTool(t.files), args =>\n run(t.files.name, args.server, async ({ client }) => {\n const result = await versionFiles(client, args.name, args.versionId)\n return {\n summary: describeVersionFiles(result.name, result, {\n current: result.current,\n url: result.url,\n }),\n data: result,\n }\n })\n )\n\n server.registerTool(t.share.name, serverTool(t.share), args =>\n run(t.share.name, args.server, async ({ client }) => {\n if (args.refresh && args.revoke) throw new CliError('Use either refresh or revoke, not both')\n const result = await share(client, args.name, args)\n if (result.action === 'revoked')\n return { summary: `Share link for ${args.name} revoked`, data: result }\n let edge = { ready: true, note: '' }\n if (result.action !== 'existing') {\n const files = await versionFiles(client, args.name).catch(() => null)\n edge = await edgeReady(result.shareUrl, files?.files.map(f => f.path) ?? [])\n }\n return {\n summary: `Share link (${result.action}): ${result.shareUrl} \u2014 anyone with it can view the site${edge.note}`,\n data: { ...result, ready: edge.ready },\n }\n })\n )\n\n server.registerTool(t.setVisibility.name, serverTool(t.setVisibility), args =>\n run(t.setVisibility.name, args.server, async ({ client }) => {\n const site = await setVisibility(client, args.name, args.visibility)\n return { summary: `${site.name} is now ${site.visibility}: ${site.url}`, data: site }\n })\n )\n\n // Audiences: offered when a Fling known at start has them; each call checks the Fling it goes to.\n if (servers.some(s => audiencesEnabled(s.instance))) {\n server.registerTool(t.setAudience.name, serverTool(t.setAudience), args =>\n run(t.setAudience.name, args.server, async target => {\n const instance = await target.instance()\n if (instance && !audiencesEnabled(instance)) {\n throw new CliError(\n `${instance.name} (${serverLabel(target.url)}) can't limit a site to listed people`\n )\n }\n const change = {\n add: args.add,\n remove: args.remove,\n set: args.set,\n addGroups: args.addGroups,\n removeGroups: args.removeGroups,\n setGroups: args.setGroups,\n clear: args.clear,\n }\n if (!changesAudience(change)) {\n throw new CliError(\n 'Pass `add`, `remove`, `set`, `addGroups`, `removeGroups`, `setGroups` or `clear`'\n )\n }\n const site = await setAudience(target.client, args.name, change)\n return {\n summary: `${site.name}: ${describeAudience(site, await membersOn(target))}${onFling(target.url, instance)}`,\n data: site,\n }\n })\n )\n }\n\n // Groups: offered when a Fling known at start has them; each call checks the Fling it goes to.\n if (servers.some(s => groupsEnabled(s.instance))) {\n /** The call's Fling, refused when it has no groups. */\n const withGroups = async (target: Target) => {\n const instance = await target.instance()\n if (instance && !groupsEnabled(instance)) {\n throw new CliError(`${instance.name} (${serverLabel(target.url)}) has no groups`)\n }\n return instance\n }\n\n server.registerTool(t.groups.name, serverTool(t.groups), args =>\n run(t.groups.name, args.server, async target => {\n const instance = await withGroups(target)\n const [groups, me] = await Promise.all([\n listGroups(target.client, { mine: args.mine, members: args.members }),\n whoami(target.client),\n ])\n const which = args.members ? ' of exactly those people' : ''\n return {\n summary:\n args.members && groups.length === 0\n ? `No group has exactly those people${onFling(target.url, instance)}`\n : `${groups.length} ${args.mine ? 'of your ' : ''}group(s)${which}${onFling(target.url, instance)}\\n${describeGroups(groups, me.email)}`,\n data: { groups },\n }\n })\n )\n\n server.registerTool(t.groupShow.name, serverTool(t.groupShow), args =>\n run(t.groupShow.name, args.server, async target => {\n await withGroups(target)\n const group = await getGroup(target.client, args.slug)\n return { summary: describeGroup(group), data: group }\n })\n )\n\n server.registerTool(t.groupCreate.name, serverTool(t.groupCreate), args =>\n run(t.groupCreate.name, args.server, async target => {\n const instance = await withGroups(target)\n const group = await createGroup(target.client, {\n slug: args.slug,\n name: args.name,\n members: args.members,\n })\n return {\n summary: `Created ${describeGroup(group)}${onFling(target.url, instance)}`,\n data: group,\n }\n })\n )\n\n server.registerTool(t.groupMembers.name, serverTool(t.groupMembers), args =>\n run(t.groupMembers.name, args.server, async target => {\n await withGroups(target)\n if (!args.add?.length && !args.remove?.length) {\n throw new CliError('Pass `add` or `remove`')\n }\n const group = await changeGroupMembers(target.client, args.slug, {\n add: args.add,\n remove: args.remove,\n })\n return { summary: describeGroup(group), data: group }\n })\n )\n\n server.registerTool(t.groupRename.name, serverTool(t.groupRename), args =>\n run(t.groupRename.name, args.server, async target => {\n await withGroups(target)\n const group = await renameGroup(target.client, args.slug, args.name)\n return { summary: describeGroup(group), data: group }\n })\n )\n\n server.registerTool(t.groupDelete.name, serverTool(t.groupDelete), args =>\n run(t.groupDelete.name, args.server, async target => {\n await withGroups(target)\n const result = await deleteGroup(target.client, args.slug)\n return {\n summary: `Group ${args.slug} deleted. Sites whose audience named it keep their restriction: anyone it let in has lost access`,\n data: result,\n }\n })\n )\n }\n\n server.registerTool(t.archive.name, serverTool(t.archive), args =>\n run(t.archive.name, args.server, async ({ client }) => {\n const site = await archiveSite(client, args.name, { unarchive: args.unarchive })\n return { summary: `${site.name} ${args.unarchive ? 'restored' : 'archived'}`, data: site }\n })\n )\n\n server.registerTool(t.delete.name, serverTool(t.delete), args =>\n run(t.delete.name, args.server, async ({ client, url }) => {\n const result = await deleteSite(client, args.name)\n return { summary: `${args.name} deleted from ${serverLabel(url)}`, data: result }\n })\n )\n\n server.registerTool(t.rollback.name, serverTool(t.rollback), args =>\n run(t.rollback.name, args.server, async ({ client }) => {\n const site = await rollback(client, args.name, args.versionId)\n return {\n summary: `${site.name} now serves version ${site.currentVersionId}: ${site.url}`,\n data: site,\n }\n })\n )\n\n // Comments: offered when a Fling known at start has them; each call checks the Fling it goes to.\n if (servers.some(s => commentsEnabled(s.instance))) {\n /** The review page of `name` on the call's Fling; refuses when that Fling has no comments. */\n async function reviewOn(target: Target) {\n const instance = await target.instance()\n if (instance?.capabilities.comments === false)\n throw new CliError(`${instance.name} (${serverLabel(target.url)}) has comments turned off`)\n const appOrigin = instance?.appOrigin ?? target.url\n return {\n review: (name: string) => reviewUrl(appOrigin, name),\n fling: onFling(target.url, instance),\n }\n }\n\n server.registerTool(t.commentsList.name, serverTool(t.commentsList), args =>\n run(t.commentsList.name, args.server, async target => {\n const { review, fling } = await reviewOn(target)\n const list = await listComments(target.client, args.name, { path: args.path })\n const reviewPage = review(list.site.name)\n return {\n summary: `${describeComments(list, { includeResolved: args.includeResolved, reviewUrl: reviewPage })}${fling}`,\n data: { ...list, reviewUrl: reviewPage },\n }\n })\n )\n\n server.registerTool(t.commentAdd.name, serverTool(t.commentAdd), args =>\n run(t.commentAdd.name, args.server, async target => {\n const { review, fling } = await reviewOn(target)\n const comment = await addComment(target.client, args.name, {\n body: args.body,\n path: args.path,\n parentId: args.replyTo,\n })\n const what = comment.parentId ? `Replied to thread ${comment.parentId}` : 'Comment added'\n return {\n summary: `${what} on ${args.name} (${comment.path}, id ${comment.id}). Review page: ${review(args.name)}${fling}`,\n data: comment,\n }\n })\n )\n\n server.registerTool(t.commentResolve.name, serverTool(t.commentResolve), args =>\n run(t.commentResolve.name, args.server, async target => {\n await reviewOn(target)\n const comment = await resolveComment(target.client, args.name, args.id, !args.reopen)\n return {\n summary: `Thread ${comment.id} on ${args.name} ${args.reopen ? 'reopened' : 'resolved'}`,\n data: comment,\n }\n })\n )\n\n server.registerTool(t.commentDelete.name, serverTool(t.commentDelete), args =>\n run(t.commentDelete.name, args.server, async target => {\n await reviewOn(target)\n const result = await deleteComment(target.client, args.name, args.id)\n return { summary: `Comment ${args.id} on ${args.name} deleted`, data: result }\n })\n )\n }\n\n server.registerTool(t.whoami.name, serverTool(t.whoami), args =>\n run(t.whoami.name, args.server, async target => {\n const me = await whoami(target.client)\n const instance = await target.instance()\n const base = sitesBaseOf(instance)\n return {\n summary: `Signed in to ${serverLabel(target.url)}${instance ? ` (${instance.name})` : ''} as ${me.email} (sites are served at ${sitesPattern(base)})`,\n data: { ...me, server: target.url },\n }\n })\n )\n\n return server\n}\n\nconst textResult = (text: string): CallToolResult => ({ content: [{ type: 'text', text }] })\n\n/**\n * Inline files (fling_publish) \u2192 a folder: `./a` and `/a` mean `a`; no traversal, no duplicates.\n * Dotfiles (`.env`, `.well-known/x`) are left out and returned in `skippedDotfiles`; secret files\n * (`server.key`, `id_rsa`\u2026) are refused. Contents are scanned for secrets by buildManifest.\n */\nexport async function writeInlineFiles(\n dir: string,\n files: readonly { path: string; content: string; encoding?: 'utf8' | 'base64' }[]\n): Promise<{ skippedDotfiles: string[] }> {\n const seen = new Set<string>()\n const skippedDotfiles: string[] = []\n const secretFiles: string[] = []\n let total = 0\n for (const f of files) {\n const path = f.path.replace(/^(\\.\\/)+/, '').replace(/^\\/+/, '')\n const segments = path.split('/')\n if (\n path &&\n !path.includes('\\\\') &&\n segments.every(s => s !== '' && s !== '.' && s !== '..') &&\n segments.some(s => s.startsWith('.'))\n ) {\n skippedDotfiles.push(path)\n continue\n }\n if (!isValidSitePath(path)) throw new CliError(`Invalid file path: \"${f.path}\"`)\n if (isSecretPath(path)) {\n secretFiles.push(path)\n continue\n }\n if (seen.has(path)) throw new CliError(`\"${path}\" is listed twice`)\n seen.add(path)\n const bytes = Buffer.from(f.content, f.encoding === 'base64' ? 'base64' : 'utf8')\n total += bytes.length\n if (total > MAX_DEPLOY_BYTES)\n throw new CliError(`The site is larger than ${formatBytes(MAX_DEPLOY_BYTES)}`)\n const target = join(dir, ...path.split('/'))\n await mkdir(dirname(target), { recursive: true })\n await writeFile(target, bytes)\n }\n if (secretFiles.length > 0) throw new SecretFilesError(secretFiles)\n return { skippedDotfiles }\n}\n\n/**\n * An error as a tool result. A call that needs `server` is not a failure: it answers with the list\n * of Flings so the model can ask the user.\n */\nfunction failure(error: unknown): CallToolResult {\n if (error instanceof ServerNeededError) {\n const data = {\n status: 'needs_server',\n servers: error.servers.map(s => ({\n url: s.url,\n host: serverLabel(s.url),\n instance: s.instance?.name ?? null,\n signedIn: s.signedIn,\n email: s.email ?? null,\n current: s.current,\n })),\n }\n return textResult(`${error.message}\\n\\n${JSON.stringify(data, null, 2)}`)\n }\n return { isError: true, content: [{ type: 'text', text: describeError(error) }] }\n}\n\nfunction describeError(error: unknown): string {\n if (error instanceof NoServerError) return NO_SERVER_HINT\n if (error instanceof CliError && error.exitCode === EXIT_NOT_LOGGED_IN) return LOGIN_HINT\n if (error instanceof CliApiError && error.status === 401) return LOGIN_HINT\n if (error instanceof CliError)\n return error.hint ? `${error.message}\\n${error.hint}` : error.message\n return error instanceof Error ? error.message : String(error)\n}\n\nexport async function runMcpServer(deps: McpDeps = {}): Promise<void> {\n const store = deps.store ?? createConfigStore()\n const fetchImpl: FetchLike = deps.fetch ?? ((i, init) => fetch(i, init))\n // Remember the Fling the extension came from, and read the known ones for the descriptions;\n // never fail to start over either.\n await addServerOnStart(store, serverToAdd(), fetchImpl).catch(() => {})\n const servers =\n deps.servers ?? (await knownServers(store, fetchImpl, deps.server).catch(() => []))\n const server = createMcpServer({ ...deps, store, servers })\n await server.connect(new StdioServerTransport())\n}\n", "/**\n * Find what the user means by a path. An existing path (absolute, `~/\u2026` or relative to the working\n * directory) is used as is. Anything else \u2014 a bare file name (\"Pitch Deck.html\"), a path that only\n * exists inside Claude's sandbox (`/mnt/user-data/outputs/x.html`, `/sessions/\u2026/outputs/x.html`) \u2014\n * is looked up by name, newest first, in the places people and Claude Desktop put files:\n *\n * the working directory (unless it is `/` or home), Downloads (FLING_DOWNLOADS_DIR or the\n * platform default; XDG user-dirs on Linux), Desktop, ~/Documents/Claude, ~/Claude, and the\n * `outputs` folders of Claude Desktop / Cowork sessions\n * (macOS `~/Library/Application Support/Claude/local-agent-mode-sessions`,\n * Windows `%APPDATA%\\Claude\\local-agent-mode-sessions`).\n *\n * The walk is bounded (depth per root, an entry budget and a time budget) and skips dot-folders,\n * node_modules and __MACOSX. Pure apart from the injectable filesystem: tests pass a fake one and\n * a `platform` to exercise Windows paths on any OS.\n */\nimport { lstat, readdir, readFile, realpath, stat } from 'node:fs/promises'\nimport { posix, win32 } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { CliError } from './errors.ts'\n\nexport const DOWNLOADS_DIR_ENV = 'FLING_DOWNLOADS_DIR'\n\nexport interface FsStat {\n isFile: boolean\n isDirectory: boolean\n mtimeMs: number\n size: number\n}\n\nexport interface FsEntry {\n name: string\n isFile: boolean\n isDirectory: boolean\n}\n\n/** The filesystem calls the search needs; every method swallows errors (null / []). */\nexport interface LocateFs {\n stat(path: string): Promise<FsStat | null>\n /** Directory entries; symlinked directories are reported as neither file nor directory. */\n readdir(path: string): Promise<FsEntry[]>\n readText(path: string): Promise<string | null>\n /** Resolve symlinks (so overlapping roots dedupe); null when missing. Optional. */\n realpath?(path: string): Promise<string | null>\n}\n\nexport interface LocateOptions {\n cwd: string\n home: string\n platform: NodeJS.Platform\n env: Record<string, string | undefined>\n /** Overrides the Downloads folder (else FLING_DOWNLOADS_DIR, else the platform default). */\n downloadsDir?: string\n fs?: LocateFs\n /** Give up walking after this long (default 4 s). */\n timeBudgetMs?: number\n /** Give up walking after this many directory entries (default 60 000). */\n entryBudget?: number\n now?: () => number\n}\n\nexport interface SearchRoot {\n /** Human label, e.g. \"Downloads\". */\n label: string\n path: string\n /** How many folder levels below `path` to look. */\n depth: number\n /** Claude session store: search only the `outputs` folders found below it. */\n sessions?: boolean\n}\n\nexport interface Candidate {\n path: string\n /** Label of the root it was found in. */\n foundIn: string\n kind: 'file' | 'folder'\n modified: string\n size: number\n}\n\nexport interface Resolved {\n path: string\n /** `\"path\"` when the input existed as given, else the label of the root it was found in. */\n foundIn: string\n isDirectory: boolean\n /** Other matches, newest first (only when found by searching). */\n alternatives: Candidate[]\n}\n\nexport const FOUND_AS_GIVEN = 'path'\n\nconst SKIP_DIRS = new Set(['node_modules', '__MACOSX', 'Library', 'AppData', '$RECYCLE.BIN'])\nconst SESSION_SKIP_DIRS = new Set(['skills-plugin', 'rpm', 'uploads', 'memory'])\nconst SESSIONS_DEPTH = 4\nconst OUTPUTS_DEPTH = 4\n/** Sandbox / VM path prefixes Claude uses for its own files: never real paths on this computer. */\nconst SANDBOX_PATH_RE = /^\\/(mnt\\/user-data|mnt\\/data|sessions|home\\/claude|tmp\\/outputs)(\\/|$)/\n\nexport const nodeFs: LocateFs = {\n async stat(path) {\n try {\n const s = await stat(path)\n return { isFile: s.isFile(), isDirectory: s.isDirectory(), mtimeMs: s.mtimeMs, size: s.size }\n } catch {\n return null\n }\n },\n async readdir(path) {\n try {\n const entries = await readdir(path, { withFileTypes: true })\n const out: FsEntry[] = []\n for (const e of entries) {\n if (e.isSymbolicLink()) {\n // Follow links to files (a linked download), never to folders (cycles).\n const s = await stat(`${path}/${e.name}`).catch(() => null)\n out.push({ name: e.name, isFile: Boolean(s?.isFile()), isDirectory: false })\n } else out.push({ name: e.name, isFile: e.isFile(), isDirectory: e.isDirectory() })\n }\n return out\n } catch {\n return []\n }\n },\n async realpath(path) {\n return realpath(path).catch(() => null)\n },\n async readText(path) {\n try {\n if (!(await lstat(path)).isFile()) return null\n return await readFile(path, 'utf8')\n } catch {\n return null\n }\n },\n}\n\nconst pathFor = (platform: NodeJS.Platform) => (platform === 'win32' ? win32 : posix)\n\nconst usable = (value: string | undefined): value is string =>\n Boolean(value?.trim()) && !value?.trim().startsWith('${')\n\n/** `XDG_<KEY>_DIR` from the env or `~/.config/user-dirs.dirs` (Linux). */\nasync function xdgUserDir(\n key: 'DOWNLOAD' | 'DESKTOP' | 'DOCUMENTS',\n opts: LocateOptions,\n fs: LocateFs\n): Promise<string | undefined> {\n const fromEnv = opts.env[`XDG_${key}_DIR`]\n if (usable(fromEnv)) return fromEnv\n const configHome = opts.env.XDG_CONFIG_HOME || posix.join(opts.home, '.config')\n const text = await fs.readText(posix.join(configHome, 'user-dirs.dirs'))\n const match = text?.match(new RegExp(`^XDG_${key}_DIR=\"([^\"]*)\"`, 'm'))\n if (!match?.[1]) return undefined\n return match[1].replace(/^\\$HOME(?=\\/|$)/, opts.home)\n}\n\n/** The folders searched, in order. Folders that do not exist are dropped by the walk. */\nexport async function searchRoots(opts: LocateOptions): Promise<SearchRoot[]> {\n const fs = opts.fs ?? nodeFs\n const p = pathFor(opts.platform)\n const { home, env, platform } = opts\n const userHome = platform === 'win32' && usable(env.USERPROFILE) ? env.USERPROFILE : home\n const roots: SearchRoot[] = []\n const add = (label: string, path: string | undefined, depth: number, sessions = false) => {\n if (!path) return\n const norm = p.resolve(path)\n if (roots.some(r => r.path === norm)) return\n roots.push({ label, path: norm, depth, ...(sessions ? { sessions } : {}) })\n }\n\n const cwd = p.resolve(opts.cwd)\n if (cwd !== p.parse(cwd).root && cwd !== p.resolve(userHome)) add('current folder', cwd, 4)\n\n const configured = usable(opts.downloadsDir)\n ? opts.downloadsDir\n : usable(env[DOWNLOADS_DIR_ENV])\n ? env[DOWNLOADS_DIR_ENV]\n : undefined\n const defaultDownloads =\n platform === 'linux'\n ? ((await xdgUserDir('DOWNLOAD', opts, fs)) ?? p.join(home, 'Downloads'))\n : p.join(userHome, 'Downloads')\n add('Downloads', configured ? expandHome(configured, home, platform) : defaultDownloads, 3)\n add('Downloads', defaultDownloads, 3)\n\n const desktop =\n platform === 'linux'\n ? ((await xdgUserDir('DESKTOP', opts, fs)) ?? p.join(home, 'Desktop'))\n : p.join(userHome, 'Desktop')\n add('Desktop', desktop, 3)\n if (platform === 'win32' && usable(env.OneDrive))\n add('Desktop', p.join(env.OneDrive, 'Desktop'), 3)\n\n const documents =\n platform === 'linux'\n ? ((await xdgUserDir('DOCUMENTS', opts, fs)) ?? p.join(home, 'Documents'))\n : p.join(userHome, 'Documents')\n add('Documents/Claude', p.join(documents, 'Claude'), 4)\n add('~/Claude', p.join(userHome, 'Claude'), 4)\n\n const claudeConfig =\n platform === 'darwin'\n ? p.join(home, 'Library', 'Application Support', 'Claude')\n : platform === 'win32'\n ? p.join(\n usable(env.APPDATA) ? env.APPDATA : p.join(userHome, 'AppData', 'Roaming'),\n 'Claude'\n )\n : p.join(env.XDG_CONFIG_HOME || p.join(home, '.config'), 'Claude')\n add(\n 'Claude Desktop outputs',\n p.join(claudeConfig, 'local-agent-mode-sessions'),\n SESSIONS_DEPTH,\n true\n )\n\n // Same folder through a symlink (macOS /var \u2192 /private/var\u2026): keep the first.\n if (!fs.realpath) return roots\n const real: SearchRoot[] = []\n for (const root of roots) {\n const path = (await fs.realpath(root.path)) ?? root.path\n if (!real.some(r => r.path === path)) real.push({ ...root, path })\n }\n return real\n}\n\nexport function expandHome(input: string, home: string, platform: NodeJS.Platform): string {\n if (input === '~') return home\n if (input.startsWith('~/') || (platform === 'win32' && input.startsWith('~\\\\')))\n return pathFor(platform).join(home, input.slice(2))\n return input\n}\n\n// ---- walking -------------------------------------------------------------------------------\n\ninterface Visit {\n root: SearchRoot\n path: string\n entry: FsEntry\n /** Entries of the folder `entry` is in (to spot index.html next to it). */\n siblings: FsEntry[]\n}\n\n/**\n * Walk the roots breadth-first within their depth and the budgets, calling `visit` for every entry.\n * `visit` returning `'skip'` for a folder stops the walk descending into it.\n */\nasync function walk(\n roots: SearchRoot[],\n opts: LocateOptions,\n visit: (v: Visit) => Promise<undefined | 'skip'>\n): Promise<{ complete: boolean }> {\n const fs = opts.fs ?? nodeFs\n const p = pathFor(opts.platform)\n const now = opts.now ?? Date.now\n const deadline = now() + (opts.timeBudgetMs ?? 4000)\n let budget = opts.entryBudget ?? 60_000\n const skip = (name: string) => name.startsWith('.') || SKIP_DIRS.has(name)\n\n // Expand the session store into its `outputs` folders.\n const expanded: SearchRoot[] = []\n for (const root of roots) {\n if (!root.sessions) {\n expanded.push(root)\n continue\n }\n let level = [root.path]\n for (let depth = 0; depth < root.depth && level.length; depth++) {\n const next: string[] = []\n for (const dir of level) {\n for (const e of await fs.readdir(dir)) {\n if (!e.isDirectory || skip(e.name) || SESSION_SKIP_DIRS.has(e.name)) continue\n const child = p.join(dir, e.name)\n if (e.name === 'outputs')\n expanded.push({ label: root.label, path: child, depth: OUTPUTS_DEPTH })\n else next.push(child)\n }\n }\n level = next\n }\n }\n\n for (const root of expanded) {\n let level = [root.path]\n for (let depth = 0; depth <= root.depth && level.length; depth++) {\n const next: string[] = []\n for (const dir of level) {\n if (now() > deadline || budget <= 0) return { complete: false }\n const entries = await fs.readdir(dir)\n budget -= entries.length\n for (const entry of entries) {\n if (entry.name.startsWith('.')) continue\n const path = p.join(dir, entry.name)\n const result = await visit({ root, path, entry, siblings: entries })\n if (entry.isDirectory && !skip(entry.name) && result !== 'skip' && depth < root.depth)\n next.push(path)\n }\n }\n level = next\n }\n }\n return { complete: true }\n}\n\n/** Browsers save a second download of `deck.html` as `deck (1).html`. */\nfunction withoutDuplicateSuffix(name: string): string {\n return name.replace(/ \\(\\d+\\)(?=\\.[^.]+$|$)/, '')\n}\n\nfunction namesMatch(candidate: string, wanted: string): boolean {\n const a = candidate.toLowerCase()\n const b = wanted.toLowerCase()\n return a === b || withoutDuplicateSuffix(a) === withoutDuplicateSuffix(b)\n}\n\nconst splitSegments = (path: string) =>\n path.split(/[\\\\/]+/).filter(s => s !== '' && s !== '.' && s !== '~')\n\n/** How many trailing path segments of `path` equal the wanted ones (the name counts as 1). */\nfunction suffixScore(path: string, wanted: string[]): number {\n const have = splitSegments(path)\n let score = 1\n for (let i = 2; i <= Math.min(have.length, wanted.length); i++) {\n if (have[have.length - i]?.toLowerCase() !== wanted[wanted.length - i]?.toLowerCase()) break\n score++\n }\n return score\n}\n\nconst looksLikeSandboxPath = (input: string) => SANDBOX_PATH_RE.test(input.replace(/\\\\/g, '/'))\n\nfunction normaliseInput(raw: string, opts: LocateOptions): string {\n let input = raw.trim().replace(/^([\"'])(.*)\\1$/, '$2')\n if (input.startsWith('file://')) {\n try {\n input = fileURLToPath(input, { windows: opts.platform === 'win32' })\n } catch {\n input = decodeURIComponent(input.slice('file://'.length))\n }\n }\n return expandHome(input, opts.home, opts.platform)\n}\n\n/**\n * Resolve user input to a file or folder on this computer (see the module comment). Throws a\n * CliError listing where it looked when nothing matches.\n */\nexport async function resolveInput(input: string, opts: LocateOptions): Promise<Resolved> {\n const fs = opts.fs ?? nodeFs\n const p = pathFor(opts.platform)\n const given = normaliseInput(input, opts)\n if (!given) throw new CliError('No path given')\n\n const direct = p.isAbsolute(given) ? p.normalize(given) : p.resolve(opts.cwd, given)\n const directStat = await fs.stat(direct)\n if (directStat && (directStat.isFile || directStat.isDirectory)) {\n return {\n path: direct,\n foundIn: FOUND_AS_GIVEN,\n isDirectory: directStat.isDirectory,\n alternatives: [],\n }\n }\n\n const wanted = splitSegments(given)\n const name = wanted.at(-1)\n const roots = await searchRoots(opts)\n if (!name) throw notFound(input, roots)\n\n const found: (Candidate & { score: number; mtimeMs: number; isDirectory: boolean })[] = []\n const seen = new Set<string>()\n await walk(roots, opts, async ({ root, path, entry }) => {\n if (!(entry.isFile || entry.isDirectory) || !namesMatch(entry.name, name)) return\n if (seen.has(path)) return\n seen.add(path)\n const s = await fs.stat(path)\n if (!s) return\n found.push({\n path,\n foundIn: root.label,\n kind: s.isDirectory ? 'folder' : 'file',\n modified: new Date(s.mtimeMs).toISOString(),\n size: s.size,\n score: suffixScore(path, wanted),\n mtimeMs: s.mtimeMs,\n isDirectory: s.isDirectory,\n })\n return undefined\n })\n if (found.length === 0) throw notFound(input, roots)\n\n found.sort((a, b) => b.score - a.score || b.mtimeMs - a.mtimeMs)\n const strip = ({ score: _s, mtimeMs: _m, isDirectory: _d, ...c }: (typeof found)[number]) => c\n const [best, ...rest] = found as [(typeof found)[number], ...typeof found]\n return {\n path: best.path,\n foundIn: best.foundIn,\n isDirectory: best.isDirectory,\n alternatives: rest.slice(0, 5).map(strip),\n }\n}\n\nfunction notFound(input: string, roots: SearchRoot[]): CliError {\n const where = roots.map(r => `${r.label} (${r.path})`).join(', ')\n const sandbox = looksLikeSandboxPath(input)\n ? ' That looks like a path inside Claude\u2019s sandbox, which this computer cannot see: publish the content inline with fling_publish, or save/download the file to this computer first.'\n : ''\n return new CliError(`Could not find \"${input}\". Looked for it by name in: ${where}.${sandbox}`, {\n hint: 'Pass the full path, or save the file to your Downloads folder and use just its name.',\n })\n}\n\n// ---- listing -------------------------------------------------------------------------------\n\nexport interface FindFilesOptions {\n /** Case-insensitive substring of the file or folder name. */\n query?: string\n /** Max results (default 20). */\n limit?: number\n /** Only things modified in the last N days (default 14). */\n days?: number\n}\n\nconst LISTED_EXT = /\\.(html?|zip)$/i\n\n/**\n * Recent things worth flinging, newest first: .html/.htm/.zip files and folders that contain an\n * index.html (listed once, not descended into).\n */\nexport async function findFiles(\n opts: LocateOptions,\n find: FindFilesOptions = {}\n): Promise<{ files: Candidate[]; searched: SearchRoot[]; complete: boolean }> {\n const fs = opts.fs ?? nodeFs\n const p = pathFor(opts.platform)\n const now = (opts.now ?? Date.now)()\n const since = now - (find.days ?? 14) * 24 * 60 * 60 * 1000\n const query = find.query?.trim().toLowerCase()\n const roots = await searchRoots(opts)\n const found = new Map<string, Candidate & { mtimeMs: number }>()\n const rootPaths = new Set(roots.map(r => r.path))\n\n const { complete } = await walk(roots, opts, async ({ root, path, entry }) => {\n if (entry.isDirectory) {\n if (rootPaths.has(path)) return\n const index = (await fs.readdir(path)).find(e => e.isFile && /^index\\.html?$/i.test(e.name))\n if (!index) return\n const s = await fs.stat(p.join(path, index.name))\n if (s && s.mtimeMs >= since && (!query || entry.name.toLowerCase().includes(query)))\n found.set(path, {\n path,\n foundIn: root.label,\n kind: 'folder',\n modified: new Date(s.mtimeMs).toISOString(),\n size: s.size,\n mtimeMs: s.mtimeMs,\n })\n return 'skip'\n }\n if (!entry.isFile || !LISTED_EXT.test(entry.name)) return\n if (query && !entry.name.toLowerCase().includes(query)) return\n const s = await fs.stat(path)\n if (!s || s.mtimeMs < since || found.has(path)) return\n found.set(path, {\n path,\n foundIn: root.label,\n kind: 'file',\n modified: new Date(s.mtimeMs).toISOString(),\n size: s.size,\n mtimeMs: s.mtimeMs,\n })\n return undefined\n })\n\n const files = [...found.values()]\n .sort((a, b) => b.mtimeMs - a.mtimeMs)\n .slice(0, find.limit ?? 20)\n .map(({ mtimeMs: _m, ...c }) => c)\n return { files, searched: roots, complete }\n}\n", "/**\n * Which Fling a local MCP tool call goes to, and how the server describes the Flings it knows.\n *\n * The local MCP server knows every Fling the CLI remembers (`~/.fling/config.json`). A call picks\n * one with its `server` argument (an address, host or unique parent domain, matched with\n * `matchServer` against the remembered ones). Without it:\n * - with `fling mcp --server` or `FLING_URL` set, the call goes there (the server is pinned);\n * - with one remembered Fling (or none), the call goes to it, as the CLI would;\n * - with several, the call does not run: it answers with the list, so the model settles with the\n * user which Fling the conversation uses and passes it on every call. The current Fling\n * (`fling use`) is only suggested, never used silently.\n *\n * On start, the server remembers the Fling the extension was downloaded from (`FLING_ADD_SERVER`),\n * best effort, without touching an existing entry and making it current only when none is.\n * Descriptions are written at start from the Flings known then; `fling_servers` lists them live.\n */\nimport type { InstanceMetadata } from '@fling/shared'\nimport type { FetchLike } from './api.ts'\nimport {\n type CliConfig,\n type ConfigStore,\n matchServer,\n normalizeServerUrl,\n type ResolvedConfig,\n} from './config.ts'\nimport { CliError } from './errors.ts'\nimport { fetchInstance } from './instance.ts'\n\n/** A Fling the MCP server knows, as its descriptions and `fling_servers` show it. */\nexport interface KnownServer {\n url: string\n instance?: InstanceMetadata | null\n /** The CLI's current server (`fling use`): the user's usual one. */\n current: boolean\n signedIn: boolean\n email?: string\n}\n\n/** How a server is shown to the model: its host (instance names can be the same). */\nexport function serverLabel(url: string): string {\n const u = new URL(url)\n return `${u.host}${u.pathname}`.replace(/\\/+$/, '')\n}\n\n/** `fling.example.com (Example Fling; signed in as ada@example.com; current)` */\nexport function describeServer(s: KnownServer): string {\n const facts = [\n s.instance?.name,\n s.signedIn ? (s.email ? `signed in as ${s.email}` : 'signed in') : 'signed out',\n s.current ? \"current: the user's usual one\" : undefined,\n ].filter(Boolean)\n return `${serverLabel(s.url)} (${facts.join('; ')})`\n}\n\n/** The remembered servers, from a loaded config. */\nexport function knownServersOf(config: CliConfig): KnownServer[] {\n return Object.entries(config.servers).map(([url, entry]) => ({\n url,\n instance: entry.instance,\n current: url === config.current,\n signedIn: Boolean(entry.apiKey),\n ...(entry.apiKey && entry.user?.email ? { email: entry.user.email } : {}),\n }))\n}\n\nconst listing = (servers: readonly KnownServer[]) =>\n servers.map(s => `- ${describeServer(s)}`).join('\\n')\n\n/** A call that needs `server`: answered (not failed) with the list, so the model can ask. */\nexport class ServerNeededError extends CliError {\n readonly servers: KnownServer[]\n constructor(servers: KnownServer[], tool: string) {\n super(\n `Not run: several Flings are set up on this computer, so ${tool} needs \\`server\\`.\\n${listing(servers)}\\n` +\n 'Unless the conversation already says which Fling to use, ask the user (suggest their usual one, marked ' +\n `current). Then call ${tool} again with \\`server\\` (e.g. \"${serverLabel(servers[0]?.url ?? 'https://fling.example.com')}\"), ` +\n 'and pass the same `server` on every call for the rest of the conversation.'\n )\n this.name = 'ServerNeededError'\n this.servers = servers\n }\n}\n\n/**\n * The remembered server `input` names. Throws a CliError listing the remembered servers when it\n * names none of them, or several.\n */\nexport function rememberedServer(config: CliConfig, input: string): string {\n const servers = knownServersOf(config)\n const known = servers.length\n ? `The Flings set up on this computer:\\n${listing(servers)}`\n : 'No Fling is set up on this computer yet.'\n let match: { url: string; remembered: boolean }\n try {\n match = matchServer(Object.keys(config.servers), input, { loose: true })\n } catch (error) {\n throw new CliError((error as Error).message, { hint: known })\n }\n if (!match.remembered)\n throw new CliError(`\"${input}\" is not a Fling set up on this computer`, {\n hint: `${known}\\nTo add one, call fling_login with its address as \\`server\\`.`,\n })\n return match.url\n}\n\n/** Whether `fling mcp --server` or `FLING_URL` pins the server calls go to by default. */\nexport const isPinned = (config: Pick<ResolvedConfig, 'serverUrlSource'>) =>\n config.serverUrlSource === 'flag' || config.serverUrlSource === 'env'\n\n/** Settle `promise` within `ms`, else `fallback`; never throws. */\nasync function within<T>(promise: Promise<T>, ms: number, fallback: T): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined\n const late = new Promise<T>(r => {\n timer = setTimeout(() => r(fallback), ms)\n })\n try {\n return await Promise.race([promise.catch(() => fallback), late])\n } finally {\n clearTimeout(timer)\n }\n}\n\n/** How long start-up waits for a server's `/.well-known/fling`. */\nconst START_FETCH_MS = 5_000\n\n/**\n * Remember `address` (a Fling the extension was downloaded from) if it is new: its metadata is\n * fetched best effort, and it becomes current only when no server is. A known one is left as is.\n */\nexport async function addServerOnStart(\n store: ConfigStore,\n address: string | undefined,\n fetch: FetchLike\n): Promise<void> {\n if (!address) return\n let url: string\n try {\n url = normalizeServerUrl(address)\n } catch {\n return\n }\n if (url in (await store.load()).servers) return\n const instance = await within(fetchInstance(url, fetch), START_FETCH_MS, null)\n await store.putServer(url, instance ? { instance } : {})\n}\n\n/**\n * The Flings the descriptions name, read at start: the pinned one alone, else every remembered\n * one. Missing metadata is fetched best effort (and stored).\n */\nexport async function knownServers(\n store: ConfigStore,\n fetch: FetchLike,\n pin?: string\n): Promise<KnownServer[]> {\n const resolved = await store.resolve({ serverUrl: pin })\n const config = await store.load()\n const all = knownServersOf(config)\n const servers = isPinned(resolved)\n ? resolved.serverUrl\n ? [\n all.find(s => s.url === resolved.serverUrl) ?? {\n url: resolved.serverUrl,\n current: false,\n signedIn: Boolean(resolved.apiKey),\n },\n ]\n : []\n : all\n return Promise.all(\n servers.map(async s => {\n if (s.instance) return s\n const instance = await within(fetchInstance(s.url, fetch), START_FETCH_MS, null)\n if (instance && s.url in config.servers)\n await store.putServer(s.url, { instance }, { makeCurrent: false }).catch(() => {})\n return { ...s, instance }\n })\n )\n}\n\n// --- wording ------------------------------------------------------------------------------------\n\n/** The `server` argument's description. */\nexport function serverArgDescription(servers: readonly KnownServer[]): string {\n const [only] = servers\n if (servers.length > 1)\n return (\n `Which Fling: ${servers.map(s => serverLabel(s.url)).join(', ')} (an address, host or unique part of it). ` +\n 'Required while several Flings are set up: the one settled on for this conversation, on every call'\n )\n return `Which Fling, by address or host (any set up on this computer; see fling_servers). Omit it to use ${only ? serverLabel(only.url) : 'the one this computer is signed in to'}`\n}\n\n/** Appended to a server tool's description when several Flings are known. */\nexport function serverToolNote(servers: readonly KnownServer[]): string {\n if (servers.length < 2) return ''\n return ` Pass \\`server\\`: several Flings are set up (${servers.map(s => serverLabel(s.url)).join(', ')}), and every call names the one settled on for this conversation.`\n}\n\n/** The instructions' paragraph on choosing a Fling, when several are known. */\nexport function serversInstructions(servers: readonly KnownServer[]): string | undefined {\n if (servers.length < 2) return undefined\n const usual = servers.find(s => s.current)\n return [\n `Several Flings are set up on this computer:\\n${listing(servers)}`,\n \"Settle which one this conversation uses before anything else: from the user's words \" +\n `(\"on ${serverLabel(servers[0]?.url ?? '')}\", \"on the ${servers[0]?.instance?.name ?? 'other'} one\") or, if they don't say, by asking them` +\n `${usual ? ` (suggest ${serverLabel(usual.url)}, their usual one)` : ''}. ` +\n 'Say which Fling you are using, and pass it as `server` on every call for the rest of the conversation; ' +\n 'switch only when the user asks. Calls without `server` do not run while several Flings are set up. ' +\n 'Each Fling has its own sites, sign-in and sites domain: give the user the links that come back, which name the Fling.',\n 'This list was read when this server started and may have changed: call fling_servers to see the Flings ' +\n 'set up now. To sign in to a Fling, or add one, call fling_login with its address as `server`.',\n ].join('\\n\\n')\n}\n", "/**\n * What a bare `fling \u2026` means, decided before commander parses it:\n *\n * fling \u2192 help\n * fling ./dist \u2026 \u2192 `fling deploy ./dist \u2026` when the first argument exists on disk\n * fling ls \u2026 \u2192 the command\n * fling nonsense \u2192 \"unknown command or path\" + help\n *\n * A path wins over a command of the same name (a folder called `ls` deploys); `fling deploy ls`\n * is always explicit. `-h`/`--help`/`-V`/`--version` pass straight through.\n */\nimport { stat } from 'node:fs/promises'\nimport { resolve } from 'node:path'\nimport type { Command } from 'commander'\n\nexport type Route =\n | { kind: 'help' }\n | { kind: 'run'; args: string[] }\n | { kind: 'unknown'; arg: string }\n\nexport interface RouteOptions {\n /** Command names and aliases (plus `help`). */\n commands: ReadonlySet<string>\n /** Flags (`-n`, `--name`\u2026) that take a value, so it isn't mistaken for the first argument. */\n valueFlags: ReadonlySet<string>\n exists?: (path: string) => Promise<boolean>\n}\n\nconst PASS_THROUGH = new Set(['-h', '--help', '-V', '--version'])\n\nconst pathExists = (path: string) =>\n stat(resolve(path)).then(\n () => true,\n () => false\n )\n\nexport async function routeArgs(args: readonly string[], opts: RouteOptions): Promise<Route> {\n const exists = opts.exists ?? pathExists\n let first: string | undefined\n for (let i = 0; i < args.length; i++) {\n const arg = args[i] as string\n if (arg === '--') {\n first = args[i + 1]\n break\n }\n if (arg.startsWith('-')) {\n if (PASS_THROUGH.has(arg)) return { kind: 'run', args: [...args] }\n if (opts.valueFlags.has(arg)) i++\n continue\n }\n first = arg\n break\n }\n if (first === undefined) return { kind: 'help' }\n if (await exists(first)) return { kind: 'run', args: ['deploy', ...args] }\n if (opts.commands.has(first)) return { kind: 'run', args: [...args] }\n return { kind: 'unknown', arg: first }\n}\n\n/** The names, aliases and value-taking flags of `program` and its commands, for `routeArgs`. */\nexport function routeOptionsFor(program: Command): RouteOptions {\n const commands = new Set(['help'])\n const valueFlags = new Set<string>()\n const addFlags = (command: Command) => {\n for (const option of command.options)\n if (option.required || option.optional)\n for (const flag of [option.short, option.long]) if (flag) valueFlags.add(flag)\n }\n addFlags(program)\n for (const command of program.commands) {\n commands.add(command.name())\n for (const alias of command.aliases()) commands.add(alias)\n addFlags(command)\n }\n return { commands, valueFlags }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["z", "emails", "groups", "privateAudience", "share", "z", "path", "text", "path", "z", "z", "z", "z", "z", "path", "z", "z", "groups", "members", "z", "z", "z", "z", "path", "path", "siteName", "groups", "z", "z", "reviewPage", "n", "resolve", "siteUrl", "z", "z", "z", "z", "path", "hash", "chalk", "chalk", "path", "text", "z", "z", "fetch", "resolve", "escapeHtml", "text", "chalk", "chalk", "text", "chalk", "chalk", "chalk", "text", "z", "ShareResponseSchema", "z", "sitePath", "entry", "chalk", "chalk", "path", "chalk", "text", "stat", "resolve", "chalk", "readFile", "readFile", "realpath", "stat", "join", "relative", "sep", "ignore", "readFile", "join", "resolve", "text", "path", "hash", "realpath", "stat", "sep", "walk", "join", "relative", "readFile", "siteName", "ignore", "homedir", "relative", "sep", "homedir", "sep", "relative", "siteName", "defaultSleep", "path", "readFile", "mkdir", "readFile", "stat", "writeFile", "basename", "join", "resolve", "sep", "path", "basename", "join", "stat", "readFile", "writeFile", "resolve", "sep", "mkdir", "escapeHtml", "path", "resolve", "stat", "chalk", "describe", "check", "chalk", "members", "groups", "chalk", "emails", "chalk", "execFile", "mkdtemp", "writeFile", "homedir", "tmpdir", "join", "resolve", "execFile", "path", "join", "homedir", "fetch", "mkdtemp", "tmpdir", "writeFile", "chalk", "chalk", "chalk", "access", "mkdir", "mkdtemp", "rm", "writeFile", "tmpdir", "basename", "dirname", "join", "z", "readdir", "readFile", "realpath", "stat", "path", "stat", "readdir", "realpath", "readFile", "fromEnv", "text", "s", "tool", "fetch", "mcpTools", "z", "server", "tool", "t", "listing", "listHtml", "spa", "basename", "mkdtemp", "join", "tmpdir", "rm", "check", "config", "target", "sites", "access", "groups", "reviewPage", "text", "path", "mkdir", "dirname", "writeFile", "stat", "resolve", "path", "program", "chalk", "text", "path", "emails"]
|
|
7
|
-
}
|