@gpc-cli/core 0.9.23 → 0.9.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/output.ts","../src/plugins.ts","../src/commands/apps.ts","../src/utils/file-validation.ts","../src/commands/releases.ts","../src/utils/bcp47.ts","../src/utils/image-validation.ts","../src/utils/fastlane.ts","../src/commands/listings.ts","../src/commands/migrate.ts","../src/utils/validation.ts","../src/utils/release-notes.ts","../src/commands/validate.ts","../src/commands/publish.ts","../src/commands/reviews.ts","../src/commands/vitals.ts","../src/commands/subscriptions.ts","../src/commands/iap.ts","../src/commands/purchases.ts","../src/commands/pricing.ts","../src/commands/reports.ts","../src/commands/users.ts","../src/commands/testers.ts","../src/utils/git-notes.ts","../src/commands/app-recovery.ts","../src/commands/data-safety.ts","../src/commands/external-transactions.ts","../src/commands/device-tiers.ts","../src/commands/one-time-products.ts","../src/utils/spinner.ts","../src/utils/safe-path.ts","../src/utils/sort.ts","../src/commands/plugin-scaffold.ts","../src/audit.ts","../src/utils/webhooks.ts","../src/commands/internal-sharing.ts","../src/commands/generated-apks.ts","../src/commands/purchase-options.ts","../src/commands/bundle-analysis.ts","../src/commands/status.ts"],"sourcesContent":["export class GpcError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n public readonly exitCode: number,\n public readonly suggestion?: string,\n ) {\n super(message);\n this.name = \"GpcError\";\n }\n\n toJSON() {\n return {\n success: false,\n error: {\n code: this.code,\n message: this.message,\n suggestion: this.suggestion,\n },\n };\n }\n}\n\nexport class ConfigError extends GpcError {\n constructor(message: string, code: string, suggestion?: string) {\n super(message, code, 1, suggestion);\n this.name = \"ConfigError\";\n }\n}\n\nexport class ApiError extends GpcError {\n constructor(\n message: string,\n code: string,\n public readonly statusCode?: number,\n suggestion?: string,\n ) {\n super(message, code, 4, suggestion);\n this.name = \"ApiError\";\n }\n}\n\nexport class NetworkError extends GpcError {\n constructor(message: string, suggestion?: string) {\n super(message, \"NETWORK_ERROR\", 5, suggestion);\n this.name = \"NetworkError\";\n }\n}\n","import type { OutputFormat } from \"@gpc-cli/config\";\nimport process from \"node:process\";\n\nexport function detectOutputFormat(): OutputFormat {\n return process.stdout.isTTY ? \"table\" : \"json\";\n}\n\nexport function formatOutput(data: unknown, format: OutputFormat, redact = true): string {\n const safe = redact ? redactSensitive(data) : data;\n switch (format) {\n case \"json\":\n return formatJson(safe);\n case \"yaml\":\n return formatYaml(safe);\n case \"markdown\":\n return formatMarkdown(safe);\n case \"table\":\n return formatTable(safe);\n case \"junit\":\n return formatJunit(safe);\n default:\n return formatJson(safe);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Sensitive field redaction\n// ---------------------------------------------------------------------------\n\nexport const SENSITIVE_KEYS = new Set([\n \"private_key\",\n \"privateKey\",\n \"private_key_id\",\n \"privateKeyId\",\n \"accessToken\",\n \"access_token\",\n \"refreshToken\",\n \"refresh_token\",\n \"client_secret\",\n \"clientSecret\",\n \"token\",\n \"password\",\n \"secret\",\n \"credentials\",\n \"keyFile\",\n \"key_file\",\n \"serviceAccount\",\n \"service-account\",\n \"apiKey\",\n \"api_key\",\n \"auth_token\",\n \"bearer\",\n \"jwt\",\n \"signing_key\",\n \"keystore_password\",\n \"store_password\",\n \"key_password\",\n]);\n\nconst REDACTED = \"[REDACTED]\";\n\n/** Recursively redact sensitive fields from data before output. */\nexport function redactSensitive(data: unknown): unknown {\n if (data === null || data === undefined) return data;\n\n if (typeof data === \"string\") return data;\n if (typeof data === \"number\" || typeof data === \"boolean\") return data;\n\n if (Array.isArray(data)) {\n return data.map((item) => redactSensitive(item));\n }\n\n if (typeof data === \"object\") {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data as Record<string, unknown>)) {\n if (SENSITIVE_KEYS.has(key) && typeof value === \"string\") {\n result[key] = REDACTED;\n } else {\n result[key] = redactSensitive(value);\n }\n }\n return result;\n }\n\n return data;\n}\n\nfunction formatJson(data: unknown): string {\n return JSON.stringify(data, null, 2);\n}\n\nfunction formatYaml(data: unknown, indent = 0): string {\n if (data === null || data === undefined) {\n return \"null\";\n }\n\n if (typeof data === \"string\") {\n return data.includes(\"\\n\")\n ? `|\\n${data\n .split(\"\\n\")\n .map((l) => `${\" \".repeat(indent + 1)}${l}`)\n .join(\"\\n\")}`\n : data;\n }\n\n if (typeof data === \"number\" || typeof data === \"boolean\") {\n return String(data);\n }\n\n if (Array.isArray(data)) {\n if (data.length === 0) return \"[]\";\n return data\n .map((item) => {\n const value = formatYaml(item, indent + 1);\n const prefix = `${\" \".repeat(indent)}- `;\n if (typeof item === \"object\" && item !== null && !Array.isArray(item)) {\n const lines = value.split(\"\\n\");\n return `${prefix}${lines[0]}\\n${lines\n .slice(1)\n .map((l) => `${\" \".repeat(indent)} ${l}`)\n .join(\"\\n\")}`;\n }\n return `${prefix}${value}`;\n })\n .join(\"\\n\");\n }\n\n if (typeof data === \"object\") {\n const entries = Object.entries(data as Record<string, unknown>);\n if (entries.length === 0) return \"{}\";\n return entries\n .map(([key, value]) => {\n if (typeof value === \"object\" && value !== null) {\n return `${\" \".repeat(indent)}${key}:\\n${formatYaml(value, indent + 1)}`;\n }\n return `${\" \".repeat(indent)}${key}: ${formatYaml(value, indent)}`;\n })\n .join(\"\\n\");\n }\n\n return String(data);\n}\n\nconst MAX_CELL_WIDTH = 60;\n\nfunction truncateCell(value: string): string {\n if (value.length <= MAX_CELL_WIDTH) return value;\n return value.slice(0, MAX_CELL_WIDTH - 3) + \"...\";\n}\n\nfunction cellValue(val: unknown): string {\n if (val === null || val === undefined) return \"\";\n if (typeof val === \"object\") {\n if (Array.isArray(val)) return val.length === 0 ? \"\" : JSON.stringify(val);\n return JSON.stringify(val);\n }\n return String(val);\n}\n\nfunction formatTable(data: unknown): string {\n const rows = toRows(data);\n if (rows.length === 0) return \"\";\n\n const firstRow = rows[0];\n if (!firstRow) return \"\";\n const keys = Object.keys(firstRow);\n if (keys.length === 0) return \"\";\n\n const widths = keys.map((key) =>\n Math.max(key.length, ...rows.map((row) => truncateCell(cellValue(row[key])).length)),\n );\n\n const header = keys.map((key, i) => key.padEnd(widths[i] ?? 0)).join(\" \");\n const separator = widths.map((w) => \"-\".repeat(w)).join(\" \");\n const body = rows\n .map((row) => keys.map((key, i) => truncateCell(cellValue(row[key])).padEnd(widths[i] ?? 0)).join(\" \"))\n .join(\"\\n\");\n\n return `${header}\\n${separator}\\n${body}`;\n}\n\nfunction formatMarkdown(data: unknown): string {\n const rows = toRows(data);\n if (rows.length === 0) return \"\";\n\n const firstRow = rows[0];\n if (!firstRow) return \"\";\n const keys = Object.keys(firstRow);\n if (keys.length === 0) return \"\";\n\n const widths = keys.map((key) =>\n Math.max(key.length, ...rows.map((row) => truncateCell(cellValue(row[key])).length)),\n );\n\n const header = `| ${keys.map((key, i) => key.padEnd(widths[i] ?? 0)).join(\" | \")} |`;\n const separator = `| ${widths.map((w) => \"-\".repeat(w)).join(\" | \")} |`;\n const body = rows\n .map(\n (row) =>\n `| ${keys.map((key, i) => truncateCell(cellValue(row[key])).padEnd(widths[i] ?? 0)).join(\" | \")} |`,\n )\n .join(\"\\n\");\n\n return `${header}\\n${separator}\\n${body}`;\n}\n\nfunction toRows(data: unknown): Record<string, unknown>[] {\n if (Array.isArray(data)) {\n return data.filter(\n (item): item is Record<string, unknown> => typeof item === \"object\" && item !== null,\n );\n }\n if (typeof data === \"object\" && data !== null) {\n return [data as Record<string, unknown>];\n }\n return [];\n}\n\n// ---------------------------------------------------------------------------\n// JUnit XML output\n// ---------------------------------------------------------------------------\n\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&apos;\");\n}\n\nfunction toTestCases(data: unknown, commandName: string): { cases: string[]; failures: number } {\n const cases: string[] = [];\n let failures = 0;\n\n if (Array.isArray(data)) {\n for (let i = 0; i < data.length; i++) {\n const tc = buildTestCase(data[i], commandName, i);\n cases.push(tc.xml);\n if (tc.failed) failures++;\n }\n } else if (typeof data === \"object\" && data !== null) {\n const tc = buildTestCase(data, commandName);\n cases.push(tc.xml);\n if (tc.failed) failures++;\n } else if (typeof data === \"string\") {\n cases.push(\n ` <testcase name=\"${escapeXml(data)}\" classname=\"gpc.${escapeXml(commandName)}\" />`,\n );\n }\n\n return { cases, failures };\n}\n\nfunction buildTestCase(\n item: unknown,\n commandName: string,\n index = 0,\n): { xml: string; failed: boolean } {\n if (typeof item !== \"object\" || item === null) {\n const text = String(item);\n return {\n xml: ` <testcase name=\"${escapeXml(text)}\" classname=\"gpc.${escapeXml(commandName)}\" />`,\n failed: false,\n };\n }\n\n const record = item as Record<string, unknown>;\n\n // Pick the first meaningful identifier, skipping sentinel dash/empty values\n // that commands use as display placeholders (e.g. `name: s[\"name\"] || \"-\"`).\n const CANDIDATE_KEYS = [\n \"name\", \"title\", \"sku\", \"id\", \"reviewId\", \"productId\", \"packageName\",\n \"track\", \"trackId\", \"versionCode\", \"region\", \"languageCode\",\n ] as const;\n let resolvedName = `item-${index + 1}`;\n for (const key of CANDIDATE_KEYS) {\n const val = record[key];\n if (val != null && val !== \"\" && val !== \"-\") {\n resolvedName = String(val);\n break;\n }\n }\n const name = escapeXml(resolvedName);\n const classname = `gpc.${escapeXml(commandName)}`;\n\n // Detect threshold breach (vitals)\n const breached = record[\"breached\"];\n if (breached === true) {\n const message = escapeXml(String(record[\"message\"] ?? \"threshold breached\"));\n const details = escapeXml(\n String(record[\"details\"] ?? record[\"metric\"] ?? JSON.stringify(item)),\n );\n return {\n xml: ` <testcase name=\"${name}\" classname=\"${classname}\">\\n <failure message=\"${message}\">${details}</failure>\\n </testcase>`,\n failed: true,\n };\n }\n\n return {\n xml: ` <testcase name=\"${name}\" classname=\"${classname}\" />`,\n failed: false,\n };\n}\n\nexport function formatJunit(data: unknown, commandName = \"command\"): string {\n const { cases, failures } = toTestCases(data, commandName);\n const tests = cases.length;\n\n const lines = [\n '<?xml version=\"1.0\" encoding=\"UTF-8\"?>',\n `<testsuites name=\"gpc\" tests=\"${tests}\" failures=\"${failures}\" time=\"0\">`,\n ` <testsuite name=\"${escapeXml(commandName)}\" tests=\"${tests}\" failures=\"${failures}\">`,\n ...cases,\n \" </testsuite>\",\n \"</testsuites>\",\n ];\n\n return lines.join(\"\\n\");\n}\n","import type {\n GpcPlugin,\n PluginHooks,\n BeforeCommandHandler,\n AfterCommandHandler,\n ErrorHandler,\n BeforeRequestHandler,\n AfterResponseHandler,\n CommandEvent,\n CommandResult,\n PluginError,\n PluginCommand,\n PluginManifest,\n PluginPermission,\n RequestEvent,\n ResponseEvent,\n} from \"@gpc-cli/plugin-sdk\";\nimport { GpcError } from \"./errors.js\";\n\n// ---------------------------------------------------------------------------\n// Plugin Manager — orchestrates discovery, loading, and lifecycle\n// ---------------------------------------------------------------------------\n\nexport class PluginManager {\n private plugins: LoadedPlugin[] = [];\n private beforeHandlers: BeforeCommandHandler[] = [];\n private afterHandlers: AfterCommandHandler[] = [];\n private errorHandlers: ErrorHandler[] = [];\n private beforeRequestHandlers: BeforeRequestHandler[] = [];\n private afterResponseHandlers: AfterResponseHandler[] = [];\n private registeredCommands: PluginCommand[] = [];\n\n /** Load and register a plugin */\n async load(plugin: GpcPlugin, manifest?: PluginManifest): Promise<void> {\n const isTrusted = manifest?.trusted ?? plugin.name.startsWith(\"@gpc-cli/\");\n\n if (!isTrusted && manifest?.permissions) {\n validatePermissions(manifest.permissions);\n }\n\n const hooks = createHooks(\n this.beforeHandlers,\n this.afterHandlers,\n this.errorHandlers,\n this.beforeRequestHandlers,\n this.afterResponseHandlers,\n this.registeredCommands,\n );\n\n await plugin.register(hooks);\n\n this.plugins.push({\n name: plugin.name,\n version: plugin.version,\n trusted: isTrusted,\n });\n }\n\n /** Run all beforeCommand handlers */\n async runBeforeCommand(event: CommandEvent): Promise<void> {\n for (const handler of this.beforeHandlers) {\n await handler(event);\n }\n }\n\n /** Run all afterCommand handlers */\n async runAfterCommand(event: CommandEvent, result: CommandResult): Promise<void> {\n for (const handler of this.afterHandlers) {\n await handler(event, result);\n }\n }\n\n /** Run all onError handlers */\n async runOnError(event: CommandEvent, error: PluginError): Promise<void> {\n for (const handler of this.errorHandlers) {\n try {\n await handler(event, error);\n } catch {\n // Don't let error handlers crash the process\n }\n }\n }\n\n /** Run all beforeRequest handlers */\n async runBeforeRequest(event: RequestEvent): Promise<void> {\n for (const handler of this.beforeRequestHandlers) {\n try {\n await handler(event);\n } catch {\n // Don't let request hooks block API calls\n }\n }\n }\n\n /** Run all afterResponse handlers */\n async runAfterResponse(event: RequestEvent, response: ResponseEvent): Promise<void> {\n for (const handler of this.afterResponseHandlers) {\n try {\n await handler(event, response);\n } catch {\n // Don't let response hooks crash the process\n }\n }\n }\n\n /** Get commands registered by plugins */\n getRegisteredCommands(): PluginCommand[] {\n return [...this.registeredCommands];\n }\n\n /** Get list of loaded plugins */\n getLoadedPlugins(): LoadedPlugin[] {\n return [...this.plugins];\n }\n\n /** Whether any request/response hooks are registered */\n hasRequestHooks(): boolean {\n return this.beforeRequestHandlers.length > 0 || this.afterResponseHandlers.length > 0;\n }\n\n /** Reset (for testing) */\n reset(): void {\n this.plugins = [];\n this.beforeHandlers = [];\n this.afterHandlers = [];\n this.errorHandlers = [];\n this.beforeRequestHandlers = [];\n this.afterResponseHandlers = [];\n this.registeredCommands = [];\n }\n}\n\nexport interface LoadedPlugin {\n name: string;\n version: string;\n trusted: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Hook factory\n// ---------------------------------------------------------------------------\n\nfunction createHooks(\n beforeHandlers: BeforeCommandHandler[],\n afterHandlers: AfterCommandHandler[],\n errorHandlers: ErrorHandler[],\n beforeRequestHandlers: BeforeRequestHandler[],\n afterResponseHandlers: AfterResponseHandler[],\n registeredCommands: PluginCommand[],\n): PluginHooks {\n return {\n beforeCommand(handler) {\n beforeHandlers.push(handler);\n },\n afterCommand(handler) {\n afterHandlers.push(handler);\n },\n onError(handler) {\n errorHandlers.push(handler);\n },\n beforeRequest(handler) {\n beforeRequestHandlers.push(handler);\n },\n afterResponse(handler) {\n afterResponseHandlers.push(handler);\n },\n registerCommands(registrar) {\n const registry = {\n add(cmd: PluginCommand) {\n registeredCommands.push(cmd);\n },\n };\n registrar(registry);\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Permission validation\n// ---------------------------------------------------------------------------\n\nconst VALID_PERMISSIONS: ReadonlySet<string> = new Set<PluginPermission>([\n \"read:config\",\n \"write:config\",\n \"read:auth\",\n \"api:read\",\n \"api:write\",\n \"commands:register\",\n \"hooks:beforeCommand\",\n \"hooks:afterCommand\",\n \"hooks:onError\",\n \"hooks:beforeRequest\",\n \"hooks:afterResponse\",\n]);\n\nfunction validatePermissions(permissions: PluginPermission[]): void {\n for (const perm of permissions) {\n if (!VALID_PERMISSIONS.has(perm)) {\n throw new GpcError(\n `Unknown plugin permission: \"${perm}\"`,\n \"PLUGIN_INVALID_PERMISSION\",\n 10,\n `Valid permissions: ${[...VALID_PERMISSIONS].join(\", \")}`,\n );\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Plugin discovery\n// ---------------------------------------------------------------------------\n\nexport interface DiscoverPluginsOptions {\n /** Plugin names from config file */\n configPlugins?: string[];\n\n /** Working directory for node_modules scanning */\n cwd?: string;\n}\n\n/**\n * Discover plugins from multiple sources:\n * 1. Explicit config: gpc.config.ts → plugins: [...]\n * 2. Convention: node_modules/@gpc-cli/plugin-*\n * 3. Convention: node_modules/gpc-plugin-*\n */\nexport async function discoverPlugins(options?: DiscoverPluginsOptions): Promise<GpcPlugin[]> {\n const plugins: GpcPlugin[] = [];\n const seen = new Set<string>();\n\n // Source 1: Explicit config plugins\n if (options?.configPlugins) {\n for (const name of options.configPlugins) {\n if (seen.has(name)) continue;\n try {\n const mod = await import(name);\n const plugin = resolvePlugin(mod);\n if (plugin) {\n plugins.push(plugin);\n seen.add(name);\n }\n } catch {\n // Plugin not found — skip silently\n }\n }\n }\n\n return plugins;\n}\n\n/**\n * Resolve a plugin from a module.\n * Supports: default export, named `plugin` export, or the module itself as a plugin.\n */\nfunction resolvePlugin(mod: unknown): GpcPlugin | undefined {\n if (!mod || typeof mod !== \"object\") return undefined;\n\n const m = mod as Record<string, unknown>;\n\n // Check default export\n if (isPlugin(m[\"default\"])) return m[\"default\"];\n\n // Check named `plugin` export\n if (isPlugin(m[\"plugin\"])) return m[\"plugin\"];\n\n // Check if module itself is a plugin\n if (isPlugin(m)) return m as unknown as GpcPlugin;\n\n return undefined;\n}\n\nfunction isPlugin(obj: unknown): obj is GpcPlugin {\n if (!obj || typeof obj !== \"object\") return false;\n const p = obj as Record<string, unknown>;\n return (\n typeof p[\"name\"] === \"string\" &&\n typeof p[\"version\"] === \"string\" &&\n typeof p[\"register\"] === \"function\"\n );\n}\n","import type { PlayApiClient } from \"@gpc-cli/api\";\n\nexport interface AppInfo {\n packageName: string;\n title?: string;\n defaultLanguage?: string;\n contactEmail?: string;\n}\n\nexport async function getAppInfo(client: PlayApiClient, packageName: string): Promise<AppInfo> {\n // Create an edit to read app details (Google Play requires an edit context)\n const edit = await client.edits.insert(packageName);\n try {\n const details = await client.details.get(packageName, edit.id);\n // Delete the edit since we're only reading\n await client.edits.delete(packageName, edit.id);\n return {\n packageName,\n title: details.title,\n defaultLanguage: details.defaultLanguage,\n contactEmail: details.contactEmail,\n };\n } catch (error) {\n // Clean up edit on failure\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n","import { readFile, stat } from \"node:fs/promises\";\nimport { extname } from \"node:path\";\n\nexport interface FileValidationResult {\n valid: boolean;\n fileType: \"aab\" | \"apk\" | \"unknown\";\n sizeBytes: number;\n errors: string[];\n warnings: string[];\n}\n\n// ZIP magic bytes: PK\\x03\\x04\nconst ZIP_MAGIC = Buffer.from([0x50, 0x4b, 0x03, 0x04]);\n\nconst MAX_APK_SIZE = 150 * 1024 * 1024; // 150 MB\nconst MAX_AAB_SIZE = 500 * 1024 * 1024; // 500 MB (Play Store limit for AABs)\nconst LARGE_FILE_THRESHOLD = 100 * 1024 * 1024; // 100 MB — warn about upload time\n\nexport async function validateUploadFile(filePath: string): Promise<FileValidationResult> {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n // Check extension\n const ext = extname(filePath).toLowerCase();\n let fileType: FileValidationResult[\"fileType\"] = \"unknown\";\n\n if (ext === \".aab\") {\n fileType = \"aab\";\n } else if (ext === \".apk\") {\n fileType = \"apk\";\n } else {\n errors.push(`Unsupported file extension \"${ext}\". Expected .aab or .apk`);\n }\n\n // Check file exists and get size\n let sizeBytes: number;\n try {\n const stats = await stat(filePath);\n sizeBytes = stats.size;\n\n if (sizeBytes === 0) {\n errors.push(\"File is empty (0 bytes)\");\n }\n } catch {\n errors.push(`File not found: ${filePath}`);\n return { valid: false, fileType, sizeBytes: 0, errors, warnings };\n }\n\n // Check size limits\n if (fileType === \"apk\" && sizeBytes > MAX_APK_SIZE) {\n errors.push(\n `APK exceeds 150 MB limit (${formatSize(sizeBytes)}). Consider using AAB format instead.`,\n );\n }\n if (fileType === \"aab\" && sizeBytes > MAX_AAB_SIZE) {\n errors.push(`AAB exceeds 500 MB limit (${formatSize(sizeBytes)}).`);\n }\n\n if (sizeBytes > LARGE_FILE_THRESHOLD && errors.length === 0) {\n warnings.push(\n `Large file (${formatSize(sizeBytes)}). Upload may take a while on slow connections.`,\n );\n }\n\n // Check magic bytes (ZIP format — both AAB and APK are ZIP-based)\n if (sizeBytes > 0) {\n try {\n const fd = await readFile(filePath, { flag: \"r\" });\n const header = fd.subarray(0, 4);\n\n if (!header.equals(ZIP_MAGIC)) {\n errors.push(\n \"File does not have valid ZIP magic bytes (PK\\\\x03\\\\x04). \" +\n \"Both AAB and APK files must be valid ZIP archives.\",\n );\n }\n } catch {\n errors.push(\"Unable to read file header for validation\");\n }\n }\n\n return {\n valid: errors.length === 0,\n fileType,\n sizeBytes,\n errors,\n warnings,\n };\n}\n\nfunction formatSize(bytes: number): string {\n if (bytes >= 1024 * 1024 * 1024) {\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;\n }\n if (bytes >= 1024 * 1024) {\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n }\n if (bytes >= 1024) {\n return `${(bytes / 1024).toFixed(1)} KB`;\n }\n return `${bytes} B`;\n}\n","import type { PlayApiClient, Release, Track, ExternallyHostedApk, ExternallyHostedApkResponse } from \"@gpc-cli/api\";\nimport { GpcError } from \"../errors.js\";\nimport { validateUploadFile } from \"../utils/file-validation.js\";\n\nexport interface UploadResult {\n versionCode: number;\n track: string;\n status: string;\n}\n\nexport interface ReleaseStatusResult {\n track: string;\n status: string;\n versionCodes: string[];\n userFraction?: number;\n releaseNotes?: { language: string; text: string }[];\n}\n\nexport interface DryRunUploadResult {\n dryRun: true;\n file: { path: string; valid: boolean; errors: string[]; warnings: string[] };\n track: string;\n currentReleases: { versionCodes: string[]; status: string; userFraction?: number }[];\n plannedRelease: { status: string; userFraction?: number };\n}\n\nexport async function uploadRelease(\n client: PlayApiClient,\n packageName: string,\n filePath: string,\n options: {\n track: string;\n status?: string;\n userFraction?: number;\n releaseNotes?: { language: string; text: string }[];\n releaseName?: string;\n mappingFile?: string;\n dryRun?: boolean;\n },\n): Promise<UploadResult | DryRunUploadResult> {\n // Validate file before upload\n const validation = await validateUploadFile(filePath);\n\n if (options.dryRun) {\n const plannedStatus = options.status ||\n (options.userFraction ? \"inProgress\" : \"completed\");\n\n // Fetch current track state without modifying anything\n let currentReleases: DryRunUploadResult[\"currentReleases\"] = [];\n const edit = await client.edits.insert(packageName);\n try {\n const trackData = await client.tracks.get(packageName, edit.id, options.track);\n currentReleases = (trackData.releases || []).map((r) => ({\n versionCodes: r.versionCodes || [],\n status: r.status,\n ...(r.userFraction !== undefined && { userFraction: r.userFraction }),\n }));\n } catch {\n // Track may not exist yet — that's fine for dry-run\n } finally {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n }\n\n return {\n dryRun: true,\n file: {\n path: filePath,\n valid: validation.valid,\n errors: validation.errors,\n warnings: validation.warnings,\n },\n track: options.track,\n currentReleases,\n plannedRelease: {\n status: plannedStatus,\n ...(options.userFraction !== undefined && { userFraction: options.userFraction }),\n },\n };\n }\n\n if (!validation.valid) {\n throw new GpcError(\n `File validation failed:\\n${validation.errors.join(\"\\n\")}`,\n \"RELEASE_INVALID_FILE\",\n 2,\n \"Check that the file is a valid AAB or APK and is not corrupted.\",\n );\n }\n\n const edit = await client.edits.insert(packageName);\n try {\n // Upload the bundle\n const bundle = await client.bundles.upload(packageName, edit.id, filePath);\n\n // Upload mapping file if provided\n if (options.mappingFile) {\n await client.deobfuscation.upload(\n packageName,\n edit.id,\n bundle.versionCode,\n options.mappingFile,\n );\n }\n\n // Create release and assign to track\n const release: Release = {\n versionCodes: [String(bundle.versionCode)],\n status: (options.status ||\n (options.userFraction ? \"inProgress\" : \"completed\")) as Release[\"status\"],\n ...(options.userFraction && { userFraction: options.userFraction }),\n ...(options.releaseNotes && { releaseNotes: options.releaseNotes }),\n ...(options.releaseName && { name: options.releaseName }),\n };\n\n await client.tracks.update(packageName, edit.id, options.track, release);\n\n // Validate and commit\n await client.edits.validate(packageName, edit.id);\n await client.edits.commit(packageName, edit.id);\n\n return {\n versionCode: bundle.versionCode,\n track: options.track,\n status: release.status,\n };\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function getReleasesStatus(\n client: PlayApiClient,\n packageName: string,\n trackFilter?: string,\n): Promise<ReleaseStatusResult[]> {\n const edit = await client.edits.insert(packageName);\n try {\n const tracks = trackFilter\n ? [await client.tracks.get(packageName, edit.id, trackFilter)]\n : await client.tracks.list(packageName, edit.id);\n\n await client.edits.delete(packageName, edit.id);\n\n const results: ReleaseStatusResult[] = [];\n for (const track of tracks) {\n for (const release of track.releases || []) {\n results.push({\n track: track.track,\n status: release.status,\n versionCodes: release.versionCodes || [],\n userFraction: release.userFraction,\n releaseNotes: release.releaseNotes,\n });\n }\n }\n return results;\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function promoteRelease(\n client: PlayApiClient,\n packageName: string,\n fromTrack: string,\n toTrack: string,\n options?: { userFraction?: number; releaseNotes?: { language: string; text: string }[] },\n): Promise<ReleaseStatusResult> {\n const edit = await client.edits.insert(packageName);\n try {\n // Get current release from source track\n const sourceTrack = await client.tracks.get(packageName, edit.id, fromTrack);\n const currentRelease = sourceTrack.releases?.find(\n (r) => r.status === \"completed\" || r.status === \"inProgress\",\n );\n\n if (!currentRelease) {\n throw new GpcError(\n `No active release found on track \"${fromTrack}\"`,\n \"RELEASE_NOT_FOUND\",\n 1,\n `Ensure there is a completed or in-progress release on the \"${fromTrack}\" track before promoting.`,\n );\n }\n\n // Create release on target track\n if (options?.userFraction && (options.userFraction <= 0 || options.userFraction > 1)) {\n throw new GpcError(\n \"Rollout percentage must be between 0 and 1 (e.g., 0.1 for 10%)\",\n \"RELEASE_INVALID_FRACTION\",\n 2,\n \"Use a decimal value like 0.1 for 10%, 0.5 for 50%, or 1.0 for 100%.\",\n );\n }\n const release: Release = {\n versionCodes: currentRelease.versionCodes,\n status: (options?.userFraction ? \"inProgress\" : \"completed\") as Release[\"status\"],\n ...(options?.userFraction && { userFraction: options.userFraction }),\n releaseNotes: options?.releaseNotes || currentRelease.releaseNotes || [],\n };\n\n await client.tracks.update(packageName, edit.id, toTrack, release);\n await client.edits.validate(packageName, edit.id);\n await client.edits.commit(packageName, edit.id);\n\n return {\n track: toTrack,\n status: release.status,\n versionCodes: release.versionCodes,\n userFraction: release.userFraction,\n };\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function updateRollout(\n client: PlayApiClient,\n packageName: string,\n track: string,\n action: \"increase\" | \"halt\" | \"resume\" | \"complete\",\n userFraction?: number,\n): Promise<ReleaseStatusResult> {\n const edit = await client.edits.insert(packageName);\n try {\n const trackData = await client.tracks.get(packageName, edit.id, track);\n const currentRelease = trackData.releases?.find(\n (r) => r.status === \"inProgress\" || r.status === \"halted\",\n );\n\n if (!currentRelease) {\n throw new GpcError(\n `No active rollout found on track \"${track}\"`,\n \"ROLLOUT_NOT_FOUND\",\n 1,\n `There is no in-progress or halted rollout on the \"${track}\" track. Start a staged rollout first with: gpc releases upload --track ${track} --status inProgress --fraction 0.1`,\n );\n }\n\n let newStatus: string;\n let newFraction: number | undefined;\n\n switch (action) {\n case \"increase\":\n if (!userFraction) throw new GpcError(\n \"--to <percentage> is required for rollout increase\",\n \"ROLLOUT_MISSING_FRACTION\",\n 2,\n \"Specify the target rollout percentage with --to, e.g.: gpc rollout increase --to 0.5\",\n );\n if (userFraction <= 0 || userFraction > 1) {\n throw new GpcError(\n \"Rollout percentage must be between 0 and 1 (e.g., 0.1 for 10%)\",\n \"RELEASE_INVALID_FRACTION\",\n 2,\n \"Use a decimal value like 0.1 for 10%, 0.5 for 50%, or 1.0 for 100%.\",\n );\n }\n newStatus = \"inProgress\";\n newFraction = userFraction;\n break;\n case \"halt\":\n newStatus = \"halted\";\n newFraction = currentRelease.userFraction;\n break;\n case \"resume\":\n newStatus = \"inProgress\";\n newFraction = currentRelease.userFraction;\n break;\n case \"complete\":\n newStatus = \"completed\";\n newFraction = undefined;\n break;\n }\n\n const release: Release = {\n versionCodes: currentRelease.versionCodes,\n status: newStatus as Release[\"status\"],\n ...(newFraction !== undefined && { userFraction: newFraction }),\n releaseNotes: currentRelease.releaseNotes || [],\n };\n\n await client.tracks.update(packageName, edit.id, track, release);\n await client.edits.validate(packageName, edit.id);\n await client.edits.commit(packageName, edit.id);\n\n return {\n track,\n status: newStatus,\n versionCodes: release.versionCodes,\n userFraction: newFraction,\n };\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function listTracks(client: PlayApiClient, packageName: string): Promise<Track[]> {\n const edit = await client.edits.insert(packageName);\n try {\n const tracks = await client.tracks.list(packageName, edit.id);\n await client.edits.delete(packageName, edit.id);\n return tracks;\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function createTrack(\n client: PlayApiClient,\n packageName: string,\n trackName: string,\n): Promise<Track> {\n if (!trackName || trackName.trim().length === 0) {\n throw new GpcError(\n \"Track name must not be empty\",\n \"TRACK_INVALID_NAME\",\n 2,\n \"Provide a valid custom track name, e.g.: gpc tracks create my-qa-track\",\n );\n }\n\n const edit = await client.edits.insert(packageName);\n try {\n const track = await client.tracks.create(packageName, edit.id, trackName);\n await client.edits.validate(packageName, edit.id);\n await client.edits.commit(packageName, edit.id);\n return track;\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function updateTrackConfig(\n client: PlayApiClient,\n packageName: string,\n trackName: string,\n config: Record<string, unknown>,\n): Promise<Track> {\n if (!trackName || trackName.trim().length === 0) {\n throw new GpcError(\n \"Track name must not be empty\",\n \"TRACK_INVALID_NAME\",\n 2,\n \"Provide a valid track name.\",\n );\n }\n\n const edit = await client.edits.insert(packageName);\n try {\n const release: Release = {\n versionCodes: (config[\"versionCodes\"] as string[]) || [],\n status: ((config[\"status\"] as string) || \"completed\") as Release[\"status\"],\n };\n if (config[\"userFraction\"] !== undefined) {\n release.userFraction = config[\"userFraction\"] as number;\n }\n if (config[\"releaseNotes\"]) {\n release.releaseNotes = config[\"releaseNotes\"] as { language: string; text: string }[];\n }\n if (config[\"name\"]) {\n release.name = config[\"name\"] as string;\n }\n\n const track = await client.tracks.update(packageName, edit.id, trackName, release);\n await client.edits.validate(packageName, edit.id);\n await client.edits.commit(packageName, edit.id);\n return track;\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport interface ReleaseDiff {\n field: string;\n track1Value: string;\n track2Value: string;\n}\n\nexport async function diffReleases(\n client: PlayApiClient,\n packageName: string,\n fromTrack: string,\n toTrack: string,\n): Promise<{ fromTrack: string; toTrack: string; diffs: ReleaseDiff[] }> {\n const edit = await client.edits.insert(packageName);\n try {\n const [fromData, toData] = await Promise.all([\n client.tracks.get(packageName, edit.id, fromTrack),\n client.tracks.get(packageName, edit.id, toTrack),\n ]);\n await client.edits.delete(packageName, edit.id);\n\n const fromRelease = fromData.releases?.[0];\n const toRelease = toData.releases?.[0];\n const diffs: ReleaseDiff[] = [];\n\n const fields = [\"versionCodes\", \"status\", \"userFraction\", \"releaseNotes\", \"name\"] as const;\n for (const field of fields) {\n const v1 = fromRelease ? JSON.stringify(fromRelease[field] ?? null) : \"null\";\n const v2 = toRelease ? JSON.stringify(toRelease[field] ?? null) : \"null\";\n if (v1 !== v2) {\n diffs.push({ field, track1Value: v1, track2Value: v2 });\n }\n }\n\n return { fromTrack, toTrack, diffs };\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function uploadExternallyHosted(\n client: PlayApiClient,\n packageName: string,\n data: ExternallyHostedApk,\n): Promise<ExternallyHostedApkResponse> {\n if (!data.externallyHostedUrl) {\n throw new GpcError(\n \"externallyHostedUrl is required\",\n \"EXTERNAL_APK_MISSING_URL\",\n 2,\n \"Provide a valid URL for the externally hosted APK.\",\n );\n }\n\n if (!data.packageName) {\n throw new GpcError(\n \"packageName is required in externally hosted APK data\",\n \"EXTERNAL_APK_MISSING_PACKAGE\",\n 2,\n \"Include the packageName field in the APK configuration.\",\n );\n }\n\n const edit = await client.edits.insert(packageName);\n try {\n const result = await client.apks.addExternallyHosted(packageName, edit.id, data);\n await client.edits.validate(packageName, edit.id);\n await client.edits.commit(packageName, edit.id);\n return result;\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n","export const GOOGLE_PLAY_LANGUAGES: string[] = [\n \"af\",\n \"am\",\n \"ar\",\n \"hy-AM\",\n \"az-AZ\",\n \"eu-ES\",\n \"be\",\n \"bn-BD\",\n \"bg\",\n \"my-MM\",\n \"ca\",\n \"zh-HK\",\n \"zh-CN\",\n \"zh-TW\",\n \"hr\",\n \"cs-CZ\",\n \"da-DK\",\n \"nl-NL\",\n \"en-AU\",\n \"en-CA\",\n \"en-IN\",\n \"en-SG\",\n \"en-GB\",\n \"en-US\",\n \"et\",\n \"fil\",\n \"fi-FI\",\n \"fr-FR\",\n \"fr-CA\",\n \"gl-ES\",\n \"ka-GE\",\n \"de-DE\",\n \"el-GR\",\n \"gu\",\n \"iw-IL\",\n \"hi-IN\",\n \"hu-HU\",\n \"is-IS\",\n \"id\",\n \"it-IT\",\n \"ja-JP\",\n \"kn-IN\",\n \"kk\",\n \"km-KH\",\n \"ko-KR\",\n \"ky-KG\",\n \"lo-LA\",\n \"lv\",\n \"lt\",\n \"mk-MK\",\n \"ms\",\n \"ms-MY\",\n \"ml-IN\",\n \"mr-IN\",\n \"mn-MN\",\n \"ne-NP\",\n \"no-NO\",\n \"fa\",\n \"pl-PL\",\n \"pt-BR\",\n \"pt-PT\",\n \"pa\",\n \"ro\",\n \"rm\",\n \"ru-RU\",\n \"sr\",\n \"si-LK\",\n \"sk\",\n \"sl\",\n \"es-419\",\n \"es-ES\",\n \"es-US\",\n \"sw\",\n \"sv-SE\",\n \"ta-IN\",\n \"te-IN\",\n \"th\",\n \"tr-TR\",\n \"uk\",\n \"ur\",\n \"vi\",\n \"zu\",\n];\n\nexport function isValidBcp47(tag: string): boolean {\n return GOOGLE_PLAY_LANGUAGES.includes(tag);\n}\n","import { stat } from \"node:fs/promises\";\nimport { extname } from \"node:path\";\n\nexport interface ImageValidationResult {\n valid: boolean;\n warnings: string[];\n errors: string[];\n}\n\n// Google Play image size limits\nconst IMAGE_SIZE_LIMITS: Record<string, { maxBytes: number; label: string }> = {\n icon: { maxBytes: 1024 * 1024, label: \"1 MB\" },\n featureGraphic: { maxBytes: 1024 * 1024, label: \"1 MB\" },\n tvBanner: { maxBytes: 1024 * 1024, label: \"1 MB\" },\n phoneScreenshots: { maxBytes: 8 * 1024 * 1024, label: \"8 MB\" },\n sevenInchScreenshots: { maxBytes: 8 * 1024 * 1024, label: \"8 MB\" },\n tenInchScreenshots: { maxBytes: 8 * 1024 * 1024, label: \"8 MB\" },\n tvScreenshots: { maxBytes: 8 * 1024 * 1024, label: \"8 MB\" },\n wearScreenshots: { maxBytes: 8 * 1024 * 1024, label: \"8 MB\" },\n};\n\nconst VALID_EXTENSIONS = new Set([\".png\", \".jpg\", \".jpeg\"]);\nconst LARGE_IMAGE_THRESHOLD = 2 * 1024 * 1024; // 2 MB\n\nexport async function validateImage(\n filePath: string,\n imageType?: string,\n): Promise<ImageValidationResult> {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n // Check extension\n const ext = extname(filePath).toLowerCase();\n if (!VALID_EXTENSIONS.has(ext)) {\n errors.push(`Unsupported image format \"${ext}\". Use PNG or JPEG.`);\n }\n\n // Check file exists and size\n let sizeBytes: number;\n try {\n const stats = await stat(filePath);\n sizeBytes = stats.size;\n\n if (sizeBytes === 0) {\n errors.push(\"Image file is empty (0 bytes)\");\n }\n } catch {\n errors.push(`Image file not found: ${filePath}`);\n return { valid: false, errors, warnings };\n }\n\n // Check size limits per image type\n if (imageType && sizeBytes > 0) {\n const limit = IMAGE_SIZE_LIMITS[imageType];\n if (limit && sizeBytes > limit.maxBytes) {\n errors.push(`Image exceeds ${limit.label} limit for ${imageType} (${formatSize(sizeBytes)})`);\n }\n }\n\n // Warn about large images\n if (sizeBytes > LARGE_IMAGE_THRESHOLD && errors.length === 0) {\n warnings.push(\n `Large image (${formatSize(sizeBytes)}). Consider optimizing for faster upload and better store performance.`,\n );\n }\n\n // PNG optimization warning\n if (ext === \".png\" && sizeBytes > 512 * 1024) {\n warnings.push(\n \"PNG file is over 512 KB. Consider compressing with tools like pngquant or optipng.\",\n );\n }\n\n return { valid: errors.length === 0, errors, warnings };\n}\n\nfunction formatSize(bytes: number): string {\n if (bytes >= 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n if (bytes >= 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${bytes} B`;\n}\n","import { readFile, writeFile, mkdir, readdir, stat } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { Listing } from \"@gpc-cli/api\";\n\nconst FILE_MAP: Record<string, keyof Omit<Listing, \"language\">> = {\n \"title.txt\": \"title\",\n \"short_description.txt\": \"shortDescription\",\n \"full_description.txt\": \"fullDescription\",\n \"video.txt\": \"video\",\n};\n\nconst FIELD_TO_FILE: Record<string, string> = Object.fromEntries(\n Object.entries(FILE_MAP).map(([file, field]) => [field, file]),\n);\n\nexport interface ListingDiff {\n language: string;\n field: string;\n local: string;\n remote: string;\n}\n\nasync function exists(path: string): Promise<boolean> {\n try {\n await stat(path);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function readListingsFromDir(dir: string): Promise<Listing[]> {\n const listings: Listing[] = [];\n\n if (!(await exists(dir))) return listings;\n\n const entries = await readdir(dir);\n // Validate directory names to prevent path traversal\n const SAFE_LANG = /^[a-zA-Z]{2,3}(-[a-zA-Z0-9]{2,8})*$/;\n for (const lang of entries) {\n if (!SAFE_LANG.test(lang)) continue;\n const langDir = join(dir, lang);\n const langStat = await stat(langDir);\n if (!langStat.isDirectory()) continue;\n\n const listing: Listing = {\n language: lang,\n title: \"\",\n shortDescription: \"\",\n fullDescription: \"\",\n };\n\n for (const [fileName, field] of Object.entries(FILE_MAP)) {\n const filePath = join(langDir, fileName);\n if (await exists(filePath)) {\n const content = await readFile(filePath, \"utf-8\");\n (listing as unknown as Record<string, string>)[field] = content.trimEnd();\n }\n }\n\n listings.push(listing);\n }\n\n return listings;\n}\n\nexport async function writeListingsToDir(dir: string, listings: Listing[]): Promise<void> {\n for (const listing of listings) {\n const langDir = join(dir, listing.language);\n await mkdir(langDir, { recursive: true });\n\n for (const [field, fileName] of Object.entries(FIELD_TO_FILE)) {\n const value = (listing as unknown as Record<string, string>)[field];\n if (value !== undefined && value !== \"\") {\n await writeFile(join(langDir, fileName), value + \"\\n\", \"utf-8\");\n }\n }\n }\n}\n\nexport function diffListings(local: Listing[], remote: Listing[]): ListingDiff[] {\n const diffs: ListingDiff[] = [];\n const remoteMap = new Map(remote.map((l) => [l.language, l]));\n const localMap = new Map(local.map((l) => [l.language, l]));\n\n // Check all local listings against remote\n for (const localListing of local) {\n const remoteListing = remoteMap.get(localListing.language);\n for (const [field] of Object.entries(FIELD_TO_FILE)) {\n const localVal = (\n (localListing as unknown as Record<string, string>)[field] ?? \"\"\n ).toString();\n const remoteVal = remoteListing\n ? ((remoteListing as unknown as Record<string, string>)[field] ?? \"\").toString()\n : \"\";\n if (localVal !== remoteVal) {\n diffs.push({\n language: localListing.language,\n field,\n local: localVal,\n remote: remoteVal,\n });\n }\n }\n }\n\n // Check for remote-only languages\n for (const remoteListing of remote) {\n if (!localMap.has(remoteListing.language)) {\n for (const [field] of Object.entries(FIELD_TO_FILE)) {\n const remoteVal = (\n (remoteListing as unknown as Record<string, string>)[field] ?? \"\"\n ).toString();\n if (remoteVal) {\n diffs.push({\n language: remoteListing.language,\n field,\n local: \"\",\n remote: remoteVal,\n });\n }\n }\n }\n }\n\n return diffs;\n}\n","import type {\n PlayApiClient,\n Listing,\n Image,\n ImageType,\n AppDetails,\n CountryAvailability,\n} from \"@gpc-cli/api\";\nimport { GpcError } from \"../errors.js\";\nimport { isValidBcp47 } from \"../utils/bcp47.js\";\nimport { validateImage } from \"../utils/image-validation.js\";\nimport { readListingsFromDir, writeListingsToDir, diffListings } from \"../utils/fastlane.js\";\nimport type { ListingDiff } from \"../utils/fastlane.js\";\n\nexport interface ListingsResult {\n listings: Listing[];\n}\n\nexport interface PushResult {\n updated: number;\n languages: string[];\n}\n\nexport interface DryRunResult {\n diffs: ListingDiff[];\n}\n\nfunction validateLanguage(lang: string): void {\n if (!isValidBcp47(lang)) {\n throw new GpcError(\n `Invalid language tag \"${lang}\". Must be a valid Google Play BCP 47 code.`,\n \"LISTING_INVALID_LANGUAGE\",\n 2,\n \"Use a valid BCP 47 language code such as en-US, de-DE, or ja-JP. See the Google Play Console for supported language codes.\",\n );\n }\n}\n\nexport async function getListings(\n client: PlayApiClient,\n packageName: string,\n language?: string,\n): Promise<Listing[]> {\n const edit = await client.edits.insert(packageName);\n try {\n let listings: Listing[];\n if (language) {\n validateLanguage(language);\n const listing = await client.listings.get(packageName, edit.id, language);\n listings = [listing];\n } else {\n listings = await client.listings.list(packageName, edit.id);\n }\n await client.edits.delete(packageName, edit.id);\n return listings;\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function updateListing(\n client: PlayApiClient,\n packageName: string,\n language: string,\n data: Partial<Omit<Listing, \"language\">>,\n): Promise<Listing> {\n validateLanguage(language);\n const edit = await client.edits.insert(packageName);\n try {\n const listing = await client.listings.patch(packageName, edit.id, language, data);\n await client.edits.validate(packageName, edit.id);\n await client.edits.commit(packageName, edit.id);\n return listing;\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function deleteListing(\n client: PlayApiClient,\n packageName: string,\n language: string,\n): Promise<void> {\n validateLanguage(language);\n const edit = await client.edits.insert(packageName);\n try {\n await client.listings.delete(packageName, edit.id, language);\n await client.edits.validate(packageName, edit.id);\n await client.edits.commit(packageName, edit.id);\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function pullListings(\n client: PlayApiClient,\n packageName: string,\n dir: string,\n): Promise<ListingsResult> {\n const edit = await client.edits.insert(packageName);\n try {\n const listings = await client.listings.list(packageName, edit.id);\n await client.edits.delete(packageName, edit.id);\n await writeListingsToDir(dir, listings);\n return { listings };\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function pushListings(\n client: PlayApiClient,\n packageName: string,\n dir: string,\n options?: { dryRun?: boolean },\n): Promise<PushResult | DryRunResult> {\n const localListings = await readListingsFromDir(dir);\n\n if (localListings.length === 0) {\n throw new GpcError(\n `No listings found in directory \"${dir}\"`,\n \"LISTING_DIR_EMPTY\",\n 1,\n `The directory must contain subdirectories named by language code (e.g., en-US/) with listing metadata files. Pull existing listings first with: gpc listings pull --dir \"${dir}\"`,\n );\n }\n\n // Validate all languages\n for (const listing of localListings) {\n validateLanguage(listing.language);\n }\n\n const edit = await client.edits.insert(packageName);\n try {\n if (options?.dryRun) {\n const remoteListings = await client.listings.list(packageName, edit.id);\n await client.edits.delete(packageName, edit.id);\n const diffs = diffListings(localListings, remoteListings);\n return { diffs };\n }\n\n for (const listing of localListings) {\n const { language, ...data } = listing;\n await client.listings.update(packageName, edit.id, language, data);\n }\n\n await client.edits.validate(packageName, edit.id);\n await client.edits.commit(packageName, edit.id);\n\n return {\n updated: localListings.length,\n languages: localListings.map((l) => l.language),\n };\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function listImages(\n client: PlayApiClient,\n packageName: string,\n language: string,\n imageType: ImageType,\n): Promise<Image[]> {\n validateLanguage(language);\n const edit = await client.edits.insert(packageName);\n try {\n const images = await client.images.list(packageName, edit.id, language, imageType);\n await client.edits.delete(packageName, edit.id);\n return images;\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function uploadImage(\n client: PlayApiClient,\n packageName: string,\n language: string,\n imageType: ImageType,\n filePath: string,\n): Promise<Image> {\n validateLanguage(language);\n\n // Validate image before upload\n const imageCheck = await validateImage(filePath, imageType);\n if (!imageCheck.valid) {\n throw new GpcError(\n `Image validation failed: ${imageCheck.errors.join(\"; \")}`,\n \"IMAGE_INVALID\",\n 2,\n \"Check image dimensions, file size, and format. Google Play requires PNG or JPEG images within specific size limits per image type.\",\n );\n }\n if (imageCheck.warnings.length > 0) {\n for (const w of imageCheck.warnings) {\n console.warn(`Warning: ${w}`);\n }\n }\n\n const edit = await client.edits.insert(packageName);\n try {\n const image = await client.images.upload(packageName, edit.id, language, imageType, filePath);\n await client.edits.validate(packageName, edit.id);\n await client.edits.commit(packageName, edit.id);\n return image;\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function deleteImage(\n client: PlayApiClient,\n packageName: string,\n language: string,\n imageType: ImageType,\n imageId: string,\n): Promise<void> {\n validateLanguage(language);\n const edit = await client.edits.insert(packageName);\n try {\n await client.images.delete(packageName, edit.id, language, imageType, imageId);\n await client.edits.validate(packageName, edit.id);\n await client.edits.commit(packageName, edit.id);\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function diffListingsCommand(\n client: PlayApiClient,\n packageName: string,\n dir: string,\n): Promise<ListingDiff[]> {\n const localListings = await readListingsFromDir(dir);\n\n const edit = await client.edits.insert(packageName);\n try {\n const remoteListings = await client.listings.list(packageName, edit.id);\n await client.edits.delete(packageName, edit.id);\n return diffListings(localListings, remoteListings);\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function getCountryAvailability(\n client: PlayApiClient,\n packageName: string,\n track: string,\n): Promise<CountryAvailability> {\n const edit = await client.edits.insert(packageName);\n try {\n const availability = await client.countryAvailability.get(packageName, edit.id, track);\n await client.edits.delete(packageName, edit.id);\n return availability;\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport interface ExportImagesOptions {\n lang?: string;\n type?: ImageType;\n}\n\nexport interface ExportImagesSummary {\n languages: number;\n images: number;\n totalSize: number;\n}\n\nconst ALL_IMAGE_TYPES: ImageType[] = [\n \"phoneScreenshots\",\n \"sevenInchScreenshots\",\n \"tenInchScreenshots\",\n \"tvScreenshots\",\n \"wearScreenshots\",\n \"icon\",\n \"featureGraphic\",\n \"tvBanner\",\n];\n\nexport async function exportImages(\n client: PlayApiClient,\n packageName: string,\n dir: string,\n options?: ExportImagesOptions,\n): Promise<ExportImagesSummary> {\n const { mkdir, writeFile } = await import(\"node:fs/promises\");\n const { join } = await import(\"node:path\");\n\n const edit = await client.edits.insert(packageName);\n try {\n // Determine languages\n let languages: string[];\n if (options?.lang) {\n validateLanguage(options.lang);\n languages = [options.lang];\n } else {\n const listings = await client.listings.list(packageName, edit.id);\n languages = listings.map((l) => l.language);\n }\n\n const imageTypes: ImageType[] = options?.type ? [options.type] : ALL_IMAGE_TYPES;\n\n let totalImages = 0;\n let totalSize = 0;\n\n // Collect all download tasks\n const tasks: Array<{ language: string; imageType: ImageType; url: string; index: number }> = [];\n\n for (const language of languages) {\n for (const imageType of imageTypes) {\n const images = await client.images.list(packageName, edit.id, language, imageType);\n for (let i = 0; i < images.length; i++) {\n const img = images[i];\n if (img && img.url) {\n tasks.push({ language, imageType, url: img.url, index: i + 1 });\n }\n }\n }\n }\n\n // Process downloads with concurrency limit of 5\n const concurrency = 5;\n for (let i = 0; i < tasks.length; i += concurrency) {\n const batch = tasks.slice(i, i + concurrency);\n const results = await Promise.all(\n batch.map(async (task) => {\n const dirPath = join(dir, task.language, task.imageType);\n await mkdir(dirPath, { recursive: true });\n\n const response = await fetch(task.url);\n const buffer = Buffer.from(await response.arrayBuffer());\n const filePath = join(dirPath, `${task.index}.png`);\n await writeFile(filePath, buffer);\n\n return buffer.length;\n }),\n );\n\n for (const size of results) {\n totalImages++;\n totalSize += size;\n }\n }\n\n await client.edits.delete(packageName, edit.id);\n\n return {\n languages: languages.length,\n images: totalImages,\n totalSize,\n };\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function updateAppDetails(\n client: PlayApiClient,\n packageName: string,\n details: Partial<AppDetails>,\n): Promise<AppDetails> {\n const edit = await client.edits.insert(packageName);\n try {\n const result = await client.details.patch(packageName, edit.id, details);\n await client.edits.validate(packageName, edit.id);\n await client.edits.commit(packageName, edit.id);\n return result;\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n","import { readdir, readFile, writeFile, mkdir, access } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport interface FastlaneDetection {\n hasFastfile: boolean;\n hasAppfile: boolean;\n hasMetadata: boolean;\n hasGemfile: boolean;\n packageName?: string;\n jsonKeyPath?: string;\n lanes: FastlaneLane[];\n metadataLanguages: string[];\n parseWarnings: string[];\n}\n\nexport interface FastlaneLane {\n name: string;\n actions: string[];\n gpcEquivalent?: string;\n}\n\nexport interface MigrationResult {\n config: Record<string, unknown>;\n checklist: string[];\n warnings: string[];\n}\n\n// Ruby constructs that confuse the lane-end regex\nconst COMPLEX_RUBY_RE = /\\b(begin|rescue|ensure|if |unless |case |while |until |for )\\b/;\n\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function detectFastlane(cwd: string): Promise<FastlaneDetection> {\n const result: FastlaneDetection = {\n hasFastfile: false,\n hasAppfile: false,\n hasMetadata: false,\n hasGemfile: false,\n lanes: [],\n metadataLanguages: [],\n parseWarnings: [],\n };\n\n // Check for fastlane directory or root-level files\n const fastlaneDir = join(cwd, \"fastlane\");\n const hasFastlaneDir = await fileExists(fastlaneDir);\n\n const fastfilePath = hasFastlaneDir\n ? join(fastlaneDir, \"Fastfile\")\n : join(cwd, \"Fastfile\");\n const appfilePath = hasFastlaneDir\n ? join(fastlaneDir, \"Appfile\")\n : join(cwd, \"Appfile\");\n\n result.hasFastfile = await fileExists(fastfilePath);\n result.hasAppfile = await fileExists(appfilePath);\n result.hasGemfile = await fileExists(join(cwd, \"Gemfile\"));\n\n // Check for metadata directory\n const metadataDir = hasFastlaneDir\n ? join(fastlaneDir, \"metadata\", \"android\")\n : join(cwd, \"metadata\", \"android\");\n\n result.hasMetadata = await fileExists(metadataDir);\n\n if (result.hasMetadata) {\n try {\n const entries = await readdir(metadataDir, { withFileTypes: true });\n result.metadataLanguages = entries\n .filter((e) => e.isDirectory())\n .map((e) => e.name);\n } catch {\n result.parseWarnings.push(\"Could not read metadata directory — check permissions\");\n }\n }\n\n // Parse Fastfile if present\n if (result.hasFastfile) {\n try {\n const content = await readFile(fastfilePath, \"utf-8\");\n result.lanes = parseFastfile(content);\n\n // Warn if the Fastfile contains complex Ruby that may have been misread\n if (COMPLEX_RUBY_RE.test(content)) {\n result.parseWarnings.push(\n \"Fastfile contains complex Ruby constructs (begin/rescue/if/unless/case). \" +\n \"Lane detection may be incomplete — review MIGRATION.md and adjust manually.\",\n );\n }\n } catch {\n result.parseWarnings.push(\"Could not read Fastfile — check permissions\");\n }\n }\n\n // Parse Appfile if present\n if (result.hasAppfile) {\n try {\n const content = await readFile(appfilePath, \"utf-8\");\n const parsed = parseAppfile(content);\n result.packageName = parsed.packageName;\n result.jsonKeyPath = parsed.jsonKeyPath;\n } catch {\n result.parseWarnings.push(\"Could not read Appfile — check permissions\");\n }\n }\n\n return result;\n}\n\nexport function parseFastfile(content: string): FastlaneLane[] {\n const lanes: FastlaneLane[] = [];\n // Match lane blocks: lane :name do ... end\n const laneRegex = /lane\\s+:(\\w+)\\s+do([\\s\\S]*?)(?=\\bend\\b)/g;\n let match: RegExpExecArray | null;\n\n while ((match = laneRegex.exec(content)) !== null) {\n const name = match[1] ?? \"\";\n const body = match[2] ?? \"\";\n const actions: string[] = [];\n\n // Extract action calls\n const actionRegex =\n /\\b(supply|upload_to_play_store|capture_android_screenshots|deliver|gradle)\\b/g;\n let actionMatch: RegExpExecArray | null;\n while ((actionMatch = actionRegex.exec(body)) !== null) {\n const action = actionMatch[1] ?? \"\";\n if (!actions.includes(action)) {\n actions.push(action);\n }\n }\n\n // Determine GPC equivalent\n const gpcEquivalent = mapLaneToGpc(name, actions, body);\n\n lanes.push({ name, actions, gpcEquivalent });\n }\n\n return lanes;\n}\n\nfunction mapLaneToGpc(name: string, actions: string[], body: string): string | undefined {\n if (actions.includes(\"upload_to_play_store\") || actions.includes(\"supply\")) {\n const trackMatch = body.match(/track\\s*:\\s*[\"'](\\w+)[\"']/);\n const rolloutMatch = body.match(/rollout\\s*:\\s*[\"']?([\\d.]+)[\"']?/);\n\n if (rolloutMatch) {\n const raw = parseFloat(rolloutMatch[1] ?? \"0\");\n // Fastlane uses 0.0–1.0; convert to whole percentage for gpc\n const pct = raw > 1 ? Math.round(raw) : Math.round(raw * 100);\n return `gpc releases upload --rollout ${pct}${trackMatch ? ` --track ${trackMatch[1]}` : \"\"}`;\n }\n\n if (trackMatch) {\n return `gpc releases upload --track ${trackMatch[1]}`;\n }\n\n // Metadata-only supply\n if (body.match(/skip_upload_apk\\s*:\\s*true/) || body.match(/skip_upload_aab\\s*:\\s*true/)) {\n return \"gpc listings push\";\n }\n\n return \"gpc releases upload\";\n }\n\n if (actions.includes(\"capture_android_screenshots\")) {\n return undefined; // No equivalent\n }\n\n return undefined;\n}\n\nexport function parseAppfile(content: string): { packageName?: string; jsonKeyPath?: string } {\n const result: { packageName?: string; jsonKeyPath?: string } = {};\n\n // Match package_name(\"com.example.app\") or package_name \"com.example.app\"\n const pkgMatch = content.match(/package_name\\s*\\(?\\s*[\"']([^\"']+)[\"']\\s*\\)?/);\n if (pkgMatch) {\n result.packageName = pkgMatch[1];\n }\n\n // Match json_key_file(\"path/to/key.json\") or json_key_file \"path/to/key.json\"\n const keyMatch = content.match(/json_key_file\\s*\\(?\\s*[\"']([^\"']+)[\"']\\s*\\)?/);\n if (keyMatch) {\n result.jsonKeyPath = keyMatch[1];\n }\n\n return result;\n}\n\nexport function generateMigrationPlan(detection: FastlaneDetection): MigrationResult {\n const config: Record<string, unknown> = {};\n const checklist: string[] = [];\n const warnings: string[] = [...detection.parseWarnings];\n\n // Set package name if detected\n if (detection.packageName) {\n config[\"app\"] = detection.packageName;\n } else {\n checklist.push(\"Set your package name: gpc config set app <package-name>\");\n }\n\n // Set auth config if key path detected\n if (detection.jsonKeyPath) {\n config[\"auth\"] = { serviceAccount: detection.jsonKeyPath };\n } else {\n checklist.push(\"Configure authentication: gpc auth login\");\n }\n\n // Lane mappings\n for (const lane of detection.lanes) {\n if (lane.gpcEquivalent) {\n checklist.push(\n `Replace Fastlane lane \"${lane.name}\" with: ${lane.gpcEquivalent} <your.aab>`,\n );\n }\n\n if (lane.actions.includes(\"capture_android_screenshots\")) {\n warnings.push(\n `Lane \"${lane.name}\" uses capture_android_screenshots which has no GPC equivalent. ` +\n \"Use a separate screenshot tool or check gpc plugins list for community plugins.\",\n );\n }\n\n // Lanes with no known action and no GPC equivalent\n if (\n lane.actions.length === 0 ||\n (lane.gpcEquivalent === undefined && !lane.actions.includes(\"capture_android_screenshots\"))\n ) {\n warnings.push(\n `Lane \"${lane.name}\" has no automatic GPC equivalent. ` +\n \"Check \\`gpc plugins list\\` or the plugin SDK docs to build a custom command.\",\n );\n }\n }\n\n // Metadata migration\n if (detection.hasMetadata && detection.metadataLanguages.length > 0) {\n const langs = detection.metadataLanguages.slice(0, 3).join(\", \");\n const more =\n detection.metadataLanguages.length > 3\n ? ` (+${detection.metadataLanguages.length - 3} more)`\n : \"\";\n checklist.push(\n `Pull current metadata for ${detection.metadataLanguages.length} language(s) (${langs}${more}): gpc listings pull --dir fastlane/metadata/android`,\n );\n checklist.push(\n \"Review pulled metadata, then push back: gpc listings push --dir fastlane/metadata/android\",\n );\n }\n\n // General checklist items\n checklist.push(\"Run gpc doctor to verify your setup\");\n checklist.push(\"Test each command with --dry-run before making real changes\");\n\n if (detection.hasGemfile) {\n checklist.push(\"Remove Fastlane from your Gemfile once migration is complete\");\n }\n\n // CI/CD reminder\n if (\n detection.lanes.some(\n (l) => l.actions.includes(\"supply\") || l.actions.includes(\"upload_to_play_store\"),\n )\n ) {\n checklist.push(\"Update CI/CD pipelines to call gpc commands instead of Fastlane lanes\");\n }\n\n return { config, checklist, warnings };\n}\n\nexport async function writeMigrationOutput(\n result: MigrationResult,\n dir: string,\n): Promise<string[]> {\n await mkdir(dir, { recursive: true });\n const files: string[] = [];\n\n // Write .gpcrc.json only if we have something meaningful to put in it\n if (Object.keys(result.config).length > 0) {\n const configPath = join(dir, \".gpcrc.json\");\n await writeFile(configPath, JSON.stringify(result.config, null, 2) + \"\\n\", \"utf-8\");\n files.push(configPath);\n }\n\n // Write MIGRATION.md\n const migrationPath = join(dir, \"MIGRATION.md\");\n const lines: string[] = [\n \"# Fastlane to GPC Migration\",\n \"\",\n \"Generated by `gpc migrate fastlane`. Review and adjust before applying.\",\n \"\",\n \"## Migration Checklist\",\n \"\",\n ];\n\n for (const item of result.checklist) {\n lines.push(`- [ ] ${item}`);\n }\n\n if (result.warnings.length > 0) {\n lines.push(\"\");\n lines.push(\"## Warnings\");\n lines.push(\"\");\n for (const warning of result.warnings) {\n lines.push(`> ⚠ ${warning}`);\n }\n }\n\n lines.push(\"\");\n lines.push(\"## Quick Reference\");\n lines.push(\"\");\n lines.push(\"| Fastlane | GPC |\");\n lines.push(\"|----------|-----|\");\n lines.push(\"| `fastlane supply` | `gpc releases upload` / `gpc listings push` |\");\n lines.push(\"| `upload_to_play_store` | `gpc releases upload` |\");\n lines.push(\"| `supply(track: \\\"internal\\\")` | `gpc releases upload --track internal` |\");\n lines.push(\"| `supply(rollout: \\\"0.1\\\")` | `gpc releases upload --rollout 10` |\");\n lines.push(\"| `supply(skip_upload_aab: true)` | `gpc listings push` |\");\n lines.push(\"| `capture_android_screenshots` | No equivalent — use separate tool |\");\n lines.push(\"\");\n lines.push(\"See the full migration guide: https://yasserstudio.github.io/gpc/migration/from-fastlane\");\n lines.push(\"\");\n\n await writeFile(migrationPath, lines.join(\"\\n\"), \"utf-8\");\n files.push(migrationPath);\n\n return files;\n}\n","import { GpcError } from \"../errors.js\";\nimport { isValidBcp47 } from \"./bcp47.js\";\n\nconst PACKAGE_NAME_RE = /^[a-zA-Z][a-zA-Z0-9_]*(\\.[a-zA-Z][a-zA-Z0-9_]*){1,}$/;\nconst SKU_RE = /^[a-zA-Z0-9._]+$/;\nconst TRACK_NAMES = [\"internal\", \"alpha\", \"beta\", \"production\"];\nconst CUSTOM_TRACK_RE = /^[a-zA-Z0-9\\-_]+$/;\n\nexport function validatePackageName(name: string): void {\n if (!name || !PACKAGE_NAME_RE.test(name)) {\n throw new GpcError(\n `Invalid package name: \"${name}\"`,\n \"INVALID_PACKAGE_NAME\",\n 2,\n \"Package name must be a valid Android application ID (e.g., com.example.myapp)\",\n );\n }\n}\n\nexport function validateVersionCode(code: string | number): void {\n const num = typeof code === \"string\" ? parseInt(code, 10) : code;\n if (!Number.isInteger(num) || num < 1) {\n throw new GpcError(\n `Invalid version code: \"${code}\"`,\n \"INVALID_VERSION_CODE\",\n 2,\n \"Version code must be a positive integer (e.g., 142)\",\n );\n }\n}\n\nexport function validateLanguageCode(code: string): void {\n if (!code || !isValidBcp47(code)) {\n throw new GpcError(\n `Invalid language code: \"${code}\"`,\n \"INVALID_LANGUAGE_CODE\",\n 2,\n \"Language code must be a valid BCP-47 tag supported by Google Play (e.g., en-US, ja-JP, fr-FR)\",\n );\n }\n}\n\nexport function validateTrackName(name: string): void {\n if (!name) {\n throw new GpcError(\n \"Track name is required\",\n \"INVALID_TRACK_NAME\",\n 2,\n \"Specify a track: internal, alpha, beta, production, or a custom track name\",\n );\n }\n if (!TRACK_NAMES.includes(name) && !CUSTOM_TRACK_RE.test(name)) {\n throw new GpcError(\n `Invalid track name: \"${name}\"`,\n \"INVALID_TRACK_NAME\",\n 2,\n `Valid tracks: ${TRACK_NAMES.join(\", \")}, or a custom track matching [a-zA-Z0-9-_]+`,\n );\n }\n}\n\nexport function validateSku(sku: string): void {\n if (!sku || !SKU_RE.test(sku)) {\n throw new GpcError(\n `Invalid product ID (SKU): \"${sku}\"`,\n \"INVALID_SKU\",\n 2,\n \"Product ID must contain only letters, numbers, dots, and underscores (e.g., premium_upgrade)\",\n );\n }\n}\n","import { readdir, readFile, stat } from \"node:fs/promises\";\nimport { extname, basename, join } from \"node:path\";\nimport { GpcError } from \"../errors.js\";\n\nexport interface ReleaseNote {\n language: string;\n text: string;\n}\n\nexport interface ReleaseNotesValidation {\n valid: boolean;\n errors: string[];\n warnings: string[];\n}\n\nconst MAX_NOTES_LENGTH = 500;\n\nexport async function readReleaseNotesFromDir(dir: string): Promise<ReleaseNote[]> {\n let entries: string[];\n try {\n entries = await readdir(dir);\n } catch {\n throw new GpcError(\n `Release notes directory not found: ${dir}`,\n \"RELEASE_NOTES_DIR_NOT_FOUND\",\n 1,\n `Create the directory and add .txt files named by language code (e.g., en-US.txt). Path: ${dir}`,\n );\n }\n\n const notes: ReleaseNote[] = [];\n\n for (const entry of entries) {\n if (extname(entry) !== \".txt\") continue;\n\n const language = basename(entry, \".txt\");\n const filePath = join(dir, entry);\n\n const stats = await stat(filePath);\n if (!stats.isFile()) continue;\n\n const text = (await readFile(filePath, \"utf-8\")).trim();\n if (text.length === 0) continue;\n\n notes.push({ language, text });\n }\n\n return notes;\n}\n\nexport function validateReleaseNotes(notes: ReleaseNote[]): ReleaseNotesValidation {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n const seen = new Set<string>();\n for (const note of notes) {\n if (seen.has(note.language)) {\n errors.push(`Duplicate language code: ${note.language}`);\n }\n seen.add(note.language);\n\n if (note.text.length > MAX_NOTES_LENGTH) {\n errors.push(\n `Release notes for \"${note.language}\" exceed ${MAX_NOTES_LENGTH} chars (${note.text.length} chars)`,\n );\n }\n }\n\n return { valid: errors.length === 0, errors, warnings };\n}\n","import { stat } from \"node:fs/promises\";\nimport { validateUploadFile } from \"../utils/file-validation.js\";\nimport { readReleaseNotesFromDir, validateReleaseNotes } from \"../utils/release-notes.js\";\n\nexport interface ValidateOptions {\n filePath: string;\n mappingFile?: string;\n track?: string;\n notes?: { language: string; text: string }[];\n notesDir?: string;\n}\n\nexport interface ValidateCheck {\n name: string;\n passed: boolean;\n message: string;\n}\n\nexport interface ValidateResult {\n valid: boolean;\n checks: ValidateCheck[];\n warnings: string[];\n}\n\nconst STANDARD_TRACKS = new Set([\n \"internal\",\n \"alpha\",\n \"beta\",\n \"production\",\n // Form factor tracks\n \"wear:internal\",\n \"wear:alpha\",\n \"wear:beta\",\n \"wear:production\",\n \"automotive:internal\",\n \"automotive:alpha\",\n \"automotive:beta\",\n \"automotive:production\",\n \"tv:internal\",\n \"tv:alpha\",\n \"tv:beta\",\n \"tv:production\",\n \"android_xr:internal\",\n \"android_xr:alpha\",\n \"android_xr:beta\",\n \"android_xr:production\",\n]);\nconst TRACK_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9_:-]*$/;\n\nexport async function validatePreSubmission(options: ValidateOptions): Promise<ValidateResult> {\n const checks: ValidateCheck[] = [];\n\n const resultWarnings: string[] = [];\n\n // 1. File validation\n const fileResult = await validateUploadFile(options.filePath);\n checks.push({\n name: \"file\",\n passed: fileResult.valid,\n message: fileResult.valid\n ? `Valid ${fileResult.fileType.toUpperCase()} (${formatSize(fileResult.sizeBytes)})`\n : fileResult.errors.join(\"; \"),\n });\n // Surface file validation warnings (e.g. large file upload time notice)\n for (const w of fileResult.warnings) {\n resultWarnings.push(w);\n }\n\n // 2. Mapping file\n if (options.mappingFile) {\n try {\n const stats = await stat(options.mappingFile);\n checks.push({\n name: \"mapping\",\n passed: stats.isFile(),\n message: stats.isFile()\n ? `Mapping file found (${formatSize(stats.size)})`\n : \"Mapping path is not a file\",\n });\n } catch {\n checks.push({\n name: \"mapping\",\n passed: false,\n message: `Mapping file not found: ${options.mappingFile}`,\n });\n }\n }\n\n // 3. Track validation\n if (options.track) {\n const isValid = STANDARD_TRACKS.has(options.track) || TRACK_PATTERN.test(options.track);\n checks.push({\n name: \"track\",\n passed: isValid,\n message: isValid\n ? `Track \"${options.track}\" is valid`\n : `Invalid track name \"${options.track}\". Use: internal, alpha, beta, production, or a custom track ID`,\n });\n }\n\n // 4. Release notes validation\n let resolvedNotes = options.notes;\n if (options.notesDir) {\n try {\n resolvedNotes = await readReleaseNotesFromDir(options.notesDir);\n checks.push({\n name: \"notes-dir\",\n passed: true,\n message: `Read release notes for ${resolvedNotes.length} language(s)`,\n });\n } catch (err) {\n checks.push({\n name: \"notes-dir\",\n passed: false,\n message: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n if (resolvedNotes && resolvedNotes.length > 0) {\n const notesResult = validateReleaseNotes(resolvedNotes);\n checks.push({\n name: \"notes\",\n passed: notesResult.valid,\n message: notesResult.valid\n ? `Release notes valid (${resolvedNotes.length} language(s))`\n : notesResult.errors.join(\"; \"),\n });\n }\n\n return {\n valid: checks.every((c) => c.passed),\n checks,\n warnings: resultWarnings,\n };\n}\n\nfunction formatSize(bytes: number): string {\n if (bytes >= 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n if (bytes >= 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${bytes} B`;\n}\n","import type { PlayApiClient } from \"@gpc-cli/api\";\nimport { uploadRelease } from \"./releases.js\";\nimport type { UploadResult, DryRunUploadResult } from \"./releases.js\";\nimport { validatePreSubmission } from \"./validate.js\";\nimport type { ValidateResult } from \"./validate.js\";\nimport { readReleaseNotesFromDir } from \"../utils/release-notes.js\";\n\nexport interface PublishOptions {\n track?: string;\n rolloutPercent?: number;\n notes?: string;\n notesDir?: string;\n releaseName?: string;\n mappingFile?: string;\n dryRun?: boolean;\n}\n\nexport interface PublishResult {\n validation: ValidateResult;\n upload?: UploadResult;\n}\n\nexport interface DryRunPublishResult {\n dryRun: true;\n validation: ValidateResult;\n upload: DryRunUploadResult;\n}\n\nexport async function publish(\n client: PlayApiClient,\n packageName: string,\n filePath: string,\n options: PublishOptions,\n): Promise<PublishResult | DryRunPublishResult> {\n // Resolve release notes\n let releaseNotes: { language: string; text: string }[] | undefined;\n if (options.notesDir) {\n releaseNotes = await readReleaseNotesFromDir(options.notesDir);\n } else if (options.notes) {\n releaseNotes = [{ language: \"en-US\", text: options.notes }];\n }\n\n // Validate\n const validation = await validatePreSubmission({\n filePath,\n mappingFile: options.mappingFile,\n track: options.track || \"internal\",\n notes: releaseNotes,\n });\n\n if (options.dryRun) {\n const upload = await uploadRelease(client, packageName, filePath, {\n track: options.track || \"internal\",\n userFraction: options.rolloutPercent ? options.rolloutPercent / 100 : undefined,\n dryRun: true,\n }) as DryRunUploadResult;\n\n return { dryRun: true, validation, upload };\n }\n\n if (!validation.valid) {\n return { validation };\n }\n\n // Upload\n const upload = await uploadRelease(client, packageName, filePath, {\n track: options.track || \"internal\",\n userFraction: options.rolloutPercent ? options.rolloutPercent / 100 : undefined,\n releaseNotes,\n releaseName: options.releaseName,\n mappingFile: options.mappingFile,\n });\n\n return { validation, upload } as PublishResult;\n}\n","import type { PlayApiClient, Review, ReviewsListOptions, ReviewReplyResponse } from \"@gpc-cli/api\";\nimport { paginateAll } from \"@gpc-cli/api\";\nimport { GpcError } from \"../errors.js\";\n\nexport interface ReviewsFilterOptions {\n stars?: number;\n language?: string;\n since?: string;\n translationLanguage?: string;\n maxResults?: number;\n limit?: number;\n nextPage?: string;\n}\n\nexport interface ReviewExportOptions extends ReviewsFilterOptions {\n format?: \"json\" | \"csv\";\n}\n\nexport async function listReviews(\n client: PlayApiClient,\n packageName: string,\n options?: ReviewsFilterOptions,\n): Promise<Review[]> {\n const apiOptions: ReviewsListOptions = {};\n if (options?.translationLanguage) apiOptions.translationLanguage = options.translationLanguage;\n if (options?.maxResults) apiOptions.maxResults = options.maxResults;\n\n const response = await client.reviews.list(packageName, apiOptions);\n let reviews = response.reviews || [];\n\n // Client-side filters\n if (options?.stars !== undefined) {\n reviews = reviews.filter((r) => {\n const userComment = r.comments?.[0]?.userComment;\n return userComment && userComment.starRating === options.stars;\n });\n }\n\n if (options?.language) {\n reviews = reviews.filter((r) => {\n const userComment = r.comments?.[0]?.userComment;\n return userComment?.reviewerLanguage === options.language;\n });\n }\n\n if (options?.since) {\n const sinceTime = new Date(options.since).getTime() / 1000;\n reviews = reviews.filter((r) => {\n const userComment = r.comments?.[0]?.userComment;\n return userComment && Number(userComment.lastModified.seconds) >= sinceTime;\n });\n }\n\n return reviews;\n}\n\nexport async function getReview(\n client: PlayApiClient,\n packageName: string,\n reviewId: string,\n translationLanguage?: string,\n): Promise<Review> {\n return client.reviews.get(packageName, reviewId, translationLanguage);\n}\n\nconst MAX_REPLY_LENGTH = 350;\n\nexport async function replyToReview(\n client: PlayApiClient,\n packageName: string,\n reviewId: string,\n replyText: string,\n): Promise<ReviewReplyResponse> {\n if (replyText.length > MAX_REPLY_LENGTH) {\n throw new GpcError(\n `Reply text exceeds ${MAX_REPLY_LENGTH} characters (${replyText.length}). Google Play limits replies to ${MAX_REPLY_LENGTH} characters.`,\n \"REVIEW_REPLY_TOO_LONG\",\n 2,\n `Shorten your reply to ${MAX_REPLY_LENGTH} characters or fewer. Current length: ${replyText.length}.`,\n );\n }\n if (replyText.length === 0) {\n throw new GpcError(\n \"Reply text cannot be empty.\",\n \"REVIEW_REPLY_EMPTY\",\n 2,\n \"Provide a non-empty reply text with --text or -t.\",\n );\n }\n return client.reviews.reply(packageName, reviewId, replyText);\n}\n\nexport async function exportReviews(\n client: PlayApiClient,\n packageName: string,\n options?: ReviewExportOptions,\n): Promise<string> {\n const { items: allReviews } = await paginateAll<Review>(async (pageToken) => {\n const apiOptions: ReviewsListOptions = { token: pageToken };\n if (options?.translationLanguage) apiOptions.translationLanguage = options.translationLanguage;\n const response = await client.reviews.list(packageName, apiOptions);\n return {\n items: response.reviews || [],\n nextPageToken: response.tokenPagination?.nextPageToken,\n };\n });\n\n let filtered = allReviews;\n\n if (options?.stars !== undefined) {\n filtered = filtered.filter((r) => {\n const uc = r.comments?.[0]?.userComment;\n return uc && uc.starRating === options.stars;\n });\n }\n\n if (options?.language) {\n filtered = filtered.filter((r) => {\n const uc = r.comments?.[0]?.userComment;\n return uc?.reviewerLanguage === options.language;\n });\n }\n\n if (options?.since) {\n const sinceTime = new Date(options.since).getTime() / 1000;\n filtered = filtered.filter((r) => {\n const uc = r.comments?.[0]?.userComment;\n return uc && Number(uc.lastModified.seconds) >= sinceTime;\n });\n }\n\n if (options?.format === \"csv\") {\n return reviewsToCsv(filtered);\n }\n\n return JSON.stringify(filtered, null, 2);\n}\n\nfunction reviewsToCsv(reviews: Review[]): string {\n const header = \"reviewId,authorName,starRating,text,language,date,device,appVersionName\";\n const rows = reviews.map((r) => {\n const uc = r.comments?.[0]?.userComment;\n const fields = [\n r.reviewId,\n csvEscape(r.authorName),\n uc?.starRating ?? \"\",\n csvEscape(uc?.text ?? \"\"),\n uc?.reviewerLanguage ?? \"\",\n uc ? new Date(Number(uc.lastModified.seconds) * 1000).toISOString() : \"\",\n csvEscape(uc?.device ?? \"\"),\n csvEscape(uc?.appVersionName ?? \"\"),\n ];\n return fields.join(\",\");\n });\n return [header, ...rows].join(\"\\n\");\n}\n\nfunction csvEscape(value: string): string {\n if (value.includes(\",\") || value.includes('\"') || value.includes(\"\\n\")) {\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\n }\n return value;\n}\n","import type {\n ReportingApiClient,\n VitalsMetricSet,\n MetricSetQuery,\n MetricSetResponse,\n MetricRow,\n AnomalyDetectionResponse,\n ErrorIssuesResponse,\n ReportingDimension,\n ReportingAggregation,\n} from \"@gpc-cli/api\";\n\nexport interface VitalsQueryOptions {\n dimension?: ReportingDimension;\n days?: number;\n aggregation?: ReportingAggregation;\n}\n\nexport interface VitalsOverview {\n crashRate?: MetricRow[];\n anrRate?: MetricRow[];\n slowStartRate?: MetricRow[];\n slowRenderingRate?: MetricRow[];\n excessiveWakeupRate?: MetricRow[];\n stuckWakelockRate?: MetricRow[];\n}\n\nexport interface ThresholdResult {\n breached: boolean;\n value: number | undefined;\n threshold: number;\n}\n\nconst METRIC_SET_METRICS: Record<VitalsMetricSet, string[]> = {\n crashRateMetricSet: [\"crashRate\", \"userPerceivedCrashRate\", \"distinctUsers\"],\n anrRateMetricSet: [\"anrRate\", \"userPerceivedAnrRate\", \"distinctUsers\"],\n slowStartRateMetricSet: [\"slowStartRate\", \"distinctUsers\"],\n slowRenderingRateMetricSet: [\"slowRenderingRate\", \"distinctUsers\"],\n excessiveWakeupRateMetricSet: [\"excessiveWakeupRate\", \"distinctUsers\"],\n stuckBackgroundWakelockRateMetricSet: [\"stuckBackgroundWakelockRate\", \"distinctUsers\"],\n errorCountMetricSet: [\"errorReportCount\", \"distinctUsers\"],\n};\n\nfunction buildQuery(metricSet: VitalsMetricSet, options?: VitalsQueryOptions): MetricSetQuery {\n const metrics = METRIC_SET_METRICS[metricSet] ?? [\"errorReportCount\", \"distinctUsers\"];\n\n const days = options?.days ?? 30;\n const DAY_MS = 24 * 60 * 60 * 1000;\n const end = new Date(Date.now() - DAY_MS); // API data lags ~1 day; cap to yesterday\n const start = new Date(Date.now() - DAY_MS - days * DAY_MS);\n\n const query: MetricSetQuery = {\n metrics,\n timelineSpec: {\n aggregationPeriod: options?.aggregation ?? \"DAILY\",\n startTime: {\n year: start.getUTCFullYear(),\n month: start.getUTCMonth() + 1,\n day: start.getUTCDate(),\n },\n endTime: {\n year: end.getUTCFullYear(),\n month: end.getUTCMonth() + 1,\n day: end.getUTCDate(),\n },\n },\n };\n\n if (options?.dimension) {\n query.dimensions = [options.dimension];\n }\n\n return query;\n}\n\nasync function queryMetric(\n reporting: ReportingApiClient,\n packageName: string,\n metricSet: VitalsMetricSet,\n options?: VitalsQueryOptions,\n): Promise<MetricSetResponse> {\n const query = buildQuery(metricSet, options);\n return reporting.queryMetricSet(packageName, metricSet, query);\n}\n\nexport async function getVitalsOverview(\n reporting: ReportingApiClient,\n packageName: string,\n): Promise<VitalsOverview> {\n const metricSets: [VitalsMetricSet, keyof VitalsOverview][] = [\n [\"crashRateMetricSet\", \"crashRate\"],\n [\"anrRateMetricSet\", \"anrRate\"],\n [\"slowStartRateMetricSet\", \"slowStartRate\"],\n [\"slowRenderingRateMetricSet\", \"slowRenderingRate\"],\n [\"excessiveWakeupRateMetricSet\", \"excessiveWakeupRate\"],\n [\"stuckBackgroundWakelockRateMetricSet\", \"stuckWakelockRate\"],\n ];\n\n const results = await Promise.allSettled(\n metricSets.map(([metric]) =>\n reporting.queryMetricSet(packageName, metric, buildQuery(metric)),\n ),\n );\n\n const overview: VitalsOverview = {};\n for (let i = 0; i < metricSets.length; i++) {\n const entry = metricSets[i];\n if (!entry) continue;\n const key = entry[1];\n const result = results[i];\n if (!result) continue;\n if (result.status === \"fulfilled\") {\n overview[key] = result.value.rows || [];\n }\n }\n\n return overview;\n}\n\nexport async function getVitalsCrashes(\n reporting: ReportingApiClient,\n packageName: string,\n options?: VitalsQueryOptions,\n): Promise<MetricSetResponse> {\n return queryMetric(reporting, packageName, \"crashRateMetricSet\", options);\n}\n\nexport async function getVitalsAnr(\n reporting: ReportingApiClient,\n packageName: string,\n options?: VitalsQueryOptions,\n): Promise<MetricSetResponse> {\n return queryMetric(reporting, packageName, \"anrRateMetricSet\", options);\n}\n\nexport async function getVitalsStartup(\n reporting: ReportingApiClient,\n packageName: string,\n options?: VitalsQueryOptions,\n): Promise<MetricSetResponse> {\n return queryMetric(reporting, packageName, \"slowStartRateMetricSet\", options);\n}\n\nexport async function getVitalsRendering(\n reporting: ReportingApiClient,\n packageName: string,\n options?: VitalsQueryOptions,\n): Promise<MetricSetResponse> {\n return queryMetric(reporting, packageName, \"slowRenderingRateMetricSet\", options);\n}\n\nexport async function getVitalsBattery(\n reporting: ReportingApiClient,\n packageName: string,\n options?: VitalsQueryOptions,\n): Promise<MetricSetResponse> {\n return queryMetric(reporting, packageName, \"excessiveWakeupRateMetricSet\", options);\n}\n\nexport async function getVitalsMemory(\n reporting: ReportingApiClient,\n packageName: string,\n options?: VitalsQueryOptions,\n): Promise<MetricSetResponse> {\n return queryMetric(reporting, packageName, \"stuckBackgroundWakelockRateMetricSet\", options);\n}\n\nexport async function getVitalsAnomalies(\n reporting: ReportingApiClient,\n packageName: string,\n): Promise<AnomalyDetectionResponse> {\n return reporting.getAnomalies(packageName);\n}\n\nexport async function searchVitalsErrors(\n reporting: ReportingApiClient,\n packageName: string,\n options?: { filter?: string; maxResults?: number },\n): Promise<ErrorIssuesResponse> {\n return reporting.searchErrorIssues(packageName, options?.filter, options?.maxResults);\n}\n\nexport interface VitalsTrendComparison {\n metric: string;\n current: number | undefined;\n previous: number | undefined;\n changePercent: number | undefined;\n direction: \"improved\" | \"degraded\" | \"unchanged\" | \"unknown\";\n}\n\nexport async function compareVitalsTrend(\n reporting: ReportingApiClient,\n packageName: string,\n metricSet: VitalsMetricSet,\n days: number = 7,\n): Promise<VitalsTrendComparison> {\n const DAY_MS = 24 * 60 * 60 * 1000;\n const nowMs = Date.now();\n\n // Cap to 2 days ago — API data typically lags 1-2 days; using 2 ensures\n // the endTime is always within the available data window.\n const baseMs = nowMs - 2 * DAY_MS;\n\n // Current period: [base - days, base]\n const currentEnd = new Date(baseMs);\n const currentStart = new Date(baseMs - days * DAY_MS);\n\n // Previous period: [base - 2*days - 1, base - days - 1] (1-day gap)\n const previousEnd = new Date(baseMs - days * DAY_MS - DAY_MS);\n const previousStart = new Date(baseMs - days * DAY_MS - DAY_MS - days * DAY_MS);\n\n const metrics = METRIC_SET_METRICS[metricSet] ?? [\"errorReportCount\", \"distinctUsers\"];\n\n // Use UTC accessors to avoid timezone-dependent off-by-one on date boundaries\n const toApiDate = (d: Date) => ({\n year: d.getUTCFullYear(),\n month: d.getUTCMonth() + 1,\n day: d.getUTCDate(),\n });\n\n const makeQuery = (start: Date, end: Date): MetricSetQuery => ({\n metrics,\n timelineSpec: {\n aggregationPeriod: \"DAILY\",\n startTime: toApiDate(start),\n endTime: toApiDate(end),\n },\n });\n\n const [currentResult, previousResult] = await Promise.all([\n reporting.queryMetricSet(packageName, metricSet, makeQuery(currentStart, currentEnd)),\n reporting.queryMetricSet(packageName, metricSet, makeQuery(previousStart, previousEnd)),\n ]);\n\n const extractAvg = (rows: MetricRow[] | undefined): number | undefined => {\n if (!rows || rows.length === 0) return undefined;\n const values = rows\n .map((r) => {\n const keys = Object.keys(r.metrics);\n const first = keys[0];\n return first ? Number(r.metrics[first]?.decimalValue?.value) : NaN;\n })\n .filter((v) => !isNaN(v));\n if (values.length === 0) return undefined;\n return values.reduce((a, b) => a + b, 0) / values.length;\n };\n\n const current = extractAvg(currentResult.rows);\n const previous = extractAvg(previousResult.rows);\n\n let changePercent: number | undefined;\n let direction: VitalsTrendComparison[\"direction\"] = \"unknown\";\n\n if (current !== undefined && previous !== undefined && previous !== 0) {\n changePercent = ((current - previous) / previous) * 100;\n if (Math.abs(changePercent) < 1) {\n direction = \"unchanged\";\n } else if (changePercent < 0) {\n direction = \"improved\"; // lower error rate = better\n } else {\n direction = \"degraded\";\n }\n }\n\n return {\n metric: metricSet,\n current,\n previous,\n changePercent: changePercent !== undefined ? Math.round(changePercent * 10) / 10 : undefined,\n direction,\n };\n}\n\nexport function checkThreshold(value: number | undefined, threshold: number): ThresholdResult {\n return {\n breached: value !== undefined && value > threshold,\n value,\n threshold,\n };\n}\n","import type {\n PlayApiClient,\n Subscription,\n BasePlanMigratePricesRequest,\n SubscriptionOffer,\n OffersListResponse,\n Money,\n} from \"@gpc-cli/api\";\nimport { paginateAll } from \"@gpc-cli/api\";\nimport { validatePackageName, validateSku } from \"../utils/validation.js\";\nimport { GpcError } from \"../errors.js\";\n\nexport interface ListSubscriptionsOptions {\n pageToken?: string;\n pageSize?: number;\n limit?: number;\n nextPage?: string;\n}\n\n// --- Sanitization: strip output-only fields, coerce types ---\n\nfunction coerceMoneyUnits(money: Money): Money {\n if (money.units !== undefined && typeof money.units !== \"string\") {\n return { ...money, units: String(money.units) };\n }\n return money;\n}\n\nfunction sanitizeSubscription(data: Subscription): Subscription {\n const { ...cleaned } = data;\n // Strip output-only fields from top level\n delete (cleaned as Record<string, unknown>)[\"state\"];\n delete (cleaned as Record<string, unknown>)[\"archived\"];\n\n if (cleaned.basePlans) {\n cleaned.basePlans = cleaned.basePlans.map((bp) => {\n const { state: _s, archived: _a, ...cleanBp } = bp;\n // Coerce Money.units to string in regional configs\n if (cleanBp.regionalConfigs) {\n cleanBp.regionalConfigs = cleanBp.regionalConfigs.map((rc) => ({\n ...rc,\n price: coerceMoneyUnits(rc.price),\n }));\n }\n return cleanBp;\n });\n }\n return cleaned;\n}\n\nfunction sanitizeOffer(data: SubscriptionOffer): SubscriptionOffer {\n const { state: _s, ...cleaned } = data;\n delete (cleaned as Record<string, unknown>)[\"archived\"];\n return cleaned as SubscriptionOffer;\n}\n\n// --- Client-side validation ---\n\nfunction parseDuration(iso: string): number {\n const match = iso.match(/^P(\\d+)D$/);\n return match?.[1] ? parseInt(match[1], 10) : 0;\n}\n\nconst PRORATION_MODE_PREFIX = \"SUBSCRIPTION_PRORATION_MODE_\";\nconst VALID_PRORATION_MODES = [\n \"SUBSCRIPTION_PRORATION_MODE_CHARGE_ON_NEXT_BILLING_DATE\",\n \"SUBSCRIPTION_PRORATION_MODE_CHARGE_FULL_PRICE_IMMEDIATELY\",\n];\n\nfunction autoFixProrationMode(data: Subscription): void {\n if (!data.basePlans) return;\n for (const bp of data.basePlans) {\n const mode = bp.autoRenewingBasePlanType?.prorationMode;\n if (mode && !mode.startsWith(PRORATION_MODE_PREFIX)) {\n bp.autoRenewingBasePlanType!.prorationMode = `${PRORATION_MODE_PREFIX}${mode}`;\n }\n if (bp.autoRenewingBasePlanType?.prorationMode) {\n const fullMode = bp.autoRenewingBasePlanType.prorationMode;\n if (!VALID_PRORATION_MODES.includes(fullMode)) {\n throw new GpcError(\n `Invalid prorationMode: \"${fullMode}\"`,\n \"INVALID_SUBSCRIPTION_DATA\",\n 2,\n `Valid values: ${VALID_PRORATION_MODES.join(\", \")}`,\n );\n }\n }\n }\n}\n\nfunction validateSubscriptionData(data: Subscription): void {\n // Auto-fix prorationMode prefix\n autoFixProrationMode(data);\n\n // Validate listings\n if (data.listings) {\n for (const [lang, listing] of Object.entries(data.listings)) {\n if (listing.benefits && listing.benefits.length > 4) {\n throw new GpcError(\n `Listing \"${lang}\" has ${listing.benefits.length} benefits (max 4)`,\n \"INVALID_SUBSCRIPTION_DATA\",\n 2,\n \"Google Play allows a maximum of 4 benefits per subscription listing\",\n );\n }\n if (listing.description && listing.description.length > 80) {\n throw new GpcError(\n `Listing \"${lang}\" description is ${listing.description.length} chars (max 80)`,\n \"INVALID_SUBSCRIPTION_DATA\",\n 2,\n \"Google Play limits subscription descriptions to 80 characters\",\n );\n }\n }\n }\n\n // Validate base plan durations\n if (data.basePlans) {\n for (const bp of data.basePlans) {\n const autoType = bp.autoRenewingBasePlanType;\n if (autoType?.gracePeriodDuration && autoType?.accountHoldDuration) {\n const grace = parseDuration(autoType.gracePeriodDuration);\n const hold = parseDuration(autoType.accountHoldDuration);\n const sum = grace + hold;\n if (sum < 30 || sum > 60) {\n throw new GpcError(\n `Base plan \"${bp.basePlanId}\": gracePeriodDuration (${grace}d) + accountHoldDuration (${hold}d) = ${sum}d (must be 30-60)`,\n \"INVALID_SUBSCRIPTION_DATA\",\n 2,\n \"gracePeriodDuration + accountHoldDuration must sum to between P30D and P60D\",\n );\n }\n }\n }\n }\n}\n\nexport async function listSubscriptions(\n client: PlayApiClient,\n packageName: string,\n options?: ListSubscriptionsOptions,\n): Promise<{ subscriptions: Subscription[]; nextPageToken?: string }> {\n validatePackageName(packageName);\n if (options?.limit || options?.nextPage) {\n const result = await paginateAll<Subscription>(\n async (pageToken) => {\n const resp = await client.subscriptions.list(packageName, {\n pageToken,\n pageSize: options?.pageSize,\n });\n return { items: resp.subscriptions || [], nextPageToken: resp.nextPageToken };\n },\n { limit: options.limit, startPageToken: options.nextPage },\n );\n return { subscriptions: result.items, nextPageToken: result.nextPageToken };\n }\n return client.subscriptions.list(packageName, {\n pageToken: options?.pageToken,\n pageSize: options?.pageSize,\n });\n}\n\nexport async function getSubscription(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n): Promise<Subscription> {\n validatePackageName(packageName);\n validateSku(productId);\n return client.subscriptions.get(packageName, productId);\n}\n\nexport async function createSubscription(\n client: PlayApiClient,\n packageName: string,\n data: Subscription,\n): Promise<Subscription> {\n validatePackageName(packageName);\n validateSubscriptionData(data);\n const sanitized = sanitizeSubscription(data);\n return client.subscriptions.create(packageName, sanitized, data.productId);\n}\n\nconst SUBSCRIPTION_ID_FIELDS = new Set([\"productId\", \"packageName\"]);\n\nfunction deriveSubscriptionUpdateMask(data: Subscription): string {\n return Object.keys(data)\n .filter((k) => !SUBSCRIPTION_ID_FIELDS.has(k))\n .join(\",\");\n}\n\nexport async function updateSubscription(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n data: Subscription,\n updateMask?: string,\n): Promise<Subscription> {\n validatePackageName(packageName);\n validateSku(productId);\n validateSubscriptionData(data);\n const sanitized = sanitizeSubscription(data);\n const mask = updateMask || deriveSubscriptionUpdateMask(data);\n return client.subscriptions.update(packageName, productId, sanitized, mask);\n}\n\nexport async function deleteSubscription(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n): Promise<void> {\n validatePackageName(packageName);\n validateSku(productId);\n return client.subscriptions.delete(packageName, productId);\n}\n\nexport async function activateBasePlan(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n basePlanId: string,\n): Promise<Subscription> {\n validatePackageName(packageName);\n validateSku(productId);\n return client.subscriptions.activateBasePlan(packageName, productId, basePlanId);\n}\n\nexport async function deactivateBasePlan(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n basePlanId: string,\n): Promise<Subscription> {\n validatePackageName(packageName);\n validateSku(productId);\n return client.subscriptions.deactivateBasePlan(packageName, productId, basePlanId);\n}\n\nexport async function deleteBasePlan(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n basePlanId: string,\n): Promise<void> {\n validatePackageName(packageName);\n validateSku(productId);\n return client.subscriptions.deleteBasePlan(packageName, productId, basePlanId);\n}\n\nexport async function migratePrices(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n basePlanId: string,\n data: BasePlanMigratePricesRequest,\n): Promise<Subscription> {\n validatePackageName(packageName);\n validateSku(productId);\n return client.subscriptions.migratePrices(packageName, productId, basePlanId, data);\n}\n\nexport async function listOffers(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n basePlanId: string,\n): Promise<OffersListResponse> {\n validatePackageName(packageName);\n validateSku(productId);\n return client.subscriptions.listOffers(packageName, productId, basePlanId);\n}\n\nexport async function getOffer(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n basePlanId: string,\n offerId: string,\n): Promise<SubscriptionOffer> {\n validatePackageName(packageName);\n validateSku(productId);\n return client.subscriptions.getOffer(packageName, productId, basePlanId, offerId);\n}\n\nexport async function createOffer(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n basePlanId: string,\n data: SubscriptionOffer,\n): Promise<SubscriptionOffer> {\n validatePackageName(packageName);\n validateSku(productId);\n const sanitized = sanitizeOffer(data);\n return client.subscriptions.createOffer(packageName, productId, basePlanId, sanitized, data.offerId);\n}\n\nconst OFFER_ID_FIELDS = new Set([\"productId\", \"basePlanId\", \"offerId\"]);\n\nfunction deriveOfferUpdateMask(data: SubscriptionOffer): string {\n return Object.keys(data)\n .filter((k) => !OFFER_ID_FIELDS.has(k))\n .join(\",\");\n}\n\nexport async function updateOffer(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n basePlanId: string,\n offerId: string,\n data: SubscriptionOffer,\n updateMask?: string,\n): Promise<SubscriptionOffer> {\n validatePackageName(packageName);\n validateSku(productId);\n const sanitized = sanitizeOffer(data);\n const mask = updateMask || deriveOfferUpdateMask(data);\n return client.subscriptions.updateOffer(\n packageName,\n productId,\n basePlanId,\n offerId,\n sanitized,\n mask,\n );\n}\n\nexport async function deleteOffer(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n basePlanId: string,\n offerId: string,\n): Promise<void> {\n validatePackageName(packageName);\n validateSku(productId);\n return client.subscriptions.deleteOffer(packageName, productId, basePlanId, offerId);\n}\n\nexport async function activateOffer(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n basePlanId: string,\n offerId: string,\n): Promise<SubscriptionOffer> {\n validatePackageName(packageName);\n validateSku(productId);\n return client.subscriptions.activateOffer(packageName, productId, basePlanId, offerId);\n}\n\nexport interface SubscriptionDiff {\n field: string;\n local: string;\n remote: string;\n}\n\nexport async function diffSubscription(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n localData: Subscription,\n): Promise<SubscriptionDiff[]> {\n validatePackageName(packageName);\n validateSku(productId);\n const remote = await client.subscriptions.get(packageName, productId);\n const diffs: SubscriptionDiff[] = [];\n const fieldsToCompare = [\"listings\", \"basePlans\", \"taxAndComplianceSettings\"];\n\n for (const field of fieldsToCompare) {\n const localVal = JSON.stringify((localData as unknown as Record<string, unknown>)[field] ?? null);\n const remoteVal = JSON.stringify((remote as unknown as Record<string, unknown>)[field] ?? null);\n if (localVal !== remoteVal) {\n diffs.push({ field, local: localVal, remote: remoteVal });\n }\n }\n return diffs;\n}\n\nexport async function deactivateOffer(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n basePlanId: string,\n offerId: string,\n): Promise<SubscriptionOffer> {\n validatePackageName(packageName);\n validateSku(productId);\n return client.subscriptions.deactivateOffer(packageName, productId, basePlanId, offerId);\n}\n","import { readdir, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { PlayApiClient, InAppProduct, InAppProductsBatchUpdateRequest } from \"@gpc-cli/api\";\nimport { paginateAll } from \"@gpc-cli/api\";\nimport { GpcError } from \"../errors.js\";\n\nexport interface ListIapOptions {\n token?: string;\n maxResults?: number;\n limit?: number;\n nextPage?: string;\n}\n\nexport async function listInAppProducts(\n client: PlayApiClient,\n packageName: string,\n options?: ListIapOptions,\n): Promise<{ inappproduct: InAppProduct[]; nextPageToken?: string }> {\n if (options?.limit || options?.nextPage) {\n const result = await paginateAll<InAppProduct>(\n async (pageToken) => {\n const resp = await client.inappproducts.list(packageName, {\n token: pageToken,\n maxResults: options?.maxResults,\n });\n return {\n items: resp.inappproduct || [],\n nextPageToken: resp.tokenPagination?.nextPageToken,\n };\n },\n { limit: options.limit, startPageToken: options.nextPage },\n );\n return { inappproduct: result.items, nextPageToken: result.nextPageToken };\n }\n return client.inappproducts.list(packageName, {\n token: options?.token,\n maxResults: options?.maxResults,\n });\n}\n\nexport async function getInAppProduct(\n client: PlayApiClient,\n packageName: string,\n sku: string,\n): Promise<InAppProduct> {\n return client.inappproducts.get(packageName, sku);\n}\n\nexport async function createInAppProduct(\n client: PlayApiClient,\n packageName: string,\n data: InAppProduct,\n): Promise<InAppProduct> {\n return client.inappproducts.create(packageName, data);\n}\n\nexport async function updateInAppProduct(\n client: PlayApiClient,\n packageName: string,\n sku: string,\n data: InAppProduct,\n): Promise<InAppProduct> {\n return client.inappproducts.update(packageName, sku, data);\n}\n\nexport async function deleteInAppProduct(\n client: PlayApiClient,\n packageName: string,\n sku: string,\n): Promise<void> {\n return client.inappproducts.delete(packageName, sku);\n}\n\nexport interface SyncResult {\n created: number;\n updated: number;\n unchanged: number;\n skus: string[];\n}\n\nexport async function syncInAppProducts(\n client: PlayApiClient,\n packageName: string,\n dir: string,\n options?: { dryRun?: boolean },\n): Promise<SyncResult> {\n const localProducts = await readProductsFromDir(dir);\n\n if (localProducts.length === 0) {\n return { created: 0, updated: 0, unchanged: 0, skus: [] };\n }\n\n const response = await client.inappproducts.list(packageName);\n const remoteSkus = new Set((response.inappproduct || []).map((p) => p.sku));\n\n const toUpdate = localProducts.filter((p) => remoteSkus.has(p.sku));\n const toCreate = localProducts.filter((p) => !remoteSkus.has(p.sku));\n const skus = localProducts.map((p) => p.sku);\n\n if (options?.dryRun) {\n return { created: toCreate.length, updated: toUpdate.length, unchanged: 0, skus };\n }\n\n // Attempt batch update for products that need updating (multiple items)\n if (toUpdate.length > 1) {\n try {\n await batchUpdateProducts(client, packageName, toUpdate);\n } catch {\n // Fallback to serial updates\n for (const product of toUpdate) {\n await client.inappproducts.update(packageName, product.sku, product);\n }\n }\n } else {\n for (const product of toUpdate) {\n await client.inappproducts.update(packageName, product.sku, product);\n }\n }\n\n for (const product of toCreate) {\n await client.inappproducts.create(packageName, product);\n }\n\n return { created: toCreate.length, updated: toUpdate.length, unchanged: 0, skus };\n}\n\nconst BATCH_CHUNK_SIZE = 100;\n\nasync function batchUpdateProducts(\n client: PlayApiClient,\n packageName: string,\n products: InAppProduct[],\n): Promise<InAppProduct[]> {\n const results: InAppProduct[] = [];\n for (let i = 0; i < products.length; i += BATCH_CHUNK_SIZE) {\n const chunk = products.slice(i, i + BATCH_CHUNK_SIZE);\n const request: InAppProductsBatchUpdateRequest = {\n requests: chunk.map((p) => ({\n inappproduct: p,\n packageName,\n sku: p.sku,\n })),\n };\n const response = await client.inappproducts.batchUpdate(packageName, request);\n results.push(...(response.inappproducts || []));\n }\n return results;\n}\n\nasync function readProductsFromDir(dir: string): Promise<InAppProduct[]> {\n const files = await readdir(dir);\n const jsonFiles = files.filter((f) => f.endsWith(\".json\"));\n const localProducts: InAppProduct[] = [];\n for (const file of jsonFiles) {\n const content = await readFile(join(dir, file), \"utf-8\");\n try {\n localProducts.push(JSON.parse(content) as InAppProduct);\n } catch {\n throw new GpcError(\n `Failed to parse ${file}: invalid JSON`,\n \"IAP_INVALID_JSON\",\n 1,\n `Check that \"${file}\" contains valid JSON. You can validate it with: cat \"${file}\" | jq .`,\n );\n }\n }\n return localProducts;\n}\n\nexport interface BatchSyncResult extends SyncResult {\n batchUsed: boolean;\n batchErrors: number;\n}\n\nexport async function batchSyncInAppProducts(\n client: PlayApiClient,\n packageName: string,\n dir: string,\n options?: { dryRun?: boolean },\n): Promise<BatchSyncResult> {\n const localProducts = await readProductsFromDir(dir);\n\n if (localProducts.length === 0) {\n return { created: 0, updated: 0, unchanged: 0, skus: [], batchUsed: false, batchErrors: 0 };\n }\n\n const response = await client.inappproducts.list(packageName);\n const remoteSkus = new Set((response.inappproduct || []).map((p) => p.sku));\n\n const toUpdate = localProducts.filter((p) => remoteSkus.has(p.sku));\n const toCreate = localProducts.filter((p) => !remoteSkus.has(p.sku));\n const skus = localProducts.map((p) => p.sku);\n\n if (options?.dryRun) {\n return {\n created: toCreate.length,\n updated: toUpdate.length,\n unchanged: 0,\n skus,\n batchUsed: toUpdate.length > 1,\n batchErrors: 0,\n };\n }\n\n let batchUsed = false;\n let batchErrors = 0;\n\n if (toUpdate.length > 1) {\n batchUsed = true;\n try {\n await batchUpdateProducts(client, packageName, toUpdate);\n } catch {\n batchErrors++;\n // Fallback to serial updates\n for (const product of toUpdate) {\n await client.inappproducts.update(packageName, product.sku, product);\n }\n }\n } else {\n for (const product of toUpdate) {\n await client.inappproducts.update(packageName, product.sku, product);\n }\n }\n\n for (const product of toCreate) {\n await client.inappproducts.create(packageName, product);\n }\n\n return {\n created: toCreate.length,\n updated: toUpdate.length,\n unchanged: 0,\n skus,\n batchUsed,\n batchErrors,\n };\n}\n","import type {\n PlayApiClient,\n ProductPurchase,\n SubscriptionPurchaseV2,\n SubscriptionDeferResponse,\n} from \"@gpc-cli/api\";\nimport { validatePackageName } from \"../utils/validation.js\";\n\nexport async function getProductPurchase(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n token: string,\n): Promise<ProductPurchase> {\n validatePackageName(packageName);\n return client.purchases.getProduct(packageName, productId, token);\n}\n\nexport async function acknowledgeProductPurchase(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n token: string,\n payload?: string,\n): Promise<void> {\n validatePackageName(packageName);\n const body = payload ? { developerPayload: payload } : undefined;\n return client.purchases.acknowledgeProduct(packageName, productId, token, body);\n}\n\nexport async function consumeProductPurchase(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n token: string,\n): Promise<void> {\n validatePackageName(packageName);\n return client.purchases.consumeProduct(packageName, productId, token);\n}\n\nexport async function getSubscriptionPurchase(\n client: PlayApiClient,\n packageName: string,\n token: string,\n): Promise<SubscriptionPurchaseV2> {\n validatePackageName(packageName);\n return client.purchases.getSubscriptionV2(packageName, token);\n}\n\nexport async function cancelSubscriptionPurchase(\n client: PlayApiClient,\n packageName: string,\n subscriptionId: string,\n token: string,\n): Promise<void> {\n validatePackageName(packageName);\n return client.purchases.cancelSubscription(packageName, subscriptionId, token);\n}\n\nexport async function deferSubscriptionPurchase(\n client: PlayApiClient,\n packageName: string,\n subscriptionId: string,\n token: string,\n desiredExpiry: string,\n): Promise<SubscriptionDeferResponse> {\n validatePackageName(packageName);\n const sub = await client.purchases.getSubscriptionV1(packageName, subscriptionId, token);\n return client.purchases.deferSubscription(packageName, subscriptionId, token, {\n deferralInfo: {\n expectedExpiryTimeMillis: sub.expiryTimeMillis,\n desiredExpiryTimeMillis: String(new Date(desiredExpiry).getTime()),\n },\n });\n}\n\nexport async function revokeSubscriptionPurchase(\n client: PlayApiClient,\n packageName: string,\n token: string,\n): Promise<void> {\n validatePackageName(packageName);\n return client.purchases.revokeSubscriptionV2(packageName, token);\n}\n\nimport type { VoidedPurchase } from \"@gpc-cli/api\";\nimport { paginateAll } from \"@gpc-cli/api\";\n\nexport interface ListVoidedOptions {\n startTime?: string;\n endTime?: string;\n maxResults?: number;\n limit?: number;\n nextPage?: string;\n}\n\nexport async function listVoidedPurchases(\n client: PlayApiClient,\n packageName: string,\n options?: ListVoidedOptions,\n): Promise<{ voidedPurchases: VoidedPurchase[]; nextPageToken?: string }> {\n validatePackageName(packageName);\n if (options?.limit || options?.nextPage) {\n const result = await paginateAll<VoidedPurchase>(\n async (pageToken) => {\n const resp = await client.purchases.listVoided(packageName, {\n startTime: options?.startTime,\n endTime: options?.endTime,\n maxResults: options?.maxResults,\n token: pageToken,\n });\n return {\n items: resp.voidedPurchases || [],\n nextPageToken: resp.tokenPagination?.nextPageToken,\n };\n },\n { limit: options.limit, startPageToken: options.nextPage },\n );\n return { voidedPurchases: result.items, nextPageToken: result.nextPageToken };\n }\n return client.purchases.listVoided(packageName, options);\n}\n\nexport async function refundOrder(\n client: PlayApiClient,\n packageName: string,\n orderId: string,\n options?: { fullRefund?: boolean; proratedRefund?: boolean },\n): Promise<void> {\n validatePackageName(packageName);\n return client.orders.refund(packageName, orderId, options);\n}\n","import type { PlayApiClient, ConvertRegionPricesResponse } from \"@gpc-cli/api\";\n\nexport async function convertRegionPrices(\n client: PlayApiClient,\n packageName: string,\n currencyCode: string,\n amount: string,\n): Promise<ConvertRegionPricesResponse> {\n const units = amount.split(\".\")[0] || \"0\";\n const fractional = amount.split(\".\")[1] || \"0\";\n const nanos = Number(fractional.padEnd(9, \"0\").slice(0, 9));\n\n return client.monetization.convertRegionPrices(packageName, {\n price: {\n currencyCode,\n units,\n nanos,\n },\n });\n}\n","import type { PlayApiClient, ReportBucket, ReportType, StatsDimension } from \"@gpc-cli/api\";\nimport { GpcError } from \"../errors.js\";\n\nconst FINANCIAL_REPORT_TYPES: ReadonlySet<string> = new Set([\n \"earnings\",\n \"sales\",\n \"estimated_sales\",\n \"play_balance\",\n]);\n\nconst STATS_REPORT_TYPES: ReadonlySet<string> = new Set([\n \"installs\",\n \"crashes\",\n \"ratings\",\n \"reviews\",\n \"store_performance\",\n \"subscriptions\",\n]);\n\nconst VALID_DIMENSIONS: ReadonlySet<string> = new Set([\n \"country\",\n \"language\",\n \"os_version\",\n \"device\",\n \"app_version\",\n \"carrier\",\n \"overview\",\n]);\n\nexport function isFinancialReportType(type: string): boolean {\n return FINANCIAL_REPORT_TYPES.has(type);\n}\n\nexport function isStatsReportType(type: string): boolean {\n return STATS_REPORT_TYPES.has(type);\n}\n\nexport function isValidReportType(type: string): type is ReportType {\n return FINANCIAL_REPORT_TYPES.has(type) || STATS_REPORT_TYPES.has(type);\n}\n\nexport function isValidStatsDimension(dim: string): dim is StatsDimension {\n return VALID_DIMENSIONS.has(dim);\n}\n\nexport interface ParsedMonth {\n year: number;\n month: number;\n}\n\nexport function parseMonth(monthStr: string): ParsedMonth {\n const match = /^(\\d{4})-(\\d{2})$/.exec(monthStr);\n if (!match) {\n throw new GpcError(\n `Invalid month format \"${monthStr}\". Expected YYYY-MM (e.g., 2026-03).`,\n \"REPORT_INVALID_MONTH\",\n 2,\n \"Use the format YYYY-MM, for example: --month 2026-03\",\n );\n }\n const year = Number(match[1]);\n const month = Number(match[2]);\n if (month < 1 || month > 12) {\n throw new GpcError(\n `Invalid month \"${month}\". Must be between 01 and 12.`,\n \"REPORT_INVALID_MONTH\",\n 2,\n \"The month value must be between 01 and 12.\",\n );\n }\n return { year, month };\n}\n\nexport async function listReports(\n _client: PlayApiClient,\n _packageName: string,\n reportType: ReportType,\n _year: number,\n _month: number,\n): Promise<ReportBucket[]> {\n throw new GpcError(\n `Report listing for \"${reportType}\" is not available through the Google Play Developer API.`,\n \"REPORT_NOT_SUPPORTED\",\n 1,\n isFinancialReportType(reportType)\n ? \"Financial reports are delivered via Google Cloud Storage. Access them from Play Console → Download reports → Financial.\"\n : \"Stats reports are delivered via Google Cloud Storage. For real-time metrics, use 'gpc vitals' commands.\",\n );\n}\n\nexport async function downloadReport(\n _client: PlayApiClient,\n _packageName: string,\n reportType: ReportType,\n _year: number,\n _month: number,\n): Promise<string> {\n throw new GpcError(\n `Report download for \"${reportType}\" is not available through the Google Play Developer API.`,\n \"REPORT_NOT_SUPPORTED\",\n 1,\n isFinancialReportType(reportType)\n ? \"Financial reports are delivered via Google Cloud Storage. Access them from Play Console → Download reports → Financial.\"\n : \"Stats reports are delivered via Google Cloud Storage. For real-time metrics, use 'gpc vitals' commands.\",\n );\n}\n","import type { UsersApiClient, User, DeveloperPermission, Grant } from \"@gpc-cli/api\";\nimport { paginateAll } from \"@gpc-cli/api\";\nimport { GpcError } from \"../errors.js\";\n\nexport const PERMISSION_PROPAGATION_WARNING =\n \"Note: Permission changes may take up to 48 hours to propagate.\";\n\nexport interface ListUsersOptions {\n pageToken?: string;\n pageSize?: number;\n limit?: number;\n nextPage?: string;\n}\n\nexport async function listUsers(\n client: UsersApiClient,\n developerId: string,\n options?: ListUsersOptions,\n): Promise<{ users: User[]; nextPageToken?: string }> {\n if (options?.limit || options?.nextPage) {\n const result = await paginateAll<User>(\n async (pageToken) => {\n const resp = await client.list(developerId, { pageToken, pageSize: options?.pageSize });\n return { items: resp.users || [], nextPageToken: resp.nextPageToken };\n },\n { limit: options.limit, startPageToken: options.nextPage },\n );\n return { users: result.items, nextPageToken: result.nextPageToken };\n }\n const response = await client.list(developerId, options);\n return { users: response.users || [], nextPageToken: response.nextPageToken };\n}\n\nexport async function getUser(\n client: UsersApiClient,\n developerId: string,\n userId: string,\n): Promise<User> {\n return client.get(developerId, userId);\n}\n\nexport async function inviteUser(\n client: UsersApiClient,\n developerId: string,\n email: string,\n permissions?: DeveloperPermission[],\n grants?: Grant[],\n): Promise<User> {\n const user: Partial<User> = { email };\n if (permissions) user.developerAccountPermission = permissions;\n if (grants) user.grants = grants;\n return client.create(developerId, user);\n}\n\nexport async function updateUser(\n client: UsersApiClient,\n developerId: string,\n userId: string,\n permissions?: DeveloperPermission[],\n grants?: Grant[],\n): Promise<User> {\n const updates: Partial<User> = {};\n const masks: string[] = [];\n\n if (permissions) {\n updates.developerAccountPermission = permissions;\n masks.push(\"developerAccountPermission\");\n }\n if (grants) {\n updates.grants = grants;\n masks.push(\"grants\");\n }\n\n const updateMask = masks.length > 0 ? masks.join(\",\") : undefined;\n return client.update(developerId, userId, updates, updateMask);\n}\n\nexport async function removeUser(\n client: UsersApiClient,\n developerId: string,\n userId: string,\n): Promise<void> {\n return client.delete(developerId, userId);\n}\n\nexport function parseGrantArg(grantStr: string): Grant {\n const colonIdx = grantStr.indexOf(\":\");\n if (colonIdx === -1) {\n throw new GpcError(\n `Invalid grant format \"${grantStr}\". Expected <packageName>:<PERMISSION>[,<PERMISSION>...]`,\n \"USER_INVALID_GRANT\",\n 2,\n \"Use the format: com.example.app:VIEW_APP_INFORMATION,MANAGE_STORE_LISTING\",\n );\n }\n const packageName = grantStr.slice(0, colonIdx);\n const perms = grantStr.slice(colonIdx + 1).split(\",\") as DeveloperPermission[];\n return { packageName, appLevelPermissions: perms };\n}\n","import type { PlayApiClient, Testers } from \"@gpc-cli/api\";\nimport { readFile } from \"node:fs/promises\";\nimport { GpcError } from \"../errors.js\";\n\nexport async function listTesters(\n client: PlayApiClient,\n packageName: string,\n track: string,\n): Promise<Testers> {\n const edit = await client.edits.insert(packageName);\n try {\n const testers = await client.testers.get(packageName, edit.id, track);\n return testers;\n } finally {\n await client.edits.delete(packageName, edit.id);\n }\n}\n\nexport async function addTesters(\n client: PlayApiClient,\n packageName: string,\n track: string,\n groupEmails: string[],\n): Promise<Testers> {\n const edit = await client.edits.insert(packageName);\n try {\n const current = await client.testers.get(packageName, edit.id, track);\n const existing = new Set(current.googleGroups || []);\n for (const email of groupEmails) {\n existing.add(email.trim());\n }\n const updated = await client.testers.update(packageName, edit.id, track, {\n googleGroups: [...existing],\n });\n await client.edits.validate(packageName, edit.id);\n await client.edits.commit(packageName, edit.id);\n return updated;\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function removeTesters(\n client: PlayApiClient,\n packageName: string,\n track: string,\n groupEmails: string[],\n): Promise<Testers> {\n const edit = await client.edits.insert(packageName);\n try {\n const current = await client.testers.get(packageName, edit.id, track);\n const toRemove = new Set(groupEmails.map((e) => e.trim()));\n const filtered = (current.googleGroups || []).filter((g) => !toRemove.has(g));\n const updated = await client.testers.update(packageName, edit.id, track, {\n googleGroups: filtered,\n });\n await client.edits.validate(packageName, edit.id);\n await client.edits.commit(packageName, edit.id);\n return updated;\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function importTestersFromCsv(\n client: PlayApiClient,\n packageName: string,\n track: string,\n csvPath: string,\n): Promise<{ added: number; testers: Testers }> {\n const content = await readFile(csvPath, \"utf-8\");\n const emails = content\n .split(/[,\\n\\r]+/)\n .map((e) => e.trim())\n .filter((e) => e.length > 0 && e.includes(\"@\"));\n\n if (emails.length === 0) {\n throw new GpcError(\n `No valid email addresses found in ${csvPath}.`,\n \"TESTER_NO_EMAILS\",\n 1,\n \"The CSV file must contain email addresses separated by commas or newlines. Each email must contain an @ symbol.\",\n );\n }\n\n const testers = await addTesters(client, packageName, track, emails);\n return { added: emails.length, testers };\n}\n","import { execFile as execFileCb } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { GpcError } from \"../errors.js\";\n\nconst execFile = promisify(execFileCb);\n\nexport interface GitNotesOptions {\n since?: string;\n language?: string;\n maxLength?: number;\n}\n\nexport interface GitReleaseNotes {\n language: string;\n text: string;\n commitCount: number;\n since: string;\n truncated: boolean;\n}\n\ninterface ParsedCommit {\n type: string;\n message: string;\n}\n\nconst COMMIT_TYPE_HEADERS: Record<string, string> = {\n feat: \"New\",\n fix: \"Fixed\",\n perf: \"Improved\",\n};\n\nconst DEFAULT_MAX_LENGTH = 500;\n\nfunction parseConventionalCommit(subject: string): ParsedCommit {\n const match = subject.match(/^(\\w+)(?:\\([^)]*\\))?:\\s*(.+)$/);\n if (match) {\n return { type: match[1]!, message: match[2]!.trim() };\n }\n return { type: \"other\", message: subject.trim() };\n}\n\nfunction formatNotes(commits: ParsedCommit[], maxLength: number): { text: string; truncated: boolean } {\n const groups = new Map<string, string[]>();\n\n for (const commit of commits) {\n const header = COMMIT_TYPE_HEADERS[commit.type] || \"Changes\";\n if (!groups.has(header)) {\n groups.set(header, []);\n }\n groups.get(header)!.push(commit.message);\n }\n\n // Order: New, Fixed, Improved, then Changes\n const order = [\"New\", \"Fixed\", \"Improved\", \"Changes\"];\n const sections: string[] = [];\n\n for (const header of order) {\n const items = groups.get(header);\n if (!items || items.length === 0) continue;\n const bullets = items.map((m) => `\\u2022 ${m}`).join(\"\\n\");\n sections.push(`${header}:\\n${bullets}`);\n }\n\n let text = sections.join(\"\\n\\n\");\n let truncated = false;\n\n if (text.length > maxLength) {\n text = text.slice(0, maxLength - 3) + \"...\";\n truncated = true;\n }\n\n return { text, truncated };\n}\n\nasync function gitExec(args: string[]): Promise<string> {\n try {\n const { stdout } = await execFile(\"git\", args);\n return stdout.trim();\n } catch (error: unknown) {\n const err = error as { code?: string; stderr?: string; message?: string };\n if (err.code === \"ENOENT\") {\n throw new GpcError(\n \"git is not available on this system\",\n \"GIT_NOT_FOUND\",\n 1,\n \"Install git and ensure it is in your PATH.\",\n );\n }\n throw error;\n }\n}\n\nexport async function generateNotesFromGit(\n options?: GitNotesOptions,\n): Promise<GitReleaseNotes> {\n const language = options?.language || \"en-US\";\n const maxLength = options?.maxLength ?? DEFAULT_MAX_LENGTH;\n let since = options?.since;\n\n if (!since) {\n try {\n since = await gitExec([\"describe\", \"--tags\", \"--abbrev=0\"]);\n } catch (e) {\n if (e instanceof GpcError && e.code === \"GIT_NOT_FOUND\") throw e;\n throw new GpcError(\n \"No git tags found. Cannot determine commit range for release notes.\",\n \"GIT_NO_TAGS\",\n 1,\n \"Create a tag first (e.g., git tag v1.0.0) or use --since <ref> to specify a starting point.\",\n );\n }\n }\n\n let logOutput: string;\n try {\n logOutput = await gitExec([\"log\", `${since}..HEAD`, \"--format=%s\"]);\n } catch (error: unknown) {\n const err = error as { stderr?: string; message?: string };\n const msg = err.stderr || err.message || String(error);\n throw new GpcError(\n `Failed to read git log from \"${since}\": ${msg}`,\n \"GIT_LOG_FAILED\",\n 1,\n `Verify that \"${since}\" is a valid git ref (tag, branch, or SHA).`,\n );\n }\n\n if (!logOutput) {\n return {\n language,\n text: \"No changes since last release.\",\n commitCount: 0,\n since,\n truncated: false,\n };\n }\n\n const subjects = logOutput.split(\"\\n\").filter((line) => line.length > 0);\n const commits = subjects.map(parseConventionalCommit);\n const { text, truncated } = formatNotes(commits, maxLength);\n\n return {\n language,\n text,\n commitCount: subjects.length,\n since,\n truncated,\n };\n}\n","import type {\n PlayApiClient,\n AppRecoveryAction,\n AppRecoveryTargeting,\n CreateAppRecoveryActionRequest,\n} from \"@gpc-cli/api\";\n\nexport async function listRecoveryActions(\n client: PlayApiClient,\n packageName: string,\n versionCode?: number,\n): Promise<AppRecoveryAction[]> {\n return client.appRecovery.list(packageName, versionCode);\n}\n\nexport async function cancelRecoveryAction(\n client: PlayApiClient,\n packageName: string,\n recoveryId: string,\n): Promise<void> {\n return client.appRecovery.cancel(packageName, recoveryId);\n}\n\nexport async function deployRecoveryAction(\n client: PlayApiClient,\n packageName: string,\n recoveryId: string,\n): Promise<void> {\n return client.appRecovery.deploy(packageName, recoveryId);\n}\n\nexport async function createRecoveryAction(\n client: PlayApiClient,\n packageName: string,\n request: CreateAppRecoveryActionRequest,\n): Promise<AppRecoveryAction> {\n return client.appRecovery.create(packageName, request);\n}\n\nexport async function addRecoveryTargeting(\n client: PlayApiClient,\n packageName: string,\n actionId: string,\n targeting: AppRecoveryTargeting,\n): Promise<AppRecoveryAction> {\n return client.appRecovery.addTargeting(packageName, actionId, targeting);\n}\n","import type { PlayApiClient, DataSafety } from \"@gpc-cli/api\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { GpcError } from \"../errors.js\";\n\nexport async function getDataSafety(\n client: PlayApiClient,\n packageName: string,\n): Promise<DataSafety> {\n return client.dataSafety.get(packageName);\n}\n\nexport async function updateDataSafety(\n client: PlayApiClient,\n packageName: string,\n data: DataSafety,\n): Promise<DataSafety> {\n return client.dataSafety.update(packageName, data);\n}\n\nexport async function exportDataSafety(\n client: PlayApiClient,\n packageName: string,\n outputPath: string,\n): Promise<DataSafety> {\n const dataSafety = await getDataSafety(client, packageName);\n await writeFile(outputPath, JSON.stringify(dataSafety, null, 2) + \"\\n\", \"utf-8\");\n return dataSafety;\n}\n\nexport async function importDataSafety(\n client: PlayApiClient,\n packageName: string,\n filePath: string,\n): Promise<DataSafety> {\n const content = await readFile(filePath, \"utf-8\");\n let data: DataSafety;\n try {\n data = JSON.parse(content) as DataSafety;\n } catch {\n throw new GpcError(\n `Failed to parse data safety JSON from \"${filePath}\"`,\n \"INVALID_JSON\",\n 1,\n \"Ensure the file contains valid JSON matching the data safety schema.\",\n );\n }\n return updateDataSafety(client, packageName, data);\n}\n","import type {\n PlayApiClient,\n ExternalTransaction,\n ExternalTransactionRefund,\n} from \"@gpc-cli/api\";\n\nexport async function createExternalTransaction(\n client: PlayApiClient,\n packageName: string,\n data: ExternalTransaction,\n): Promise<ExternalTransaction> {\n return client.externalTransactions.create(packageName, data);\n}\n\nexport async function getExternalTransaction(\n client: PlayApiClient,\n packageName: string,\n transactionId: string,\n): Promise<ExternalTransaction> {\n return client.externalTransactions.get(packageName, transactionId);\n}\n\nexport async function refundExternalTransaction(\n client: PlayApiClient,\n packageName: string,\n transactionId: string,\n refundData: ExternalTransactionRefund,\n): Promise<ExternalTransaction> {\n return client.externalTransactions.refund(packageName, transactionId, refundData);\n}\n","import type { PlayApiClient, DeviceTierConfig } from \"@gpc-cli/api\";\nimport { GpcError } from \"../errors.js\";\n\nexport async function listDeviceTiers(\n client: PlayApiClient,\n packageName: string,\n): Promise<DeviceTierConfig[]> {\n if (!packageName) {\n throw new GpcError(\n \"Package name is required\",\n \"MISSING_PACKAGE_NAME\",\n 2,\n \"Provide a package name with --app or set it in config.\",\n );\n }\n return client.deviceTiers.list(packageName);\n}\n\nexport async function getDeviceTier(\n client: PlayApiClient,\n packageName: string,\n configId: string,\n): Promise<DeviceTierConfig> {\n if (!packageName) {\n throw new GpcError(\n \"Package name is required\",\n \"MISSING_PACKAGE_NAME\",\n 2,\n \"Provide a package name with --app or set it in config.\",\n );\n }\n if (!configId) {\n throw new GpcError(\n \"Config ID is required\",\n \"MISSING_CONFIG_ID\",\n 2,\n \"Provide a device tier config ID.\",\n );\n }\n return client.deviceTiers.get(packageName, configId);\n}\n\nexport async function createDeviceTier(\n client: PlayApiClient,\n packageName: string,\n config: DeviceTierConfig,\n): Promise<DeviceTierConfig> {\n if (!packageName) {\n throw new GpcError(\n \"Package name is required\",\n \"MISSING_PACKAGE_NAME\",\n 2,\n \"Provide a package name with --app or set it in config.\",\n );\n }\n if (!config || !config.deviceGroups || config.deviceGroups.length === 0) {\n throw new GpcError(\n \"Device tier config must include at least one device group\",\n \"INVALID_DEVICE_TIER_CONFIG\",\n 2,\n \"Provide a valid config with deviceGroups.\",\n );\n }\n return client.deviceTiers.create(packageName, config);\n}\n","import type {\n PlayApiClient,\n OneTimeProduct,\n OneTimeProductsListResponse,\n OneTimeOffer,\n OneTimeOffersListResponse,\n} from \"@gpc-cli/api\";\nimport { GpcError } from \"../errors.js\";\n\nexport async function listOneTimeProducts(\n client: PlayApiClient,\n packageName: string,\n): Promise<OneTimeProductsListResponse> {\n try {\n return await client.oneTimeProducts.list(packageName);\n } catch (error) {\n throw new GpcError(\n `Failed to list one-time products: ${error instanceof Error ? error.message : String(error)}`,\n \"OTP_LIST_FAILED\",\n 4,\n \"Check your package name and API credentials.\",\n );\n }\n}\n\nexport async function getOneTimeProduct(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n): Promise<OneTimeProduct> {\n try {\n return await client.oneTimeProducts.get(packageName, productId);\n } catch (error) {\n throw new GpcError(\n `Failed to get one-time product \"${productId}\": ${error instanceof Error ? error.message : String(error)}`,\n \"OTP_GET_FAILED\",\n 4,\n \"Check that the product ID exists.\",\n );\n }\n}\n\nexport async function createOneTimeProduct(\n client: PlayApiClient,\n packageName: string,\n data: OneTimeProduct,\n): Promise<OneTimeProduct> {\n try {\n return await client.oneTimeProducts.create(packageName, data);\n } catch (error) {\n throw new GpcError(\n `Failed to create one-time product: ${error instanceof Error ? error.message : String(error)}`,\n \"OTP_CREATE_FAILED\",\n 4,\n \"Verify the product data and ensure the product ID is unique.\",\n );\n }\n}\n\nconst OTP_ID_FIELDS = new Set([\"productId\", \"packageName\"]);\n\nfunction deriveOtpUpdateMask(data: Partial<OneTimeProduct>): string {\n return Object.keys(data)\n .filter((k) => !OTP_ID_FIELDS.has(k))\n .join(\",\");\n}\n\nconst OTP_OFFER_ID_FIELDS = new Set([\"productId\", \"offerId\"]);\n\nfunction deriveOtpOfferUpdateMask(data: Partial<OneTimeOffer>): string {\n return Object.keys(data)\n .filter((k) => !OTP_OFFER_ID_FIELDS.has(k))\n .join(\",\");\n}\n\nexport async function updateOneTimeProduct(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n data: Partial<OneTimeProduct>,\n updateMask?: string,\n): Promise<OneTimeProduct> {\n try {\n const mask = updateMask || deriveOtpUpdateMask(data);\n return await client.oneTimeProducts.update(packageName, productId, data, mask);\n } catch (error) {\n throw new GpcError(\n `Failed to update one-time product \"${productId}\": ${error instanceof Error ? error.message : String(error)}`,\n \"OTP_UPDATE_FAILED\",\n 4,\n \"Check that the product ID exists and the data is valid.\",\n );\n }\n}\n\nexport async function deleteOneTimeProduct(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n): Promise<void> {\n try {\n await client.oneTimeProducts.delete(packageName, productId);\n } catch (error) {\n throw new GpcError(\n `Failed to delete one-time product \"${productId}\": ${error instanceof Error ? error.message : String(error)}`,\n \"OTP_DELETE_FAILED\",\n 4,\n \"Check that the product ID exists and is not active.\",\n );\n }\n}\n\nexport async function listOneTimeOffers(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n): Promise<OneTimeOffersListResponse> {\n try {\n return await client.oneTimeProducts.listOffers(packageName, productId);\n } catch (error) {\n throw new GpcError(\n `Failed to list offers for product \"${productId}\": ${error instanceof Error ? error.message : String(error)}`,\n \"OTP_OFFERS_LIST_FAILED\",\n 4,\n \"Check the product ID and your API credentials.\",\n );\n }\n}\n\nexport async function getOneTimeOffer(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n offerId: string,\n): Promise<OneTimeOffer> {\n try {\n return await client.oneTimeProducts.getOffer(packageName, productId, offerId);\n } catch (error) {\n throw new GpcError(\n `Failed to get offer \"${offerId}\" for product \"${productId}\": ${error instanceof Error ? error.message : String(error)}`,\n \"OTP_OFFER_GET_FAILED\",\n 4,\n \"Check that the product and offer IDs exist.\",\n );\n }\n}\n\nexport async function createOneTimeOffer(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n data: OneTimeOffer,\n): Promise<OneTimeOffer> {\n try {\n return await client.oneTimeProducts.createOffer(packageName, productId, data);\n } catch (error) {\n throw new GpcError(\n `Failed to create offer for product \"${productId}\": ${error instanceof Error ? error.message : String(error)}`,\n \"OTP_OFFER_CREATE_FAILED\",\n 4,\n \"Verify the offer data and ensure the offer ID is unique.\",\n );\n }\n}\n\nexport async function updateOneTimeOffer(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n offerId: string,\n data: Partial<OneTimeOffer>,\n updateMask?: string,\n): Promise<OneTimeOffer> {\n try {\n const mask = updateMask || deriveOtpOfferUpdateMask(data);\n return await client.oneTimeProducts.updateOffer(packageName, productId, offerId, data, mask);\n } catch (error) {\n throw new GpcError(\n `Failed to update offer \"${offerId}\" for product \"${productId}\": ${error instanceof Error ? error.message : String(error)}`,\n \"OTP_OFFER_UPDATE_FAILED\",\n 4,\n \"Check that the product and offer IDs exist and the data is valid.\",\n );\n }\n}\n\nexport interface OneTimeProductDiff {\n field: string;\n local: string;\n remote: string;\n}\n\nexport async function diffOneTimeProduct(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n localData: OneTimeProduct,\n): Promise<OneTimeProductDiff[]> {\n const remote = await client.oneTimeProducts.get(packageName, productId);\n const diffs: OneTimeProductDiff[] = [];\n const fieldsToCompare = [\"listings\", \"purchaseType\", \"taxAndComplianceSettings\"];\n\n for (const field of fieldsToCompare) {\n const localVal = JSON.stringify((localData as unknown as Record<string, unknown>)[field] ?? null);\n const remoteVal = JSON.stringify((remote as unknown as Record<string, unknown>)[field] ?? null);\n if (localVal !== remoteVal) {\n diffs.push({ field, local: localVal, remote: remoteVal });\n }\n }\n return diffs;\n}\n\nexport async function deleteOneTimeOffer(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n offerId: string,\n): Promise<void> {\n try {\n await client.oneTimeProducts.deleteOffer(packageName, productId, offerId);\n } catch (error) {\n throw new GpcError(\n `Failed to delete offer \"${offerId}\" for product \"${productId}\": ${error instanceof Error ? error.message : String(error)}`,\n \"OTP_OFFER_DELETE_FAILED\",\n 4,\n \"Check that the product and offer IDs exist.\",\n );\n }\n}\n","import process from \"node:process\";\n\nconst FRAMES = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"];\nconst INTERVAL_MS = 80;\n\nexport interface Spinner {\n start(): void;\n stop(message?: string): void;\n fail(message?: string): void;\n update(message: string): void;\n}\n\nexport function createSpinner(message: string): Spinner {\n const isTTY = process.stderr.isTTY === true;\n let frameIndex = 0;\n let timer: ReturnType<typeof setInterval> | undefined;\n let currentMessage = message;\n let started = false;\n\n function clearLine(): void {\n if (isTTY) {\n process.stderr.write(\"\\r\\x1b[K\");\n }\n }\n\n function renderFrame(): void {\n const frame = FRAMES[frameIndex % FRAMES.length];\n process.stderr.write(`\\r\\x1b[K${frame} ${currentMessage}`);\n frameIndex++;\n }\n\n return {\n start(): void {\n if (started) return;\n started = true;\n\n if (!isTTY) {\n process.stderr.write(`${currentMessage}\\n`);\n return;\n }\n\n renderFrame();\n timer = setInterval(renderFrame, INTERVAL_MS);\n },\n\n stop(msg?: string): void {\n if (timer) {\n clearInterval(timer);\n timer = undefined;\n }\n const text = msg ?? currentMessage;\n if (isTTY) {\n clearLine();\n process.stderr.write(`\\u2714 ${text}\\n`);\n } else if (!started) {\n process.stderr.write(`${text}\\n`);\n }\n started = false;\n },\n\n fail(msg?: string): void {\n if (timer) {\n clearInterval(timer);\n timer = undefined;\n }\n const text = msg ?? currentMessage;\n if (isTTY) {\n clearLine();\n process.stderr.write(`\\u2718 ${text}\\n`);\n } else if (!started) {\n process.stderr.write(`${text}\\n`);\n }\n started = false;\n },\n\n update(msg: string): void {\n currentMessage = msg;\n if (!isTTY || !started) return;\n renderFrame();\n },\n };\n}\n","import { resolve, normalize } from \"node:path\";\nimport { GpcError } from \"../errors.js\";\n\n/**\n * Normalize and resolve a user-supplied path.\n * Prevents path traversal by normalizing `.` and `..` components.\n */\nexport function safePath(userPath: string): string {\n return resolve(normalize(userPath));\n}\n\n/**\n * Validate that a resolved path is within an expected base directory.\n * Returns the resolved path or throws if it escapes the base.\n */\nexport function safePathWithin(userPath: string, baseDir: string): string {\n const resolved = safePath(userPath);\n const base = safePath(baseDir);\n\n if (!resolved.startsWith(base + \"/\") && resolved !== base) {\n throw new GpcError(\n `Path \"${userPath}\" resolves outside the expected directory \"${baseDir}\"`,\n \"PATH_TRAVERSAL\",\n 2,\n \"The path must stay within the target directory. Remove any ../ segments or use an absolute path within the expected directory.\",\n );\n }\n\n return resolved;\n}\n","/**\n * Sort utility for CLI list command results.\n *\n * Supports ascending (field) and descending (-field) sort specs,\n * including dot notation for nested fields (e.g., \"comments.userComment.starRating\").\n */\n\nfunction getNestedValue(obj: unknown, path: string): unknown {\n const parts = path.split(\".\");\n let current: unknown = obj;\n for (const part of parts) {\n if (current === null || current === undefined || typeof current !== \"object\") {\n return undefined;\n }\n current = (current as Record<string, unknown>)[part];\n }\n return current;\n}\n\nfunction compare(a: unknown, b: unknown): number {\n if (a === undefined && b === undefined) return 0;\n if (a === undefined) return 1;\n if (b === undefined) return -1;\n\n if (typeof a === \"number\" && typeof b === \"number\") {\n return a - b;\n }\n\n return String(a).localeCompare(String(b));\n}\n\n/**\n * Sort an array of items by a field specification.\n *\n * @param items - Array to sort (not mutated; returns a new array)\n * @param sortSpec - Field name for ascending, or `-field` for descending.\n * Supports dot notation for nested fields.\n * If undefined/empty, returns items in original order.\n * @returns Sorted copy of items\n */\nexport function sortResults<T>(items: T[], sortSpec?: string): T[] {\n if (!sortSpec || items.length === 0) {\n return items;\n }\n\n const descending = sortSpec.startsWith(\"-\");\n const field = descending ? sortSpec.slice(1) : sortSpec;\n\n // Validate that at least one item has the field — if none do, return original order\n const hasField = items.some((item) => getNestedValue(item, field) !== undefined);\n if (!hasField) {\n return items;\n }\n\n const sorted = [...items].sort((a, b) => {\n const aVal = getNestedValue(a, field);\n const bVal = getNestedValue(b, field);\n const result = compare(aVal, bVal);\n return descending ? -result : result;\n });\n\n return sorted;\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport interface ScaffoldOptions {\n name: string;\n dir: string;\n description?: string;\n}\n\nexport interface ScaffoldResult {\n dir: string;\n files: string[];\n}\n\n/**\n * Scaffold a new GPC plugin project.\n */\nexport async function scaffoldPlugin(options: ScaffoldOptions): Promise<ScaffoldResult> {\n const { name, dir, description = `GPC plugin: ${name}` } = options;\n\n // Ensure name follows convention\n const pluginName = name.startsWith(\"gpc-plugin-\") ? name : `gpc-plugin-${name}`;\n const shortName = pluginName.replace(/^gpc-plugin-/, \"\");\n\n const srcDir = join(dir, \"src\");\n const testDir = join(dir, \"tests\");\n\n await mkdir(srcDir, { recursive: true });\n await mkdir(testDir, { recursive: true });\n\n const files: string[] = [];\n\n // package.json\n const pkg = {\n name: pluginName,\n version: \"0.1.0\",\n description,\n type: \"module\",\n main: \"./dist/index.js\",\n types: \"./dist/index.d.ts\",\n exports: {\n \".\": {\n import: \"./dist/index.js\",\n types: \"./dist/index.d.ts\",\n },\n },\n files: [\"dist\"],\n scripts: {\n build: \"tsup src/index.ts --format esm --dts\",\n dev: \"tsup src/index.ts --format esm --dts --watch\",\n test: \"vitest run\",\n \"test:watch\": \"vitest\",\n },\n keywords: [\"gpc\", \"gpc-plugin\", \"google-play\"],\n license: \"MIT\",\n peerDependencies: {\n \"@gpc-cli/plugin-sdk\": \">=0.8.0\",\n },\n devDependencies: {\n \"@gpc-cli/plugin-sdk\": \"^0.8.0\",\n tsup: \"^8.0.0\",\n typescript: \"^5.0.0\",\n vitest: \"^3.0.0\",\n },\n };\n await writeFile(join(dir, \"package.json\"), JSON.stringify(pkg, null, 2) + \"\\n\");\n files.push(\"package.json\");\n\n // tsconfig.json\n const tsconfig = {\n compilerOptions: {\n target: \"ES2022\",\n module: \"ESNext\",\n moduleResolution: \"bundler\",\n declaration: true,\n strict: true,\n esModuleInterop: true,\n skipLibCheck: true,\n outDir: \"./dist\",\n rootDir: \"./src\",\n },\n include: [\"src\"],\n };\n await writeFile(join(dir, \"tsconfig.json\"), JSON.stringify(tsconfig, null, 2) + \"\\n\");\n files.push(\"tsconfig.json\");\n\n // src/index.ts\n const srcContent = `import { definePlugin } from \"@gpc-cli/plugin-sdk\";\nimport type { CommandEvent, CommandResult } from \"@gpc-cli/plugin-sdk\";\n\nexport const plugin = definePlugin({\n name: \"${pluginName}\",\n version: \"0.1.0\",\n\n register(hooks) {\n hooks.beforeCommand(async (event: CommandEvent) => {\n // Called before every gpc command\n // Example: log command usage, validate prerequisites, etc.\n });\n\n hooks.afterCommand(async (event: CommandEvent, result: CommandResult) => {\n // Called after every successful gpc command\n // Example: send notifications, update dashboards, etc.\n });\n\n // Uncomment to add custom commands:\n // hooks.registerCommands((registry) => {\n // registry.add({\n // name: \"${shortName}\",\n // description: \"${description}\",\n // action: async (args, opts) => {\n // console.log(\"Hello from ${pluginName}!\");\n // },\n // });\n // });\n },\n});\n`;\n await writeFile(join(srcDir, \"index.ts\"), srcContent);\n files.push(\"src/index.ts\");\n\n // tests/plugin.test.ts\n const testContent = `import { describe, it, expect, vi } from \"vitest\";\nimport { plugin } from \"../src/index\";\n\ndescribe(\"${pluginName}\", () => {\n it(\"has correct name and version\", () => {\n expect(plugin.name).toBe(\"${pluginName}\");\n expect(plugin.version).toBe(\"0.1.0\");\n });\n\n it(\"registers without errors\", () => {\n const hooks = {\n beforeCommand: vi.fn(),\n afterCommand: vi.fn(),\n onError: vi.fn(),\n beforeRequest: vi.fn(),\n afterResponse: vi.fn(),\n registerCommands: vi.fn(),\n };\n\n expect(() => plugin.register(hooks)).not.toThrow();\n });\n});\n`;\n await writeFile(join(testDir, \"plugin.test.ts\"), testContent);\n files.push(\"tests/plugin.test.ts\");\n\n return { dir, files };\n}\n","import { appendFile, chmod, mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport interface AuditEntry {\n timestamp: string;\n command: string;\n app?: string;\n args: Record<string, unknown>;\n user?: string;\n success?: boolean;\n durationMs?: number;\n error?: string;\n}\n\nlet auditDir: string | null = null;\n\n/**\n * Initialize audit logging with a directory path.\n * Typically ~/.config/gpc/ or the XDG config dir.\n */\nexport function initAudit(configDir: string): void {\n auditDir = configDir;\n}\n\n/**\n * Write an audit log entry. Non-blocking — errors are silently ignored.\n */\nexport async function writeAuditLog(entry: AuditEntry): Promise<void> {\n if (!auditDir) return;\n\n try {\n await mkdir(auditDir, { recursive: true, mode: 0o700 });\n const logPath = join(auditDir, \"audit.log\");\n const redactedEntry = redactAuditArgs(entry);\n const line = JSON.stringify(redactedEntry) + \"\\n\";\n await appendFile(logPath, line, { encoding: \"utf-8\", mode: 0o600 });\n await chmod(logPath, 0o600).catch(() => {});\n } catch {\n // Audit logging must never break the CLI\n }\n}\n\nconst SENSITIVE_ARG_KEYS = new Set([\n \"keyFile\",\n \"key_file\",\n \"serviceAccount\",\n \"service-account\",\n \"token\",\n \"password\",\n \"secret\",\n \"credentials\",\n \"private_key\",\n \"privateKey\",\n \"private_key_id\",\n \"privateKeyId\",\n \"client_secret\",\n \"clientSecret\",\n \"accessToken\",\n \"access_token\",\n \"refreshToken\",\n \"refresh_token\",\n \"apiKey\",\n \"api_key\",\n \"auth_token\",\n \"bearer\",\n \"jwt\",\n \"signing_key\",\n \"keystore_password\",\n \"store_password\",\n \"key_password\",\n]);\n\nexport { SENSITIVE_ARG_KEYS };\n\nexport function redactAuditArgs(entry: AuditEntry): AuditEntry {\n const redacted: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(entry.args)) {\n redacted[k] = SENSITIVE_ARG_KEYS.has(k) ? \"[REDACTED]\" : v;\n }\n return { ...entry, args: redacted };\n}\n\n/**\n * Convenience: create an audit entry for a write command.\n */\nexport function createAuditEntry(\n command: string,\n args: Record<string, unknown>,\n app?: string,\n): AuditEntry {\n return {\n timestamp: new Date().toISOString(),\n command,\n app,\n args,\n };\n}\n\nexport async function listAuditEvents(options?: {\n limit?: number;\n since?: string;\n command?: string;\n}): Promise<AuditEntry[]> {\n if (!auditDir) return [];\n const logPath = join(auditDir, \"audit.log\");\n let content: string;\n try {\n content = await readFile(logPath, \"utf-8\");\n } catch {\n return [];\n }\n const lines = content.trim().split(\"\\n\").filter(Boolean);\n let entries: AuditEntry[] = [];\n for (const line of lines) {\n try {\n entries.push(JSON.parse(line) as AuditEntry);\n } catch {\n // skip malformed lines\n }\n }\n if (options?.since) {\n const sinceDate = new Date(options.since).getTime();\n entries = entries.filter((e) => new Date(e.timestamp).getTime() >= sinceDate);\n }\n if (options?.command) {\n const cmd = options.command.toLowerCase();\n entries = entries.filter((e) => e.command.toLowerCase().includes(cmd));\n }\n if (options?.limit) {\n entries = entries.slice(-options.limit);\n }\n return entries;\n}\n\nexport async function searchAuditEvents(query: string): Promise<AuditEntry[]> {\n const all = await listAuditEvents();\n const q = query.toLowerCase();\n return all.filter((e) => {\n const text = JSON.stringify(e).toLowerCase();\n return text.includes(q);\n });\n}\n\nexport async function clearAuditLog(options?: {\n before?: string;\n dryRun?: boolean;\n}): Promise<{ deleted: number; remaining: number }> {\n if (!auditDir) return { deleted: 0, remaining: 0 };\n const logPath = join(auditDir, \"audit.log\");\n let content: string;\n try {\n content = await readFile(logPath, \"utf-8\");\n } catch {\n return { deleted: 0, remaining: 0 };\n }\n const lines = content.trim().split(\"\\n\").filter(Boolean);\n if (!options?.before) {\n const count = lines.length;\n if (!options?.dryRun) {\n await writeFile(logPath, \"\", { encoding: \"utf-8\", mode: 0o600 });\n }\n return { deleted: count, remaining: 0 };\n }\n const beforeDate = new Date(options.before).getTime();\n const keep: string[] = [];\n const remove: string[] = [];\n for (const line of lines) {\n try {\n const entry = JSON.parse(line) as AuditEntry;\n if (new Date(entry.timestamp).getTime() < beforeDate) {\n remove.push(line);\n } else {\n keep.push(line);\n }\n } catch {\n keep.push(line);\n }\n }\n if (!options?.dryRun) {\n await writeFile(logPath, keep.length > 0 ? keep.join(\"\\n\") + \"\\n\" : \"\", {\n encoding: \"utf-8\",\n mode: 0o600,\n });\n }\n return { deleted: remove.length, remaining: keep.length };\n}\n","import type { WebhookConfig } from \"@gpc-cli/config\";\n\nexport interface WebhookPayload {\n command: string;\n success: boolean;\n duration: number;\n app?: string;\n details?: Record<string, unknown>;\n error?: string;\n}\n\nexport function formatSlackPayload(payload: WebhookPayload): object {\n const status = payload.success ? \"\\u2713\" : \"\\u2717\";\n const color = payload.success ? \"#2eb886\" : \"#e01e5a\";\n const durationSec = (payload.duration / 1000).toFixed(1);\n\n const fields: Array<{ title: string; value: string; short: boolean }> = [\n { title: \"Command\", value: payload.command, short: true },\n { title: \"Duration\", value: `${durationSec}s`, short: true },\n ];\n\n if (payload.app) {\n fields.push({ title: \"App\", value: payload.app, short: true });\n }\n\n if (payload.error) {\n fields.push({ title: \"Error\", value: payload.error, short: false });\n }\n\n if (payload.details) {\n for (const [key, value] of Object.entries(payload.details)) {\n fields.push({ title: key, value: String(value), short: true });\n }\n }\n\n return {\n attachments: [\n {\n color,\n fallback: `GPC: ${payload.command} ${status}`,\n title: `GPC: ${payload.command} ${status}`,\n fields,\n footer: \"GPC CLI\",\n ts: Math.floor(Date.now() / 1000),\n },\n ],\n };\n}\n\nexport function formatDiscordPayload(payload: WebhookPayload): object {\n const status = payload.success ? \"\\u2713\" : \"\\u2717\";\n const color = payload.success ? 0x2eb886 : 0xe01e5a;\n const durationSec = (payload.duration / 1000).toFixed(1);\n\n const fields: Array<{ name: string; value: string; inline: boolean }> = [\n { name: \"Command\", value: payload.command, inline: true },\n { name: \"Duration\", value: `${durationSec}s`, inline: true },\n ];\n\n if (payload.app) {\n fields.push({ name: \"App\", value: payload.app, inline: true });\n }\n\n if (payload.error) {\n fields.push({ name: \"Error\", value: payload.error, inline: false });\n }\n\n if (payload.details) {\n for (const [key, value] of Object.entries(payload.details)) {\n fields.push({ name: key, value: String(value), inline: true });\n }\n }\n\n return {\n embeds: [\n {\n title: `GPC: ${payload.command} ${status}`,\n color,\n fields,\n footer: { text: \"GPC CLI\" },\n timestamp: new Date().toISOString(),\n },\n ],\n };\n}\n\nexport function formatCustomPayload(payload: WebhookPayload): object {\n return { ...payload };\n}\n\ntype WebhookTarget = \"slack\" | \"discord\" | \"custom\";\n\nconst FORMATTERS: Record<WebhookTarget, (p: WebhookPayload) => object> = {\n slack: formatSlackPayload,\n discord: formatDiscordPayload,\n custom: formatCustomPayload,\n};\n\nconst WEBHOOK_TIMEOUT_MS = 5000;\n\nasync function sendSingle(url: string, body: object): Promise<void> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), WEBHOOK_TIMEOUT_MS);\n\n try {\n await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function sendWebhook(\n config: WebhookConfig,\n payload: WebhookPayload,\n target?: string,\n): Promise<void> {\n try {\n const targets: WebhookTarget[] = target\n ? [target as WebhookTarget]\n : (Object.keys(FORMATTERS) as WebhookTarget[]);\n\n const promises: Promise<void>[] = [];\n\n for (const t of targets) {\n const url = config[t];\n if (!url) continue;\n\n const formatter = FORMATTERS[t];\n if (!formatter) continue;\n\n const body = formatter(payload);\n promises.push(sendSingle(url, body).catch(() => {}));\n }\n\n await Promise.all(promises);\n } catch {\n // Never throw — webhook failures must not break the CLI\n }\n}\n","import { extname } from \"node:path\";\nimport type { PlayApiClient, InternalAppSharingArtifact } from \"@gpc-cli/api\";\nimport { GpcError } from \"../errors.js\";\nimport { validateUploadFile } from \"../utils/file-validation.js\";\n\nexport interface InternalSharingUploadResult {\n downloadUrl: string;\n sha256: string;\n certificateFingerprint: string;\n fileType: \"bundle\" | \"apk\";\n}\n\nexport async function uploadInternalSharing(\n client: PlayApiClient,\n packageName: string,\n filePath: string,\n fileType?: \"bundle\" | \"apk\",\n): Promise<InternalSharingUploadResult> {\n // Auto-detect file type from extension if not provided\n const resolvedType = fileType ?? detectFileType(filePath);\n\n // Validate the file\n const validation = await validateUploadFile(filePath);\n if (!validation.valid) {\n throw new GpcError(\n `File validation failed:\\n${validation.errors.join(\"\\n\")}`,\n \"INTERNAL_SHARING_INVALID_FILE\",\n 2,\n \"Check that the file is a valid AAB or APK and is not corrupted.\",\n );\n }\n\n let artifact: InternalAppSharingArtifact;\n if (resolvedType === \"bundle\") {\n artifact = await client.internalAppSharing.uploadBundle(packageName, filePath);\n } else {\n artifact = await client.internalAppSharing.uploadApk(packageName, filePath);\n }\n\n return {\n downloadUrl: artifact.downloadUrl,\n sha256: artifact.sha256,\n certificateFingerprint: artifact.certificateFingerprint,\n fileType: resolvedType,\n };\n}\n\nfunction detectFileType(filePath: string): \"bundle\" | \"apk\" {\n const ext = extname(filePath).toLowerCase();\n if (ext === \".aab\") return \"bundle\";\n if (ext === \".apk\") return \"apk\";\n throw new GpcError(\n `Cannot detect file type from extension \"${ext}\". Use --type to specify bundle or apk.`,\n \"INTERNAL_SHARING_UNKNOWN_TYPE\",\n 2,\n \"Use --type bundle for .aab files or --type apk for .apk files.\",\n );\n}\n","import { writeFile } from \"node:fs/promises\";\nimport type { PlayApiClient, GeneratedApk } from \"@gpc-cli/api\";\nimport { GpcError } from \"../errors.js\";\n\nexport async function listGeneratedApks(\n client: PlayApiClient,\n packageName: string,\n versionCode: number,\n): Promise<GeneratedApk[]> {\n if (!Number.isInteger(versionCode) || versionCode <= 0) {\n throw new GpcError(\n `Invalid version code: ${versionCode}`,\n \"GENERATED_APKS_INVALID_VERSION\",\n 2,\n \"Provide a positive integer version code.\",\n );\n }\n return client.generatedApks.list(packageName, versionCode);\n}\n\nexport async function downloadGeneratedApk(\n client: PlayApiClient,\n packageName: string,\n versionCode: number,\n apkId: string,\n outputPath: string,\n): Promise<{ path: string; sizeBytes: number }> {\n if (!Number.isInteger(versionCode) || versionCode <= 0) {\n throw new GpcError(\n `Invalid version code: ${versionCode}`,\n \"GENERATED_APKS_INVALID_VERSION\",\n 2,\n \"Provide a positive integer version code.\",\n );\n }\n\n if (!apkId) {\n throw new GpcError(\n \"APK ID is required\",\n \"GENERATED_APKS_MISSING_ID\",\n 2,\n \"Provide the generated APK ID. Use 'gpc generated-apks list <version-code>' to see available APKs.\",\n );\n }\n\n const buffer = await client.generatedApks.download(packageName, versionCode, apkId);\n const bytes = new Uint8Array(buffer);\n await writeFile(outputPath, bytes);\n\n return { path: outputPath, sizeBytes: bytes.byteLength };\n}\n","import type { PlayApiClient, PurchaseOption, PurchaseOptionsListResponse } from \"@gpc-cli/api\";\nimport { GpcError } from \"../errors.js\";\n\nexport async function listPurchaseOptions(\n client: PlayApiClient,\n packageName: string,\n): Promise<PurchaseOptionsListResponse> {\n try {\n return await client.purchaseOptions.list(packageName);\n } catch (error) {\n throw new GpcError(\n `Failed to list purchase options: ${error instanceof Error ? error.message : String(error)}`,\n \"PURCHASE_OPTIONS_LIST_FAILED\",\n 4,\n \"Check your package name and API permissions.\",\n );\n }\n}\n\nexport async function getPurchaseOption(\n client: PlayApiClient,\n packageName: string,\n purchaseOptionId: string,\n): Promise<PurchaseOption> {\n try {\n return await client.purchaseOptions.get(packageName, purchaseOptionId);\n } catch (error) {\n throw new GpcError(\n `Failed to get purchase option \"${purchaseOptionId}\": ${error instanceof Error ? error.message : String(error)}`,\n \"PURCHASE_OPTION_GET_FAILED\",\n 4,\n \"Check that the purchase option ID exists.\",\n );\n }\n}\n\nexport async function createPurchaseOption(\n client: PlayApiClient,\n packageName: string,\n data: PurchaseOption,\n): Promise<PurchaseOption> {\n try {\n return await client.purchaseOptions.create(packageName, data);\n } catch (error) {\n throw new GpcError(\n `Failed to create purchase option: ${error instanceof Error ? error.message : String(error)}`,\n \"PURCHASE_OPTION_CREATE_FAILED\",\n 4,\n \"Check your purchase option data and API permissions.\",\n );\n }\n}\n\nexport async function activatePurchaseOption(\n client: PlayApiClient,\n packageName: string,\n purchaseOptionId: string,\n): Promise<PurchaseOption> {\n try {\n return await client.purchaseOptions.activate(packageName, purchaseOptionId);\n } catch (error) {\n throw new GpcError(\n `Failed to activate purchase option \"${purchaseOptionId}\": ${error instanceof Error ? error.message : String(error)}`,\n \"PURCHASE_OPTION_ACTIVATE_FAILED\",\n 4,\n \"Check that the purchase option exists and is in a valid state for activation.\",\n );\n }\n}\n\nexport async function deactivatePurchaseOption(\n client: PlayApiClient,\n packageName: string,\n purchaseOptionId: string,\n): Promise<PurchaseOption> {\n try {\n return await client.purchaseOptions.deactivate(packageName, purchaseOptionId);\n } catch (error) {\n throw new GpcError(\n `Failed to deactivate purchase option \"${purchaseOptionId}\": ${error instanceof Error ? error.message : String(error)}`,\n \"PURCHASE_OPTION_DEACTIVATE_FAILED\",\n 4,\n \"Check that the purchase option exists and is in a valid state for deactivation.\",\n );\n }\n}\n","import { readFile, stat } from \"node:fs/promises\";\n\nexport interface BundleEntry {\n path: string;\n module: string;\n category: string;\n compressedSize: number;\n uncompressedSize: number;\n}\n\nexport interface BundleAnalysis {\n filePath: string;\n fileType: \"aab\" | \"apk\";\n totalCompressed: number;\n totalUncompressed: number;\n entryCount: number;\n modules: { name: string; compressedSize: number; uncompressedSize: number; entries: number }[];\n categories: { name: string; compressedSize: number; uncompressedSize: number; entries: number }[];\n entries: BundleEntry[];\n}\n\nexport interface BundleComparison {\n before: { path: string; totalCompressed: number };\n after: { path: string; totalCompressed: number };\n sizeDelta: number;\n sizeDeltaPercent: number;\n moduleDeltas: { module: string; before: number; after: number; delta: number }[];\n categoryDeltas: { category: string; before: number; after: number; delta: number }[];\n}\n\nconst EOCD_SIGNATURE = 0x06054b50;\nconst CD_SIGNATURE = 0x02014b50;\n\n/** Known AAB module subdirs that distinguish feature modules from arbitrary top-level dirs. */\nconst MODULE_SUBDIRS = new Set([\"dex\", \"manifest\", \"res\", \"assets\", \"lib\", \"resources.pb\", \"root\"]);\n\nfunction detectCategory(path: string): string {\n const lower = path.toLowerCase();\n // dex files\n if (lower.endsWith(\".dex\") || /\\/dex\\/[^/]+\\.dex$/.test(lower)) return \"dex\";\n // resources\n if (\n lower === \"resources.arsc\" ||\n lower.endsWith(\"/resources.arsc\") ||\n lower.endsWith(\"/resources.pb\") ||\n /^(([^/]+\\/)?res\\/)/.test(lower)\n ) return \"resources\";\n // assets\n if (/^(([^/]+\\/)?assets\\/)/.test(lower)) return \"assets\";\n // native libs\n if (/^(([^/]+\\/)?lib\\/)/.test(lower)) return \"native-libs\";\n // manifest\n if (\n lower === \"androidmanifest.xml\" ||\n lower.endsWith(\"/androidmanifest.xml\") ||\n /^(([^/]+\\/)?manifest\\/)/.test(lower)\n ) return \"manifest\";\n // signing\n if (lower.startsWith(\"meta-inf/\") || lower === \"meta-inf\") return \"signing\";\n return \"other\";\n}\n\nfunction detectModule(path: string, isAab: boolean): string {\n if (!isAab) return \"(root)\";\n\n const slashIdx = path.indexOf(\"/\");\n if (slashIdx === -1) return \"(root)\";\n\n const topDir = path.substring(0, slashIdx);\n const rest = path.substring(slashIdx + 1);\n\n // \"base/\" module\n if (topDir === \"base\") return \"base\";\n\n // Root-level metadata\n if (topDir === \"BUNDLE-METADATA\" || topDir === \"META-INF\") return \"(root)\";\n if (path === \"BundleConfig.pb\") return \"(root)\";\n\n // Check if subdirectory matches known module structure\n const subDir = rest.split(\"/\")[0] || \"\";\n if (MODULE_SUBDIRS.has(subDir)) return topDir;\n\n return \"(root)\";\n}\n\ninterface CentralDirectoryEntry {\n filename: string;\n compressedSize: number;\n uncompressedSize: number;\n}\n\nfunction parseCentralDirectory(buf: Buffer): CentralDirectoryEntry[] {\n // Find EOCD — scan backwards from end (minimum EOCD is 22 bytes)\n let eocdOffset = -1;\n for (let i = buf.length - 22; i >= 0 && i >= buf.length - 65557; i--) {\n if (buf.readUInt32LE(i) === EOCD_SIGNATURE) {\n eocdOffset = i;\n break;\n }\n }\n if (eocdOffset === -1) {\n throw new Error(\"Not a valid ZIP file: EOCD signature not found\");\n }\n\n const cdSize = buf.readUInt32LE(eocdOffset + 12);\n let cdOffset = buf.readUInt32LE(eocdOffset + 16);\n\n // Handle ZIP64 — if offset is 0xFFFFFFFF, look for ZIP64 EOCD locator\n if (cdOffset === 0xffffffff) {\n // ZIP64 end of central directory locator is 20 bytes before EOCD\n const zip64LocatorOffset = eocdOffset - 20;\n if (zip64LocatorOffset >= 0 && buf.readUInt32LE(zip64LocatorOffset) === 0x07064b50) {\n // ZIP64 EOCD is at offset stored in locator bytes 8-15\n const zip64EocdOffset = Number(buf.readBigUInt64LE(zip64LocatorOffset + 8));\n if (zip64EocdOffset >= 0 && zip64EocdOffset < buf.length) {\n cdOffset = Number(buf.readBigUInt64LE(zip64EocdOffset + 48));\n }\n }\n }\n\n const entries: CentralDirectoryEntry[] = [];\n let pos = cdOffset;\n const end = cdOffset + cdSize;\n\n while (pos < end && pos + 46 <= buf.length) {\n const sig = buf.readUInt32LE(pos);\n if (sig !== CD_SIGNATURE) break;\n\n const compressedSize = buf.readUInt32LE(pos + 20);\n const uncompressedSize = buf.readUInt32LE(pos + 24);\n const filenameLen = buf.readUInt16LE(pos + 28);\n const extraLen = buf.readUInt16LE(pos + 30);\n const commentLen = buf.readUInt16LE(pos + 32);\n\n const filename = buf.toString(\"utf-8\", pos + 46, pos + 46 + filenameLen);\n\n // Skip directory entries (trailing slash)\n if (!filename.endsWith(\"/\")) {\n entries.push({ filename, compressedSize, uncompressedSize });\n }\n\n pos += 46 + filenameLen + extraLen + commentLen;\n }\n\n return entries;\n}\n\nfunction detectFileType(filePath: string): \"aab\" | \"apk\" {\n const lower = filePath.toLowerCase();\n if (lower.endsWith(\".aab\")) return \"aab\";\n return \"apk\";\n}\n\nexport async function analyzeBundle(filePath: string): Promise<BundleAnalysis> {\n const fileInfo = await stat(filePath).catch(() => null);\n if (!fileInfo || !fileInfo.isFile()) {\n throw new Error(`File not found: ${filePath}`);\n }\n\n const buf = await readFile(filePath);\n const cdEntries = parseCentralDirectory(buf);\n const fileType = detectFileType(filePath);\n const isAab = fileType === \"aab\";\n\n const entries: BundleEntry[] = cdEntries.map((e) => ({\n path: e.filename,\n module: detectModule(e.filename, isAab),\n category: detectCategory(e.filename),\n compressedSize: e.compressedSize,\n uncompressedSize: e.uncompressedSize,\n }));\n\n // Aggregate by module\n const moduleMap = new Map<string, { compressedSize: number; uncompressedSize: number; entries: number }>();\n for (const entry of entries) {\n const existing = moduleMap.get(entry.module) ?? { compressedSize: 0, uncompressedSize: 0, entries: 0 };\n existing.compressedSize += entry.compressedSize;\n existing.uncompressedSize += entry.uncompressedSize;\n existing.entries += 1;\n moduleMap.set(entry.module, existing);\n }\n\n // Aggregate by category\n const categoryMap = new Map<string, { compressedSize: number; uncompressedSize: number; entries: number }>();\n for (const entry of entries) {\n const existing = categoryMap.get(entry.category) ?? { compressedSize: 0, uncompressedSize: 0, entries: 0 };\n existing.compressedSize += entry.compressedSize;\n existing.uncompressedSize += entry.uncompressedSize;\n existing.entries += 1;\n categoryMap.set(entry.category, existing);\n }\n\n const modules = [...moduleMap.entries()]\n .map(([name, data]) => ({ name, ...data }))\n .sort((a, b) => b.compressedSize - a.compressedSize);\n\n const categories = [...categoryMap.entries()]\n .map(([name, data]) => ({ name, ...data }))\n .sort((a, b) => b.compressedSize - a.compressedSize);\n\n const totalCompressed = entries.reduce((sum, e) => sum + e.compressedSize, 0);\n const totalUncompressed = entries.reduce((sum, e) => sum + e.uncompressedSize, 0);\n\n return {\n filePath,\n fileType,\n totalCompressed,\n totalUncompressed,\n entryCount: entries.length,\n modules,\n categories,\n entries,\n };\n}\n\nexport function compareBundles(before: BundleAnalysis, after: BundleAnalysis): BundleComparison {\n const sizeDelta = after.totalCompressed - before.totalCompressed;\n const sizeDeltaPercent = before.totalCompressed > 0\n ? Math.round(((sizeDelta / before.totalCompressed) * 100) * 10) / 10\n : 0;\n\n // Module deltas\n const allModules = new Set([\n ...before.modules.map((m) => m.name),\n ...after.modules.map((m) => m.name),\n ]);\n const moduleDeltas = [...allModules].map((module) => {\n const b = before.modules.find((m) => m.name === module)?.compressedSize ?? 0;\n const a = after.modules.find((m) => m.name === module)?.compressedSize ?? 0;\n return { module, before: b, after: a, delta: a - b };\n }).sort((a, b) => Math.abs(b.delta) - Math.abs(a.delta));\n\n // Category deltas\n const allCategories = new Set([\n ...before.categories.map((c) => c.name),\n ...after.categories.map((c) => c.name),\n ]);\n const categoryDeltas = [...allCategories].map((category) => {\n const b = before.categories.find((c) => c.name === category)?.compressedSize ?? 0;\n const a = after.categories.find((c) => c.name === category)?.compressedSize ?? 0;\n return { category, before: b, after: a, delta: a - b };\n }).sort((a, b) => Math.abs(b.delta) - Math.abs(a.delta));\n\n return {\n before: { path: before.filePath, totalCompressed: before.totalCompressed },\n after: { path: after.filePath, totalCompressed: after.totalCompressed },\n sizeDelta,\n sizeDeltaPercent,\n moduleDeltas,\n categoryDeltas,\n };\n}\n","import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { PlayApiClient } from \"@gpc-cli/api\";\nimport type { ReportingApiClient } from \"@gpc-cli/api\";\nimport { getCacheDir } from \"@gpc-cli/config\";\nimport { getReleasesStatus } from \"./releases.js\";\nimport { listReviews } from \"./reviews.js\";\nimport type { VitalsMetricSet, MetricSetQuery } from \"@gpc-cli/api\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface StatusVitalMetric {\n value: number | undefined;\n threshold: number;\n status: \"ok\" | \"warn\" | \"breach\" | \"unknown\";\n}\n\nexport interface StatusRelease {\n track: string;\n versionCode: string;\n status: string;\n userFraction: number | null;\n}\n\nexport interface StatusReviews {\n windowDays: number;\n averageRating: number | undefined;\n previousAverageRating: number | undefined;\n totalNew: number;\n positivePercent: number | undefined;\n}\n\nexport interface AppStatus {\n packageName: string;\n fetchedAt: string;\n cached: boolean;\n releases: StatusRelease[];\n vitals: {\n windowDays: number;\n crashes: StatusVitalMetric;\n anr: StatusVitalMetric;\n slowStarts: StatusVitalMetric;\n slowRender: StatusVitalMetric;\n };\n reviews: StatusReviews;\n}\n\nexport interface GetAppStatusOptions {\n days?: number;\n vitalThresholds?: {\n crashRate?: number;\n anrRate?: number;\n slowStartRate?: number;\n slowRenderingRate?: number;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Cache\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_TTL_SECONDS = 3600;\n\ninterface CacheEntry {\n fetchedAt: string;\n ttl: number;\n data: AppStatus;\n}\n\nfunction cacheFilePath(packageName: string): string {\n return join(getCacheDir(), `status-${packageName}.json`);\n}\n\nexport async function loadStatusCache(\n packageName: string,\n ttlSeconds = DEFAULT_TTL_SECONDS,\n): Promise<AppStatus | null> {\n try {\n const raw = await readFile(cacheFilePath(packageName), \"utf-8\");\n const entry = JSON.parse(raw) as CacheEntry;\n const age = (Date.now() - new Date(entry.fetchedAt).getTime()) / 1000;\n if (age > (entry.ttl ?? ttlSeconds)) return null;\n return { ...entry.data, cached: true };\n } catch {\n return null;\n }\n}\n\nexport async function saveStatusCache(\n packageName: string,\n data: AppStatus,\n ttlSeconds = DEFAULT_TTL_SECONDS,\n): Promise<void> {\n try {\n const dir = getCacheDir();\n await mkdir(dir, { recursive: true });\n const entry: CacheEntry = {\n fetchedAt: data.fetchedAt,\n ttl: ttlSeconds,\n data,\n };\n await writeFile(cacheFilePath(packageName), JSON.stringify(entry, null, 2), { encoding: \"utf-8\", mode: 0o600 });\n } catch {\n // Cache write failures must never break the command\n }\n}\n\n// ---------------------------------------------------------------------------\n// Vitals helpers\n// ---------------------------------------------------------------------------\n\nconst METRIC_SET_METRICS: Partial<Record<VitalsMetricSet, string[]>> = {\n crashRateMetricSet: [\"crashRate\", \"userPerceivedCrashRate\", \"distinctUsers\"],\n anrRateMetricSet: [\"anrRate\", \"userPerceivedAnrRate\", \"distinctUsers\"],\n slowStartRateMetricSet: [\"slowStartRate\", \"distinctUsers\"],\n slowRenderingRateMetricSet: [\"slowRenderingRate\", \"distinctUsers\"],\n};\n\nconst DEFAULT_THRESHOLDS = {\n crashRate: 0.02,\n anrRate: 0.01,\n slowStartRate: 0.05,\n slowRenderingRate: 0.1,\n};\n\nconst WARN_MARGIN = 0.2; // within 20% of threshold → warn\n\nfunction toApiDate(d: Date): { year: number; month: number; day: number } {\n return { year: d.getUTCFullYear(), month: d.getUTCMonth() + 1, day: d.getUTCDate() };\n}\n\nasync function queryVitalForStatus(\n reporting: ReportingApiClient,\n packageName: string,\n metricSet: VitalsMetricSet,\n days: number,\n): Promise<number | undefined> {\n const DAY_MS = 24 * 60 * 60 * 1000;\n const baseMs = Date.now() - 2 * DAY_MS;\n const end = new Date(baseMs);\n const start = new Date(baseMs - days * DAY_MS);\n const metrics = METRIC_SET_METRICS[metricSet] ?? [\"distinctUsers\"];\n\n const query: MetricSetQuery = {\n metrics,\n timelineSpec: {\n aggregationPeriod: \"DAILY\",\n startTime: toApiDate(start),\n endTime: toApiDate(end),\n },\n };\n\n const result = await reporting.queryMetricSet(packageName, metricSet, query);\n if (!result.rows || result.rows.length === 0) return undefined;\n\n const values = result.rows\n .map((row) => {\n const firstKey = Object.keys(row.metrics)[0];\n return firstKey ? Number(row.metrics[firstKey]?.decimalValue?.value) : NaN;\n })\n .filter((v) => !isNaN(v));\n\n if (values.length === 0) return undefined;\n return values.reduce((a, b) => a + b, 0) / values.length;\n}\n\nfunction toVitalMetric(\n value: number | undefined,\n threshold: number,\n): StatusVitalMetric {\n if (value === undefined) {\n return { value: undefined, threshold, status: \"unknown\" };\n }\n if (value > threshold) return { value, threshold, status: \"breach\" };\n if (value > threshold * (1 - WARN_MARGIN)) return { value, threshold, status: \"warn\" };\n return { value, threshold, status: \"ok\" };\n}\n\n// ---------------------------------------------------------------------------\n// Reviews helpers\n// ---------------------------------------------------------------------------\n\nfunction computeReviewSentiment(\n reviews: Awaited<ReturnType<typeof listReviews>>,\n windowDays: number,\n): StatusReviews {\n const now = Date.now();\n const DAY_MS = 24 * 60 * 60 * 1000;\n const windowMs = windowDays * DAY_MS;\n const prevWindowStart = now - 2 * windowMs;\n const curWindowStart = now - windowMs;\n\n const current = reviews.filter((r) => {\n const uc = r.comments?.[0]?.userComment;\n if (!uc) return false;\n const ts = Number(uc.lastModified.seconds) * 1000;\n return ts >= curWindowStart;\n });\n\n const previous = reviews.filter((r) => {\n const uc = r.comments?.[0]?.userComment;\n if (!uc) return false;\n const ts = Number(uc.lastModified.seconds) * 1000;\n return ts >= prevWindowStart && ts < curWindowStart;\n });\n\n const avgRating = (items: typeof reviews): number | undefined => {\n const ratings = items\n .map((r) => r.comments?.[0]?.userComment?.starRating)\n .filter((v): v is number => v !== undefined && v > 0);\n if (ratings.length === 0) return undefined;\n return Math.round((ratings.reduce((a, b) => a + b, 0) / ratings.length) * 10) / 10;\n };\n\n const positiveCount = current.filter(\n (r) => (r.comments?.[0]?.userComment?.starRating ?? 0) >= 4,\n ).length;\n\n const positivePercent =\n current.length > 0\n ? Math.round((positiveCount / current.length) * 100)\n : undefined;\n\n return {\n windowDays,\n averageRating: avgRating(current),\n previousAverageRating: avgRating(previous),\n totalNew: current.length,\n positivePercent,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Main orchestrator\n// ---------------------------------------------------------------------------\n\nexport async function getAppStatus(\n client: PlayApiClient,\n reporting: ReportingApiClient,\n packageName: string,\n options: GetAppStatusOptions = {},\n): Promise<AppStatus> {\n const days = options.days ?? 7;\n const thresholds = {\n crashRate: options.vitalThresholds?.crashRate ?? DEFAULT_THRESHOLDS.crashRate,\n anrRate: options.vitalThresholds?.anrRate ?? DEFAULT_THRESHOLDS.anrRate,\n slowStartRate: options.vitalThresholds?.slowStartRate ?? DEFAULT_THRESHOLDS.slowStartRate,\n slowRenderingRate:\n options.vitalThresholds?.slowRenderingRate ?? DEFAULT_THRESHOLDS.slowRenderingRate,\n };\n\n // Fire all 6 calls in parallel; use allSettled so partial failures show \"unknown\"\n const [releasesResult, crashesResult, anrResult, slowStartResult, slowRenderResult, reviewsResult] =\n await Promise.allSettled([\n getReleasesStatus(client, packageName),\n queryVitalForStatus(reporting, packageName, \"crashRateMetricSet\", days),\n queryVitalForStatus(reporting, packageName, \"anrRateMetricSet\", days),\n queryVitalForStatus(reporting, packageName, \"slowStartRateMetricSet\", days),\n queryVitalForStatus(reporting, packageName, \"slowRenderingRateMetricSet\", days),\n listReviews(client, packageName, { maxResults: 500 }),\n ]);\n\n // Releases\n const rawReleases =\n releasesResult.status === \"fulfilled\" ? releasesResult.value : [];\n const releases: StatusRelease[] = rawReleases.map((r) => ({\n track: r.track,\n versionCode: r.versionCodes[r.versionCodes.length - 1] ?? \"—\",\n status: r.status,\n userFraction: r.userFraction ?? null,\n }));\n\n // Vitals\n const crashValue =\n crashesResult.status === \"fulfilled\" ? crashesResult.value : undefined;\n const anrValue =\n anrResult.status === \"fulfilled\" ? anrResult.value : undefined;\n const slowStartValue =\n slowStartResult.status === \"fulfilled\" ? slowStartResult.value : undefined;\n const slowRenderValue =\n slowRenderResult.status === \"fulfilled\" ? slowRenderResult.value : undefined;\n\n // Reviews\n const rawReviews =\n reviewsResult.status === \"fulfilled\" ? reviewsResult.value : [];\n const reviews = computeReviewSentiment(rawReviews, 30);\n\n const fetchedAt = new Date().toISOString();\n\n return {\n packageName,\n fetchedAt,\n cached: false,\n releases,\n vitals: {\n windowDays: days,\n crashes: toVitalMetric(crashValue, thresholds.crashRate),\n anr: toVitalMetric(anrValue, thresholds.anrRate),\n slowStarts: toVitalMetric(slowStartValue, thresholds.slowStartRate),\n slowRender: toVitalMetric(slowRenderValue, thresholds.slowRenderingRate),\n },\n reviews,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Table formatter\n// ---------------------------------------------------------------------------\n\nfunction vitalIndicator(metric: StatusVitalMetric): string {\n if (metric.status === \"unknown\") return \"?\";\n if (metric.status === \"breach\") return \"✗\";\n if (metric.status === \"warn\") return \"⚠\";\n return \"✓\";\n}\n\nfunction formatVitalValue(metric: StatusVitalMetric): string {\n if (metric.value === undefined) return \"n/a\";\n return `${(metric.value * 100).toFixed(2)}%`;\n}\n\nfunction formatFraction(fraction: number | null): string {\n if (fraction === null) return \"—\";\n return `${Math.round(fraction * 100)}%`;\n}\n\nfunction formatRating(rating: number | undefined): string {\n if (rating === undefined) return \"n/a\";\n return `★ ${rating.toFixed(1)}`;\n}\n\nfunction formatTrend(current: number | undefined, previous: number | undefined): string {\n if (current === undefined || previous === undefined) return \"\";\n if (current > previous) return ` ↑ from ${previous.toFixed(1)}`;\n if (current < previous) return ` ↓ from ${previous.toFixed(1)}`;\n return \"\";\n}\n\nexport function formatStatusTable(status: AppStatus): string {\n const lines: string[] = [];\n const cachedLabel = status.cached\n ? ` (cached ${new Date(status.fetchedAt).toLocaleTimeString()})`\n : ` (fetched ${new Date(status.fetchedAt).toLocaleTimeString()})`;\n\n lines.push(`App: ${status.packageName}${cachedLabel}`);\n lines.push(\"\");\n\n // Releases\n lines.push(\"RELEASES\");\n if (status.releases.length === 0) {\n lines.push(\" No releases found.\");\n } else {\n const trackW = Math.max(10, ...status.releases.map((r) => r.track.length));\n const versionW = Math.max(7, ...status.releases.map((r) => r.versionCode.length));\n const statusW = Math.max(8, ...status.releases.map((r) => r.status.length));\n for (const r of status.releases) {\n lines.push(\n ` ${r.track.padEnd(trackW)} ${r.versionCode.padEnd(versionW)} ${r.status.padEnd(statusW)} ${formatFraction(r.userFraction)}`,\n );\n }\n }\n\n // Vitals\n lines.push(\"\");\n lines.push(`VITALS (last ${status.vitals.windowDays} days)`);\n const { crashes, anr, slowStarts, slowRender } = status.vitals;\n lines.push(\n ` crashes ${formatVitalValue(crashes).padEnd(8)} ${vitalIndicator(crashes)} ` +\n `anr ${formatVitalValue(anr).padEnd(8)} ${vitalIndicator(anr)}`,\n );\n lines.push(\n ` slow starts ${formatVitalValue(slowStarts).padEnd(8)} ${vitalIndicator(slowStarts)} ` +\n `slow render ${formatVitalValue(slowRender).padEnd(8)} ${vitalIndicator(slowRender)}`,\n );\n\n // Reviews\n lines.push(\"\");\n lines.push(`REVIEWS (last ${status.reviews.windowDays} days)`);\n const { averageRating, previousAverageRating, totalNew, positivePercent } = status.reviews;\n const trend = formatTrend(averageRating, previousAverageRating);\n const positiveStr = positivePercent !== undefined ? ` ${positivePercent}% positive` : \"\";\n lines.push(\n ` ${formatRating(averageRating)} ${totalNew} new${positiveStr}${trend}`,\n );\n\n return lines.join(\"\\n\");\n}\n\n// ---------------------------------------------------------------------------\n// Status indicator for exit code (mirrors gpc vitals behaviour)\n// ---------------------------------------------------------------------------\n\nexport function statusHasBreach(status: AppStatus): boolean {\n return (\n status.vitals.crashes.status === \"breach\" ||\n status.vitals.anr.status === \"breach\" ||\n status.vitals.slowStarts.status === \"breach\" ||\n status.vitals.slowRender.status === \"breach\"\n );\n}\n"],"mappings":"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","names":["edit","stat","extname","formatSize","readFile","stat","mkdir","writeFile","join","readdir","readFile","writeFile","mkdir","join","readdir","readFile","stat","extname","join","readdir","extname","join","stat","readFile","stat","formatSize","stat","upload","toApiDate","paginateAll","paginateAll","readdir","readFile","join","paginateAll","paginateAll","readdir","readFile","join","paginateAll","paginateAll","paginateAll","readFile","readFile","readFile","writeFile","writeFile","readFile","process","mkdir","writeFile","join","mkdir","readFile","writeFile","join","join","readFile","writeFile","extname","extname","writeFile","writeFile","readFile","stat","detectFileType","mkdir","readFile","writeFile","join","join","readFile","mkdir","writeFile","METRIC_SET_METRICS"]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/output.ts","../src/plugins.ts","../src/commands/apps.ts","../src/utils/file-validation.ts","../src/commands/releases.ts","../src/utils/bcp47.ts","../src/utils/image-validation.ts","../src/utils/fastlane.ts","../src/commands/listings.ts","../src/commands/migrate.ts","../src/utils/validation.ts","../src/utils/release-notes.ts","../src/commands/validate.ts","../src/commands/publish.ts","../src/commands/reviews.ts","../src/commands/vitals.ts","../src/commands/subscriptions.ts","../src/commands/iap.ts","../src/commands/purchases.ts","../src/commands/pricing.ts","../src/commands/reports.ts","../src/commands/users.ts","../src/commands/testers.ts","../src/utils/git-notes.ts","../src/commands/app-recovery.ts","../src/commands/data-safety.ts","../src/commands/external-transactions.ts","../src/commands/device-tiers.ts","../src/commands/one-time-products.ts","../src/utils/spinner.ts","../src/utils/safe-path.ts","../src/utils/sort.ts","../src/commands/plugin-scaffold.ts","../src/audit.ts","../src/utils/webhooks.ts","../src/commands/internal-sharing.ts","../src/commands/generated-apks.ts","../src/commands/purchase-options.ts","../src/commands/bundle-analysis.ts","../src/commands/status.ts"],"sourcesContent":["export class GpcError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n public readonly exitCode: number,\n public readonly suggestion?: string,\n ) {\n super(message);\n this.name = \"GpcError\";\n }\n\n toJSON() {\n return {\n success: false,\n error: {\n code: this.code,\n message: this.message,\n suggestion: this.suggestion,\n },\n };\n }\n}\n\nexport class ConfigError extends GpcError {\n constructor(message: string, code: string, suggestion?: string) {\n super(message, code, 1, suggestion);\n this.name = \"ConfigError\";\n }\n}\n\nexport class ApiError extends GpcError {\n constructor(\n message: string,\n code: string,\n public readonly statusCode?: number,\n suggestion?: string,\n ) {\n super(message, code, 4, suggestion);\n this.name = \"ApiError\";\n }\n}\n\nexport class NetworkError extends GpcError {\n constructor(message: string, suggestion?: string) {\n super(message, \"NETWORK_ERROR\", 5, suggestion);\n this.name = \"NetworkError\";\n }\n}\n","import type { OutputFormat } from \"@gpc-cli/config\";\nimport process from \"node:process\";\n\nexport function detectOutputFormat(): OutputFormat {\n return process.stdout.isTTY ? \"table\" : \"json\";\n}\n\nexport function formatOutput(data: unknown, format: OutputFormat, redact = true): string {\n const safe = redact ? redactSensitive(data) : data;\n switch (format) {\n case \"json\":\n return formatJson(safe);\n case \"yaml\":\n return formatYaml(safe);\n case \"markdown\":\n return formatMarkdown(safe);\n case \"table\":\n return formatTable(safe);\n case \"junit\":\n return formatJunit(safe);\n default:\n return formatJson(safe);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Sensitive field redaction\n// ---------------------------------------------------------------------------\n\nexport const SENSITIVE_KEYS = new Set([\n \"private_key\",\n \"privateKey\",\n \"private_key_id\",\n \"privateKeyId\",\n \"accessToken\",\n \"access_token\",\n \"refreshToken\",\n \"refresh_token\",\n \"client_secret\",\n \"clientSecret\",\n \"token\",\n \"password\",\n \"secret\",\n \"credentials\",\n \"keyFile\",\n \"key_file\",\n \"serviceAccount\",\n \"service-account\",\n \"apiKey\",\n \"api_key\",\n \"auth_token\",\n \"bearer\",\n \"jwt\",\n \"signing_key\",\n \"keystore_password\",\n \"store_password\",\n \"key_password\",\n]);\n\nconst REDACTED = \"[REDACTED]\";\n\n/** Recursively redact sensitive fields from data before output. */\nexport function redactSensitive(data: unknown): unknown {\n if (data === null || data === undefined) return data;\n\n if (typeof data === \"string\") return data;\n if (typeof data === \"number\" || typeof data === \"boolean\") return data;\n\n if (Array.isArray(data)) {\n return data.map((item) => redactSensitive(item));\n }\n\n if (typeof data === \"object\") {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data as Record<string, unknown>)) {\n if (SENSITIVE_KEYS.has(key) && typeof value === \"string\") {\n result[key] = REDACTED;\n } else {\n result[key] = redactSensitive(value);\n }\n }\n return result;\n }\n\n return data;\n}\n\nfunction formatJson(data: unknown): string {\n return JSON.stringify(data, null, 2);\n}\n\nfunction formatYaml(data: unknown, indent = 0): string {\n if (data === null || data === undefined) {\n return \"null\";\n }\n\n if (typeof data === \"string\") {\n return data.includes(\"\\n\")\n ? `|\\n${data\n .split(\"\\n\")\n .map((l) => `${\" \".repeat(indent + 1)}${l}`)\n .join(\"\\n\")}`\n : data;\n }\n\n if (typeof data === \"number\" || typeof data === \"boolean\") {\n return String(data);\n }\n\n if (Array.isArray(data)) {\n if (data.length === 0) return \"[]\";\n return data\n .map((item) => {\n const value = formatYaml(item, indent + 1);\n const prefix = `${\" \".repeat(indent)}- `;\n if (typeof item === \"object\" && item !== null && !Array.isArray(item)) {\n const lines = value.split(\"\\n\");\n return `${prefix}${lines[0]}\\n${lines\n .slice(1)\n .map((l) => `${\" \".repeat(indent)} ${l}`)\n .join(\"\\n\")}`;\n }\n return `${prefix}${value}`;\n })\n .join(\"\\n\");\n }\n\n if (typeof data === \"object\") {\n const entries = Object.entries(data as Record<string, unknown>);\n if (entries.length === 0) return \"{}\";\n return entries\n .map(([key, value]) => {\n if (typeof value === \"object\" && value !== null) {\n return `${\" \".repeat(indent)}${key}:\\n${formatYaml(value, indent + 1)}`;\n }\n return `${\" \".repeat(indent)}${key}: ${formatYaml(value, indent)}`;\n })\n .join(\"\\n\");\n }\n\n return String(data);\n}\n\nconst MAX_CELL_WIDTH = 60;\n\nfunction truncateCell(value: string): string {\n if (value.length <= MAX_CELL_WIDTH) return value;\n return value.slice(0, MAX_CELL_WIDTH - 3) + \"...\";\n}\n\nfunction cellValue(val: unknown): string {\n if (val === null || val === undefined) return \"\";\n if (typeof val === \"object\") {\n if (Array.isArray(val)) return val.length === 0 ? \"\" : JSON.stringify(val);\n return JSON.stringify(val);\n }\n return String(val);\n}\n\nfunction formatTable(data: unknown): string {\n const rows = toRows(data);\n if (rows.length === 0) return \"\";\n\n const firstRow = rows[0];\n if (!firstRow) return \"\";\n const keys = Object.keys(firstRow);\n if (keys.length === 0) return \"\";\n\n const widths = keys.map((key) =>\n Math.max(key.length, ...rows.map((row) => truncateCell(cellValue(row[key])).length)),\n );\n\n const header = keys.map((key, i) => key.padEnd(widths[i] ?? 0)).join(\" \");\n const separator = widths.map((w) => \"-\".repeat(w)).join(\" \");\n const body = rows\n .map((row) => keys.map((key, i) => truncateCell(cellValue(row[key])).padEnd(widths[i] ?? 0)).join(\" \"))\n .join(\"\\n\");\n\n return `${header}\\n${separator}\\n${body}`;\n}\n\nfunction formatMarkdown(data: unknown): string {\n const rows = toRows(data);\n if (rows.length === 0) return \"\";\n\n const firstRow = rows[0];\n if (!firstRow) return \"\";\n const keys = Object.keys(firstRow);\n if (keys.length === 0) return \"\";\n\n const widths = keys.map((key) =>\n Math.max(key.length, ...rows.map((row) => truncateCell(cellValue(row[key])).length)),\n );\n\n const header = `| ${keys.map((key, i) => key.padEnd(widths[i] ?? 0)).join(\" | \")} |`;\n const separator = `| ${widths.map((w) => \"-\".repeat(w)).join(\" | \")} |`;\n const body = rows\n .map(\n (row) =>\n `| ${keys.map((key, i) => truncateCell(cellValue(row[key])).padEnd(widths[i] ?? 0)).join(\" | \")} |`,\n )\n .join(\"\\n\");\n\n return `${header}\\n${separator}\\n${body}`;\n}\n\nfunction toRows(data: unknown): Record<string, unknown>[] {\n if (Array.isArray(data)) {\n return data.filter(\n (item): item is Record<string, unknown> => typeof item === \"object\" && item !== null,\n );\n }\n if (typeof data === \"object\" && data !== null) {\n return [data as Record<string, unknown>];\n }\n return [];\n}\n\n// ---------------------------------------------------------------------------\n// JUnit XML output\n// ---------------------------------------------------------------------------\n\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&apos;\");\n}\n\nfunction toTestCases(data: unknown, commandName: string): { cases: string[]; failures: number } {\n const cases: string[] = [];\n let failures = 0;\n\n if (Array.isArray(data)) {\n for (let i = 0; i < data.length; i++) {\n const tc = buildTestCase(data[i], commandName, i);\n cases.push(tc.xml);\n if (tc.failed) failures++;\n }\n } else if (typeof data === \"object\" && data !== null) {\n const tc = buildTestCase(data, commandName);\n cases.push(tc.xml);\n if (tc.failed) failures++;\n } else if (typeof data === \"string\") {\n cases.push(\n ` <testcase name=\"${escapeXml(data)}\" classname=\"gpc.${escapeXml(commandName)}\" />`,\n );\n }\n\n return { cases, failures };\n}\n\nfunction buildTestCase(\n item: unknown,\n commandName: string,\n index = 0,\n): { xml: string; failed: boolean } {\n if (typeof item !== \"object\" || item === null) {\n const text = String(item);\n return {\n xml: ` <testcase name=\"${escapeXml(text)}\" classname=\"gpc.${escapeXml(commandName)}\" />`,\n failed: false,\n };\n }\n\n const record = item as Record<string, unknown>;\n\n // Pick the first meaningful identifier, skipping sentinel dash/empty values\n // that commands use as display placeholders (e.g. `name: s[\"name\"] || \"-\"`).\n const CANDIDATE_KEYS = [\n \"name\", \"title\", \"sku\", \"id\", \"reviewId\", \"productId\", \"packageName\",\n \"track\", \"trackId\", \"versionCode\", \"region\", \"languageCode\",\n ] as const;\n let resolvedName = `item-${index + 1}`;\n for (const key of CANDIDATE_KEYS) {\n const val = record[key];\n if (val != null && val !== \"\" && val !== \"-\") {\n resolvedName = String(val);\n break;\n }\n }\n const name = escapeXml(resolvedName);\n const classname = `gpc.${escapeXml(commandName)}`;\n\n // Detect threshold breach (vitals)\n const breached = record[\"breached\"];\n if (breached === true) {\n const message = escapeXml(String(record[\"message\"] ?? \"threshold breached\"));\n const details = escapeXml(\n String(record[\"details\"] ?? record[\"metric\"] ?? JSON.stringify(item)),\n );\n return {\n xml: ` <testcase name=\"${name}\" classname=\"${classname}\">\\n <failure message=\"${message}\">${details}</failure>\\n </testcase>`,\n failed: true,\n };\n }\n\n return {\n xml: ` <testcase name=\"${name}\" classname=\"${classname}\" />`,\n failed: false,\n };\n}\n\nexport function formatJunit(data: unknown, commandName = \"command\"): string {\n const { cases, failures } = toTestCases(data, commandName);\n const tests = cases.length;\n\n const lines = [\n '<?xml version=\"1.0\" encoding=\"UTF-8\"?>',\n `<testsuites name=\"gpc\" tests=\"${tests}\" failures=\"${failures}\" time=\"0\">`,\n ` <testsuite name=\"${escapeXml(commandName)}\" tests=\"${tests}\" failures=\"${failures}\">`,\n ...cases,\n \" </testsuite>\",\n \"</testsuites>\",\n ];\n\n return lines.join(\"\\n\");\n}\n","import type {\n GpcPlugin,\n PluginHooks,\n BeforeCommandHandler,\n AfterCommandHandler,\n ErrorHandler,\n BeforeRequestHandler,\n AfterResponseHandler,\n CommandEvent,\n CommandResult,\n PluginError,\n PluginCommand,\n PluginManifest,\n PluginPermission,\n RequestEvent,\n ResponseEvent,\n} from \"@gpc-cli/plugin-sdk\";\nimport { GpcError } from \"./errors.js\";\n\n// ---------------------------------------------------------------------------\n// Plugin Manager — orchestrates discovery, loading, and lifecycle\n// ---------------------------------------------------------------------------\n\nexport class PluginManager {\n private plugins: LoadedPlugin[] = [];\n private beforeHandlers: BeforeCommandHandler[] = [];\n private afterHandlers: AfterCommandHandler[] = [];\n private errorHandlers: ErrorHandler[] = [];\n private beforeRequestHandlers: BeforeRequestHandler[] = [];\n private afterResponseHandlers: AfterResponseHandler[] = [];\n private registeredCommands: PluginCommand[] = [];\n\n /** Load and register a plugin */\n async load(plugin: GpcPlugin, manifest?: PluginManifest): Promise<void> {\n const isTrusted = manifest?.trusted ?? plugin.name.startsWith(\"@gpc-cli/\");\n\n if (!isTrusted && manifest?.permissions) {\n validatePermissions(manifest.permissions);\n }\n\n const hooks = createHooks(\n this.beforeHandlers,\n this.afterHandlers,\n this.errorHandlers,\n this.beforeRequestHandlers,\n this.afterResponseHandlers,\n this.registeredCommands,\n );\n\n await plugin.register(hooks);\n\n this.plugins.push({\n name: plugin.name,\n version: plugin.version,\n trusted: isTrusted,\n });\n }\n\n /** Run all beforeCommand handlers */\n async runBeforeCommand(event: CommandEvent): Promise<void> {\n for (const handler of this.beforeHandlers) {\n await handler(event);\n }\n }\n\n /** Run all afterCommand handlers */\n async runAfterCommand(event: CommandEvent, result: CommandResult): Promise<void> {\n for (const handler of this.afterHandlers) {\n await handler(event, result);\n }\n }\n\n /** Run all onError handlers */\n async runOnError(event: CommandEvent, error: PluginError): Promise<void> {\n for (const handler of this.errorHandlers) {\n try {\n await handler(event, error);\n } catch {\n // Don't let error handlers crash the process\n }\n }\n }\n\n /** Run all beforeRequest handlers */\n async runBeforeRequest(event: RequestEvent): Promise<void> {\n for (const handler of this.beforeRequestHandlers) {\n try {\n await handler(event);\n } catch {\n // Don't let request hooks block API calls\n }\n }\n }\n\n /** Run all afterResponse handlers */\n async runAfterResponse(event: RequestEvent, response: ResponseEvent): Promise<void> {\n for (const handler of this.afterResponseHandlers) {\n try {\n await handler(event, response);\n } catch {\n // Don't let response hooks crash the process\n }\n }\n }\n\n /** Get commands registered by plugins */\n getRegisteredCommands(): PluginCommand[] {\n return [...this.registeredCommands];\n }\n\n /** Get list of loaded plugins */\n getLoadedPlugins(): LoadedPlugin[] {\n return [...this.plugins];\n }\n\n /** Whether any request/response hooks are registered */\n hasRequestHooks(): boolean {\n return this.beforeRequestHandlers.length > 0 || this.afterResponseHandlers.length > 0;\n }\n\n /** Reset (for testing) */\n reset(): void {\n this.plugins = [];\n this.beforeHandlers = [];\n this.afterHandlers = [];\n this.errorHandlers = [];\n this.beforeRequestHandlers = [];\n this.afterResponseHandlers = [];\n this.registeredCommands = [];\n }\n}\n\nexport interface LoadedPlugin {\n name: string;\n version: string;\n trusted: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Hook factory\n// ---------------------------------------------------------------------------\n\nfunction createHooks(\n beforeHandlers: BeforeCommandHandler[],\n afterHandlers: AfterCommandHandler[],\n errorHandlers: ErrorHandler[],\n beforeRequestHandlers: BeforeRequestHandler[],\n afterResponseHandlers: AfterResponseHandler[],\n registeredCommands: PluginCommand[],\n): PluginHooks {\n return {\n beforeCommand(handler) {\n beforeHandlers.push(handler);\n },\n afterCommand(handler) {\n afterHandlers.push(handler);\n },\n onError(handler) {\n errorHandlers.push(handler);\n },\n beforeRequest(handler) {\n beforeRequestHandlers.push(handler);\n },\n afterResponse(handler) {\n afterResponseHandlers.push(handler);\n },\n registerCommands(registrar) {\n const registry = {\n add(cmd: PluginCommand) {\n registeredCommands.push(cmd);\n },\n };\n registrar(registry);\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Permission validation\n// ---------------------------------------------------------------------------\n\nconst VALID_PERMISSIONS: ReadonlySet<string> = new Set<PluginPermission>([\n \"read:config\",\n \"write:config\",\n \"read:auth\",\n \"api:read\",\n \"api:write\",\n \"commands:register\",\n \"hooks:beforeCommand\",\n \"hooks:afterCommand\",\n \"hooks:onError\",\n \"hooks:beforeRequest\",\n \"hooks:afterResponse\",\n]);\n\nfunction validatePermissions(permissions: PluginPermission[]): void {\n for (const perm of permissions) {\n if (!VALID_PERMISSIONS.has(perm)) {\n throw new GpcError(\n `Unknown plugin permission: \"${perm}\"`,\n \"PLUGIN_INVALID_PERMISSION\",\n 10,\n `Valid permissions: ${[...VALID_PERMISSIONS].join(\", \")}`,\n );\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Plugin discovery\n// ---------------------------------------------------------------------------\n\nexport interface DiscoverPluginsOptions {\n /** Plugin names from config file */\n configPlugins?: string[];\n\n /** Working directory for node_modules scanning */\n cwd?: string;\n}\n\n/**\n * Discover plugins from multiple sources:\n * 1. Explicit config: gpc.config.ts → plugins: [...]\n * 2. Convention: node_modules/@gpc-cli/plugin-*\n * 3. Convention: node_modules/gpc-plugin-*\n */\nexport async function discoverPlugins(options?: DiscoverPluginsOptions): Promise<GpcPlugin[]> {\n const plugins: GpcPlugin[] = [];\n const seen = new Set<string>();\n\n // Source 1: Explicit config plugins\n if (options?.configPlugins) {\n for (const name of options.configPlugins) {\n if (seen.has(name)) continue;\n try {\n const mod = await import(name);\n const plugin = resolvePlugin(mod);\n if (plugin) {\n plugins.push(plugin);\n seen.add(name);\n }\n } catch {\n // Plugin not found — skip silently\n }\n }\n }\n\n return plugins;\n}\n\n/**\n * Resolve a plugin from a module.\n * Supports: default export, named `plugin` export, or the module itself as a plugin.\n */\nfunction resolvePlugin(mod: unknown): GpcPlugin | undefined {\n if (!mod || typeof mod !== \"object\") return undefined;\n\n const m = mod as Record<string, unknown>;\n\n // Check default export\n if (isPlugin(m[\"default\"])) return m[\"default\"];\n\n // Check named `plugin` export\n if (isPlugin(m[\"plugin\"])) return m[\"plugin\"];\n\n // Check if module itself is a plugin\n if (isPlugin(m)) return m as unknown as GpcPlugin;\n\n return undefined;\n}\n\nfunction isPlugin(obj: unknown): obj is GpcPlugin {\n if (!obj || typeof obj !== \"object\") return false;\n const p = obj as Record<string, unknown>;\n return (\n typeof p[\"name\"] === \"string\" &&\n typeof p[\"version\"] === \"string\" &&\n typeof p[\"register\"] === \"function\"\n );\n}\n","import type { PlayApiClient } from \"@gpc-cli/api\";\n\nexport interface AppInfo {\n packageName: string;\n title?: string;\n defaultLanguage?: string;\n contactEmail?: string;\n}\n\nexport async function getAppInfo(client: PlayApiClient, packageName: string): Promise<AppInfo> {\n // Create an edit to read app details (Google Play requires an edit context)\n const edit = await client.edits.insert(packageName);\n try {\n const details = await client.details.get(packageName, edit.id);\n // Delete the edit since we're only reading\n await client.edits.delete(packageName, edit.id);\n return {\n packageName,\n title: details.title,\n defaultLanguage: details.defaultLanguage,\n contactEmail: details.contactEmail,\n };\n } catch (error) {\n // Clean up edit on failure\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n","import { readFile, stat } from \"node:fs/promises\";\nimport { extname } from \"node:path\";\n\nexport interface FileValidationResult {\n valid: boolean;\n fileType: \"aab\" | \"apk\" | \"unknown\";\n sizeBytes: number;\n errors: string[];\n warnings: string[];\n}\n\n// ZIP magic bytes: PK\\x03\\x04\nconst ZIP_MAGIC = Buffer.from([0x50, 0x4b, 0x03, 0x04]);\n\nconst MAX_APK_SIZE = 150 * 1024 * 1024; // 150 MB\nconst MAX_AAB_SIZE = 500 * 1024 * 1024; // 500 MB (Play Store limit for AABs)\nconst LARGE_FILE_THRESHOLD = 100 * 1024 * 1024; // 100 MB — warn about upload time\n\nexport async function validateUploadFile(filePath: string): Promise<FileValidationResult> {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n // Check extension\n const ext = extname(filePath).toLowerCase();\n let fileType: FileValidationResult[\"fileType\"] = \"unknown\";\n\n if (ext === \".aab\") {\n fileType = \"aab\";\n } else if (ext === \".apk\") {\n fileType = \"apk\";\n } else {\n errors.push(`Unsupported file extension \"${ext}\". Expected .aab or .apk`);\n }\n\n // Check file exists and get size\n let sizeBytes: number;\n try {\n const stats = await stat(filePath);\n sizeBytes = stats.size;\n\n if (sizeBytes === 0) {\n errors.push(\"File is empty (0 bytes)\");\n }\n } catch {\n errors.push(`File not found: ${filePath}`);\n return { valid: false, fileType, sizeBytes: 0, errors, warnings };\n }\n\n // Check size limits\n if (fileType === \"apk\" && sizeBytes > MAX_APK_SIZE) {\n errors.push(\n `APK exceeds 150 MB limit (${formatSize(sizeBytes)}). Consider using AAB format instead.`,\n );\n }\n if (fileType === \"aab\" && sizeBytes > MAX_AAB_SIZE) {\n errors.push(`AAB exceeds 500 MB limit (${formatSize(sizeBytes)}).`);\n }\n\n if (sizeBytes > LARGE_FILE_THRESHOLD && errors.length === 0) {\n warnings.push(\n `Large file (${formatSize(sizeBytes)}). Upload may take a while on slow connections.`,\n );\n }\n\n // Check magic bytes (ZIP format — both AAB and APK are ZIP-based)\n if (sizeBytes > 0) {\n try {\n const fd = await readFile(filePath, { flag: \"r\" });\n const header = fd.subarray(0, 4);\n\n if (!header.equals(ZIP_MAGIC)) {\n errors.push(\n \"File does not have valid ZIP magic bytes (PK\\\\x03\\\\x04). \" +\n \"Both AAB and APK files must be valid ZIP archives.\",\n );\n }\n } catch {\n errors.push(\"Unable to read file header for validation\");\n }\n }\n\n return {\n valid: errors.length === 0,\n fileType,\n sizeBytes,\n errors,\n warnings,\n };\n}\n\nfunction formatSize(bytes: number): string {\n if (bytes >= 1024 * 1024 * 1024) {\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;\n }\n if (bytes >= 1024 * 1024) {\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n }\n if (bytes >= 1024) {\n return `${(bytes / 1024).toFixed(1)} KB`;\n }\n return `${bytes} B`;\n}\n","import type { PlayApiClient, Release, Track, ExternallyHostedApk, ExternallyHostedApkResponse } from \"@gpc-cli/api\";\nimport { GpcError } from \"../errors.js\";\nimport { validateUploadFile } from \"../utils/file-validation.js\";\n\nexport interface UploadResult {\n versionCode: number;\n track: string;\n status: string;\n}\n\nexport interface ReleaseStatusResult {\n track: string;\n status: string;\n versionCodes: string[];\n userFraction?: number;\n releaseNotes?: { language: string; text: string }[];\n}\n\nexport interface DryRunUploadResult {\n dryRun: true;\n file: { path: string; valid: boolean; errors: string[]; warnings: string[] };\n track: string;\n currentReleases: { versionCodes: string[]; status: string; userFraction?: number }[];\n plannedRelease: { status: string; userFraction?: number };\n}\n\nexport async function uploadRelease(\n client: PlayApiClient,\n packageName: string,\n filePath: string,\n options: {\n track: string;\n status?: string;\n userFraction?: number;\n releaseNotes?: { language: string; text: string }[];\n releaseName?: string;\n mappingFile?: string;\n dryRun?: boolean;\n },\n): Promise<UploadResult | DryRunUploadResult> {\n // Validate file before upload\n const validation = await validateUploadFile(filePath);\n\n if (options.dryRun) {\n const plannedStatus = options.status ||\n (options.userFraction ? \"inProgress\" : \"completed\");\n\n // Fetch current track state without modifying anything\n let currentReleases: DryRunUploadResult[\"currentReleases\"] = [];\n const edit = await client.edits.insert(packageName);\n try {\n const trackData = await client.tracks.get(packageName, edit.id, options.track);\n currentReleases = (trackData.releases || []).map((r) => ({\n versionCodes: r.versionCodes || [],\n status: r.status,\n ...(r.userFraction !== undefined && { userFraction: r.userFraction }),\n }));\n } catch {\n // Track may not exist yet — that's fine for dry-run\n } finally {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n }\n\n return {\n dryRun: true,\n file: {\n path: filePath,\n valid: validation.valid,\n errors: validation.errors,\n warnings: validation.warnings,\n },\n track: options.track,\n currentReleases,\n plannedRelease: {\n status: plannedStatus,\n ...(options.userFraction !== undefined && { userFraction: options.userFraction }),\n },\n };\n }\n\n if (!validation.valid) {\n throw new GpcError(\n `File validation failed:\\n${validation.errors.join(\"\\n\")}`,\n \"RELEASE_INVALID_FILE\",\n 2,\n \"Check that the file is a valid AAB or APK and is not corrupted.\",\n );\n }\n\n const edit = await client.edits.insert(packageName);\n try {\n // Upload the bundle\n const bundle = await client.bundles.upload(packageName, edit.id, filePath);\n\n // Upload mapping file if provided\n if (options.mappingFile) {\n await client.deobfuscation.upload(\n packageName,\n edit.id,\n bundle.versionCode,\n options.mappingFile,\n );\n }\n\n // Create release and assign to track\n const release: Release = {\n versionCodes: [String(bundle.versionCode)],\n status: (options.status ||\n (options.userFraction ? \"inProgress\" : \"completed\")) as Release[\"status\"],\n ...(options.userFraction && { userFraction: options.userFraction }),\n ...(options.releaseNotes && { releaseNotes: options.releaseNotes }),\n ...(options.releaseName && { name: options.releaseName }),\n };\n\n await client.tracks.update(packageName, edit.id, options.track, release);\n\n // Validate and commit\n await client.edits.validate(packageName, edit.id);\n await client.edits.commit(packageName, edit.id);\n\n return {\n versionCode: bundle.versionCode,\n track: options.track,\n status: release.status,\n };\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function getReleasesStatus(\n client: PlayApiClient,\n packageName: string,\n trackFilter?: string,\n): Promise<ReleaseStatusResult[]> {\n const edit = await client.edits.insert(packageName);\n try {\n const tracks = trackFilter\n ? [await client.tracks.get(packageName, edit.id, trackFilter)]\n : await client.tracks.list(packageName, edit.id);\n\n await client.edits.delete(packageName, edit.id);\n\n const results: ReleaseStatusResult[] = [];\n for (const track of tracks) {\n for (const release of track.releases || []) {\n results.push({\n track: track.track,\n status: release.status,\n versionCodes: release.versionCodes || [],\n userFraction: release.userFraction,\n releaseNotes: release.releaseNotes,\n });\n }\n }\n return results;\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function promoteRelease(\n client: PlayApiClient,\n packageName: string,\n fromTrack: string,\n toTrack: string,\n options?: { userFraction?: number; releaseNotes?: { language: string; text: string }[] },\n): Promise<ReleaseStatusResult> {\n const edit = await client.edits.insert(packageName);\n try {\n // Get current release from source track\n const sourceTrack = await client.tracks.get(packageName, edit.id, fromTrack);\n const currentRelease = sourceTrack.releases?.find(\n (r) => r.status === \"completed\" || r.status === \"inProgress\",\n );\n\n if (!currentRelease) {\n throw new GpcError(\n `No active release found on track \"${fromTrack}\"`,\n \"RELEASE_NOT_FOUND\",\n 1,\n `Ensure there is a completed or in-progress release on the \"${fromTrack}\" track before promoting.`,\n );\n }\n\n // Create release on target track\n if (options?.userFraction && (options.userFraction <= 0 || options.userFraction > 1)) {\n throw new GpcError(\n \"Rollout percentage must be between 0 and 1 (e.g., 0.1 for 10%)\",\n \"RELEASE_INVALID_FRACTION\",\n 2,\n \"Use a decimal value like 0.1 for 10%, 0.5 for 50%, or 1.0 for 100%.\",\n );\n }\n const release: Release = {\n versionCodes: currentRelease.versionCodes,\n status: (options?.userFraction ? \"inProgress\" : \"completed\") as Release[\"status\"],\n ...(options?.userFraction && { userFraction: options.userFraction }),\n releaseNotes: options?.releaseNotes || currentRelease.releaseNotes || [],\n };\n\n await client.tracks.update(packageName, edit.id, toTrack, release);\n await client.edits.validate(packageName, edit.id);\n await client.edits.commit(packageName, edit.id);\n\n return {\n track: toTrack,\n status: release.status,\n versionCodes: release.versionCodes,\n userFraction: release.userFraction,\n };\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function updateRollout(\n client: PlayApiClient,\n packageName: string,\n track: string,\n action: \"increase\" | \"halt\" | \"resume\" | \"complete\",\n userFraction?: number,\n): Promise<ReleaseStatusResult> {\n const edit = await client.edits.insert(packageName);\n try {\n const trackData = await client.tracks.get(packageName, edit.id, track);\n const currentRelease = trackData.releases?.find(\n (r) => r.status === \"inProgress\" || r.status === \"halted\",\n );\n\n if (!currentRelease) {\n throw new GpcError(\n `No active rollout found on track \"${track}\"`,\n \"ROLLOUT_NOT_FOUND\",\n 1,\n `There is no in-progress or halted rollout on the \"${track}\" track. Start a staged rollout first with: gpc releases upload --track ${track} --status inProgress --fraction 0.1`,\n );\n }\n\n let newStatus: string;\n let newFraction: number | undefined;\n\n switch (action) {\n case \"increase\":\n if (!userFraction) throw new GpcError(\n \"--to <percentage> is required for rollout increase\",\n \"ROLLOUT_MISSING_FRACTION\",\n 2,\n \"Specify the target rollout percentage with --to, e.g.: gpc rollout increase --to 0.5\",\n );\n if (userFraction <= 0 || userFraction > 1) {\n throw new GpcError(\n \"Rollout percentage must be between 0 and 1 (e.g., 0.1 for 10%)\",\n \"RELEASE_INVALID_FRACTION\",\n 2,\n \"Use a decimal value like 0.1 for 10%, 0.5 for 50%, or 1.0 for 100%.\",\n );\n }\n newStatus = \"inProgress\";\n newFraction = userFraction;\n break;\n case \"halt\":\n newStatus = \"halted\";\n newFraction = currentRelease.userFraction;\n break;\n case \"resume\":\n newStatus = \"inProgress\";\n newFraction = currentRelease.userFraction;\n break;\n case \"complete\":\n newStatus = \"completed\";\n newFraction = undefined;\n break;\n }\n\n const release: Release = {\n versionCodes: currentRelease.versionCodes,\n status: newStatus as Release[\"status\"],\n ...(newFraction !== undefined && { userFraction: newFraction }),\n releaseNotes: currentRelease.releaseNotes || [],\n };\n\n await client.tracks.update(packageName, edit.id, track, release);\n await client.edits.validate(packageName, edit.id);\n await client.edits.commit(packageName, edit.id);\n\n return {\n track,\n status: newStatus,\n versionCodes: release.versionCodes,\n userFraction: newFraction,\n };\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function listTracks(client: PlayApiClient, packageName: string): Promise<Track[]> {\n const edit = await client.edits.insert(packageName);\n try {\n const tracks = await client.tracks.list(packageName, edit.id);\n await client.edits.delete(packageName, edit.id);\n return tracks;\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function createTrack(\n client: PlayApiClient,\n packageName: string,\n trackName: string,\n): Promise<Track> {\n if (!trackName || trackName.trim().length === 0) {\n throw new GpcError(\n \"Track name must not be empty\",\n \"TRACK_INVALID_NAME\",\n 2,\n \"Provide a valid custom track name, e.g.: gpc tracks create my-qa-track\",\n );\n }\n\n const edit = await client.edits.insert(packageName);\n try {\n const track = await client.tracks.create(packageName, edit.id, trackName);\n await client.edits.validate(packageName, edit.id);\n await client.edits.commit(packageName, edit.id);\n return track;\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function updateTrackConfig(\n client: PlayApiClient,\n packageName: string,\n trackName: string,\n config: Record<string, unknown>,\n): Promise<Track> {\n if (!trackName || trackName.trim().length === 0) {\n throw new GpcError(\n \"Track name must not be empty\",\n \"TRACK_INVALID_NAME\",\n 2,\n \"Provide a valid track name.\",\n );\n }\n\n const edit = await client.edits.insert(packageName);\n try {\n const release: Release = {\n versionCodes: (config[\"versionCodes\"] as string[]) || [],\n status: ((config[\"status\"] as string) || \"completed\") as Release[\"status\"],\n };\n if (config[\"userFraction\"] !== undefined) {\n release.userFraction = config[\"userFraction\"] as number;\n }\n if (config[\"releaseNotes\"]) {\n release.releaseNotes = config[\"releaseNotes\"] as { language: string; text: string }[];\n }\n if (config[\"name\"]) {\n release.name = config[\"name\"] as string;\n }\n\n const track = await client.tracks.update(packageName, edit.id, trackName, release);\n await client.edits.validate(packageName, edit.id);\n await client.edits.commit(packageName, edit.id);\n return track;\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport interface ReleaseDiff {\n field: string;\n track1Value: string;\n track2Value: string;\n}\n\nexport async function diffReleases(\n client: PlayApiClient,\n packageName: string,\n fromTrack: string,\n toTrack: string,\n): Promise<{ fromTrack: string; toTrack: string; diffs: ReleaseDiff[] }> {\n const edit = await client.edits.insert(packageName);\n try {\n const [fromData, toData] = await Promise.all([\n client.tracks.get(packageName, edit.id, fromTrack),\n client.tracks.get(packageName, edit.id, toTrack),\n ]);\n await client.edits.delete(packageName, edit.id);\n\n const fromRelease = fromData.releases?.[0];\n const toRelease = toData.releases?.[0];\n const diffs: ReleaseDiff[] = [];\n\n const fields = [\"versionCodes\", \"status\", \"userFraction\", \"releaseNotes\", \"name\"] as const;\n for (const field of fields) {\n const v1 = fromRelease ? JSON.stringify(fromRelease[field] ?? null) : \"null\";\n const v2 = toRelease ? JSON.stringify(toRelease[field] ?? null) : \"null\";\n if (v1 !== v2) {\n diffs.push({ field, track1Value: v1, track2Value: v2 });\n }\n }\n\n return { fromTrack, toTrack, diffs };\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function uploadExternallyHosted(\n client: PlayApiClient,\n packageName: string,\n data: ExternallyHostedApk,\n): Promise<ExternallyHostedApkResponse> {\n if (!data.externallyHostedUrl) {\n throw new GpcError(\n \"externallyHostedUrl is required\",\n \"EXTERNAL_APK_MISSING_URL\",\n 2,\n \"Provide a valid URL for the externally hosted APK.\",\n );\n }\n\n if (!data.packageName) {\n throw new GpcError(\n \"packageName is required in externally hosted APK data\",\n \"EXTERNAL_APK_MISSING_PACKAGE\",\n 2,\n \"Include the packageName field in the APK configuration.\",\n );\n }\n\n const edit = await client.edits.insert(packageName);\n try {\n const result = await client.apks.addExternallyHosted(packageName, edit.id, data);\n await client.edits.validate(packageName, edit.id);\n await client.edits.commit(packageName, edit.id);\n return result;\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n","export const GOOGLE_PLAY_LANGUAGES: string[] = [\n \"af\",\n \"am\",\n \"ar\",\n \"hy-AM\",\n \"az-AZ\",\n \"eu-ES\",\n \"be\",\n \"bn-BD\",\n \"bg\",\n \"my-MM\",\n \"ca\",\n \"zh-HK\",\n \"zh-CN\",\n \"zh-TW\",\n \"hr\",\n \"cs-CZ\",\n \"da-DK\",\n \"nl-NL\",\n \"en-AU\",\n \"en-CA\",\n \"en-IN\",\n \"en-SG\",\n \"en-GB\",\n \"en-US\",\n \"et\",\n \"fil\",\n \"fi-FI\",\n \"fr-FR\",\n \"fr-CA\",\n \"gl-ES\",\n \"ka-GE\",\n \"de-DE\",\n \"el-GR\",\n \"gu\",\n \"iw-IL\",\n \"hi-IN\",\n \"hu-HU\",\n \"is-IS\",\n \"id\",\n \"it-IT\",\n \"ja-JP\",\n \"kn-IN\",\n \"kk\",\n \"km-KH\",\n \"ko-KR\",\n \"ky-KG\",\n \"lo-LA\",\n \"lv\",\n \"lt\",\n \"mk-MK\",\n \"ms\",\n \"ms-MY\",\n \"ml-IN\",\n \"mr-IN\",\n \"mn-MN\",\n \"ne-NP\",\n \"no-NO\",\n \"fa\",\n \"pl-PL\",\n \"pt-BR\",\n \"pt-PT\",\n \"pa\",\n \"ro\",\n \"rm\",\n \"ru-RU\",\n \"sr\",\n \"si-LK\",\n \"sk\",\n \"sl\",\n \"es-419\",\n \"es-ES\",\n \"es-US\",\n \"sw\",\n \"sv-SE\",\n \"ta-IN\",\n \"te-IN\",\n \"th\",\n \"tr-TR\",\n \"uk\",\n \"ur\",\n \"vi\",\n \"zu\",\n];\n\nexport function isValidBcp47(tag: string): boolean {\n return GOOGLE_PLAY_LANGUAGES.includes(tag);\n}\n","import { stat } from \"node:fs/promises\";\nimport { extname } from \"node:path\";\n\nexport interface ImageValidationResult {\n valid: boolean;\n warnings: string[];\n errors: string[];\n}\n\n// Google Play image size limits\nconst IMAGE_SIZE_LIMITS: Record<string, { maxBytes: number; label: string }> = {\n icon: { maxBytes: 1024 * 1024, label: \"1 MB\" },\n featureGraphic: { maxBytes: 1024 * 1024, label: \"1 MB\" },\n tvBanner: { maxBytes: 1024 * 1024, label: \"1 MB\" },\n phoneScreenshots: { maxBytes: 8 * 1024 * 1024, label: \"8 MB\" },\n sevenInchScreenshots: { maxBytes: 8 * 1024 * 1024, label: \"8 MB\" },\n tenInchScreenshots: { maxBytes: 8 * 1024 * 1024, label: \"8 MB\" },\n tvScreenshots: { maxBytes: 8 * 1024 * 1024, label: \"8 MB\" },\n wearScreenshots: { maxBytes: 8 * 1024 * 1024, label: \"8 MB\" },\n};\n\nconst VALID_EXTENSIONS = new Set([\".png\", \".jpg\", \".jpeg\"]);\nconst LARGE_IMAGE_THRESHOLD = 2 * 1024 * 1024; // 2 MB\n\nexport async function validateImage(\n filePath: string,\n imageType?: string,\n): Promise<ImageValidationResult> {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n // Check extension\n const ext = extname(filePath).toLowerCase();\n if (!VALID_EXTENSIONS.has(ext)) {\n errors.push(`Unsupported image format \"${ext}\". Use PNG or JPEG.`);\n }\n\n // Check file exists and size\n let sizeBytes: number;\n try {\n const stats = await stat(filePath);\n sizeBytes = stats.size;\n\n if (sizeBytes === 0) {\n errors.push(\"Image file is empty (0 bytes)\");\n }\n } catch {\n errors.push(`Image file not found: ${filePath}`);\n return { valid: false, errors, warnings };\n }\n\n // Check size limits per image type\n if (imageType && sizeBytes > 0) {\n const limit = IMAGE_SIZE_LIMITS[imageType];\n if (limit && sizeBytes > limit.maxBytes) {\n errors.push(`Image exceeds ${limit.label} limit for ${imageType} (${formatSize(sizeBytes)})`);\n }\n }\n\n // Warn about large images\n if (sizeBytes > LARGE_IMAGE_THRESHOLD && errors.length === 0) {\n warnings.push(\n `Large image (${formatSize(sizeBytes)}). Consider optimizing for faster upload and better store performance.`,\n );\n }\n\n // PNG optimization warning\n if (ext === \".png\" && sizeBytes > 512 * 1024) {\n warnings.push(\n \"PNG file is over 512 KB. Consider compressing with tools like pngquant or optipng.\",\n );\n }\n\n return { valid: errors.length === 0, errors, warnings };\n}\n\nfunction formatSize(bytes: number): string {\n if (bytes >= 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n if (bytes >= 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${bytes} B`;\n}\n","import { readFile, writeFile, mkdir, readdir, stat } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { Listing } from \"@gpc-cli/api\";\n\nconst FILE_MAP: Record<string, keyof Omit<Listing, \"language\">> = {\n \"title.txt\": \"title\",\n \"short_description.txt\": \"shortDescription\",\n \"full_description.txt\": \"fullDescription\",\n \"video.txt\": \"video\",\n};\n\nconst FIELD_TO_FILE: Record<string, string> = Object.fromEntries(\n Object.entries(FILE_MAP).map(([file, field]) => [field, file]),\n);\n\nexport interface ListingDiff {\n language: string;\n field: string;\n local: string;\n remote: string;\n}\n\nasync function exists(path: string): Promise<boolean> {\n try {\n await stat(path);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function readListingsFromDir(dir: string): Promise<Listing[]> {\n const listings: Listing[] = [];\n\n if (!(await exists(dir))) return listings;\n\n const entries = await readdir(dir);\n // Validate directory names to prevent path traversal\n const SAFE_LANG = /^[a-zA-Z]{2,3}(-[a-zA-Z0-9]{2,8})*$/;\n for (const lang of entries) {\n if (!SAFE_LANG.test(lang)) continue;\n const langDir = join(dir, lang);\n const langStat = await stat(langDir);\n if (!langStat.isDirectory()) continue;\n\n const listing: Listing = {\n language: lang,\n title: \"\",\n shortDescription: \"\",\n fullDescription: \"\",\n };\n\n for (const [fileName, field] of Object.entries(FILE_MAP)) {\n const filePath = join(langDir, fileName);\n if (await exists(filePath)) {\n const content = await readFile(filePath, \"utf-8\");\n (listing as unknown as Record<string, string>)[field] = content.trimEnd();\n }\n }\n\n listings.push(listing);\n }\n\n return listings;\n}\n\nexport async function writeListingsToDir(dir: string, listings: Listing[]): Promise<void> {\n for (const listing of listings) {\n const langDir = join(dir, listing.language);\n await mkdir(langDir, { recursive: true });\n\n for (const [field, fileName] of Object.entries(FIELD_TO_FILE)) {\n const value = (listing as unknown as Record<string, string>)[field];\n if (value !== undefined && value !== \"\") {\n await writeFile(join(langDir, fileName), value + \"\\n\", \"utf-8\");\n }\n }\n }\n}\n\nexport function diffListings(local: Listing[], remote: Listing[]): ListingDiff[] {\n const diffs: ListingDiff[] = [];\n const remoteMap = new Map(remote.map((l) => [l.language, l]));\n const localMap = new Map(local.map((l) => [l.language, l]));\n\n // Check all local listings against remote\n for (const localListing of local) {\n const remoteListing = remoteMap.get(localListing.language);\n for (const [field] of Object.entries(FIELD_TO_FILE)) {\n const localVal = (\n (localListing as unknown as Record<string, string>)[field] ?? \"\"\n ).toString();\n const remoteVal = remoteListing\n ? ((remoteListing as unknown as Record<string, string>)[field] ?? \"\").toString()\n : \"\";\n if (localVal !== remoteVal) {\n diffs.push({\n language: localListing.language,\n field,\n local: localVal,\n remote: remoteVal,\n });\n }\n }\n }\n\n // Check for remote-only languages\n for (const remoteListing of remote) {\n if (!localMap.has(remoteListing.language)) {\n for (const [field] of Object.entries(FIELD_TO_FILE)) {\n const remoteVal = (\n (remoteListing as unknown as Record<string, string>)[field] ?? \"\"\n ).toString();\n if (remoteVal) {\n diffs.push({\n language: remoteListing.language,\n field,\n local: \"\",\n remote: remoteVal,\n });\n }\n }\n }\n }\n\n return diffs;\n}\n","import type {\n PlayApiClient,\n Listing,\n Image,\n ImageType,\n AppDetails,\n CountryAvailability,\n} from \"@gpc-cli/api\";\nimport { GpcError } from \"../errors.js\";\nimport { isValidBcp47 } from \"../utils/bcp47.js\";\nimport { validateImage } from \"../utils/image-validation.js\";\nimport { readListingsFromDir, writeListingsToDir, diffListings } from \"../utils/fastlane.js\";\nimport type { ListingDiff } from \"../utils/fastlane.js\";\n\nexport interface ListingsResult {\n listings: Listing[];\n}\n\nexport interface PushResult {\n updated: number;\n languages: string[];\n}\n\nexport interface DryRunResult {\n diffs: ListingDiff[];\n}\n\nfunction validateLanguage(lang: string): void {\n if (!isValidBcp47(lang)) {\n throw new GpcError(\n `Invalid language tag \"${lang}\". Must be a valid Google Play BCP 47 code.`,\n \"LISTING_INVALID_LANGUAGE\",\n 2,\n \"Use a valid BCP 47 language code such as en-US, de-DE, or ja-JP. See the Google Play Console for supported language codes.\",\n );\n }\n}\n\nexport async function getListings(\n client: PlayApiClient,\n packageName: string,\n language?: string,\n): Promise<Listing[]> {\n const edit = await client.edits.insert(packageName);\n try {\n let listings: Listing[];\n if (language) {\n validateLanguage(language);\n const listing = await client.listings.get(packageName, edit.id, language);\n listings = [listing];\n } else {\n listings = await client.listings.list(packageName, edit.id);\n }\n await client.edits.delete(packageName, edit.id);\n return listings;\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function updateListing(\n client: PlayApiClient,\n packageName: string,\n language: string,\n data: Partial<Omit<Listing, \"language\">>,\n): Promise<Listing> {\n validateLanguage(language);\n const edit = await client.edits.insert(packageName);\n try {\n const listing = await client.listings.patch(packageName, edit.id, language, data);\n await client.edits.validate(packageName, edit.id);\n await client.edits.commit(packageName, edit.id);\n return listing;\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function deleteListing(\n client: PlayApiClient,\n packageName: string,\n language: string,\n): Promise<void> {\n validateLanguage(language);\n const edit = await client.edits.insert(packageName);\n try {\n await client.listings.delete(packageName, edit.id, language);\n await client.edits.validate(packageName, edit.id);\n await client.edits.commit(packageName, edit.id);\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function pullListings(\n client: PlayApiClient,\n packageName: string,\n dir: string,\n): Promise<ListingsResult> {\n const edit = await client.edits.insert(packageName);\n try {\n const listings = await client.listings.list(packageName, edit.id);\n await client.edits.delete(packageName, edit.id);\n await writeListingsToDir(dir, listings);\n return { listings };\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function pushListings(\n client: PlayApiClient,\n packageName: string,\n dir: string,\n options?: { dryRun?: boolean },\n): Promise<PushResult | DryRunResult> {\n const localListings = await readListingsFromDir(dir);\n\n if (localListings.length === 0) {\n throw new GpcError(\n `No listings found in directory \"${dir}\"`,\n \"LISTING_DIR_EMPTY\",\n 1,\n `The directory must contain subdirectories named by language code (e.g., en-US/) with listing metadata files. Pull existing listings first with: gpc listings pull --dir \"${dir}\"`,\n );\n }\n\n // Validate all languages\n for (const listing of localListings) {\n validateLanguage(listing.language);\n }\n\n const edit = await client.edits.insert(packageName);\n try {\n if (options?.dryRun) {\n const remoteListings = await client.listings.list(packageName, edit.id);\n await client.edits.delete(packageName, edit.id);\n const diffs = diffListings(localListings, remoteListings);\n return { diffs };\n }\n\n for (const listing of localListings) {\n const { language, ...data } = listing;\n await client.listings.update(packageName, edit.id, language, data);\n }\n\n await client.edits.validate(packageName, edit.id);\n await client.edits.commit(packageName, edit.id);\n\n return {\n updated: localListings.length,\n languages: localListings.map((l) => l.language),\n };\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function listImages(\n client: PlayApiClient,\n packageName: string,\n language: string,\n imageType: ImageType,\n): Promise<Image[]> {\n validateLanguage(language);\n const edit = await client.edits.insert(packageName);\n try {\n const images = await client.images.list(packageName, edit.id, language, imageType);\n await client.edits.delete(packageName, edit.id);\n return images;\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function uploadImage(\n client: PlayApiClient,\n packageName: string,\n language: string,\n imageType: ImageType,\n filePath: string,\n): Promise<Image> {\n validateLanguage(language);\n\n // Validate image before upload\n const imageCheck = await validateImage(filePath, imageType);\n if (!imageCheck.valid) {\n throw new GpcError(\n `Image validation failed: ${imageCheck.errors.join(\"; \")}`,\n \"IMAGE_INVALID\",\n 2,\n \"Check image dimensions, file size, and format. Google Play requires PNG or JPEG images within specific size limits per image type.\",\n );\n }\n if (imageCheck.warnings.length > 0) {\n for (const w of imageCheck.warnings) {\n console.warn(`Warning: ${w}`);\n }\n }\n\n const edit = await client.edits.insert(packageName);\n try {\n const image = await client.images.upload(packageName, edit.id, language, imageType, filePath);\n await client.edits.validate(packageName, edit.id);\n await client.edits.commit(packageName, edit.id);\n return image;\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function deleteImage(\n client: PlayApiClient,\n packageName: string,\n language: string,\n imageType: ImageType,\n imageId: string,\n): Promise<void> {\n validateLanguage(language);\n const edit = await client.edits.insert(packageName);\n try {\n await client.images.delete(packageName, edit.id, language, imageType, imageId);\n await client.edits.validate(packageName, edit.id);\n await client.edits.commit(packageName, edit.id);\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function diffListingsCommand(\n client: PlayApiClient,\n packageName: string,\n dir: string,\n): Promise<ListingDiff[]> {\n const localListings = await readListingsFromDir(dir);\n\n const edit = await client.edits.insert(packageName);\n try {\n const remoteListings = await client.listings.list(packageName, edit.id);\n await client.edits.delete(packageName, edit.id);\n return diffListings(localListings, remoteListings);\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function getCountryAvailability(\n client: PlayApiClient,\n packageName: string,\n track: string,\n): Promise<CountryAvailability> {\n const edit = await client.edits.insert(packageName);\n try {\n const availability = await client.countryAvailability.get(packageName, edit.id, track);\n await client.edits.delete(packageName, edit.id);\n return availability;\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport interface ExportImagesOptions {\n lang?: string;\n type?: ImageType;\n}\n\nexport interface ExportImagesSummary {\n languages: number;\n images: number;\n totalSize: number;\n}\n\nconst ALL_IMAGE_TYPES: ImageType[] = [\n \"phoneScreenshots\",\n \"sevenInchScreenshots\",\n \"tenInchScreenshots\",\n \"tvScreenshots\",\n \"wearScreenshots\",\n \"icon\",\n \"featureGraphic\",\n \"tvBanner\",\n];\n\nexport async function exportImages(\n client: PlayApiClient,\n packageName: string,\n dir: string,\n options?: ExportImagesOptions,\n): Promise<ExportImagesSummary> {\n const { mkdir, writeFile } = await import(\"node:fs/promises\");\n const { join } = await import(\"node:path\");\n\n const edit = await client.edits.insert(packageName);\n try {\n // Determine languages\n let languages: string[];\n if (options?.lang) {\n validateLanguage(options.lang);\n languages = [options.lang];\n } else {\n const listings = await client.listings.list(packageName, edit.id);\n languages = listings.map((l) => l.language);\n }\n\n const imageTypes: ImageType[] = options?.type ? [options.type] : ALL_IMAGE_TYPES;\n\n let totalImages = 0;\n let totalSize = 0;\n\n // Collect all download tasks\n const tasks: Array<{ language: string; imageType: ImageType; url: string; index: number }> = [];\n\n for (const language of languages) {\n for (const imageType of imageTypes) {\n const images = await client.images.list(packageName, edit.id, language, imageType);\n for (let i = 0; i < images.length; i++) {\n const img = images[i];\n if (img && img.url) {\n tasks.push({ language, imageType, url: img.url, index: i + 1 });\n }\n }\n }\n }\n\n // Process downloads with concurrency limit of 5\n const concurrency = 5;\n for (let i = 0; i < tasks.length; i += concurrency) {\n const batch = tasks.slice(i, i + concurrency);\n const results = await Promise.all(\n batch.map(async (task) => {\n const dirPath = join(dir, task.language, task.imageType);\n await mkdir(dirPath, { recursive: true });\n\n const response = await fetch(task.url);\n const buffer = Buffer.from(await response.arrayBuffer());\n const filePath = join(dirPath, `${task.index}.png`);\n await writeFile(filePath, buffer);\n\n return buffer.length;\n }),\n );\n\n for (const size of results) {\n totalImages++;\n totalSize += size;\n }\n }\n\n await client.edits.delete(packageName, edit.id);\n\n return {\n languages: languages.length,\n images: totalImages,\n totalSize,\n };\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function updateAppDetails(\n client: PlayApiClient,\n packageName: string,\n details: Partial<AppDetails>,\n): Promise<AppDetails> {\n const edit = await client.edits.insert(packageName);\n try {\n const result = await client.details.patch(packageName, edit.id, details);\n await client.edits.validate(packageName, edit.id);\n await client.edits.commit(packageName, edit.id);\n return result;\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n","import { readdir, readFile, writeFile, mkdir, access } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport interface FastlaneDetection {\n hasFastfile: boolean;\n hasAppfile: boolean;\n hasMetadata: boolean;\n hasGemfile: boolean;\n packageName?: string;\n jsonKeyPath?: string;\n lanes: FastlaneLane[];\n metadataLanguages: string[];\n parseWarnings: string[];\n}\n\nexport interface FastlaneLane {\n name: string;\n actions: string[];\n gpcEquivalent?: string;\n}\n\nexport interface MigrationResult {\n config: Record<string, unknown>;\n checklist: string[];\n warnings: string[];\n}\n\n// Ruby constructs that confuse the lane-end regex\nconst COMPLEX_RUBY_RE = /\\b(begin|rescue|ensure|if |unless |case |while |until |for )\\b/;\n\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function detectFastlane(cwd: string): Promise<FastlaneDetection> {\n const result: FastlaneDetection = {\n hasFastfile: false,\n hasAppfile: false,\n hasMetadata: false,\n hasGemfile: false,\n lanes: [],\n metadataLanguages: [],\n parseWarnings: [],\n };\n\n // Check for fastlane directory or root-level files\n const fastlaneDir = join(cwd, \"fastlane\");\n const hasFastlaneDir = await fileExists(fastlaneDir);\n\n const fastfilePath = hasFastlaneDir\n ? join(fastlaneDir, \"Fastfile\")\n : join(cwd, \"Fastfile\");\n const appfilePath = hasFastlaneDir\n ? join(fastlaneDir, \"Appfile\")\n : join(cwd, \"Appfile\");\n\n result.hasFastfile = await fileExists(fastfilePath);\n result.hasAppfile = await fileExists(appfilePath);\n result.hasGemfile = await fileExists(join(cwd, \"Gemfile\"));\n\n // Check for metadata directory\n const metadataDir = hasFastlaneDir\n ? join(fastlaneDir, \"metadata\", \"android\")\n : join(cwd, \"metadata\", \"android\");\n\n result.hasMetadata = await fileExists(metadataDir);\n\n if (result.hasMetadata) {\n try {\n const entries = await readdir(metadataDir, { withFileTypes: true });\n result.metadataLanguages = entries\n .filter((e) => e.isDirectory())\n .map((e) => e.name);\n } catch {\n result.parseWarnings.push(\"Could not read metadata directory — check permissions\");\n }\n }\n\n // Parse Fastfile if present\n if (result.hasFastfile) {\n try {\n const content = await readFile(fastfilePath, \"utf-8\");\n result.lanes = parseFastfile(content);\n\n // Warn if the Fastfile contains complex Ruby that may have been misread\n if (COMPLEX_RUBY_RE.test(content)) {\n result.parseWarnings.push(\n \"Fastfile contains complex Ruby constructs (begin/rescue/if/unless/case). \" +\n \"Lane detection may be incomplete — review MIGRATION.md and adjust manually.\",\n );\n }\n } catch {\n result.parseWarnings.push(\"Could not read Fastfile — check permissions\");\n }\n }\n\n // Parse Appfile if present\n if (result.hasAppfile) {\n try {\n const content = await readFile(appfilePath, \"utf-8\");\n const parsed = parseAppfile(content);\n result.packageName = parsed.packageName;\n result.jsonKeyPath = parsed.jsonKeyPath;\n } catch {\n result.parseWarnings.push(\"Could not read Appfile — check permissions\");\n }\n }\n\n return result;\n}\n\nexport function parseFastfile(content: string): FastlaneLane[] {\n const lanes: FastlaneLane[] = [];\n // Match lane blocks: lane :name do ... end\n const laneRegex = /lane\\s+:(\\w+)\\s+do([\\s\\S]*?)(?=\\bend\\b)/g;\n let match: RegExpExecArray | null;\n\n while ((match = laneRegex.exec(content)) !== null) {\n const name = match[1] ?? \"\";\n const body = match[2] ?? \"\";\n const actions: string[] = [];\n\n // Extract action calls\n const actionRegex =\n /\\b(supply|upload_to_play_store|capture_android_screenshots|deliver|gradle)\\b/g;\n let actionMatch: RegExpExecArray | null;\n while ((actionMatch = actionRegex.exec(body)) !== null) {\n const action = actionMatch[1] ?? \"\";\n if (!actions.includes(action)) {\n actions.push(action);\n }\n }\n\n // Determine GPC equivalent\n const gpcEquivalent = mapLaneToGpc(name, actions, body);\n\n lanes.push({ name, actions, gpcEquivalent });\n }\n\n return lanes;\n}\n\nfunction mapLaneToGpc(name: string, actions: string[], body: string): string | undefined {\n if (actions.includes(\"upload_to_play_store\") || actions.includes(\"supply\")) {\n const trackMatch = body.match(/track\\s*:\\s*[\"'](\\w+)[\"']/);\n const rolloutMatch = body.match(/rollout\\s*:\\s*[\"']?([\\d.]+)[\"']?/);\n\n if (rolloutMatch) {\n const raw = parseFloat(rolloutMatch[1] ?? \"0\");\n // Fastlane uses 0.0–1.0; convert to whole percentage for gpc\n const pct = raw > 1 ? Math.round(raw) : Math.round(raw * 100);\n return `gpc releases upload --rollout ${pct}${trackMatch ? ` --track ${trackMatch[1]}` : \"\"}`;\n }\n\n if (trackMatch) {\n return `gpc releases upload --track ${trackMatch[1]}`;\n }\n\n // Metadata-only supply\n if (body.match(/skip_upload_apk\\s*:\\s*true/) || body.match(/skip_upload_aab\\s*:\\s*true/)) {\n return \"gpc listings push\";\n }\n\n return \"gpc releases upload\";\n }\n\n if (actions.includes(\"capture_android_screenshots\")) {\n return undefined; // No equivalent\n }\n\n return undefined;\n}\n\nexport function parseAppfile(content: string): { packageName?: string; jsonKeyPath?: string } {\n const result: { packageName?: string; jsonKeyPath?: string } = {};\n\n // Match package_name(\"com.example.app\") or package_name \"com.example.app\"\n const pkgMatch = content.match(/package_name\\s*\\(?\\s*[\"']([^\"']+)[\"']\\s*\\)?/);\n if (pkgMatch) {\n result.packageName = pkgMatch[1];\n }\n\n // Match json_key_file(\"path/to/key.json\") or json_key_file \"path/to/key.json\"\n const keyMatch = content.match(/json_key_file\\s*\\(?\\s*[\"']([^\"']+)[\"']\\s*\\)?/);\n if (keyMatch) {\n result.jsonKeyPath = keyMatch[1];\n }\n\n return result;\n}\n\nexport function generateMigrationPlan(detection: FastlaneDetection): MigrationResult {\n const config: Record<string, unknown> = {};\n const checklist: string[] = [];\n const warnings: string[] = [...detection.parseWarnings];\n\n // Set package name if detected\n if (detection.packageName) {\n config[\"app\"] = detection.packageName;\n } else {\n checklist.push(\"Set your package name: gpc config set app <package-name>\");\n }\n\n // Set auth config if key path detected\n if (detection.jsonKeyPath) {\n config[\"auth\"] = { serviceAccount: detection.jsonKeyPath };\n } else {\n checklist.push(\"Configure authentication: gpc auth login\");\n }\n\n // Lane mappings\n for (const lane of detection.lanes) {\n if (lane.gpcEquivalent) {\n checklist.push(\n `Replace Fastlane lane \"${lane.name}\" with: ${lane.gpcEquivalent} <your.aab>`,\n );\n }\n\n if (lane.actions.includes(\"capture_android_screenshots\")) {\n warnings.push(\n `Lane \"${lane.name}\" uses capture_android_screenshots which has no GPC equivalent. ` +\n \"Use a separate screenshot tool or check gpc plugins list for community plugins.\",\n );\n }\n\n // Lanes with no known action and no GPC equivalent\n if (\n lane.actions.length === 0 ||\n (lane.gpcEquivalent === undefined && !lane.actions.includes(\"capture_android_screenshots\"))\n ) {\n warnings.push(\n `Lane \"${lane.name}\" has no automatic GPC equivalent. ` +\n \"Check \\`gpc plugins list\\` or the plugin SDK docs to build a custom command.\",\n );\n }\n }\n\n // Metadata migration\n if (detection.hasMetadata && detection.metadataLanguages.length > 0) {\n const langs = detection.metadataLanguages.slice(0, 3).join(\", \");\n const more =\n detection.metadataLanguages.length > 3\n ? ` (+${detection.metadataLanguages.length - 3} more)`\n : \"\";\n checklist.push(\n `Pull current metadata for ${detection.metadataLanguages.length} language(s) (${langs}${more}): gpc listings pull --dir fastlane/metadata/android`,\n );\n checklist.push(\n \"Review pulled metadata, then push back: gpc listings push --dir fastlane/metadata/android\",\n );\n }\n\n // General checklist items\n checklist.push(\"Run gpc doctor to verify your setup\");\n checklist.push(\"Test each command with --dry-run before making real changes\");\n\n if (detection.hasGemfile) {\n checklist.push(\"Remove Fastlane from your Gemfile once migration is complete\");\n }\n\n // CI/CD reminder\n if (\n detection.lanes.some(\n (l) => l.actions.includes(\"supply\") || l.actions.includes(\"upload_to_play_store\"),\n )\n ) {\n checklist.push(\"Update CI/CD pipelines to call gpc commands instead of Fastlane lanes\");\n }\n\n return { config, checklist, warnings };\n}\n\nexport async function writeMigrationOutput(\n result: MigrationResult,\n dir: string,\n): Promise<string[]> {\n await mkdir(dir, { recursive: true });\n const files: string[] = [];\n\n // Write .gpcrc.json only if we have something meaningful to put in it\n if (Object.keys(result.config).length > 0) {\n const configPath = join(dir, \".gpcrc.json\");\n await writeFile(configPath, JSON.stringify(result.config, null, 2) + \"\\n\", \"utf-8\");\n files.push(configPath);\n }\n\n // Write MIGRATION.md\n const migrationPath = join(dir, \"MIGRATION.md\");\n const lines: string[] = [\n \"# Fastlane to GPC Migration\",\n \"\",\n \"Generated by `gpc migrate fastlane`. Review and adjust before applying.\",\n \"\",\n \"## Migration Checklist\",\n \"\",\n ];\n\n for (const item of result.checklist) {\n lines.push(`- [ ] ${item}`);\n }\n\n if (result.warnings.length > 0) {\n lines.push(\"\");\n lines.push(\"## Warnings\");\n lines.push(\"\");\n for (const warning of result.warnings) {\n lines.push(`> ⚠ ${warning}`);\n }\n }\n\n lines.push(\"\");\n lines.push(\"## Quick Reference\");\n lines.push(\"\");\n lines.push(\"| Fastlane | GPC |\");\n lines.push(\"|----------|-----|\");\n lines.push(\"| `fastlane supply` | `gpc releases upload` / `gpc listings push` |\");\n lines.push(\"| `upload_to_play_store` | `gpc releases upload` |\");\n lines.push(\"| `supply(track: \\\"internal\\\")` | `gpc releases upload --track internal` |\");\n lines.push(\"| `supply(rollout: \\\"0.1\\\")` | `gpc releases upload --rollout 10` |\");\n lines.push(\"| `supply(skip_upload_aab: true)` | `gpc listings push` |\");\n lines.push(\"| `capture_android_screenshots` | No equivalent — use separate tool |\");\n lines.push(\"\");\n lines.push(\"See the full migration guide: https://yasserstudio.github.io/gpc/migration/from-fastlane\");\n lines.push(\"\");\n\n await writeFile(migrationPath, lines.join(\"\\n\"), \"utf-8\");\n files.push(migrationPath);\n\n return files;\n}\n","import { GpcError } from \"../errors.js\";\nimport { isValidBcp47 } from \"./bcp47.js\";\n\nconst PACKAGE_NAME_RE = /^[a-zA-Z][a-zA-Z0-9_]*(\\.[a-zA-Z][a-zA-Z0-9_]*){1,}$/;\nconst SKU_RE = /^[a-zA-Z0-9._]+$/;\nconst TRACK_NAMES = [\"internal\", \"alpha\", \"beta\", \"production\"];\nconst CUSTOM_TRACK_RE = /^[a-zA-Z0-9\\-_]+$/;\n\nexport function validatePackageName(name: string): void {\n if (!name || !PACKAGE_NAME_RE.test(name)) {\n throw new GpcError(\n `Invalid package name: \"${name}\"`,\n \"INVALID_PACKAGE_NAME\",\n 2,\n \"Package name must be a valid Android application ID (e.g., com.example.myapp)\",\n );\n }\n}\n\nexport function validateVersionCode(code: string | number): void {\n const num = typeof code === \"string\" ? parseInt(code, 10) : code;\n if (!Number.isInteger(num) || num < 1) {\n throw new GpcError(\n `Invalid version code: \"${code}\"`,\n \"INVALID_VERSION_CODE\",\n 2,\n \"Version code must be a positive integer (e.g., 142)\",\n );\n }\n}\n\nexport function validateLanguageCode(code: string): void {\n if (!code || !isValidBcp47(code)) {\n throw new GpcError(\n `Invalid language code: \"${code}\"`,\n \"INVALID_LANGUAGE_CODE\",\n 2,\n \"Language code must be a valid BCP-47 tag supported by Google Play (e.g., en-US, ja-JP, fr-FR)\",\n );\n }\n}\n\nexport function validateTrackName(name: string): void {\n if (!name) {\n throw new GpcError(\n \"Track name is required\",\n \"INVALID_TRACK_NAME\",\n 2,\n \"Specify a track: internal, alpha, beta, production, or a custom track name\",\n );\n }\n if (!TRACK_NAMES.includes(name) && !CUSTOM_TRACK_RE.test(name)) {\n throw new GpcError(\n `Invalid track name: \"${name}\"`,\n \"INVALID_TRACK_NAME\",\n 2,\n `Valid tracks: ${TRACK_NAMES.join(\", \")}, or a custom track matching [a-zA-Z0-9-_]+`,\n );\n }\n}\n\nexport function validateSku(sku: string): void {\n if (!sku || !SKU_RE.test(sku)) {\n throw new GpcError(\n `Invalid product ID (SKU): \"${sku}\"`,\n \"INVALID_SKU\",\n 2,\n \"Product ID must contain only letters, numbers, dots, and underscores (e.g., premium_upgrade)\",\n );\n }\n}\n","import { readdir, readFile, stat } from \"node:fs/promises\";\nimport { extname, basename, join } from \"node:path\";\nimport { GpcError } from \"../errors.js\";\n\nexport interface ReleaseNote {\n language: string;\n text: string;\n}\n\nexport interface ReleaseNotesValidation {\n valid: boolean;\n errors: string[];\n warnings: string[];\n}\n\nconst MAX_NOTES_LENGTH = 500;\n\nexport async function readReleaseNotesFromDir(dir: string): Promise<ReleaseNote[]> {\n let entries: string[];\n try {\n entries = await readdir(dir);\n } catch {\n throw new GpcError(\n `Release notes directory not found: ${dir}`,\n \"RELEASE_NOTES_DIR_NOT_FOUND\",\n 1,\n `Create the directory and add .txt files named by language code (e.g., en-US.txt). Path: ${dir}`,\n );\n }\n\n const notes: ReleaseNote[] = [];\n\n for (const entry of entries) {\n if (extname(entry) !== \".txt\") continue;\n\n const language = basename(entry, \".txt\");\n const filePath = join(dir, entry);\n\n const stats = await stat(filePath);\n if (!stats.isFile()) continue;\n\n const text = (await readFile(filePath, \"utf-8\")).trim();\n if (text.length === 0) continue;\n\n notes.push({ language, text });\n }\n\n return notes;\n}\n\nexport function validateReleaseNotes(notes: ReleaseNote[]): ReleaseNotesValidation {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n const seen = new Set<string>();\n for (const note of notes) {\n if (seen.has(note.language)) {\n errors.push(`Duplicate language code: ${note.language}`);\n }\n seen.add(note.language);\n\n if (note.text.length > MAX_NOTES_LENGTH) {\n errors.push(\n `Release notes for \"${note.language}\" exceed ${MAX_NOTES_LENGTH} chars (${note.text.length} chars)`,\n );\n }\n }\n\n return { valid: errors.length === 0, errors, warnings };\n}\n","import { stat } from \"node:fs/promises\";\nimport { validateUploadFile } from \"../utils/file-validation.js\";\nimport { readReleaseNotesFromDir, validateReleaseNotes } from \"../utils/release-notes.js\";\n\nexport interface ValidateOptions {\n filePath: string;\n mappingFile?: string;\n track?: string;\n notes?: { language: string; text: string }[];\n notesDir?: string;\n}\n\nexport interface ValidateCheck {\n name: string;\n passed: boolean;\n message: string;\n}\n\nexport interface ValidateResult {\n valid: boolean;\n checks: ValidateCheck[];\n warnings: string[];\n}\n\nconst STANDARD_TRACKS = new Set([\n \"internal\",\n \"alpha\",\n \"beta\",\n \"production\",\n // Form factor tracks\n \"wear:internal\",\n \"wear:alpha\",\n \"wear:beta\",\n \"wear:production\",\n \"automotive:internal\",\n \"automotive:alpha\",\n \"automotive:beta\",\n \"automotive:production\",\n \"tv:internal\",\n \"tv:alpha\",\n \"tv:beta\",\n \"tv:production\",\n \"android_xr:internal\",\n \"android_xr:alpha\",\n \"android_xr:beta\",\n \"android_xr:production\",\n]);\nconst TRACK_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9_:-]*$/;\n\nexport async function validatePreSubmission(options: ValidateOptions): Promise<ValidateResult> {\n const checks: ValidateCheck[] = [];\n\n const resultWarnings: string[] = [];\n\n // 1. File validation\n const fileResult = await validateUploadFile(options.filePath);\n checks.push({\n name: \"file\",\n passed: fileResult.valid,\n message: fileResult.valid\n ? `Valid ${fileResult.fileType.toUpperCase()} (${formatSize(fileResult.sizeBytes)})`\n : fileResult.errors.join(\"; \"),\n });\n // Surface file validation warnings (e.g. large file upload time notice)\n for (const w of fileResult.warnings) {\n resultWarnings.push(w);\n }\n\n // 2. Mapping file\n if (options.mappingFile) {\n try {\n const stats = await stat(options.mappingFile);\n checks.push({\n name: \"mapping\",\n passed: stats.isFile(),\n message: stats.isFile()\n ? `Mapping file found (${formatSize(stats.size)})`\n : \"Mapping path is not a file\",\n });\n } catch {\n checks.push({\n name: \"mapping\",\n passed: false,\n message: `Mapping file not found: ${options.mappingFile}`,\n });\n }\n }\n\n // 3. Track validation\n if (options.track) {\n const isValid = STANDARD_TRACKS.has(options.track) || TRACK_PATTERN.test(options.track);\n checks.push({\n name: \"track\",\n passed: isValid,\n message: isValid\n ? `Track \"${options.track}\" is valid`\n : `Invalid track name \"${options.track}\". Use: internal, alpha, beta, production, or a custom track ID`,\n });\n }\n\n // 4. Release notes validation\n let resolvedNotes = options.notes;\n if (options.notesDir) {\n try {\n resolvedNotes = await readReleaseNotesFromDir(options.notesDir);\n checks.push({\n name: \"notes-dir\",\n passed: true,\n message: `Read release notes for ${resolvedNotes.length} language(s)`,\n });\n } catch (err) {\n checks.push({\n name: \"notes-dir\",\n passed: false,\n message: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n if (resolvedNotes && resolvedNotes.length > 0) {\n const notesResult = validateReleaseNotes(resolvedNotes);\n checks.push({\n name: \"notes\",\n passed: notesResult.valid,\n message: notesResult.valid\n ? `Release notes valid (${resolvedNotes.length} language(s))`\n : notesResult.errors.join(\"; \"),\n });\n }\n\n return {\n valid: checks.every((c) => c.passed),\n checks,\n warnings: resultWarnings,\n };\n}\n\nfunction formatSize(bytes: number): string {\n if (bytes >= 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n if (bytes >= 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${bytes} B`;\n}\n","import type { PlayApiClient } from \"@gpc-cli/api\";\nimport { uploadRelease } from \"./releases.js\";\nimport type { UploadResult, DryRunUploadResult } from \"./releases.js\";\nimport { validatePreSubmission } from \"./validate.js\";\nimport type { ValidateResult } from \"./validate.js\";\nimport { readReleaseNotesFromDir } from \"../utils/release-notes.js\";\n\nexport interface PublishOptions {\n track?: string;\n rolloutPercent?: number;\n notes?: string;\n notesDir?: string;\n releaseName?: string;\n mappingFile?: string;\n dryRun?: boolean;\n}\n\nexport interface PublishResult {\n validation: ValidateResult;\n upload?: UploadResult;\n}\n\nexport interface DryRunPublishResult {\n dryRun: true;\n validation: ValidateResult;\n upload: DryRunUploadResult;\n}\n\nexport async function publish(\n client: PlayApiClient,\n packageName: string,\n filePath: string,\n options: PublishOptions,\n): Promise<PublishResult | DryRunPublishResult> {\n // Resolve release notes\n let releaseNotes: { language: string; text: string }[] | undefined;\n if (options.notesDir) {\n releaseNotes = await readReleaseNotesFromDir(options.notesDir);\n } else if (options.notes) {\n releaseNotes = [{ language: \"en-US\", text: options.notes }];\n }\n\n // Validate\n const validation = await validatePreSubmission({\n filePath,\n mappingFile: options.mappingFile,\n track: options.track || \"internal\",\n notes: releaseNotes,\n });\n\n if (options.dryRun) {\n const upload = await uploadRelease(client, packageName, filePath, {\n track: options.track || \"internal\",\n userFraction: options.rolloutPercent ? options.rolloutPercent / 100 : undefined,\n dryRun: true,\n }) as DryRunUploadResult;\n\n return { dryRun: true, validation, upload };\n }\n\n if (!validation.valid) {\n return { validation };\n }\n\n // Upload\n const upload = await uploadRelease(client, packageName, filePath, {\n track: options.track || \"internal\",\n userFraction: options.rolloutPercent ? options.rolloutPercent / 100 : undefined,\n releaseNotes,\n releaseName: options.releaseName,\n mappingFile: options.mappingFile,\n });\n\n return { validation, upload } as PublishResult;\n}\n","import type { PlayApiClient, Review, ReviewsListOptions, ReviewReplyResponse } from \"@gpc-cli/api\";\nimport { paginateAll } from \"@gpc-cli/api\";\nimport { GpcError } from \"../errors.js\";\n\nexport interface ReviewsFilterOptions {\n stars?: number;\n language?: string;\n since?: string;\n translationLanguage?: string;\n maxResults?: number;\n limit?: number;\n nextPage?: string;\n}\n\nexport interface ReviewExportOptions extends ReviewsFilterOptions {\n format?: \"json\" | \"csv\";\n}\n\nexport async function listReviews(\n client: PlayApiClient,\n packageName: string,\n options?: ReviewsFilterOptions,\n): Promise<Review[]> {\n const apiOptions: ReviewsListOptions = {};\n if (options?.translationLanguage) apiOptions.translationLanguage = options.translationLanguage;\n if (options?.maxResults) apiOptions.maxResults = options.maxResults;\n\n const response = await client.reviews.list(packageName, apiOptions);\n let reviews = response.reviews || [];\n\n // Client-side filters\n if (options?.stars !== undefined) {\n reviews = reviews.filter((r) => {\n const userComment = r.comments?.[0]?.userComment;\n return userComment && userComment.starRating === options.stars;\n });\n }\n\n if (options?.language) {\n reviews = reviews.filter((r) => {\n const userComment = r.comments?.[0]?.userComment;\n return userComment?.reviewerLanguage === options.language;\n });\n }\n\n if (options?.since) {\n const sinceTime = new Date(options.since).getTime() / 1000;\n reviews = reviews.filter((r) => {\n const userComment = r.comments?.[0]?.userComment;\n return userComment && Number(userComment.lastModified.seconds) >= sinceTime;\n });\n }\n\n return reviews;\n}\n\nexport async function getReview(\n client: PlayApiClient,\n packageName: string,\n reviewId: string,\n translationLanguage?: string,\n): Promise<Review> {\n return client.reviews.get(packageName, reviewId, translationLanguage);\n}\n\nconst MAX_REPLY_LENGTH = 350;\n\nexport async function replyToReview(\n client: PlayApiClient,\n packageName: string,\n reviewId: string,\n replyText: string,\n): Promise<ReviewReplyResponse> {\n if (replyText.length > MAX_REPLY_LENGTH) {\n throw new GpcError(\n `Reply text exceeds ${MAX_REPLY_LENGTH} characters (${replyText.length}). Google Play limits replies to ${MAX_REPLY_LENGTH} characters.`,\n \"REVIEW_REPLY_TOO_LONG\",\n 2,\n `Shorten your reply to ${MAX_REPLY_LENGTH} characters or fewer. Current length: ${replyText.length}.`,\n );\n }\n if (replyText.length === 0) {\n throw new GpcError(\n \"Reply text cannot be empty.\",\n \"REVIEW_REPLY_EMPTY\",\n 2,\n \"Provide a non-empty reply text with --text or -t.\",\n );\n }\n return client.reviews.reply(packageName, reviewId, replyText);\n}\n\nexport async function exportReviews(\n client: PlayApiClient,\n packageName: string,\n options?: ReviewExportOptions,\n): Promise<string> {\n const { items: allReviews } = await paginateAll<Review>(async (pageToken) => {\n const apiOptions: ReviewsListOptions = { token: pageToken };\n if (options?.translationLanguage) apiOptions.translationLanguage = options.translationLanguage;\n const response = await client.reviews.list(packageName, apiOptions);\n return {\n items: response.reviews || [],\n nextPageToken: response.tokenPagination?.nextPageToken,\n };\n });\n\n let filtered = allReviews;\n\n if (options?.stars !== undefined) {\n filtered = filtered.filter((r) => {\n const uc = r.comments?.[0]?.userComment;\n return uc && uc.starRating === options.stars;\n });\n }\n\n if (options?.language) {\n filtered = filtered.filter((r) => {\n const uc = r.comments?.[0]?.userComment;\n return uc?.reviewerLanguage === options.language;\n });\n }\n\n if (options?.since) {\n const sinceTime = new Date(options.since).getTime() / 1000;\n filtered = filtered.filter((r) => {\n const uc = r.comments?.[0]?.userComment;\n return uc && Number(uc.lastModified.seconds) >= sinceTime;\n });\n }\n\n if (options?.format === \"csv\") {\n return reviewsToCsv(filtered);\n }\n\n return JSON.stringify(filtered, null, 2);\n}\n\nfunction reviewsToCsv(reviews: Review[]): string {\n const header = \"reviewId,authorName,starRating,text,language,date,device,appVersionName\";\n const rows = reviews.map((r) => {\n const uc = r.comments?.[0]?.userComment;\n const fields = [\n r.reviewId,\n csvEscape(r.authorName),\n uc?.starRating ?? \"\",\n csvEscape(uc?.text ?? \"\"),\n uc?.reviewerLanguage ?? \"\",\n uc ? new Date(Number(uc.lastModified.seconds) * 1000).toISOString() : \"\",\n csvEscape(uc?.device ?? \"\"),\n csvEscape(uc?.appVersionName ?? \"\"),\n ];\n return fields.join(\",\");\n });\n return [header, ...rows].join(\"\\n\");\n}\n\nfunction csvEscape(value: string): string {\n if (value.includes(\",\") || value.includes('\"') || value.includes(\"\\n\")) {\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\n }\n return value;\n}\n","import type {\n ReportingApiClient,\n VitalsMetricSet,\n MetricSetQuery,\n MetricSetResponse,\n MetricRow,\n AnomalyDetectionResponse,\n ErrorIssuesResponse,\n ReportingDimension,\n ReportingAggregation,\n} from \"@gpc-cli/api\";\n\nexport interface VitalsQueryOptions {\n dimension?: ReportingDimension;\n days?: number;\n aggregation?: ReportingAggregation;\n}\n\nexport interface VitalsOverview {\n crashRate?: MetricRow[];\n anrRate?: MetricRow[];\n slowStartRate?: MetricRow[];\n slowRenderingRate?: MetricRow[];\n excessiveWakeupRate?: MetricRow[];\n stuckWakelockRate?: MetricRow[];\n}\n\nexport interface ThresholdResult {\n breached: boolean;\n value: number | undefined;\n threshold: number;\n}\n\nconst METRIC_SET_METRICS: Record<VitalsMetricSet, string[]> = {\n crashRateMetricSet: [\"crashRate\", \"userPerceivedCrashRate\", \"distinctUsers\"],\n anrRateMetricSet: [\"anrRate\", \"userPerceivedAnrRate\", \"distinctUsers\"],\n slowStartRateMetricSet: [\"slowStartRate\", \"distinctUsers\"],\n slowRenderingRateMetricSet: [\"slowRenderingRate\", \"distinctUsers\"],\n excessiveWakeupRateMetricSet: [\"excessiveWakeupRate\", \"distinctUsers\"],\n stuckBackgroundWakelockRateMetricSet: [\"stuckBackgroundWakelockRate\", \"distinctUsers\"],\n errorCountMetricSet: [\"errorReportCount\", \"distinctUsers\"],\n};\n\nfunction buildQuery(metricSet: VitalsMetricSet, options?: VitalsQueryOptions): MetricSetQuery {\n const metrics = METRIC_SET_METRICS[metricSet] ?? [\"errorReportCount\", \"distinctUsers\"];\n\n const days = options?.days ?? 30;\n const DAY_MS = 24 * 60 * 60 * 1000;\n const end = new Date(Date.now() - DAY_MS); // API data lags ~1 day; cap to yesterday\n const start = new Date(Date.now() - DAY_MS - days * DAY_MS);\n\n const query: MetricSetQuery = {\n metrics,\n timelineSpec: {\n aggregationPeriod: options?.aggregation ?? \"DAILY\",\n startTime: {\n year: start.getUTCFullYear(),\n month: start.getUTCMonth() + 1,\n day: start.getUTCDate(),\n },\n endTime: {\n year: end.getUTCFullYear(),\n month: end.getUTCMonth() + 1,\n day: end.getUTCDate(),\n },\n },\n };\n\n if (options?.dimension) {\n query.dimensions = [options.dimension];\n }\n\n return query;\n}\n\nasync function queryMetric(\n reporting: ReportingApiClient,\n packageName: string,\n metricSet: VitalsMetricSet,\n options?: VitalsQueryOptions,\n): Promise<MetricSetResponse> {\n const query = buildQuery(metricSet, options);\n return reporting.queryMetricSet(packageName, metricSet, query);\n}\n\nexport async function getVitalsOverview(\n reporting: ReportingApiClient,\n packageName: string,\n): Promise<VitalsOverview> {\n const metricSets: [VitalsMetricSet, keyof VitalsOverview][] = [\n [\"crashRateMetricSet\", \"crashRate\"],\n [\"anrRateMetricSet\", \"anrRate\"],\n [\"slowStartRateMetricSet\", \"slowStartRate\"],\n [\"slowRenderingRateMetricSet\", \"slowRenderingRate\"],\n [\"excessiveWakeupRateMetricSet\", \"excessiveWakeupRate\"],\n [\"stuckBackgroundWakelockRateMetricSet\", \"stuckWakelockRate\"],\n ];\n\n const results = await Promise.allSettled(\n metricSets.map(([metric]) =>\n reporting.queryMetricSet(packageName, metric, buildQuery(metric)),\n ),\n );\n\n const overview: VitalsOverview = {};\n for (let i = 0; i < metricSets.length; i++) {\n const entry = metricSets[i];\n if (!entry) continue;\n const key = entry[1];\n const result = results[i];\n if (!result) continue;\n if (result.status === \"fulfilled\") {\n overview[key] = result.value.rows || [];\n }\n }\n\n return overview;\n}\n\nexport async function getVitalsCrashes(\n reporting: ReportingApiClient,\n packageName: string,\n options?: VitalsQueryOptions,\n): Promise<MetricSetResponse> {\n return queryMetric(reporting, packageName, \"crashRateMetricSet\", options);\n}\n\nexport async function getVitalsAnr(\n reporting: ReportingApiClient,\n packageName: string,\n options?: VitalsQueryOptions,\n): Promise<MetricSetResponse> {\n return queryMetric(reporting, packageName, \"anrRateMetricSet\", options);\n}\n\nexport async function getVitalsStartup(\n reporting: ReportingApiClient,\n packageName: string,\n options?: VitalsQueryOptions,\n): Promise<MetricSetResponse> {\n return queryMetric(reporting, packageName, \"slowStartRateMetricSet\", options);\n}\n\nexport async function getVitalsRendering(\n reporting: ReportingApiClient,\n packageName: string,\n options?: VitalsQueryOptions,\n): Promise<MetricSetResponse> {\n return queryMetric(reporting, packageName, \"slowRenderingRateMetricSet\", options);\n}\n\nexport async function getVitalsBattery(\n reporting: ReportingApiClient,\n packageName: string,\n options?: VitalsQueryOptions,\n): Promise<MetricSetResponse> {\n return queryMetric(reporting, packageName, \"excessiveWakeupRateMetricSet\", options);\n}\n\nexport async function getVitalsMemory(\n reporting: ReportingApiClient,\n packageName: string,\n options?: VitalsQueryOptions,\n): Promise<MetricSetResponse> {\n return queryMetric(reporting, packageName, \"stuckBackgroundWakelockRateMetricSet\", options);\n}\n\nexport async function getVitalsAnomalies(\n reporting: ReportingApiClient,\n packageName: string,\n): Promise<AnomalyDetectionResponse> {\n return reporting.getAnomalies(packageName);\n}\n\nexport async function searchVitalsErrors(\n reporting: ReportingApiClient,\n packageName: string,\n options?: { filter?: string; maxResults?: number },\n): Promise<ErrorIssuesResponse> {\n return reporting.searchErrorIssues(packageName, options?.filter, options?.maxResults);\n}\n\nexport interface VitalsTrendComparison {\n metric: string;\n current: number | undefined;\n previous: number | undefined;\n changePercent: number | undefined;\n direction: \"improved\" | \"degraded\" | \"unchanged\" | \"unknown\";\n}\n\nexport async function compareVitalsTrend(\n reporting: ReportingApiClient,\n packageName: string,\n metricSet: VitalsMetricSet,\n days: number = 7,\n): Promise<VitalsTrendComparison> {\n const DAY_MS = 24 * 60 * 60 * 1000;\n const nowMs = Date.now();\n\n // Cap to 2 days ago — API data typically lags 1-2 days; using 2 ensures\n // the endTime is always within the available data window.\n const baseMs = nowMs - 2 * DAY_MS;\n\n // Current period: [base - days, base]\n const currentEnd = new Date(baseMs);\n const currentStart = new Date(baseMs - days * DAY_MS);\n\n // Previous period: [base - 2*days - 1, base - days - 1] (1-day gap)\n const previousEnd = new Date(baseMs - days * DAY_MS - DAY_MS);\n const previousStart = new Date(baseMs - days * DAY_MS - DAY_MS - days * DAY_MS);\n\n const metrics = METRIC_SET_METRICS[metricSet] ?? [\"errorReportCount\", \"distinctUsers\"];\n\n // Use UTC accessors to avoid timezone-dependent off-by-one on date boundaries\n const toApiDate = (d: Date) => ({\n year: d.getUTCFullYear(),\n month: d.getUTCMonth() + 1,\n day: d.getUTCDate(),\n });\n\n const makeQuery = (start: Date, end: Date): MetricSetQuery => ({\n metrics,\n timelineSpec: {\n aggregationPeriod: \"DAILY\",\n startTime: toApiDate(start),\n endTime: toApiDate(end),\n },\n });\n\n const [currentResult, previousResult] = await Promise.all([\n reporting.queryMetricSet(packageName, metricSet, makeQuery(currentStart, currentEnd)),\n reporting.queryMetricSet(packageName, metricSet, makeQuery(previousStart, previousEnd)),\n ]);\n\n const extractAvg = (rows: MetricRow[] | undefined): number | undefined => {\n if (!rows || rows.length === 0) return undefined;\n const values = rows\n .map((r) => {\n const keys = Object.keys(r.metrics);\n const first = keys[0];\n return first ? Number(r.metrics[first]?.decimalValue?.value) : NaN;\n })\n .filter((v) => !isNaN(v));\n if (values.length === 0) return undefined;\n return values.reduce((a, b) => a + b, 0) / values.length;\n };\n\n const current = extractAvg(currentResult.rows);\n const previous = extractAvg(previousResult.rows);\n\n let changePercent: number | undefined;\n let direction: VitalsTrendComparison[\"direction\"] = \"unknown\";\n\n if (current !== undefined && previous !== undefined && previous !== 0) {\n changePercent = ((current - previous) / previous) * 100;\n if (Math.abs(changePercent) < 1) {\n direction = \"unchanged\";\n } else if (changePercent < 0) {\n direction = \"improved\"; // lower error rate = better\n } else {\n direction = \"degraded\";\n }\n }\n\n return {\n metric: metricSet,\n current,\n previous,\n changePercent: changePercent !== undefined ? Math.round(changePercent * 10) / 10 : undefined,\n direction,\n };\n}\n\nexport function checkThreshold(value: number | undefined, threshold: number): ThresholdResult {\n return {\n breached: value !== undefined && value > threshold,\n value,\n threshold,\n };\n}\n","import type {\n PlayApiClient,\n Subscription,\n BasePlanMigratePricesRequest,\n SubscriptionOffer,\n OffersListResponse,\n Money,\n} from \"@gpc-cli/api\";\nimport { paginateAll } from \"@gpc-cli/api\";\nimport { validatePackageName, validateSku } from \"../utils/validation.js\";\nimport { GpcError } from \"../errors.js\";\n\nexport interface ListSubscriptionsOptions {\n pageToken?: string;\n pageSize?: number;\n limit?: number;\n nextPage?: string;\n}\n\n// --- Sanitization: strip output-only fields, coerce types ---\n\nfunction coerceMoneyUnits(money: Money): Money {\n if (money.units !== undefined && typeof money.units !== \"string\") {\n return { ...money, units: String(money.units) };\n }\n return money;\n}\n\nfunction sanitizeSubscription(data: Subscription): Subscription {\n const { ...cleaned } = data;\n // Strip output-only fields from top level\n delete (cleaned as Record<string, unknown>)[\"state\"];\n delete (cleaned as Record<string, unknown>)[\"archived\"];\n\n if (cleaned.basePlans) {\n cleaned.basePlans = cleaned.basePlans.map((bp) => {\n const { state: _s, archived: _a, ...cleanBp } = bp;\n // Coerce Money.units to string in regional configs\n if (cleanBp.regionalConfigs) {\n cleanBp.regionalConfigs = cleanBp.regionalConfigs.map((rc) => ({\n ...rc,\n price: coerceMoneyUnits(rc.price),\n }));\n }\n return cleanBp;\n });\n }\n return cleaned;\n}\n\nfunction sanitizeOffer(data: SubscriptionOffer): SubscriptionOffer {\n const { state: _s, ...cleaned } = data;\n delete (cleaned as Record<string, unknown>)[\"archived\"];\n return cleaned as SubscriptionOffer;\n}\n\n// --- Client-side validation ---\n\nfunction parseDuration(iso: string): number {\n const match = iso.match(/^P(\\d+)D$/);\n return match?.[1] ? parseInt(match[1], 10) : 0;\n}\n\nconst PRORATION_MODE_PREFIX = \"SUBSCRIPTION_PRORATION_MODE_\";\nconst VALID_PRORATION_MODES = [\n \"SUBSCRIPTION_PRORATION_MODE_CHARGE_ON_NEXT_BILLING_DATE\",\n \"SUBSCRIPTION_PRORATION_MODE_CHARGE_FULL_PRICE_IMMEDIATELY\",\n];\n\nfunction autoFixProrationMode(data: Subscription): void {\n if (!data.basePlans) return;\n for (const bp of data.basePlans) {\n const mode = bp.autoRenewingBasePlanType?.prorationMode;\n if (mode && !mode.startsWith(PRORATION_MODE_PREFIX)) {\n bp.autoRenewingBasePlanType!.prorationMode = `${PRORATION_MODE_PREFIX}${mode}`;\n }\n if (bp.autoRenewingBasePlanType?.prorationMode) {\n const fullMode = bp.autoRenewingBasePlanType.prorationMode;\n if (!VALID_PRORATION_MODES.includes(fullMode)) {\n throw new GpcError(\n `Invalid prorationMode: \"${fullMode}\"`,\n \"INVALID_SUBSCRIPTION_DATA\",\n 2,\n `Valid values: ${VALID_PRORATION_MODES.join(\", \")}`,\n );\n }\n }\n }\n}\n\nfunction validateSubscriptionData(data: Subscription): void {\n // Auto-fix prorationMode prefix\n autoFixProrationMode(data);\n\n // Validate listings\n if (data.listings) {\n for (const [lang, listing] of Object.entries(data.listings)) {\n if (listing.benefits && listing.benefits.length > 4) {\n throw new GpcError(\n `Listing \"${lang}\" has ${listing.benefits.length} benefits (max 4)`,\n \"INVALID_SUBSCRIPTION_DATA\",\n 2,\n \"Google Play allows a maximum of 4 benefits per subscription listing\",\n );\n }\n if (listing.description && listing.description.length > 80) {\n throw new GpcError(\n `Listing \"${lang}\" description is ${listing.description.length} chars (max 80)`,\n \"INVALID_SUBSCRIPTION_DATA\",\n 2,\n \"Google Play limits subscription descriptions to 80 characters\",\n );\n }\n }\n }\n\n // Validate base plan durations\n if (data.basePlans) {\n for (const bp of data.basePlans) {\n const autoType = bp.autoRenewingBasePlanType;\n if (autoType?.gracePeriodDuration && autoType?.accountHoldDuration) {\n const grace = parseDuration(autoType.gracePeriodDuration);\n const hold = parseDuration(autoType.accountHoldDuration);\n const sum = grace + hold;\n if (sum < 30 || sum > 60) {\n throw new GpcError(\n `Base plan \"${bp.basePlanId}\": gracePeriodDuration (${grace}d) + accountHoldDuration (${hold}d) = ${sum}d (must be 30-60)`,\n \"INVALID_SUBSCRIPTION_DATA\",\n 2,\n \"gracePeriodDuration + accountHoldDuration must sum to between P30D and P60D\",\n );\n }\n }\n }\n }\n}\n\nexport async function listSubscriptions(\n client: PlayApiClient,\n packageName: string,\n options?: ListSubscriptionsOptions,\n): Promise<{ subscriptions: Subscription[]; nextPageToken?: string }> {\n validatePackageName(packageName);\n if (options?.limit || options?.nextPage) {\n const result = await paginateAll<Subscription>(\n async (pageToken) => {\n const resp = await client.subscriptions.list(packageName, {\n pageToken,\n pageSize: options?.pageSize,\n });\n return { items: resp.subscriptions || [], nextPageToken: resp.nextPageToken };\n },\n { limit: options.limit, startPageToken: options.nextPage },\n );\n return { subscriptions: result.items, nextPageToken: result.nextPageToken };\n }\n return client.subscriptions.list(packageName, {\n pageToken: options?.pageToken,\n pageSize: options?.pageSize,\n });\n}\n\nexport async function getSubscription(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n): Promise<Subscription> {\n validatePackageName(packageName);\n validateSku(productId);\n return client.subscriptions.get(packageName, productId);\n}\n\nexport async function createSubscription(\n client: PlayApiClient,\n packageName: string,\n data: Subscription,\n): Promise<Subscription> {\n validatePackageName(packageName);\n validateSubscriptionData(data);\n const sanitized = sanitizeSubscription(data);\n return client.subscriptions.create(packageName, sanitized, data.productId);\n}\n\nconst SUBSCRIPTION_ID_FIELDS = new Set([\"productId\", \"packageName\"]);\n\nfunction deriveSubscriptionUpdateMask(data: Subscription): string {\n return Object.keys(data)\n .filter((k) => !SUBSCRIPTION_ID_FIELDS.has(k))\n .join(\",\");\n}\n\nexport async function updateSubscription(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n data: Subscription,\n updateMask?: string,\n): Promise<Subscription> {\n validatePackageName(packageName);\n validateSku(productId);\n validateSubscriptionData(data);\n const sanitized = sanitizeSubscription(data);\n const mask = updateMask || deriveSubscriptionUpdateMask(data);\n return client.subscriptions.update(packageName, productId, sanitized, mask);\n}\n\nexport async function deleteSubscription(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n): Promise<void> {\n validatePackageName(packageName);\n validateSku(productId);\n return client.subscriptions.delete(packageName, productId);\n}\n\nexport async function activateBasePlan(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n basePlanId: string,\n): Promise<Subscription> {\n validatePackageName(packageName);\n validateSku(productId);\n return client.subscriptions.activateBasePlan(packageName, productId, basePlanId);\n}\n\nexport async function deactivateBasePlan(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n basePlanId: string,\n): Promise<Subscription> {\n validatePackageName(packageName);\n validateSku(productId);\n return client.subscriptions.deactivateBasePlan(packageName, productId, basePlanId);\n}\n\nexport async function deleteBasePlan(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n basePlanId: string,\n): Promise<void> {\n validatePackageName(packageName);\n validateSku(productId);\n return client.subscriptions.deleteBasePlan(packageName, productId, basePlanId);\n}\n\nexport async function migratePrices(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n basePlanId: string,\n data: BasePlanMigratePricesRequest,\n): Promise<Subscription> {\n validatePackageName(packageName);\n validateSku(productId);\n return client.subscriptions.migratePrices(packageName, productId, basePlanId, data);\n}\n\nexport async function listOffers(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n basePlanId: string,\n): Promise<OffersListResponse> {\n validatePackageName(packageName);\n validateSku(productId);\n return client.subscriptions.listOffers(packageName, productId, basePlanId);\n}\n\nexport async function getOffer(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n basePlanId: string,\n offerId: string,\n): Promise<SubscriptionOffer> {\n validatePackageName(packageName);\n validateSku(productId);\n return client.subscriptions.getOffer(packageName, productId, basePlanId, offerId);\n}\n\nexport async function createOffer(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n basePlanId: string,\n data: SubscriptionOffer,\n): Promise<SubscriptionOffer> {\n validatePackageName(packageName);\n validateSku(productId);\n const sanitized = sanitizeOffer(data);\n return client.subscriptions.createOffer(packageName, productId, basePlanId, sanitized, data.offerId);\n}\n\nconst OFFER_ID_FIELDS = new Set([\"productId\", \"basePlanId\", \"offerId\"]);\n\nfunction deriveOfferUpdateMask(data: SubscriptionOffer): string {\n return Object.keys(data)\n .filter((k) => !OFFER_ID_FIELDS.has(k))\n .join(\",\");\n}\n\nexport async function updateOffer(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n basePlanId: string,\n offerId: string,\n data: SubscriptionOffer,\n updateMask?: string,\n): Promise<SubscriptionOffer> {\n validatePackageName(packageName);\n validateSku(productId);\n const sanitized = sanitizeOffer(data);\n const mask = updateMask || deriveOfferUpdateMask(data);\n return client.subscriptions.updateOffer(\n packageName,\n productId,\n basePlanId,\n offerId,\n sanitized,\n mask,\n );\n}\n\nexport async function deleteOffer(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n basePlanId: string,\n offerId: string,\n): Promise<void> {\n validatePackageName(packageName);\n validateSku(productId);\n return client.subscriptions.deleteOffer(packageName, productId, basePlanId, offerId);\n}\n\nexport async function activateOffer(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n basePlanId: string,\n offerId: string,\n): Promise<SubscriptionOffer> {\n validatePackageName(packageName);\n validateSku(productId);\n return client.subscriptions.activateOffer(packageName, productId, basePlanId, offerId);\n}\n\nexport interface SubscriptionDiff {\n field: string;\n local: string;\n remote: string;\n}\n\nexport async function diffSubscription(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n localData: Subscription,\n): Promise<SubscriptionDiff[]> {\n validatePackageName(packageName);\n validateSku(productId);\n const remote = await client.subscriptions.get(packageName, productId);\n const diffs: SubscriptionDiff[] = [];\n const fieldsToCompare = [\"listings\", \"basePlans\", \"taxAndComplianceSettings\"];\n\n for (const field of fieldsToCompare) {\n const localVal = JSON.stringify((localData as unknown as Record<string, unknown>)[field] ?? null);\n const remoteVal = JSON.stringify((remote as unknown as Record<string, unknown>)[field] ?? null);\n if (localVal !== remoteVal) {\n diffs.push({ field, local: localVal, remote: remoteVal });\n }\n }\n return diffs;\n}\n\nexport async function deactivateOffer(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n basePlanId: string,\n offerId: string,\n): Promise<SubscriptionOffer> {\n validatePackageName(packageName);\n validateSku(productId);\n return client.subscriptions.deactivateOffer(packageName, productId, basePlanId, offerId);\n}\n","import { readdir, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { PlayApiClient, InAppProduct, InAppProductsBatchUpdateRequest } from \"@gpc-cli/api\";\nimport { paginateAll } from \"@gpc-cli/api\";\nimport { GpcError } from \"../errors.js\";\n\nexport interface ListIapOptions {\n token?: string;\n maxResults?: number;\n limit?: number;\n nextPage?: string;\n}\n\nexport async function listInAppProducts(\n client: PlayApiClient,\n packageName: string,\n options?: ListIapOptions,\n): Promise<{ inappproduct: InAppProduct[]; nextPageToken?: string }> {\n if (options?.limit || options?.nextPage) {\n const result = await paginateAll<InAppProduct>(\n async (pageToken) => {\n const resp = await client.inappproducts.list(packageName, {\n token: pageToken,\n maxResults: options?.maxResults,\n });\n return {\n items: resp.inappproduct || [],\n nextPageToken: resp.tokenPagination?.nextPageToken,\n };\n },\n { limit: options.limit, startPageToken: options.nextPage },\n );\n return { inappproduct: result.items, nextPageToken: result.nextPageToken };\n }\n return client.inappproducts.list(packageName, {\n token: options?.token,\n maxResults: options?.maxResults,\n });\n}\n\nexport async function getInAppProduct(\n client: PlayApiClient,\n packageName: string,\n sku: string,\n): Promise<InAppProduct> {\n return client.inappproducts.get(packageName, sku);\n}\n\nexport async function createInAppProduct(\n client: PlayApiClient,\n packageName: string,\n data: InAppProduct,\n): Promise<InAppProduct> {\n return client.inappproducts.create(packageName, data);\n}\n\nexport async function updateInAppProduct(\n client: PlayApiClient,\n packageName: string,\n sku: string,\n data: InAppProduct,\n): Promise<InAppProduct> {\n return client.inappproducts.update(packageName, sku, data);\n}\n\nexport async function deleteInAppProduct(\n client: PlayApiClient,\n packageName: string,\n sku: string,\n): Promise<void> {\n return client.inappproducts.delete(packageName, sku);\n}\n\nexport interface SyncResult {\n created: number;\n updated: number;\n unchanged: number;\n skus: string[];\n}\n\nexport async function syncInAppProducts(\n client: PlayApiClient,\n packageName: string,\n dir: string,\n options?: { dryRun?: boolean },\n): Promise<SyncResult> {\n const localProducts = await readProductsFromDir(dir);\n\n if (localProducts.length === 0) {\n return { created: 0, updated: 0, unchanged: 0, skus: [] };\n }\n\n const response = await client.inappproducts.list(packageName);\n const remoteSkus = new Set((response.inappproduct || []).map((p) => p.sku));\n\n const toUpdate = localProducts.filter((p) => remoteSkus.has(p.sku));\n const toCreate = localProducts.filter((p) => !remoteSkus.has(p.sku));\n const skus = localProducts.map((p) => p.sku);\n\n if (options?.dryRun) {\n return { created: toCreate.length, updated: toUpdate.length, unchanged: 0, skus };\n }\n\n // Attempt batch update for products that need updating (multiple items)\n if (toUpdate.length > 1) {\n try {\n await batchUpdateProducts(client, packageName, toUpdate);\n } catch {\n // Fallback to serial updates\n for (const product of toUpdate) {\n await client.inappproducts.update(packageName, product.sku, product);\n }\n }\n } else {\n for (const product of toUpdate) {\n await client.inappproducts.update(packageName, product.sku, product);\n }\n }\n\n for (const product of toCreate) {\n await client.inappproducts.create(packageName, product);\n }\n\n return { created: toCreate.length, updated: toUpdate.length, unchanged: 0, skus };\n}\n\nconst BATCH_CHUNK_SIZE = 100;\n\nasync function batchUpdateProducts(\n client: PlayApiClient,\n packageName: string,\n products: InAppProduct[],\n): Promise<InAppProduct[]> {\n const results: InAppProduct[] = [];\n for (let i = 0; i < products.length; i += BATCH_CHUNK_SIZE) {\n const chunk = products.slice(i, i + BATCH_CHUNK_SIZE);\n const request: InAppProductsBatchUpdateRequest = {\n requests: chunk.map((p) => ({\n inappproduct: p,\n packageName,\n sku: p.sku,\n })),\n };\n const response = await client.inappproducts.batchUpdate(packageName, request);\n results.push(...(response.inappproducts || []));\n }\n return results;\n}\n\nasync function readProductsFromDir(dir: string): Promise<InAppProduct[]> {\n const files = await readdir(dir);\n const jsonFiles = files.filter((f) => f.endsWith(\".json\"));\n const localProducts: InAppProduct[] = [];\n for (const file of jsonFiles) {\n const content = await readFile(join(dir, file), \"utf-8\");\n try {\n localProducts.push(JSON.parse(content) as InAppProduct);\n } catch {\n throw new GpcError(\n `Failed to parse ${file}: invalid JSON`,\n \"IAP_INVALID_JSON\",\n 1,\n `Check that \"${file}\" contains valid JSON. You can validate it with: cat \"${file}\" | jq .`,\n );\n }\n }\n return localProducts;\n}\n\nexport interface BatchSyncResult extends SyncResult {\n batchUsed: boolean;\n batchErrors: number;\n}\n\nexport async function batchSyncInAppProducts(\n client: PlayApiClient,\n packageName: string,\n dir: string,\n options?: { dryRun?: boolean },\n): Promise<BatchSyncResult> {\n const localProducts = await readProductsFromDir(dir);\n\n if (localProducts.length === 0) {\n return { created: 0, updated: 0, unchanged: 0, skus: [], batchUsed: false, batchErrors: 0 };\n }\n\n const response = await client.inappproducts.list(packageName);\n const remoteSkus = new Set((response.inappproduct || []).map((p) => p.sku));\n\n const toUpdate = localProducts.filter((p) => remoteSkus.has(p.sku));\n const toCreate = localProducts.filter((p) => !remoteSkus.has(p.sku));\n const skus = localProducts.map((p) => p.sku);\n\n if (options?.dryRun) {\n return {\n created: toCreate.length,\n updated: toUpdate.length,\n unchanged: 0,\n skus,\n batchUsed: toUpdate.length > 1,\n batchErrors: 0,\n };\n }\n\n let batchUsed = false;\n let batchErrors = 0;\n\n if (toUpdate.length > 1) {\n batchUsed = true;\n try {\n await batchUpdateProducts(client, packageName, toUpdate);\n } catch {\n batchErrors++;\n // Fallback to serial updates\n for (const product of toUpdate) {\n await client.inappproducts.update(packageName, product.sku, product);\n }\n }\n } else {\n for (const product of toUpdate) {\n await client.inappproducts.update(packageName, product.sku, product);\n }\n }\n\n for (const product of toCreate) {\n await client.inappproducts.create(packageName, product);\n }\n\n return {\n created: toCreate.length,\n updated: toUpdate.length,\n unchanged: 0,\n skus,\n batchUsed,\n batchErrors,\n };\n}\n","import type {\n PlayApiClient,\n ProductPurchase,\n SubscriptionPurchaseV2,\n SubscriptionDeferResponse,\n} from \"@gpc-cli/api\";\nimport { validatePackageName } from \"../utils/validation.js\";\n\nexport async function getProductPurchase(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n token: string,\n): Promise<ProductPurchase> {\n validatePackageName(packageName);\n return client.purchases.getProduct(packageName, productId, token);\n}\n\nexport async function acknowledgeProductPurchase(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n token: string,\n payload?: string,\n): Promise<void> {\n validatePackageName(packageName);\n const body = payload ? { developerPayload: payload } : undefined;\n return client.purchases.acknowledgeProduct(packageName, productId, token, body);\n}\n\nexport async function consumeProductPurchase(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n token: string,\n): Promise<void> {\n validatePackageName(packageName);\n return client.purchases.consumeProduct(packageName, productId, token);\n}\n\nexport async function getSubscriptionPurchase(\n client: PlayApiClient,\n packageName: string,\n token: string,\n): Promise<SubscriptionPurchaseV2> {\n validatePackageName(packageName);\n return client.purchases.getSubscriptionV2(packageName, token);\n}\n\nexport async function cancelSubscriptionPurchase(\n client: PlayApiClient,\n packageName: string,\n subscriptionId: string,\n token: string,\n): Promise<void> {\n validatePackageName(packageName);\n return client.purchases.cancelSubscription(packageName, subscriptionId, token);\n}\n\nexport async function deferSubscriptionPurchase(\n client: PlayApiClient,\n packageName: string,\n subscriptionId: string,\n token: string,\n desiredExpiry: string,\n): Promise<SubscriptionDeferResponse> {\n validatePackageName(packageName);\n const sub = await client.purchases.getSubscriptionV1(packageName, subscriptionId, token);\n return client.purchases.deferSubscription(packageName, subscriptionId, token, {\n deferralInfo: {\n expectedExpiryTimeMillis: sub.expiryTimeMillis,\n desiredExpiryTimeMillis: String(new Date(desiredExpiry).getTime()),\n },\n });\n}\n\nexport async function revokeSubscriptionPurchase(\n client: PlayApiClient,\n packageName: string,\n token: string,\n): Promise<void> {\n validatePackageName(packageName);\n return client.purchases.revokeSubscriptionV2(packageName, token);\n}\n\nimport type { VoidedPurchase } from \"@gpc-cli/api\";\nimport { paginateAll } from \"@gpc-cli/api\";\n\nexport interface ListVoidedOptions {\n startTime?: string;\n endTime?: string;\n maxResults?: number;\n limit?: number;\n nextPage?: string;\n}\n\nexport async function listVoidedPurchases(\n client: PlayApiClient,\n packageName: string,\n options?: ListVoidedOptions,\n): Promise<{ voidedPurchases: VoidedPurchase[]; nextPageToken?: string }> {\n validatePackageName(packageName);\n if (options?.limit || options?.nextPage) {\n const result = await paginateAll<VoidedPurchase>(\n async (pageToken) => {\n const resp = await client.purchases.listVoided(packageName, {\n startTime: options?.startTime,\n endTime: options?.endTime,\n maxResults: options?.maxResults,\n token: pageToken,\n });\n return {\n items: resp.voidedPurchases || [],\n nextPageToken: resp.tokenPagination?.nextPageToken,\n };\n },\n { limit: options.limit, startPageToken: options.nextPage },\n );\n return { voidedPurchases: result.items, nextPageToken: result.nextPageToken };\n }\n return client.purchases.listVoided(packageName, options);\n}\n\nexport async function refundOrder(\n client: PlayApiClient,\n packageName: string,\n orderId: string,\n options?: { fullRefund?: boolean; proratedRefund?: boolean },\n): Promise<void> {\n validatePackageName(packageName);\n return client.orders.refund(packageName, orderId, options);\n}\n","import type { PlayApiClient, ConvertRegionPricesResponse } from \"@gpc-cli/api\";\n\nexport async function convertRegionPrices(\n client: PlayApiClient,\n packageName: string,\n currencyCode: string,\n amount: string,\n): Promise<ConvertRegionPricesResponse> {\n const units = amount.split(\".\")[0] || \"0\";\n const fractional = amount.split(\".\")[1] || \"0\";\n const nanos = Number(fractional.padEnd(9, \"0\").slice(0, 9));\n\n return client.monetization.convertRegionPrices(packageName, {\n price: {\n currencyCode,\n units,\n nanos,\n },\n });\n}\n","import type { PlayApiClient, ReportBucket, ReportType, StatsDimension } from \"@gpc-cli/api\";\nimport { GpcError } from \"../errors.js\";\n\nconst FINANCIAL_REPORT_TYPES: ReadonlySet<string> = new Set([\n \"earnings\",\n \"sales\",\n \"estimated_sales\",\n \"play_balance\",\n]);\n\nconst STATS_REPORT_TYPES: ReadonlySet<string> = new Set([\n \"installs\",\n \"crashes\",\n \"ratings\",\n \"reviews\",\n \"store_performance\",\n \"subscriptions\",\n]);\n\nconst VALID_DIMENSIONS: ReadonlySet<string> = new Set([\n \"country\",\n \"language\",\n \"os_version\",\n \"device\",\n \"app_version\",\n \"carrier\",\n \"overview\",\n]);\n\nexport function isFinancialReportType(type: string): boolean {\n return FINANCIAL_REPORT_TYPES.has(type);\n}\n\nexport function isStatsReportType(type: string): boolean {\n return STATS_REPORT_TYPES.has(type);\n}\n\nexport function isValidReportType(type: string): type is ReportType {\n return FINANCIAL_REPORT_TYPES.has(type) || STATS_REPORT_TYPES.has(type);\n}\n\nexport function isValidStatsDimension(dim: string): dim is StatsDimension {\n return VALID_DIMENSIONS.has(dim);\n}\n\nexport interface ParsedMonth {\n year: number;\n month: number;\n}\n\nexport function parseMonth(monthStr: string): ParsedMonth {\n const match = /^(\\d{4})-(\\d{2})$/.exec(monthStr);\n if (!match) {\n throw new GpcError(\n `Invalid month format \"${monthStr}\". Expected YYYY-MM (e.g., 2026-03).`,\n \"REPORT_INVALID_MONTH\",\n 2,\n \"Use the format YYYY-MM, for example: --month 2026-03\",\n );\n }\n const year = Number(match[1]);\n const month = Number(match[2]);\n if (month < 1 || month > 12) {\n throw new GpcError(\n `Invalid month \"${month}\". Must be between 01 and 12.`,\n \"REPORT_INVALID_MONTH\",\n 2,\n \"The month value must be between 01 and 12.\",\n );\n }\n return { year, month };\n}\n\nexport async function listReports(\n _client: PlayApiClient,\n _packageName: string,\n reportType: ReportType,\n _year: number,\n _month: number,\n): Promise<ReportBucket[]> {\n throw new GpcError(\n `Report listing for \"${reportType}\" is not available through the Google Play Developer API.`,\n \"REPORT_NOT_SUPPORTED\",\n 1,\n isFinancialReportType(reportType)\n ? \"Financial reports are delivered via Google Cloud Storage. Access them from Play Console → Download reports → Financial.\"\n : \"Stats reports are delivered via Google Cloud Storage. For real-time metrics, use 'gpc vitals' commands.\",\n );\n}\n\nexport async function downloadReport(\n _client: PlayApiClient,\n _packageName: string,\n reportType: ReportType,\n _year: number,\n _month: number,\n): Promise<string> {\n throw new GpcError(\n `Report download for \"${reportType}\" is not available through the Google Play Developer API.`,\n \"REPORT_NOT_SUPPORTED\",\n 1,\n isFinancialReportType(reportType)\n ? \"Financial reports are delivered via Google Cloud Storage. Access them from Play Console → Download reports → Financial.\"\n : \"Stats reports are delivered via Google Cloud Storage. For real-time metrics, use 'gpc vitals' commands.\",\n );\n}\n","import type { UsersApiClient, User, DeveloperPermission, Grant } from \"@gpc-cli/api\";\nimport { paginateAll } from \"@gpc-cli/api\";\nimport { GpcError } from \"../errors.js\";\n\nexport const PERMISSION_PROPAGATION_WARNING =\n \"Note: Permission changes may take up to 48 hours to propagate.\";\n\nexport interface ListUsersOptions {\n pageToken?: string;\n pageSize?: number;\n limit?: number;\n nextPage?: string;\n}\n\nexport async function listUsers(\n client: UsersApiClient,\n developerId: string,\n options?: ListUsersOptions,\n): Promise<{ users: User[]; nextPageToken?: string }> {\n if (options?.limit || options?.nextPage) {\n const result = await paginateAll<User>(\n async (pageToken) => {\n const resp = await client.list(developerId, { pageToken, pageSize: options?.pageSize });\n return { items: resp.users || [], nextPageToken: resp.nextPageToken };\n },\n { limit: options.limit, startPageToken: options.nextPage },\n );\n return { users: result.items, nextPageToken: result.nextPageToken };\n }\n const response = await client.list(developerId, options);\n return { users: response.users || [], nextPageToken: response.nextPageToken };\n}\n\nexport async function getUser(\n client: UsersApiClient,\n developerId: string,\n userId: string,\n): Promise<User> {\n return client.get(developerId, userId);\n}\n\nexport async function inviteUser(\n client: UsersApiClient,\n developerId: string,\n email: string,\n permissions?: DeveloperPermission[],\n grants?: Grant[],\n): Promise<User> {\n const user: Partial<User> = { email };\n if (permissions) user.developerAccountPermission = permissions;\n if (grants) user.grants = grants;\n return client.create(developerId, user);\n}\n\nexport async function updateUser(\n client: UsersApiClient,\n developerId: string,\n userId: string,\n permissions?: DeveloperPermission[],\n grants?: Grant[],\n): Promise<User> {\n const updates: Partial<User> = {};\n const masks: string[] = [];\n\n if (permissions) {\n updates.developerAccountPermission = permissions;\n masks.push(\"developerAccountPermission\");\n }\n if (grants) {\n updates.grants = grants;\n masks.push(\"grants\");\n }\n\n const updateMask = masks.length > 0 ? masks.join(\",\") : undefined;\n return client.update(developerId, userId, updates, updateMask);\n}\n\nexport async function removeUser(\n client: UsersApiClient,\n developerId: string,\n userId: string,\n): Promise<void> {\n return client.delete(developerId, userId);\n}\n\nexport function parseGrantArg(grantStr: string): Grant {\n const colonIdx = grantStr.indexOf(\":\");\n if (colonIdx === -1) {\n throw new GpcError(\n `Invalid grant format \"${grantStr}\". Expected <packageName>:<PERMISSION>[,<PERMISSION>...]`,\n \"USER_INVALID_GRANT\",\n 2,\n \"Use the format: com.example.app:VIEW_APP_INFORMATION,MANAGE_STORE_LISTING\",\n );\n }\n const packageName = grantStr.slice(0, colonIdx);\n const perms = grantStr.slice(colonIdx + 1).split(\",\") as DeveloperPermission[];\n return { packageName, appLevelPermissions: perms };\n}\n","import type { PlayApiClient, Testers } from \"@gpc-cli/api\";\nimport { readFile } from \"node:fs/promises\";\nimport { GpcError } from \"../errors.js\";\n\nexport async function listTesters(\n client: PlayApiClient,\n packageName: string,\n track: string,\n): Promise<Testers> {\n const edit = await client.edits.insert(packageName);\n try {\n const testers = await client.testers.get(packageName, edit.id, track);\n return testers;\n } finally {\n await client.edits.delete(packageName, edit.id);\n }\n}\n\nexport async function addTesters(\n client: PlayApiClient,\n packageName: string,\n track: string,\n groupEmails: string[],\n): Promise<Testers> {\n const edit = await client.edits.insert(packageName);\n try {\n const current = await client.testers.get(packageName, edit.id, track);\n const existing = new Set(current.googleGroups || []);\n for (const email of groupEmails) {\n existing.add(email.trim());\n }\n const updated = await client.testers.update(packageName, edit.id, track, {\n googleGroups: [...existing],\n });\n await client.edits.validate(packageName, edit.id);\n await client.edits.commit(packageName, edit.id);\n return updated;\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function removeTesters(\n client: PlayApiClient,\n packageName: string,\n track: string,\n groupEmails: string[],\n): Promise<Testers> {\n const edit = await client.edits.insert(packageName);\n try {\n const current = await client.testers.get(packageName, edit.id, track);\n const toRemove = new Set(groupEmails.map((e) => e.trim()));\n const filtered = (current.googleGroups || []).filter((g) => !toRemove.has(g));\n const updated = await client.testers.update(packageName, edit.id, track, {\n googleGroups: filtered,\n });\n await client.edits.validate(packageName, edit.id);\n await client.edits.commit(packageName, edit.id);\n return updated;\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function importTestersFromCsv(\n client: PlayApiClient,\n packageName: string,\n track: string,\n csvPath: string,\n): Promise<{ added: number; testers: Testers }> {\n const content = await readFile(csvPath, \"utf-8\");\n const emails = content\n .split(/[,\\n\\r]+/)\n .map((e) => e.trim())\n .filter((e) => e.length > 0 && e.includes(\"@\"));\n\n if (emails.length === 0) {\n throw new GpcError(\n `No valid email addresses found in ${csvPath}.`,\n \"TESTER_NO_EMAILS\",\n 1,\n \"The CSV file must contain email addresses separated by commas or newlines. Each email must contain an @ symbol.\",\n );\n }\n\n const testers = await addTesters(client, packageName, track, emails);\n return { added: emails.length, testers };\n}\n","import { execFile as execFileCb } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { GpcError } from \"../errors.js\";\n\nconst execFile = promisify(execFileCb);\n\nexport interface GitNotesOptions {\n since?: string;\n language?: string;\n maxLength?: number;\n}\n\nexport interface GitReleaseNotes {\n language: string;\n text: string;\n commitCount: number;\n since: string;\n truncated: boolean;\n}\n\ninterface ParsedCommit {\n type: string;\n message: string;\n}\n\nconst COMMIT_TYPE_HEADERS: Record<string, string> = {\n feat: \"New\",\n fix: \"Fixed\",\n perf: \"Improved\",\n};\n\nconst DEFAULT_MAX_LENGTH = 500;\n\nfunction parseConventionalCommit(subject: string): ParsedCommit {\n const match = subject.match(/^(\\w+)(?:\\([^)]*\\))?:\\s*(.+)$/);\n if (match) {\n return { type: match[1]!, message: match[2]!.trim() };\n }\n return { type: \"other\", message: subject.trim() };\n}\n\nfunction formatNotes(commits: ParsedCommit[], maxLength: number): { text: string; truncated: boolean } {\n const groups = new Map<string, string[]>();\n\n for (const commit of commits) {\n const header = COMMIT_TYPE_HEADERS[commit.type] || \"Changes\";\n if (!groups.has(header)) {\n groups.set(header, []);\n }\n groups.get(header)!.push(commit.message);\n }\n\n // Order: New, Fixed, Improved, then Changes\n const order = [\"New\", \"Fixed\", \"Improved\", \"Changes\"];\n const sections: string[] = [];\n\n for (const header of order) {\n const items = groups.get(header);\n if (!items || items.length === 0) continue;\n const bullets = items.map((m) => `\\u2022 ${m}`).join(\"\\n\");\n sections.push(`${header}:\\n${bullets}`);\n }\n\n let text = sections.join(\"\\n\\n\");\n let truncated = false;\n\n if (text.length > maxLength) {\n text = text.slice(0, maxLength - 3) + \"...\";\n truncated = true;\n }\n\n return { text, truncated };\n}\n\nasync function gitExec(args: string[]): Promise<string> {\n try {\n const { stdout } = await execFile(\"git\", args);\n return stdout.trim();\n } catch (error: unknown) {\n const err = error as { code?: string; stderr?: string; message?: string };\n if (err.code === \"ENOENT\") {\n throw new GpcError(\n \"git is not available on this system\",\n \"GIT_NOT_FOUND\",\n 1,\n \"Install git and ensure it is in your PATH.\",\n );\n }\n throw error;\n }\n}\n\nexport async function generateNotesFromGit(\n options?: GitNotesOptions,\n): Promise<GitReleaseNotes> {\n const language = options?.language || \"en-US\";\n const maxLength = options?.maxLength ?? DEFAULT_MAX_LENGTH;\n let since = options?.since;\n\n if (!since) {\n try {\n since = await gitExec([\"describe\", \"--tags\", \"--abbrev=0\"]);\n } catch (e) {\n if (e instanceof GpcError && e.code === \"GIT_NOT_FOUND\") throw e;\n throw new GpcError(\n \"No git tags found. Cannot determine commit range for release notes.\",\n \"GIT_NO_TAGS\",\n 1,\n \"Create a tag first (e.g., git tag v1.0.0) or use --since <ref> to specify a starting point.\",\n );\n }\n }\n\n let logOutput: string;\n try {\n logOutput = await gitExec([\"log\", `${since}..HEAD`, \"--format=%s\"]);\n } catch (error: unknown) {\n const err = error as { stderr?: string; message?: string };\n const msg = err.stderr || err.message || String(error);\n throw new GpcError(\n `Failed to read git log from \"${since}\": ${msg}`,\n \"GIT_LOG_FAILED\",\n 1,\n `Verify that \"${since}\" is a valid git ref (tag, branch, or SHA).`,\n );\n }\n\n if (!logOutput) {\n return {\n language,\n text: \"No changes since last release.\",\n commitCount: 0,\n since,\n truncated: false,\n };\n }\n\n const subjects = logOutput.split(\"\\n\").filter((line) => line.length > 0);\n const commits = subjects.map(parseConventionalCommit);\n const { text, truncated } = formatNotes(commits, maxLength);\n\n return {\n language,\n text,\n commitCount: subjects.length,\n since,\n truncated,\n };\n}\n","import type {\n PlayApiClient,\n AppRecoveryAction,\n AppRecoveryTargeting,\n CreateAppRecoveryActionRequest,\n} from \"@gpc-cli/api\";\n\nexport async function listRecoveryActions(\n client: PlayApiClient,\n packageName: string,\n versionCode?: number,\n): Promise<AppRecoveryAction[]> {\n return client.appRecovery.list(packageName, versionCode);\n}\n\nexport async function cancelRecoveryAction(\n client: PlayApiClient,\n packageName: string,\n recoveryId: string,\n): Promise<void> {\n return client.appRecovery.cancel(packageName, recoveryId);\n}\n\nexport async function deployRecoveryAction(\n client: PlayApiClient,\n packageName: string,\n recoveryId: string,\n): Promise<void> {\n return client.appRecovery.deploy(packageName, recoveryId);\n}\n\nexport async function createRecoveryAction(\n client: PlayApiClient,\n packageName: string,\n request: CreateAppRecoveryActionRequest,\n): Promise<AppRecoveryAction> {\n return client.appRecovery.create(packageName, request);\n}\n\nexport async function addRecoveryTargeting(\n client: PlayApiClient,\n packageName: string,\n actionId: string,\n targeting: AppRecoveryTargeting,\n): Promise<AppRecoveryAction> {\n return client.appRecovery.addTargeting(packageName, actionId, targeting);\n}\n","import type { PlayApiClient, DataSafety } from \"@gpc-cli/api\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { GpcError } from \"../errors.js\";\n\nexport async function getDataSafety(\n client: PlayApiClient,\n packageName: string,\n): Promise<DataSafety> {\n return client.dataSafety.get(packageName);\n}\n\nexport async function updateDataSafety(\n client: PlayApiClient,\n packageName: string,\n data: DataSafety,\n): Promise<DataSafety> {\n return client.dataSafety.update(packageName, data);\n}\n\nexport async function exportDataSafety(\n client: PlayApiClient,\n packageName: string,\n outputPath: string,\n): Promise<DataSafety> {\n const dataSafety = await getDataSafety(client, packageName);\n await writeFile(outputPath, JSON.stringify(dataSafety, null, 2) + \"\\n\", \"utf-8\");\n return dataSafety;\n}\n\nexport async function importDataSafety(\n client: PlayApiClient,\n packageName: string,\n filePath: string,\n): Promise<DataSafety> {\n const content = await readFile(filePath, \"utf-8\");\n let data: DataSafety;\n try {\n data = JSON.parse(content) as DataSafety;\n } catch {\n throw new GpcError(\n `Failed to parse data safety JSON from \"${filePath}\"`,\n \"INVALID_JSON\",\n 1,\n \"Ensure the file contains valid JSON matching the data safety schema.\",\n );\n }\n return updateDataSafety(client, packageName, data);\n}\n","import type {\n PlayApiClient,\n ExternalTransaction,\n ExternalTransactionRefund,\n} from \"@gpc-cli/api\";\n\nexport async function createExternalTransaction(\n client: PlayApiClient,\n packageName: string,\n data: ExternalTransaction,\n): Promise<ExternalTransaction> {\n return client.externalTransactions.create(packageName, data);\n}\n\nexport async function getExternalTransaction(\n client: PlayApiClient,\n packageName: string,\n transactionId: string,\n): Promise<ExternalTransaction> {\n return client.externalTransactions.get(packageName, transactionId);\n}\n\nexport async function refundExternalTransaction(\n client: PlayApiClient,\n packageName: string,\n transactionId: string,\n refundData: ExternalTransactionRefund,\n): Promise<ExternalTransaction> {\n return client.externalTransactions.refund(packageName, transactionId, refundData);\n}\n","import type { PlayApiClient, DeviceTierConfig } from \"@gpc-cli/api\";\nimport { GpcError } from \"../errors.js\";\n\nexport async function listDeviceTiers(\n client: PlayApiClient,\n packageName: string,\n): Promise<DeviceTierConfig[]> {\n if (!packageName) {\n throw new GpcError(\n \"Package name is required\",\n \"MISSING_PACKAGE_NAME\",\n 2,\n \"Provide a package name with --app or set it in config.\",\n );\n }\n return client.deviceTiers.list(packageName);\n}\n\nexport async function getDeviceTier(\n client: PlayApiClient,\n packageName: string,\n configId: string,\n): Promise<DeviceTierConfig> {\n if (!packageName) {\n throw new GpcError(\n \"Package name is required\",\n \"MISSING_PACKAGE_NAME\",\n 2,\n \"Provide a package name with --app or set it in config.\",\n );\n }\n if (!configId) {\n throw new GpcError(\n \"Config ID is required\",\n \"MISSING_CONFIG_ID\",\n 2,\n \"Provide a device tier config ID.\",\n );\n }\n return client.deviceTiers.get(packageName, configId);\n}\n\nexport async function createDeviceTier(\n client: PlayApiClient,\n packageName: string,\n config: DeviceTierConfig,\n): Promise<DeviceTierConfig> {\n if (!packageName) {\n throw new GpcError(\n \"Package name is required\",\n \"MISSING_PACKAGE_NAME\",\n 2,\n \"Provide a package name with --app or set it in config.\",\n );\n }\n if (!config || !config.deviceGroups || config.deviceGroups.length === 0) {\n throw new GpcError(\n \"Device tier config must include at least one device group\",\n \"INVALID_DEVICE_TIER_CONFIG\",\n 2,\n \"Provide a valid config with deviceGroups.\",\n );\n }\n return client.deviceTiers.create(packageName, config);\n}\n","import type {\n PlayApiClient,\n OneTimeProduct,\n OneTimeProductsListResponse,\n OneTimeOffer,\n OneTimeOffersListResponse,\n} from \"@gpc-cli/api\";\nimport { GpcError } from \"../errors.js\";\n\nexport async function listOneTimeProducts(\n client: PlayApiClient,\n packageName: string,\n): Promise<OneTimeProductsListResponse> {\n try {\n return await client.oneTimeProducts.list(packageName);\n } catch (error) {\n throw new GpcError(\n `Failed to list one-time products: ${error instanceof Error ? error.message : String(error)}`,\n \"OTP_LIST_FAILED\",\n 4,\n \"Check your package name and API credentials.\",\n );\n }\n}\n\nexport async function getOneTimeProduct(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n): Promise<OneTimeProduct> {\n try {\n return await client.oneTimeProducts.get(packageName, productId);\n } catch (error) {\n throw new GpcError(\n `Failed to get one-time product \"${productId}\": ${error instanceof Error ? error.message : String(error)}`,\n \"OTP_GET_FAILED\",\n 4,\n \"Check that the product ID exists.\",\n );\n }\n}\n\nexport async function createOneTimeProduct(\n client: PlayApiClient,\n packageName: string,\n data: OneTimeProduct,\n): Promise<OneTimeProduct> {\n try {\n return await client.oneTimeProducts.create(packageName, data);\n } catch (error) {\n throw new GpcError(\n `Failed to create one-time product: ${error instanceof Error ? error.message : String(error)}`,\n \"OTP_CREATE_FAILED\",\n 4,\n \"Verify the product data and ensure the product ID is unique.\",\n );\n }\n}\n\nconst OTP_ID_FIELDS = new Set([\"productId\", \"packageName\"]);\n\nfunction deriveOtpUpdateMask(data: Partial<OneTimeProduct>): string {\n return Object.keys(data)\n .filter((k) => !OTP_ID_FIELDS.has(k))\n .join(\",\");\n}\n\nconst OTP_OFFER_ID_FIELDS = new Set([\"productId\", \"offerId\"]);\n\nfunction deriveOtpOfferUpdateMask(data: Partial<OneTimeOffer>): string {\n return Object.keys(data)\n .filter((k) => !OTP_OFFER_ID_FIELDS.has(k))\n .join(\",\");\n}\n\nexport async function updateOneTimeProduct(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n data: Partial<OneTimeProduct>,\n updateMask?: string,\n): Promise<OneTimeProduct> {\n try {\n const mask = updateMask || deriveOtpUpdateMask(data);\n return await client.oneTimeProducts.update(packageName, productId, data, mask);\n } catch (error) {\n throw new GpcError(\n `Failed to update one-time product \"${productId}\": ${error instanceof Error ? error.message : String(error)}`,\n \"OTP_UPDATE_FAILED\",\n 4,\n \"Check that the product ID exists and the data is valid.\",\n );\n }\n}\n\nexport async function deleteOneTimeProduct(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n): Promise<void> {\n try {\n await client.oneTimeProducts.delete(packageName, productId);\n } catch (error) {\n throw new GpcError(\n `Failed to delete one-time product \"${productId}\": ${error instanceof Error ? error.message : String(error)}`,\n \"OTP_DELETE_FAILED\",\n 4,\n \"Check that the product ID exists and is not active.\",\n );\n }\n}\n\nexport async function listOneTimeOffers(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n): Promise<OneTimeOffersListResponse> {\n try {\n return await client.oneTimeProducts.listOffers(packageName, productId);\n } catch (error) {\n throw new GpcError(\n `Failed to list offers for product \"${productId}\": ${error instanceof Error ? error.message : String(error)}`,\n \"OTP_OFFERS_LIST_FAILED\",\n 4,\n \"Check the product ID and your API credentials.\",\n );\n }\n}\n\nexport async function getOneTimeOffer(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n offerId: string,\n): Promise<OneTimeOffer> {\n try {\n return await client.oneTimeProducts.getOffer(packageName, productId, offerId);\n } catch (error) {\n throw new GpcError(\n `Failed to get offer \"${offerId}\" for product \"${productId}\": ${error instanceof Error ? error.message : String(error)}`,\n \"OTP_OFFER_GET_FAILED\",\n 4,\n \"Check that the product and offer IDs exist.\",\n );\n }\n}\n\nexport async function createOneTimeOffer(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n data: OneTimeOffer,\n): Promise<OneTimeOffer> {\n try {\n return await client.oneTimeProducts.createOffer(packageName, productId, data);\n } catch (error) {\n throw new GpcError(\n `Failed to create offer for product \"${productId}\": ${error instanceof Error ? error.message : String(error)}`,\n \"OTP_OFFER_CREATE_FAILED\",\n 4,\n \"Verify the offer data and ensure the offer ID is unique.\",\n );\n }\n}\n\nexport async function updateOneTimeOffer(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n offerId: string,\n data: Partial<OneTimeOffer>,\n updateMask?: string,\n): Promise<OneTimeOffer> {\n try {\n const mask = updateMask || deriveOtpOfferUpdateMask(data);\n return await client.oneTimeProducts.updateOffer(packageName, productId, offerId, data, mask);\n } catch (error) {\n throw new GpcError(\n `Failed to update offer \"${offerId}\" for product \"${productId}\": ${error instanceof Error ? error.message : String(error)}`,\n \"OTP_OFFER_UPDATE_FAILED\",\n 4,\n \"Check that the product and offer IDs exist and the data is valid.\",\n );\n }\n}\n\nexport interface OneTimeProductDiff {\n field: string;\n local: string;\n remote: string;\n}\n\nexport async function diffOneTimeProduct(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n localData: OneTimeProduct,\n): Promise<OneTimeProductDiff[]> {\n const remote = await client.oneTimeProducts.get(packageName, productId);\n const diffs: OneTimeProductDiff[] = [];\n const fieldsToCompare = [\"listings\", \"purchaseType\", \"taxAndComplianceSettings\"];\n\n for (const field of fieldsToCompare) {\n const localVal = JSON.stringify((localData as unknown as Record<string, unknown>)[field] ?? null);\n const remoteVal = JSON.stringify((remote as unknown as Record<string, unknown>)[field] ?? null);\n if (localVal !== remoteVal) {\n diffs.push({ field, local: localVal, remote: remoteVal });\n }\n }\n return diffs;\n}\n\nexport async function deleteOneTimeOffer(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n offerId: string,\n): Promise<void> {\n try {\n await client.oneTimeProducts.deleteOffer(packageName, productId, offerId);\n } catch (error) {\n throw new GpcError(\n `Failed to delete offer \"${offerId}\" for product \"${productId}\": ${error instanceof Error ? error.message : String(error)}`,\n \"OTP_OFFER_DELETE_FAILED\",\n 4,\n \"Check that the product and offer IDs exist.\",\n );\n }\n}\n","import process from \"node:process\";\n\nconst FRAMES = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"];\nconst INTERVAL_MS = 80;\n\nexport interface Spinner {\n start(): void;\n stop(message?: string): void;\n fail(message?: string): void;\n update(message: string): void;\n}\n\nexport function createSpinner(message: string): Spinner {\n const isTTY = process.stderr.isTTY === true;\n let frameIndex = 0;\n let timer: ReturnType<typeof setInterval> | undefined;\n let currentMessage = message;\n let started = false;\n\n function clearLine(): void {\n if (isTTY) {\n process.stderr.write(\"\\r\\x1b[K\");\n }\n }\n\n function renderFrame(): void {\n const frame = FRAMES[frameIndex % FRAMES.length];\n process.stderr.write(`\\r\\x1b[K${frame} ${currentMessage}`);\n frameIndex++;\n }\n\n return {\n start(): void {\n if (started) return;\n started = true;\n\n if (!isTTY) {\n process.stderr.write(`${currentMessage}\\n`);\n return;\n }\n\n renderFrame();\n timer = setInterval(renderFrame, INTERVAL_MS);\n },\n\n stop(msg?: string): void {\n if (timer) {\n clearInterval(timer);\n timer = undefined;\n }\n const text = msg ?? currentMessage;\n if (isTTY) {\n clearLine();\n process.stderr.write(`\\u2714 ${text}\\n`);\n } else if (!started) {\n process.stderr.write(`${text}\\n`);\n }\n started = false;\n },\n\n fail(msg?: string): void {\n if (timer) {\n clearInterval(timer);\n timer = undefined;\n }\n const text = msg ?? currentMessage;\n if (isTTY) {\n clearLine();\n process.stderr.write(`\\u2718 ${text}\\n`);\n } else if (!started) {\n process.stderr.write(`${text}\\n`);\n }\n started = false;\n },\n\n update(msg: string): void {\n currentMessage = msg;\n if (!isTTY || !started) return;\n renderFrame();\n },\n };\n}\n","import { resolve, normalize } from \"node:path\";\nimport { GpcError } from \"../errors.js\";\n\n/**\n * Normalize and resolve a user-supplied path.\n * Prevents path traversal by normalizing `.` and `..` components.\n */\nexport function safePath(userPath: string): string {\n return resolve(normalize(userPath));\n}\n\n/**\n * Validate that a resolved path is within an expected base directory.\n * Returns the resolved path or throws if it escapes the base.\n */\nexport function safePathWithin(userPath: string, baseDir: string): string {\n const resolved = safePath(userPath);\n const base = safePath(baseDir);\n\n if (!resolved.startsWith(base + \"/\") && resolved !== base) {\n throw new GpcError(\n `Path \"${userPath}\" resolves outside the expected directory \"${baseDir}\"`,\n \"PATH_TRAVERSAL\",\n 2,\n \"The path must stay within the target directory. Remove any ../ segments or use an absolute path within the expected directory.\",\n );\n }\n\n return resolved;\n}\n","/**\n * Sort utility for CLI list command results.\n *\n * Supports ascending (field) and descending (-field) sort specs,\n * including dot notation for nested fields (e.g., \"comments.userComment.starRating\").\n */\n\nfunction getNestedValue(obj: unknown, path: string): unknown {\n const parts = path.split(\".\");\n let current: unknown = obj;\n for (const part of parts) {\n if (current === null || current === undefined || typeof current !== \"object\") {\n return undefined;\n }\n current = (current as Record<string, unknown>)[part];\n }\n return current;\n}\n\nfunction compare(a: unknown, b: unknown): number {\n if (a === undefined && b === undefined) return 0;\n if (a === undefined) return 1;\n if (b === undefined) return -1;\n\n if (typeof a === \"number\" && typeof b === \"number\") {\n return a - b;\n }\n\n return String(a).localeCompare(String(b));\n}\n\n/**\n * Sort an array of items by a field specification.\n *\n * @param items - Array to sort (not mutated; returns a new array)\n * @param sortSpec - Field name for ascending, or `-field` for descending.\n * Supports dot notation for nested fields.\n * If undefined/empty, returns items in original order.\n * @returns Sorted copy of items\n */\nexport function sortResults<T>(items: T[], sortSpec?: string): T[] {\n if (!sortSpec || items.length === 0) {\n return items;\n }\n\n const descending = sortSpec.startsWith(\"-\");\n const field = descending ? sortSpec.slice(1) : sortSpec;\n\n // Validate that at least one item has the field — if none do, return original order\n const hasField = items.some((item) => getNestedValue(item, field) !== undefined);\n if (!hasField) {\n return items;\n }\n\n const sorted = [...items].sort((a, b) => {\n const aVal = getNestedValue(a, field);\n const bVal = getNestedValue(b, field);\n const result = compare(aVal, bVal);\n return descending ? -result : result;\n });\n\n return sorted;\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport interface ScaffoldOptions {\n name: string;\n dir: string;\n description?: string;\n}\n\nexport interface ScaffoldResult {\n dir: string;\n files: string[];\n}\n\n/**\n * Scaffold a new GPC plugin project.\n */\nexport async function scaffoldPlugin(options: ScaffoldOptions): Promise<ScaffoldResult> {\n const { name, dir, description = `GPC plugin: ${name}` } = options;\n\n // Ensure name follows convention\n const pluginName = name.startsWith(\"gpc-plugin-\") ? name : `gpc-plugin-${name}`;\n const shortName = pluginName.replace(/^gpc-plugin-/, \"\");\n\n const srcDir = join(dir, \"src\");\n const testDir = join(dir, \"tests\");\n\n await mkdir(srcDir, { recursive: true });\n await mkdir(testDir, { recursive: true });\n\n const files: string[] = [];\n\n // package.json\n const pkg = {\n name: pluginName,\n version: \"0.1.0\",\n description,\n type: \"module\",\n main: \"./dist/index.js\",\n types: \"./dist/index.d.ts\",\n exports: {\n \".\": {\n import: \"./dist/index.js\",\n types: \"./dist/index.d.ts\",\n },\n },\n files: [\"dist\"],\n scripts: {\n build: \"tsup src/index.ts --format esm --dts\",\n dev: \"tsup src/index.ts --format esm --dts --watch\",\n test: \"vitest run\",\n \"test:watch\": \"vitest\",\n },\n keywords: [\"gpc\", \"gpc-plugin\", \"google-play\"],\n license: \"MIT\",\n peerDependencies: {\n \"@gpc-cli/plugin-sdk\": \">=0.8.0\",\n },\n devDependencies: {\n \"@gpc-cli/plugin-sdk\": \"^0.8.0\",\n tsup: \"^8.0.0\",\n typescript: \"^5.0.0\",\n vitest: \"^3.0.0\",\n },\n };\n await writeFile(join(dir, \"package.json\"), JSON.stringify(pkg, null, 2) + \"\\n\");\n files.push(\"package.json\");\n\n // tsconfig.json\n const tsconfig = {\n compilerOptions: {\n target: \"ES2022\",\n module: \"ESNext\",\n moduleResolution: \"bundler\",\n declaration: true,\n strict: true,\n esModuleInterop: true,\n skipLibCheck: true,\n outDir: \"./dist\",\n rootDir: \"./src\",\n },\n include: [\"src\"],\n };\n await writeFile(join(dir, \"tsconfig.json\"), JSON.stringify(tsconfig, null, 2) + \"\\n\");\n files.push(\"tsconfig.json\");\n\n // src/index.ts\n const srcContent = `import { definePlugin } from \"@gpc-cli/plugin-sdk\";\nimport type { CommandEvent, CommandResult } from \"@gpc-cli/plugin-sdk\";\n\nexport const plugin = definePlugin({\n name: \"${pluginName}\",\n version: \"0.1.0\",\n\n register(hooks) {\n hooks.beforeCommand(async (event: CommandEvent) => {\n // Called before every gpc command\n // Example: log command usage, validate prerequisites, etc.\n });\n\n hooks.afterCommand(async (event: CommandEvent, result: CommandResult) => {\n // Called after every successful gpc command\n // Example: send notifications, update dashboards, etc.\n });\n\n // Uncomment to add custom commands:\n // hooks.registerCommands((registry) => {\n // registry.add({\n // name: \"${shortName}\",\n // description: \"${description}\",\n // action: async (args, opts) => {\n // console.log(\"Hello from ${pluginName}!\");\n // },\n // });\n // });\n },\n});\n`;\n await writeFile(join(srcDir, \"index.ts\"), srcContent);\n files.push(\"src/index.ts\");\n\n // tests/plugin.test.ts\n const testContent = `import { describe, it, expect, vi } from \"vitest\";\nimport { plugin } from \"../src/index\";\n\ndescribe(\"${pluginName}\", () => {\n it(\"has correct name and version\", () => {\n expect(plugin.name).toBe(\"${pluginName}\");\n expect(plugin.version).toBe(\"0.1.0\");\n });\n\n it(\"registers without errors\", () => {\n const hooks = {\n beforeCommand: vi.fn(),\n afterCommand: vi.fn(),\n onError: vi.fn(),\n beforeRequest: vi.fn(),\n afterResponse: vi.fn(),\n registerCommands: vi.fn(),\n };\n\n expect(() => plugin.register(hooks)).not.toThrow();\n });\n});\n`;\n await writeFile(join(testDir, \"plugin.test.ts\"), testContent);\n files.push(\"tests/plugin.test.ts\");\n\n return { dir, files };\n}\n","import { appendFile, chmod, mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport interface AuditEntry {\n timestamp: string;\n command: string;\n app?: string;\n args: Record<string, unknown>;\n user?: string;\n success?: boolean;\n durationMs?: number;\n error?: string;\n}\n\nlet auditDir: string | null = null;\n\n/**\n * Initialize audit logging with a directory path.\n * Typically ~/.config/gpc/ or the XDG config dir.\n */\nexport function initAudit(configDir: string): void {\n auditDir = configDir;\n}\n\n/**\n * Write an audit log entry. Non-blocking — errors are silently ignored.\n */\nexport async function writeAuditLog(entry: AuditEntry): Promise<void> {\n if (!auditDir) return;\n\n try {\n await mkdir(auditDir, { recursive: true, mode: 0o700 });\n const logPath = join(auditDir, \"audit.log\");\n const redactedEntry = redactAuditArgs(entry);\n const line = JSON.stringify(redactedEntry) + \"\\n\";\n await appendFile(logPath, line, { encoding: \"utf-8\", mode: 0o600 });\n await chmod(logPath, 0o600).catch(() => {});\n } catch {\n // Audit logging must never break the CLI\n }\n}\n\nconst SENSITIVE_ARG_KEYS = new Set([\n \"keyFile\",\n \"key_file\",\n \"serviceAccount\",\n \"service-account\",\n \"token\",\n \"password\",\n \"secret\",\n \"credentials\",\n \"private_key\",\n \"privateKey\",\n \"private_key_id\",\n \"privateKeyId\",\n \"client_secret\",\n \"clientSecret\",\n \"accessToken\",\n \"access_token\",\n \"refreshToken\",\n \"refresh_token\",\n \"apiKey\",\n \"api_key\",\n \"auth_token\",\n \"bearer\",\n \"jwt\",\n \"signing_key\",\n \"keystore_password\",\n \"store_password\",\n \"key_password\",\n]);\n\nexport { SENSITIVE_ARG_KEYS };\n\nexport function redactAuditArgs(entry: AuditEntry): AuditEntry {\n const redacted: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(entry.args)) {\n redacted[k] = SENSITIVE_ARG_KEYS.has(k) ? \"[REDACTED]\" : v;\n }\n return { ...entry, args: redacted };\n}\n\n/**\n * Convenience: create an audit entry for a write command.\n */\nexport function createAuditEntry(\n command: string,\n args: Record<string, unknown>,\n app?: string,\n): AuditEntry {\n return {\n timestamp: new Date().toISOString(),\n command,\n app,\n args,\n };\n}\n\nexport async function listAuditEvents(options?: {\n limit?: number;\n since?: string;\n command?: string;\n}): Promise<AuditEntry[]> {\n if (!auditDir) return [];\n const logPath = join(auditDir, \"audit.log\");\n let content: string;\n try {\n content = await readFile(logPath, \"utf-8\");\n } catch {\n return [];\n }\n const lines = content.trim().split(\"\\n\").filter(Boolean);\n let entries: AuditEntry[] = [];\n for (const line of lines) {\n try {\n entries.push(JSON.parse(line) as AuditEntry);\n } catch {\n // skip malformed lines\n }\n }\n if (options?.since) {\n const sinceDate = new Date(options.since).getTime();\n entries = entries.filter((e) => new Date(e.timestamp).getTime() >= sinceDate);\n }\n if (options?.command) {\n const cmd = options.command.toLowerCase();\n entries = entries.filter((e) => e.command.toLowerCase().includes(cmd));\n }\n if (options?.limit) {\n entries = entries.slice(-options.limit);\n }\n return entries;\n}\n\nexport async function searchAuditEvents(query: string): Promise<AuditEntry[]> {\n const all = await listAuditEvents();\n const q = query.toLowerCase();\n return all.filter((e) => {\n const text = JSON.stringify(e).toLowerCase();\n return text.includes(q);\n });\n}\n\nexport async function clearAuditLog(options?: {\n before?: string;\n dryRun?: boolean;\n}): Promise<{ deleted: number; remaining: number }> {\n if (!auditDir) return { deleted: 0, remaining: 0 };\n const logPath = join(auditDir, \"audit.log\");\n let content: string;\n try {\n content = await readFile(logPath, \"utf-8\");\n } catch {\n return { deleted: 0, remaining: 0 };\n }\n const lines = content.trim().split(\"\\n\").filter(Boolean);\n if (!options?.before) {\n const count = lines.length;\n if (!options?.dryRun) {\n await writeFile(logPath, \"\", { encoding: \"utf-8\", mode: 0o600 });\n }\n return { deleted: count, remaining: 0 };\n }\n const beforeDate = new Date(options.before).getTime();\n const keep: string[] = [];\n const remove: string[] = [];\n for (const line of lines) {\n try {\n const entry = JSON.parse(line) as AuditEntry;\n if (new Date(entry.timestamp).getTime() < beforeDate) {\n remove.push(line);\n } else {\n keep.push(line);\n }\n } catch {\n keep.push(line);\n }\n }\n if (!options?.dryRun) {\n await writeFile(logPath, keep.length > 0 ? keep.join(\"\\n\") + \"\\n\" : \"\", {\n encoding: \"utf-8\",\n mode: 0o600,\n });\n }\n return { deleted: remove.length, remaining: keep.length };\n}\n","import type { WebhookConfig } from \"@gpc-cli/config\";\n\nexport interface WebhookPayload {\n command: string;\n success: boolean;\n duration: number;\n app?: string;\n details?: Record<string, unknown>;\n error?: string;\n}\n\nexport function formatSlackPayload(payload: WebhookPayload): object {\n const status = payload.success ? \"\\u2713\" : \"\\u2717\";\n const color = payload.success ? \"#2eb886\" : \"#e01e5a\";\n const durationSec = (payload.duration / 1000).toFixed(1);\n\n const fields: Array<{ title: string; value: string; short: boolean }> = [\n { title: \"Command\", value: payload.command, short: true },\n { title: \"Duration\", value: `${durationSec}s`, short: true },\n ];\n\n if (payload.app) {\n fields.push({ title: \"App\", value: payload.app, short: true });\n }\n\n if (payload.error) {\n fields.push({ title: \"Error\", value: payload.error, short: false });\n }\n\n if (payload.details) {\n for (const [key, value] of Object.entries(payload.details)) {\n fields.push({ title: key, value: String(value), short: true });\n }\n }\n\n return {\n attachments: [\n {\n color,\n fallback: `GPC: ${payload.command} ${status}`,\n title: `GPC: ${payload.command} ${status}`,\n fields,\n footer: \"GPC CLI\",\n ts: Math.floor(Date.now() / 1000),\n },\n ],\n };\n}\n\nexport function formatDiscordPayload(payload: WebhookPayload): object {\n const status = payload.success ? \"\\u2713\" : \"\\u2717\";\n const color = payload.success ? 0x2eb886 : 0xe01e5a;\n const durationSec = (payload.duration / 1000).toFixed(1);\n\n const fields: Array<{ name: string; value: string; inline: boolean }> = [\n { name: \"Command\", value: payload.command, inline: true },\n { name: \"Duration\", value: `${durationSec}s`, inline: true },\n ];\n\n if (payload.app) {\n fields.push({ name: \"App\", value: payload.app, inline: true });\n }\n\n if (payload.error) {\n fields.push({ name: \"Error\", value: payload.error, inline: false });\n }\n\n if (payload.details) {\n for (const [key, value] of Object.entries(payload.details)) {\n fields.push({ name: key, value: String(value), inline: true });\n }\n }\n\n return {\n embeds: [\n {\n title: `GPC: ${payload.command} ${status}`,\n color,\n fields,\n footer: { text: \"GPC CLI\" },\n timestamp: new Date().toISOString(),\n },\n ],\n };\n}\n\nexport function formatCustomPayload(payload: WebhookPayload): object {\n return { ...payload };\n}\n\ntype WebhookTarget = \"slack\" | \"discord\" | \"custom\";\n\nconst FORMATTERS: Record<WebhookTarget, (p: WebhookPayload) => object> = {\n slack: formatSlackPayload,\n discord: formatDiscordPayload,\n custom: formatCustomPayload,\n};\n\nconst WEBHOOK_TIMEOUT_MS = 5000;\n\nasync function sendSingle(url: string, body: object): Promise<void> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), WEBHOOK_TIMEOUT_MS);\n\n try {\n await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function sendWebhook(\n config: WebhookConfig,\n payload: WebhookPayload,\n target?: string,\n): Promise<void> {\n try {\n const targets: WebhookTarget[] = target\n ? [target as WebhookTarget]\n : (Object.keys(FORMATTERS) as WebhookTarget[]);\n\n const promises: Promise<void>[] = [];\n\n for (const t of targets) {\n const url = config[t];\n if (!url) continue;\n\n const formatter = FORMATTERS[t];\n if (!formatter) continue;\n\n const body = formatter(payload);\n promises.push(sendSingle(url, body).catch(() => {}));\n }\n\n await Promise.all(promises);\n } catch {\n // Never throw — webhook failures must not break the CLI\n }\n}\n","import { extname } from \"node:path\";\nimport type { PlayApiClient, InternalAppSharingArtifact } from \"@gpc-cli/api\";\nimport { GpcError } from \"../errors.js\";\nimport { validateUploadFile } from \"../utils/file-validation.js\";\n\nexport interface InternalSharingUploadResult {\n downloadUrl: string;\n sha256: string;\n certificateFingerprint: string;\n fileType: \"bundle\" | \"apk\";\n}\n\nexport async function uploadInternalSharing(\n client: PlayApiClient,\n packageName: string,\n filePath: string,\n fileType?: \"bundle\" | \"apk\",\n): Promise<InternalSharingUploadResult> {\n // Auto-detect file type from extension if not provided\n const resolvedType = fileType ?? detectFileType(filePath);\n\n // Validate the file\n const validation = await validateUploadFile(filePath);\n if (!validation.valid) {\n throw new GpcError(\n `File validation failed:\\n${validation.errors.join(\"\\n\")}`,\n \"INTERNAL_SHARING_INVALID_FILE\",\n 2,\n \"Check that the file is a valid AAB or APK and is not corrupted.\",\n );\n }\n\n let artifact: InternalAppSharingArtifact;\n if (resolvedType === \"bundle\") {\n artifact = await client.internalAppSharing.uploadBundle(packageName, filePath);\n } else {\n artifact = await client.internalAppSharing.uploadApk(packageName, filePath);\n }\n\n return {\n downloadUrl: artifact.downloadUrl,\n sha256: artifact.sha256,\n certificateFingerprint: artifact.certificateFingerprint,\n fileType: resolvedType,\n };\n}\n\nfunction detectFileType(filePath: string): \"bundle\" | \"apk\" {\n const ext = extname(filePath).toLowerCase();\n if (ext === \".aab\") return \"bundle\";\n if (ext === \".apk\") return \"apk\";\n throw new GpcError(\n `Cannot detect file type from extension \"${ext}\". Use --type to specify bundle or apk.`,\n \"INTERNAL_SHARING_UNKNOWN_TYPE\",\n 2,\n \"Use --type bundle for .aab files or --type apk for .apk files.\",\n );\n}\n","import { writeFile } from \"node:fs/promises\";\nimport type { PlayApiClient, GeneratedApk } from \"@gpc-cli/api\";\nimport { GpcError } from \"../errors.js\";\n\nexport async function listGeneratedApks(\n client: PlayApiClient,\n packageName: string,\n versionCode: number,\n): Promise<GeneratedApk[]> {\n if (!Number.isInteger(versionCode) || versionCode <= 0) {\n throw new GpcError(\n `Invalid version code: ${versionCode}`,\n \"GENERATED_APKS_INVALID_VERSION\",\n 2,\n \"Provide a positive integer version code.\",\n );\n }\n return client.generatedApks.list(packageName, versionCode);\n}\n\nexport async function downloadGeneratedApk(\n client: PlayApiClient,\n packageName: string,\n versionCode: number,\n apkId: string,\n outputPath: string,\n): Promise<{ path: string; sizeBytes: number }> {\n if (!Number.isInteger(versionCode) || versionCode <= 0) {\n throw new GpcError(\n `Invalid version code: ${versionCode}`,\n \"GENERATED_APKS_INVALID_VERSION\",\n 2,\n \"Provide a positive integer version code.\",\n );\n }\n\n if (!apkId) {\n throw new GpcError(\n \"APK ID is required\",\n \"GENERATED_APKS_MISSING_ID\",\n 2,\n \"Provide the generated APK ID. Use 'gpc generated-apks list <version-code>' to see available APKs.\",\n );\n }\n\n const buffer = await client.generatedApks.download(packageName, versionCode, apkId);\n const bytes = new Uint8Array(buffer);\n await writeFile(outputPath, bytes);\n\n return { path: outputPath, sizeBytes: bytes.byteLength };\n}\n","import type { PlayApiClient, PurchaseOption, PurchaseOptionsListResponse } from \"@gpc-cli/api\";\nimport { GpcError } from \"../errors.js\";\n\nexport async function listPurchaseOptions(\n client: PlayApiClient,\n packageName: string,\n): Promise<PurchaseOptionsListResponse> {\n try {\n return await client.purchaseOptions.list(packageName);\n } catch (error) {\n throw new GpcError(\n `Failed to list purchase options: ${error instanceof Error ? error.message : String(error)}`,\n \"PURCHASE_OPTIONS_LIST_FAILED\",\n 4,\n \"Check your package name and API permissions.\",\n );\n }\n}\n\nexport async function getPurchaseOption(\n client: PlayApiClient,\n packageName: string,\n purchaseOptionId: string,\n): Promise<PurchaseOption> {\n try {\n return await client.purchaseOptions.get(packageName, purchaseOptionId);\n } catch (error) {\n throw new GpcError(\n `Failed to get purchase option \"${purchaseOptionId}\": ${error instanceof Error ? error.message : String(error)}`,\n \"PURCHASE_OPTION_GET_FAILED\",\n 4,\n \"Check that the purchase option ID exists.\",\n );\n }\n}\n\nexport async function createPurchaseOption(\n client: PlayApiClient,\n packageName: string,\n data: PurchaseOption,\n): Promise<PurchaseOption> {\n try {\n return await client.purchaseOptions.create(packageName, data);\n } catch (error) {\n throw new GpcError(\n `Failed to create purchase option: ${error instanceof Error ? error.message : String(error)}`,\n \"PURCHASE_OPTION_CREATE_FAILED\",\n 4,\n \"Check your purchase option data and API permissions.\",\n );\n }\n}\n\nexport async function activatePurchaseOption(\n client: PlayApiClient,\n packageName: string,\n purchaseOptionId: string,\n): Promise<PurchaseOption> {\n try {\n return await client.purchaseOptions.activate(packageName, purchaseOptionId);\n } catch (error) {\n throw new GpcError(\n `Failed to activate purchase option \"${purchaseOptionId}\": ${error instanceof Error ? error.message : String(error)}`,\n \"PURCHASE_OPTION_ACTIVATE_FAILED\",\n 4,\n \"Check that the purchase option exists and is in a valid state for activation.\",\n );\n }\n}\n\nexport async function deactivatePurchaseOption(\n client: PlayApiClient,\n packageName: string,\n purchaseOptionId: string,\n): Promise<PurchaseOption> {\n try {\n return await client.purchaseOptions.deactivate(packageName, purchaseOptionId);\n } catch (error) {\n throw new GpcError(\n `Failed to deactivate purchase option \"${purchaseOptionId}\": ${error instanceof Error ? error.message : String(error)}`,\n \"PURCHASE_OPTION_DEACTIVATE_FAILED\",\n 4,\n \"Check that the purchase option exists and is in a valid state for deactivation.\",\n );\n }\n}\n","import { readFile, stat } from \"node:fs/promises\";\n\nexport interface BundleEntry {\n path: string;\n module: string;\n category: string;\n compressedSize: number;\n uncompressedSize: number;\n}\n\nexport interface BundleAnalysis {\n filePath: string;\n fileType: \"aab\" | \"apk\";\n totalCompressed: number;\n totalUncompressed: number;\n entryCount: number;\n modules: { name: string; compressedSize: number; uncompressedSize: number; entries: number }[];\n categories: { name: string; compressedSize: number; uncompressedSize: number; entries: number }[];\n entries: BundleEntry[];\n}\n\nexport interface BundleComparison {\n before: { path: string; totalCompressed: number };\n after: { path: string; totalCompressed: number };\n sizeDelta: number;\n sizeDeltaPercent: number;\n moduleDeltas: { module: string; before: number; after: number; delta: number }[];\n categoryDeltas: { category: string; before: number; after: number; delta: number }[];\n}\n\nconst EOCD_SIGNATURE = 0x06054b50;\nconst CD_SIGNATURE = 0x02014b50;\n\n/** Known AAB module subdirs that distinguish feature modules from arbitrary top-level dirs. */\nconst MODULE_SUBDIRS = new Set([\"dex\", \"manifest\", \"res\", \"assets\", \"lib\", \"resources.pb\", \"root\"]);\n\nfunction detectCategory(path: string): string {\n const lower = path.toLowerCase();\n // dex files\n if (lower.endsWith(\".dex\") || /\\/dex\\/[^/]+\\.dex$/.test(lower)) return \"dex\";\n // resources\n if (\n lower === \"resources.arsc\" ||\n lower.endsWith(\"/resources.arsc\") ||\n lower.endsWith(\"/resources.pb\") ||\n /^(([^/]+\\/)?res\\/)/.test(lower)\n ) return \"resources\";\n // assets\n if (/^(([^/]+\\/)?assets\\/)/.test(lower)) return \"assets\";\n // native libs\n if (/^(([^/]+\\/)?lib\\/)/.test(lower)) return \"native-libs\";\n // manifest\n if (\n lower === \"androidmanifest.xml\" ||\n lower.endsWith(\"/androidmanifest.xml\") ||\n /^(([^/]+\\/)?manifest\\/)/.test(lower)\n ) return \"manifest\";\n // signing\n if (lower.startsWith(\"meta-inf/\") || lower === \"meta-inf\") return \"signing\";\n return \"other\";\n}\n\nfunction detectModule(path: string, isAab: boolean): string {\n if (!isAab) return \"(root)\";\n\n const slashIdx = path.indexOf(\"/\");\n if (slashIdx === -1) return \"(root)\";\n\n const topDir = path.substring(0, slashIdx);\n const rest = path.substring(slashIdx + 1);\n\n // \"base/\" module\n if (topDir === \"base\") return \"base\";\n\n // Root-level metadata\n if (topDir === \"BUNDLE-METADATA\" || topDir === \"META-INF\") return \"(root)\";\n if (path === \"BundleConfig.pb\") return \"(root)\";\n\n // Check if subdirectory matches known module structure\n const subDir = rest.split(\"/\")[0] || \"\";\n if (MODULE_SUBDIRS.has(subDir)) return topDir;\n\n return \"(root)\";\n}\n\ninterface CentralDirectoryEntry {\n filename: string;\n compressedSize: number;\n uncompressedSize: number;\n}\n\nfunction parseCentralDirectory(buf: Buffer): CentralDirectoryEntry[] {\n // Find EOCD — scan backwards from end (minimum EOCD is 22 bytes)\n let eocdOffset = -1;\n for (let i = buf.length - 22; i >= 0 && i >= buf.length - 65557; i--) {\n if (buf.readUInt32LE(i) === EOCD_SIGNATURE) {\n eocdOffset = i;\n break;\n }\n }\n if (eocdOffset === -1) {\n throw new Error(\"Not a valid ZIP file: EOCD signature not found\");\n }\n\n const cdSize = buf.readUInt32LE(eocdOffset + 12);\n let cdOffset = buf.readUInt32LE(eocdOffset + 16);\n\n // Handle ZIP64 — if offset is 0xFFFFFFFF, look for ZIP64 EOCD locator\n if (cdOffset === 0xffffffff) {\n // ZIP64 end of central directory locator is 20 bytes before EOCD\n const zip64LocatorOffset = eocdOffset - 20;\n if (zip64LocatorOffset >= 0 && buf.readUInt32LE(zip64LocatorOffset) === 0x07064b50) {\n // ZIP64 EOCD is at offset stored in locator bytes 8-15\n const zip64EocdOffset = Number(buf.readBigUInt64LE(zip64LocatorOffset + 8));\n if (zip64EocdOffset >= 0 && zip64EocdOffset < buf.length) {\n cdOffset = Number(buf.readBigUInt64LE(zip64EocdOffset + 48));\n }\n }\n }\n\n const entries: CentralDirectoryEntry[] = [];\n let pos = cdOffset;\n const end = cdOffset + cdSize;\n\n while (pos < end && pos + 46 <= buf.length) {\n const sig = buf.readUInt32LE(pos);\n if (sig !== CD_SIGNATURE) break;\n\n const compressedSize = buf.readUInt32LE(pos + 20);\n const uncompressedSize = buf.readUInt32LE(pos + 24);\n const filenameLen = buf.readUInt16LE(pos + 28);\n const extraLen = buf.readUInt16LE(pos + 30);\n const commentLen = buf.readUInt16LE(pos + 32);\n\n const filename = buf.toString(\"utf-8\", pos + 46, pos + 46 + filenameLen);\n\n // Skip directory entries (trailing slash)\n if (!filename.endsWith(\"/\")) {\n entries.push({ filename, compressedSize, uncompressedSize });\n }\n\n pos += 46 + filenameLen + extraLen + commentLen;\n }\n\n return entries;\n}\n\nfunction detectFileType(filePath: string): \"aab\" | \"apk\" {\n const lower = filePath.toLowerCase();\n if (lower.endsWith(\".aab\")) return \"aab\";\n return \"apk\";\n}\n\nexport async function analyzeBundle(filePath: string): Promise<BundleAnalysis> {\n const fileInfo = await stat(filePath).catch(() => null);\n if (!fileInfo || !fileInfo.isFile()) {\n throw new Error(`File not found: ${filePath}`);\n }\n\n const buf = await readFile(filePath);\n const cdEntries = parseCentralDirectory(buf);\n const fileType = detectFileType(filePath);\n const isAab = fileType === \"aab\";\n\n const entries: BundleEntry[] = cdEntries.map((e) => ({\n path: e.filename,\n module: detectModule(e.filename, isAab),\n category: detectCategory(e.filename),\n compressedSize: e.compressedSize,\n uncompressedSize: e.uncompressedSize,\n }));\n\n // Aggregate by module\n const moduleMap = new Map<string, { compressedSize: number; uncompressedSize: number; entries: number }>();\n for (const entry of entries) {\n const existing = moduleMap.get(entry.module) ?? { compressedSize: 0, uncompressedSize: 0, entries: 0 };\n existing.compressedSize += entry.compressedSize;\n existing.uncompressedSize += entry.uncompressedSize;\n existing.entries += 1;\n moduleMap.set(entry.module, existing);\n }\n\n // Aggregate by category\n const categoryMap = new Map<string, { compressedSize: number; uncompressedSize: number; entries: number }>();\n for (const entry of entries) {\n const existing = categoryMap.get(entry.category) ?? { compressedSize: 0, uncompressedSize: 0, entries: 0 };\n existing.compressedSize += entry.compressedSize;\n existing.uncompressedSize += entry.uncompressedSize;\n existing.entries += 1;\n categoryMap.set(entry.category, existing);\n }\n\n const modules = [...moduleMap.entries()]\n .map(([name, data]) => ({ name, ...data }))\n .sort((a, b) => b.compressedSize - a.compressedSize);\n\n const categories = [...categoryMap.entries()]\n .map(([name, data]) => ({ name, ...data }))\n .sort((a, b) => b.compressedSize - a.compressedSize);\n\n const totalCompressed = entries.reduce((sum, e) => sum + e.compressedSize, 0);\n const totalUncompressed = entries.reduce((sum, e) => sum + e.uncompressedSize, 0);\n\n return {\n filePath,\n fileType,\n totalCompressed,\n totalUncompressed,\n entryCount: entries.length,\n modules,\n categories,\n entries,\n };\n}\n\nexport function compareBundles(before: BundleAnalysis, after: BundleAnalysis): BundleComparison {\n const sizeDelta = after.totalCompressed - before.totalCompressed;\n const sizeDeltaPercent = before.totalCompressed > 0\n ? Math.round(((sizeDelta / before.totalCompressed) * 100) * 10) / 10\n : 0;\n\n // Module deltas\n const allModules = new Set([\n ...before.modules.map((m) => m.name),\n ...after.modules.map((m) => m.name),\n ]);\n const moduleDeltas = [...allModules].map((module) => {\n const b = before.modules.find((m) => m.name === module)?.compressedSize ?? 0;\n const a = after.modules.find((m) => m.name === module)?.compressedSize ?? 0;\n return { module, before: b, after: a, delta: a - b };\n }).sort((a, b) => Math.abs(b.delta) - Math.abs(a.delta));\n\n // Category deltas\n const allCategories = new Set([\n ...before.categories.map((c) => c.name),\n ...after.categories.map((c) => c.name),\n ]);\n const categoryDeltas = [...allCategories].map((category) => {\n const b = before.categories.find((c) => c.name === category)?.compressedSize ?? 0;\n const a = after.categories.find((c) => c.name === category)?.compressedSize ?? 0;\n return { category, before: b, after: a, delta: a - b };\n }).sort((a, b) => Math.abs(b.delta) - Math.abs(a.delta));\n\n return {\n before: { path: before.filePath, totalCompressed: before.totalCompressed },\n after: { path: after.filePath, totalCompressed: after.totalCompressed },\n sizeDelta,\n sizeDeltaPercent,\n moduleDeltas,\n categoryDeltas,\n };\n}\n","import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { execSync } from \"node:child_process\";\nimport { join } from \"node:path\";\nimport type { PlayApiClient } from \"@gpc-cli/api\";\nimport type { ReportingApiClient } from \"@gpc-cli/api\";\nimport { getCacheDir } from \"@gpc-cli/config\";\nimport { getReleasesStatus } from \"./releases.js\";\nimport { listReviews } from \"./reviews.js\";\nimport type { VitalsMetricSet, MetricSetQuery } from \"@gpc-cli/api\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface StatusVitalMetric {\n value: number | undefined;\n threshold: number;\n status: \"ok\" | \"warn\" | \"breach\" | \"unknown\";\n previousValue?: number | undefined;\n trend?: \"up\" | \"down\" | \"flat\" | null;\n}\n\nexport interface StatusRelease {\n track: string;\n versionCode: string;\n status: string;\n userFraction: number | null;\n}\n\nexport interface StatusReviews {\n windowDays: number;\n averageRating: number | undefined;\n previousAverageRating: number | undefined;\n totalNew: number;\n positivePercent: number | undefined;\n}\n\nexport interface AppStatus {\n packageName: string;\n fetchedAt: string;\n cached: boolean;\n releases: StatusRelease[];\n vitals: {\n windowDays: number;\n crashes: StatusVitalMetric;\n anr: StatusVitalMetric;\n slowStarts: StatusVitalMetric;\n slowRender: StatusVitalMetric;\n };\n reviews: StatusReviews;\n}\n\nexport interface StatusDiff {\n versionCode: { from: string | null; to: string | null };\n crashRate: { from: number | null; to: number | null; delta: number | null };\n anrRate: { from: number | null; to: number | null; delta: number | null };\n reviewCount: { from: number | null; to: number | null };\n averageRating: { from: number | null; to: number | null; delta: number | null };\n}\n\nexport interface GetAppStatusOptions {\n days?: number;\n sections?: string[]; // \"releases\" | \"vitals\" | \"reviews\"\n vitalThresholds?: {\n crashRate?: number;\n anrRate?: number;\n slowStartRate?: number;\n slowRenderingRate?: number;\n };\n}\n\nexport interface WatchOptions {\n intervalSeconds: number;\n render: (status: AppStatus) => string;\n fetch: () => Promise<AppStatus>;\n save: (status: AppStatus) => Promise<void>;\n}\n\n// ---------------------------------------------------------------------------\n// Cache\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_TTL_SECONDS = 3600;\n\ninterface CacheEntry {\n fetchedAt: string;\n ttl: number;\n data: AppStatus;\n}\n\nfunction cacheFilePath(packageName: string): string {\n return join(getCacheDir(), `status-${packageName}.json`);\n}\n\nexport async function loadStatusCache(\n packageName: string,\n ttlSeconds = DEFAULT_TTL_SECONDS,\n): Promise<AppStatus | null> {\n try {\n const raw = await readFile(cacheFilePath(packageName), \"utf-8\");\n const entry = JSON.parse(raw) as CacheEntry;\n const age = (Date.now() - new Date(entry.fetchedAt).getTime()) / 1000;\n if (age > (entry.ttl ?? ttlSeconds)) return null;\n return { ...entry.data, cached: true };\n } catch {\n return null;\n }\n}\n\nexport async function saveStatusCache(\n packageName: string,\n data: AppStatus,\n ttlSeconds = DEFAULT_TTL_SECONDS,\n): Promise<void> {\n try {\n const dir = getCacheDir();\n await mkdir(dir, { recursive: true });\n const entry: CacheEntry = { fetchedAt: data.fetchedAt, ttl: ttlSeconds, data };\n await writeFile(cacheFilePath(packageName), JSON.stringify(entry, null, 2), {\n encoding: \"utf-8\",\n mode: 0o600,\n });\n } catch {\n // Cache write failures must never break the command\n }\n}\n\n// ---------------------------------------------------------------------------\n// Vitals helpers\n// ---------------------------------------------------------------------------\n\nconst METRIC_SET_METRICS: Partial<Record<VitalsMetricSet, string[]>> = {\n crashRateMetricSet: [\"crashRate\", \"userPerceivedCrashRate\", \"distinctUsers\"],\n anrRateMetricSet: [\"anrRate\", \"userPerceivedAnrRate\", \"distinctUsers\"],\n slowStartRateMetricSet: [\"slowStartRate\", \"distinctUsers\"],\n slowRenderingRateMetricSet: [\"slowRenderingRate\", \"distinctUsers\"],\n};\n\nconst DEFAULT_THRESHOLDS = {\n crashRate: 0.02,\n anrRate: 0.01,\n slowStartRate: 0.05,\n slowRenderingRate: 0.1,\n};\n\nconst WARN_MARGIN = 0.2; // within 20% of threshold → warn\n\nfunction toApiDate(d: Date): { year: number; month: number; day: number } {\n return { year: d.getUTCFullYear(), month: d.getUTCMonth() + 1, day: d.getUTCDate() };\n}\n\nasync function queryVitalForStatus(\n reporting: ReportingApiClient,\n packageName: string,\n metricSet: VitalsMetricSet,\n days: number,\n offsetDays = 0,\n): Promise<number | undefined> {\n const DAY_MS = 24 * 60 * 60 * 1000;\n const baseMs = Date.now() - 2 * DAY_MS - offsetDays * DAY_MS;\n const end = new Date(baseMs);\n const start = new Date(baseMs - days * DAY_MS);\n const metrics = METRIC_SET_METRICS[metricSet] ?? [\"distinctUsers\"];\n\n const query: MetricSetQuery = {\n metrics,\n timelineSpec: {\n aggregationPeriod: \"DAILY\",\n startTime: toApiDate(start),\n endTime: toApiDate(end),\n },\n };\n\n const result = await reporting.queryMetricSet(packageName, metricSet, query);\n if (!result.rows || result.rows.length === 0) return undefined;\n\n const values = result.rows\n .map((row) => {\n const firstKey = Object.keys(row.metrics)[0];\n return firstKey ? Number(row.metrics[firstKey]?.decimalValue?.value) : NaN;\n })\n .filter((v) => !isNaN(v));\n\n if (values.length === 0) return undefined;\n return values.reduce((a, b) => a + b, 0) / values.length;\n}\n\ninterface VitalWithTrend {\n current: number | undefined;\n previous: number | undefined;\n trend: \"up\" | \"down\" | \"flat\" | null;\n}\n\nasync function queryVitalWithTrend(\n reporting: ReportingApiClient,\n packageName: string,\n metricSet: VitalsMetricSet,\n days: number,\n): Promise<VitalWithTrend> {\n const [current, previous] = await Promise.all([\n queryVitalForStatus(reporting, packageName, metricSet, days, 0),\n queryVitalForStatus(reporting, packageName, metricSet, days, days),\n ]);\n\n let trend: \"up\" | \"down\" | \"flat\" | null = null;\n if (current !== undefined && previous !== undefined) {\n if (current > previous) trend = \"up\";\n else if (current < previous) trend = \"down\";\n else trend = \"flat\";\n }\n\n return { current, previous, trend };\n}\n\nconst SKIPPED_VITAL: VitalWithTrend = { current: undefined, previous: undefined, trend: null };\n\nfunction toVitalMetric(\n value: number | undefined,\n threshold: number,\n previousValue?: number | undefined,\n trend?: \"up\" | \"down\" | \"flat\" | null,\n): StatusVitalMetric {\n const base: StatusVitalMetric =\n previousValue !== undefined\n ? { value, threshold, status: \"unknown\", previousValue, trend: trend ?? null }\n : { value, threshold, status: \"unknown\" };\n\n if (value === undefined) return { ...base, status: \"unknown\" };\n if (value > threshold) return { ...base, status: \"breach\" };\n if (value > threshold * (1 - WARN_MARGIN)) return { ...base, status: \"warn\" };\n return { ...base, status: \"ok\" };\n}\n\n// ---------------------------------------------------------------------------\n// Reviews helpers\n// ---------------------------------------------------------------------------\n\nfunction computeReviewSentiment(\n reviews: Awaited<ReturnType<typeof listReviews>>,\n windowDays: number,\n): StatusReviews {\n const now = Date.now();\n const DAY_MS = 24 * 60 * 60 * 1000;\n const windowMs = windowDays * DAY_MS;\n const prevWindowStart = now - 2 * windowMs;\n const curWindowStart = now - windowMs;\n\n const current = reviews.filter((r) => {\n const uc = r.comments?.[0]?.userComment;\n if (!uc) return false;\n const ts = Number(uc.lastModified.seconds) * 1000;\n return ts >= curWindowStart;\n });\n\n const previous = reviews.filter((r) => {\n const uc = r.comments?.[0]?.userComment;\n if (!uc) return false;\n const ts = Number(uc.lastModified.seconds) * 1000;\n return ts >= prevWindowStart && ts < curWindowStart;\n });\n\n const avgRating = (items: typeof reviews): number | undefined => {\n const ratings = items\n .map((r) => r.comments?.[0]?.userComment?.starRating)\n .filter((v): v is number => v !== undefined && v > 0);\n if (ratings.length === 0) return undefined;\n return Math.round((ratings.reduce((a, b) => a + b, 0) / ratings.length) * 10) / 10;\n };\n\n const positiveCount = current.filter(\n (r) => (r.comments?.[0]?.userComment?.starRating ?? 0) >= 4,\n ).length;\n\n const positivePercent =\n current.length > 0 ? Math.round((positiveCount / current.length) * 100) : undefined;\n\n return {\n windowDays,\n averageRating: avgRating(current),\n previousAverageRating: avgRating(previous),\n totalNew: current.length,\n positivePercent,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Main orchestrator\n// ---------------------------------------------------------------------------\n\nexport async function getAppStatus(\n client: PlayApiClient,\n reporting: ReportingApiClient,\n packageName: string,\n options: GetAppStatusOptions = {},\n): Promise<AppStatus> {\n const days = options.days ?? 7;\n const sections = new Set(options.sections ?? [\"releases\", \"vitals\", \"reviews\"]);\n const thresholds = {\n crashRate: options.vitalThresholds?.crashRate ?? DEFAULT_THRESHOLDS.crashRate,\n anrRate: options.vitalThresholds?.anrRate ?? DEFAULT_THRESHOLDS.anrRate,\n slowStartRate: options.vitalThresholds?.slowStartRate ?? DEFAULT_THRESHOLDS.slowStartRate,\n slowRenderingRate:\n options.vitalThresholds?.slowRenderingRate ?? DEFAULT_THRESHOLDS.slowRenderingRate,\n };\n\n const [releasesResult, crashesResult, anrResult, slowStartResult, slowRenderResult, reviewsResult] =\n await Promise.allSettled([\n sections.has(\"releases\")\n ? getReleasesStatus(client, packageName)\n : Promise.resolve([]),\n sections.has(\"vitals\")\n ? queryVitalWithTrend(reporting, packageName, \"crashRateMetricSet\", days)\n : Promise.resolve(SKIPPED_VITAL),\n sections.has(\"vitals\")\n ? queryVitalWithTrend(reporting, packageName, \"anrRateMetricSet\", days)\n : Promise.resolve(SKIPPED_VITAL),\n sections.has(\"vitals\")\n ? queryVitalWithTrend(reporting, packageName, \"slowStartRateMetricSet\", days)\n : Promise.resolve(SKIPPED_VITAL),\n sections.has(\"vitals\")\n ? queryVitalWithTrend(reporting, packageName, \"slowRenderingRateMetricSet\", days)\n : Promise.resolve(SKIPPED_VITAL),\n sections.has(\"reviews\")\n ? listReviews(client, packageName, { maxResults: 500 })\n : Promise.resolve([]),\n ]);\n\n const rawReleases = releasesResult.status === \"fulfilled\" ? releasesResult.value : [];\n const releases: StatusRelease[] = rawReleases.map((r) => ({\n track: r.track,\n versionCode: r.versionCodes[r.versionCodes.length - 1] ?? \"—\",\n status: r.status,\n userFraction: r.userFraction ?? null,\n }));\n\n const crashes =\n crashesResult.status === \"fulfilled\" ? crashesResult.value : SKIPPED_VITAL;\n const anr =\n anrResult.status === \"fulfilled\" ? anrResult.value : SKIPPED_VITAL;\n const slowStart =\n slowStartResult.status === \"fulfilled\" ? slowStartResult.value : SKIPPED_VITAL;\n const slowRender =\n slowRenderResult.status === \"fulfilled\" ? slowRenderResult.value : SKIPPED_VITAL;\n\n const rawReviews = reviewsResult.status === \"fulfilled\" ? reviewsResult.value : [];\n const reviews = computeReviewSentiment(rawReviews, 30);\n\n return {\n packageName,\n fetchedAt: new Date().toISOString(),\n cached: false,\n releases,\n vitals: {\n windowDays: days,\n crashes: toVitalMetric(crashes.current, thresholds.crashRate, crashes.previous, crashes.trend),\n anr: toVitalMetric(anr.current, thresholds.anrRate, anr.previous, anr.trend),\n slowStarts: toVitalMetric(\n slowStart.current,\n thresholds.slowStartRate,\n slowStart.previous,\n slowStart.trend,\n ),\n slowRender: toVitalMetric(\n slowRender.current,\n thresholds.slowRenderingRate,\n slowRender.previous,\n slowRender.trend,\n ),\n },\n reviews,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Table formatter\n// ---------------------------------------------------------------------------\n\nfunction vitalIndicator(metric: StatusVitalMetric): string {\n if (metric.status === \"unknown\") return \"—\";\n if (metric.status === \"breach\") return \"✗\";\n if (metric.status === \"warn\") return \"⚠\";\n return \"✓\";\n}\n\n// For all vital metrics (crash rate, ANR, slow starts, slow render) lower is better:\n// trend \"up\" (increasing) is bad → ↑, trend \"down\" (decreasing) is good → ↓\nfunction vitalTrendArrow(metric: StatusVitalMetric): string {\n if (!metric.trend || metric.trend === \"flat\") return \"\";\n return metric.trend === \"up\" ? \" ↑\" : \" ↓\";\n}\n\nfunction formatVitalValue(metric: StatusVitalMetric): string {\n if (metric.value === undefined) return \"—\";\n return `${(metric.value * 100).toFixed(2)}%`;\n}\n\nfunction formatFraction(fraction: number | null): string {\n if (fraction === null) return \"—\";\n return `${Math.round(fraction * 100)}%`;\n}\n\nfunction formatRating(rating: number | undefined): string {\n if (rating === undefined) return \"—\";\n return `★ ${rating.toFixed(1)}`;\n}\n\nfunction formatTrend(current: number | undefined, previous: number | undefined): string {\n if (current === undefined || previous === undefined) return \"\";\n if (current > previous) return ` ↑ from ${previous.toFixed(1)}`;\n if (current < previous) return ` ↓ from ${previous.toFixed(1)}`;\n return \"\";\n}\n\nfunction allVitalsUnknown(vitals: AppStatus[\"vitals\"]): boolean {\n return (\n vitals.crashes.status === \"unknown\" &&\n vitals.anr.status === \"unknown\" &&\n vitals.slowStarts.status === \"unknown\" &&\n vitals.slowRender.status === \"unknown\"\n );\n}\n\nexport function formatStatusTable(status: AppStatus): string {\n const lines: string[] = [];\n const cachedLabel = status.cached\n ? ` (cached ${new Date(status.fetchedAt).toLocaleTimeString()})`\n : ` (fetched ${new Date(status.fetchedAt).toLocaleTimeString()})`;\n\n lines.push(`App: ${status.packageName}${cachedLabel}`);\n lines.push(\"\");\n\n // Releases\n lines.push(\"RELEASES\");\n if (status.releases.length === 0) {\n lines.push(\" No releases found.\");\n } else {\n const trackW = Math.max(10, ...status.releases.map((r) => r.track.length));\n const versionW = Math.max(7, ...status.releases.map((r) => r.versionCode.length));\n const statusW = Math.max(8, ...status.releases.map((r) => r.status.length));\n for (const r of status.releases) {\n lines.push(\n ` ${r.track.padEnd(trackW)} ${r.versionCode.padEnd(versionW)} ${r.status.padEnd(statusW)} ${formatFraction(r.userFraction)}`,\n );\n }\n }\n\n // Vitals\n lines.push(\"\");\n lines.push(`VITALS (last ${status.vitals.windowDays} days)`);\n if (allVitalsUnknown(status.vitals)) {\n lines.push(\" No vitals data available for this period.\");\n } else {\n const { crashes, anr, slowStarts, slowRender } = status.vitals;\n const crashVal = `${formatVitalValue(crashes)}${vitalTrendArrow(crashes)}`;\n const anrVal = `${formatVitalValue(anr)}${vitalTrendArrow(anr)}`;\n const slowStartVal = `${formatVitalValue(slowStarts)}${vitalTrendArrow(slowStarts)}`;\n const slowRenderVal = `${formatVitalValue(slowRender)}${vitalTrendArrow(slowRender)}`;\n lines.push(\n ` crashes ${crashVal.padEnd(10)} ${vitalIndicator(crashes)} ` +\n `anr ${anrVal.padEnd(10)} ${vitalIndicator(anr)}`,\n );\n lines.push(\n ` slow starts ${slowStartVal.padEnd(10)} ${vitalIndicator(slowStarts)} ` +\n `slow render ${slowRenderVal.padEnd(10)} ${vitalIndicator(slowRender)}`,\n );\n }\n\n // Reviews\n lines.push(\"\");\n lines.push(`REVIEWS (last ${status.reviews.windowDays} days)`);\n const { averageRating, previousAverageRating, totalNew, positivePercent } = status.reviews;\n if (totalNew === 0 && averageRating === undefined) {\n lines.push(\" No reviews in this period.\");\n } else {\n const trend = formatTrend(averageRating, previousAverageRating);\n const positiveStr = positivePercent !== undefined ? ` ${positivePercent}% positive` : \"\";\n lines.push(` ${formatRating(averageRating)} ${totalNew} new${positiveStr}${trend}`);\n }\n\n return lines.join(\"\\n\");\n}\n\n// ---------------------------------------------------------------------------\n// Summary formatter (one-liner for --format summary)\n// ---------------------------------------------------------------------------\n\nexport function formatStatusSummary(status: AppStatus): string {\n const parts: string[] = [status.packageName];\n\n // Latest non-draft release\n const latestRelease =\n status.releases.find((r) => r.status !== \"draft\") ?? status.releases[0];\n if (latestRelease) {\n parts.push(`v${latestRelease.versionCode} ${latestRelease.track}`);\n }\n\n // Vitals (crashes + ANR only for brevity)\n const { crashes, anr } = status.vitals;\n if (crashes.status !== \"unknown\") {\n const arrow = crashes.trend === \"up\" ? \" ↑\" : crashes.trend === \"down\" ? \" ↓\" : \"\";\n parts.push(`crashes ${formatVitalValue(crashes)}${arrow} ${vitalIndicator(crashes)}`);\n }\n if (anr.status !== \"unknown\") {\n const arrow = anr.trend === \"up\" ? \" ↑\" : anr.trend === \"down\" ? \" ↓\" : \"\";\n parts.push(`ANR ${formatVitalValue(anr)}${arrow} ${vitalIndicator(anr)}`);\n }\n\n // Reviews\n const { averageRating, totalNew } = status.reviews;\n if (averageRating !== undefined) {\n parts.push(`avg ${averageRating.toFixed(1)}★`);\n }\n if (totalNew > 0) {\n parts.push(`${totalNew} reviews`);\n }\n\n return parts.join(\" · \") + (statusHasBreach(status) ? \" [ALERT]\" : \"\");\n}\n\n// ---------------------------------------------------------------------------\n// Diff (--since-last)\n// ---------------------------------------------------------------------------\n\nexport function computeStatusDiff(prev: AppStatus, curr: AppStatus): StatusDiff {\n const prevVersion = prev.releases[0]?.versionCode ?? null;\n const currVersion = curr.releases[0]?.versionCode ?? null;\n const prevCrash = prev.vitals.crashes.value ?? null;\n const currCrash = curr.vitals.crashes.value ?? null;\n const prevAnr = prev.vitals.anr.value ?? null;\n const currAnr = curr.vitals.anr.value ?? null;\n const prevRating = prev.reviews.averageRating ?? null;\n const currRating = curr.reviews.averageRating ?? null;\n\n return {\n versionCode: { from: prevVersion, to: currVersion },\n crashRate: {\n from: prevCrash,\n to: currCrash,\n delta: currCrash !== null && prevCrash !== null ? currCrash - prevCrash : null,\n },\n anrRate: {\n from: prevAnr,\n to: currAnr,\n delta: currAnr !== null && prevAnr !== null ? currAnr - prevAnr : null,\n },\n reviewCount: { from: prev.reviews.totalNew, to: curr.reviews.totalNew },\n averageRating: {\n from: prevRating,\n to: currRating,\n delta:\n currRating !== null && prevRating !== null\n ? Math.round((currRating - prevRating) * 10) / 10\n : null,\n },\n };\n}\n\nexport function formatStatusDiff(diff: StatusDiff, since: string): string {\n const lines: string[] = [`Changes since ${since}:`];\n\n if (diff.versionCode.from !== diff.versionCode.to) {\n lines.push(` Version: ${diff.versionCode.from ?? \"—\"} → ${diff.versionCode.to ?? \"—\"}`);\n }\n\n const fmtRate = (v: number | null): string =>\n v !== null ? `${(v * 100).toFixed(2)}%` : \"—\";\n\n const fmtDelta = (d: number | null, lowerIsBetter = true): string => {\n if (d === null || Math.abs(d) < 0.0001) return \"no change\";\n const sign = d > 0 ? \"+\" : \"\";\n const good = lowerIsBetter ? d < 0 : d > 0;\n return `${sign}${(d * 100).toFixed(2)}% ${good ? \"✓\" : \"✗\"}`;\n };\n\n lines.push(\n ` Crash rate: ${fmtRate(diff.crashRate.from)} → ${fmtRate(diff.crashRate.to)} (${fmtDelta(diff.crashRate.delta)})`,\n );\n lines.push(\n ` ANR rate: ${fmtRate(diff.anrRate.from)} → ${fmtRate(diff.anrRate.to)} (${fmtDelta(diff.anrRate.delta)})`,\n );\n\n const ratingDelta = diff.averageRating.delta;\n const prevR =\n diff.averageRating.from !== null ? `${diff.averageRating.from.toFixed(1)}★` : \"—\";\n const currR =\n diff.averageRating.to !== null ? `${diff.averageRating.to.toFixed(1)}★` : \"—\";\n const ratingStr =\n ratingDelta === null || Math.abs(ratingDelta) < 0.05\n ? \"no change\"\n : `${ratingDelta > 0 ? \"+\" : \"\"}${ratingDelta.toFixed(1)} ${ratingDelta > 0 ? \"✓\" : \"✗\"}`;\n lines.push(` Reviews: ${prevR} → ${currR} (${ratingStr})`);\n\n return lines.join(\"\\n\");\n}\n\n// ---------------------------------------------------------------------------\n// Watch loop (--watch N)\n// ---------------------------------------------------------------------------\n\nexport async function runWatchLoop(opts: WatchOptions): Promise<void> {\n if (opts.intervalSeconds < 10) {\n console.error(\"Error: --watch interval must be at least 10 seconds\");\n process.exit(2);\n }\n\n let running = true;\n\n const cleanup = () => {\n running = false;\n process.stdout.write(\"\\n\");\n process.exit(0);\n };\n process.on(\"SIGINT\", cleanup);\n process.on(\"SIGTERM\", cleanup);\n\n while (running) {\n process.stdout.write(\"\\x1b[2J\\x1b[H\"); // clear terminal\n\n try {\n const status = await opts.fetch();\n await opts.save(status);\n console.log(opts.render(status));\n } catch (err) {\n console.error(`Error: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n console.log(`\\n[gpc status] Refreshing in ${opts.intervalSeconds}s… (Ctrl+C to stop)`);\n\n // Sleep in 1s ticks so SIGINT is responsive\n for (let i = 0; i < opts.intervalSeconds && running; i++) {\n await new Promise<void>((r) => setTimeout(r, 1000));\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Notifications (--notify)\n// ---------------------------------------------------------------------------\n\nfunction breachStateFilePath(packageName: string): string {\n return join(getCacheDir(), `breach-state-${packageName}.json`);\n}\n\n/** Returns true if breach state changed (breach started or cleared). */\nexport async function trackBreachState(\n packageName: string,\n isBreaching: boolean,\n): Promise<boolean> {\n const filePath = breachStateFilePath(packageName);\n let prevBreaching = false;\n\n try {\n const raw = await readFile(filePath, \"utf-8\");\n prevBreaching = (JSON.parse(raw) as { breaching: boolean }).breaching;\n } catch {\n // No prior state — first run\n }\n\n if (prevBreaching !== isBreaching) {\n try {\n await mkdir(getCacheDir(), { recursive: true });\n await writeFile(\n filePath,\n JSON.stringify({ breaching: isBreaching, since: new Date().toISOString() }, null, 2),\n { encoding: \"utf-8\", mode: 0o600 },\n );\n } catch {\n // State write failure is non-fatal\n }\n return true;\n }\n return false;\n}\n\nexport function sendNotification(title: string, body: string): void {\n if (process.env[\"CI\"]) return; // Skip in CI environments\n\n try {\n const p = process.platform;\n if (p === \"darwin\") {\n execSync(\n `osascript -e 'display notification ${JSON.stringify(body)} with title ${JSON.stringify(title)}'`,\n { stdio: \"ignore\" },\n );\n } else if (p === \"linux\") {\n execSync(`notify-send ${JSON.stringify(title)} ${JSON.stringify(body)}`, {\n stdio: \"ignore\",\n });\n } else if (p === \"win32\") {\n const escaped = (s: string) => s.replace(/'/g, \"''\");\n execSync(\n `powershell -Command \"Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.MessageBox]::Show('${escaped(body)}', '${escaped(title)}')\"`,\n { stdio: \"ignore\" },\n );\n }\n } catch {\n // Notification failures are non-fatal\n }\n}\n\n// ---------------------------------------------------------------------------\n// Status indicator for exit code (mirrors gpc vitals behaviour)\n// ---------------------------------------------------------------------------\n\nexport function statusHasBreach(status: AppStatus): boolean {\n return (\n status.vitals.crashes.status === \"breach\" ||\n status.vitals.anr.status === \"breach\" ||\n status.vitals.slowStarts.status === \"breach\" ||\n status.vitals.slowRender.status === \"breach\"\n );\n}\n"],"mappings":";AAAO,IAAM,WAAN,cAAuB,MAAM;AAAA,EAClC,YACE,SACgB,MACA,UACA,YAChB;AACA,UAAM,OAAO;AAJG;AACA;AACA;AAGhB,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,SAAS;AACP,WAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO;AAAA,QACL,MAAM,KAAK;AAAA,QACX,SAAS,KAAK;AAAA,QACd,YAAY,KAAK;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AACF;AAEO,IAAM,cAAN,cAA0B,SAAS;AAAA,EACxC,YAAY,SAAiB,MAAc,YAAqB;AAC9D,UAAM,SAAS,MAAM,GAAG,UAAU;AAClC,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,WAAN,cAAuB,SAAS;AAAA,EACrC,YACE,SACA,MACgB,YAChB,YACA;AACA,UAAM,SAAS,MAAM,GAAG,UAAU;AAHlB;AAIhB,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,eAAN,cAA2B,SAAS;AAAA,EACzC,YAAY,SAAiB,YAAqB;AAChD,UAAM,SAAS,iBAAiB,GAAG,UAAU;AAC7C,SAAK,OAAO;AAAA,EACd;AACF;;;AC9CA,OAAOA,cAAa;AAEb,SAAS,qBAAmC;AACjD,SAAOA,SAAQ,OAAO,QAAQ,UAAU;AAC1C;AAEO,SAAS,aAAa,MAAe,QAAsB,SAAS,MAAc;AACvF,QAAM,OAAO,SAAS,gBAAgB,IAAI,IAAI;AAC9C,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO,WAAW,IAAI;AAAA,IACxB,KAAK;AACH,aAAO,WAAW,IAAI;AAAA,IACxB,KAAK;AACH,aAAO,eAAe,IAAI;AAAA,IAC5B,KAAK;AACH,aAAO,YAAY,IAAI;AAAA,IACzB,KAAK;AACH,aAAO,YAAY,IAAI;AAAA,IACzB;AACE,aAAO,WAAW,IAAI;AAAA,EAC1B;AACF;AAMO,IAAM,iBAAiB,oBAAI,IAAI;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAM,WAAW;AAGV,SAAS,gBAAgB,MAAwB;AACtD,MAAI,SAAS,QAAQ,SAAS,OAAW,QAAO;AAEhD,MAAI,OAAO,SAAS,SAAU,QAAO;AACrC,MAAI,OAAO,SAAS,YAAY,OAAO,SAAS,UAAW,QAAO;AAElE,MAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,WAAO,KAAK,IAAI,CAAC,SAAS,gBAAgB,IAAI,CAAC;AAAA,EACjD;AAEA,MAAI,OAAO,SAAS,UAAU;AAC5B,UAAM,SAAkC,CAAC;AACzC,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAA+B,GAAG;AAC1E,UAAI,eAAe,IAAI,GAAG,KAAK,OAAO,UAAU,UAAU;AACxD,eAAO,GAAG,IAAI;AAAA,MAChB,OAAO;AACL,eAAO,GAAG,IAAI,gBAAgB,KAAK;AAAA,MACrC;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEA,SAAS,WAAW,MAAuB;AACzC,SAAO,KAAK,UAAU,MAAM,MAAM,CAAC;AACrC;AAEA,SAAS,WAAW,MAAe,SAAS,GAAW;AACrD,MAAI,SAAS,QAAQ,SAAS,QAAW;AACvC,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,SAAS,UAAU;AAC5B,WAAO,KAAK,SAAS,IAAI,IACrB;AAAA,EAAM,KACH,MAAM,IAAI,EACV,IAAI,CAAC,MAAM,GAAG,KAAK,OAAO,SAAS,CAAC,CAAC,GAAG,CAAC,EAAE,EAC3C,KAAK,IAAI,CAAC,KACb;AAAA,EACN;AAEA,MAAI,OAAO,SAAS,YAAY,OAAO,SAAS,WAAW;AACzD,WAAO,OAAO,IAAI;AAAA,EACpB;AAEA,MAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,QAAI,KAAK,WAAW,EAAG,QAAO;AAC9B,WAAO,KACJ,IAAI,CAAC,SAAS;AACb,YAAM,QAAQ,WAAW,MAAM,SAAS,CAAC;AACzC,YAAM,SAAS,GAAG,KAAK,OAAO,MAAM,CAAC;AACrC,UAAI,OAAO,SAAS,YAAY,SAAS,QAAQ,CAAC,MAAM,QAAQ,IAAI,GAAG;AACrE,cAAM,QAAQ,MAAM,MAAM,IAAI;AAC9B,eAAO,GAAG,MAAM,GAAG,MAAM,CAAC,CAAC;AAAA,EAAK,MAC7B,MAAM,CAAC,EACP,IAAI,CAAC,MAAM,GAAG,KAAK,OAAO,MAAM,CAAC,KAAK,CAAC,EAAE,EACzC,KAAK,IAAI,CAAC;AAAA,MACf;AACA,aAAO,GAAG,MAAM,GAAG,KAAK;AAAA,IAC1B,CAAC,EACA,KAAK,IAAI;AAAA,EACd;AAEA,MAAI,OAAO,SAAS,UAAU;AAC5B,UAAM,UAAU,OAAO,QAAQ,IAA+B;AAC9D,QAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,WAAO,QACJ,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM;AACrB,UAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,eAAO,GAAG,KAAK,OAAO,MAAM,CAAC,GAAG,GAAG;AAAA,EAAM,WAAW,OAAO,SAAS,CAAC,CAAC;AAAA,MACxE;AACA,aAAO,GAAG,KAAK,OAAO,MAAM,CAAC,GAAG,GAAG,KAAK,WAAW,OAAO,MAAM,CAAC;AAAA,IACnE,CAAC,EACA,KAAK,IAAI;AAAA,EACd;AAEA,SAAO,OAAO,IAAI;AACpB;AAEA,IAAM,iBAAiB;AAEvB,SAAS,aAAa,OAAuB;AAC3C,MAAI,MAAM,UAAU,eAAgB,QAAO;AAC3C,SAAO,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI;AAC9C;AAEA,SAAS,UAAU,KAAsB;AACvC,MAAI,QAAQ,QAAQ,QAAQ,OAAW,QAAO;AAC9C,MAAI,OAAO,QAAQ,UAAU;AAC3B,QAAI,MAAM,QAAQ,GAAG,EAAG,QAAO,IAAI,WAAW,IAAI,KAAK,KAAK,UAAU,GAAG;AACzE,WAAO,KAAK,UAAU,GAAG;AAAA,EAC3B;AACA,SAAO,OAAO,GAAG;AACnB;AAEA,SAAS,YAAY,MAAuB;AAC1C,QAAM,OAAO,OAAO,IAAI;AACxB,MAAI,KAAK,WAAW,EAAG,QAAO;AAE9B,QAAM,WAAW,KAAK,CAAC;AACvB,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,OAAO,OAAO,KAAK,QAAQ;AACjC,MAAI,KAAK,WAAW,EAAG,QAAO;AAE9B,QAAM,SAAS,KAAK;AAAA,IAAI,CAAC,QACvB,KAAK,IAAI,IAAI,QAAQ,GAAG,KAAK,IAAI,CAAC,QAAQ,aAAa,UAAU,IAAI,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC;AAAA,EACrF;AAEA,QAAM,SAAS,KAAK,IAAI,CAAC,KAAK,MAAM,IAAI,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,IAAI;AACzE,QAAM,YAAY,OAAO,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,IAAI;AAC5D,QAAM,OAAO,KACV,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,KAAK,MAAM,aAAa,UAAU,IAAI,GAAG,CAAC,CAAC,EAAE,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,EACtG,KAAK,IAAI;AAEZ,SAAO,GAAG,MAAM;AAAA,EAAK,SAAS;AAAA,EAAK,IAAI;AACzC;AAEA,SAAS,eAAe,MAAuB;AAC7C,QAAM,OAAO,OAAO,IAAI;AACxB,MAAI,KAAK,WAAW,EAAG,QAAO;AAE9B,QAAM,WAAW,KAAK,CAAC;AACvB,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,OAAO,OAAO,KAAK,QAAQ;AACjC,MAAI,KAAK,WAAW,EAAG,QAAO;AAE9B,QAAM,SAAS,KAAK;AAAA,IAAI,CAAC,QACvB,KAAK,IAAI,IAAI,QAAQ,GAAG,KAAK,IAAI,CAAC,QAAQ,aAAa,UAAU,IAAI,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC;AAAA,EACrF;AAEA,QAAM,SAAS,KAAK,KAAK,IAAI,CAAC,KAAK,MAAM,IAAI,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC;AAChF,QAAM,YAAY,KAAK,OAAO,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC;AACnE,QAAM,OAAO,KACV;AAAA,IACC,CAAC,QACC,KAAK,KAAK,IAAI,CAAC,KAAK,MAAM,aAAa,UAAU,IAAI,GAAG,CAAC,CAAC,EAAE,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC;AAAA,EACnG,EACC,KAAK,IAAI;AAEZ,SAAO,GAAG,MAAM;AAAA,EAAK,SAAS;AAAA,EAAK,IAAI;AACzC;AAEA,SAAS,OAAO,MAA0C;AACxD,MAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,WAAO,KAAK;AAAA,MACV,CAAC,SAA0C,OAAO,SAAS,YAAY,SAAS;AAAA,IAClF;AAAA,EACF;AACA,MAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAC7C,WAAO,CAAC,IAA+B;AAAA,EACzC;AACA,SAAO,CAAC;AACV;AAMA,SAAS,UAAU,KAAqB;AACtC,SAAO,IACJ,QAAQ,MAAM,OAAO,EACrB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,QAAQ,EACtB,QAAQ,MAAM,QAAQ;AAC3B;AAEA,SAAS,YAAY,MAAe,aAA4D;AAC9F,QAAM,QAAkB,CAAC;AACzB,MAAI,WAAW;AAEf,MAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,YAAM,KAAK,cAAc,KAAK,CAAC,GAAG,aAAa,CAAC;AAChD,YAAM,KAAK,GAAG,GAAG;AACjB,UAAI,GAAG,OAAQ;AAAA,IACjB;AAAA,EACF,WAAW,OAAO,SAAS,YAAY,SAAS,MAAM;AACpD,UAAM,KAAK,cAAc,MAAM,WAAW;AAC1C,UAAM,KAAK,GAAG,GAAG;AACjB,QAAI,GAAG,OAAQ;AAAA,EACjB,WAAW,OAAO,SAAS,UAAU;AACnC,UAAM;AAAA,MACJ,uBAAuB,UAAU,IAAI,CAAC,oBAAoB,UAAU,WAAW,CAAC;AAAA,IAClF;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,SAAS;AAC3B;AAEA,SAAS,cACP,MACA,aACA,QAAQ,GAC0B;AAClC,MAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAC7C,UAAM,OAAO,OAAO,IAAI;AACxB,WAAO;AAAA,MACL,KAAK,uBAAuB,UAAU,IAAI,CAAC,oBAAoB,UAAU,WAAW,CAAC;AAAA,MACrF,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,QAAM,SAAS;AAIf,QAAM,iBAAiB;AAAA,IACrB;AAAA,IAAQ;AAAA,IAAS;AAAA,IAAO;AAAA,IAAM;AAAA,IAAY;AAAA,IAAa;AAAA,IACvD;AAAA,IAAS;AAAA,IAAW;AAAA,IAAe;AAAA,IAAU;AAAA,EAC/C;AACA,MAAI,eAAe,QAAQ,QAAQ,CAAC;AACpC,aAAW,OAAO,gBAAgB;AAChC,UAAM,MAAM,OAAO,GAAG;AACtB,QAAI,OAAO,QAAQ,QAAQ,MAAM,QAAQ,KAAK;AAC5C,qBAAe,OAAO,GAAG;AACzB;AAAA,IACF;AAAA,EACF;AACA,QAAM,OAAO,UAAU,YAAY;AACnC,QAAM,YAAY,OAAO,UAAU,WAAW,CAAC;AAG/C,QAAM,WAAW,OAAO,UAAU;AAClC,MAAI,aAAa,MAAM;AACrB,UAAM,UAAU,UAAU,OAAO,OAAO,SAAS,KAAK,oBAAoB,CAAC;AAC3E,UAAM,UAAU;AAAA,MACd,OAAO,OAAO,SAAS,KAAK,OAAO,QAAQ,KAAK,KAAK,UAAU,IAAI,CAAC;AAAA,IACtE;AACA,WAAO;AAAA,MACL,KAAK,uBAAuB,IAAI,gBAAgB,SAAS;AAAA,0BAA+B,OAAO,KAAK,OAAO;AAAA;AAAA,MAC3G,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,SAAO;AAAA,IACL,KAAK,uBAAuB,IAAI,gBAAgB,SAAS;AAAA,IACzD,QAAQ;AAAA,EACV;AACF;AAEO,SAAS,YAAY,MAAe,cAAc,WAAmB;AAC1E,QAAM,EAAE,OAAO,SAAS,IAAI,YAAY,MAAM,WAAW;AACzD,QAAM,QAAQ,MAAM;AAEpB,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA,iCAAiC,KAAK,eAAe,QAAQ;AAAA,IAC7D,sBAAsB,UAAU,WAAW,CAAC,YAAY,KAAK,eAAe,QAAQ;AAAA,IACpF,GAAG;AAAA,IACH;AAAA,IACA;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;;;ACxSO,IAAM,gBAAN,MAAoB;AAAA,EACjB,UAA0B,CAAC;AAAA,EAC3B,iBAAyC,CAAC;AAAA,EAC1C,gBAAuC,CAAC;AAAA,EACxC,gBAAgC,CAAC;AAAA,EACjC,wBAAgD,CAAC;AAAA,EACjD,wBAAgD,CAAC;AAAA,EACjD,qBAAsC,CAAC;AAAA;AAAA,EAG/C,MAAM,KAAK,QAAmB,UAA0C;AACtE,UAAM,YAAY,UAAU,WAAW,OAAO,KAAK,WAAW,WAAW;AAEzE,QAAI,CAAC,aAAa,UAAU,aAAa;AACvC,0BAAoB,SAAS,WAAW;AAAA,IAC1C;AAEA,UAAM,QAAQ;AAAA,MACZ,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAEA,UAAM,OAAO,SAAS,KAAK;AAE3B,SAAK,QAAQ,KAAK;AAAA,MAChB,MAAM,OAAO;AAAA,MACb,SAAS,OAAO;AAAA,MAChB,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,iBAAiB,OAAoC;AACzD,eAAW,WAAW,KAAK,gBAAgB;AACzC,YAAM,QAAQ,KAAK;AAAA,IACrB;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,gBAAgB,OAAqB,QAAsC;AAC/E,eAAW,WAAW,KAAK,eAAe;AACxC,YAAM,QAAQ,OAAO,MAAM;AAAA,IAC7B;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,WAAW,OAAqB,OAAmC;AACvE,eAAW,WAAW,KAAK,eAAe;AACxC,UAAI;AACF,cAAM,QAAQ,OAAO,KAAK;AAAA,MAC5B,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,iBAAiB,OAAoC;AACzD,eAAW,WAAW,KAAK,uBAAuB;AAChD,UAAI;AACF,cAAM,QAAQ,KAAK;AAAA,MACrB,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,iBAAiB,OAAqB,UAAwC;AAClF,eAAW,WAAW,KAAK,uBAAuB;AAChD,UAAI;AACF,cAAM,QAAQ,OAAO,QAAQ;AAAA,MAC/B,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,wBAAyC;AACvC,WAAO,CAAC,GAAG,KAAK,kBAAkB;AAAA,EACpC;AAAA;AAAA,EAGA,mBAAmC;AACjC,WAAO,CAAC,GAAG,KAAK,OAAO;AAAA,EACzB;AAAA;AAAA,EAGA,kBAA2B;AACzB,WAAO,KAAK,sBAAsB,SAAS,KAAK,KAAK,sBAAsB,SAAS;AAAA,EACtF;AAAA;AAAA,EAGA,QAAc;AACZ,SAAK,UAAU,CAAC;AAChB,SAAK,iBAAiB,CAAC;AACvB,SAAK,gBAAgB,CAAC;AACtB,SAAK,gBAAgB,CAAC;AACtB,SAAK,wBAAwB,CAAC;AAC9B,SAAK,wBAAwB,CAAC;AAC9B,SAAK,qBAAqB,CAAC;AAAA,EAC7B;AACF;AAYA,SAAS,YACP,gBACA,eACA,eACA,uBACA,uBACA,oBACa;AACb,SAAO;AAAA,IACL,cAAc,SAAS;AACrB,qBAAe,KAAK,OAAO;AAAA,IAC7B;AAAA,IACA,aAAa,SAAS;AACpB,oBAAc,KAAK,OAAO;AAAA,IAC5B;AAAA,IACA,QAAQ,SAAS;AACf,oBAAc,KAAK,OAAO;AAAA,IAC5B;AAAA,IACA,cAAc,SAAS;AACrB,4BAAsB,KAAK,OAAO;AAAA,IACpC;AAAA,IACA,cAAc,SAAS;AACrB,4BAAsB,KAAK,OAAO;AAAA,IACpC;AAAA,IACA,iBAAiB,WAAW;AAC1B,YAAM,WAAW;AAAA,QACf,IAAI,KAAoB;AACtB,6BAAmB,KAAK,GAAG;AAAA,QAC7B;AAAA,MACF;AACA,gBAAU,QAAQ;AAAA,IACpB;AAAA,EACF;AACF;AAMA,IAAM,oBAAyC,oBAAI,IAAsB;AAAA,EACvE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,SAAS,oBAAoB,aAAuC;AAClE,aAAW,QAAQ,aAAa;AAC9B,QAAI,CAAC,kBAAkB,IAAI,IAAI,GAAG;AAChC,YAAM,IAAI;AAAA,QACR,+BAA+B,IAAI;AAAA,QACnC;AAAA,QACA;AAAA,QACA,sBAAsB,CAAC,GAAG,iBAAiB,EAAE,KAAK,IAAI,CAAC;AAAA,MACzD;AAAA,IACF;AAAA,EACF;AACF;AAoBA,eAAsB,gBAAgB,SAAwD;AAC5F,QAAM,UAAuB,CAAC;AAC9B,QAAM,OAAO,oBAAI,IAAY;AAG7B,MAAI,SAAS,eAAe;AAC1B,eAAW,QAAQ,QAAQ,eAAe;AACxC,UAAI,KAAK,IAAI,IAAI,EAAG;AACpB,UAAI;AACF,cAAM,MAAM,MAAM,OAAO;AACzB,cAAM,SAAS,cAAc,GAAG;AAChC,YAAI,QAAQ;AACV,kBAAQ,KAAK,MAAM;AACnB,eAAK,IAAI,IAAI;AAAA,QACf;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,cAAc,KAAqC;AAC1D,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAE5C,QAAM,IAAI;AAGV,MAAI,SAAS,EAAE,SAAS,CAAC,EAAG,QAAO,EAAE,SAAS;AAG9C,MAAI,SAAS,EAAE,QAAQ,CAAC,EAAG,QAAO,EAAE,QAAQ;AAG5C,MAAI,SAAS,CAAC,EAAG,QAAO;AAExB,SAAO;AACT;AAEA,SAAS,SAAS,KAAgC;AAChD,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,IAAI;AACV,SACE,OAAO,EAAE,MAAM,MAAM,YACrB,OAAO,EAAE,SAAS,MAAM,YACxB,OAAO,EAAE,UAAU,MAAM;AAE7B;;;AC9QA,eAAsB,WAAW,QAAuB,aAAuC;AAE7F,QAAM,OAAO,MAAM,OAAO,MAAM,OAAO,WAAW;AAClD,MAAI;AACF,UAAM,UAAU,MAAM,OAAO,QAAQ,IAAI,aAAa,KAAK,EAAE;AAE7D,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE;AAC9C,WAAO;AAAA,MACL;AAAA,MACA,OAAO,QAAQ;AAAA,MACf,iBAAiB,QAAQ;AAAA,MACzB,cAAc,QAAQ;AAAA,IACxB;AAAA,EACF,SAAS,OAAO;AAEd,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9D,UAAM;AAAA,EACR;AACF;;;AC3BA,SAAS,UAAU,YAAY;AAC/B,SAAS,eAAe;AAWxB,IAAM,YAAY,OAAO,KAAK,CAAC,IAAM,IAAM,GAAM,CAAI,CAAC;AAEtD,IAAM,eAAe,MAAM,OAAO;AAClC,IAAM,eAAe,MAAM,OAAO;AAClC,IAAM,uBAAuB,MAAM,OAAO;AAE1C,eAAsB,mBAAmB,UAAiD;AACxF,QAAM,SAAmB,CAAC;AAC1B,QAAM,WAAqB,CAAC;AAG5B,QAAM,MAAM,QAAQ,QAAQ,EAAE,YAAY;AAC1C,MAAI,WAA6C;AAEjD,MAAI,QAAQ,QAAQ;AAClB,eAAW;AAAA,EACb,WAAW,QAAQ,QAAQ;AACzB,eAAW;AAAA,EACb,OAAO;AACL,WAAO,KAAK,+BAA+B,GAAG,0BAA0B;AAAA,EAC1E;AAGA,MAAI;AACJ,MAAI;AACF,UAAM,QAAQ,MAAM,KAAK,QAAQ;AACjC,gBAAY,MAAM;AAElB,QAAI,cAAc,GAAG;AACnB,aAAO,KAAK,yBAAyB;AAAA,IACvC;AAAA,EACF,QAAQ;AACN,WAAO,KAAK,mBAAmB,QAAQ,EAAE;AACzC,WAAO,EAAE,OAAO,OAAO,UAAU,WAAW,GAAG,QAAQ,SAAS;AAAA,EAClE;AAGA,MAAI,aAAa,SAAS,YAAY,cAAc;AAClD,WAAO;AAAA,MACL,6BAA6B,WAAW,SAAS,CAAC;AAAA,IACpD;AAAA,EACF;AACA,MAAI,aAAa,SAAS,YAAY,cAAc;AAClD,WAAO,KAAK,6BAA6B,WAAW,SAAS,CAAC,IAAI;AAAA,EACpE;AAEA,MAAI,YAAY,wBAAwB,OAAO,WAAW,GAAG;AAC3D,aAAS;AAAA,MACP,eAAe,WAAW,SAAS,CAAC;AAAA,IACtC;AAAA,EACF;AAGA,MAAI,YAAY,GAAG;AACjB,QAAI;AACF,YAAM,KAAK,MAAM,SAAS,UAAU,EAAE,MAAM,IAAI,CAAC;AACjD,YAAM,SAAS,GAAG,SAAS,GAAG,CAAC;AAE/B,UAAI,CAAC,OAAO,OAAO,SAAS,GAAG;AAC7B,eAAO;AAAA,UACL;AAAA,QAEF;AAAA,MACF;AAAA,IACF,QAAQ;AACN,aAAO,KAAK,2CAA2C;AAAA,IACzD;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO,OAAO,WAAW;AAAA,IACzB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,WAAW,OAAuB;AACzC,MAAI,SAAS,OAAO,OAAO,MAAM;AAC/B,WAAO,IAAI,SAAS,OAAO,OAAO,OAAO,QAAQ,CAAC,CAAC;AAAA,EACrD;AACA,MAAI,SAAS,OAAO,MAAM;AACxB,WAAO,IAAI,SAAS,OAAO,OAAO,QAAQ,CAAC,CAAC;AAAA,EAC9C;AACA,MAAI,SAAS,MAAM;AACjB,WAAO,IAAI,QAAQ,MAAM,QAAQ,CAAC,CAAC;AAAA,EACrC;AACA,SAAO,GAAG,KAAK;AACjB;;;AC3EA,eAAsB,cACpB,QACA,aACA,UACA,SAS4C;AAE5C,QAAM,aAAa,MAAM,mBAAmB,QAAQ;AAEpD,MAAI,QAAQ,QAAQ;AAClB,UAAM,gBAAgB,QAAQ,WAC3B,QAAQ,eAAe,eAAe;AAGzC,QAAI,kBAAyD,CAAC;AAC9D,UAAMC,QAAO,MAAM,OAAO,MAAM,OAAO,WAAW;AAClD,QAAI;AACF,YAAM,YAAY,MAAM,OAAO,OAAO,IAAI,aAAaA,MAAK,IAAI,QAAQ,KAAK;AAC7E,yBAAmB,UAAU,YAAY,CAAC,GAAG,IAAI,CAAC,OAAO;AAAA,QACvD,cAAc,EAAE,gBAAgB,CAAC;AAAA,QACjC,QAAQ,EAAE;AAAA,QACV,GAAI,EAAE,iBAAiB,UAAa,EAAE,cAAc,EAAE,aAAa;AAAA,MACrE,EAAE;AAAA,IACJ,QAAQ;AAAA,IAER,UAAE;AACA,YAAM,OAAO,MAAM,OAAO,aAAaA,MAAK,EAAE,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IAChE;AAEA,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,OAAO,WAAW;AAAA,QAClB,QAAQ,WAAW;AAAA,QACnB,UAAU,WAAW;AAAA,MACvB;AAAA,MACA,OAAO,QAAQ;AAAA,MACf;AAAA,MACA,gBAAgB;AAAA,QACd,QAAQ;AAAA,QACR,GAAI,QAAQ,iBAAiB,UAAa,EAAE,cAAc,QAAQ,aAAa;AAAA,MACjF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,WAAW,OAAO;AACrB,UAAM,IAAI;AAAA,MACR;AAAA,EAA4B,WAAW,OAAO,KAAK,IAAI,CAAC;AAAA,MACxD;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,OAAO,MAAM,OAAO,MAAM,OAAO,WAAW;AAClD,MAAI;AAEF,UAAM,SAAS,MAAM,OAAO,QAAQ,OAAO,aAAa,KAAK,IAAI,QAAQ;AAGzE,QAAI,QAAQ,aAAa;AACvB,YAAM,OAAO,cAAc;AAAA,QACzB;AAAA,QACA,KAAK;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,MACV;AAAA,IACF;AAGA,UAAM,UAAmB;AAAA,MACvB,cAAc,CAAC,OAAO,OAAO,WAAW,CAAC;AAAA,MACzC,QAAS,QAAQ,WACd,QAAQ,eAAe,eAAe;AAAA,MACzC,GAAI,QAAQ,gBAAgB,EAAE,cAAc,QAAQ,aAAa;AAAA,MACjE,GAAI,QAAQ,gBAAgB,EAAE,cAAc,QAAQ,aAAa;AAAA,MACjE,GAAI,QAAQ,eAAe,EAAE,MAAM,QAAQ,YAAY;AAAA,IACzD;AAEA,UAAM,OAAO,OAAO,OAAO,aAAa,KAAK,IAAI,QAAQ,OAAO,OAAO;AAGvE,UAAM,OAAO,MAAM,SAAS,aAAa,KAAK,EAAE;AAChD,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE;AAE9C,WAAO;AAAA,MACL,aAAa,OAAO;AAAA,MACpB,OAAO,QAAQ;AAAA,MACf,QAAQ,QAAQ;AAAA,IAClB;AAAA,EACF,SAAS,OAAO;AACd,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9D,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,kBACpB,QACA,aACA,aACgC;AAChC,QAAM,OAAO,MAAM,OAAO,MAAM,OAAO,WAAW;AAClD,MAAI;AACF,UAAM,SAAS,cACX,CAAC,MAAM,OAAO,OAAO,IAAI,aAAa,KAAK,IAAI,WAAW,CAAC,IAC3D,MAAM,OAAO,OAAO,KAAK,aAAa,KAAK,EAAE;AAEjD,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE;AAE9C,UAAM,UAAiC,CAAC;AACxC,eAAW,SAAS,QAAQ;AAC1B,iBAAW,WAAW,MAAM,YAAY,CAAC,GAAG;AAC1C,gBAAQ,KAAK;AAAA,UACX,OAAO,MAAM;AAAA,UACb,QAAQ,QAAQ;AAAA,UAChB,cAAc,QAAQ,gBAAgB,CAAC;AAAA,UACvC,cAAc,QAAQ;AAAA,UACtB,cAAc,QAAQ;AAAA,QACxB,CAAC;AAAA,MACH;AAAA,IACF;AACA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9D,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,eACpB,QACA,aACA,WACA,SACA,SAC8B;AAC9B,QAAM,OAAO,MAAM,OAAO,MAAM,OAAO,WAAW;AAClD,MAAI;AAEF,UAAM,cAAc,MAAM,OAAO,OAAO,IAAI,aAAa,KAAK,IAAI,SAAS;AAC3E,UAAM,iBAAiB,YAAY,UAAU;AAAA,MAC3C,CAAC,MAAM,EAAE,WAAW,eAAe,EAAE,WAAW;AAAA,IAClD;AAEA,QAAI,CAAC,gBAAgB;AACnB,YAAM,IAAI;AAAA,QACR,qCAAqC,SAAS;AAAA,QAC9C;AAAA,QACA;AAAA,QACA,8DAA8D,SAAS;AAAA,MACzE;AAAA,IACF;AAGA,QAAI,SAAS,iBAAiB,QAAQ,gBAAgB,KAAK,QAAQ,eAAe,IAAI;AACpF,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,UAAM,UAAmB;AAAA,MACvB,cAAc,eAAe;AAAA,MAC7B,QAAS,SAAS,eAAe,eAAe;AAAA,MAChD,GAAI,SAAS,gBAAgB,EAAE,cAAc,QAAQ,aAAa;AAAA,MAClE,cAAc,SAAS,gBAAgB,eAAe,gBAAgB,CAAC;AAAA,IACzE;AAEA,UAAM,OAAO,OAAO,OAAO,aAAa,KAAK,IAAI,SAAS,OAAO;AACjE,UAAM,OAAO,MAAM,SAAS,aAAa,KAAK,EAAE;AAChD,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE;AAE9C,WAAO;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,QAAQ;AAAA,MAChB,cAAc,QAAQ;AAAA,MACtB,cAAc,QAAQ;AAAA,IACxB;AAAA,EACF,SAAS,OAAO;AACd,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9D,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,cACpB,QACA,aACA,OACA,QACA,cAC8B;AAC9B,QAAM,OAAO,MAAM,OAAO,MAAM,OAAO,WAAW;AAClD,MAAI;AACF,UAAM,YAAY,MAAM,OAAO,OAAO,IAAI,aAAa,KAAK,IAAI,KAAK;AACrE,UAAM,iBAAiB,UAAU,UAAU;AAAA,MACzC,CAAC,MAAM,EAAE,WAAW,gBAAgB,EAAE,WAAW;AAAA,IACnD;AAEA,QAAI,CAAC,gBAAgB;AACnB,YAAM,IAAI;AAAA,QACR,qCAAqC,KAAK;AAAA,QAC1C;AAAA,QACA;AAAA,QACA,qDAAqD,KAAK,2EAA2E,KAAK;AAAA,MAC5I;AAAA,IACF;AAEA,QAAI;AACJ,QAAI;AAEJ,YAAQ,QAAQ;AAAA,MACd,KAAK;AACH,YAAI,CAAC,aAAc,OAAM,IAAI;AAAA,UAC3B;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AACA,YAAI,gBAAgB,KAAK,eAAe,GAAG;AACzC,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AACA,oBAAY;AACZ,sBAAc;AACd;AAAA,MACF,KAAK;AACH,oBAAY;AACZ,sBAAc,eAAe;AAC7B;AAAA,MACF,KAAK;AACH,oBAAY;AACZ,sBAAc,eAAe;AAC7B;AAAA,MACF,KAAK;AACH,oBAAY;AACZ,sBAAc;AACd;AAAA,IACJ;AAEA,UAAM,UAAmB;AAAA,MACvB,cAAc,eAAe;AAAA,MAC7B,QAAQ;AAAA,MACR,GAAI,gBAAgB,UAAa,EAAE,cAAc,YAAY;AAAA,MAC7D,cAAc,eAAe,gBAAgB,CAAC;AAAA,IAChD;AAEA,UAAM,OAAO,OAAO,OAAO,aAAa,KAAK,IAAI,OAAO,OAAO;AAC/D,UAAM,OAAO,MAAM,SAAS,aAAa,KAAK,EAAE;AAChD,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE;AAE9C,WAAO;AAAA,MACL;AAAA,MACA,QAAQ;AAAA,MACR,cAAc,QAAQ;AAAA,MACtB,cAAc;AAAA,IAChB;AAAA,EACF,SAAS,OAAO;AACd,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9D,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,WAAW,QAAuB,aAAuC;AAC7F,QAAM,OAAO,MAAM,OAAO,MAAM,OAAO,WAAW;AAClD,MAAI;AACF,UAAM,SAAS,MAAM,OAAO,OAAO,KAAK,aAAa,KAAK,EAAE;AAC5D,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE;AAC9C,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9D,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,YACpB,QACA,aACA,WACgB;AAChB,MAAI,CAAC,aAAa,UAAU,KAAK,EAAE,WAAW,GAAG;AAC/C,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,OAAO,MAAM,OAAO,MAAM,OAAO,WAAW;AAClD,MAAI;AACF,UAAM,QAAQ,MAAM,OAAO,OAAO,OAAO,aAAa,KAAK,IAAI,SAAS;AACxE,UAAM,OAAO,MAAM,SAAS,aAAa,KAAK,EAAE;AAChD,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE;AAC9C,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9D,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,kBACpB,QACA,aACA,WACA,QACgB;AAChB,MAAI,CAAC,aAAa,UAAU,KAAK,EAAE,WAAW,GAAG;AAC/C,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,OAAO,MAAM,OAAO,MAAM,OAAO,WAAW;AAClD,MAAI;AACF,UAAM,UAAmB;AAAA,MACvB,cAAe,OAAO,cAAc,KAAkB,CAAC;AAAA,MACvD,QAAU,OAAO,QAAQ,KAAgB;AAAA,IAC3C;AACA,QAAI,OAAO,cAAc,MAAM,QAAW;AACxC,cAAQ,eAAe,OAAO,cAAc;AAAA,IAC9C;AACA,QAAI,OAAO,cAAc,GAAG;AAC1B,cAAQ,eAAe,OAAO,cAAc;AAAA,IAC9C;AACA,QAAI,OAAO,MAAM,GAAG;AAClB,cAAQ,OAAO,OAAO,MAAM;AAAA,IAC9B;AAEA,UAAM,QAAQ,MAAM,OAAO,OAAO,OAAO,aAAa,KAAK,IAAI,WAAW,OAAO;AACjF,UAAM,OAAO,MAAM,SAAS,aAAa,KAAK,EAAE;AAChD,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE;AAC9C,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9D,UAAM;AAAA,EACR;AACF;AAQA,eAAsB,aACpB,QACA,aACA,WACA,SACuE;AACvE,QAAM,OAAO,MAAM,OAAO,MAAM,OAAO,WAAW;AAClD,MAAI;AACF,UAAM,CAAC,UAAU,MAAM,IAAI,MAAM,QAAQ,IAAI;AAAA,MAC3C,OAAO,OAAO,IAAI,aAAa,KAAK,IAAI,SAAS;AAAA,MACjD,OAAO,OAAO,IAAI,aAAa,KAAK,IAAI,OAAO;AAAA,IACjD,CAAC;AACD,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE;AAE9C,UAAM,cAAc,SAAS,WAAW,CAAC;AACzC,UAAM,YAAY,OAAO,WAAW,CAAC;AACrC,UAAM,QAAuB,CAAC;AAE9B,UAAM,SAAS,CAAC,gBAAgB,UAAU,gBAAgB,gBAAgB,MAAM;AAChF,eAAW,SAAS,QAAQ;AAC1B,YAAM,KAAK,cAAc,KAAK,UAAU,YAAY,KAAK,KAAK,IAAI,IAAI;AACtE,YAAM,KAAK,YAAY,KAAK,UAAU,UAAU,KAAK,KAAK,IAAI,IAAI;AAClE,UAAI,OAAO,IAAI;AACb,cAAM,KAAK,EAAE,OAAO,aAAa,IAAI,aAAa,GAAG,CAAC;AAAA,MACxD;AAAA,IACF;AAEA,WAAO,EAAE,WAAW,SAAS,MAAM;AAAA,EACrC,SAAS,OAAO;AACd,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9D,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,uBACpB,QACA,aACA,MACsC;AACtC,MAAI,CAAC,KAAK,qBAAqB;AAC7B,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,KAAK,aAAa;AACrB,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,OAAO,MAAM,OAAO,MAAM,OAAO,WAAW;AAClD,MAAI;AACF,UAAM,SAAS,MAAM,OAAO,KAAK,oBAAoB,aAAa,KAAK,IAAI,IAAI;AAC/E,UAAM,OAAO,MAAM,SAAS,aAAa,KAAK,EAAE;AAChD,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE;AAC9C,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9D,UAAM;AAAA,EACR;AACF;;;ACrcO,IAAM,wBAAkC;AAAA,EAC7C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAAS,aAAa,KAAsB;AACjD,SAAO,sBAAsB,SAAS,GAAG;AAC3C;;;ACvFA,SAAS,QAAAC,aAAY;AACrB,SAAS,WAAAC,gBAAe;AASxB,IAAM,oBAAyE;AAAA,EAC7E,MAAM,EAAE,UAAU,OAAO,MAAM,OAAO,OAAO;AAAA,EAC7C,gBAAgB,EAAE,UAAU,OAAO,MAAM,OAAO,OAAO;AAAA,EACvD,UAAU,EAAE,UAAU,OAAO,MAAM,OAAO,OAAO;AAAA,EACjD,kBAAkB,EAAE,UAAU,IAAI,OAAO,MAAM,OAAO,OAAO;AAAA,EAC7D,sBAAsB,EAAE,UAAU,IAAI,OAAO,MAAM,OAAO,OAAO;AAAA,EACjE,oBAAoB,EAAE,UAAU,IAAI,OAAO,MAAM,OAAO,OAAO;AAAA,EAC/D,eAAe,EAAE,UAAU,IAAI,OAAO,MAAM,OAAO,OAAO;AAAA,EAC1D,iBAAiB,EAAE,UAAU,IAAI,OAAO,MAAM,OAAO,OAAO;AAC9D;AAEA,IAAM,mBAAmB,oBAAI,IAAI,CAAC,QAAQ,QAAQ,OAAO,CAAC;AAC1D,IAAM,wBAAwB,IAAI,OAAO;AAEzC,eAAsB,cACpB,UACA,WACgC;AAChC,QAAM,SAAmB,CAAC;AAC1B,QAAM,WAAqB,CAAC;AAG5B,QAAM,MAAMA,SAAQ,QAAQ,EAAE,YAAY;AAC1C,MAAI,CAAC,iBAAiB,IAAI,GAAG,GAAG;AAC9B,WAAO,KAAK,6BAA6B,GAAG,qBAAqB;AAAA,EACnE;AAGA,MAAI;AACJ,MAAI;AACF,UAAM,QAAQ,MAAMD,MAAK,QAAQ;AACjC,gBAAY,MAAM;AAElB,QAAI,cAAc,GAAG;AACnB,aAAO,KAAK,+BAA+B;AAAA,IAC7C;AAAA,EACF,QAAQ;AACN,WAAO,KAAK,yBAAyB,QAAQ,EAAE;AAC/C,WAAO,EAAE,OAAO,OAAO,QAAQ,SAAS;AAAA,EAC1C;AAGA,MAAI,aAAa,YAAY,GAAG;AAC9B,UAAM,QAAQ,kBAAkB,SAAS;AACzC,QAAI,SAAS,YAAY,MAAM,UAAU;AACvC,aAAO,KAAK,iBAAiB,MAAM,KAAK,cAAc,SAAS,KAAKE,YAAW,SAAS,CAAC,GAAG;AAAA,IAC9F;AAAA,EACF;AAGA,MAAI,YAAY,yBAAyB,OAAO,WAAW,GAAG;AAC5D,aAAS;AAAA,MACP,gBAAgBA,YAAW,SAAS,CAAC;AAAA,IACvC;AAAA,EACF;AAGA,MAAI,QAAQ,UAAU,YAAY,MAAM,MAAM;AAC5C,aAAS;AAAA,MACP;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,OAAO,WAAW,GAAG,QAAQ,SAAS;AACxD;AAEA,SAASA,YAAW,OAAuB;AACzC,MAAI,SAAS,OAAO,KAAM,QAAO,IAAI,SAAS,OAAO,OAAO,QAAQ,CAAC,CAAC;AACtE,MAAI,SAAS,KAAM,QAAO,IAAI,QAAQ,MAAM,QAAQ,CAAC,CAAC;AACtD,SAAO,GAAG,KAAK;AACjB;;;AChFA,SAAS,YAAAC,WAAU,WAAW,OAAO,SAAS,QAAAC,aAAY;AAC1D,SAAS,YAAY;AAGrB,IAAM,WAA4D;AAAA,EAChE,aAAa;AAAA,EACb,yBAAyB;AAAA,EACzB,wBAAwB;AAAA,EACxB,aAAa;AACf;AAEA,IAAM,gBAAwC,OAAO;AAAA,EACnD,OAAO,QAAQ,QAAQ,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,OAAO,IAAI,CAAC;AAC/D;AASA,eAAe,OAAO,MAAgC;AACpD,MAAI;AACF,UAAMA,MAAK,IAAI;AACf,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,oBAAoB,KAAiC;AACzE,QAAM,WAAsB,CAAC;AAE7B,MAAI,CAAE,MAAM,OAAO,GAAG,EAAI,QAAO;AAEjC,QAAM,UAAU,MAAM,QAAQ,GAAG;AAEjC,QAAM,YAAY;AAClB,aAAW,QAAQ,SAAS;AAC1B,QAAI,CAAC,UAAU,KAAK,IAAI,EAAG;AAC3B,UAAM,UAAU,KAAK,KAAK,IAAI;AAC9B,UAAM,WAAW,MAAMA,MAAK,OAAO;AACnC,QAAI,CAAC,SAAS,YAAY,EAAG;AAE7B,UAAM,UAAmB;AAAA,MACvB,UAAU;AAAA,MACV,OAAO;AAAA,MACP,kBAAkB;AAAA,MAClB,iBAAiB;AAAA,IACnB;AAEA,eAAW,CAAC,UAAU,KAAK,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACxD,YAAM,WAAW,KAAK,SAAS,QAAQ;AACvC,UAAI,MAAM,OAAO,QAAQ,GAAG;AAC1B,cAAM,UAAU,MAAMD,UAAS,UAAU,OAAO;AAChD,QAAC,QAA8C,KAAK,IAAI,QAAQ,QAAQ;AAAA,MAC1E;AAAA,IACF;AAEA,aAAS,KAAK,OAAO;AAAA,EACvB;AAEA,SAAO;AACT;AAEA,eAAsB,mBAAmB,KAAa,UAAoC;AACxF,aAAW,WAAW,UAAU;AAC9B,UAAM,UAAU,KAAK,KAAK,QAAQ,QAAQ;AAC1C,UAAM,MAAM,SAAS,EAAE,WAAW,KAAK,CAAC;AAExC,eAAW,CAAC,OAAO,QAAQ,KAAK,OAAO,QAAQ,aAAa,GAAG;AAC7D,YAAM,QAAS,QAA8C,KAAK;AAClE,UAAI,UAAU,UAAa,UAAU,IAAI;AACvC,cAAM,UAAU,KAAK,SAAS,QAAQ,GAAG,QAAQ,MAAM,OAAO;AAAA,MAChE;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,aAAa,OAAkB,QAAkC;AAC/E,QAAM,QAAuB,CAAC;AAC9B,QAAM,YAAY,IAAI,IAAI,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;AAC5D,QAAM,WAAW,IAAI,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;AAG1D,aAAW,gBAAgB,OAAO;AAChC,UAAM,gBAAgB,UAAU,IAAI,aAAa,QAAQ;AACzD,eAAW,CAAC,KAAK,KAAK,OAAO,QAAQ,aAAa,GAAG;AACnD,YAAM,YACH,aAAmD,KAAK,KAAK,IAC9D,SAAS;AACX,YAAM,YAAY,iBACZ,cAAoD,KAAK,KAAK,IAAI,SAAS,IAC7E;AACJ,UAAI,aAAa,WAAW;AAC1B,cAAM,KAAK;AAAA,UACT,UAAU,aAAa;AAAA,UACvB;AAAA,UACA,OAAO;AAAA,UACP,QAAQ;AAAA,QACV,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAGA,aAAW,iBAAiB,QAAQ;AAClC,QAAI,CAAC,SAAS,IAAI,cAAc,QAAQ,GAAG;AACzC,iBAAW,CAAC,KAAK,KAAK,OAAO,QAAQ,aAAa,GAAG;AACnD,cAAM,aACH,cAAoD,KAAK,KAAK,IAC/D,SAAS;AACX,YAAI,WAAW;AACb,gBAAM,KAAK;AAAA,YACT,UAAU,cAAc;AAAA,YACxB;AAAA,YACA,OAAO;AAAA,YACP,QAAQ;AAAA,UACV,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;ACnGA,SAAS,iBAAiB,MAAoB;AAC5C,MAAI,CAAC,aAAa,IAAI,GAAG;AACvB,UAAM,IAAI;AAAA,MACR,yBAAyB,IAAI;AAAA,MAC7B;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,YACpB,QACA,aACA,UACoB;AACpB,QAAM,OAAO,MAAM,OAAO,MAAM,OAAO,WAAW;AAClD,MAAI;AACF,QAAI;AACJ,QAAI,UAAU;AACZ,uBAAiB,QAAQ;AACzB,YAAM,UAAU,MAAM,OAAO,SAAS,IAAI,aAAa,KAAK,IAAI,QAAQ;AACxE,iBAAW,CAAC,OAAO;AAAA,IACrB,OAAO;AACL,iBAAW,MAAM,OAAO,SAAS,KAAK,aAAa,KAAK,EAAE;AAAA,IAC5D;AACA,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE;AAC9C,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9D,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,cACpB,QACA,aACA,UACA,MACkB;AAClB,mBAAiB,QAAQ;AACzB,QAAM,OAAO,MAAM,OAAO,MAAM,OAAO,WAAW;AAClD,MAAI;AACF,UAAM,UAAU,MAAM,OAAO,SAAS,MAAM,aAAa,KAAK,IAAI,UAAU,IAAI;AAChF,UAAM,OAAO,MAAM,SAAS,aAAa,KAAK,EAAE;AAChD,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE;AAC9C,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9D,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,cACpB,QACA,aACA,UACe;AACf,mBAAiB,QAAQ;AACzB,QAAM,OAAO,MAAM,OAAO,MAAM,OAAO,WAAW;AAClD,MAAI;AACF,UAAM,OAAO,SAAS,OAAO,aAAa,KAAK,IAAI,QAAQ;AAC3D,UAAM,OAAO,MAAM,SAAS,aAAa,KAAK,EAAE;AAChD,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE;AAAA,EAChD,SAAS,OAAO;AACd,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9D,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,aACpB,QACA,aACA,KACyB;AACzB,QAAM,OAAO,MAAM,OAAO,MAAM,OAAO,WAAW;AAClD,MAAI;AACF,UAAM,WAAW,MAAM,OAAO,SAAS,KAAK,aAAa,KAAK,EAAE;AAChE,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE;AAC9C,UAAM,mBAAmB,KAAK,QAAQ;AACtC,WAAO,EAAE,SAAS;AAAA,EACpB,SAAS,OAAO;AACd,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9D,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,aACpB,QACA,aACA,KACA,SACoC;AACpC,QAAM,gBAAgB,MAAM,oBAAoB,GAAG;AAEnD,MAAI,cAAc,WAAW,GAAG;AAC9B,UAAM,IAAI;AAAA,MACR,mCAAmC,GAAG;AAAA,MACtC;AAAA,MACA;AAAA,MACA,4KAA4K,GAAG;AAAA,IACjL;AAAA,EACF;AAGA,aAAW,WAAW,eAAe;AACnC,qBAAiB,QAAQ,QAAQ;AAAA,EACnC;AAEA,QAAM,OAAO,MAAM,OAAO,MAAM,OAAO,WAAW;AAClD,MAAI;AACF,QAAI,SAAS,QAAQ;AACnB,YAAM,iBAAiB,MAAM,OAAO,SAAS,KAAK,aAAa,KAAK,EAAE;AACtE,YAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE;AAC9C,YAAM,QAAQ,aAAa,eAAe,cAAc;AACxD,aAAO,EAAE,MAAM;AAAA,IACjB;AAEA,eAAW,WAAW,eAAe;AACnC,YAAM,EAAE,UAAU,GAAG,KAAK,IAAI;AAC9B,YAAM,OAAO,SAAS,OAAO,aAAa,KAAK,IAAI,UAAU,IAAI;AAAA,IACnE;AAEA,UAAM,OAAO,MAAM,SAAS,aAAa,KAAK,EAAE;AAChD,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE;AAE9C,WAAO;AAAA,MACL,SAAS,cAAc;AAAA,MACvB,WAAW,cAAc,IAAI,CAAC,MAAM,EAAE,QAAQ;AAAA,IAChD;AAAA,EACF,SAAS,OAAO;AACd,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9D,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,WACpB,QACA,aACA,UACA,WACkB;AAClB,mBAAiB,QAAQ;AACzB,QAAM,OAAO,MAAM,OAAO,MAAM,OAAO,WAAW;AAClD,MAAI;AACF,UAAM,SAAS,MAAM,OAAO,OAAO,KAAK,aAAa,KAAK,IAAI,UAAU,SAAS;AACjF,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE;AAC9C,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9D,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,YACpB,QACA,aACA,UACA,WACA,UACgB;AAChB,mBAAiB,QAAQ;AAGzB,QAAM,aAAa,MAAM,cAAc,UAAU,SAAS;AAC1D,MAAI,CAAC,WAAW,OAAO;AACrB,UAAM,IAAI;AAAA,MACR,4BAA4B,WAAW,OAAO,KAAK,IAAI,CAAC;AAAA,MACxD;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,WAAW,SAAS,SAAS,GAAG;AAClC,eAAW,KAAK,WAAW,UAAU;AACnC,cAAQ,KAAK,YAAY,CAAC,EAAE;AAAA,IAC9B;AAAA,EACF;AAEA,QAAM,OAAO,MAAM,OAAO,MAAM,OAAO,WAAW;AAClD,MAAI;AACF,UAAM,QAAQ,MAAM,OAAO,OAAO,OAAO,aAAa,KAAK,IAAI,UAAU,WAAW,QAAQ;AAC5F,UAAM,OAAO,MAAM,SAAS,aAAa,KAAK,EAAE;AAChD,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE;AAC9C,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9D,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,YACpB,QACA,aACA,UACA,WACA,SACe;AACf,mBAAiB,QAAQ;AACzB,QAAM,OAAO,MAAM,OAAO,MAAM,OAAO,WAAW;AAClD,MAAI;AACF,UAAM,OAAO,OAAO,OAAO,aAAa,KAAK,IAAI,UAAU,WAAW,OAAO;AAC7E,UAAM,OAAO,MAAM,SAAS,aAAa,KAAK,EAAE;AAChD,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE;AAAA,EAChD,SAAS,OAAO;AACd,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9D,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,oBACpB,QACA,aACA,KACwB;AACxB,QAAM,gBAAgB,MAAM,oBAAoB,GAAG;AAEnD,QAAM,OAAO,MAAM,OAAO,MAAM,OAAO,WAAW;AAClD,MAAI;AACF,UAAM,iBAAiB,MAAM,OAAO,SAAS,KAAK,aAAa,KAAK,EAAE;AACtE,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE;AAC9C,WAAO,aAAa,eAAe,cAAc;AAAA,EACnD,SAAS,OAAO;AACd,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9D,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,uBACpB,QACA,aACA,OAC8B;AAC9B,QAAM,OAAO,MAAM,OAAO,MAAM,OAAO,WAAW;AAClD,MAAI;AACF,UAAM,eAAe,MAAM,OAAO,oBAAoB,IAAI,aAAa,KAAK,IAAI,KAAK;AACrF,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE;AAC9C,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9D,UAAM;AAAA,EACR;AACF;AAaA,IAAM,kBAA+B;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,eAAsB,aACpB,QACA,aACA,KACA,SAC8B;AAC9B,QAAM,EAAE,OAAAE,QAAO,WAAAC,WAAU,IAAI,MAAM,OAAO,aAAkB;AAC5D,QAAM,EAAE,MAAAC,MAAK,IAAI,MAAM,OAAO,MAAW;AAEzC,QAAM,OAAO,MAAM,OAAO,MAAM,OAAO,WAAW;AAClD,MAAI;AAEF,QAAI;AACJ,QAAI,SAAS,MAAM;AACjB,uBAAiB,QAAQ,IAAI;AAC7B,kBAAY,CAAC,QAAQ,IAAI;AAAA,IAC3B,OAAO;AACL,YAAM,WAAW,MAAM,OAAO,SAAS,KAAK,aAAa,KAAK,EAAE;AAChE,kBAAY,SAAS,IAAI,CAAC,MAAM,EAAE,QAAQ;AAAA,IAC5C;AAEA,UAAM,aAA0B,SAAS,OAAO,CAAC,QAAQ,IAAI,IAAI;AAEjE,QAAI,cAAc;AAClB,QAAI,YAAY;AAGhB,UAAM,QAAuF,CAAC;AAE9F,eAAW,YAAY,WAAW;AAChC,iBAAW,aAAa,YAAY;AAClC,cAAM,SAAS,MAAM,OAAO,OAAO,KAAK,aAAa,KAAK,IAAI,UAAU,SAAS;AACjF,iBAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,gBAAM,MAAM,OAAO,CAAC;AACpB,cAAI,OAAO,IAAI,KAAK;AAClB,kBAAM,KAAK,EAAE,UAAU,WAAW,KAAK,IAAI,KAAK,OAAO,IAAI,EAAE,CAAC;AAAA,UAChE;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,UAAM,cAAc;AACpB,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,aAAa;AAClD,YAAM,QAAQ,MAAM,MAAM,GAAG,IAAI,WAAW;AAC5C,YAAM,UAAU,MAAM,QAAQ;AAAA,QAC5B,MAAM,IAAI,OAAO,SAAS;AACxB,gBAAM,UAAUA,MAAK,KAAK,KAAK,UAAU,KAAK,SAAS;AACvD,gBAAMF,OAAM,SAAS,EAAE,WAAW,KAAK,CAAC;AAExC,gBAAM,WAAW,MAAM,MAAM,KAAK,GAAG;AACrC,gBAAM,SAAS,OAAO,KAAK,MAAM,SAAS,YAAY,CAAC;AACvD,gBAAM,WAAWE,MAAK,SAAS,GAAG,KAAK,KAAK,MAAM;AAClD,gBAAMD,WAAU,UAAU,MAAM;AAEhC,iBAAO,OAAO;AAAA,QAChB,CAAC;AAAA,MACH;AAEA,iBAAW,QAAQ,SAAS;AAC1B;AACA,qBAAa;AAAA,MACf;AAAA,IACF;AAEA,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE;AAE9C,WAAO;AAAA,MACL,WAAW,UAAU;AAAA,MACrB,QAAQ;AAAA,MACR;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9D,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,iBACpB,QACA,aACA,SACqB;AACrB,QAAM,OAAO,MAAM,OAAO,MAAM,OAAO,WAAW;AAClD,MAAI;AACF,UAAM,SAAS,MAAM,OAAO,QAAQ,MAAM,aAAa,KAAK,IAAI,OAAO;AACvE,UAAM,OAAO,MAAM,SAAS,aAAa,KAAK,EAAE;AAChD,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE;AAC9C,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9D,UAAM;AAAA,EACR;AACF;;;AClYA,SAAS,WAAAE,UAAS,YAAAC,WAAU,aAAAC,YAAW,SAAAC,QAAO,cAAc;AAC5D,SAAS,QAAAC,aAAY;AA2BrB,IAAM,kBAAkB;AAExB,eAAe,WAAW,MAAgC;AACxD,MAAI;AACF,UAAM,OAAO,IAAI;AACjB,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,eAAe,KAAyC;AAC5E,QAAM,SAA4B;AAAA,IAChC,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,OAAO,CAAC;AAAA,IACR,mBAAmB,CAAC;AAAA,IACpB,eAAe,CAAC;AAAA,EAClB;AAGA,QAAM,cAAcA,MAAK,KAAK,UAAU;AACxC,QAAM,iBAAiB,MAAM,WAAW,WAAW;AAEnD,QAAM,eAAe,iBACjBA,MAAK,aAAa,UAAU,IAC5BA,MAAK,KAAK,UAAU;AACxB,QAAM,cAAc,iBAChBA,MAAK,aAAa,SAAS,IAC3BA,MAAK,KAAK,SAAS;AAEvB,SAAO,cAAc,MAAM,WAAW,YAAY;AAClD,SAAO,aAAa,MAAM,WAAW,WAAW;AAChD,SAAO,aAAa,MAAM,WAAWA,MAAK,KAAK,SAAS,CAAC;AAGzD,QAAM,cAAc,iBAChBA,MAAK,aAAa,YAAY,SAAS,IACvCA,MAAK,KAAK,YAAY,SAAS;AAEnC,SAAO,cAAc,MAAM,WAAW,WAAW;AAEjD,MAAI,OAAO,aAAa;AACtB,QAAI;AACF,YAAM,UAAU,MAAMJ,SAAQ,aAAa,EAAE,eAAe,KAAK,CAAC;AAClE,aAAO,oBAAoB,QACxB,OAAO,CAAC,MAAM,EAAE,YAAY,CAAC,EAC7B,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,IACtB,QAAQ;AACN,aAAO,cAAc,KAAK,4DAAuD;AAAA,IACnF;AAAA,EACF;AAGA,MAAI,OAAO,aAAa;AACtB,QAAI;AACF,YAAM,UAAU,MAAMC,UAAS,cAAc,OAAO;AACpD,aAAO,QAAQ,cAAc,OAAO;AAGpC,UAAI,gBAAgB,KAAK,OAAO,GAAG;AACjC,eAAO,cAAc;AAAA,UACnB;AAAA,QAEF;AAAA,MACF;AAAA,IACF,QAAQ;AACN,aAAO,cAAc,KAAK,kDAA6C;AAAA,IACzE;AAAA,EACF;AAGA,MAAI,OAAO,YAAY;AACrB,QAAI;AACF,YAAM,UAAU,MAAMA,UAAS,aAAa,OAAO;AACnD,YAAM,SAAS,aAAa,OAAO;AACnC,aAAO,cAAc,OAAO;AAC5B,aAAO,cAAc,OAAO;AAAA,IAC9B,QAAQ;AACN,aAAO,cAAc,KAAK,iDAA4C;AAAA,IACxE;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,cAAc,SAAiC;AAC7D,QAAM,QAAwB,CAAC;AAE/B,QAAM,YAAY;AAClB,MAAI;AAEJ,UAAQ,QAAQ,UAAU,KAAK,OAAO,OAAO,MAAM;AACjD,UAAM,OAAO,MAAM,CAAC,KAAK;AACzB,UAAM,OAAO,MAAM,CAAC,KAAK;AACzB,UAAM,UAAoB,CAAC;AAG3B,UAAM,cACJ;AACF,QAAI;AACJ,YAAQ,cAAc,YAAY,KAAK,IAAI,OAAO,MAAM;AACtD,YAAM,SAAS,YAAY,CAAC,KAAK;AACjC,UAAI,CAAC,QAAQ,SAAS,MAAM,GAAG;AAC7B,gBAAQ,KAAK,MAAM;AAAA,MACrB;AAAA,IACF;AAGA,UAAM,gBAAgB,aAAa,MAAM,SAAS,IAAI;AAEtD,UAAM,KAAK,EAAE,MAAM,SAAS,cAAc,CAAC;AAAA,EAC7C;AAEA,SAAO;AACT;AAEA,SAAS,aAAa,MAAc,SAAmB,MAAkC;AACvF,MAAI,QAAQ,SAAS,sBAAsB,KAAK,QAAQ,SAAS,QAAQ,GAAG;AAC1E,UAAM,aAAa,KAAK,MAAM,2BAA2B;AACzD,UAAM,eAAe,KAAK,MAAM,kCAAkC;AAElE,QAAI,cAAc;AAChB,YAAM,MAAM,WAAW,aAAa,CAAC,KAAK,GAAG;AAE7C,YAAM,MAAM,MAAM,IAAI,KAAK,MAAM,GAAG,IAAI,KAAK,MAAM,MAAM,GAAG;AAC5D,aAAO,iCAAiC,GAAG,GAAG,aAAa,YAAY,WAAW,CAAC,CAAC,KAAK,EAAE;AAAA,IAC7F;AAEA,QAAI,YAAY;AACd,aAAO,+BAA+B,WAAW,CAAC,CAAC;AAAA,IACrD;AAGA,QAAI,KAAK,MAAM,4BAA4B,KAAK,KAAK,MAAM,4BAA4B,GAAG;AACxF,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAEA,MAAI,QAAQ,SAAS,6BAA6B,GAAG;AACnD,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEO,SAAS,aAAa,SAAiE;AAC5F,QAAM,SAAyD,CAAC;AAGhE,QAAM,WAAW,QAAQ,MAAM,6CAA6C;AAC5E,MAAI,UAAU;AACZ,WAAO,cAAc,SAAS,CAAC;AAAA,EACjC;AAGA,QAAM,WAAW,QAAQ,MAAM,8CAA8C;AAC7E,MAAI,UAAU;AACZ,WAAO,cAAc,SAAS,CAAC;AAAA,EACjC;AAEA,SAAO;AACT;AAEO,SAAS,sBAAsB,WAA+C;AACnF,QAAM,SAAkC,CAAC;AACzC,QAAM,YAAsB,CAAC;AAC7B,QAAM,WAAqB,CAAC,GAAG,UAAU,aAAa;AAGtD,MAAI,UAAU,aAAa;AACzB,WAAO,KAAK,IAAI,UAAU;AAAA,EAC5B,OAAO;AACL,cAAU,KAAK,0DAA0D;AAAA,EAC3E;AAGA,MAAI,UAAU,aAAa;AACzB,WAAO,MAAM,IAAI,EAAE,gBAAgB,UAAU,YAAY;AAAA,EAC3D,OAAO;AACL,cAAU,KAAK,0CAA0C;AAAA,EAC3D;AAGA,aAAW,QAAQ,UAAU,OAAO;AAClC,QAAI,KAAK,eAAe;AACtB,gBAAU;AAAA,QACR,0BAA0B,KAAK,IAAI,WAAW,KAAK,aAAa;AAAA,MAClE;AAAA,IACF;AAEA,QAAI,KAAK,QAAQ,SAAS,6BAA6B,GAAG;AACxD,eAAS;AAAA,QACP,SAAS,KAAK,IAAI;AAAA,MAEpB;AAAA,IACF;AAGA,QACE,KAAK,QAAQ,WAAW,KACvB,KAAK,kBAAkB,UAAa,CAAC,KAAK,QAAQ,SAAS,6BAA6B,GACzF;AACA,eAAS;AAAA,QACP,SAAS,KAAK,IAAI;AAAA,MAEpB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,UAAU,eAAe,UAAU,kBAAkB,SAAS,GAAG;AACnE,UAAM,QAAQ,UAAU,kBAAkB,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI;AAC/D,UAAM,OACJ,UAAU,kBAAkB,SAAS,IACjC,MAAM,UAAU,kBAAkB,SAAS,CAAC,WAC5C;AACN,cAAU;AAAA,MACR,6BAA6B,UAAU,kBAAkB,MAAM,iBAAiB,KAAK,GAAG,IAAI;AAAA,IAC9F;AACA,cAAU;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAGA,YAAU,KAAK,qCAAqC;AACpD,YAAU,KAAK,6DAA6D;AAE5E,MAAI,UAAU,YAAY;AACxB,cAAU,KAAK,8DAA8D;AAAA,EAC/E;AAGA,MACE,UAAU,MAAM;AAAA,IACd,CAAC,MAAM,EAAE,QAAQ,SAAS,QAAQ,KAAK,EAAE,QAAQ,SAAS,sBAAsB;AAAA,EAClF,GACA;AACA,cAAU,KAAK,uEAAuE;AAAA,EACxF;AAEA,SAAO,EAAE,QAAQ,WAAW,SAAS;AACvC;AAEA,eAAsB,qBACpB,QACA,KACmB;AACnB,QAAME,OAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AACpC,QAAM,QAAkB,CAAC;AAGzB,MAAI,OAAO,KAAK,OAAO,MAAM,EAAE,SAAS,GAAG;AACzC,UAAM,aAAaC,MAAK,KAAK,aAAa;AAC1C,UAAMF,WAAU,YAAY,KAAK,UAAU,OAAO,QAAQ,MAAM,CAAC,IAAI,MAAM,OAAO;AAClF,UAAM,KAAK,UAAU;AAAA,EACvB;AAGA,QAAM,gBAAgBE,MAAK,KAAK,cAAc;AAC9C,QAAM,QAAkB;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,aAAW,QAAQ,OAAO,WAAW;AACnC,UAAM,KAAK,SAAS,IAAI,EAAE;AAAA,EAC5B;AAEA,MAAI,OAAO,SAAS,SAAS,GAAG;AAC9B,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,aAAa;AACxB,UAAM,KAAK,EAAE;AACb,eAAW,WAAW,OAAO,UAAU;AACrC,YAAM,KAAK,YAAO,OAAO,EAAE;AAAA,IAC7B;AAAA,EACF;AAEA,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,oBAAoB;AAC/B,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,oBAAoB;AAC/B,QAAM,KAAK,oBAAoB;AAC/B,QAAM,KAAK,qEAAqE;AAChF,QAAM,KAAK,oDAAoD;AAC/D,QAAM,KAAK,0EAA4E;AACvF,QAAM,KAAK,mEAAqE;AAChF,QAAM,KAAK,2DAA2D;AACtE,QAAM,KAAK,4EAAuE;AAClF,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,0FAA0F;AACrG,QAAM,KAAK,EAAE;AAEb,QAAMF,WAAU,eAAe,MAAM,KAAK,IAAI,GAAG,OAAO;AACxD,QAAM,KAAK,aAAa;AAExB,SAAO;AACT;;;AC3UA,IAAM,kBAAkB;AACxB,IAAM,SAAS;AACf,IAAM,cAAc,CAAC,YAAY,SAAS,QAAQ,YAAY;AAC9D,IAAM,kBAAkB;AAEjB,SAAS,oBAAoB,MAAoB;AACtD,MAAI,CAAC,QAAQ,CAAC,gBAAgB,KAAK,IAAI,GAAG;AACxC,UAAM,IAAI;AAAA,MACR,0BAA0B,IAAI;AAAA,MAC9B;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,oBAAoB,MAA6B;AAC/D,QAAM,MAAM,OAAO,SAAS,WAAW,SAAS,MAAM,EAAE,IAAI;AAC5D,MAAI,CAAC,OAAO,UAAU,GAAG,KAAK,MAAM,GAAG;AACrC,UAAM,IAAI;AAAA,MACR,0BAA0B,IAAI;AAAA,MAC9B;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,qBAAqB,MAAoB;AACvD,MAAI,CAAC,QAAQ,CAAC,aAAa,IAAI,GAAG;AAChC,UAAM,IAAI;AAAA,MACR,2BAA2B,IAAI;AAAA,MAC/B;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,kBAAkB,MAAoB;AACpD,MAAI,CAAC,MAAM;AACT,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,CAAC,YAAY,SAAS,IAAI,KAAK,CAAC,gBAAgB,KAAK,IAAI,GAAG;AAC9D,UAAM,IAAI;AAAA,MACR,wBAAwB,IAAI;AAAA,MAC5B;AAAA,MACA;AAAA,MACA,iBAAiB,YAAY,KAAK,IAAI,CAAC;AAAA,IACzC;AAAA,EACF;AACF;AAEO,SAAS,YAAY,KAAmB;AAC7C,MAAI,CAAC,OAAO,CAAC,OAAO,KAAK,GAAG,GAAG;AAC7B,UAAM,IAAI;AAAA,MACR,8BAA8B,GAAG;AAAA,MACjC;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;ACtEA,SAAS,WAAAG,UAAS,YAAAC,WAAU,QAAAC,aAAY;AACxC,SAAS,WAAAC,UAAS,UAAU,QAAAC,aAAY;AAcxC,IAAM,mBAAmB;AAEzB,eAAsB,wBAAwB,KAAqC;AACjF,MAAI;AACJ,MAAI;AACF,cAAU,MAAMC,SAAQ,GAAG;AAAA,EAC7B,QAAQ;AACN,UAAM,IAAI;AAAA,MACR,sCAAsC,GAAG;AAAA,MACzC;AAAA,MACA;AAAA,MACA,2FAA2F,GAAG;AAAA,IAChG;AAAA,EACF;AAEA,QAAM,QAAuB,CAAC;AAE9B,aAAW,SAAS,SAAS;AAC3B,QAAIC,SAAQ,KAAK,MAAM,OAAQ;AAE/B,UAAM,WAAW,SAAS,OAAO,MAAM;AACvC,UAAM,WAAWC,MAAK,KAAK,KAAK;AAEhC,UAAM,QAAQ,MAAMC,MAAK,QAAQ;AACjC,QAAI,CAAC,MAAM,OAAO,EAAG;AAErB,UAAM,QAAQ,MAAMC,UAAS,UAAU,OAAO,GAAG,KAAK;AACtD,QAAI,KAAK,WAAW,EAAG;AAEvB,UAAM,KAAK,EAAE,UAAU,KAAK,CAAC;AAAA,EAC/B;AAEA,SAAO;AACT;AAEO,SAAS,qBAAqB,OAA8C;AACjF,QAAM,SAAmB,CAAC;AAC1B,QAAM,WAAqB,CAAC;AAE5B,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,IAAI,KAAK,QAAQ,GAAG;AAC3B,aAAO,KAAK,4BAA4B,KAAK,QAAQ,EAAE;AAAA,IACzD;AACA,SAAK,IAAI,KAAK,QAAQ;AAEtB,QAAI,KAAK,KAAK,SAAS,kBAAkB;AACvC,aAAO;AAAA,QACL,sBAAsB,KAAK,QAAQ,YAAY,gBAAgB,WAAW,KAAK,KAAK,MAAM;AAAA,MAC5F;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,OAAO,WAAW,GAAG,QAAQ,SAAS;AACxD;;;ACrEA,SAAS,QAAAC,aAAY;AAwBrB,IAAM,kBAAkB,oBAAI,IAAI;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AACD,IAAM,gBAAgB;AAEtB,eAAsB,sBAAsB,SAAmD;AAC7F,QAAM,SAA0B,CAAC;AAEjC,QAAM,iBAA2B,CAAC;AAGlC,QAAM,aAAa,MAAM,mBAAmB,QAAQ,QAAQ;AAC5D,SAAO,KAAK;AAAA,IACV,MAAM;AAAA,IACN,QAAQ,WAAW;AAAA,IACnB,SAAS,WAAW,QAChB,SAAS,WAAW,SAAS,YAAY,CAAC,KAAKC,YAAW,WAAW,SAAS,CAAC,MAC/E,WAAW,OAAO,KAAK,IAAI;AAAA,EACjC,CAAC;AAED,aAAW,KAAK,WAAW,UAAU;AACnC,mBAAe,KAAK,CAAC;AAAA,EACvB;AAGA,MAAI,QAAQ,aAAa;AACvB,QAAI;AACF,YAAM,QAAQ,MAAMC,MAAK,QAAQ,WAAW;AAC5C,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,QAAQ,MAAM,OAAO;AAAA,QACrB,SAAS,MAAM,OAAO,IAClB,uBAAuBD,YAAW,MAAM,IAAI,CAAC,MAC7C;AAAA,MACN,CAAC;AAAA,IACH,QAAQ;AACN,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS,2BAA2B,QAAQ,WAAW;AAAA,MACzD,CAAC;AAAA,IACH;AAAA,EACF;AAGA,MAAI,QAAQ,OAAO;AACjB,UAAM,UAAU,gBAAgB,IAAI,QAAQ,KAAK,KAAK,cAAc,KAAK,QAAQ,KAAK;AACtF,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS,UACL,UAAU,QAAQ,KAAK,eACvB,uBAAuB,QAAQ,KAAK;AAAA,IAC1C,CAAC;AAAA,EACH;AAGA,MAAI,gBAAgB,QAAQ;AAC5B,MAAI,QAAQ,UAAU;AACpB,QAAI;AACF,sBAAgB,MAAM,wBAAwB,QAAQ,QAAQ;AAC9D,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS,0BAA0B,cAAc,MAAM;AAAA,MACzD,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,MAC1D,CAAC;AAAA,IACH;AAAA,EACF;AAEA,MAAI,iBAAiB,cAAc,SAAS,GAAG;AAC7C,UAAM,cAAc,qBAAqB,aAAa;AACtD,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,QAAQ,YAAY;AAAA,MACpB,SAAS,YAAY,QACjB,wBAAwB,cAAc,MAAM,kBAC5C,YAAY,OAAO,KAAK,IAAI;AAAA,IAClC,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,OAAO,OAAO,MAAM,CAAC,MAAM,EAAE,MAAM;AAAA,IACnC;AAAA,IACA,UAAU;AAAA,EACZ;AACF;AAEA,SAASA,YAAW,OAAuB;AACzC,MAAI,SAAS,OAAO,KAAM,QAAO,IAAI,SAAS,OAAO,OAAO,QAAQ,CAAC,CAAC;AACtE,MAAI,SAAS,KAAM,QAAO,IAAI,QAAQ,MAAM,QAAQ,CAAC,CAAC;AACtD,SAAO,GAAG,KAAK;AACjB;;;ACjHA,eAAsB,QACpB,QACA,aACA,UACA,SAC8C;AAE9C,MAAI;AACJ,MAAI,QAAQ,UAAU;AACpB,mBAAe,MAAM,wBAAwB,QAAQ,QAAQ;AAAA,EAC/D,WAAW,QAAQ,OAAO;AACxB,mBAAe,CAAC,EAAE,UAAU,SAAS,MAAM,QAAQ,MAAM,CAAC;AAAA,EAC5D;AAGA,QAAM,aAAa,MAAM,sBAAsB;AAAA,IAC7C;AAAA,IACA,aAAa,QAAQ;AAAA,IACrB,OAAO,QAAQ,SAAS;AAAA,IACxB,OAAO;AAAA,EACT,CAAC;AAED,MAAI,QAAQ,QAAQ;AAClB,UAAME,UAAS,MAAM,cAAc,QAAQ,aAAa,UAAU;AAAA,MAChE,OAAO,QAAQ,SAAS;AAAA,MACxB,cAAc,QAAQ,iBAAiB,QAAQ,iBAAiB,MAAM;AAAA,MACtE,QAAQ;AAAA,IACV,CAAC;AAED,WAAO,EAAE,QAAQ,MAAM,YAAY,QAAAA,QAAO;AAAA,EAC5C;AAEA,MAAI,CAAC,WAAW,OAAO;AACrB,WAAO,EAAE,WAAW;AAAA,EACtB;AAGA,QAAM,SAAS,MAAM,cAAc,QAAQ,aAAa,UAAU;AAAA,IAChE,OAAO,QAAQ,SAAS;AAAA,IACxB,cAAc,QAAQ,iBAAiB,QAAQ,iBAAiB,MAAM;AAAA,IACtE;AAAA,IACA,aAAa,QAAQ;AAAA,IACrB,aAAa,QAAQ;AAAA,EACvB,CAAC;AAED,SAAO,EAAE,YAAY,OAAO;AAC9B;;;ACzEA,SAAS,mBAAmB;AAiB5B,eAAsB,YACpB,QACA,aACA,SACmB;AACnB,QAAM,aAAiC,CAAC;AACxC,MAAI,SAAS,oBAAqB,YAAW,sBAAsB,QAAQ;AAC3E,MAAI,SAAS,WAAY,YAAW,aAAa,QAAQ;AAEzD,QAAM,WAAW,MAAM,OAAO,QAAQ,KAAK,aAAa,UAAU;AAClE,MAAI,UAAU,SAAS,WAAW,CAAC;AAGnC,MAAI,SAAS,UAAU,QAAW;AAChC,cAAU,QAAQ,OAAO,CAAC,MAAM;AAC9B,YAAM,cAAc,EAAE,WAAW,CAAC,GAAG;AACrC,aAAO,eAAe,YAAY,eAAe,QAAQ;AAAA,IAC3D,CAAC;AAAA,EACH;AAEA,MAAI,SAAS,UAAU;AACrB,cAAU,QAAQ,OAAO,CAAC,MAAM;AAC9B,YAAM,cAAc,EAAE,WAAW,CAAC,GAAG;AACrC,aAAO,aAAa,qBAAqB,QAAQ;AAAA,IACnD,CAAC;AAAA,EACH;AAEA,MAAI,SAAS,OAAO;AAClB,UAAM,YAAY,IAAI,KAAK,QAAQ,KAAK,EAAE,QAAQ,IAAI;AACtD,cAAU,QAAQ,OAAO,CAAC,MAAM;AAC9B,YAAM,cAAc,EAAE,WAAW,CAAC,GAAG;AACrC,aAAO,eAAe,OAAO,YAAY,aAAa,OAAO,KAAK;AAAA,IACpE,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAEA,eAAsB,UACpB,QACA,aACA,UACA,qBACiB;AACjB,SAAO,OAAO,QAAQ,IAAI,aAAa,UAAU,mBAAmB;AACtE;AAEA,IAAM,mBAAmB;AAEzB,eAAsB,cACpB,QACA,aACA,UACA,WAC8B;AAC9B,MAAI,UAAU,SAAS,kBAAkB;AACvC,UAAM,IAAI;AAAA,MACR,sBAAsB,gBAAgB,gBAAgB,UAAU,MAAM,oCAAoC,gBAAgB;AAAA,MAC1H;AAAA,MACA;AAAA,MACA,yBAAyB,gBAAgB,yCAAyC,UAAU,MAAM;AAAA,IACpG;AAAA,EACF;AACA,MAAI,UAAU,WAAW,GAAG;AAC1B,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,SAAO,OAAO,QAAQ,MAAM,aAAa,UAAU,SAAS;AAC9D;AAEA,eAAsB,cACpB,QACA,aACA,SACiB;AACjB,QAAM,EAAE,OAAO,WAAW,IAAI,MAAM,YAAoB,OAAO,cAAc;AAC3E,UAAM,aAAiC,EAAE,OAAO,UAAU;AAC1D,QAAI,SAAS,oBAAqB,YAAW,sBAAsB,QAAQ;AAC3E,UAAM,WAAW,MAAM,OAAO,QAAQ,KAAK,aAAa,UAAU;AAClE,WAAO;AAAA,MACL,OAAO,SAAS,WAAW,CAAC;AAAA,MAC5B,eAAe,SAAS,iBAAiB;AAAA,IAC3C;AAAA,EACF,CAAC;AAED,MAAI,WAAW;AAEf,MAAI,SAAS,UAAU,QAAW;AAChC,eAAW,SAAS,OAAO,CAAC,MAAM;AAChC,YAAM,KAAK,EAAE,WAAW,CAAC,GAAG;AAC5B,aAAO,MAAM,GAAG,eAAe,QAAQ;AAAA,IACzC,CAAC;AAAA,EACH;AAEA,MAAI,SAAS,UAAU;AACrB,eAAW,SAAS,OAAO,CAAC,MAAM;AAChC,YAAM,KAAK,EAAE,WAAW,CAAC,GAAG;AAC5B,aAAO,IAAI,qBAAqB,QAAQ;AAAA,IAC1C,CAAC;AAAA,EACH;AAEA,MAAI,SAAS,OAAO;AAClB,UAAM,YAAY,IAAI,KAAK,QAAQ,KAAK,EAAE,QAAQ,IAAI;AACtD,eAAW,SAAS,OAAO,CAAC,MAAM;AAChC,YAAM,KAAK,EAAE,WAAW,CAAC,GAAG;AAC5B,aAAO,MAAM,OAAO,GAAG,aAAa,OAAO,KAAK;AAAA,IAClD,CAAC;AAAA,EACH;AAEA,MAAI,SAAS,WAAW,OAAO;AAC7B,WAAO,aAAa,QAAQ;AAAA,EAC9B;AAEA,SAAO,KAAK,UAAU,UAAU,MAAM,CAAC;AACzC;AAEA,SAAS,aAAa,SAA2B;AAC/C,QAAM,SAAS;AACf,QAAM,OAAO,QAAQ,IAAI,CAAC,MAAM;AAC9B,UAAM,KAAK,EAAE,WAAW,CAAC,GAAG;AAC5B,UAAM,SAAS;AAAA,MACb,EAAE;AAAA,MACF,UAAU,EAAE,UAAU;AAAA,MACtB,IAAI,cAAc;AAAA,MAClB,UAAU,IAAI,QAAQ,EAAE;AAAA,MACxB,IAAI,oBAAoB;AAAA,MACxB,KAAK,IAAI,KAAK,OAAO,GAAG,aAAa,OAAO,IAAI,GAAI,EAAE,YAAY,IAAI;AAAA,MACtE,UAAU,IAAI,UAAU,EAAE;AAAA,MAC1B,UAAU,IAAI,kBAAkB,EAAE;AAAA,IACpC;AACA,WAAO,OAAO,KAAK,GAAG;AAAA,EACxB,CAAC;AACD,SAAO,CAAC,QAAQ,GAAG,IAAI,EAAE,KAAK,IAAI;AACpC;AAEA,SAAS,UAAU,OAAuB;AACxC,MAAI,MAAM,SAAS,GAAG,KAAK,MAAM,SAAS,GAAG,KAAK,MAAM,SAAS,IAAI,GAAG;AACtE,WAAO,IAAI,MAAM,QAAQ,MAAM,IAAI,CAAC;AAAA,EACtC;AACA,SAAO;AACT;;;ACjIA,IAAM,qBAAwD;AAAA,EAC5D,oBAAoB,CAAC,aAAa,0BAA0B,eAAe;AAAA,EAC3E,kBAAkB,CAAC,WAAW,wBAAwB,eAAe;AAAA,EACrE,wBAAwB,CAAC,iBAAiB,eAAe;AAAA,EACzD,4BAA4B,CAAC,qBAAqB,eAAe;AAAA,EACjE,8BAA8B,CAAC,uBAAuB,eAAe;AAAA,EACrE,sCAAsC,CAAC,+BAA+B,eAAe;AAAA,EACrF,qBAAqB,CAAC,oBAAoB,eAAe;AAC3D;AAEA,SAAS,WAAW,WAA4B,SAA8C;AAC5F,QAAM,UAAU,mBAAmB,SAAS,KAAK,CAAC,oBAAoB,eAAe;AAErF,QAAM,OAAO,SAAS,QAAQ;AAC9B,QAAM,SAAS,KAAK,KAAK,KAAK;AAC9B,QAAM,MAAM,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM;AACxC,QAAM,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,SAAS,OAAO,MAAM;AAE1D,QAAM,QAAwB;AAAA,IAC5B;AAAA,IACA,cAAc;AAAA,MACZ,mBAAmB,SAAS,eAAe;AAAA,MAC3C,WAAW;AAAA,QACT,MAAM,MAAM,eAAe;AAAA,QAC3B,OAAO,MAAM,YAAY,IAAI;AAAA,QAC7B,KAAK,MAAM,WAAW;AAAA,MACxB;AAAA,MACA,SAAS;AAAA,QACP,MAAM,IAAI,eAAe;AAAA,QACzB,OAAO,IAAI,YAAY,IAAI;AAAA,QAC3B,KAAK,IAAI,WAAW;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,SAAS,WAAW;AACtB,UAAM,aAAa,CAAC,QAAQ,SAAS;AAAA,EACvC;AAEA,SAAO;AACT;AAEA,eAAe,YACb,WACA,aACA,WACA,SAC4B;AAC5B,QAAM,QAAQ,WAAW,WAAW,OAAO;AAC3C,SAAO,UAAU,eAAe,aAAa,WAAW,KAAK;AAC/D;AAEA,eAAsB,kBACpB,WACA,aACyB;AACzB,QAAM,aAAwD;AAAA,IAC5D,CAAC,sBAAsB,WAAW;AAAA,IAClC,CAAC,oBAAoB,SAAS;AAAA,IAC9B,CAAC,0BAA0B,eAAe;AAAA,IAC1C,CAAC,8BAA8B,mBAAmB;AAAA,IAClD,CAAC,gCAAgC,qBAAqB;AAAA,IACtD,CAAC,wCAAwC,mBAAmB;AAAA,EAC9D;AAEA,QAAM,UAAU,MAAM,QAAQ;AAAA,IAC5B,WAAW;AAAA,MAAI,CAAC,CAAC,MAAM,MACrB,UAAU,eAAe,aAAa,QAAQ,WAAW,MAAM,CAAC;AAAA,IAClE;AAAA,EACF;AAEA,QAAM,WAA2B,CAAC;AAClC,WAAS,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK;AAC1C,UAAM,QAAQ,WAAW,CAAC;AAC1B,QAAI,CAAC,MAAO;AACZ,UAAM,MAAM,MAAM,CAAC;AACnB,UAAM,SAAS,QAAQ,CAAC;AACxB,QAAI,CAAC,OAAQ;AACb,QAAI,OAAO,WAAW,aAAa;AACjC,eAAS,GAAG,IAAI,OAAO,MAAM,QAAQ,CAAC;AAAA,IACxC;AAAA,EACF;AAEA,SAAO;AACT;AAEA,eAAsB,iBACpB,WACA,aACA,SAC4B;AAC5B,SAAO,YAAY,WAAW,aAAa,sBAAsB,OAAO;AAC1E;AAEA,eAAsB,aACpB,WACA,aACA,SAC4B;AAC5B,SAAO,YAAY,WAAW,aAAa,oBAAoB,OAAO;AACxE;AAEA,eAAsB,iBACpB,WACA,aACA,SAC4B;AAC5B,SAAO,YAAY,WAAW,aAAa,0BAA0B,OAAO;AAC9E;AAEA,eAAsB,mBACpB,WACA,aACA,SAC4B;AAC5B,SAAO,YAAY,WAAW,aAAa,8BAA8B,OAAO;AAClF;AAEA,eAAsB,iBACpB,WACA,aACA,SAC4B;AAC5B,SAAO,YAAY,WAAW,aAAa,gCAAgC,OAAO;AACpF;AAEA,eAAsB,gBACpB,WACA,aACA,SAC4B;AAC5B,SAAO,YAAY,WAAW,aAAa,wCAAwC,OAAO;AAC5F;AAEA,eAAsB,mBACpB,WACA,aACmC;AACnC,SAAO,UAAU,aAAa,WAAW;AAC3C;AAEA,eAAsB,mBACpB,WACA,aACA,SAC8B;AAC9B,SAAO,UAAU,kBAAkB,aAAa,SAAS,QAAQ,SAAS,UAAU;AACtF;AAUA,eAAsB,mBACpB,WACA,aACA,WACA,OAAe,GACiB;AAChC,QAAM,SAAS,KAAK,KAAK,KAAK;AAC9B,QAAM,QAAQ,KAAK,IAAI;AAIvB,QAAM,SAAS,QAAQ,IAAI;AAG3B,QAAM,aAAa,IAAI,KAAK,MAAM;AAClC,QAAM,eAAe,IAAI,KAAK,SAAS,OAAO,MAAM;AAGpD,QAAM,cAAc,IAAI,KAAK,SAAS,OAAO,SAAS,MAAM;AAC5D,QAAM,gBAAgB,IAAI,KAAK,SAAS,OAAO,SAAS,SAAS,OAAO,MAAM;AAE9E,QAAM,UAAU,mBAAmB,SAAS,KAAK,CAAC,oBAAoB,eAAe;AAGrF,QAAMC,aAAY,CAAC,OAAa;AAAA,IAC9B,MAAM,EAAE,eAAe;AAAA,IACvB,OAAO,EAAE,YAAY,IAAI;AAAA,IACzB,KAAK,EAAE,WAAW;AAAA,EACpB;AAEA,QAAM,YAAY,CAAC,OAAa,SAA+B;AAAA,IAC7D;AAAA,IACA,cAAc;AAAA,MACZ,mBAAmB;AAAA,MACnB,WAAWA,WAAU,KAAK;AAAA,MAC1B,SAASA,WAAU,GAAG;AAAA,IACxB;AAAA,EACF;AAEA,QAAM,CAAC,eAAe,cAAc,IAAI,MAAM,QAAQ,IAAI;AAAA,IACxD,UAAU,eAAe,aAAa,WAAW,UAAU,cAAc,UAAU,CAAC;AAAA,IACpF,UAAU,eAAe,aAAa,WAAW,UAAU,eAAe,WAAW,CAAC;AAAA,EACxF,CAAC;AAED,QAAM,aAAa,CAAC,SAAsD;AACxE,QAAI,CAAC,QAAQ,KAAK,WAAW,EAAG,QAAO;AACvC,UAAM,SAAS,KACZ,IAAI,CAAC,MAAM;AACV,YAAM,OAAO,OAAO,KAAK,EAAE,OAAO;AAClC,YAAM,QAAQ,KAAK,CAAC;AACpB,aAAO,QAAQ,OAAO,EAAE,QAAQ,KAAK,GAAG,cAAc,KAAK,IAAI;AAAA,IACjE,CAAC,EACA,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAC1B,QAAI,OAAO,WAAW,EAAG,QAAO;AAChC,WAAO,OAAO,OAAO,CAAC,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI,OAAO;AAAA,EACpD;AAEA,QAAM,UAAU,WAAW,cAAc,IAAI;AAC7C,QAAM,WAAW,WAAW,eAAe,IAAI;AAE/C,MAAI;AACJ,MAAI,YAAgD;AAEpD,MAAI,YAAY,UAAa,aAAa,UAAa,aAAa,GAAG;AACrE,qBAAkB,UAAU,YAAY,WAAY;AACpD,QAAI,KAAK,IAAI,aAAa,IAAI,GAAG;AAC/B,kBAAY;AAAA,IACd,WAAW,gBAAgB,GAAG;AAC5B,kBAAY;AAAA,IACd,OAAO;AACL,kBAAY;AAAA,IACd;AAAA,EACF;AAEA,SAAO;AAAA,IACL,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA,eAAe,kBAAkB,SAAY,KAAK,MAAM,gBAAgB,EAAE,IAAI,KAAK;AAAA,IACnF;AAAA,EACF;AACF;AAEO,SAAS,eAAe,OAA2B,WAAoC;AAC5F,SAAO;AAAA,IACL,UAAU,UAAU,UAAa,QAAQ;AAAA,IACzC;AAAA,IACA;AAAA,EACF;AACF;;;AC/QA,SAAS,eAAAC,oBAAmB;AAa5B,SAAS,iBAAiB,OAAqB;AAC7C,MAAI,MAAM,UAAU,UAAa,OAAO,MAAM,UAAU,UAAU;AAChE,WAAO,EAAE,GAAG,OAAO,OAAO,OAAO,MAAM,KAAK,EAAE;AAAA,EAChD;AACA,SAAO;AACT;AAEA,SAAS,qBAAqB,MAAkC;AAC9D,QAAM,EAAE,GAAG,QAAQ,IAAI;AAEvB,SAAQ,QAAoC,OAAO;AACnD,SAAQ,QAAoC,UAAU;AAEtD,MAAI,QAAQ,WAAW;AACrB,YAAQ,YAAY,QAAQ,UAAU,IAAI,CAAC,OAAO;AAChD,YAAM,EAAE,OAAO,IAAI,UAAU,IAAI,GAAG,QAAQ,IAAI;AAEhD,UAAI,QAAQ,iBAAiB;AAC3B,gBAAQ,kBAAkB,QAAQ,gBAAgB,IAAI,CAAC,QAAQ;AAAA,UAC7D,GAAG;AAAA,UACH,OAAO,iBAAiB,GAAG,KAAK;AAAA,QAClC,EAAE;AAAA,MACJ;AACA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAEA,SAAS,cAAc,MAA4C;AACjE,QAAM,EAAE,OAAO,IAAI,GAAG,QAAQ,IAAI;AAClC,SAAQ,QAAoC,UAAU;AACtD,SAAO;AACT;AAIA,SAAS,cAAc,KAAqB;AAC1C,QAAM,QAAQ,IAAI,MAAM,WAAW;AACnC,SAAO,QAAQ,CAAC,IAAI,SAAS,MAAM,CAAC,GAAG,EAAE,IAAI;AAC/C;AAEA,IAAM,wBAAwB;AAC9B,IAAM,wBAAwB;AAAA,EAC5B;AAAA,EACA;AACF;AAEA,SAAS,qBAAqB,MAA0B;AACtD,MAAI,CAAC,KAAK,UAAW;AACrB,aAAW,MAAM,KAAK,WAAW;AAC/B,UAAM,OAAO,GAAG,0BAA0B;AAC1C,QAAI,QAAQ,CAAC,KAAK,WAAW,qBAAqB,GAAG;AACnD,SAAG,yBAA0B,gBAAgB,GAAG,qBAAqB,GAAG,IAAI;AAAA,IAC9E;AACA,QAAI,GAAG,0BAA0B,eAAe;AAC9C,YAAM,WAAW,GAAG,yBAAyB;AAC7C,UAAI,CAAC,sBAAsB,SAAS,QAAQ,GAAG;AAC7C,cAAM,IAAI;AAAA,UACR,2BAA2B,QAAQ;AAAA,UACnC;AAAA,UACA;AAAA,UACA,iBAAiB,sBAAsB,KAAK,IAAI,CAAC;AAAA,QACnD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,yBAAyB,MAA0B;AAE1D,uBAAqB,IAAI;AAGzB,MAAI,KAAK,UAAU;AACjB,eAAW,CAAC,MAAM,OAAO,KAAK,OAAO,QAAQ,KAAK,QAAQ,GAAG;AAC3D,UAAI,QAAQ,YAAY,QAAQ,SAAS,SAAS,GAAG;AACnD,cAAM,IAAI;AAAA,UACR,YAAY,IAAI,SAAS,QAAQ,SAAS,MAAM;AAAA,UAChD;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA,UAAI,QAAQ,eAAe,QAAQ,YAAY,SAAS,IAAI;AAC1D,cAAM,IAAI;AAAA,UACR,YAAY,IAAI,oBAAoB,QAAQ,YAAY,MAAM;AAAA,UAC9D;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,MAAI,KAAK,WAAW;AAClB,eAAW,MAAM,KAAK,WAAW;AAC/B,YAAM,WAAW,GAAG;AACpB,UAAI,UAAU,uBAAuB,UAAU,qBAAqB;AAClE,cAAM,QAAQ,cAAc,SAAS,mBAAmB;AACxD,cAAM,OAAO,cAAc,SAAS,mBAAmB;AACvD,cAAM,MAAM,QAAQ;AACpB,YAAI,MAAM,MAAM,MAAM,IAAI;AACxB,gBAAM,IAAI;AAAA,YACR,cAAc,GAAG,UAAU,2BAA2B,KAAK,6BAA6B,IAAI,QAAQ,GAAG;AAAA,YACvG;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,kBACpB,QACA,aACA,SACoE;AACpE,sBAAoB,WAAW;AAC/B,MAAI,SAAS,SAAS,SAAS,UAAU;AACvC,UAAM,SAAS,MAAMC;AAAA,MACnB,OAAO,cAAc;AACnB,cAAM,OAAO,MAAM,OAAO,cAAc,KAAK,aAAa;AAAA,UACxD;AAAA,UACA,UAAU,SAAS;AAAA,QACrB,CAAC;AACD,eAAO,EAAE,OAAO,KAAK,iBAAiB,CAAC,GAAG,eAAe,KAAK,cAAc;AAAA,MAC9E;AAAA,MACA,EAAE,OAAO,QAAQ,OAAO,gBAAgB,QAAQ,SAAS;AAAA,IAC3D;AACA,WAAO,EAAE,eAAe,OAAO,OAAO,eAAe,OAAO,cAAc;AAAA,EAC5E;AACA,SAAO,OAAO,cAAc,KAAK,aAAa;AAAA,IAC5C,WAAW,SAAS;AAAA,IACpB,UAAU,SAAS;AAAA,EACrB,CAAC;AACH;AAEA,eAAsB,gBACpB,QACA,aACA,WACuB;AACvB,sBAAoB,WAAW;AAC/B,cAAY,SAAS;AACrB,SAAO,OAAO,cAAc,IAAI,aAAa,SAAS;AACxD;AAEA,eAAsB,mBACpB,QACA,aACA,MACuB;AACvB,sBAAoB,WAAW;AAC/B,2BAAyB,IAAI;AAC7B,QAAM,YAAY,qBAAqB,IAAI;AAC3C,SAAO,OAAO,cAAc,OAAO,aAAa,WAAW,KAAK,SAAS;AAC3E;AAEA,IAAM,yBAAyB,oBAAI,IAAI,CAAC,aAAa,aAAa,CAAC;AAEnE,SAAS,6BAA6B,MAA4B;AAChE,SAAO,OAAO,KAAK,IAAI,EACpB,OAAO,CAAC,MAAM,CAAC,uBAAuB,IAAI,CAAC,CAAC,EAC5C,KAAK,GAAG;AACb;AAEA,eAAsB,mBACpB,QACA,aACA,WACA,MACA,YACuB;AACvB,sBAAoB,WAAW;AAC/B,cAAY,SAAS;AACrB,2BAAyB,IAAI;AAC7B,QAAM,YAAY,qBAAqB,IAAI;AAC3C,QAAM,OAAO,cAAc,6BAA6B,IAAI;AAC5D,SAAO,OAAO,cAAc,OAAO,aAAa,WAAW,WAAW,IAAI;AAC5E;AAEA,eAAsB,mBACpB,QACA,aACA,WACe;AACf,sBAAoB,WAAW;AAC/B,cAAY,SAAS;AACrB,SAAO,OAAO,cAAc,OAAO,aAAa,SAAS;AAC3D;AAEA,eAAsB,iBACpB,QACA,aACA,WACA,YACuB;AACvB,sBAAoB,WAAW;AAC/B,cAAY,SAAS;AACrB,SAAO,OAAO,cAAc,iBAAiB,aAAa,WAAW,UAAU;AACjF;AAEA,eAAsB,mBACpB,QACA,aACA,WACA,YACuB;AACvB,sBAAoB,WAAW;AAC/B,cAAY,SAAS;AACrB,SAAO,OAAO,cAAc,mBAAmB,aAAa,WAAW,UAAU;AACnF;AAEA,eAAsB,eACpB,QACA,aACA,WACA,YACe;AACf,sBAAoB,WAAW;AAC/B,cAAY,SAAS;AACrB,SAAO,OAAO,cAAc,eAAe,aAAa,WAAW,UAAU;AAC/E;AAEA,eAAsB,cACpB,QACA,aACA,WACA,YACA,MACuB;AACvB,sBAAoB,WAAW;AAC/B,cAAY,SAAS;AACrB,SAAO,OAAO,cAAc,cAAc,aAAa,WAAW,YAAY,IAAI;AACpF;AAEA,eAAsB,WACpB,QACA,aACA,WACA,YAC6B;AAC7B,sBAAoB,WAAW;AAC/B,cAAY,SAAS;AACrB,SAAO,OAAO,cAAc,WAAW,aAAa,WAAW,UAAU;AAC3E;AAEA,eAAsB,SACpB,QACA,aACA,WACA,YACA,SAC4B;AAC5B,sBAAoB,WAAW;AAC/B,cAAY,SAAS;AACrB,SAAO,OAAO,cAAc,SAAS,aAAa,WAAW,YAAY,OAAO;AAClF;AAEA,eAAsB,YACpB,QACA,aACA,WACA,YACA,MAC4B;AAC5B,sBAAoB,WAAW;AAC/B,cAAY,SAAS;AACrB,QAAM,YAAY,cAAc,IAAI;AACpC,SAAO,OAAO,cAAc,YAAY,aAAa,WAAW,YAAY,WAAW,KAAK,OAAO;AACrG;AAEA,IAAM,kBAAkB,oBAAI,IAAI,CAAC,aAAa,cAAc,SAAS,CAAC;AAEtE,SAAS,sBAAsB,MAAiC;AAC9D,SAAO,OAAO,KAAK,IAAI,EACpB,OAAO,CAAC,MAAM,CAAC,gBAAgB,IAAI,CAAC,CAAC,EACrC,KAAK,GAAG;AACb;AAEA,eAAsB,YACpB,QACA,aACA,WACA,YACA,SACA,MACA,YAC4B;AAC5B,sBAAoB,WAAW;AAC/B,cAAY,SAAS;AACrB,QAAM,YAAY,cAAc,IAAI;AACpC,QAAM,OAAO,cAAc,sBAAsB,IAAI;AACrD,SAAO,OAAO,cAAc;AAAA,IAC1B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAsB,YACpB,QACA,aACA,WACA,YACA,SACe;AACf,sBAAoB,WAAW;AAC/B,cAAY,SAAS;AACrB,SAAO,OAAO,cAAc,YAAY,aAAa,WAAW,YAAY,OAAO;AACrF;AAEA,eAAsB,cACpB,QACA,aACA,WACA,YACA,SAC4B;AAC5B,sBAAoB,WAAW;AAC/B,cAAY,SAAS;AACrB,SAAO,OAAO,cAAc,cAAc,aAAa,WAAW,YAAY,OAAO;AACvF;AAQA,eAAsB,iBACpB,QACA,aACA,WACA,WAC6B;AAC7B,sBAAoB,WAAW;AAC/B,cAAY,SAAS;AACrB,QAAM,SAAS,MAAM,OAAO,cAAc,IAAI,aAAa,SAAS;AACpE,QAAM,QAA4B,CAAC;AACnC,QAAM,kBAAkB,CAAC,YAAY,aAAa,0BAA0B;AAE5E,aAAW,SAAS,iBAAiB;AACnC,UAAM,WAAW,KAAK,UAAW,UAAiD,KAAK,KAAK,IAAI;AAChG,UAAM,YAAY,KAAK,UAAW,OAA8C,KAAK,KAAK,IAAI;AAC9F,QAAI,aAAa,WAAW;AAC1B,YAAM,KAAK,EAAE,OAAO,OAAO,UAAU,QAAQ,UAAU,CAAC;AAAA,IAC1D;AAAA,EACF;AACA,SAAO;AACT;AAEA,eAAsB,gBACpB,QACA,aACA,WACA,YACA,SAC4B;AAC5B,sBAAoB,WAAW;AAC/B,cAAY,SAAS;AACrB,SAAO,OAAO,cAAc,gBAAgB,aAAa,WAAW,YAAY,OAAO;AACzF;;;ACtYA,SAAS,WAAAC,UAAS,YAAAC,iBAAgB;AAClC,SAAS,QAAAC,aAAY;AAErB,SAAS,eAAAC,oBAAmB;AAU5B,eAAsB,kBACpB,QACA,aACA,SACmE;AACnE,MAAI,SAAS,SAAS,SAAS,UAAU;AACvC,UAAM,SAAS,MAAMC;AAAA,MACnB,OAAO,cAAc;AACnB,cAAM,OAAO,MAAM,OAAO,cAAc,KAAK,aAAa;AAAA,UACxD,OAAO;AAAA,UACP,YAAY,SAAS;AAAA,QACvB,CAAC;AACD,eAAO;AAAA,UACL,OAAO,KAAK,gBAAgB,CAAC;AAAA,UAC7B,eAAe,KAAK,iBAAiB;AAAA,QACvC;AAAA,MACF;AAAA,MACA,EAAE,OAAO,QAAQ,OAAO,gBAAgB,QAAQ,SAAS;AAAA,IAC3D;AACA,WAAO,EAAE,cAAc,OAAO,OAAO,eAAe,OAAO,cAAc;AAAA,EAC3E;AACA,SAAO,OAAO,cAAc,KAAK,aAAa;AAAA,IAC5C,OAAO,SAAS;AAAA,IAChB,YAAY,SAAS;AAAA,EACvB,CAAC;AACH;AAEA,eAAsB,gBACpB,QACA,aACA,KACuB;AACvB,SAAO,OAAO,cAAc,IAAI,aAAa,GAAG;AAClD;AAEA,eAAsB,mBACpB,QACA,aACA,MACuB;AACvB,SAAO,OAAO,cAAc,OAAO,aAAa,IAAI;AACtD;AAEA,eAAsB,mBACpB,QACA,aACA,KACA,MACuB;AACvB,SAAO,OAAO,cAAc,OAAO,aAAa,KAAK,IAAI;AAC3D;AAEA,eAAsB,mBACpB,QACA,aACA,KACe;AACf,SAAO,OAAO,cAAc,OAAO,aAAa,GAAG;AACrD;AASA,eAAsB,kBACpB,QACA,aACA,KACA,SACqB;AACrB,QAAM,gBAAgB,MAAM,oBAAoB,GAAG;AAEnD,MAAI,cAAc,WAAW,GAAG;AAC9B,WAAO,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,MAAM,CAAC,EAAE;AAAA,EAC1D;AAEA,QAAM,WAAW,MAAM,OAAO,cAAc,KAAK,WAAW;AAC5D,QAAM,aAAa,IAAI,KAAK,SAAS,gBAAgB,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC;AAE1E,QAAM,WAAW,cAAc,OAAO,CAAC,MAAM,WAAW,IAAI,EAAE,GAAG,CAAC;AAClE,QAAM,WAAW,cAAc,OAAO,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,GAAG,CAAC;AACnE,QAAM,OAAO,cAAc,IAAI,CAAC,MAAM,EAAE,GAAG;AAE3C,MAAI,SAAS,QAAQ;AACnB,WAAO,EAAE,SAAS,SAAS,QAAQ,SAAS,SAAS,QAAQ,WAAW,GAAG,KAAK;AAAA,EAClF;AAGA,MAAI,SAAS,SAAS,GAAG;AACvB,QAAI;AACF,YAAM,oBAAoB,QAAQ,aAAa,QAAQ;AAAA,IACzD,QAAQ;AAEN,iBAAW,WAAW,UAAU;AAC9B,cAAM,OAAO,cAAc,OAAO,aAAa,QAAQ,KAAK,OAAO;AAAA,MACrE;AAAA,IACF;AAAA,EACF,OAAO;AACL,eAAW,WAAW,UAAU;AAC9B,YAAM,OAAO,cAAc,OAAO,aAAa,QAAQ,KAAK,OAAO;AAAA,IACrE;AAAA,EACF;AAEA,aAAW,WAAW,UAAU;AAC9B,UAAM,OAAO,cAAc,OAAO,aAAa,OAAO;AAAA,EACxD;AAEA,SAAO,EAAE,SAAS,SAAS,QAAQ,SAAS,SAAS,QAAQ,WAAW,GAAG,KAAK;AAClF;AAEA,IAAM,mBAAmB;AAEzB,eAAe,oBACb,QACA,aACA,UACyB;AACzB,QAAM,UAA0B,CAAC;AACjC,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK,kBAAkB;AAC1D,UAAM,QAAQ,SAAS,MAAM,GAAG,IAAI,gBAAgB;AACpD,UAAM,UAA2C;AAAA,MAC/C,UAAU,MAAM,IAAI,CAAC,OAAO;AAAA,QAC1B,cAAc;AAAA,QACd;AAAA,QACA,KAAK,EAAE;AAAA,MACT,EAAE;AAAA,IACJ;AACA,UAAM,WAAW,MAAM,OAAO,cAAc,YAAY,aAAa,OAAO;AAC5E,YAAQ,KAAK,GAAI,SAAS,iBAAiB,CAAC,CAAE;AAAA,EAChD;AACA,SAAO;AACT;AAEA,eAAe,oBAAoB,KAAsC;AACvE,QAAM,QAAQ,MAAMC,SAAQ,GAAG;AAC/B,QAAM,YAAY,MAAM,OAAO,CAAC,MAAM,EAAE,SAAS,OAAO,CAAC;AACzD,QAAM,gBAAgC,CAAC;AACvC,aAAW,QAAQ,WAAW;AAC5B,UAAM,UAAU,MAAMC,UAASC,MAAK,KAAK,IAAI,GAAG,OAAO;AACvD,QAAI;AACF,oBAAc,KAAK,KAAK,MAAM,OAAO,CAAiB;AAAA,IACxD,QAAQ;AACN,YAAM,IAAI;AAAA,QACR,mBAAmB,IAAI;AAAA,QACvB;AAAA,QACA;AAAA,QACA,eAAe,IAAI,yDAAyD,IAAI;AAAA,MAClF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAOA,eAAsB,uBACpB,QACA,aACA,KACA,SAC0B;AAC1B,QAAM,gBAAgB,MAAM,oBAAoB,GAAG;AAEnD,MAAI,cAAc,WAAW,GAAG;AAC9B,WAAO,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,MAAM,CAAC,GAAG,WAAW,OAAO,aAAa,EAAE;AAAA,EAC5F;AAEA,QAAM,WAAW,MAAM,OAAO,cAAc,KAAK,WAAW;AAC5D,QAAM,aAAa,IAAI,KAAK,SAAS,gBAAgB,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC;AAE1E,QAAM,WAAW,cAAc,OAAO,CAAC,MAAM,WAAW,IAAI,EAAE,GAAG,CAAC;AAClE,QAAM,WAAW,cAAc,OAAO,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,GAAG,CAAC;AACnE,QAAM,OAAO,cAAc,IAAI,CAAC,MAAM,EAAE,GAAG;AAE3C,MAAI,SAAS,QAAQ;AACnB,WAAO;AAAA,MACL,SAAS,SAAS;AAAA,MAClB,SAAS,SAAS;AAAA,MAClB,WAAW;AAAA,MACX;AAAA,MACA,WAAW,SAAS,SAAS;AAAA,MAC7B,aAAa;AAAA,IACf;AAAA,EACF;AAEA,MAAI,YAAY;AAChB,MAAI,cAAc;AAElB,MAAI,SAAS,SAAS,GAAG;AACvB,gBAAY;AACZ,QAAI;AACF,YAAM,oBAAoB,QAAQ,aAAa,QAAQ;AAAA,IACzD,QAAQ;AACN;AAEA,iBAAW,WAAW,UAAU;AAC9B,cAAM,OAAO,cAAc,OAAO,aAAa,QAAQ,KAAK,OAAO;AAAA,MACrE;AAAA,IACF;AAAA,EACF,OAAO;AACL,eAAW,WAAW,UAAU;AAC9B,YAAM,OAAO,cAAc,OAAO,aAAa,QAAQ,KAAK,OAAO;AAAA,IACrE;AAAA,EACF;AAEA,aAAW,WAAW,UAAU;AAC9B,UAAM,OAAO,cAAc,OAAO,aAAa,OAAO;AAAA,EACxD;AAEA,SAAO;AAAA,IACL,SAAS,SAAS;AAAA,IAClB,SAAS,SAAS;AAAA,IAClB,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACtJA,SAAS,eAAAC,oBAAmB;AA9E5B,eAAsB,mBACpB,QACA,aACA,WACA,OAC0B;AAC1B,sBAAoB,WAAW;AAC/B,SAAO,OAAO,UAAU,WAAW,aAAa,WAAW,KAAK;AAClE;AAEA,eAAsB,2BACpB,QACA,aACA,WACA,OACA,SACe;AACf,sBAAoB,WAAW;AAC/B,QAAM,OAAO,UAAU,EAAE,kBAAkB,QAAQ,IAAI;AACvD,SAAO,OAAO,UAAU,mBAAmB,aAAa,WAAW,OAAO,IAAI;AAChF;AAEA,eAAsB,uBACpB,QACA,aACA,WACA,OACe;AACf,sBAAoB,WAAW;AAC/B,SAAO,OAAO,UAAU,eAAe,aAAa,WAAW,KAAK;AACtE;AAEA,eAAsB,wBACpB,QACA,aACA,OACiC;AACjC,sBAAoB,WAAW;AAC/B,SAAO,OAAO,UAAU,kBAAkB,aAAa,KAAK;AAC9D;AAEA,eAAsB,2BACpB,QACA,aACA,gBACA,OACe;AACf,sBAAoB,WAAW;AAC/B,SAAO,OAAO,UAAU,mBAAmB,aAAa,gBAAgB,KAAK;AAC/E;AAEA,eAAsB,0BACpB,QACA,aACA,gBACA,OACA,eACoC;AACpC,sBAAoB,WAAW;AAC/B,QAAM,MAAM,MAAM,OAAO,UAAU,kBAAkB,aAAa,gBAAgB,KAAK;AACvF,SAAO,OAAO,UAAU,kBAAkB,aAAa,gBAAgB,OAAO;AAAA,IAC5E,cAAc;AAAA,MACZ,0BAA0B,IAAI;AAAA,MAC9B,yBAAyB,OAAO,IAAI,KAAK,aAAa,EAAE,QAAQ,CAAC;AAAA,IACnE;AAAA,EACF,CAAC;AACH;AAEA,eAAsB,2BACpB,QACA,aACA,OACe;AACf,sBAAoB,WAAW;AAC/B,SAAO,OAAO,UAAU,qBAAqB,aAAa,KAAK;AACjE;AAaA,eAAsB,oBACpB,QACA,aACA,SACwE;AACxE,sBAAoB,WAAW;AAC/B,MAAI,SAAS,SAAS,SAAS,UAAU;AACvC,UAAM,SAAS,MAAMA;AAAA,MACnB,OAAO,cAAc;AACnB,cAAM,OAAO,MAAM,OAAO,UAAU,WAAW,aAAa;AAAA,UAC1D,WAAW,SAAS;AAAA,UACpB,SAAS,SAAS;AAAA,UAClB,YAAY,SAAS;AAAA,UACrB,OAAO;AAAA,QACT,CAAC;AACD,eAAO;AAAA,UACL,OAAO,KAAK,mBAAmB,CAAC;AAAA,UAChC,eAAe,KAAK,iBAAiB;AAAA,QACvC;AAAA,MACF;AAAA,MACA,EAAE,OAAO,QAAQ,OAAO,gBAAgB,QAAQ,SAAS;AAAA,IAC3D;AACA,WAAO,EAAE,iBAAiB,OAAO,OAAO,eAAe,OAAO,cAAc;AAAA,EAC9E;AACA,SAAO,OAAO,UAAU,WAAW,aAAa,OAAO;AACzD;AAEA,eAAsB,YACpB,QACA,aACA,SACA,SACe;AACf,sBAAoB,WAAW;AAC/B,SAAO,OAAO,OAAO,OAAO,aAAa,SAAS,OAAO;AAC3D;;;ACjIA,eAAsB,oBACpB,QACA,aACA,cACA,QACsC;AACtC,QAAM,QAAQ,OAAO,MAAM,GAAG,EAAE,CAAC,KAAK;AACtC,QAAM,aAAa,OAAO,MAAM,GAAG,EAAE,CAAC,KAAK;AAC3C,QAAM,QAAQ,OAAO,WAAW,OAAO,GAAG,GAAG,EAAE,MAAM,GAAG,CAAC,CAAC;AAE1D,SAAO,OAAO,aAAa,oBAAoB,aAAa;AAAA,IAC1D,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF,CAAC;AACH;;;AChBA,IAAM,yBAA8C,oBAAI,IAAI;AAAA,EAC1D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAM,qBAA0C,oBAAI,IAAI;AAAA,EACtD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAM,mBAAwC,oBAAI,IAAI;AAAA,EACpD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,SAAS,sBAAsB,MAAuB;AAC3D,SAAO,uBAAuB,IAAI,IAAI;AACxC;AAEO,SAAS,kBAAkB,MAAuB;AACvD,SAAO,mBAAmB,IAAI,IAAI;AACpC;AAEO,SAAS,kBAAkB,MAAkC;AAClE,SAAO,uBAAuB,IAAI,IAAI,KAAK,mBAAmB,IAAI,IAAI;AACxE;AAEO,SAAS,sBAAsB,KAAoC;AACxE,SAAO,iBAAiB,IAAI,GAAG;AACjC;AAOO,SAAS,WAAW,UAA+B;AACxD,QAAM,QAAQ,oBAAoB,KAAK,QAAQ;AAC/C,MAAI,CAAC,OAAO;AACV,UAAM,IAAI;AAAA,MACR,yBAAyB,QAAQ;AAAA,MACjC;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,QAAM,OAAO,OAAO,MAAM,CAAC,CAAC;AAC5B,QAAM,QAAQ,OAAO,MAAM,CAAC,CAAC;AAC7B,MAAI,QAAQ,KAAK,QAAQ,IAAI;AAC3B,UAAM,IAAI;AAAA,MACR,kBAAkB,KAAK;AAAA,MACvB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,SAAO,EAAE,MAAM,MAAM;AACvB;AAEA,eAAsB,YACpB,SACA,cACA,YACA,OACA,QACyB;AACzB,QAAM,IAAI;AAAA,IACR,uBAAuB,UAAU;AAAA,IACjC;AAAA,IACA;AAAA,IACA,sBAAsB,UAAU,IAC5B,sIACA;AAAA,EACN;AACF;AAEA,eAAsB,eACpB,SACA,cACA,YACA,OACA,QACiB;AACjB,QAAM,IAAI;AAAA,IACR,wBAAwB,UAAU;AAAA,IAClC;AAAA,IACA;AAAA,IACA,sBAAsB,UAAU,IAC5B,sIACA;AAAA,EACN;AACF;;;ACxGA,SAAS,eAAAC,oBAAmB;AAGrB,IAAM,iCACX;AASF,eAAsB,UACpB,QACA,aACA,SACoD;AACpD,MAAI,SAAS,SAAS,SAAS,UAAU;AACvC,UAAM,SAAS,MAAMC;AAAA,MACnB,OAAO,cAAc;AACnB,cAAM,OAAO,MAAM,OAAO,KAAK,aAAa,EAAE,WAAW,UAAU,SAAS,SAAS,CAAC;AACtF,eAAO,EAAE,OAAO,KAAK,SAAS,CAAC,GAAG,eAAe,KAAK,cAAc;AAAA,MACtE;AAAA,MACA,EAAE,OAAO,QAAQ,OAAO,gBAAgB,QAAQ,SAAS;AAAA,IAC3D;AACA,WAAO,EAAE,OAAO,OAAO,OAAO,eAAe,OAAO,cAAc;AAAA,EACpE;AACA,QAAM,WAAW,MAAM,OAAO,KAAK,aAAa,OAAO;AACvD,SAAO,EAAE,OAAO,SAAS,SAAS,CAAC,GAAG,eAAe,SAAS,cAAc;AAC9E;AAEA,eAAsB,QACpB,QACA,aACA,QACe;AACf,SAAO,OAAO,IAAI,aAAa,MAAM;AACvC;AAEA,eAAsB,WACpB,QACA,aACA,OACA,aACA,QACe;AACf,QAAM,OAAsB,EAAE,MAAM;AACpC,MAAI,YAAa,MAAK,6BAA6B;AACnD,MAAI,OAAQ,MAAK,SAAS;AAC1B,SAAO,OAAO,OAAO,aAAa,IAAI;AACxC;AAEA,eAAsB,WACpB,QACA,aACA,QACA,aACA,QACe;AACf,QAAM,UAAyB,CAAC;AAChC,QAAM,QAAkB,CAAC;AAEzB,MAAI,aAAa;AACf,YAAQ,6BAA6B;AACrC,UAAM,KAAK,4BAA4B;AAAA,EACzC;AACA,MAAI,QAAQ;AACV,YAAQ,SAAS;AACjB,UAAM,KAAK,QAAQ;AAAA,EACrB;AAEA,QAAM,aAAa,MAAM,SAAS,IAAI,MAAM,KAAK,GAAG,IAAI;AACxD,SAAO,OAAO,OAAO,aAAa,QAAQ,SAAS,UAAU;AAC/D;AAEA,eAAsB,WACpB,QACA,aACA,QACe;AACf,SAAO,OAAO,OAAO,aAAa,MAAM;AAC1C;AAEO,SAAS,cAAc,UAAyB;AACrD,QAAM,WAAW,SAAS,QAAQ,GAAG;AACrC,MAAI,aAAa,IAAI;AACnB,UAAM,IAAI;AAAA,MACR,yBAAyB,QAAQ;AAAA,MACjC;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,QAAM,cAAc,SAAS,MAAM,GAAG,QAAQ;AAC9C,QAAM,QAAQ,SAAS,MAAM,WAAW,CAAC,EAAE,MAAM,GAAG;AACpD,SAAO,EAAE,aAAa,qBAAqB,MAAM;AACnD;;;ACjGA,SAAS,YAAAC,iBAAgB;AAGzB,eAAsB,YACpB,QACA,aACA,OACkB;AAClB,QAAM,OAAO,MAAM,OAAO,MAAM,OAAO,WAAW;AAClD,MAAI;AACF,UAAM,UAAU,MAAM,OAAO,QAAQ,IAAI,aAAa,KAAK,IAAI,KAAK;AACpE,WAAO;AAAA,EACT,UAAE;AACA,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE;AAAA,EAChD;AACF;AAEA,eAAsB,WACpB,QACA,aACA,OACA,aACkB;AAClB,QAAM,OAAO,MAAM,OAAO,MAAM,OAAO,WAAW;AAClD,MAAI;AACF,UAAM,UAAU,MAAM,OAAO,QAAQ,IAAI,aAAa,KAAK,IAAI,KAAK;AACpE,UAAM,WAAW,IAAI,IAAI,QAAQ,gBAAgB,CAAC,CAAC;AACnD,eAAW,SAAS,aAAa;AAC/B,eAAS,IAAI,MAAM,KAAK,CAAC;AAAA,IAC3B;AACA,UAAM,UAAU,MAAM,OAAO,QAAQ,OAAO,aAAa,KAAK,IAAI,OAAO;AAAA,MACvE,cAAc,CAAC,GAAG,QAAQ;AAAA,IAC5B,CAAC;AACD,UAAM,OAAO,MAAM,SAAS,aAAa,KAAK,EAAE;AAChD,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE;AAC9C,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9D,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,cACpB,QACA,aACA,OACA,aACkB;AAClB,QAAM,OAAO,MAAM,OAAO,MAAM,OAAO,WAAW;AAClD,MAAI;AACF,UAAM,UAAU,MAAM,OAAO,QAAQ,IAAI,aAAa,KAAK,IAAI,KAAK;AACpE,UAAM,WAAW,IAAI,IAAI,YAAY,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AACzD,UAAM,YAAY,QAAQ,gBAAgB,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,CAAC;AAC5E,UAAM,UAAU,MAAM,OAAO,QAAQ,OAAO,aAAa,KAAK,IAAI,OAAO;AAAA,MACvE,cAAc;AAAA,IAChB,CAAC;AACD,UAAM,OAAO,MAAM,SAAS,aAAa,KAAK,EAAE;AAChD,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE;AAC9C,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,OAAO,MAAM,OAAO,aAAa,KAAK,EAAE,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9D,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,qBACpB,QACA,aACA,OACA,SAC8C;AAC9C,QAAM,UAAU,MAAMC,UAAS,SAAS,OAAO;AAC/C,QAAM,SAAS,QACZ,MAAM,UAAU,EAChB,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,SAAS,GAAG,CAAC;AAEhD,MAAI,OAAO,WAAW,GAAG;AACvB,UAAM,IAAI;AAAA,MACR,qCAAqC,OAAO;AAAA,MAC5C;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAAU,MAAM,WAAW,QAAQ,aAAa,OAAO,MAAM;AACnE,SAAO,EAAE,OAAO,OAAO,QAAQ,QAAQ;AACzC;;;ACzFA,SAAS,YAAY,kBAAkB;AACvC,SAAS,iBAAiB;AAG1B,IAAM,WAAW,UAAU,UAAU;AAqBrC,IAAM,sBAA8C;AAAA,EAClD,MAAM;AAAA,EACN,KAAK;AAAA,EACL,MAAM;AACR;AAEA,IAAM,qBAAqB;AAE3B,SAAS,wBAAwB,SAA+B;AAC9D,QAAM,QAAQ,QAAQ,MAAM,+BAA+B;AAC3D,MAAI,OAAO;AACT,WAAO,EAAE,MAAM,MAAM,CAAC,GAAI,SAAS,MAAM,CAAC,EAAG,KAAK,EAAE;AAAA,EACtD;AACA,SAAO,EAAE,MAAM,SAAS,SAAS,QAAQ,KAAK,EAAE;AAClD;AAEA,SAAS,YAAY,SAAyB,WAAyD;AACrG,QAAM,SAAS,oBAAI,IAAsB;AAEzC,aAAW,UAAU,SAAS;AAC5B,UAAM,SAAS,oBAAoB,OAAO,IAAI,KAAK;AACnD,QAAI,CAAC,OAAO,IAAI,MAAM,GAAG;AACvB,aAAO,IAAI,QAAQ,CAAC,CAAC;AAAA,IACvB;AACA,WAAO,IAAI,MAAM,EAAG,KAAK,OAAO,OAAO;AAAA,EACzC;AAGA,QAAM,QAAQ,CAAC,OAAO,SAAS,YAAY,SAAS;AACpD,QAAM,WAAqB,CAAC;AAE5B,aAAW,UAAU,OAAO;AAC1B,UAAM,QAAQ,OAAO,IAAI,MAAM;AAC/B,QAAI,CAAC,SAAS,MAAM,WAAW,EAAG;AAClC,UAAM,UAAU,MAAM,IAAI,CAAC,MAAM,UAAU,CAAC,EAAE,EAAE,KAAK,IAAI;AACzD,aAAS,KAAK,GAAG,MAAM;AAAA,EAAM,OAAO,EAAE;AAAA,EACxC;AAEA,MAAI,OAAO,SAAS,KAAK,MAAM;AAC/B,MAAI,YAAY;AAEhB,MAAI,KAAK,SAAS,WAAW;AAC3B,WAAO,KAAK,MAAM,GAAG,YAAY,CAAC,IAAI;AACtC,gBAAY;AAAA,EACd;AAEA,SAAO,EAAE,MAAM,UAAU;AAC3B;AAEA,eAAe,QAAQ,MAAiC;AACtD,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAM,SAAS,OAAO,IAAI;AAC7C,WAAO,OAAO,KAAK;AAAA,EACrB,SAAS,OAAgB;AACvB,UAAM,MAAM;AACZ,QAAI,IAAI,SAAS,UAAU;AACzB,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,qBACpB,SAC0B;AAC1B,QAAM,WAAW,SAAS,YAAY;AACtC,QAAM,YAAY,SAAS,aAAa;AACxC,MAAI,QAAQ,SAAS;AAErB,MAAI,CAAC,OAAO;AACV,QAAI;AACF,cAAQ,MAAM,QAAQ,CAAC,YAAY,UAAU,YAAY,CAAC;AAAA,IAC5D,SAAS,GAAG;AACV,UAAI,aAAa,YAAY,EAAE,SAAS,gBAAiB,OAAM;AAC/D,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MAAI;AACJ,MAAI;AACF,gBAAY,MAAM,QAAQ,CAAC,OAAO,GAAG,KAAK,UAAU,aAAa,CAAC;AAAA,EACpE,SAAS,OAAgB;AACvB,UAAM,MAAM;AACZ,UAAM,MAAM,IAAI,UAAU,IAAI,WAAW,OAAO,KAAK;AACrD,UAAM,IAAI;AAAA,MACR,gCAAgC,KAAK,MAAM,GAAG;AAAA,MAC9C;AAAA,MACA;AAAA,MACA,gBAAgB,KAAK;AAAA,IACvB;AAAA,EACF;AAEA,MAAI,CAAC,WAAW;AACd,WAAO;AAAA,MACL;AAAA,MACA,MAAM;AAAA,MACN,aAAa;AAAA,MACb;AAAA,MACA,WAAW;AAAA,IACb;AAAA,EACF;AAEA,QAAM,WAAW,UAAU,MAAM,IAAI,EAAE,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC;AACvE,QAAM,UAAU,SAAS,IAAI,uBAAuB;AACpD,QAAM,EAAE,MAAM,UAAU,IAAI,YAAY,SAAS,SAAS;AAE1D,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,aAAa,SAAS;AAAA,IACtB;AAAA,IACA;AAAA,EACF;AACF;;;AC7IA,eAAsB,oBACpB,QACA,aACA,aAC8B;AAC9B,SAAO,OAAO,YAAY,KAAK,aAAa,WAAW;AACzD;AAEA,eAAsB,qBACpB,QACA,aACA,YACe;AACf,SAAO,OAAO,YAAY,OAAO,aAAa,UAAU;AAC1D;AAEA,eAAsB,qBACpB,QACA,aACA,YACe;AACf,SAAO,OAAO,YAAY,OAAO,aAAa,UAAU;AAC1D;AAEA,eAAsB,qBACpB,QACA,aACA,SAC4B;AAC5B,SAAO,OAAO,YAAY,OAAO,aAAa,OAAO;AACvD;AAEA,eAAsB,qBACpB,QACA,aACA,UACA,WAC4B;AAC5B,SAAO,OAAO,YAAY,aAAa,aAAa,UAAU,SAAS;AACzE;;;AC7CA,SAAS,YAAAC,WAAU,aAAAC,kBAAiB;AAGpC,eAAsB,cACpB,QACA,aACqB;AACrB,SAAO,OAAO,WAAW,IAAI,WAAW;AAC1C;AAEA,eAAsB,iBACpB,QACA,aACA,MACqB;AACrB,SAAO,OAAO,WAAW,OAAO,aAAa,IAAI;AACnD;AAEA,eAAsB,iBACpB,QACA,aACA,YACqB;AACrB,QAAM,aAAa,MAAM,cAAc,QAAQ,WAAW;AAC1D,QAAMC,WAAU,YAAY,KAAK,UAAU,YAAY,MAAM,CAAC,IAAI,MAAM,OAAO;AAC/E,SAAO;AACT;AAEA,eAAsB,iBACpB,QACA,aACA,UACqB;AACrB,QAAM,UAAU,MAAMC,UAAS,UAAU,OAAO;AAChD,MAAI;AACJ,MAAI;AACF,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,UAAM,IAAI;AAAA,MACR,0CAA0C,QAAQ;AAAA,MAClD;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,SAAO,iBAAiB,QAAQ,aAAa,IAAI;AACnD;;;ACzCA,eAAsB,0BACpB,QACA,aACA,MAC8B;AAC9B,SAAO,OAAO,qBAAqB,OAAO,aAAa,IAAI;AAC7D;AAEA,eAAsB,uBACpB,QACA,aACA,eAC8B;AAC9B,SAAO,OAAO,qBAAqB,IAAI,aAAa,aAAa;AACnE;AAEA,eAAsB,0BACpB,QACA,aACA,eACA,YAC8B;AAC9B,SAAO,OAAO,qBAAqB,OAAO,aAAa,eAAe,UAAU;AAClF;;;AC1BA,eAAsB,gBACpB,QACA,aAC6B;AAC7B,MAAI,CAAC,aAAa;AAChB,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,SAAO,OAAO,YAAY,KAAK,WAAW;AAC5C;AAEA,eAAsB,cACpB,QACA,aACA,UAC2B;AAC3B,MAAI,CAAC,aAAa;AAChB,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,CAAC,UAAU;AACb,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,SAAO,OAAO,YAAY,IAAI,aAAa,QAAQ;AACrD;AAEA,eAAsB,iBACpB,QACA,aACA,QAC2B;AAC3B,MAAI,CAAC,aAAa;AAChB,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,CAAC,UAAU,CAAC,OAAO,gBAAgB,OAAO,aAAa,WAAW,GAAG;AACvE,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,SAAO,OAAO,YAAY,OAAO,aAAa,MAAM;AACtD;;;ACvDA,eAAsB,oBACpB,QACA,aACsC;AACtC,MAAI;AACF,WAAO,MAAM,OAAO,gBAAgB,KAAK,WAAW;AAAA,EACtD,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,qCAAqC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MAC3F;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,kBACpB,QACA,aACA,WACyB;AACzB,MAAI;AACF,WAAO,MAAM,OAAO,gBAAgB,IAAI,aAAa,SAAS;AAAA,EAChE,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,mCAAmC,SAAS,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MACxG;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,qBACpB,QACA,aACA,MACyB;AACzB,MAAI;AACF,WAAO,MAAM,OAAO,gBAAgB,OAAO,aAAa,IAAI;AAAA,EAC9D,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,sCAAsC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MAC5F;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAM,gBAAgB,oBAAI,IAAI,CAAC,aAAa,aAAa,CAAC;AAE1D,SAAS,oBAAoB,MAAuC;AAClE,SAAO,OAAO,KAAK,IAAI,EACpB,OAAO,CAAC,MAAM,CAAC,cAAc,IAAI,CAAC,CAAC,EACnC,KAAK,GAAG;AACb;AAEA,IAAM,sBAAsB,oBAAI,IAAI,CAAC,aAAa,SAAS,CAAC;AAE5D,SAAS,yBAAyB,MAAqC;AACrE,SAAO,OAAO,KAAK,IAAI,EACpB,OAAO,CAAC,MAAM,CAAC,oBAAoB,IAAI,CAAC,CAAC,EACzC,KAAK,GAAG;AACb;AAEA,eAAsB,qBACpB,QACA,aACA,WACA,MACA,YACyB;AACzB,MAAI;AACF,UAAM,OAAO,cAAc,oBAAoB,IAAI;AACnD,WAAO,MAAM,OAAO,gBAAgB,OAAO,aAAa,WAAW,MAAM,IAAI;AAAA,EAC/E,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,sCAAsC,SAAS,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MAC3G;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,qBACpB,QACA,aACA,WACe;AACf,MAAI;AACF,UAAM,OAAO,gBAAgB,OAAO,aAAa,SAAS;AAAA,EAC5D,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,sCAAsC,SAAS,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MAC3G;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,kBACpB,QACA,aACA,WACoC;AACpC,MAAI;AACF,WAAO,MAAM,OAAO,gBAAgB,WAAW,aAAa,SAAS;AAAA,EACvE,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,sCAAsC,SAAS,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MAC3G;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,gBACpB,QACA,aACA,WACA,SACuB;AACvB,MAAI;AACF,WAAO,MAAM,OAAO,gBAAgB,SAAS,aAAa,WAAW,OAAO;AAAA,EAC9E,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,wBAAwB,OAAO,kBAAkB,SAAS,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MACtH;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,mBACpB,QACA,aACA,WACA,MACuB;AACvB,MAAI;AACF,WAAO,MAAM,OAAO,gBAAgB,YAAY,aAAa,WAAW,IAAI;AAAA,EAC9E,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,uCAAuC,SAAS,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MAC5G;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,mBACpB,QACA,aACA,WACA,SACA,MACA,YACuB;AACvB,MAAI;AACF,UAAM,OAAO,cAAc,yBAAyB,IAAI;AACxD,WAAO,MAAM,OAAO,gBAAgB,YAAY,aAAa,WAAW,SAAS,MAAM,IAAI;AAAA,EAC7F,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,2BAA2B,OAAO,kBAAkB,SAAS,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MACzH;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAQA,eAAsB,mBACpB,QACA,aACA,WACA,WAC+B;AAC/B,QAAM,SAAS,MAAM,OAAO,gBAAgB,IAAI,aAAa,SAAS;AACtE,QAAM,QAA8B,CAAC;AACrC,QAAM,kBAAkB,CAAC,YAAY,gBAAgB,0BAA0B;AAE/E,aAAW,SAAS,iBAAiB;AACnC,UAAM,WAAW,KAAK,UAAW,UAAiD,KAAK,KAAK,IAAI;AAChG,UAAM,YAAY,KAAK,UAAW,OAA8C,KAAK,KAAK,IAAI;AAC9F,QAAI,aAAa,WAAW;AAC1B,YAAM,KAAK,EAAE,OAAO,OAAO,UAAU,QAAQ,UAAU,CAAC;AAAA,IAC1D;AAAA,EACF;AACA,SAAO;AACT;AAEA,eAAsB,mBACpB,QACA,aACA,WACA,SACe;AACf,MAAI;AACF,UAAM,OAAO,gBAAgB,YAAY,aAAa,WAAW,OAAO;AAAA,EAC1E,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,2BAA2B,OAAO,kBAAkB,SAAS,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MACzH;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;ACpOA,OAAOC,cAAa;AAEpB,IAAM,SAAS,CAAC,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,QAAG;AAChE,IAAM,cAAc;AASb,SAAS,cAAc,SAA0B;AACtD,QAAM,QAAQA,SAAQ,OAAO,UAAU;AACvC,MAAI,aAAa;AACjB,MAAI;AACJ,MAAI,iBAAiB;AACrB,MAAI,UAAU;AAEd,WAAS,YAAkB;AACzB,QAAI,OAAO;AACT,MAAAA,SAAQ,OAAO,MAAM,UAAU;AAAA,IACjC;AAAA,EACF;AAEA,WAAS,cAAoB;AAC3B,UAAM,QAAQ,OAAO,aAAa,OAAO,MAAM;AAC/C,IAAAA,SAAQ,OAAO,MAAM,WAAW,KAAK,IAAI,cAAc,EAAE;AACzD;AAAA,EACF;AAEA,SAAO;AAAA,IACL,QAAc;AACZ,UAAI,QAAS;AACb,gBAAU;AAEV,UAAI,CAAC,OAAO;AACV,QAAAA,SAAQ,OAAO,MAAM,GAAG,cAAc;AAAA,CAAI;AAC1C;AAAA,MACF;AAEA,kBAAY;AACZ,cAAQ,YAAY,aAAa,WAAW;AAAA,IAC9C;AAAA,IAEA,KAAK,KAAoB;AACvB,UAAI,OAAO;AACT,sBAAc,KAAK;AACnB,gBAAQ;AAAA,MACV;AACA,YAAM,OAAO,OAAO;AACpB,UAAI,OAAO;AACT,kBAAU;AACV,QAAAA,SAAQ,OAAO,MAAM,UAAU,IAAI;AAAA,CAAI;AAAA,MACzC,WAAW,CAAC,SAAS;AACnB,QAAAA,SAAQ,OAAO,MAAM,GAAG,IAAI;AAAA,CAAI;AAAA,MAClC;AACA,gBAAU;AAAA,IACZ;AAAA,IAEA,KAAK,KAAoB;AACvB,UAAI,OAAO;AACT,sBAAc,KAAK;AACnB,gBAAQ;AAAA,MACV;AACA,YAAM,OAAO,OAAO;AACpB,UAAI,OAAO;AACT,kBAAU;AACV,QAAAA,SAAQ,OAAO,MAAM,UAAU,IAAI;AAAA,CAAI;AAAA,MACzC,WAAW,CAAC,SAAS;AACnB,QAAAA,SAAQ,OAAO,MAAM,GAAG,IAAI;AAAA,CAAI;AAAA,MAClC;AACA,gBAAU;AAAA,IACZ;AAAA,IAEA,OAAO,KAAmB;AACxB,uBAAiB;AACjB,UAAI,CAAC,SAAS,CAAC,QAAS;AACxB,kBAAY;AAAA,IACd;AAAA,EACF;AACF;;;ACjFA,SAAS,SAAS,iBAAiB;AAO5B,SAAS,SAAS,UAA0B;AACjD,SAAO,QAAQ,UAAU,QAAQ,CAAC;AACpC;AAMO,SAAS,eAAe,UAAkB,SAAyB;AACxE,QAAM,WAAW,SAAS,QAAQ;AAClC,QAAM,OAAO,SAAS,OAAO;AAE7B,MAAI,CAAC,SAAS,WAAW,OAAO,GAAG,KAAK,aAAa,MAAM;AACzD,UAAM,IAAI;AAAA,MACR,SAAS,QAAQ,8CAA8C,OAAO;AAAA,MACtE;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;ACtBA,SAAS,eAAe,KAAc,MAAuB;AAC3D,QAAM,QAAQ,KAAK,MAAM,GAAG;AAC5B,MAAI,UAAmB;AACvB,aAAW,QAAQ,OAAO;AACxB,QAAI,YAAY,QAAQ,YAAY,UAAa,OAAO,YAAY,UAAU;AAC5E,aAAO;AAAA,IACT;AACA,cAAW,QAAoC,IAAI;AAAA,EACrD;AACA,SAAO;AACT;AAEA,SAAS,QAAQ,GAAY,GAAoB;AAC/C,MAAI,MAAM,UAAa,MAAM,OAAW,QAAO;AAC/C,MAAI,MAAM,OAAW,QAAO;AAC5B,MAAI,MAAM,OAAW,QAAO;AAE5B,MAAI,OAAO,MAAM,YAAY,OAAO,MAAM,UAAU;AAClD,WAAO,IAAI;AAAA,EACb;AAEA,SAAO,OAAO,CAAC,EAAE,cAAc,OAAO,CAAC,CAAC;AAC1C;AAWO,SAAS,YAAe,OAAY,UAAwB;AACjE,MAAI,CAAC,YAAY,MAAM,WAAW,GAAG;AACnC,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,SAAS,WAAW,GAAG;AAC1C,QAAM,QAAQ,aAAa,SAAS,MAAM,CAAC,IAAI;AAG/C,QAAM,WAAW,MAAM,KAAK,CAAC,SAAS,eAAe,MAAM,KAAK,MAAM,MAAS;AAC/E,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM;AACvC,UAAM,OAAO,eAAe,GAAG,KAAK;AACpC,UAAM,OAAO,eAAe,GAAG,KAAK;AACpC,UAAM,SAAS,QAAQ,MAAM,IAAI;AACjC,WAAO,aAAa,CAAC,SAAS;AAAA,EAChC,CAAC;AAED,SAAO;AACT;;;AC9DA,SAAS,SAAAC,QAAO,aAAAC,kBAAiB;AACjC,SAAS,QAAAC,aAAY;AAgBrB,eAAsB,eAAe,SAAmD;AACtF,QAAM,EAAE,MAAM,KAAK,cAAc,eAAe,IAAI,GAAG,IAAI;AAG3D,QAAM,aAAa,KAAK,WAAW,aAAa,IAAI,OAAO,cAAc,IAAI;AAC7E,QAAM,YAAY,WAAW,QAAQ,gBAAgB,EAAE;AAEvD,QAAM,SAASA,MAAK,KAAK,KAAK;AAC9B,QAAM,UAAUA,MAAK,KAAK,OAAO;AAEjC,QAAMF,OAAM,QAAQ,EAAE,WAAW,KAAK,CAAC;AACvC,QAAMA,OAAM,SAAS,EAAE,WAAW,KAAK,CAAC;AAExC,QAAM,QAAkB,CAAC;AAGzB,QAAM,MAAM;AAAA,IACV,MAAM;AAAA,IACN,SAAS;AAAA,IACT;AAAA,IACA,MAAM;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SAAS;AAAA,MACP,KAAK;AAAA,QACH,QAAQ;AAAA,QACR,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,OAAO,CAAC,MAAM;AAAA,IACd,SAAS;AAAA,MACP,OAAO;AAAA,MACP,KAAK;AAAA,MACL,MAAM;AAAA,MACN,cAAc;AAAA,IAChB;AAAA,IACA,UAAU,CAAC,OAAO,cAAc,aAAa;AAAA,IAC7C,SAAS;AAAA,IACT,kBAAkB;AAAA,MAChB,uBAAuB;AAAA,IACzB;AAAA,IACA,iBAAiB;AAAA,MACf,uBAAuB;AAAA,MACvB,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,QAAQ;AAAA,IACV;AAAA,EACF;AACA,QAAMC,WAAUC,MAAK,KAAK,cAAc,GAAG,KAAK,UAAU,KAAK,MAAM,CAAC,IAAI,IAAI;AAC9E,QAAM,KAAK,cAAc;AAGzB,QAAM,WAAW;AAAA,IACf,iBAAiB;AAAA,MACf,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,kBAAkB;AAAA,MAClB,aAAa;AAAA,MACb,QAAQ;AAAA,MACR,iBAAiB;AAAA,MACjB,cAAc;AAAA,MACd,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,IACA,SAAS,CAAC,KAAK;AAAA,EACjB;AACA,QAAMD,WAAUC,MAAK,KAAK,eAAe,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,IAAI,IAAI;AACpF,QAAM,KAAK,eAAe;AAG1B,QAAM,aAAa;AAAA;AAAA;AAAA;AAAA,WAIV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAiBD,SAAS;AAAA,2BACF,WAAW;AAAA;AAAA,uCAEC,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAO/C,QAAMD,WAAUC,MAAK,QAAQ,UAAU,GAAG,UAAU;AACpD,QAAM,KAAK,cAAc;AAGzB,QAAM,cAAc;AAAA;AAAA;AAAA,YAGV,UAAU;AAAA;AAAA,gCAEU,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkBxC,QAAMD,WAAUC,MAAK,SAAS,gBAAgB,GAAG,WAAW;AAC5D,QAAM,KAAK,sBAAsB;AAEjC,SAAO,EAAE,KAAK,MAAM;AACtB;;;ACrJA,SAAS,YAAY,OAAO,SAAAC,QAAO,YAAAC,WAAU,aAAAC,kBAAiB;AAC9D,SAAS,QAAAC,aAAY;AAarB,IAAI,WAA0B;AAMvB,SAAS,UAAU,WAAyB;AACjD,aAAW;AACb;AAKA,eAAsB,cAAc,OAAkC;AACpE,MAAI,CAAC,SAAU;AAEf,MAAI;AACF,UAAMH,OAAM,UAAU,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AACtD,UAAM,UAAUG,MAAK,UAAU,WAAW;AAC1C,UAAM,gBAAgB,gBAAgB,KAAK;AAC3C,UAAM,OAAO,KAAK,UAAU,aAAa,IAAI;AAC7C,UAAM,WAAW,SAAS,MAAM,EAAE,UAAU,SAAS,MAAM,IAAM,CAAC;AAClE,UAAM,MAAM,SAAS,GAAK,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EAC5C,QAAQ;AAAA,EAER;AACF;AAEA,IAAM,qBAAqB,oBAAI,IAAI;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAIM,SAAS,gBAAgB,OAA+B;AAC7D,QAAM,WAAoC,CAAC;AAC3C,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,MAAM,IAAI,GAAG;AAC/C,aAAS,CAAC,IAAI,mBAAmB,IAAI,CAAC,IAAI,eAAe;AAAA,EAC3D;AACA,SAAO,EAAE,GAAG,OAAO,MAAM,SAAS;AACpC;AAKO,SAAS,iBACd,SACA,MACA,KACY;AACZ,SAAO;AAAA,IACL,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAsB,gBAAgB,SAIZ;AACxB,MAAI,CAAC,SAAU,QAAO,CAAC;AACvB,QAAM,UAAUC,MAAK,UAAU,WAAW;AAC1C,MAAI;AACJ,MAAI;AACF,cAAU,MAAMC,UAAS,SAAS,OAAO;AAAA,EAC3C,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACA,QAAM,QAAQ,QAAQ,KAAK,EAAE,MAAM,IAAI,EAAE,OAAO,OAAO;AACvD,MAAI,UAAwB,CAAC;AAC7B,aAAW,QAAQ,OAAO;AACxB,QAAI;AACF,cAAQ,KAAK,KAAK,MAAM,IAAI,CAAe;AAAA,IAC7C,QAAQ;AAAA,IAER;AAAA,EACF;AACA,MAAI,SAAS,OAAO;AAClB,UAAM,YAAY,IAAI,KAAK,QAAQ,KAAK,EAAE,QAAQ;AAClD,cAAU,QAAQ,OAAO,CAAC,MAAM,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ,KAAK,SAAS;AAAA,EAC9E;AACA,MAAI,SAAS,SAAS;AACpB,UAAM,MAAM,QAAQ,QAAQ,YAAY;AACxC,cAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,QAAQ,YAAY,EAAE,SAAS,GAAG,CAAC;AAAA,EACvE;AACA,MAAI,SAAS,OAAO;AAClB,cAAU,QAAQ,MAAM,CAAC,QAAQ,KAAK;AAAA,EACxC;AACA,SAAO;AACT;AAEA,eAAsB,kBAAkB,OAAsC;AAC5E,QAAM,MAAM,MAAM,gBAAgB;AAClC,QAAM,IAAI,MAAM,YAAY;AAC5B,SAAO,IAAI,OAAO,CAAC,MAAM;AACvB,UAAM,OAAO,KAAK,UAAU,CAAC,EAAE,YAAY;AAC3C,WAAO,KAAK,SAAS,CAAC;AAAA,EACxB,CAAC;AACH;AAEA,eAAsB,cAAc,SAGgB;AAClD,MAAI,CAAC,SAAU,QAAO,EAAE,SAAS,GAAG,WAAW,EAAE;AACjD,QAAM,UAAUD,MAAK,UAAU,WAAW;AAC1C,MAAI;AACJ,MAAI;AACF,cAAU,MAAMC,UAAS,SAAS,OAAO;AAAA,EAC3C,QAAQ;AACN,WAAO,EAAE,SAAS,GAAG,WAAW,EAAE;AAAA,EACpC;AACA,QAAM,QAAQ,QAAQ,KAAK,EAAE,MAAM,IAAI,EAAE,OAAO,OAAO;AACvD,MAAI,CAAC,SAAS,QAAQ;AACpB,UAAM,QAAQ,MAAM;AACpB,QAAI,CAAC,SAAS,QAAQ;AACpB,YAAMC,WAAU,SAAS,IAAI,EAAE,UAAU,SAAS,MAAM,IAAM,CAAC;AAAA,IACjE;AACA,WAAO,EAAE,SAAS,OAAO,WAAW,EAAE;AAAA,EACxC;AACA,QAAM,aAAa,IAAI,KAAK,QAAQ,MAAM,EAAE,QAAQ;AACpD,QAAM,OAAiB,CAAC;AACxB,QAAM,SAAmB,CAAC;AAC1B,aAAW,QAAQ,OAAO;AACxB,QAAI;AACF,YAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,UAAI,IAAI,KAAK,MAAM,SAAS,EAAE,QAAQ,IAAI,YAAY;AACpD,eAAO,KAAK,IAAI;AAAA,MAClB,OAAO;AACL,aAAK,KAAK,IAAI;AAAA,MAChB;AAAA,IACF,QAAQ;AACN,WAAK,KAAK,IAAI;AAAA,IAChB;AAAA,EACF;AACA,MAAI,CAAC,SAAS,QAAQ;AACpB,UAAMA,WAAU,SAAS,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,IAAI;AAAA,MACtE,UAAU;AAAA,MACV,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AACA,SAAO,EAAE,SAAS,OAAO,QAAQ,WAAW,KAAK,OAAO;AAC1D;;;AC9KO,SAAS,mBAAmB,SAAiC;AAClE,QAAM,SAAS,QAAQ,UAAU,WAAW;AAC5C,QAAM,QAAQ,QAAQ,UAAU,YAAY;AAC5C,QAAM,eAAe,QAAQ,WAAW,KAAM,QAAQ,CAAC;AAEvD,QAAM,SAAkE;AAAA,IACtE,EAAE,OAAO,WAAW,OAAO,QAAQ,SAAS,OAAO,KAAK;AAAA,IACxD,EAAE,OAAO,YAAY,OAAO,GAAG,WAAW,KAAK,OAAO,KAAK;AAAA,EAC7D;AAEA,MAAI,QAAQ,KAAK;AACf,WAAO,KAAK,EAAE,OAAO,OAAO,OAAO,QAAQ,KAAK,OAAO,KAAK,CAAC;AAAA,EAC/D;AAEA,MAAI,QAAQ,OAAO;AACjB,WAAO,KAAK,EAAE,OAAO,SAAS,OAAO,QAAQ,OAAO,OAAO,MAAM,CAAC;AAAA,EACpE;AAEA,MAAI,QAAQ,SAAS;AACnB,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,OAAO,GAAG;AAC1D,aAAO,KAAK,EAAE,OAAO,KAAK,OAAO,OAAO,KAAK,GAAG,OAAO,KAAK,CAAC;AAAA,IAC/D;AAAA,EACF;AAEA,SAAO;AAAA,IACL,aAAa;AAAA,MACX;AAAA,QACE;AAAA,QACA,UAAU,QAAQ,QAAQ,OAAO,IAAI,MAAM;AAAA,QAC3C,OAAO,QAAQ,QAAQ,OAAO,IAAI,MAAM;AAAA,QACxC;AAAA,QACA,QAAQ;AAAA,QACR,IAAI,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAAA,MAClC;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,qBAAqB,SAAiC;AACpE,QAAM,SAAS,QAAQ,UAAU,WAAW;AAC5C,QAAM,QAAQ,QAAQ,UAAU,UAAW;AAC3C,QAAM,eAAe,QAAQ,WAAW,KAAM,QAAQ,CAAC;AAEvD,QAAM,SAAkE;AAAA,IACtE,EAAE,MAAM,WAAW,OAAO,QAAQ,SAAS,QAAQ,KAAK;AAAA,IACxD,EAAE,MAAM,YAAY,OAAO,GAAG,WAAW,KAAK,QAAQ,KAAK;AAAA,EAC7D;AAEA,MAAI,QAAQ,KAAK;AACf,WAAO,KAAK,EAAE,MAAM,OAAO,OAAO,QAAQ,KAAK,QAAQ,KAAK,CAAC;AAAA,EAC/D;AAEA,MAAI,QAAQ,OAAO;AACjB,WAAO,KAAK,EAAE,MAAM,SAAS,OAAO,QAAQ,OAAO,QAAQ,MAAM,CAAC;AAAA,EACpE;AAEA,MAAI,QAAQ,SAAS;AACnB,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,OAAO,GAAG;AAC1D,aAAO,KAAK,EAAE,MAAM,KAAK,OAAO,OAAO,KAAK,GAAG,QAAQ,KAAK,CAAC;AAAA,IAC/D;AAAA,EACF;AAEA,SAAO;AAAA,IACL,QAAQ;AAAA,MACN;AAAA,QACE,OAAO,QAAQ,QAAQ,OAAO,IAAI,MAAM;AAAA,QACxC;AAAA,QACA;AAAA,QACA,QAAQ,EAAE,MAAM,UAAU;AAAA,QAC1B,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MACpC;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,oBAAoB,SAAiC;AACnE,SAAO,EAAE,GAAG,QAAQ;AACtB;AAIA,IAAM,aAAmE;AAAA,EACvE,OAAO;AAAA,EACP,SAAS;AAAA,EACT,QAAQ;AACV;AAEA,IAAM,qBAAqB;AAE3B,eAAe,WAAW,KAAa,MAA6B;AAClE,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,QAAQ,WAAW,MAAM,WAAW,MAAM,GAAG,kBAAkB;AAErE,MAAI;AACF,UAAM,MAAM,KAAK;AAAA,MACf,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,IAAI;AAAA,MACzB,QAAQ,WAAW;AAAA,IACrB,CAAC;AAAA,EACH,UAAE;AACA,iBAAa,KAAK;AAAA,EACpB;AACF;AAEA,eAAsB,YACpB,QACA,SACA,QACe;AACf,MAAI;AACF,UAAM,UAA2B,SAC7B,CAAC,MAAuB,IACvB,OAAO,KAAK,UAAU;AAE3B,UAAM,WAA4B,CAAC;AAEnC,eAAW,KAAK,SAAS;AACvB,YAAM,MAAM,OAAO,CAAC;AACpB,UAAI,CAAC,IAAK;AAEV,YAAM,YAAY,WAAW,CAAC;AAC9B,UAAI,CAAC,UAAW;AAEhB,YAAM,OAAO,UAAU,OAAO;AAC9B,eAAS,KAAK,WAAW,KAAK,IAAI,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC,CAAC;AAAA,IACrD;AAEA,UAAM,QAAQ,IAAI,QAAQ;AAAA,EAC5B,QAAQ;AAAA,EAER;AACF;;;AC/IA,SAAS,WAAAC,gBAAe;AAYxB,eAAsB,sBACpB,QACA,aACA,UACA,UACsC;AAEtC,QAAM,eAAe,YAAY,eAAe,QAAQ;AAGxD,QAAM,aAAa,MAAM,mBAAmB,QAAQ;AACpD,MAAI,CAAC,WAAW,OAAO;AACrB,UAAM,IAAI;AAAA,MACR;AAAA,EAA4B,WAAW,OAAO,KAAK,IAAI,CAAC;AAAA,MACxD;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI;AACJ,MAAI,iBAAiB,UAAU;AAC7B,eAAW,MAAM,OAAO,mBAAmB,aAAa,aAAa,QAAQ;AAAA,EAC/E,OAAO;AACL,eAAW,MAAM,OAAO,mBAAmB,UAAU,aAAa,QAAQ;AAAA,EAC5E;AAEA,SAAO;AAAA,IACL,aAAa,SAAS;AAAA,IACtB,QAAQ,SAAS;AAAA,IACjB,wBAAwB,SAAS;AAAA,IACjC,UAAU;AAAA,EACZ;AACF;AAEA,SAAS,eAAe,UAAoC;AAC1D,QAAM,MAAMC,SAAQ,QAAQ,EAAE,YAAY;AAC1C,MAAI,QAAQ,OAAQ,QAAO;AAC3B,MAAI,QAAQ,OAAQ,QAAO;AAC3B,QAAM,IAAI;AAAA,IACR,2CAA2C,GAAG;AAAA,IAC9C;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACzDA,SAAS,aAAAC,kBAAiB;AAI1B,eAAsB,kBACpB,QACA,aACA,aACyB;AACzB,MAAI,CAAC,OAAO,UAAU,WAAW,KAAK,eAAe,GAAG;AACtD,UAAM,IAAI;AAAA,MACR,yBAAyB,WAAW;AAAA,MACpC;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,SAAO,OAAO,cAAc,KAAK,aAAa,WAAW;AAC3D;AAEA,eAAsB,qBACpB,QACA,aACA,aACA,OACA,YAC8C;AAC9C,MAAI,CAAC,OAAO,UAAU,WAAW,KAAK,eAAe,GAAG;AACtD,UAAM,IAAI;AAAA,MACR,yBAAyB,WAAW;AAAA,MACpC;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,OAAO;AACV,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,MAAM,OAAO,cAAc,SAAS,aAAa,aAAa,KAAK;AAClF,QAAM,QAAQ,IAAI,WAAW,MAAM;AACnC,QAAMC,WAAU,YAAY,KAAK;AAEjC,SAAO,EAAE,MAAM,YAAY,WAAW,MAAM,WAAW;AACzD;;;AC/CA,eAAsB,oBACpB,QACA,aACsC;AACtC,MAAI;AACF,WAAO,MAAM,OAAO,gBAAgB,KAAK,WAAW;AAAA,EACtD,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,oCAAoC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MAC1F;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,kBACpB,QACA,aACA,kBACyB;AACzB,MAAI;AACF,WAAO,MAAM,OAAO,gBAAgB,IAAI,aAAa,gBAAgB;AAAA,EACvE,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,kCAAkC,gBAAgB,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MAC9G;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,qBACpB,QACA,aACA,MACyB;AACzB,MAAI;AACF,WAAO,MAAM,OAAO,gBAAgB,OAAO,aAAa,IAAI;AAAA,EAC9D,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,qCAAqC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MAC3F;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,uBACpB,QACA,aACA,kBACyB;AACzB,MAAI;AACF,WAAO,MAAM,OAAO,gBAAgB,SAAS,aAAa,gBAAgB;AAAA,EAC5E,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,uCAAuC,gBAAgB,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MACnH;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,yBACpB,QACA,aACA,kBACyB;AACzB,MAAI;AACF,WAAO,MAAM,OAAO,gBAAgB,WAAW,aAAa,gBAAgB;AAAA,EAC9E,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,yCAAyC,gBAAgB,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MACrH;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;ACrFA,SAAS,YAAAC,WAAU,QAAAC,aAAY;AA8B/B,IAAM,iBAAiB;AACvB,IAAM,eAAe;AAGrB,IAAM,iBAAiB,oBAAI,IAAI,CAAC,OAAO,YAAY,OAAO,UAAU,OAAO,gBAAgB,MAAM,CAAC;AAElG,SAAS,eAAe,MAAsB;AAC5C,QAAM,QAAQ,KAAK,YAAY;AAE/B,MAAI,MAAM,SAAS,MAAM,KAAK,qBAAqB,KAAK,KAAK,EAAG,QAAO;AAEvE,MACE,UAAU,oBACV,MAAM,SAAS,iBAAiB,KAChC,MAAM,SAAS,eAAe,KAC9B,qBAAqB,KAAK,KAAK,EAC/B,QAAO;AAET,MAAI,wBAAwB,KAAK,KAAK,EAAG,QAAO;AAEhD,MAAI,qBAAqB,KAAK,KAAK,EAAG,QAAO;AAE7C,MACE,UAAU,yBACV,MAAM,SAAS,sBAAsB,KACrC,0BAA0B,KAAK,KAAK,EACpC,QAAO;AAET,MAAI,MAAM,WAAW,WAAW,KAAK,UAAU,WAAY,QAAO;AAClE,SAAO;AACT;AAEA,SAAS,aAAa,MAAc,OAAwB;AAC1D,MAAI,CAAC,MAAO,QAAO;AAEnB,QAAM,WAAW,KAAK,QAAQ,GAAG;AACjC,MAAI,aAAa,GAAI,QAAO;AAE5B,QAAM,SAAS,KAAK,UAAU,GAAG,QAAQ;AACzC,QAAM,OAAO,KAAK,UAAU,WAAW,CAAC;AAGxC,MAAI,WAAW,OAAQ,QAAO;AAG9B,MAAI,WAAW,qBAAqB,WAAW,WAAY,QAAO;AAClE,MAAI,SAAS,kBAAmB,QAAO;AAGvC,QAAM,SAAS,KAAK,MAAM,GAAG,EAAE,CAAC,KAAK;AACrC,MAAI,eAAe,IAAI,MAAM,EAAG,QAAO;AAEvC,SAAO;AACT;AAQA,SAAS,sBAAsB,KAAsC;AAEnE,MAAI,aAAa;AACjB,WAAS,IAAI,IAAI,SAAS,IAAI,KAAK,KAAK,KAAK,IAAI,SAAS,OAAO,KAAK;AACpE,QAAI,IAAI,aAAa,CAAC,MAAM,gBAAgB;AAC1C,mBAAa;AACb;AAAA,IACF;AAAA,EACF;AACA,MAAI,eAAe,IAAI;AACrB,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AAEA,QAAM,SAAS,IAAI,aAAa,aAAa,EAAE;AAC/C,MAAI,WAAW,IAAI,aAAa,aAAa,EAAE;AAG/C,MAAI,aAAa,YAAY;AAE3B,UAAM,qBAAqB,aAAa;AACxC,QAAI,sBAAsB,KAAK,IAAI,aAAa,kBAAkB,MAAM,WAAY;AAElF,YAAM,kBAAkB,OAAO,IAAI,gBAAgB,qBAAqB,CAAC,CAAC;AAC1E,UAAI,mBAAmB,KAAK,kBAAkB,IAAI,QAAQ;AACxD,mBAAW,OAAO,IAAI,gBAAgB,kBAAkB,EAAE,CAAC;AAAA,MAC7D;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAAmC,CAAC;AAC1C,MAAI,MAAM;AACV,QAAM,MAAM,WAAW;AAEvB,SAAO,MAAM,OAAO,MAAM,MAAM,IAAI,QAAQ;AAC1C,UAAM,MAAM,IAAI,aAAa,GAAG;AAChC,QAAI,QAAQ,aAAc;AAE1B,UAAM,iBAAiB,IAAI,aAAa,MAAM,EAAE;AAChD,UAAM,mBAAmB,IAAI,aAAa,MAAM,EAAE;AAClD,UAAM,cAAc,IAAI,aAAa,MAAM,EAAE;AAC7C,UAAM,WAAW,IAAI,aAAa,MAAM,EAAE;AAC1C,UAAM,aAAa,IAAI,aAAa,MAAM,EAAE;AAE5C,UAAM,WAAW,IAAI,SAAS,SAAS,MAAM,IAAI,MAAM,KAAK,WAAW;AAGvE,QAAI,CAAC,SAAS,SAAS,GAAG,GAAG;AAC3B,cAAQ,KAAK,EAAE,UAAU,gBAAgB,iBAAiB,CAAC;AAAA,IAC7D;AAEA,WAAO,KAAK,cAAc,WAAW;AAAA,EACvC;AAEA,SAAO;AACT;AAEA,SAASC,gBAAe,UAAiC;AACvD,QAAM,QAAQ,SAAS,YAAY;AACnC,MAAI,MAAM,SAAS,MAAM,EAAG,QAAO;AACnC,SAAO;AACT;AAEA,eAAsB,cAAc,UAA2C;AAC7E,QAAM,WAAW,MAAMD,MAAK,QAAQ,EAAE,MAAM,MAAM,IAAI;AACtD,MAAI,CAAC,YAAY,CAAC,SAAS,OAAO,GAAG;AACnC,UAAM,IAAI,MAAM,mBAAmB,QAAQ,EAAE;AAAA,EAC/C;AAEA,QAAM,MAAM,MAAMD,UAAS,QAAQ;AACnC,QAAM,YAAY,sBAAsB,GAAG;AAC3C,QAAM,WAAWE,gBAAe,QAAQ;AACxC,QAAM,QAAQ,aAAa;AAE3B,QAAM,UAAyB,UAAU,IAAI,CAAC,OAAO;AAAA,IACnD,MAAM,EAAE;AAAA,IACR,QAAQ,aAAa,EAAE,UAAU,KAAK;AAAA,IACtC,UAAU,eAAe,EAAE,QAAQ;AAAA,IACnC,gBAAgB,EAAE;AAAA,IAClB,kBAAkB,EAAE;AAAA,EACtB,EAAE;AAGF,QAAM,YAAY,oBAAI,IAAmF;AACzG,aAAW,SAAS,SAAS;AAC3B,UAAM,WAAW,UAAU,IAAI,MAAM,MAAM,KAAK,EAAE,gBAAgB,GAAG,kBAAkB,GAAG,SAAS,EAAE;AACrG,aAAS,kBAAkB,MAAM;AACjC,aAAS,oBAAoB,MAAM;AACnC,aAAS,WAAW;AACpB,cAAU,IAAI,MAAM,QAAQ,QAAQ;AAAA,EACtC;AAGA,QAAM,cAAc,oBAAI,IAAmF;AAC3G,aAAW,SAAS,SAAS;AAC3B,UAAM,WAAW,YAAY,IAAI,MAAM,QAAQ,KAAK,EAAE,gBAAgB,GAAG,kBAAkB,GAAG,SAAS,EAAE;AACzG,aAAS,kBAAkB,MAAM;AACjC,aAAS,oBAAoB,MAAM;AACnC,aAAS,WAAW;AACpB,gBAAY,IAAI,MAAM,UAAU,QAAQ;AAAA,EAC1C;AAEA,QAAM,UAAU,CAAC,GAAG,UAAU,QAAQ,CAAC,EACpC,IAAI,CAAC,CAAC,MAAM,IAAI,OAAO,EAAE,MAAM,GAAG,KAAK,EAAE,EACzC,KAAK,CAAC,GAAG,MAAM,EAAE,iBAAiB,EAAE,cAAc;AAErD,QAAM,aAAa,CAAC,GAAG,YAAY,QAAQ,CAAC,EACzC,IAAI,CAAC,CAAC,MAAM,IAAI,OAAO,EAAE,MAAM,GAAG,KAAK,EAAE,EACzC,KAAK,CAAC,GAAG,MAAM,EAAE,iBAAiB,EAAE,cAAc;AAErD,QAAM,kBAAkB,QAAQ,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,gBAAgB,CAAC;AAC5E,QAAM,oBAAoB,QAAQ,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,kBAAkB,CAAC;AAEhF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY,QAAQ;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,eAAe,QAAwB,OAAyC;AAC9F,QAAM,YAAY,MAAM,kBAAkB,OAAO;AACjD,QAAM,mBAAmB,OAAO,kBAAkB,IAC9C,KAAK,MAAQ,YAAY,OAAO,kBAAmB,MAAO,EAAE,IAAI,KAChE;AAGJ,QAAM,aAAa,oBAAI,IAAI;AAAA,IACzB,GAAG,OAAO,QAAQ,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,IACnC,GAAG,MAAM,QAAQ,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,EACpC,CAAC;AACD,QAAM,eAAe,CAAC,GAAG,UAAU,EAAE,IAAI,CAAC,WAAW;AACnD,UAAM,IAAI,OAAO,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,GAAG,kBAAkB;AAC3E,UAAM,IAAI,MAAM,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,GAAG,kBAAkB;AAC1E,WAAO,EAAE,QAAQ,QAAQ,GAAG,OAAO,GAAG,OAAO,IAAI,EAAE;AAAA,EACrD,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,KAAK,IAAI,EAAE,KAAK,IAAI,KAAK,IAAI,EAAE,KAAK,CAAC;AAGvD,QAAM,gBAAgB,oBAAI,IAAI;AAAA,IAC5B,GAAG,OAAO,WAAW,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,IACtC,GAAG,MAAM,WAAW,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,EACvC,CAAC;AACD,QAAM,iBAAiB,CAAC,GAAG,aAAa,EAAE,IAAI,CAAC,aAAa;AAC1D,UAAM,IAAI,OAAO,WAAW,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ,GAAG,kBAAkB;AAChF,UAAM,IAAI,MAAM,WAAW,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ,GAAG,kBAAkB;AAC/E,WAAO,EAAE,UAAU,QAAQ,GAAG,OAAO,GAAG,OAAO,IAAI,EAAE;AAAA,EACvD,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,KAAK,IAAI,EAAE,KAAK,IAAI,KAAK,IAAI,EAAE,KAAK,CAAC;AAEvD,SAAO;AAAA,IACL,QAAQ,EAAE,MAAM,OAAO,UAAU,iBAAiB,OAAO,gBAAgB;AAAA,IACzE,OAAO,EAAE,MAAM,MAAM,UAAU,iBAAiB,MAAM,gBAAgB;AAAA,IACtE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AC3PA,SAAS,SAAAC,QAAO,YAAAC,YAAU,aAAAC,kBAAiB;AAC3C,SAAS,gBAAgB;AACzB,SAAS,QAAAC,aAAY;AAGrB,SAAS,mBAAmB;AA6E5B,IAAM,sBAAsB;AAQ5B,SAAS,cAAc,aAA6B;AAClD,SAAOC,MAAK,YAAY,GAAG,UAAU,WAAW,OAAO;AACzD;AAEA,eAAsB,gBACpB,aACA,aAAa,qBACc;AAC3B,MAAI;AACF,UAAM,MAAM,MAAMC,WAAS,cAAc,WAAW,GAAG,OAAO;AAC9D,UAAM,QAAQ,KAAK,MAAM,GAAG;AAC5B,UAAM,OAAO,KAAK,IAAI,IAAI,IAAI,KAAK,MAAM,SAAS,EAAE,QAAQ,KAAK;AACjE,QAAI,OAAO,MAAM,OAAO,YAAa,QAAO;AAC5C,WAAO,EAAE,GAAG,MAAM,MAAM,QAAQ,KAAK;AAAA,EACvC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,gBACpB,aACA,MACA,aAAa,qBACE;AACf,MAAI;AACF,UAAM,MAAM,YAAY;AACxB,UAAMC,OAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AACpC,UAAM,QAAoB,EAAE,WAAW,KAAK,WAAW,KAAK,YAAY,KAAK;AAC7E,UAAMC,WAAU,cAAc,WAAW,GAAG,KAAK,UAAU,OAAO,MAAM,CAAC,GAAG;AAAA,MAC1E,UAAU;AAAA,MACV,MAAM;AAAA,IACR,CAAC;AAAA,EACH,QAAQ;AAAA,EAER;AACF;AAMA,IAAMC,sBAAiE;AAAA,EACrE,oBAAoB,CAAC,aAAa,0BAA0B,eAAe;AAAA,EAC3E,kBAAkB,CAAC,WAAW,wBAAwB,eAAe;AAAA,EACrE,wBAAwB,CAAC,iBAAiB,eAAe;AAAA,EACzD,4BAA4B,CAAC,qBAAqB,eAAe;AACnE;AAEA,IAAM,qBAAqB;AAAA,EACzB,WAAW;AAAA,EACX,SAAS;AAAA,EACT,eAAe;AAAA,EACf,mBAAmB;AACrB;AAEA,IAAM,cAAc;AAEpB,SAAS,UAAU,GAAuD;AACxE,SAAO,EAAE,MAAM,EAAE,eAAe,GAAG,OAAO,EAAE,YAAY,IAAI,GAAG,KAAK,EAAE,WAAW,EAAE;AACrF;AAEA,eAAe,oBACb,WACA,aACA,WACA,MACA,aAAa,GACgB;AAC7B,QAAM,SAAS,KAAK,KAAK,KAAK;AAC9B,QAAM,SAAS,KAAK,IAAI,IAAI,IAAI,SAAS,aAAa;AACtD,QAAM,MAAM,IAAI,KAAK,MAAM;AAC3B,QAAM,QAAQ,IAAI,KAAK,SAAS,OAAO,MAAM;AAC7C,QAAM,UAAUA,oBAAmB,SAAS,KAAK,CAAC,eAAe;AAEjE,QAAM,QAAwB;AAAA,IAC5B;AAAA,IACA,cAAc;AAAA,MACZ,mBAAmB;AAAA,MACnB,WAAW,UAAU,KAAK;AAAA,MAC1B,SAAS,UAAU,GAAG;AAAA,IACxB;AAAA,EACF;AAEA,QAAM,SAAS,MAAM,UAAU,eAAe,aAAa,WAAW,KAAK;AAC3E,MAAI,CAAC,OAAO,QAAQ,OAAO,KAAK,WAAW,EAAG,QAAO;AAErD,QAAM,SAAS,OAAO,KACnB,IAAI,CAAC,QAAQ;AACZ,UAAM,WAAW,OAAO,KAAK,IAAI,OAAO,EAAE,CAAC;AAC3C,WAAO,WAAW,OAAO,IAAI,QAAQ,QAAQ,GAAG,cAAc,KAAK,IAAI;AAAA,EACzE,CAAC,EACA,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAE1B,MAAI,OAAO,WAAW,EAAG,QAAO;AAChC,SAAO,OAAO,OAAO,CAAC,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI,OAAO;AACpD;AAQA,eAAe,oBACb,WACA,aACA,WACA,MACyB;AACzB,QAAM,CAAC,SAAS,QAAQ,IAAI,MAAM,QAAQ,IAAI;AAAA,IAC5C,oBAAoB,WAAW,aAAa,WAAW,MAAM,CAAC;AAAA,IAC9D,oBAAoB,WAAW,aAAa,WAAW,MAAM,IAAI;AAAA,EACnE,CAAC;AAED,MAAI,QAAuC;AAC3C,MAAI,YAAY,UAAa,aAAa,QAAW;AACnD,QAAI,UAAU,SAAU,SAAQ;AAAA,aACvB,UAAU,SAAU,SAAQ;AAAA,QAChC,SAAQ;AAAA,EACf;AAEA,SAAO,EAAE,SAAS,UAAU,MAAM;AACpC;AAEA,IAAM,gBAAgC,EAAE,SAAS,QAAW,UAAU,QAAW,OAAO,KAAK;AAE7F,SAAS,cACP,OACA,WACA,eACA,OACmB;AACnB,QAAM,OACJ,kBAAkB,SACd,EAAE,OAAO,WAAW,QAAQ,WAAW,eAAe,OAAO,SAAS,KAAK,IAC3E,EAAE,OAAO,WAAW,QAAQ,UAAU;AAE5C,MAAI,UAAU,OAAW,QAAO,EAAE,GAAG,MAAM,QAAQ,UAAU;AAC7D,MAAI,QAAQ,UAAW,QAAO,EAAE,GAAG,MAAM,QAAQ,SAAS;AAC1D,MAAI,QAAQ,aAAa,IAAI,aAAc,QAAO,EAAE,GAAG,MAAM,QAAQ,OAAO;AAC5E,SAAO,EAAE,GAAG,MAAM,QAAQ,KAAK;AACjC;AAMA,SAAS,uBACP,SACA,YACe;AACf,QAAM,MAAM,KAAK,IAAI;AACrB,QAAM,SAAS,KAAK,KAAK,KAAK;AAC9B,QAAM,WAAW,aAAa;AAC9B,QAAM,kBAAkB,MAAM,IAAI;AAClC,QAAM,iBAAiB,MAAM;AAE7B,QAAM,UAAU,QAAQ,OAAO,CAAC,MAAM;AACpC,UAAM,KAAK,EAAE,WAAW,CAAC,GAAG;AAC5B,QAAI,CAAC,GAAI,QAAO;AAChB,UAAM,KAAK,OAAO,GAAG,aAAa,OAAO,IAAI;AAC7C,WAAO,MAAM;AAAA,EACf,CAAC;AAED,QAAM,WAAW,QAAQ,OAAO,CAAC,MAAM;AACrC,UAAM,KAAK,EAAE,WAAW,CAAC,GAAG;AAC5B,QAAI,CAAC,GAAI,QAAO;AAChB,UAAM,KAAK,OAAO,GAAG,aAAa,OAAO,IAAI;AAC7C,WAAO,MAAM,mBAAmB,KAAK;AAAA,EACvC,CAAC;AAED,QAAM,YAAY,CAAC,UAA8C;AAC/D,UAAM,UAAU,MACb,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,aAAa,UAAU,EACnD,OAAO,CAAC,MAAmB,MAAM,UAAa,IAAI,CAAC;AACtD,QAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,WAAO,KAAK,MAAO,QAAQ,OAAO,CAAC,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI,QAAQ,SAAU,EAAE,IAAI;AAAA,EAClF;AAEA,QAAM,gBAAgB,QAAQ;AAAA,IAC5B,CAAC,OAAO,EAAE,WAAW,CAAC,GAAG,aAAa,cAAc,MAAM;AAAA,EAC5D,EAAE;AAEF,QAAM,kBACJ,QAAQ,SAAS,IAAI,KAAK,MAAO,gBAAgB,QAAQ,SAAU,GAAG,IAAI;AAE5E,SAAO;AAAA,IACL;AAAA,IACA,eAAe,UAAU,OAAO;AAAA,IAChC,uBAAuB,UAAU,QAAQ;AAAA,IACzC,UAAU,QAAQ;AAAA,IAClB;AAAA,EACF;AACF;AAMA,eAAsB,aACpB,QACA,WACA,aACA,UAA+B,CAAC,GACZ;AACpB,QAAM,OAAO,QAAQ,QAAQ;AAC7B,QAAM,WAAW,IAAI,IAAI,QAAQ,YAAY,CAAC,YAAY,UAAU,SAAS,CAAC;AAC9E,QAAM,aAAa;AAAA,IACjB,WAAW,QAAQ,iBAAiB,aAAa,mBAAmB;AAAA,IACpE,SAAS,QAAQ,iBAAiB,WAAW,mBAAmB;AAAA,IAChE,eAAe,QAAQ,iBAAiB,iBAAiB,mBAAmB;AAAA,IAC5E,mBACE,QAAQ,iBAAiB,qBAAqB,mBAAmB;AAAA,EACrE;AAEA,QAAM,CAAC,gBAAgB,eAAe,WAAW,iBAAiB,kBAAkB,aAAa,IAC/F,MAAM,QAAQ,WAAW;AAAA,IACvB,SAAS,IAAI,UAAU,IACnB,kBAAkB,QAAQ,WAAW,IACrC,QAAQ,QAAQ,CAAC,CAAC;AAAA,IACtB,SAAS,IAAI,QAAQ,IACjB,oBAAoB,WAAW,aAAa,sBAAsB,IAAI,IACtE,QAAQ,QAAQ,aAAa;AAAA,IACjC,SAAS,IAAI,QAAQ,IACjB,oBAAoB,WAAW,aAAa,oBAAoB,IAAI,IACpE,QAAQ,QAAQ,aAAa;AAAA,IACjC,SAAS,IAAI,QAAQ,IACjB,oBAAoB,WAAW,aAAa,0BAA0B,IAAI,IAC1E,QAAQ,QAAQ,aAAa;AAAA,IACjC,SAAS,IAAI,QAAQ,IACjB,oBAAoB,WAAW,aAAa,8BAA8B,IAAI,IAC9E,QAAQ,QAAQ,aAAa;AAAA,IACjC,SAAS,IAAI,SAAS,IAClB,YAAY,QAAQ,aAAa,EAAE,YAAY,IAAI,CAAC,IACpD,QAAQ,QAAQ,CAAC,CAAC;AAAA,EACxB,CAAC;AAEH,QAAM,cAAc,eAAe,WAAW,cAAc,eAAe,QAAQ,CAAC;AACpF,QAAM,WAA4B,YAAY,IAAI,CAAC,OAAO;AAAA,IACxD,OAAO,EAAE;AAAA,IACT,aAAa,EAAE,aAAa,EAAE,aAAa,SAAS,CAAC,KAAK;AAAA,IAC1D,QAAQ,EAAE;AAAA,IACV,cAAc,EAAE,gBAAgB;AAAA,EAClC,EAAE;AAEF,QAAM,UACJ,cAAc,WAAW,cAAc,cAAc,QAAQ;AAC/D,QAAM,MACJ,UAAU,WAAW,cAAc,UAAU,QAAQ;AACvD,QAAM,YACJ,gBAAgB,WAAW,cAAc,gBAAgB,QAAQ;AACnE,QAAM,aACJ,iBAAiB,WAAW,cAAc,iBAAiB,QAAQ;AAErE,QAAM,aAAa,cAAc,WAAW,cAAc,cAAc,QAAQ,CAAC;AACjF,QAAM,UAAU,uBAAuB,YAAY,EAAE;AAErD,SAAO;AAAA,IACL;AAAA,IACA,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,QAAQ;AAAA,IACR;AAAA,IACA,QAAQ;AAAA,MACN,YAAY;AAAA,MACZ,SAAS,cAAc,QAAQ,SAAS,WAAW,WAAW,QAAQ,UAAU,QAAQ,KAAK;AAAA,MAC7F,KAAK,cAAc,IAAI,SAAS,WAAW,SAAS,IAAI,UAAU,IAAI,KAAK;AAAA,MAC3E,YAAY;AAAA,QACV,UAAU;AAAA,QACV,WAAW;AAAA,QACX,UAAU;AAAA,QACV,UAAU;AAAA,MACZ;AAAA,MACA,YAAY;AAAA,QACV,WAAW;AAAA,QACX,WAAW;AAAA,QACX,WAAW;AAAA,QACX,WAAW;AAAA,MACb;AAAA,IACF;AAAA,IACA;AAAA,EACF;AACF;AAMA,SAAS,eAAe,QAAmC;AACzD,MAAI,OAAO,WAAW,UAAW,QAAO;AACxC,MAAI,OAAO,WAAW,SAAU,QAAO;AACvC,MAAI,OAAO,WAAW,OAAQ,QAAO;AACrC,SAAO;AACT;AAIA,SAAS,gBAAgB,QAAmC;AAC1D,MAAI,CAAC,OAAO,SAAS,OAAO,UAAU,OAAQ,QAAO;AACrD,SAAO,OAAO,UAAU,OAAO,YAAO;AACxC;AAEA,SAAS,iBAAiB,QAAmC;AAC3D,MAAI,OAAO,UAAU,OAAW,QAAO;AACvC,SAAO,IAAI,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC;AAC3C;AAEA,SAAS,eAAe,UAAiC;AACvD,MAAI,aAAa,KAAM,QAAO;AAC9B,SAAO,GAAG,KAAK,MAAM,WAAW,GAAG,CAAC;AACtC;AAEA,SAAS,aAAa,QAAoC;AACxD,MAAI,WAAW,OAAW,QAAO;AACjC,SAAO,UAAK,OAAO,QAAQ,CAAC,CAAC;AAC/B;AAEA,SAAS,YAAY,SAA6B,UAAsC;AACtF,MAAI,YAAY,UAAa,aAAa,OAAW,QAAO;AAC5D,MAAI,UAAU,SAAU,QAAO,iBAAY,SAAS,QAAQ,CAAC,CAAC;AAC9D,MAAI,UAAU,SAAU,QAAO,iBAAY,SAAS,QAAQ,CAAC,CAAC;AAC9D,SAAO;AACT;AAEA,SAAS,iBAAiB,QAAsC;AAC9D,SACE,OAAO,QAAQ,WAAW,aAC1B,OAAO,IAAI,WAAW,aACtB,OAAO,WAAW,WAAW,aAC7B,OAAO,WAAW,WAAW;AAEjC;AAEO,SAAS,kBAAkB,QAA2B;AAC3D,QAAM,QAAkB,CAAC;AACzB,QAAM,cAAc,OAAO,SACvB,aAAa,IAAI,KAAK,OAAO,SAAS,EAAE,mBAAmB,CAAC,MAC5D,cAAc,IAAI,KAAK,OAAO,SAAS,EAAE,mBAAmB,CAAC;AAEjE,QAAM,KAAK,QAAQ,OAAO,WAAW,GAAG,WAAW,EAAE;AACrD,QAAM,KAAK,EAAE;AAGb,QAAM,KAAK,UAAU;AACrB,MAAI,OAAO,SAAS,WAAW,GAAG;AAChC,UAAM,KAAK,sBAAsB;AAAA,EACnC,OAAO;AACL,UAAM,SAAS,KAAK,IAAI,IAAI,GAAG,OAAO,SAAS,IAAI,CAAC,MAAM,EAAE,MAAM,MAAM,CAAC;AACzE,UAAM,WAAW,KAAK,IAAI,GAAG,GAAG,OAAO,SAAS,IAAI,CAAC,MAAM,EAAE,YAAY,MAAM,CAAC;AAChF,UAAM,UAAU,KAAK,IAAI,GAAG,GAAG,OAAO,SAAS,IAAI,CAAC,MAAM,EAAE,OAAO,MAAM,CAAC;AAC1E,eAAW,KAAK,OAAO,UAAU;AAC/B,YAAM;AAAA,QACJ,KAAK,EAAE,MAAM,OAAO,MAAM,CAAC,KAAK,EAAE,YAAY,OAAO,QAAQ,CAAC,KAAK,EAAE,OAAO,OAAO,OAAO,CAAC,KAAK,eAAe,EAAE,YAAY,CAAC;AAAA,MAChI;AAAA,IACF;AAAA,EACF;AAGA,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,iBAAiB,OAAO,OAAO,UAAU,QAAQ;AAC5D,MAAI,iBAAiB,OAAO,MAAM,GAAG;AACnC,UAAM,KAAK,6CAA6C;AAAA,EAC1D,OAAO;AACL,UAAM,EAAE,SAAS,KAAK,YAAY,WAAW,IAAI,OAAO;AACxD,UAAM,WAAW,GAAG,iBAAiB,OAAO,CAAC,GAAG,gBAAgB,OAAO,CAAC;AACxE,UAAM,SAAS,GAAG,iBAAiB,GAAG,CAAC,GAAG,gBAAgB,GAAG,CAAC;AAC9D,UAAM,eAAe,GAAG,iBAAiB,UAAU,CAAC,GAAG,gBAAgB,UAAU,CAAC;AAClF,UAAM,gBAAgB,GAAG,iBAAiB,UAAU,CAAC,GAAG,gBAAgB,UAAU,CAAC;AACnF,UAAM;AAAA,MACJ,iBAAiB,SAAS,OAAO,EAAE,CAAC,KAAK,eAAe,OAAO,CAAC,mBAC/C,OAAO,OAAO,EAAE,CAAC,KAAK,eAAe,GAAG,CAAC;AAAA,IAC5D;AACA,UAAM;AAAA,MACJ,iBAAiB,aAAa,OAAO,EAAE,CAAC,KAAK,eAAe,UAAU,CAAC,mBACtD,cAAc,OAAO,EAAE,CAAC,KAAK,eAAe,UAAU,CAAC;AAAA,IAC1E;AAAA,EACF;AAGA,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,kBAAkB,OAAO,QAAQ,UAAU,QAAQ;AAC9D,QAAM,EAAE,eAAe,uBAAuB,UAAU,gBAAgB,IAAI,OAAO;AACnF,MAAI,aAAa,KAAK,kBAAkB,QAAW;AACjD,UAAM,KAAK,8BAA8B;AAAA,EAC3C,OAAO;AACL,UAAM,QAAQ,YAAY,eAAe,qBAAqB;AAC9D,UAAM,cAAc,oBAAoB,SAAY,KAAK,eAAe,eAAe;AACvF,UAAM,KAAK,KAAK,aAAa,aAAa,CAAC,MAAM,QAAQ,OAAO,WAAW,GAAG,KAAK,EAAE;AAAA,EACvF;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAMO,SAAS,oBAAoB,QAA2B;AAC7D,QAAM,QAAkB,CAAC,OAAO,WAAW;AAG3C,QAAM,gBACJ,OAAO,SAAS,KAAK,CAAC,MAAM,EAAE,WAAW,OAAO,KAAK,OAAO,SAAS,CAAC;AACxE,MAAI,eAAe;AACjB,UAAM,KAAK,IAAI,cAAc,WAAW,IAAI,cAAc,KAAK,EAAE;AAAA,EACnE;AAGA,QAAM,EAAE,SAAS,IAAI,IAAI,OAAO;AAChC,MAAI,QAAQ,WAAW,WAAW;AAChC,UAAM,QAAQ,QAAQ,UAAU,OAAO,YAAO,QAAQ,UAAU,SAAS,YAAO;AAChF,UAAM,KAAK,WAAW,iBAAiB,OAAO,CAAC,GAAG,KAAK,IAAI,eAAe,OAAO,CAAC,EAAE;AAAA,EACtF;AACA,MAAI,IAAI,WAAW,WAAW;AAC5B,UAAM,QAAQ,IAAI,UAAU,OAAO,YAAO,IAAI,UAAU,SAAS,YAAO;AACxE,UAAM,KAAK,OAAO,iBAAiB,GAAG,CAAC,GAAG,KAAK,IAAI,eAAe,GAAG,CAAC,EAAE;AAAA,EAC1E;AAGA,QAAM,EAAE,eAAe,SAAS,IAAI,OAAO;AAC3C,MAAI,kBAAkB,QAAW;AAC/B,UAAM,KAAK,OAAO,cAAc,QAAQ,CAAC,CAAC,QAAG;AAAA,EAC/C;AACA,MAAI,WAAW,GAAG;AAChB,UAAM,KAAK,GAAG,QAAQ,UAAU;AAAA,EAClC;AAEA,SAAO,MAAM,KAAK,QAAK,KAAK,gBAAgB,MAAM,IAAI,aAAa;AACrE;AAMO,SAAS,kBAAkB,MAAiB,MAA6B;AAC9E,QAAM,cAAc,KAAK,SAAS,CAAC,GAAG,eAAe;AACrD,QAAM,cAAc,KAAK,SAAS,CAAC,GAAG,eAAe;AACrD,QAAM,YAAY,KAAK,OAAO,QAAQ,SAAS;AAC/C,QAAM,YAAY,KAAK,OAAO,QAAQ,SAAS;AAC/C,QAAM,UAAU,KAAK,OAAO,IAAI,SAAS;AACzC,QAAM,UAAU,KAAK,OAAO,IAAI,SAAS;AACzC,QAAM,aAAa,KAAK,QAAQ,iBAAiB;AACjD,QAAM,aAAa,KAAK,QAAQ,iBAAiB;AAEjD,SAAO;AAAA,IACL,aAAa,EAAE,MAAM,aAAa,IAAI,YAAY;AAAA,IAClD,WAAW;AAAA,MACT,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,OAAO,cAAc,QAAQ,cAAc,OAAO,YAAY,YAAY;AAAA,IAC5E;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,OAAO,YAAY,QAAQ,YAAY,OAAO,UAAU,UAAU;AAAA,IACpE;AAAA,IACA,aAAa,EAAE,MAAM,KAAK,QAAQ,UAAU,IAAI,KAAK,QAAQ,SAAS;AAAA,IACtE,eAAe;AAAA,MACb,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,OACE,eAAe,QAAQ,eAAe,OAClC,KAAK,OAAO,aAAa,cAAc,EAAE,IAAI,KAC7C;AAAA,IACR;AAAA,EACF;AACF;AAEO,SAAS,iBAAiB,MAAkB,OAAuB;AACxE,QAAM,QAAkB,CAAC,iBAAiB,KAAK,GAAG;AAElD,MAAI,KAAK,YAAY,SAAS,KAAK,YAAY,IAAI;AACjD,UAAM,KAAK,iBAAiB,KAAK,YAAY,QAAQ,QAAG,WAAM,KAAK,YAAY,MAAM,QAAG,EAAE;AAAA,EAC5F;AAEA,QAAM,UAAU,CAAC,MACf,MAAM,OAAO,IAAI,IAAI,KAAK,QAAQ,CAAC,CAAC,MAAM;AAE5C,QAAM,WAAW,CAAC,GAAkB,gBAAgB,SAAiB;AACnE,QAAI,MAAM,QAAQ,KAAK,IAAI,CAAC,IAAI,KAAQ,QAAO;AAC/C,UAAM,OAAO,IAAI,IAAI,MAAM;AAC3B,UAAM,OAAO,gBAAgB,IAAI,IAAI,IAAI;AACzC,WAAO,GAAG,IAAI,IAAI,IAAI,KAAK,QAAQ,CAAC,CAAC,KAAK,OAAO,WAAM,QAAG;AAAA,EAC5D;AAEA,QAAM;AAAA,IACJ,iBAAiB,QAAQ,KAAK,UAAU,IAAI,CAAC,WAAM,QAAQ,KAAK,UAAU,EAAE,CAAC,KAAK,SAAS,KAAK,UAAU,KAAK,CAAC;AAAA,EAClH;AACA,QAAM;AAAA,IACJ,iBAAiB,QAAQ,KAAK,QAAQ,IAAI,CAAC,WAAM,QAAQ,KAAK,QAAQ,EAAE,CAAC,KAAK,SAAS,KAAK,QAAQ,KAAK,CAAC;AAAA,EAC5G;AAEA,QAAM,cAAc,KAAK,cAAc;AACvC,QAAM,QACJ,KAAK,cAAc,SAAS,OAAO,GAAG,KAAK,cAAc,KAAK,QAAQ,CAAC,CAAC,WAAM;AAChF,QAAM,QACJ,KAAK,cAAc,OAAO,OAAO,GAAG,KAAK,cAAc,GAAG,QAAQ,CAAC,CAAC,WAAM;AAC5E,QAAM,YACJ,gBAAgB,QAAQ,KAAK,IAAI,WAAW,IAAI,OAC5C,cACA,GAAG,cAAc,IAAI,MAAM,EAAE,GAAG,YAAY,QAAQ,CAAC,CAAC,IAAI,cAAc,IAAI,WAAM,QAAG;AAC3F,QAAM,KAAK,iBAAiB,KAAK,WAAM,KAAK,KAAK,SAAS,GAAG;AAE7D,SAAO,MAAM,KAAK,IAAI;AACxB;AAMA,eAAsB,aAAa,MAAmC;AACpE,MAAI,KAAK,kBAAkB,IAAI;AAC7B,YAAQ,MAAM,qDAAqD;AACnE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,UAAU;AAEd,QAAM,UAAU,MAAM;AACpB,cAAU;AACV,YAAQ,OAAO,MAAM,IAAI;AACzB,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,UAAQ,GAAG,UAAU,OAAO;AAC5B,UAAQ,GAAG,WAAW,OAAO;AAE7B,SAAO,SAAS;AACd,YAAQ,OAAO,MAAM,eAAe;AAEpC,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,MAAM;AAChC,YAAM,KAAK,KAAK,MAAM;AACtB,cAAQ,IAAI,KAAK,OAAO,MAAM,CAAC;AAAA,IACjC,SAAS,KAAK;AACZ,cAAQ,MAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,IAC5E;AAEA,YAAQ,IAAI;AAAA,6BAAgC,KAAK,eAAe,0BAAqB;AAGrF,aAAS,IAAI,GAAG,IAAI,KAAK,mBAAmB,SAAS,KAAK;AACxD,YAAM,IAAI,QAAc,CAAC,MAAM,WAAW,GAAG,GAAI,CAAC;AAAA,IACpD;AAAA,EACF;AACF;AAMA,SAAS,oBAAoB,aAA6B;AACxD,SAAOJ,MAAK,YAAY,GAAG,gBAAgB,WAAW,OAAO;AAC/D;AAGA,eAAsB,iBACpB,aACA,aACkB;AAClB,QAAM,WAAW,oBAAoB,WAAW;AAChD,MAAI,gBAAgB;AAEpB,MAAI;AACF,UAAM,MAAM,MAAMC,WAAS,UAAU,OAAO;AAC5C,oBAAiB,KAAK,MAAM,GAAG,EAA6B;AAAA,EAC9D,QAAQ;AAAA,EAER;AAEA,MAAI,kBAAkB,aAAa;AACjC,QAAI;AACF,YAAMC,OAAM,YAAY,GAAG,EAAE,WAAW,KAAK,CAAC;AAC9C,YAAMC;AAAA,QACJ;AAAA,QACA,KAAK,UAAU,EAAE,WAAW,aAAa,QAAO,oBAAI,KAAK,GAAE,YAAY,EAAE,GAAG,MAAM,CAAC;AAAA,QACnF,EAAE,UAAU,SAAS,MAAM,IAAM;AAAA,MACnC;AAAA,IACF,QAAQ;AAAA,IAER;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,SAAS,iBAAiB,OAAe,MAAoB;AAClE,MAAI,QAAQ,IAAI,IAAI,EAAG;AAEvB,MAAI;AACF,UAAM,IAAI,QAAQ;AAClB,QAAI,MAAM,UAAU;AAClB;AAAA,QACE,sCAAsC,KAAK,UAAU,IAAI,CAAC,eAAe,KAAK,UAAU,KAAK,CAAC;AAAA,QAC9F,EAAE,OAAO,SAAS;AAAA,MACpB;AAAA,IACF,WAAW,MAAM,SAAS;AACxB,eAAS,eAAe,KAAK,UAAU,KAAK,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,IAAI;AAAA,QACvE,OAAO;AAAA,MACT,CAAC;AAAA,IACH,WAAW,MAAM,SAAS;AACxB,YAAM,UAAU,CAAC,MAAc,EAAE,QAAQ,MAAM,IAAI;AACnD;AAAA,QACE,8GAA8G,QAAQ,IAAI,CAAC,OAAO,QAAQ,KAAK,CAAC;AAAA,QAChJ,EAAE,OAAO,SAAS;AAAA,MACpB;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AACF;AAMO,SAAS,gBAAgB,QAA4B;AAC1D,SACE,OAAO,OAAO,QAAQ,WAAW,YACjC,OAAO,OAAO,IAAI,WAAW,YAC7B,OAAO,OAAO,WAAW,WAAW,YACpC,OAAO,OAAO,WAAW,WAAW;AAExC;","names":["process","edit","stat","extname","formatSize","readFile","stat","mkdir","writeFile","join","readdir","readFile","writeFile","mkdir","join","readdir","readFile","stat","extname","join","readdir","extname","join","stat","readFile","stat","formatSize","stat","upload","toApiDate","paginateAll","paginateAll","readdir","readFile","join","paginateAll","paginateAll","readdir","readFile","join","paginateAll","paginateAll","paginateAll","readFile","readFile","readFile","writeFile","writeFile","readFile","process","mkdir","writeFile","join","mkdir","readFile","writeFile","join","join","readFile","writeFile","extname","extname","writeFile","writeFile","readFile","stat","detectFileType","mkdir","readFile","writeFile","join","join","readFile","mkdir","writeFile","METRIC_SET_METRICS"]}