@nearform/fling 0.0.0-stage → 0.1.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.
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/cli.ts", "../src/commands/auth.ts", "../src/auth.ts", "../../../packages/shared/src/api.ts", "../../../packages/shared/src/manifest.ts", "../../../packages/shared/src/limits.ts", "../../../packages/shared/src/hosts.ts", "../../../packages/shared/src/kvs.ts", "../../../packages/shared/src/listing.ts", "../../../packages/shared/src/mcp-tools.ts", "../../../packages/shared/src/ready.ts", "../src/errors.ts", "../package.json", "../src/package-info.ts", "../src/api.ts", "../src/config.ts", "../src/context.ts", "../src/ready.ts", "../src/utils/logger.ts", "../src/utils/output.ts", "../src/sites.ts", "../src/commands/deploy.ts", "../src/deploy.ts", "../src/manifest.ts", "../src/naming.ts", "../src/inputs.ts", "../src/locate.ts", "../src/commands/sites.ts", "../src/mcp.ts"],
4
+ "sourcesContent": ["/**\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. The default command deploys a folder.\n */\nimport { Command } from 'commander'\nimport { runLogin, runLogout, runWhoami } from './commands/auth.ts'\nimport { runDeploy } from './commands/deploy.ts'\nimport {\n runArchive,\n runFiles,\n runInfo,\n runList,\n runRemove,\n runRollback,\n runShare,\n runVersions,\n runVisibility,\n} from './commands/sites.ts'\nimport { DEFAULT_SERVER_URL, 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 { 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 URL (default: $${ENV.url} or config, else ${DEFAULT_SERVER_URL})`\n )\n .option('--json', 'print JSON instead of human output', false)\n .showHelpAfterError()\n .addHelpText(\n 'after',\n `\nExamples:\n $ ${BIN_NAME} login\n $ ${BIN_NAME} ./dist --name my-app deploy \u2192 https://my-app.fling.labs.nearform.com\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; found in Downloads if it is not here\n $ ${BIN_NAME} site.zip a zip of a site\n $ ${BIN_NAME} share my-app public link for people outside Nearform\n\nExit 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 = (error as { code?: unknown }).code\n process.stdout.write(\n `${formatJson({ error: { message, exitCode: exitCodeFor(error), ...(typeof code === 'string' ? { code } : {}) } })}\\n`\n )\n }\n}\n\n// ---- deploy (default) ----------------------------------------------------------------------\n\nprogram\n .command('deploy [path]', { isDefault: true })\n .description(\n 'deploy a folder (default: .), a single .html file, a .zip or any file \u2014 the default command, so `fling ./dist` works. ' +\n 'A path that does not exist is looked up by name in Downloads, Desktop and Claude output folders'\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('--public', 'make the site public (default: Nearform sign-in required)')\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// ---- auth ----------------------------------------------------------------------------------\n\nprogram\n .command('login')\n .description('sign in through the browser and store an API key')\n .action(action(ctx => runLogin(ctx)))\nprogram\n .command('logout')\n .description('remove the stored API key')\n .action(action(ctx => runLogout(ctx)))\nprogram\n .command('whoami')\n .description('show the signed-in user')\n .action(action(ctx => runWhoami(ctx)))\n\n// ---- sites ---------------------------------------------------------------------------------\n\nprogram\n .command('ls')\n .alias('list')\n .description('list your sites')\n .option('--archived', 'list archived sites')\n .action(action((ctx, opts: { archived?: boolean }) => runList(ctx, opts)))\nprogram\n .command('info <name>')\n .description('show a site')\n .action(action((ctx, name: string) => runInfo(ctx, name)))\nprogram\n .command('versions <name>')\n .description(\"list a site's versions (* = live)\")\n .action(action((ctx, name: string) => runVersions(ctx, name)))\nprogram\n .command('files <name> [versionId]')\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 .description('serve an earlier version again')\n .action(action((ctx, name: string, versionId: string) => runRollback(ctx, name, versionId)))\nprogram\n .command('share <name>')\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 .description('private (Nearform sign-in) or public (anyone)')\n .action(action((ctx, name: string, visibility: string) => runVisibility(ctx, name, visibility)))\nprogram\n .command('archive <name>')\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 .description('bring an archived site back')\n .action(action((ctx, name: string) => runArchive(ctx, name, true)))\nprogram\n .command('rm <name>')\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// ---- agents --------------------------------------------------------------------------------\n\nprogram\n .command('mcp')\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\nprogram.parseAsync(process.argv)\n", "/** `fling login | logout | whoami`. */\nimport chalk from 'chalk'\nimport { loginFlow } from '../auth.ts'\nimport { redactKey } from '../config.ts'\nimport { type CommandContext, requireClient } from '../context.ts'\nimport { discoverSitesBase, sitesPattern, whoami } from '../sites.ts'\n\nexport async function runLogin(ctx: CommandContext): Promise<void> {\n const result = await loginFlow({\n serverUrl: ctx.config.serverUrl,\n store: ctx.store,\n log: ctx.log,\n open: ctx.open,\n fetch: ctx.fetch,\n })\n if (ctx.json) ctx.out.data(result, () => '')\n}\n\nexport async function runLogout(ctx: CommandContext): Promise<void> {\n const config = await ctx.store.load()\n if (!config.apiKey) {\n ctx.log.info('Not logged in \u2014 nothing to do')\n return\n }\n await ctx.store.clearCredentials()\n ctx.log.success('Logged out; API key removed from this machine')\n ctx.log.hint(`Revoke it on the server under API keys at ${ctx.config.serverUrl}`)\n}\n\nexport async function runWhoami(ctx: CommandContext): Promise<void> {\n const client = requireClient(ctx)\n const me = await whoami(client)\n const base = ctx.json ? null : await discoverSitesBase(client)\n ctx.out.data(\n {\n ...me,\n serverUrl: ctx.config.serverUrl,\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(base)} ${chalk.dim('(names are first come, first served)')}`,\n `${chalk.bold('Server:')} ${ctx.config.serverUrl}`,\n `${chalk.bold('API key:')} ${redactKey(ctx.config.apiKey)} ${chalk.dim(`(from ${ctx.config.apiKeySource})`)}`,\n ].join('\\n')\n )\n}\n", "/**\n * Login handoff. 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 Google 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 writes the config. 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 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 { 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}\n\nexport interface LoginResult {\n serverUrl: string\n keyPrefix: string\n user: Me\n}\n\nexport async function loginFlow(options: LoginOptions): Promise<LoginResult> {\n const { serverUrl, store, log } = options\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 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.update({\n serverUrl,\n apiKey: key,\n user: { email: user.email, name: user.name, userSlug: user.userSlug },\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 }\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", "import { z } from 'zod'\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})\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 createdAt: z.string(),\n updatedAt: z.string(),\n})\nexport type Site = z.infer<typeof SiteSchema>\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 = SiteSchema.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 * 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/** PATCH /api/sites/:name { visibility?, spa? } */\nexport const UpdateSiteRequestSchema = z.object({\n visibility: VisibilitySchema.optional(),\n spa: z.boolean().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", "import { z } from 'zod'\nimport { MAX_DEPLOY_BYTES, MAX_FILE_BYTES, MAX_FILES, MAX_PATH_LENGTH } from './limits.ts'\n\n/** A site-relative POSIX path: no leading slash, no `.`/`..` segments, no backslashes. */\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 !== '.' && seg !== '..')\n}\n\nexport const ManifestFileSchema = z.object({\n path: z.string().refine(isValidSitePath, 'invalid path'),\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", "// 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 const SITE_NAME_MAX = 50\nexport const USER_SLUG_MAX = 20\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 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 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 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 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\nexport function siteUrl(label: string, sitesDomain: string, protocol = 'https:'): string {\n return `${protocol}//${label}.${sitesDomain}/`\n}\n", "import { z } from 'zod'\n\n// CloudFront KeyValueStore contract between the API (writer) and\n// edge/site-router.js (reader). Values must stay under 1 KB.\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\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})\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\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", "// \"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 => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;', \"'\": '&#39;' })[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(/&amp;/g, '&')\n .replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>')\n .replace(/&quot;/g, '\"')\n .replace(/&#39;/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 */\nimport { z } from 'zod'\nimport type { VersionFiles } from './api.ts'\nimport { SITE_NAME_MAX } from './hosts.ts'\nimport { MAX_FILES } from './limits.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// --- shared wording -----------------------------------------------------------------------------\n\nconst 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 https://<name>.fling.labs.nearform.com.'\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 VISIBILITY =\n 'Sites are private by default (only signed-in Nearformers can open them); pass `public: true` only if the ' +\n 'user asks for a public site. Share links (fling_share) are public to anyone who has them.'\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\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\".'\n )\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\nconst isPublic = z\n .boolean()\n .optional()\n .describe(\n 'true \u2192 anyone can view; false \u2192 Nearformers only. Omit to keep the current setting (new sites are private)'\n )\n\n// --- tools --------------------------------------------------------------------------------------\n\nexport const mcpTools = {\n whoami: tool({\n name: 'fling_whoami',\n title: 'Who am I',\n description: 'Show the signed-in Nearform user that Fling 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: \"List the user's Fling sites with URL, visibility and share link.\",\n inputSchema: {\n archived: z.boolean().optional().describe('List archived sites instead of live ones'),\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} ` +\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}`,\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 outside Nearform). `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 (signed-in Nearformers only) or public (anyone).',\n inputSchema: { name: siteName, visibility: z.enum(['private', 'public']) },\n annotations: { idempotentHint: true, openWorldHint: true },\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 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/** Sent at `initialize` by the remote server. */\nexport const MCP_REMOTE_INSTRUCTIONS = [\n 'Fling publishes static sites (HTML/CSS/JS, images, documents) for Nearform staff at https://<name>.fling.labs.nearform.com.',\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 (Nearformers only) by default. Only make one public if asked; to show a private site to someone ' +\n 'outside Nearform, 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 `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 'Always give the user the URL that comes back. 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].join('\\n\\n')\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 * 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", "/**\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/** 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.1.0\",\n \"license\": \"MIT\",\n \"description\": \"Fling a folder of static files at fling.labs.nearform.com 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 ],\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 \"@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, 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 @nearform/fling@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 return new CliApiError({\n status,\n code: envelope.data.error.code,\n body,\n message: envelope.data.error.message,\n })\n }\n return new CliApiError({ status, body, message: `${method} ${path} failed with HTTP ${status}` })\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) holding the server URL, API key and the\n * signed-in user. Env overrides (for CI): `FLING_API_KEY`, `FLING_URL`, and `FLING_CONFIG_DIR` to\n * relocate the directory. `FLING_DEBUG` enables debug lines. This is the only module that reads\n * `process.env`.\n */\nimport { chmod, mkdir, readFile, stat, writeFile } from 'node:fs/promises'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport { z } from 'zod'\n\nexport const CONFIG_DIR_NAME = '.fling'\nexport const CONFIG_FILE_NAME = 'config.json'\nexport const DEFAULT_SERVER_URL = 'https://fling.labs.nearform.com'\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} as const\n\nexport const cliConfigSchema = z.object({\n serverUrl: z.string().url().optional(),\n apiKey: z.string().min(1).optional(),\n user: z\n .object({\n email: z.string().optional(),\n name: z.string().optional(),\n userSlug: z.string().optional(),\n })\n .optional(),\n})\nexport type CliConfig = z.infer<typeof cliConfigSchema>\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\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 serverUrl: string\n serverUrlSource: 'flag' | 'env' | 'config' | 'default'\n apiKey?: string\n apiKeySource: 'env' | 'config' | 'none'\n user?: CliConfig['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 update(patch: Partial<CliConfig>): Promise<CliConfig>\n /** Remove the key and user, keep `serverUrl`. */\n clearCredentials(): 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\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 {}\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 const parsed = cliConfigSchema.safeParse(json)\n if (!parsed.success) {\n throw new Error(`Config file ${file} is invalid: ${parsed.error.issues[0]?.message}`)\n }\n return parsed.data\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 await writeFile(file, `${JSON.stringify(config, null, 2)}\\n`, { mode: 0o600 })\n // `mode` only applies on creation; tighten an existing file too.\n await chmod(file, 0o600)\n }\n\n return {\n dir,\n file,\n load,\n save,\n async update(patch) {\n const next = { ...(await load()), ...patch }\n await save(next)\n return next\n },\n async clearCredentials() {\n const { serverUrl } = await load()\n await save(serverUrl ? { serverUrl } : {})\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 [serverUrl, serverUrlSource]: [string, ResolvedConfig['serverUrlSource']] =\n overrides.serverUrl\n ? [overrides.serverUrl, 'flag']\n : envUrl\n ? [envUrl, 'env']\n : config.serverUrl\n ? [config.serverUrl, 'config']\n : [DEFAULT_SERVER_URL, 'default']\n const [apiKey, apiKeySource]: [string | undefined, ResolvedConfig['apiKeySource']] = envKey\n ? [envKey, 'env']\n : config.apiKey\n ? [config.apiKey, 'config']\n : [undefined, 'none']\n return {\n serverUrl: serverUrl.replace(/\\/+$/, ''),\n serverUrlSource,\n apiKey,\n apiKeySource,\n user: config.user,\n debug: Boolean(env[ENV.debug]),\n }\n },\n }\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 * 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 { createInterface } from 'node:readline/promises'\nimport { type ApiClient, createApiClient, type FetchLike } from './api.ts'\nimport { type ConfigStore, createConfigStore, type Env, type ResolvedConfig } from './config.ts'\nimport { NotLoggedInError } from './errors.ts'\nimport type { LocateOptions } from './locate.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 /** Where file names are looked up (default: this machine; tests pass a fake). */\n locate?: LocateOptions\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\nasync function ttyConfirm(question: string): Promise<boolean> {\n const answer = await ttyPrompt(`${question} [y/N] `)\n return /^y(es)?$/i.test(answer.trim())\n}\n\nasync function ttyPrompt(question: string): Promise<string> {\n const rl = createInterface({ input: process.stdin, output: process.stderr })\n try {\n return await rl.question(question)\n } finally {\n rl.close()\n }\n}\n\nfunction ttyProgress(line: string | null): void {\n process.stderr.write(`\\r\\x1b[2K${line ?? ''}`)\n}\n\n/** An authenticated client, or `NotLoggedInError` (exit 2) when no key is configured. */\nexport function requireClient(\n ctx: Pick<CommandContext, 'config' | 'fetch' | 'binName'>\n): ApiClient {\n if (!ctx.config.apiKey) throw new NotLoggedInError(ctx.binName)\n return createApiClient({\n serverUrl: ctx.config.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'\n\nconst PREFIX = chalk.cyan('fling')\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(`${PREFIX} ${message}`),\n success: message => write(`${PREFIX} ${chalk.green('\u2713')} ${message}`),\n warn: message => write(`${PREFIX} ${chalk.yellow('!')} ${message}`),\n error: message => write(`${PREFIX} ${chalk.red('\u2717')} ${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 * 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 /** 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 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 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 Me,\n MeSchema,\n type NameCheck,\n NameCheckSchema,\n type Site,\n type SiteDetail,\n SiteDetailSchema,\n SiteListSchema,\n SiteSchema,\n siteUrl,\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:` + `fling.labs.nearform.com` (a site is `<name>.<domain>`). */\nexport interface SitesBase {\n protocol: string\n /** host, including any port */\n domain: string\n}\n\n/**\n * Inferred from the server URL: the API lives at `https://fling.labs.nearform.com` and sites at\n * `https://<name>.fling.labs.nearform.com`. Null when that can't be relied on \u2014 a server with an\n * explicit port (local dev serves sites on another port), an IP or a dotless host.\n */\nexport function sitesBaseFor(serverUrl: string): SitesBase | null {\n try {\n const url = new URL(serverUrl)\n const { hostname } = url\n if (\n url.port ||\n !hostname.includes('.') ||\n /^[\\d.]+$/.test(hostname) ||\n hostname.startsWith('[')\n )\n return null\n return { protocol: url.protocol, domain: hostname }\n } catch {\n return null\n }\n}\n\n/** From an existing site URL: `http://docs.fling.lvh.me:4102/` \u2192 `http:` + `fling.lvh.me:4102`. */\nexport function sitesBaseFromSiteUrl(siteUrl: string): SitesBase | null {\n try {\n const url = new URL(siteUrl)\n const dot = url.host.indexOf('.')\n return dot > 0 ? { protocol: url.protocol, domain: url.host.slice(dot + 1) } : null\n } catch {\n return null\n }\n}\n\n/**\n * The sites base for display: inferred from the server URL, else read off one of the user's sites\n * (the API has no endpoint for it). Null when neither works; never throws.\n */\nexport async function discoverSitesBase(client: ApiClient): Promise<SitesBase | null> {\n const inferred = sitesBaseFor(client.serverUrl)\n if (inferred) return inferred\n const sites = await listSites(client).catch(() => [])\n const first = sites[0]\n return first ? sitesBaseFromSiteUrl(first.url) : null\n}\n\nexport function siteUrlFor(name: string, base: SitesBase): string {\n return siteUrl(name, base.domain, base.protocol)\n}\n\n/** `https://<name>.fling.labs.nearform.com/` 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 } = {}\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 res.sites\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\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 * `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). When it does not\n * exist as given, it is looked up by name in Downloads, Desktop and Claude's output folders\n * (locate.ts) and the CLI says where it found it.\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 */\nimport { isValidSiteName, SITE_NAME_MAX } from '@fling/shared'\nimport chalk from 'chalk'\nimport type { ApiClient } from '../api.ts'\nimport { systemLocateOptions } from '../config.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 { FOUND_AS_GIVEN, resolveInput } from '../locate.ts'\nimport {\n buildManifest,\n hasRootIndex,\n htmlPages,\n NO_INDEX_WARNING,\n withHtmlListing,\n} from '../manifest.ts'\nimport { waitWithSpinner } from '../ready.ts'\nimport { checkName, discoverSitesBase, type SitesBase, sitesBaseFor, siteUrlFor } from '../sites.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, for the prompts (only worth a lookup when we're asking).\n const base = ask ? await discoverSitesBase(client) : sitesBaseFor(client.serverUrl)\n\n const located = await resolveInput(input ?? '.', ctx.locate ?? systemLocateOptions())\n if (located.foundIn !== FOUND_AS_GIVEN) {\n ctx.log.info(`Found in ${located.foundIn}: ${located.path}`)\n if (located.alternatives.length)\n ctx.log.hint(\n `Also found (older): ${located.alternatives.map(a => a.path).join(', ')} \u2014 pass the full path to fling another.`\n )\n }\n const prepared = await prepareInput(located.path)\n try {\n await deployPrepared(ctx, client, base, prepared, opts, ask)\n } finally {\n await prepared.cleanup()\n }\n}\n\nasync function deployPrepared(\n ctx: CommandContext,\n client: ApiClient,\n base: SitesBase | null,\n prepared: PreparedInput,\n opts: DeployCommandOptions,\n ask: boolean\n): Promise<void> {\n let local = await buildManifest(prepared.dir)\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 `${chalk.cyan('fling')} 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 ctx.out.data({ status: result.status, site: result.site, ready }, () => {\n const lines = [chalk.bold(result.url)]\n if (result.site.visibility === 'private')\n lines.push(\n chalk.dim(\n `Private: Nearform sign-in required. Share publicly with \\`${ctx.binName} share ${result.name}\\`.`\n )\n )\n return lines.join('\\n')\n })\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 * Skipped: dotfiles and dot-directories, `node_modules`, anything matched by a root `.flingignore`\n * (gitignore syntax). Symlinks are followed only when their real target is inside the folder; a\n * link pointing outside 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, sep } from 'node:path'\nimport {\n extractHtmlTitle,\n isHtmlPath,\n isValidSitePath,\n MAX_DEPLOY_BYTES,\n MAX_FILE_BYTES,\n MAX_FILES,\n MAX_PATH_LENGTH,\n type Manifest,\n renderHtmlListing,\n} from '@fling/shared'\nimport ignore, { type Ignore } from 'ignore'\nimport mime from 'mime'\nimport { CliError } from './errors.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'])\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 LocalManifest {\n root: string\n files: LocalFile[]\n totalBytes: number\n warnings: string[]\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 warnings: 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 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 if (entry.name.startsWith('.') || ALWAYS_SKIP.has(entry.name)) continue\n const rel = relDir ? `${relDir}/${entry.name}` : entry.name\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 abs = target\n isDir = info.isDirectory()\n isFile = info.isFile()\n }\n if (isDir) {\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 (ig.ignores(rel)) continue\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 (found.length === 0) {\n throw new CliError(\n `Nothing to deploy: ${dir} has no files (dotfiles 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 files = await mapLimit(found, 16, async f => ({\n ...f,\n sha256: await sha256File(f.absPath),\n contentType: contentTypeFor(f.path),\n }))\n return { root, files, totalBytes: files.reduce((n, f) => n + f.size, 0), warnings }\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 * 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/` and dotfiles, 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 * 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 { MAX_DEPLOY_BYTES, MAX_FILE_BYTES, MAX_FILES } from '@fling/shared'\nimport { unzipSync } from 'fflate'\nimport { CliError } from './errors.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 /** 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 { kind, source: path, dir: path, defaultName, cleanup: async () => {} }\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 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)\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, 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/** Extract a zip into `dest` (see the module comment). Throws on unsafe names or over-limit sizes. */\nexport async function extractZip(data: Uint8Array, dest: string): 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) return false\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 * 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", "/** Site management: ls, info, versions, rollback, share, visibility, archive/unarchive, rm. */\nimport type { Site, SiteDetail, Visibility } 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 deleteSite,\n getSite,\n listSites,\n rollback,\n setVisibility,\n share,\n versionFiles,\n} from '../sites.ts'\nimport { formatBytes, formatDate, renderTable } from '../utils/output.ts'\n\nexport async function runList(ctx: CommandContext, opts: { archived?: boolean }): 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\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\nexport async function runInfo(ctx: CommandContext, name: string): Promise<void> {\n const site = await getSite(requireClient(ctx), name)\n ctx.out.data(site, () =>\n [\n ...describeSite(site),\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 Nearform sign-in required`\n )\n ctx.out.data(site, () => site.url)\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 reuses the CLI's stored login (`~/.fling/config.json`\n * or `FLING_API_KEY`), re-read on every call so a `fling login` in another terminal takes effect\n * without a restart; `fling_login` runs the same browser sign-in itself.\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. Local extras: fling_deploy (a file,\n * zip or folder on this computer, found by name in Downloads etc. \u2014 see locate.ts / inputs.ts),\n * fling_find_files and fling_login. Never relies 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 describeVersionFiles,\n isValidSitePath,\n MAX_DEPLOY_BYTES,\n type McpToolDef,\n mcpTools,\n NOT_READY_NOTE,\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 { type ConfigStore, createConfigStore, systemLocateOptions } from './config.ts'\nimport type { OpenLike } from './context.ts'\nimport { deploy, NameTakenError, resolveSiteName } from './deploy.ts'\nimport { CliError, EXIT_NOT_LOGGED_IN } from './errors.ts'\nimport { defaultNameFor, prepareInput } from './inputs.ts'\nimport {\n FOUND_AS_GIVEN,\n findFiles,\n type LocateOptions,\n type Resolved,\n resolveInput,\n} from './locate.ts'\nimport { buildManifest, hasRootIndex, htmlPages, withHtmlListing } from './manifest.ts'\nimport { NPX_COMMAND, VERSION } from './package-info.ts'\nimport { createReadyWaiter, type ReadyWaiter } from './ready.ts'\nimport {\n archiveSite,\n checkName,\n deleteSite,\n discoverSitesBase,\n getSite,\n listSites,\n rollback,\n setVisibility,\n share,\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\nexport const LOGIN_HINT = `Not logged in to Fling. Call fling_login (it opens the browser to sign in with Nearform Google), or ask the user to run \\`${NPX_COMMAND} login\\` in a terminal (in Claude Code: \\`! ${NPX_COMMAND} login\\`), then try again.`\n\n/** Sent at `initialize`: how to use this (local) server. */\nexport const MCP_LOCAL_INSTRUCTIONS = [\n \"Fling publishes static sites (HTML/CSS/JS, images, documents) for Nearform staff at https://<name>.fling.labs.nearform.com. This server runs on the user's computer.\",\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 'Not logged in? Call fling_login, let the user finish signing in in the browser, then retry.',\n 'Sites are private (Nearformers only) by default; only make one public if asked. Use fling_share for a link people outside Nearform can open. Always give the user the URL that comes back.',\n].join('\\n\\n')\n\nconst toolDef = <S extends z.ZodRawShape>(def: McpToolDef<S>) => ({\n title: def.title,\n description: def.description,\n inputSchema: def.inputSchema,\n annotations: def.annotations,\n})\n\ntype DeployOutcome =\n | { kind: 'needs_decision'; summary: string; data: unknown }\n | { kind: 'deployed'; summary: string; data: unknown }\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\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 async function client(): Promise<ApiClient> {\n const config = await store.resolve({ serverUrl: deps.server })\n if (!config.apiKey) throw new CliError('Not logged in', { exitCode: EXIT_NOT_LOGGED_IN })\n return createApiClient({ serverUrl: config.serverUrl, apiKey: config.apiKey, fetch: fetchImpl })\n }\n\n /** Run an operation and shape its outcome as a tool result. */\n async function run(\n op: (c: ApiClient) => Promise<{ summary: string; data: unknown }>\n ): Promise<CallToolResult> {\n try {\n const { summary, data } = await op(await client())\n return { content: [{ type: 'text', text: `${summary}\\n\\n${JSON.stringify(data, null, 2)}` }] }\n } catch (error) {\n return { isError: true, content: [{ type: 'text', text: describeError(error) }] }\n }\n }\n\n /** Deploy a prepared folder: the listing decision, the deploy, and the name-taken message. */\n async function deployFolder(\n c: ApiClient,\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 }\n ): Promise<DeployOutcome> {\n let local = await buildManifest(dir)\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: c, 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.${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 return {\n kind: 'deployed',\n summary:\n `${what}: ${result.url} (${result.site.visibility})${generatedIndex ? ' \u2014 with a generated index.html listing the HTML pages' : ''}${warnings}${edge.note}` +\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 name: result.name,\n nameGenerated: !opts.nameGiven,\n versionId: result.versionId,\n site: result.site,\n generatedIndex,\n warnings: result.warnings,\n },\n }\n }\n\n const server = new McpServer(\n { name: 'fling', version: VERSION },\n { instructions: MCP_LOCAL_INSTRUCTIONS }\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 (https://<name>.fling.labs.nearform.com): \" +\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 to signed-in Nearformers unless `public` is set.',\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 },\n annotations: { destructiveHint: false, idempotentHint: true, openWorldHint: true },\n },\n args =>\n run(async c => {\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(c, 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 })\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 {\n content: [{ type: 'text', text: `${summary}\\n\\n${JSON.stringify(data, null, 2)}` }],\n }\n } catch (error) {\n return { isError: true, content: [{ type: 'text', text: describeError(error) }] }\n }\n }\n )\n\n const publishDef = mcpTools.publish\n server.registerTool(\n publishDef.name,\n {\n ...toolDef(publishDef),\n // This server has no chunked upload tools; big sites go through fling_deploy instead.\n description: 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(async c => {\n const name = resolveSiteName('.', args.name)\n const tmp = await mkdtemp(join(tmpdir(), 'fling-publish-'))\n try {\n await writeInlineFiles(tmp, args.files)\n const outcome = await deployFolder(c, tmp, {\n name,\n nameGiven: true,\n spa: args.spa,\n public: args.public,\n listHtml: args.listHtml,\n retryWith: 'fling_publish',\n })\n return outcome\n } finally {\n await rm(tmp, { recursive: true, force: true })\n }\n })\n )\n\n server.registerTool(\n 'fling_check_name',\n {\n ...toolDef(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.',\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 },\n },\n args =>\n run(async c => {\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(c, name)\n const base = check.status === 'invalid' ? null : await discoverSitesBase(c)\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 ...(source\n ? { generated: true, source: { path: source.path, foundIn: source.foundIn } }\n : {}),\n },\n }\n })\n )\n\n let pendingLogin: { url?: string; done: Promise<LoginResult> } | undefined\n\n server.registerTool(\n 'fling_login',\n {\n title: 'Sign in to Fling',\n description:\n 'Sign the user in to Fling: opens their browser at the Fling sign-in page (Nearform Google account) 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 inputSchema: {},\n annotations: { readOnlyHint: false, openWorldHint: true },\n },\n async () => {\n try {\n const config = await store.resolve({ serverUrl: deps.server })\n if (config.apiKey && !pendingLogin) {\n const me = await whoami(\n createApiClient({\n serverUrl: config.serverUrl,\n apiKey: config.apiKey,\n fetch: fetchImpl,\n })\n ).catch(() => null)\n if (me) return textResult(`Already signed in to ${config.serverUrl} as ${me.email}.`)\n }\n if (!pendingLogin) {\n const login: { url?: string; done: Promise<LoginResult> } = {\n done: Promise.resolve() as unknown as Promise<LoginResult>,\n }\n login.done = loginFlow({\n serverUrl: config.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 onAuthUrl: url => {\n login.url = url\n },\n })\n login.done\n .catch(() => {})\n .finally(() => {\n if (pendingLogin === login) pendingLogin = undefined\n })\n pendingLogin = login\n }\n const current = pendingLogin\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(`Signed in as ${waited.r.user.email} (${waited.r.serverUrl}).`)\n } catch (error) {\n return { isError: true, content: [{ type: 'text', text: describeError(error) }] }\n }\n }\n )\n\n const t = mcpTools\n server.registerTool(t.list.name, toolDef(t.list), args =>\n run(async c => {\n const sites = await listSites(c, { archived: args.archived })\n return { summary: `${sites.length} site(s)`, data: { sites } }\n })\n )\n\n server.registerTool(t.info.name, toolDef(t.info), args =>\n run(async c => {\n const site = await getSite(c, args.name)\n return { summary: `${site.name}: ${site.url}`, data: site }\n })\n )\n\n server.registerTool(t.files.name, toolDef(t.files), args =>\n run(async c => {\n const result = await versionFiles(c, 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, toolDef(t.share), args =>\n run(async c => {\n if (args.refresh && args.revoke) throw new CliError('Use either refresh or revoke, not both')\n const result = await share(c, 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(c, 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, toolDef(t.setVisibility), args =>\n run(async c => {\n const site = await setVisibility(c, args.name, args.visibility)\n return { summary: `${site.name} is now ${site.visibility}: ${site.url}`, data: site }\n })\n )\n\n server.registerTool(t.archive.name, toolDef(t.archive), args =>\n run(async c => {\n const site = await archiveSite(c, 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, toolDef(t.delete), args =>\n run(async c => {\n const result = await deleteSite(c, args.name)\n return { summary: `${args.name} deleted`, data: result }\n })\n )\n\n server.registerTool(t.rollback.name, toolDef(t.rollback), args =>\n run(async c => {\n const site = await rollback(c, 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 server.registerTool(t.whoami.name, toolDef(t.whoami), () =>\n run(async c => {\n const me = await whoami(c)\n const base = await discoverSitesBase(c)\n return {\n summary: `Signed in as ${me.email} (sites are served at ${sitesPattern(base)})`,\n data: me,\n }\n })\n )\n\n return server\n}\n\nconst textResult = (text: string): CallToolResult => ({ content: [{ type: 'text', text }] })\n\n/** Inline files (fling_publish) \u2192 a folder: `./a` and `/a` mean `a`; no traversal, no duplicates. */\nexport async function writeInlineFiles(\n dir: string,\n files: readonly { path: string; content: string; encoding?: 'utf8' | 'base64' }[]\n): Promise<void> {\n const seen = new Set<string>()\n let total = 0\n for (const f of files) {\n const path = f.path.replace(/^(\\.\\/)+/, '').replace(/^\\/+/, '')\n if (!isValidSitePath(path)) throw new CliError(`Invalid file path: \"${f.path}\"`)\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}\n\nfunction describeError(error: unknown): string {\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 server = createMcpServer(deps)\n await server.connect(new StdioServerTransport())\n}\n"],
5
+ "mappings": ";;;AAKA,SAAS,eAAe;;;ACJxB,OAAOA,YAAW;;;ACQlB,SAAS,mBAAmB;AAC5B,SAAS,oBAA4E;AACrF,SAAS,YAAY,kBAAkB;;;ACXvC,SAAS,KAAAC,UAAS;;;ACAlB,SAAS,SAAS;;;ACAX,IAAM,mBAAmB,MAAM,OAAO;AACtC,IAAM,iBAAiB,KAAK,OAAO;AACnC,IAAM,YAAY;AAClB,IAAM,kBAAkB;;;ADCxB,SAAS,gBAAgB,MAAuB;AACrD,MAAI,CAAC,QAAQ,KAAK,SAAS,gBAAiB,QAAO;AACnD,MAAI,KAAK,WAAW,GAAG,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,IAAI,EAAG,QAAO;AAC/E,SAAO,KAAK,MAAM,GAAG,EAAE,MAAM,SAAO,QAAQ,MAAM,QAAQ,OAAO,QAAQ,IAAI;AAC/E;AAEO,IAAM,qBAAqB,EAAE,OAAO;AAAA,EACzC,MAAM,EAAE,OAAO,EAAE,OAAO,iBAAiB,cAAc;AAAA,EACvD,QAAQ,EAAE,OAAO,EAAE,MAAM,gBAAgB;AAAA,EACzC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,cAAc;AAAA,EAChD,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG;AACxC,CAAC;AAGM,IAAM,iBAAiB,EAC3B,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,EAAE,IAAI,CAAC,EAAE,IAAI,SAAS,EAAE,CAAC,EACnE,OAAO,OAAK,IAAI,IAAI,EAAE,MAAM,IAAI,OAAK,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,MAAM,QAAQ,iBAAiB,EACxF,OAAO,OAAK,EAAE,MAAM,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,MAAM,CAAC,KAAK,kBAAkB,kBAAkB;;;ADfvF,IAAM,mBAAmBC,GAAE,KAAK,CAAC,WAAW,QAAQ,CAAC;AAGrD,IAAM,WAAWA,GAAE,OAAO;AAAA,EAC/B,OAAOA,GAAE,OAAO;AAAA,EAChB,MAAMA,GAAE,OAAO;AAAA,EACf,SAASA,GAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,UAAUA,GAAE,OAAO;AACrB,CAAC;AAGM,IAAM,aAAaA,GAAE,OAAO;AAAA,EACjC,MAAMA,GAAE,OAAO;AAAA,EACf,KAAKA,GAAE,OAAO;AAAA,EACd,YAAY;AAAA,EACZ,KAAKA,GAAE,QAAQ;AAAA,EACf,UAAUA,GAAE,QAAQ;AAAA,EACpB,kBAAkBA,GAAE,OAAO,EAAE,SAAS;AAAA,EACtC,UAAUA,GAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,WAAWA,GAAE,OAAO;AAAA,EACpB,WAAWA,GAAE,OAAO;AACtB,CAAC;AAGM,IAAM,gBAAgBA,GAAE,OAAO;AAAA,EACpC,IAAIA,GAAE,OAAO;AAAA,EACb,WAAWA,GAAE,OAAO;AAAA,EACpB,YAAYA,GAAE,OAAO;AAAA,EACrB,WAAWA,GAAE,OAAO;AACtB,CAAC;AAGM,IAAM,mBAAmB,WAAW,OAAO,EAAE,UAAUA,GAAE,MAAM,aAAa,EAAE,CAAC;AAG/E,IAAM,iBAAiBA,GAAE,OAAO,EAAE,OAAOA,GAAE,MAAM,UAAU,EAAE,CAAC;AAQ9D,IAAM,iBAAiBA,GAAE,OAAO;AAAA,EACrC,MAAMA,GAAE,OAAO;AAAA,EACf,MAAMA,GAAE,OAAO;AAAA,EACf,aAAaA,GAAE,OAAO;AACxB,CAAC;AAGM,IAAM,qBAAqBA,GAAE,OAAO;AAAA,EACzC,WAAWA,GAAE,OAAO;AAAA,EACpB,OAAOA,GAAE,MAAM,cAAc;AAAA,EAC7B,YAAYA,GAAE,OAAO;AAAA,EACrB,gBAAgBA,GAAE,QAAQ;AAC5B,CAAC;AAWM,IAAM,kBAAkBA,GAAE,OAAO;AAAA,EACtC,MAAMA,GAAE,OAAO;AAAA,EACf,QAAQA,GAAE,KAAK,CAAC,aAAa,SAAS,SAAS,SAAS,CAAC;AAAA,EACzD,aAAaA,GAAE,MAAMA,GAAE,OAAO,CAAC;AACjC,CAAC;AAIM,IAAM,sBAAsBA,GAAE,OAAO;AAAA,EAC1C,UAAU;AAAA,EACV,KAAKA,GAAE,QAAQ,EAAE,SAAS;AAAA,EAC1B,YAAY,iBAAiB,SAAS;AACxC,CAAC;AAGM,IAAM,eAAeA,GAAE,OAAO;AAAA,EACnC,MAAMA,GAAE,OAAO;AAAA,EACf,KAAKA,GAAE,OAAO;AAAA;AAAA,EAEd,SAASA,GAAE,OAAOA,GAAE,OAAO,GAAGA,GAAE,OAAO,CAAC;AAC1C,CAAC;AAEM,IAAM,uBAAuBA,GAAE,mBAAmB,UAAU;AAAA;AAAA,EAEjEA,GAAE,OAAO,EAAE,QAAQA,GAAE,QAAQ,WAAW,GAAG,WAAWA,GAAE,OAAO,GAAG,MAAM,WAAW,CAAC;AAAA;AAAA,EAEpFA,GAAE,OAAO,EAAE,QAAQA,GAAE,QAAQ,WAAW,GAAG,WAAWA,GAAE,OAAO,GAAG,MAAM,WAAW,CAAC;AAAA;AAAA,EAEpFA,GAAE,OAAO;AAAA,IACP,QAAQA,GAAE,QAAQ,QAAQ;AAAA,IAC1B,WAAWA,GAAE,OAAO;AAAA,IACpB,SAASA,GAAE,MAAM,YAAY;AAAA,EAC/B,CAAC;AACH,CAAC;AAIM,IAAM,yBAAyBA,GAAE,OAAO;AAAA,EAC7C,QAAQA,GAAE,QAAQ,MAAM;AAAA,EACxB,WAAWA,GAAE,OAAO;AAAA,EACpB,MAAM;AACR,CAAC;AAGM,IAAM,wBAAwBA,GAAE,OAAO,EAAE,WAAWA,GAAE,OAAO,EAAE,CAAC;AAGhE,IAAM,0BAA0BA,GAAE,OAAO;AAAA,EAC9C,YAAY,iBAAiB,SAAS;AAAA,EACtC,KAAKA,GAAE,QAAQ,EAAE,SAAS;AAC5B,CAAC;AAEM,IAAM,eAAeA,GAAE,OAAO;AAAA,EACnC,IAAIA,GAAE,OAAO;AAAA,EACb,MAAMA,GAAE,OAAO;AAAA,EACf,WAAWA,GAAE,OAAO;AAAA,EACpB,YAAYA,GAAE,OAAO,EAAE,SAAS;AAClC,CAAC;AACM,IAAM,mBAAmBA,GAAE,OAAO,EAAE,MAAMA,GAAE,MAAM,YAAY,EAAE,CAAC;AAEjE,IAAM,sBAAsBA,GAAE,OAAO;AAAA,EAC1C,OAAOA,GAAE,OAAO,EAAE,MAAMA,GAAE,OAAO,GAAG,SAASA,GAAE,OAAO,EAAE,CAAC;AAC3D,CAAC;AAIM,IAAM,sBAAsBA,GAAE,OAAO,EAAE,UAAUA,GAAE,OAAO,EAAE,CAAC;AAa7D,IAAM,mBAAmBC,GAAE,OAAO;AAAA,EACvC,IAAIA,GAAE,OAAO;AAAA,EACb,YAAYA,GAAE,OAAO;AAAA;AAAA,EAErB,YAAYA,GAAE,OAAO,EAAE,SAAS;AAAA,EAChC,WAAWA,GAAE,OAAO;AAAA,EACpB,YAAYA,GAAE,OAAO,EAAE,SAAS;AAClC,CAAC;AAEM,IAAM,uBAAuBA,GAAE,OAAO,EAAE,aAAaA,GAAE,MAAM,gBAAgB,EAAE,CAAC;AAGhF,IAAM,yBAAyBA,GAAE,OAAO;AAAA,EAC7C,YAAYA,GAAE,OAAO;AAAA,EACrB,WAAWA,GAAE,OAAO,EAAE,SAAS;AAAA;AAAA,EAE/B,cAAcA,GAAE,OAAO,EAAE,SAAS;AAAA,EAClC,cAAcA,GAAE,OAAO;AAAA;AAAA,EAEvB,UAAUA,GAAE,QAAQ;AAAA,EACpB,QAAQA,GAAE,MAAMA,GAAE,OAAO,CAAC;AAAA,EAC1B,OAAOA,GAAE,OAAO;AAClB,CAAC;AAIM,IAAM,sBAAsBA,GAAE,OAAO,EAAE,aAAaA,GAAE,OAAO,EAAE,CAAC;;;AG3KhE,IAAM,gBAAgB;AAEtB,IAAM,qBAAqB;AAG3B,IAAM,sBAAyC;AAAA,EACpD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,UAAU;AAChB,IAAM,iBAAiB,IAAI,OAAO,aAAa,kBAAkB,IAAI;AAE9D,SAAS,QAAQ,OAAe,MAAM,eAAuB;AAClE,SAAO,MACJ,UAAU,MAAM,EAChB,QAAQ,UAAU,EAAE,EACpB,YAAY,EACZ,QAAQ,eAAe,GAAG,EAC1B,QAAQ,YAAY,EAAE,EACtB,MAAM,GAAG,GAAG,EACZ,QAAQ,QAAQ,EAAE;AACvB;AAEO,SAAS,gBAAgB,MAAuB;AACrD,SACE,KAAK,UAAU,iBACf,QAAQ,KAAK,IAAI,KACjB,CAAC,KAAK,SAAS,IAAI,KACnB,CAAC,oBAAoB,SAAS,IAAI;AAEtC;AAuDO,SAAS,QAAQ,OAAe,aAAqB,WAAW,UAAkB;AACvF,SAAO,GAAG,QAAQ,KAAK,KAAK,IAAI,WAAW;AAC7C;;;AC1GA,SAAS,KAAAC,UAAS;AAYX,IAAM,qBAAqBC,GAAE,OAAO;AAAA;AAAA,EAEzC,IAAIA,GAAE,OAAO;AAAA;AAAA,EAEb,GAAGA,GAAE,OAAO;AAAA,EACZ,KAAKA,GAAE,KAAK,CAAC,WAAW,QAAQ,CAAC;AAAA;AAAA,EAEjC,KAAKA,GAAE,QAAQ;AACjB,CAAC;;;AChBM,IAAM,yBAAyB;AAStC,IAAM,aAAa,CAAC,MAClB,EAAE;AAAA,EACA;AAAA,EACA,QAAM,EAAE,KAAK,SAAS,KAAK,QAAQ,KAAK,QAAQ,KAAK,UAAU,KAAK,QAAQ,GAAG,CAAC;AAClF;AAGF,IAAM,UAAU,CAAC,SAAiB,KAAK,MAAM,GAAG,EAAE,IAAI,kBAAkB,EAAE,KAAK,GAAG;AAU3E,SAAS,WAAW,MAAuB;AAChD,SAAO,YAAY,KAAK,IAAI;AAC9B;AAGO,SAAS,iBAAiB,MAA6B;AAC5D,QAAM,QAAQ,mCAAmC,KAAK,KAAK,MAAM,GAAG,KAAK,CAAC;AAC1E,QAAM,QAAQ,QAAQ,CAAC,GACnB,QAAQ,YAAY,EAAE,EACvB,QAAQ,UAAU,GAAG,EACrB,QAAQ,SAAS,GAAG,EACpB,QAAQ,SAAS,GAAG,EACpB,QAAQ,WAAW,GAAG,EACtB,QAAQ,UAAU,GAAG,EACrB,QAAQ,QAAQ,GAAG,EACnB,KAAK;AACR,SAAO,QAAQ,QAAQ;AACzB;AAMO,SAAS,kBAAkBC,WAAkB,SAA0C;AAC5F,QAAM,QAAQ,QACX,OAAO,OAAK,WAAW,EAAE,IAAI,KAAK,EAAE,KAAK,YAAY,MAAM,YAAY,EACvE,KAAK,CAAC,GAAG,MAAO,EAAE,OAAO,EAAE,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,IAAI,CAAE;AAElE,QAAM,SAAS,oBAAI,IAA4B;AAC/C,aAAW,QAAQ,OAAO;AACxB,UAAM,QAAQ,KAAK,KAAK,YAAY,GAAG;AACvC,UAAM,SAAS,UAAU,KAAK,KAAK,KAAK,KAAK,MAAM,GAAG,KAAK;AAC3D,WAAO,IAAI,QAAQ,CAAC,GAAI,OAAO,IAAI,MAAM,KAAK,CAAC,GAAI,IAAI,CAAC;AAAA,EAC1D;AAEA,QAAM,WAAW,CAAC,GAAG,OAAO,QAAQ,CAAC,EAClC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAO,MAAM,KAAK,KAAK,MAAM,KAAK,IAAI,IAAI,IAAI,KAAK,CAAE,EAClE,IAAI,CAAC,CAAC,QAAQ,KAAK,MAAM;AACxB,UAAM,UAAU,SAAS,OAAO,WAAW,MAAM,CAAC,WAAW;AAC7D,UAAM,OAAO,MACV,IAAI,UAAQ;AACX,YAAM,OAAO,KAAK,KAAK,MAAM,KAAK,KAAK,YAAY,GAAG,IAAI,CAAC;AAC3D,YAAM,QAAQ,KAAK,QAAQ,WAAW,KAAK,KAAK,IAAI,WAAW,IAAI;AACnE,YAAM,MAAM,KAAK,QAAQ,sBAAsB,WAAW,IAAI,CAAC,YAAY;AAC3E,aAAO,gBAAgB,QAAQ,KAAK,IAAI,CAAC,KAAK,KAAK,OAAO,GAAG;AAAA,IAC/D,CAAC,EACA,KAAK,IAAI;AACZ,WAAO,GAAG,OAAO;AAAA,EAAS,IAAI;AAAA;AAAA,EAChC,CAAC,EACA,KAAK,IAAI;AAEZ,QAAM,OAAO,MAAM,SAAS,WAAW;AACvC,QAAM,QAAQ,GAAG,MAAM,MAAM,QAAQ,MAAM,WAAW,IAAI,KAAK,GAAG;AAElE,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA,kCAKyB,sBAAsB;AAAA,SAC/C,WAAWA,SAAQ,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,cA4Bf,WAAWA,SAAQ,CAAC,WAAW,KAAK;AAAA,EAChD,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAMN;;;ACrHA,SAAS,KAAAC,UAAS;AAMX,IAAM,wBAAwB,IAAI,OAAO;AAEzC,IAAM,6BAA6B,IAAI,OAAO;AAE9C,IAAM,yBAAyB,KAAK;AAmB3C,IAAM,OAAO,CAA0B,QAAuB;AAI9D,IAAM,aACJ,oBAAoB,aAAa;AAGnC,IAAM,gBACJ;AAIF,IAAM,aACJ;AAGF,IAAM,cACJ;AAGF,IAAM,WACJ;AAEF,IAAM,YACJ;AAKF,IAAM,WAAWC,GACd,QAAQ,EACR,SAAS,EACT;AAAA,EACC;AACF;AAEF,IAAM,WAAWA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,6BAA6B;AAElF,IAAM,WAAWA,GACd,OAAO,EACP,IAAI,CAAC,EACL,IAAI,IAAI,EACR;AAAA,EACC;AACF;AAEF,IAAM,WAAWA,GACd,KAAK,CAAC,QAAQ,QAAQ,CAAC,EACvB,SAAS,EACT,SAAS,gFAAgF;AAE5F,IAAM,MAAMA,GACT,QAAQ,EACR,SAAS,EACT;AAAA,EACC;AACF;AAEF,IAAM,WAAWA,GACd,QAAQ,EACR,SAAS,EACT;AAAA,EACC;AACF;AAIK,IAAM,WAAW;AAAA,EACtB,QAAQ,KAAK;AAAA,IACX,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa,CAAC;AAAA,IACd,aAAa,EAAE,cAAc,MAAM,eAAe,MAAM;AAAA,EAC1D,CAAC;AAAA,EAED,MAAM,KAAK;AAAA,IACT,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,MACX,UAAUA,GAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,0CAA0C;AAAA,IACtF;AAAA,IACA,aAAa,EAAE,cAAc,MAAM,eAAe,MAAM;AAAA,EAC1D,CAAC;AAAA,EAED,MAAM,KAAK;AAAA,IACT,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aACE;AAAA,IACF,aAAa,EAAE,MAAM,SAAS;AAAA,IAC9B,aAAa,EAAE,cAAc,MAAM,eAAe,MAAM;AAAA,EAC1D,CAAC;AAAA,EAED,OAAO,KAAK;AAAA,IACV,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aACE;AAAA,IAGF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,WAAWA,GACR,OAAO,EACP,IAAI,CAAC,EACL,IAAI,GAAG,EACP,SAAS,EACT,SAAS,iEAAiE;AAAA,IAC/E;AAAA,IACA,aAAa,EAAE,cAAc,MAAM,eAAe,MAAM;AAAA,EAC1D,CAAC;AAAA,EAED,WAAW,KAAK;AAAA,IACd,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aACE,6NAEA;AAAA,IACF,aAAa,EAAE,MAAMA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,oBAAoB,EAAE;AAAA,IAC/E,aAAa,EAAE,cAAc,MAAM,eAAe,MAAM;AAAA,EAC1D,CAAC;AAAA,EAED,SAAS,KAAK;AAAA,IACZ,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aACE,uIACgC,wBAAwB,OAAO,IAAI,sGACD,WAAW,IAAI,QAAQ,iKAGtF,aAAa,IAAI,UAAU,IAAI,UAAU,IAAI,SAAS;AAAA,IAG3D,aAAa;AAAA,MACX,MAAM;AAAA,MACN,OAAOA,GACJ;AAAA,QACCA,GAAE,OAAO;AAAA,UACP,MAAM;AAAA,UACN,SAASA,GAAE,OAAO,EAAE,SAAS,8CAA8C;AAAA,UAC3E;AAAA,QACF,CAAC;AAAA,MACH,EACC,IAAI,CAAC,EACL,IAAI,SAAS,EACb,SAAS,wBAAwB;AAAA,MACpC;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,IACF;AAAA,IACA,aAAa,EAAE,iBAAiB,OAAO,gBAAgB,MAAM,eAAe,KAAK;AAAA,EACnF,CAAC;AAAA,EAED,aAAa,KAAK;AAAA,IAChB,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aACE,oEAAoE,wBAAwB,OAAO,IAAI,+IAEzE,yBAAyB,EAAE,aAAa,WAAW,IAC9E,aAAa,IAAI,UAAU;AAAA,IAChC,aAAa,EAAE,MAAM,UAAU,KAAK,QAAQ,SAAS;AAAA,IACrD,aAAa,EAAE,iBAAiB,OAAO,eAAe,MAAM;AAAA,EAC9D,CAAC;AAAA,EAED,YAAY,KAAK;AAAA,IACf,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aACE,iIACsB,6BAA6B,OAAO,IAAI,+LAE1B,QAAQ;AAAA,IAC9C,aAAa;AAAA,MACX,UAAUA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,yBAAyB;AAAA,MACvE,MAAM;AAAA,MACN,SAASA,GACN,OAAO,EACP,IAAI,0BAA0B,EAC9B,SAAS,0DAA0D;AAAA,MACtE;AAAA,MACA,QAAQA,GACL,QAAQ,EACR,SAAS,EACT,SAAS,iEAAiE;AAAA,IAC/E;AAAA,IACA,aAAa,EAAE,iBAAiB,OAAO,eAAe,MAAM;AAAA,EAC9D,CAAC;AAAA,EAED,cAAc,KAAK;AAAA,IACjB,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aACE,kJACuC,SAAS;AAAA,IAElD,aAAa;AAAA,MACX,UAAUA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,yBAAyB;AAAA,MACvE;AAAA,IACF;AAAA,IACA,aAAa,EAAE,iBAAiB,OAAO,eAAe,KAAK;AAAA,EAC7D,CAAC;AAAA,EAED,OAAO,KAAK;AAAA,IACV,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aACE;AAAA,IAGF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,SAASA,GAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,iBAAiB;AAAA,MAC1D,QAAQA,GAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,iBAAiB;AAAA,IAC3D;AAAA,IACA,aAAa,EAAE,iBAAiB,OAAO,eAAe,KAAK;AAAA,EAC7D,CAAC;AAAA,EAED,eAAe,KAAK;AAAA,IAClB,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa,EAAE,MAAM,UAAU,YAAYA,GAAE,KAAK,CAAC,WAAW,QAAQ,CAAC,EAAE;AAAA,IACzE,aAAa,EAAE,gBAAgB,MAAM,eAAe,KAAK;AAAA,EAC3D,CAAC;AAAA,EAED,SAAS,KAAK;AAAA,IACZ,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aACE;AAAA,IAEF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,WAAWA,GAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,0BAA0B;AAAA,IACvE;AAAA,IACA,aAAa,EAAE,gBAAgB,MAAM,eAAe,MAAM;AAAA,EAC5D,CAAC;AAAA,EAED,QAAQ,KAAK;AAAA,IACX,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aACE;AAAA,IAEF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,SAASA,GAAE,QAAQ,IAAI,EAAE,SAAS,mDAAmD;AAAA,IACvF;AAAA,IACA,aAAa,EAAE,iBAAiB,MAAM,eAAe,MAAM;AAAA,EAC7D,CAAC;AAAA,EAED,UAAU,KAAK;AAAA,IACb,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,WAAWA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,qBAAqB;AAAA,IACtE;AAAA,IACA,aAAa,EAAE,gBAAgB,MAAM,eAAe,MAAM;AAAA,EAC5D,CAAC;AACH;AAGO,IAAM,0BAA0B;AAAA,EACrC;AAAA,EACA;AAAA,EAIA;AAAA,EAGA;AAAA,EAEA;AAAA,EAGA,kBAAkB,wBAAwB,OAAO,IAAI;AAAA,EAErD;AAGF,EAAE,KAAK,MAAM;AAGN,IAAM,mBAAmB;AAMzB,SAAS,qBACd,MACA,OACA,MACQ;AACR,QAAM,KAAK,CAACC,OACVA,KAAI,OACA,GAAGA,EAAC,OACJA,KAAI,OAAO,OACT,IAAIA,KAAI,MAAM,QAAQ,CAAC,CAAC,QACxB,IAAIA,KAAI,OAAO,MAAM,QAAQ,CAAC,CAAC;AACvC,QAAM,IAAI,MAAM,MAAM;AACtB,QAAM,QAAQ,KAAK,UAAU,oBAAoB;AACjD,QAAM,QAAQ;AAAA,IACZ,GAAG,IAAI,IAAI,KAAK,IAAI,MAAM,SAAS,KAAK,CAAC,QAAQ,MAAM,IAAI,KAAK,GAAG,KAAK,GAAG,MAAM,UAAU,CAAC,MACzF,KAAK,WAAW,KAAK,MAAM,qBAAgB,KAAK,GAAG,KAAK,OACxD,KAAK,UAAU,KAAK;AAAA,EACzB;AACA,MAAI,CAAC,MAAM,MAAM,KAAK,OAAK,EAAE,SAAS,YAAY,GAAG;AACnD,UAAM;AAAA,MACJ;AAAA,IACF;AAAA,EACF,WAAW,MAAM,gBAAgB;AAC/B,UAAM,KAAK,wDAAwD;AAAA,EACrE;AACA,aAAW,KAAK,MAAM,MAAM,MAAM,GAAG,gBAAgB,GAAG;AACtD,UAAM,KAAK,KAAK,EAAE,IAAI,KAAK,GAAG,EAAE,IAAI,CAAC,KAAK,EAAE,WAAW,GAAG;AAAA,EAC5D;AACA,MAAI,IAAI,iBAAkB,OAAM,KAAK,cAAS,IAAI,gBAAgB,OAAO;AACzE,SAAO,MAAM,KAAK,IAAI;AACxB;;;ACnVO,IAAM,mBAAmB;AAKzB,IAAM,iBACX;AAEK,IAAM,oBAAoB,CAAC,WAC/B,UAAU,OAAO,SAAS,OAAQ,WAAW,OAAO,WAAW;AAElE,IAAM,eAAe,CAAC,OAAe,IAAI,QAAc,CAAAC,aAAW,WAAWA,UAAS,EAAE,CAAC;AAEzF,eAAsB,mBACpB,KACA,OAAoB,CAAC,GACK;AAC1B,QAAM,YAAY,KAAK,aAAa;AACpC,QAAM,UAAU,KAAK,UAAU,CAAC,GAAW,SAAsB,MAAM,GAAG,IAAI;AAC9E,QAAM,QAAQ,KAAK,SAAS;AAC5B,QAAM,MAAM,KAAK,QAAQ,MAAM,KAAK,IAAI;AACxC,QAAM,QAAQ,IAAI;AAClB,MAAI,WAAW,KAAK,cAAc;AAClC,MAAI,YAAY;AAEhB,aAAS;AACP,UAAM,YAAY,aAAa,IAAI,IAAI;AACvC,QAAI;AACF,YAAM,MAAM,MAAM,QAAQ,KAAK;AAAA,QAC7B,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,OAAO;AAAA,QACP,QAAQ,YAAY,QAAQ,KAAK,IAAI,KAAK,KAAK,IAAI,WAAW,GAAK,CAAC,CAAC;AAAA,MACvE,CAAC;AACD,YAAM,IAAI,MAAM,OAAO,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AACvC,UAAI,kBAAkB,IAAI,MAAM,EAAG,QAAO,EAAE,OAAO,MAAM,UAAU,IAAI,IAAI,MAAM;AAAA,IACnF,QAAQ;AAAA,IAER;AACA,QAAI,CAAC,WAAW;AACd,kBAAY;AACZ,WAAK,YAAY;AAAA,IACnB;AACA,UAAM,OAAO,aAAa,IAAI,IAAI;AAClC,QAAI,QAAQ,EAAG,QAAO,EAAE,OAAO,OAAO,UAAU,IAAI,IAAI,MAAM;AAC9D,UAAM,MAAM,KAAK,IAAI,UAAU,IAAI,CAAC;AACpC,eAAW,KAAK,IAAI,WAAW,MAAM,GAAK;AAAA,EAC5C;AACF;AAOO,SAAS,SAASC,UAAiB,OAAkC;AAC1E,QAAM,OAAOA,SAAQ,SAAS,GAAG,IAAIA,WAAU,GAAGA,QAAO;AACzD,MAAI,MAAM,WAAW,KAAK,MAAM,SAAS,YAAY,EAAG,QAAO;AAC/D,QAAM,OAAO,MAAM,KAAK,OAAK,YAAY,KAAK,CAAC,CAAC,KAAK,MAAM,CAAC;AAC5D,SAAO,OAAQ,KAAgB,MAAM,GAAG,EAAE,IAAI,kBAAkB,EAAE,KAAK,GAAG;AAC5E;AAGO,SAAS,sBAAsB,KAAkD;AACtF,SAAO,IAAI,kBAAkB,OAAO,IAAI,WAAW,UAAU,IAAI,aAAa;AAChF;;;ACtFO,IAAM,aAAa;AACnB,IAAM,qBAAqB;AAC3B,IAAM,iBAAiB;AAEvB,IAAM,WAAN,cAAuB,MAAM;AAAA,EACzB;AAAA;AAAA,EAEA;AAAA,EAET,YACE,SACA,UAAiE,CAAC,GAClE;AACA,UAAM,SAAS,QAAQ,UAAU,SAAY,SAAY,EAAE,OAAO,QAAQ,MAAM,CAAC;AACjF,SAAK,OAAO;AACZ,SAAK,WAAW,QAAQ,YAAY;AACpC,SAAK,OAAO,QAAQ;AAAA,EACtB;AACF;AAEO,IAAM,mBAAN,cAA+B,SAAS;AAAA,EAC7C,YAAY,SAAiB;AAC3B,UAAM,iBAAiB;AAAA,MACrB,UAAU;AAAA,MACV,MAAM,SAAS,OAAO;AAAA,IACxB,CAAC;AACD,SAAK,OAAO;AAAA,EACd;AACF;AAGO,SAAS,YAAY,OAAwB;AAClD,SAAO,iBAAiB,WAAW,MAAM,WAAW;AACtD;;;ACvCA;AAAA,EACE,MAAQ;AAAA,EACR,SAAW;AAAA,EACX,SAAW;AAAA,EACX,aAAe;AAAA,EACf,MAAQ;AAAA,EACR,KAAO;AAAA,IACL,OAAS;AAAA,EACX;AAAA,EACA,OAAS;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,SAAW;AAAA,IACT,MAAQ;AAAA,EACV;AAAA,EACA,YAAc;AAAA,IACZ,MAAQ;AAAA,IACR,KAAO;AAAA,IACP,WAAa;AAAA,EACf;AAAA,EACA,eAAiB;AAAA,IACf,QAAU;AAAA,EACZ;AAAA,EACA,SAAW;AAAA,IACT,KAAO;AAAA,IACP,OAAS;AAAA,IACT,cAAc;AAAA,IACd,WAAa;AAAA,IACb,MAAQ;AAAA,EACV;AAAA,EACA,cAAgB;AAAA,IACd,6BAA6B;AAAA,IAC7B,OAAS;AAAA,IACT,WAAa;AAAA,IACb,QAAU;AAAA,IACV,QAAU;AAAA,IACV,MAAQ;AAAA,IACR,MAAQ;AAAA,IACR,KAAO;AAAA,EACT;AAAA,EACA,iBAAmB;AAAA,IACjB,iBAAiB;AAAA,IACjB,eAAe;AAAA,IACf,SAAW;AAAA,IACX,KAAO;AAAA,IACP,YAAc;AAAA,IACd,QAAU;AAAA,EACZ;AACF;;;AC/CO,IAAM,eAAuB,gBAAI;AACjC,IAAM,UAAkB,gBAAI;AAC5B,IAAM,WAAmB,OAAO,KAAK,gBAAI,GAAG,EAAE,CAAC,KAAK;AAEpD,IAAM,cAAc,OAAO,gBAAI,IAAI;;;ACwBnC,IAAM,cAAN,cAA0B,SAAS;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,SAOT;AACD,UAAM,QAAQ,SAAS;AAAA,MACrB,UAAU,kBAAkB,QAAQ,MAAM;AAAA,MAC1C,MAAM,QAAQ,QAAQ,YAAY,QAAQ,MAAM;AAAA,MAChD,OAAO,QAAQ;AAAA,IACjB,CAAC;AACD,SAAK,OAAO;AACZ,SAAK,SAAS,QAAQ;AACtB,SAAK,OAAO,QAAQ;AACpB,SAAK,OAAO,QAAQ;AAAA,EACtB;AACF;AAEO,SAAS,kBAAkB,QAAwB;AACxD,MAAI,WAAW,IAAK,QAAO;AAC3B,MAAI,WAAW,IAAK,QAAO;AAC3B,SAAO;AACT;AAEA,SAAS,YAAY,QAAoC;AACvD,MAAI,WAAW,IAAK,QAAO,SAAS,QAAQ;AAC5C,MAAI,WAAW,IAAK,QAAO;AAC3B,SAAO;AACT;AAOO,SAAS,SAAS,WAAmB,MAAc,OAAoC;AAC5F,QAAM,MAAM,IAAI,IAAI,GAAG,UAAU,QAAQ,QAAQ,EAAE,CAAC,GAAG,KAAK,WAAW,GAAG,IAAI,OAAO,IAAI,IAAI,EAAE,EAAE;AACjG,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,SAAS,CAAC,CAAC,GAAG;AACtD,QAAI,UAAU,UAAa,UAAU,KAAM,KAAI,aAAa,IAAI,KAAK,OAAO,KAAK,CAAC;AAAA,EACpF;AACA,SAAO,IAAI,SAAS;AACtB;AAEO,SAAS,gBAAgB,SAAsC;AACpE,QAAM,YAAY,QAAQ,UAAU,QAAQ,QAAQ,EAAE;AACtD,QAAM,YAAuB,QAAQ,UAAU,CAAC,OAAO,SAAS,MAAM,OAAO,IAAI;AACjF,QAAM,YAAY,QAAQ,aAAa;AAEvC,iBAAe,QACb,QACA,MACA,aAAgC,CAAC,GACrB;AACZ,UAAM,MAAM,SAAS,WAAW,MAAM,WAAW,KAAK;AACtD,UAAM,UAAkC;AAAA,MACtC,QAAQ;AAAA,MACR,cAAc,GAAG,QAAQ,QAAQ,OAAO;AAAA,IAC1C;AACA,QAAI,QAAQ,OAAQ,SAAQ,gBAAgB,UAAU,QAAQ,MAAM;AACpE,QAAI,WAAW,SAAS,OAAW,SAAQ,cAAc,IAAI;AAE7D,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,UAAU,KAAK;AAAA,QAC9B;AAAA,QACA;AAAA,QACA,MAAM,WAAW,SAAS,SAAY,SAAY,KAAK,UAAU,WAAW,IAAI;AAAA,QAChF,QAAQ,YAAY,QAAQ,SAAS;AAAA,MACvC,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,IAAI,YAAY;AAAA,QACpB,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,SAAS,mBAAmB,SAAS,KAAK,cAAc,KAAK,CAAC;AAAA,QAC9D,MAAM;AAAA,QACN;AAAA,MACF,CAAC;AAAA,IACH;AAEA,UAAM,MAAM,MAAM,SAAS,QAAQ;AACnC,QAAI,CAAC,SAAS,GAAI,OAAM,kBAAkB,SAAS,QAAQ,KAAK,QAAQ,IAAI;AAC5E,QAAI,CAAC,WAAW,OAAQ,QAAO;AAE/B,UAAM,SAAS,WAAW,OAAO,UAAU,GAAG;AAC9C,QAAI,CAAC,OAAO,SAAS;AACnB,YAAM,QAAQ,OAAO,MAAM,OAAO,CAAC;AACnC,YAAM,QAAQ,OAAO,KAAK,SAAS,OAAO,MAAM,KAAK,KAAK,GAAG,CAAC,KAAK;AACnE,YAAM,IAAI,YAAY;AAAA,QACpB,QAAQ,SAAS;AAAA,QACjB,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,4BAA4B,MAAM,IAAI,IAAI,GAAG,KAAK,KAAK,OAAO,WAAW,SAAS;AAAA,QAC3F,MAAM,QAAQ,QAAQ;AAAA,MACxB,CAAC;AAAA,IACH;AACA,WAAO,OAAO;AAAA,EAChB;AAEA,SAAO,EAAE,WAAW,QAAQ;AAC9B;AAGO,IAAM,cAAN,cAA0B,MAAM;AAAA,EACrC,YACE,SACS,WACT;AACA,UAAM,OAAO;AAFJ;AAGT,SAAK,OAAO;AAAA,EACd;AACF;AAGA,eAAsB,UACpB,WACA,KACA,SACA,MACA,YAAY,IAAI,KACD;AACf,MAAI;AACJ,MAAI;AACF,eAAW,MAAM,UAAU,KAAK;AAAA,MAC9B,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA,QAAQ,YAAY,QAAQ,SAAS;AAAA,IACvC,CAAC;AAAA,EACH,SAAS,OAAO;AACd,UAAM,IAAI,YAAY,kBAAkB,cAAc,KAAK,CAAC,KAAK,IAAI;AAAA,EACvE;AAEA,QAAM,SAAS,KAAK,EAAE,MAAM,MAAM,EAAE;AACpC,MAAI,SAAS,GAAI;AACjB,QAAM,YAAY,SAAS,UAAU,OAAO,SAAS,WAAW,OAAO,SAAS,WAAW;AAC3F,QAAM,IAAI,YAAY,QAAQ,SAAS,MAAM,IAAI,SAAS;AAC5D;AAEA,eAAe,SAAS,UAAsC;AAC5D,MAAI,SAAS,WAAW,IAAK,QAAO;AACpC,QAAM,OAAO,MAAM,SAAS,KAAK;AACjC,MAAI,SAAS,GAAI,QAAO;AACxB,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,kBAAkB,QAAgB,MAAe,QAAgB,MAAc;AACtF,QAAM,WAAW,oBAAoB,UAAU,IAAI;AACnD,MAAI,SAAS,SAAS;AACpB,WAAO,IAAI,YAAY;AAAA,MACrB;AAAA,MACA,MAAM,SAAS,KAAK,MAAM;AAAA,MAC1B;AAAA,MACA,SAAS,SAAS,KAAK,MAAM;AAAA,IAC/B,CAAC;AAAA,EACH;AACA,SAAO,IAAI,YAAY,EAAE,QAAQ,MAAM,SAAS,GAAG,MAAM,IAAI,IAAI,qBAAqB,MAAM,GAAG,CAAC;AAClG;AAEA,SAAS,cAAc,OAAwB;AAC7C,MAAI,iBAAiB,OAAO;AAC1B,UAAM,QAAS,MAA8B;AAC7C,QAAI,iBAAiB,SAAS,UAAU,MAAO,QAAO,OAAQ,MAA4B,IAAI;AAC9F,QAAI,MAAM,SAAS,eAAgB,QAAO;AAC1C,WAAO,MAAM;AAAA,EACf;AACA,SAAO,OAAO,KAAK;AACrB;;;AC1MA,SAAS,OAAO,OAAO,UAAU,MAAM,iBAAiB;AACxD,SAAS,eAAe;AACxB,SAAS,YAAY;AACrB,SAAS,KAAAC,UAAS;AAEX,IAAM,kBAAkB;AACxB,IAAM,mBAAmB;AACzB,IAAM,qBAAqB;AAE3B,IAAM,MAAM;AAAA,EACjB,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,WAAW;AAAA,EACX,OAAO;AAAA;AAAA,EAEP,cAAc;AAChB;AAEO,IAAM,kBAAkBA,GAAE,OAAO;AAAA,EACtC,WAAWA,GAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EACrC,QAAQA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACnC,MAAMA,GACH,OAAO;AAAA,IACN,OAAOA,GAAE,OAAO,EAAE,SAAS;AAAA,IAC3B,MAAMA,GAAE,OAAO,EAAE,SAAS;AAAA,IAC1B,UAAUA,GAAE,OAAO,EAAE,SAAS;AAAA,EAChC,CAAC,EACA,SAAS;AACd,CAAC;AAMM,SAAS,oBAAoB,MAAW,QAAQ,KAAK;AAC1D,SAAO,EAAE,KAAK,QAAQ,IAAI,GAAG,MAAM,QAAQ,GAAG,UAAU,QAAQ,UAAU,IAAI;AAChF;AAGA,SAAS,QAAQ,OAA+C;AAC9D,QAAM,IAAI,OAAO,KAAK;AACtB,SAAO,KAAK,CAAC,EAAE,WAAW,IAAI,IAAI,IAAI;AACxC;AAEO,SAAS,iBAAiB,MAAW,QAAQ,KAAa;AAC/D,SAAO,IAAI,IAAI,SAAS,KAAK,KAAK,IAAI,QAAQ,QAAQ,GAAG,eAAe;AAC1E;AAuBO,SAAS,kBAAkB,UAAuC,CAAC,GAAgB;AACxF,QAAM,MAAM,QAAQ,OAAO,QAAQ;AACnC,QAAM,MAAM,QAAQ,OAAO,iBAAiB,GAAG;AAC/C,QAAM,OAAO,KAAK,KAAK,gBAAgB;AAEvC,iBAAe,OAA2B;AACxC,QAAI;AACJ,QAAI;AACF,YAAM,MAAM,SAAS,MAAM,MAAM;AAAA,IACnC,SAAS,OAAO;AACd,UAAK,MAAgC,SAAS,SAAU,QAAO,CAAC;AAChE,YAAM;AAAA,IACR;AACA,QAAI;AACJ,QAAI;AACF,aAAO,KAAK,MAAM,GAAG;AAAA,IACvB,QAAQ;AACN,YAAM,IAAI,MAAM,eAAe,IAAI,oBAAoB;AAAA,IACzD;AACA,UAAM,SAAS,gBAAgB,UAAU,IAAI;AAC7C,QAAI,CAAC,OAAO,SAAS;AACnB,YAAM,IAAI,MAAM,eAAe,IAAI,gBAAgB,OAAO,MAAM,OAAO,CAAC,GAAG,OAAO,EAAE;AAAA,IACtF;AACA,WAAO,OAAO;AAAA,EAChB;AAEA,iBAAe,KAAK,QAAkC;AACpD,UAAM,MAAM,KAAK,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AACjD,UAAM,MAAM,KAAK,GAAK,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AACtC,UAAM,UAAU,MAAM,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,GAAM,EAAE,MAAM,IAAM,CAAC;AAE7E,UAAM,MAAM,MAAM,GAAK;AAAA,EACzB;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM,OAAO,OAAO;AAClB,YAAM,OAAO,EAAE,GAAI,MAAM,KAAK,GAAI,GAAG,MAAM;AAC3C,YAAM,KAAK,IAAI;AACf,aAAO;AAAA,IACT;AAAA,IACA,MAAM,mBAAmB;AACvB,YAAM,EAAE,UAAU,IAAI,MAAM,KAAK;AACjC,YAAM,KAAK,YAAY,EAAE,UAAU,IAAI,CAAC,CAAC;AAAA,IAC3C;AAAA,IACA,MAAM,QAAQ,YAAY,CAAC,GAAG;AAC5B,YAAM,SAAS,MAAM,KAAK;AAC1B,YAAM,SAAS,QAAQ,IAAI,IAAI,GAAG,CAAC;AACnC,YAAM,SAAS,QAAQ,IAAI,IAAI,MAAM,CAAC;AACtC,YAAM,CAAC,WAAW,eAAe,IAC/B,UAAU,YACN,CAAC,UAAU,WAAW,MAAM,IAC5B,SACE,CAAC,QAAQ,KAAK,IACd,OAAO,YACL,CAAC,OAAO,WAAW,QAAQ,IAC3B,CAAC,oBAAoB,SAAS;AACxC,YAAM,CAAC,QAAQ,YAAY,IAA0D,SACjF,CAAC,QAAQ,KAAK,IACd,OAAO,SACL,CAAC,OAAO,QAAQ,QAAQ,IACxB,CAAC,QAAW,MAAM;AACxB,aAAO;AAAA,QACL,WAAW,UAAU,QAAQ,QAAQ,EAAE;AAAA,QACvC;AAAA,QACA;AAAA,QACA;AAAA,QACA,MAAM,OAAO;AAAA,QACb,OAAO,QAAQ,IAAI,IAAI,KAAK,CAAC;AAAA,MAC/B;AAAA,IACF;AAAA,EACF;AACF;AAWA,IAAM,qBAAqB;AAGpB,SAAS,UAAU,KAAiC;AACzD,MAAI,CAAC,IAAK,QAAO;AACjB,SAAO,IAAI,UAAU,qBAAqB,IAAI,SAAS,GAAG,IAAI,MAAM,GAAG,kBAAkB,CAAC;AAC5F;;;AbnJO,IAAM,sBAAsB;AAC5B,IAAM,oBAAoB;AAC1B,IAAM,mBAAmB,IAAI,KAAK;AAClC,IAAM,gBAAgB;AAEtB,IAAM,gBAAgB;AAoB7B,eAAsB,UAAU,SAA6C;AAC3E,QAAM,EAAE,WAAW,OAAO,IAAI,IAAI;AAClC,QAAM,QAAQ,YAAY,EAAE,EAAE,SAAS,KAAK;AAC5C,QAAM,WAAW,MAAM,oBAAoB,EAAE,OAAO,WAAW,QAAQ,UAAU,CAAC;AAClF,MAAI;AACF,UAAM,UAAU,aAAa,WAAW,SAAS,KAAK,QAAQ,YAAY,WAAW,GAAG,KAAK;AAC7F,YAAQ,YAAY,OAAO;AAC3B,QAAI,KAAK,sCAAsC,SAAS,EAAE;AAC1D,QAAI,KAAK,+BAA+B,OAAO,EAAE;AACjD,QAAI;AACF,YAAM,QAAQ,KAAK,OAAO;AAAA,IAC5B,SAAS,OAAO;AACd,UAAI,KAAK,6BAA8B,MAAgB,OAAO,wBAAwB;AAAA,IACxF;AACA,QAAI,KAAK,sEAAiE;AAE1E,UAAM,EAAE,IAAI,IAAI,MAAM,SAAS;AAC/B,UAAM,SAAS,gBAAgB,EAAE,WAAW,QAAQ,KAAK,OAAO,QAAQ,MAAM,CAAC;AAC/E,UAAM,OAAO,MAAM,OAAO,QAAQ,OAAO,WAAW,EAAE,QAAQ,SAAS,CAAC;AAExE,UAAM,MAAM,OAAO;AAAA,MACjB;AAAA,MACA,QAAQ;AAAA,MACR,MAAM,EAAE,OAAO,KAAK,OAAO,MAAM,KAAK,MAAM,UAAU,KAAK,SAAS;AAAA,IACtE,CAAC;AACD,UAAM,YAAY,UAAU,GAAG;AAC/B,QAAI,QAAQ,gBAAgB,KAAK,KAAK,EAAE;AACxC,QAAI,KAAK,WAAW,SAAS,EAAE;AAC/B,QAAI,KAAK,YAAY,SAAS,eAAe,MAAM,IAAI,GAAG;AAC1D,WAAO,EAAE,WAAW,WAAW,KAAK;AAAA,EACtC,UAAE;AACA,aAAS,MAAM;AAAA,EACjB;AACF;AAEO,SAAS,aACd,WACA,aACA,UACA,OACQ;AACR,QAAM,MAAM,IAAI,IAAI,eAAe,GAAG,UAAU,QAAQ,QAAQ,EAAE,CAAC,GAAG;AACtE,MAAI,aAAa,IAAI,gBAAgB,WAAW;AAChD,MAAI,aAAa,IAAI,YAAY,QAAQ;AACzC,MAAI,aAAa,IAAI,SAAS,KAAK;AACnC,SAAO,IAAI,SAAS;AACtB;AAmBO,SAAS,cACd,KACA,eAC4D;AAC5D,QAAM,QAAQ,IAAI,aAAa,IAAI,OAAO;AAC1C,MAAI,MAAO,QAAO,EAAE,IAAI,OAAO,SAAS,mBAAmB,KAAK,GAAG;AACnE,QAAM,QAAQ,IAAI,aAAa,IAAI,OAAO;AAC1C,MAAI,UAAU,QAAQ,kBAAkB,UAAa,UAAU,eAAe;AAC5E,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,SAAS;AAAA,IACX;AAAA,EACF;AACA,QAAM,MAAM,IAAI,aAAa,IAAI,KAAK;AACtC,MAAI,CAAC,IAAK,QAAO,EAAE,IAAI,OAAO,SAAS,2CAA2C;AAClF,SAAO,EAAE,IAAI,MAAM,IAAI;AACzB;AAEA,eAAsB,oBACpB,UAAkD,CAAC,GAC1B;AACzB,QAAM,YAAY,QAAQ,aAAa;AACvC,MAAI;AACJ,MAAI;AACJ,QAAM,SAAS,IAAI,QAAsB,CAACC,UAAS,WAAW;AAC5D,aAAS,EAAE,SAAAA,UAAS,OAAO;AAAA,EAC7B,CAAC,EAAE,QAAQ,MAAM,aAAa,KAAK,CAAC;AAEpC,SAAO,MAAM,MAAM;AAAA,EAAC,CAAC;AAErB,QAAM,SAAS,aAAa,CAAC,KAAK,QAAQ,eAAe,KAAK,KAAK,MAAM,QAAQ,OAAO,MAAM,CAAC;AAC/F,QAAM,OAAO,MAAM,iBAAiB,MAAM;AAC1C,UAAQ,WAAW,MAAM;AACvB,YAAQ;AAAA,MACN,IAAI;AAAA,QACF,mBAAmB,KAAK,MAAM,YAAY,GAAM,KAAK,CAAC;AAAA,QACtD,EAAE,MAAM,SAAS,QAAQ,yDAAyD;AAAA,MACpF;AAAA,IACF;AAAA,EACF,GAAG,SAAS;AAEZ,SAAO;AAAA,IACL;AAAA,IACA,KAAK,oBAAoB,IAAI,GAAG,aAAa;AAAA,IAC7C;AAAA,IACA,OAAO,MAAM;AACX,mBAAa,KAAK;AAClB,aAAO,MAAM;AACb,aAAO,sBAAsB;AAAA,IAC/B;AAAA,EACF;AACF;AAEA,SAAS,eACP,KACA,KACA,MACA,eACA,QACM;AACN,QAAM,MAAM,IAAI,IAAI,IAAI,OAAO,KAAK,oBAAoB,IAAI,EAAE;AAC9D,MAAI,IAAI,aAAa,eAAe;AAClC,QAAI,UAAU,KAAK,EAAE,gBAAgB,aAAa,CAAC,EAAE,IAAI,WAAW;AACpE;AAAA,EACF;AACA,QAAM,SAAS,cAAc,KAAK,aAAa;AAC/C,MAAI,CAAC,OAAO,IAAI;AACd;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAGC,YAAW,OAAO,OAAO,CAAC;AAAA,IAC/B;AACA,YAAQ;AAAA,MACN,IAAI,SAAS,OAAO,SAAS,EAAE,MAAM,SAAS,QAAQ,yBAAyB,CAAC;AAAA,IAClF;AACA;AAAA,EACF;AACA,cAAY,KAAK,KAAK,aAAa,sDAAsD,IAAI;AAC7F,UAAQ,QAAQ,EAAE,KAAK,OAAO,IAAI,CAAC;AACrC;AAEA,SAAS,YACP,KACA,QACA,OACA,MACA,QAAQ,OACR;AACA,QAAM,OAAO,wEAAmE,KAAK;AAAA;AAAA,+BAExD,KAAK,WAAW,IAAI;AAAA,EACjD,QAAQ,gEAAgE,EAAE;AAAA;AAE1E,MAAI,UAAU,QAAQ;AAAA,IACpB,gBAAgB;AAAA,IAChB,iBAAiB;AAAA,IACjB,YAAY;AAAA,EACd,CAAC;AACD,MAAI,IAAI,IAAI;AACd;AAEA,SAAS,iBAAiB,QAAiC;AACzD,SAAO,IAAI,QAAQ,CAACD,UAAS,WAAW;AACtC,QAAI,OAAO;AACX,UAAM,UAAU,MAAM;AACpB,UAAI,OAAO,mBAAmB;AAC5B;AAAA,UACE,IAAI;AAAA,YACF,mBAAmB,mBAAmB,SAAI,iBAAiB;AAAA,YAC3D;AAAA,cACE,MAAM;AAAA,YACR;AAAA,UACF;AAAA,QACF;AACA;AAAA,MACF;AACA,aAAO,KAAK,SAAS,CAAC,UAAiC;AACrD,YAAI,MAAM,SAAS,gBAAgB,MAAM,SAAS,UAAU;AAC1D,kBAAQ;AACR,kBAAQ;AAAA,QACV,MAAO,QAAO,KAAK;AAAA,MACrB,CAAC;AACD,aAAO,OAAO,MAAM,aAAa,MAAM;AACrC,eAAO,mBAAmB,OAAO;AACjC,QAAAA,SAAQ,IAAI;AAAA,MACd,CAAC;AAAA,IACH;AACA,YAAQ;AAAA,EACV,CAAC;AACH;AAEA,SAASC,YAAW,MAAsB;AACxC,SAAO,KAAK,QAAQ,YAAY,QAAM,KAAK,GAAG,WAAW,CAAC,CAAC,GAAG;AAChE;;;Ac/OA,SAAS,uBAAuB;;;ACOhC,OAAO,WAAW;AAgBX,IAAM,WAAwB,aAAa,EAAE,OAAO,MAAM,UAAU,GAAG,SAAS,KAAK;AAErF,SAAS,kBACd,UAAgE,CAAC,GACpD;AACb,MAAI,sBAAsB,QAAQ,OAAO,QAAQ,GAAG,EAAG,QAAO;AAC9D,SAAO,CAAC,KAAK,OAAO,SAClB,mBAAmB,SAAS,KAAK,KAAK,GAAG;AAAA,IACvC,WAAW,QAAQ;AAAA,IACnB,OAAO,QAAQ;AAAA,IACf,WAAW,MAAM;AAAA,EACnB,CAAC;AACL;AAEA,IAAM,UAAU,CAAC,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,QAAG;AAMjE,eAAsB,gBACpB,QACA,KACA,OACA,IACsB;AACtB,MAAI,CAAC,OAAQ,QAAO,EAAE,OAAO,MAAM,UAAU,GAAG,SAAS,KAAK;AAC9D,MAAI,QAAQ;AACZ,MAAI;AACJ,QAAM,OAAO,MACX,GAAG,SAAS,GAAG,MAAM,KAAK,QAAQ,UAAU,QAAQ,MAAM,CAAC,CAAC,6BAAwB;AACtF,MAAI;AACF,UAAM,SAAS,MAAM,OAAO,KAAK,OAAO;AAAA,MACtC,WAAW,MAAM;AACf,aAAK;AACL,gBAAQ,YAAY,MAAM,GAAG;AAC7B,cAAM,QAAQ;AAAA,MAChB;AAAA,IACF,CAAC,EAAE,MAAM,OAAO,EAAE,OAAO,OAAO,UAAU,EAAE,EAAE;AAC9C,QAAI,MAAO,IAAG,SAAS,IAAI;AAC3B,QAAI,CAAC,OAAO,MAAO,IAAG,KAAK,GAAG,GAAG,WAAM,cAAc,EAAE;AACvD,WAAO;AAAA,EACT,UAAE;AACA,QAAI,MAAO,eAAc,KAAK;AAAA,EAChC;AACF;;;ACrEA,OAAOC,YAAW;AAElB,IAAM,SAASA,OAAM,KAAK,OAAO;AAiB1B,SAAS,aAAa,UAAyB,CAAC,GAAW;AAChE,QAAM,QAAQ,QAAQ,UAAU,CAAC,SAAiB,QAAQ,OAAO,MAAM,GAAG,IAAI;AAAA,CAAI;AAClF,QAAM,eAAe,QAAQ,SAAS;AACtC,SAAO;AAAA,IACL,MAAM,aAAW,MAAM,GAAG,MAAM,IAAI,OAAO,EAAE;AAAA,IAC7C,SAAS,aAAW,MAAM,GAAG,MAAM,IAAIA,OAAM,MAAM,QAAG,CAAC,IAAI,OAAO,EAAE;AAAA,IACpE,MAAM,aAAW,MAAM,GAAG,MAAM,IAAIA,OAAM,OAAO,GAAG,CAAC,IAAI,OAAO,EAAE;AAAA,IAClE,OAAO,aAAW,MAAM,GAAG,MAAM,IAAIA,OAAM,IAAI,QAAG,CAAC,IAAI,OAAO,EAAE;AAAA,IAChE,MAAM,aAAW,MAAMA,OAAM,IAAI,KAAK,OAAO,EAAE,CAAC;AAAA,IAChD,OAAO,aAAW;AAChB,UAAI,aAAc,OAAMA,OAAM,IAAI,WAAW,OAAO,EAAE,CAAC;AAAA,IACzD;AAAA,EACF;AACF;AAUO,IAAM,eAAuB;AAAA,EAClC,MAAM,MAAM;AAAA,EAAC;AAAA,EACb,SAAS,MAAM;AAAA,EAAC;AAAA,EAChB,MAAM,MAAM;AAAA,EAAC;AAAA,EACb,OAAO,MAAM;AAAA,EAAC;AAAA,EACd,MAAM,MAAM;AAAA,EAAC;AAAA,EACb,OAAO,MAAM;AAAA,EAAC;AAChB;;;ACjDA,OAAOC,YAAW;AAeX,SAAS,aAAa,UAAyB,CAAC,GAAW;AAChE,QAAM,OAAO,QAAQ,QAAQ;AAC7B,QAAM,QAAQ,QAAQ,UAAU,CAAC,UAAkB,QAAQ,OAAO,MAAM,KAAK;AAC7E,SAAO;AAAA,IACL;AAAA,IACA,MAAM,CAAC,KAAK,UAAU,MAAM,GAAG,OAAO,WAAW,GAAG,IAAI,MAAM,CAAC;AAAA,CAAI;AAAA,IACnE,MAAM,UAAQ;AACZ,UAAI,CAAC,KAAM,OAAM,GAAG,IAAI;AAAA,CAAI;AAAA,IAC9B;AAAA,EACF;AACF;AASO,SAAS,WAAW,OAAwB;AACjD,SAAO,KAAK,UAAU,OAAO,MAAM,CAAC;AACtC;AAQO,SAAS,YAAiB,MAAsB,SAAyC;AAC9F,MAAI,KAAK,WAAW,EAAG,QAAOC,OAAM,IAAI,cAAc;AACtD,QAAM,QAAQ,KAAK,IAAI,SAAO,QAAQ,IAAI,YAAU,WAAW,OAAO,MAAM,GAAG,CAAC,CAAC,CAAC;AAClF,QAAM,SAAS,QAAQ;AAAA,IAAI,CAAC,QAAQ,MAClC,KAAK,IAAI,OAAO,OAAO,QAAQ,GAAG,MAAM,IAAI,UAAQ,KAAK,CAAC,GAAG,UAAU,CAAC,CAAC;AAAA,EAC3E;AACA,QAAM,MAAM,CAAC,MAAc,MACzB,MAAM,QAAQ,SAAS,IAAI,OAAO,KAAK,OAAO,OAAO,CAAC,KAAK,CAAC;AAC9D,QAAM,SAAS,QAAQ,IAAI,CAAC,QAAQ,MAAM,IAAI,OAAO,QAAQ,CAAC,CAAC,EAAE,KAAK,IAAI;AAC1E,QAAM,OAAO,MAAM,IAAI,UAAQ,KAAK,IAAI,GAAG,EAAE,KAAK,IAAI,CAAC;AACvD,SAAO,CAACA,OAAM,KAAK,MAAM,GAAG,GAAG,IAAI,EAAE,KAAK,IAAI;AAChD;AAEO,SAAS,WAAW,OAAwB;AACjD,MAAI,UAAU,QAAQ,UAAU,UAAa,UAAU,GAAI,QAAO;AAClE,MAAI,OAAO,UAAU,SAAU,QAAO,KAAK,UAAU,KAAK;AAC1D,SAAO,OAAO,KAAK;AACrB;AAGO,SAAS,WAAW,OAA0C;AACnE,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,OAAO,IAAI,KAAK,KAAK;AAC3B,MAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,EAAG,QAAO,OAAO,KAAK;AACrD,QAAM,MAAM,CAAC,MAAc,OAAO,CAAC,EAAE,SAAS,GAAG,GAAG;AACpD,SAAO,GAAG,KAAK,YAAY,CAAC,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,IAAI,IAAI,KAAK,QAAQ,CAAC,CAAC,IAAI,IAAI,KAAK,SAAS,CAAC,CAAC,IAAI,IAAI,KAAK,WAAW,CAAC,CAAC;AACnI;AAGO,SAAS,YAAY,OAAuB;AACjD,MAAI,QAAQ,KAAM,QAAO,GAAG,KAAK;AACjC,QAAM,QAAQ,CAAC,MAAM,MAAM,IAAI;AAC/B,MAAI,QAAQ,QAAQ;AACpB,MAAI,OAAO;AACX,SAAO,SAAS,QAAQ,OAAO,MAAM,SAAS,GAAG;AAC/C,aAAS;AACT;AAAA,EACF;AACA,SAAO,GAAG,MAAM,QAAQ,QAAQ,KAAK,IAAI,CAAC,CAAC,IAAI,MAAM,IAAI,CAAC;AAC5D;;;AHjCA,eAAsB,cAAc,UAA0B,CAAC,GAA4B;AACzF,QAAM,QAAQ,QAAQ,SAAS,kBAAkB,EAAE,KAAK,QAAQ,IAAI,CAAC;AACrE,QAAM,OAAO,QAAQ,QAAQ;AAC7B,QAAM,SAAS,MAAM,MAAM,QAAQ,EAAE,WAAW,QAAQ,OAAO,CAAC;AAChE,QAAM,cAAc,QAAQ,QAAQ,MAAM,SAAS,QAAQ,OAAO,KAAK;AACvE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,KAAK,QAAQ,OAAO,aAAa,EAAE,OAAO,OAAO,MAAM,CAAC;AAAA,IACxD,KAAK,QAAQ,OAAO,aAAa,EAAE,KAAK,CAAC;AAAA,IACzC,OAAO,QAAQ,UAAU,CAAC,OAAO,SAAS,MAAM,OAAO,IAAI;AAAA,IAC3D,MAAM,QAAQ,SAAS,OAAM,SAAQ,MAAM,OAAO,MAAM,GAAG,QAAQ,GAAG;AAAA,IACtE;AAAA,IACA,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,UAAU,cAAc,cAAc,MAAM;AAAA,IAAC;AAAA,IAC7C,SAAS;AAAA,IACT,WAAW,kBAAkB,EAAE,KAAK,QAAQ,IAAI,CAAC;AAAA,EACnD;AACF;AAEA,eAAe,WAAW,UAAoC;AAC5D,QAAM,SAAS,MAAM,UAAU,GAAG,QAAQ,SAAS;AACnD,SAAO,YAAY,KAAK,OAAO,KAAK,CAAC;AACvC;AAEA,eAAe,UAAU,UAAmC;AAC1D,QAAM,KAAK,gBAAgB,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,CAAC;AAC3E,MAAI;AACF,WAAO,MAAM,GAAG,SAAS,QAAQ;AAAA,EACnC,UAAE;AACA,OAAG,MAAM;AAAA,EACX;AACF;AAEA,SAAS,YAAY,MAA2B;AAC9C,UAAQ,OAAO,MAAM,YAAY,QAAQ,EAAE,EAAE;AAC/C;AAGO,SAAS,cACd,KACW;AACX,MAAI,CAAC,IAAI,OAAO,OAAQ,OAAM,IAAI,iBAAiB,IAAI,OAAO;AAC9D,SAAO,gBAAgB;AAAA,IACrB,WAAW,IAAI,OAAO;AAAA,IACtB,QAAQ,IAAI,OAAO;AAAA,IACnB,OAAO,IAAI;AAAA,EACb,CAAC;AACH;;;AIrFA,SAAS,KAAAC,UAAS;AAQX,IAAMC,uBAAsBC,GAAE,YAAY,EAAE,UAAUA,GAAE,OAAO,EAAE,CAAC;AAEzE,IAAMC,YAAW,CAAC,SAAiB,cAAc,mBAAmB,IAAI,CAAC;AAElE,SAAS,OAAO,QAAgC;AACrD,SAAO,OAAO,QAAQ,OAAO,WAAW,EAAE,QAAQ,SAAS,CAAC;AAC9D;AAGO,SAAS,UAAU,QAAmB,MAAkC;AAC7E,SAAO,OAAO,QAAQ,OAAO,cAAc,mBAAmB,IAAI,CAAC,IAAI;AAAA,IACrE,QAAQ;AAAA,EACV,CAAC;AACH;AAcO,SAAS,aAAa,WAAqC;AAChE,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,SAAS;AAC7B,UAAM,EAAE,SAAS,IAAI;AACrB,QACE,IAAI,QACJ,CAAC,SAAS,SAAS,GAAG,KACtB,WAAW,KAAK,QAAQ,KACxB,SAAS,WAAW,GAAG;AAEvB,aAAO;AACT,WAAO,EAAE,UAAU,IAAI,UAAU,QAAQ,SAAS;AAAA,EACpD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,qBAAqBC,UAAmC;AACtE,MAAI;AACF,UAAM,MAAM,IAAI,IAAIA,QAAO;AAC3B,UAAM,MAAM,IAAI,KAAK,QAAQ,GAAG;AAChC,WAAO,MAAM,IAAI,EAAE,UAAU,IAAI,UAAU,QAAQ,IAAI,KAAK,MAAM,MAAM,CAAC,EAAE,IAAI;AAAA,EACjF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMA,eAAsB,kBAAkB,QAA8C;AACpF,QAAM,WAAW,aAAa,OAAO,SAAS;AAC9C,MAAI,SAAU,QAAO;AACrB,QAAM,QAAQ,MAAM,UAAU,MAAM,EAAE,MAAM,MAAM,CAAC,CAAC;AACpD,QAAM,QAAQ,MAAM,CAAC;AACrB,SAAO,QAAQ,qBAAqB,MAAM,GAAG,IAAI;AACnD;AAEO,SAAS,WAAW,MAAc,MAAyB;AAChE,SAAO,QAAQ,MAAM,KAAK,QAAQ,KAAK,QAAQ;AACjD;AAGO,SAAS,aAAa,MAAgC;AAC3D,SAAO,OAAO,WAAW,UAAU,IAAI,IAAI;AAC7C;AAEA,eAAsB,UACpB,QACA,OAA+B,CAAC,GACf;AACjB,QAAM,MAAM,MAAM,OAAO,QAAQ,OAAO,cAAc;AAAA,IACpD,QAAQ;AAAA,IACR,OAAO,EAAE,UAAU,KAAK,WAAW,IAAI,OAAU;AAAA,EACnD,CAAC;AACD,SAAO,IAAI;AACb;AAEO,SAAS,QAAQ,QAAmB,MAAmC;AAC5E,SAAO,OAAO,QAAQ,OAAOD,UAAS,IAAI,GAAG,EAAE,QAAQ,iBAAiB,CAAC;AAC3E;AAUA,eAAsB,aACpB,QACA,MACA,WACoB;AACpB,QAAM,OAAO,MAAM,QAAQ,QAAQ,IAAI;AACvC,QAAM,KAAK,aAAa,KAAK;AAC7B,MAAI,CAAC,GAAI,OAAM,IAAI,SAAS,GAAG,IAAI,+BAA+B;AAClE,QAAM,QAAQ,MAAM,OAAO;AAAA,IACzB;AAAA,IACA,GAAGA,UAAS,IAAI,CAAC,aAAa,mBAAmB,EAAE,CAAC;AAAA,IACpD,EAAE,QAAQ,mBAAmB;AAAA,EAC/B;AACA,SAAO,EAAE,MAAM,KAAK,MAAM,KAAK,KAAK,KAAK,SAAS,OAAO,KAAK,kBAAkB,GAAG,MAAM;AAC3F;AAMA,eAAe,UAAU,QAAmB,MAAc,KAA6B;AACrF,QAAM,SAAS,WAAW,UAAU,GAAG;AACvC,MAAI,OAAO,QAAS,QAAO,OAAO;AAClC,QAAM,SAAS,WAAW,UAAW,KAAwC,IAAI;AACjF,MAAI,OAAO,QAAS,QAAO,OAAO;AAClC,SAAO,QAAQ,QAAQ,IAAI;AAC7B;AAEA,eAAsB,SAAS,QAAmB,MAAc,WAAkC;AAChG,QAAM,MAAM,MAAM,OAAO,QAAQ,QAAQ,GAAGA,UAAS,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AAC7F,SAAO,UAAU,QAAQ,MAAM,GAAG;AACpC;AAEA,eAAsB,cACpB,QACA,MACA,YACe;AACf,QAAM,MAAM,MAAM,OAAO,QAAQ,SAASA,UAAS,IAAI,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;AAClF,SAAO,UAAU,QAAQ,MAAM,GAAG;AACpC;AAEA,eAAsB,YACpB,QACA,MACA,OAAgC,CAAC,GAClB;AACf,QAAM,MAAM,MAAM,OAAO;AAAA,IACvB;AAAA,IACA,GAAGA,UAAS,IAAI,CAAC,IAAI,KAAK,YAAY,cAAc,SAAS;AAAA,EAC/D;AACA,SAAO,UAAU,QAAQ,MAAM,GAAG;AACpC;AAEA,eAAsB,WACpB,QACA,MAC0C;AAC1C,QAAM,OAAO,QAAQ,UAAUA,UAAS,IAAI,CAAC;AAC7C,SAAO,EAAE,MAAM,SAAS,KAAK;AAC/B;AAUA,eAAsB,MACpB,QACA,MACA,OAAgD,CAAC,GAC3B;AACtB,MAAI,KAAK,QAAQ;AACf,UAAM,OAAO,QAAQ,UAAU,GAAGA,UAAS,IAAI,CAAC,QAAQ;AACxD,WAAO,EAAE,MAAM,QAAQ,WAAW,UAAU,KAAK;AAAA,EACnD;AACA,MAAI,UAAU;AACd,MAAI,CAAC,KAAK,SAAS;AACjB,UAAM,OAAO,MAAM,QAAQ,QAAQ,IAAI;AACvC,QAAI,KAAK,SAAU,QAAO,EAAE,MAAM,QAAQ,YAAY,UAAU,KAAK,SAAS;AAAA,EAChF,MAAO,WAAU;AACjB,QAAM,MAAM,MAAM,OAAO,QAAQ,QAAQ,GAAGA,UAAS,IAAI,CAAC,UAAU;AAAA,IAClE,QAAQF;AAAA,EACV,CAAC;AACD,SAAO,EAAE,MAAM,QAAQ,UAAU,cAAc,WAAW,UAAU,IAAI,SAAS;AACnF;;;AnB/MA,eAAsB,SAAS,KAAoC;AACjE,QAAM,SAAS,MAAM,UAAU;AAAA,IAC7B,WAAW,IAAI,OAAO;AAAA,IACtB,OAAO,IAAI;AAAA,IACX,KAAK,IAAI;AAAA,IACT,MAAM,IAAI;AAAA,IACV,OAAO,IAAI;AAAA,EACb,CAAC;AACD,MAAI,IAAI,KAAM,KAAI,IAAI,KAAK,QAAQ,MAAM,EAAE;AAC7C;AAEA,eAAsB,UAAU,KAAoC;AAClE,QAAM,SAAS,MAAM,IAAI,MAAM,KAAK;AACpC,MAAI,CAAC,OAAO,QAAQ;AAClB,QAAI,IAAI,KAAK,oCAA+B;AAC5C;AAAA,EACF;AACA,QAAM,IAAI,MAAM,iBAAiB;AACjC,MAAI,IAAI,QAAQ,+CAA+C;AAC/D,MAAI,IAAI,KAAK,6CAA6C,IAAI,OAAO,SAAS,EAAE;AAClF;AAEA,eAAsB,UAAU,KAAoC;AAClE,QAAM,SAAS,cAAc,GAAG;AAChC,QAAM,KAAK,MAAM,OAAO,MAAM;AAC9B,QAAM,OAAO,IAAI,OAAO,OAAO,MAAM,kBAAkB,MAAM;AAC7D,MAAI,IAAI;AAAA,IACN;AAAA,MACE,GAAG;AAAA,MACH,WAAW,IAAI,OAAO;AAAA,MACtB,QAAQ,UAAU,IAAI,OAAO,MAAM;AAAA,MACnC,cAAc,IAAI,OAAO;AAAA,IAC3B;AAAA,IACA,MACE;AAAA,MACE,GAAGI,OAAM,KAAK,OAAO,CAAC,OAAO,GAAG,IAAI,KAAK,GAAG,KAAK;AAAA,MACjD,GAAGA,OAAM,KAAK,QAAQ,CAAC,MAAM,aAAa,IAAI,CAAC,IAAIA,OAAM,IAAI,sCAAsC,CAAC;AAAA,MACpG,GAAGA,OAAM,KAAK,SAAS,CAAC,KAAK,IAAI,OAAO,SAAS;AAAA,MACjD,GAAGA,OAAM,KAAK,UAAU,CAAC,IAAI,UAAU,IAAI,OAAO,MAAM,CAAC,IAAIA,OAAM,IAAI,SAAS,IAAI,OAAO,YAAY,GAAG,CAAC;AAAA,IAC7G,EAAE,KAAK,IAAI;AAAA,EACf;AACF;;;AoBhCA,OAAOC,YAAW;;;ACZlB,SAAS,YAAAC,iBAAgB;;;ACIzB,SAAS,kBAAkB;AAC3B,SAAS,wBAAwB;AACjC,SAAS,SAAS,YAAAC,WAAU,UAAU,QAAAC,aAAY;AAClD,SAAS,QAAAC,OAAM,WAAW;AAY1B,OAAO,YAA6B;AACpC,OAAO,UAAU;AAIV,IAAM,cAAc;AACpB,IAAM,mBAAmB;AAChC,IAAM,cAAc,oBAAI,IAAI,CAAC,cAAc,CAAC;AAC5C,IAAM,gBAAgB,oBAAI,IAAI;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAqBM,SAAS,eAAe,MAAsB;AACnD,QAAM,OAAO,KAAK,QAAQ,IAAI,KAAK;AACnC,SAAO,KAAK,WAAW,OAAO,KAAK,cAAc,IAAI,IAAI,IAAI,GAAG,IAAI,oBAAoB;AAC1F;AAEA,eAAsB,WAAW,MAA+B;AAC9D,QAAM,OAAO,WAAW,QAAQ;AAChC,mBAAiB,SAAS,iBAAiB,IAAI,EAAG,MAAK,OAAO,KAAe;AAC7E,SAAO,KAAK,OAAO,KAAK;AAC1B;AAGO,SAAS,WAAW,OAAgC;AACzD,SAAO;AAAA,IACL,OAAO,MAAM,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,MAAM,YAAY,OAAO;AAAA,MAC/D;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE;AAAA,EACJ;AACF;AAEA,eAAsB,cAAc,KAAqC;AACvE,MAAI;AACJ,MAAI;AACF,WAAO,MAAM,SAAS,GAAG;AAAA,EAC3B,QAAQ;AACN,UAAM,IAAI,SAAS,qBAAqB,GAAG,EAAE;AAAA,EAC/C;AACA,MAAI,EAAE,MAAMC,MAAK,IAAI,GAAG,YAAY,EAAG,OAAM,IAAI,SAAS,iBAAiB,GAAG,EAAE;AAEhF,QAAM,KAAK,MAAM,WAAW,IAAI;AAChC,QAAM,WAAqB,CAAC;AAC5B,QAAM,QAA2D,CAAC;AAClE,QAAM,cAAc,oBAAI,IAAY,CAAC,IAAI,CAAC;AAE1C,QAAM,SAAS,CAAC,SAAiB,SAAS,QAAQ,KAAK,WAAW,OAAO,GAAG;AAE5E,iBAAeC,MAAK,SAAiB,QAA+B;AAClE,UAAM,UAAU,MAAM,QAAQ,SAAS,EAAE,eAAe,KAAK,CAAC;AAC9D,YAAQ,KAAK,CAAC,GAAG,MAAO,EAAE,OAAO,EAAE,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,IAAI,CAAE;AACvE,eAAW,SAAS,SAAS;AAC3B,UAAI,MAAM,KAAK,WAAW,GAAG,KAAK,YAAY,IAAI,MAAM,IAAI,EAAG;AAC/D,YAAM,MAAM,SAAS,GAAG,MAAM,IAAI,MAAM,IAAI,KAAK,MAAM;AACvD,UAAI,MAAMC,MAAK,SAAS,MAAM,IAAI;AAClC,UAAI,QAAQ,MAAM,YAAY;AAC9B,UAAI,SAAS,MAAM,OAAO;AAC1B,UAAI,MAAM,eAAe,GAAG;AAC1B,YAAI;AACJ,YAAI;AACF,mBAAS,MAAM,SAAS,GAAG;AAAA,QAC7B,QAAQ;AACN,mBAAS,KAAK,2BAA2B,GAAG,EAAE;AAC9C;AAAA,QACF;AACA,YAAI,CAAC,OAAO,MAAM,GAAG;AACnB,mBAAS,KAAK,gDAAgD,GAAG,EAAE;AACnE;AAAA,QACF;AACA,cAAM,OAAO,MAAMF,MAAK,MAAM;AAC9B,cAAM;AACN,gBAAQ,KAAK,YAAY;AACzB,iBAAS,KAAK,OAAO;AAAA,MACvB;AACA,UAAI,OAAO;AACT,YAAI,GAAG,QAAQ,GAAG,GAAG,GAAG,EAAG;AAC3B,YAAI,YAAY,IAAI,GAAG,EAAG;AAC1B,oBAAY,IAAI,GAAG;AACnB,cAAMC,MAAK,KAAK,GAAG;AAAA,MACrB,WAAW,QAAQ;AACjB,YAAI,GAAG,QAAQ,GAAG,EAAG;AACrB,cAAM,EAAE,KAAK,IAAI,MAAMD,MAAK,GAAG;AAC/B,cAAM,KAAK,EAAE,MAAM,KAAK,SAAS,KAAK,KAAK,CAAC;AAC5C,YAAI,MAAM,SAAS,WAAW;AAC5B,gBAAM,IAAI,SAAS,6BAA6B,SAAS,OAAO,GAAG,IAAI;AAAA,YACrE,MAAM,SAAS,WAAW;AAAA,UAC5B,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,QAAMC,MAAK,MAAM,EAAE;AAEnB,MAAI,MAAM,WAAW,GAAG;AACtB,UAAM,IAAI;AAAA,MACR,sBAAsB,GAAG;AAAA,IAC3B;AAAA,EACF;AACA,cAAY,OAAO,GAAG;AACtB,MAAI,CAAC,MAAM,KAAK,OAAK,EAAE,SAAS,YAAY,GAAG;AAC7C,aAAS,KAAK,gBAAgB;AAAA,EAChC;AAEA,QAAM,QAAQ,MAAM,SAAS,OAAO,IAAI,OAAM,OAAM;AAAA,IAClD,GAAG;AAAA,IACH,QAAQ,MAAM,WAAW,EAAE,OAAO;AAAA,IAClC,aAAa,eAAe,EAAE,IAAI;AAAA,EACpC,EAAE;AACF,SAAO,EAAE,MAAM,OAAO,YAAY,MAAM,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,MAAM,CAAC,GAAG,SAAS;AACpF;AAEA,SAAS,YAAY,OAAyC,KAAmB;AAC/E,aAAW,KAAK,OAAO;AACrB,QAAI,EAAE,KAAK,SAAS,iBAAiB;AACnC,YAAM,IAAI;AAAA,QACR,sBAAsB,eAAe,iBAAiB,EAAE,KAAK,MAAM,GAAG,EAAE,CAAC;AAAA,MAC3E;AAAA,IACF;AACA,QAAI,CAAC,gBAAgB,EAAE,IAAI,EAAG,OAAM,IAAI,SAAS,0BAA0B,EAAE,IAAI,EAAE;AACnF,QAAI,EAAE,OAAO,gBAAgB;AAC3B,YAAM,IAAI;AAAA,QACR,GAAG,EAAE,IAAI,OAAO,YAAY,EAAE,IAAI,CAAC,kBAAkB,YAAY,cAAc,CAAC;AAAA,QAChF,EAAE,MAAM,aAAa,WAAW,iCAAiC;AAAA,MACnE;AAAA,IACF;AAAA,EACF;AACA,QAAM,QAAQ,MAAM,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,MAAM,CAAC;AAClD,MAAI,QAAQ,kBAAkB;AAC5B,UAAM,IAAI;AAAA,MACR,GAAG,GAAG,OAAO,YAAY,KAAK,CAAC,kBAAkB,YAAY,gBAAgB,CAAC;AAAA,MAC9E,EAAE,MAAM,SAAS,WAAW,wCAAwC;AAAA,IACtE;AAAA,EACF;AACF;AAEO,IAAM,eAAe,CAAC,UAC3B,MAAM,MAAM,KAAK,OAAK,EAAE,SAAS,YAAY;AAExC,IAAM,YAAY,CAAC,UACxB,MAAM,MAAM,OAAO,OAAK,WAAW,EAAE,IAAI,KAAK,EAAE,SAAS,YAAY;AAEvE,IAAM,cAAc;AAEpB,eAAe,SAAS,MAAkC;AACxD,MAAI,KAAK,QAAS,QAAO,KAAK,QAAQ,SAAS,GAAG,WAAW,EAAE,SAAS,MAAM;AAC9E,QAAM,SAAmB,CAAC;AAC1B,MAAI,OAAO;AACX,mBAAiB,SAAS,iBAAiB,KAAK,SAAS,EAAE,KAAK,cAAc,EAAE,CAAC,GAAG;AAClF,WAAO,KAAK,KAAe;AAC3B,YAAS,MAAiB;AAAA,EAC5B;AACA,SAAO,OAAO,OAAO,QAAQ,IAAI,EAAE,SAAS,MAAM;AACpD;AAOA,eAAsB,gBACpB,OACAE,WACwB;AACxB,QAAM,QAAQ,UAAU,KAAK;AAC7B,QAAM,UAAU,MAAM,SAAS,OAAO,IAAI,OAAM,OAAM;AAAA,IACpD,MAAM,EAAE;AAAA,IACR,OAAO,iBAAiB,MAAM,SAAS,CAAC,CAAC;AAAA,EAC3C,EAAE;AACF,QAAM,UAAU,OAAO,KAAK,kBAAkBA,WAAU,OAAO,GAAG,MAAM;AACxE,QAAM,QAAmB;AAAA,IACvB,MAAM;AAAA,IACN,SAAS;AAAA,IACT;AAAA,IACA,QAAQ,WAAW,QAAQ,EAAE,OAAO,OAAO,EAAE,OAAO,KAAK;AAAA,IACzD,MAAM,QAAQ;AAAA,IACd,aAAa,eAAe,YAAY;AAAA,EAC1C;AACA,QAAM,QAAQ,CAAC,GAAG,MAAM,MAAM,OAAO,OAAK,EAAE,SAAS,YAAY,GAAG,KAAK,EAAE;AAAA,IAAK,CAAC,GAAG,MAClF,EAAE,OAAO,EAAE,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,IAAI;AAAA,EAC/C;AACA,SAAO;AAAA,IACL,GAAG;AAAA,IACH;AAAA,IACA,YAAY,MAAM,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,MAAM,CAAC;AAAA,IAChD,UAAU,MAAM,SAAS,OAAO,OAAK,MAAM,gBAAgB;AAAA,EAC7D;AACF;AAEA,eAAe,WAAW,MAA+B;AACvD,QAAM,KAAK,OAAO;AAClB,MAAI;AACF,OAAG,IAAI,MAAMC,UAASF,MAAK,MAAM,WAAW,GAAG,MAAM,CAAC;AAAA,EACxD,SAAS,OAAO;AACd,QAAK,MAAgC,SAAS,SAAU,OAAM;AAAA,EAChE;AACA,SAAO;AACT;AAGA,eAAsB,SACpB,OACA,OACA,IACc;AACd,QAAM,UAAU,IAAI,MAAS,MAAM,MAAM;AACzC,MAAI,OAAO;AACX,QAAM,SAAS,YAAY;AACzB,WAAO,OAAO,MAAM,QAAQ;AAC1B,YAAM,IAAI;AACV,cAAQ,CAAC,IAAI,MAAM,GAAG,MAAM,CAAC,GAAQ,CAAC;AAAA,IACxC;AAAA,EACF;AACA,QAAM,QAAQ,IAAI,MAAM,KAAK,EAAE,QAAQ,KAAK,IAAI,OAAO,MAAM,MAAM,EAAE,GAAG,MAAM,CAAC;AAC/E,SAAO;AACT;;;ACnPA,SAAS,kBAAkB;AAC3B,SAAS,WAAAG,gBAAe;AACxB,SAAS,UAAU,SAAS,YAAY,UAAU,SAAS,OAAAC,YAAW;AAI/D,IAAM,kBAAkB,CAAC,gBAAgB,kBAAkB,cAAc,QAAQ;AAGjF,IAAM,oBAAyC,oBAAI,IAAI;AAAA,EAC5D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAGM,IAAM,iBAAsC,oBAAI,IAAI;AAAA,EACzD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAGD,IAAM,kBAAkB;AAExB,IAAM,gBAAgB;AAUf,SAAS,gBAAgB,KAAa,MAAiB,CAAC,GAAkB;AAC/E,QAAM,SAAS,IAAI,UAAU;AAC7B,QAAM,OAAO,QAAQ,IAAI,QAAQC,SAAQ,CAAC;AAC1C,QAAM,aAAuB,CAAC;AAC9B,WAAS,IAAI,QAAQ,GAAG,GAAG,MAAM,QAAQ,QAAQ,CAAC,MAAM,GAAG,IAAI,QAAQ,CAAC,EAAG,YAAW,KAAK,CAAC;AAC5F,SACE,WAAW,KAAK,OAAK,OAAO,GAAG,CAAC,GAAGC,IAAG,MAAM,CAAC,KAC7C,WAAW,KAAK,OAAK,gBAAgB,KAAK,OAAK,OAAO,GAAG,CAAC,GAAGA,IAAG,GAAG,CAAC,EAAE,CAAC,CAAC,KACxE;AAEJ;AAEA,IAAM,YAAY,CAAC,YACjB,QAAQ,WAAW,GAAG,KAAK,kBAAkB,IAAI,QAAQ,YAAY,CAAC;AAGjE,SAAS,UAAU,KAAa,MAAiB,CAAC,GAAa;AACpE,QAAM,MAAM,QAAQ,GAAG;AACvB,QAAM,OAAO,gBAAgB,KAAK,GAAG;AACrC,MAAI,CAAC,MAAM;AAET,UAAM,WAAW,SAAS,QAAQ,IAAI,QAAQD,SAAQ,CAAC,GAAG,GAAG;AAC7D,QAAI,aAAa,GAAI,QAAO,CAAC;AAC7B,UAAM,YAAY,YAAY,CAAC,SAAS,WAAW,IAAI,KAAK,CAAC,WAAW,QAAQ;AAChF,UAAM,YAAY,YAAY,WAAW,KAAK,MAAMC,IAAG,EAAE,OAAO,OAAO;AACvE,UAAM,OAAO,CAAC,GAAG,QAAQ,EAAE,QAAQ,EAAE,KAAK,OAAK,CAAC,UAAU,CAAC,CAAC,KAAK,SAAS,GAAG,EAAE;AAC/E,WAAO,OAAO,CAAC,IAAI,IAAI,CAAC;AAAA,EAC1B;AACA,QAAM,QAAQ,CAAC,SAAS,IAAI,CAAC;AAC7B,QAAM,MAAM,SAAS,MAAM,GAAG;AAC9B,aAAW,OAAO,MAAM,IAAI,MAAMA,IAAG,IAAI,CAAC,GAAG;AAC3C,QAAI,UAAU,GAAG,KAAK,eAAe,IAAI,IAAI,YAAY,CAAC,EAAG;AAC7D,UAAM,UAAU,IAAI,QAAQ,iBAAiB,EAAE;AAC/C,UAAM,OAAO,QAAQ,SAAS,GAAG;AACjC,QAAI,CAAC,QAAQ,SAAS,QAAQ,MAAM,CAAC,KAAK,IAAI,GAAG,EAAG;AACpD,QAAI,SAAS,QAAQ,MAAM,GAAG,EAAE,KAAK,IAAI,GAAG,EAAG;AAC/C,UAAM,KAAK,OAAO;AAAA,EACpB;AACA,SAAO;AACT;AAGO,SAAS,QAAQ,OAAyB;AAC/C,QAAM,QAAQ,MAAM,IAAI,OAAK,QAAQ,GAAG,GAAG,CAAC,EAAE,OAAO,OAAO;AAC5D,SAAO,MAAM,SAAS,KAAK,MAAM,KAAK,GAAG,EAAE,SAAS,cAAe,OAAM,OAAO,GAAG,CAAC;AACpF,MAAI,OAAO,QAAQ,MAAM,KAAK,GAAG,CAAC;AAClC,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,CAAC,gBAAgB,IAAI,GAAG;AAC1B,WAAO,GAAG,KAAK,MAAM,GAAG,gBAAgB,CAAC,EAAE,QAAQ,OAAO,EAAE,CAAC;AAAA,EAC/D;AACA,SAAO,gBAAgB,IAAI,IAAI,OAAO;AACxC;AAGO,SAAS,gBAAgB,KAAa,MAAiB,CAAC,GAAW;AACxE,SAAO,QAAQ,UAAU,KAAK,GAAG,CAAC;AACpC;;;AFhGO,IAAM,iBAAN,cAA6B,SAAS;AAAA,EAE3C,YACWC,WACA,aACT,MACA;AACA;AAAA,MACE,kBAAkBA,SAAQ,gCACvB,YAAY,SAAS,wBAAwB,YAAY,KAAK,IAAI,CAAC,KAAK;AAAA,MAC3E;AAAA,QACE,MACE,QACA,uCAAuC,YAAY,CAAC,IAAI,iBAAiB,YAAY,CAAC,CAAC,KAAK,EAAE;AAAA,MAClG;AAAA,IACF;AAZS,oBAAAA;AACA;AAYT,SAAK,OAAO;AAAA,EACd;AAAA,EAhBS,OAAO;AAiBlB;AAGA,eAAe,eAAe,QAAmB,MAAc,MAAe;AAC5E,QAAM,MAAO,MAA4D,OAAO;AAChF,MAAI,cAAc,MAAM,QAAQ,GAAG,IAAI,IAAI,OAAO,CAAC,MAAmB,OAAO,MAAM,QAAQ,IAAI,CAAC;AAChG,MAAI,YAAY,WAAW,GAAG;AAC5B,kBAAc,MAAM,UAAU,QAAQ,IAAI,EACvC,KAAK,OAAK,EAAE,WAAW,EACvB,MAAM,MAAM,CAAC,CAAC;AAAA,EACnB;AACA,SAAO,IAAI,eAAe,MAAM,WAAW;AAC7C;AAEO,IAAM,qBAAqB;AAC3B,IAAM,iBAAiB;AAEvB,SAAS,gBAAgB,KAAa,MAAuB;AAClE,MAAI,SAAS,QAAW;AACtB,QAAI,CAAC,gBAAgB,IAAI,GAAG;AAC1B,YAAM,IAAI,SAAS,sBAAsB,IAAI,KAAK;AAAA,QAChD,MAAM,2DAA2D,aAAa,sBAAsB,QAAQ,IAAI,KAAK,SAAS;AAAA,MAChI,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AACA,QAAM,UAAU,gBAAgB,GAAG;AACnC,MAAI,CAAC,gBAAgB,OAAO,GAAG;AAC7B,UAAM,IAAI,SAAS,sCAAsC,GAAG,KAAK;AAAA,MAC/D,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAqCA,IAAMC,gBAAe,CAAC,OAAe,IAAI,QAAc,OAAK,WAAW,GAAG,EAAE,CAAC;AAE7E,eAAsB,OAAO,MAAkB,MAA4C;AACzF,QAAM,OAAO,gBAAgB,KAAK,KAAK,KAAK,IAAI;AAChD,QAAM,QAAQ,KAAK,YAAa,MAAM,cAAc,KAAK,GAAG;AAC5D,QAAM,OAAO;AAAA,IACX;AAAA,IACA,WAAW,MAAM,MAAM;AAAA,IACvB,YAAY,MAAM;AAAA,IAClB,UAAU,MAAM;AAAA,EAClB;AACA,QAAM,OAAO,cAAc,mBAAmB,IAAI,CAAC;AACnD,QAAM,MAAM,MAAM,KAAK,OACpB,QAAQ,QAAQ,MAAM;AAAA,IACrB,QAAQ;AAAA,IACR,MAAM;AAAA,MACJ,UAAU,WAAW,KAAK;AAAA,MAC1B,GAAI,KAAK,QAAQ,SAAY,EAAE,KAAK,KAAK,IAAI,IAAI,CAAC;AAAA,MAClD,GAAI,KAAK,SAAS,EAAE,YAAY,SAAkB,IAAI,CAAC;AAAA,IACzD;AAAA,EACF,CAAC,EACA,MAAM,OAAO,UAAmB;AAC/B,QAAI,iBAAiB,eAAe,MAAM,WAAW,OAAO,MAAM,SAAS;AACzE,YAAM,MAAM,eAAe,KAAK,QAAQ,MAAM,MAAM,IAAI;AAC1D,UAAM;AAAA,EACR,CAAC;AACH,MAAI,IAAI,WAAW,UAAU;AAC3B,WAAO;AAAA,MACL,GAAG;AAAA,MACH,QAAQ,IAAI;AAAA,MACZ,KAAK,IAAI,KAAK;AAAA,MACd,WAAW,IAAI;AAAA,MACf,MAAM,IAAI;AAAA,MACV,UAAU;AAAA,IACZ;AAAA,EACF;AAEA,QAAM,SAAS,IAAI,IAAI,MAAM,MAAM,IAAI,OAAK,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AACxD,QAAM,UAAU,IAAI,QAAQ,IAAI,OAAK;AACnC,UAAM,OAAO,OAAO,IAAI,EAAE,IAAI;AAC9B,QAAI,CAAC,KAAM,OAAM,IAAI,SAAS,wDAAwD,EAAE,IAAI,EAAE;AAC9F,WAAO,EAAE,GAAG,GAAG,KAAK;AAAA,EACtB,CAAC;AACD,QAAM,aAAa,QAAQ,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,KAAK,MAAM,CAAC;AAC9D,MAAI,OAAO;AACX,MAAI,QAAQ;AACZ,OAAK,aAAa,EAAE,UAAU,GAAG,OAAO,QAAQ,QAAQ,OAAO,GAAG,WAAW,CAAC;AAC9E,QAAM,SAAS,SAAS,oBAAoB,OAAM,MAAK;AACrD,UAAM,gBAAgB,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;AACpD;AACA,aAAS,EAAE,KAAK;AAChB,SAAK,aAAa,EAAE,UAAU,MAAM,OAAO,QAAQ,QAAQ,OAAO,WAAW,CAAC;AAAA,EAChF,CAAC;AAED,QAAM,MAAM,MAAM,KAAK,OAAO;AAAA,IAC5B;AAAA,IACA,GAAG,IAAI,IAAI,mBAAmB,IAAI,SAAS,CAAC;AAAA,IAC5C,EAAE,QAAQ,uBAAuB;AAAA,EACnC;AACA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,QAAQ;AAAA,IACR,KAAK,IAAI,KAAK;AAAA,IACd,WAAW,IAAI;AAAA,IACf,MAAM,IAAI;AAAA,IACV,UAAU,QAAQ;AAAA,EACpB;AACF;AAEA,eAAe,gBACb,MACA,MACA,KACA,SACe;AACf,QAAM,QAAQ,KAAK,SAASA;AAC5B,QAAM,OAAO,KAAK,WAAY,MAAMC,UAAS,KAAK,OAAO;AACzD,WAAS,UAAU,KAAK,WAAW;AACjC,QAAI;AACF,YAAM,UAAU,KAAK,OAAO,KAAK,SAAS,IAAI;AAC9C;AAAA,IACF,SAAS,OAAO;AACd,YAAM,YAAY,iBAAiB,eAAe,MAAM;AACxD,UAAI,CAAC,aAAa,WAAW,gBAAgB;AAC3C,cAAM,IAAI,SAAS,aAAa,KAAK,IAAI,YAAa,MAAgB,OAAO,IAAI;AAAA,UAC/E,MAAM,YAAY,oDAAoD;AAAA,QACxE,CAAC;AAAA,MACH;AACA,YAAM,MAAM,MAAM,KAAK,OAAO;AAAA,IAChC;AAAA,EACF;AACF;;;AGjMA,SAAS,UAAU,SAAAC,QAAO,SAAS,YAAAC,WAAU,IAAI,QAAAC,OAAM,aAAAC,kBAAiB;AACxE,SAAS,cAAc;AACvB,SAAS,YAAAC,WAAU,SAAS,QAAAC,OAAM,WAAAC,UAAS,OAAAC,YAAW;AAEtD,SAAS,iBAAiB;AAkBnB,SAAS,UAAU,MAAc,aAAiC;AACvE,MAAI,YAAa,QAAO;AACxB,QAAM,MAAM,QAAQ,IAAI,EAAE,YAAY;AACtC,MAAI,QAAQ,WAAW,QAAQ,OAAQ,QAAO;AAC9C,MAAI,QAAQ,OAAQ,QAAO;AAC3B,SAAO;AACT;AAGO,SAAS,aAAa,MAAsB;AACjD,QAAM,OAAOC,UAAS,KAAK,QAAQ,OAAO,GAAG,CAAC;AAC9C,QAAM,OAAO,KAAK,MAAM,GAAG,KAAK,SAAS,QAAQ,IAAI,EAAE,MAAM,KAAK;AAClE,SAAO,QAAQ,CAAC,KAAK,QAAQ,eAAe,EAAE,CAAC,CAAC;AAClD;AAEO,SAAS,eAAe,MAAc,aAA8B;AACzE,SAAO,cAAc,gBAAgB,IAAI,IAAI,aAAa,IAAI;AAChE;AAEA,eAAe,aAAqE;AAClF,QAAM,MAAM,MAAM,QAAQC,MAAK,OAAO,GAAG,QAAQ,CAAC;AAClD,SAAO,EAAE,KAAK,SAAS,MAAM,GAAG,KAAK,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC,EAAE;AACzE;AAEA,eAAsB,aAAa,MAAsC;AACvE,MAAI;AACJ,MAAI;AACF,WAAO,MAAMC,MAAK,IAAI;AAAA,EACxB,QAAQ;AACN,UAAM,IAAI,SAAS,cAAc,IAAI,EAAE;AAAA,EACzC;AACA,QAAM,OAAO,UAAU,MAAM,KAAK,YAAY,CAAC;AAC/C,QAAM,cAAc,eAAe,MAAM,KAAK,YAAY,CAAC;AAC3D,MAAI,SAAS;AACX,WAAO,EAAE,MAAM,QAAQ,MAAM,KAAK,MAAM,aAAa,SAAS,YAAY;AAAA,IAAC,EAAE;AAE/E,MAAI,KAAK,OAAO;AACd,UAAM,IAAI;AAAA,MACR,GAAGF,UAAS,IAAI,CAAC,OAAO,YAAY,KAAK,IAAI,CAAC,kBAAkB,YAAY,gBAAgB,CAAC;AAAA,IAC/F;AACF,QAAM,MAAM,MAAM,WAAW;AAC7B,MAAI;AACF,QAAI,SAAS,QAAQ;AACnB,UAAI,KAAK,OAAO;AACd,cAAM,IAAI;AAAA,UACR,GAAGA,UAAS,IAAI,CAAC,OAAO,YAAY,KAAK,IAAI,CAAC,kBAAkB,YAAY,cAAc,CAAC;AAAA,QAC7F;AACF,YAAM,SAAS,MAAMC,MAAK,IAAI,KAAK,YAAY,CAAC;AAAA,IAClD,WAAW,SAAS,OAAO;AACzB,YAAM,WAAW,MAAME,UAAS,IAAI,GAAG,IAAI,GAAG;AAAA,IAChD,OAAO;AACL,YAAM,OAAOH,UAAS,IAAI;AAC1B,YAAM,SAAS,MAAMC,MAAK,IAAI,KAAK,IAAI,CAAC;AACxC,YAAMG,WAAUH,MAAK,IAAI,KAAK,YAAY,GAAG,YAAY,IAAI,CAAC;AAAA,IAChE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,IAAI,QAAQ;AAClB,UAAM;AAAA,EACR;AACA,SAAO,EAAE,MAAM,QAAQ,MAAM,KAAK,IAAI,KAAK,aAAa,SAAS,IAAI,QAAQ;AAC/E;AAIA,IAAM,aAAa,oBAAI,IAAI,CAAC,aAAa,aAAa,CAAC;AAMhD,SAAS,aAAa,MAAwC;AACnE,QAAM,aAAa,KAAK,QAAQ,OAAO,GAAG;AAC1C,MAAI,WAAW,SAAS,IAAI,EAAG,QAAO;AACtC,MAAI,WAAW,WAAW,GAAG,KAAK,aAAa,KAAK,UAAU,EAAG,QAAO;AACxE,QAAM,WAAW,WAAW,MAAM,GAAG,EAAE,OAAO,OAAK,MAAM,MAAM,MAAM,GAAG;AACxE,MAAI,SAAS,SAAS,IAAI,EAAG,QAAO;AACpC,MAAI,WAAW,SAAS,GAAG,KAAK,SAAS,WAAW,EAAG,QAAO;AAC9D,MAAI,SAAS,CAAC,MAAM,WAAY,QAAO;AACvC,MAAI,SAAS,KAAK,OAAK,EAAE,WAAW,GAAG,CAAC,EAAG,QAAO;AAClD,MAAI,WAAW,KAAK,SAAS,GAAG,EAAE,KAAK,IAAI,YAAY,CAAC,EAAG,QAAO;AAClE,SAAO,SAAS,KAAK,GAAG;AAC1B;AAGO,SAAS,mBAAmB,OAA2B;AAC5D,MAAI,UAAU;AACd,aAAS;AACP,UAAM,QAAQ,QAAQ,CAAC,GAAG,MAAM,GAAG,EAAE,CAAC;AACtC,QAAI,CAAC,SAAS,CAAC,QAAQ,MAAM,OAAK,EAAE,SAAS,GAAG,KAAK,EAAE,MAAM,GAAG,EAAE,CAAC,MAAM,KAAK,EAAG,QAAO;AACxF,cAAU,QAAQ,IAAI,OAAK,EAAE,MAAM,MAAM,SAAS,CAAC,CAAC;AAAA,EACtD;AACF;AAGA,eAAsB,WAAW,MAAkB,MAAiC;AAClF,QAAM,SAAmB,CAAC;AAC1B,MAAI,WAAW;AACf,MAAI,QAAQ;AACZ,MAAI;AACJ,MAAI;AACF,cAAU,UAAU,MAAM;AAAA,MACxB,QAAQ,UAAQ;AACd,cAAM,OAAO,aAAa,KAAK,IAAI;AACnC,YAAI,SAAS,UAAU;AACrB,iBAAO,KAAK,KAAK,IAAI;AACrB,iBAAO;AAAA,QACT;AACA,YAAI,SAAS,KAAM,QAAO;AAC1B;AACA,oBAAY,KAAK;AACjB,YAAI,KAAK,eAAe;AACtB,gBAAM,IAAI;AAAA,YACR,GAAG,IAAI,kBAAkB,YAAY,KAAK,YAAY,CAAC,kBAAkB,YAAY,cAAc,CAAC;AAAA,UACtG;AACF,YAAI,WAAW;AACb,gBAAM,IAAI;AAAA,YACR,gCAAgC,YAAY,gBAAgB,CAAC;AAAA,UAC/D;AACF,YAAI,QAAQ,UAAW,OAAM,IAAI,SAAS,yBAAyB,SAAS,QAAQ;AACpF,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAAA,EACH,SAAS,OAAO;AACd,QAAI,iBAAiB,SAAU,OAAM;AACrC,UAAM,IAAI,SAAS,2BAA4B,MAAgB,OAAO,EAAE;AAAA,EAC1E;AACA,MAAI,OAAO;AACT,UAAM,IAAI;AAAA,MACR,qEAAqE,OAAO,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA,IACpG;AAEF,QAAM,QAAQ,OAAO,KAAK,OAAO;AACjC,QAAM,QAAQ,oBAAI,IAAoB;AACtC,QAAM,OAAO,MAAM,IAAI,OAAK,aAAa,CAAC,CAAW;AACrD,QAAM,YAAY,mBAAmB,IAAI;AACzC,QAAM,QAAQ,CAAC,GAAG,MAAM;AACtB,UAAM,IAAI,GAAG,UAAU,CAAC,CAAW;AAAA,EACrC,CAAC;AACD,MAAI,MAAM,WAAW,EAAG,OAAM,IAAI,SAAS,+BAA+B;AAE1E,QAAM,OAAOI,SAAQ,IAAI;AACzB,MAAI,QAAQ;AACZ,QAAM,UAAoB,CAAC;AAC3B,aAAW,QAAQ,OAAO;AACxB,UAAM,UAAU,QAAQ,IAAI;AAC5B,aAAS,QAAQ;AACjB,QAAI,QAAQ,SAAS,kBAAkB,QAAQ;AAC7C,YAAM,IAAI,SAAS,+CAA+C;AACpE,UAAM,MAAM,MAAM,IAAI,IAAI;AAC1B,UAAM,SAASA,SAAQ,MAAM,GAAG,IAAI,MAAM,GAAG,CAAC;AAC9C,QAAI,CAAC,OAAO,WAAW,OAAOC,IAAG,EAAG,OAAM,IAAI,SAAS,2BAA2B,IAAI,EAAE;AACxF,UAAMC,OAAMN,MAAK,QAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AACnD,UAAMG,WAAU,QAAQ,OAAO;AAC/B,YAAQ,KAAK,GAAG;AAAA,EAClB;AACA,SAAO,QAAQ,KAAK;AACtB;AAIA,IAAMI,cAAa,CAAC,MAAc,EAAE,QAAQ,YAAY,OAAK,KAAK,EAAE,WAAW,CAAC,CAAC,GAAG;AAG7E,SAAS,YAAY,MAAsB;AAChD,QAAM,OAAOA,YAAW,mBAAmB,IAAI,CAAC;AAChD,QAAM,QAAQA,YAAW,IAAI;AAC7B,QAAM,MAAM,QAAQ,IAAI,EAAE,YAAY;AACtC,MAAI;AACJ,MAAI,4CAA4C,KAAK,GAAG;AACtD,WAAO,aAAa,IAAI,UAAU,KAAK;AAAA,WAChC,QAAQ,OAAQ,QAAO,gBAAgB,IAAI,YAAY,KAAK;AAAA,WAC5D,yBAAyB,KAAK,GAAG,EAAG,QAAO,eAAe,IAAI;AAAA,WAC9D,6BAA6B,KAAK,GAAG,EAAG,QAAO,eAAe,IAAI;AAAA,MACtE,QAAO;AACZ,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA,SAKA,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAUI,KAAK,sBAAsB,IAAI,oCAAoC,IAAI;AAAA,QACjF,IAAI;AAAA;AAAA;AAAA;AAIZ;;;ACtNA,SAAS,OAAO,WAAAC,UAAS,YAAAC,WAAU,YAAAC,WAAU,QAAAC,aAAY;AACzD,SAAS,OAAO,aAAa;AAC7B,SAAS,qBAAqB;AAGvB,IAAM,oBAAoB;AAoE1B,IAAM,iBAAiB;AAE9B,IAAM,YAAY,oBAAI,IAAI,CAAC,gBAAgB,YAAY,WAAW,WAAW,cAAc,CAAC;AAC5F,IAAM,oBAAoB,oBAAI,IAAI,CAAC,iBAAiB,OAAO,WAAW,QAAQ,CAAC;AAC/E,IAAM,iBAAiB;AACvB,IAAM,gBAAgB;AAEtB,IAAM,kBAAkB;AAEjB,IAAM,SAAmB;AAAA,EAC9B,MAAM,KAAK,MAAM;AACf,QAAI;AACF,YAAM,IAAI,MAAMC,MAAK,IAAI;AACzB,aAAO,EAAE,QAAQ,EAAE,OAAO,GAAG,aAAa,EAAE,YAAY,GAAG,SAAS,EAAE,SAAS,MAAM,EAAE,KAAK;AAAA,IAC9F,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EACA,MAAM,QAAQ,MAAM;AAClB,QAAI;AACF,YAAM,UAAU,MAAMC,SAAQ,MAAM,EAAE,eAAe,KAAK,CAAC;AAC3D,YAAM,MAAiB,CAAC;AACxB,iBAAW,KAAK,SAAS;AACvB,YAAI,EAAE,eAAe,GAAG;AAEtB,gBAAM,IAAI,MAAMD,MAAK,GAAG,IAAI,IAAI,EAAE,IAAI,EAAE,EAAE,MAAM,MAAM,IAAI;AAC1D,cAAI,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,QAAQ,GAAG,OAAO,CAAC,GAAG,aAAa,MAAM,CAAC;AAAA,QAC7E,MAAO,KAAI,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,EAAE,OAAO,GAAG,aAAa,EAAE,YAAY,EAAE,CAAC;AAAA,MACpF;AACA,aAAO;AAAA,IACT,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA,EACA,MAAM,SAAS,MAAM;AACnB,WAAOE,UAAS,IAAI,EAAE,MAAM,MAAM,IAAI;AAAA,EACxC;AAAA,EACA,MAAM,SAAS,MAAM;AACnB,QAAI;AACF,UAAI,EAAE,MAAM,MAAM,IAAI,GAAG,OAAO,EAAG,QAAO;AAC1C,aAAO,MAAMC,UAAS,MAAM,MAAM;AAAA,IACpC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEA,IAAM,UAAU,CAAC,aAA+B,aAAa,UAAU,QAAQ;AAE/E,IAAM,SAAS,CAAC,UACd,QAAQ,OAAO,KAAK,CAAC,KAAK,CAAC,OAAO,KAAK,EAAE,WAAW,IAAI;AAG1D,eAAe,WACb,KACA,MACA,IAC6B;AAC7B,QAAMC,WAAU,KAAK,IAAI,OAAO,GAAG,MAAM;AACzC,MAAI,OAAOA,QAAO,EAAG,QAAOA;AAC5B,QAAM,aAAa,KAAK,IAAI,mBAAmB,MAAM,KAAK,KAAK,MAAM,SAAS;AAC9E,QAAM,OAAO,MAAM,GAAG,SAAS,MAAM,KAAK,YAAY,gBAAgB,CAAC;AACvE,QAAM,QAAQ,MAAM,MAAM,IAAI,OAAO,QAAQ,GAAG,kBAAkB,GAAG,CAAC;AACtE,MAAI,CAAC,QAAQ,CAAC,EAAG,QAAO;AACxB,SAAO,MAAM,CAAC,EAAE,QAAQ,mBAAmB,KAAK,IAAI;AACtD;AAGA,eAAsB,YAAY,MAA4C;AAC5E,QAAM,KAAK,KAAK,MAAM;AACtB,QAAM,IAAI,QAAQ,KAAK,QAAQ;AAC/B,QAAM,EAAE,MAAM,KAAK,SAAS,IAAI;AAChC,QAAM,WAAW,aAAa,WAAW,OAAO,IAAI,WAAW,IAAI,IAAI,cAAc;AACrF,QAAM,QAAsB,CAAC;AAC7B,QAAM,MAAM,CAAC,OAAe,MAA0B,OAAe,WAAW,UAAU;AACxF,QAAI,CAAC,KAAM;AACX,UAAM,OAAO,EAAE,QAAQ,IAAI;AAC3B,QAAI,MAAM,KAAK,OAAK,EAAE,SAAS,IAAI,EAAG;AACtC,UAAM,KAAK,EAAE,OAAO,MAAM,MAAM,OAAO,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC,EAAG,CAAC;AAAA,EAC5E;AAEA,QAAM,MAAM,EAAE,QAAQ,KAAK,GAAG;AAC9B,MAAI,QAAQ,EAAE,MAAM,GAAG,EAAE,QAAQ,QAAQ,EAAE,QAAQ,QAAQ,EAAG,KAAI,kBAAkB,KAAK,CAAC;AAE1F,QAAM,aAAa,OAAO,KAAK,YAAY,IACvC,KAAK,eACL,OAAO,IAAI,iBAAiB,CAAC,IAC3B,IAAI,iBAAiB,IACrB;AACN,QAAM,mBACJ,aAAa,UACP,MAAM,WAAW,YAAY,MAAM,EAAE,KAAM,EAAE,KAAK,MAAM,WAAW,IACrE,EAAE,KAAK,UAAU,WAAW;AAClC,MAAI,aAAa,aAAa,WAAW,YAAY,MAAM,QAAQ,IAAI,kBAAkB,CAAC;AAC1F,MAAI,aAAa,kBAAkB,CAAC;AAEpC,QAAM,UACJ,aAAa,UACP,MAAM,WAAW,WAAW,MAAM,EAAE,KAAM,EAAE,KAAK,MAAM,SAAS,IAClE,EAAE,KAAK,UAAU,SAAS;AAChC,MAAI,WAAW,SAAS,CAAC;AACzB,MAAI,aAAa,WAAW,OAAO,IAAI,QAAQ;AAC7C,QAAI,WAAW,EAAE,KAAK,IAAI,UAAU,SAAS,GAAG,CAAC;AAEnD,QAAM,YACJ,aAAa,UACP,MAAM,WAAW,aAAa,MAAM,EAAE,KAAM,EAAE,KAAK,MAAM,WAAW,IACtE,EAAE,KAAK,UAAU,WAAW;AAClC,MAAI,oBAAoB,EAAE,KAAK,WAAW,QAAQ,GAAG,CAAC;AACtD,MAAI,YAAY,EAAE,KAAK,UAAU,QAAQ,GAAG,CAAC;AAE7C,QAAM,eACJ,aAAa,WACT,EAAE,KAAK,MAAM,WAAW,uBAAuB,QAAQ,IACvD,aAAa,UACX,EAAE;AAAA,IACA,OAAO,IAAI,OAAO,IAAI,IAAI,UAAU,EAAE,KAAK,UAAU,WAAW,SAAS;AAAA,IACzE;AAAA,EACF,IACA,EAAE,KAAK,IAAI,mBAAmB,EAAE,KAAK,MAAM,SAAS,GAAG,QAAQ;AACvE;AAAA,IACE;AAAA,IACA,EAAE,KAAK,cAAc,2BAA2B;AAAA,IAChD;AAAA,IACA;AAAA,EACF;AAGA,MAAI,CAAC,GAAG,SAAU,QAAO;AACzB,QAAM,OAAqB,CAAC;AAC5B,aAAW,QAAQ,OAAO;AACxB,UAAM,OAAQ,MAAM,GAAG,SAAS,KAAK,IAAI,KAAM,KAAK;AACpD,QAAI,CAAC,KAAK,KAAK,OAAK,EAAE,SAAS,IAAI,EAAG,MAAK,KAAK,EAAE,GAAG,MAAM,KAAK,CAAC;AAAA,EACnE;AACA,SAAO;AACT;AAEO,SAAS,WAAW,OAAe,MAAc,UAAmC;AACzF,MAAI,UAAU,IAAK,QAAO;AAC1B,MAAI,MAAM,WAAW,IAAI,KAAM,aAAa,WAAW,MAAM,WAAW,KAAK;AAC3E,WAAO,QAAQ,QAAQ,EAAE,KAAK,MAAM,MAAM,MAAM,CAAC,CAAC;AACpD,SAAO;AACT;AAgBA,eAAe,KACb,OACA,MACA,OACgC;AAChC,QAAM,KAAK,KAAK,MAAM;AACtB,QAAM,IAAI,QAAQ,KAAK,QAAQ;AAC/B,QAAM,MAAM,KAAK,OAAO,KAAK;AAC7B,QAAM,WAAW,IAAI,KAAK,KAAK,gBAAgB;AAC/C,MAAI,SAAS,KAAK,eAAe;AACjC,QAAM,OAAO,CAAC,SAAiB,KAAK,WAAW,GAAG,KAAK,UAAU,IAAI,IAAI;AAGzE,QAAM,WAAyB,CAAC;AAChC,aAAW,QAAQ,OAAO;AACxB,QAAI,CAAC,KAAK,UAAU;AAClB,eAAS,KAAK,IAAI;AAClB;AAAA,IACF;AACA,QAAI,QAAQ,CAAC,KAAK,IAAI;AACtB,aAAS,QAAQ,GAAG,QAAQ,KAAK,SAAS,MAAM,QAAQ,SAAS;AAC/D,YAAM,OAAiB,CAAC;AACxB,iBAAW,OAAO,OAAO;AACvB,mBAAW,KAAK,MAAM,GAAG,QAAQ,GAAG,GAAG;AACrC,cAAI,CAAC,EAAE,eAAe,KAAK,EAAE,IAAI,KAAK,kBAAkB,IAAI,EAAE,IAAI,EAAG;AACrE,gBAAM,QAAQ,EAAE,KAAK,KAAK,EAAE,IAAI;AAChC,cAAI,EAAE,SAAS;AACb,qBAAS,KAAK,EAAE,OAAO,KAAK,OAAO,MAAM,OAAO,OAAO,cAAc,CAAC;AAAA,cACnE,MAAK,KAAK,KAAK;AAAA,QACtB;AAAA,MACF;AACA,cAAQ;AAAA,IACV;AAAA,EACF;AAEA,aAAW,QAAQ,UAAU;AAC3B,QAAI,QAAQ,CAAC,KAAK,IAAI;AACtB,aAAS,QAAQ,GAAG,SAAS,KAAK,SAAS,MAAM,QAAQ,SAAS;AAChE,YAAM,OAAiB,CAAC;AACxB,iBAAW,OAAO,OAAO;AACvB,YAAI,IAAI,IAAI,YAAY,UAAU,EAAG,QAAO,EAAE,UAAU,MAAM;AAC9D,cAAM,UAAU,MAAM,GAAG,QAAQ,GAAG;AACpC,kBAAU,QAAQ;AAClB,mBAAW,SAAS,SAAS;AAC3B,cAAI,MAAM,KAAK,WAAW,GAAG,EAAG;AAChC,gBAAM,OAAO,EAAE,KAAK,KAAK,MAAM,IAAI;AACnC,gBAAM,SAAS,MAAM,MAAM,EAAE,MAAM,MAAM,OAAO,UAAU,QAAQ,CAAC;AACnE,cAAI,MAAM,eAAe,CAAC,KAAK,MAAM,IAAI,KAAK,WAAW,UAAU,QAAQ,KAAK;AAC9E,iBAAK,KAAK,IAAI;AAAA,QAClB;AAAA,MACF;AACA,cAAQ;AAAA,IACV;AAAA,EACF;AACA,SAAO,EAAE,UAAU,KAAK;AAC1B;AAGA,SAAS,uBAAuB,MAAsB;AACpD,SAAO,KAAK,QAAQ,0BAA0B,EAAE;AAClD;AAEA,SAAS,WAAW,WAAmB,QAAyB;AAC9D,QAAM,IAAI,UAAU,YAAY;AAChC,QAAM,IAAI,OAAO,YAAY;AAC7B,SAAO,MAAM,KAAK,uBAAuB,CAAC,MAAM,uBAAuB,CAAC;AAC1E;AAEA,IAAM,gBAAgB,CAAC,SACrB,KAAK,MAAM,QAAQ,EAAE,OAAO,OAAK,MAAM,MAAM,MAAM,OAAO,MAAM,GAAG;AAGrE,SAAS,YAAY,MAAc,QAA0B;AAC3D,QAAM,OAAO,cAAc,IAAI;AAC/B,MAAI,QAAQ;AACZ,WAAS,IAAI,GAAG,KAAK,KAAK,IAAI,KAAK,QAAQ,OAAO,MAAM,GAAG,KAAK;AAC9D,QAAI,KAAK,KAAK,SAAS,CAAC,GAAG,YAAY,MAAM,OAAO,OAAO,SAAS,CAAC,GAAG,YAAY,EAAG;AACvF;AAAA,EACF;AACA,SAAO;AACT;AAEA,IAAM,uBAAuB,CAAC,UAAkB,gBAAgB,KAAK,MAAM,QAAQ,OAAO,GAAG,CAAC;AAE9F,SAAS,eAAe,KAAa,MAA6B;AAChE,MAAI,QAAQ,IAAI,KAAK,EAAE,QAAQ,kBAAkB,IAAI;AACrD,MAAI,MAAM,WAAW,SAAS,GAAG;AAC/B,QAAI;AACF,cAAQ,cAAc,OAAO,EAAE,SAAS,KAAK,aAAa,QAAQ,CAAC;AAAA,IACrE,QAAQ;AACN,cAAQ,mBAAmB,MAAM,MAAM,UAAU,MAAM,CAAC;AAAA,IAC1D;AAAA,EACF;AACA,SAAO,WAAW,OAAO,KAAK,MAAM,KAAK,QAAQ;AACnD;AAMA,eAAsB,aAAa,OAAe,MAAwC;AACxF,QAAM,KAAK,KAAK,MAAM;AACtB,QAAM,IAAI,QAAQ,KAAK,QAAQ;AAC/B,QAAM,QAAQ,eAAe,OAAO,IAAI;AACxC,MAAI,CAAC,MAAO,OAAM,IAAI,SAAS,eAAe;AAE9C,QAAM,SAAS,EAAE,WAAW,KAAK,IAAI,EAAE,UAAU,KAAK,IAAI,EAAE,QAAQ,KAAK,KAAK,KAAK;AACnF,QAAM,aAAa,MAAM,GAAG,KAAK,MAAM;AACvC,MAAI,eAAe,WAAW,UAAU,WAAW,cAAc;AAC/D,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS;AAAA,MACT,aAAa,WAAW;AAAA,MACxB,cAAc,CAAC;AAAA,IACjB;AAAA,EACF;AAEA,QAAM,SAAS,cAAc,KAAK;AAClC,QAAM,OAAO,OAAO,GAAG,EAAE;AACzB,QAAM,QAAQ,MAAM,YAAY,IAAI;AACpC,MAAI,CAAC,KAAM,OAAM,SAAS,OAAO,KAAK;AAEtC,QAAM,QAAkF,CAAC;AACzF,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,KAAK,OAAO,MAAM,OAAO,EAAE,MAAM,MAAM,MAAM,MAAM;AACvD,QAAI,EAAE,MAAM,UAAU,MAAM,gBAAgB,CAAC,WAAW,MAAM,MAAM,IAAI,EAAG;AAC3E,QAAI,KAAK,IAAI,IAAI,EAAG;AACpB,SAAK,IAAI,IAAI;AACb,UAAM,IAAI,MAAM,GAAG,KAAK,IAAI;AAC5B,QAAI,CAAC,EAAG;AACR,UAAM,KAAK;AAAA,MACT;AAAA,MACA,SAAS,KAAK;AAAA,MACd,MAAM,EAAE,cAAc,WAAW;AAAA,MACjC,UAAU,IAAI,KAAK,EAAE,OAAO,EAAE,YAAY;AAAA,MAC1C,MAAM,EAAE;AAAA,MACR,OAAO,YAAY,MAAM,MAAM;AAAA,MAC/B,SAAS,EAAE;AAAA,MACX,aAAa,EAAE;AAAA,IACjB,CAAC;AACD,WAAO;AAAA,EACT,CAAC;AACD,MAAI,MAAM,WAAW,EAAG,OAAM,SAAS,OAAO,KAAK;AAEnD,QAAM,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO;AAC/D,QAAM,QAAQ,CAAC,EAAE,OAAO,IAAI,SAAS,IAAI,aAAa,IAAI,GAAG,EAAE,MAA8B;AAC7F,QAAM,CAAC,MAAM,GAAG,IAAI,IAAI;AACxB,SAAO;AAAA,IACL,MAAM,KAAK;AAAA,IACX,SAAS,KAAK;AAAA,IACd,aAAa,KAAK;AAAA,IAClB,cAAc,KAAK,MAAM,GAAG,CAAC,EAAE,IAAI,KAAK;AAAA,EAC1C;AACF;AAEA,SAAS,SAAS,OAAe,OAA+B;AAC9D,QAAM,QAAQ,MAAM,IAAI,OAAK,GAAG,EAAE,KAAK,KAAK,EAAE,IAAI,GAAG,EAAE,KAAK,IAAI;AAChE,QAAM,UAAU,qBAAqB,KAAK,IACtC,2LACA;AACJ,SAAO,IAAI,SAAS,mBAAmB,KAAK,gCAAgC,KAAK,IAAI,OAAO,IAAI;AAAA,IAC9F,MAAM;AAAA,EACR,CAAC;AACH;AAaA,IAAM,aAAa;AAMnB,eAAsB,UACpB,MACA,OAAyB,CAAC,GACkD;AAC5E,QAAM,KAAK,KAAK,MAAM;AACtB,QAAM,IAAI,QAAQ,KAAK,QAAQ;AAC/B,QAAM,OAAO,KAAK,OAAO,KAAK,KAAK;AACnC,QAAM,QAAQ,OAAO,KAAK,QAAQ,MAAM,KAAK,KAAK,KAAK;AACvD,QAAM,QAAQ,KAAK,OAAO,KAAK,EAAE,YAAY;AAC7C,QAAM,QAAQ,MAAM,YAAY,IAAI;AACpC,QAAM,QAAQ,oBAAI,IAA6C;AAC/D,QAAM,YAAY,IAAI,IAAI,MAAM,IAAI,OAAK,EAAE,IAAI,CAAC;AAEhD,QAAM,EAAE,SAAS,IAAI,MAAM,KAAK,OAAO,MAAM,OAAO,EAAE,MAAM,MAAM,MAAM,MAAM;AAC5E,QAAI,MAAM,aAAa;AACrB,UAAI,UAAU,IAAI,IAAI,EAAG;AACzB,YAAM,SAAS,MAAM,GAAG,QAAQ,IAAI,GAAG,KAAK,OAAK,EAAE,UAAU,kBAAkB,KAAK,EAAE,IAAI,CAAC;AAC3F,UAAI,CAAC,MAAO;AACZ,YAAMC,KAAI,MAAM,GAAG,KAAK,EAAE,KAAK,MAAM,MAAM,IAAI,CAAC;AAChD,UAAIA,MAAKA,GAAE,WAAW,UAAU,CAAC,SAAS,MAAM,KAAK,YAAY,EAAE,SAAS,KAAK;AAC/E,cAAM,IAAI,MAAM;AAAA,UACd;AAAA,UACA,SAAS,KAAK;AAAA,UACd,MAAM;AAAA,UACN,UAAU,IAAI,KAAKA,GAAE,OAAO,EAAE,YAAY;AAAA,UAC1C,MAAMA,GAAE;AAAA,UACR,SAASA,GAAE;AAAA,QACb,CAAC;AACH,aAAO;AAAA,IACT;AACA,QAAI,CAAC,MAAM,UAAU,CAAC,WAAW,KAAK,MAAM,IAAI,EAAG;AACnD,QAAI,SAAS,CAAC,MAAM,KAAK,YAAY,EAAE,SAAS,KAAK,EAAG;AACxD,UAAM,IAAI,MAAM,GAAG,KAAK,IAAI;AAC5B,QAAI,CAAC,KAAK,EAAE,UAAU,SAAS,MAAM,IAAI,IAAI,EAAG;AAChD,UAAM,IAAI,MAAM;AAAA,MACd;AAAA,MACA,SAAS,KAAK;AAAA,MACd,MAAM;AAAA,MACN,UAAU,IAAI,KAAK,EAAE,OAAO,EAAE,YAAY;AAAA,MAC1C,MAAM,EAAE;AAAA,MACR,SAAS,EAAE;AAAA,IACb,CAAC;AACD,WAAO;AAAA,EACT,CAAC;AAED,QAAM,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,EAC7B,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,OAAO,EACpC,MAAM,GAAG,KAAK,SAAS,EAAE,EACzB,IAAI,CAAC,EAAE,SAAS,IAAI,GAAG,EAAE,MAAM,CAAC;AACnC,SAAO,EAAE,OAAO,UAAU,OAAO,SAAS;AAC5C;;;ALhbA,eAAsB,UACpB,KACA,OACA,MACe;AACf,QAAM,SAAS,cAAc,GAAG;AAChC,QAAM,MAAM,IAAI,eAAe,CAAC,KAAK;AAErC,QAAM,OAAO,MAAM,MAAM,kBAAkB,MAAM,IAAI,aAAa,OAAO,SAAS;AAElF,QAAM,UAAU,MAAM,aAAa,SAAS,KAAK,IAAI,UAAU,oBAAoB,CAAC;AACpF,MAAI,QAAQ,YAAY,gBAAgB;AACtC,QAAI,IAAI,KAAK,YAAY,QAAQ,OAAO,KAAK,QAAQ,IAAI,EAAE;AAC3D,QAAI,QAAQ,aAAa;AACvB,UAAI,IAAI;AAAA,QACN,uBAAuB,QAAQ,aAAa,IAAI,OAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;AAAA,MACzE;AAAA,EACJ;AACA,QAAM,WAAW,MAAM,aAAa,QAAQ,IAAI;AAChD,MAAI;AACF,UAAM,eAAe,KAAK,QAAQ,MAAM,UAAU,MAAM,GAAG;AAAA,EAC7D,UAAE;AACA,UAAM,SAAS,QAAQ;AAAA,EACzB;AACF;AAEA,eAAe,eACb,KACA,QACA,MACA,UACA,MACA,KACe;AACf,MAAI,QAAQ,MAAM,cAAc,SAAS,GAAG;AAC5C,MAAI,OACF,KAAK,SAAS,SAAY,gBAAgB,SAAS,KAAK,KAAK,IAAI,IAAI,SAAS;AAChF,MAAI,KAAK,SAAS,UAAa,IAAK,QAAO,MAAM,gBAAgB,KAAK,QAAQ,MAAM,IAAI;AAExF,MAAI,CAAC,aAAa,KAAK,GAAG;AACxB,UAAM,QAAQ,UAAU,KAAK,EAAE;AAC/B,UAAM,OAAO,OAAO,WAAW,MAAM,IAAI,IAAI;AAC7C,UAAM,UAAU,oCAA+B,IAAI;AACnD,UAAM,SACJ,KAAK,aAAa,OACd,SACA,KAAK,aAAa,QAChB,UACA,MACE,MAAM,WAAW,KAAK,KAAK,IAC3B,QAAQ,IACN,SACA;AACZ,QAAI,WAAW,QAAQ;AACrB,cAAQ,MAAM,gBAAgB,OAAO,IAAI;AACzC,UAAI,IAAI,KAAK,gCAAgC,KAAK,aAAa,UAAU,IAAI,KAAK,GAAG,EAAE;AAAA,IACzF,MAAO,KAAI,IAAI,KAAK,OAAO;AAAA,EAC7B;AAEA,MAAI,gBAAgB;AACpB,QAAM,SAAS,MAAM;AAAA,IACnB,EAAE,QAAQ,OAAO,IAAI,MAAM;AAAA,IAC3B;AAAA,MACE,KAAK,SAAS;AAAA,MACd;AAAA,MACA,UAAU;AAAA,MACV,KAAK,KAAK,MAAM,OAAO;AAAA,MACvB,QAAQ,KAAK;AAAA,MACb,YAAY,OAAK;AACf,YAAI,EAAE,UAAU,EAAG;AACnB,wBAAgB;AAChB,YAAI;AAAA,UACF,GAAGC,OAAM,KAAK,OAAO,CAAC,cAAc,EAAE,QAAQ,IAAI,EAAE,KAAK,eAAY,YAAY,EAAE,KAAK,CAAC,IAAI,YAAY,EAAE,UAAU,CAAC;AAAA,QACxH;AAAA,MACF;AAAA,IACF;AAAA,EACF,EAAE,QAAQ,MAAM;AACd,QAAI,cAAe,KAAI,SAAS,IAAI;AAAA,EACtC,CAAC;AAED,aAAW,WAAW,OAAO,SAAU,KAAI,YAAY,iBAAkB,KAAI,IAAI,KAAK,OAAO;AAC7F,QAAM,UAAU,GAAG,OAAO,SAAS,WAAW,YAAY,OAAO,UAAU,CAAC;AAC5E,MAAI,OAAO,WAAW,YAAa,KAAI,IAAI,KAAK,aAAaA,OAAM,IAAI,IAAI,OAAO,GAAG,CAAC,EAAE;AAAA,WAC/E,OAAO,WAAW;AACzB,QAAI,IAAI,QAAQ,oBAAoB,OAAO,SAAS,IAAIA,OAAM,IAAI,IAAI,OAAO,GAAG,CAAC,EAAE;AAAA;AAEnF,QAAI,IAAI;AAAA,MACN,YAAY,OAAO,IAAI,IAAIA,OAAM,IAAI,IAAI,OAAO,cAAc,OAAO,QAAQ,aAAa,OAAO,SAAS,GAAG,CAAC;AAAA,IAChH;AAIF,QAAM,QACJ,OAAO,WAAW,cACd,QAEE,MAAM;AAAA,IACJ,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,MAAM,MAAM,IAAI,OAAK,EAAE,IAAI;AAAA,IAC3B,EAAE,UAAU,IAAI,UAAU,MAAM,OAAK,IAAI,IAAI,KAAK,CAAC,EAAE;AAAA,EACvD,GACA;AAER,MAAI,IAAI,KAAK,EAAE,QAAQ,OAAO,QAAQ,MAAM,OAAO,MAAM,MAAM,GAAG,MAAM;AACtE,UAAM,QAAQ,CAACA,OAAM,KAAK,OAAO,GAAG,CAAC;AACrC,QAAI,OAAO,KAAK,eAAe;AAC7B,YAAM;AAAA,QACJA,OAAM;AAAA,UACJ,6DAA6D,IAAI,OAAO,UAAU,OAAO,IAAI;AAAA,QAC/F;AAAA,MACF;AACF,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB,CAAC;AACH;AAMA,eAAsB,WAAW,KAAqB,OAAuC;AAC3F,QAAM,WACJ,QAAQ,IACJ,+HACA;AACN,aAAS;AACP,UAAM,UAAU,MAAM,IAAI,OAAO,QAAQ,GAAG,KAAK,EAAE,YAAY;AAC/D,QAAI,QAAQ,MAAM,WAAW,MAAM,WAAW,OAAO,WAAW,QAAS,QAAO;AAChF,QAAI,WAAW,OAAO,WAAW,QAAS,QAAO;AACjD,QAAI,WAAW,OAAO,WAAW,WAAW,WAAW,OAAO,WAAW,QAAQ,WAAW;AAC1F,YAAM,IAAI,SAAS,wCAAwC;AAAA,QACzD,MAAM;AAAA,MACR,CAAC;AAAA,EACL;AACF;AAMA,eAAsB,gBACpB,KACA,QACA,WACA,MACiB;AACjB,QAAM,QAAQ,CAAC,MAAe,OAAO,WAAM,WAAW,GAAG,IAAI,CAAC,KAAK;AACnE,QAAM,WAAW,CAAC,GAAW,SAC3B,IAAI,IAAI,KAAK,cAAcA,OAAM,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,KAAKA,OAAM,IAAI,IAAI,IAAI,GAAG,CAAC,EAAE;AAElF,MAAI,YAAY;AAChB,aAAS;AACP,UAAM,QAAQ,MAAM,UAAU,QAAQ,SAAS;AAC/C,QAAI;AACJ,QAAI,MAAM,WAAW,eAAe,MAAM,WAAW,SAAS;AAC5D,iBAAW;AACX,eAAS,WAAW,MAAM,WAAW,UAAU,+BAA+B,KAAK;AAAA,IACrF,OAAO;AACL,YAAM,MAAM,MAAM,WAAW,UAAU,aAAa;AACpD,YAAM,eAAe,MAAM,YAAY,SACnC,iBAAiB,MAAM,YAAY,KAAK,IAAI,CAAC,KAC7C;AACJ,UAAI,IAAI,KAAK,GAAG,SAAS,IAAI,GAAG,IAAI,YAAY,EAAE;AAClD,iBAAW,MAAM,YAAY,CAAC;AAC9B,UAAI,SAAU,UAAS,UAAU,KAAK;AAAA,IACxC;AAEA,eAAS;AACP,YAAM,WAAW,WACb,QAAQ,QAAQ,mCAChB;AACJ,YAAM,UAAU,MAAM,IAAI,OAAO,QAAQ,GAAG,KAAK;AACjD,UAAI,aAAa,WAAW,MAAM,YAAY,KAAK,MAAM,GAAI,QAAO;AACpE,UAAI,SAAS,KAAK,MAAM;AACtB,cAAM,IAAI,SAAS,oCAA+B;AAAA,UAChD,MAAM;AAAA,QACR,CAAC;AACH,UAAI,WAAW,GAAI;AACnB,UAAI,CAAC,gBAAgB,MAAM,GAAG;AAC5B,YAAI,IAAI;AAAA,UACN,IAAI,MAAM,qFAAqF,aAAa;AAAA,QAC9G;AACA;AAAA,MACF;AACA,kBAAY;AACZ;AAAA,IACF;AAAA,EACF;AACF;;;AMzOA,OAAOC,YAAW;AAgBlB,eAAsB,QAAQ,KAAqB,MAA6C;AAC9F,QAAM,QAAQ,MAAM,UAAU,cAAc,GAAG,GAAG,IAAI;AACtD,MAAI,IAAI;AAAA,IAAK,EAAE,MAAM;AAAA,IAAG,MACtB,YAAY,OAAO;AAAA,MACjB,EAAE,QAAQ,QAAQ,OAAO,OAAK,EAAE,KAAK;AAAA,MACrC,EAAE,QAAQ,OAAO,OAAO,OAAK,EAAE,IAAI;AAAA,MACnC;AAAA,QACE,QAAQ;AAAA,QACR,OAAO,OAAM,EAAE,WAAW,GAAG,EAAE,UAAU,gBAAgB,EAAE;AAAA,MAC7D;AAAA,MACA,EAAE,QAAQ,SAAS,OAAO,OAAK,EAAE,SAAS;AAAA,MAC1C,EAAE,QAAQ,WAAW,OAAO,OAAK,WAAW,EAAE,SAAS,EAAE;AAAA,IAC3D,CAAC;AAAA,EACH;AACF;AAEA,SAAS,aAAa,MAA8D;AAClF,QAAM,MAAM,CAAC,OAAe,UAAkB,GAAGC,OAAM,KAAK,GAAG,KAAK,IAAI,OAAO,EAAE,CAAC,CAAC,GAAG,KAAK;AAC3F,SAAO;AAAA,IACL,IAAI,QAAQ,KAAK,IAAI;AAAA,IACrB,IAAI,OAAO,KAAK,GAAG;AAAA,IACnB,IAAI,cAAc,KAAK,cAAc,KAAK,WAAWA,OAAM,OAAO,aAAa,IAAI,GAAG;AAAA,IACtF,IAAI,OAAO,KAAK,MAAM,QAAQ,IAAI;AAAA,IAClC,IAAI,cAAc,KAAK,YAAY,GAAG;AAAA,IACtC,IAAI,WAAW,KAAK,oBAAoB,GAAG;AAAA,IAC3C,GAAG,SAAS,MAAM,GAAG;AAAA,IACrB,IAAI,WAAW,WAAW,KAAK,SAAS,CAAC;AAAA,IACzC,IAAI,WAAW,WAAW,KAAK,SAAS,CAAC;AAAA,EAC3C;AACF;AAEA,SAAS,SACP,MACA,KACU;AACV,QAAM,UAAU,KAAK,UAAU,KAAK,OAAK,EAAE,OAAO,KAAK,gBAAgB;AACvE,MAAI,CAAC,QAAS,QAAO,CAAC;AACtB,QAAM,IAAI,QAAQ;AAClB,SAAO,CAAC,IAAI,SAAS,GAAG,CAAC,QAAQ,MAAM,IAAI,KAAK,GAAG,KAAK,YAAY,QAAQ,UAAU,CAAC,EAAE,CAAC;AAC5F;AAEA,eAAsB,QAAQ,KAAqB,MAA6B;AAC9E,QAAM,OAAO,MAAM,QAAQ,cAAc,GAAG,GAAG,IAAI;AACnD,MAAI,IAAI;AAAA,IAAK;AAAA,IAAM,MACjB;AAAA,MACE,GAAG,aAAa,IAAI;AAAA,MACpB;AAAA,MACAA,OAAM;AAAA,QACJ,GAAG,KAAK,SAAS,MAAM,uCAAkC,IAAI,kCAA6B,IAAI;AAAA,MAChG;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,EACb;AACF;AAEA,eAAsB,YAAY,KAAqB,MAA6B;AAClF,QAAM,OAAO,MAAM,QAAQ,cAAc,GAAG,GAAG,IAAI;AACnD,MAAI,IAAI;AAAA,IACN,EAAE,MAAM,KAAK,MAAM,kBAAkB,KAAK,kBAAkB,UAAU,KAAK,SAAS;AAAA,IACpF,MACE,YAAY,KAAK,UAAU;AAAA,MACzB,EAAE,QAAQ,IAAI,OAAO,OAAM,EAAE,OAAO,KAAK,mBAAmB,MAAM,IAAK;AAAA,MACvE,EAAE,QAAQ,WAAW,OAAO,OAAK,EAAE,GAAG;AAAA,MACtC,EAAE,QAAQ,SAAS,OAAO,OAAK,EAAE,UAAU;AAAA,MAC3C,EAAE,QAAQ,QAAQ,OAAO,OAAK,YAAY,EAAE,UAAU,EAAE;AAAA,MACxD,EAAE,QAAQ,WAAW,OAAO,OAAK,WAAW,EAAE,SAAS,EAAE;AAAA,IAC3D,CAAC;AAAA,EACL;AACF;AAEA,eAAsB,SACpB,KACA,MACA,WACe;AACf,QAAM,SAAS,MAAM,aAAa,cAAc,GAAG,GAAG,MAAM,SAAS;AACrE,MAAI,CAAC,OAAO,MAAM,KAAK,OAAK,EAAE,SAAS,YAAY,GAAG;AACpD,QAAI,IAAI,KAAK,6DAAwD;AAAA,EACvE;AACA,MAAI,IAAI,KAAK,QAAQ,MAAM;AACzB,UAAM,IAAI,OAAO,MAAM;AACvB,UAAM,SAASA,OAAM;AAAA,MACnB,GAAG,OAAO,SAAS,GAAG,OAAO,UAAU,eAAe,eAAe,WAAM,CAAC,QAAQ,MAAM,IAAI,KAAK,GAAG,KACjG,YAAY,OAAO,UAAU,CAAC,GAAG,OAAO,iBAAiB,2BAA2B,EAAE;AAAA,IAC7F;AACA,UAAM,QAAQ,YAAY,OAAO,OAAO;AAAA,MACtC,EAAE,QAAQ,QAAQ,OAAO,OAAK,EAAE,KAAK;AAAA,MACrC,EAAE,QAAQ,QAAQ,OAAO,OAAK,YAAY,EAAE,IAAI,EAAE;AAAA,MAClD,EAAE,QAAQ,QAAQ,OAAO,OAAK,EAAE,YAAY;AAAA,IAC9C,CAAC;AACD,WAAO,GAAG,MAAM;AAAA,EAAK,KAAK;AAAA,EAC5B,CAAC;AACH;AAEA,eAAsB,YACpB,KACA,MACA,WACe;AACf,QAAM,OAAO,MAAM,SAAS,cAAc,GAAG,GAAG,MAAM,SAAS;AAC/D,MAAI,IAAI,QAAQ,GAAG,IAAI,uBAAuB,KAAK,oBAAoB,SAAS,EAAE;AAClF,MAAI,IAAI,KAAK,MAAM,MAAM,KAAK,GAAG;AACnC;AAEA,eAAsB,SACpB,KACA,MACA,MACe;AACf,MAAI,KAAK,WAAW,KAAK,OAAQ,OAAM,IAAI,SAAS,4CAA4C;AAChG,QAAM,SAAS,cAAc,GAAG;AAChC,QAAM,SAAS,MAAM,MAAM,QAAQ,MAAM,IAAI;AAC7C,MAAI;AACJ,MAAI,OAAO,WAAW,aAAa,OAAO,WAAW,aAAa;AAEhE,UAAM,QAAQ,IAAI,YAAY,MAAM,aAAa,QAAQ,IAAI,EAAE,MAAM,MAAM,IAAI,IAAI;AACnF,aACE,MAAM,gBAAgB,IAAI,WAAW,OAAO,UAAU,OAAO,MAAM,IAAI,OAAK,EAAE,IAAI,KAAK,CAAC,GAAG;AAAA,MACzF,UAAU,IAAI;AAAA,MACd,MAAM,OAAK,IAAI,IAAI,KAAK,CAAC;AAAA,IAC3B,CAAC,GACD;AAAA,EACJ;AACA,MAAI,OAAO,WAAW,UAAW,KAAI,IAAI,QAAQ,kBAAkB,IAAI,UAAU;AAAA,WACxE,OAAO,WAAW;AACzB,QAAI,IAAI,QAAQ,mDAA8C;AAAA,WACvD,OAAO,WAAW;AACzB,QAAI,IAAI,QAAQ,4DAAuD;AACzE,MAAI,IAAI;AAAA,IAAK,UAAU,SAAY,SAAS,EAAE,GAAG,QAAQ,MAAM;AAAA,IAAG,MAChE,OAAO,WAAW,OAAO,WAAWA,OAAM,IAAI,iBAAiB;AAAA,EACjE;AACF;AAEA,eAAsB,cACpB,KACA,MACA,YACe;AACf,MAAI,eAAe,aAAa,eAAe,UAAU;AACvD,UAAM,IAAI,SAAS,kDAAkD,UAAU,GAAG;AAAA,EACpF;AACA,QAAM,OAAO,MAAM,cAAc,cAAc,GAAG,GAAG,MAAM,UAAwB;AACnF,MAAI,IAAI;AAAA,IACN,KAAK,eAAe,WAChB,GAAG,IAAI,wCACP,GAAG,IAAI;AAAA,EACb;AACA,MAAI,IAAI,KAAK,MAAM,MAAM,KAAK,GAAG;AACnC;AAEA,eAAsB,WACpB,KACA,MACA,YAAY,OACG;AACf,QAAM,OAAO,MAAM,YAAY,cAAc,GAAG,GAAG,MAAM,EAAE,UAAU,CAAC;AACtE,MAAI,IAAI;AAAA,IACN,YAAY,GAAG,IAAI,cAAc,GAAG,IAAI,oDAA+C,IAAI;AAAA,EAC7F;AACA,MAAI,IAAI,KAAM,KAAI,IAAI,KAAK,MAAM,MAAM,EAAE;AAAA,WAChC,UAAW,KAAI,IAAI,KAAK,KAAK,GAAG;AAC3C;AAEA,eAAsB,UACpB,KACA,MACA,MACe;AACf,MAAI,CAAC,KAAK,KAAK;AACb,QAAI,CAAC,IAAI,aAAa;AACpB,YAAM,IAAI,SAAS,sBAAsB,IAAI,yBAAyB;AAAA,QACpE,MAAM;AAAA,MACR,CAAC;AAAA,IACH;AACA,UAAM,KAAK,MAAM,IAAI,QAAQ,UAAU,IAAI,kDAAkD;AAC7F,QAAI,CAAC,GAAI,OAAM,IAAI,SAAS,WAAW;AAAA,EACzC;AACA,QAAM,SAAS,MAAM,WAAW,cAAc,GAAG,GAAG,IAAI;AACxD,MAAI,IAAI,QAAQ,GAAG,IAAI,UAAU;AACjC,MAAI,IAAI,KAAM,KAAI,IAAI,KAAK,QAAQ,MAAM,EAAE;AAC7C;;;ACxLA,SAAS,SAAAC,QAAO,WAAAC,UAAS,MAAAC,KAAI,aAAAC,kBAAiB;AAC9C,SAAS,UAAAC,eAAc;AACvB,SAAS,YAAAC,WAAU,WAAAC,UAAS,QAAAC,aAAY;AASxC,SAAS,iBAAiB;AAC1B,SAAS,4BAA4B;AAErC,SAAS,KAAAC,UAAS;AAuDX,IAAM,aAAa,6HAA6H,WAAW,+CAA+C,WAAW;AAGrN,IAAM,yBAAyB;AAAA,EACpC;AAAA,EACA;AAAA,EAEA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,MAAM;AAEb,IAAM,UAAU,CAA0B,SAAwB;AAAA,EAChE,OAAO,IAAI;AAAA,EACX,aAAa,IAAI;AAAA,EACjB,aAAa,IAAI;AAAA,EACjB,aAAa,IAAI;AACnB;AAMO,SAAS,gBAAgB,OAAgB,CAAC,GAAc;AAC7D,QAAM,QAAQ,KAAK,SAAS,kBAAkB;AAC9C,QAAM,YAAuB,KAAK,UAAU,CAAC,OAAO,SAAS,MAAM,OAAO,IAAI;AAC9E,QAAM,MAAM,KAAK,OAAO,QAAQ,IAAI;AACpC,QAAM,SAAwB,KAAK,UAAU,EAAE,GAAG,oBAAoB,GAAG,IAAI;AAC7E,QAAM,YAAyB,KAAK,aAAa,kBAAkB;AAGnE,iBAAe,UAAU,KAAa,OAA0B;AAC9D,UAAM,IAAI,MAAM,UAAU,KAAK,KAAK,EAAE,MAAM,OAAO,EAAE,OAAO,OAAO,UAAU,EAAE,EAAE;AACjF,WAAO;AAAA,MACL,OAAO,EAAE;AAAA,MACT,MAAM,EAAE,QAAQ,KAAK;AAAA,uBAA0B,GAAG,KAAK,cAAc;AAAA,IACvE;AAAA,EACF;AAEA,iBAAe,SAA6B;AAC1C,UAAM,SAAS,MAAM,MAAM,QAAQ,EAAE,WAAW,KAAK,OAAO,CAAC;AAC7D,QAAI,CAAC,OAAO,OAAQ,OAAM,IAAI,SAAS,iBAAiB,EAAE,UAAU,mBAAmB,CAAC;AACxF,WAAO,gBAAgB,EAAE,WAAW,OAAO,WAAW,QAAQ,OAAO,QAAQ,OAAO,UAAU,CAAC;AAAA,EACjG;AAGA,iBAAe,IACb,IACyB;AACzB,QAAI;AACF,YAAM,EAAE,SAAS,KAAK,IAAI,MAAM,GAAG,MAAM,OAAO,CAAC;AACjD,aAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,GAAG,OAAO;AAAA;AAAA,EAAO,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC,GAAG,CAAC,EAAE;AAAA,IAC/F,SAAS,OAAO;AACd,aAAO,EAAE,SAAS,MAAM,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,cAAc,KAAK,EAAE,CAAC,EAAE;AAAA,IAClF;AAAA,EACF;AAGA,iBAAe,aACb,GACA,KACA,MAUwB;AACxB,QAAI,QAAQ,MAAM,cAAc,GAAG;AACnC,QAAI,iBAAiB;AACrB,QAAI,CAAC,aAAa,KAAK,GAAG;AACxB,YAAM,QAAQ,UAAU,KAAK,EAAE,IAAI,OAAK,EAAE,IAAI;AAC9C,UAAI,MAAM,SAAS,KAAK,KAAK,aAAa,QAAW;AACnD,cAAM,QAAQ,MAAM,MAAM,GAAG,EAAE;AAC/B,eAAO;AAAA,UACL,MAAM;AAAA,UACN,SACE,oEAAoE,MAAM,WAAW,IAAI,mBAAmB,OAAO,MAAM,MAAM,aAAa,uOAE3B,KAAK,SAAS;AAAA,UACjI,MAAM;AAAA,YACJ,QAAQ;AAAA,YACR,WAAW;AAAA,YACX,GAAI,MAAM,SAAS,MAAM,SAAS,EAAE,eAAe,MAAM,SAAS,MAAM,OAAO,IAAI,CAAC;AAAA,YACpF,WAAW,MAAM,MAAM;AAAA,UACzB;AAAA,QACF;AAAA,MACF;AACA,UAAI,KAAK,UAAU;AACjB,gBAAQ,MAAM,gBAAgB,OAAO,KAAK,IAAI;AAC9C,yBAAiB;AAAA,MACnB;AAAA,IACF;AACA,UAAM,SAAS,MAAM;AAAA,MACnB,EAAE,QAAQ,GAAG,OAAO,UAAU;AAAA,MAC9B,EAAE,KAAK,MAAM,KAAK,MAAM,UAAU,OAAO,KAAK,KAAK,KAAK,QAAQ,KAAK,OAAO;AAAA,IAC9E,EAAE,MAAM,CAAC,UAAmB;AAC1B,UAAI,EAAE,iBAAiB,gBAAiB,OAAM;AAC9C,YAAM,MAAM,KAAK,YAAY,KAAK,oBAAoB,KAAK,YAAY,YAAY;AACnF,YAAM,OAAO,MAAM,YAAY,SAC3B,uBAAuB,MAAM,YAAY,KAAK,IAAI,CAAC,MACnD;AACJ,YAAM,IAAI;AAAA,QACR,gCAAgC,MAAM,QAAQ,IAAI,GAAG,6BAA6B,IAAI,0EACX,KAAK,SAAS;AAAA,MAC3F;AAAA,IACF,CAAC;AACD,UAAM,OACJ,OAAO,WAAW,cACd,kCACA,OAAO,WAAW,cAChB,oBAAoB,OAAO,SAAS,KACpC,YAAY,OAAO,SAAS,oBAAoB,OAAO,QAAQ;AACvE,UAAM,WAAW,OAAO,SAAS,SAAS;AAAA;AAAA,IAAkB,OAAO,SAAS,KAAK,MAAM,CAAC,KAAK;AAC7F,UAAM,OACJ,OAAO,WAAW,cACd,EAAE,OAAO,MAAM,MAAM,GAAG,IACxB,MAAM;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,MAAM,IAAI,OAAK,EAAE,IAAI;AAAA,IAC7B;AACN,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SACE,GAAG,IAAI,KAAK,OAAO,GAAG,KAAK,OAAO,KAAK,UAAU,IAAI,iBAAiB,+DAA0D,EAAE,GAAG,QAAQ,GAAG,KAAK,IAAI;AAAA,yEAC7E,OAAO,IAAI;AAAA,MACzF,MAAM;AAAA,QACJ,QAAQ,OAAO;AAAA,QACf,OAAO,KAAK;AAAA,QACZ,MAAM,OAAO;AAAA,QACb,eAAe,CAAC,KAAK;AAAA,QACrB,WAAW,OAAO;AAAA,QAClB,MAAM,OAAO;AAAA,QACb;AAAA,QACA,UAAU,OAAO;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,IAAI;AAAA,IACjB,EAAE,MAAM,SAAS,SAAS,QAAQ;AAAA,IAClC,EAAE,cAAc,uBAAuB;AAAA,EACzC;AACA,QAAM,EAAE,UAAAC,WAAU,KAAAC,MAAK,QAAQC,UAAS,IAAI,SAAS,QAAQ;AAE7D,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MAcF,aAAa;AAAA,QACX,MAAMC,GACH,OAAO,EACP,IAAI,CAAC,EACL;AAAA,UACC;AAAA,QACF;AAAA,QACF,MAAMA,GACH,OAAO,EACP,SAAS,EACT;AAAA,UACC;AAAA,QACF;AAAA,QACF,KAAAF;AAAA,QACA,QAAQC;AAAA,QACR,UAAAF;AAAA,MACF;AAAA,MACA,aAAa,EAAE,iBAAiB,OAAO,gBAAgB,MAAM,eAAe,KAAK;AAAA,IACnF;AAAA,IACA,UACE,IAAI,OAAM,MAAK;AACb,YAAM,UAAU,MAAM,aAAa,KAAK,MAAM,MAAM;AACpD,YAAM,WAAW,MAAM,aAAa,QAAQ,IAAI;AAChD,UAAI;AACF,cAAM,OACJ,KAAK,SAAS,SACV,gBAAgB,SAAS,KAAK,KAAK,IAAI,IACvC,SAAS;AACf,cAAM,UAAU,MAAM,aAAa,GAAG,SAAS,KAAK;AAAA,UAClD;AAAA,UACA,WAAW,KAAK,SAAS;AAAA,UACzB,UAAU,SAAS,SAAS,WAAW,eAAe;AAAA,UACtD,KAAK,KAAK;AAAA,UACV,QAAQ,KAAK;AAAA,UACb,UAAU,KAAK;AAAA,UACf,WAAW;AAAA,QACb,CAAC;AACD,cAAM,QACJ,QAAQ,YAAY,iBAChB,KACA,UAAUI,UAAS,QAAQ,IAAI,CAAC,QAAQ,QAAQ,OAAO,KAAK,QAAQ,IAAI;AAAA;AAC9E,eAAO;AAAA,UACL,SAAS,GAAG,KAAK,GAAG,QAAQ,OAAO;AAAA,UACnC,MAAM;AAAA,YACJ,GAAI,QAAQ;AAAA,YACZ,QAAQ;AAAA,cACN,MAAM,QAAQ;AAAA,cACd,SAAS,QAAQ;AAAA,cACjB,MAAM,SAAS;AAAA,cACf,GAAI,QAAQ,aAAa,SAAS,EAAE,cAAc,QAAQ,aAAa,IAAI,CAAC;AAAA,YAC9E;AAAA,UACF;AAAA,QACF;AAAA,MACF,UAAE;AACA,cAAM,SAAS,QAAQ;AAAA,MACzB;AAAA,IACF,CAAC;AAAA,EACL;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MAIF,aAAa;AAAA,QACX,OAAOD,GACJ,OAAO,EACP,SAAS,EACT,SAAS,iEAAiE;AAAA,QAC7E,OAAOA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,SAAS,0BAA0B;AAAA,QACtF,MAAMA,GACH,OAAO,EACP,IAAI,EACJ,IAAI,CAAC,EACL,IAAI,IAAI,EACR,SAAS,EACT,SAAS,sDAAsD;AAAA,MACpE;AAAA,MACA,aAAa,EAAE,cAAc,MAAM,eAAe,MAAM;AAAA,IAC1D;AAAA,IACA,OAAM,SAAQ;AACZ,UAAI;AACF,cAAM,EAAE,OAAO,UAAU,SAAS,IAAI,MAAM,UAAU,QAAQ,IAAI;AAClE,cAAM,QAAQ,MAAM;AAAA,UAClB,OACE,KAAK,EAAE,IAAI,KAAK,EAAE,IAAI,KAAK,EAAE,OAAO,KAAK,YAAY,EAAE,IAAI,CAAC,cAAc,EAAE,QAAQ;AAAA,QACxF;AACA,cAAM,UAAU,MAAM,SAClB,GAAG,MAAM,MAAM;AAAA,EAAmC,MAAM,KAAK,IAAI,CAAC,KAClE,+BAA+B,KAAK,QAAQ,EAAE,QAAQ,KAAK,QAAQ,cAAc,KAAK,KAAK,MAAM,EAAE;AACvG,cAAM,OAAO;AAAA,UACX;AAAA,UACA,UAAU,SAAS,IAAI,QAAM,EAAE,OAAO,EAAE,OAAO,MAAM,EAAE,KAAK,EAAE;AAAA,UAC9D,GAAI,WAAW,CAAC,IAAI,EAAE,WAAW,KAAK;AAAA,QACxC;AACA,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,GAAG,OAAO;AAAA;AAAA,EAAO,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC,GAAG,CAAC;AAAA,QACpF;AAAA,MACF,SAAS,OAAO;AACd,eAAO,EAAE,SAAS,MAAM,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,cAAc,KAAK,EAAE,CAAC,EAAE;AAAA,MAClF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAa,SAAS;AAC5B,SAAO;AAAA,IACL,WAAW;AAAA,IACX;AAAA,MACE,GAAG,QAAQ,UAAU;AAAA;AAAA,MAErB,aAAa,WAAW,YAAY;AAAA,QAClC;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,IACA,UACE,IAAI,OAAM,MAAK;AACb,YAAM,OAAO,gBAAgB,KAAK,KAAK,IAAI;AAC3C,YAAM,MAAM,MAAME,SAAQC,MAAKC,QAAO,GAAG,gBAAgB,CAAC;AAC1D,UAAI;AACF,cAAM,iBAAiB,KAAK,KAAK,KAAK;AACtC,cAAM,UAAU,MAAM,aAAa,GAAG,KAAK;AAAA,UACzC;AAAA,UACA,WAAW;AAAA,UACX,KAAK,KAAK;AAAA,UACV,QAAQ,KAAK;AAAA,UACb,UAAU,KAAK;AAAA,UACf,WAAW;AAAA,QACb,CAAC;AACD,eAAO;AAAA,MACT,UAAE;AACA,cAAMC,IAAG,KAAK,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,MAChD;AAAA,IACF,CAAC;AAAA,EACL;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,GAAG,QAAQ,SAAS,SAAS;AAAA,MAC7B,aACE,GAAG,SAAS,UAAU,WAAW;AAAA,MAEnC,aAAa;AAAA,QACX,MAAML,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,SAAS,oBAAoB;AAAA,QACzE,MAAMA,GACH,OAAO,EACP,SAAS,EACT,SAAS,0EAA0E;AAAA,MACxF;AAAA,IACF;AAAA,IACA,UACE,IAAI,OAAM,MAAK;AACb,UAAI,KAAK,SAAS,UAAa,KAAK,SAAS;AAC3C,cAAM,IAAI,SAAS,uBAAuB;AAC5C,UAAI,OAAO,KAAK;AAChB,UAAI;AACJ,UAAI,SAAS,QAAW;AACtB,iBAAS,MAAM,aAAa,KAAK,MAAgB,MAAM;AACvD,eAAO,eAAe,OAAO,MAAM,OAAO,WAAW;AAAA,MACvD;AACA,YAAM,QAAQ,MAAM,UAAU,GAAG,IAAI;AACrC,YAAM,OAAO,MAAM,WAAW,YAAY,OAAO,MAAM,kBAAkB,CAAC;AAC1E,YAAM,MAAM,OAAO,WAAW,MAAM,IAAI,IAAI;AAC5C,YAAM,cAAc,MAAM,YAAY,SAClC,iBAAiB,MAAM,YAAY,KAAK,IAAI,CAAC,MAC7C;AACJ,YAAM,UAAU;AAAA,QACd,WAAW,IAAI,IAAI,iBAAiB,MAAM,WAAM,GAAG,KAAK,EAAE;AAAA,QAC1D,OAAO,IAAI,IAAI,gCAAgC,MAAM,KAAK,GAAG,MAAM,EAAE;AAAA,QACrE,OAAO,IAAI,IAAI,8BAA8B,WAAW;AAAA,QACxD,SAAS,IAAI,IAAI,8BAA8B,WAAW;AAAA,MAC5D,EAAE,MAAM,MAAM;AACd,aAAO;AAAA,QACL;AAAA,QACA,MAAM;AAAA,UACJ,GAAG;AAAA,UACH;AAAA,UACA,GAAI,SACA,EAAE,WAAW,MAAM,QAAQ,EAAE,MAAM,OAAO,MAAM,SAAS,OAAO,QAAQ,EAAE,IAC1E,CAAC;AAAA,QACP;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACL;AAEA,MAAI;AAEJ,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MAIF,aAAa,CAAC;AAAA,MACd,aAAa,EAAE,cAAc,OAAO,eAAe,KAAK;AAAA,IAC1D;AAAA,IACA,YAAY;AACV,UAAI;AACF,cAAM,SAAS,MAAM,MAAM,QAAQ,EAAE,WAAW,KAAK,OAAO,CAAC;AAC7D,YAAI,OAAO,UAAU,CAAC,cAAc;AAClC,gBAAM,KAAK,MAAM;AAAA,YACf,gBAAgB;AAAA,cACd,WAAW,OAAO;AAAA,cAClB,QAAQ,OAAO;AAAA,cACf,OAAO;AAAA,YACT,CAAC;AAAA,UACH,EAAE,MAAM,MAAM,IAAI;AAClB,cAAI,GAAI,QAAO,WAAW,wBAAwB,OAAO,SAAS,OAAO,GAAG,KAAK,GAAG;AAAA,QACtF;AACA,YAAI,CAAC,cAAc;AACjB,gBAAM,QAAsD;AAAA,YAC1D,MAAM,QAAQ,QAAQ;AAAA,UACxB;AACA,gBAAM,OAAO,UAAU;AAAA,YACrB,WAAW,OAAO;AAAA,YAClB;AAAA,YACA,KAAK;AAAA,YACL,MAAM,KAAK,SAAS,OAAM,SAAQ,MAAM,OAAO,MAAM,GAAG,QAAQ,GAAG;AAAA,YACnE,OAAO;AAAA,YACP,WAAW,KAAK;AAAA,YAChB,WAAW,SAAO;AAChB,oBAAM,MAAM;AAAA,YACd;AAAA,UACF,CAAC;AACD,gBAAM,KACH,MAAM,MAAM;AAAA,UAAC,CAAC,EACd,QAAQ,MAAM;AACb,gBAAI,iBAAiB,MAAO,gBAAe;AAAA,UAC7C,CAAC;AACH,yBAAe;AAAA,QACjB;AACA,cAAM,UAAU;AAChB,cAAM,SAAS,MAAM,QAAQ,KAAK;AAAA,UAChC,QAAQ,KAAK;AAAA,YACX,QAAM,EAAE,IAAI,MAAe,EAAE;AAAA,YAC7B,CAAC,OAAgB,EAAE,IAAI,OAAgB,EAAE;AAAA,UAC3C;AAAA,UACA,IAAI,QAAc,OAAK,WAAW,MAAM,EAAE,IAAI,GAAG,KAAK,eAAe,GAAM,EAAE,QAAQ,CAAC;AAAA,QACxF,CAAC;AACD,YAAI,WAAW;AACb,iBAAO;AAAA,YACL,4GAC2D,QAAQ,OAAO,gBAAgB;AAAA,UAC5F;AACF,YAAI,CAAC,OAAO,GAAI,OAAM,OAAO;AAC7B,eAAO,WAAW,gBAAgB,OAAO,EAAE,KAAK,KAAK,KAAK,OAAO,EAAE,SAAS,IAAI;AAAA,MAClF,SAAS,OAAO;AACd,eAAO,EAAE,SAAS,MAAM,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,cAAc,KAAK,EAAE,CAAC,EAAE;AAAA,MAClF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,IAAI;AACV,SAAO;AAAA,IAAa,EAAE,KAAK;AAAA,IAAM,QAAQ,EAAE,IAAI;AAAA,IAAG,UAChD,IAAI,OAAM,MAAK;AACb,YAAM,QAAQ,MAAM,UAAU,GAAG,EAAE,UAAU,KAAK,SAAS,CAAC;AAC5D,aAAO,EAAE,SAAS,GAAG,MAAM,MAAM,YAAY,MAAM,EAAE,MAAM,EAAE;AAAA,IAC/D,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IAAa,EAAE,KAAK;AAAA,IAAM,QAAQ,EAAE,IAAI;AAAA,IAAG,UAChD,IAAI,OAAM,MAAK;AACb,YAAM,OAAO,MAAM,QAAQ,GAAG,KAAK,IAAI;AACvC,aAAO,EAAE,SAAS,GAAG,KAAK,IAAI,KAAK,KAAK,GAAG,IAAI,MAAM,KAAK;AAAA,IAC5D,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IAAa,EAAE,MAAM;AAAA,IAAM,QAAQ,EAAE,KAAK;AAAA,IAAG,UAClD,IAAI,OAAM,MAAK;AACb,YAAM,SAAS,MAAM,aAAa,GAAG,KAAK,MAAM,KAAK,SAAS;AAC9D,aAAO;AAAA,QACL,SAAS,qBAAqB,OAAO,MAAM,QAAQ;AAAA,UACjD,SAAS,OAAO;AAAA,UAChB,KAAK,OAAO;AAAA,QACd,CAAC;AAAA,QACD,MAAM;AAAA,MACR;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IAAa,EAAE,MAAM;AAAA,IAAM,QAAQ,EAAE,KAAK;AAAA,IAAG,UAClD,IAAI,OAAM,MAAK;AACb,UAAI,KAAK,WAAW,KAAK,OAAQ,OAAM,IAAI,SAAS,wCAAwC;AAC5F,YAAM,SAAS,MAAM,MAAM,GAAG,KAAK,MAAM,IAAI;AAC7C,UAAI,OAAO,WAAW;AACpB,eAAO,EAAE,SAAS,kBAAkB,KAAK,IAAI,YAAY,MAAM,OAAO;AACxE,UAAI,OAAO,EAAE,OAAO,MAAM,MAAM,GAAG;AACnC,UAAI,OAAO,WAAW,YAAY;AAChC,cAAM,QAAQ,MAAM,aAAa,GAAG,KAAK,IAAI,EAAE,MAAM,MAAM,IAAI;AAC/D,eAAO,MAAM,UAAU,OAAO,UAAU,OAAO,MAAM,IAAI,OAAK,EAAE,IAAI,KAAK,CAAC,CAAC;AAAA,MAC7E;AACA,aAAO;AAAA,QACL,SAAS,eAAe,OAAO,MAAM,MAAM,OAAO,QAAQ,2CAAsC,KAAK,IAAI;AAAA,QACzG,MAAM,EAAE,GAAG,QAAQ,OAAO,KAAK,MAAM;AAAA,MACvC;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IAAa,EAAE,cAAc;AAAA,IAAM,QAAQ,EAAE,aAAa;AAAA,IAAG,UAClE,IAAI,OAAM,MAAK;AACb,YAAM,OAAO,MAAM,cAAc,GAAG,KAAK,MAAM,KAAK,UAAU;AAC9D,aAAO,EAAE,SAAS,GAAG,KAAK,IAAI,WAAW,KAAK,UAAU,KAAK,KAAK,GAAG,IAAI,MAAM,KAAK;AAAA,IACtF,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IAAa,EAAE,QAAQ;AAAA,IAAM,QAAQ,EAAE,OAAO;AAAA,IAAG,UACtD,IAAI,OAAM,MAAK;AACb,YAAM,OAAO,MAAM,YAAY,GAAG,KAAK,MAAM,EAAE,WAAW,KAAK,UAAU,CAAC;AAC1E,aAAO,EAAE,SAAS,GAAG,KAAK,IAAI,IAAI,KAAK,YAAY,aAAa,UAAU,IAAI,MAAM,KAAK;AAAA,IAC3F,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IAAa,EAAE,OAAO;AAAA,IAAM,QAAQ,EAAE,MAAM;AAAA,IAAG,UACpD,IAAI,OAAM,MAAK;AACb,YAAM,SAAS,MAAM,WAAW,GAAG,KAAK,IAAI;AAC5C,aAAO,EAAE,SAAS,GAAG,KAAK,IAAI,YAAY,MAAM,OAAO;AAAA,IACzD,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IAAa,EAAE,SAAS;AAAA,IAAM,QAAQ,EAAE,QAAQ;AAAA,IAAG,UACxD,IAAI,OAAM,MAAK;AACb,YAAM,OAAO,MAAM,SAAS,GAAG,KAAK,MAAM,KAAK,SAAS;AACxD,aAAO;AAAA,QACL,SAAS,GAAG,KAAK,IAAI,uBAAuB,KAAK,gBAAgB,KAAK,KAAK,GAAG;AAAA,QAC9E,MAAM;AAAA,MACR;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IAAa,EAAE,OAAO;AAAA,IAAM,QAAQ,EAAE,MAAM;AAAA,IAAG,MACpD,IAAI,OAAM,MAAK;AACb,YAAM,KAAK,MAAM,OAAO,CAAC;AACzB,YAAM,OAAO,MAAM,kBAAkB,CAAC;AACtC,aAAO;AAAA,QACL,SAAS,gBAAgB,GAAG,KAAK,yBAAyB,aAAa,IAAI,CAAC;AAAA,QAC5E,MAAM;AAAA,MACR;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAEA,IAAM,aAAa,CAAC,UAAkC,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,KAAK,CAAC,EAAE;AAG1F,eAAsB,iBACpB,KACA,OACe;AACf,QAAM,OAAO,oBAAI,IAAY;AAC7B,MAAI,QAAQ;AACZ,aAAW,KAAK,OAAO;AACrB,UAAM,OAAO,EAAE,KAAK,QAAQ,YAAY,EAAE,EAAE,QAAQ,QAAQ,EAAE;AAC9D,QAAI,CAAC,gBAAgB,IAAI,EAAG,OAAM,IAAI,SAAS,uBAAuB,EAAE,IAAI,GAAG;AAC/E,QAAI,KAAK,IAAI,IAAI,EAAG,OAAM,IAAI,SAAS,IAAI,IAAI,mBAAmB;AAClE,SAAK,IAAI,IAAI;AACb,UAAM,QAAQ,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,WAAW,WAAW,MAAM;AAChF,aAAS,MAAM;AACf,QAAI,QAAQ;AACV,YAAM,IAAI,SAAS,2BAA2B,YAAY,gBAAgB,CAAC,EAAE;AAC/E,UAAM,SAASG,MAAK,KAAK,GAAG,KAAK,MAAM,GAAG,CAAC;AAC3C,UAAMG,OAAMC,SAAQ,MAAM,GAAG,EAAE,WAAW,KAAK,CAAC;AAChD,UAAMC,WAAU,QAAQ,KAAK;AAAA,EAC/B;AACF;AAEA,SAAS,cAAc,OAAwB;AAC7C,MAAI,iBAAiB,YAAY,MAAM,aAAa,mBAAoB,QAAO;AAC/E,MAAI,iBAAiB,eAAe,MAAM,WAAW,IAAK,QAAO;AACjE,MAAI,iBAAiB;AACnB,WAAO,MAAM,OAAO,GAAG,MAAM,OAAO;AAAA,EAAK,MAAM,IAAI,KAAK,MAAM;AAChE,SAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC9D;AAEA,eAAsB,aAAa,OAAgB,CAAC,GAAkB;AACpE,QAAM,SAAS,gBAAgB,IAAI;AACnC,QAAM,OAAO,QAAQ,IAAI,qBAAqB,CAAC;AACjD;;;A5B/lBA,IAAM,UAAU,IAAI,QAAQ;AAC5B,QACG,KAAK,QAAQ,EACb,YAAY,6DAA6D,EACzE,QAAQ,OAAO,EACf;AAAA,EACC;AAAA,EACA,yBAAyB,IAAI,GAAG,oBAAoB,kBAAkB;AACxE,EACC,OAAO,UAAU,sCAAsC,KAAK,EAC5D,mBAAmB,EACnB;AAAA,EACC;AAAA,EACA;AAAA;AAAA,MAEE,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA;AAAA;AAAA,cAGA,IAAI,MAAM,SAAM,IAAI,GAAG,SAAM,IAAI,SAAS,SAAM,IAAI,KAAK;AACrE;AAGF,SAAS,OAA4B,SAA6D;AAChG,SAAO,UAAU,SAAoB;AACnC,UAAM,UAAU,KAAK,GAAG,EAAE;AAC1B,UAAM,UAAU,QAAQ,gBAA+B;AACvD,QAAI;AACJ,QAAI;AACF,YAAM,MAAM,cAAc,EAAE,QAAQ,QAAQ,QAAQ,MAAM,QAAQ,KAAK,CAAC;AACxE,YAAM,QAAQ,KAAK,GAAI,KAAK,MAAM,GAAG,EAAE,CAAO;AAAA,IAChD,SAAS,OAAO;AACd,aAAO,OAAO,GAAG;AACjB,cAAQ,WAAW,YAAY,KAAK;AAAA,IACtC;AAAA,EACF;AACF;AAEA,SAAS,OAAO,OAAgB,KAAuC;AACrE,QAAM,MAAM,KAAK,OAAO,aAAa;AACrC,QAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,MAAI,MAAM,OAAO;AACjB,MAAI,iBAAiB,YAAY,MAAM,KAAM,KAAI,KAAK,MAAM,IAAI;AAChE,MAAI,KAAK,OAAO,SAAS,iBAAiB,SAAS,MAAM,MAAO,KAAI,KAAK,MAAM,KAAK;AACpF,MAAI,KAAK,MAAM;AACb,UAAM,OAAQ,MAA6B;AAC3C,YAAQ,OAAO;AAAA,MACb,GAAG,WAAW,EAAE,OAAO,EAAE,SAAS,UAAU,YAAY,KAAK,GAAG,GAAI,OAAO,SAAS,WAAW,EAAE,KAAK,IAAI,CAAC,EAAG,EAAE,CAAC,CAAC;AAAA;AAAA,IACpH;AAAA,EACF;AACF;AAIA,QACG,QAAQ,iBAAiB,EAAE,WAAW,KAAK,CAAC,EAC5C;AAAA,EACC;AAEF,EACC;AAAA,EACC;AAAA,EACA;AACF,EACC,OAAO,SAAS,qDAAqD,EACrE,OAAO,YAAY,2DAA2D,EAC9E;AAAA,EACC;AAAA,EACA;AACF,EACC,OAAO,eAAe,gEAAgE,EACtF,OAAO,kBAAkB,6DAA6D,EACtF;AAAA,EACC;AAAA,IACE,CACE,KACA,MACA,SACG,UAAU,KAAK,MAAM,IAAI;AAAA,EAChC;AACF;AAIF,QACG,QAAQ,OAAO,EACf,YAAY,kDAAkD,EAC9D,OAAO,OAAO,SAAO,SAAS,GAAG,CAAC,CAAC;AACtC,QACG,QAAQ,QAAQ,EAChB,YAAY,2BAA2B,EACvC,OAAO,OAAO,SAAO,UAAU,GAAG,CAAC,CAAC;AACvC,QACG,QAAQ,QAAQ,EAChB,YAAY,yBAAyB,EACrC,OAAO,OAAO,SAAO,UAAU,GAAG,CAAC,CAAC;AAIvC,QACG,QAAQ,IAAI,EACZ,MAAM,MAAM,EACZ,YAAY,iBAAiB,EAC7B,OAAO,cAAc,qBAAqB,EAC1C,OAAO,OAAO,CAAC,KAAK,SAAiC,QAAQ,KAAK,IAAI,CAAC,CAAC;AAC3E,QACG,QAAQ,aAAa,EACrB,YAAY,aAAa,EACzB,OAAO,OAAO,CAAC,KAAK,SAAiB,QAAQ,KAAK,IAAI,CAAC,CAAC;AAC3D,QACG,QAAQ,iBAAiB,EACzB,YAAY,mCAAmC,EAC/C,OAAO,OAAO,CAAC,KAAK,SAAiB,YAAY,KAAK,IAAI,CAAC,CAAC;AAC/D,QACG,QAAQ,0BAA0B,EAClC,YAAY,2DAA2D,EACvE;AAAA,EACC,OAAO,CAAC,KAAK,MAAc,cAAkC,SAAS,KAAK,MAAM,SAAS,CAAC;AAC7F;AACF,QACG,QAAQ,6BAA6B,EACrC,YAAY,gCAAgC,EAC5C,OAAO,OAAO,CAAC,KAAK,MAAc,cAAsB,YAAY,KAAK,MAAM,SAAS,CAAC,CAAC;AAC7F,QACG,QAAQ,cAAc,EACtB,YAAY,+EAA0E,EACtF,OAAO,aAAa,6CAA6C,EACjE,OAAO,YAAY,iBAAiB,EACpC;AAAA,EACC;AAAA,IAAO,CAAC,KAAK,MAAc,SACzB,SAAS,KAAK,MAAM,IAAI;AAAA,EAC1B;AACF;AACF,QACG,QAAQ,gCAAgC,EACxC,YAAY,+CAA+C,EAC3D,OAAO,OAAO,CAAC,KAAK,MAAc,eAAuB,cAAc,KAAK,MAAM,UAAU,CAAC,CAAC;AACjG,QACG,QAAQ,gBAAgB,EACxB,YAAY,mEAAmE,EAC/E,OAAO,OAAO,CAAC,KAAK,SAAiB,WAAW,KAAK,IAAI,CAAC,CAAC;AAC9D,QACG,QAAQ,kBAAkB,EAC1B,YAAY,6BAA6B,EACzC,OAAO,OAAO,CAAC,KAAK,SAAiB,WAAW,KAAK,MAAM,IAAI,CAAC,CAAC;AACpE,QACG,QAAQ,WAAW,EACnB,MAAM,QAAQ,EACd,YAAY,8DAA8D,EAC1E,OAAO,aAAa,6BAA6B,EACjD,OAAO,OAAO,CAAC,KAAK,MAAc,SAA4B,UAAU,KAAK,MAAM,IAAI,CAAC,CAAC;AAI5F,QACG,QAAQ,KAAK,EACb,YAAY,8DAA8D,EAC1E,OAAO,OAAO,OAAgB,YAAqB;AAClD,QAAM,UAAU,QAAQ,gBAA+B;AACvD,QAAM,aAAa,EAAE,QAAQ,QAAQ,OAAO,CAAC;AAC/C,CAAC;AAEH,QAAQ,WAAW,QAAQ,IAAI;",
6
+ "names": ["chalk", "z", "z", "z", "z", "z", "siteName", "z", "z", "n", "resolve", "siteUrl", "z", "resolve", "escapeHtml", "chalk", "chalk", "chalk", "z", "ShareResponseSchema", "z", "sitePath", "siteUrl", "chalk", "chalk", "readFile", "readFile", "stat", "join", "stat", "walk", "join", "siteName", "readFile", "homedir", "sep", "homedir", "sep", "siteName", "defaultSleep", "readFile", "mkdir", "readFile", "stat", "writeFile", "basename", "join", "resolve", "sep", "basename", "join", "stat", "readFile", "writeFile", "resolve", "sep", "mkdir", "escapeHtml", "readdir", "readFile", "realpath", "stat", "stat", "readdir", "realpath", "readFile", "fromEnv", "s", "chalk", "chalk", "chalk", "mkdir", "mkdtemp", "rm", "writeFile", "tmpdir", "basename", "dirname", "join", "z", "listHtml", "spa", "isPublic", "z", "basename", "mkdtemp", "join", "tmpdir", "rm", "mkdir", "dirname", "writeFile"]
7
+ }