emdash 0.0.1 → 0.0.3

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.
Files changed (36) hide show
  1. package/dist/astro/index.mjs +41 -38
  2. package/dist/astro/index.mjs.map +1 -1
  3. package/dist/astro/middleware.d.mts.map +1 -1
  4. package/dist/astro/middleware.mjs +18 -1
  5. package/dist/astro/middleware.mjs.map +1 -1
  6. package/dist/cli/index.mjs +1 -1
  7. package/dist/cli/index.mjs.map +1 -1
  8. package/dist/db/index.mjs +1 -1
  9. package/dist/index.mjs +1 -1
  10. package/dist/{runner-B-u2F2b6.mjs → runner-C0hCbYnD.mjs} +15 -15
  11. package/dist/runner-C0hCbYnD.mjs.map +1 -0
  12. package/dist/storage/local.d.mts.map +1 -1
  13. package/dist/storage/local.mjs.map +1 -1
  14. package/dist/storage/s3.d.mts.map +1 -1
  15. package/dist/storage/s3.mjs.map +1 -1
  16. package/package.json +5 -5
  17. package/src/api/handlers/device-flow.ts +1 -4
  18. package/src/api/handlers/oauth-clients.ts +1 -5
  19. package/src/astro/integration/index.ts +1 -1
  20. package/src/astro/integration/vite-config.ts +8 -1
  21. package/src/astro/middleware.ts +35 -0
  22. package/src/astro/routes/api/admin/comments/[id]/status.ts +1 -5
  23. package/src/astro/routes/api/auth/passkey/register/verify.ts +1 -3
  24. package/src/astro/routes/api/content/[collection]/[id]/schedule.ts +1 -5
  25. package/src/astro/routes/api/import/wordpress/analyze.ts +1 -1
  26. package/src/astro/routes/api/import/wordpress/media.ts +1 -1
  27. package/src/astro/routes/api/revisions/[revisionId]/restore.ts +1 -5
  28. package/src/astro/routes/api/widget-areas/[name]/reorder.ts +1 -5
  29. package/src/cli/commands/publish.ts +1 -3
  30. package/src/cli/commands/seed.ts +1 -3
  31. package/src/database/migrations/001_initial.ts +39 -5
  32. package/src/database/migrations/032_rate_limits.ts +1 -4
  33. package/src/mcp/server.ts +2 -2
  34. package/src/storage/local.ts +1 -5
  35. package/src/storage/s3.ts +2 -10
  36. package/dist/runner-B-u2F2b6.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["listCommand","getCommand","createCommand","deleteCommand","publishCommand","readPackageJson","fileExists","fileExists","fileExists","readPackageJson","listCommand","getCommand","deleteCommand","listCommand","getCommand","fileExists","fileExists","fileExists","listCommand","commonArgs","consola"],"sources":["../../src/cli/commands/auth.ts","../../src/cli/credentials.ts","../../src/cli/client-factory.ts","../../src/cli/output.ts","../../src/cli/commands/content.ts","../../src/cli/commands/dev.ts","../../src/cli/commands/doctor.ts","../../src/cli/commands/export-seed.ts","../../src/cli/commands/init.ts","../../src/cli/commands/login.ts","../../src/cli/commands/media.ts","../../src/cli/commands/menu.ts","../../src/cli/commands/bundle-utils.ts","../../src/cli/commands/bundle.ts","../../src/cli/commands/plugin-init.ts","../../src/cli/commands/plugin-validate.ts","../../src/cli/commands/publish.ts","../../src/cli/commands/plugin.ts","../../src/cli/commands/schema.ts","../../src/cli/commands/search-cmd.ts","../../src/cli/commands/seed.ts","../../src/cli/commands/taxonomy.ts","../../src/cli/commands/types.ts","../../src/cli/index.ts"],"sourcesContent":["/**\n * Auth CLI commands\n */\n\nimport { defineCommand } from \"citty\";\nimport { consola } from \"consola\";\nimport pc from \"picocolors\";\n\nimport { encodeBase64url } from \"../../utils/base64.js\";\n\n/**\n * Generate a cryptographically secure auth secret\n */\nfunction generateAuthSecret(): string {\n\tconst bytes = new Uint8Array(32);\n\tcrypto.getRandomValues(bytes);\n\treturn encodeBase64url(bytes);\n}\n\nconst secretCommand = defineCommand({\n\tmeta: {\n\t\tname: \"secret\",\n\t\tdescription: \"Generate a secure auth secret\",\n\t},\n\trun() {\n\t\tconst secret = generateAuthSecret();\n\n\t\tconsola.log(\"\");\n\t\tconsola.log(pc.bold(\"Generated auth secret:\"));\n\t\tconsola.log(\"\");\n\t\tconsola.log(` ${pc.cyan(\"EMDASH_AUTH_SECRET\")}=${pc.green(secret)}`);\n\t\tconsola.log(\"\");\n\t\tconsola.log(pc.dim(\"Add this to your environment variables.\"));\n\t\tconsola.log(\"\");\n\t},\n});\n\nexport const authCommand = defineCommand({\n\tmeta: {\n\t\tname: \"auth\",\n\t\tdescription: \"Authentication utilities\",\n\t},\n\tsubCommands: {\n\t\tsecret: secretCommand,\n\t},\n});\n","/**\n * Credential storage for CLI auth tokens.\n *\n * Stores OAuth tokens in ~/.config/emdash/auth.json.\n * Remote URLs are keyed by origin, local dev by project path.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface StoredCredential {\n\taccessToken: string;\n\trefreshToken: string;\n\texpiresAt: string;\n\turl?: string; // For local dev: the localhost URL\n\t/** Custom headers to send with every request (e.g. CF Access service token) */\n\tcustomHeaders?: Record<string, string>;\n\tuser?: {\n\t\temail: string;\n\t\trole: string;\n\t};\n}\n\n/** Credential for marketplace auth (GitHub OAuth JWT, no refresh token) */\nexport interface MarketplaceCredential {\n\ttoken: string;\n\texpiresAt: string;\n\tauthor?: {\n\t\tid: string;\n\t\tname: string;\n\t};\n}\n\ntype CredentialStore = Record<string, StoredCredential | MarketplaceCredential>;\n\n// ---------------------------------------------------------------------------\n// Paths\n// ---------------------------------------------------------------------------\n\nfunction getConfigDir(): string {\n\t// XDG_CONFIG_HOME or ~/.config\n\tconst xdg = process.env[\"XDG_CONFIG_HOME\"];\n\tif (xdg) return join(xdg, \"emdash\");\n\treturn join(homedir(), \".config\", \"emdash\");\n}\n\nfunction getCredentialPath(): string {\n\treturn join(getConfigDir(), \"auth.json\");\n}\n\n// ---------------------------------------------------------------------------\n// Key resolution\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the credential key for a given URL.\n *\n * Remote URLs are keyed by origin (e.g. \"https://my-site.pages.dev\").\n * Local dev instances are keyed by project path (e.g. \"path:/Users/matt/sites/blog\").\n */\nexport function resolveCredentialKey(baseUrl: string): string {\n\ttry {\n\t\tconst url = new URL(baseUrl);\n\t\tconst isLocal =\n\t\t\turl.hostname === \"localhost\" || url.hostname === \"127.0.0.1\" || url.hostname === \"[::1]\";\n\n\t\tif (isLocal) {\n\t\t\t// For local dev, key by project path\n\t\t\tconst projectPath = findProjectRoot(process.cwd());\n\t\t\tif (projectPath) {\n\t\t\t\treturn `path:${projectPath}`;\n\t\t\t}\n\t\t\t// Fallback to URL if no project root found\n\t\t\treturn url.origin;\n\t\t}\n\n\t\treturn url.origin;\n\t} catch {\n\t\treturn baseUrl;\n\t}\n}\n\n/**\n * Walk up from cwd to find the project root (directory containing astro.config.*).\n */\nfunction findProjectRoot(from: string): string | null {\n\tlet dir = resolve(from);\n\tconst root = resolve(\"/\");\n\n\twhile (dir !== root) {\n\t\tfor (const name of [\n\t\t\t\"astro.config.ts\",\n\t\t\t\"astro.config.mts\",\n\t\t\t\"astro.config.js\",\n\t\t\t\"astro.config.mjs\",\n\t\t]) {\n\t\t\tif (existsSync(join(dir, name))) {\n\t\t\t\treturn dir;\n\t\t\t}\n\t\t}\n\t\tconst parent = resolve(dir, \"..\");\n\t\tif (parent === dir) break;\n\t\tdir = parent;\n\t}\n\n\treturn null;\n}\n\n// ---------------------------------------------------------------------------\n// Read/write\n// ---------------------------------------------------------------------------\n\nfunction readStore(): CredentialStore {\n\tconst path = getCredentialPath();\n\ttry {\n\t\tif (existsSync(path)) {\n\t\t\tconst content = readFileSync(path, \"utf-8\");\n\t\t\treturn JSON.parse(content) as CredentialStore;\n\t\t}\n\t} catch {\n\t\t// Corrupt file — start fresh\n\t}\n\treturn {};\n}\n\nfunction writeStore(store: CredentialStore): void {\n\tconst dir = getConfigDir();\n\tmkdirSync(dir, { recursive: true });\n\n\tconst path = getCredentialPath();\n\twriteFileSync(path, JSON.stringify(store, null, \"\\t\"), {\n\t\tencoding: \"utf-8\",\n\t\tmode: 0o600, // Owner read/write only\n\t});\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Get stored credentials for a URL.\n */\nexport function getCredentials(baseUrl: string): StoredCredential | null {\n\tconst key = resolveCredentialKey(baseUrl);\n\tconst store = readStore();\n\tconst cred = store[key];\n\tif (!cred || !(\"accessToken\" in cred)) return null;\n\treturn cred;\n}\n\n/**\n * Save credentials for a URL.\n */\nexport function saveCredentials(baseUrl: string, cred: StoredCredential): void {\n\tconst key = resolveCredentialKey(baseUrl);\n\tconst store = readStore();\n\tstore[key] = cred;\n\twriteStore(store);\n}\n\n/**\n * Remove credentials for a URL.\n */\nexport function removeCredentials(baseUrl: string): boolean {\n\tconst key = resolveCredentialKey(baseUrl);\n\tconst store = readStore();\n\tif (key in store) {\n\t\tdelete store[key];\n\t\twriteStore(store);\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n/**\n * List all stored credential keys.\n */\nexport function listCredentialKeys(): string[] {\n\tconst store = readStore();\n\treturn Object.keys(store);\n}\n\n// ---------------------------------------------------------------------------\n// Marketplace credentials\n// ---------------------------------------------------------------------------\n\nfunction marketplaceKey(registryUrl: string): string {\n\ttry {\n\t\treturn `marketplace:${new URL(registryUrl).origin}`;\n\t} catch {\n\t\treturn `marketplace:${registryUrl}`;\n\t}\n}\n\n/**\n * Get stored marketplace credential for a registry URL.\n */\nexport function getMarketplaceCredential(registryUrl: string): MarketplaceCredential | null {\n\tconst key = marketplaceKey(registryUrl);\n\tconst store = readStore();\n\tconst cred = store[key];\n\tif (!cred || !(\"token\" in cred)) return null;\n\t// Check expiry\n\tif (new Date(cred.expiresAt) < new Date()) return null;\n\treturn cred;\n}\n\n/**\n * Save marketplace credential for a registry URL.\n */\nexport function saveMarketplaceCredential(registryUrl: string, cred: MarketplaceCredential): void {\n\tconst key = marketplaceKey(registryUrl);\n\tconst store = readStore();\n\tstore[key] = cred;\n\twriteStore(store);\n}\n\n/**\n * Remove marketplace credential for a registry URL.\n */\nexport function removeMarketplaceCredential(registryUrl: string): boolean {\n\tconst key = marketplaceKey(registryUrl);\n\tconst store = readStore();\n\tif (key in store) {\n\t\tdelete store[key];\n\t\twriteStore(store);\n\t\treturn true;\n\t}\n\treturn false;\n}\n","import { customHeadersInterceptor, resolveCustomHeaders } from \"../client/cf-access.js\";\nimport { EmDashClient } from \"../client/index.js\";\nimport type { Interceptor } from \"../client/transport.js\";\nimport { getCredentials, saveCredentials } from \"./credentials.js\";\n\nexport interface ClientArgs {\n\turl?: string;\n\ttoken?: string;\n}\n\n/**\n * Shared connection args for all CLI commands that talk to an EmDash instance.\n * Spread into each command's `args` definition.\n */\nexport const connectionArgs = {\n\turl: {\n\t\ttype: \"string\" as const,\n\t\talias: \"u\",\n\t\tdescription: \"EmDash instance URL\",\n\t\tdefault: \"http://localhost:4321\",\n\t},\n\ttoken: {\n\t\ttype: \"string\" as const,\n\t\talias: \"t\",\n\t\tdescription: \"Auth token\",\n\t},\n\theader: {\n\t\ttype: \"string\" as const,\n\t\talias: \"H\",\n\t\tdescription: 'Custom header \"Name: Value\" (repeatable, or use EMDASH_HEADERS env)',\n\t},\n\tjson: {\n\t\ttype: \"boolean\" as const,\n\t\tdescription: \"Output as JSON\",\n\t},\n};\n\n/**\n * Create an EmDashClient from CLI args, env vars, and stored credentials.\n *\n * Auth resolution order:\n * 1. --token flag\n * 2. EMDASH_TOKEN env var\n * 3. Stored credentials (~/.config/emdash/auth.json)\n * 4. Dev bypass (if URL is localhost)\n *\n * Custom headers are merged from (in priority order):\n * 1. Stored credentials (persisted during `emdash login --header`)\n * 2. EMDASH_HEADERS env var\n * 3. --header CLI flags\n */\nexport function createClientFromArgs(args: ClientArgs): EmDashClient {\n\tconst baseUrl = args.url || process.env[\"EMDASH_URL\"] || \"http://localhost:4321\";\n\tlet token = args.token || process.env[\"EMDASH_TOKEN\"];\n\n\tconst isLocal = baseUrl.includes(\"localhost\") || baseUrl.includes(\"127.0.0.1\");\n\tconst cred = !token ? getCredentials(baseUrl) : null;\n\n\t// Merge custom headers: stored credentials < env var < CLI flags\n\tconst customHeaders = {\n\t\t...cred?.customHeaders,\n\t\t...resolveCustomHeaders(),\n\t};\n\n\tconst extraInterceptors: Interceptor[] = [];\n\tif (Object.keys(customHeaders).length > 0) {\n\t\textraInterceptors.push(customHeadersInterceptor(customHeaders));\n\t}\n\n\t// Check stored credentials if no explicit token\n\tif (!token && cred) {\n\t\t// Check if access token is expired\n\t\tif (new Date(cred.expiresAt) > new Date()) {\n\t\t\ttoken = cred.accessToken;\n\t\t} else {\n\t\t\t// Token expired — use the refresh interceptor in the client\n\t\t\t// Pass the refresh token so the client can auto-refresh\n\t\t\treturn new EmDashClient({\n\t\t\t\tbaseUrl,\n\t\t\t\ttoken: cred.accessToken,\n\t\t\t\trefreshToken: cred.refreshToken,\n\t\t\t\tonTokenRefresh: (newAccessToken, expiresIn) => {\n\t\t\t\t\tsaveCredentials(baseUrl, {\n\t\t\t\t\t\t...cred,\n\t\t\t\t\t\taccessToken: newAccessToken,\n\t\t\t\t\t\texpiresAt: new Date(Date.now() + expiresIn * 1000).toISOString(),\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\tinterceptors: extraInterceptors,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn new EmDashClient({\n\t\tbaseUrl,\n\t\ttoken,\n\t\tdevBypass: !token && isLocal,\n\t\tinterceptors: extraInterceptors,\n\t});\n}\n","import { consola } from \"consola\";\n\ninterface OutputArgs {\n\tjson?: boolean;\n}\n\n/**\n * Output data as JSON or pretty-printed.\n *\n * If stdout is not a TTY or --json is set, outputs JSON.\n * Otherwise, outputs a formatted representation.\n */\nexport function output(data: unknown, args: OutputArgs): void {\n\tconst useJson = args.json || !process.stdout.isTTY;\n\n\tif (useJson) {\n\t\t// JSON output to stdout for piping\n\t\tprocess.stdout.write(JSON.stringify(data, null, 2) + \"\\n\");\n\t} else {\n\t\t// Pretty output via consola\n\t\tprettyPrint(data);\n\t}\n}\n\nfunction prettyPrint(data: unknown, indent: number = 0): void {\n\tif (data === null || data === undefined) {\n\t\tconsola.log(\"(empty)\");\n\t\treturn;\n\t}\n\n\tif (Array.isArray(data)) {\n\t\tif (data.length === 0) {\n\t\t\tconsola.log(\"(no items)\");\n\t\t\treturn;\n\t\t}\n\t\tfor (const item of data) {\n\t\t\tprettyPrint(item, indent);\n\t\t\tif (indent === 0) consola.log(\"---\");\n\t\t}\n\t\treturn;\n\t}\n\n\tif (typeof data === \"object\") {\n\t\tconst obj = Object(data) as Record<string, unknown>;\n\n\t\t// Check if it's a list result with items\n\t\tif (\"items\" in obj && Array.isArray(obj.items)) {\n\t\t\tprettyPrint(obj.items, indent);\n\t\t\tif (typeof obj.nextCursor === \"string\") {\n\t\t\t\tconsola.log(`\\nNext cursor: ${obj.nextCursor}`);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Print object fields\n\t\tconst prefix = \" \".repeat(indent);\n\t\tfor (const [key, value] of Object.entries(obj)) {\n\t\t\tif (value === null || value === undefined) continue;\n\t\t\tif (typeof value === \"object\" && !Array.isArray(value)) {\n\t\t\t\tconsola.log(`${prefix}${key}:`);\n\t\t\t\tprettyPrint(value, indent + 1);\n\t\t\t} else if (Array.isArray(value)) {\n\t\t\t\tconsola.log(`${prefix}${key}: [${value.length} items]`);\n\t\t\t} else {\n\t\t\t\tconst str = typeof value === \"string\" ? value : JSON.stringify(value);\n\t\t\t\t// Truncate long values\n\t\t\t\tconst display = str.length > 80 ? str.slice(0, 77) + \"...\" : str;\n\t\t\t\tconsola.log(`${prefix}${key}: ${display}`);\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\n\tconsola.log(typeof data === \"string\" ? data : JSON.stringify(data));\n}\n","/**\n * emdash content\n *\n * CRUD commands for managing content items via the EmDash REST API.\n */\n\nimport { readFile } from \"node:fs/promises\";\n\nimport { defineCommand } from \"citty\";\nimport { consola } from \"consola\";\n\nimport { connectionArgs, createClientFromArgs } from \"../client-factory.js\";\nimport { output } from \"../output.js\";\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Read content data from --data, --file, or --stdin */\nasync function readInputData(args: {\n\tdata?: string;\n\tfile?: string;\n\tstdin?: boolean;\n}): Promise<Record<string, unknown>> {\n\tif (args.data) {\n\t\ttry {\n\t\t\treturn JSON.parse(args.data) as Record<string, unknown>;\n\t\t} catch {\n\t\t\tthrow new Error(\"Invalid JSON in --data argument\");\n\t\t}\n\t}\n\n\tif (args.file) {\n\t\ttry {\n\t\t\tconst content = await readFile(args.file, \"utf-8\");\n\t\t\treturn JSON.parse(content) as Record<string, unknown>;\n\t\t} catch (error) {\n\t\t\tif (error instanceof SyntaxError) {\n\t\t\t\tthrow new Error(`Invalid JSON in file: ${args.file}`, { cause: error });\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tif (args.stdin) {\n\t\tconst chunks: Buffer[] = [];\n\t\tfor await (const chunk of process.stdin) {\n\t\t\tchunks.push(chunk as Buffer);\n\t\t}\n\t\tconst content = Buffer.concat(chunks).toString(\"utf-8\");\n\t\ttry {\n\t\t\treturn JSON.parse(content) as Record<string, unknown>;\n\t\t} catch {\n\t\t\tthrow new Error(\"Invalid JSON from stdin\");\n\t\t}\n\t}\n\n\tthrow new Error(\"Provide content data via --data, --file, or --stdin\");\n}\n\n// ---------------------------------------------------------------------------\n// Subcommands\n// ---------------------------------------------------------------------------\n\nconst listCommand = defineCommand({\n\tmeta: { name: \"list\", description: \"List content items\" },\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tstatus: { type: \"string\", description: \"Filter by status\" },\n\t\tlocale: { type: \"string\", description: \"Filter by locale\" },\n\t\tlimit: { type: \"string\", description: \"Maximum items to return\" },\n\t\tcursor: { type: \"string\", description: \"Pagination cursor\" },\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst result = await client.list(args.collection, {\n\t\t\t\tstatus: args.status,\n\t\t\t\tlocale: args.locale,\n\t\t\t\tlimit: args.limit ? parseInt(args.limit, 10) : undefined,\n\t\t\t\tcursor: args.cursor,\n\t\t\t});\n\t\t\t// Summarize items — strip heavy data fields for readable output\n\t\t\tconst summary = {\n\t\t\t\titems: result.items.map((item) => ({\n\t\t\t\t\tid: item.id,\n\t\t\t\t\tslug: item.slug,\n\t\t\t\t\tlocale: item.locale,\n\t\t\t\t\tstatus: item.status,\n\t\t\t\t\ttitle: typeof item.data?.title === \"string\" ? item.data.title : undefined,\n\t\t\t\t\tupdatedAt: item.updatedAt,\n\t\t\t\t})),\n\t\t\t\tnextCursor: result.nextCursor,\n\t\t\t};\n\t\t\toutput(summary, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst getCommand = defineCommand({\n\tmeta: { name: \"get\", description: \"Get a single content item\" },\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tid: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Content item ID or slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tlocale: { type: \"string\", description: \"Locale for slug resolution\" },\n\t\traw: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Return raw Portable Text (skip markdown conversion)\",\n\t\t},\n\t\tpublished: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Return published data only (ignore pending draft)\",\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst item = await client.get(args.collection, args.id, {\n\t\t\t\traw: args.raw,\n\t\t\t\tlocale: args.locale,\n\t\t\t});\n\n\t\t\t// If a draft exists, overlay draft data unless --published\n\t\t\tif (!args.published && item.draftRevisionId) {\n\t\t\t\tconst comparison = await client.compare(args.collection, args.id);\n\t\t\t\tif (comparison.hasChanges && comparison.draft) {\n\t\t\t\t\titem.data = comparison.draft;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\toutput(item, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst createCommand = defineCommand({\n\tmeta: { name: \"create\", description: \"Create a content item\" },\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tdata: { type: \"string\", description: \"Content data as JSON string\" },\n\t\tfile: { type: \"string\", description: \"Read content data from a JSON file\" },\n\t\tstdin: { type: \"boolean\", description: \"Read content data from stdin\" },\n\t\tslug: { type: \"string\", description: \"Content slug\" },\n\t\tlocale: { type: \"string\", description: \"Content locale\" },\n\t\t\"translation-of\": {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"ID of content item to link as translation\",\n\t\t},\n\t\tdraft: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Keep as draft instead of auto-publishing\",\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst data = await readInputData(args);\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst item = await client.create(args.collection, {\n\t\t\t\tdata,\n\t\t\t\tslug: args.slug,\n\t\t\t\tlocale: args.locale,\n\t\t\t\ttranslationOf: args[\"translation-of\"],\n\t\t\t});\n\n\t\t\t// Auto-publish unless --draft is set\n\t\t\tif (!args.draft) {\n\t\t\t\tawait client.publish(args.collection, item.id);\n\t\t\t}\n\n\t\t\t// Re-fetch to return the current state\n\t\t\tconst result = await client.get(args.collection, item.id);\n\t\t\toutput(result, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst updateCommand = defineCommand({\n\tmeta: { name: \"update\", description: \"Update a content item\" },\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tid: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Content item ID or slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tdata: { type: \"string\", description: \"Content data as JSON string\" },\n\t\tfile: { type: \"string\", description: \"Read content data from a JSON file\" },\n\t\trev: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Revision token from get (prevents overwriting unseen changes)\",\n\t\t\trequired: true,\n\t\t},\n\t\tdraft: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Keep as draft instead of auto-publishing\",\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst data = await readInputData(args);\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst updated = await client.update(args.collection, args.id, {\n\t\t\t\tdata,\n\t\t\t\t_rev: args.rev,\n\t\t\t});\n\n\t\t\t// Auto-publish unless --draft is set.\n\t\t\t// Only publish if the update created a draft revision (i.e. the\n\t\t\t// collection supports revisions and data went to a draft).\n\t\t\tif (!args.draft && updated.draftRevisionId) {\n\t\t\t\tawait client.publish(args.collection, args.id);\n\t\t\t}\n\n\t\t\t// Re-fetch to return the current state\n\t\t\tconst item = await client.get(args.collection, args.id);\n\t\t\toutput(item, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst deleteCommand = defineCommand({\n\tmeta: { name: \"delete\", description: \"Delete a content item\" },\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tid: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Content item ID or slug\",\n\t\t\trequired: true,\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tawait client.delete(args.collection, args.id);\n\t\t\tconsola.success(`Deleted ${args.collection}/${args.id}`);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst publishCommand = defineCommand({\n\tmeta: { name: \"publish\", description: \"Publish a content item\" },\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tid: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Content item ID or slug\",\n\t\t\trequired: true,\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tawait client.publish(args.collection, args.id);\n\t\t\tconsola.success(`Published ${args.collection}/${args.id}`);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst unpublishCommand = defineCommand({\n\tmeta: { name: \"unpublish\", description: \"Unpublish a content item\" },\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tid: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Content item ID or slug\",\n\t\t\trequired: true,\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tawait client.unpublish(args.collection, args.id);\n\t\t\tconsola.success(`Unpublished ${args.collection}/${args.id}`);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst scheduleCommand = defineCommand({\n\tmeta: { name: \"schedule\", description: \"Schedule content for publishing\" },\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tid: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Content item ID or slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tat: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"ISO 8601 datetime to publish at\",\n\t\t\trequired: true,\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tawait client.schedule(args.collection, args.id, { at: args.at });\n\t\t\tconsola.success(`Scheduled ${args.collection}/${args.id} for ${args.at}`);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst restoreCommand = defineCommand({\n\tmeta: { name: \"restore\", description: \"Restore a trashed content item\" },\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tid: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Content item ID or slug\",\n\t\t\trequired: true,\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tawait client.restore(args.collection, args.id);\n\t\t\tconsola.success(`Restored ${args.collection}/${args.id}`);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst translationsCommand = defineCommand({\n\tmeta: { name: \"translations\", description: \"List translations for a content item\" },\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tid: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Content item ID or slug\",\n\t\t\trequired: true,\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst translations = await client.translations(args.collection, args.id);\n\t\t\toutput(translations, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\n// ---------------------------------------------------------------------------\n// Export\n// ---------------------------------------------------------------------------\n\nexport const contentCommand = defineCommand({\n\tmeta: { name: \"content\", description: \"Manage content\" },\n\tsubCommands: {\n\t\tlist: listCommand,\n\t\tget: getCommand,\n\t\tcreate: createCommand,\n\t\tupdate: updateCommand,\n\t\tdelete: deleteCommand,\n\t\tpublish: publishCommand,\n\t\tunpublish: unpublishCommand,\n\t\tschedule: scheduleCommand,\n\t\trestore: restoreCommand,\n\t\ttranslations: translationsCommand,\n\t},\n});\n","/**\n * emdash dev\n *\n * Start development server with optional schema sync from remote\n */\n\nimport { spawn } from \"node:child_process\";\nimport { readFile, access } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\n\nimport { defineCommand } from \"citty\";\nimport consola from \"consola\";\n\nimport { createDatabase } from \"../../database/connection.js\";\nimport { runMigrations } from \"../../database/migrations/runner.js\";\n\ninterface PackageJson {\n\tname?: string;\n\tscripts?: Record<string, string>;\n\temdash?: {\n\t\turl?: string;\n\t\tdatabase?: string;\n\t};\n}\n\nasync function readPackageJson(cwd: string): Promise<PackageJson | null> {\n\tconst pkgPath = resolve(cwd, \"package.json\");\n\ttry {\n\t\tconst content = await readFile(pkgPath, \"utf-8\");\n\t\treturn JSON.parse(content);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nasync function fileExists(path: string): Promise<boolean> {\n\ttry {\n\t\tawait access(path);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nexport const devCommand = defineCommand({\n\tmeta: {\n\t\tname: \"dev\",\n\t\tdescription: \"Start dev server with local database\",\n\t},\n\targs: {\n\t\tdatabase: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"d\",\n\t\t\tdescription: \"Database path (default: ./data.db)\",\n\t\t\tdefault: \"./data.db\",\n\t\t},\n\t\ttypes: {\n\t\t\ttype: \"boolean\",\n\t\t\talias: \"t\",\n\t\t\tdescription: \"Generate types from remote before starting\",\n\t\t\tdefault: false,\n\t\t},\n\t\tport: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"p\",\n\t\t\tdescription: \"Port for dev server\",\n\t\t\tdefault: \"4321\",\n\t\t},\n\t\tcwd: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Working directory\",\n\t\t\tdefault: process.cwd(),\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst cwd = resolve(args.cwd);\n\t\tconst pkg = await readPackageJson(cwd);\n\n\t\tif (!pkg) {\n\t\t\tconsola.error(\"No package.json found\");\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tconst dbPath = resolve(cwd, args.database);\n\n\t\t// Run migrations if database doesn't exist\n\t\tconst dbExists = await fileExists(dbPath);\n\t\tif (!dbExists) {\n\t\t\tconsola.start(\"Database not found, initializing...\");\n\t\t}\n\n\t\t// Always run migrations (they're idempotent)\n\t\tconst db = createDatabase({ url: `file:${dbPath}` });\n\t\ttry {\n\t\t\tconsola.start(\"Checking database migrations...\");\n\t\t\tconst { applied } = await runMigrations(db);\n\t\t\tif (applied.length > 0) {\n\t\t\t\tconsola.success(`Applied ${applied.length} migrations`);\n\t\t\t} else {\n\t\t\t\tconsola.info(\"Database up to date\");\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsola.error(\"Migration failed:\", error);\n\t\t\tawait db.destroy();\n\t\t\tprocess.exit(1);\n\t\t}\n\t\tawait db.destroy();\n\n\t\t// Generate types from remote if requested\n\t\tif (args.types) {\n\t\t\tconst remoteUrl = pkg.emdash?.url || process.env.EMDASH_URL;\n\n\t\t\tif (!remoteUrl) {\n\t\t\t\tconsola.warn(\"No remote URL configured. Set EMDASH_URL or emdash.url in package.json\");\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tconst { createClientFromArgs } = await import(\"../client-factory.js\");\n\t\t\t\t\tconst client = createClientFromArgs({ url: remoteUrl });\n\t\t\t\t\tconst schema = await client.schemaExport();\n\t\t\t\t\tconst types = await client.schemaTypes();\n\n\t\t\t\t\tconst { writeFile, mkdir } = await import(\"node:fs/promises\");\n\t\t\t\t\tconst { resolve: resolvePath, dirname } = await import(\"node:path\");\n\t\t\t\t\tconst outputPath = resolvePath(cwd, \".emdash/types.ts\");\n\t\t\t\t\tawait mkdir(dirname(outputPath), { recursive: true });\n\t\t\t\t\tawait writeFile(outputPath, types, \"utf-8\");\n\t\t\t\t\tawait writeFile(\n\t\t\t\t\t\tresolvePath(dirname(outputPath), \"schema.json\"),\n\t\t\t\t\t\tJSON.stringify(schema, null, 2),\n\t\t\t\t\t\t\"utf-8\",\n\t\t\t\t\t);\n\t\t\t\t\tconsola.success(`Generated types for ${schema.collections.length} collections`);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsola.warn(\"Type generation failed:\", error instanceof Error ? error.message : error);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Start Astro dev server\n\t\tconsola.start(\"Starting Astro dev server...\");\n\n\t\tconst astroArgs = [\"astro\", \"dev\", \"--port\", args.port];\n\n\t\t// Check if using pnpm, npm, or yarn\n\t\tconst pnpmLockExists = await fileExists(resolve(cwd, \"pnpm-lock.yaml\"));\n\t\tconst yarnLockExists = await fileExists(resolve(cwd, \"yarn.lock\"));\n\n\t\tlet cmd: string;\n\t\tlet cmdArgs: string[];\n\n\t\tif (pnpmLockExists) {\n\t\t\tcmd = \"pnpm\";\n\t\t\tcmdArgs = astroArgs;\n\t\t} else if (yarnLockExists) {\n\t\t\tcmd = \"yarn\";\n\t\t\tcmdArgs = astroArgs;\n\t\t} else {\n\t\t\tcmd = \"npx\";\n\t\t\tcmdArgs = astroArgs;\n\t\t}\n\n\t\tconsola.info(`Running: ${cmd} ${cmdArgs.join(\" \")}`);\n\n\t\tconst child = spawn(cmd, cmdArgs, {\n\t\t\tcwd,\n\t\t\tstdio: \"inherit\",\n\t\t\tenv: {\n\t\t\t\t...process.env,\n\t\t\t\t// Pass database path to Astro\n\t\t\t\tEMDASH_DATABASE_URL: `file:${dbPath}`,\n\t\t\t},\n\t\t});\n\n\t\tchild.on(\"error\", (error) => {\n\t\t\tconsola.error(\"Failed to start dev server:\", error);\n\t\t\tprocess.exit(1);\n\t\t});\n\n\t\tchild.on(\"exit\", (code) => {\n\t\t\tprocess.exit(code ?? 0);\n\t\t});\n\n\t\t// Handle termination signals\n\t\tconst cleanup = () => {\n\t\t\tchild.kill(\"SIGTERM\");\n\t\t};\n\n\t\tprocess.on(\"SIGINT\", cleanup);\n\t\tprocess.on(\"SIGTERM\", cleanup);\n\t},\n});\n","/**\n * emdash doctor\n *\n * Diagnose database health: connection, migrations, schema integrity.\n */\n\nimport { access } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\n\nimport { defineCommand } from \"citty\";\nimport consola from \"consola\";\n\nimport { createDatabase } from \"../../database/connection.js\";\nimport { listTablesLike } from \"../../database/dialect-helpers.js\";\nimport { getMigrationStatus } from \"../../database/migrations/runner.js\";\n\ninterface CheckResult {\n\tname: string;\n\tstatus: \"pass\" | \"warn\" | \"fail\";\n\tmessage: string;\n}\n\nasync function fileExists(path: string): Promise<boolean> {\n\ttry {\n\t\tawait access(path);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction printResult(result: CheckResult): void {\n\tconst color =\n\t\tresult.status === \"pass\"\n\t\t\t? consola.success\n\t\t\t: result.status === \"warn\"\n\t\t\t\t? consola.warn\n\t\t\t\t: consola.error;\n\tcolor(`${result.name}: ${result.message}`);\n}\n\nasync function checkDatabase(dbPath: string): Promise<CheckResult[]> {\n\tconst results: CheckResult[] = [];\n\n\t// Check database file exists\n\tif (!(await fileExists(dbPath))) {\n\t\tresults.push({\n\t\t\tname: \"database\",\n\t\t\tstatus: \"fail\",\n\t\t\tmessage: `not found at ${dbPath} — run \"emdash init\"`,\n\t\t});\n\t\treturn results;\n\t}\n\n\tresults.push({\n\t\tname: \"database\",\n\t\tstatus: \"pass\",\n\t\tmessage: dbPath,\n\t});\n\n\t// Connect and check migrations\n\tlet db;\n\ttry {\n\t\tdb = createDatabase({ url: `file:${dbPath}` });\n\n\t\tconst { applied, pending } = await getMigrationStatus(db);\n\t\tif (pending.length === 0) {\n\t\t\tresults.push({\n\t\t\t\tname: \"migrations\",\n\t\t\t\tstatus: \"pass\",\n\t\t\t\tmessage: `${applied.length} applied, none pending`,\n\t\t\t});\n\t\t} else {\n\t\t\tresults.push({\n\t\t\t\tname: \"migrations\",\n\t\t\t\tstatus: \"warn\",\n\t\t\t\tmessage: `${applied.length} applied, ${pending.length} pending — run \"emdash init\"`,\n\t\t\t});\n\t\t}\n\n\t\tconst { sql } = await import(\"kysely\");\n\n\t\t// Check collections exist\n\t\ttry {\n\t\t\tconst collectionsResult = await sql<{\n\t\t\t\tcount: number;\n\t\t\t}>`SELECT COUNT(id) as count FROM _emdash_collections`.execute(db);\n\t\t\tconst count = collectionsResult.rows[0]?.count ?? 0;\n\t\t\tresults.push({\n\t\t\t\tname: \"collections\",\n\t\t\t\tstatus: count > 0 ? \"pass\" : \"warn\",\n\t\t\t\tmessage:\n\t\t\t\t\tcount > 0 ? `${count} collections defined` : \"no collections — seed or create via admin\",\n\t\t\t});\n\t\t} catch {\n\t\t\tresults.push({\n\t\t\t\tname: \"collections\",\n\t\t\t\tstatus: \"fail\",\n\t\t\t\tmessage: \"could not query collections table — migrations may not have run\",\n\t\t\t});\n\t\t}\n\n\t\t// Check for orphaned ec_ tables without matching collection records\n\t\ttry {\n\t\t\tconst tableNames = await listTablesLike(db, \"ec_%\");\n\t\t\tconst collectionsResult = await sql<{\n\t\t\t\tslug: string;\n\t\t\t}>`SELECT slug FROM _emdash_collections`.execute(db);\n\t\t\tconst registeredSlugs = new Set(collectionsResult.rows.map((r) => `ec_${r.slug}`));\n\t\t\tconst orphaned = tableNames.filter((name) => !registeredSlugs.has(name));\n\n\t\t\tif (orphaned.length > 0) {\n\t\t\t\tresults.push({\n\t\t\t\t\tname: \"orphaned tables\",\n\t\t\t\t\tstatus: \"warn\",\n\t\t\t\t\tmessage: `found ${orphaned.length}: ${orphaned.join(\", \")}`,\n\t\t\t\t});\n\t\t\t}\n\t\t} catch {\n\t\t\t// Non-critical — tables may not exist on fresh DB\n\t\t}\n\n\t\t// Check users exist\n\t\ttry {\n\t\t\tconst usersResult = await sql<{\n\t\t\t\tcount: number;\n\t\t\t}>`SELECT COUNT(id) as count FROM _emdash_users`.execute(db);\n\t\t\tconst count = usersResult.rows[0]?.count ?? 0;\n\t\t\tresults.push({\n\t\t\t\tname: \"users\",\n\t\t\t\tstatus: count > 0 ? \"pass\" : \"warn\",\n\t\t\t\tmessage:\n\t\t\t\t\tcount > 0 ? `${count} users` : \"no users — complete setup wizard at /_emdash/admin\",\n\t\t\t});\n\t\t} catch {\n\t\t\tresults.push({\n\t\t\t\tname: \"users\",\n\t\t\t\tstatus: \"warn\",\n\t\t\t\tmessage: \"could not query users table\",\n\t\t\t});\n\t\t}\n\t} catch (error) {\n\t\tresults.push({\n\t\t\tname: \"database connection\",\n\t\t\tstatus: \"fail\",\n\t\t\tmessage: error instanceof Error ? error.message : \"failed to connect\",\n\t\t});\n\t} finally {\n\t\tif (db) {\n\t\t\tawait db.destroy();\n\t\t}\n\t}\n\n\treturn results;\n}\n\nexport const doctorCommand = defineCommand({\n\tmeta: {\n\t\tname: \"doctor\",\n\t\tdescription: \"Check database health and diagnose issues\",\n\t},\n\targs: {\n\t\tdatabase: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"d\",\n\t\t\tdescription: \"Database path (default: ./data.db)\",\n\t\t\tdefault: \"./data.db\",\n\t\t},\n\t\tcwd: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Working directory\",\n\t\t\tdefault: process.cwd(),\n\t\t},\n\t\tjson: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Output results as JSON\",\n\t\t\tdefault: false,\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst cwd = resolve(args.cwd);\n\t\tconst dbPath = resolve(cwd, args.database);\n\n\t\tconst results = await checkDatabase(dbPath);\n\n\t\tif (args.json) {\n\t\t\tprocess.stdout.write(JSON.stringify(results, null, 2) + \"\\n\");\n\t\t\treturn;\n\t\t}\n\n\t\tconsola.start(\"EmDash Doctor\\n\");\n\n\t\tfor (const result of results) {\n\t\t\tprintResult(result);\n\t\t}\n\n\t\t// Summary\n\t\tconst fails = results.filter((r) => r.status === \"fail\");\n\t\tconst warns = results.filter((r) => r.status === \"warn\");\n\n\t\tconsola.log(\"\");\n\t\tif (fails.length === 0 && warns.length === 0) {\n\t\t\tconsola.success(\"All checks passed\");\n\t\t} else if (fails.length === 0) {\n\t\t\tconsola.info(`All critical checks passed (${warns.length} warnings)`);\n\t\t} else {\n\t\t\tconsola.error(`${fails.length} issues found`);\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\t},\n});\n","/**\n * emdash export-seed\n *\n * Export current database schema (and optionally content) as a seed file\n */\n\nimport { resolve } from \"node:path\";\n\nimport { defineCommand } from \"citty\";\nimport consola from \"consola\";\nimport type { Kysely } from \"kysely\";\n\nimport { createDatabase } from \"../../database/connection.js\";\nimport { runMigrations } from \"../../database/migrations/runner.js\";\nimport { ContentRepository } from \"../../database/repositories/content.js\";\nimport { MediaRepository } from \"../../database/repositories/media.js\";\nimport { OptionsRepository } from \"../../database/repositories/options.js\";\nimport { TaxonomyRepository } from \"../../database/repositories/taxonomy.js\";\nimport type { Database } from \"../../database/types.js\";\nimport { isI18nEnabled } from \"../../i18n/config.js\";\nimport { SchemaRegistry } from \"../../schema/registry.js\";\nimport type { FieldType } from \"../../schema/types.js\";\nimport type {\n\tSeedFile,\n\tSeedCollection,\n\tSeedField,\n\tSeedTaxonomy,\n\tSeedTaxonomyTerm,\n\tSeedMenu,\n\tSeedMenuItem,\n\tSeedWidgetArea,\n\tSeedWidget,\n\tSeedContentEntry,\n} from \"../../seed/types.js\";\n\nconst SETTINGS_PREFIX = \"site:\";\n\nexport const exportSeedCommand = defineCommand({\n\tmeta: {\n\t\tname: \"export-seed\",\n\t\tdescription: \"Export database schema and content as a seed file\",\n\t},\n\targs: {\n\t\tdatabase: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"d\",\n\t\t\tdescription: \"Database path\",\n\t\t\tdefault: \"./data.db\",\n\t\t},\n\t\tcwd: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Working directory\",\n\t\t\tdefault: process.cwd(),\n\t\t},\n\t\t\"with-content\": {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Include content (all or comma-separated collection names)\",\n\t\t\trequired: false,\n\t\t},\n\t\tpretty: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Pretty print JSON output\",\n\t\t\tdefault: true,\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst cwd = resolve(args.cwd);\n\n\t\t// Connect to database\n\t\tconst dbPath = resolve(cwd, args.database);\n\t\tconsola.info(`Database: ${dbPath}`);\n\n\t\tconst db = createDatabase({ url: `file:${dbPath}` });\n\n\t\t// Run migrations to ensure tables exist\n\t\ttry {\n\t\t\tawait runMigrations(db);\n\t\t} catch (error) {\n\t\t\tconsola.error(\"Migration failed:\", error);\n\t\t\tawait db.destroy();\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\ttry {\n\t\t\tconst seed = await exportSeed(db, args[\"with-content\"]);\n\n\t\t\t// Output to stdout\n\t\t\tconst output = args.pretty ? JSON.stringify(seed, null, \"\\t\") : JSON.stringify(seed);\n\n\t\t\tconsole.log(output);\n\t\t} catch (error) {\n\t\t\tconsola.error(\"Export failed:\", error);\n\t\t\tawait db.destroy();\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tawait db.destroy();\n\t},\n});\n\n/**\n * Export database to seed file format\n */\nasync function exportSeed(db: Kysely<Database>, withContent?: string): Promise<SeedFile> {\n\tconst seed: SeedFile = {\n\t\t$schema: \"https://emdashcms.com/seed.schema.json\",\n\t\tversion: \"1\",\n\t\tmeta: {\n\t\t\tname: \"Exported Seed\",\n\t\t\tdescription: \"Exported from existing EmDash database\",\n\t\t},\n\t};\n\n\t// 1. Export settings\n\tseed.settings = await exportSettings(db);\n\n\t// 2. Export collections and fields\n\tseed.collections = await exportCollections(db);\n\n\t// 3. Export taxonomy definitions and terms\n\tseed.taxonomies = await exportTaxonomies(db);\n\n\t// 4. Export menus\n\tseed.menus = await exportMenus(db);\n\n\t// 5. Export widget areas\n\tseed.widgetAreas = await exportWidgetAreas(db);\n\n\t// 6. Export content (if requested)\n\tif (withContent !== undefined) {\n\t\tconst collections =\n\t\t\twithContent === \"\" || withContent === \"true\"\n\t\t\t\t? null // all collections\n\t\t\t\t: withContent\n\t\t\t\t\t\t.split(\",\")\n\t\t\t\t\t\t.map((s) => s.trim())\n\t\t\t\t\t\t.filter(Boolean);\n\n\t\tseed.content = await exportContent(db, seed.collections || [], collections);\n\t}\n\n\treturn seed;\n}\n\n/**\n * Export site settings\n */\nasync function exportSettings(db: Kysely<Database>): Promise<SeedFile[\"settings\"]> {\n\tconst options = new OptionsRepository(db);\n\tconst allOptions = await options.getByPrefix(SETTINGS_PREFIX);\n\n\tconst settings: Record<string, unknown> = {};\n\tfor (const [key, value] of allOptions) {\n\t\tconst settingKey = key.replace(SETTINGS_PREFIX, \"\");\n\t\tsettings[settingKey] = value;\n\t}\n\n\treturn Object.keys(settings).length > 0 ? settings : undefined;\n}\n\n/**\n * Export collections and their fields\n */\nasync function exportCollections(db: Kysely<Database>): Promise<SeedCollection[]> {\n\tconst registry = new SchemaRegistry(db);\n\tconst collections = await registry.listCollections();\n\tconst result: SeedCollection[] = [];\n\n\tfor (const collection of collections) {\n\t\tconst fields = await registry.listFields(collection.id);\n\n\t\tconst seedCollection: SeedCollection = {\n\t\t\tslug: collection.slug,\n\t\t\tlabel: collection.label,\n\t\t\tlabelSingular: collection.labelSingular || undefined,\n\t\t\tdescription: collection.description || undefined,\n\t\t\ticon: collection.icon || undefined,\n\t\t\tsupports:\n\t\t\t\tcollection.supports.length > 0\n\t\t\t\t\t? (collection.supports as (\n\t\t\t\t\t\t\t| \"drafts\"\n\t\t\t\t\t\t\t| \"revisions\"\n\t\t\t\t\t\t\t| \"preview\"\n\t\t\t\t\t\t\t| \"scheduling\"\n\t\t\t\t\t\t\t| \"search\"\n\t\t\t\t\t\t)[])\n\t\t\t\t\t: undefined,\n\t\t\turlPattern: collection.urlPattern || undefined,\n\t\t\tfields: fields.map(\n\t\t\t\t(field): SeedField => ({\n\t\t\t\t\tslug: field.slug,\n\t\t\t\t\tlabel: field.label,\n\t\t\t\t\ttype: field.type,\n\t\t\t\t\trequired: field.required || undefined,\n\t\t\t\t\tunique: field.unique || undefined,\n\t\t\t\t\tsearchable: field.searchable || undefined,\n\t\t\t\t\tdefaultValue: field.defaultValue,\n\t\t\t\t\tvalidation: field.validation ? { ...field.validation } : undefined,\n\t\t\t\t\twidget: field.widget || undefined,\n\t\t\t\t\toptions: field.options || undefined,\n\t\t\t\t}),\n\t\t\t),\n\t\t};\n\n\t\tresult.push(seedCollection);\n\t}\n\n\treturn result;\n}\n\n/**\n * Export taxonomy definitions and terms\n */\nasync function exportTaxonomies(db: Kysely<Database>): Promise<SeedTaxonomy[]> {\n\t// Get taxonomy definitions\n\tconst defs = await db.selectFrom(\"_emdash_taxonomy_defs\").selectAll().execute();\n\n\tconst result: SeedTaxonomy[] = [];\n\tconst termRepo = new TaxonomyRepository(db);\n\n\tfor (const def of defs) {\n\t\t// Get terms for this taxonomy\n\t\tconst terms = await termRepo.findByName(def.name);\n\n\t\t// Build term tree for hierarchical taxonomies\n\t\tconst seedTerms: SeedTaxonomyTerm[] = [];\n\n\t\t// First, create a map of id -> slug for parent resolution\n\t\tconst idToSlug = new Map<string, string>();\n\t\tfor (const term of terms) {\n\t\t\tidToSlug.set(term.id, term.slug);\n\t\t}\n\n\t\tfor (const term of terms) {\n\t\t\tconst seedTerm: SeedTaxonomyTerm = {\n\t\t\t\tslug: term.slug,\n\t\t\t\tlabel: term.label,\n\t\t\t\tdescription: typeof term.data?.description === \"string\" ? term.data.description : undefined,\n\t\t\t};\n\n\t\t\t// Resolve parent slug\n\t\t\tif (term.parentId) {\n\t\t\t\tseedTerm.parent = idToSlug.get(term.parentId);\n\t\t\t}\n\n\t\t\tseedTerms.push(seedTerm);\n\t\t}\n\n\t\tconst taxonomy: SeedTaxonomy = {\n\t\t\tname: def.name,\n\t\t\tlabel: def.label,\n\t\t\tlabelSingular: def.label_singular || undefined,\n\t\t\thierarchical: def.hierarchical === 1,\n\t\t\tcollections: def.collections ? JSON.parse(def.collections) : [],\n\t\t};\n\n\t\tif (seedTerms.length > 0) {\n\t\t\ttaxonomy.terms = seedTerms;\n\t\t}\n\n\t\tresult.push(taxonomy);\n\t}\n\n\treturn result;\n}\n\n/**\n * Export menus with their items\n */\nasync function exportMenus(db: Kysely<Database>): Promise<SeedMenu[]> {\n\t// Get all menus\n\tconst menus = await db.selectFrom(\"_emdash_menus\").selectAll().execute();\n\n\tconst result: SeedMenu[] = [];\n\n\tfor (const menu of menus) {\n\t\t// Get menu items\n\t\tconst items = await db\n\t\t\t.selectFrom(\"_emdash_menu_items\")\n\t\t\t.selectAll()\n\t\t\t.where(\"menu_id\", \"=\", menu.id)\n\t\t\t.orderBy(\"sort_order\", \"asc\")\n\t\t\t.execute();\n\n\t\t// Build item tree\n\t\tconst seedItems = buildMenuItemTree(items);\n\n\t\tresult.push({\n\t\t\tname: menu.name,\n\t\t\tlabel: menu.label,\n\t\t\titems: seedItems,\n\t\t});\n\t}\n\n\treturn result;\n}\n\n/** Type guard for valid widget types */\nfunction isWidgetType(t: string): t is SeedWidget[\"type\"] {\n\treturn t === \"content\" || t === \"menu\" || t === \"component\";\n}\n\n/**\n * Build hierarchical menu item tree from flat array\n */\nfunction buildMenuItemTree(\n\titems: Array<{\n\t\tid: string;\n\t\tparent_id: string | null;\n\t\ttype: string;\n\t\tlabel: string;\n\t\tcustom_url: string | null;\n\t\treference_collection: string | null;\n\t\treference_id: string | null;\n\t\ttarget: string | null;\n\t\ttitle_attr: string | null;\n\t\tcss_classes: string | null;\n\t}>,\n): SeedMenuItem[] {\n\t// Build parent -> children map\n\tconst childMap = new Map<string | null, typeof items>();\n\n\tfor (const item of items) {\n\t\tconst parentId = item.parent_id;\n\t\tif (!childMap.has(parentId)) {\n\t\t\tchildMap.set(parentId, []);\n\t\t}\n\t\tchildMap.get(parentId)!.push(item);\n\t}\n\n\t// Recursively build tree\n\tfunction buildLevel(parentId: string | null): SeedMenuItem[] {\n\t\tconst children = childMap.get(parentId) || [];\n\t\treturn children.map((item) => {\n\t\t\tconst seedItem: SeedMenuItem = {\n\t\t\t\ttype: item.type,\n\t\t\t\tlabel: item.label || undefined,\n\t\t\t};\n\n\t\t\tif (item.type === \"custom\") {\n\t\t\t\tseedItem.url = item.custom_url || undefined;\n\t\t\t} else {\n\t\t\t\tseedItem.ref = item.reference_id || undefined;\n\t\t\t\tseedItem.collection = item.reference_collection || undefined;\n\t\t\t}\n\n\t\t\tif (item.target === \"_blank\") {\n\t\t\t\tseedItem.target = \"_blank\";\n\t\t\t}\n\t\t\tif (item.title_attr) {\n\t\t\t\tseedItem.titleAttr = item.title_attr;\n\t\t\t}\n\t\t\tif (item.css_classes) {\n\t\t\t\tseedItem.cssClasses = item.css_classes;\n\t\t\t}\n\n\t\t\t// Add children\n\t\t\tconst itemChildren = buildLevel(item.id);\n\t\t\tif (itemChildren.length > 0) {\n\t\t\t\tseedItem.children = itemChildren;\n\t\t\t}\n\n\t\t\treturn seedItem;\n\t\t});\n\t}\n\n\treturn buildLevel(null);\n}\n\n/**\n * Export widget areas with their widgets\n */\nasync function exportWidgetAreas(db: Kysely<Database>): Promise<SeedWidgetArea[]> {\n\t// Get all widget areas\n\tconst areas = await db.selectFrom(\"_emdash_widget_areas\").selectAll().execute();\n\n\tconst result: SeedWidgetArea[] = [];\n\n\tfor (const area of areas) {\n\t\t// Get widgets for this area\n\t\tconst widgets = await db\n\t\t\t.selectFrom(\"_emdash_widgets\")\n\t\t\t.selectAll()\n\t\t\t.where(\"area_id\", \"=\", area.id)\n\t\t\t.orderBy(\"sort_order\", \"asc\")\n\t\t\t.execute();\n\n\t\tconst seedWidgets: SeedWidget[] = widgets\n\t\t\t.filter((w) => isWidgetType(w.type))\n\t\t\t.map((widget) => {\n\t\t\t\tconst wType: SeedWidget[\"type\"] = isWidgetType(widget.type) ? widget.type : \"content\";\n\t\t\t\tconst seedWidget: SeedWidget = {\n\t\t\t\t\ttype: wType,\n\t\t\t\t};\n\n\t\t\t\tif (widget.title) {\n\t\t\t\t\tseedWidget.title = widget.title;\n\t\t\t\t}\n\n\t\t\t\tif (widget.type === \"content\" && widget.content) {\n\t\t\t\t\tseedWidget.content = JSON.parse(widget.content);\n\t\t\t\t} else if (widget.type === \"menu\" && widget.menu_name) {\n\t\t\t\t\tseedWidget.menuName = widget.menu_name;\n\t\t\t\t} else if (widget.type === \"component\") {\n\t\t\t\t\tif (widget.component_id) {\n\t\t\t\t\t\tseedWidget.componentId = widget.component_id;\n\t\t\t\t\t}\n\t\t\t\t\tif (widget.component_props) {\n\t\t\t\t\t\tseedWidget.props = JSON.parse(widget.component_props);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn seedWidget;\n\t\t\t});\n\n\t\tresult.push({\n\t\t\tname: area.name,\n\t\t\tlabel: area.label,\n\t\t\tdescription: area.description || undefined,\n\t\t\twidgets: seedWidgets,\n\t\t});\n\t}\n\n\treturn result;\n}\n\n/**\n * Export content from collections\n */\nasync function exportContent(\n\tdb: Kysely<Database>,\n\tcollections: SeedCollection[],\n\tincludeCollections: string[] | null,\n): Promise<Record<string, SeedContentEntry[]>> {\n\tconst content: Record<string, SeedContentEntry[]> = {};\n\tconst contentRepo = new ContentRepository(db);\n\tconst taxonomyRepo = new TaxonomyRepository(db);\n\tconst mediaRepo = new MediaRepository(db);\n\n\t// Build media id -> info map for $media conversion\n\tconst mediaMap = new Map<\n\t\tstring,\n\t\t{ url: string; filename: string; alt?: string; caption?: string }\n\t>();\n\ttry {\n\t\tlet cursor: string | undefined;\n\t\tdo {\n\t\t\tconst result = await mediaRepo.findMany({\n\t\t\t\tlimit: 100,\n\t\t\t\tcursor,\n\t\t\t\tstatus: \"all\",\n\t\t\t});\n\t\t\tfor (const media of result.items) {\n\t\t\t\tmediaMap.set(media.id, {\n\t\t\t\t\turl: `/_emdash/api/media/file/${media.storageKey}`,\n\t\t\t\t\tfilename: media.filename,\n\t\t\t\t\talt: media.alt || undefined,\n\t\t\t\t\tcaption: media.caption || undefined,\n\t\t\t\t});\n\t\t\t}\n\t\t\tcursor = result.nextCursor;\n\t\t} while (cursor);\n\t} catch {\n\t\t// Media table might not exist or be empty\n\t}\n\n\tconst i18nEnabled = isI18nEnabled();\n\n\tfor (const collection of collections) {\n\t\t// Skip if not in include list\n\t\tif (includeCollections && !includeCollections.includes(collection.slug)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst entries: SeedContentEntry[] = [];\n\t\tlet cursor: string | undefined;\n\n\t\t// When i18n is enabled, track translation_group -> seed ID so that\n\t\t// translations can reference the source entry's seed-local ID.\n\t\t// Key: EmDash translation_group ULID, Value: seed-local ID of the first entry in that group\n\t\tconst translationGroupToSeedId = new Map<string, string>();\n\n\t\t// Paginate through all entries\n\t\tdo {\n\t\t\tconst result = await contentRepo.findMany(collection.slug, {\n\t\t\t\tlimit: 100,\n\t\t\t\tcursor,\n\t\t\t});\n\n\t\t\tfor (const item of result.items) {\n\t\t\t\t// Generate seed ID from collection:slug:locale for stable references\n\t\t\t\tconst seedId = item.slug\n\t\t\t\t\t? i18nEnabled && item.locale\n\t\t\t\t\t\t? `${collection.slug}:${item.slug}:${item.locale}`\n\t\t\t\t\t\t: `${collection.slug}:${item.slug}`\n\t\t\t\t\t: item.id;\n\n\t\t\t\t// Process data fields for $media conversion\n\t\t\t\tconst processedData = processDataForExport(item.data, collection.fields, mediaMap);\n\n\t\t\t\tconst entry: SeedContentEntry = {\n\t\t\t\t\tid: seedId,\n\t\t\t\t\tslug: item.slug || item.id,\n\t\t\t\t\tstatus: item.status === \"published\" || item.status === \"draft\" ? item.status : undefined,\n\t\t\t\t\tdata: processedData,\n\t\t\t\t};\n\n\t\t\t\t// Add i18n fields when enabled\n\t\t\t\tif (i18nEnabled && item.locale) {\n\t\t\t\t\tentry.locale = item.locale;\n\n\t\t\t\t\tif (item.translationGroup) {\n\t\t\t\t\t\tconst sourceSeedId = translationGroupToSeedId.get(item.translationGroup);\n\t\t\t\t\t\tif (sourceSeedId) {\n\t\t\t\t\t\t\t// This is a translation — reference the source entry\n\t\t\t\t\t\t\tentry.translationOf = sourceSeedId;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// First entry in this translation group — track it\n\t\t\t\t\t\t\ttranslationGroupToSeedId.set(item.translationGroup, seedId);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Get taxonomy assignments\n\t\t\t\tconst taxonomies = await getTaxonomyAssignments(taxonomyRepo, collection.slug, item.id);\n\t\t\t\tif (Object.keys(taxonomies).length > 0) {\n\t\t\t\t\tentry.taxonomies = taxonomies;\n\t\t\t\t}\n\n\t\t\t\tentries.push(entry);\n\t\t\t}\n\n\t\t\tcursor = result.nextCursor;\n\t\t} while (cursor);\n\n\t\tif (i18nEnabled && entries.length > 0) {\n\t\t\t// Sort entries so source locale entries appear before their translations.\n\t\t\t// Entries without translationOf come first; entries with translationOf come after.\n\t\t\tentries.sort((a, b) => {\n\t\t\t\tif (a.translationOf && !b.translationOf) return 1;\n\t\t\t\tif (!a.translationOf && b.translationOf) return -1;\n\t\t\t\treturn 0;\n\t\t\t});\n\t\t}\n\n\t\tif (entries.length > 0) {\n\t\t\tcontent[collection.slug] = entries;\n\t\t}\n\t}\n\n\treturn content;\n}\n\n/**\n * Process content data for export, converting image fields to $media syntax\n */\nfunction processDataForExport(\n\tdata: Record<string, unknown>,\n\tfields: SeedField[],\n\tmediaMap: Map<string, { url: string; filename: string; alt?: string; caption?: string }>,\n): Record<string, unknown> {\n\tconst result: Record<string, unknown> = {};\n\n\t// Create field type lookup\n\tconst fieldTypes = new Map<string, FieldType>();\n\tfor (const field of fields) {\n\t\tfieldTypes.set(field.slug, field.type);\n\t}\n\n\tfor (const [key, value] of Object.entries(data)) {\n\t\tconst fieldType = fieldTypes.get(key);\n\n\t\tif (fieldType === \"image\" && value && typeof value === \"object\") {\n\t\t\t// Convert image field to $media syntax\n\t\t\tconst imageValue = value as { id?: string; src?: string; alt?: string };\n\t\t\tif (imageValue.id) {\n\t\t\t\tconst mediaInfo = mediaMap.get(imageValue.id);\n\t\t\t\tif (mediaInfo) {\n\t\t\t\t\tresult[key] = {\n\t\t\t\t\t\t$media: {\n\t\t\t\t\t\t\turl: mediaInfo.url,\n\t\t\t\t\t\t\tfilename: mediaInfo.filename,\n\t\t\t\t\t\t\talt: imageValue.alt || mediaInfo.alt,\n\t\t\t\t\t\t\tcaption: mediaInfo.caption,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Fallback: keep as-is if no media info found\n\t\t\tresult[key] = value;\n\t\t} else if (fieldType === \"reference\" && typeof value === \"string\") {\n\t\t\t// Convert reference to $ref syntax (assumes same collection for now)\n\t\t\tresult[key] = `$ref:${value}`;\n\t\t} else if (Array.isArray(value)) {\n\t\t\t// Process arrays (could contain references or images)\n\t\t\tresult[key] = value.map((item) => {\n\t\t\t\tif (typeof item === \"string\" && fieldType === \"reference\") {\n\t\t\t\t\treturn `$ref:${item}`;\n\t\t\t\t}\n\t\t\t\treturn item;\n\t\t\t});\n\t\t} else {\n\t\t\tresult[key] = value;\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Get taxonomy term assignments for a content entry\n */\nasync function getTaxonomyAssignments(\n\ttaxonomyRepo: TaxonomyRepository,\n\tcollection: string,\n\tentryId: string,\n): Promise<Record<string, string[]>> {\n\tconst terms = await taxonomyRepo.getTermsForEntry(collection, entryId);\n\tconst result: Record<string, string[]> = {};\n\n\tfor (const term of terms) {\n\t\tif (!result[term.name]) {\n\t\t\tresult[term.name] = [];\n\t\t}\n\t\tresult[term.name].push(term.slug);\n\t}\n\n\treturn result;\n}\n","/**\n * emdash init\n *\n * Initialize database from template config in package.json\n */\n\nimport { readFile, access } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\n\nimport { defineCommand } from \"citty\";\nimport consola from \"consola\";\n\nimport { createDatabase } from \"../../database/connection.js\";\nimport { runMigrations } from \"../../database/migrations/runner.js\";\n\nexport interface EmDashConfig {\n\tlabel?: string;\n\tschema?: string;\n\tseed?: string;\n}\n\ninterface PackageJson {\n\tname?: string;\n\temdash?: EmDashConfig;\n}\n\nasync function fileExists(path: string): Promise<boolean> {\n\ttry {\n\t\tawait access(path);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nasync function readPackageJson(cwd: string): Promise<PackageJson | null> {\n\tconst pkgPath = resolve(cwd, \"package.json\");\n\ttry {\n\t\tconst content = await readFile(pkgPath, \"utf-8\");\n\t\treturn JSON.parse(content);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nasync function runSqlFile(db: ReturnType<typeof createDatabase>, filePath: string): Promise<void> {\n\tconst sql = await readFile(filePath, \"utf-8\");\n\n\t// Remove single-line comments\n\tconst withoutComments = sql\n\t\t.split(\"\\n\")\n\t\t.filter((line) => !line.trim().startsWith(\"--\"))\n\t\t.join(\"\\n\");\n\n\t// Split on semicolons, filter empty statements\n\tconst statements = withoutComments\n\t\t.split(\";\")\n\t\t.map((s) => s.trim())\n\t\t.filter((s) => s.length > 0);\n\n\tfor (const statement of statements) {\n\t\tawait db.executeQuery({\n\t\t\tsql: statement,\n\t\t\tparameters: [],\n\t\t\tquery: { kind: \"RawNode\", sqlFragments: [statement], parameters: [] },\n\t\t});\n\t}\n}\n\n/**\n * Check if database has already been initialized with template schema\n */\nasync function isAlreadyInitialized(db: ReturnType<typeof createDatabase>): Promise<boolean> {\n\ttry {\n\t\t// Use raw SQL since this runs on an untyped database connection\n\t\tconst { sql } = await import(\"kysely\");\n\t\tconst result = await sql<{\n\t\t\tcount: number;\n\t\t}>`SELECT COUNT(id) as count FROM _emdash_collections`.execute(db);\n\t\tconst row = result.rows[0];\n\t\treturn row ? row.count > 0 : false;\n\t} catch {\n\t\t// Table doesn't exist yet\n\t\treturn false;\n\t}\n}\n\nexport const initCommand = defineCommand({\n\tmeta: {\n\t\tname: \"init\",\n\t\tdescription: \"Initialize database from template config\",\n\t},\n\targs: {\n\t\tdatabase: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"d\",\n\t\t\tdescription: \"Database path (default: ./data.db)\",\n\t\t\tdefault: \"./data.db\",\n\t\t},\n\t\tcwd: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Working directory\",\n\t\t\tdefault: process.cwd(),\n\t\t},\n\t\tforce: {\n\t\t\ttype: \"boolean\",\n\t\t\talias: \"f\",\n\t\t\tdescription: \"Force re-initialization\",\n\t\t\tdefault: false,\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst cwd = resolve(args.cwd);\n\t\tconsola.start(\"Initializing EmDash...\");\n\n\t\t// 1. Read package.json\n\t\tconst pkg = await readPackageJson(cwd);\n\t\tif (!pkg) {\n\t\t\tconsola.error(\"No package.json found in\", cwd);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tconst config = pkg.emdash;\n\t\tconsola.info(`Project: ${pkg.name || \"unknown\"}`);\n\n\t\tif (config?.label) {\n\t\t\tconsola.info(`Template: ${config.label}`);\n\t\t}\n\n\t\t// 2. Create/connect to database\n\t\tconst dbPath = resolve(cwd, args.database);\n\t\tconsola.info(`Database: ${dbPath}`);\n\n\t\tconst db = createDatabase({ url: `file:${dbPath}` });\n\n\t\t// 3. Run core migrations (always run - they're idempotent)\n\t\tconsola.start(\"Running migrations...\");\n\t\ttry {\n\t\t\tconst { applied } = await runMigrations(db);\n\t\t\tif (applied.length > 0) {\n\t\t\t\tconsola.success(`Applied ${applied.length} migrations`);\n\t\t\t\tfor (const name of applied) {\n\t\t\t\t\tconsola.info(` - ${name}`);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconsola.info(\"Migrations already up to date\");\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsola.error(\"Migration failed:\", error);\n\t\t\tawait db.destroy();\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\t// 4. Check if already initialized (has collections)\n\t\tconst alreadyInitialized = await isAlreadyInitialized(db);\n\t\tif (alreadyInitialized && !args.force) {\n\t\t\tawait db.destroy();\n\t\t\tconsola.success(\"Already initialized. Use --force to re-run schema/seed.\");\n\t\t\treturn;\n\t\t}\n\n\t\tif (alreadyInitialized && args.force) {\n\t\t\tconsola.warn(\"Re-initializing (--force)...\");\n\t\t}\n\n\t\t// 5. Run template schema.sql if present\n\t\tif (config?.schema) {\n\t\t\tconst schemaPath = resolve(cwd, config.schema);\n\t\t\tif (await fileExists(schemaPath)) {\n\t\t\t\tconsola.start(`Running schema: ${config.schema}`);\n\t\t\t\ttry {\n\t\t\t\t\tawait runSqlFile(db, schemaPath);\n\t\t\t\t\tconsola.success(\"Schema applied\");\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsola.error(\"Schema failed:\", error);\n\t\t\t\t\tawait db.destroy();\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconsola.warn(`Schema file not found: ${config.schema}`);\n\t\t\t}\n\t\t}\n\n\t\t// 6. JSON seed files are now handled by `emdash seed` command\n\t\t// The bootstrap script runs `emdash init && emdash seed`\n\t\t// Legacy SQL seed files (seed.sql) could be handled here if needed\n\n\t\tawait db.destroy();\n\t\tconsola.success(\"EmDash initialized successfully!\");\n\t\tconsola.info(\"Run `pnpm dev` to start the development server\");\n\t},\n});\n","/**\n * Login/logout/whoami CLI commands\n *\n * Login uses the OAuth Device Flow (RFC 8628):\n * 1. POST /oauth/device/code → get device_code + user_code\n * 2. Display URL + code to user\n * 3. Poll POST /oauth/device/token until authorized\n * 4. Save tokens to ~/.config/emdash/auth.json\n *\n * Custom headers (--header / EMDASH_HEADERS) are sent with every request\n * and persisted to credentials so subsequent commands inherit them.\n * This supports sites behind reverse proxies like Cloudflare Access.\n */\n\nimport { defineCommand } from \"citty\";\nimport { consola } from \"consola\";\nimport pc from \"picocolors\";\n\nimport {\n\tcreateHeaderAwareFetch,\n\tgetCachedAccessToken,\n\tisAccessRedirect,\n\tresolveCustomHeaders,\n\trunCloudflaredLogin,\n} from \"../../client/cf-access.js\";\nimport {\n\tgetCredentials,\n\tremoveCredentials,\n\tresolveCredentialKey,\n\tsaveCredentials,\n} from \"../credentials.js\";\n\n// ---------------------------------------------------------------------------\n// Types for discovery + device flow responses\n// ---------------------------------------------------------------------------\n\ninterface DiscoveryResponse {\n\tinstance?: { name?: string };\n\tauth?: {\n\t\tmode?: string;\n\t\tmethods?: {\n\t\t\tdevice_flow?: {\n\t\t\t\tdevice_authorization_endpoint: string;\n\t\t\t\ttoken_endpoint: string;\n\t\t\t};\n\t\t\tapi_tokens?: boolean;\n\t\t};\n\t};\n}\n\ninterface DeviceCodeResponse {\n\tdevice_code: string;\n\tuser_code: string;\n\tverification_uri: string;\n\texpires_in: number;\n\tinterval: number;\n}\n\ninterface TokenResponse {\n\taccess_token: string;\n\trefresh_token: string;\n\ttoken_type: string;\n\texpires_in: number;\n\tscope: string;\n}\n\n// ---------------------------------------------------------------------------\n// Device Flow polling\n// ---------------------------------------------------------------------------\n\nasync function pollForToken(\n\ttokenEndpoint: string,\n\tdeviceCode: string,\n\tinterval: number,\n\texpiresIn: number,\n\tfetchFn: typeof fetch,\n): Promise<TokenResponse> {\n\tconst deadline = Date.now() + expiresIn * 1000;\n\tlet currentInterval = interval;\n\n\twhile (Date.now() < deadline) {\n\t\tawait new Promise((resolve) => setTimeout(resolve, currentInterval * 1000));\n\n\t\tconst res = await fetchFn(tokenEndpoint, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({\n\t\t\t\tdevice_code: deviceCode,\n\t\t\t\tgrant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n\t\t\t}),\n\t\t});\n\n\t\tif (res.ok) {\n\t\t\treturn (await res.json()) as TokenResponse;\n\t\t}\n\n\t\tconst body = (await res.json()) as { error?: string; interval?: number };\n\n\t\tif (body.error === \"authorization_pending\") {\n\t\t\t// Keep polling\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (body.error === \"slow_down\") {\n\t\t\t// Use server-provided interval, or fall back to incrementing by 5s\n\t\t\tcurrentInterval = body.interval ?? currentInterval + 5;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (body.error === \"expired_token\") {\n\t\t\tthrow new Error(\"Device code expired. Please try again.\");\n\t\t}\n\n\t\tif (body.error === \"access_denied\") {\n\t\t\tthrow new Error(\"Authorization was denied.\");\n\t\t}\n\n\t\t// Unknown error\n\t\tthrow new Error(`Token exchange failed: ${body.error || res.statusText}`);\n\t}\n\n\tthrow new Error(\"Device code expired (timeout). Please try again.\");\n}\n\n// ---------------------------------------------------------------------------\n// Cloudflare Access handling\n// ---------------------------------------------------------------------------\n\n/**\n * Handle a Cloudflare Access redirect during login.\n *\n * 1. Try `cloudflared access token` for a cached JWT\n * 2. Try `cloudflared access login` to do the browser flow\n * 3. If cloudflared isn't available, print instructions for service tokens\n *\n * Returns the Access JWT, or null if auth couldn't be resolved.\n */\nasync function handleAccessRedirect(baseUrl: string): Promise<string | null> {\n\tconsola.info(\"This site is behind Cloudflare Access.\");\n\n\t// Try cached token first\n\tconst cached = await getCachedAccessToken(baseUrl);\n\tif (cached) {\n\t\tconsola.success(\"Using cached Cloudflare Access token from cloudflared.\");\n\t\treturn cached;\n\t}\n\n\t// Try interactive login via cloudflared\n\tconsola.info(\"Launching browser for Cloudflare Access login...\");\n\tconst loginOk = await runCloudflaredLogin(baseUrl);\n\n\tif (loginOk) {\n\t\tconst token = await getCachedAccessToken(baseUrl);\n\t\tif (token) {\n\t\t\tconsola.success(\"Cloudflare Access authentication successful.\");\n\t\t\treturn token;\n\t\t}\n\t}\n\n\t// cloudflared not available or login failed — guide the user\n\tconsole.log();\n\tconsola.info(\"Could not authenticate with Cloudflare Access automatically.\");\n\tconsola.info(\"You have two options:\");\n\tconsole.log();\n\tconsola.info(` ${pc.bold(\"Option 1:\")} Install cloudflared and run:`);\n\tconsole.log(` ${pc.cyan(`cloudflared access login ${baseUrl}`)}`);\n\tconsole.log(` ${pc.cyan(`emdash login --url ${baseUrl}`)}`);\n\tconsole.log();\n\tconsola.info(` ${pc.bold(\"Option 2:\")} Use a service token:`);\n\tconsole.log(\n\t\t` ${pc.cyan(`emdash login --url ${baseUrl} -H \"CF-Access-Client-Id: <id>\" -H \"CF-Access-Client-Secret: <secret>\"`)}`,\n\t);\n\tconsole.log();\n\n\treturn null;\n}\n\n// ---------------------------------------------------------------------------\n// Commands\n// ---------------------------------------------------------------------------\n\nexport const loginCommand = defineCommand({\n\tmeta: { name: \"login\", description: \"Log in to an EmDash instance\" },\n\targs: {\n\t\turl: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"u\",\n\t\t\tdescription: \"EmDash instance URL\",\n\t\t\tdefault: \"http://localhost:4321\",\n\t\t},\n\t\theader: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"H\",\n\t\t\tdescription: 'Custom header \"Name: Value\" (repeatable, or use EMDASH_HEADERS env)',\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst baseUrl = args.url || \"http://localhost:4321\";\n\t\tconsola.start(`Connecting to ${baseUrl}...`);\n\n\t\t// Resolve custom headers from --header flags and EMDASH_HEADERS env\n\t\tconst customHeaders = resolveCustomHeaders();\n\t\tlet headerFetch = createHeaderAwareFetch(customHeaders);\n\n\t\ttry {\n\t\t\t// Step 1: Fetch auth discovery.\n\t\t\t// Use redirect: \"manual\" to detect Cloudflare Access.\n\t\t\tconst discoveryUrl = new URL(\"/_emdash/.well-known/auth\", baseUrl);\n\t\t\tlet res = await headerFetch(discoveryUrl, { redirect: \"manual\" });\n\n\t\t\t// Handle Cloudflare Access\n\t\t\tif (isAccessRedirect(res)) {\n\t\t\t\tconst accessToken = await handleAccessRedirect(baseUrl);\n\t\t\t\tif (!accessToken) {\n\t\t\t\t\treturn; // handleAccessRedirect printed instructions\n\t\t\t\t}\n\t\t\t\t// Add the Access token to our custom headers and rebuild the fetch wrapper\n\t\t\t\tcustomHeaders[\"cf-access-token\"] = accessToken;\n\t\t\t\theaderFetch = createHeaderAwareFetch(customHeaders);\n\t\t\t\tres = await headerFetch(discoveryUrl);\n\t\t\t} else if (res.status === 301 || res.status === 302) {\n\t\t\t\t// Non-Access redirect — follow it normally\n\t\t\t\tres = await headerFetch(discoveryUrl);\n\t\t\t}\n\n\t\t\tif (!res.ok) {\n\t\t\t\tif (res.status === 404) {\n\t\t\t\t\tconst isLocal = baseUrl.includes(\"localhost\") || baseUrl.includes(\"127.0.0.1\");\n\t\t\t\t\tif (isLocal) {\n\t\t\t\t\t\tconsola.info(\"Auth discovery not available. Trying dev bypass...\");\n\t\t\t\t\t\tconst bypassRes = await fetch(new URL(\"/_emdash/api/auth/dev-bypass\", baseUrl), {\n\t\t\t\t\t\t\tredirect: \"manual\",\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (bypassRes.status === 302 || bypassRes.ok) {\n\t\t\t\t\t\t\tconsola.success(\"Dev bypass available. Client will authenticate automatically.\");\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconsola.error(\"Could not authenticate. Is the dev server running?\");\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconsola.error(\"Auth discovery endpoint not found. Is this an EmDash instance?\");\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconsola.error(`Discovery failed: ${res.status} ${res.statusText}`);\n\t\t\t\tprocess.exit(2);\n\t\t\t}\n\n\t\t\tconst discovery = (await res.json()) as DiscoveryResponse;\n\t\t\tconsola.success(`Connected to ${discovery.instance?.name || \"EmDash\"}`);\n\n\t\t\tconst deviceFlow = discovery.auth?.methods?.device_flow;\n\n\t\t\tif (!deviceFlow) {\n\t\t\t\t// No device flow available (external auth mode)\n\t\t\t\tconsola.info(\"Device Flow is not available for this instance.\");\n\t\t\t\tconsola.info(\"Generate an API token in Settings > API Tokens\");\n\t\t\t\tconsola.info(`Then run: ${pc.cyan(`emdash --token <token> --url ${baseUrl}`)}`);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Step 2: Request device code\n\t\t\tconst codeUrl = new URL(deviceFlow.device_authorization_endpoint, baseUrl);\n\t\t\tconst codeRes = await headerFetch(codeUrl, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\"X-EmDash-Request\": \"1\",\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tclient_id: \"emdash-cli\",\n\t\t\t\t}),\n\t\t\t});\n\n\t\t\tif (!codeRes.ok) {\n\t\t\t\tconsola.error(`Failed to request device code: ${codeRes.status}`);\n\t\t\t\tprocess.exit(2);\n\t\t\t}\n\n\t\t\tconst deviceCode = (await codeRes.json()) as DeviceCodeResponse;\n\n\t\t\t// Step 3: Display instructions\n\t\t\tconsole.log();\n\t\t\tconsola.info(`Open your browser to:`);\n\t\t\tconsole.log(` ${pc.cyan(pc.bold(deviceCode.verification_uri))}`);\n\t\t\tconsole.log();\n\t\t\tconsola.info(`Enter code: ${pc.yellow(pc.bold(deviceCode.user_code))}`);\n\t\t\tconsole.log();\n\n\t\t\t// Try to open browser (best-effort)\n\t\t\ttry {\n\t\t\t\tconst { execFile } = await import(\"node:child_process\");\n\t\t\t\tif (process.platform === \"darwin\") {\n\t\t\t\t\texecFile(\"open\", [deviceCode.verification_uri]);\n\t\t\t\t} else if (process.platform === \"win32\") {\n\t\t\t\t\texecFile(\"cmd\", [\"/c\", \"start\", \"\", deviceCode.verification_uri]);\n\t\t\t\t} else {\n\t\t\t\t\texecFile(\"xdg-open\", [deviceCode.verification_uri]);\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Ignore — user can open manually\n\t\t\t}\n\n\t\t\t// Step 4: Poll for token\n\t\t\tconsola.start(\"Waiting for authorization...\");\n\n\t\t\tconst tokenUrl = new URL(deviceFlow.token_endpoint, baseUrl);\n\t\t\tconst tokenResult = await pollForToken(\n\t\t\t\ttokenUrl.toString(),\n\t\t\t\tdeviceCode.device_code,\n\t\t\t\tdeviceCode.interval,\n\t\t\t\tdeviceCode.expires_in,\n\t\t\t\theaderFetch,\n\t\t\t);\n\n\t\t\t// Step 5: Fetch user info\n\t\t\tlet userEmail = \"unknown\";\n\t\t\tlet userRole = \"unknown\";\n\t\t\ttry {\n\t\t\t\tconst meRes = await headerFetch(new URL(\"/_emdash/api/auth/me\", baseUrl), {\n\t\t\t\t\theaders: { Authorization: `Bearer ${tokenResult.access_token}` },\n\t\t\t\t});\n\t\t\t\tif (meRes.ok) {\n\t\t\t\t\tconst meJson = (await meRes.json()) as {\n\t\t\t\t\t\tdata: { email?: string; role?: number };\n\t\t\t\t\t};\n\t\t\t\t\tconst me = meJson.data;\n\t\t\t\t\tuserEmail = me.email || \"unknown\";\n\t\t\t\t\t// Map role number to name\n\t\t\t\t\tconst roleNames: Record<number, string> = {\n\t\t\t\t\t\t10: \"subscriber\",\n\t\t\t\t\t\t20: \"contributor\",\n\t\t\t\t\t\t30: \"author\",\n\t\t\t\t\t\t40: \"editor\",\n\t\t\t\t\t\t50: \"admin\",\n\t\t\t\t\t};\n\t\t\t\t\tuserRole = (me.role ? roleNames[me.role] : undefined) || \"unknown\";\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Non-critical\n\t\t\t}\n\n\t\t\t// Step 6: Save credentials (persist custom headers so subsequent commands inherit them)\n\t\t\tconst expiresAt = new Date(Date.now() + tokenResult.expires_in * 1000).toISOString();\n\t\t\tconst hasCustomHeaders = Object.keys(customHeaders).length > 0;\n\t\t\tsaveCredentials(baseUrl, {\n\t\t\t\taccessToken: tokenResult.access_token,\n\t\t\t\trefreshToken: tokenResult.refresh_token,\n\t\t\t\texpiresAt,\n\t\t\t\t...(hasCustomHeaders ? { customHeaders } : {}),\n\t\t\t\tuser: { email: userEmail, role: userRole },\n\t\t\t});\n\n\t\t\tconsola.success(`Logged in as ${pc.bold(userEmail)} (${userRole})`);\n\t\t\tconsola.info(`Token saved to ${pc.dim(resolveCredentialKey(baseUrl))}`);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Login failed\");\n\t\t\tprocess.exit(2);\n\t\t}\n\t},\n});\n\nexport const logoutCommand = defineCommand({\n\tmeta: { name: \"logout\", description: \"Log out of an EmDash instance\" },\n\targs: {\n\t\turl: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"u\",\n\t\t\tdescription: \"EmDash instance URL\",\n\t\t\tdefault: \"http://localhost:4321\",\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst baseUrl = args.url || \"http://localhost:4321\";\n\n\t\t// Get stored credentials\n\t\tconst cred = getCredentials(baseUrl);\n\n\t\tif (!cred) {\n\t\t\tconsola.info(\"No stored credentials found for this instance.\");\n\t\t\treturn;\n\t\t}\n\n\t\tconst headerFetch = createHeaderAwareFetch(cred.customHeaders ?? {});\n\n\t\t// Revoke tokens server-side (best-effort)\n\t\ttry {\n\t\t\t// Revoke the refresh token (which also revokes associated access tokens)\n\t\t\tawait headerFetch(new URL(\"/_emdash/api/oauth/token/revoke\", baseUrl), {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\t\tbody: JSON.stringify({ token: cred.refreshToken }),\n\t\t\t});\n\t\t} catch {\n\t\t\t// Non-critical — the local removal still works\n\t\t}\n\n\t\t// Remove local credentials\n\t\tremoveCredentials(baseUrl);\n\t\tconsola.success(\"Logged out successfully.\");\n\t},\n});\n\nexport const whoamiCommand = defineCommand({\n\tmeta: {\n\t\tname: \"whoami\",\n\t\tdescription: \"Show current user and auth method\",\n\t},\n\targs: {\n\t\turl: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"u\",\n\t\t\tdescription: \"EmDash instance URL\",\n\t\t\tdefault: \"http://localhost:4321\",\n\t\t},\n\t\ttoken: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"t\",\n\t\t\tdescription: \"Auth token\",\n\t\t},\n\t\tjson: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Output as JSON\",\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst baseUrl = args.url || \"http://localhost:4321\";\n\n\t\t// Resolve token: --token flag > EMDASH_TOKEN env > stored credentials\n\t\tlet token = args.token || process.env[\"EMDASH_TOKEN\"];\n\t\tlet authMethod = token ? \"token\" : \"none\";\n\t\tlet storedHeaders: Record<string, string> = {};\n\n\t\tif (!token) {\n\t\t\tconst cred = getCredentials(baseUrl);\n\t\t\tif (cred) {\n\t\t\t\ttoken = cred.accessToken;\n\t\t\t\tauthMethod = \"stored\";\n\t\t\t\tstoredHeaders = cred.customHeaders ?? {};\n\n\t\t\t\t// Check if expired\n\t\t\t\tif (new Date(cred.expiresAt) < new Date()) {\n\t\t\t\t\tconst headerFetch = createHeaderAwareFetch(storedHeaders);\n\t\t\t\t\t// Try to refresh\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst refreshRes = await headerFetch(\n\t\t\t\t\t\t\tnew URL(\"/_emdash/api/oauth/token/refresh\", baseUrl),\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\t\t\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\t\t\t\t\trefresh_token: cred.refreshToken,\n\t\t\t\t\t\t\t\t\tgrant_type: \"refresh_token\",\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (refreshRes.ok) {\n\t\t\t\t\t\t\tconst refreshed = (await refreshRes.json()) as TokenResponse;\n\t\t\t\t\t\t\ttoken = refreshed.access_token;\n\t\t\t\t\t\t\tsaveCredentials(baseUrl, {\n\t\t\t\t\t\t\t\t...cred,\n\t\t\t\t\t\t\t\taccessToken: refreshed.access_token,\n\t\t\t\t\t\t\t\texpiresAt: new Date(Date.now() + refreshed.expires_in * 1000).toISOString(),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconsola.warn(\"Stored token expired and refresh failed. Run: emdash login\");\n\t\t\t\t\t\t\tprocess.exit(2);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tconsola.warn(\"Stored token expired. Run: emdash login\");\n\t\t\t\t\t\tprocess.exit(2);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!token) {\n\t\t\t// Try dev bypass for local\n\t\t\tconst isLocal = baseUrl.includes(\"localhost\") || baseUrl.includes(\"127.0.0.1\");\n\t\t\tif (isLocal) {\n\t\t\t\tauthMethod = \"dev-bypass\";\n\t\t\t\tconsola.info(`Auth method: ${pc.cyan(\"dev-bypass\")}`);\n\t\t\t\tconsola.info(\"No stored credentials. Client will use dev bypass for localhost.\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconsola.error(\"Not logged in. Run: emdash login\");\n\t\t\tprocess.exit(2);\n\t\t}\n\n\t\tconst headerFetch = createHeaderAwareFetch(storedHeaders);\n\n\t\ttry {\n\t\t\tconst meRes = await headerFetch(new URL(\"/_emdash/api/auth/me\", baseUrl), {\n\t\t\t\theaders: { Authorization: `Bearer ${token}` },\n\t\t\t});\n\n\t\t\tif (!meRes.ok) {\n\t\t\t\tif (meRes.status === 401) {\n\t\t\t\t\tconsola.error(\"Token is invalid or expired. Run: emdash login\");\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t}\n\t\t\t\tconsola.error(`Failed to fetch user info: ${meRes.status}`);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\tconst raw = (await meRes.json()) as {\n\t\t\t\tdata: {\n\t\t\t\t\tid: string;\n\t\t\t\t\temail: string;\n\t\t\t\t\tname: string | null;\n\t\t\t\t\trole: number;\n\t\t\t\t};\n\t\t\t};\n\t\t\tconst me = raw.data;\n\n\t\t\tconst roleNames: Record<number, string> = {\n\t\t\t\t10: \"subscriber\",\n\t\t\t\t20: \"contributor\",\n\t\t\t\t30: \"author\",\n\t\t\t\t40: \"editor\",\n\t\t\t\t50: \"admin\",\n\t\t\t};\n\n\t\t\tif (args.json) {\n\t\t\t\tconsole.log(\n\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\tid: me.id,\n\t\t\t\t\t\temail: me.email,\n\t\t\t\t\t\tname: me.name,\n\t\t\t\t\t\trole: roleNames[me.role] || `unknown (${me.role})`,\n\t\t\t\t\t\tauthMethod,\n\t\t\t\t\t\turl: baseUrl,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tconsola.info(`Email: ${pc.bold(me.email)}`);\n\t\t\t\tif (me.name) consola.info(`Name: ${me.name}`);\n\t\t\t\tconsola.info(`Role: ${pc.cyan(roleNames[me.role] || `unknown (${me.role})`)}`);\n\t\t\t\tconsola.info(`Auth: ${pc.dim(authMethod)}`);\n\t\t\t\tconsola.info(`URL: ${pc.dim(baseUrl)}`);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n","/**\n * emdash media\n *\n * Manage media items via the EmDash API\n */\n\nimport { readFile } from \"node:fs/promises\";\nimport { basename } from \"node:path\";\n\nimport { defineCommand } from \"citty\";\nimport { consola } from \"consola\";\n\nimport { connectionArgs, createClientFromArgs } from \"../client-factory.js\";\nimport { output } from \"../output.js\";\n\nconst listCommand = defineCommand({\n\tmeta: {\n\t\tname: \"list\",\n\t\tdescription: \"List media items\",\n\t},\n\targs: {\n\t\t...connectionArgs,\n\t\tmime: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Filter by MIME type (e.g., image/png)\",\n\t\t},\n\t\tlimit: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Number of items to return\",\n\t\t},\n\t\tcursor: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Pagination cursor\",\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst client = createClientFromArgs(args);\n\n\t\ttry {\n\t\t\tconst result = await client.mediaList({\n\t\t\t\tmimeType: args.mime,\n\t\t\t\tlimit: args.limit ? Number(args.limit) : undefined,\n\t\t\t\tcursor: args.cursor,\n\t\t\t});\n\n\t\t\toutput(result, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(\"Failed to list media:\", error instanceof Error ? error.message : error);\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst uploadCommand = defineCommand({\n\tmeta: {\n\t\tname: \"upload\",\n\t\tdescription: \"Upload a media file\",\n\t},\n\targs: {\n\t\tfile: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Path to the file to upload\",\n\t\t\trequired: true,\n\t\t},\n\t\t...connectionArgs,\n\t\talt: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Alt text for the media item\",\n\t\t},\n\t\tcaption: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Caption for the media item\",\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst client = createClientFromArgs(args);\n\t\tconst filename = basename(args.file);\n\n\t\tconsola.start(`Uploading ${filename}...`);\n\n\t\ttry {\n\t\t\tconst buffer = await readFile(args.file);\n\t\t\tconst result = await client.mediaUpload(buffer, filename, {\n\t\t\t\talt: args.alt,\n\t\t\t\tcaption: args.caption,\n\t\t\t});\n\n\t\t\tconsola.success(`Uploaded ${filename}`);\n\t\t\toutput(result, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(\"Failed to upload:\", error instanceof Error ? error.message : error);\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst getCommand = defineCommand({\n\tmeta: {\n\t\tname: \"get\",\n\t\tdescription: \"Get a media item\",\n\t},\n\targs: {\n\t\tid: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Media item ID\",\n\t\t\trequired: true,\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\tconst client = createClientFromArgs(args);\n\n\t\ttry {\n\t\t\tconst result = await client.mediaGet(args.id);\n\t\t\toutput(result, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(\"Failed to get media:\", error instanceof Error ? error.message : error);\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst deleteCommand = defineCommand({\n\tmeta: {\n\t\tname: \"delete\",\n\t\tdescription: \"Delete a media item\",\n\t},\n\targs: {\n\t\tid: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Media item ID\",\n\t\t\trequired: true,\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\tconst client = createClientFromArgs(args);\n\n\t\ttry {\n\t\t\tawait client.mediaDelete(args.id);\n\n\t\t\tif (args.json) {\n\t\t\t\toutput({ deleted: true }, args);\n\t\t\t} else {\n\t\t\t\tconsola.success(`Deleted media item ${args.id}`);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsola.error(\"Failed to delete media:\", error instanceof Error ? error.message : error);\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nexport const mediaCommand = defineCommand({\n\tmeta: {\n\t\tname: \"media\",\n\t\tdescription: \"Manage media items\",\n\t},\n\tsubCommands: {\n\t\tlist: listCommand,\n\t\tupload: uploadCommand,\n\t\tget: getCommand,\n\t\tdelete: deleteCommand,\n\t},\n});\n","/**\n * emdash menu\n *\n * Manage menus via the EmDash REST API.\n */\n\nimport { defineCommand } from \"citty\";\nimport { consola } from \"consola\";\n\nimport { connectionArgs, createClientFromArgs } from \"../client-factory.js\";\nimport { output } from \"../output.js\";\n\nconst listCommand = defineCommand({\n\tmeta: {\n\t\tname: \"list\",\n\t\tdescription: \"List all menus\",\n\t},\n\targs: {\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst menus = await client.menus();\n\t\t\toutput(menus, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst getCommand = defineCommand({\n\tmeta: {\n\t\tname: \"get\",\n\t\tdescription: \"Get a menu with its items\",\n\t},\n\targs: {\n\t\tname: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Menu name\",\n\t\t\trequired: true,\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst menu = await client.menu(args.name);\n\t\t\toutput(menu, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nexport const menuCommand = defineCommand({\n\tmeta: {\n\t\tname: \"menu\",\n\t\tdescription: \"Manage menus\",\n\t},\n\tsubCommands: {\n\t\tlist: listCommand,\n\t\tget: getCommand,\n\t},\n});\n","/**\n * Bundle utility functions\n *\n * Shared logic extracted from the bundle command so it can be tested\n * without the CLI harness and tsdown dependency.\n */\n\nimport { createWriteStream } from \"node:fs\";\nimport { readdir, stat, access } from \"node:fs/promises\";\nimport { resolve, join } from \"node:path\";\nimport { pipeline } from \"node:stream/promises\";\n\nimport { imageSize } from \"image-size\";\nimport { packTar } from \"modern-tar/fs\";\n\nimport type {\n\tPluginManifest,\n\tResolvedPlugin,\n\tHookName,\n\tManifestHookEntry,\n} from \"../../plugins/types.js\";\n\n// ── Constants ────────────────────────────────────────────────────────────────\n\nexport const MAX_BUNDLE_SIZE = 5 * 1024 * 1024;\nexport const MAX_SCREENSHOTS = 5;\nexport const MAX_SCREENSHOT_WIDTH = 1920;\nexport const MAX_SCREENSHOT_HEIGHT = 1080;\nexport const ICON_SIZE = 256;\n\n// ── Regex patterns (module-scope to avoid re-compilation) ────────────────────\n\n/** Matches require(\"node:xxx\") / require(\"xxx\") / import(\"node:xxx\") in bundled output */\nconst NODE_BUILTIN_IMPORT_RE = /(?:import|require)\\s*\\(?[\"'](?:node:)?([a-z_]+)[\"']\\)?/g;\nconst LEADING_DOT_SLASH_RE = /^\\.\\//;\nconst DIST_PREFIX_RE = /^dist\\//;\nconst MJS_EXT_RE = /\\.m?js$/;\nconst TS_TO_TSX_RE = /\\.ts$/;\n\n/** Node.js built-in modules that shouldn't appear in sandbox code */\nconst NODE_BUILTINS = new Set([\n\t\"assert\",\n\t\"buffer\",\n\t\"child_process\",\n\t\"cluster\",\n\t\"crypto\",\n\t\"dgram\",\n\t\"dns\",\n\t\"domain\",\n\t\"events\",\n\t\"fs\",\n\t\"http\",\n\t\"http2\",\n\t\"https\",\n\t\"inspector\",\n\t\"module\",\n\t\"net\",\n\t\"os\",\n\t\"path\",\n\t\"perf_hooks\",\n\t\"process\",\n\t\"punycode\",\n\t\"querystring\",\n\t\"readline\",\n\t\"repl\",\n\t\"stream\",\n\t\"string_decoder\",\n\t\"sys\",\n\t\"timers\",\n\t\"tls\",\n\t\"trace_events\",\n\t\"tty\",\n\t\"url\",\n\t\"util\",\n\t\"v8\",\n\t\"vm\",\n\t\"wasi\",\n\t\"worker_threads\",\n\t\"zlib\",\n]);\n\n// ── File helpers ─────────────────────────────────────────────────────────────\n\nexport async function fileExists(path: string): Promise<boolean> {\n\ttry {\n\t\tawait access(path);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n// ── Image dimension readers ──────────────────────────────────────────────────\n\n/**\n * Read image dimensions from a buffer.\n * Returns [width, height] or null if the format is unrecognized.\n */\nexport function readImageDimensions(buf: Uint8Array): [number, number] | null {\n\ttry {\n\t\tconst result = imageSize(buf);\n\t\tif (result.width != null && result.height != null) {\n\t\t\treturn [result.width, result.height];\n\t\t}\n\t\treturn null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n// ── Manifest extraction ──────────────────────────────────────────────────────\n\n/**\n * Extract manifest metadata from a ResolvedPlugin.\n * Strips functions (hooks, route handlers) and keeps only serializable metadata.\n */\nexport function extractManifest(plugin: ResolvedPlugin): PluginManifest {\n\t// Build hook entries preserving exclusive/priority/timeout metadata.\n\t// Plain HookName strings are emitted for hooks with default settings;\n\t// structured ManifestHookEntry objects are emitted when metadata differs.\n\tconst hooks: Array<ManifestHookEntry | HookName> = [];\n\tfor (const [name, resolved] of Object.entries(plugin.hooks)) {\n\t\tif (!resolved) continue;\n\t\tconst hasMetadata =\n\t\t\tresolved.exclusive || resolved.priority !== 100 || resolved.timeout !== 5000;\n\t\tif (hasMetadata) {\n\t\t\tconst entry: ManifestHookEntry = { name };\n\t\t\tif (resolved.exclusive) entry.exclusive = true;\n\t\t\tif (resolved.priority !== 100) entry.priority = resolved.priority;\n\t\t\tif (resolved.timeout !== 5000) entry.timeout = resolved.timeout;\n\t\t\thooks.push(entry);\n\t\t} else {\n\t\t\thooks.push(name as HookName);\n\t\t}\n\t}\n\n\treturn {\n\t\tid: plugin.id,\n\t\tversion: plugin.version,\n\t\tcapabilities: plugin.capabilities,\n\t\tallowedHosts: plugin.allowedHosts,\n\t\tstorage: plugin.storage,\n\t\thooks,\n\t\troutes: Object.keys(plugin.routes),\n\t\tadmin: {\n\t\t\t// Omit entry (it's a module specifier for the host, not relevant in bundles)\n\t\t\tsettingsSchema: plugin.admin.settingsSchema,\n\t\t\tpages: plugin.admin.pages,\n\t\t\twidgets: plugin.admin.widgets,\n\t\t},\n\t};\n}\n\n// ── Node.js built-in detection ───────────────────────────────────────────────\n\n/**\n * Scan bundled code for Node.js built-in imports.\n * Matches require(\"node:xxx\"), require(\"xxx\"), import(\"node:xxx\") — the patterns\n * that appear in bundled ESM/CJS output (not source-level named imports).\n * Returns deduplicated array of built-in module names found.\n */\nexport function findNodeBuiltinImports(code: string): string[] {\n\tconst found: string[] = [];\n\tNODE_BUILTIN_IMPORT_RE.lastIndex = 0;\n\tlet match;\n\twhile ((match = NODE_BUILTIN_IMPORT_RE.exec(code)) !== null) {\n\t\tconst mod = match[1];\n\t\tif (NODE_BUILTINS.has(mod)) {\n\t\t\tfound.push(mod);\n\t\t}\n\t}\n\treturn [...new Set(found)];\n}\n\n// ── Path resolution ──────────────────────────────────────────────────────────\n\n/**\n * Find a build output file by base name, checking common extensions.\n * tsdown may output .mjs, .js, or .cjs depending on format and config.\n */\nexport async function findBuildOutput(dir: string, baseName: string): Promise<string | undefined> {\n\tfor (const ext of [\".mjs\", \".js\", \".cjs\"]) {\n\t\tconst candidate = join(dir, `${baseName}${ext}`);\n\t\tif (await fileExists(candidate)) return candidate;\n\t}\n\treturn undefined;\n}\n\n/**\n * Resolve a dist/built path back to its source .ts/.tsx equivalent.\n * E.g., \"./dist/index.mjs\" → \"src/index.ts\"\n */\nexport async function resolveSourceEntry(\n\tpluginDir: string,\n\tdistPath: string,\n): Promise<string | undefined> {\n\tconst cleaned = distPath.replace(LEADING_DOT_SLASH_RE, \"\");\n\n\t// Try the path directly (might be source already)\n\tconst direct = resolve(pluginDir, cleaned);\n\tif (await fileExists(direct)) return direct;\n\n\t// Convert dist path to src: dist/foo.mjs → src/foo.ts\n\tconst srcPath = cleaned.replace(DIST_PREFIX_RE, \"src/\").replace(MJS_EXT_RE, \".ts\");\n\tconst srcFull = resolve(pluginDir, srcPath);\n\tif (await fileExists(srcFull)) return srcFull;\n\n\t// Try .tsx\n\tconst tsxPath = srcPath.replace(TS_TO_TSX_RE, \".tsx\");\n\tconst tsxFull = resolve(pluginDir, tsxPath);\n\tif (await fileExists(tsxFull)) return tsxFull;\n\n\treturn undefined;\n}\n\n// ── Directory helpers ────────────────────────────────────────────────────────\n\n/**\n * Recursively calculate the total size of all files in a directory.\n */\nexport async function calculateDirectorySize(dir: string): Promise<number> {\n\tlet total = 0;\n\tconst items = await readdir(dir, { withFileTypes: true });\n\tfor (const item of items) {\n\t\tconst fullPath = join(dir, item.name);\n\t\tif (item.isFile()) {\n\t\t\tconst s = await stat(fullPath);\n\t\t\ttotal += s.size;\n\t\t} else if (item.isDirectory()) {\n\t\t\ttotal += await calculateDirectorySize(fullPath);\n\t\t}\n\t}\n\treturn total;\n}\n\n// ── Tarball creation ─────────────────────────────────────────────────────────\n\n/**\n * Create a gzipped tarball from a directory.\n */\nexport async function createTarball(sourceDir: string, outputPath: string): Promise<void> {\n\tconst { createGzip } = await import(\"node:zlib\");\n\tconst tarStream = packTar(sourceDir);\n\tconst gzip = createGzip({ level: 9 });\n\tconst out = createWriteStream(outputPath);\n\tawait pipeline(tarStream, gzip, out);\n}\n","/**\n * emdash plugin bundle\n *\n * Produces a publishable plugin tarball from a plugin source directory.\n *\n * Steps:\n * 1. Resolve plugin entrypoint (finds definePlugin() export)\n * 2. Bundle backend code with tsdown → backend.js (single ES module, tree-shaken)\n * 3. Bundle admin code if present → admin.js\n * 4. Extract manifest from definePlugin() → manifest.json\n * 5. Collect assets (README.md, icon.png, screenshots/)\n * 6. Validate bundle (manifest schema, size limits, no Node.js builtins)\n * 7. Create tarball ({id}-{version}.tar.gz)\n */\n\nimport { createHash } from \"node:crypto\";\nimport { readFile, stat, mkdir, writeFile, rm, copyFile, symlink, readdir } from \"node:fs/promises\";\nimport { resolve, join, extname, basename } from \"node:path\";\n\nimport { defineCommand } from \"citty\";\nimport consola from \"consola\";\n\nimport type { ResolvedPlugin } from \"../../plugins/types.js\";\nimport {\n\tfileExists,\n\treadImageDimensions,\n\textractManifest,\n\tfindNodeBuiltinImports,\n\tfindBuildOutput,\n\tresolveSourceEntry,\n\tcalculateDirectorySize,\n\tcreateTarball,\n\tMAX_BUNDLE_SIZE,\n\tMAX_SCREENSHOTS,\n\tMAX_SCREENSHOT_WIDTH,\n\tMAX_SCREENSHOT_HEIGHT,\n\tICON_SIZE,\n} from \"./bundle-utils.js\";\n\nconst TS_EXT_RE = /\\.tsx?$/;\nconst SLASH_RE = /\\//g;\nconst LEADING_AT_RE = /^@/;\nconst emdash_SCOPE_RE = /^@emdash-cms\\//;\n\nexport const bundleCommand = defineCommand({\n\tmeta: {\n\t\tname: \"bundle\",\n\t\tdescription: \"Bundle a plugin for marketplace distribution\",\n\t},\n\targs: {\n\t\tdir: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Plugin directory (default: current directory)\",\n\t\t\tdefault: process.cwd(),\n\t\t},\n\t\toutDir: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"o\",\n\t\t\tdescription: \"Output directory for the tarball (default: ./dist)\",\n\t\t\tdefault: \"dist\",\n\t\t},\n\t\tvalidateOnly: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Run validation only, skip tarball creation\",\n\t\t\tdefault: false,\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst pluginDir = resolve(args.dir);\n\t\tconst outDir = resolve(pluginDir, args.outDir);\n\t\tconst validateOnly = args.validateOnly;\n\n\t\tconsola.start(validateOnly ? \"Validating plugin...\" : \"Bundling plugin...\");\n\n\t\t// ── Step 1: Read package.json and resolve entrypoints ──\n\n\t\tconst pkgPath = join(pluginDir, \"package.json\");\n\t\tif (!(await fileExists(pkgPath))) {\n\t\t\tconsola.error(\"No package.json found in\", pluginDir);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tconst pkg = JSON.parse(await readFile(pkgPath, \"utf-8\")) as {\n\t\t\tname?: string;\n\t\t\tmain?: string;\n\t\t\texports?: Record<string, unknown>;\n\t\t};\n\n\t\t// Find the sandbox entrypoint — look for ./sandbox export first, then main\n\t\tlet backendEntry: string | undefined;\n\t\tlet adminEntry: string | undefined;\n\n\t\tif (pkg.exports) {\n\t\t\t// Check for explicit sandbox export\n\t\t\tconst sandboxExport = pkg.exports[\"./sandbox\"];\n\t\t\tif (typeof sandboxExport === \"string\") {\n\t\t\t\tbackendEntry = await resolveSourceEntry(pluginDir, sandboxExport);\n\t\t\t} else if (sandboxExport && typeof sandboxExport === \"object\" && \"import\" in sandboxExport) {\n\t\t\t\tbackendEntry = await resolveSourceEntry(\n\t\t\t\t\tpluginDir,\n\t\t\t\t\t(sandboxExport as { import: string }).import,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Check for admin export\n\t\t\tconst adminExport = pkg.exports[\"./admin\"];\n\t\t\tif (typeof adminExport === \"string\") {\n\t\t\t\tadminEntry = await resolveSourceEntry(pluginDir, adminExport);\n\t\t\t} else if (adminExport && typeof adminExport === \"object\" && \"import\" in adminExport) {\n\t\t\t\tadminEntry = await resolveSourceEntry(\n\t\t\t\t\tpluginDir,\n\t\t\t\t\t(adminExport as { import: string }).import,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// If no sandbox export, look for src/sandbox-entry.ts\n\t\tif (!backendEntry) {\n\t\t\tconst defaultSandbox = join(pluginDir, \"src/sandbox-entry.ts\");\n\t\t\tif (await fileExists(defaultSandbox)) {\n\t\t\t\tbackendEntry = defaultSandbox;\n\t\t\t}\n\t\t}\n\n\t\t// Find the main entry for manifest extraction\n\t\tlet mainEntry: string | undefined;\n\t\tif (pkg.exports?.[\".\"] !== undefined) {\n\t\t\tconst mainExport = pkg.exports[\".\"];\n\t\t\tif (typeof mainExport === \"string\") {\n\t\t\t\tmainEntry = await resolveSourceEntry(pluginDir, mainExport);\n\t\t\t} else if (mainExport && typeof mainExport === \"object\" && \"import\" in mainExport) {\n\t\t\t\tmainEntry = await resolveSourceEntry(pluginDir, (mainExport as { import: string }).import);\n\t\t\t}\n\t\t}\n\t\tif (!mainEntry && pkg.main) {\n\t\t\tmainEntry = await resolveSourceEntry(pluginDir, pkg.main);\n\t\t}\n\t\tif (!mainEntry) {\n\t\t\tconst defaultMain = join(pluginDir, \"src/index.ts\");\n\t\t\tif (await fileExists(defaultMain)) {\n\t\t\t\tmainEntry = defaultMain;\n\t\t\t}\n\t\t}\n\n\t\tif (!mainEntry) {\n\t\t\tconsola.error(\n\t\t\t\t\"Cannot find plugin entrypoint. Expected src/index.ts or main/exports in package.json\",\n\t\t\t);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tconsola.info(`Main entry: ${mainEntry}`);\n\t\tif (backendEntry) consola.info(`Backend entry: ${backendEntry}`);\n\t\tif (adminEntry) consola.info(`Admin entry: ${adminEntry}`);\n\n\t\t// ── Step 2: Extract manifest by importing the plugin ──\n\n\t\tconsola.start(\"Extracting plugin manifest...\");\n\n\t\t// Build the main entry first so we can import it\n\t\tconst { build } = await import(\"tsdown\");\n\t\tconst tmpDir = join(pluginDir, \".emdash-bundle-tmp\");\n\n\t\ttry {\n\t\t\tawait mkdir(tmpDir, { recursive: true });\n\n\t\t\t// Build main entry to extract manifest.\n\t\t\t// Externalize emdash and sibling packages — they'll resolve\n\t\t\t// via the symlinked node_modules below.\n\t\t\tconst mainOutDir = join(tmpDir, \"main\");\n\t\t\tawait build({\n\t\t\t\tconfig: false,\n\t\t\t\tentry: [mainEntry],\n\t\t\t\tformat: \"esm\",\n\t\t\t\toutDir: mainOutDir,\n\t\t\t\tdts: false,\n\t\t\t\tplatform: \"node\",\n\t\t\t\texternal: [\"emdash\", emdash_SCOPE_RE],\n\t\t\t});\n\n\t\t\t// Symlink plugin's node_modules so the built module can resolve\n\t\t\t// external dependencies (emdash, @emdash-cms/*, etc.)\n\t\t\tconst pluginNodeModules = join(pluginDir, \"node_modules\");\n\t\t\tconst tmpNodeModules = join(mainOutDir, \"node_modules\");\n\t\t\tif (await fileExists(pluginNodeModules)) {\n\t\t\t\tawait symlink(pluginNodeModules, tmpNodeModules, \"junction\");\n\t\t\t}\n\n\t\t\t// Import the built module to get the resolved plugin\n\t\t\tconst mainBaseName = basename(mainEntry).replace(TS_EXT_RE, \"\");\n\t\t\tconst mainOutputPath = await findBuildOutput(mainOutDir, mainBaseName);\n\n\t\t\tif (!mainOutputPath) {\n\t\t\t\tconsola.error(\"Failed to build main entry — no output found in\", mainOutDir);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\t// Dynamic import of the built plugin\n\t\t\tconst pluginModule = (await import(mainOutputPath)) as Record<string, unknown>;\n\n\t\t\t// Extract manifest from the imported module.\n\t\t\t// Supports three patterns:\n\t\t\t// 1. Native: createPlugin() export -> ResolvedPlugin\n\t\t\t// 2. Native: default export that is/returns a ResolvedPlugin (has id+version)\n\t\t\t// 3. Standard: descriptor factory function (returns { id, version, ... })\n\t\t\tlet resolvedPlugin: ResolvedPlugin | undefined;\n\n\t\t\tif (typeof pluginModule.createPlugin === \"function\") {\n\t\t\t\tresolvedPlugin = pluginModule.createPlugin() as ResolvedPlugin;\n\t\t\t} else if (typeof pluginModule.default === \"function\") {\n\t\t\t\tresolvedPlugin = pluginModule.default() as ResolvedPlugin;\n\t\t\t} else if (typeof pluginModule.default === \"object\" && pluginModule.default !== null) {\n\t\t\t\tconst defaultExport = pluginModule.default as Record<string, unknown>;\n\t\t\t\tif (\"id\" in defaultExport && \"version\" in defaultExport) {\n\t\t\t\t\tresolvedPlugin = defaultExport as unknown as ResolvedPlugin;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Standard format: no createPlugin, no default with id/version.\n\t\t\t// Look for a descriptor factory -- any named export function that\n\t\t\t// returns an object with { id, version }.\n\t\t\tif (!resolvedPlugin) {\n\t\t\t\tfor (const [key, value] of Object.entries(pluginModule)) {\n\t\t\t\t\tif (key === \"default\" || typeof value !== \"function\") continue;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst result = (value as () => unknown)() as Record<string, unknown> | null;\n\t\t\t\t\t\tif (result && typeof result === \"object\" && \"id\" in result && \"version\" in result) {\n\t\t\t\t\t\t\tresolvedPlugin = {\n\t\t\t\t\t\t\t\tid: result.id,\n\t\t\t\t\t\t\t\tversion: result.version,\n\t\t\t\t\t\t\t\tcapabilities: result.capabilities ?? [],\n\t\t\t\t\t\t\t\tallowedHosts: result.allowedHosts ?? [],\n\t\t\t\t\t\t\t\tstorage: result.storage ?? {},\n\t\t\t\t\t\t\t\thooks: {},\n\t\t\t\t\t\t\t\troutes: {},\n\t\t\t\t\t\t\t\tadmin: {\n\t\t\t\t\t\t\t\t\tpages: result.adminPages,\n\t\t\t\t\t\t\t\t\twidgets: result.adminWidgets,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t} as ResolvedPlugin;\n\n\t\t\t\t\t\t\t// If there's a sandbox entry, build and import it\n\t\t\t\t\t\t\t// to get hook/route names for the manifest.\n\t\t\t\t\t\t\tif (backendEntry) {\n\t\t\t\t\t\t\t\tconst backendProbeDir = join(tmpDir, \"backend-probe\");\n\t\t\t\t\t\t\t\tconst probeShimDir = join(tmpDir, \"probe-shims\");\n\t\t\t\t\t\t\t\tawait mkdir(probeShimDir, { recursive: true });\n\t\t\t\t\t\t\t\tawait writeFile(\n\t\t\t\t\t\t\t\t\tjoin(probeShimDir, \"emdash.mjs\"),\n\t\t\t\t\t\t\t\t\t\"export const definePlugin = (d) => d;\\n\",\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tawait build({\n\t\t\t\t\t\t\t\t\tconfig: false,\n\t\t\t\t\t\t\t\t\tentry: [backendEntry],\n\t\t\t\t\t\t\t\t\tformat: \"esm\",\n\t\t\t\t\t\t\t\t\toutDir: backendProbeDir,\n\t\t\t\t\t\t\t\t\tdts: false,\n\t\t\t\t\t\t\t\t\tplatform: \"neutral\",\n\t\t\t\t\t\t\t\t\texternal: [],\n\t\t\t\t\t\t\t\t\talias: { emdash: join(probeShimDir, \"emdash.mjs\") },\n\t\t\t\t\t\t\t\t\ttreeshake: true,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tconst backendBaseName = basename(backendEntry).replace(TS_EXT_RE, \"\");\n\t\t\t\t\t\t\t\tconst backendProbePath = await findBuildOutput(backendProbeDir, backendBaseName);\n\t\t\t\t\t\t\t\tif (backendProbePath) {\n\t\t\t\t\t\t\t\t\tconst backendModule = (await import(backendProbePath)) as Record<string, unknown>;\n\t\t\t\t\t\t\t\t\tconst standardDef = (backendModule.default ?? {}) as Record<string, unknown>;\n\t\t\t\t\t\t\t\t\tconst hooks = standardDef.hooks as Record<string, unknown> | undefined;\n\t\t\t\t\t\t\t\t\tconst routes = standardDef.routes as Record<string, unknown> | undefined;\n\t\t\t\t\t\t\t\t\tif (hooks) {\n\t\t\t\t\t\t\t\t\t\tfor (const hookName of Object.keys(hooks)) {\n\t\t\t\t\t\t\t\t\t\t\tconst hookEntry = hooks[hookName];\n\t\t\t\t\t\t\t\t\t\t\tconst isConfig =\n\t\t\t\t\t\t\t\t\t\t\t\ttypeof hookEntry === \"object\" &&\n\t\t\t\t\t\t\t\t\t\t\t\thookEntry !== null &&\n\t\t\t\t\t\t\t\t\t\t\t\t\"handler\" in hookEntry;\n\t\t\t\t\t\t\t\t\t\t\tconst config = isConfig ? (hookEntry as Record<string, unknown>) : {};\n\t\t\t\t\t\t\t\t\t\t\t(resolvedPlugin.hooks as Record<string, unknown>)[hookName] = {\n\t\t\t\t\t\t\t\t\t\t\t\thandler: isConfig\n\t\t\t\t\t\t\t\t\t\t\t\t\t? (hookEntry as Record<string, unknown>).handler\n\t\t\t\t\t\t\t\t\t\t\t\t\t: hookEntry,\n\t\t\t\t\t\t\t\t\t\t\t\tpriority: (config.priority as number) ?? 100,\n\t\t\t\t\t\t\t\t\t\t\t\ttimeout: (config.timeout as number) ?? 5000,\n\t\t\t\t\t\t\t\t\t\t\t\tdependencies: (config.dependencies as string[]) ?? [],\n\t\t\t\t\t\t\t\t\t\t\t\terrorPolicy: (config.errorPolicy as string) ?? \"abort\",\n\t\t\t\t\t\t\t\t\t\t\t\texclusive: (config.exclusive as boolean) ?? false,\n\t\t\t\t\t\t\t\t\t\t\t\tpluginId: result.id,\n\t\t\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (routes) {\n\t\t\t\t\t\t\t\t\t\tfor (const [name, route] of Object.entries(routes)) {\n\t\t\t\t\t\t\t\t\t\t\tconst routeObj = route as Record<string, unknown>;\n\t\t\t\t\t\t\t\t\t\t\t(resolvedPlugin.routes as Record<string, unknown>)[name] = {\n\t\t\t\t\t\t\t\t\t\t\t\thandler: routeObj.handler,\n\t\t\t\t\t\t\t\t\t\t\t\tpublic: routeObj.public,\n\t\t\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Not a descriptor factory, skip\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!resolvedPlugin?.id || !resolvedPlugin?.version) {\n\t\t\t\tconsola.error(\n\t\t\t\t\t\"Could not extract plugin definition. Expected one of:\\n\" +\n\t\t\t\t\t\t\" - createPlugin() export (native format)\\n\" +\n\t\t\t\t\t\t\" - Descriptor factory function returning { id, version, ... } (standard format)\",\n\t\t\t\t);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\tconst manifest = extractManifest(resolvedPlugin);\n\n\t\t\t// Validate format consistency: bundled plugins are for the marketplace\n\t\t\t// (sandboxed), so they must be standard format without trusted-only features.\n\t\t\tif (resolvedPlugin.admin?.entry) {\n\t\t\t\tconsola.error(\n\t\t\t\t\t`Plugin declares adminEntry — React admin components require native/trusted mode. ` +\n\t\t\t\t\t\t`Use Block Kit for sandboxed admin pages, or remove adminEntry.`,\n\t\t\t\t);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t\tif (\n\t\t\t\tresolvedPlugin.admin?.portableTextBlocks &&\n\t\t\t\tresolvedPlugin.admin.portableTextBlocks.length > 0\n\t\t\t) {\n\t\t\t\tconsola.error(\n\t\t\t\t\t`Plugin declares portableTextBlocks — these require native/trusted mode ` +\n\t\t\t\t\t\t`and cannot be bundled for the marketplace.`,\n\t\t\t\t);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\tconsola.success(`Plugin: ${manifest.id}@${manifest.version}`);\n\t\t\tconsola.info(\n\t\t\t\t` Capabilities: ${manifest.capabilities.length > 0 ? manifest.capabilities.join(\", \") : \"(none)\"}`,\n\t\t\t);\n\t\t\tconsola.info(\n\t\t\t\t` Hooks: ${manifest.hooks.length > 0 ? manifest.hooks.map((h) => (typeof h === \"string\" ? h : h.name)).join(\", \") : \"(none)\"}`,\n\t\t\t);\n\t\t\tconsola.info(\n\t\t\t\t` Routes: ${manifest.routes.length > 0 ? manifest.routes.map((r) => (typeof r === \"string\" ? r : r.name)).join(\", \") : \"(none)\"}`,\n\t\t\t);\n\n\t\t\t// ── Step 3: Bundle backend.js ──\n\n\t\t\tconst bundleDir = join(tmpDir, \"bundle\");\n\t\t\tawait mkdir(bundleDir, { recursive: true });\n\n\t\t\tif (backendEntry) {\n\t\t\t\tconsola.start(\"Bundling backend...\");\n\n\t\t\t\t// Create a shim for emdash so the sandbox entry doesn't pull in the\n\t\t\t\t// entire core package. definePlugin is an identity function for standard\n\t\t\t\t// format, and PluginContext is a type-only import that disappears.\n\t\t\t\tconst shimDir = join(tmpDir, \"shims\");\n\t\t\t\tawait mkdir(shimDir, { recursive: true });\n\t\t\t\tawait writeFile(join(shimDir, \"emdash.mjs\"), \"export const definePlugin = (d) => d;\\n\");\n\n\t\t\t\tawait build({\n\t\t\t\t\tconfig: false,\n\t\t\t\t\tentry: [backendEntry],\n\t\t\t\t\tformat: \"esm\",\n\t\t\t\t\toutDir: join(tmpDir, \"backend\"),\n\t\t\t\t\tdts: false,\n\t\t\t\t\tplatform: \"neutral\",\n\t\t\t\t\t// Bundle everything for a self-contained sandbox file,\n\t\t\t\t\t// but alias emdash to our shim so we don't pull in the core.\n\t\t\t\t\texternal: [],\n\t\t\t\t\talias: { emdash: join(shimDir, \"emdash.mjs\") },\n\t\t\t\t\tminify: true,\n\t\t\t\t\ttreeshake: true,\n\t\t\t\t});\n\n\t\t\t\tconst backendBaseName = basename(backendEntry).replace(TS_EXT_RE, \"\");\n\t\t\t\tconst backendOutputPath = await findBuildOutput(join(tmpDir, \"backend\"), backendBaseName);\n\n\t\t\t\tif (backendOutputPath) {\n\t\t\t\t\tawait copyFile(backendOutputPath, join(bundleDir, \"backend.js\"));\n\t\t\t\t\tconsola.success(\"Built backend.js\");\n\t\t\t\t} else {\n\t\t\t\t\tconsola.error(\"Backend build produced no output\");\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconsola.warn(\"No sandbox entry found — bundle will have no backend.js\");\n\t\t\t\tconsola.warn(' Add a \"sandbox-entry.ts\" in src/ or a \"./sandbox\" export in package.json');\n\t\t\t}\n\n\t\t\t// ── Step 4: Bundle admin.js ──\n\n\t\t\tif (adminEntry) {\n\t\t\t\tconsola.start(\"Bundling admin...\");\n\t\t\t\tawait build({\n\t\t\t\t\tconfig: false,\n\t\t\t\t\tentry: [adminEntry],\n\t\t\t\t\tformat: \"esm\",\n\t\t\t\t\toutDir: join(tmpDir, \"admin\"),\n\t\t\t\t\tdts: false,\n\t\t\t\t\tplatform: \"neutral\",\n\t\t\t\t\texternal: [],\n\t\t\t\t\tminify: true,\n\t\t\t\t\ttreeshake: true,\n\t\t\t\t});\n\n\t\t\t\tconst adminBaseName = basename(adminEntry).replace(TS_EXT_RE, \"\");\n\t\t\t\tconst adminOutputPath = await findBuildOutput(join(tmpDir, \"admin\"), adminBaseName);\n\n\t\t\t\tif (adminOutputPath) {\n\t\t\t\t\tawait copyFile(adminOutputPath, join(bundleDir, \"admin.js\"));\n\t\t\t\t\tconsola.success(\"Built admin.js\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// ── Step 5: Write manifest.json ──\n\n\t\t\tawait writeFile(join(bundleDir, \"manifest.json\"), JSON.stringify(manifest, null, 2));\n\n\t\t\t// ── Step 6: Collect assets ──\n\n\t\t\tconsola.start(\"Collecting assets...\");\n\n\t\t\t// README.md\n\t\t\tconst readmePath = join(pluginDir, \"README.md\");\n\t\t\tif (await fileExists(readmePath)) {\n\t\t\t\tawait copyFile(readmePath, join(bundleDir, \"README.md\"));\n\t\t\t\tconsola.success(\"Included README.md\");\n\t\t\t}\n\n\t\t\t// icon.png\n\t\t\tconst iconPath = join(pluginDir, \"icon.png\");\n\t\t\tif (await fileExists(iconPath)) {\n\t\t\t\tconst iconBuf = await readFile(iconPath);\n\t\t\t\tconst dims = readImageDimensions(iconBuf);\n\t\t\t\tif (!dims) {\n\t\t\t\t\tconsola.warn(\"icon.png is not a valid PNG — skipping\");\n\t\t\t\t} else if (dims[0] !== ICON_SIZE || dims[1] !== ICON_SIZE) {\n\t\t\t\t\tconsola.warn(\n\t\t\t\t\t\t`icon.png is ${dims[0]}x${dims[1]}, expected ${ICON_SIZE}x${ICON_SIZE} — including anyway`,\n\t\t\t\t\t);\n\t\t\t\t\tawait copyFile(iconPath, join(bundleDir, \"icon.png\"));\n\t\t\t\t} else {\n\t\t\t\t\tawait copyFile(iconPath, join(bundleDir, \"icon.png\"));\n\t\t\t\t\tconsola.success(\"Included icon.png\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// screenshots/\n\t\t\tconst screenshotsDir = join(pluginDir, \"screenshots\");\n\t\t\tif (await fileExists(screenshotsDir)) {\n\t\t\t\tconst screenshotFiles = (await readdir(screenshotsDir))\n\t\t\t\t\t.filter((f) => {\n\t\t\t\t\t\tconst ext = extname(f).toLowerCase();\n\t\t\t\t\t\treturn ext === \".png\" || ext === \".jpg\" || ext === \".jpeg\";\n\t\t\t\t\t})\n\t\t\t\t\t.toSorted()\n\t\t\t\t\t.slice(0, MAX_SCREENSHOTS);\n\n\t\t\t\tif (screenshotFiles.length > 0) {\n\t\t\t\t\tawait mkdir(join(bundleDir, \"screenshots\"), { recursive: true });\n\n\t\t\t\t\tfor (const file of screenshotFiles) {\n\t\t\t\t\t\tconst filePath = join(screenshotsDir, file);\n\t\t\t\t\t\tconst buf = await readFile(filePath);\n\n\t\t\t\t\t\tconst dims = readImageDimensions(buf);\n\n\t\t\t\t\t\tif (!dims) {\n\t\t\t\t\t\t\tconsola.warn(`screenshots/${file} — cannot read dimensions, skipping`);\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (dims[0] > MAX_SCREENSHOT_WIDTH || dims[1] > MAX_SCREENSHOT_HEIGHT) {\n\t\t\t\t\t\t\tconsola.warn(\n\t\t\t\t\t\t\t\t`screenshots/${file} is ${dims[0]}x${dims[1]}, max ${MAX_SCREENSHOT_WIDTH}x${MAX_SCREENSHOT_HEIGHT} — including anyway`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tawait copyFile(filePath, join(bundleDir, \"screenshots\", file));\n\t\t\t\t\t}\n\n\t\t\t\t\tconsola.success(`Included ${screenshotFiles.length} screenshot(s)`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// ── Step 7: Validation ──\n\n\t\t\tconsola.start(\"Validating bundle...\");\n\t\t\tlet hasErrors = false;\n\n\t\t\t// Check for Node.js builtins in backend.js\n\t\t\tconst backendPath = join(bundleDir, \"backend.js\");\n\t\t\tif (await fileExists(backendPath)) {\n\t\t\t\tconst backendCode = await readFile(backendPath, \"utf-8\");\n\t\t\t\tconst builtins = findNodeBuiltinImports(backendCode);\n\t\t\t\tif (builtins.length > 0) {\n\t\t\t\t\tconsola.error(`backend.js imports Node.js built-in modules: ${builtins.join(\", \")}`);\n\t\t\t\t\tconsola.error(\"Sandboxed plugins cannot use Node.js APIs\");\n\t\t\t\t\thasErrors = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check capabilities warnings\n\t\t\tif (manifest.capabilities.includes(\"network:fetch:any\")) {\n\t\t\t\tconsola.warn(\n\t\t\t\t\t\"Plugin declares unrestricted network access (network:fetch:any) — it can make requests to any host\",\n\t\t\t\t);\n\t\t\t} else if (\n\t\t\t\tmanifest.capabilities.includes(\"network:fetch\") &&\n\t\t\t\tmanifest.allowedHosts.length === 0\n\t\t\t) {\n\t\t\t\tconsola.warn(\n\t\t\t\t\t\"Plugin declares network:fetch capability but no allowedHosts — all fetch requests will be blocked\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Check for features that won't work in sandboxed mode\n\t\t\tif (\n\t\t\t\tresolvedPlugin.admin?.portableTextBlocks &&\n\t\t\t\tresolvedPlugin.admin.portableTextBlocks.length > 0\n\t\t\t) {\n\t\t\t\tconsola.warn(\n\t\t\t\t\t\"Plugin declares portableTextBlocks — these require trusted mode and will be ignored in sandboxed plugins\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (resolvedPlugin.admin?.entry) {\n\t\t\t\tconsola.warn(\n\t\t\t\t\t\"Plugin declares admin.entry — custom React components require trusted mode. Use Block Kit for sandboxed admin pages\",\n\t\t\t\t);\n\t\t\t}\n\t\t\t// Check for page:fragments hook — trusted-only, not allowed in sandbox\n\t\t\tif (resolvedPlugin.hooks[\"page:fragments\"]) {\n\t\t\t\tconsola.warn(\n\t\t\t\t\t\"Plugin declares page:fragments hook — this is trusted-only and will not work in sandboxed mode\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Check: if plugin declares admin pages or widgets, it must have an \"admin\" route\n\t\t\tconst hasAdminPages = (manifest.admin?.pages?.length ?? 0) > 0;\n\t\t\tconst hasAdminWidgets = (manifest.admin?.widgets?.length ?? 0) > 0;\n\t\t\tif (hasAdminPages || hasAdminWidgets) {\n\t\t\t\tconst routeNames = manifest.routes.map((r: string | { name: string }) =>\n\t\t\t\t\ttypeof r === \"string\" ? r : r.name,\n\t\t\t\t);\n\t\t\t\tif (!routeNames.includes(\"admin\")) {\n\t\t\t\t\tconsola.error(\n\t\t\t\t\t\t`Plugin declares ${hasAdminPages ? \"adminPages\" : \"\"}${hasAdminPages && hasAdminWidgets ? \" and \" : \"\"}${hasAdminWidgets ? \"adminWidgets\" : \"\"} ` +\n\t\t\t\t\t\t\t`but the sandbox entry has no \"admin\" route. ` +\n\t\t\t\t\t\t\t`Add an admin route handler to serve Block Kit pages.`,\n\t\t\t\t\t);\n\t\t\t\t\thasErrors = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Calculate total bundle size\n\t\t\tconst totalSize = await calculateDirectorySize(bundleDir);\n\t\t\tif (totalSize > MAX_BUNDLE_SIZE) {\n\t\t\t\tconst sizeMB = (totalSize / 1024 / 1024).toFixed(2);\n\t\t\t\tconsola.error(`Bundle size ${sizeMB}MB exceeds maximum of 5MB`);\n\t\t\t\thasErrors = true;\n\t\t\t} else {\n\t\t\t\tconst sizeKB = (totalSize / 1024).toFixed(1);\n\t\t\t\tconsola.info(`Bundle size: ${sizeKB}KB`);\n\t\t\t}\n\n\t\t\tif (hasErrors) {\n\t\t\t\tconsola.error(\"Bundle validation failed\");\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\tconsola.success(\"Validation passed\");\n\n\t\t\tif (validateOnly) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// ── Step 8: Create tarball ──\n\n\t\t\tawait mkdir(outDir, { recursive: true });\n\t\t\tconst tarballName = `${manifest.id.replace(SLASH_RE, \"-\").replace(LEADING_AT_RE, \"\")}-${manifest.version}.tar.gz`;\n\t\t\tconst tarballPath = join(outDir, tarballName);\n\n\t\t\tconsola.start(\"Creating tarball...\");\n\t\t\tawait createTarball(bundleDir, tarballPath);\n\n\t\t\tconst tarballStat = await stat(tarballPath);\n\t\t\tconst tarballSizeKB = (tarballStat.size / 1024).toFixed(1);\n\n\t\t\t// Calculate checksum\n\t\t\tconst tarballBuf = await readFile(tarballPath);\n\t\t\tconst checksum = createHash(\"sha256\").update(tarballBuf).digest(\"hex\");\n\n\t\t\tconsola.success(`Created ${tarballName} (${tarballSizeKB}KB)`);\n\t\t\tconsola.info(` SHA-256: ${checksum}`);\n\t\t\tconsola.info(` Path: ${tarballPath}`);\n\t\t} finally {\n\t\t\tif (tmpDir.endsWith(\".emdash-bundle-tmp\")) {\n\t\t\t\tawait rm(tmpDir, { recursive: true, force: true });\n\t\t\t}\n\t\t}\n\t},\n});\n","/**\n * emdash plugin init\n *\n * Scaffold a new EmDash plugin. Generates the standard-format boilerplate:\n * src/index.ts -- descriptor factory\n * src/sandbox-entry.ts -- definePlugin({ hooks, routes })\n * package.json\n * tsconfig.json\n *\n * Use --native to generate native-format boilerplate instead (createPlugin + React admin).\n *\n */\n\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { resolve, join, basename } from \"node:path\";\n\nimport { defineCommand } from \"citty\";\nimport consola from \"consola\";\n\nimport { fileExists } from \"./bundle-utils.js\";\n\nconst SLUG_RE = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;\nconst SCOPE_RE = /^@[^/]+\\//;\n\nexport const pluginInitCommand = defineCommand({\n\tmeta: {\n\t\tname: \"init\",\n\t\tdescription: \"Scaffold a new plugin\",\n\t},\n\targs: {\n\t\tdir: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Directory to create the plugin in (default: current directory)\",\n\t\t\tdefault: \".\",\n\t\t},\n\t\tname: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Plugin name/id (e.g. my-plugin or @org/my-plugin)\",\n\t\t},\n\t\tnative: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Generate native-format plugin (createPlugin + React admin)\",\n\t\t\tdefault: false,\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst targetDir = resolve(args.dir);\n\t\tconst isNative = args.native;\n\n\t\t// Derive plugin name from --name or directory name\n\t\tlet pluginName = args.name || basename(targetDir);\n\t\tif (!pluginName || pluginName === \".\") {\n\t\t\tpluginName = basename(resolve(\".\"));\n\t\t}\n\n\t\t// Strip scope for the slug\n\t\tconst slug = pluginName.replace(SCOPE_RE, \"\");\n\t\tif (!SLUG_RE.test(slug)) {\n\t\t\tconsola.error(\n\t\t\t\t`Invalid plugin name \"${pluginName}\". ` +\n\t\t\t\t\t\"Use lowercase letters, numbers, and hyphens (e.g. my-plugin).\",\n\t\t\t);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\t// Check if directory already has files\n\t\tconst srcDir = join(targetDir, \"src\");\n\t\tconst pkgPath = join(targetDir, \"package.json\");\n\t\tif (await fileExists(pkgPath)) {\n\t\t\tconsola.error(`package.json already exists in ${targetDir}`);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tconsola.start(`Scaffolding ${isNative ? \"native\" : \"standard\"} plugin: ${pluginName}`);\n\n\t\tawait mkdir(srcDir, { recursive: true });\n\n\t\tif (isNative) {\n\t\t\tawait scaffoldNative(targetDir, srcDir, pluginName, slug);\n\t\t} else {\n\t\t\tawait scaffoldStandard(targetDir, srcDir, pluginName, slug);\n\t\t}\n\n\t\tconsola.success(`Plugin scaffolded in ${targetDir}`);\n\t\tconsola.info(\"Next steps:\");\n\t\tif (args.dir !== \".\") {\n\t\t\tconsola.info(` 1. cd ${args.dir}`);\n\t\t}\n\t\tconsola.info(` ${args.dir !== \".\" ? \"2\" : \"1\"}. pnpm install`);\n\t\tif (isNative) {\n\t\t\tconsola.info(` ${args.dir !== \".\" ? \"3\" : \"2\"}. Edit src/index.ts to add hooks and routes`);\n\t\t} else {\n\t\t\tconsola.info(\n\t\t\t\t` ${args.dir !== \".\" ? \"3\" : \"2\"}. Edit src/sandbox-entry.ts to add hooks and routes`,\n\t\t\t);\n\t\t}\n\t\tconsola.info(` ${args.dir !== \".\" ? \"4\" : \"3\"}. emdash plugin validate --dir .`);\n\t},\n});\n\n// ── Standard format scaffolding ──────────────────────────────────\n\nasync function scaffoldStandard(\n\ttargetDir: string,\n\tsrcDir: string,\n\tpluginName: string,\n\tslug: string,\n): Promise<void> {\n\t// Derive the camelCase function name from slug\n\tconst fnName = slug\n\t\t.split(\"-\")\n\t\t.map((s, i) => (i === 0 ? s : s[0].toUpperCase() + s.slice(1)))\n\t\t.join(\"\");\n\n\t// package.json\n\tawait writeFile(\n\t\tjoin(targetDir, \"package.json\"),\n\t\tJSON.stringify(\n\t\t\t{\n\t\t\t\tname: pluginName,\n\t\t\t\tversion: \"0.1.0\",\n\t\t\t\ttype: \"module\",\n\t\t\t\texports: {\n\t\t\t\t\t\".\": \"./src/index.ts\",\n\t\t\t\t\t\"./sandbox\": \"./src/sandbox-entry.ts\",\n\t\t\t\t},\n\t\t\t\tfiles: [\"src\"],\n\t\t\t\tpeerDependencies: {\n\t\t\t\t\temdash: \"*\",\n\t\t\t\t},\n\t\t\t},\n\t\t\tnull,\n\t\t\t\"\\t\",\n\t\t) + \"\\n\",\n\t);\n\n\t// tsconfig.json\n\tawait writeFile(\n\t\tjoin(targetDir, \"tsconfig.json\"),\n\t\tJSON.stringify(\n\t\t\t{\n\t\t\t\tcompilerOptions: {\n\t\t\t\t\ttarget: \"ES2022\",\n\t\t\t\t\tmodule: \"preserve\",\n\t\t\t\t\tmoduleResolution: \"bundler\",\n\t\t\t\t\tstrict: true,\n\t\t\t\t\tesModuleInterop: true,\n\t\t\t\t\tdeclaration: true,\n\t\t\t\t\toutDir: \"./dist\",\n\t\t\t\t\trootDir: \"./src\",\n\t\t\t\t},\n\t\t\t\tinclude: [\"src/**/*\"],\n\t\t\t\texclude: [\"node_modules\", \"dist\"],\n\t\t\t},\n\t\t\tnull,\n\t\t\t\"\\t\",\n\t\t) + \"\\n\",\n\t);\n\n\t// src/index.ts -- descriptor factory\n\tawait writeFile(\n\t\tjoin(srcDir, \"index.ts\"),\n\t\t`import type { PluginDescriptor } from \"emdash\";\n\nexport function ${fnName}Plugin(): PluginDescriptor {\n\\treturn {\n\\t\\tid: \"${pluginName}\",\n\\t\\tversion: \"0.1.0\",\n\\t\\tformat: \"standard\",\n\\t\\tentrypoint: \"${pluginName}/sandbox\",\n\\t\\tcapabilities: [],\n\\t};\n}\n`,\n\t);\n\n\t// src/sandbox-entry.ts -- plugin definition\n\tawait writeFile(\n\t\tjoin(srcDir, \"sandbox-entry.ts\"),\n\t\t`import { definePlugin } from \"emdash\";\nimport type { PluginContext } from \"emdash\";\n\nexport default definePlugin({\n\\thooks: {\n\\t\\t\"content:afterSave\": {\n\\t\\t\\thandler: async (event: any, ctx: PluginContext) => {\n\\t\\t\\t\\tctx.log.info(\"Content saved\", {\n\\t\\t\\t\\t\\tcollection: event.collection,\n\\t\\t\\t\\t\\tid: event.content.id,\n\\t\\t\\t\\t});\n\\t\\t\\t},\n\\t\\t},\n\\t},\n});\n`,\n\t);\n}\n\n// ── Native format scaffolding ────────────────────────────────────\n\nasync function scaffoldNative(\n\ttargetDir: string,\n\tsrcDir: string,\n\tpluginName: string,\n\tslug: string,\n): Promise<void> {\n\tconst fnName = slug\n\t\t.split(\"-\")\n\t\t.map((s, i) => (i === 0 ? s : s[0].toUpperCase() + s.slice(1)))\n\t\t.join(\"\");\n\n\t// package.json\n\tawait writeFile(\n\t\tjoin(targetDir, \"package.json\"),\n\t\tJSON.stringify(\n\t\t\t{\n\t\t\t\tname: pluginName,\n\t\t\t\tversion: \"0.1.0\",\n\t\t\t\ttype: \"module\",\n\t\t\t\texports: {\n\t\t\t\t\t\".\": \"./src/index.ts\",\n\t\t\t\t},\n\t\t\t\tfiles: [\"src\"],\n\t\t\t\tpeerDependencies: {\n\t\t\t\t\temdash: \"*\",\n\t\t\t\t},\n\t\t\t},\n\t\t\tnull,\n\t\t\t\"\\t\",\n\t\t) + \"\\n\",\n\t);\n\n\t// tsconfig.json\n\tawait writeFile(\n\t\tjoin(targetDir, \"tsconfig.json\"),\n\t\tJSON.stringify(\n\t\t\t{\n\t\t\t\tcompilerOptions: {\n\t\t\t\t\ttarget: \"ES2022\",\n\t\t\t\t\tmodule: \"preserve\",\n\t\t\t\t\tmoduleResolution: \"bundler\",\n\t\t\t\t\tstrict: true,\n\t\t\t\t\tesModuleInterop: true,\n\t\t\t\t\tdeclaration: true,\n\t\t\t\t\toutDir: \"./dist\",\n\t\t\t\t\trootDir: \"./src\",\n\t\t\t\t},\n\t\t\t\tinclude: [\"src/**/*\"],\n\t\t\t\texclude: [\"node_modules\", \"dist\"],\n\t\t\t},\n\t\t\tnull,\n\t\t\t\"\\t\",\n\t\t) + \"\\n\",\n\t);\n\n\t// src/index.ts -- descriptor + createPlugin\n\tawait writeFile(\n\t\tjoin(srcDir, \"index.ts\"),\n\t\t`import { definePlugin } from \"emdash\";\nimport type { PluginDescriptor } from \"emdash\";\n\nexport function ${fnName}Plugin(): PluginDescriptor {\n\\treturn {\n\\t\\tid: \"${pluginName}\",\n\\t\\tversion: \"0.1.0\",\n\\t\\tformat: \"native\",\n\\t\\tentrypoint: \"${pluginName}\",\n\\t\\toptions: {},\n\\t};\n}\n\nexport function createPlugin() {\n\\treturn definePlugin({\n\\t\\tid: \"${pluginName}\",\n\\t\\tversion: \"0.1.0\",\n\n\\t\\thooks: {\n\\t\\t\\t\"content:afterSave\": async (event, ctx) => {\n\\t\\t\\t\\tctx.log.info(\"Content saved\", {\n\\t\\t\\t\\t\\tcollection: event.collection,\n\\t\\t\\t\\t\\tid: event.content.id,\n\\t\\t\\t\\t});\n\\t\\t\\t},\n\\t\\t},\n\\t});\n}\n\nexport default createPlugin;\n`,\n\t);\n}\n","/**\n * emdash plugin validate\n *\n * Runs bundle validation without producing a tarball.\n * Thin wrapper around `emdash plugin bundle --validate-only`.\n *\n */\n\nimport { defineCommand, runCommand } from \"citty\";\n\nimport { bundleCommand } from \"./bundle.js\";\n\nexport const pluginValidateCommand = defineCommand({\n\tmeta: {\n\t\tname: \"validate\",\n\t\tdescription: \"Validate a plugin without producing a tarball (same checks as bundle)\",\n\t},\n\targs: {\n\t\tdir: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Plugin directory (default: current directory)\",\n\t\t\tdefault: \".\",\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\t// Delegate to the bundle command with validateOnly flag\n\t\tawait runCommand(bundleCommand, {\n\t\t\trawArgs: [\"--dir\", args.dir, \"--validateOnly\"],\n\t\t});\n\t},\n});\n","/**\n * emdash plugin publish\n *\n * Publishes a plugin tarball to the EmDash Marketplace.\n *\n * Flow:\n * 1. Resolve tarball (from --tarball path, or build via `emdash plugin bundle`)\n * 2. Read manifest.json from tarball to show summary\n * 3. Authenticate (stored credential or GitHub device flow)\n * 4. Pre-publish validation (check plugin exists, version not published)\n * 5. Upload via multipart POST\n * 6. Display audit results\n */\n\nimport { readFile, stat } from \"node:fs/promises\";\nimport { resolve, basename } from \"node:path\";\n\nimport { defineCommand } from \"citty\";\nimport consola from \"consola\";\nimport { createGzipDecoder, unpackTar } from \"modern-tar\";\nimport pc from \"picocolors\";\n\nimport { pluginManifestSchema } from \"../../plugins/manifest-schema.js\";\nimport {\n\tgetMarketplaceCredential,\n\tsaveMarketplaceCredential,\n\tremoveMarketplaceCredential,\n} from \"../credentials.js\";\n\nconst DEFAULT_REGISTRY = \"https://marketplace.emdashcms.com\";\n\n// ── GitHub Device Flow ──────────────────────────────────────────\n\ninterface DeviceCodeResponse {\n\tdevice_code: string;\n\tuser_code: string;\n\tverification_uri: string;\n\texpires_in: number;\n\tinterval: number;\n}\n\ninterface GitHubTokenResponse {\n\taccess_token?: string;\n\ttoken_type?: string;\n\terror?: string;\n\terror_description?: string;\n\tinterval?: number;\n}\n\ninterface MarketplaceAuthResponse {\n\ttoken: string;\n\tauthor: {\n\t\tid: string;\n\t\tname: string;\n\t\tavatarUrl: string;\n\t};\n}\n\ninterface AuthDiscovery {\n\tgithub: {\n\t\tclientId: string;\n\t\tdeviceAuthorizationEndpoint: string;\n\t\ttokenEndpoint: string;\n\t};\n\tmarketplace: {\n\t\tdeviceTokenEndpoint: string;\n\t};\n}\n\n/**\n * Authenticate with the marketplace via GitHub Device Flow.\n * Returns the marketplace JWT and author info.\n */\nasync function authenticateViaDeviceFlow(registryUrl: string): Promise<MarketplaceAuthResponse> {\n\t// Step 1: Fetch auth discovery to get GitHub client_id\n\tconsola.start(\"Fetching auth configuration...\");\n\tconst discoveryRes = await fetch(new URL(\"/api/v1/auth/discovery\", registryUrl));\n\tif (!discoveryRes.ok) {\n\t\tthrow new Error(`Marketplace unreachable: ${discoveryRes.status} ${discoveryRes.statusText}`);\n\t}\n\tconst discovery = (await discoveryRes.json()) as AuthDiscovery;\n\n\t// Step 2: Request device code from GitHub\n\tconst deviceRes = await fetch(discovery.github.deviceAuthorizationEndpoint, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\tAccept: \"application/json\",\n\t\t},\n\t\tbody: JSON.stringify({\n\t\t\tclient_id: discovery.github.clientId,\n\t\t\tscope: \"read:user user:email\",\n\t\t}),\n\t});\n\n\tif (!deviceRes.ok) {\n\t\tthrow new Error(`GitHub device flow failed: ${deviceRes.status}`);\n\t}\n\n\tconst deviceCode = (await deviceRes.json()) as DeviceCodeResponse;\n\n\t// Step 3: Display instructions\n\tconsole.log();\n\tconsola.info(\"Open your browser to:\");\n\tconsole.log(` ${pc.cyan(pc.bold(deviceCode.verification_uri))}`);\n\tconsole.log();\n\tconsola.info(`Enter code: ${pc.yellow(pc.bold(deviceCode.user_code))}`);\n\tconsole.log();\n\n\t// Try to open browser\n\ttry {\n\t\tconst { execFile } = await import(\"node:child_process\");\n\t\tif (process.platform === \"darwin\") {\n\t\t\texecFile(\"open\", [deviceCode.verification_uri]);\n\t\t} else if (process.platform === \"win32\") {\n\t\t\texecFile(\"cmd\", [\"/c\", \"start\", \"\", deviceCode.verification_uri]);\n\t\t} else {\n\t\t\texecFile(\"xdg-open\", [deviceCode.verification_uri]);\n\t\t}\n\t} catch {\n\t\t// User can open manually\n\t}\n\n\t// Step 4: Poll GitHub for access token\n\tconsola.start(\"Waiting for authorization...\");\n\tconst githubToken = await pollGitHubDeviceFlow(\n\t\tdiscovery.github.tokenEndpoint,\n\t\tdiscovery.github.clientId,\n\t\tdeviceCode.device_code,\n\t\tdeviceCode.interval,\n\t\tdeviceCode.expires_in,\n\t);\n\n\t// Step 5: Exchange GitHub token for marketplace JWT\n\tconsola.start(\"Authenticating with marketplace...\");\n\tconst deviceTokenUrl = new URL(discovery.marketplace.deviceTokenEndpoint, registryUrl);\n\tconst authRes = await fetch(deviceTokenUrl, {\n\t\tmethod: \"POST\",\n\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\tbody: JSON.stringify({ access_token: githubToken }),\n\t});\n\n\tif (!authRes.ok) {\n\t\tconst body = (await authRes.json().catch(() => ({}))) as { error?: string };\n\t\tthrow new Error(`Marketplace auth failed: ${body.error ?? authRes.statusText}`);\n\t}\n\n\treturn (await authRes.json()) as MarketplaceAuthResponse;\n}\n\nasync function pollGitHubDeviceFlow(\n\ttokenEndpoint: string,\n\tclientId: string,\n\tdeviceCode: string,\n\tinterval: number,\n\texpiresIn: number,\n): Promise<string> {\n\tconst deadline = Date.now() + expiresIn * 1000;\n\tlet currentInterval = interval;\n\n\twhile (Date.now() < deadline) {\n\t\tawait new Promise((r) => setTimeout(r, currentInterval * 1000));\n\n\t\tconst res = await fetch(tokenEndpoint, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\tAccept: \"application/json\",\n\t\t\t},\n\t\t\tbody: JSON.stringify({\n\t\t\t\tclient_id: clientId,\n\t\t\t\tdevice_code: deviceCode,\n\t\t\t\tgrant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n\t\t\t}),\n\t\t});\n\n\t\tconst body = (await res.json()) as GitHubTokenResponse;\n\n\t\tif (body.access_token) {\n\t\t\treturn body.access_token;\n\t\t}\n\n\t\tif (body.error === \"authorization_pending\") continue;\n\t\tif (body.error === \"slow_down\") {\n\t\t\tcurrentInterval = body.interval ?? currentInterval + 5;\n\t\t\tcontinue;\n\t\t}\n\t\tif (body.error === \"expired_token\") {\n\t\t\tthrow new Error(\"Device code expired. Please try again.\");\n\t\t}\n\t\tif (body.error === \"access_denied\") {\n\t\t\tthrow new Error(\"Authorization was denied.\");\n\t\t}\n\n\t\tthrow new Error(`GitHub token exchange failed: ${body.error ?? \"unknown error\"}`);\n\t}\n\n\tthrow new Error(\"Device code expired (timeout). Please try again.\");\n}\n\n// ── Tarball reading ─────────────────────────────────────────────\n\nconst manifestSummarySchema = pluginManifestSchema.pick({\n\tid: true,\n\tversion: true,\n\tcapabilities: true,\n\tallowedHosts: true,\n});\n\ntype ManifestSummary = typeof manifestSummarySchema._zod.output;\n\n/**\n * Read manifest.json from a tarball without fully extracting it.\n */\nasync function readManifestFromTarball(tarballPath: string): Promise<ManifestSummary> {\n\tconst data = await readFile(tarballPath);\n\tconst stream = new ReadableStream<Uint8Array>({\n\t\tstart(controller) {\n\t\t\tcontroller.enqueue(new Uint8Array(data.buffer, data.byteOffset, data.byteLength));\n\t\t\tcontroller.close();\n\t\t},\n\t});\n\n\tconst entries = await unpackTar(stream.pipeThrough(createGzipDecoder()), {\n\t\tfilter: (header) => header.name === \"manifest.json\",\n\t});\n\n\tconst manifest = entries.find((e) => e.header.name === \"manifest.json\");\n\tif (!manifest?.data) {\n\t\tthrow new Error(\"Tarball does not contain manifest.json\");\n\t}\n\n\tconst content = new TextDecoder().decode(manifest.data);\n\tconst parsed: unknown = JSON.parse(content);\n\tconst result = manifestSummarySchema.safeParse(parsed);\n\tif (!result.success) {\n\t\tthrow new Error(`Invalid manifest.json: ${result.error.message}`);\n\t}\n\treturn result.data;\n}\n\n// ── Audit polling helpers ───────────────────────────────────────\n\nconst POLL_INTERVAL_MS = 3000;\nconst POLL_TIMEOUT_MS = 120_000; // 2 minutes\n\ninterface VersionStatusResponse {\n\tversion: string;\n\tstatus: string;\n\taudit_verdict?: string | null;\n\taudit_id?: string | null;\n\timage_audit_verdict?: string | null;\n}\n\n/**\n * Poll the version endpoint until status leaves \"pending\" or timeout.\n * Returns the final version data, or null on timeout.\n */\nasync function pollVersionStatus(\n\tversionUrl: string,\n\ttoken: string,\n): Promise<VersionStatusResponse | null> {\n\tconst deadline = Date.now() + POLL_TIMEOUT_MS;\n\n\twhile (Date.now() < deadline) {\n\t\tawait new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));\n\n\t\ttry {\n\t\t\tconst res = await fetch(versionUrl, {\n\t\t\t\theaders: { Authorization: `Bearer ${token}` },\n\t\t\t});\n\n\t\t\tif (!res.ok) continue;\n\n\t\t\tconst data = (await res.json()) as VersionStatusResponse;\n\t\t\tif (data.status !== \"pending\") {\n\t\t\t\treturn data;\n\t\t\t}\n\t\t} catch {\n\t\t\t// Network error — retry\n\t\t}\n\t}\n\n\treturn null;\n}\n\nfunction displayAuditResults(version: VersionStatusResponse): void {\n\tconst statusColor =\n\t\tversion.status === \"published\" ? pc.green : version.status === \"flagged\" ? pc.yellow : pc.red;\n\tconsola.info(` Status: ${statusColor(version.status)}`);\n\n\tif (version.audit_verdict) {\n\t\tconst verdictColor =\n\t\t\tversion.audit_verdict === \"pass\"\n\t\t\t\t? pc.green\n\t\t\t\t: version.audit_verdict === \"warn\"\n\t\t\t\t\t? pc.yellow\n\t\t\t\t\t: pc.red;\n\t\tconsola.info(` Audit: ${verdictColor(version.audit_verdict)}`);\n\t}\n\n\tif (version.image_audit_verdict) {\n\t\tconst verdictColor =\n\t\t\tversion.image_audit_verdict === \"pass\"\n\t\t\t\t? pc.green\n\t\t\t\t: version.image_audit_verdict === \"warn\"\n\t\t\t\t\t? pc.yellow\n\t\t\t\t\t: pc.red;\n\t\tconsola.info(` Image audit: ${verdictColor(version.image_audit_verdict)}`);\n\t}\n}\n\nfunction displayInlineAuditResults(\n\taudit: {\n\t\tverdict: string;\n\t\triskScore: number;\n\t\tsummary: string;\n\t\tfindings: { category: string; severity: string; description: string }[];\n\t},\n\timageAudit: { verdict: string } | null,\n): void {\n\tconst verdictColor =\n\t\taudit.verdict === \"pass\" ? pc.green : audit.verdict === \"warn\" ? pc.yellow : pc.red;\n\tconsola.info(` Audit: ${verdictColor(audit.verdict)} (risk: ${audit.riskScore}/100)`);\n\tif (audit.findings.length > 0) {\n\t\tfor (const finding of audit.findings) {\n\t\t\tconst icon = finding.severity === \"high\" ? pc.red(\"!\") : pc.yellow(\"~\");\n\t\t\tconsola.info(` ${icon} [${finding.category}] ${finding.description}`);\n\t\t}\n\t}\n\n\tif (imageAudit) {\n\t\tconst imgColor =\n\t\t\timageAudit.verdict === \"pass\" ? pc.green : imageAudit.verdict === \"warn\" ? pc.yellow : pc.red;\n\t\tconsola.info(` Image audit: ${imgColor(imageAudit.verdict)}`);\n\t}\n}\n\n// ── Publish command ─────────────────────────────────────────────\n\nexport const publishCommand = defineCommand({\n\tmeta: {\n\t\tname: \"publish\",\n\t\tdescription: \"Publish a plugin to the EmDash Marketplace\",\n\t},\n\targs: {\n\t\ttarball: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Path to plugin tarball (default: build first via `emdash plugin bundle`)\",\n\t\t},\n\t\tdir: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Plugin directory (used with --build, default: current directory)\",\n\t\t\tdefault: process.cwd(),\n\t\t},\n\t\tbuild: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Build the plugin before publishing\",\n\t\t\tdefault: false,\n\t\t},\n\t\tregistry: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Marketplace registry URL\",\n\t\t\tdefault: DEFAULT_REGISTRY,\n\t\t},\n\t\t\"no-wait\": {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Exit immediately after upload without waiting for audit (useful for CI)\",\n\t\t\tdefault: false,\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst registryUrl = args.registry;\n\n\t\t// ── Step 1: Resolve tarball ──\n\n\t\tlet tarballPath: string;\n\n\t\tif (args.tarball) {\n\t\t\ttarballPath = resolve(args.tarball);\n\t\t} else if (args.build) {\n\t\t\t// Build first, then find the output tarball\n\t\t\tconsola.start(\"Building plugin...\");\n\t\t\tconst pluginDir = resolve(args.dir);\n\t\t\ttry {\n\t\t\t\tconst { runCommand } = await import(\"citty\");\n\t\t\t\tconst { bundleCommand } = await import(\"./bundle.js\");\n\t\t\t\tawait runCommand(bundleCommand, {\n\t\t\t\t\trawArgs: [\"--dir\", pluginDir],\n\t\t\t\t});\n\t\t\t} catch {\n\t\t\t\tconsola.error(\"Build failed\");\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\t// Find the tarball in dist/\n\t\t\tconst { readdir } = await import(\"node:fs/promises\");\n\t\t\tconst distDir = resolve(pluginDir, \"dist\");\n\t\t\tconst files = await readdir(distDir);\n\t\t\tconst tarball = files.find((f) => f.endsWith(\".tar.gz\"));\n\t\t\tif (!tarball) {\n\t\t\t\tconsola.error(\"Build succeeded but no .tar.gz found in dist/\");\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t\ttarballPath = resolve(distDir, tarball);\n\t\t} else {\n\t\t\t// Look for an existing tarball in dist/\n\t\t\tconst pluginDir = resolve(args.dir);\n\t\t\tconst { readdir } = await import(\"node:fs/promises\");\n\t\t\ttry {\n\t\t\t\tconst distDir = resolve(pluginDir, \"dist\");\n\t\t\t\tconst files = await readdir(distDir);\n\t\t\t\tconst tarball = files.find((f) => f.endsWith(\".tar.gz\"));\n\t\t\t\tif (tarball) {\n\t\t\t\t\ttarballPath = resolve(distDir, tarball);\n\t\t\t\t} else {\n\t\t\t\t\tconsola.error(\"No tarball found. Run `emdash plugin bundle` first or use --build.\");\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\tconsola.error(\n\t\t\t\t\t\"No dist/ directory found. Run `emdash plugin bundle` first or use --build.\",\n\t\t\t\t);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t}\n\n\t\tconst tarballStat = await stat(tarballPath);\n\t\tconst sizeKB = (tarballStat.size / 1024).toFixed(1);\n\t\tconsola.info(`Tarball: ${pc.dim(tarballPath)} (${sizeKB}KB)`);\n\n\t\t// ── Step 2: Read manifest from tarball ──\n\n\t\tconst manifest = await readManifestFromTarball(tarballPath);\n\t\tconsole.log();\n\t\tconsola.info(`Plugin: ${pc.bold(`${manifest.id}@${manifest.version}`)}`);\n\t\tif (manifest.capabilities.length > 0) {\n\t\t\tconsola.info(`Capabilities: ${manifest.capabilities.join(\", \")}`);\n\t\t}\n\t\tif (manifest.allowedHosts?.length) {\n\t\t\tconsola.info(`Allowed hosts: ${manifest.allowedHosts.join(\", \")}`);\n\t\t}\n\t\tconsole.log();\n\n\t\t// ── Step 3: Authenticate ──\n\t\t//\n\t\t// Priority: EMDASH_MARKETPLACE_TOKEN env var > stored credential > interactive device flow.\n\t\t// The env var enables CI pipelines (including seed token auth) without interactive login.\n\n\t\tlet token: string;\n\t\tconst envToken = process.env.EMDASH_MARKETPLACE_TOKEN;\n\t\tconst stored = !envToken ? getMarketplaceCredential(registryUrl) : null;\n\n\t\tif (envToken) {\n\t\t\ttoken = envToken;\n\t\t\tconsola.info(\"Using EMDASH_MARKETPLACE_TOKEN for authentication\");\n\t\t} else if (stored) {\n\t\t\ttoken = stored.token;\n\t\t\tconsola.info(`Authenticated as ${pc.bold(stored.author?.name ?? \"unknown\")}`);\n\t\t} else {\n\t\t\tconsola.info(\"Not logged in to marketplace. Starting GitHub authentication...\");\n\t\t\tconst result = await authenticateViaDeviceFlow(registryUrl);\n\t\t\ttoken = result.token;\n\n\t\t\t// Save for next time\n\t\t\tsaveMarketplaceCredential(registryUrl, {\n\t\t\t\ttoken: result.token,\n\t\t\t\texpiresAt: new Date(Date.now() + 30 * 86400 * 1000).toISOString(), // 30 days\n\t\t\t\tauthor: { id: result.author.id, name: result.author.name },\n\t\t\t});\n\n\t\t\tconsola.success(`Authenticated as ${pc.bold(result.author.name)}`);\n\t\t}\n\n\t\t// ── Step 4: Pre-publish validation ──\n\n\t\tconsola.start(\"Checking marketplace...\");\n\n\t\t// Check if plugin exists\n\t\tconst pluginRes = await fetch(new URL(`/api/v1/plugins/${manifest.id}`, registryUrl));\n\n\t\tif (pluginRes.status === 404 && !envToken) {\n\t\t\t// Plugin doesn't exist — register it first.\n\t\t\t// When using env token (seed), the server auto-registers on publish.\n\t\t\tconsola.info(`Plugin ${pc.bold(manifest.id)} not found in marketplace. Registering...`);\n\n\t\t\tconst createRes = await fetch(new URL(\"/api/v1/plugins\", registryUrl), {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\tAuthorization: `Bearer ${token}`,\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tid: manifest.id,\n\t\t\t\t\tname: manifest.id, // Use ID as name initially\n\t\t\t\t\tcapabilities: manifest.capabilities,\n\t\t\t\t}),\n\t\t\t});\n\n\t\t\tif (!createRes.ok) {\n\t\t\t\tconst body = (await createRes.json().catch(() => ({}))) as { error?: string };\n\t\t\t\tif (createRes.status === 401) {\n\t\t\t\t\t// Token expired — clear and retry\n\t\t\t\t\tremoveMarketplaceCredential(registryUrl);\n\t\t\t\t\tconsola.error(\n\t\t\t\t\t\t\"Authentication expired. Please run `emdash plugin publish` again to re-authenticate.\",\n\t\t\t\t\t);\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t}\n\t\t\t\tconsola.error(`Failed to register plugin: ${body.error ?? createRes.statusText}`);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\tconsola.success(`Registered ${pc.bold(manifest.id)}`);\n\t\t} else if (pluginRes.status === 404 && envToken) {\n\t\t\t// Using env token — server handles auto-registration on publish\n\t\t\tconsola.info(`Plugin ${pc.bold(manifest.id)} will be auto-registered on publish`);\n\t\t} else if (!pluginRes.ok) {\n\t\t\tconsola.error(`Marketplace error: ${pluginRes.status}`);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\t// ── Step 5: Upload ──\n\n\t\tconsola.start(`Publishing ${manifest.id}@${manifest.version}...`);\n\n\t\tconst tarballData = await readFile(tarballPath);\n\t\tconst formData = new FormData();\n\t\tformData.append(\n\t\t\t\"bundle\",\n\t\t\tnew Blob([tarballData], { type: \"application/gzip\" }),\n\t\t\tbasename(tarballPath),\n\t\t);\n\n\t\tconst uploadUrl = new URL(`/api/v1/plugins/${manifest.id}/versions`, registryUrl);\n\t\tconst uploadRes = await fetch(uploadUrl, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${token}`,\n\t\t\t},\n\t\t\tbody: formData,\n\t\t});\n\n\t\tif (!uploadRes.ok && uploadRes.status !== 202) {\n\t\t\tconst body = (await uploadRes.json().catch(() => ({}))) as {\n\t\t\t\terror?: string;\n\t\t\t\tlatestVersion?: string;\n\t\t\t\taudit?: { verdict: string; summary: string; findings: unknown[] };\n\t\t\t};\n\n\t\t\tif (uploadRes.status === 401) {\n\t\t\t\tif (envToken) {\n\t\t\t\t\tconsola.error(\"EMDASH_MARKETPLACE_TOKEN was rejected by the marketplace.\");\n\t\t\t\t} else {\n\t\t\t\t\tremoveMarketplaceCredential(registryUrl);\n\t\t\t\t\tconsola.error(\"Authentication expired. Please run `emdash plugin publish` again.\");\n\t\t\t\t}\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\tif (uploadRes.status === 409) {\n\t\t\t\tif (body.latestVersion) {\n\t\t\t\t\tconsola.error(`Version ${manifest.version} must be greater than ${body.latestVersion}`);\n\t\t\t\t} else {\n\t\t\t\t\tconsola.error(body.error ?? \"Version conflict\");\n\t\t\t\t}\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\tif (uploadRes.status === 422 && body.audit) {\n\t\t\t\t// Failed security audit\n\t\t\t\tconsola.error(\"Plugin failed security audit:\");\n\t\t\t\tconsola.error(` Verdict: ${pc.red(body.audit.verdict)}`);\n\t\t\t\tconsola.error(` Summary: ${body.audit.summary}`);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\tconsola.error(`Publish failed: ${body.error ?? uploadRes.statusText}`);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\t// ── Step 6: Handle response ──\n\n\t\tconst result = (await uploadRes.json()) as {\n\t\t\tversion: string;\n\t\t\tbundleSize: number;\n\t\t\tchecksum: string;\n\t\t\tpublishedAt: string;\n\t\t\tstatus?: string;\n\t\t\tworkflowId?: string;\n\t\t\taudit?: {\n\t\t\t\tverdict: string;\n\t\t\t\triskScore: number;\n\t\t\t\tsummary: string;\n\t\t\t\tfindings: { category: string; severity: string; description: string }[];\n\t\t\t};\n\t\t\timageAudit?: {\n\t\t\t\tverdict: string;\n\t\t\t} | null;\n\t\t};\n\n\t\tconsole.log();\n\t\tconsola.success(`Uploaded ${pc.bold(`${manifest.id}@${result.version}`)}`);\n\t\tconsola.info(` Checksum: ${pc.dim(result.checksum)}`);\n\t\tconsola.info(` Size: ${(result.bundleSize / 1024).toFixed(1)}KB`);\n\n\t\t// Async audit flow (202 Accepted)\n\t\tif (uploadRes.status === 202) {\n\t\t\tconsola.info(` Status: ${pc.yellow(\"pending\")} (audit running in background)`);\n\n\t\t\tif (args[\"no-wait\"]) {\n\t\t\t\tconsola.info(\"Skipping audit wait (--no-wait). Check status later.\");\n\t\t\t\tconsole.log();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Poll version endpoint for audit completion\n\t\t\tconsola.start(\"Waiting for security audit to complete...\");\n\t\t\tconst versionUrl = new URL(\n\t\t\t\t`/api/v1/plugins/${manifest.id}/versions/${manifest.version}`,\n\t\t\t\tregistryUrl,\n\t\t\t);\n\t\t\tconst finalStatus = await pollVersionStatus(versionUrl.toString(), token);\n\n\t\t\tif (finalStatus) {\n\t\t\t\tdisplayAuditResults(finalStatus);\n\t\t\t} else {\n\t\t\t\tconsola.warn(\"Audit did not complete within timeout. Check status later with:\");\n\t\t\t\tconsola.info(` ${pc.dim(`curl ${versionUrl.toString()}`)}`);\n\t\t\t}\n\t\t} else {\n\t\t\t// Synchronous response (201 or legacy)\n\t\t\tif (result.audit) {\n\t\t\t\tdisplayInlineAuditResults(result.audit, result.imageAudit ?? null);\n\t\t\t}\n\t\t\tconsola.info(` Status: ${pc.green(result.status ?? \"published\")}`);\n\t\t}\n\n\t\tconsole.log();\n\t},\n});\n\n// ── Marketplace auth subcommands ────────────────────────────────\n\nexport const marketplaceLoginCommand = defineCommand({\n\tmeta: {\n\t\tname: \"login\",\n\t\tdescription: \"Log in to the EmDash Marketplace via GitHub\",\n\t},\n\targs: {\n\t\tregistry: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Marketplace registry URL\",\n\t\t\tdefault: DEFAULT_REGISTRY,\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst registryUrl = args.registry;\n\n\t\tconst existing = getMarketplaceCredential(registryUrl);\n\t\tif (existing) {\n\t\t\tconsola.info(`Already logged in as ${pc.bold(existing.author?.name ?? \"unknown\")}`);\n\t\t\tconsola.info(\"Use `emdash plugin logout` to log out first.\");\n\t\t\treturn;\n\t\t}\n\n\t\tconst result = await authenticateViaDeviceFlow(registryUrl);\n\n\t\tsaveMarketplaceCredential(registryUrl, {\n\t\t\ttoken: result.token,\n\t\t\texpiresAt: new Date(Date.now() + 30 * 86400 * 1000).toISOString(),\n\t\t\tauthor: { id: result.author.id, name: result.author.name },\n\t\t});\n\n\t\tconsola.success(`Logged in as ${pc.bold(result.author.name)}`);\n\t},\n});\n\nexport const marketplaceLogoutCommand = defineCommand({\n\tmeta: {\n\t\tname: \"logout\",\n\t\tdescription: \"Log out of the EmDash Marketplace\",\n\t},\n\targs: {\n\t\tregistry: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Marketplace registry URL\",\n\t\t\tdefault: DEFAULT_REGISTRY,\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst removed = removeMarketplaceCredential(args.registry);\n\t\tif (removed) {\n\t\t\tconsola.success(\"Logged out of marketplace.\");\n\t\t} else {\n\t\t\tconsola.info(\"No marketplace credentials found.\");\n\t\t}\n\t},\n});\n","/**\n * emdash plugin\n *\n * Plugin management commands grouped under a single namespace.\n *\n * Subcommands:\n * - init: Scaffold a new plugin\n * - bundle: Bundle a plugin for marketplace distribution\n * - validate: Run bundle validation without producing a tarball\n * - publish: Publish a plugin to the marketplace\n * - login: Log in to the marketplace via GitHub\n * - logout: Log out of the marketplace\n *\n */\n\nimport { defineCommand } from \"citty\";\n\nimport { bundleCommand } from \"./bundle.js\";\nimport { pluginInitCommand } from \"./plugin-init.js\";\nimport { pluginValidateCommand } from \"./plugin-validate.js\";\nimport { publishCommand, marketplaceLoginCommand, marketplaceLogoutCommand } from \"./publish.js\";\n\nexport const pluginCommand = defineCommand({\n\tmeta: { name: \"plugin\", description: \"Manage plugins\" },\n\tsubCommands: {\n\t\tinit: pluginInitCommand,\n\t\tbundle: bundleCommand,\n\t\tvalidate: pluginValidateCommand,\n\t\tpublish: publishCommand,\n\t\tlogin: marketplaceLoginCommand,\n\t\tlogout: marketplaceLogoutCommand,\n\t},\n});\n","/**\n * emdash schema\n *\n * Manage collections and fields via the remote API\n */\n\nimport { defineCommand } from \"citty\";\nimport { consola } from \"consola\";\n\nimport { connectionArgs as commonArgs, createClientFromArgs } from \"../client-factory.js\";\nimport { output } from \"../output.js\";\n\nconst listCommand = defineCommand({\n\tmeta: {\n\t\tname: \"list\",\n\t\tdescription: \"List all collections\",\n\t},\n\targs: {\n\t\t...commonArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst collections = await client.collections();\n\t\t\toutput(collections, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst getCommand = defineCommand({\n\tmeta: {\n\t\tname: \"get\",\n\t\tdescription: \"Get collection with fields\",\n\t},\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\t...commonArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst collection = await client.collection(args.collection);\n\t\t\toutput(collection, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst createCommand = defineCommand({\n\tmeta: {\n\t\tname: \"create\",\n\t\tdescription: \"Create a collection\",\n\t},\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tlabel: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Collection label\",\n\t\t\trequired: true,\n\t\t},\n\t\t\"label-singular\": {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Singular label (defaults to label)\",\n\t\t},\n\t\tdescription: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Collection description\",\n\t\t},\n\t\t...commonArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst data = await client.createCollection({\n\t\t\t\tslug: args.collection,\n\t\t\t\tlabel: args.label,\n\t\t\t\tlabelSingular: args[\"label-singular\"] || args.label,\n\t\t\t\tdescription: args.description,\n\t\t\t});\n\t\t\tconsola.success(`Created collection \"${args.collection}\"`);\n\t\t\toutput(data, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst deleteCommand = defineCommand({\n\tmeta: {\n\t\tname: \"delete\",\n\t\tdescription: \"Delete a collection\",\n\t},\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tforce: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Skip confirmation\",\n\t\t},\n\t\t...commonArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tif (!args.force) {\n\t\t\t\tconst confirmed = await consola.prompt(`Delete collection \"${args.collection}\"?`, {\n\t\t\t\t\ttype: \"confirm\",\n\t\t\t\t});\n\t\t\t\tif (!confirmed) {\n\t\t\t\t\tconsola.info(\"Cancelled\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tawait client.deleteCollection(args.collection);\n\t\t\tconsola.success(`Deleted collection \"${args.collection}\"`);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst addFieldCommand = defineCommand({\n\tmeta: {\n\t\tname: \"add-field\",\n\t\tdescription: \"Add a field to a collection\",\n\t},\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tfield: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Field slug\",\n\t\t\trequired: true,\n\t\t},\n\t\ttype: {\n\t\t\ttype: \"string\",\n\t\t\tdescription:\n\t\t\t\t\"Field type (string, text, number, integer, boolean, datetime, image, reference, portableText, json)\",\n\t\t\trequired: true,\n\t\t},\n\t\tlabel: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Field label\",\n\t\t},\n\t\trequired: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Whether the field is required\",\n\t\t},\n\t\t...commonArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst data = await client.createField(args.collection, {\n\t\t\t\tslug: args.field,\n\t\t\t\ttype: args.type,\n\t\t\t\tlabel: args.label || args.field,\n\t\t\t\trequired: args.required,\n\t\t\t});\n\t\t\tconsola.success(`Added field \"${args.field}\" to \"${args.collection}\"`);\n\t\t\toutput(data, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst removeFieldCommand = defineCommand({\n\tmeta: {\n\t\tname: \"remove-field\",\n\t\tdescription: \"Remove a field from a collection\",\n\t},\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tfield: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Field slug\",\n\t\t\trequired: true,\n\t\t},\n\t\t...commonArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tawait client.deleteField(args.collection, args.field);\n\t\t\tconsola.success(`Removed field \"${args.field}\" from \"${args.collection}\"`);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nexport const schemaCommand = defineCommand({\n\tmeta: {\n\t\tname: \"schema\",\n\t\tdescription: \"Manage collections and fields\",\n\t},\n\tsubCommands: {\n\t\tlist: listCommand,\n\t\tget: getCommand,\n\t\tcreate: createCommand,\n\t\tdelete: deleteCommand,\n\t\t\"add-field\": addFieldCommand,\n\t\t\"remove-field\": removeFieldCommand,\n\t},\n});\n","/**\n * emdash search\n *\n * Full-text search across content\n */\n\nimport { defineCommand } from \"citty\";\nimport { consola } from \"consola\";\n\nimport { connectionArgs, createClientFromArgs } from \"../client-factory.js\";\nimport { output } from \"../output.js\";\n\nexport const searchCommand = defineCommand({\n\tmeta: {\n\t\tname: \"search\",\n\t\tdescription: \"Full-text search across content\",\n\t},\n\targs: {\n\t\tquery: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Search query\",\n\t\t\trequired: true,\n\t\t},\n\t\tcollection: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"c\",\n\t\t\tdescription: \"Filter by collection\",\n\t\t},\n\t\tlocale: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Filter by locale\",\n\t\t},\n\t\tlimit: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"l\",\n\t\t\tdescription: \"Maximum results to return\",\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst results = await client.search(args.query, {\n\t\t\t\tcollection: args.collection,\n\t\t\t\tlocale: args.locale,\n\t\t\t\tlimit: args.limit ? parseInt(args.limit, 10) : undefined,\n\t\t\t});\n\t\t\toutput(results, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n","/**\n * emdash seed\n *\n * Apply a seed file to the database\n */\n\nimport { readFile, access, mkdir } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\n\nimport { defineCommand } from \"citty\";\nimport consola from \"consola\";\n\nimport { createDatabase } from \"../../database/connection.js\";\nimport { runMigrations } from \"../../database/migrations/runner.js\";\nimport { applySeed } from \"../../seed/apply.js\";\nimport type { SeedFile, SeedApplyOptions } from \"../../seed/types.js\";\nimport { validateSeed } from \"../../seed/validate.js\";\nimport { LocalStorage } from \"../../storage/local.js\";\n\ninterface PackageJson {\n\tname?: string;\n\temdash?: {\n\t\tseed?: string;\n\t};\n}\n\nasync function fileExists(path: string): Promise<boolean> {\n\ttry {\n\t\tawait access(path);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nasync function readPackageJson(cwd: string): Promise<PackageJson | null> {\n\tconst pkgPath = resolve(cwd, \"package.json\");\n\ttry {\n\t\tconst content = await readFile(pkgPath, \"utf-8\");\n\t\treturn JSON.parse(content);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Resolve seed file path from:\n * 1. Positional argument (if provided)\n * 2. .emdash/seed.json (convention)\n * 3. package.json emdash.seed (config)\n */\nasync function resolveSeedPath(cwd: string, positional?: string): Promise<string | null> {\n\t// 1. Positional argument\n\tif (positional) {\n\t\tconst resolved = resolve(cwd, positional);\n\t\tif (await fileExists(resolved)) {\n\t\t\treturn resolved;\n\t\t}\n\t\tconsola.error(`Seed file not found: ${positional}`);\n\t\treturn null;\n\t}\n\n\t// 2. Convention: .emdash/seed.json\n\tconst conventionPath = resolve(cwd, \".emdash\", \"seed.json\");\n\tif (await fileExists(conventionPath)) {\n\t\treturn conventionPath;\n\t}\n\n\t// 3. package.json emdash.seed\n\tconst pkg = await readPackageJson(cwd);\n\tif (pkg?.emdash?.seed) {\n\t\tconst pkgSeedPath = resolve(cwd, pkg.emdash.seed);\n\t\tif (await fileExists(pkgSeedPath)) {\n\t\t\treturn pkgSeedPath;\n\t\t}\n\t\tconsola.warn(`Seed file from package.json not found: ${pkg.emdash.seed}`);\n\t}\n\n\treturn null;\n}\n\nexport const seedCommand = defineCommand({\n\tmeta: {\n\t\tname: \"seed\",\n\t\tdescription: \"Apply a seed file to the database\",\n\t},\n\targs: {\n\t\tpath: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Path to seed file (default: .emdash/seed.json)\",\n\t\t\trequired: false,\n\t\t},\n\t\tdatabase: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"d\",\n\t\t\tdescription: \"Database path\",\n\t\t\tdefault: \"./data.db\",\n\t\t},\n\t\tcwd: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Working directory\",\n\t\t\tdefault: process.cwd(),\n\t\t},\n\t\tvalidate: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Validate only, don't apply\",\n\t\t\tdefault: false,\n\t\t},\n\t\t\"no-content\": {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Skip sample content\",\n\t\t\tdefault: false,\n\t\t},\n\t\t\"on-conflict\": {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Conflict handling: skip, update, error\",\n\t\t\tdefault: \"skip\",\n\t\t},\n\t\t\"uploads-dir\": {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Directory for media uploads\",\n\t\t\tdefault: \"./uploads\",\n\t\t},\n\t\t\"media-base-url\": {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Base URL for media files\",\n\t\t\tdefault: \"/_emdash/api/media/file\",\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst cwd = resolve(args.cwd);\n\t\tconsola.start(\"Loading seed file...\");\n\n\t\t// Resolve seed file path\n\t\tconst seedPath = await resolveSeedPath(cwd, args.path);\n\t\tif (!seedPath) {\n\t\t\tconsola.error(\"No seed file found\");\n\t\t\tconsola.info(\n\t\t\t\t\"Provide a path, create .emdash/seed.json, or set emdash.seed in package.json\",\n\t\t\t);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tconsola.info(`Seed file: ${seedPath}`);\n\n\t\t// Load and parse seed file\n\t\tlet seed: SeedFile;\n\t\ttry {\n\t\t\tconst content = await readFile(seedPath, \"utf-8\");\n\t\t\tseed = JSON.parse(content);\n\t\t} catch (error) {\n\t\t\tconsola.error(\"Failed to parse seed file:\", error);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\t// Validate seed\n\t\tconsola.start(\"Validating seed file...\");\n\t\tconst validation = validateSeed(seed);\n\n\t\tif (validation.warnings.length > 0) {\n\t\t\tfor (const warning of validation.warnings) {\n\t\t\t\tconsola.warn(warning);\n\t\t\t}\n\t\t}\n\n\t\tif (!validation.valid) {\n\t\t\tconsola.error(\"Seed validation failed:\");\n\t\t\tfor (const error of validation.errors) {\n\t\t\t\tconsola.error(` - ${error}`);\n\t\t\t}\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tconsola.success(\"Seed file is valid\");\n\n\t\t// If validate-only mode, exit here\n\t\tif (args.validate) {\n\t\t\tconsola.success(\"Validation complete\");\n\t\t\treturn;\n\t\t}\n\n\t\t// Connect to database\n\t\tconst dbPath = resolve(cwd, args.database);\n\t\tconsola.info(`Database: ${dbPath}`);\n\n\t\tconst db = createDatabase({ url: `file:${dbPath}` });\n\n\t\t// Run migrations\n\t\tconsola.start(\"Running migrations...\");\n\t\ttry {\n\t\t\tconst { applied } = await runMigrations(db);\n\t\t\tif (applied.length > 0) {\n\t\t\t\tconsola.success(`Applied ${applied.length} migrations`);\n\t\t\t} else {\n\t\t\t\tconsola.info(\"Database up to date\");\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsola.error(\"Migration failed:\", error);\n\t\t\tawait db.destroy();\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\t// Set up storage for $media resolution\n\t\tconst uploadsDir = resolve(cwd, args[\"uploads-dir\"]);\n\t\tawait mkdir(uploadsDir, { recursive: true });\n\n\t\tconst storage = new LocalStorage({\n\t\t\tdirectory: uploadsDir,\n\t\t\tbaseUrl: args[\"media-base-url\"],\n\t\t});\n\n\t\t// Prepare apply options\n\t\tconst onConflictRaw = args[\"on-conflict\"];\n\t\tif (onConflictRaw !== \"skip\" && onConflictRaw !== \"update\" && onConflictRaw !== \"error\") {\n\t\t\tconsola.error(`Invalid --on-conflict value: ${onConflictRaw}`);\n\t\t\tconsola.info(\"Use: skip, update, or error\");\n\t\t\tawait db.destroy();\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tconst options: SeedApplyOptions = {\n\t\t\tincludeContent: !args[\"no-content\"],\n\t\t\tonConflict: onConflictRaw,\n\t\t\tstorage,\n\t\t};\n\n\t\t// Apply seed\n\t\tconsola.start(\"Applying seed...\");\n\t\ttry {\n\t\t\tconst result = await applySeed(db, seed, options);\n\n\t\t\tconsola.success(\"Seed applied successfully!\");\n\t\t\tconsola.log(\"\");\n\n\t\t\t// Print summary\n\t\t\tif (result.settings.applied > 0) {\n\t\t\t\tconsola.info(`Settings: ${result.settings.applied} applied`);\n\t\t\t}\n\t\t\tif (\n\t\t\t\tresult.collections.created > 0 ||\n\t\t\t\tresult.collections.skipped > 0 ||\n\t\t\t\tresult.collections.updated > 0\n\t\t\t) {\n\t\t\t\tconsola.info(\n\t\t\t\t\t`Collections: ${result.collections.created} created, ${result.collections.skipped} skipped, ${result.collections.updated} updated`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (result.fields.created > 0 || result.fields.skipped > 0 || result.fields.updated > 0) {\n\t\t\t\tconsola.info(\n\t\t\t\t\t`Fields: ${result.fields.created} created, ${result.fields.skipped} skipped, ${result.fields.updated} updated`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (result.taxonomies.created > 0 || result.taxonomies.terms > 0) {\n\t\t\t\tconsola.info(\n\t\t\t\t\t`Taxonomies: ${result.taxonomies.created} created, ${result.taxonomies.terms} terms`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (result.bylines.created > 0 || result.bylines.skipped > 0 || result.bylines.updated > 0) {\n\t\t\t\tconsola.info(\n\t\t\t\t\t`Bylines: ${result.bylines.created} created, ${result.bylines.skipped} skipped, ${result.bylines.updated} updated`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (result.menus.created > 0 || result.menus.items > 0) {\n\t\t\t\tconsola.info(`Menus: ${result.menus.created} created, ${result.menus.items} items`);\n\t\t\t}\n\t\t\tif (result.widgetAreas.created > 0 || result.widgetAreas.widgets > 0) {\n\t\t\t\tconsola.info(\n\t\t\t\t\t`Widget Areas: ${result.widgetAreas.created} created, ${result.widgetAreas.widgets} widgets`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (result.content.created > 0 || result.content.skipped > 0 || result.content.updated > 0) {\n\t\t\t\tconsola.info(\n\t\t\t\t\t`Content: ${result.content.created} created, ${result.content.skipped} skipped, ${result.content.updated} updated`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (result.media.created > 0 || result.media.skipped > 0) {\n\t\t\t\tconsola.info(`Media: ${result.media.created} created, ${result.media.skipped} skipped`);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsola.error(\"Seed failed:\", error instanceof Error ? error.message : error);\n\t\t\tawait db.destroy();\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tawait db.destroy();\n\t\tconsola.success(\"Done!\");\n\t},\n});\n","/**\n * emdash taxonomy\n *\n * Manage taxonomies and terms via the EmDash REST API.\n */\n\nimport { defineCommand } from \"citty\";\nimport { consola } from \"consola\";\n\nimport { connectionArgs, createClientFromArgs } from \"../client-factory.js\";\nimport { output } from \"../output.js\";\n\n/** Pattern to replace whitespace with hyphens for slug generation */\nconst WHITESPACE_PATTERN = /\\s+/g;\n\nconst listCommand = defineCommand({\n\tmeta: {\n\t\tname: \"list\",\n\t\tdescription: \"List all taxonomies\",\n\t},\n\targs: {\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst taxonomies = await client.taxonomies();\n\t\t\toutput(taxonomies, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst termsCommand = defineCommand({\n\tmeta: {\n\t\tname: \"terms\",\n\t\tdescription: \"List terms in a taxonomy\",\n\t},\n\targs: {\n\t\tname: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Taxonomy name\",\n\t\t\trequired: true,\n\t\t},\n\t\tlimit: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"l\",\n\t\t\tdescription: \"Maximum terms to return\",\n\t\t},\n\t\tcursor: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Pagination cursor\",\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst result = await client.terms(args.name, {\n\t\t\t\tlimit: args.limit ? parseInt(args.limit, 10) : undefined,\n\t\t\t\tcursor: args.cursor,\n\t\t\t});\n\t\t\toutput(result, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst addTermCommand = defineCommand({\n\tmeta: {\n\t\tname: \"add-term\",\n\t\tdescription: \"Create a term in a taxonomy\",\n\t},\n\targs: {\n\t\ttaxonomy: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Taxonomy name\",\n\t\t\trequired: true,\n\t\t},\n\t\tname: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Term label\",\n\t\t\trequired: true,\n\t\t},\n\t\tslug: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Term slug (defaults to slugified name)\",\n\t\t},\n\t\tparent: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Parent term ID\",\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst label = args.name;\n\t\t\tconst slug = args.slug || label.toLowerCase().replace(WHITESPACE_PATTERN, \"-\");\n\t\t\tconst term = await client.createTerm(args.taxonomy, {\n\t\t\t\tslug,\n\t\t\t\tlabel,\n\t\t\t\tparentId: args.parent,\n\t\t\t});\n\t\t\tconsola.success(`Created term \"${label}\" in ${args.taxonomy}`);\n\t\t\toutput(term, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nexport const taxonomyCommand = defineCommand({\n\tmeta: {\n\t\tname: \"taxonomy\",\n\t\tdescription: \"Manage taxonomies and terms\",\n\t},\n\tsubCommands: {\n\t\tlist: listCommand,\n\t\tterms: termsCommand,\n\t\t\"add-term\": addTermCommand,\n\t},\n});\n","/**\n * emdash types\n *\n * Fetch schema from an EmDash instance and generate TypeScript types\n */\n\nimport { writeFile, mkdir } from \"node:fs/promises\";\nimport { resolve, dirname } from \"node:path\";\n\nimport { defineCommand } from \"citty\";\nimport consola from \"consola\";\n\nimport { connectionArgs, createClientFromArgs } from \"../client-factory.js\";\n\nexport const typesCommand = defineCommand({\n\tmeta: {\n\t\tname: \"types\",\n\t\tdescription: \"Generate TypeScript types from schema\",\n\t},\n\targs: {\n\t\t...connectionArgs,\n\t\toutput: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"o\",\n\t\t\tdescription: \"Output path for generated types\",\n\t\t\tdefault: \".emdash/types.ts\",\n\t\t},\n\t\tcwd: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Working directory\",\n\t\t\tdefault: process.cwd(),\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst cwd = resolve(args.cwd);\n\t\tconsola.start(\"Fetching schema...\");\n\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\n\t\t\t// Fetch JSON schema\n\t\t\tconst schema = await client.schemaExport();\n\t\t\tconsola.success(`Found ${schema.collections.length} collections`);\n\n\t\t\t// Fetch TypeScript types\n\t\t\tconst types = await client.schemaTypes();\n\n\t\t\t// Write types file\n\t\t\tconst outputPath = resolve(cwd, args.output);\n\t\t\tawait mkdir(dirname(outputPath), { recursive: true });\n\t\t\tawait writeFile(outputPath, types, \"utf-8\");\n\t\t\tconsola.success(`Generated ${args.output}`);\n\n\t\t\t// Also write a schema.json for reference\n\t\t\tconst schemaJsonPath = resolve(dirname(outputPath), \"schema.json\");\n\t\t\tawait writeFile(schemaJsonPath, JSON.stringify(schema, null, 2), \"utf-8\");\n\t\t\tconsola.info(`Schema version: ${schema.version}`);\n\n\t\t\tconsola.box({\n\t\t\t\ttitle: \"Types generated\",\n\t\t\t\tmessage: `${schema.collections.length} collections\\n\\nTypes: ${args.output}\\nSchema: .emdash/schema.json`,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconsola.error(\"Failed to fetch schema:\", error instanceof Error ? error.message : error);\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n","#!/usr/bin/env node\n\n/**\n * EmDash CLI\n *\n * Built with citty + clack (same stack as Nuxt CLI)\n *\n * Commands:\n * - init: Bootstrap database from template config, or interactive setup\n * - types: Generate TypeScript types from schema\n * - dev: Run dev server with local D1\n * - seed: Apply a seed file to the database\n * - export-seed: Export database schema and content as a seed file\n * - auth: Authentication utilities (secret generation)\n * - login/logout/whoami: Session management\n * - content: Create, read, update, delete content\n * - schema: Manage collections and fields\n * - media: Upload and manage media\n * - search: Full-text search\n * - taxonomy: Manage taxonomies and terms\n * - menu: Manage navigation menus\n * - plugin: Plugin management (init, bundle, validate, publish, login, logout)\n */\n\nimport { defineCommand, runMain } from \"citty\";\n\nimport { authCommand } from \"./commands/auth.js\";\nimport { contentCommand } from \"./commands/content.js\";\nimport { devCommand } from \"./commands/dev.js\";\nimport { doctorCommand } from \"./commands/doctor.js\";\nimport { exportSeedCommand } from \"./commands/export-seed.js\";\nimport { initCommand } from \"./commands/init.js\";\nimport { loginCommand, logoutCommand, whoamiCommand } from \"./commands/login.js\";\nimport { mediaCommand } from \"./commands/media.js\";\nimport { menuCommand } from \"./commands/menu.js\";\nimport { pluginCommand } from \"./commands/plugin.js\";\nimport { schemaCommand } from \"./commands/schema.js\";\nimport { searchCommand } from \"./commands/search-cmd.js\";\nimport { seedCommand } from \"./commands/seed.js\";\nimport { taxonomyCommand } from \"./commands/taxonomy.js\";\nimport { typesCommand } from \"./commands/types.js\";\n\nconst main = defineCommand({\n\tmeta: {\n\t\tname: \"emdash\",\n\t\tversion: \"0.0.0\",\n\t\tdescription: \"CLI for EmDash CMS\",\n\t},\n\tsubCommands: {\n\t\tinit: initCommand,\n\t\ttypes: typesCommand,\n\t\tdev: devCommand,\n\t\tdoctor: doctorCommand,\n\t\tseed: seedCommand,\n\t\t\"export-seed\": exportSeedCommand,\n\t\tauth: authCommand,\n\t\tlogin: loginCommand,\n\t\tlogout: logoutCommand,\n\t\twhoami: whoamiCommand,\n\t\tcontent: contentCommand,\n\t\tschema: schemaCommand,\n\t\tmedia: mediaCommand,\n\t\tsearch: searchCommand,\n\t\ttaxonomy: taxonomyCommand,\n\t\tmenu: menuCommand,\n\t\tplugin: pluginCommand,\n\t},\n});\n\nvoid runMain(main);\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["listCommand","getCommand","createCommand","deleteCommand","publishCommand","readPackageJson","fileExists","fileExists","fileExists","readPackageJson","listCommand","getCommand","deleteCommand","listCommand","getCommand","fileExists","fileExists","fileExists","listCommand","commonArgs","consola"],"sources":["../../src/cli/commands/auth.ts","../../src/cli/credentials.ts","../../src/cli/client-factory.ts","../../src/cli/output.ts","../../src/cli/commands/content.ts","../../src/cli/commands/dev.ts","../../src/cli/commands/doctor.ts","../../src/cli/commands/export-seed.ts","../../src/cli/commands/init.ts","../../src/cli/commands/login.ts","../../src/cli/commands/media.ts","../../src/cli/commands/menu.ts","../../src/cli/commands/bundle-utils.ts","../../src/cli/commands/bundle.ts","../../src/cli/commands/plugin-init.ts","../../src/cli/commands/plugin-validate.ts","../../src/cli/commands/publish.ts","../../src/cli/commands/plugin.ts","../../src/cli/commands/schema.ts","../../src/cli/commands/search-cmd.ts","../../src/cli/commands/seed.ts","../../src/cli/commands/taxonomy.ts","../../src/cli/commands/types.ts","../../src/cli/index.ts"],"sourcesContent":["/**\n * Auth CLI commands\n */\n\nimport { defineCommand } from \"citty\";\nimport { consola } from \"consola\";\nimport pc from \"picocolors\";\n\nimport { encodeBase64url } from \"../../utils/base64.js\";\n\n/**\n * Generate a cryptographically secure auth secret\n */\nfunction generateAuthSecret(): string {\n\tconst bytes = new Uint8Array(32);\n\tcrypto.getRandomValues(bytes);\n\treturn encodeBase64url(bytes);\n}\n\nconst secretCommand = defineCommand({\n\tmeta: {\n\t\tname: \"secret\",\n\t\tdescription: \"Generate a secure auth secret\",\n\t},\n\trun() {\n\t\tconst secret = generateAuthSecret();\n\n\t\tconsola.log(\"\");\n\t\tconsola.log(pc.bold(\"Generated auth secret:\"));\n\t\tconsola.log(\"\");\n\t\tconsola.log(` ${pc.cyan(\"EMDASH_AUTH_SECRET\")}=${pc.green(secret)}`);\n\t\tconsola.log(\"\");\n\t\tconsola.log(pc.dim(\"Add this to your environment variables.\"));\n\t\tconsola.log(\"\");\n\t},\n});\n\nexport const authCommand = defineCommand({\n\tmeta: {\n\t\tname: \"auth\",\n\t\tdescription: \"Authentication utilities\",\n\t},\n\tsubCommands: {\n\t\tsecret: secretCommand,\n\t},\n});\n","/**\n * Credential storage for CLI auth tokens.\n *\n * Stores OAuth tokens in ~/.config/emdash/auth.json.\n * Remote URLs are keyed by origin, local dev by project path.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface StoredCredential {\n\taccessToken: string;\n\trefreshToken: string;\n\texpiresAt: string;\n\turl?: string; // For local dev: the localhost URL\n\t/** Custom headers to send with every request (e.g. CF Access service token) */\n\tcustomHeaders?: Record<string, string>;\n\tuser?: {\n\t\temail: string;\n\t\trole: string;\n\t};\n}\n\n/** Credential for marketplace auth (GitHub OAuth JWT, no refresh token) */\nexport interface MarketplaceCredential {\n\ttoken: string;\n\texpiresAt: string;\n\tauthor?: {\n\t\tid: string;\n\t\tname: string;\n\t};\n}\n\ntype CredentialStore = Record<string, StoredCredential | MarketplaceCredential>;\n\n// ---------------------------------------------------------------------------\n// Paths\n// ---------------------------------------------------------------------------\n\nfunction getConfigDir(): string {\n\t// XDG_CONFIG_HOME or ~/.config\n\tconst xdg = process.env[\"XDG_CONFIG_HOME\"];\n\tif (xdg) return join(xdg, \"emdash\");\n\treturn join(homedir(), \".config\", \"emdash\");\n}\n\nfunction getCredentialPath(): string {\n\treturn join(getConfigDir(), \"auth.json\");\n}\n\n// ---------------------------------------------------------------------------\n// Key resolution\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the credential key for a given URL.\n *\n * Remote URLs are keyed by origin (e.g. \"https://my-site.pages.dev\").\n * Local dev instances are keyed by project path (e.g. \"path:/Users/matt/sites/blog\").\n */\nexport function resolveCredentialKey(baseUrl: string): string {\n\ttry {\n\t\tconst url = new URL(baseUrl);\n\t\tconst isLocal =\n\t\t\turl.hostname === \"localhost\" || url.hostname === \"127.0.0.1\" || url.hostname === \"[::1]\";\n\n\t\tif (isLocal) {\n\t\t\t// For local dev, key by project path\n\t\t\tconst projectPath = findProjectRoot(process.cwd());\n\t\t\tif (projectPath) {\n\t\t\t\treturn `path:${projectPath}`;\n\t\t\t}\n\t\t\t// Fallback to URL if no project root found\n\t\t\treturn url.origin;\n\t\t}\n\n\t\treturn url.origin;\n\t} catch {\n\t\treturn baseUrl;\n\t}\n}\n\n/**\n * Walk up from cwd to find the project root (directory containing astro.config.*).\n */\nfunction findProjectRoot(from: string): string | null {\n\tlet dir = resolve(from);\n\tconst root = resolve(\"/\");\n\n\twhile (dir !== root) {\n\t\tfor (const name of [\n\t\t\t\"astro.config.ts\",\n\t\t\t\"astro.config.mts\",\n\t\t\t\"astro.config.js\",\n\t\t\t\"astro.config.mjs\",\n\t\t]) {\n\t\t\tif (existsSync(join(dir, name))) {\n\t\t\t\treturn dir;\n\t\t\t}\n\t\t}\n\t\tconst parent = resolve(dir, \"..\");\n\t\tif (parent === dir) break;\n\t\tdir = parent;\n\t}\n\n\treturn null;\n}\n\n// ---------------------------------------------------------------------------\n// Read/write\n// ---------------------------------------------------------------------------\n\nfunction readStore(): CredentialStore {\n\tconst path = getCredentialPath();\n\ttry {\n\t\tif (existsSync(path)) {\n\t\t\tconst content = readFileSync(path, \"utf-8\");\n\t\t\treturn JSON.parse(content) as CredentialStore;\n\t\t}\n\t} catch {\n\t\t// Corrupt file — start fresh\n\t}\n\treturn {};\n}\n\nfunction writeStore(store: CredentialStore): void {\n\tconst dir = getConfigDir();\n\tmkdirSync(dir, { recursive: true });\n\n\tconst path = getCredentialPath();\n\twriteFileSync(path, JSON.stringify(store, null, \"\\t\"), {\n\t\tencoding: \"utf-8\",\n\t\tmode: 0o600, // Owner read/write only\n\t});\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Get stored credentials for a URL.\n */\nexport function getCredentials(baseUrl: string): StoredCredential | null {\n\tconst key = resolveCredentialKey(baseUrl);\n\tconst store = readStore();\n\tconst cred = store[key];\n\tif (!cred || !(\"accessToken\" in cred)) return null;\n\treturn cred;\n}\n\n/**\n * Save credentials for a URL.\n */\nexport function saveCredentials(baseUrl: string, cred: StoredCredential): void {\n\tconst key = resolveCredentialKey(baseUrl);\n\tconst store = readStore();\n\tstore[key] = cred;\n\twriteStore(store);\n}\n\n/**\n * Remove credentials for a URL.\n */\nexport function removeCredentials(baseUrl: string): boolean {\n\tconst key = resolveCredentialKey(baseUrl);\n\tconst store = readStore();\n\tif (key in store) {\n\t\tdelete store[key];\n\t\twriteStore(store);\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n/**\n * List all stored credential keys.\n */\nexport function listCredentialKeys(): string[] {\n\tconst store = readStore();\n\treturn Object.keys(store);\n}\n\n// ---------------------------------------------------------------------------\n// Marketplace credentials\n// ---------------------------------------------------------------------------\n\nfunction marketplaceKey(registryUrl: string): string {\n\ttry {\n\t\treturn `marketplace:${new URL(registryUrl).origin}`;\n\t} catch {\n\t\treturn `marketplace:${registryUrl}`;\n\t}\n}\n\n/**\n * Get stored marketplace credential for a registry URL.\n */\nexport function getMarketplaceCredential(registryUrl: string): MarketplaceCredential | null {\n\tconst key = marketplaceKey(registryUrl);\n\tconst store = readStore();\n\tconst cred = store[key];\n\tif (!cred || !(\"token\" in cred)) return null;\n\t// Check expiry\n\tif (new Date(cred.expiresAt) < new Date()) return null;\n\treturn cred;\n}\n\n/**\n * Save marketplace credential for a registry URL.\n */\nexport function saveMarketplaceCredential(registryUrl: string, cred: MarketplaceCredential): void {\n\tconst key = marketplaceKey(registryUrl);\n\tconst store = readStore();\n\tstore[key] = cred;\n\twriteStore(store);\n}\n\n/**\n * Remove marketplace credential for a registry URL.\n */\nexport function removeMarketplaceCredential(registryUrl: string): boolean {\n\tconst key = marketplaceKey(registryUrl);\n\tconst store = readStore();\n\tif (key in store) {\n\t\tdelete store[key];\n\t\twriteStore(store);\n\t\treturn true;\n\t}\n\treturn false;\n}\n","import { customHeadersInterceptor, resolveCustomHeaders } from \"../client/cf-access.js\";\nimport { EmDashClient } from \"../client/index.js\";\nimport type { Interceptor } from \"../client/transport.js\";\nimport { getCredentials, saveCredentials } from \"./credentials.js\";\n\nexport interface ClientArgs {\n\turl?: string;\n\ttoken?: string;\n}\n\n/**\n * Shared connection args for all CLI commands that talk to an EmDash instance.\n * Spread into each command's `args` definition.\n */\nexport const connectionArgs = {\n\turl: {\n\t\ttype: \"string\" as const,\n\t\talias: \"u\",\n\t\tdescription: \"EmDash instance URL\",\n\t\tdefault: \"http://localhost:4321\",\n\t},\n\ttoken: {\n\t\ttype: \"string\" as const,\n\t\talias: \"t\",\n\t\tdescription: \"Auth token\",\n\t},\n\theader: {\n\t\ttype: \"string\" as const,\n\t\talias: \"H\",\n\t\tdescription: 'Custom header \"Name: Value\" (repeatable, or use EMDASH_HEADERS env)',\n\t},\n\tjson: {\n\t\ttype: \"boolean\" as const,\n\t\tdescription: \"Output as JSON\",\n\t},\n};\n\n/**\n * Create an EmDashClient from CLI args, env vars, and stored credentials.\n *\n * Auth resolution order:\n * 1. --token flag\n * 2. EMDASH_TOKEN env var\n * 3. Stored credentials (~/.config/emdash/auth.json)\n * 4. Dev bypass (if URL is localhost)\n *\n * Custom headers are merged from (in priority order):\n * 1. Stored credentials (persisted during `emdash login --header`)\n * 2. EMDASH_HEADERS env var\n * 3. --header CLI flags\n */\nexport function createClientFromArgs(args: ClientArgs): EmDashClient {\n\tconst baseUrl = args.url || process.env[\"EMDASH_URL\"] || \"http://localhost:4321\";\n\tlet token = args.token || process.env[\"EMDASH_TOKEN\"];\n\n\tconst isLocal = baseUrl.includes(\"localhost\") || baseUrl.includes(\"127.0.0.1\");\n\tconst cred = !token ? getCredentials(baseUrl) : null;\n\n\t// Merge custom headers: stored credentials < env var < CLI flags\n\tconst customHeaders = {\n\t\t...cred?.customHeaders,\n\t\t...resolveCustomHeaders(),\n\t};\n\n\tconst extraInterceptors: Interceptor[] = [];\n\tif (Object.keys(customHeaders).length > 0) {\n\t\textraInterceptors.push(customHeadersInterceptor(customHeaders));\n\t}\n\n\t// Check stored credentials if no explicit token\n\tif (!token && cred) {\n\t\t// Check if access token is expired\n\t\tif (new Date(cred.expiresAt) > new Date()) {\n\t\t\ttoken = cred.accessToken;\n\t\t} else {\n\t\t\t// Token expired — use the refresh interceptor in the client\n\t\t\t// Pass the refresh token so the client can auto-refresh\n\t\t\treturn new EmDashClient({\n\t\t\t\tbaseUrl,\n\t\t\t\ttoken: cred.accessToken,\n\t\t\t\trefreshToken: cred.refreshToken,\n\t\t\t\tonTokenRefresh: (newAccessToken, expiresIn) => {\n\t\t\t\t\tsaveCredentials(baseUrl, {\n\t\t\t\t\t\t...cred,\n\t\t\t\t\t\taccessToken: newAccessToken,\n\t\t\t\t\t\texpiresAt: new Date(Date.now() + expiresIn * 1000).toISOString(),\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\tinterceptors: extraInterceptors,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn new EmDashClient({\n\t\tbaseUrl,\n\t\ttoken,\n\t\tdevBypass: !token && isLocal,\n\t\tinterceptors: extraInterceptors,\n\t});\n}\n","import { consola } from \"consola\";\n\ninterface OutputArgs {\n\tjson?: boolean;\n}\n\n/**\n * Output data as JSON or pretty-printed.\n *\n * If stdout is not a TTY or --json is set, outputs JSON.\n * Otherwise, outputs a formatted representation.\n */\nexport function output(data: unknown, args: OutputArgs): void {\n\tconst useJson = args.json || !process.stdout.isTTY;\n\n\tif (useJson) {\n\t\t// JSON output to stdout for piping\n\t\tprocess.stdout.write(JSON.stringify(data, null, 2) + \"\\n\");\n\t} else {\n\t\t// Pretty output via consola\n\t\tprettyPrint(data);\n\t}\n}\n\nfunction prettyPrint(data: unknown, indent: number = 0): void {\n\tif (data === null || data === undefined) {\n\t\tconsola.log(\"(empty)\");\n\t\treturn;\n\t}\n\n\tif (Array.isArray(data)) {\n\t\tif (data.length === 0) {\n\t\t\tconsola.log(\"(no items)\");\n\t\t\treturn;\n\t\t}\n\t\tfor (const item of data) {\n\t\t\tprettyPrint(item, indent);\n\t\t\tif (indent === 0) consola.log(\"---\");\n\t\t}\n\t\treturn;\n\t}\n\n\tif (typeof data === \"object\") {\n\t\tconst obj = Object(data) as Record<string, unknown>;\n\n\t\t// Check if it's a list result with items\n\t\tif (\"items\" in obj && Array.isArray(obj.items)) {\n\t\t\tprettyPrint(obj.items, indent);\n\t\t\tif (typeof obj.nextCursor === \"string\") {\n\t\t\t\tconsola.log(`\\nNext cursor: ${obj.nextCursor}`);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Print object fields\n\t\tconst prefix = \" \".repeat(indent);\n\t\tfor (const [key, value] of Object.entries(obj)) {\n\t\t\tif (value === null || value === undefined) continue;\n\t\t\tif (typeof value === \"object\" && !Array.isArray(value)) {\n\t\t\t\tconsola.log(`${prefix}${key}:`);\n\t\t\t\tprettyPrint(value, indent + 1);\n\t\t\t} else if (Array.isArray(value)) {\n\t\t\t\tconsola.log(`${prefix}${key}: [${value.length} items]`);\n\t\t\t} else {\n\t\t\t\tconst str = typeof value === \"string\" ? value : JSON.stringify(value);\n\t\t\t\t// Truncate long values\n\t\t\t\tconst display = str.length > 80 ? str.slice(0, 77) + \"...\" : str;\n\t\t\t\tconsola.log(`${prefix}${key}: ${display}`);\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\n\tconsola.log(typeof data === \"string\" ? data : JSON.stringify(data));\n}\n","/**\n * emdash content\n *\n * CRUD commands for managing content items via the EmDash REST API.\n */\n\nimport { readFile } from \"node:fs/promises\";\n\nimport { defineCommand } from \"citty\";\nimport { consola } from \"consola\";\n\nimport { connectionArgs, createClientFromArgs } from \"../client-factory.js\";\nimport { output } from \"../output.js\";\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Read content data from --data, --file, or --stdin */\nasync function readInputData(args: {\n\tdata?: string;\n\tfile?: string;\n\tstdin?: boolean;\n}): Promise<Record<string, unknown>> {\n\tif (args.data) {\n\t\ttry {\n\t\t\treturn JSON.parse(args.data) as Record<string, unknown>;\n\t\t} catch {\n\t\t\tthrow new Error(\"Invalid JSON in --data argument\");\n\t\t}\n\t}\n\n\tif (args.file) {\n\t\ttry {\n\t\t\tconst content = await readFile(args.file, \"utf-8\");\n\t\t\treturn JSON.parse(content) as Record<string, unknown>;\n\t\t} catch (error) {\n\t\t\tif (error instanceof SyntaxError) {\n\t\t\t\tthrow new Error(`Invalid JSON in file: ${args.file}`, { cause: error });\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tif (args.stdin) {\n\t\tconst chunks: Buffer[] = [];\n\t\tfor await (const chunk of process.stdin) {\n\t\t\tchunks.push(chunk as Buffer);\n\t\t}\n\t\tconst content = Buffer.concat(chunks).toString(\"utf-8\");\n\t\ttry {\n\t\t\treturn JSON.parse(content) as Record<string, unknown>;\n\t\t} catch {\n\t\t\tthrow new Error(\"Invalid JSON from stdin\");\n\t\t}\n\t}\n\n\tthrow new Error(\"Provide content data via --data, --file, or --stdin\");\n}\n\n// ---------------------------------------------------------------------------\n// Subcommands\n// ---------------------------------------------------------------------------\n\nconst listCommand = defineCommand({\n\tmeta: { name: \"list\", description: \"List content items\" },\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tstatus: { type: \"string\", description: \"Filter by status\" },\n\t\tlocale: { type: \"string\", description: \"Filter by locale\" },\n\t\tlimit: { type: \"string\", description: \"Maximum items to return\" },\n\t\tcursor: { type: \"string\", description: \"Pagination cursor\" },\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst result = await client.list(args.collection, {\n\t\t\t\tstatus: args.status,\n\t\t\t\tlocale: args.locale,\n\t\t\t\tlimit: args.limit ? parseInt(args.limit, 10) : undefined,\n\t\t\t\tcursor: args.cursor,\n\t\t\t});\n\t\t\t// Summarize items — strip heavy data fields for readable output\n\t\t\tconst summary = {\n\t\t\t\titems: result.items.map((item) => ({\n\t\t\t\t\tid: item.id,\n\t\t\t\t\tslug: item.slug,\n\t\t\t\t\tlocale: item.locale,\n\t\t\t\t\tstatus: item.status,\n\t\t\t\t\ttitle: typeof item.data?.title === \"string\" ? item.data.title : undefined,\n\t\t\t\t\tupdatedAt: item.updatedAt,\n\t\t\t\t})),\n\t\t\t\tnextCursor: result.nextCursor,\n\t\t\t};\n\t\t\toutput(summary, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst getCommand = defineCommand({\n\tmeta: { name: \"get\", description: \"Get a single content item\" },\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tid: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Content item ID or slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tlocale: { type: \"string\", description: \"Locale for slug resolution\" },\n\t\traw: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Return raw Portable Text (skip markdown conversion)\",\n\t\t},\n\t\tpublished: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Return published data only (ignore pending draft)\",\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst item = await client.get(args.collection, args.id, {\n\t\t\t\traw: args.raw,\n\t\t\t\tlocale: args.locale,\n\t\t\t});\n\n\t\t\t// If a draft exists, overlay draft data unless --published\n\t\t\tif (!args.published && item.draftRevisionId) {\n\t\t\t\tconst comparison = await client.compare(args.collection, args.id);\n\t\t\t\tif (comparison.hasChanges && comparison.draft) {\n\t\t\t\t\titem.data = comparison.draft;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\toutput(item, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst createCommand = defineCommand({\n\tmeta: { name: \"create\", description: \"Create a content item\" },\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tdata: { type: \"string\", description: \"Content data as JSON string\" },\n\t\tfile: { type: \"string\", description: \"Read content data from a JSON file\" },\n\t\tstdin: { type: \"boolean\", description: \"Read content data from stdin\" },\n\t\tslug: { type: \"string\", description: \"Content slug\" },\n\t\tlocale: { type: \"string\", description: \"Content locale\" },\n\t\t\"translation-of\": {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"ID of content item to link as translation\",\n\t\t},\n\t\tdraft: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Keep as draft instead of auto-publishing\",\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst data = await readInputData(args);\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst item = await client.create(args.collection, {\n\t\t\t\tdata,\n\t\t\t\tslug: args.slug,\n\t\t\t\tlocale: args.locale,\n\t\t\t\ttranslationOf: args[\"translation-of\"],\n\t\t\t});\n\n\t\t\t// Auto-publish unless --draft is set\n\t\t\tif (!args.draft) {\n\t\t\t\tawait client.publish(args.collection, item.id);\n\t\t\t}\n\n\t\t\t// Re-fetch to return the current state\n\t\t\tconst result = await client.get(args.collection, item.id);\n\t\t\toutput(result, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst updateCommand = defineCommand({\n\tmeta: { name: \"update\", description: \"Update a content item\" },\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tid: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Content item ID or slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tdata: { type: \"string\", description: \"Content data as JSON string\" },\n\t\tfile: { type: \"string\", description: \"Read content data from a JSON file\" },\n\t\trev: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Revision token from get (prevents overwriting unseen changes)\",\n\t\t\trequired: true,\n\t\t},\n\t\tdraft: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Keep as draft instead of auto-publishing\",\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst data = await readInputData(args);\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst updated = await client.update(args.collection, args.id, {\n\t\t\t\tdata,\n\t\t\t\t_rev: args.rev,\n\t\t\t});\n\n\t\t\t// Auto-publish unless --draft is set.\n\t\t\t// Only publish if the update created a draft revision (i.e. the\n\t\t\t// collection supports revisions and data went to a draft).\n\t\t\tif (!args.draft && updated.draftRevisionId) {\n\t\t\t\tawait client.publish(args.collection, args.id);\n\t\t\t}\n\n\t\t\t// Re-fetch to return the current state\n\t\t\tconst item = await client.get(args.collection, args.id);\n\t\t\toutput(item, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst deleteCommand = defineCommand({\n\tmeta: { name: \"delete\", description: \"Delete a content item\" },\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tid: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Content item ID or slug\",\n\t\t\trequired: true,\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tawait client.delete(args.collection, args.id);\n\t\t\tconsola.success(`Deleted ${args.collection}/${args.id}`);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst publishCommand = defineCommand({\n\tmeta: { name: \"publish\", description: \"Publish a content item\" },\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tid: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Content item ID or slug\",\n\t\t\trequired: true,\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tawait client.publish(args.collection, args.id);\n\t\t\tconsola.success(`Published ${args.collection}/${args.id}`);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst unpublishCommand = defineCommand({\n\tmeta: { name: \"unpublish\", description: \"Unpublish a content item\" },\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tid: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Content item ID or slug\",\n\t\t\trequired: true,\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tawait client.unpublish(args.collection, args.id);\n\t\t\tconsola.success(`Unpublished ${args.collection}/${args.id}`);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst scheduleCommand = defineCommand({\n\tmeta: { name: \"schedule\", description: \"Schedule content for publishing\" },\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tid: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Content item ID or slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tat: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"ISO 8601 datetime to publish at\",\n\t\t\trequired: true,\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tawait client.schedule(args.collection, args.id, { at: args.at });\n\t\t\tconsola.success(`Scheduled ${args.collection}/${args.id} for ${args.at}`);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst restoreCommand = defineCommand({\n\tmeta: { name: \"restore\", description: \"Restore a trashed content item\" },\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tid: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Content item ID or slug\",\n\t\t\trequired: true,\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tawait client.restore(args.collection, args.id);\n\t\t\tconsola.success(`Restored ${args.collection}/${args.id}`);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst translationsCommand = defineCommand({\n\tmeta: { name: \"translations\", description: \"List translations for a content item\" },\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tid: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Content item ID or slug\",\n\t\t\trequired: true,\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst translations = await client.translations(args.collection, args.id);\n\t\t\toutput(translations, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\n// ---------------------------------------------------------------------------\n// Export\n// ---------------------------------------------------------------------------\n\nexport const contentCommand = defineCommand({\n\tmeta: { name: \"content\", description: \"Manage content\" },\n\tsubCommands: {\n\t\tlist: listCommand,\n\t\tget: getCommand,\n\t\tcreate: createCommand,\n\t\tupdate: updateCommand,\n\t\tdelete: deleteCommand,\n\t\tpublish: publishCommand,\n\t\tunpublish: unpublishCommand,\n\t\tschedule: scheduleCommand,\n\t\trestore: restoreCommand,\n\t\ttranslations: translationsCommand,\n\t},\n});\n","/**\n * emdash dev\n *\n * Start development server with optional schema sync from remote\n */\n\nimport { spawn } from \"node:child_process\";\nimport { readFile, access } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\n\nimport { defineCommand } from \"citty\";\nimport consola from \"consola\";\n\nimport { createDatabase } from \"../../database/connection.js\";\nimport { runMigrations } from \"../../database/migrations/runner.js\";\n\ninterface PackageJson {\n\tname?: string;\n\tscripts?: Record<string, string>;\n\temdash?: {\n\t\turl?: string;\n\t\tdatabase?: string;\n\t};\n}\n\nasync function readPackageJson(cwd: string): Promise<PackageJson | null> {\n\tconst pkgPath = resolve(cwd, \"package.json\");\n\ttry {\n\t\tconst content = await readFile(pkgPath, \"utf-8\");\n\t\treturn JSON.parse(content);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nasync function fileExists(path: string): Promise<boolean> {\n\ttry {\n\t\tawait access(path);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nexport const devCommand = defineCommand({\n\tmeta: {\n\t\tname: \"dev\",\n\t\tdescription: \"Start dev server with local database\",\n\t},\n\targs: {\n\t\tdatabase: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"d\",\n\t\t\tdescription: \"Database path (default: ./data.db)\",\n\t\t\tdefault: \"./data.db\",\n\t\t},\n\t\ttypes: {\n\t\t\ttype: \"boolean\",\n\t\t\talias: \"t\",\n\t\t\tdescription: \"Generate types from remote before starting\",\n\t\t\tdefault: false,\n\t\t},\n\t\tport: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"p\",\n\t\t\tdescription: \"Port for dev server\",\n\t\t\tdefault: \"4321\",\n\t\t},\n\t\tcwd: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Working directory\",\n\t\t\tdefault: process.cwd(),\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst cwd = resolve(args.cwd);\n\t\tconst pkg = await readPackageJson(cwd);\n\n\t\tif (!pkg) {\n\t\t\tconsola.error(\"No package.json found\");\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tconst dbPath = resolve(cwd, args.database);\n\n\t\t// Run migrations if database doesn't exist\n\t\tconst dbExists = await fileExists(dbPath);\n\t\tif (!dbExists) {\n\t\t\tconsola.start(\"Database not found, initializing...\");\n\t\t}\n\n\t\t// Always run migrations (they're idempotent)\n\t\tconst db = createDatabase({ url: `file:${dbPath}` });\n\t\ttry {\n\t\t\tconsola.start(\"Checking database migrations...\");\n\t\t\tconst { applied } = await runMigrations(db);\n\t\t\tif (applied.length > 0) {\n\t\t\t\tconsola.success(`Applied ${applied.length} migrations`);\n\t\t\t} else {\n\t\t\t\tconsola.info(\"Database up to date\");\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsola.error(\"Migration failed:\", error);\n\t\t\tawait db.destroy();\n\t\t\tprocess.exit(1);\n\t\t}\n\t\tawait db.destroy();\n\n\t\t// Generate types from remote if requested\n\t\tif (args.types) {\n\t\t\tconst remoteUrl = pkg.emdash?.url || process.env.EMDASH_URL;\n\n\t\t\tif (!remoteUrl) {\n\t\t\t\tconsola.warn(\"No remote URL configured. Set EMDASH_URL or emdash.url in package.json\");\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tconst { createClientFromArgs } = await import(\"../client-factory.js\");\n\t\t\t\t\tconst client = createClientFromArgs({ url: remoteUrl });\n\t\t\t\t\tconst schema = await client.schemaExport();\n\t\t\t\t\tconst types = await client.schemaTypes();\n\n\t\t\t\t\tconst { writeFile, mkdir } = await import(\"node:fs/promises\");\n\t\t\t\t\tconst { resolve: resolvePath, dirname } = await import(\"node:path\");\n\t\t\t\t\tconst outputPath = resolvePath(cwd, \".emdash/types.ts\");\n\t\t\t\t\tawait mkdir(dirname(outputPath), { recursive: true });\n\t\t\t\t\tawait writeFile(outputPath, types, \"utf-8\");\n\t\t\t\t\tawait writeFile(\n\t\t\t\t\t\tresolvePath(dirname(outputPath), \"schema.json\"),\n\t\t\t\t\t\tJSON.stringify(schema, null, 2),\n\t\t\t\t\t\t\"utf-8\",\n\t\t\t\t\t);\n\t\t\t\t\tconsola.success(`Generated types for ${schema.collections.length} collections`);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsola.warn(\"Type generation failed:\", error instanceof Error ? error.message : error);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Start Astro dev server\n\t\tconsola.start(\"Starting Astro dev server...\");\n\n\t\tconst astroArgs = [\"astro\", \"dev\", \"--port\", args.port];\n\n\t\t// Check if using pnpm, npm, or yarn\n\t\tconst pnpmLockExists = await fileExists(resolve(cwd, \"pnpm-lock.yaml\"));\n\t\tconst yarnLockExists = await fileExists(resolve(cwd, \"yarn.lock\"));\n\n\t\tlet cmd: string;\n\t\tlet cmdArgs: string[];\n\n\t\tif (pnpmLockExists) {\n\t\t\tcmd = \"pnpm\";\n\t\t\tcmdArgs = astroArgs;\n\t\t} else if (yarnLockExists) {\n\t\t\tcmd = \"yarn\";\n\t\t\tcmdArgs = astroArgs;\n\t\t} else {\n\t\t\tcmd = \"npx\";\n\t\t\tcmdArgs = astroArgs;\n\t\t}\n\n\t\tconsola.info(`Running: ${cmd} ${cmdArgs.join(\" \")}`);\n\n\t\tconst child = spawn(cmd, cmdArgs, {\n\t\t\tcwd,\n\t\t\tstdio: \"inherit\",\n\t\t\tenv: {\n\t\t\t\t...process.env,\n\t\t\t\t// Pass database path to Astro\n\t\t\t\tEMDASH_DATABASE_URL: `file:${dbPath}`,\n\t\t\t},\n\t\t});\n\n\t\tchild.on(\"error\", (error) => {\n\t\t\tconsola.error(\"Failed to start dev server:\", error);\n\t\t\tprocess.exit(1);\n\t\t});\n\n\t\tchild.on(\"exit\", (code) => {\n\t\t\tprocess.exit(code ?? 0);\n\t\t});\n\n\t\t// Handle termination signals\n\t\tconst cleanup = () => {\n\t\t\tchild.kill(\"SIGTERM\");\n\t\t};\n\n\t\tprocess.on(\"SIGINT\", cleanup);\n\t\tprocess.on(\"SIGTERM\", cleanup);\n\t},\n});\n","/**\n * emdash doctor\n *\n * Diagnose database health: connection, migrations, schema integrity.\n */\n\nimport { access } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\n\nimport { defineCommand } from \"citty\";\nimport consola from \"consola\";\n\nimport { createDatabase } from \"../../database/connection.js\";\nimport { listTablesLike } from \"../../database/dialect-helpers.js\";\nimport { getMigrationStatus } from \"../../database/migrations/runner.js\";\n\ninterface CheckResult {\n\tname: string;\n\tstatus: \"pass\" | \"warn\" | \"fail\";\n\tmessage: string;\n}\n\nasync function fileExists(path: string): Promise<boolean> {\n\ttry {\n\t\tawait access(path);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction printResult(result: CheckResult): void {\n\tconst color =\n\t\tresult.status === \"pass\"\n\t\t\t? consola.success\n\t\t\t: result.status === \"warn\"\n\t\t\t\t? consola.warn\n\t\t\t\t: consola.error;\n\tcolor(`${result.name}: ${result.message}`);\n}\n\nasync function checkDatabase(dbPath: string): Promise<CheckResult[]> {\n\tconst results: CheckResult[] = [];\n\n\t// Check database file exists\n\tif (!(await fileExists(dbPath))) {\n\t\tresults.push({\n\t\t\tname: \"database\",\n\t\t\tstatus: \"fail\",\n\t\t\tmessage: `not found at ${dbPath} — run \"emdash init\"`,\n\t\t});\n\t\treturn results;\n\t}\n\n\tresults.push({\n\t\tname: \"database\",\n\t\tstatus: \"pass\",\n\t\tmessage: dbPath,\n\t});\n\n\t// Connect and check migrations\n\tlet db;\n\ttry {\n\t\tdb = createDatabase({ url: `file:${dbPath}` });\n\n\t\tconst { applied, pending } = await getMigrationStatus(db);\n\t\tif (pending.length === 0) {\n\t\t\tresults.push({\n\t\t\t\tname: \"migrations\",\n\t\t\t\tstatus: \"pass\",\n\t\t\t\tmessage: `${applied.length} applied, none pending`,\n\t\t\t});\n\t\t} else {\n\t\t\tresults.push({\n\t\t\t\tname: \"migrations\",\n\t\t\t\tstatus: \"warn\",\n\t\t\t\tmessage: `${applied.length} applied, ${pending.length} pending — run \"emdash init\"`,\n\t\t\t});\n\t\t}\n\n\t\tconst { sql } = await import(\"kysely\");\n\n\t\t// Check collections exist\n\t\ttry {\n\t\t\tconst collectionsResult = await sql<{\n\t\t\t\tcount: number;\n\t\t\t}>`SELECT COUNT(id) as count FROM _emdash_collections`.execute(db);\n\t\t\tconst count = collectionsResult.rows[0]?.count ?? 0;\n\t\t\tresults.push({\n\t\t\t\tname: \"collections\",\n\t\t\t\tstatus: count > 0 ? \"pass\" : \"warn\",\n\t\t\t\tmessage:\n\t\t\t\t\tcount > 0 ? `${count} collections defined` : \"no collections — seed or create via admin\",\n\t\t\t});\n\t\t} catch {\n\t\t\tresults.push({\n\t\t\t\tname: \"collections\",\n\t\t\t\tstatus: \"fail\",\n\t\t\t\tmessage: \"could not query collections table — migrations may not have run\",\n\t\t\t});\n\t\t}\n\n\t\t// Check for orphaned ec_ tables without matching collection records\n\t\ttry {\n\t\t\tconst tableNames = await listTablesLike(db, \"ec_%\");\n\t\t\tconst collectionsResult = await sql<{\n\t\t\t\tslug: string;\n\t\t\t}>`SELECT slug FROM _emdash_collections`.execute(db);\n\t\t\tconst registeredSlugs = new Set(collectionsResult.rows.map((r) => `ec_${r.slug}`));\n\t\t\tconst orphaned = tableNames.filter((name) => !registeredSlugs.has(name));\n\n\t\t\tif (orphaned.length > 0) {\n\t\t\t\tresults.push({\n\t\t\t\t\tname: \"orphaned tables\",\n\t\t\t\t\tstatus: \"warn\",\n\t\t\t\t\tmessage: `found ${orphaned.length}: ${orphaned.join(\", \")}`,\n\t\t\t\t});\n\t\t\t}\n\t\t} catch {\n\t\t\t// Non-critical — tables may not exist on fresh DB\n\t\t}\n\n\t\t// Check users exist\n\t\ttry {\n\t\t\tconst usersResult = await sql<{\n\t\t\t\tcount: number;\n\t\t\t}>`SELECT COUNT(id) as count FROM _emdash_users`.execute(db);\n\t\t\tconst count = usersResult.rows[0]?.count ?? 0;\n\t\t\tresults.push({\n\t\t\t\tname: \"users\",\n\t\t\t\tstatus: count > 0 ? \"pass\" : \"warn\",\n\t\t\t\tmessage:\n\t\t\t\t\tcount > 0 ? `${count} users` : \"no users — complete setup wizard at /_emdash/admin\",\n\t\t\t});\n\t\t} catch {\n\t\t\tresults.push({\n\t\t\t\tname: \"users\",\n\t\t\t\tstatus: \"warn\",\n\t\t\t\tmessage: \"could not query users table\",\n\t\t\t});\n\t\t}\n\t} catch (error) {\n\t\tresults.push({\n\t\t\tname: \"database connection\",\n\t\t\tstatus: \"fail\",\n\t\t\tmessage: error instanceof Error ? error.message : \"failed to connect\",\n\t\t});\n\t} finally {\n\t\tif (db) {\n\t\t\tawait db.destroy();\n\t\t}\n\t}\n\n\treturn results;\n}\n\nexport const doctorCommand = defineCommand({\n\tmeta: {\n\t\tname: \"doctor\",\n\t\tdescription: \"Check database health and diagnose issues\",\n\t},\n\targs: {\n\t\tdatabase: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"d\",\n\t\t\tdescription: \"Database path (default: ./data.db)\",\n\t\t\tdefault: \"./data.db\",\n\t\t},\n\t\tcwd: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Working directory\",\n\t\t\tdefault: process.cwd(),\n\t\t},\n\t\tjson: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Output results as JSON\",\n\t\t\tdefault: false,\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst cwd = resolve(args.cwd);\n\t\tconst dbPath = resolve(cwd, args.database);\n\n\t\tconst results = await checkDatabase(dbPath);\n\n\t\tif (args.json) {\n\t\t\tprocess.stdout.write(JSON.stringify(results, null, 2) + \"\\n\");\n\t\t\treturn;\n\t\t}\n\n\t\tconsola.start(\"EmDash Doctor\\n\");\n\n\t\tfor (const result of results) {\n\t\t\tprintResult(result);\n\t\t}\n\n\t\t// Summary\n\t\tconst fails = results.filter((r) => r.status === \"fail\");\n\t\tconst warns = results.filter((r) => r.status === \"warn\");\n\n\t\tconsola.log(\"\");\n\t\tif (fails.length === 0 && warns.length === 0) {\n\t\t\tconsola.success(\"All checks passed\");\n\t\t} else if (fails.length === 0) {\n\t\t\tconsola.info(`All critical checks passed (${warns.length} warnings)`);\n\t\t} else {\n\t\t\tconsola.error(`${fails.length} issues found`);\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\t},\n});\n","/**\n * emdash export-seed\n *\n * Export current database schema (and optionally content) as a seed file\n */\n\nimport { resolve } from \"node:path\";\n\nimport { defineCommand } from \"citty\";\nimport consola from \"consola\";\nimport type { Kysely } from \"kysely\";\n\nimport { createDatabase } from \"../../database/connection.js\";\nimport { runMigrations } from \"../../database/migrations/runner.js\";\nimport { ContentRepository } from \"../../database/repositories/content.js\";\nimport { MediaRepository } from \"../../database/repositories/media.js\";\nimport { OptionsRepository } from \"../../database/repositories/options.js\";\nimport { TaxonomyRepository } from \"../../database/repositories/taxonomy.js\";\nimport type { Database } from \"../../database/types.js\";\nimport { isI18nEnabled } from \"../../i18n/config.js\";\nimport { SchemaRegistry } from \"../../schema/registry.js\";\nimport type { FieldType } from \"../../schema/types.js\";\nimport type {\n\tSeedFile,\n\tSeedCollection,\n\tSeedField,\n\tSeedTaxonomy,\n\tSeedTaxonomyTerm,\n\tSeedMenu,\n\tSeedMenuItem,\n\tSeedWidgetArea,\n\tSeedWidget,\n\tSeedContentEntry,\n} from \"../../seed/types.js\";\n\nconst SETTINGS_PREFIX = \"site:\";\n\nexport const exportSeedCommand = defineCommand({\n\tmeta: {\n\t\tname: \"export-seed\",\n\t\tdescription: \"Export database schema and content as a seed file\",\n\t},\n\targs: {\n\t\tdatabase: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"d\",\n\t\t\tdescription: \"Database path\",\n\t\t\tdefault: \"./data.db\",\n\t\t},\n\t\tcwd: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Working directory\",\n\t\t\tdefault: process.cwd(),\n\t\t},\n\t\t\"with-content\": {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Include content (all or comma-separated collection names)\",\n\t\t\trequired: false,\n\t\t},\n\t\tpretty: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Pretty print JSON output\",\n\t\t\tdefault: true,\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst cwd = resolve(args.cwd);\n\n\t\t// Connect to database\n\t\tconst dbPath = resolve(cwd, args.database);\n\t\tconsola.info(`Database: ${dbPath}`);\n\n\t\tconst db = createDatabase({ url: `file:${dbPath}` });\n\n\t\t// Run migrations to ensure tables exist\n\t\ttry {\n\t\t\tawait runMigrations(db);\n\t\t} catch (error) {\n\t\t\tconsola.error(\"Migration failed:\", error);\n\t\t\tawait db.destroy();\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\ttry {\n\t\t\tconst seed = await exportSeed(db, args[\"with-content\"]);\n\n\t\t\t// Output to stdout\n\t\t\tconst output = args.pretty ? JSON.stringify(seed, null, \"\\t\") : JSON.stringify(seed);\n\n\t\t\tconsole.log(output);\n\t\t} catch (error) {\n\t\t\tconsola.error(\"Export failed:\", error);\n\t\t\tawait db.destroy();\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tawait db.destroy();\n\t},\n});\n\n/**\n * Export database to seed file format\n */\nasync function exportSeed(db: Kysely<Database>, withContent?: string): Promise<SeedFile> {\n\tconst seed: SeedFile = {\n\t\t$schema: \"https://emdashcms.com/seed.schema.json\",\n\t\tversion: \"1\",\n\t\tmeta: {\n\t\t\tname: \"Exported Seed\",\n\t\t\tdescription: \"Exported from existing EmDash database\",\n\t\t},\n\t};\n\n\t// 1. Export settings\n\tseed.settings = await exportSettings(db);\n\n\t// 2. Export collections and fields\n\tseed.collections = await exportCollections(db);\n\n\t// 3. Export taxonomy definitions and terms\n\tseed.taxonomies = await exportTaxonomies(db);\n\n\t// 4. Export menus\n\tseed.menus = await exportMenus(db);\n\n\t// 5. Export widget areas\n\tseed.widgetAreas = await exportWidgetAreas(db);\n\n\t// 6. Export content (if requested)\n\tif (withContent !== undefined) {\n\t\tconst collections =\n\t\t\twithContent === \"\" || withContent === \"true\"\n\t\t\t\t? null // all collections\n\t\t\t\t: withContent\n\t\t\t\t\t\t.split(\",\")\n\t\t\t\t\t\t.map((s) => s.trim())\n\t\t\t\t\t\t.filter(Boolean);\n\n\t\tseed.content = await exportContent(db, seed.collections || [], collections);\n\t}\n\n\treturn seed;\n}\n\n/**\n * Export site settings\n */\nasync function exportSettings(db: Kysely<Database>): Promise<SeedFile[\"settings\"]> {\n\tconst options = new OptionsRepository(db);\n\tconst allOptions = await options.getByPrefix(SETTINGS_PREFIX);\n\n\tconst settings: Record<string, unknown> = {};\n\tfor (const [key, value] of allOptions) {\n\t\tconst settingKey = key.replace(SETTINGS_PREFIX, \"\");\n\t\tsettings[settingKey] = value;\n\t}\n\n\treturn Object.keys(settings).length > 0 ? settings : undefined;\n}\n\n/**\n * Export collections and their fields\n */\nasync function exportCollections(db: Kysely<Database>): Promise<SeedCollection[]> {\n\tconst registry = new SchemaRegistry(db);\n\tconst collections = await registry.listCollections();\n\tconst result: SeedCollection[] = [];\n\n\tfor (const collection of collections) {\n\t\tconst fields = await registry.listFields(collection.id);\n\n\t\tconst seedCollection: SeedCollection = {\n\t\t\tslug: collection.slug,\n\t\t\tlabel: collection.label,\n\t\t\tlabelSingular: collection.labelSingular || undefined,\n\t\t\tdescription: collection.description || undefined,\n\t\t\ticon: collection.icon || undefined,\n\t\t\tsupports:\n\t\t\t\tcollection.supports.length > 0\n\t\t\t\t\t? (collection.supports as (\n\t\t\t\t\t\t\t| \"drafts\"\n\t\t\t\t\t\t\t| \"revisions\"\n\t\t\t\t\t\t\t| \"preview\"\n\t\t\t\t\t\t\t| \"scheduling\"\n\t\t\t\t\t\t\t| \"search\"\n\t\t\t\t\t\t)[])\n\t\t\t\t\t: undefined,\n\t\t\turlPattern: collection.urlPattern || undefined,\n\t\t\tfields: fields.map(\n\t\t\t\t(field): SeedField => ({\n\t\t\t\t\tslug: field.slug,\n\t\t\t\t\tlabel: field.label,\n\t\t\t\t\ttype: field.type,\n\t\t\t\t\trequired: field.required || undefined,\n\t\t\t\t\tunique: field.unique || undefined,\n\t\t\t\t\tsearchable: field.searchable || undefined,\n\t\t\t\t\tdefaultValue: field.defaultValue,\n\t\t\t\t\tvalidation: field.validation ? { ...field.validation } : undefined,\n\t\t\t\t\twidget: field.widget || undefined,\n\t\t\t\t\toptions: field.options || undefined,\n\t\t\t\t}),\n\t\t\t),\n\t\t};\n\n\t\tresult.push(seedCollection);\n\t}\n\n\treturn result;\n}\n\n/**\n * Export taxonomy definitions and terms\n */\nasync function exportTaxonomies(db: Kysely<Database>): Promise<SeedTaxonomy[]> {\n\t// Get taxonomy definitions\n\tconst defs = await db.selectFrom(\"_emdash_taxonomy_defs\").selectAll().execute();\n\n\tconst result: SeedTaxonomy[] = [];\n\tconst termRepo = new TaxonomyRepository(db);\n\n\tfor (const def of defs) {\n\t\t// Get terms for this taxonomy\n\t\tconst terms = await termRepo.findByName(def.name);\n\n\t\t// Build term tree for hierarchical taxonomies\n\t\tconst seedTerms: SeedTaxonomyTerm[] = [];\n\n\t\t// First, create a map of id -> slug for parent resolution\n\t\tconst idToSlug = new Map<string, string>();\n\t\tfor (const term of terms) {\n\t\t\tidToSlug.set(term.id, term.slug);\n\t\t}\n\n\t\tfor (const term of terms) {\n\t\t\tconst seedTerm: SeedTaxonomyTerm = {\n\t\t\t\tslug: term.slug,\n\t\t\t\tlabel: term.label,\n\t\t\t\tdescription: typeof term.data?.description === \"string\" ? term.data.description : undefined,\n\t\t\t};\n\n\t\t\t// Resolve parent slug\n\t\t\tif (term.parentId) {\n\t\t\t\tseedTerm.parent = idToSlug.get(term.parentId);\n\t\t\t}\n\n\t\t\tseedTerms.push(seedTerm);\n\t\t}\n\n\t\tconst taxonomy: SeedTaxonomy = {\n\t\t\tname: def.name,\n\t\t\tlabel: def.label,\n\t\t\tlabelSingular: def.label_singular || undefined,\n\t\t\thierarchical: def.hierarchical === 1,\n\t\t\tcollections: def.collections ? JSON.parse(def.collections) : [],\n\t\t};\n\n\t\tif (seedTerms.length > 0) {\n\t\t\ttaxonomy.terms = seedTerms;\n\t\t}\n\n\t\tresult.push(taxonomy);\n\t}\n\n\treturn result;\n}\n\n/**\n * Export menus with their items\n */\nasync function exportMenus(db: Kysely<Database>): Promise<SeedMenu[]> {\n\t// Get all menus\n\tconst menus = await db.selectFrom(\"_emdash_menus\").selectAll().execute();\n\n\tconst result: SeedMenu[] = [];\n\n\tfor (const menu of menus) {\n\t\t// Get menu items\n\t\tconst items = await db\n\t\t\t.selectFrom(\"_emdash_menu_items\")\n\t\t\t.selectAll()\n\t\t\t.where(\"menu_id\", \"=\", menu.id)\n\t\t\t.orderBy(\"sort_order\", \"asc\")\n\t\t\t.execute();\n\n\t\t// Build item tree\n\t\tconst seedItems = buildMenuItemTree(items);\n\n\t\tresult.push({\n\t\t\tname: menu.name,\n\t\t\tlabel: menu.label,\n\t\t\titems: seedItems,\n\t\t});\n\t}\n\n\treturn result;\n}\n\n/** Type guard for valid widget types */\nfunction isWidgetType(t: string): t is SeedWidget[\"type\"] {\n\treturn t === \"content\" || t === \"menu\" || t === \"component\";\n}\n\n/**\n * Build hierarchical menu item tree from flat array\n */\nfunction buildMenuItemTree(\n\titems: Array<{\n\t\tid: string;\n\t\tparent_id: string | null;\n\t\ttype: string;\n\t\tlabel: string;\n\t\tcustom_url: string | null;\n\t\treference_collection: string | null;\n\t\treference_id: string | null;\n\t\ttarget: string | null;\n\t\ttitle_attr: string | null;\n\t\tcss_classes: string | null;\n\t}>,\n): SeedMenuItem[] {\n\t// Build parent -> children map\n\tconst childMap = new Map<string | null, typeof items>();\n\n\tfor (const item of items) {\n\t\tconst parentId = item.parent_id;\n\t\tif (!childMap.has(parentId)) {\n\t\t\tchildMap.set(parentId, []);\n\t\t}\n\t\tchildMap.get(parentId)!.push(item);\n\t}\n\n\t// Recursively build tree\n\tfunction buildLevel(parentId: string | null): SeedMenuItem[] {\n\t\tconst children = childMap.get(parentId) || [];\n\t\treturn children.map((item) => {\n\t\t\tconst seedItem: SeedMenuItem = {\n\t\t\t\ttype: item.type,\n\t\t\t\tlabel: item.label || undefined,\n\t\t\t};\n\n\t\t\tif (item.type === \"custom\") {\n\t\t\t\tseedItem.url = item.custom_url || undefined;\n\t\t\t} else {\n\t\t\t\tseedItem.ref = item.reference_id || undefined;\n\t\t\t\tseedItem.collection = item.reference_collection || undefined;\n\t\t\t}\n\n\t\t\tif (item.target === \"_blank\") {\n\t\t\t\tseedItem.target = \"_blank\";\n\t\t\t}\n\t\t\tif (item.title_attr) {\n\t\t\t\tseedItem.titleAttr = item.title_attr;\n\t\t\t}\n\t\t\tif (item.css_classes) {\n\t\t\t\tseedItem.cssClasses = item.css_classes;\n\t\t\t}\n\n\t\t\t// Add children\n\t\t\tconst itemChildren = buildLevel(item.id);\n\t\t\tif (itemChildren.length > 0) {\n\t\t\t\tseedItem.children = itemChildren;\n\t\t\t}\n\n\t\t\treturn seedItem;\n\t\t});\n\t}\n\n\treturn buildLevel(null);\n}\n\n/**\n * Export widget areas with their widgets\n */\nasync function exportWidgetAreas(db: Kysely<Database>): Promise<SeedWidgetArea[]> {\n\t// Get all widget areas\n\tconst areas = await db.selectFrom(\"_emdash_widget_areas\").selectAll().execute();\n\n\tconst result: SeedWidgetArea[] = [];\n\n\tfor (const area of areas) {\n\t\t// Get widgets for this area\n\t\tconst widgets = await db\n\t\t\t.selectFrom(\"_emdash_widgets\")\n\t\t\t.selectAll()\n\t\t\t.where(\"area_id\", \"=\", area.id)\n\t\t\t.orderBy(\"sort_order\", \"asc\")\n\t\t\t.execute();\n\n\t\tconst seedWidgets: SeedWidget[] = widgets\n\t\t\t.filter((w) => isWidgetType(w.type))\n\t\t\t.map((widget) => {\n\t\t\t\tconst wType: SeedWidget[\"type\"] = isWidgetType(widget.type) ? widget.type : \"content\";\n\t\t\t\tconst seedWidget: SeedWidget = {\n\t\t\t\t\ttype: wType,\n\t\t\t\t};\n\n\t\t\t\tif (widget.title) {\n\t\t\t\t\tseedWidget.title = widget.title;\n\t\t\t\t}\n\n\t\t\t\tif (widget.type === \"content\" && widget.content) {\n\t\t\t\t\tseedWidget.content = JSON.parse(widget.content);\n\t\t\t\t} else if (widget.type === \"menu\" && widget.menu_name) {\n\t\t\t\t\tseedWidget.menuName = widget.menu_name;\n\t\t\t\t} else if (widget.type === \"component\") {\n\t\t\t\t\tif (widget.component_id) {\n\t\t\t\t\t\tseedWidget.componentId = widget.component_id;\n\t\t\t\t\t}\n\t\t\t\t\tif (widget.component_props) {\n\t\t\t\t\t\tseedWidget.props = JSON.parse(widget.component_props);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn seedWidget;\n\t\t\t});\n\n\t\tresult.push({\n\t\t\tname: area.name,\n\t\t\tlabel: area.label,\n\t\t\tdescription: area.description || undefined,\n\t\t\twidgets: seedWidgets,\n\t\t});\n\t}\n\n\treturn result;\n}\n\n/**\n * Export content from collections\n */\nasync function exportContent(\n\tdb: Kysely<Database>,\n\tcollections: SeedCollection[],\n\tincludeCollections: string[] | null,\n): Promise<Record<string, SeedContentEntry[]>> {\n\tconst content: Record<string, SeedContentEntry[]> = {};\n\tconst contentRepo = new ContentRepository(db);\n\tconst taxonomyRepo = new TaxonomyRepository(db);\n\tconst mediaRepo = new MediaRepository(db);\n\n\t// Build media id -> info map for $media conversion\n\tconst mediaMap = new Map<\n\t\tstring,\n\t\t{ url: string; filename: string; alt?: string; caption?: string }\n\t>();\n\ttry {\n\t\tlet cursor: string | undefined;\n\t\tdo {\n\t\t\tconst result = await mediaRepo.findMany({\n\t\t\t\tlimit: 100,\n\t\t\t\tcursor,\n\t\t\t\tstatus: \"all\",\n\t\t\t});\n\t\t\tfor (const media of result.items) {\n\t\t\t\tmediaMap.set(media.id, {\n\t\t\t\t\turl: `/_emdash/api/media/file/${media.storageKey}`,\n\t\t\t\t\tfilename: media.filename,\n\t\t\t\t\talt: media.alt || undefined,\n\t\t\t\t\tcaption: media.caption || undefined,\n\t\t\t\t});\n\t\t\t}\n\t\t\tcursor = result.nextCursor;\n\t\t} while (cursor);\n\t} catch {\n\t\t// Media table might not exist or be empty\n\t}\n\n\tconst i18nEnabled = isI18nEnabled();\n\n\tfor (const collection of collections) {\n\t\t// Skip if not in include list\n\t\tif (includeCollections && !includeCollections.includes(collection.slug)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst entries: SeedContentEntry[] = [];\n\t\tlet cursor: string | undefined;\n\n\t\t// When i18n is enabled, track translation_group -> seed ID so that\n\t\t// translations can reference the source entry's seed-local ID.\n\t\t// Key: EmDash translation_group ULID, Value: seed-local ID of the first entry in that group\n\t\tconst translationGroupToSeedId = new Map<string, string>();\n\n\t\t// Paginate through all entries\n\t\tdo {\n\t\t\tconst result = await contentRepo.findMany(collection.slug, {\n\t\t\t\tlimit: 100,\n\t\t\t\tcursor,\n\t\t\t});\n\n\t\t\tfor (const item of result.items) {\n\t\t\t\t// Generate seed ID from collection:slug:locale for stable references\n\t\t\t\tconst seedId = item.slug\n\t\t\t\t\t? i18nEnabled && item.locale\n\t\t\t\t\t\t? `${collection.slug}:${item.slug}:${item.locale}`\n\t\t\t\t\t\t: `${collection.slug}:${item.slug}`\n\t\t\t\t\t: item.id;\n\n\t\t\t\t// Process data fields for $media conversion\n\t\t\t\tconst processedData = processDataForExport(item.data, collection.fields, mediaMap);\n\n\t\t\t\tconst entry: SeedContentEntry = {\n\t\t\t\t\tid: seedId,\n\t\t\t\t\tslug: item.slug || item.id,\n\t\t\t\t\tstatus: item.status === \"published\" || item.status === \"draft\" ? item.status : undefined,\n\t\t\t\t\tdata: processedData,\n\t\t\t\t};\n\n\t\t\t\t// Add i18n fields when enabled\n\t\t\t\tif (i18nEnabled && item.locale) {\n\t\t\t\t\tentry.locale = item.locale;\n\n\t\t\t\t\tif (item.translationGroup) {\n\t\t\t\t\t\tconst sourceSeedId = translationGroupToSeedId.get(item.translationGroup);\n\t\t\t\t\t\tif (sourceSeedId) {\n\t\t\t\t\t\t\t// This is a translation — reference the source entry\n\t\t\t\t\t\t\tentry.translationOf = sourceSeedId;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// First entry in this translation group — track it\n\t\t\t\t\t\t\ttranslationGroupToSeedId.set(item.translationGroup, seedId);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Get taxonomy assignments\n\t\t\t\tconst taxonomies = await getTaxonomyAssignments(taxonomyRepo, collection.slug, item.id);\n\t\t\t\tif (Object.keys(taxonomies).length > 0) {\n\t\t\t\t\tentry.taxonomies = taxonomies;\n\t\t\t\t}\n\n\t\t\t\tentries.push(entry);\n\t\t\t}\n\n\t\t\tcursor = result.nextCursor;\n\t\t} while (cursor);\n\n\t\tif (i18nEnabled && entries.length > 0) {\n\t\t\t// Sort entries so source locale entries appear before their translations.\n\t\t\t// Entries without translationOf come first; entries with translationOf come after.\n\t\t\tentries.sort((a, b) => {\n\t\t\t\tif (a.translationOf && !b.translationOf) return 1;\n\t\t\t\tif (!a.translationOf && b.translationOf) return -1;\n\t\t\t\treturn 0;\n\t\t\t});\n\t\t}\n\n\t\tif (entries.length > 0) {\n\t\t\tcontent[collection.slug] = entries;\n\t\t}\n\t}\n\n\treturn content;\n}\n\n/**\n * Process content data for export, converting image fields to $media syntax\n */\nfunction processDataForExport(\n\tdata: Record<string, unknown>,\n\tfields: SeedField[],\n\tmediaMap: Map<string, { url: string; filename: string; alt?: string; caption?: string }>,\n): Record<string, unknown> {\n\tconst result: Record<string, unknown> = {};\n\n\t// Create field type lookup\n\tconst fieldTypes = new Map<string, FieldType>();\n\tfor (const field of fields) {\n\t\tfieldTypes.set(field.slug, field.type);\n\t}\n\n\tfor (const [key, value] of Object.entries(data)) {\n\t\tconst fieldType = fieldTypes.get(key);\n\n\t\tif (fieldType === \"image\" && value && typeof value === \"object\") {\n\t\t\t// Convert image field to $media syntax\n\t\t\tconst imageValue = value as { id?: string; src?: string; alt?: string };\n\t\t\tif (imageValue.id) {\n\t\t\t\tconst mediaInfo = mediaMap.get(imageValue.id);\n\t\t\t\tif (mediaInfo) {\n\t\t\t\t\tresult[key] = {\n\t\t\t\t\t\t$media: {\n\t\t\t\t\t\t\turl: mediaInfo.url,\n\t\t\t\t\t\t\tfilename: mediaInfo.filename,\n\t\t\t\t\t\t\talt: imageValue.alt || mediaInfo.alt,\n\t\t\t\t\t\t\tcaption: mediaInfo.caption,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Fallback: keep as-is if no media info found\n\t\t\tresult[key] = value;\n\t\t} else if (fieldType === \"reference\" && typeof value === \"string\") {\n\t\t\t// Convert reference to $ref syntax (assumes same collection for now)\n\t\t\tresult[key] = `$ref:${value}`;\n\t\t} else if (Array.isArray(value)) {\n\t\t\t// Process arrays (could contain references or images)\n\t\t\tresult[key] = value.map((item) => {\n\t\t\t\tif (typeof item === \"string\" && fieldType === \"reference\") {\n\t\t\t\t\treturn `$ref:${item}`;\n\t\t\t\t}\n\t\t\t\treturn item;\n\t\t\t});\n\t\t} else {\n\t\t\tresult[key] = value;\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Get taxonomy term assignments for a content entry\n */\nasync function getTaxonomyAssignments(\n\ttaxonomyRepo: TaxonomyRepository,\n\tcollection: string,\n\tentryId: string,\n): Promise<Record<string, string[]>> {\n\tconst terms = await taxonomyRepo.getTermsForEntry(collection, entryId);\n\tconst result: Record<string, string[]> = {};\n\n\tfor (const term of terms) {\n\t\tif (!result[term.name]) {\n\t\t\tresult[term.name] = [];\n\t\t}\n\t\tresult[term.name].push(term.slug);\n\t}\n\n\treturn result;\n}\n","/**\n * emdash init\n *\n * Initialize database from template config in package.json\n */\n\nimport { readFile, access } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\n\nimport { defineCommand } from \"citty\";\nimport consola from \"consola\";\n\nimport { createDatabase } from \"../../database/connection.js\";\nimport { runMigrations } from \"../../database/migrations/runner.js\";\n\nexport interface EmDashConfig {\n\tlabel?: string;\n\tschema?: string;\n\tseed?: string;\n}\n\ninterface PackageJson {\n\tname?: string;\n\temdash?: EmDashConfig;\n}\n\nasync function fileExists(path: string): Promise<boolean> {\n\ttry {\n\t\tawait access(path);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nasync function readPackageJson(cwd: string): Promise<PackageJson | null> {\n\tconst pkgPath = resolve(cwd, \"package.json\");\n\ttry {\n\t\tconst content = await readFile(pkgPath, \"utf-8\");\n\t\treturn JSON.parse(content);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nasync function runSqlFile(db: ReturnType<typeof createDatabase>, filePath: string): Promise<void> {\n\tconst sql = await readFile(filePath, \"utf-8\");\n\n\t// Remove single-line comments\n\tconst withoutComments = sql\n\t\t.split(\"\\n\")\n\t\t.filter((line) => !line.trim().startsWith(\"--\"))\n\t\t.join(\"\\n\");\n\n\t// Split on semicolons, filter empty statements\n\tconst statements = withoutComments\n\t\t.split(\";\")\n\t\t.map((s) => s.trim())\n\t\t.filter((s) => s.length > 0);\n\n\tfor (const statement of statements) {\n\t\tawait db.executeQuery({\n\t\t\tsql: statement,\n\t\t\tparameters: [],\n\t\t\tquery: { kind: \"RawNode\", sqlFragments: [statement], parameters: [] },\n\t\t});\n\t}\n}\n\n/**\n * Check if database has already been initialized with template schema\n */\nasync function isAlreadyInitialized(db: ReturnType<typeof createDatabase>): Promise<boolean> {\n\ttry {\n\t\t// Use raw SQL since this runs on an untyped database connection\n\t\tconst { sql } = await import(\"kysely\");\n\t\tconst result = await sql<{\n\t\t\tcount: number;\n\t\t}>`SELECT COUNT(id) as count FROM _emdash_collections`.execute(db);\n\t\tconst row = result.rows[0];\n\t\treturn row ? row.count > 0 : false;\n\t} catch {\n\t\t// Table doesn't exist yet\n\t\treturn false;\n\t}\n}\n\nexport const initCommand = defineCommand({\n\tmeta: {\n\t\tname: \"init\",\n\t\tdescription: \"Initialize database from template config\",\n\t},\n\targs: {\n\t\tdatabase: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"d\",\n\t\t\tdescription: \"Database path (default: ./data.db)\",\n\t\t\tdefault: \"./data.db\",\n\t\t},\n\t\tcwd: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Working directory\",\n\t\t\tdefault: process.cwd(),\n\t\t},\n\t\tforce: {\n\t\t\ttype: \"boolean\",\n\t\t\talias: \"f\",\n\t\t\tdescription: \"Force re-initialization\",\n\t\t\tdefault: false,\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst cwd = resolve(args.cwd);\n\t\tconsola.start(\"Initializing EmDash...\");\n\n\t\t// 1. Read package.json\n\t\tconst pkg = await readPackageJson(cwd);\n\t\tif (!pkg) {\n\t\t\tconsola.error(\"No package.json found in\", cwd);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tconst config = pkg.emdash;\n\t\tconsola.info(`Project: ${pkg.name || \"unknown\"}`);\n\n\t\tif (config?.label) {\n\t\t\tconsola.info(`Template: ${config.label}`);\n\t\t}\n\n\t\t// 2. Create/connect to database\n\t\tconst dbPath = resolve(cwd, args.database);\n\t\tconsola.info(`Database: ${dbPath}`);\n\n\t\tconst db = createDatabase({ url: `file:${dbPath}` });\n\n\t\t// 3. Run core migrations (always run - they're idempotent)\n\t\tconsola.start(\"Running migrations...\");\n\t\ttry {\n\t\t\tconst { applied } = await runMigrations(db);\n\t\t\tif (applied.length > 0) {\n\t\t\t\tconsola.success(`Applied ${applied.length} migrations`);\n\t\t\t\tfor (const name of applied) {\n\t\t\t\t\tconsola.info(` - ${name}`);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconsola.info(\"Migrations already up to date\");\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsola.error(\"Migration failed:\", error);\n\t\t\tawait db.destroy();\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\t// 4. Check if already initialized (has collections)\n\t\tconst alreadyInitialized = await isAlreadyInitialized(db);\n\t\tif (alreadyInitialized && !args.force) {\n\t\t\tawait db.destroy();\n\t\t\tconsola.success(\"Already initialized. Use --force to re-run schema/seed.\");\n\t\t\treturn;\n\t\t}\n\n\t\tif (alreadyInitialized && args.force) {\n\t\t\tconsola.warn(\"Re-initializing (--force)...\");\n\t\t}\n\n\t\t// 5. Run template schema.sql if present\n\t\tif (config?.schema) {\n\t\t\tconst schemaPath = resolve(cwd, config.schema);\n\t\t\tif (await fileExists(schemaPath)) {\n\t\t\t\tconsola.start(`Running schema: ${config.schema}`);\n\t\t\t\ttry {\n\t\t\t\t\tawait runSqlFile(db, schemaPath);\n\t\t\t\t\tconsola.success(\"Schema applied\");\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsola.error(\"Schema failed:\", error);\n\t\t\t\t\tawait db.destroy();\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconsola.warn(`Schema file not found: ${config.schema}`);\n\t\t\t}\n\t\t}\n\n\t\t// 6. JSON seed files are now handled by `emdash seed` command\n\t\t// The bootstrap script runs `emdash init && emdash seed`\n\t\t// Legacy SQL seed files (seed.sql) could be handled here if needed\n\n\t\tawait db.destroy();\n\t\tconsola.success(\"EmDash initialized successfully!\");\n\t\tconsola.info(\"Run `pnpm dev` to start the development server\");\n\t},\n});\n","/**\n * Login/logout/whoami CLI commands\n *\n * Login uses the OAuth Device Flow (RFC 8628):\n * 1. POST /oauth/device/code → get device_code + user_code\n * 2. Display URL + code to user\n * 3. Poll POST /oauth/device/token until authorized\n * 4. Save tokens to ~/.config/emdash/auth.json\n *\n * Custom headers (--header / EMDASH_HEADERS) are sent with every request\n * and persisted to credentials so subsequent commands inherit them.\n * This supports sites behind reverse proxies like Cloudflare Access.\n */\n\nimport { defineCommand } from \"citty\";\nimport { consola } from \"consola\";\nimport pc from \"picocolors\";\n\nimport {\n\tcreateHeaderAwareFetch,\n\tgetCachedAccessToken,\n\tisAccessRedirect,\n\tresolveCustomHeaders,\n\trunCloudflaredLogin,\n} from \"../../client/cf-access.js\";\nimport {\n\tgetCredentials,\n\tremoveCredentials,\n\tresolveCredentialKey,\n\tsaveCredentials,\n} from \"../credentials.js\";\n\n// ---------------------------------------------------------------------------\n// Types for discovery + device flow responses\n// ---------------------------------------------------------------------------\n\ninterface DiscoveryResponse {\n\tinstance?: { name?: string };\n\tauth?: {\n\t\tmode?: string;\n\t\tmethods?: {\n\t\t\tdevice_flow?: {\n\t\t\t\tdevice_authorization_endpoint: string;\n\t\t\t\ttoken_endpoint: string;\n\t\t\t};\n\t\t\tapi_tokens?: boolean;\n\t\t};\n\t};\n}\n\ninterface DeviceCodeResponse {\n\tdevice_code: string;\n\tuser_code: string;\n\tverification_uri: string;\n\texpires_in: number;\n\tinterval: number;\n}\n\ninterface TokenResponse {\n\taccess_token: string;\n\trefresh_token: string;\n\ttoken_type: string;\n\texpires_in: number;\n\tscope: string;\n}\n\n// ---------------------------------------------------------------------------\n// Device Flow polling\n// ---------------------------------------------------------------------------\n\nasync function pollForToken(\n\ttokenEndpoint: string,\n\tdeviceCode: string,\n\tinterval: number,\n\texpiresIn: number,\n\tfetchFn: typeof fetch,\n): Promise<TokenResponse> {\n\tconst deadline = Date.now() + expiresIn * 1000;\n\tlet currentInterval = interval;\n\n\twhile (Date.now() < deadline) {\n\t\tawait new Promise((resolve) => setTimeout(resolve, currentInterval * 1000));\n\n\t\tconst res = await fetchFn(tokenEndpoint, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({\n\t\t\t\tdevice_code: deviceCode,\n\t\t\t\tgrant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n\t\t\t}),\n\t\t});\n\n\t\tif (res.ok) {\n\t\t\treturn (await res.json()) as TokenResponse;\n\t\t}\n\n\t\tconst body = (await res.json()) as { error?: string; interval?: number };\n\n\t\tif (body.error === \"authorization_pending\") {\n\t\t\t// Keep polling\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (body.error === \"slow_down\") {\n\t\t\t// Use server-provided interval, or fall back to incrementing by 5s\n\t\t\tcurrentInterval = body.interval ?? currentInterval + 5;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (body.error === \"expired_token\") {\n\t\t\tthrow new Error(\"Device code expired. Please try again.\");\n\t\t}\n\n\t\tif (body.error === \"access_denied\") {\n\t\t\tthrow new Error(\"Authorization was denied.\");\n\t\t}\n\n\t\t// Unknown error\n\t\tthrow new Error(`Token exchange failed: ${body.error || res.statusText}`);\n\t}\n\n\tthrow new Error(\"Device code expired (timeout). Please try again.\");\n}\n\n// ---------------------------------------------------------------------------\n// Cloudflare Access handling\n// ---------------------------------------------------------------------------\n\n/**\n * Handle a Cloudflare Access redirect during login.\n *\n * 1. Try `cloudflared access token` for a cached JWT\n * 2. Try `cloudflared access login` to do the browser flow\n * 3. If cloudflared isn't available, print instructions for service tokens\n *\n * Returns the Access JWT, or null if auth couldn't be resolved.\n */\nasync function handleAccessRedirect(baseUrl: string): Promise<string | null> {\n\tconsola.info(\"This site is behind Cloudflare Access.\");\n\n\t// Try cached token first\n\tconst cached = await getCachedAccessToken(baseUrl);\n\tif (cached) {\n\t\tconsola.success(\"Using cached Cloudflare Access token from cloudflared.\");\n\t\treturn cached;\n\t}\n\n\t// Try interactive login via cloudflared\n\tconsola.info(\"Launching browser for Cloudflare Access login...\");\n\tconst loginOk = await runCloudflaredLogin(baseUrl);\n\n\tif (loginOk) {\n\t\tconst token = await getCachedAccessToken(baseUrl);\n\t\tif (token) {\n\t\t\tconsola.success(\"Cloudflare Access authentication successful.\");\n\t\t\treturn token;\n\t\t}\n\t}\n\n\t// cloudflared not available or login failed — guide the user\n\tconsole.log();\n\tconsola.info(\"Could not authenticate with Cloudflare Access automatically.\");\n\tconsola.info(\"You have two options:\");\n\tconsole.log();\n\tconsola.info(` ${pc.bold(\"Option 1:\")} Install cloudflared and run:`);\n\tconsole.log(` ${pc.cyan(`cloudflared access login ${baseUrl}`)}`);\n\tconsole.log(` ${pc.cyan(`emdash login --url ${baseUrl}`)}`);\n\tconsole.log();\n\tconsola.info(` ${pc.bold(\"Option 2:\")} Use a service token:`);\n\tconsole.log(\n\t\t` ${pc.cyan(`emdash login --url ${baseUrl} -H \"CF-Access-Client-Id: <id>\" -H \"CF-Access-Client-Secret: <secret>\"`)}`,\n\t);\n\tconsole.log();\n\n\treturn null;\n}\n\n// ---------------------------------------------------------------------------\n// Commands\n// ---------------------------------------------------------------------------\n\nexport const loginCommand = defineCommand({\n\tmeta: { name: \"login\", description: \"Log in to an EmDash instance\" },\n\targs: {\n\t\turl: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"u\",\n\t\t\tdescription: \"EmDash instance URL\",\n\t\t\tdefault: \"http://localhost:4321\",\n\t\t},\n\t\theader: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"H\",\n\t\t\tdescription: 'Custom header \"Name: Value\" (repeatable, or use EMDASH_HEADERS env)',\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst baseUrl = args.url || \"http://localhost:4321\";\n\t\tconsola.start(`Connecting to ${baseUrl}...`);\n\n\t\t// Resolve custom headers from --header flags and EMDASH_HEADERS env\n\t\tconst customHeaders = resolveCustomHeaders();\n\t\tlet headerFetch = createHeaderAwareFetch(customHeaders);\n\n\t\ttry {\n\t\t\t// Step 1: Fetch auth discovery.\n\t\t\t// Use redirect: \"manual\" to detect Cloudflare Access.\n\t\t\tconst discoveryUrl = new URL(\"/_emdash/.well-known/auth\", baseUrl);\n\t\t\tlet res = await headerFetch(discoveryUrl, { redirect: \"manual\" });\n\n\t\t\t// Handle Cloudflare Access\n\t\t\tif (isAccessRedirect(res)) {\n\t\t\t\tconst accessToken = await handleAccessRedirect(baseUrl);\n\t\t\t\tif (!accessToken) {\n\t\t\t\t\treturn; // handleAccessRedirect printed instructions\n\t\t\t\t}\n\t\t\t\t// Add the Access token to our custom headers and rebuild the fetch wrapper\n\t\t\t\tcustomHeaders[\"cf-access-token\"] = accessToken;\n\t\t\t\theaderFetch = createHeaderAwareFetch(customHeaders);\n\t\t\t\tres = await headerFetch(discoveryUrl);\n\t\t\t} else if (res.status === 301 || res.status === 302) {\n\t\t\t\t// Non-Access redirect — follow it normally\n\t\t\t\tres = await headerFetch(discoveryUrl);\n\t\t\t}\n\n\t\t\tif (!res.ok) {\n\t\t\t\tif (res.status === 404) {\n\t\t\t\t\tconst isLocal = baseUrl.includes(\"localhost\") || baseUrl.includes(\"127.0.0.1\");\n\t\t\t\t\tif (isLocal) {\n\t\t\t\t\t\tconsola.info(\"Auth discovery not available. Trying dev bypass...\");\n\t\t\t\t\t\tconst bypassRes = await fetch(new URL(\"/_emdash/api/auth/dev-bypass\", baseUrl), {\n\t\t\t\t\t\t\tredirect: \"manual\",\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (bypassRes.status === 302 || bypassRes.ok) {\n\t\t\t\t\t\t\tconsola.success(\"Dev bypass available. Client will authenticate automatically.\");\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconsola.error(\"Could not authenticate. Is the dev server running?\");\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconsola.error(\"Auth discovery endpoint not found. Is this an EmDash instance?\");\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconsola.error(`Discovery failed: ${res.status} ${res.statusText}`);\n\t\t\t\tprocess.exit(2);\n\t\t\t}\n\n\t\t\tconst discovery = (await res.json()) as DiscoveryResponse;\n\t\t\tconsola.success(`Connected to ${discovery.instance?.name || \"EmDash\"}`);\n\n\t\t\tconst deviceFlow = discovery.auth?.methods?.device_flow;\n\n\t\t\tif (!deviceFlow) {\n\t\t\t\t// No device flow available (external auth mode)\n\t\t\t\tconsola.info(\"Device Flow is not available for this instance.\");\n\t\t\t\tconsola.info(\"Generate an API token in Settings > API Tokens\");\n\t\t\t\tconsola.info(`Then run: ${pc.cyan(`emdash --token <token> --url ${baseUrl}`)}`);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Step 2: Request device code\n\t\t\tconst codeUrl = new URL(deviceFlow.device_authorization_endpoint, baseUrl);\n\t\t\tconst codeRes = await headerFetch(codeUrl, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\"X-EmDash-Request\": \"1\",\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tclient_id: \"emdash-cli\",\n\t\t\t\t}),\n\t\t\t});\n\n\t\t\tif (!codeRes.ok) {\n\t\t\t\tconsola.error(`Failed to request device code: ${codeRes.status}`);\n\t\t\t\tprocess.exit(2);\n\t\t\t}\n\n\t\t\tconst deviceCode = (await codeRes.json()) as DeviceCodeResponse;\n\n\t\t\t// Step 3: Display instructions\n\t\t\tconsole.log();\n\t\t\tconsola.info(`Open your browser to:`);\n\t\t\tconsole.log(` ${pc.cyan(pc.bold(deviceCode.verification_uri))}`);\n\t\t\tconsole.log();\n\t\t\tconsola.info(`Enter code: ${pc.yellow(pc.bold(deviceCode.user_code))}`);\n\t\t\tconsole.log();\n\n\t\t\t// Try to open browser (best-effort)\n\t\t\ttry {\n\t\t\t\tconst { execFile } = await import(\"node:child_process\");\n\t\t\t\tif (process.platform === \"darwin\") {\n\t\t\t\t\texecFile(\"open\", [deviceCode.verification_uri]);\n\t\t\t\t} else if (process.platform === \"win32\") {\n\t\t\t\t\texecFile(\"cmd\", [\"/c\", \"start\", \"\", deviceCode.verification_uri]);\n\t\t\t\t} else {\n\t\t\t\t\texecFile(\"xdg-open\", [deviceCode.verification_uri]);\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Ignore — user can open manually\n\t\t\t}\n\n\t\t\t// Step 4: Poll for token\n\t\t\tconsola.start(\"Waiting for authorization...\");\n\n\t\t\tconst tokenUrl = new URL(deviceFlow.token_endpoint, baseUrl);\n\t\t\tconst tokenResult = await pollForToken(\n\t\t\t\ttokenUrl.toString(),\n\t\t\t\tdeviceCode.device_code,\n\t\t\t\tdeviceCode.interval,\n\t\t\t\tdeviceCode.expires_in,\n\t\t\t\theaderFetch,\n\t\t\t);\n\n\t\t\t// Step 5: Fetch user info\n\t\t\tlet userEmail = \"unknown\";\n\t\t\tlet userRole = \"unknown\";\n\t\t\ttry {\n\t\t\t\tconst meRes = await headerFetch(new URL(\"/_emdash/api/auth/me\", baseUrl), {\n\t\t\t\t\theaders: { Authorization: `Bearer ${tokenResult.access_token}` },\n\t\t\t\t});\n\t\t\t\tif (meRes.ok) {\n\t\t\t\t\tconst meJson = (await meRes.json()) as {\n\t\t\t\t\t\tdata: { email?: string; role?: number };\n\t\t\t\t\t};\n\t\t\t\t\tconst me = meJson.data;\n\t\t\t\t\tuserEmail = me.email || \"unknown\";\n\t\t\t\t\t// Map role number to name\n\t\t\t\t\tconst roleNames: Record<number, string> = {\n\t\t\t\t\t\t10: \"subscriber\",\n\t\t\t\t\t\t20: \"contributor\",\n\t\t\t\t\t\t30: \"author\",\n\t\t\t\t\t\t40: \"editor\",\n\t\t\t\t\t\t50: \"admin\",\n\t\t\t\t\t};\n\t\t\t\t\tuserRole = (me.role ? roleNames[me.role] : undefined) || \"unknown\";\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Non-critical\n\t\t\t}\n\n\t\t\t// Step 6: Save credentials (persist custom headers so subsequent commands inherit them)\n\t\t\tconst expiresAt = new Date(Date.now() + tokenResult.expires_in * 1000).toISOString();\n\t\t\tconst hasCustomHeaders = Object.keys(customHeaders).length > 0;\n\t\t\tsaveCredentials(baseUrl, {\n\t\t\t\taccessToken: tokenResult.access_token,\n\t\t\t\trefreshToken: tokenResult.refresh_token,\n\t\t\t\texpiresAt,\n\t\t\t\t...(hasCustomHeaders ? { customHeaders } : {}),\n\t\t\t\tuser: { email: userEmail, role: userRole },\n\t\t\t});\n\n\t\t\tconsola.success(`Logged in as ${pc.bold(userEmail)} (${userRole})`);\n\t\t\tconsola.info(`Token saved to ${pc.dim(resolveCredentialKey(baseUrl))}`);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Login failed\");\n\t\t\tprocess.exit(2);\n\t\t}\n\t},\n});\n\nexport const logoutCommand = defineCommand({\n\tmeta: { name: \"logout\", description: \"Log out of an EmDash instance\" },\n\targs: {\n\t\turl: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"u\",\n\t\t\tdescription: \"EmDash instance URL\",\n\t\t\tdefault: \"http://localhost:4321\",\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst baseUrl = args.url || \"http://localhost:4321\";\n\n\t\t// Get stored credentials\n\t\tconst cred = getCredentials(baseUrl);\n\n\t\tif (!cred) {\n\t\t\tconsola.info(\"No stored credentials found for this instance.\");\n\t\t\treturn;\n\t\t}\n\n\t\tconst headerFetch = createHeaderAwareFetch(cred.customHeaders ?? {});\n\n\t\t// Revoke tokens server-side (best-effort)\n\t\ttry {\n\t\t\t// Revoke the refresh token (which also revokes associated access tokens)\n\t\t\tawait headerFetch(new URL(\"/_emdash/api/oauth/token/revoke\", baseUrl), {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\t\tbody: JSON.stringify({ token: cred.refreshToken }),\n\t\t\t});\n\t\t} catch {\n\t\t\t// Non-critical — the local removal still works\n\t\t}\n\n\t\t// Remove local credentials\n\t\tremoveCredentials(baseUrl);\n\t\tconsola.success(\"Logged out successfully.\");\n\t},\n});\n\nexport const whoamiCommand = defineCommand({\n\tmeta: {\n\t\tname: \"whoami\",\n\t\tdescription: \"Show current user and auth method\",\n\t},\n\targs: {\n\t\turl: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"u\",\n\t\t\tdescription: \"EmDash instance URL\",\n\t\t\tdefault: \"http://localhost:4321\",\n\t\t},\n\t\ttoken: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"t\",\n\t\t\tdescription: \"Auth token\",\n\t\t},\n\t\tjson: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Output as JSON\",\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst baseUrl = args.url || \"http://localhost:4321\";\n\n\t\t// Resolve token: --token flag > EMDASH_TOKEN env > stored credentials\n\t\tlet token = args.token || process.env[\"EMDASH_TOKEN\"];\n\t\tlet authMethod = token ? \"token\" : \"none\";\n\t\tlet storedHeaders: Record<string, string> = {};\n\n\t\tif (!token) {\n\t\t\tconst cred = getCredentials(baseUrl);\n\t\t\tif (cred) {\n\t\t\t\ttoken = cred.accessToken;\n\t\t\t\tauthMethod = \"stored\";\n\t\t\t\tstoredHeaders = cred.customHeaders ?? {};\n\n\t\t\t\t// Check if expired\n\t\t\t\tif (new Date(cred.expiresAt) < new Date()) {\n\t\t\t\t\tconst headerFetch = createHeaderAwareFetch(storedHeaders);\n\t\t\t\t\t// Try to refresh\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst refreshRes = await headerFetch(\n\t\t\t\t\t\t\tnew URL(\"/_emdash/api/oauth/token/refresh\", baseUrl),\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\t\t\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\t\t\t\t\trefresh_token: cred.refreshToken,\n\t\t\t\t\t\t\t\t\tgrant_type: \"refresh_token\",\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (refreshRes.ok) {\n\t\t\t\t\t\t\tconst refreshed = (await refreshRes.json()) as TokenResponse;\n\t\t\t\t\t\t\ttoken = refreshed.access_token;\n\t\t\t\t\t\t\tsaveCredentials(baseUrl, {\n\t\t\t\t\t\t\t\t...cred,\n\t\t\t\t\t\t\t\taccessToken: refreshed.access_token,\n\t\t\t\t\t\t\t\texpiresAt: new Date(Date.now() + refreshed.expires_in * 1000).toISOString(),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconsola.warn(\"Stored token expired and refresh failed. Run: emdash login\");\n\t\t\t\t\t\t\tprocess.exit(2);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tconsola.warn(\"Stored token expired. Run: emdash login\");\n\t\t\t\t\t\tprocess.exit(2);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!token) {\n\t\t\t// Try dev bypass for local\n\t\t\tconst isLocal = baseUrl.includes(\"localhost\") || baseUrl.includes(\"127.0.0.1\");\n\t\t\tif (isLocal) {\n\t\t\t\tauthMethod = \"dev-bypass\";\n\t\t\t\tconsola.info(`Auth method: ${pc.cyan(\"dev-bypass\")}`);\n\t\t\t\tconsola.info(\"No stored credentials. Client will use dev bypass for localhost.\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconsola.error(\"Not logged in. Run: emdash login\");\n\t\t\tprocess.exit(2);\n\t\t}\n\n\t\tconst headerFetch = createHeaderAwareFetch(storedHeaders);\n\n\t\ttry {\n\t\t\tconst meRes = await headerFetch(new URL(\"/_emdash/api/auth/me\", baseUrl), {\n\t\t\t\theaders: { Authorization: `Bearer ${token}` },\n\t\t\t});\n\n\t\t\tif (!meRes.ok) {\n\t\t\t\tif (meRes.status === 401) {\n\t\t\t\t\tconsola.error(\"Token is invalid or expired. Run: emdash login\");\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t}\n\t\t\t\tconsola.error(`Failed to fetch user info: ${meRes.status}`);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\tconst raw = (await meRes.json()) as {\n\t\t\t\tdata: {\n\t\t\t\t\tid: string;\n\t\t\t\t\temail: string;\n\t\t\t\t\tname: string | null;\n\t\t\t\t\trole: number;\n\t\t\t\t};\n\t\t\t};\n\t\t\tconst me = raw.data;\n\n\t\t\tconst roleNames: Record<number, string> = {\n\t\t\t\t10: \"subscriber\",\n\t\t\t\t20: \"contributor\",\n\t\t\t\t30: \"author\",\n\t\t\t\t40: \"editor\",\n\t\t\t\t50: \"admin\",\n\t\t\t};\n\n\t\t\tif (args.json) {\n\t\t\t\tconsole.log(\n\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\tid: me.id,\n\t\t\t\t\t\temail: me.email,\n\t\t\t\t\t\tname: me.name,\n\t\t\t\t\t\trole: roleNames[me.role] || `unknown (${me.role})`,\n\t\t\t\t\t\tauthMethod,\n\t\t\t\t\t\turl: baseUrl,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tconsola.info(`Email: ${pc.bold(me.email)}`);\n\t\t\t\tif (me.name) consola.info(`Name: ${me.name}`);\n\t\t\t\tconsola.info(`Role: ${pc.cyan(roleNames[me.role] || `unknown (${me.role})`)}`);\n\t\t\t\tconsola.info(`Auth: ${pc.dim(authMethod)}`);\n\t\t\t\tconsola.info(`URL: ${pc.dim(baseUrl)}`);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n","/**\n * emdash media\n *\n * Manage media items via the EmDash API\n */\n\nimport { readFile } from \"node:fs/promises\";\nimport { basename } from \"node:path\";\n\nimport { defineCommand } from \"citty\";\nimport { consola } from \"consola\";\n\nimport { connectionArgs, createClientFromArgs } from \"../client-factory.js\";\nimport { output } from \"../output.js\";\n\nconst listCommand = defineCommand({\n\tmeta: {\n\t\tname: \"list\",\n\t\tdescription: \"List media items\",\n\t},\n\targs: {\n\t\t...connectionArgs,\n\t\tmime: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Filter by MIME type (e.g., image/png)\",\n\t\t},\n\t\tlimit: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Number of items to return\",\n\t\t},\n\t\tcursor: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Pagination cursor\",\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst client = createClientFromArgs(args);\n\n\t\ttry {\n\t\t\tconst result = await client.mediaList({\n\t\t\t\tmimeType: args.mime,\n\t\t\t\tlimit: args.limit ? Number(args.limit) : undefined,\n\t\t\t\tcursor: args.cursor,\n\t\t\t});\n\n\t\t\toutput(result, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(\"Failed to list media:\", error instanceof Error ? error.message : error);\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst uploadCommand = defineCommand({\n\tmeta: {\n\t\tname: \"upload\",\n\t\tdescription: \"Upload a media file\",\n\t},\n\targs: {\n\t\tfile: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Path to the file to upload\",\n\t\t\trequired: true,\n\t\t},\n\t\t...connectionArgs,\n\t\talt: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Alt text for the media item\",\n\t\t},\n\t\tcaption: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Caption for the media item\",\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst client = createClientFromArgs(args);\n\t\tconst filename = basename(args.file);\n\n\t\tconsola.start(`Uploading ${filename}...`);\n\n\t\ttry {\n\t\t\tconst buffer = await readFile(args.file);\n\t\t\tconst result = await client.mediaUpload(buffer, filename, {\n\t\t\t\talt: args.alt,\n\t\t\t\tcaption: args.caption,\n\t\t\t});\n\n\t\t\tconsola.success(`Uploaded ${filename}`);\n\t\t\toutput(result, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(\"Failed to upload:\", error instanceof Error ? error.message : error);\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst getCommand = defineCommand({\n\tmeta: {\n\t\tname: \"get\",\n\t\tdescription: \"Get a media item\",\n\t},\n\targs: {\n\t\tid: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Media item ID\",\n\t\t\trequired: true,\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\tconst client = createClientFromArgs(args);\n\n\t\ttry {\n\t\t\tconst result = await client.mediaGet(args.id);\n\t\t\toutput(result, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(\"Failed to get media:\", error instanceof Error ? error.message : error);\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst deleteCommand = defineCommand({\n\tmeta: {\n\t\tname: \"delete\",\n\t\tdescription: \"Delete a media item\",\n\t},\n\targs: {\n\t\tid: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Media item ID\",\n\t\t\trequired: true,\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\tconst client = createClientFromArgs(args);\n\n\t\ttry {\n\t\t\tawait client.mediaDelete(args.id);\n\n\t\t\tif (args.json) {\n\t\t\t\toutput({ deleted: true }, args);\n\t\t\t} else {\n\t\t\t\tconsola.success(`Deleted media item ${args.id}`);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsola.error(\"Failed to delete media:\", error instanceof Error ? error.message : error);\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nexport const mediaCommand = defineCommand({\n\tmeta: {\n\t\tname: \"media\",\n\t\tdescription: \"Manage media items\",\n\t},\n\tsubCommands: {\n\t\tlist: listCommand,\n\t\tupload: uploadCommand,\n\t\tget: getCommand,\n\t\tdelete: deleteCommand,\n\t},\n});\n","/**\n * emdash menu\n *\n * Manage menus via the EmDash REST API.\n */\n\nimport { defineCommand } from \"citty\";\nimport { consola } from \"consola\";\n\nimport { connectionArgs, createClientFromArgs } from \"../client-factory.js\";\nimport { output } from \"../output.js\";\n\nconst listCommand = defineCommand({\n\tmeta: {\n\t\tname: \"list\",\n\t\tdescription: \"List all menus\",\n\t},\n\targs: {\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst menus = await client.menus();\n\t\t\toutput(menus, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst getCommand = defineCommand({\n\tmeta: {\n\t\tname: \"get\",\n\t\tdescription: \"Get a menu with its items\",\n\t},\n\targs: {\n\t\tname: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Menu name\",\n\t\t\trequired: true,\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst menu = await client.menu(args.name);\n\t\t\toutput(menu, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nexport const menuCommand = defineCommand({\n\tmeta: {\n\t\tname: \"menu\",\n\t\tdescription: \"Manage menus\",\n\t},\n\tsubCommands: {\n\t\tlist: listCommand,\n\t\tget: getCommand,\n\t},\n});\n","/**\n * Bundle utility functions\n *\n * Shared logic extracted from the bundle command so it can be tested\n * without the CLI harness and tsdown dependency.\n */\n\nimport { createWriteStream } from \"node:fs\";\nimport { readdir, stat, access } from \"node:fs/promises\";\nimport { resolve, join } from \"node:path\";\nimport { pipeline } from \"node:stream/promises\";\n\nimport { imageSize } from \"image-size\";\nimport { packTar } from \"modern-tar/fs\";\n\nimport type {\n\tPluginManifest,\n\tResolvedPlugin,\n\tHookName,\n\tManifestHookEntry,\n} from \"../../plugins/types.js\";\n\n// ── Constants ────────────────────────────────────────────────────────────────\n\nexport const MAX_BUNDLE_SIZE = 5 * 1024 * 1024;\nexport const MAX_SCREENSHOTS = 5;\nexport const MAX_SCREENSHOT_WIDTH = 1920;\nexport const MAX_SCREENSHOT_HEIGHT = 1080;\nexport const ICON_SIZE = 256;\n\n// ── Regex patterns (module-scope to avoid re-compilation) ────────────────────\n\n/** Matches require(\"node:xxx\") / require(\"xxx\") / import(\"node:xxx\") in bundled output */\nconst NODE_BUILTIN_IMPORT_RE = /(?:import|require)\\s*\\(?[\"'](?:node:)?([a-z_]+)[\"']\\)?/g;\nconst LEADING_DOT_SLASH_RE = /^\\.\\//;\nconst DIST_PREFIX_RE = /^dist\\//;\nconst MJS_EXT_RE = /\\.m?js$/;\nconst TS_TO_TSX_RE = /\\.ts$/;\n\n/** Node.js built-in modules that shouldn't appear in sandbox code */\nconst NODE_BUILTINS = new Set([\n\t\"assert\",\n\t\"buffer\",\n\t\"child_process\",\n\t\"cluster\",\n\t\"crypto\",\n\t\"dgram\",\n\t\"dns\",\n\t\"domain\",\n\t\"events\",\n\t\"fs\",\n\t\"http\",\n\t\"http2\",\n\t\"https\",\n\t\"inspector\",\n\t\"module\",\n\t\"net\",\n\t\"os\",\n\t\"path\",\n\t\"perf_hooks\",\n\t\"process\",\n\t\"punycode\",\n\t\"querystring\",\n\t\"readline\",\n\t\"repl\",\n\t\"stream\",\n\t\"string_decoder\",\n\t\"sys\",\n\t\"timers\",\n\t\"tls\",\n\t\"trace_events\",\n\t\"tty\",\n\t\"url\",\n\t\"util\",\n\t\"v8\",\n\t\"vm\",\n\t\"wasi\",\n\t\"worker_threads\",\n\t\"zlib\",\n]);\n\n// ── File helpers ─────────────────────────────────────────────────────────────\n\nexport async function fileExists(path: string): Promise<boolean> {\n\ttry {\n\t\tawait access(path);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n// ── Image dimension readers ──────────────────────────────────────────────────\n\n/**\n * Read image dimensions from a buffer.\n * Returns [width, height] or null if the format is unrecognized.\n */\nexport function readImageDimensions(buf: Uint8Array): [number, number] | null {\n\ttry {\n\t\tconst result = imageSize(buf);\n\t\tif (result.width != null && result.height != null) {\n\t\t\treturn [result.width, result.height];\n\t\t}\n\t\treturn null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n// ── Manifest extraction ──────────────────────────────────────────────────────\n\n/**\n * Extract manifest metadata from a ResolvedPlugin.\n * Strips functions (hooks, route handlers) and keeps only serializable metadata.\n */\nexport function extractManifest(plugin: ResolvedPlugin): PluginManifest {\n\t// Build hook entries preserving exclusive/priority/timeout metadata.\n\t// Plain HookName strings are emitted for hooks with default settings;\n\t// structured ManifestHookEntry objects are emitted when metadata differs.\n\tconst hooks: Array<ManifestHookEntry | HookName> = [];\n\tfor (const [name, resolved] of Object.entries(plugin.hooks)) {\n\t\tif (!resolved) continue;\n\t\tconst hasMetadata =\n\t\t\tresolved.exclusive || resolved.priority !== 100 || resolved.timeout !== 5000;\n\t\tif (hasMetadata) {\n\t\t\tconst entry: ManifestHookEntry = { name };\n\t\t\tif (resolved.exclusive) entry.exclusive = true;\n\t\t\tif (resolved.priority !== 100) entry.priority = resolved.priority;\n\t\t\tif (resolved.timeout !== 5000) entry.timeout = resolved.timeout;\n\t\t\thooks.push(entry);\n\t\t} else {\n\t\t\thooks.push(name as HookName);\n\t\t}\n\t}\n\n\treturn {\n\t\tid: plugin.id,\n\t\tversion: plugin.version,\n\t\tcapabilities: plugin.capabilities,\n\t\tallowedHosts: plugin.allowedHosts,\n\t\tstorage: plugin.storage,\n\t\thooks,\n\t\troutes: Object.keys(plugin.routes),\n\t\tadmin: {\n\t\t\t// Omit entry (it's a module specifier for the host, not relevant in bundles)\n\t\t\tsettingsSchema: plugin.admin.settingsSchema,\n\t\t\tpages: plugin.admin.pages,\n\t\t\twidgets: plugin.admin.widgets,\n\t\t},\n\t};\n}\n\n// ── Node.js built-in detection ───────────────────────────────────────────────\n\n/**\n * Scan bundled code for Node.js built-in imports.\n * Matches require(\"node:xxx\"), require(\"xxx\"), import(\"node:xxx\") — the patterns\n * that appear in bundled ESM/CJS output (not source-level named imports).\n * Returns deduplicated array of built-in module names found.\n */\nexport function findNodeBuiltinImports(code: string): string[] {\n\tconst found: string[] = [];\n\tNODE_BUILTIN_IMPORT_RE.lastIndex = 0;\n\tlet match;\n\twhile ((match = NODE_BUILTIN_IMPORT_RE.exec(code)) !== null) {\n\t\tconst mod = match[1];\n\t\tif (NODE_BUILTINS.has(mod)) {\n\t\t\tfound.push(mod);\n\t\t}\n\t}\n\treturn [...new Set(found)];\n}\n\n// ── Path resolution ──────────────────────────────────────────────────────────\n\n/**\n * Find a build output file by base name, checking common extensions.\n * tsdown may output .mjs, .js, or .cjs depending on format and config.\n */\nexport async function findBuildOutput(dir: string, baseName: string): Promise<string | undefined> {\n\tfor (const ext of [\".mjs\", \".js\", \".cjs\"]) {\n\t\tconst candidate = join(dir, `${baseName}${ext}`);\n\t\tif (await fileExists(candidate)) return candidate;\n\t}\n\treturn undefined;\n}\n\n/**\n * Resolve a dist/built path back to its source .ts/.tsx equivalent.\n * E.g., \"./dist/index.mjs\" → \"src/index.ts\"\n */\nexport async function resolveSourceEntry(\n\tpluginDir: string,\n\tdistPath: string,\n): Promise<string | undefined> {\n\tconst cleaned = distPath.replace(LEADING_DOT_SLASH_RE, \"\");\n\n\t// Try the path directly (might be source already)\n\tconst direct = resolve(pluginDir, cleaned);\n\tif (await fileExists(direct)) return direct;\n\n\t// Convert dist path to src: dist/foo.mjs → src/foo.ts\n\tconst srcPath = cleaned.replace(DIST_PREFIX_RE, \"src/\").replace(MJS_EXT_RE, \".ts\");\n\tconst srcFull = resolve(pluginDir, srcPath);\n\tif (await fileExists(srcFull)) return srcFull;\n\n\t// Try .tsx\n\tconst tsxPath = srcPath.replace(TS_TO_TSX_RE, \".tsx\");\n\tconst tsxFull = resolve(pluginDir, tsxPath);\n\tif (await fileExists(tsxFull)) return tsxFull;\n\n\treturn undefined;\n}\n\n// ── Directory helpers ────────────────────────────────────────────────────────\n\n/**\n * Recursively calculate the total size of all files in a directory.\n */\nexport async function calculateDirectorySize(dir: string): Promise<number> {\n\tlet total = 0;\n\tconst items = await readdir(dir, { withFileTypes: true });\n\tfor (const item of items) {\n\t\tconst fullPath = join(dir, item.name);\n\t\tif (item.isFile()) {\n\t\t\tconst s = await stat(fullPath);\n\t\t\ttotal += s.size;\n\t\t} else if (item.isDirectory()) {\n\t\t\ttotal += await calculateDirectorySize(fullPath);\n\t\t}\n\t}\n\treturn total;\n}\n\n// ── Tarball creation ─────────────────────────────────────────────────────────\n\n/**\n * Create a gzipped tarball from a directory.\n */\nexport async function createTarball(sourceDir: string, outputPath: string): Promise<void> {\n\tconst { createGzip } = await import(\"node:zlib\");\n\tconst tarStream = packTar(sourceDir);\n\tconst gzip = createGzip({ level: 9 });\n\tconst out = createWriteStream(outputPath);\n\tawait pipeline(tarStream, gzip, out);\n}\n","/**\n * emdash plugin bundle\n *\n * Produces a publishable plugin tarball from a plugin source directory.\n *\n * Steps:\n * 1. Resolve plugin entrypoint (finds definePlugin() export)\n * 2. Bundle backend code with tsdown → backend.js (single ES module, tree-shaken)\n * 3. Bundle admin code if present → admin.js\n * 4. Extract manifest from definePlugin() → manifest.json\n * 5. Collect assets (README.md, icon.png, screenshots/)\n * 6. Validate bundle (manifest schema, size limits, no Node.js builtins)\n * 7. Create tarball ({id}-{version}.tar.gz)\n */\n\nimport { createHash } from \"node:crypto\";\nimport { readFile, stat, mkdir, writeFile, rm, copyFile, symlink, readdir } from \"node:fs/promises\";\nimport { resolve, join, extname, basename } from \"node:path\";\n\nimport { defineCommand } from \"citty\";\nimport consola from \"consola\";\n\nimport type { ResolvedPlugin } from \"../../plugins/types.js\";\nimport {\n\tfileExists,\n\treadImageDimensions,\n\textractManifest,\n\tfindNodeBuiltinImports,\n\tfindBuildOutput,\n\tresolveSourceEntry,\n\tcalculateDirectorySize,\n\tcreateTarball,\n\tMAX_BUNDLE_SIZE,\n\tMAX_SCREENSHOTS,\n\tMAX_SCREENSHOT_WIDTH,\n\tMAX_SCREENSHOT_HEIGHT,\n\tICON_SIZE,\n} from \"./bundle-utils.js\";\n\nconst TS_EXT_RE = /\\.tsx?$/;\nconst SLASH_RE = /\\//g;\nconst LEADING_AT_RE = /^@/;\nconst emdash_SCOPE_RE = /^@emdash-cms\\//;\n\nexport const bundleCommand = defineCommand({\n\tmeta: {\n\t\tname: \"bundle\",\n\t\tdescription: \"Bundle a plugin for marketplace distribution\",\n\t},\n\targs: {\n\t\tdir: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Plugin directory (default: current directory)\",\n\t\t\tdefault: process.cwd(),\n\t\t},\n\t\toutDir: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"o\",\n\t\t\tdescription: \"Output directory for the tarball (default: ./dist)\",\n\t\t\tdefault: \"dist\",\n\t\t},\n\t\tvalidateOnly: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Run validation only, skip tarball creation\",\n\t\t\tdefault: false,\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst pluginDir = resolve(args.dir);\n\t\tconst outDir = resolve(pluginDir, args.outDir);\n\t\tconst validateOnly = args.validateOnly;\n\n\t\tconsola.start(validateOnly ? \"Validating plugin...\" : \"Bundling plugin...\");\n\n\t\t// ── Step 1: Read package.json and resolve entrypoints ──\n\n\t\tconst pkgPath = join(pluginDir, \"package.json\");\n\t\tif (!(await fileExists(pkgPath))) {\n\t\t\tconsola.error(\"No package.json found in\", pluginDir);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tconst pkg = JSON.parse(await readFile(pkgPath, \"utf-8\")) as {\n\t\t\tname?: string;\n\t\t\tmain?: string;\n\t\t\texports?: Record<string, unknown>;\n\t\t};\n\n\t\t// Find the sandbox entrypoint — look for ./sandbox export first, then main\n\t\tlet backendEntry: string | undefined;\n\t\tlet adminEntry: string | undefined;\n\n\t\tif (pkg.exports) {\n\t\t\t// Check for explicit sandbox export\n\t\t\tconst sandboxExport = pkg.exports[\"./sandbox\"];\n\t\t\tif (typeof sandboxExport === \"string\") {\n\t\t\t\tbackendEntry = await resolveSourceEntry(pluginDir, sandboxExport);\n\t\t\t} else if (sandboxExport && typeof sandboxExport === \"object\" && \"import\" in sandboxExport) {\n\t\t\t\tbackendEntry = await resolveSourceEntry(\n\t\t\t\t\tpluginDir,\n\t\t\t\t\t(sandboxExport as { import: string }).import,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Check for admin export\n\t\t\tconst adminExport = pkg.exports[\"./admin\"];\n\t\t\tif (typeof adminExport === \"string\") {\n\t\t\t\tadminEntry = await resolveSourceEntry(pluginDir, adminExport);\n\t\t\t} else if (adminExport && typeof adminExport === \"object\" && \"import\" in adminExport) {\n\t\t\t\tadminEntry = await resolveSourceEntry(\n\t\t\t\t\tpluginDir,\n\t\t\t\t\t(adminExport as { import: string }).import,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// If no sandbox export, look for src/sandbox-entry.ts\n\t\tif (!backendEntry) {\n\t\t\tconst defaultSandbox = join(pluginDir, \"src/sandbox-entry.ts\");\n\t\t\tif (await fileExists(defaultSandbox)) {\n\t\t\t\tbackendEntry = defaultSandbox;\n\t\t\t}\n\t\t}\n\n\t\t// Find the main entry for manifest extraction\n\t\tlet mainEntry: string | undefined;\n\t\tif (pkg.exports?.[\".\"] !== undefined) {\n\t\t\tconst mainExport = pkg.exports[\".\"];\n\t\t\tif (typeof mainExport === \"string\") {\n\t\t\t\tmainEntry = await resolveSourceEntry(pluginDir, mainExport);\n\t\t\t} else if (mainExport && typeof mainExport === \"object\" && \"import\" in mainExport) {\n\t\t\t\tmainEntry = await resolveSourceEntry(pluginDir, (mainExport as { import: string }).import);\n\t\t\t}\n\t\t}\n\t\tif (!mainEntry && pkg.main) {\n\t\t\tmainEntry = await resolveSourceEntry(pluginDir, pkg.main);\n\t\t}\n\t\tif (!mainEntry) {\n\t\t\tconst defaultMain = join(pluginDir, \"src/index.ts\");\n\t\t\tif (await fileExists(defaultMain)) {\n\t\t\t\tmainEntry = defaultMain;\n\t\t\t}\n\t\t}\n\n\t\tif (!mainEntry) {\n\t\t\tconsola.error(\n\t\t\t\t\"Cannot find plugin entrypoint. Expected src/index.ts or main/exports in package.json\",\n\t\t\t);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tconsola.info(`Main entry: ${mainEntry}`);\n\t\tif (backendEntry) consola.info(`Backend entry: ${backendEntry}`);\n\t\tif (adminEntry) consola.info(`Admin entry: ${adminEntry}`);\n\n\t\t// ── Step 2: Extract manifest by importing the plugin ──\n\n\t\tconsola.start(\"Extracting plugin manifest...\");\n\n\t\t// Build the main entry first so we can import it\n\t\tconst { build } = await import(\"tsdown\");\n\t\tconst tmpDir = join(pluginDir, \".emdash-bundle-tmp\");\n\n\t\ttry {\n\t\t\tawait mkdir(tmpDir, { recursive: true });\n\n\t\t\t// Build main entry to extract manifest.\n\t\t\t// Externalize emdash and sibling packages — they'll resolve\n\t\t\t// via the symlinked node_modules below.\n\t\t\tconst mainOutDir = join(tmpDir, \"main\");\n\t\t\tawait build({\n\t\t\t\tconfig: false,\n\t\t\t\tentry: [mainEntry],\n\t\t\t\tformat: \"esm\",\n\t\t\t\toutDir: mainOutDir,\n\t\t\t\tdts: false,\n\t\t\t\tplatform: \"node\",\n\t\t\t\texternal: [\"emdash\", emdash_SCOPE_RE],\n\t\t\t});\n\n\t\t\t// Symlink plugin's node_modules so the built module can resolve\n\t\t\t// external dependencies (emdash, @emdash-cms/*, etc.)\n\t\t\tconst pluginNodeModules = join(pluginDir, \"node_modules\");\n\t\t\tconst tmpNodeModules = join(mainOutDir, \"node_modules\");\n\t\t\tif (await fileExists(pluginNodeModules)) {\n\t\t\t\tawait symlink(pluginNodeModules, tmpNodeModules, \"junction\");\n\t\t\t}\n\n\t\t\t// Import the built module to get the resolved plugin\n\t\t\tconst mainBaseName = basename(mainEntry).replace(TS_EXT_RE, \"\");\n\t\t\tconst mainOutputPath = await findBuildOutput(mainOutDir, mainBaseName);\n\n\t\t\tif (!mainOutputPath) {\n\t\t\t\tconsola.error(\"Failed to build main entry — no output found in\", mainOutDir);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\t// Dynamic import of the built plugin\n\t\t\tconst pluginModule = (await import(mainOutputPath)) as Record<string, unknown>;\n\n\t\t\t// Extract manifest from the imported module.\n\t\t\t// Supports three patterns:\n\t\t\t// 1. Native: createPlugin() export -> ResolvedPlugin\n\t\t\t// 2. Native: default export that is/returns a ResolvedPlugin (has id+version)\n\t\t\t// 3. Standard: descriptor factory function (returns { id, version, ... })\n\t\t\tlet resolvedPlugin: ResolvedPlugin | undefined;\n\n\t\t\tif (typeof pluginModule.createPlugin === \"function\") {\n\t\t\t\tresolvedPlugin = pluginModule.createPlugin() as ResolvedPlugin;\n\t\t\t} else if (typeof pluginModule.default === \"function\") {\n\t\t\t\tresolvedPlugin = pluginModule.default() as ResolvedPlugin;\n\t\t\t} else if (typeof pluginModule.default === \"object\" && pluginModule.default !== null) {\n\t\t\t\tconst defaultExport = pluginModule.default as Record<string, unknown>;\n\t\t\t\tif (\"id\" in defaultExport && \"version\" in defaultExport) {\n\t\t\t\t\tresolvedPlugin = defaultExport as unknown as ResolvedPlugin;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Standard format: no createPlugin, no default with id/version.\n\t\t\t// Look for a descriptor factory -- any named export function that\n\t\t\t// returns an object with { id, version }.\n\t\t\tif (!resolvedPlugin) {\n\t\t\t\tfor (const [key, value] of Object.entries(pluginModule)) {\n\t\t\t\t\tif (key === \"default\" || typeof value !== \"function\") continue;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst result = (value as () => unknown)() as Record<string, unknown> | null;\n\t\t\t\t\t\tif (result && typeof result === \"object\" && \"id\" in result && \"version\" in result) {\n\t\t\t\t\t\t\tresolvedPlugin = {\n\t\t\t\t\t\t\t\tid: result.id,\n\t\t\t\t\t\t\t\tversion: result.version,\n\t\t\t\t\t\t\t\tcapabilities: result.capabilities ?? [],\n\t\t\t\t\t\t\t\tallowedHosts: result.allowedHosts ?? [],\n\t\t\t\t\t\t\t\tstorage: result.storage ?? {},\n\t\t\t\t\t\t\t\thooks: {},\n\t\t\t\t\t\t\t\troutes: {},\n\t\t\t\t\t\t\t\tadmin: {\n\t\t\t\t\t\t\t\t\tpages: result.adminPages,\n\t\t\t\t\t\t\t\t\twidgets: result.adminWidgets,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t} as ResolvedPlugin;\n\n\t\t\t\t\t\t\t// If there's a sandbox entry, build and import it\n\t\t\t\t\t\t\t// to get hook/route names for the manifest.\n\t\t\t\t\t\t\tif (backendEntry) {\n\t\t\t\t\t\t\t\tconst backendProbeDir = join(tmpDir, \"backend-probe\");\n\t\t\t\t\t\t\t\tconst probeShimDir = join(tmpDir, \"probe-shims\");\n\t\t\t\t\t\t\t\tawait mkdir(probeShimDir, { recursive: true });\n\t\t\t\t\t\t\t\tawait writeFile(\n\t\t\t\t\t\t\t\t\tjoin(probeShimDir, \"emdash.mjs\"),\n\t\t\t\t\t\t\t\t\t\"export const definePlugin = (d) => d;\\n\",\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tawait build({\n\t\t\t\t\t\t\t\t\tconfig: false,\n\t\t\t\t\t\t\t\t\tentry: [backendEntry],\n\t\t\t\t\t\t\t\t\tformat: \"esm\",\n\t\t\t\t\t\t\t\t\toutDir: backendProbeDir,\n\t\t\t\t\t\t\t\t\tdts: false,\n\t\t\t\t\t\t\t\t\tplatform: \"neutral\",\n\t\t\t\t\t\t\t\t\texternal: [],\n\t\t\t\t\t\t\t\t\talias: { emdash: join(probeShimDir, \"emdash.mjs\") },\n\t\t\t\t\t\t\t\t\ttreeshake: true,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tconst backendBaseName = basename(backendEntry).replace(TS_EXT_RE, \"\");\n\t\t\t\t\t\t\t\tconst backendProbePath = await findBuildOutput(backendProbeDir, backendBaseName);\n\t\t\t\t\t\t\t\tif (backendProbePath) {\n\t\t\t\t\t\t\t\t\tconst backendModule = (await import(backendProbePath)) as Record<string, unknown>;\n\t\t\t\t\t\t\t\t\tconst standardDef = (backendModule.default ?? {}) as Record<string, unknown>;\n\t\t\t\t\t\t\t\t\tconst hooks = standardDef.hooks as Record<string, unknown> | undefined;\n\t\t\t\t\t\t\t\t\tconst routes = standardDef.routes as Record<string, unknown> | undefined;\n\t\t\t\t\t\t\t\t\tif (hooks) {\n\t\t\t\t\t\t\t\t\t\tfor (const hookName of Object.keys(hooks)) {\n\t\t\t\t\t\t\t\t\t\t\tconst hookEntry = hooks[hookName];\n\t\t\t\t\t\t\t\t\t\t\tconst isConfig =\n\t\t\t\t\t\t\t\t\t\t\t\ttypeof hookEntry === \"object\" &&\n\t\t\t\t\t\t\t\t\t\t\t\thookEntry !== null &&\n\t\t\t\t\t\t\t\t\t\t\t\t\"handler\" in hookEntry;\n\t\t\t\t\t\t\t\t\t\t\tconst config = isConfig ? (hookEntry as Record<string, unknown>) : {};\n\t\t\t\t\t\t\t\t\t\t\t(resolvedPlugin.hooks as Record<string, unknown>)[hookName] = {\n\t\t\t\t\t\t\t\t\t\t\t\thandler: isConfig\n\t\t\t\t\t\t\t\t\t\t\t\t\t? (hookEntry as Record<string, unknown>).handler\n\t\t\t\t\t\t\t\t\t\t\t\t\t: hookEntry,\n\t\t\t\t\t\t\t\t\t\t\t\tpriority: (config.priority as number) ?? 100,\n\t\t\t\t\t\t\t\t\t\t\t\ttimeout: (config.timeout as number) ?? 5000,\n\t\t\t\t\t\t\t\t\t\t\t\tdependencies: (config.dependencies as string[]) ?? [],\n\t\t\t\t\t\t\t\t\t\t\t\terrorPolicy: (config.errorPolicy as string) ?? \"abort\",\n\t\t\t\t\t\t\t\t\t\t\t\texclusive: (config.exclusive as boolean) ?? false,\n\t\t\t\t\t\t\t\t\t\t\t\tpluginId: result.id,\n\t\t\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (routes) {\n\t\t\t\t\t\t\t\t\t\tfor (const [name, route] of Object.entries(routes)) {\n\t\t\t\t\t\t\t\t\t\t\tconst routeObj = route as Record<string, unknown>;\n\t\t\t\t\t\t\t\t\t\t\t(resolvedPlugin.routes as Record<string, unknown>)[name] = {\n\t\t\t\t\t\t\t\t\t\t\t\thandler: routeObj.handler,\n\t\t\t\t\t\t\t\t\t\t\t\tpublic: routeObj.public,\n\t\t\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Not a descriptor factory, skip\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!resolvedPlugin?.id || !resolvedPlugin?.version) {\n\t\t\t\tconsola.error(\n\t\t\t\t\t\"Could not extract plugin definition. Expected one of:\\n\" +\n\t\t\t\t\t\t\" - createPlugin() export (native format)\\n\" +\n\t\t\t\t\t\t\" - Descriptor factory function returning { id, version, ... } (standard format)\",\n\t\t\t\t);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\tconst manifest = extractManifest(resolvedPlugin);\n\n\t\t\t// Validate format consistency: bundled plugins are for the marketplace\n\t\t\t// (sandboxed), so they must be standard format without trusted-only features.\n\t\t\tif (resolvedPlugin.admin?.entry) {\n\t\t\t\tconsola.error(\n\t\t\t\t\t`Plugin declares adminEntry — React admin components require native/trusted mode. ` +\n\t\t\t\t\t\t`Use Block Kit for sandboxed admin pages, or remove adminEntry.`,\n\t\t\t\t);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t\tif (\n\t\t\t\tresolvedPlugin.admin?.portableTextBlocks &&\n\t\t\t\tresolvedPlugin.admin.portableTextBlocks.length > 0\n\t\t\t) {\n\t\t\t\tconsola.error(\n\t\t\t\t\t`Plugin declares portableTextBlocks — these require native/trusted mode ` +\n\t\t\t\t\t\t`and cannot be bundled for the marketplace.`,\n\t\t\t\t);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\tconsola.success(`Plugin: ${manifest.id}@${manifest.version}`);\n\t\t\tconsola.info(\n\t\t\t\t` Capabilities: ${manifest.capabilities.length > 0 ? manifest.capabilities.join(\", \") : \"(none)\"}`,\n\t\t\t);\n\t\t\tconsola.info(\n\t\t\t\t` Hooks: ${manifest.hooks.length > 0 ? manifest.hooks.map((h) => (typeof h === \"string\" ? h : h.name)).join(\", \") : \"(none)\"}`,\n\t\t\t);\n\t\t\tconsola.info(\n\t\t\t\t` Routes: ${manifest.routes.length > 0 ? manifest.routes.map((r) => (typeof r === \"string\" ? r : r.name)).join(\", \") : \"(none)\"}`,\n\t\t\t);\n\n\t\t\t// ── Step 3: Bundle backend.js ──\n\n\t\t\tconst bundleDir = join(tmpDir, \"bundle\");\n\t\t\tawait mkdir(bundleDir, { recursive: true });\n\n\t\t\tif (backendEntry) {\n\t\t\t\tconsola.start(\"Bundling backend...\");\n\n\t\t\t\t// Create a shim for emdash so the sandbox entry doesn't pull in the\n\t\t\t\t// entire core package. definePlugin is an identity function for standard\n\t\t\t\t// format, and PluginContext is a type-only import that disappears.\n\t\t\t\tconst shimDir = join(tmpDir, \"shims\");\n\t\t\t\tawait mkdir(shimDir, { recursive: true });\n\t\t\t\tawait writeFile(join(shimDir, \"emdash.mjs\"), \"export const definePlugin = (d) => d;\\n\");\n\n\t\t\t\tawait build({\n\t\t\t\t\tconfig: false,\n\t\t\t\t\tentry: [backendEntry],\n\t\t\t\t\tformat: \"esm\",\n\t\t\t\t\toutDir: join(tmpDir, \"backend\"),\n\t\t\t\t\tdts: false,\n\t\t\t\t\tplatform: \"neutral\",\n\t\t\t\t\t// Bundle everything for a self-contained sandbox file,\n\t\t\t\t\t// but alias emdash to our shim so we don't pull in the core.\n\t\t\t\t\texternal: [],\n\t\t\t\t\talias: { emdash: join(shimDir, \"emdash.mjs\") },\n\t\t\t\t\tminify: true,\n\t\t\t\t\ttreeshake: true,\n\t\t\t\t});\n\n\t\t\t\tconst backendBaseName = basename(backendEntry).replace(TS_EXT_RE, \"\");\n\t\t\t\tconst backendOutputPath = await findBuildOutput(join(tmpDir, \"backend\"), backendBaseName);\n\n\t\t\t\tif (backendOutputPath) {\n\t\t\t\t\tawait copyFile(backendOutputPath, join(bundleDir, \"backend.js\"));\n\t\t\t\t\tconsola.success(\"Built backend.js\");\n\t\t\t\t} else {\n\t\t\t\t\tconsola.error(\"Backend build produced no output\");\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconsola.warn(\"No sandbox entry found — bundle will have no backend.js\");\n\t\t\t\tconsola.warn(' Add a \"sandbox-entry.ts\" in src/ or a \"./sandbox\" export in package.json');\n\t\t\t}\n\n\t\t\t// ── Step 4: Bundle admin.js ──\n\n\t\t\tif (adminEntry) {\n\t\t\t\tconsola.start(\"Bundling admin...\");\n\t\t\t\tawait build({\n\t\t\t\t\tconfig: false,\n\t\t\t\t\tentry: [adminEntry],\n\t\t\t\t\tformat: \"esm\",\n\t\t\t\t\toutDir: join(tmpDir, \"admin\"),\n\t\t\t\t\tdts: false,\n\t\t\t\t\tplatform: \"neutral\",\n\t\t\t\t\texternal: [],\n\t\t\t\t\tminify: true,\n\t\t\t\t\ttreeshake: true,\n\t\t\t\t});\n\n\t\t\t\tconst adminBaseName = basename(adminEntry).replace(TS_EXT_RE, \"\");\n\t\t\t\tconst adminOutputPath = await findBuildOutput(join(tmpDir, \"admin\"), adminBaseName);\n\n\t\t\t\tif (adminOutputPath) {\n\t\t\t\t\tawait copyFile(adminOutputPath, join(bundleDir, \"admin.js\"));\n\t\t\t\t\tconsola.success(\"Built admin.js\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// ── Step 5: Write manifest.json ──\n\n\t\t\tawait writeFile(join(bundleDir, \"manifest.json\"), JSON.stringify(manifest, null, 2));\n\n\t\t\t// ── Step 6: Collect assets ──\n\n\t\t\tconsola.start(\"Collecting assets...\");\n\n\t\t\t// README.md\n\t\t\tconst readmePath = join(pluginDir, \"README.md\");\n\t\t\tif (await fileExists(readmePath)) {\n\t\t\t\tawait copyFile(readmePath, join(bundleDir, \"README.md\"));\n\t\t\t\tconsola.success(\"Included README.md\");\n\t\t\t}\n\n\t\t\t// icon.png\n\t\t\tconst iconPath = join(pluginDir, \"icon.png\");\n\t\t\tif (await fileExists(iconPath)) {\n\t\t\t\tconst iconBuf = await readFile(iconPath);\n\t\t\t\tconst dims = readImageDimensions(iconBuf);\n\t\t\t\tif (!dims) {\n\t\t\t\t\tconsola.warn(\"icon.png is not a valid PNG — skipping\");\n\t\t\t\t} else if (dims[0] !== ICON_SIZE || dims[1] !== ICON_SIZE) {\n\t\t\t\t\tconsola.warn(\n\t\t\t\t\t\t`icon.png is ${dims[0]}x${dims[1]}, expected ${ICON_SIZE}x${ICON_SIZE} — including anyway`,\n\t\t\t\t\t);\n\t\t\t\t\tawait copyFile(iconPath, join(bundleDir, \"icon.png\"));\n\t\t\t\t} else {\n\t\t\t\t\tawait copyFile(iconPath, join(bundleDir, \"icon.png\"));\n\t\t\t\t\tconsola.success(\"Included icon.png\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// screenshots/\n\t\t\tconst screenshotsDir = join(pluginDir, \"screenshots\");\n\t\t\tif (await fileExists(screenshotsDir)) {\n\t\t\t\tconst screenshotFiles = (await readdir(screenshotsDir))\n\t\t\t\t\t.filter((f) => {\n\t\t\t\t\t\tconst ext = extname(f).toLowerCase();\n\t\t\t\t\t\treturn ext === \".png\" || ext === \".jpg\" || ext === \".jpeg\";\n\t\t\t\t\t})\n\t\t\t\t\t.toSorted()\n\t\t\t\t\t.slice(0, MAX_SCREENSHOTS);\n\n\t\t\t\tif (screenshotFiles.length > 0) {\n\t\t\t\t\tawait mkdir(join(bundleDir, \"screenshots\"), { recursive: true });\n\n\t\t\t\t\tfor (const file of screenshotFiles) {\n\t\t\t\t\t\tconst filePath = join(screenshotsDir, file);\n\t\t\t\t\t\tconst buf = await readFile(filePath);\n\n\t\t\t\t\t\tconst dims = readImageDimensions(buf);\n\n\t\t\t\t\t\tif (!dims) {\n\t\t\t\t\t\t\tconsola.warn(`screenshots/${file} — cannot read dimensions, skipping`);\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (dims[0] > MAX_SCREENSHOT_WIDTH || dims[1] > MAX_SCREENSHOT_HEIGHT) {\n\t\t\t\t\t\t\tconsola.warn(\n\t\t\t\t\t\t\t\t`screenshots/${file} is ${dims[0]}x${dims[1]}, max ${MAX_SCREENSHOT_WIDTH}x${MAX_SCREENSHOT_HEIGHT} — including anyway`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tawait copyFile(filePath, join(bundleDir, \"screenshots\", file));\n\t\t\t\t\t}\n\n\t\t\t\t\tconsola.success(`Included ${screenshotFiles.length} screenshot(s)`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// ── Step 7: Validation ──\n\n\t\t\tconsola.start(\"Validating bundle...\");\n\t\t\tlet hasErrors = false;\n\n\t\t\t// Check for Node.js builtins in backend.js\n\t\t\tconst backendPath = join(bundleDir, \"backend.js\");\n\t\t\tif (await fileExists(backendPath)) {\n\t\t\t\tconst backendCode = await readFile(backendPath, \"utf-8\");\n\t\t\t\tconst builtins = findNodeBuiltinImports(backendCode);\n\t\t\t\tif (builtins.length > 0) {\n\t\t\t\t\tconsola.error(`backend.js imports Node.js built-in modules: ${builtins.join(\", \")}`);\n\t\t\t\t\tconsola.error(\"Sandboxed plugins cannot use Node.js APIs\");\n\t\t\t\t\thasErrors = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check capabilities warnings\n\t\t\tif (manifest.capabilities.includes(\"network:fetch:any\")) {\n\t\t\t\tconsola.warn(\n\t\t\t\t\t\"Plugin declares unrestricted network access (network:fetch:any) — it can make requests to any host\",\n\t\t\t\t);\n\t\t\t} else if (\n\t\t\t\tmanifest.capabilities.includes(\"network:fetch\") &&\n\t\t\t\tmanifest.allowedHosts.length === 0\n\t\t\t) {\n\t\t\t\tconsola.warn(\n\t\t\t\t\t\"Plugin declares network:fetch capability but no allowedHosts — all fetch requests will be blocked\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Check for features that won't work in sandboxed mode\n\t\t\tif (\n\t\t\t\tresolvedPlugin.admin?.portableTextBlocks &&\n\t\t\t\tresolvedPlugin.admin.portableTextBlocks.length > 0\n\t\t\t) {\n\t\t\t\tconsola.warn(\n\t\t\t\t\t\"Plugin declares portableTextBlocks — these require trusted mode and will be ignored in sandboxed plugins\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (resolvedPlugin.admin?.entry) {\n\t\t\t\tconsola.warn(\n\t\t\t\t\t\"Plugin declares admin.entry — custom React components require trusted mode. Use Block Kit for sandboxed admin pages\",\n\t\t\t\t);\n\t\t\t}\n\t\t\t// Check for page:fragments hook — trusted-only, not allowed in sandbox\n\t\t\tif (resolvedPlugin.hooks[\"page:fragments\"]) {\n\t\t\t\tconsola.warn(\n\t\t\t\t\t\"Plugin declares page:fragments hook — this is trusted-only and will not work in sandboxed mode\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Check: if plugin declares admin pages or widgets, it must have an \"admin\" route\n\t\t\tconst hasAdminPages = (manifest.admin?.pages?.length ?? 0) > 0;\n\t\t\tconst hasAdminWidgets = (manifest.admin?.widgets?.length ?? 0) > 0;\n\t\t\tif (hasAdminPages || hasAdminWidgets) {\n\t\t\t\tconst routeNames = manifest.routes.map((r: string | { name: string }) =>\n\t\t\t\t\ttypeof r === \"string\" ? r : r.name,\n\t\t\t\t);\n\t\t\t\tif (!routeNames.includes(\"admin\")) {\n\t\t\t\t\tconsola.error(\n\t\t\t\t\t\t`Plugin declares ${hasAdminPages ? \"adminPages\" : \"\"}${hasAdminPages && hasAdminWidgets ? \" and \" : \"\"}${hasAdminWidgets ? \"adminWidgets\" : \"\"} ` +\n\t\t\t\t\t\t\t`but the sandbox entry has no \"admin\" route. ` +\n\t\t\t\t\t\t\t`Add an admin route handler to serve Block Kit pages.`,\n\t\t\t\t\t);\n\t\t\t\t\thasErrors = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Calculate total bundle size\n\t\t\tconst totalSize = await calculateDirectorySize(bundleDir);\n\t\t\tif (totalSize > MAX_BUNDLE_SIZE) {\n\t\t\t\tconst sizeMB = (totalSize / 1024 / 1024).toFixed(2);\n\t\t\t\tconsola.error(`Bundle size ${sizeMB}MB exceeds maximum of 5MB`);\n\t\t\t\thasErrors = true;\n\t\t\t} else {\n\t\t\t\tconst sizeKB = (totalSize / 1024).toFixed(1);\n\t\t\t\tconsola.info(`Bundle size: ${sizeKB}KB`);\n\t\t\t}\n\n\t\t\tif (hasErrors) {\n\t\t\t\tconsola.error(\"Bundle validation failed\");\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\tconsola.success(\"Validation passed\");\n\n\t\t\tif (validateOnly) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// ── Step 8: Create tarball ──\n\n\t\t\tawait mkdir(outDir, { recursive: true });\n\t\t\tconst tarballName = `${manifest.id.replace(SLASH_RE, \"-\").replace(LEADING_AT_RE, \"\")}-${manifest.version}.tar.gz`;\n\t\t\tconst tarballPath = join(outDir, tarballName);\n\n\t\t\tconsola.start(\"Creating tarball...\");\n\t\t\tawait createTarball(bundleDir, tarballPath);\n\n\t\t\tconst tarballStat = await stat(tarballPath);\n\t\t\tconst tarballSizeKB = (tarballStat.size / 1024).toFixed(1);\n\n\t\t\t// Calculate checksum\n\t\t\tconst tarballBuf = await readFile(tarballPath);\n\t\t\tconst checksum = createHash(\"sha256\").update(tarballBuf).digest(\"hex\");\n\n\t\t\tconsola.success(`Created ${tarballName} (${tarballSizeKB}KB)`);\n\t\t\tconsola.info(` SHA-256: ${checksum}`);\n\t\t\tconsola.info(` Path: ${tarballPath}`);\n\t\t} finally {\n\t\t\tif (tmpDir.endsWith(\".emdash-bundle-tmp\")) {\n\t\t\t\tawait rm(tmpDir, { recursive: true, force: true });\n\t\t\t}\n\t\t}\n\t},\n});\n","/**\n * emdash plugin init\n *\n * Scaffold a new EmDash plugin. Generates the standard-format boilerplate:\n * src/index.ts -- descriptor factory\n * src/sandbox-entry.ts -- definePlugin({ hooks, routes })\n * package.json\n * tsconfig.json\n *\n * Use --native to generate native-format boilerplate instead (createPlugin + React admin).\n *\n */\n\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { resolve, join, basename } from \"node:path\";\n\nimport { defineCommand } from \"citty\";\nimport consola from \"consola\";\n\nimport { fileExists } from \"./bundle-utils.js\";\n\nconst SLUG_RE = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;\nconst SCOPE_RE = /^@[^/]+\\//;\n\nexport const pluginInitCommand = defineCommand({\n\tmeta: {\n\t\tname: \"init\",\n\t\tdescription: \"Scaffold a new plugin\",\n\t},\n\targs: {\n\t\tdir: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Directory to create the plugin in (default: current directory)\",\n\t\t\tdefault: \".\",\n\t\t},\n\t\tname: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Plugin name/id (e.g. my-plugin or @org/my-plugin)\",\n\t\t},\n\t\tnative: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Generate native-format plugin (createPlugin + React admin)\",\n\t\t\tdefault: false,\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst targetDir = resolve(args.dir);\n\t\tconst isNative = args.native;\n\n\t\t// Derive plugin name from --name or directory name\n\t\tlet pluginName = args.name || basename(targetDir);\n\t\tif (!pluginName || pluginName === \".\") {\n\t\t\tpluginName = basename(resolve(\".\"));\n\t\t}\n\n\t\t// Strip scope for the slug\n\t\tconst slug = pluginName.replace(SCOPE_RE, \"\");\n\t\tif (!SLUG_RE.test(slug)) {\n\t\t\tconsola.error(\n\t\t\t\t`Invalid plugin name \"${pluginName}\". ` +\n\t\t\t\t\t\"Use lowercase letters, numbers, and hyphens (e.g. my-plugin).\",\n\t\t\t);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\t// Check if directory already has files\n\t\tconst srcDir = join(targetDir, \"src\");\n\t\tconst pkgPath = join(targetDir, \"package.json\");\n\t\tif (await fileExists(pkgPath)) {\n\t\t\tconsola.error(`package.json already exists in ${targetDir}`);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tconsola.start(`Scaffolding ${isNative ? \"native\" : \"standard\"} plugin: ${pluginName}`);\n\n\t\tawait mkdir(srcDir, { recursive: true });\n\n\t\tif (isNative) {\n\t\t\tawait scaffoldNative(targetDir, srcDir, pluginName, slug);\n\t\t} else {\n\t\t\tawait scaffoldStandard(targetDir, srcDir, pluginName, slug);\n\t\t}\n\n\t\tconsola.success(`Plugin scaffolded in ${targetDir}`);\n\t\tconsola.info(\"Next steps:\");\n\t\tif (args.dir !== \".\") {\n\t\t\tconsola.info(` 1. cd ${args.dir}`);\n\t\t}\n\t\tconsola.info(` ${args.dir !== \".\" ? \"2\" : \"1\"}. pnpm install`);\n\t\tif (isNative) {\n\t\t\tconsola.info(` ${args.dir !== \".\" ? \"3\" : \"2\"}. Edit src/index.ts to add hooks and routes`);\n\t\t} else {\n\t\t\tconsola.info(\n\t\t\t\t` ${args.dir !== \".\" ? \"3\" : \"2\"}. Edit src/sandbox-entry.ts to add hooks and routes`,\n\t\t\t);\n\t\t}\n\t\tconsola.info(` ${args.dir !== \".\" ? \"4\" : \"3\"}. emdash plugin validate --dir .`);\n\t},\n});\n\n// ── Standard format scaffolding ──────────────────────────────────\n\nasync function scaffoldStandard(\n\ttargetDir: string,\n\tsrcDir: string,\n\tpluginName: string,\n\tslug: string,\n): Promise<void> {\n\t// Derive the camelCase function name from slug\n\tconst fnName = slug\n\t\t.split(\"-\")\n\t\t.map((s, i) => (i === 0 ? s : s[0].toUpperCase() + s.slice(1)))\n\t\t.join(\"\");\n\n\t// package.json\n\tawait writeFile(\n\t\tjoin(targetDir, \"package.json\"),\n\t\tJSON.stringify(\n\t\t\t{\n\t\t\t\tname: pluginName,\n\t\t\t\tversion: \"0.1.0\",\n\t\t\t\ttype: \"module\",\n\t\t\t\texports: {\n\t\t\t\t\t\".\": \"./src/index.ts\",\n\t\t\t\t\t\"./sandbox\": \"./src/sandbox-entry.ts\",\n\t\t\t\t},\n\t\t\t\tfiles: [\"src\"],\n\t\t\t\tpeerDependencies: {\n\t\t\t\t\temdash: \"*\",\n\t\t\t\t},\n\t\t\t},\n\t\t\tnull,\n\t\t\t\"\\t\",\n\t\t) + \"\\n\",\n\t);\n\n\t// tsconfig.json\n\tawait writeFile(\n\t\tjoin(targetDir, \"tsconfig.json\"),\n\t\tJSON.stringify(\n\t\t\t{\n\t\t\t\tcompilerOptions: {\n\t\t\t\t\ttarget: \"ES2022\",\n\t\t\t\t\tmodule: \"preserve\",\n\t\t\t\t\tmoduleResolution: \"bundler\",\n\t\t\t\t\tstrict: true,\n\t\t\t\t\tesModuleInterop: true,\n\t\t\t\t\tdeclaration: true,\n\t\t\t\t\toutDir: \"./dist\",\n\t\t\t\t\trootDir: \"./src\",\n\t\t\t\t},\n\t\t\t\tinclude: [\"src/**/*\"],\n\t\t\t\texclude: [\"node_modules\", \"dist\"],\n\t\t\t},\n\t\t\tnull,\n\t\t\t\"\\t\",\n\t\t) + \"\\n\",\n\t);\n\n\t// src/index.ts -- descriptor factory\n\tawait writeFile(\n\t\tjoin(srcDir, \"index.ts\"),\n\t\t`import type { PluginDescriptor } from \"emdash\";\n\nexport function ${fnName}Plugin(): PluginDescriptor {\n\\treturn {\n\\t\\tid: \"${pluginName}\",\n\\t\\tversion: \"0.1.0\",\n\\t\\tformat: \"standard\",\n\\t\\tentrypoint: \"${pluginName}/sandbox\",\n\\t\\tcapabilities: [],\n\\t};\n}\n`,\n\t);\n\n\t// src/sandbox-entry.ts -- plugin definition\n\tawait writeFile(\n\t\tjoin(srcDir, \"sandbox-entry.ts\"),\n\t\t`import { definePlugin } from \"emdash\";\nimport type { PluginContext } from \"emdash\";\n\nexport default definePlugin({\n\\thooks: {\n\\t\\t\"content:afterSave\": {\n\\t\\t\\thandler: async (event: any, ctx: PluginContext) => {\n\\t\\t\\t\\tctx.log.info(\"Content saved\", {\n\\t\\t\\t\\t\\tcollection: event.collection,\n\\t\\t\\t\\t\\tid: event.content.id,\n\\t\\t\\t\\t});\n\\t\\t\\t},\n\\t\\t},\n\\t},\n});\n`,\n\t);\n}\n\n// ── Native format scaffolding ────────────────────────────────────\n\nasync function scaffoldNative(\n\ttargetDir: string,\n\tsrcDir: string,\n\tpluginName: string,\n\tslug: string,\n): Promise<void> {\n\tconst fnName = slug\n\t\t.split(\"-\")\n\t\t.map((s, i) => (i === 0 ? s : s[0].toUpperCase() + s.slice(1)))\n\t\t.join(\"\");\n\n\t// package.json\n\tawait writeFile(\n\t\tjoin(targetDir, \"package.json\"),\n\t\tJSON.stringify(\n\t\t\t{\n\t\t\t\tname: pluginName,\n\t\t\t\tversion: \"0.1.0\",\n\t\t\t\ttype: \"module\",\n\t\t\t\texports: {\n\t\t\t\t\t\".\": \"./src/index.ts\",\n\t\t\t\t},\n\t\t\t\tfiles: [\"src\"],\n\t\t\t\tpeerDependencies: {\n\t\t\t\t\temdash: \"*\",\n\t\t\t\t},\n\t\t\t},\n\t\t\tnull,\n\t\t\t\"\\t\",\n\t\t) + \"\\n\",\n\t);\n\n\t// tsconfig.json\n\tawait writeFile(\n\t\tjoin(targetDir, \"tsconfig.json\"),\n\t\tJSON.stringify(\n\t\t\t{\n\t\t\t\tcompilerOptions: {\n\t\t\t\t\ttarget: \"ES2022\",\n\t\t\t\t\tmodule: \"preserve\",\n\t\t\t\t\tmoduleResolution: \"bundler\",\n\t\t\t\t\tstrict: true,\n\t\t\t\t\tesModuleInterop: true,\n\t\t\t\t\tdeclaration: true,\n\t\t\t\t\toutDir: \"./dist\",\n\t\t\t\t\trootDir: \"./src\",\n\t\t\t\t},\n\t\t\t\tinclude: [\"src/**/*\"],\n\t\t\t\texclude: [\"node_modules\", \"dist\"],\n\t\t\t},\n\t\t\tnull,\n\t\t\t\"\\t\",\n\t\t) + \"\\n\",\n\t);\n\n\t// src/index.ts -- descriptor + createPlugin\n\tawait writeFile(\n\t\tjoin(srcDir, \"index.ts\"),\n\t\t`import { definePlugin } from \"emdash\";\nimport type { PluginDescriptor } from \"emdash\";\n\nexport function ${fnName}Plugin(): PluginDescriptor {\n\\treturn {\n\\t\\tid: \"${pluginName}\",\n\\t\\tversion: \"0.1.0\",\n\\t\\tformat: \"native\",\n\\t\\tentrypoint: \"${pluginName}\",\n\\t\\toptions: {},\n\\t};\n}\n\nexport function createPlugin() {\n\\treturn definePlugin({\n\\t\\tid: \"${pluginName}\",\n\\t\\tversion: \"0.1.0\",\n\n\\t\\thooks: {\n\\t\\t\\t\"content:afterSave\": async (event, ctx) => {\n\\t\\t\\t\\tctx.log.info(\"Content saved\", {\n\\t\\t\\t\\t\\tcollection: event.collection,\n\\t\\t\\t\\t\\tid: event.content.id,\n\\t\\t\\t\\t});\n\\t\\t\\t},\n\\t\\t},\n\\t});\n}\n\nexport default createPlugin;\n`,\n\t);\n}\n","/**\n * emdash plugin validate\n *\n * Runs bundle validation without producing a tarball.\n * Thin wrapper around `emdash plugin bundle --validate-only`.\n *\n */\n\nimport { defineCommand, runCommand } from \"citty\";\n\nimport { bundleCommand } from \"./bundle.js\";\n\nexport const pluginValidateCommand = defineCommand({\n\tmeta: {\n\t\tname: \"validate\",\n\t\tdescription: \"Validate a plugin without producing a tarball (same checks as bundle)\",\n\t},\n\targs: {\n\t\tdir: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Plugin directory (default: current directory)\",\n\t\t\tdefault: \".\",\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\t// Delegate to the bundle command with validateOnly flag\n\t\tawait runCommand(bundleCommand, {\n\t\t\trawArgs: [\"--dir\", args.dir, \"--validateOnly\"],\n\t\t});\n\t},\n});\n","/**\n * emdash plugin publish\n *\n * Publishes a plugin tarball to the EmDash Marketplace.\n *\n * Flow:\n * 1. Resolve tarball (from --tarball path, or build via `emdash plugin bundle`)\n * 2. Read manifest.json from tarball to show summary\n * 3. Authenticate (stored credential or GitHub device flow)\n * 4. Pre-publish validation (check plugin exists, version not published)\n * 5. Upload via multipart POST\n * 6. Display audit results\n */\n\nimport { readFile, stat } from \"node:fs/promises\";\nimport { resolve, basename } from \"node:path\";\n\nimport { defineCommand } from \"citty\";\nimport consola from \"consola\";\nimport { createGzipDecoder, unpackTar } from \"modern-tar\";\nimport pc from \"picocolors\";\n\nimport { pluginManifestSchema } from \"../../plugins/manifest-schema.js\";\nimport {\n\tgetMarketplaceCredential,\n\tsaveMarketplaceCredential,\n\tremoveMarketplaceCredential,\n} from \"../credentials.js\";\n\nconst DEFAULT_REGISTRY = \"https://marketplace.emdashcms.com\";\n\n// ── GitHub Device Flow ──────────────────────────────────────────\n\ninterface DeviceCodeResponse {\n\tdevice_code: string;\n\tuser_code: string;\n\tverification_uri: string;\n\texpires_in: number;\n\tinterval: number;\n}\n\ninterface GitHubTokenResponse {\n\taccess_token?: string;\n\ttoken_type?: string;\n\terror?: string;\n\terror_description?: string;\n\tinterval?: number;\n}\n\ninterface MarketplaceAuthResponse {\n\ttoken: string;\n\tauthor: {\n\t\tid: string;\n\t\tname: string;\n\t\tavatarUrl: string;\n\t};\n}\n\ninterface AuthDiscovery {\n\tgithub: {\n\t\tclientId: string;\n\t\tdeviceAuthorizationEndpoint: string;\n\t\ttokenEndpoint: string;\n\t};\n\tmarketplace: {\n\t\tdeviceTokenEndpoint: string;\n\t};\n}\n\n/**\n * Authenticate with the marketplace via GitHub Device Flow.\n * Returns the marketplace JWT and author info.\n */\nasync function authenticateViaDeviceFlow(registryUrl: string): Promise<MarketplaceAuthResponse> {\n\t// Step 1: Fetch auth discovery to get GitHub client_id\n\tconsola.start(\"Fetching auth configuration...\");\n\tconst discoveryRes = await fetch(new URL(\"/api/v1/auth/discovery\", registryUrl));\n\tif (!discoveryRes.ok) {\n\t\tthrow new Error(`Marketplace unreachable: ${discoveryRes.status} ${discoveryRes.statusText}`);\n\t}\n\tconst discovery = (await discoveryRes.json()) as AuthDiscovery;\n\n\t// Step 2: Request device code from GitHub\n\tconst deviceRes = await fetch(discovery.github.deviceAuthorizationEndpoint, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\tAccept: \"application/json\",\n\t\t},\n\t\tbody: JSON.stringify({\n\t\t\tclient_id: discovery.github.clientId,\n\t\t\tscope: \"read:user user:email\",\n\t\t}),\n\t});\n\n\tif (!deviceRes.ok) {\n\t\tthrow new Error(`GitHub device flow failed: ${deviceRes.status}`);\n\t}\n\n\tconst deviceCode = (await deviceRes.json()) as DeviceCodeResponse;\n\n\t// Step 3: Display instructions\n\tconsole.log();\n\tconsola.info(\"Open your browser to:\");\n\tconsole.log(` ${pc.cyan(pc.bold(deviceCode.verification_uri))}`);\n\tconsole.log();\n\tconsola.info(`Enter code: ${pc.yellow(pc.bold(deviceCode.user_code))}`);\n\tconsole.log();\n\n\t// Try to open browser\n\ttry {\n\t\tconst { execFile } = await import(\"node:child_process\");\n\t\tif (process.platform === \"darwin\") {\n\t\t\texecFile(\"open\", [deviceCode.verification_uri]);\n\t\t} else if (process.platform === \"win32\") {\n\t\t\texecFile(\"cmd\", [\"/c\", \"start\", \"\", deviceCode.verification_uri]);\n\t\t} else {\n\t\t\texecFile(\"xdg-open\", [deviceCode.verification_uri]);\n\t\t}\n\t} catch {\n\t\t// User can open manually\n\t}\n\n\t// Step 4: Poll GitHub for access token\n\tconsola.start(\"Waiting for authorization...\");\n\tconst githubToken = await pollGitHubDeviceFlow(\n\t\tdiscovery.github.tokenEndpoint,\n\t\tdiscovery.github.clientId,\n\t\tdeviceCode.device_code,\n\t\tdeviceCode.interval,\n\t\tdeviceCode.expires_in,\n\t);\n\n\t// Step 5: Exchange GitHub token for marketplace JWT\n\tconsola.start(\"Authenticating with marketplace...\");\n\tconst deviceTokenUrl = new URL(discovery.marketplace.deviceTokenEndpoint, registryUrl);\n\tconst authRes = await fetch(deviceTokenUrl, {\n\t\tmethod: \"POST\",\n\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\tbody: JSON.stringify({ access_token: githubToken }),\n\t});\n\n\tif (!authRes.ok) {\n\t\tconst body = (await authRes.json().catch(() => ({}))) as { error?: string };\n\t\tthrow new Error(`Marketplace auth failed: ${body.error ?? authRes.statusText}`);\n\t}\n\n\treturn (await authRes.json()) as MarketplaceAuthResponse;\n}\n\nasync function pollGitHubDeviceFlow(\n\ttokenEndpoint: string,\n\tclientId: string,\n\tdeviceCode: string,\n\tinterval: number,\n\texpiresIn: number,\n): Promise<string> {\n\tconst deadline = Date.now() + expiresIn * 1000;\n\tlet currentInterval = interval;\n\n\twhile (Date.now() < deadline) {\n\t\tawait new Promise((r) => setTimeout(r, currentInterval * 1000));\n\n\t\tconst res = await fetch(tokenEndpoint, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\tAccept: \"application/json\",\n\t\t\t},\n\t\t\tbody: JSON.stringify({\n\t\t\t\tclient_id: clientId,\n\t\t\t\tdevice_code: deviceCode,\n\t\t\t\tgrant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n\t\t\t}),\n\t\t});\n\n\t\tconst body = (await res.json()) as GitHubTokenResponse;\n\n\t\tif (body.access_token) {\n\t\t\treturn body.access_token;\n\t\t}\n\n\t\tif (body.error === \"authorization_pending\") continue;\n\t\tif (body.error === \"slow_down\") {\n\t\t\tcurrentInterval = body.interval ?? currentInterval + 5;\n\t\t\tcontinue;\n\t\t}\n\t\tif (body.error === \"expired_token\") {\n\t\t\tthrow new Error(\"Device code expired. Please try again.\");\n\t\t}\n\t\tif (body.error === \"access_denied\") {\n\t\t\tthrow new Error(\"Authorization was denied.\");\n\t\t}\n\n\t\tthrow new Error(`GitHub token exchange failed: ${body.error ?? \"unknown error\"}`);\n\t}\n\n\tthrow new Error(\"Device code expired (timeout). Please try again.\");\n}\n\n// ── Tarball reading ─────────────────────────────────────────────\n\nconst manifestSummarySchema = pluginManifestSchema.pick({\n\tid: true,\n\tversion: true,\n\tcapabilities: true,\n\tallowedHosts: true,\n});\n\ntype ManifestSummary = typeof manifestSummarySchema._zod.output;\n\n/**\n * Read manifest.json from a tarball without fully extracting it.\n */\nasync function readManifestFromTarball(tarballPath: string): Promise<ManifestSummary> {\n\tconst data = await readFile(tarballPath);\n\tconst stream = new ReadableStream<Uint8Array>({\n\t\tstart(controller) {\n\t\t\tcontroller.enqueue(new Uint8Array(data.buffer, data.byteOffset, data.byteLength));\n\t\t\tcontroller.close();\n\t\t},\n\t});\n\n\tconst entries = await unpackTar(stream.pipeThrough(createGzipDecoder()), {\n\t\tfilter: (header) => header.name === \"manifest.json\",\n\t});\n\n\tconst manifest = entries.find((e) => e.header.name === \"manifest.json\");\n\tif (!manifest?.data) {\n\t\tthrow new Error(\"Tarball does not contain manifest.json\");\n\t}\n\n\tconst content = new TextDecoder().decode(manifest.data);\n\tconst parsed: unknown = JSON.parse(content);\n\tconst result = manifestSummarySchema.safeParse(parsed);\n\tif (!result.success) {\n\t\tthrow new Error(`Invalid manifest.json: ${result.error.message}`);\n\t}\n\treturn result.data;\n}\n\n// ── Audit polling helpers ───────────────────────────────────────\n\nconst POLL_INTERVAL_MS = 3000;\nconst POLL_TIMEOUT_MS = 120_000; // 2 minutes\n\ninterface VersionStatusResponse {\n\tversion: string;\n\tstatus: string;\n\taudit_verdict?: string | null;\n\taudit_id?: string | null;\n\timage_audit_verdict?: string | null;\n}\n\n/**\n * Poll the version endpoint until status leaves \"pending\" or timeout.\n * Returns the final version data, or null on timeout.\n */\nasync function pollVersionStatus(\n\tversionUrl: string,\n\ttoken: string,\n): Promise<VersionStatusResponse | null> {\n\tconst deadline = Date.now() + POLL_TIMEOUT_MS;\n\n\twhile (Date.now() < deadline) {\n\t\tawait new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));\n\n\t\ttry {\n\t\t\tconst res = await fetch(versionUrl, {\n\t\t\t\theaders: { Authorization: `Bearer ${token}` },\n\t\t\t});\n\n\t\t\tif (!res.ok) continue;\n\n\t\t\tconst data = (await res.json()) as VersionStatusResponse;\n\t\t\tif (data.status !== \"pending\") {\n\t\t\t\treturn data;\n\t\t\t}\n\t\t} catch {\n\t\t\t// Network error — retry\n\t\t}\n\t}\n\n\treturn null;\n}\n\nfunction displayAuditResults(version: VersionStatusResponse): void {\n\tconst statusColor =\n\t\tversion.status === \"published\" ? pc.green : version.status === \"flagged\" ? pc.yellow : pc.red;\n\tconsola.info(` Status: ${statusColor(version.status)}`);\n\n\tif (version.audit_verdict) {\n\t\tconst verdictColor =\n\t\t\tversion.audit_verdict === \"pass\"\n\t\t\t\t? pc.green\n\t\t\t\t: version.audit_verdict === \"warn\"\n\t\t\t\t\t? pc.yellow\n\t\t\t\t\t: pc.red;\n\t\tconsola.info(` Audit: ${verdictColor(version.audit_verdict)}`);\n\t}\n\n\tif (version.image_audit_verdict) {\n\t\tconst verdictColor =\n\t\t\tversion.image_audit_verdict === \"pass\"\n\t\t\t\t? pc.green\n\t\t\t\t: version.image_audit_verdict === \"warn\"\n\t\t\t\t\t? pc.yellow\n\t\t\t\t\t: pc.red;\n\t\tconsola.info(` Image audit: ${verdictColor(version.image_audit_verdict)}`);\n\t}\n}\n\nfunction displayInlineAuditResults(\n\taudit: {\n\t\tverdict: string;\n\t\triskScore: number;\n\t\tsummary: string;\n\t\tfindings: { category: string; severity: string; description: string }[];\n\t},\n\timageAudit: { verdict: string } | null,\n): void {\n\tconst verdictColor =\n\t\taudit.verdict === \"pass\" ? pc.green : audit.verdict === \"warn\" ? pc.yellow : pc.red;\n\tconsola.info(` Audit: ${verdictColor(audit.verdict)} (risk: ${audit.riskScore}/100)`);\n\tif (audit.findings.length > 0) {\n\t\tfor (const finding of audit.findings) {\n\t\t\tconst icon = finding.severity === \"high\" ? pc.red(\"!\") : pc.yellow(\"~\");\n\t\t\tconsola.info(` ${icon} [${finding.category}] ${finding.description}`);\n\t\t}\n\t}\n\n\tif (imageAudit) {\n\t\tconst imgColor =\n\t\t\timageAudit.verdict === \"pass\" ? pc.green : imageAudit.verdict === \"warn\" ? pc.yellow : pc.red;\n\t\tconsola.info(` Image audit: ${imgColor(imageAudit.verdict)}`);\n\t}\n}\n\n// ── Publish command ─────────────────────────────────────────────\n\nexport const publishCommand = defineCommand({\n\tmeta: {\n\t\tname: \"publish\",\n\t\tdescription: \"Publish a plugin to the EmDash Marketplace\",\n\t},\n\targs: {\n\t\ttarball: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Path to plugin tarball (default: build first via `emdash plugin bundle`)\",\n\t\t},\n\t\tdir: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Plugin directory (used with --build, default: current directory)\",\n\t\t\tdefault: process.cwd(),\n\t\t},\n\t\tbuild: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Build the plugin before publishing\",\n\t\t\tdefault: false,\n\t\t},\n\t\tregistry: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Marketplace registry URL\",\n\t\t\tdefault: DEFAULT_REGISTRY,\n\t\t},\n\t\t\"no-wait\": {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Exit immediately after upload without waiting for audit (useful for CI)\",\n\t\t\tdefault: false,\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst registryUrl = args.registry;\n\n\t\t// ── Step 1: Resolve tarball ──\n\n\t\tlet tarballPath: string;\n\n\t\tif (args.tarball) {\n\t\t\ttarballPath = resolve(args.tarball);\n\t\t} else if (args.build) {\n\t\t\t// Build first, then find the output tarball\n\t\t\tconsola.start(\"Building plugin...\");\n\t\t\tconst pluginDir = resolve(args.dir);\n\t\t\ttry {\n\t\t\t\tconst { runCommand } = await import(\"citty\");\n\t\t\t\tconst { bundleCommand } = await import(\"./bundle.js\");\n\t\t\t\tawait runCommand(bundleCommand, {\n\t\t\t\t\trawArgs: [\"--dir\", pluginDir],\n\t\t\t\t});\n\t\t\t} catch {\n\t\t\t\tconsola.error(\"Build failed\");\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\t// Find the tarball in dist/\n\t\t\tconst { readdir } = await import(\"node:fs/promises\");\n\t\t\tconst distDir = resolve(pluginDir, \"dist\");\n\t\t\tconst files = await readdir(distDir);\n\t\t\tconst tarball = files.find((f) => f.endsWith(\".tar.gz\"));\n\t\t\tif (!tarball) {\n\t\t\t\tconsola.error(\"Build succeeded but no .tar.gz found in dist/\");\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t\ttarballPath = resolve(distDir, tarball);\n\t\t} else {\n\t\t\t// Look for an existing tarball in dist/\n\t\t\tconst pluginDir = resolve(args.dir);\n\t\t\tconst { readdir } = await import(\"node:fs/promises\");\n\t\t\ttry {\n\t\t\t\tconst distDir = resolve(pluginDir, \"dist\");\n\t\t\t\tconst files = await readdir(distDir);\n\t\t\t\tconst tarball = files.find((f) => f.endsWith(\".tar.gz\"));\n\t\t\t\tif (tarball) {\n\t\t\t\t\ttarballPath = resolve(distDir, tarball);\n\t\t\t\t} else {\n\t\t\t\t\tconsola.error(\"No tarball found. Run `emdash plugin bundle` first or use --build.\");\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\tconsola.error(\"No dist/ directory found. Run `emdash plugin bundle` first or use --build.\");\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t}\n\n\t\tconst tarballStat = await stat(tarballPath);\n\t\tconst sizeKB = (tarballStat.size / 1024).toFixed(1);\n\t\tconsola.info(`Tarball: ${pc.dim(tarballPath)} (${sizeKB}KB)`);\n\n\t\t// ── Step 2: Read manifest from tarball ──\n\n\t\tconst manifest = await readManifestFromTarball(tarballPath);\n\t\tconsole.log();\n\t\tconsola.info(`Plugin: ${pc.bold(`${manifest.id}@${manifest.version}`)}`);\n\t\tif (manifest.capabilities.length > 0) {\n\t\t\tconsola.info(`Capabilities: ${manifest.capabilities.join(\", \")}`);\n\t\t}\n\t\tif (manifest.allowedHosts?.length) {\n\t\t\tconsola.info(`Allowed hosts: ${manifest.allowedHosts.join(\", \")}`);\n\t\t}\n\t\tconsole.log();\n\n\t\t// ── Step 3: Authenticate ──\n\t\t//\n\t\t// Priority: EMDASH_MARKETPLACE_TOKEN env var > stored credential > interactive device flow.\n\t\t// The env var enables CI pipelines (including seed token auth) without interactive login.\n\n\t\tlet token: string;\n\t\tconst envToken = process.env.EMDASH_MARKETPLACE_TOKEN;\n\t\tconst stored = !envToken ? getMarketplaceCredential(registryUrl) : null;\n\n\t\tif (envToken) {\n\t\t\ttoken = envToken;\n\t\t\tconsola.info(\"Using EMDASH_MARKETPLACE_TOKEN for authentication\");\n\t\t} else if (stored) {\n\t\t\ttoken = stored.token;\n\t\t\tconsola.info(`Authenticated as ${pc.bold(stored.author?.name ?? \"unknown\")}`);\n\t\t} else {\n\t\t\tconsola.info(\"Not logged in to marketplace. Starting GitHub authentication...\");\n\t\t\tconst result = await authenticateViaDeviceFlow(registryUrl);\n\t\t\ttoken = result.token;\n\n\t\t\t// Save for next time\n\t\t\tsaveMarketplaceCredential(registryUrl, {\n\t\t\t\ttoken: result.token,\n\t\t\t\texpiresAt: new Date(Date.now() + 30 * 86400 * 1000).toISOString(), // 30 days\n\t\t\t\tauthor: { id: result.author.id, name: result.author.name },\n\t\t\t});\n\n\t\t\tconsola.success(`Authenticated as ${pc.bold(result.author.name)}`);\n\t\t}\n\n\t\t// ── Step 4: Pre-publish validation ──\n\n\t\tconsola.start(\"Checking marketplace...\");\n\n\t\t// Check if plugin exists\n\t\tconst pluginRes = await fetch(new URL(`/api/v1/plugins/${manifest.id}`, registryUrl));\n\n\t\tif (pluginRes.status === 404 && !envToken) {\n\t\t\t// Plugin doesn't exist — register it first.\n\t\t\t// When using env token (seed), the server auto-registers on publish.\n\t\t\tconsola.info(`Plugin ${pc.bold(manifest.id)} not found in marketplace. Registering...`);\n\n\t\t\tconst createRes = await fetch(new URL(\"/api/v1/plugins\", registryUrl), {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\tAuthorization: `Bearer ${token}`,\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tid: manifest.id,\n\t\t\t\t\tname: manifest.id, // Use ID as name initially\n\t\t\t\t\tcapabilities: manifest.capabilities,\n\t\t\t\t}),\n\t\t\t});\n\n\t\t\tif (!createRes.ok) {\n\t\t\t\tconst body = (await createRes.json().catch(() => ({}))) as { error?: string };\n\t\t\t\tif (createRes.status === 401) {\n\t\t\t\t\t// Token expired — clear and retry\n\t\t\t\t\tremoveMarketplaceCredential(registryUrl);\n\t\t\t\t\tconsola.error(\n\t\t\t\t\t\t\"Authentication expired. Please run `emdash plugin publish` again to re-authenticate.\",\n\t\t\t\t\t);\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t}\n\t\t\t\tconsola.error(`Failed to register plugin: ${body.error ?? createRes.statusText}`);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\tconsola.success(`Registered ${pc.bold(manifest.id)}`);\n\t\t} else if (pluginRes.status === 404 && envToken) {\n\t\t\t// Using env token — server handles auto-registration on publish\n\t\t\tconsola.info(`Plugin ${pc.bold(manifest.id)} will be auto-registered on publish`);\n\t\t} else if (!pluginRes.ok) {\n\t\t\tconsola.error(`Marketplace error: ${pluginRes.status}`);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\t// ── Step 5: Upload ──\n\n\t\tconsola.start(`Publishing ${manifest.id}@${manifest.version}...`);\n\n\t\tconst tarballData = await readFile(tarballPath);\n\t\tconst formData = new FormData();\n\t\tformData.append(\n\t\t\t\"bundle\",\n\t\t\tnew Blob([tarballData], { type: \"application/gzip\" }),\n\t\t\tbasename(tarballPath),\n\t\t);\n\n\t\tconst uploadUrl = new URL(`/api/v1/plugins/${manifest.id}/versions`, registryUrl);\n\t\tconst uploadRes = await fetch(uploadUrl, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${token}`,\n\t\t\t},\n\t\t\tbody: formData,\n\t\t});\n\n\t\tif (!uploadRes.ok && uploadRes.status !== 202) {\n\t\t\tconst body = (await uploadRes.json().catch(() => ({}))) as {\n\t\t\t\terror?: string;\n\t\t\t\tlatestVersion?: string;\n\t\t\t\taudit?: { verdict: string; summary: string; findings: unknown[] };\n\t\t\t};\n\n\t\t\tif (uploadRes.status === 401) {\n\t\t\t\tif (envToken) {\n\t\t\t\t\tconsola.error(\"EMDASH_MARKETPLACE_TOKEN was rejected by the marketplace.\");\n\t\t\t\t} else {\n\t\t\t\t\tremoveMarketplaceCredential(registryUrl);\n\t\t\t\t\tconsola.error(\"Authentication expired. Please run `emdash plugin publish` again.\");\n\t\t\t\t}\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\tif (uploadRes.status === 409) {\n\t\t\t\tif (body.latestVersion) {\n\t\t\t\t\tconsola.error(`Version ${manifest.version} must be greater than ${body.latestVersion}`);\n\t\t\t\t} else {\n\t\t\t\t\tconsola.error(body.error ?? \"Version conflict\");\n\t\t\t\t}\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\tif (uploadRes.status === 422 && body.audit) {\n\t\t\t\t// Failed security audit\n\t\t\t\tconsola.error(\"Plugin failed security audit:\");\n\t\t\t\tconsola.error(` Verdict: ${pc.red(body.audit.verdict)}`);\n\t\t\t\tconsola.error(` Summary: ${body.audit.summary}`);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\tconsola.error(`Publish failed: ${body.error ?? uploadRes.statusText}`);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\t// ── Step 6: Handle response ──\n\n\t\tconst result = (await uploadRes.json()) as {\n\t\t\tversion: string;\n\t\t\tbundleSize: number;\n\t\t\tchecksum: string;\n\t\t\tpublishedAt: string;\n\t\t\tstatus?: string;\n\t\t\tworkflowId?: string;\n\t\t\taudit?: {\n\t\t\t\tverdict: string;\n\t\t\t\triskScore: number;\n\t\t\t\tsummary: string;\n\t\t\t\tfindings: { category: string; severity: string; description: string }[];\n\t\t\t};\n\t\t\timageAudit?: {\n\t\t\t\tverdict: string;\n\t\t\t} | null;\n\t\t};\n\n\t\tconsole.log();\n\t\tconsola.success(`Uploaded ${pc.bold(`${manifest.id}@${result.version}`)}`);\n\t\tconsola.info(` Checksum: ${pc.dim(result.checksum)}`);\n\t\tconsola.info(` Size: ${(result.bundleSize / 1024).toFixed(1)}KB`);\n\n\t\t// Async audit flow (202 Accepted)\n\t\tif (uploadRes.status === 202) {\n\t\t\tconsola.info(` Status: ${pc.yellow(\"pending\")} (audit running in background)`);\n\n\t\t\tif (args[\"no-wait\"]) {\n\t\t\t\tconsola.info(\"Skipping audit wait (--no-wait). Check status later.\");\n\t\t\t\tconsole.log();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Poll version endpoint for audit completion\n\t\t\tconsola.start(\"Waiting for security audit to complete...\");\n\t\t\tconst versionUrl = new URL(\n\t\t\t\t`/api/v1/plugins/${manifest.id}/versions/${manifest.version}`,\n\t\t\t\tregistryUrl,\n\t\t\t);\n\t\t\tconst finalStatus = await pollVersionStatus(versionUrl.toString(), token);\n\n\t\t\tif (finalStatus) {\n\t\t\t\tdisplayAuditResults(finalStatus);\n\t\t\t} else {\n\t\t\t\tconsola.warn(\"Audit did not complete within timeout. Check status later with:\");\n\t\t\t\tconsola.info(` ${pc.dim(`curl ${versionUrl.toString()}`)}`);\n\t\t\t}\n\t\t} else {\n\t\t\t// Synchronous response (201 or legacy)\n\t\t\tif (result.audit) {\n\t\t\t\tdisplayInlineAuditResults(result.audit, result.imageAudit ?? null);\n\t\t\t}\n\t\t\tconsola.info(` Status: ${pc.green(result.status ?? \"published\")}`);\n\t\t}\n\n\t\tconsole.log();\n\t},\n});\n\n// ── Marketplace auth subcommands ────────────────────────────────\n\nexport const marketplaceLoginCommand = defineCommand({\n\tmeta: {\n\t\tname: \"login\",\n\t\tdescription: \"Log in to the EmDash Marketplace via GitHub\",\n\t},\n\targs: {\n\t\tregistry: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Marketplace registry URL\",\n\t\t\tdefault: DEFAULT_REGISTRY,\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst registryUrl = args.registry;\n\n\t\tconst existing = getMarketplaceCredential(registryUrl);\n\t\tif (existing) {\n\t\t\tconsola.info(`Already logged in as ${pc.bold(existing.author?.name ?? \"unknown\")}`);\n\t\t\tconsola.info(\"Use `emdash plugin logout` to log out first.\");\n\t\t\treturn;\n\t\t}\n\n\t\tconst result = await authenticateViaDeviceFlow(registryUrl);\n\n\t\tsaveMarketplaceCredential(registryUrl, {\n\t\t\ttoken: result.token,\n\t\t\texpiresAt: new Date(Date.now() + 30 * 86400 * 1000).toISOString(),\n\t\t\tauthor: { id: result.author.id, name: result.author.name },\n\t\t});\n\n\t\tconsola.success(`Logged in as ${pc.bold(result.author.name)}`);\n\t},\n});\n\nexport const marketplaceLogoutCommand = defineCommand({\n\tmeta: {\n\t\tname: \"logout\",\n\t\tdescription: \"Log out of the EmDash Marketplace\",\n\t},\n\targs: {\n\t\tregistry: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Marketplace registry URL\",\n\t\t\tdefault: DEFAULT_REGISTRY,\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst removed = removeMarketplaceCredential(args.registry);\n\t\tif (removed) {\n\t\t\tconsola.success(\"Logged out of marketplace.\");\n\t\t} else {\n\t\t\tconsola.info(\"No marketplace credentials found.\");\n\t\t}\n\t},\n});\n","/**\n * emdash plugin\n *\n * Plugin management commands grouped under a single namespace.\n *\n * Subcommands:\n * - init: Scaffold a new plugin\n * - bundle: Bundle a plugin for marketplace distribution\n * - validate: Run bundle validation without producing a tarball\n * - publish: Publish a plugin to the marketplace\n * - login: Log in to the marketplace via GitHub\n * - logout: Log out of the marketplace\n *\n */\n\nimport { defineCommand } from \"citty\";\n\nimport { bundleCommand } from \"./bundle.js\";\nimport { pluginInitCommand } from \"./plugin-init.js\";\nimport { pluginValidateCommand } from \"./plugin-validate.js\";\nimport { publishCommand, marketplaceLoginCommand, marketplaceLogoutCommand } from \"./publish.js\";\n\nexport const pluginCommand = defineCommand({\n\tmeta: { name: \"plugin\", description: \"Manage plugins\" },\n\tsubCommands: {\n\t\tinit: pluginInitCommand,\n\t\tbundle: bundleCommand,\n\t\tvalidate: pluginValidateCommand,\n\t\tpublish: publishCommand,\n\t\tlogin: marketplaceLoginCommand,\n\t\tlogout: marketplaceLogoutCommand,\n\t},\n});\n","/**\n * emdash schema\n *\n * Manage collections and fields via the remote API\n */\n\nimport { defineCommand } from \"citty\";\nimport { consola } from \"consola\";\n\nimport { connectionArgs as commonArgs, createClientFromArgs } from \"../client-factory.js\";\nimport { output } from \"../output.js\";\n\nconst listCommand = defineCommand({\n\tmeta: {\n\t\tname: \"list\",\n\t\tdescription: \"List all collections\",\n\t},\n\targs: {\n\t\t...commonArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst collections = await client.collections();\n\t\t\toutput(collections, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst getCommand = defineCommand({\n\tmeta: {\n\t\tname: \"get\",\n\t\tdescription: \"Get collection with fields\",\n\t},\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\t...commonArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst collection = await client.collection(args.collection);\n\t\t\toutput(collection, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst createCommand = defineCommand({\n\tmeta: {\n\t\tname: \"create\",\n\t\tdescription: \"Create a collection\",\n\t},\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tlabel: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Collection label\",\n\t\t\trequired: true,\n\t\t},\n\t\t\"label-singular\": {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Singular label (defaults to label)\",\n\t\t},\n\t\tdescription: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Collection description\",\n\t\t},\n\t\t...commonArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst data = await client.createCollection({\n\t\t\t\tslug: args.collection,\n\t\t\t\tlabel: args.label,\n\t\t\t\tlabelSingular: args[\"label-singular\"] || args.label,\n\t\t\t\tdescription: args.description,\n\t\t\t});\n\t\t\tconsola.success(`Created collection \"${args.collection}\"`);\n\t\t\toutput(data, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst deleteCommand = defineCommand({\n\tmeta: {\n\t\tname: \"delete\",\n\t\tdescription: \"Delete a collection\",\n\t},\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tforce: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Skip confirmation\",\n\t\t},\n\t\t...commonArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tif (!args.force) {\n\t\t\t\tconst confirmed = await consola.prompt(`Delete collection \"${args.collection}\"?`, {\n\t\t\t\t\ttype: \"confirm\",\n\t\t\t\t});\n\t\t\t\tif (!confirmed) {\n\t\t\t\t\tconsola.info(\"Cancelled\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tawait client.deleteCollection(args.collection);\n\t\t\tconsola.success(`Deleted collection \"${args.collection}\"`);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst addFieldCommand = defineCommand({\n\tmeta: {\n\t\tname: \"add-field\",\n\t\tdescription: \"Add a field to a collection\",\n\t},\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tfield: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Field slug\",\n\t\t\trequired: true,\n\t\t},\n\t\ttype: {\n\t\t\ttype: \"string\",\n\t\t\tdescription:\n\t\t\t\t\"Field type (string, text, number, integer, boolean, datetime, image, reference, portableText, json)\",\n\t\t\trequired: true,\n\t\t},\n\t\tlabel: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Field label\",\n\t\t},\n\t\trequired: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Whether the field is required\",\n\t\t},\n\t\t...commonArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst data = await client.createField(args.collection, {\n\t\t\t\tslug: args.field,\n\t\t\t\ttype: args.type,\n\t\t\t\tlabel: args.label || args.field,\n\t\t\t\trequired: args.required,\n\t\t\t});\n\t\t\tconsola.success(`Added field \"${args.field}\" to \"${args.collection}\"`);\n\t\t\toutput(data, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst removeFieldCommand = defineCommand({\n\tmeta: {\n\t\tname: \"remove-field\",\n\t\tdescription: \"Remove a field from a collection\",\n\t},\n\targs: {\n\t\tcollection: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Collection slug\",\n\t\t\trequired: true,\n\t\t},\n\t\tfield: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Field slug\",\n\t\t\trequired: true,\n\t\t},\n\t\t...commonArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tawait client.deleteField(args.collection, args.field);\n\t\t\tconsola.success(`Removed field \"${args.field}\" from \"${args.collection}\"`);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nexport const schemaCommand = defineCommand({\n\tmeta: {\n\t\tname: \"schema\",\n\t\tdescription: \"Manage collections and fields\",\n\t},\n\tsubCommands: {\n\t\tlist: listCommand,\n\t\tget: getCommand,\n\t\tcreate: createCommand,\n\t\tdelete: deleteCommand,\n\t\t\"add-field\": addFieldCommand,\n\t\t\"remove-field\": removeFieldCommand,\n\t},\n});\n","/**\n * emdash search\n *\n * Full-text search across content\n */\n\nimport { defineCommand } from \"citty\";\nimport { consola } from \"consola\";\n\nimport { connectionArgs, createClientFromArgs } from \"../client-factory.js\";\nimport { output } from \"../output.js\";\n\nexport const searchCommand = defineCommand({\n\tmeta: {\n\t\tname: \"search\",\n\t\tdescription: \"Full-text search across content\",\n\t},\n\targs: {\n\t\tquery: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Search query\",\n\t\t\trequired: true,\n\t\t},\n\t\tcollection: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"c\",\n\t\t\tdescription: \"Filter by collection\",\n\t\t},\n\t\tlocale: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Filter by locale\",\n\t\t},\n\t\tlimit: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"l\",\n\t\t\tdescription: \"Maximum results to return\",\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst results = await client.search(args.query, {\n\t\t\t\tcollection: args.collection,\n\t\t\t\tlocale: args.locale,\n\t\t\t\tlimit: args.limit ? parseInt(args.limit, 10) : undefined,\n\t\t\t});\n\t\t\toutput(results, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n","/**\n * emdash seed\n *\n * Apply a seed file to the database\n */\n\nimport { readFile, access, mkdir } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\n\nimport { defineCommand } from \"citty\";\nimport consola from \"consola\";\n\nimport { createDatabase } from \"../../database/connection.js\";\nimport { runMigrations } from \"../../database/migrations/runner.js\";\nimport { applySeed } from \"../../seed/apply.js\";\nimport type { SeedFile, SeedApplyOptions } from \"../../seed/types.js\";\nimport { validateSeed } from \"../../seed/validate.js\";\nimport { LocalStorage } from \"../../storage/local.js\";\n\ninterface PackageJson {\n\tname?: string;\n\temdash?: {\n\t\tseed?: string;\n\t};\n}\n\nasync function fileExists(path: string): Promise<boolean> {\n\ttry {\n\t\tawait access(path);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nasync function readPackageJson(cwd: string): Promise<PackageJson | null> {\n\tconst pkgPath = resolve(cwd, \"package.json\");\n\ttry {\n\t\tconst content = await readFile(pkgPath, \"utf-8\");\n\t\treturn JSON.parse(content);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Resolve seed file path from:\n * 1. Positional argument (if provided)\n * 2. .emdash/seed.json (convention)\n * 3. package.json emdash.seed (config)\n */\nasync function resolveSeedPath(cwd: string, positional?: string): Promise<string | null> {\n\t// 1. Positional argument\n\tif (positional) {\n\t\tconst resolved = resolve(cwd, positional);\n\t\tif (await fileExists(resolved)) {\n\t\t\treturn resolved;\n\t\t}\n\t\tconsola.error(`Seed file not found: ${positional}`);\n\t\treturn null;\n\t}\n\n\t// 2. Convention: .emdash/seed.json\n\tconst conventionPath = resolve(cwd, \".emdash\", \"seed.json\");\n\tif (await fileExists(conventionPath)) {\n\t\treturn conventionPath;\n\t}\n\n\t// 3. package.json emdash.seed\n\tconst pkg = await readPackageJson(cwd);\n\tif (pkg?.emdash?.seed) {\n\t\tconst pkgSeedPath = resolve(cwd, pkg.emdash.seed);\n\t\tif (await fileExists(pkgSeedPath)) {\n\t\t\treturn pkgSeedPath;\n\t\t}\n\t\tconsola.warn(`Seed file from package.json not found: ${pkg.emdash.seed}`);\n\t}\n\n\treturn null;\n}\n\nexport const seedCommand = defineCommand({\n\tmeta: {\n\t\tname: \"seed\",\n\t\tdescription: \"Apply a seed file to the database\",\n\t},\n\targs: {\n\t\tpath: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Path to seed file (default: .emdash/seed.json)\",\n\t\t\trequired: false,\n\t\t},\n\t\tdatabase: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"d\",\n\t\t\tdescription: \"Database path\",\n\t\t\tdefault: \"./data.db\",\n\t\t},\n\t\tcwd: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Working directory\",\n\t\t\tdefault: process.cwd(),\n\t\t},\n\t\tvalidate: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Validate only, don't apply\",\n\t\t\tdefault: false,\n\t\t},\n\t\t\"no-content\": {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Skip sample content\",\n\t\t\tdefault: false,\n\t\t},\n\t\t\"on-conflict\": {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Conflict handling: skip, update, error\",\n\t\t\tdefault: \"skip\",\n\t\t},\n\t\t\"uploads-dir\": {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Directory for media uploads\",\n\t\t\tdefault: \"./uploads\",\n\t\t},\n\t\t\"media-base-url\": {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Base URL for media files\",\n\t\t\tdefault: \"/_emdash/api/media/file\",\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst cwd = resolve(args.cwd);\n\t\tconsola.start(\"Loading seed file...\");\n\n\t\t// Resolve seed file path\n\t\tconst seedPath = await resolveSeedPath(cwd, args.path);\n\t\tif (!seedPath) {\n\t\t\tconsola.error(\"No seed file found\");\n\t\t\tconsola.info(\"Provide a path, create .emdash/seed.json, or set emdash.seed in package.json\");\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tconsola.info(`Seed file: ${seedPath}`);\n\n\t\t// Load and parse seed file\n\t\tlet seed: SeedFile;\n\t\ttry {\n\t\t\tconst content = await readFile(seedPath, \"utf-8\");\n\t\t\tseed = JSON.parse(content);\n\t\t} catch (error) {\n\t\t\tconsola.error(\"Failed to parse seed file:\", error);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\t// Validate seed\n\t\tconsola.start(\"Validating seed file...\");\n\t\tconst validation = validateSeed(seed);\n\n\t\tif (validation.warnings.length > 0) {\n\t\t\tfor (const warning of validation.warnings) {\n\t\t\t\tconsola.warn(warning);\n\t\t\t}\n\t\t}\n\n\t\tif (!validation.valid) {\n\t\t\tconsola.error(\"Seed validation failed:\");\n\t\t\tfor (const error of validation.errors) {\n\t\t\t\tconsola.error(` - ${error}`);\n\t\t\t}\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tconsola.success(\"Seed file is valid\");\n\n\t\t// If validate-only mode, exit here\n\t\tif (args.validate) {\n\t\t\tconsola.success(\"Validation complete\");\n\t\t\treturn;\n\t\t}\n\n\t\t// Connect to database\n\t\tconst dbPath = resolve(cwd, args.database);\n\t\tconsola.info(`Database: ${dbPath}`);\n\n\t\tconst db = createDatabase({ url: `file:${dbPath}` });\n\n\t\t// Run migrations\n\t\tconsola.start(\"Running migrations...\");\n\t\ttry {\n\t\t\tconst { applied } = await runMigrations(db);\n\t\t\tif (applied.length > 0) {\n\t\t\t\tconsola.success(`Applied ${applied.length} migrations`);\n\t\t\t} else {\n\t\t\t\tconsola.info(\"Database up to date\");\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsola.error(\"Migration failed:\", error);\n\t\t\tawait db.destroy();\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\t// Set up storage for $media resolution\n\t\tconst uploadsDir = resolve(cwd, args[\"uploads-dir\"]);\n\t\tawait mkdir(uploadsDir, { recursive: true });\n\n\t\tconst storage = new LocalStorage({\n\t\t\tdirectory: uploadsDir,\n\t\t\tbaseUrl: args[\"media-base-url\"],\n\t\t});\n\n\t\t// Prepare apply options\n\t\tconst onConflictRaw = args[\"on-conflict\"];\n\t\tif (onConflictRaw !== \"skip\" && onConflictRaw !== \"update\" && onConflictRaw !== \"error\") {\n\t\t\tconsola.error(`Invalid --on-conflict value: ${onConflictRaw}`);\n\t\t\tconsola.info(\"Use: skip, update, or error\");\n\t\t\tawait db.destroy();\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tconst options: SeedApplyOptions = {\n\t\t\tincludeContent: !args[\"no-content\"],\n\t\t\tonConflict: onConflictRaw,\n\t\t\tstorage,\n\t\t};\n\n\t\t// Apply seed\n\t\tconsola.start(\"Applying seed...\");\n\t\ttry {\n\t\t\tconst result = await applySeed(db, seed, options);\n\n\t\t\tconsola.success(\"Seed applied successfully!\");\n\t\t\tconsola.log(\"\");\n\n\t\t\t// Print summary\n\t\t\tif (result.settings.applied > 0) {\n\t\t\t\tconsola.info(`Settings: ${result.settings.applied} applied`);\n\t\t\t}\n\t\t\tif (\n\t\t\t\tresult.collections.created > 0 ||\n\t\t\t\tresult.collections.skipped > 0 ||\n\t\t\t\tresult.collections.updated > 0\n\t\t\t) {\n\t\t\t\tconsola.info(\n\t\t\t\t\t`Collections: ${result.collections.created} created, ${result.collections.skipped} skipped, ${result.collections.updated} updated`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (result.fields.created > 0 || result.fields.skipped > 0 || result.fields.updated > 0) {\n\t\t\t\tconsola.info(\n\t\t\t\t\t`Fields: ${result.fields.created} created, ${result.fields.skipped} skipped, ${result.fields.updated} updated`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (result.taxonomies.created > 0 || result.taxonomies.terms > 0) {\n\t\t\t\tconsola.info(\n\t\t\t\t\t`Taxonomies: ${result.taxonomies.created} created, ${result.taxonomies.terms} terms`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (result.bylines.created > 0 || result.bylines.skipped > 0 || result.bylines.updated > 0) {\n\t\t\t\tconsola.info(\n\t\t\t\t\t`Bylines: ${result.bylines.created} created, ${result.bylines.skipped} skipped, ${result.bylines.updated} updated`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (result.menus.created > 0 || result.menus.items > 0) {\n\t\t\t\tconsola.info(`Menus: ${result.menus.created} created, ${result.menus.items} items`);\n\t\t\t}\n\t\t\tif (result.widgetAreas.created > 0 || result.widgetAreas.widgets > 0) {\n\t\t\t\tconsola.info(\n\t\t\t\t\t`Widget Areas: ${result.widgetAreas.created} created, ${result.widgetAreas.widgets} widgets`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (result.content.created > 0 || result.content.skipped > 0 || result.content.updated > 0) {\n\t\t\t\tconsola.info(\n\t\t\t\t\t`Content: ${result.content.created} created, ${result.content.skipped} skipped, ${result.content.updated} updated`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (result.media.created > 0 || result.media.skipped > 0) {\n\t\t\t\tconsola.info(`Media: ${result.media.created} created, ${result.media.skipped} skipped`);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsola.error(\"Seed failed:\", error instanceof Error ? error.message : error);\n\t\t\tawait db.destroy();\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tawait db.destroy();\n\t\tconsola.success(\"Done!\");\n\t},\n});\n","/**\n * emdash taxonomy\n *\n * Manage taxonomies and terms via the EmDash REST API.\n */\n\nimport { defineCommand } from \"citty\";\nimport { consola } from \"consola\";\n\nimport { connectionArgs, createClientFromArgs } from \"../client-factory.js\";\nimport { output } from \"../output.js\";\n\n/** Pattern to replace whitespace with hyphens for slug generation */\nconst WHITESPACE_PATTERN = /\\s+/g;\n\nconst listCommand = defineCommand({\n\tmeta: {\n\t\tname: \"list\",\n\t\tdescription: \"List all taxonomies\",\n\t},\n\targs: {\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst taxonomies = await client.taxonomies();\n\t\t\toutput(taxonomies, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst termsCommand = defineCommand({\n\tmeta: {\n\t\tname: \"terms\",\n\t\tdescription: \"List terms in a taxonomy\",\n\t},\n\targs: {\n\t\tname: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Taxonomy name\",\n\t\t\trequired: true,\n\t\t},\n\t\tlimit: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"l\",\n\t\t\tdescription: \"Maximum terms to return\",\n\t\t},\n\t\tcursor: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Pagination cursor\",\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst result = await client.terms(args.name, {\n\t\t\t\tlimit: args.limit ? parseInt(args.limit, 10) : undefined,\n\t\t\t\tcursor: args.cursor,\n\t\t\t});\n\t\t\toutput(result, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nconst addTermCommand = defineCommand({\n\tmeta: {\n\t\tname: \"add-term\",\n\t\tdescription: \"Create a term in a taxonomy\",\n\t},\n\targs: {\n\t\ttaxonomy: {\n\t\t\ttype: \"positional\",\n\t\t\tdescription: \"Taxonomy name\",\n\t\t\trequired: true,\n\t\t},\n\t\tname: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Term label\",\n\t\t\trequired: true,\n\t\t},\n\t\tslug: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Term slug (defaults to slugified name)\",\n\t\t},\n\t\tparent: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Parent term ID\",\n\t\t},\n\t\t...connectionArgs,\n\t},\n\tasync run({ args }) {\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\t\t\tconst label = args.name;\n\t\t\tconst slug = args.slug || label.toLowerCase().replace(WHITESPACE_PATTERN, \"-\");\n\t\t\tconst term = await client.createTerm(args.taxonomy, {\n\t\t\t\tslug,\n\t\t\t\tlabel,\n\t\t\t\tparentId: args.parent,\n\t\t\t});\n\t\t\tconsola.success(`Created term \"${label}\" in ${args.taxonomy}`);\n\t\t\toutput(term, args);\n\t\t} catch (error) {\n\t\t\tconsola.error(error instanceof Error ? error.message : \"Unknown error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n\nexport const taxonomyCommand = defineCommand({\n\tmeta: {\n\t\tname: \"taxonomy\",\n\t\tdescription: \"Manage taxonomies and terms\",\n\t},\n\tsubCommands: {\n\t\tlist: listCommand,\n\t\tterms: termsCommand,\n\t\t\"add-term\": addTermCommand,\n\t},\n});\n","/**\n * emdash types\n *\n * Fetch schema from an EmDash instance and generate TypeScript types\n */\n\nimport { writeFile, mkdir } from \"node:fs/promises\";\nimport { resolve, dirname } from \"node:path\";\n\nimport { defineCommand } from \"citty\";\nimport consola from \"consola\";\n\nimport { connectionArgs, createClientFromArgs } from \"../client-factory.js\";\n\nexport const typesCommand = defineCommand({\n\tmeta: {\n\t\tname: \"types\",\n\t\tdescription: \"Generate TypeScript types from schema\",\n\t},\n\targs: {\n\t\t...connectionArgs,\n\t\toutput: {\n\t\t\ttype: \"string\",\n\t\t\talias: \"o\",\n\t\t\tdescription: \"Output path for generated types\",\n\t\t\tdefault: \".emdash/types.ts\",\n\t\t},\n\t\tcwd: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Working directory\",\n\t\t\tdefault: process.cwd(),\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst cwd = resolve(args.cwd);\n\t\tconsola.start(\"Fetching schema...\");\n\n\t\ttry {\n\t\t\tconst client = createClientFromArgs(args);\n\n\t\t\t// Fetch JSON schema\n\t\t\tconst schema = await client.schemaExport();\n\t\t\tconsola.success(`Found ${schema.collections.length} collections`);\n\n\t\t\t// Fetch TypeScript types\n\t\t\tconst types = await client.schemaTypes();\n\n\t\t\t// Write types file\n\t\t\tconst outputPath = resolve(cwd, args.output);\n\t\t\tawait mkdir(dirname(outputPath), { recursive: true });\n\t\t\tawait writeFile(outputPath, types, \"utf-8\");\n\t\t\tconsola.success(`Generated ${args.output}`);\n\n\t\t\t// Also write a schema.json for reference\n\t\t\tconst schemaJsonPath = resolve(dirname(outputPath), \"schema.json\");\n\t\t\tawait writeFile(schemaJsonPath, JSON.stringify(schema, null, 2), \"utf-8\");\n\t\t\tconsola.info(`Schema version: ${schema.version}`);\n\n\t\t\tconsola.box({\n\t\t\t\ttitle: \"Types generated\",\n\t\t\t\tmessage: `${schema.collections.length} collections\\n\\nTypes: ${args.output}\\nSchema: .emdash/schema.json`,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconsola.error(\"Failed to fetch schema:\", error instanceof Error ? error.message : error);\n\t\t\tprocess.exit(1);\n\t\t}\n\t},\n});\n","#!/usr/bin/env node\n\n/**\n * EmDash CLI\n *\n * Built with citty + clack (same stack as Nuxt CLI)\n *\n * Commands:\n * - init: Bootstrap database from template config, or interactive setup\n * - types: Generate TypeScript types from schema\n * - dev: Run dev server with local D1\n * - seed: Apply a seed file to the database\n * - export-seed: Export database schema and content as a seed file\n * - auth: Authentication utilities (secret generation)\n * - login/logout/whoami: Session management\n * - content: Create, read, update, delete content\n * - schema: Manage collections and fields\n * - media: Upload and manage media\n * - search: Full-text search\n * - taxonomy: Manage taxonomies and terms\n * - menu: Manage navigation menus\n * - plugin: Plugin management (init, bundle, validate, publish, login, logout)\n */\n\nimport { defineCommand, runMain } from \"citty\";\n\nimport { authCommand } from \"./commands/auth.js\";\nimport { contentCommand } from \"./commands/content.js\";\nimport { devCommand } from \"./commands/dev.js\";\nimport { doctorCommand } from \"./commands/doctor.js\";\nimport { exportSeedCommand } from \"./commands/export-seed.js\";\nimport { initCommand } from \"./commands/init.js\";\nimport { loginCommand, logoutCommand, whoamiCommand } from \"./commands/login.js\";\nimport { mediaCommand } from \"./commands/media.js\";\nimport { menuCommand } from \"./commands/menu.js\";\nimport { pluginCommand } from \"./commands/plugin.js\";\nimport { schemaCommand } from \"./commands/schema.js\";\nimport { searchCommand } from \"./commands/search-cmd.js\";\nimport { seedCommand } from \"./commands/seed.js\";\nimport { taxonomyCommand } from \"./commands/taxonomy.js\";\nimport { typesCommand } from \"./commands/types.js\";\n\nconst main = defineCommand({\n\tmeta: {\n\t\tname: \"emdash\",\n\t\tversion: \"0.0.0\",\n\t\tdescription: \"CLI for EmDash CMS\",\n\t},\n\tsubCommands: {\n\t\tinit: initCommand,\n\t\ttypes: typesCommand,\n\t\tdev: devCommand,\n\t\tdoctor: doctorCommand,\n\t\tseed: seedCommand,\n\t\t\"export-seed\": exportSeedCommand,\n\t\tauth: authCommand,\n\t\tlogin: loginCommand,\n\t\tlogout: logoutCommand,\n\t\twhoami: whoamiCommand,\n\t\tcontent: contentCommand,\n\t\tschema: schemaCommand,\n\t\tmedia: mediaCommand,\n\t\tsearch: searchCommand,\n\t\ttaxonomy: taxonomyCommand,\n\t\tmenu: menuCommand,\n\t\tplugin: pluginCommand,\n\t},\n});\n\nvoid runMain(main);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAaA,SAAS,qBAA6B;CACrC,MAAM,QAAQ,IAAI,WAAW,GAAG;AAChC,QAAO,gBAAgB,MAAM;AAC7B,QAAO,gBAAgB,MAAM;;AAG9B,MAAM,gBAAgB,cAAc;CACnC,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM;EACL,MAAM,SAAS,oBAAoB;AAEnC,YAAQ,IAAI,GAAG;AACf,YAAQ,IAAI,GAAG,KAAK,yBAAyB,CAAC;AAC9C,YAAQ,IAAI,GAAG;AACf,YAAQ,IAAI,KAAK,GAAG,KAAK,qBAAqB,CAAC,GAAG,GAAG,MAAM,OAAO,GAAG;AACrE,YAAQ,IAAI,GAAG;AACf,YAAQ,IAAI,GAAG,IAAI,0CAA0C,CAAC;AAC9D,YAAQ,IAAI,GAAG;;CAEhB,CAAC;AAEF,MAAa,cAAc,cAAc;CACxC,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,aAAa,EACZ,QAAQ,eACR;CACD,CAAC;;;;;;;;;;ACDF,SAAS,eAAuB;CAE/B,MAAM,MAAM,QAAQ,IAAI;AACxB,KAAI,IAAK,QAAO,KAAK,KAAK,SAAS;AACnC,QAAO,KAAK,SAAS,EAAE,WAAW,SAAS;;AAG5C,SAAS,oBAA4B;AACpC,QAAO,KAAK,cAAc,EAAE,YAAY;;;;;;;;AAazC,SAAgB,qBAAqB,SAAyB;AAC7D,KAAI;EACH,MAAM,MAAM,IAAI,IAAI,QAAQ;AAI5B,MAFC,IAAI,aAAa,eAAe,IAAI,aAAa,eAAe,IAAI,aAAa,SAErE;GAEZ,MAAM,cAAc,gBAAgB,QAAQ,KAAK,CAAC;AAClD,OAAI,YACH,QAAO,QAAQ;AAGhB,UAAO,IAAI;;AAGZ,SAAO,IAAI;SACJ;AACP,SAAO;;;;;;AAOT,SAAS,gBAAgB,MAA6B;CACrD,IAAI,MAAM,QAAQ,KAAK;CACvB,MAAM,OAAO,QAAQ,IAAI;AAEzB,QAAO,QAAQ,MAAM;AACpB,OAAK,MAAM,QAAQ;GAClB;GACA;GACA;GACA;GACA,CACA,KAAI,WAAW,KAAK,KAAK,KAAK,CAAC,CAC9B,QAAO;EAGT,MAAM,SAAS,QAAQ,KAAK,KAAK;AACjC,MAAI,WAAW,IAAK;AACpB,QAAM;;AAGP,QAAO;;AAOR,SAAS,YAA6B;CACrC,MAAM,OAAO,mBAAmB;AAChC,KAAI;AACH,MAAI,WAAW,KAAK,EAAE;GACrB,MAAM,UAAU,aAAa,MAAM,QAAQ;AAC3C,UAAO,KAAK,MAAM,QAAQ;;SAEpB;AAGR,QAAO,EAAE;;AAGV,SAAS,WAAW,OAA8B;AAEjD,WADY,cAAc,EACX,EAAE,WAAW,MAAM,CAAC;AAGnC,eADa,mBAAmB,EACZ,KAAK,UAAU,OAAO,MAAM,IAAK,EAAE;EACtD,UAAU;EACV,MAAM;EACN,CAAC;;;;;AAUH,SAAgB,eAAe,SAA0C;CACxE,MAAM,MAAM,qBAAqB,QAAQ;CAEzC,MAAM,OADQ,WAAW,CACN;AACnB,KAAI,CAAC,QAAQ,EAAE,iBAAiB,MAAO,QAAO;AAC9C,QAAO;;;;;AAMR,SAAgB,gBAAgB,SAAiB,MAA8B;CAC9E,MAAM,MAAM,qBAAqB,QAAQ;CACzC,MAAM,QAAQ,WAAW;AACzB,OAAM,OAAO;AACb,YAAW,MAAM;;;;;AAMlB,SAAgB,kBAAkB,SAA0B;CAC3D,MAAM,MAAM,qBAAqB,QAAQ;CACzC,MAAM,QAAQ,WAAW;AACzB,KAAI,OAAO,OAAO;AACjB,SAAO,MAAM;AACb,aAAW,MAAM;AACjB,SAAO;;AAER,QAAO;;AAeR,SAAS,eAAe,aAA6B;AACpD,KAAI;AACH,SAAO,eAAe,IAAI,IAAI,YAAY,CAAC;SACpC;AACP,SAAO,eAAe;;;;;;AAOxB,SAAgB,yBAAyB,aAAmD;CAC3F,MAAM,MAAM,eAAe,YAAY;CAEvC,MAAM,OADQ,WAAW,CACN;AACnB,KAAI,CAAC,QAAQ,EAAE,WAAW,MAAO,QAAO;AAExC,KAAI,IAAI,KAAK,KAAK,UAAU,mBAAG,IAAI,MAAM,CAAE,QAAO;AAClD,QAAO;;;;;AAMR,SAAgB,0BAA0B,aAAqB,MAAmC;CACjG,MAAM,MAAM,eAAe,YAAY;CACvC,MAAM,QAAQ,WAAW;AACzB,OAAM,OAAO;AACb,YAAW,MAAM;;;;;AAMlB,SAAgB,4BAA4B,aAA8B;CACzE,MAAM,MAAM,eAAe,YAAY;CACvC,MAAM,QAAQ,WAAW;AACzB,KAAI,OAAO,OAAO;AACjB,SAAO,MAAM;AACb,aAAW,MAAM;AACjB,SAAO;;AAER,QAAO;;;;;;;;;;;;;AC5NR,MAAa,iBAAiB;CAC7B,KAAK;EACJ,MAAM;EACN,OAAO;EACP,aAAa;EACb,SAAS;EACT;CACD,OAAO;EACN,MAAM;EACN,OAAO;EACP,aAAa;EACb;CACD,QAAQ;EACP,MAAM;EACN,OAAO;EACP,aAAa;EACb;CACD,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD;;;;;;;;;;;;;;;AAgBD,SAAgB,qBAAqB,MAAgC;CACpE,MAAM,UAAU,KAAK,OAAO,QAAQ,IAAI,iBAAiB;CACzD,IAAI,QAAQ,KAAK,SAAS,QAAQ,IAAI;CAEtC,MAAM,UAAU,QAAQ,SAAS,YAAY,IAAI,QAAQ,SAAS,YAAY;CAC9E,MAAM,OAAO,CAAC,QAAQ,eAAe,QAAQ,GAAG;CAGhD,MAAM,gBAAgB;EACrB,GAAG,MAAM;EACT,GAAG,sBAAsB;EACzB;CAED,MAAM,oBAAmC,EAAE;AAC3C,KAAI,OAAO,KAAK,cAAc,CAAC,SAAS,EACvC,mBAAkB,KAAK,yBAAyB,cAAc,CAAC;AAIhE,KAAI,CAAC,SAAS,KAEb,KAAI,IAAI,KAAK,KAAK,UAAU,mBAAG,IAAI,MAAM,CACxC,SAAQ,KAAK;KAIb,QAAO,IAAI,aAAa;EACvB;EACA,OAAO,KAAK;EACZ,cAAc,KAAK;EACnB,iBAAiB,gBAAgB,cAAc;AAC9C,mBAAgB,SAAS;IACxB,GAAG;IACH,aAAa;IACb,WAAW,IAAI,KAAK,KAAK,KAAK,GAAG,YAAY,IAAK,CAAC,aAAa;IAChE,CAAC;;EAEH,cAAc;EACd,CAAC;AAIJ,QAAO,IAAI,aAAa;EACvB;EACA;EACA,WAAW,CAAC,SAAS;EACrB,cAAc;EACd,CAAC;;;;;;;;;;;ACtFH,SAAgB,OAAO,MAAe,MAAwB;AAG7D,KAFgB,KAAK,QAAQ,CAAC,QAAQ,OAAO,MAI5C,SAAQ,OAAO,MAAM,KAAK,UAAU,MAAM,MAAM,EAAE,GAAG,KAAK;KAG1D,aAAY,KAAK;;AAInB,SAAS,YAAY,MAAe,SAAiB,GAAS;AAC7D,KAAI,SAAS,QAAQ,SAAS,QAAW;AACxC,YAAQ,IAAI,UAAU;AACtB;;AAGD,KAAI,MAAM,QAAQ,KAAK,EAAE;AACxB,MAAI,KAAK,WAAW,GAAG;AACtB,aAAQ,IAAI,aAAa;AACzB;;AAED,OAAK,MAAM,QAAQ,MAAM;AACxB,eAAY,MAAM,OAAO;AACzB,OAAI,WAAW,EAAG,WAAQ,IAAI,MAAM;;AAErC;;AAGD,KAAI,OAAO,SAAS,UAAU;EAC7B,MAAM,MAAM,OAAO,KAAK;AAGxB,MAAI,WAAW,OAAO,MAAM,QAAQ,IAAI,MAAM,EAAE;AAC/C,eAAY,IAAI,OAAO,OAAO;AAC9B,OAAI,OAAO,IAAI,eAAe,SAC7B,WAAQ,IAAI,kBAAkB,IAAI,aAAa;AAEhD;;EAID,MAAM,SAAS,KAAK,OAAO,OAAO;AAClC,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,IAAI,EAAE;AAC/C,OAAI,UAAU,QAAQ,UAAU,OAAW;AAC3C,OAAI,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,MAAM,EAAE;AACvD,cAAQ,IAAI,GAAG,SAAS,IAAI,GAAG;AAC/B,gBAAY,OAAO,SAAS,EAAE;cACpB,MAAM,QAAQ,MAAM,CAC9B,WAAQ,IAAI,GAAG,SAAS,IAAI,KAAK,MAAM,OAAO,SAAS;QACjD;IACN,MAAM,MAAM,OAAO,UAAU,WAAW,QAAQ,KAAK,UAAU,MAAM;IAErE,MAAM,UAAU,IAAI,SAAS,KAAK,IAAI,MAAM,GAAG,GAAG,GAAG,QAAQ;AAC7D,cAAQ,IAAI,GAAG,SAAS,IAAI,IAAI,UAAU;;;AAG5C;;AAGD,WAAQ,IAAI,OAAO,SAAS,WAAW,OAAO,KAAK,UAAU,KAAK,CAAC;;;;;;;;;;;ACtDpE,eAAe,cAAc,MAIQ;AACpC,KAAI,KAAK,KACR,KAAI;AACH,SAAO,KAAK,MAAM,KAAK,KAAK;SACrB;AACP,QAAM,IAAI,MAAM,kCAAkC;;AAIpD,KAAI,KAAK,KACR,KAAI;EACH,MAAM,UAAU,MAAM,SAAS,KAAK,MAAM,QAAQ;AAClD,SAAO,KAAK,MAAM,QAAQ;UAClB,OAAO;AACf,MAAI,iBAAiB,YACpB,OAAM,IAAI,MAAM,yBAAyB,KAAK,QAAQ,EAAE,OAAO,OAAO,CAAC;AAExE,QAAM;;AAIR,KAAI,KAAK,OAAO;EACf,MAAM,SAAmB,EAAE;AAC3B,aAAW,MAAM,SAAS,QAAQ,MACjC,QAAO,KAAK,MAAgB;EAE7B,MAAM,UAAU,OAAO,OAAO,OAAO,CAAC,SAAS,QAAQ;AACvD,MAAI;AACH,UAAO,KAAK,MAAM,QAAQ;UACnB;AACP,SAAM,IAAI,MAAM,0BAA0B;;;AAI5C,OAAM,IAAI,MAAM,sDAAsD;;AAOvE,MAAMA,gBAAc,cAAc;CACjC,MAAM;EAAE,MAAM;EAAQ,aAAa;EAAsB;CACzD,MAAM;EACL,YAAY;GACX,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,QAAQ;GAAE,MAAM;GAAU,aAAa;GAAoB;EAC3D,QAAQ;GAAE,MAAM;GAAU,aAAa;GAAoB;EAC3D,OAAO;GAAE,MAAM;GAAU,aAAa;GAA2B;EACjE,QAAQ;GAAE,MAAM;GAAU,aAAa;GAAqB;EAC5D,GAAG;EACH;CACD,MAAM,IAAI,EAAE,QAAQ;AACnB,MAAI;GAEH,MAAM,SAAS,MADA,qBAAqB,KAAK,CACb,KAAK,KAAK,YAAY;IACjD,QAAQ,KAAK;IACb,QAAQ,KAAK;IACb,OAAO,KAAK,QAAQ,SAAS,KAAK,OAAO,GAAG,GAAG;IAC/C,QAAQ,KAAK;IACb,CAAC;AAaF,UAXgB;IACf,OAAO,OAAO,MAAM,KAAK,UAAU;KAClC,IAAI,KAAK;KACT,MAAM,KAAK;KACX,QAAQ,KAAK;KACb,QAAQ,KAAK;KACb,OAAO,OAAO,KAAK,MAAM,UAAU,WAAW,KAAK,KAAK,QAAQ;KAChE,WAAW,KAAK;KAChB,EAAE;IACH,YAAY,OAAO;IACnB,EACe,KAAK;WACb,OAAO;AACf,aAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,gBAAgB;AACvE,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;AAEF,MAAMC,eAAa,cAAc;CAChC,MAAM;EAAE,MAAM;EAAO,aAAa;EAA6B;CAC/D,MAAM;EACL,YAAY;GACX,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,IAAI;GACH,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,QAAQ;GAAE,MAAM;GAAU,aAAa;GAA8B;EACrE,KAAK;GACJ,MAAM;GACN,aAAa;GACb;EACD,WAAW;GACV,MAAM;GACN,aAAa;GACb;EACD,GAAG;EACH;CACD,MAAM,IAAI,EAAE,QAAQ;AACnB,MAAI;GACH,MAAM,SAAS,qBAAqB,KAAK;GACzC,MAAM,OAAO,MAAM,OAAO,IAAI,KAAK,YAAY,KAAK,IAAI;IACvD,KAAK,KAAK;IACV,QAAQ,KAAK;IACb,CAAC;AAGF,OAAI,CAAC,KAAK,aAAa,KAAK,iBAAiB;IAC5C,MAAM,aAAa,MAAM,OAAO,QAAQ,KAAK,YAAY,KAAK,GAAG;AACjE,QAAI,WAAW,cAAc,WAAW,MACvC,MAAK,OAAO,WAAW;;AAIzB,UAAO,MAAM,KAAK;WACV,OAAO;AACf,aAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,gBAAgB;AACvE,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;AAEF,MAAMC,kBAAgB,cAAc;CACnC,MAAM;EAAE,MAAM;EAAU,aAAa;EAAyB;CAC9D,MAAM;EACL,YAAY;GACX,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,MAAM;GAAE,MAAM;GAAU,aAAa;GAA+B;EACpE,MAAM;GAAE,MAAM;GAAU,aAAa;GAAsC;EAC3E,OAAO;GAAE,MAAM;GAAW,aAAa;GAAgC;EACvE,MAAM;GAAE,MAAM;GAAU,aAAa;GAAgB;EACrD,QAAQ;GAAE,MAAM;GAAU,aAAa;GAAkB;EACzD,kBAAkB;GACjB,MAAM;GACN,aAAa;GACb;EACD,OAAO;GACN,MAAM;GACN,aAAa;GACb;EACD,GAAG;EACH;CACD,MAAM,IAAI,EAAE,QAAQ;AACnB,MAAI;GACH,MAAM,OAAO,MAAM,cAAc,KAAK;GACtC,MAAM,SAAS,qBAAqB,KAAK;GACzC,MAAM,OAAO,MAAM,OAAO,OAAO,KAAK,YAAY;IACjD;IACA,MAAM,KAAK;IACX,QAAQ,KAAK;IACb,eAAe,KAAK;IACpB,CAAC;AAGF,OAAI,CAAC,KAAK,MACT,OAAM,OAAO,QAAQ,KAAK,YAAY,KAAK,GAAG;AAK/C,UADe,MAAM,OAAO,IAAI,KAAK,YAAY,KAAK,GAAG,EAC1C,KAAK;WACZ,OAAO;AACf,aAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,gBAAgB;AACvE,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;AAEF,MAAM,gBAAgB,cAAc;CACnC,MAAM;EAAE,MAAM;EAAU,aAAa;EAAyB;CAC9D,MAAM;EACL,YAAY;GACX,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,IAAI;GACH,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,MAAM;GAAE,MAAM;GAAU,aAAa;GAA+B;EACpE,MAAM;GAAE,MAAM;GAAU,aAAa;GAAsC;EAC3E,KAAK;GACJ,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,OAAO;GACN,MAAM;GACN,aAAa;GACb;EACD,GAAG;EACH;CACD,MAAM,IAAI,EAAE,QAAQ;AACnB,MAAI;GACH,MAAM,OAAO,MAAM,cAAc,KAAK;GACtC,MAAM,SAAS,qBAAqB,KAAK;GACzC,MAAM,UAAU,MAAM,OAAO,OAAO,KAAK,YAAY,KAAK,IAAI;IAC7D;IACA,MAAM,KAAK;IACX,CAAC;AAKF,OAAI,CAAC,KAAK,SAAS,QAAQ,gBAC1B,OAAM,OAAO,QAAQ,KAAK,YAAY,KAAK,GAAG;AAK/C,UADa,MAAM,OAAO,IAAI,KAAK,YAAY,KAAK,GAAG,EAC1C,KAAK;WACV,OAAO;AACf,aAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,gBAAgB;AACvE,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;AAEF,MAAMC,kBAAgB,cAAc;CACnC,MAAM;EAAE,MAAM;EAAU,aAAa;EAAyB;CAC9D,MAAM;EACL,YAAY;GACX,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,IAAI;GACH,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,GAAG;EACH;CACD,MAAM,IAAI,EAAE,QAAQ;AACnB,MAAI;AAEH,SADe,qBAAqB,KAAK,CAC5B,OAAO,KAAK,YAAY,KAAK,GAAG;AAC7C,aAAQ,QAAQ,WAAW,KAAK,WAAW,GAAG,KAAK,KAAK;WAChD,OAAO;AACf,aAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,gBAAgB;AACvE,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;AAEF,MAAMC,mBAAiB,cAAc;CACpC,MAAM;EAAE,MAAM;EAAW,aAAa;EAA0B;CAChE,MAAM;EACL,YAAY;GACX,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,IAAI;GACH,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,GAAG;EACH;CACD,MAAM,IAAI,EAAE,QAAQ;AACnB,MAAI;AAEH,SADe,qBAAqB,KAAK,CAC5B,QAAQ,KAAK,YAAY,KAAK,GAAG;AAC9C,aAAQ,QAAQ,aAAa,KAAK,WAAW,GAAG,KAAK,KAAK;WAClD,OAAO;AACf,aAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,gBAAgB;AACvE,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;AAEF,MAAM,mBAAmB,cAAc;CACtC,MAAM;EAAE,MAAM;EAAa,aAAa;EAA4B;CACpE,MAAM;EACL,YAAY;GACX,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,IAAI;GACH,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,GAAG;EACH;CACD,MAAM,IAAI,EAAE,QAAQ;AACnB,MAAI;AAEH,SADe,qBAAqB,KAAK,CAC5B,UAAU,KAAK,YAAY,KAAK,GAAG;AAChD,aAAQ,QAAQ,eAAe,KAAK,WAAW,GAAG,KAAK,KAAK;WACpD,OAAO;AACf,aAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,gBAAgB;AACvE,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;AAEF,MAAM,kBAAkB,cAAc;CACrC,MAAM;EAAE,MAAM;EAAY,aAAa;EAAmC;CAC1E,MAAM;EACL,YAAY;GACX,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,IAAI;GACH,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,IAAI;GACH,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,GAAG;EACH;CACD,MAAM,IAAI,EAAE,QAAQ;AACnB,MAAI;AAEH,SADe,qBAAqB,KAAK,CAC5B,SAAS,KAAK,YAAY,KAAK,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;AAChE,aAAQ,QAAQ,aAAa,KAAK,WAAW,GAAG,KAAK,GAAG,OAAO,KAAK,KAAK;WACjE,OAAO;AACf,aAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,gBAAgB;AACvE,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;AAEF,MAAM,iBAAiB,cAAc;CACpC,MAAM;EAAE,MAAM;EAAW,aAAa;EAAkC;CACxE,MAAM;EACL,YAAY;GACX,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,IAAI;GACH,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,GAAG;EACH;CACD,MAAM,IAAI,EAAE,QAAQ;AACnB,MAAI;AAEH,SADe,qBAAqB,KAAK,CAC5B,QAAQ,KAAK,YAAY,KAAK,GAAG;AAC9C,aAAQ,QAAQ,YAAY,KAAK,WAAW,GAAG,KAAK,KAAK;WACjD,OAAO;AACf,aAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,gBAAgB;AACvE,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;AAEF,MAAM,sBAAsB,cAAc;CACzC,MAAM;EAAE,MAAM;EAAgB,aAAa;EAAwC;CACnF,MAAM;EACL,YAAY;GACX,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,IAAI;GACH,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,GAAG;EACH;CACD,MAAM,IAAI,EAAE,QAAQ;AACnB,MAAI;AAGH,UADqB,MADN,qBAAqB,KAAK,CACP,aAAa,KAAK,YAAY,KAAK,GAAG,EACnD,KAAK;WAClB,OAAO;AACf,aAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,gBAAgB;AACvE,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;AAMF,MAAa,iBAAiB,cAAc;CAC3C,MAAM;EAAE,MAAM;EAAW,aAAa;EAAkB;CACxD,aAAa;EACZ,MAAMJ;EACN,KAAKC;EACL,QAAQC;EACR,QAAQ;EACR,QAAQC;EACR,SAASC;EACT,WAAW;EACX,UAAU;EACV,SAAS;EACT,cAAc;EACd;CACD,CAAC;;;;;;;;;AChaF,eAAeC,kBAAgB,KAA0C;CACxE,MAAM,UAAU,QAAQ,KAAK,eAAe;AAC5C,KAAI;EACH,MAAM,UAAU,MAAM,SAAS,SAAS,QAAQ;AAChD,SAAO,KAAK,MAAM,QAAQ;SACnB;AACP,SAAO;;;AAIT,eAAeC,aAAW,MAAgC;AACzD,KAAI;AACH,QAAM,OAAO,KAAK;AAClB,SAAO;SACA;AACP,SAAO;;;AAIT,MAAa,aAAa,cAAc;CACvC,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM;EACL,UAAU;GACT,MAAM;GACN,OAAO;GACP,aAAa;GACb,SAAS;GACT;EACD,OAAO;GACN,MAAM;GACN,OAAO;GACP,aAAa;GACb,SAAS;GACT;EACD,MAAM;GACL,MAAM;GACN,OAAO;GACP,aAAa;GACb,SAAS;GACT;EACD,KAAK;GACJ,MAAM;GACN,aAAa;GACb,SAAS,QAAQ,KAAK;GACtB;EACD;CACD,MAAM,IAAI,EAAE,QAAQ;EACnB,MAAM,MAAM,QAAQ,KAAK,IAAI;EAC7B,MAAM,MAAM,MAAMD,kBAAgB,IAAI;AAEtC,MAAI,CAAC,KAAK;AACT,WAAQ,MAAM,wBAAwB;AACtC,WAAQ,KAAK,EAAE;;EAGhB,MAAM,SAAS,QAAQ,KAAK,KAAK,SAAS;AAI1C,MAAI,CADa,MAAMC,aAAW,OAAO,CAExC,SAAQ,MAAM,sCAAsC;EAIrD,MAAM,KAAK,eAAe,EAAE,KAAK,QAAQ,UAAU,CAAC;AACpD,MAAI;AACH,WAAQ,MAAM,kCAAkC;GAChD,MAAM,EAAE,YAAY,MAAM,cAAc,GAAG;AAC3C,OAAI,QAAQ,SAAS,EACpB,SAAQ,QAAQ,WAAW,QAAQ,OAAO,aAAa;OAEvD,SAAQ,KAAK,sBAAsB;WAE5B,OAAO;AACf,WAAQ,MAAM,qBAAqB,MAAM;AACzC,SAAM,GAAG,SAAS;AAClB,WAAQ,KAAK,EAAE;;AAEhB,QAAM,GAAG,SAAS;AAGlB,MAAI,KAAK,OAAO;GACf,MAAM,YAAY,IAAI,QAAQ,OAAO,QAAQ,IAAI;AAEjD,OAAI,CAAC,UACJ,SAAQ,KAAK,yEAAyE;OAEtF,KAAI;IACH,MAAM,EAAE,yBAAyB;IACjC,MAAM,SAAS,qBAAqB,EAAE,KAAK,WAAW,CAAC;IACvD,MAAM,SAAS,MAAM,OAAO,cAAc;IAC1C,MAAM,QAAQ,MAAM,OAAO,aAAa;IAExC,MAAM,EAAE,WAAW,UAAU,MAAM,OAAO;IAC1C,MAAM,EAAE,SAAS,aAAa,YAAY,MAAM,OAAO;IACvD,MAAM,aAAa,YAAY,KAAK,mBAAmB;AACvD,UAAM,MAAM,QAAQ,WAAW,EAAE,EAAE,WAAW,MAAM,CAAC;AACrD,UAAM,UAAU,YAAY,OAAO,QAAQ;AAC3C,UAAM,UACL,YAAY,QAAQ,WAAW,EAAE,cAAc,EAC/C,KAAK,UAAU,QAAQ,MAAM,EAAE,EAC/B,QACA;AACD,YAAQ,QAAQ,uBAAuB,OAAO,YAAY,OAAO,cAAc;YACvE,OAAO;AACf,YAAQ,KAAK,2BAA2B,iBAAiB,QAAQ,MAAM,UAAU,MAAM;;;AAM1F,UAAQ,MAAM,+BAA+B;EAE7C,MAAM,YAAY;GAAC;GAAS;GAAO;GAAU,KAAK;GAAK;EAGvD,MAAM,iBAAiB,MAAMA,aAAW,QAAQ,KAAK,iBAAiB,CAAC;EACvE,MAAM,iBAAiB,MAAMA,aAAW,QAAQ,KAAK,YAAY,CAAC;EAElE,IAAI;EACJ,IAAI;AAEJ,MAAI,gBAAgB;AACnB,SAAM;AACN,aAAU;aACA,gBAAgB;AAC1B,SAAM;AACN,aAAU;SACJ;AACN,SAAM;AACN,aAAU;;AAGX,UAAQ,KAAK,YAAY,IAAI,GAAG,QAAQ,KAAK,IAAI,GAAG;EAEpD,MAAM,QAAQ,MAAM,KAAK,SAAS;GACjC;GACA,OAAO;GACP,KAAK;IACJ,GAAG,QAAQ;IAEX,qBAAqB,QAAQ;IAC7B;GACD,CAAC;AAEF,QAAM,GAAG,UAAU,UAAU;AAC5B,WAAQ,MAAM,+BAA+B,MAAM;AACnD,WAAQ,KAAK,EAAE;IACd;AAEF,QAAM,GAAG,SAAS,SAAS;AAC1B,WAAQ,KAAK,QAAQ,EAAE;IACtB;EAGF,MAAM,gBAAgB;AACrB,SAAM,KAAK,UAAU;;AAGtB,UAAQ,GAAG,UAAU,QAAQ;AAC7B,UAAQ,GAAG,WAAW,QAAQ;;CAE/B,CAAC;;;;;;;;;ACxKF,eAAeC,aAAW,MAAgC;AACzD,KAAI;AACH,QAAM,OAAO,KAAK;AAClB,SAAO;SACA;AACP,SAAO;;;AAIT,SAAS,YAAY,QAA2B;AAO/C,EALC,OAAO,WAAW,SACf,QAAQ,UACR,OAAO,WAAW,SACjB,QAAQ,OACR,QAAQ,OACP,GAAG,OAAO,KAAK,IAAI,OAAO,UAAU;;AAG3C,eAAe,cAAc,QAAwC;CACpE,MAAM,UAAyB,EAAE;AAGjC,KAAI,CAAE,MAAMA,aAAW,OAAO,EAAG;AAChC,UAAQ,KAAK;GACZ,MAAM;GACN,QAAQ;GACR,SAAS,gBAAgB,OAAO;GAChC,CAAC;AACF,SAAO;;AAGR,SAAQ,KAAK;EACZ,MAAM;EACN,QAAQ;EACR,SAAS;EACT,CAAC;CAGF,IAAI;AACJ,KAAI;AACH,OAAK,eAAe,EAAE,KAAK,QAAQ,UAAU,CAAC;EAE9C,MAAM,EAAE,SAAS,YAAY,MAAM,mBAAmB,GAAG;AACzD,MAAI,QAAQ,WAAW,EACtB,SAAQ,KAAK;GACZ,MAAM;GACN,QAAQ;GACR,SAAS,GAAG,QAAQ,OAAO;GAC3B,CAAC;MAEF,SAAQ,KAAK;GACZ,MAAM;GACN,QAAQ;GACR,SAAS,GAAG,QAAQ,OAAO,YAAY,QAAQ,OAAO;GACtD,CAAC;EAGH,MAAM,EAAE,QAAQ,MAAM,OAAO;AAG7B,MAAI;GAIH,MAAM,SAHoB,MAAM,GAE9B,qDAAqD,QAAQ,GAAG,EAClC,KAAK,IAAI,SAAS;AAClD,WAAQ,KAAK;IACZ,MAAM;IACN,QAAQ,QAAQ,IAAI,SAAS;IAC7B,SACC,QAAQ,IAAI,GAAG,MAAM,wBAAwB;IAC9C,CAAC;UACK;AACP,WAAQ,KAAK;IACZ,MAAM;IACN,QAAQ;IACR,SAAS;IACT,CAAC;;AAIH,MAAI;GACH,MAAM,aAAa,MAAM,eAAe,IAAI,OAAO;GACnD,MAAM,oBAAoB,MAAM,GAE9B,uCAAuC,QAAQ,GAAG;GACpD,MAAM,kBAAkB,IAAI,IAAI,kBAAkB,KAAK,KAAK,MAAM,MAAM,EAAE,OAAO,CAAC;GAClF,MAAM,WAAW,WAAW,QAAQ,SAAS,CAAC,gBAAgB,IAAI,KAAK,CAAC;AAExE,OAAI,SAAS,SAAS,EACrB,SAAQ,KAAK;IACZ,MAAM;IACN,QAAQ;IACR,SAAS,SAAS,SAAS,OAAO,IAAI,SAAS,KAAK,KAAK;IACzD,CAAC;UAEI;AAKR,MAAI;GAIH,MAAM,SAHc,MAAM,GAExB,+CAA+C,QAAQ,GAAG,EAClC,KAAK,IAAI,SAAS;AAC5C,WAAQ,KAAK;IACZ,MAAM;IACN,QAAQ,QAAQ,IAAI,SAAS;IAC7B,SACC,QAAQ,IAAI,GAAG,MAAM,UAAU;IAChC,CAAC;UACK;AACP,WAAQ,KAAK;IACZ,MAAM;IACN,QAAQ;IACR,SAAS;IACT,CAAC;;UAEK,OAAO;AACf,UAAQ,KAAK;GACZ,MAAM;GACN,QAAQ;GACR,SAAS,iBAAiB,QAAQ,MAAM,UAAU;GAClD,CAAC;WACO;AACT,MAAI,GACH,OAAM,GAAG,SAAS;;AAIpB,QAAO;;AAGR,MAAa,gBAAgB,cAAc;CAC1C,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM;EACL,UAAU;GACT,MAAM;GACN,OAAO;GACP,aAAa;GACb,SAAS;GACT;EACD,KAAK;GACJ,MAAM;GACN,aAAa;GACb,SAAS,QAAQ,KAAK;GACtB;EACD,MAAM;GACL,MAAM;GACN,aAAa;GACb,SAAS;GACT;EACD;CACD,MAAM,IAAI,EAAE,QAAQ;EAInB,MAAM,UAAU,MAAM,cAFP,QADH,QAAQ,KAAK,IAAI,EACD,KAAK,SAAS,CAEC;AAE3C,MAAI,KAAK,MAAM;AACd,WAAQ,OAAO,MAAM,KAAK,UAAU,SAAS,MAAM,EAAE,GAAG,KAAK;AAC7D;;AAGD,UAAQ,MAAM,kBAAkB;AAEhC,OAAK,MAAM,UAAU,QACpB,aAAY,OAAO;EAIpB,MAAM,QAAQ,QAAQ,QAAQ,MAAM,EAAE,WAAW,OAAO;EACxD,MAAM,QAAQ,QAAQ,QAAQ,MAAM,EAAE,WAAW,OAAO;AAExD,UAAQ,IAAI,GAAG;AACf,MAAI,MAAM,WAAW,KAAK,MAAM,WAAW,EAC1C,SAAQ,QAAQ,oBAAoB;WAC1B,MAAM,WAAW,EAC3B,SAAQ,KAAK,+BAA+B,MAAM,OAAO,YAAY;OAC/D;AACN,WAAQ,MAAM,GAAG,MAAM,OAAO,eAAe;AAC7C,WAAQ,WAAW;;;CAGrB,CAAC;;;;;;;;;AC/KF,MAAM,kBAAkB;AAExB,MAAa,oBAAoB,cAAc;CAC9C,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM;EACL,UAAU;GACT,MAAM;GACN,OAAO;GACP,aAAa;GACb,SAAS;GACT;EACD,KAAK;GACJ,MAAM;GACN,aAAa;GACb,SAAS,QAAQ,KAAK;GACtB;EACD,gBAAgB;GACf,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,QAAQ;GACP,MAAM;GACN,aAAa;GACb,SAAS;GACT;EACD;CACD,MAAM,IAAI,EAAE,QAAQ;EAInB,MAAM,SAAS,QAHH,QAAQ,KAAK,IAAI,EAGD,KAAK,SAAS;AAC1C,UAAQ,KAAK,aAAa,SAAS;EAEnC,MAAM,KAAK,eAAe,EAAE,KAAK,QAAQ,UAAU,CAAC;AAGpD,MAAI;AACH,SAAM,cAAc,GAAG;WACf,OAAO;AACf,WAAQ,MAAM,qBAAqB,MAAM;AACzC,SAAM,GAAG,SAAS;AAClB,WAAQ,KAAK,EAAE;;AAGhB,MAAI;GACH,MAAM,OAAO,MAAM,WAAW,IAAI,KAAK,gBAAgB;GAGvD,MAAM,SAAS,KAAK,SAAS,KAAK,UAAU,MAAM,MAAM,IAAK,GAAG,KAAK,UAAU,KAAK;AAEpF,WAAQ,IAAI,OAAO;WACX,OAAO;AACf,WAAQ,MAAM,kBAAkB,MAAM;AACtC,SAAM,GAAG,SAAS;AAClB,WAAQ,KAAK,EAAE;;AAGhB,QAAM,GAAG,SAAS;;CAEnB,CAAC;;;;AAKF,eAAe,WAAW,IAAsB,aAAyC;CACxF,MAAM,OAAiB;EACtB,SAAS;EACT,SAAS;EACT,MAAM;GACL,MAAM;GACN,aAAa;GACb;EACD;AAGD,MAAK,WAAW,MAAM,eAAe,GAAG;AAGxC,MAAK,cAAc,MAAM,kBAAkB,GAAG;AAG9C,MAAK,aAAa,MAAM,iBAAiB,GAAG;AAG5C,MAAK,QAAQ,MAAM,YAAY,GAAG;AAGlC,MAAK,cAAc,MAAM,kBAAkB,GAAG;AAG9C,KAAI,gBAAgB,QAAW;EAC9B,MAAM,cACL,gBAAgB,MAAM,gBAAgB,SACnC,OACA,YACC,MAAM,IAAI,CACV,KAAK,MAAM,EAAE,MAAM,CAAC,CACpB,OAAO,QAAQ;AAEpB,OAAK,UAAU,MAAM,cAAc,IAAI,KAAK,eAAe,EAAE,EAAE,YAAY;;AAG5E,QAAO;;;;;AAMR,eAAe,eAAe,IAAqD;CAElF,MAAM,aAAa,MADH,IAAI,kBAAkB,GAAG,CACR,YAAY,gBAAgB;CAE7D,MAAM,WAAoC,EAAE;AAC5C,MAAK,MAAM,CAAC,KAAK,UAAU,YAAY;EACtC,MAAM,aAAa,IAAI,QAAQ,iBAAiB,GAAG;AACnD,WAAS,cAAc;;AAGxB,QAAO,OAAO,KAAK,SAAS,CAAC,SAAS,IAAI,WAAW;;;;;AAMtD,eAAe,kBAAkB,IAAiD;CACjF,MAAM,WAAW,IAAI,eAAe,GAAG;CACvC,MAAM,cAAc,MAAM,SAAS,iBAAiB;CACpD,MAAM,SAA2B,EAAE;AAEnC,MAAK,MAAM,cAAc,aAAa;EACrC,MAAM,SAAS,MAAM,SAAS,WAAW,WAAW,GAAG;EAEvD,MAAM,iBAAiC;GACtC,MAAM,WAAW;GACjB,OAAO,WAAW;GAClB,eAAe,WAAW,iBAAiB;GAC3C,aAAa,WAAW,eAAe;GACvC,MAAM,WAAW,QAAQ;GACzB,UACC,WAAW,SAAS,SAAS,IACzB,WAAW,WAOZ;GACJ,YAAY,WAAW,cAAc;GACrC,QAAQ,OAAO,KACb,WAAsB;IACtB,MAAM,MAAM;IACZ,OAAO,MAAM;IACb,MAAM,MAAM;IACZ,UAAU,MAAM,YAAY;IAC5B,QAAQ,MAAM,UAAU;IACxB,YAAY,MAAM,cAAc;IAChC,cAAc,MAAM;IACpB,YAAY,MAAM,aAAa,EAAE,GAAG,MAAM,YAAY,GAAG;IACzD,QAAQ,MAAM,UAAU;IACxB,SAAS,MAAM,WAAW;IAC1B,EACD;GACD;AAED,SAAO,KAAK,eAAe;;AAG5B,QAAO;;;;;AAMR,eAAe,iBAAiB,IAA+C;CAE9E,MAAM,OAAO,MAAM,GAAG,WAAW,wBAAwB,CAAC,WAAW,CAAC,SAAS;CAE/E,MAAM,SAAyB,EAAE;CACjC,MAAM,WAAW,IAAI,mBAAmB,GAAG;AAE3C,MAAK,MAAM,OAAO,MAAM;EAEvB,MAAM,QAAQ,MAAM,SAAS,WAAW,IAAI,KAAK;EAGjD,MAAM,YAAgC,EAAE;EAGxC,MAAM,2BAAW,IAAI,KAAqB;AAC1C,OAAK,MAAM,QAAQ,MAClB,UAAS,IAAI,KAAK,IAAI,KAAK,KAAK;AAGjC,OAAK,MAAM,QAAQ,OAAO;GACzB,MAAM,WAA6B;IAClC,MAAM,KAAK;IACX,OAAO,KAAK;IACZ,aAAa,OAAO,KAAK,MAAM,gBAAgB,WAAW,KAAK,KAAK,cAAc;IAClF;AAGD,OAAI,KAAK,SACR,UAAS,SAAS,SAAS,IAAI,KAAK,SAAS;AAG9C,aAAU,KAAK,SAAS;;EAGzB,MAAM,WAAyB;GAC9B,MAAM,IAAI;GACV,OAAO,IAAI;GACX,eAAe,IAAI,kBAAkB;GACrC,cAAc,IAAI,iBAAiB;GACnC,aAAa,IAAI,cAAc,KAAK,MAAM,IAAI,YAAY,GAAG,EAAE;GAC/D;AAED,MAAI,UAAU,SAAS,EACtB,UAAS,QAAQ;AAGlB,SAAO,KAAK,SAAS;;AAGtB,QAAO;;;;;AAMR,eAAe,YAAY,IAA2C;CAErE,MAAM,QAAQ,MAAM,GAAG,WAAW,gBAAgB,CAAC,WAAW,CAAC,SAAS;CAExE,MAAM,SAAqB,EAAE;AAE7B,MAAK,MAAM,QAAQ,OAAO;EAUzB,MAAM,YAAY,kBARJ,MAAM,GAClB,WAAW,qBAAqB,CAChC,WAAW,CACX,MAAM,WAAW,KAAK,KAAK,GAAG,CAC9B,QAAQ,cAAc,MAAM,CAC5B,SAAS,CAG+B;AAE1C,SAAO,KAAK;GACX,MAAM,KAAK;GACX,OAAO,KAAK;GACZ,OAAO;GACP,CAAC;;AAGH,QAAO;;;AAIR,SAAS,aAAa,GAAoC;AACzD,QAAO,MAAM,aAAa,MAAM,UAAU,MAAM;;;;;AAMjD,SAAS,kBACR,OAYiB;CAEjB,MAAM,2BAAW,IAAI,KAAkC;AAEvD,MAAK,MAAM,QAAQ,OAAO;EACzB,MAAM,WAAW,KAAK;AACtB,MAAI,CAAC,SAAS,IAAI,SAAS,CAC1B,UAAS,IAAI,UAAU,EAAE,CAAC;AAE3B,WAAS,IAAI,SAAS,CAAE,KAAK,KAAK;;CAInC,SAAS,WAAW,UAAyC;AAE5D,UADiB,SAAS,IAAI,SAAS,IAAI,EAAE,EAC7B,KAAK,SAAS;GAC7B,MAAM,WAAyB;IAC9B,MAAM,KAAK;IACX,OAAO,KAAK,SAAS;IACrB;AAED,OAAI,KAAK,SAAS,SACjB,UAAS,MAAM,KAAK,cAAc;QAC5B;AACN,aAAS,MAAM,KAAK,gBAAgB;AACpC,aAAS,aAAa,KAAK,wBAAwB;;AAGpD,OAAI,KAAK,WAAW,SACnB,UAAS,SAAS;AAEnB,OAAI,KAAK,WACR,UAAS,YAAY,KAAK;AAE3B,OAAI,KAAK,YACR,UAAS,aAAa,KAAK;GAI5B,MAAM,eAAe,WAAW,KAAK,GAAG;AACxC,OAAI,aAAa,SAAS,EACzB,UAAS,WAAW;AAGrB,UAAO;IACN;;AAGH,QAAO,WAAW,KAAK;;;;;AAMxB,eAAe,kBAAkB,IAAiD;CAEjF,MAAM,QAAQ,MAAM,GAAG,WAAW,uBAAuB,CAAC,WAAW,CAAC,SAAS;CAE/E,MAAM,SAA2B,EAAE;AAEnC,MAAK,MAAM,QAAQ,OAAO;EASzB,MAAM,eAPU,MAAM,GACpB,WAAW,kBAAkB,CAC7B,WAAW,CACX,MAAM,WAAW,KAAK,KAAK,GAAG,CAC9B,QAAQ,cAAc,MAAM,CAC5B,SAAS,EAGT,QAAQ,MAAM,aAAa,EAAE,KAAK,CAAC,CACnC,KAAK,WAAW;GAEhB,MAAM,aAAyB,EAC9B,MAFiC,aAAa,OAAO,KAAK,GAAG,OAAO,OAAO,WAG3E;AAED,OAAI,OAAO,MACV,YAAW,QAAQ,OAAO;AAG3B,OAAI,OAAO,SAAS,aAAa,OAAO,QACvC,YAAW,UAAU,KAAK,MAAM,OAAO,QAAQ;YACrC,OAAO,SAAS,UAAU,OAAO,UAC3C,YAAW,WAAW,OAAO;YACnB,OAAO,SAAS,aAAa;AACvC,QAAI,OAAO,aACV,YAAW,cAAc,OAAO;AAEjC,QAAI,OAAO,gBACV,YAAW,QAAQ,KAAK,MAAM,OAAO,gBAAgB;;AAIvD,UAAO;IACN;AAEH,SAAO,KAAK;GACX,MAAM,KAAK;GACX,OAAO,KAAK;GACZ,aAAa,KAAK,eAAe;GACjC,SAAS;GACT,CAAC;;AAGH,QAAO;;;;;AAMR,eAAe,cACd,IACA,aACA,oBAC8C;CAC9C,MAAM,UAA8C,EAAE;CACtD,MAAM,cAAc,IAAI,kBAAkB,GAAG;CAC7C,MAAM,eAAe,IAAI,mBAAmB,GAAG;CAC/C,MAAM,YAAY,IAAI,gBAAgB,GAAG;CAGzC,MAAM,2BAAW,IAAI,KAGlB;AACH,KAAI;EACH,IAAI;AACJ,KAAG;GACF,MAAM,SAAS,MAAM,UAAU,SAAS;IACvC,OAAO;IACP;IACA,QAAQ;IACR,CAAC;AACF,QAAK,MAAM,SAAS,OAAO,MAC1B,UAAS,IAAI,MAAM,IAAI;IACtB,KAAK,2BAA2B,MAAM;IACtC,UAAU,MAAM;IAChB,KAAK,MAAM,OAAO;IAClB,SAAS,MAAM,WAAW;IAC1B,CAAC;AAEH,YAAS,OAAO;WACR;SACF;CAIR,MAAM,cAAc,eAAe;AAEnC,MAAK,MAAM,cAAc,aAAa;AAErC,MAAI,sBAAsB,CAAC,mBAAmB,SAAS,WAAW,KAAK,CACtE;EAGD,MAAM,UAA8B,EAAE;EACtC,IAAI;EAKJ,MAAM,2CAA2B,IAAI,KAAqB;AAG1D,KAAG;GACF,MAAM,SAAS,MAAM,YAAY,SAAS,WAAW,MAAM;IAC1D,OAAO;IACP;IACA,CAAC;AAEF,QAAK,MAAM,QAAQ,OAAO,OAAO;IAEhC,MAAM,SAAS,KAAK,OACjB,eAAe,KAAK,SACnB,GAAG,WAAW,KAAK,GAAG,KAAK,KAAK,GAAG,KAAK,WACxC,GAAG,WAAW,KAAK,GAAG,KAAK,SAC5B,KAAK;IAGR,MAAM,gBAAgB,qBAAqB,KAAK,MAAM,WAAW,QAAQ,SAAS;IAElF,MAAM,QAA0B;KAC/B,IAAI;KACJ,MAAM,KAAK,QAAQ,KAAK;KACxB,QAAQ,KAAK,WAAW,eAAe,KAAK,WAAW,UAAU,KAAK,SAAS;KAC/E,MAAM;KACN;AAGD,QAAI,eAAe,KAAK,QAAQ;AAC/B,WAAM,SAAS,KAAK;AAEpB,SAAI,KAAK,kBAAkB;MAC1B,MAAM,eAAe,yBAAyB,IAAI,KAAK,iBAAiB;AACxE,UAAI,aAEH,OAAM,gBAAgB;UAGtB,0BAAyB,IAAI,KAAK,kBAAkB,OAAO;;;IAM9D,MAAM,aAAa,MAAM,uBAAuB,cAAc,WAAW,MAAM,KAAK,GAAG;AACvF,QAAI,OAAO,KAAK,WAAW,CAAC,SAAS,EACpC,OAAM,aAAa;AAGpB,YAAQ,KAAK,MAAM;;AAGpB,YAAS,OAAO;WACR;AAET,MAAI,eAAe,QAAQ,SAAS,EAGnC,SAAQ,MAAM,GAAG,MAAM;AACtB,OAAI,EAAE,iBAAiB,CAAC,EAAE,cAAe,QAAO;AAChD,OAAI,CAAC,EAAE,iBAAiB,EAAE,cAAe,QAAO;AAChD,UAAO;IACN;AAGH,MAAI,QAAQ,SAAS,EACpB,SAAQ,WAAW,QAAQ;;AAI7B,QAAO;;;;;AAMR,SAAS,qBACR,MACA,QACA,UAC0B;CAC1B,MAAM,SAAkC,EAAE;CAG1C,MAAM,6BAAa,IAAI,KAAwB;AAC/C,MAAK,MAAM,SAAS,OACnB,YAAW,IAAI,MAAM,MAAM,MAAM,KAAK;AAGvC,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,EAAE;EAChD,MAAM,YAAY,WAAW,IAAI,IAAI;AAErC,MAAI,cAAc,WAAW,SAAS,OAAO,UAAU,UAAU;GAEhE,MAAM,aAAa;AACnB,OAAI,WAAW,IAAI;IAClB,MAAM,YAAY,SAAS,IAAI,WAAW,GAAG;AAC7C,QAAI,WAAW;AACd,YAAO,OAAO,EACb,QAAQ;MACP,KAAK,UAAU;MACf,UAAU,UAAU;MACpB,KAAK,WAAW,OAAO,UAAU;MACjC,SAAS,UAAU;MACnB,EACD;AACD;;;AAIF,UAAO,OAAO;aACJ,cAAc,eAAe,OAAO,UAAU,SAExD,QAAO,OAAO,QAAQ;WACZ,MAAM,QAAQ,MAAM,CAE9B,QAAO,OAAO,MAAM,KAAK,SAAS;AACjC,OAAI,OAAO,SAAS,YAAY,cAAc,YAC7C,QAAO,QAAQ;AAEhB,UAAO;IACN;MAEF,QAAO,OAAO;;AAIhB,QAAO;;;;;AAMR,eAAe,uBACd,cACA,YACA,SACoC;CACpC,MAAM,QAAQ,MAAM,aAAa,iBAAiB,YAAY,QAAQ;CACtE,MAAM,SAAmC,EAAE;AAE3C,MAAK,MAAM,QAAQ,OAAO;AACzB,MAAI,CAAC,OAAO,KAAK,MAChB,QAAO,KAAK,QAAQ,EAAE;AAEvB,SAAO,KAAK,MAAM,KAAK,KAAK,KAAK;;AAGlC,QAAO;;;;;;;;;;AC1lBR,eAAeC,aAAW,MAAgC;AACzD,KAAI;AACH,QAAM,OAAO,KAAK;AAClB,SAAO;SACA;AACP,SAAO;;;AAIT,eAAeC,kBAAgB,KAA0C;CACxE,MAAM,UAAU,QAAQ,KAAK,eAAe;AAC5C,KAAI;EACH,MAAM,UAAU,MAAM,SAAS,SAAS,QAAQ;AAChD,SAAO,KAAK,MAAM,QAAQ;SACnB;AACP,SAAO;;;AAIT,eAAe,WAAW,IAAuC,UAAiC;CAUjG,MAAM,cATM,MAAM,SAAS,UAAU,QAAQ,EAI3C,MAAM,KAAK,CACX,QAAQ,SAAS,CAAC,KAAK,MAAM,CAAC,WAAW,KAAK,CAAC,CAC/C,KAAK,KAAK,CAIV,MAAM,IAAI,CACV,KAAK,MAAM,EAAE,MAAM,CAAC,CACpB,QAAQ,MAAM,EAAE,SAAS,EAAE;AAE7B,MAAK,MAAM,aAAa,WACvB,OAAM,GAAG,aAAa;EACrB,KAAK;EACL,YAAY,EAAE;EACd,OAAO;GAAE,MAAM;GAAW,cAAc,CAAC,UAAU;GAAE,YAAY,EAAE;GAAE;EACrE,CAAC;;;;;AAOJ,eAAe,qBAAqB,IAAyD;AAC5F,KAAI;EAEH,MAAM,EAAE,QAAQ,MAAM,OAAO;EAI7B,MAAM,OAHS,MAAM,GAEnB,qDAAqD,QAAQ,GAAG,EAC/C,KAAK;AACxB,SAAO,MAAM,IAAI,QAAQ,IAAI;SACtB;AAEP,SAAO;;;AAIT,MAAa,cAAc,cAAc;CACxC,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM;EACL,UAAU;GACT,MAAM;GACN,OAAO;GACP,aAAa;GACb,SAAS;GACT;EACD,KAAK;GACJ,MAAM;GACN,aAAa;GACb,SAAS,QAAQ,KAAK;GACtB;EACD,OAAO;GACN,MAAM;GACN,OAAO;GACP,aAAa;GACb,SAAS;GACT;EACD;CACD,MAAM,IAAI,EAAE,QAAQ;EACnB,MAAM,MAAM,QAAQ,KAAK,IAAI;AAC7B,UAAQ,MAAM,yBAAyB;EAGvC,MAAM,MAAM,MAAMA,kBAAgB,IAAI;AACtC,MAAI,CAAC,KAAK;AACT,WAAQ,MAAM,4BAA4B,IAAI;AAC9C,WAAQ,KAAK,EAAE;;EAGhB,MAAM,SAAS,IAAI;AACnB,UAAQ,KAAK,YAAY,IAAI,QAAQ,YAAY;AAEjD,MAAI,QAAQ,MACX,SAAQ,KAAK,aAAa,OAAO,QAAQ;EAI1C,MAAM,SAAS,QAAQ,KAAK,KAAK,SAAS;AAC1C,UAAQ,KAAK,aAAa,SAAS;EAEnC,MAAM,KAAK,eAAe,EAAE,KAAK,QAAQ,UAAU,CAAC;AAGpD,UAAQ,MAAM,wBAAwB;AACtC,MAAI;GACH,MAAM,EAAE,YAAY,MAAM,cAAc,GAAG;AAC3C,OAAI,QAAQ,SAAS,GAAG;AACvB,YAAQ,QAAQ,WAAW,QAAQ,OAAO,aAAa;AACvD,SAAK,MAAM,QAAQ,QAClB,SAAQ,KAAK,OAAO,OAAO;SAG5B,SAAQ,KAAK,gCAAgC;WAEtC,OAAO;AACf,WAAQ,MAAM,qBAAqB,MAAM;AACzC,SAAM,GAAG,SAAS;AAClB,WAAQ,KAAK,EAAE;;EAIhB,MAAM,qBAAqB,MAAM,qBAAqB,GAAG;AACzD,MAAI,sBAAsB,CAAC,KAAK,OAAO;AACtC,SAAM,GAAG,SAAS;AAClB,WAAQ,QAAQ,0DAA0D;AAC1E;;AAGD,MAAI,sBAAsB,KAAK,MAC9B,SAAQ,KAAK,+BAA+B;AAI7C,MAAI,QAAQ,QAAQ;GACnB,MAAM,aAAa,QAAQ,KAAK,OAAO,OAAO;AAC9C,OAAI,MAAMD,aAAW,WAAW,EAAE;AACjC,YAAQ,MAAM,mBAAmB,OAAO,SAAS;AACjD,QAAI;AACH,WAAM,WAAW,IAAI,WAAW;AAChC,aAAQ,QAAQ,iBAAiB;aACzB,OAAO;AACf,aAAQ,MAAM,kBAAkB,MAAM;AACtC,WAAM,GAAG,SAAS;AAClB,aAAQ,KAAK,EAAE;;SAGhB,SAAQ,KAAK,0BAA0B,OAAO,SAAS;;AAQzD,QAAM,GAAG,SAAS;AAClB,UAAQ,QAAQ,mCAAmC;AACnD,UAAQ,KAAK,iDAAiD;;CAE/D,CAAC;;;;;;;;;;;;;;;;;ACzHF,eAAe,aACd,eACA,YACA,UACA,WACA,SACyB;CACzB,MAAM,WAAW,KAAK,KAAK,GAAG,YAAY;CAC1C,IAAI,kBAAkB;AAEtB,QAAO,KAAK,KAAK,GAAG,UAAU;AAC7B,QAAM,IAAI,SAAS,YAAY,WAAW,SAAS,kBAAkB,IAAK,CAAC;EAE3E,MAAM,MAAM,MAAM,QAAQ,eAAe;GACxC,QAAQ;GACR,SAAS,EAAE,gBAAgB,oBAAoB;GAC/C,MAAM,KAAK,UAAU;IACpB,aAAa;IACb,YAAY;IACZ,CAAC;GACF,CAAC;AAEF,MAAI,IAAI,GACP,QAAQ,MAAM,IAAI,MAAM;EAGzB,MAAM,OAAQ,MAAM,IAAI,MAAM;AAE9B,MAAI,KAAK,UAAU,wBAElB;AAGD,MAAI,KAAK,UAAU,aAAa;AAE/B,qBAAkB,KAAK,YAAY,kBAAkB;AACrD;;AAGD,MAAI,KAAK,UAAU,gBAClB,OAAM,IAAI,MAAM,yCAAyC;AAG1D,MAAI,KAAK,UAAU,gBAClB,OAAM,IAAI,MAAM,4BAA4B;AAI7C,QAAM,IAAI,MAAM,0BAA0B,KAAK,SAAS,IAAI,aAAa;;AAG1E,OAAM,IAAI,MAAM,mDAAmD;;;;;;;;;;;AAgBpE,eAAe,qBAAqB,SAAyC;AAC5E,WAAQ,KAAK,yCAAyC;CAGtD,MAAM,SAAS,MAAM,qBAAqB,QAAQ;AAClD,KAAI,QAAQ;AACX,YAAQ,QAAQ,yDAAyD;AACzE,SAAO;;AAIR,WAAQ,KAAK,mDAAmD;AAGhE,KAFgB,MAAM,oBAAoB,QAAQ,EAErC;EACZ,MAAM,QAAQ,MAAM,qBAAqB,QAAQ;AACjD,MAAI,OAAO;AACV,aAAQ,QAAQ,+CAA+C;AAC/D,UAAO;;;AAKT,SAAQ,KAAK;AACb,WAAQ,KAAK,+DAA+D;AAC5E,WAAQ,KAAK,wBAAwB;AACrC,SAAQ,KAAK;AACb,WAAQ,KAAK,KAAK,GAAG,KAAK,YAAY,CAAC,+BAA+B;AACtE,SAAQ,IAAI,OAAO,GAAG,KAAK,4BAA4B,UAAU,GAAG;AACpE,SAAQ,IAAI,OAAO,GAAG,KAAK,sBAAsB,UAAU,GAAG;AAC9D,SAAQ,KAAK;AACb,WAAQ,KAAK,KAAK,GAAG,KAAK,YAAY,CAAC,uBAAuB;AAC9D,SAAQ,IACP,OAAO,GAAG,KAAK,sBAAsB,QAAQ,wEAAwE,GACrH;AACD,SAAQ,KAAK;AAEb,QAAO;;AAOR,MAAa,eAAe,cAAc;CACzC,MAAM;EAAE,MAAM;EAAS,aAAa;EAAgC;CACpE,MAAM;EACL,KAAK;GACJ,MAAM;GACN,OAAO;GACP,aAAa;GACb,SAAS;GACT;EACD,QAAQ;GACP,MAAM;GACN,OAAO;GACP,aAAa;GACb;EACD;CACD,MAAM,IAAI,EAAE,QAAQ;EACnB,MAAM,UAAU,KAAK,OAAO;AAC5B,YAAQ,MAAM,iBAAiB,QAAQ,KAAK;EAG5C,MAAM,gBAAgB,sBAAsB;EAC5C,IAAI,cAAc,uBAAuB,cAAc;AAEvD,MAAI;GAGH,MAAM,eAAe,IAAI,IAAI,6BAA6B,QAAQ;GAClE,IAAI,MAAM,MAAM,YAAY,cAAc,EAAE,UAAU,UAAU,CAAC;AAGjE,OAAI,iBAAiB,IAAI,EAAE;IAC1B,MAAM,cAAc,MAAM,qBAAqB,QAAQ;AACvD,QAAI,CAAC,YACJ;AAGD,kBAAc,qBAAqB;AACnC,kBAAc,uBAAuB,cAAc;AACnD,UAAM,MAAM,YAAY,aAAa;cAC3B,IAAI,WAAW,OAAO,IAAI,WAAW,IAE/C,OAAM,MAAM,YAAY,aAAa;AAGtC,OAAI,CAAC,IAAI,IAAI;AACZ,QAAI,IAAI,WAAW,KAAK;AAEvB,SADgB,QAAQ,SAAS,YAAY,IAAI,QAAQ,SAAS,YAAY,EACjE;AACZ,gBAAQ,KAAK,qDAAqD;MAClE,MAAM,YAAY,MAAM,MAAM,IAAI,IAAI,gCAAgC,QAAQ,EAAE,EAC/E,UAAU,UACV,CAAC;AACF,UAAI,UAAU,WAAW,OAAO,UAAU,GACzC,WAAQ,QAAQ,gEAAgE;UAEhF,WAAQ,MAAM,qDAAqD;WAGpE,WAAQ,MAAM,iEAAiE;AAEhF;;AAED,cAAQ,MAAM,qBAAqB,IAAI,OAAO,GAAG,IAAI,aAAa;AAClE,YAAQ,KAAK,EAAE;;GAGhB,MAAM,YAAa,MAAM,IAAI,MAAM;AACnC,aAAQ,QAAQ,gBAAgB,UAAU,UAAU,QAAQ,WAAW;GAEvE,MAAM,aAAa,UAAU,MAAM,SAAS;AAE5C,OAAI,CAAC,YAAY;AAEhB,cAAQ,KAAK,kDAAkD;AAC/D,cAAQ,KAAK,iDAAiD;AAC9D,cAAQ,KAAK,aAAa,GAAG,KAAK,gCAAgC,UAAU,GAAG;AAC/E;;GAID,MAAM,UAAU,IAAI,IAAI,WAAW,+BAA+B,QAAQ;GAC1E,MAAM,UAAU,MAAM,YAAY,SAAS;IAC1C,QAAQ;IACR,SAAS;KACR,gBAAgB;KAChB,oBAAoB;KACpB;IACD,MAAM,KAAK,UAAU,EACpB,WAAW,cACX,CAAC;IACF,CAAC;AAEF,OAAI,CAAC,QAAQ,IAAI;AAChB,cAAQ,MAAM,kCAAkC,QAAQ,SAAS;AACjE,YAAQ,KAAK,EAAE;;GAGhB,MAAM,aAAc,MAAM,QAAQ,MAAM;AAGxC,WAAQ,KAAK;AACb,aAAQ,KAAK,wBAAwB;AACrC,WAAQ,IAAI,KAAK,GAAG,KAAK,GAAG,KAAK,WAAW,iBAAiB,CAAC,GAAG;AACjE,WAAQ,KAAK;AACb,aAAQ,KAAK,eAAe,GAAG,OAAO,GAAG,KAAK,WAAW,UAAU,CAAC,GAAG;AACvE,WAAQ,KAAK;AAGb,OAAI;IACH,MAAM,EAAE,aAAa,MAAM,OAAO;AAClC,QAAI,QAAQ,aAAa,SACxB,UAAS,QAAQ,CAAC,WAAW,iBAAiB,CAAC;aACrC,QAAQ,aAAa,QAC/B,UAAS,OAAO;KAAC;KAAM;KAAS;KAAI,WAAW;KAAiB,CAAC;QAEjE,UAAS,YAAY,CAAC,WAAW,iBAAiB,CAAC;WAE7C;AAKR,aAAQ,MAAM,+BAA+B;GAG7C,MAAM,cAAc,MAAM,aADT,IAAI,IAAI,WAAW,gBAAgB,QAAQ,CAElD,UAAU,EACnB,WAAW,aACX,WAAW,UACX,WAAW,YACX,YACA;GAGD,IAAI,YAAY;GAChB,IAAI,WAAW;AACf,OAAI;IACH,MAAM,QAAQ,MAAM,YAAY,IAAI,IAAI,wBAAwB,QAAQ,EAAE,EACzE,SAAS,EAAE,eAAe,UAAU,YAAY,gBAAgB,EAChE,CAAC;AACF,QAAI,MAAM,IAAI;KAIb,MAAM,MAHU,MAAM,MAAM,MAAM,EAGhB;AAClB,iBAAY,GAAG,SAAS;AASxB,iBAAY,GAAG,OAP2B;MACzC,IAAI;MACJ,IAAI;MACJ,IAAI;MACJ,IAAI;MACJ,IAAI;MACJ,CAC+B,GAAG,QAAQ,WAAc;;WAEnD;GAKR,MAAM,YAAY,IAAI,KAAK,KAAK,KAAK,GAAG,YAAY,aAAa,IAAK,CAAC,aAAa;GACpF,MAAM,mBAAmB,OAAO,KAAK,cAAc,CAAC,SAAS;AAC7D,mBAAgB,SAAS;IACxB,aAAa,YAAY;IACzB,cAAc,YAAY;IAC1B;IACA,GAAI,mBAAmB,EAAE,eAAe,GAAG,EAAE;IAC7C,MAAM;KAAE,OAAO;KAAW,MAAM;KAAU;IAC1C,CAAC;AAEF,aAAQ,QAAQ,gBAAgB,GAAG,KAAK,UAAU,CAAC,IAAI,SAAS,GAAG;AACnE,aAAQ,KAAK,kBAAkB,GAAG,IAAI,qBAAqB,QAAQ,CAAC,GAAG;WAC/D,OAAO;AACf,aAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,eAAe;AACtE,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;AAEF,MAAa,gBAAgB,cAAc;CAC1C,MAAM;EAAE,MAAM;EAAU,aAAa;EAAiC;CACtE,MAAM,EACL,KAAK;EACJ,MAAM;EACN,OAAO;EACP,aAAa;EACb,SAAS;EACT,EACD;CACD,MAAM,IAAI,EAAE,QAAQ;EACnB,MAAM,UAAU,KAAK,OAAO;EAG5B,MAAM,OAAO,eAAe,QAAQ;AAEpC,MAAI,CAAC,MAAM;AACV,aAAQ,KAAK,iDAAiD;AAC9D;;EAGD,MAAM,cAAc,uBAAuB,KAAK,iBAAiB,EAAE,CAAC;AAGpE,MAAI;AAEH,SAAM,YAAY,IAAI,IAAI,mCAAmC,QAAQ,EAAE;IACtE,QAAQ;IACR,SAAS,EAAE,gBAAgB,oBAAoB;IAC/C,MAAM,KAAK,UAAU,EAAE,OAAO,KAAK,cAAc,CAAC;IAClD,CAAC;UACK;AAKR,oBAAkB,QAAQ;AAC1B,YAAQ,QAAQ,2BAA2B;;CAE5C,CAAC;AAEF,MAAa,gBAAgB,cAAc;CAC1C,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM;EACL,KAAK;GACJ,MAAM;GACN,OAAO;GACP,aAAa;GACb,SAAS;GACT;EACD,OAAO;GACN,MAAM;GACN,OAAO;GACP,aAAa;GACb;EACD,MAAM;GACL,MAAM;GACN,aAAa;GACb;EACD;CACD,MAAM,IAAI,EAAE,QAAQ;EACnB,MAAM,UAAU,KAAK,OAAO;EAG5B,IAAI,QAAQ,KAAK,SAAS,QAAQ,IAAI;EACtC,IAAI,aAAa,QAAQ,UAAU;EACnC,IAAI,gBAAwC,EAAE;AAE9C,MAAI,CAAC,OAAO;GACX,MAAM,OAAO,eAAe,QAAQ;AACpC,OAAI,MAAM;AACT,YAAQ,KAAK;AACb,iBAAa;AACb,oBAAgB,KAAK,iBAAiB,EAAE;AAGxC,QAAI,IAAI,KAAK,KAAK,UAAU,mBAAG,IAAI,MAAM,EAAE;KAC1C,MAAM,cAAc,uBAAuB,cAAc;AAEzD,SAAI;MACH,MAAM,aAAa,MAAM,YACxB,IAAI,IAAI,oCAAoC,QAAQ,EACpD;OACC,QAAQ;OACR,SAAS,EAAE,gBAAgB,oBAAoB;OAC/C,MAAM,KAAK,UAAU;QACpB,eAAe,KAAK;QACpB,YAAY;QACZ,CAAC;OACF,CACD;AACD,UAAI,WAAW,IAAI;OAClB,MAAM,YAAa,MAAM,WAAW,MAAM;AAC1C,eAAQ,UAAU;AAClB,uBAAgB,SAAS;QACxB,GAAG;QACH,aAAa,UAAU;QACvB,WAAW,IAAI,KAAK,KAAK,KAAK,GAAG,UAAU,aAAa,IAAK,CAAC,aAAa;QAC3E,CAAC;aACI;AACN,iBAAQ,KAAK,6DAA6D;AAC1E,eAAQ,KAAK,EAAE;;aAET;AACP,gBAAQ,KAAK,0CAA0C;AACvD,cAAQ,KAAK,EAAE;;;;;AAMnB,MAAI,CAAC,OAAO;AAGX,OADgB,QAAQ,SAAS,YAAY,IAAI,QAAQ,SAAS,YAAY,EACjE;AACZ,iBAAa;AACb,cAAQ,KAAK,gBAAgB,GAAG,KAAK,aAAa,GAAG;AACrD,cAAQ,KAAK,mEAAmE;AAChF;;AAGD,aAAQ,MAAM,mCAAmC;AACjD,WAAQ,KAAK,EAAE;;EAGhB,MAAM,cAAc,uBAAuB,cAAc;AAEzD,MAAI;GACH,MAAM,QAAQ,MAAM,YAAY,IAAI,IAAI,wBAAwB,QAAQ,EAAE,EACzE,SAAS,EAAE,eAAe,UAAU,SAAS,EAC7C,CAAC;AAEF,OAAI,CAAC,MAAM,IAAI;AACd,QAAI,MAAM,WAAW,KAAK;AACzB,eAAQ,MAAM,iDAAiD;AAC/D,aAAQ,KAAK,EAAE;;AAEhB,cAAQ,MAAM,8BAA8B,MAAM,SAAS;AAC3D,YAAQ,KAAK,EAAE;;GAWhB,MAAM,MARO,MAAM,MAAM,MAAM,EAQhB;GAEf,MAAM,YAAoC;IACzC,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ;AAED,OAAI,KAAK,KACR,SAAQ,IACP,KAAK,UAAU;IACd,IAAI,GAAG;IACP,OAAO,GAAG;IACV,MAAM,GAAG;IACT,MAAM,UAAU,GAAG,SAAS,YAAY,GAAG,KAAK;IAChD;IACA,KAAK;IACL,CAAC,CACF;QACK;AACN,cAAQ,KAAK,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG;AAC3C,QAAI,GAAG,KAAM,WAAQ,KAAK,UAAU,GAAG,OAAO;AAC9C,cAAQ,KAAK,UAAU,GAAG,KAAK,UAAU,GAAG,SAAS,YAAY,GAAG,KAAK,GAAG,GAAG;AAC/E,cAAQ,KAAK,UAAU,GAAG,IAAI,WAAW,GAAG;AAC5C,cAAQ,KAAK,UAAU,GAAG,IAAI,QAAQ,GAAG;;WAElC,OAAO;AACf,aAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,gBAAgB;AACvE,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;;;;;;;;;ACnhBF,MAAME,gBAAc,cAAc;CACjC,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM;EACL,GAAG;EACH,MAAM;GACL,MAAM;GACN,aAAa;GACb;EACD,OAAO;GACN,MAAM;GACN,aAAa;GACb;EACD,QAAQ;GACP,MAAM;GACN,aAAa;GACb;EACD;CACD,MAAM,IAAI,EAAE,QAAQ;EACnB,MAAM,SAAS,qBAAqB,KAAK;AAEzC,MAAI;AAOH,UANe,MAAM,OAAO,UAAU;IACrC,UAAU,KAAK;IACf,OAAO,KAAK,QAAQ,OAAO,KAAK,MAAM,GAAG;IACzC,QAAQ,KAAK;IACb,CAAC,EAEa,KAAK;WACZ,OAAO;AACf,aAAQ,MAAM,yBAAyB,iBAAiB,QAAQ,MAAM,UAAU,MAAM;AACtF,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;AAEF,MAAM,gBAAgB,cAAc;CACnC,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM;EACL,MAAM;GACL,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,GAAG;EACH,KAAK;GACJ,MAAM;GACN,aAAa;GACb;EACD,SAAS;GACR,MAAM;GACN,aAAa;GACb;EACD;CACD,MAAM,IAAI,EAAE,QAAQ;EACnB,MAAM,SAAS,qBAAqB,KAAK;EACzC,MAAM,WAAW,SAAS,KAAK,KAAK;AAEpC,YAAQ,MAAM,aAAa,SAAS,KAAK;AAEzC,MAAI;GACH,MAAM,SAAS,MAAM,SAAS,KAAK,KAAK;GACxC,MAAM,SAAS,MAAM,OAAO,YAAY,QAAQ,UAAU;IACzD,KAAK,KAAK;IACV,SAAS,KAAK;IACd,CAAC;AAEF,aAAQ,QAAQ,YAAY,WAAW;AACvC,UAAO,QAAQ,KAAK;WACZ,OAAO;AACf,aAAQ,MAAM,qBAAqB,iBAAiB,QAAQ,MAAM,UAAU,MAAM;AAClF,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;AAEF,MAAMC,eAAa,cAAc;CAChC,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM;EACL,IAAI;GACH,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,GAAG;EACH;CACD,MAAM,IAAI,EAAE,QAAQ;EACnB,MAAM,SAAS,qBAAqB,KAAK;AAEzC,MAAI;AAEH,UADe,MAAM,OAAO,SAAS,KAAK,GAAG,EAC9B,KAAK;WACZ,OAAO;AACf,aAAQ,MAAM,wBAAwB,iBAAiB,QAAQ,MAAM,UAAU,MAAM;AACrF,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;AAEF,MAAMC,kBAAgB,cAAc;CACnC,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM;EACL,IAAI;GACH,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,GAAG;EACH;CACD,MAAM,IAAI,EAAE,QAAQ;EACnB,MAAM,SAAS,qBAAqB,KAAK;AAEzC,MAAI;AACH,SAAM,OAAO,YAAY,KAAK,GAAG;AAEjC,OAAI,KAAK,KACR,QAAO,EAAE,SAAS,MAAM,EAAE,KAAK;OAE/B,WAAQ,QAAQ,sBAAsB,KAAK,KAAK;WAEzC,OAAO;AACf,aAAQ,MAAM,2BAA2B,iBAAiB,QAAQ,MAAM,UAAU,MAAM;AACxF,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;AAEF,MAAa,eAAe,cAAc;CACzC,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,aAAa;EACZ,MAAMF;EACN,QAAQ;EACR,KAAKC;EACL,QAAQC;EACR;CACD,CAAC;;;;;;;;;ACxJF,MAAMC,gBAAc,cAAc;CACjC,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM,EACL,GAAG,gBACH;CACD,MAAM,IAAI,EAAE,QAAQ;AACnB,MAAI;AAGH,UADc,MADC,qBAAqB,KAAK,CACd,OAAO,EACpB,KAAK;WACX,OAAO;AACf,aAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,gBAAgB;AACvE,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;AAEF,MAAMC,eAAa,cAAc;CAChC,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM;EACL,MAAM;GACL,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,GAAG;EACH;CACD,MAAM,IAAI,EAAE,QAAQ;AACnB,MAAI;AAGH,UADa,MADE,qBAAqB,KAAK,CACf,KAAK,KAAK,KAAK,EAC5B,KAAK;WACV,OAAO;AACf,aAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,gBAAgB;AACvE,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;AAEF,MAAa,cAAc,cAAc;CACxC,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,aAAa;EACZ,MAAMD;EACN,KAAKC;EACL;CACD,CAAC;;;;;;;;;;AC1CF,MAAa,kBAAkB,IAAI,OAAO;AAC1C,MAAa,kBAAkB;AAC/B,MAAa,uBAAuB;AACpC,MAAa,wBAAwB;AACrC,MAAa,YAAY;;AAKzB,MAAM,yBAAyB;AAC/B,MAAM,uBAAuB;AAC7B,MAAM,iBAAiB;AACvB,MAAM,aAAa;AACnB,MAAM,eAAe;;AAGrB,MAAM,gBAAgB,IAAI,IAAI;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA,CAAC;AAIF,eAAsBC,aAAW,MAAgC;AAChE,KAAI;AACH,QAAM,OAAO,KAAK;AAClB,SAAO;SACA;AACP,SAAO;;;;;;;AAUT,SAAgB,oBAAoB,KAA0C;AAC7E,KAAI;EACH,MAAM,SAAS,UAAU,IAAI;AAC7B,MAAI,OAAO,SAAS,QAAQ,OAAO,UAAU,KAC5C,QAAO,CAAC,OAAO,OAAO,OAAO,OAAO;AAErC,SAAO;SACA;AACP,SAAO;;;;;;;AAUT,SAAgB,gBAAgB,QAAwC;CAIvE,MAAM,QAA6C,EAAE;AACrD,MAAK,MAAM,CAAC,MAAM,aAAa,OAAO,QAAQ,OAAO,MAAM,EAAE;AAC5D,MAAI,CAAC,SAAU;AAGf,MADC,SAAS,aAAa,SAAS,aAAa,OAAO,SAAS,YAAY,KACxD;GAChB,MAAM,QAA2B,EAAE,MAAM;AACzC,OAAI,SAAS,UAAW,OAAM,YAAY;AAC1C,OAAI,SAAS,aAAa,IAAK,OAAM,WAAW,SAAS;AACzD,OAAI,SAAS,YAAY,IAAM,OAAM,UAAU,SAAS;AACxD,SAAM,KAAK,MAAM;QAEjB,OAAM,KAAK,KAAiB;;AAI9B,QAAO;EACN,IAAI,OAAO;EACX,SAAS,OAAO;EAChB,cAAc,OAAO;EACrB,cAAc,OAAO;EACrB,SAAS,OAAO;EAChB;EACA,QAAQ,OAAO,KAAK,OAAO,OAAO;EAClC,OAAO;GAEN,gBAAgB,OAAO,MAAM;GAC7B,OAAO,OAAO,MAAM;GACpB,SAAS,OAAO,MAAM;GACtB;EACD;;;;;;;;AAWF,SAAgB,uBAAuB,MAAwB;CAC9D,MAAM,QAAkB,EAAE;AAC1B,wBAAuB,YAAY;CACnC,IAAI;AACJ,SAAQ,QAAQ,uBAAuB,KAAK,KAAK,MAAM,MAAM;EAC5D,MAAM,MAAM,MAAM;AAClB,MAAI,cAAc,IAAI,IAAI,CACzB,OAAM,KAAK,IAAI;;AAGjB,QAAO,CAAC,GAAG,IAAI,IAAI,MAAM,CAAC;;;;;;AAS3B,eAAsB,gBAAgB,KAAa,UAA+C;AACjG,MAAK,MAAM,OAAO;EAAC;EAAQ;EAAO;EAAO,EAAE;EAC1C,MAAM,YAAY,KAAK,KAAK,GAAG,WAAW,MAAM;AAChD,MAAI,MAAMA,aAAW,UAAU,CAAE,QAAO;;;;;;;AAS1C,eAAsB,mBACrB,WACA,UAC8B;CAC9B,MAAM,UAAU,SAAS,QAAQ,sBAAsB,GAAG;CAG1D,MAAM,SAAS,QAAQ,WAAW,QAAQ;AAC1C,KAAI,MAAMA,aAAW,OAAO,CAAE,QAAO;CAGrC,MAAM,UAAU,QAAQ,QAAQ,gBAAgB,OAAO,CAAC,QAAQ,YAAY,MAAM;CAClF,MAAM,UAAU,QAAQ,WAAW,QAAQ;AAC3C,KAAI,MAAMA,aAAW,QAAQ,CAAE,QAAO;CAItC,MAAM,UAAU,QAAQ,WADR,QAAQ,QAAQ,cAAc,OAAO,CACV;AAC3C,KAAI,MAAMA,aAAW,QAAQ,CAAE,QAAO;;;;;AAUvC,eAAsB,uBAAuB,KAA8B;CAC1E,IAAI,QAAQ;CACZ,MAAM,QAAQ,MAAM,QAAQ,KAAK,EAAE,eAAe,MAAM,CAAC;AACzD,MAAK,MAAM,QAAQ,OAAO;EACzB,MAAM,WAAW,KAAK,KAAK,KAAK,KAAK;AACrC,MAAI,KAAK,QAAQ,EAAE;GAClB,MAAM,IAAI,MAAM,KAAK,SAAS;AAC9B,YAAS,EAAE;aACD,KAAK,aAAa,CAC5B,UAAS,MAAM,uBAAuB,SAAS;;AAGjD,QAAO;;;;;AAQR,eAAsB,cAAc,WAAmB,YAAmC;CACzF,MAAM,EAAE,eAAe,MAAM,OAAO;AAIpC,OAAM,SAHY,QAAQ,UAAU,EACvB,WAAW,EAAE,OAAO,GAAG,CAAC,EACzB,kBAAkB,WAAW,CACL;;;;;;;;;;;;;;;;;;;;AC9MrC,MAAM,YAAY;AAClB,MAAM,WAAW;AACjB,MAAM,gBAAgB;AACtB,MAAM,kBAAkB;AAExB,MAAa,gBAAgB,cAAc;CAC1C,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM;EACL,KAAK;GACJ,MAAM;GACN,aAAa;GACb,SAAS,QAAQ,KAAK;GACtB;EACD,QAAQ;GACP,MAAM;GACN,OAAO;GACP,aAAa;GACb,SAAS;GACT;EACD,cAAc;GACb,MAAM;GACN,aAAa;GACb,SAAS;GACT;EACD;CACD,MAAM,IAAI,EAAE,QAAQ;EACnB,MAAM,YAAY,QAAQ,KAAK,IAAI;EACnC,MAAM,SAAS,QAAQ,WAAW,KAAK,OAAO;EAC9C,MAAM,eAAe,KAAK;AAE1B,UAAQ,MAAM,eAAe,yBAAyB,qBAAqB;EAI3E,MAAM,UAAU,KAAK,WAAW,eAAe;AAC/C,MAAI,CAAE,MAAMC,aAAW,QAAQ,EAAG;AACjC,WAAQ,MAAM,4BAA4B,UAAU;AACpD,WAAQ,KAAK,EAAE;;EAGhB,MAAM,MAAM,KAAK,MAAM,MAAM,SAAS,SAAS,QAAQ,CAAC;EAOxD,IAAI;EACJ,IAAI;AAEJ,MAAI,IAAI,SAAS;GAEhB,MAAM,gBAAgB,IAAI,QAAQ;AAClC,OAAI,OAAO,kBAAkB,SAC5B,gBAAe,MAAM,mBAAmB,WAAW,cAAc;YACvD,iBAAiB,OAAO,kBAAkB,YAAY,YAAY,cAC5E,gBAAe,MAAM,mBACpB,WACC,cAAqC,OACtC;GAIF,MAAM,cAAc,IAAI,QAAQ;AAChC,OAAI,OAAO,gBAAgB,SAC1B,cAAa,MAAM,mBAAmB,WAAW,YAAY;YACnD,eAAe,OAAO,gBAAgB,YAAY,YAAY,YACxE,cAAa,MAAM,mBAClB,WACC,YAAmC,OACpC;;AAKH,MAAI,CAAC,cAAc;GAClB,MAAM,iBAAiB,KAAK,WAAW,uBAAuB;AAC9D,OAAI,MAAMA,aAAW,eAAe,CACnC,gBAAe;;EAKjB,IAAI;AACJ,MAAI,IAAI,UAAU,SAAS,QAAW;GACrC,MAAM,aAAa,IAAI,QAAQ;AAC/B,OAAI,OAAO,eAAe,SACzB,aAAY,MAAM,mBAAmB,WAAW,WAAW;YACjD,cAAc,OAAO,eAAe,YAAY,YAAY,WACtE,aAAY,MAAM,mBAAmB,WAAY,WAAkC,OAAO;;AAG5F,MAAI,CAAC,aAAa,IAAI,KACrB,aAAY,MAAM,mBAAmB,WAAW,IAAI,KAAK;AAE1D,MAAI,CAAC,WAAW;GACf,MAAM,cAAc,KAAK,WAAW,eAAe;AACnD,OAAI,MAAMA,aAAW,YAAY,CAChC,aAAY;;AAId,MAAI,CAAC,WAAW;AACf,WAAQ,MACP,uFACA;AACD,WAAQ,KAAK,EAAE;;AAGhB,UAAQ,KAAK,eAAe,YAAY;AACxC,MAAI,aAAc,SAAQ,KAAK,kBAAkB,eAAe;AAChE,MAAI,WAAY,SAAQ,KAAK,gBAAgB,aAAa;AAI1D,UAAQ,MAAM,gCAAgC;EAG9C,MAAM,EAAE,UAAU,MAAM,OAAO;EAC/B,MAAM,SAAS,KAAK,WAAW,qBAAqB;AAEpD,MAAI;AACH,SAAM,MAAM,QAAQ,EAAE,WAAW,MAAM,CAAC;GAKxC,MAAM,aAAa,KAAK,QAAQ,OAAO;AACvC,SAAM,MAAM;IACX,QAAQ;IACR,OAAO,CAAC,UAAU;IAClB,QAAQ;IACR,QAAQ;IACR,KAAK;IACL,UAAU;IACV,UAAU,CAAC,UAAU,gBAAgB;IACrC,CAAC;GAIF,MAAM,oBAAoB,KAAK,WAAW,eAAe;GACzD,MAAM,iBAAiB,KAAK,YAAY,eAAe;AACvD,OAAI,MAAMA,aAAW,kBAAkB,CACtC,OAAM,QAAQ,mBAAmB,gBAAgB,WAAW;GAK7D,MAAM,iBAAiB,MAAM,gBAAgB,YADxB,SAAS,UAAU,CAAC,QAAQ,WAAW,GAAG,CACO;AAEtE,OAAI,CAAC,gBAAgB;AACpB,YAAQ,MAAM,mDAAmD,WAAW;AAC5E,YAAQ,KAAK,EAAE;;GAIhB,MAAM,eAAgB,MAAM,OAAO;GAOnC,IAAI;AAEJ,OAAI,OAAO,aAAa,iBAAiB,WACxC,kBAAiB,aAAa,cAAc;YAClC,OAAO,aAAa,YAAY,WAC1C,kBAAiB,aAAa,SAAS;YAC7B,OAAO,aAAa,YAAY,YAAY,aAAa,YAAY,MAAM;IACrF,MAAM,gBAAgB,aAAa;AACnC,QAAI,QAAQ,iBAAiB,aAAa,cACzC,kBAAiB;;AAOnB,OAAI,CAAC,eACJ,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,aAAa,EAAE;AACxD,QAAI,QAAQ,aAAa,OAAO,UAAU,WAAY;AACtD,QAAI;KACH,MAAM,SAAU,OAAyB;AACzC,SAAI,UAAU,OAAO,WAAW,YAAY,QAAQ,UAAU,aAAa,QAAQ;AAClF,uBAAiB;OAChB,IAAI,OAAO;OACX,SAAS,OAAO;OAChB,cAAc,OAAO,gBAAgB,EAAE;OACvC,cAAc,OAAO,gBAAgB,EAAE;OACvC,SAAS,OAAO,WAAW,EAAE;OAC7B,OAAO,EAAE;OACT,QAAQ,EAAE;OACV,OAAO;QACN,OAAO,OAAO;QACd,SAAS,OAAO;QAChB;OACD;AAID,UAAI,cAAc;OACjB,MAAM,kBAAkB,KAAK,QAAQ,gBAAgB;OACrD,MAAM,eAAe,KAAK,QAAQ,cAAc;AAChD,aAAM,MAAM,cAAc,EAAE,WAAW,MAAM,CAAC;AAC9C,aAAM,UACL,KAAK,cAAc,aAAa,EAChC,0CACA;AACD,aAAM,MAAM;QACX,QAAQ;QACR,OAAO,CAAC,aAAa;QACrB,QAAQ;QACR,QAAQ;QACR,KAAK;QACL,UAAU;QACV,UAAU,EAAE;QACZ,OAAO,EAAE,QAAQ,KAAK,cAAc,aAAa,EAAE;QACnD,WAAW;QACX,CAAC;OAEF,MAAM,mBAAmB,MAAM,gBAAgB,iBADvB,SAAS,aAAa,CAAC,QAAQ,WAAW,GAAG,CACW;AAChF,WAAI,kBAAkB;QAErB,MAAM,eADiB,MAAM,OAAO,mBACD,WAAW,EAAE;QAChD,MAAM,QAAQ,YAAY;QAC1B,MAAM,SAAS,YAAY;AAC3B,YAAI,MACH,MAAK,MAAM,YAAY,OAAO,KAAK,MAAM,EAAE;SAC1C,MAAM,YAAY,MAAM;SACxB,MAAM,WACL,OAAO,cAAc,YACrB,cAAc,QACd,aAAa;SACd,MAAM,SAAS,WAAY,YAAwC,EAAE;AACrE,SAAC,eAAe,MAAkC,YAAY;UAC7D,SAAS,WACL,UAAsC,UACvC;UACH,UAAW,OAAO,YAAuB;UACzC,SAAU,OAAO,WAAsB;UACvC,cAAe,OAAO,gBAA6B,EAAE;UACrD,aAAc,OAAO,eAA0B;UAC/C,WAAY,OAAO,aAAyB;UAC5C,UAAU,OAAO;UACjB;;AAGH,YAAI,OACH,MAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,OAAO,EAAE;SACnD,MAAM,WAAW;AACjB,SAAC,eAAe,OAAmC,QAAQ;UAC1D,SAAS,SAAS;UAClB,QAAQ,SAAS;UACjB;;;;AAKL;;YAEM;;AAMV,OAAI,CAAC,gBAAgB,MAAM,CAAC,gBAAgB,SAAS;AACpD,YAAQ,MACP,qLAGA;AACD,YAAQ,KAAK,EAAE;;GAGhB,MAAM,WAAW,gBAAgB,eAAe;AAIhD,OAAI,eAAe,OAAO,OAAO;AAChC,YAAQ,MACP,kJAEA;AACD,YAAQ,KAAK,EAAE;;AAEhB,OACC,eAAe,OAAO,sBACtB,eAAe,MAAM,mBAAmB,SAAS,GAChD;AACD,YAAQ,MACP,oHAEA;AACD,YAAQ,KAAK,EAAE;;AAGhB,WAAQ,QAAQ,WAAW,SAAS,GAAG,GAAG,SAAS,UAAU;AAC7D,WAAQ,KACP,mBAAmB,SAAS,aAAa,SAAS,IAAI,SAAS,aAAa,KAAK,KAAK,GAAG,WACzF;AACD,WAAQ,KACP,YAAY,SAAS,MAAM,SAAS,IAAI,SAAS,MAAM,KAAK,MAAO,OAAO,MAAM,WAAW,IAAI,EAAE,KAAM,CAAC,KAAK,KAAK,GAAG,WACrH;AACD,WAAQ,KACP,aAAa,SAAS,OAAO,SAAS,IAAI,SAAS,OAAO,KAAK,MAAO,OAAO,MAAM,WAAW,IAAI,EAAE,KAAM,CAAC,KAAK,KAAK,GAAG,WACxH;GAID,MAAM,YAAY,KAAK,QAAQ,SAAS;AACxC,SAAM,MAAM,WAAW,EAAE,WAAW,MAAM,CAAC;AAE3C,OAAI,cAAc;AACjB,YAAQ,MAAM,sBAAsB;IAKpC,MAAM,UAAU,KAAK,QAAQ,QAAQ;AACrC,UAAM,MAAM,SAAS,EAAE,WAAW,MAAM,CAAC;AACzC,UAAM,UAAU,KAAK,SAAS,aAAa,EAAE,0CAA0C;AAEvF,UAAM,MAAM;KACX,QAAQ;KACR,OAAO,CAAC,aAAa;KACrB,QAAQ;KACR,QAAQ,KAAK,QAAQ,UAAU;KAC/B,KAAK;KACL,UAAU;KAGV,UAAU,EAAE;KACZ,OAAO,EAAE,QAAQ,KAAK,SAAS,aAAa,EAAE;KAC9C,QAAQ;KACR,WAAW;KACX,CAAC;IAEF,MAAM,kBAAkB,SAAS,aAAa,CAAC,QAAQ,WAAW,GAAG;IACrE,MAAM,oBAAoB,MAAM,gBAAgB,KAAK,QAAQ,UAAU,EAAE,gBAAgB;AAEzF,QAAI,mBAAmB;AACtB,WAAM,SAAS,mBAAmB,KAAK,WAAW,aAAa,CAAC;AAChE,aAAQ,QAAQ,mBAAmB;WAC7B;AACN,aAAQ,MAAM,mCAAmC;AACjD,aAAQ,KAAK,EAAE;;UAEV;AACN,YAAQ,KAAK,0DAA0D;AACvE,YAAQ,KAAK,iFAA6E;;AAK3F,OAAI,YAAY;AACf,YAAQ,MAAM,oBAAoB;AAClC,UAAM,MAAM;KACX,QAAQ;KACR,OAAO,CAAC,WAAW;KACnB,QAAQ;KACR,QAAQ,KAAK,QAAQ,QAAQ;KAC7B,KAAK;KACL,UAAU;KACV,UAAU,EAAE;KACZ,QAAQ;KACR,WAAW;KACX,CAAC;IAEF,MAAM,gBAAgB,SAAS,WAAW,CAAC,QAAQ,WAAW,GAAG;IACjE,MAAM,kBAAkB,MAAM,gBAAgB,KAAK,QAAQ,QAAQ,EAAE,cAAc;AAEnF,QAAI,iBAAiB;AACpB,WAAM,SAAS,iBAAiB,KAAK,WAAW,WAAW,CAAC;AAC5D,aAAQ,QAAQ,iBAAiB;;;AAMnC,SAAM,UAAU,KAAK,WAAW,gBAAgB,EAAE,KAAK,UAAU,UAAU,MAAM,EAAE,CAAC;AAIpF,WAAQ,MAAM,uBAAuB;GAGrC,MAAM,aAAa,KAAK,WAAW,YAAY;AAC/C,OAAI,MAAMA,aAAW,WAAW,EAAE;AACjC,UAAM,SAAS,YAAY,KAAK,WAAW,YAAY,CAAC;AACxD,YAAQ,QAAQ,qBAAqB;;GAItC,MAAM,WAAW,KAAK,WAAW,WAAW;AAC5C,OAAI,MAAMA,aAAW,SAAS,EAAE;IAE/B,MAAM,OAAO,oBADG,MAAM,SAAS,SAAS,CACC;AACzC,QAAI,CAAC,KACJ,SAAQ,KAAK,yCAAyC;aAC5C,KAAK,OAAO,aAAa,KAAK,OAAO,WAAW;AAC1D,aAAQ,KACP,eAAe,KAAK,GAAG,GAAG,KAAK,GAAG,aAAa,UAAU,GAAG,UAAU,qBACtE;AACD,WAAM,SAAS,UAAU,KAAK,WAAW,WAAW,CAAC;WAC/C;AACN,WAAM,SAAS,UAAU,KAAK,WAAW,WAAW,CAAC;AACrD,aAAQ,QAAQ,oBAAoB;;;GAKtC,MAAM,iBAAiB,KAAK,WAAW,cAAc;AACrD,OAAI,MAAMA,aAAW,eAAe,EAAE;IACrC,MAAM,mBAAmB,MAAM,QAAQ,eAAe,EACpD,QAAQ,MAAM;KACd,MAAM,MAAM,QAAQ,EAAE,CAAC,aAAa;AACpC,YAAO,QAAQ,UAAU,QAAQ,UAAU,QAAQ;MAClD,CACD,UAAU,CACV,MAAM,GAAG,gBAAgB;AAE3B,QAAI,gBAAgB,SAAS,GAAG;AAC/B,WAAM,MAAM,KAAK,WAAW,cAAc,EAAE,EAAE,WAAW,MAAM,CAAC;AAEhE,UAAK,MAAM,QAAQ,iBAAiB;MACnC,MAAM,WAAW,KAAK,gBAAgB,KAAK;MAG3C,MAAM,OAAO,oBAFD,MAAM,SAAS,SAAS,CAEC;AAErC,UAAI,CAAC,MAAM;AACV,eAAQ,KAAK,eAAe,KAAK,qCAAqC;AACtE;;AAGD,UAAI,KAAK,KAAK,wBAAwB,KAAK,KAAK,sBAC/C,SAAQ,KACP,eAAe,KAAK,MAAM,KAAK,GAAG,GAAG,KAAK,GAAG,QAAQ,qBAAqB,GAAG,sBAAsB,qBACnG;AAGF,YAAM,SAAS,UAAU,KAAK,WAAW,eAAe,KAAK,CAAC;;AAG/D,aAAQ,QAAQ,YAAY,gBAAgB,OAAO,gBAAgB;;;AAMrE,WAAQ,MAAM,uBAAuB;GACrC,IAAI,YAAY;GAGhB,MAAM,cAAc,KAAK,WAAW,aAAa;AACjD,OAAI,MAAMA,aAAW,YAAY,EAAE;IAElC,MAAM,WAAW,uBADG,MAAM,SAAS,aAAa,QAAQ,CACJ;AACpD,QAAI,SAAS,SAAS,GAAG;AACxB,aAAQ,MAAM,gDAAgD,SAAS,KAAK,KAAK,GAAG;AACpF,aAAQ,MAAM,4CAA4C;AAC1D,iBAAY;;;AAKd,OAAI,SAAS,aAAa,SAAS,oBAAoB,CACtD,SAAQ,KACP,qGACA;YAED,SAAS,aAAa,SAAS,gBAAgB,IAC/C,SAAS,aAAa,WAAW,EAEjC,SAAQ,KACP,oGACA;AAIF,OACC,eAAe,OAAO,sBACtB,eAAe,MAAM,mBAAmB,SAAS,EAEjD,SAAQ,KACP,2GACA;AAEF,OAAI,eAAe,OAAO,MACzB,SAAQ,KACP,sHACA;AAGF,OAAI,eAAe,MAAM,kBACxB,SAAQ,KACP,iGACA;GAIF,MAAM,iBAAiB,SAAS,OAAO,OAAO,UAAU,KAAK;GAC7D,MAAM,mBAAmB,SAAS,OAAO,SAAS,UAAU,KAAK;AACjE,OAAI,iBAAiB,iBAIpB;QAAI,CAHe,SAAS,OAAO,KAAK,MACvC,OAAO,MAAM,WAAW,IAAI,EAAE,KAC9B,CACe,SAAS,QAAQ,EAAE;AAClC,aAAQ,MACP,mBAAmB,gBAAgB,eAAe,KAAK,iBAAiB,kBAAkB,UAAU,KAAK,kBAAkB,iBAAiB,GAAG,mGAG/I;AACD,iBAAY;;;GAKd,MAAM,YAAY,MAAM,uBAAuB,UAAU;AACzD,OAAI,YAAY,iBAAiB;IAChC,MAAM,UAAU,YAAY,OAAO,MAAM,QAAQ,EAAE;AACnD,YAAQ,MAAM,eAAe,OAAO,2BAA2B;AAC/D,gBAAY;UACN;IACN,MAAM,UAAU,YAAY,MAAM,QAAQ,EAAE;AAC5C,YAAQ,KAAK,gBAAgB,OAAO,IAAI;;AAGzC,OAAI,WAAW;AACd,YAAQ,MAAM,2BAA2B;AACzC,YAAQ,KAAK,EAAE;;AAGhB,WAAQ,QAAQ,oBAAoB;AAEpC,OAAI,aACH;AAKD,SAAM,MAAM,QAAQ,EAAE,WAAW,MAAM,CAAC;GACxC,MAAM,cAAc,GAAG,SAAS,GAAG,QAAQ,UAAU,IAAI,CAAC,QAAQ,eAAe,GAAG,CAAC,GAAG,SAAS,QAAQ;GACzG,MAAM,cAAc,KAAK,QAAQ,YAAY;AAE7C,WAAQ,MAAM,sBAAsB;AACpC,SAAM,cAAc,WAAW,YAAY;GAG3C,MAAM,kBADc,MAAM,KAAK,YAAY,EACR,OAAO,MAAM,QAAQ,EAAE;GAG1D,MAAM,aAAa,MAAM,SAAS,YAAY;GAC9C,MAAM,WAAW,WAAW,SAAS,CAAC,OAAO,WAAW,CAAC,OAAO,MAAM;AAEtE,WAAQ,QAAQ,WAAW,YAAY,IAAI,cAAc,KAAK;AAC9D,WAAQ,KAAK,cAAc,WAAW;AACtC,WAAQ,KAAK,WAAW,cAAc;YAC7B;AACT,OAAI,OAAO,SAAS,qBAAqB,CACxC,OAAM,GAAG,QAAQ;IAAE,WAAW;IAAM,OAAO;IAAM,CAAC;;;CAIrD,CAAC;;;;;;;;;;;;;;;;AC3kBF,MAAM,UAAU;AAChB,MAAM,WAAW;AAEjB,MAAa,oBAAoB,cAAc;CAC9C,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM;EACL,KAAK;GACJ,MAAM;GACN,aAAa;GACb,SAAS;GACT;EACD,MAAM;GACL,MAAM;GACN,aAAa;GACb;EACD,QAAQ;GACP,MAAM;GACN,aAAa;GACb,SAAS;GACT;EACD;CACD,MAAM,IAAI,EAAE,QAAQ;EACnB,MAAM,YAAY,QAAQ,KAAK,IAAI;EACnC,MAAM,WAAW,KAAK;EAGtB,IAAI,aAAa,KAAK,QAAQ,SAAS,UAAU;AACjD,MAAI,CAAC,cAAc,eAAe,IACjC,cAAa,SAAS,QAAQ,IAAI,CAAC;EAIpC,MAAM,OAAO,WAAW,QAAQ,UAAU,GAAG;AAC7C,MAAI,CAAC,QAAQ,KAAK,KAAK,EAAE;AACxB,WAAQ,MACP,wBAAwB,WAAW,kEAEnC;AACD,WAAQ,KAAK,EAAE;;EAIhB,MAAM,SAAS,KAAK,WAAW,MAAM;AAErC,MAAI,MAAMC,aADM,KAAK,WAAW,eAAe,CAClB,EAAE;AAC9B,WAAQ,MAAM,kCAAkC,YAAY;AAC5D,WAAQ,KAAK,EAAE;;AAGhB,UAAQ,MAAM,eAAe,WAAW,WAAW,WAAW,WAAW,aAAa;AAEtF,QAAM,MAAM,QAAQ,EAAE,WAAW,MAAM,CAAC;AAExC,MAAI,SACH,OAAM,eAAe,WAAW,QAAQ,YAAY,KAAK;MAEzD,OAAM,iBAAiB,WAAW,QAAQ,YAAY,KAAK;AAG5D,UAAQ,QAAQ,wBAAwB,YAAY;AACpD,UAAQ,KAAK,cAAc;AAC3B,MAAI,KAAK,QAAQ,IAChB,SAAQ,KAAK,WAAW,KAAK,MAAM;AAEpC,UAAQ,KAAK,KAAK,KAAK,QAAQ,MAAM,MAAM,IAAI,gBAAgB;AAC/D,MAAI,SACH,SAAQ,KAAK,KAAK,KAAK,QAAQ,MAAM,MAAM,IAAI,6CAA6C;MAE5F,SAAQ,KACP,KAAK,KAAK,QAAQ,MAAM,MAAM,IAAI,qDAClC;AAEF,UAAQ,KAAK,KAAK,KAAK,QAAQ,MAAM,MAAM,IAAI,kCAAkC;;CAElF,CAAC;AAIF,eAAe,iBACd,WACA,QACA,YACA,MACgB;CAEhB,MAAM,SAAS,KACb,MAAM,IAAI,CACV,KAAK,GAAG,MAAO,MAAM,IAAI,IAAI,EAAE,GAAG,aAAa,GAAG,EAAE,MAAM,EAAE,CAAE,CAC9D,KAAK,GAAG;AAGV,OAAM,UACL,KAAK,WAAW,eAAe,EAC/B,KAAK,UACJ;EACC,MAAM;EACN,SAAS;EACT,MAAM;EACN,SAAS;GACR,KAAK;GACL,aAAa;GACb;EACD,OAAO,CAAC,MAAM;EACd,kBAAkB,EACjB,QAAQ,KACR;EACD,EACD,MACA,IACA,GAAG,KACJ;AAGD,OAAM,UACL,KAAK,WAAW,gBAAgB,EAChC,KAAK,UACJ;EACC,iBAAiB;GAChB,QAAQ;GACR,QAAQ;GACR,kBAAkB;GAClB,QAAQ;GACR,iBAAiB;GACjB,aAAa;GACb,QAAQ;GACR,SAAS;GACT;EACD,SAAS,CAAC,WAAW;EACrB,SAAS,CAAC,gBAAgB,OAAO;EACjC,EACD,MACA,IACA,GAAG,KACJ;AAGD,OAAM,UACL,KAAK,QAAQ,WAAW,EACxB;;kBAEgB,OAAO;;WAEd,WAAW;;;mBAGH,WAAW;;;;EAK5B;AAGD,OAAM,UACL,KAAK,QAAQ,mBAAmB,EAChC;;;;;;;;;;;;;;;EAgBA;;AAKF,eAAe,eACd,WACA,QACA,YACA,MACgB;CAChB,MAAM,SAAS,KACb,MAAM,IAAI,CACV,KAAK,GAAG,MAAO,MAAM,IAAI,IAAI,EAAE,GAAG,aAAa,GAAG,EAAE,MAAM,EAAE,CAAE,CAC9D,KAAK,GAAG;AAGV,OAAM,UACL,KAAK,WAAW,eAAe,EAC/B,KAAK,UACJ;EACC,MAAM;EACN,SAAS;EACT,MAAM;EACN,SAAS,EACR,KAAK,kBACL;EACD,OAAO,CAAC,MAAM;EACd,kBAAkB,EACjB,QAAQ,KACR;EACD,EACD,MACA,IACA,GAAG,KACJ;AAGD,OAAM,UACL,KAAK,WAAW,gBAAgB,EAChC,KAAK,UACJ;EACC,iBAAiB;GAChB,QAAQ;GACR,QAAQ;GACR,kBAAkB;GAClB,QAAQ;GACR,iBAAiB;GACjB,aAAa;GACb,QAAQ;GACR,SAAS;GACT;EACD,SAAS,CAAC,WAAW;EACrB,SAAS,CAAC,gBAAgB,OAAO;EACjC,EACD,MACA,IACA,GAAG,KACJ;AAGD,OAAM,UACL,KAAK,QAAQ,WAAW,EACxB;;;kBAGgB,OAAO;;WAEd,WAAW;;;mBAGH,WAAW;;;;;;;WAOnB,WAAW;;;;;;;;;;;;;;;EAgBpB;;;;;;;;;;;;ACrRF,MAAa,wBAAwB,cAAc;CAClD,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM,EACL,KAAK;EACJ,MAAM;EACN,aAAa;EACb,SAAS;EACT,EACD;CACD,MAAM,IAAI,EAAE,QAAQ;AAEnB,QAAM,WAAW,eAAe,EAC/B,SAAS;GAAC;GAAS,KAAK;GAAK;GAAiB,EAC9C,CAAC;;CAEH,CAAC;;;;;;;;;;;;;;;;;ACDF,MAAM,mBAAmB;;;;;AA4CzB,eAAe,0BAA0B,aAAuD;AAE/F,SAAQ,MAAM,iCAAiC;CAC/C,MAAM,eAAe,MAAM,MAAM,IAAI,IAAI,0BAA0B,YAAY,CAAC;AAChF,KAAI,CAAC,aAAa,GACjB,OAAM,IAAI,MAAM,4BAA4B,aAAa,OAAO,GAAG,aAAa,aAAa;CAE9F,MAAM,YAAa,MAAM,aAAa,MAAM;CAG5C,MAAM,YAAY,MAAM,MAAM,UAAU,OAAO,6BAA6B;EAC3E,QAAQ;EACR,SAAS;GACR,gBAAgB;GAChB,QAAQ;GACR;EACD,MAAM,KAAK,UAAU;GACpB,WAAW,UAAU,OAAO;GAC5B,OAAO;GACP,CAAC;EACF,CAAC;AAEF,KAAI,CAAC,UAAU,GACd,OAAM,IAAI,MAAM,8BAA8B,UAAU,SAAS;CAGlE,MAAM,aAAc,MAAM,UAAU,MAAM;AAG1C,SAAQ,KAAK;AACb,SAAQ,KAAK,wBAAwB;AACrC,SAAQ,IAAI,KAAK,GAAG,KAAK,GAAG,KAAK,WAAW,iBAAiB,CAAC,GAAG;AACjE,SAAQ,KAAK;AACb,SAAQ,KAAK,eAAe,GAAG,OAAO,GAAG,KAAK,WAAW,UAAU,CAAC,GAAG;AACvE,SAAQ,KAAK;AAGb,KAAI;EACH,MAAM,EAAE,aAAa,MAAM,OAAO;AAClC,MAAI,QAAQ,aAAa,SACxB,UAAS,QAAQ,CAAC,WAAW,iBAAiB,CAAC;WACrC,QAAQ,aAAa,QAC/B,UAAS,OAAO;GAAC;GAAM;GAAS;GAAI,WAAW;GAAiB,CAAC;MAEjE,UAAS,YAAY,CAAC,WAAW,iBAAiB,CAAC;SAE7C;AAKR,SAAQ,MAAM,+BAA+B;CAC7C,MAAM,cAAc,MAAM,qBACzB,UAAU,OAAO,eACjB,UAAU,OAAO,UACjB,WAAW,aACX,WAAW,UACX,WAAW,WACX;AAGD,SAAQ,MAAM,qCAAqC;CACnD,MAAM,iBAAiB,IAAI,IAAI,UAAU,YAAY,qBAAqB,YAAY;CACtF,MAAM,UAAU,MAAM,MAAM,gBAAgB;EAC3C,QAAQ;EACR,SAAS,EAAE,gBAAgB,oBAAoB;EAC/C,MAAM,KAAK,UAAU,EAAE,cAAc,aAAa,CAAC;EACnD,CAAC;AAEF,KAAI,CAAC,QAAQ,IAAI;EAChB,MAAM,OAAQ,MAAM,QAAQ,MAAM,CAAC,aAAa,EAAE,EAAE;AACpD,QAAM,IAAI,MAAM,4BAA4B,KAAK,SAAS,QAAQ,aAAa;;AAGhF,QAAQ,MAAM,QAAQ,MAAM;;AAG7B,eAAe,qBACd,eACA,UACA,YACA,UACA,WACkB;CAClB,MAAM,WAAW,KAAK,KAAK,GAAG,YAAY;CAC1C,IAAI,kBAAkB;AAEtB,QAAO,KAAK,KAAK,GAAG,UAAU;AAC7B,QAAM,IAAI,SAAS,MAAM,WAAW,GAAG,kBAAkB,IAAK,CAAC;EAe/D,MAAM,OAAQ,OAbF,MAAM,MAAM,eAAe;GACtC,QAAQ;GACR,SAAS;IACR,gBAAgB;IAChB,QAAQ;IACR;GACD,MAAM,KAAK,UAAU;IACpB,WAAW;IACX,aAAa;IACb,YAAY;IACZ,CAAC;GACF,CAAC,EAEsB,MAAM;AAE9B,MAAI,KAAK,aACR,QAAO,KAAK;AAGb,MAAI,KAAK,UAAU,wBAAyB;AAC5C,MAAI,KAAK,UAAU,aAAa;AAC/B,qBAAkB,KAAK,YAAY,kBAAkB;AACrD;;AAED,MAAI,KAAK,UAAU,gBAClB,OAAM,IAAI,MAAM,yCAAyC;AAE1D,MAAI,KAAK,UAAU,gBAClB,OAAM,IAAI,MAAM,4BAA4B;AAG7C,QAAM,IAAI,MAAM,iCAAiC,KAAK,SAAS,kBAAkB;;AAGlF,OAAM,IAAI,MAAM,mDAAmD;;AAKpE,MAAM,wBAAwB,qBAAqB,KAAK;CACvD,IAAI;CACJ,SAAS;CACT,cAAc;CACd,cAAc;CACd,CAAC;;;;AAOF,eAAe,wBAAwB,aAA+C;CACrF,MAAM,OAAO,MAAM,SAAS,YAAY;CAYxC,MAAM,YAJU,MAAM,UAPP,IAAI,eAA2B,EAC7C,MAAM,YAAY;AACjB,aAAW,QAAQ,IAAI,WAAW,KAAK,QAAQ,KAAK,YAAY,KAAK,WAAW,CAAC;AACjF,aAAW,OAAO;IAEnB,CAAC,CAEqC,YAAY,mBAAmB,CAAC,EAAE,EACxE,SAAS,WAAW,OAAO,SAAS,iBACpC,CAAC,EAEuB,MAAM,MAAM,EAAE,OAAO,SAAS,gBAAgB;AACvE,KAAI,CAAC,UAAU,KACd,OAAM,IAAI,MAAM,yCAAyC;CAG1D,MAAM,UAAU,IAAI,aAAa,CAAC,OAAO,SAAS,KAAK;CACvD,MAAM,SAAkB,KAAK,MAAM,QAAQ;CAC3C,MAAM,SAAS,sBAAsB,UAAU,OAAO;AACtD,KAAI,CAAC,OAAO,QACX,OAAM,IAAI,MAAM,0BAA0B,OAAO,MAAM,UAAU;AAElE,QAAO,OAAO;;AAKf,MAAM,mBAAmB;AACzB,MAAM,kBAAkB;;;;;AAcxB,eAAe,kBACd,YACA,OACwC;CACxC,MAAM,WAAW,KAAK,KAAK,GAAG;AAE9B,QAAO,KAAK,KAAK,GAAG,UAAU;AAC7B,QAAM,IAAI,SAAS,MAAM,WAAW,GAAG,iBAAiB,CAAC;AAEzD,MAAI;GACH,MAAM,MAAM,MAAM,MAAM,YAAY,EACnC,SAAS,EAAE,eAAe,UAAU,SAAS,EAC7C,CAAC;AAEF,OAAI,CAAC,IAAI,GAAI;GAEb,MAAM,OAAQ,MAAM,IAAI,MAAM;AAC9B,OAAI,KAAK,WAAW,UACnB,QAAO;UAED;;AAKT,QAAO;;AAGR,SAAS,oBAAoB,SAAsC;CAClE,MAAM,cACL,QAAQ,WAAW,cAAc,GAAG,QAAQ,QAAQ,WAAW,YAAY,GAAG,SAAS,GAAG;AAC3F,SAAQ,KAAK,aAAa,YAAY,QAAQ,OAAO,GAAG;AAExD,KAAI,QAAQ,eAAe;EAC1B,MAAM,eACL,QAAQ,kBAAkB,SACvB,GAAG,QACH,QAAQ,kBAAkB,SACzB,GAAG,SACH,GAAG;AACR,UAAQ,KAAK,YAAY,aAAa,QAAQ,cAAc,GAAG;;AAGhE,KAAI,QAAQ,qBAAqB;EAChC,MAAM,eACL,QAAQ,wBAAwB,SAC7B,GAAG,QACH,QAAQ,wBAAwB,SAC/B,GAAG,SACH,GAAG;AACR,UAAQ,KAAK,kBAAkB,aAAa,QAAQ,oBAAoB,GAAG;;;AAI7E,SAAS,0BACR,OAMA,YACO;CACP,MAAM,eACL,MAAM,YAAY,SAAS,GAAG,QAAQ,MAAM,YAAY,SAAS,GAAG,SAAS,GAAG;AACjF,SAAQ,KAAK,YAAY,aAAa,MAAM,QAAQ,CAAC,UAAU,MAAM,UAAU,OAAO;AACtF,KAAI,MAAM,SAAS,SAAS,EAC3B,MAAK,MAAM,WAAW,MAAM,UAAU;EACrC,MAAM,OAAO,QAAQ,aAAa,SAAS,GAAG,IAAI,IAAI,GAAG,GAAG,OAAO,IAAI;AACvE,UAAQ,KAAK,OAAO,KAAK,IAAI,QAAQ,SAAS,IAAI,QAAQ,cAAc;;AAI1E,KAAI,YAAY;EACf,MAAM,WACL,WAAW,YAAY,SAAS,GAAG,QAAQ,WAAW,YAAY,SAAS,GAAG,SAAS,GAAG;AAC3F,UAAQ,KAAK,kBAAkB,SAAS,WAAW,QAAQ,GAAG;;;AAMhE,MAAa,iBAAiB,cAAc;CAC3C,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM;EACL,SAAS;GACR,MAAM;GACN,aAAa;GACb;EACD,KAAK;GACJ,MAAM;GACN,aAAa;GACb,SAAS,QAAQ,KAAK;GACtB;EACD,OAAO;GACN,MAAM;GACN,aAAa;GACb,SAAS;GACT;EACD,UAAU;GACT,MAAM;GACN,aAAa;GACb,SAAS;GACT;EACD,WAAW;GACV,MAAM;GACN,aAAa;GACb,SAAS;GACT;EACD;CACD,MAAM,IAAI,EAAE,QAAQ;EACnB,MAAM,cAAc,KAAK;EAIzB,IAAI;AAEJ,MAAI,KAAK,QACR,eAAc,QAAQ,KAAK,QAAQ;WACzB,KAAK,OAAO;AAEtB,WAAQ,MAAM,qBAAqB;GACnC,MAAM,YAAY,QAAQ,KAAK,IAAI;AACnC,OAAI;IACH,MAAM,EAAE,eAAe,MAAM,OAAO;IACpC,MAAM,EAAE,kBAAkB;AAC1B,UAAM,WAAW,eAAe,EAC/B,SAAS,CAAC,SAAS,UAAU,EAC7B,CAAC;WACK;AACP,YAAQ,MAAM,eAAe;AAC7B,YAAQ,KAAK,EAAE;;GAIhB,MAAM,EAAE,YAAY,MAAM,OAAO;GACjC,MAAM,UAAU,QAAQ,WAAW,OAAO;GAE1C,MAAM,WADQ,MAAM,QAAQ,QAAQ,EACd,MAAM,MAAM,EAAE,SAAS,UAAU,CAAC;AACxD,OAAI,CAAC,SAAS;AACb,YAAQ,MAAM,gDAAgD;AAC9D,YAAQ,KAAK,EAAE;;AAEhB,iBAAc,QAAQ,SAAS,QAAQ;SACjC;GAEN,MAAM,YAAY,QAAQ,KAAK,IAAI;GACnC,MAAM,EAAE,YAAY,MAAM,OAAO;AACjC,OAAI;IACH,MAAM,UAAU,QAAQ,WAAW,OAAO;IAE1C,MAAM,WADQ,MAAM,QAAQ,QAAQ,EACd,MAAM,MAAM,EAAE,SAAS,UAAU,CAAC;AACxD,QAAI,QACH,eAAc,QAAQ,SAAS,QAAQ;SACjC;AACN,aAAQ,MAAM,qEAAqE;AACnF,aAAQ,KAAK,EAAE;;WAET;AACP,YAAQ,MAAM,6EAA6E;AAC3F,YAAQ,KAAK,EAAE;;;EAKjB,MAAM,WADc,MAAM,KAAK,YAAY,EACf,OAAO,MAAM,QAAQ,EAAE;AACnD,UAAQ,KAAK,YAAY,GAAG,IAAI,YAAY,CAAC,IAAI,OAAO,KAAK;EAI7D,MAAM,WAAW,MAAM,wBAAwB,YAAY;AAC3D,UAAQ,KAAK;AACb,UAAQ,KAAK,WAAW,GAAG,KAAK,GAAG,SAAS,GAAG,GAAG,SAAS,UAAU,GAAG;AACxE,MAAI,SAAS,aAAa,SAAS,EAClC,SAAQ,KAAK,iBAAiB,SAAS,aAAa,KAAK,KAAK,GAAG;AAElE,MAAI,SAAS,cAAc,OAC1B,SAAQ,KAAK,kBAAkB,SAAS,aAAa,KAAK,KAAK,GAAG;AAEnE,UAAQ,KAAK;EAOb,IAAI;EACJ,MAAM,WAAW,QAAQ,IAAI;EAC7B,MAAM,SAAS,CAAC,WAAW,yBAAyB,YAAY,GAAG;AAEnE,MAAI,UAAU;AACb,WAAQ;AACR,WAAQ,KAAK,oDAAoD;aACvD,QAAQ;AAClB,WAAQ,OAAO;AACf,WAAQ,KAAK,oBAAoB,GAAG,KAAK,OAAO,QAAQ,QAAQ,UAAU,GAAG;SACvE;AACN,WAAQ,KAAK,kEAAkE;GAC/E,MAAM,SAAS,MAAM,0BAA0B,YAAY;AAC3D,WAAQ,OAAO;AAGf,6BAA0B,aAAa;IACtC,OAAO,OAAO;IACd,WAAW,IAAI,KAAK,KAAK,KAAK,GAAG,KAAK,QAAQ,IAAK,CAAC,aAAa;IACjE,QAAQ;KAAE,IAAI,OAAO,OAAO;KAAI,MAAM,OAAO,OAAO;KAAM;IAC1D,CAAC;AAEF,WAAQ,QAAQ,oBAAoB,GAAG,KAAK,OAAO,OAAO,KAAK,GAAG;;AAKnE,UAAQ,MAAM,0BAA0B;EAGxC,MAAM,YAAY,MAAM,MAAM,IAAI,IAAI,mBAAmB,SAAS,MAAM,YAAY,CAAC;AAErF,MAAI,UAAU,WAAW,OAAO,CAAC,UAAU;AAG1C,WAAQ,KAAK,UAAU,GAAG,KAAK,SAAS,GAAG,CAAC,2CAA2C;GAEvF,MAAM,YAAY,MAAM,MAAM,IAAI,IAAI,mBAAmB,YAAY,EAAE;IACtE,QAAQ;IACR,SAAS;KACR,gBAAgB;KAChB,eAAe,UAAU;KACzB;IACD,MAAM,KAAK,UAAU;KACpB,IAAI,SAAS;KACb,MAAM,SAAS;KACf,cAAc,SAAS;KACvB,CAAC;IACF,CAAC;AAEF,OAAI,CAAC,UAAU,IAAI;IAClB,MAAM,OAAQ,MAAM,UAAU,MAAM,CAAC,aAAa,EAAE,EAAE;AACtD,QAAI,UAAU,WAAW,KAAK;AAE7B,iCAA4B,YAAY;AACxC,aAAQ,MACP,uFACA;AACD,aAAQ,KAAK,EAAE;;AAEhB,YAAQ,MAAM,8BAA8B,KAAK,SAAS,UAAU,aAAa;AACjF,YAAQ,KAAK,EAAE;;AAGhB,WAAQ,QAAQ,cAAc,GAAG,KAAK,SAAS,GAAG,GAAG;aAC3C,UAAU,WAAW,OAAO,SAEtC,SAAQ,KAAK,UAAU,GAAG,KAAK,SAAS,GAAG,CAAC,qCAAqC;WACvE,CAAC,UAAU,IAAI;AACzB,WAAQ,MAAM,sBAAsB,UAAU,SAAS;AACvD,WAAQ,KAAK,EAAE;;AAKhB,UAAQ,MAAM,cAAc,SAAS,GAAG,GAAG,SAAS,QAAQ,KAAK;EAEjE,MAAM,cAAc,MAAM,SAAS,YAAY;EAC/C,MAAM,WAAW,IAAI,UAAU;AAC/B,WAAS,OACR,UACA,IAAI,KAAK,CAAC,YAAY,EAAE,EAAE,MAAM,oBAAoB,CAAC,EACrD,SAAS,YAAY,CACrB;EAED,MAAM,YAAY,IAAI,IAAI,mBAAmB,SAAS,GAAG,YAAY,YAAY;EACjF,MAAM,YAAY,MAAM,MAAM,WAAW;GACxC,QAAQ;GACR,SAAS,EACR,eAAe,UAAU,SACzB;GACD,MAAM;GACN,CAAC;AAEF,MAAI,CAAC,UAAU,MAAM,UAAU,WAAW,KAAK;GAC9C,MAAM,OAAQ,MAAM,UAAU,MAAM,CAAC,aAAa,EAAE,EAAE;AAMtD,OAAI,UAAU,WAAW,KAAK;AAC7B,QAAI,SACH,SAAQ,MAAM,4DAA4D;SACpE;AACN,iCAA4B,YAAY;AACxC,aAAQ,MAAM,oEAAoE;;AAEnF,YAAQ,KAAK,EAAE;;AAGhB,OAAI,UAAU,WAAW,KAAK;AAC7B,QAAI,KAAK,cACR,SAAQ,MAAM,WAAW,SAAS,QAAQ,wBAAwB,KAAK,gBAAgB;QAEvF,SAAQ,MAAM,KAAK,SAAS,mBAAmB;AAEhD,YAAQ,KAAK,EAAE;;AAGhB,OAAI,UAAU,WAAW,OAAO,KAAK,OAAO;AAE3C,YAAQ,MAAM,gCAAgC;AAC9C,YAAQ,MAAM,cAAc,GAAG,IAAI,KAAK,MAAM,QAAQ,GAAG;AACzD,YAAQ,MAAM,cAAc,KAAK,MAAM,UAAU;AACjD,YAAQ,KAAK,EAAE;;AAGhB,WAAQ,MAAM,mBAAmB,KAAK,SAAS,UAAU,aAAa;AACtE,WAAQ,KAAK,EAAE;;EAKhB,MAAM,SAAU,MAAM,UAAU,MAAM;AAkBtC,UAAQ,KAAK;AACb,UAAQ,QAAQ,YAAY,GAAG,KAAK,GAAG,SAAS,GAAG,GAAG,OAAO,UAAU,GAAG;AAC1E,UAAQ,KAAK,eAAe,GAAG,IAAI,OAAO,SAAS,GAAG;AACtD,UAAQ,KAAK,YAAY,OAAO,aAAa,MAAM,QAAQ,EAAE,CAAC,IAAI;AAGlE,MAAI,UAAU,WAAW,KAAK;AAC7B,WAAQ,KAAK,aAAa,GAAG,OAAO,UAAU,CAAC,gCAAgC;AAE/E,OAAI,KAAK,YAAY;AACpB,YAAQ,KAAK,uDAAuD;AACpE,YAAQ,KAAK;AACb;;AAID,WAAQ,MAAM,4CAA4C;GAC1D,MAAM,aAAa,IAAI,IACtB,mBAAmB,SAAS,GAAG,YAAY,SAAS,WACpD,YACA;GACD,MAAM,cAAc,MAAM,kBAAkB,WAAW,UAAU,EAAE,MAAM;AAEzE,OAAI,YACH,qBAAoB,YAAY;QAC1B;AACN,YAAQ,KAAK,kEAAkE;AAC/E,YAAQ,KAAK,KAAK,GAAG,IAAI,QAAQ,WAAW,UAAU,GAAG,GAAG;;SAEvD;AAEN,OAAI,OAAO,MACV,2BAA0B,OAAO,OAAO,OAAO,cAAc,KAAK;AAEnE,WAAQ,KAAK,aAAa,GAAG,MAAM,OAAO,UAAU,YAAY,GAAG;;AAGpE,UAAQ,KAAK;;CAEd,CAAC;AAIF,MAAa,0BAA0B,cAAc;CACpD,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM,EACL,UAAU;EACT,MAAM;EACN,aAAa;EACb,SAAS;EACT,EACD;CACD,MAAM,IAAI,EAAE,QAAQ;EACnB,MAAM,cAAc,KAAK;EAEzB,MAAM,WAAW,yBAAyB,YAAY;AACtD,MAAI,UAAU;AACb,WAAQ,KAAK,wBAAwB,GAAG,KAAK,SAAS,QAAQ,QAAQ,UAAU,GAAG;AACnF,WAAQ,KAAK,+CAA+C;AAC5D;;EAGD,MAAM,SAAS,MAAM,0BAA0B,YAAY;AAE3D,4BAA0B,aAAa;GACtC,OAAO,OAAO;GACd,WAAW,IAAI,KAAK,KAAK,KAAK,GAAG,KAAK,QAAQ,IAAK,CAAC,aAAa;GACjE,QAAQ;IAAE,IAAI,OAAO,OAAO;IAAI,MAAM,OAAO,OAAO;IAAM;GAC1D,CAAC;AAEF,UAAQ,QAAQ,gBAAgB,GAAG,KAAK,OAAO,OAAO,KAAK,GAAG;;CAE/D,CAAC;AAEF,MAAa,2BAA2B,cAAc;CACrD,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM,EACL,UAAU;EACT,MAAM;EACN,aAAa;EACb,SAAS;EACT,EACD;CACD,MAAM,IAAI,EAAE,QAAQ;AAEnB,MADgB,4BAA4B,KAAK,SAAS,CAEzD,SAAQ,QAAQ,6BAA6B;MAE7C,SAAQ,KAAK,oCAAoC;;CAGnD,CAAC;;;;;;;;;;;;;;;;;;AClqBF,MAAa,gBAAgB,cAAc;CAC1C,MAAM;EAAE,MAAM;EAAU,aAAa;EAAkB;CACvD,aAAa;EACZ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,SAAS;EACT,OAAO;EACP,QAAQ;EACR;CACD,CAAC;;;;;;;;;ACpBF,MAAMC,gBAAc,cAAc;CACjC,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM,EACL,GAAGC,gBACH;CACD,MAAM,IAAI,EAAE,QAAQ;AACnB,MAAI;AAGH,UADoB,MADL,qBAAqB,KAAK,CACR,aAAa,EAC1B,KAAK;WACjB,OAAO;AACf,aAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,gBAAgB;AACvE,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;AAEF,MAAM,aAAa,cAAc;CAChC,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM;EACL,YAAY;GACX,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,GAAGA;EACH;CACD,MAAM,IAAI,EAAE,QAAQ;AACnB,MAAI;AAGH,UADmB,MADJ,qBAAqB,KAAK,CACT,WAAW,KAAK,WAAW,EACxC,KAAK;WAChB,OAAO;AACf,aAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,gBAAgB;AACvE,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;AAEF,MAAM,gBAAgB,cAAc;CACnC,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM;EACL,YAAY;GACX,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,OAAO;GACN,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,kBAAkB;GACjB,MAAM;GACN,aAAa;GACb;EACD,aAAa;GACZ,MAAM;GACN,aAAa;GACb;EACD,GAAGA;EACH;CACD,MAAM,IAAI,EAAE,QAAQ;AACnB,MAAI;GAEH,MAAM,OAAO,MADE,qBAAqB,KAAK,CACf,iBAAiB;IAC1C,MAAM,KAAK;IACX,OAAO,KAAK;IACZ,eAAe,KAAK,qBAAqB,KAAK;IAC9C,aAAa,KAAK;IAClB,CAAC;AACF,aAAQ,QAAQ,uBAAuB,KAAK,WAAW,GAAG;AAC1D,UAAO,MAAM,KAAK;WACV,OAAO;AACf,aAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,gBAAgB;AACvE,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;AAEF,MAAM,gBAAgB,cAAc;CACnC,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM;EACL,YAAY;GACX,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,OAAO;GACN,MAAM;GACN,aAAa;GACb;EACD,GAAGA;EACH;CACD,MAAM,IAAI,EAAE,QAAQ;AACnB,MAAI;AACH,OAAI,CAAC,KAAK,OAIT;QAAI,CAHc,MAAMC,UAAQ,OAAO,sBAAsB,KAAK,WAAW,KAAK,EACjF,MAAM,WACN,CAAC,EACc;AACf,eAAQ,KAAK,YAAY;AACzB;;;AAIF,SADe,qBAAqB,KAAK,CAC5B,iBAAiB,KAAK,WAAW;AAC9C,aAAQ,QAAQ,uBAAuB,KAAK,WAAW,GAAG;WAClD,OAAO;AACf,aAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,gBAAgB;AACvE,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;AAEF,MAAM,kBAAkB,cAAc;CACrC,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM;EACL,YAAY;GACX,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,OAAO;GACN,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,MAAM;GACL,MAAM;GACN,aACC;GACD,UAAU;GACV;EACD,OAAO;GACN,MAAM;GACN,aAAa;GACb;EACD,UAAU;GACT,MAAM;GACN,aAAa;GACb;EACD,GAAGD;EACH;CACD,MAAM,IAAI,EAAE,QAAQ;AACnB,MAAI;GAEH,MAAM,OAAO,MADE,qBAAqB,KAAK,CACf,YAAY,KAAK,YAAY;IACtD,MAAM,KAAK;IACX,MAAM,KAAK;IACX,OAAO,KAAK,SAAS,KAAK;IAC1B,UAAU,KAAK;IACf,CAAC;AACF,aAAQ,QAAQ,gBAAgB,KAAK,MAAM,QAAQ,KAAK,WAAW,GAAG;AACtE,UAAO,MAAM,KAAK;WACV,OAAO;AACf,aAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,gBAAgB;AACvE,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;AAEF,MAAM,qBAAqB,cAAc;CACxC,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM;EACL,YAAY;GACX,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,OAAO;GACN,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,GAAGA;EACH;CACD,MAAM,IAAI,EAAE,QAAQ;AACnB,MAAI;AAEH,SADe,qBAAqB,KAAK,CAC5B,YAAY,KAAK,YAAY,KAAK,MAAM;AACrD,aAAQ,QAAQ,kBAAkB,KAAK,MAAM,UAAU,KAAK,WAAW,GAAG;WAClE,OAAO;AACf,aAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,gBAAgB;AACvE,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;AAEF,MAAa,gBAAgB,cAAc;CAC1C,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,aAAa;EACZ,MAAMD;EACN,KAAK;EACL,QAAQ;EACR,QAAQ;EACR,aAAa;EACb,gBAAgB;EAChB;CACD,CAAC;;;;;;;;;AC5NF,MAAa,gBAAgB,cAAc;CAC1C,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM;EACL,OAAO;GACN,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,YAAY;GACX,MAAM;GACN,OAAO;GACP,aAAa;GACb;EACD,QAAQ;GACP,MAAM;GACN,aAAa;GACb;EACD,OAAO;GACN,MAAM;GACN,OAAO;GACP,aAAa;GACb;EACD,GAAG;EACH;CACD,MAAM,IAAI,EAAE,QAAQ;AACnB,MAAI;AAOH,UALgB,MADD,qBAAqB,KAAK,CACZ,OAAO,KAAK,OAAO;IAC/C,YAAY,KAAK;IACjB,QAAQ,KAAK;IACb,OAAO,KAAK,QAAQ,SAAS,KAAK,OAAO,GAAG,GAAG;IAC/C,CAAC,EACc,KAAK;WACb,OAAO;AACf,aAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,gBAAgB;AACvE,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;;;;;;;;;AC3BF,eAAe,WAAW,MAAgC;AACzD,KAAI;AACH,QAAM,OAAO,KAAK;AAClB,SAAO;SACA;AACP,SAAO;;;AAIT,eAAe,gBAAgB,KAA0C;CACxE,MAAM,UAAU,QAAQ,KAAK,eAAe;AAC5C,KAAI;EACH,MAAM,UAAU,MAAM,SAAS,SAAS,QAAQ;AAChD,SAAO,KAAK,MAAM,QAAQ;SACnB;AACP,SAAO;;;;;;;;;AAUT,eAAe,gBAAgB,KAAa,YAA6C;AAExF,KAAI,YAAY;EACf,MAAM,WAAW,QAAQ,KAAK,WAAW;AACzC,MAAI,MAAM,WAAW,SAAS,CAC7B,QAAO;AAER,UAAQ,MAAM,wBAAwB,aAAa;AACnD,SAAO;;CAIR,MAAM,iBAAiB,QAAQ,KAAK,WAAW,YAAY;AAC3D,KAAI,MAAM,WAAW,eAAe,CACnC,QAAO;CAIR,MAAM,MAAM,MAAM,gBAAgB,IAAI;AACtC,KAAI,KAAK,QAAQ,MAAM;EACtB,MAAM,cAAc,QAAQ,KAAK,IAAI,OAAO,KAAK;AACjD,MAAI,MAAM,WAAW,YAAY,CAChC,QAAO;AAER,UAAQ,KAAK,0CAA0C,IAAI,OAAO,OAAO;;AAG1E,QAAO;;AAGR,MAAa,cAAc,cAAc;CACxC,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM;EACL,MAAM;GACL,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,UAAU;GACT,MAAM;GACN,OAAO;GACP,aAAa;GACb,SAAS;GACT;EACD,KAAK;GACJ,MAAM;GACN,aAAa;GACb,SAAS,QAAQ,KAAK;GACtB;EACD,UAAU;GACT,MAAM;GACN,aAAa;GACb,SAAS;GACT;EACD,cAAc;GACb,MAAM;GACN,aAAa;GACb,SAAS;GACT;EACD,eAAe;GACd,MAAM;GACN,aAAa;GACb,SAAS;GACT;EACD,eAAe;GACd,MAAM;GACN,aAAa;GACb,SAAS;GACT;EACD,kBAAkB;GACjB,MAAM;GACN,aAAa;GACb,SAAS;GACT;EACD;CACD,MAAM,IAAI,EAAE,QAAQ;EACnB,MAAM,MAAM,QAAQ,KAAK,IAAI;AAC7B,UAAQ,MAAM,uBAAuB;EAGrC,MAAM,WAAW,MAAM,gBAAgB,KAAK,KAAK,KAAK;AACtD,MAAI,CAAC,UAAU;AACd,WAAQ,MAAM,qBAAqB;AACnC,WAAQ,KAAK,+EAA+E;AAC5F,WAAQ,KAAK,EAAE;;AAGhB,UAAQ,KAAK,cAAc,WAAW;EAGtC,IAAI;AACJ,MAAI;GACH,MAAM,UAAU,MAAM,SAAS,UAAU,QAAQ;AACjD,UAAO,KAAK,MAAM,QAAQ;WAClB,OAAO;AACf,WAAQ,MAAM,8BAA8B,MAAM;AAClD,WAAQ,KAAK,EAAE;;AAIhB,UAAQ,MAAM,0BAA0B;EACxC,MAAM,aAAa,aAAa,KAAK;AAErC,MAAI,WAAW,SAAS,SAAS,EAChC,MAAK,MAAM,WAAW,WAAW,SAChC,SAAQ,KAAK,QAAQ;AAIvB,MAAI,CAAC,WAAW,OAAO;AACtB,WAAQ,MAAM,0BAA0B;AACxC,QAAK,MAAM,SAAS,WAAW,OAC9B,SAAQ,MAAM,OAAO,QAAQ;AAE9B,WAAQ,KAAK,EAAE;;AAGhB,UAAQ,QAAQ,qBAAqB;AAGrC,MAAI,KAAK,UAAU;AAClB,WAAQ,QAAQ,sBAAsB;AACtC;;EAID,MAAM,SAAS,QAAQ,KAAK,KAAK,SAAS;AAC1C,UAAQ,KAAK,aAAa,SAAS;EAEnC,MAAM,KAAK,eAAe,EAAE,KAAK,QAAQ,UAAU,CAAC;AAGpD,UAAQ,MAAM,wBAAwB;AACtC,MAAI;GACH,MAAM,EAAE,YAAY,MAAM,cAAc,GAAG;AAC3C,OAAI,QAAQ,SAAS,EACpB,SAAQ,QAAQ,WAAW,QAAQ,OAAO,aAAa;OAEvD,SAAQ,KAAK,sBAAsB;WAE5B,OAAO;AACf,WAAQ,MAAM,qBAAqB,MAAM;AACzC,SAAM,GAAG,SAAS;AAClB,WAAQ,KAAK,EAAE;;EAIhB,MAAM,aAAa,QAAQ,KAAK,KAAK,eAAe;AACpD,QAAM,MAAM,YAAY,EAAE,WAAW,MAAM,CAAC;EAE5C,MAAM,UAAU,IAAI,aAAa;GAChC,WAAW;GACX,SAAS,KAAK;GACd,CAAC;EAGF,MAAM,gBAAgB,KAAK;AAC3B,MAAI,kBAAkB,UAAU,kBAAkB,YAAY,kBAAkB,SAAS;AACxF,WAAQ,MAAM,gCAAgC,gBAAgB;AAC9D,WAAQ,KAAK,8BAA8B;AAC3C,SAAM,GAAG,SAAS;AAClB,WAAQ,KAAK,EAAE;;EAGhB,MAAM,UAA4B;GACjC,gBAAgB,CAAC,KAAK;GACtB,YAAY;GACZ;GACA;AAGD,UAAQ,MAAM,mBAAmB;AACjC,MAAI;GACH,MAAM,SAAS,MAAM,UAAU,IAAI,MAAM,QAAQ;AAEjD,WAAQ,QAAQ,6BAA6B;AAC7C,WAAQ,IAAI,GAAG;AAGf,OAAI,OAAO,SAAS,UAAU,EAC7B,SAAQ,KAAK,aAAa,OAAO,SAAS,QAAQ,UAAU;AAE7D,OACC,OAAO,YAAY,UAAU,KAC7B,OAAO,YAAY,UAAU,KAC7B,OAAO,YAAY,UAAU,EAE7B,SAAQ,KACP,gBAAgB,OAAO,YAAY,QAAQ,YAAY,OAAO,YAAY,QAAQ,YAAY,OAAO,YAAY,QAAQ,UACzH;AAEF,OAAI,OAAO,OAAO,UAAU,KAAK,OAAO,OAAO,UAAU,KAAK,OAAO,OAAO,UAAU,EACrF,SAAQ,KACP,WAAW,OAAO,OAAO,QAAQ,YAAY,OAAO,OAAO,QAAQ,YAAY,OAAO,OAAO,QAAQ,UACrG;AAEF,OAAI,OAAO,WAAW,UAAU,KAAK,OAAO,WAAW,QAAQ,EAC9D,SAAQ,KACP,eAAe,OAAO,WAAW,QAAQ,YAAY,OAAO,WAAW,MAAM,QAC7E;AAEF,OAAI,OAAO,QAAQ,UAAU,KAAK,OAAO,QAAQ,UAAU,KAAK,OAAO,QAAQ,UAAU,EACxF,SAAQ,KACP,YAAY,OAAO,QAAQ,QAAQ,YAAY,OAAO,QAAQ,QAAQ,YAAY,OAAO,QAAQ,QAAQ,UACzG;AAEF,OAAI,OAAO,MAAM,UAAU,KAAK,OAAO,MAAM,QAAQ,EACpD,SAAQ,KAAK,UAAU,OAAO,MAAM,QAAQ,YAAY,OAAO,MAAM,MAAM,QAAQ;AAEpF,OAAI,OAAO,YAAY,UAAU,KAAK,OAAO,YAAY,UAAU,EAClE,SAAQ,KACP,iBAAiB,OAAO,YAAY,QAAQ,YAAY,OAAO,YAAY,QAAQ,UACnF;AAEF,OAAI,OAAO,QAAQ,UAAU,KAAK,OAAO,QAAQ,UAAU,KAAK,OAAO,QAAQ,UAAU,EACxF,SAAQ,KACP,YAAY,OAAO,QAAQ,QAAQ,YAAY,OAAO,QAAQ,QAAQ,YAAY,OAAO,QAAQ,QAAQ,UACzG;AAEF,OAAI,OAAO,MAAM,UAAU,KAAK,OAAO,MAAM,UAAU,EACtD,SAAQ,KAAK,UAAU,OAAO,MAAM,QAAQ,YAAY,OAAO,MAAM,QAAQ,UAAU;WAEhF,OAAO;AACf,WAAQ,MAAM,gBAAgB,iBAAiB,QAAQ,MAAM,UAAU,MAAM;AAC7E,SAAM,GAAG,SAAS;AAClB,WAAQ,KAAK,EAAE;;AAGhB,QAAM,GAAG,SAAS;AAClB,UAAQ,QAAQ,QAAQ;;CAEzB,CAAC;;;;;;;;;;AChRF,MAAM,qBAAqB;AAE3B,MAAM,cAAc,cAAc;CACjC,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM,EACL,GAAG,gBACH;CACD,MAAM,IAAI,EAAE,QAAQ;AACnB,MAAI;AAGH,UADmB,MADJ,qBAAqB,KAAK,CACT,YAAY,EACzB,KAAK;WAChB,OAAO;AACf,aAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,gBAAgB;AACvE,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;AAEF,MAAM,eAAe,cAAc;CAClC,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM;EACL,MAAM;GACL,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,OAAO;GACN,MAAM;GACN,OAAO;GACP,aAAa;GACb;EACD,QAAQ;GACP,MAAM;GACN,aAAa;GACb;EACD,GAAG;EACH;CACD,MAAM,IAAI,EAAE,QAAQ;AACnB,MAAI;AAMH,UAJe,MADA,qBAAqB,KAAK,CACb,MAAM,KAAK,MAAM;IAC5C,OAAO,KAAK,QAAQ,SAAS,KAAK,OAAO,GAAG,GAAG;IAC/C,QAAQ,KAAK;IACb,CAAC,EACa,KAAK;WACZ,OAAO;AACf,aAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,gBAAgB;AACvE,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;AAEF,MAAM,iBAAiB,cAAc;CACpC,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM;EACL,UAAU;GACT,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,MAAM;GACL,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,MAAM;GACL,MAAM;GACN,aAAa;GACb;EACD,QAAQ;GACP,MAAM;GACN,aAAa;GACb;EACD,GAAG;EACH;CACD,MAAM,IAAI,EAAE,QAAQ;AACnB,MAAI;GACH,MAAM,SAAS,qBAAqB,KAAK;GACzC,MAAM,QAAQ,KAAK;GACnB,MAAM,OAAO,KAAK,QAAQ,MAAM,aAAa,CAAC,QAAQ,oBAAoB,IAAI;GAC9E,MAAM,OAAO,MAAM,OAAO,WAAW,KAAK,UAAU;IACnD;IACA;IACA,UAAU,KAAK;IACf,CAAC;AACF,aAAQ,QAAQ,iBAAiB,MAAM,OAAO,KAAK,WAAW;AAC9D,UAAO,MAAM,KAAK;WACV,OAAO;AACf,aAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,gBAAgB;AACvE,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;AAEF,MAAa,kBAAkB,cAAc;CAC5C,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,aAAa;EACZ,MAAM;EACN,OAAO;EACP,YAAY;EACZ;CACD,CAAC;;;;;;;;;ACjHF,MAAa,eAAe,cAAc;CACzC,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,MAAM;EACL,GAAG;EACH,QAAQ;GACP,MAAM;GACN,OAAO;GACP,aAAa;GACb,SAAS;GACT;EACD,KAAK;GACJ,MAAM;GACN,aAAa;GACb,SAAS,QAAQ,KAAK;GACtB;EACD;CACD,MAAM,IAAI,EAAE,QAAQ;EACnB,MAAM,MAAM,QAAQ,KAAK,IAAI;AAC7B,UAAQ,MAAM,qBAAqB;AAEnC,MAAI;GACH,MAAM,SAAS,qBAAqB,KAAK;GAGzC,MAAM,SAAS,MAAM,OAAO,cAAc;AAC1C,WAAQ,QAAQ,SAAS,OAAO,YAAY,OAAO,cAAc;GAGjE,MAAM,QAAQ,MAAM,OAAO,aAAa;GAGxC,MAAM,aAAa,QAAQ,KAAK,KAAK,OAAO;AAC5C,SAAM,MAAM,QAAQ,WAAW,EAAE,EAAE,WAAW,MAAM,CAAC;AACrD,SAAM,UAAU,YAAY,OAAO,QAAQ;AAC3C,WAAQ,QAAQ,aAAa,KAAK,SAAS;AAI3C,SAAM,UADiB,QAAQ,QAAQ,WAAW,EAAE,cAAc,EAClC,KAAK,UAAU,QAAQ,MAAM,EAAE,EAAE,QAAQ;AACzE,WAAQ,KAAK,mBAAmB,OAAO,UAAU;AAEjD,WAAQ,IAAI;IACX,OAAO;IACP,SAAS,GAAG,OAAO,YAAY,OAAO,yBAAyB,KAAK,OAAO;IAC3E,CAAC;WACM,OAAO;AACf,WAAQ,MAAM,2BAA2B,iBAAiB,QAAQ,MAAM,UAAU,MAAM;AACxF,WAAQ,KAAK,EAAE;;;CAGjB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;ACEG,QA3BQ,cAAc;CAC1B,MAAM;EACL,MAAM;EACN,SAAS;EACT,aAAa;EACb;CACD,aAAa;EACZ,MAAM;EACN,OAAO;EACP,KAAK;EACL,QAAQ;EACR,MAAM;EACN,eAAe;EACf,MAAM;EACN,OAAO;EACP,QAAQ;EACR,QAAQ;EACR,SAAS;EACT,QAAQ;EACR,OAAO;EACP,QAAQ;EACR,UAAU;EACV,MAAM;EACN,QAAQ;EACR;CACD,CAAC,CAEgB"}