@gpc-cli/core 0.9.6 → 0.9.7

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/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/safe-path.ts","../src/commands/plugin-scaffold.ts","../src/audit.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 default:\n return formatJson(safe);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Sensitive field redaction\n// ---------------------------------------------------------------------------\n\nconst 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]);\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\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) => String(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) => String(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) => String(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) => String(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","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 } from \"@gpc-cli/api\";\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 Error(`File validation failed:\\n${validation.errors.join(\"\\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 Error(`No active release found on track \"${fromTrack}\"`);\n }\n\n // Create release on target track\n if (options?.userFraction && (options.userFraction <= 0 || options.userFraction > 1)) {\n throw new Error(\"Rollout percentage must be between 0 and 1 (e.g., 0.1 for 10%)\");\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 Error(`No active rollout found on track \"${track}\"`);\n }\n\n let newStatus: string;\n let newFraction: number | undefined;\n\n switch (action) {\n case \"increase\":\n if (!userFraction) throw new Error(\"--to <percentage> is required for rollout increase\");\n if (userFraction <= 0 || userFraction > 1) {\n throw new Error(\"Rollout percentage must be between 0 and 1 (e.g., 0.1 for 10%)\");\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","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 { 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 Error(`Invalid language tag \"${lang}\". Must be a valid Google Play BCP 47 code.`);\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 Error(`No listings found in directory \"${dir}\"`);\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 Error(`Image validation failed: ${imageCheck.errors.join(\"; \")}`);\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 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 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, stat } from \"node:fs/promises\";\nimport { extname, basename, join } from \"node:path\";\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 Error(`Release notes directory not found: ${dir}`);\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}\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 // 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} file (${formatSize(fileResult.sizeBytes)})`\n : fileResult.errors.join(\"; \"),\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 };\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\";\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 Error(\n `Reply text exceeds ${MAX_REPLY_LENGTH} characters (${replyText.length}). Google Play limits replies to ${MAX_REPLY_LENGTH} characters.`,\n );\n }\n if (replyText.length === 0) {\n throw new Error(\"Reply text cannot be empty.\");\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\nfunction buildQuery(options?: VitalsQueryOptions): MetricSetQuery {\n const query: MetricSetQuery = {\n metrics: [\"errorReportCount\", \"distinctUsers\"],\n };\n\n if (options?.dimension) {\n query.dimensions = [options.dimension];\n }\n\n if (options?.days) {\n const end = new Date();\n const start = new Date();\n start.setDate(start.getDate() - options.days);\n query.timelineSpec = {\n aggregationPeriod: options.aggregation ?? \"DAILY\",\n startTime: {\n year: start.getFullYear(),\n month: start.getMonth() + 1,\n day: start.getDate(),\n },\n endTime: {\n year: end.getFullYear(),\n month: end.getMonth() + 1,\n day: end.getDate(),\n },\n };\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(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 [\"vitals.crashrate\", \"crashRate\"],\n [\"vitals.anrrate\", \"anrRate\"],\n [\"vitals.slowstartrate\", \"slowStartRate\"],\n [\"vitals.slowrenderingrate\", \"slowRenderingRate\"],\n [\"vitals.excessivewakeuprate\", \"excessiveWakeupRate\"],\n [\"vitals.stuckbackgroundwakelockrate\", \"stuckWakelockRate\"],\n ];\n\n const results = await Promise.allSettled(\n metricSets.map(([metric]) =>\n reporting.queryMetricSet(packageName, metric, {\n metrics: [\"errorReportCount\", \"distinctUsers\"],\n }),\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, \"vitals.crashrate\", options);\n}\n\nexport async function getVitalsAnr(\n reporting: ReportingApiClient,\n packageName: string,\n options?: VitalsQueryOptions,\n): Promise<MetricSetResponse> {\n return queryMetric(reporting, packageName, \"vitals.anrrate\", options);\n}\n\nexport async function getVitalsStartup(\n reporting: ReportingApiClient,\n packageName: string,\n options?: VitalsQueryOptions,\n): Promise<MetricSetResponse> {\n return queryMetric(reporting, packageName, \"vitals.slowstartrate\", options);\n}\n\nexport async function getVitalsRendering(\n reporting: ReportingApiClient,\n packageName: string,\n options?: VitalsQueryOptions,\n): Promise<MetricSetResponse> {\n return queryMetric(reporting, packageName, \"vitals.slowrenderingrate\", options);\n}\n\nexport async function getVitalsBattery(\n reporting: ReportingApiClient,\n packageName: string,\n options?: VitalsQueryOptions,\n): Promise<MetricSetResponse> {\n return queryMetric(reporting, packageName, \"vitals.excessivewakeuprate\", options);\n}\n\nexport async function getVitalsMemory(\n reporting: ReportingApiClient,\n packageName: string,\n options?: VitalsQueryOptions,\n): Promise<MetricSetResponse> {\n return queryMetric(reporting, packageName, \"vitals.stuckbackgroundwakelockrate\", 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 now = new Date();\n\n // Current period\n const currentEnd = new Date(now);\n const currentStart = new Date(now);\n currentStart.setDate(currentStart.getDate() - days);\n\n // Previous period\n const previousEnd = new Date(currentStart);\n const previousStart = new Date(previousEnd);\n previousStart.setDate(previousStart.getDate() - days);\n\n const makeQuery = (start: Date, end: Date): MetricSetQuery => ({\n metrics: [\"errorReportCount\", \"distinctUsers\"],\n timelineSpec: {\n aggregationPeriod: \"DAILY\",\n startTime: { year: start.getFullYear(), month: start.getMonth() + 1, day: start.getDate() },\n endTime: { year: end.getFullYear(), month: end.getMonth() + 1, day: end.getDate() },\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} from \"@gpc-cli/api\";\nimport { paginateAll } from \"@gpc-cli/api\";\n\nexport interface ListSubscriptionsOptions {\n pageToken?: string;\n pageSize?: number;\n limit?: number;\n nextPage?: string;\n}\n\nexport async function listSubscriptions(\n client: PlayApiClient,\n packageName: string,\n options?: ListSubscriptionsOptions,\n): Promise<{ subscriptions: Subscription[]; nextPageToken?: string }> {\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 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 return client.subscriptions.create(packageName, data);\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 return client.subscriptions.update(packageName, productId, data, updateMask);\n}\n\nexport async function deleteSubscription(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n): Promise<void> {\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 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 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 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 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 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 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 return client.subscriptions.createOffer(packageName, productId, basePlanId, data);\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 return client.subscriptions.updateOffer(\n packageName,\n productId,\n basePlanId,\n offerId,\n data,\n updateMask,\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 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 return client.subscriptions.activateOffer(packageName, productId, basePlanId, offerId);\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 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 } from \"@gpc-cli/api\";\nimport { paginateAll } from \"@gpc-cli/api\";\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 files = await readdir(dir);\n const jsonFiles = files.filter((f) => f.endsWith(\".json\"));\n\n if (jsonFiles.length === 0) {\n return { created: 0, updated: 0, unchanged: 0, skus: [] };\n }\n\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 Error(`Failed to parse ${file}: invalid JSON`);\n }\n }\n\n const response = await client.inappproducts.list(packageName);\n const remoteSkus = new Set((response.inappproduct || []).map((p) => p.sku));\n\n let created = 0;\n let updated = 0;\n const unchanged = 0;\n const skus: string[] = [];\n\n for (const product of localProducts) {\n skus.push(product.sku);\n if (remoteSkus.has(product.sku)) {\n if (!options?.dryRun) {\n await client.inappproducts.update(packageName, product.sku, product);\n }\n updated++;\n } else {\n if (!options?.dryRun) {\n await client.inappproducts.create(packageName, product);\n }\n created++;\n }\n }\n\n return { created, updated, unchanged, skus };\n}\n","import type {\n PlayApiClient,\n ProductPurchase,\n SubscriptionPurchaseV2,\n SubscriptionDeferResponse,\n} from \"@gpc-cli/api\";\n\nexport async function getProductPurchase(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n token: string,\n): Promise<ProductPurchase> {\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 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 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 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 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 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 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 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 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\";\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 Error(`Invalid month format \"${monthStr}\". Expected YYYY-MM (e.g., 2026-03).`);\n }\n const year = Number(match[1]);\n const month = Number(match[2]);\n if (month < 1 || month > 12) {\n throw new Error(`Invalid month \"${month}\". Must be between 01 and 12.`);\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 const response = await client.reports.list(packageName, reportType, year, month);\n return response.reports || [];\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 const reports = await listReports(client, packageName, reportType, year, month);\n\n if (reports.length === 0) {\n throw new Error(\n `No ${reportType} reports found for ${year}-${String(month).padStart(2, \"0\")}.`,\n );\n }\n\n // Download the first report bucket (signed URI — no auth needed)\n const bucket = reports[0];\n if (!bucket) {\n throw new Error(\n `No ${reportType} reports found for ${year}-${String(month).padStart(2, \"0\")}.`,\n );\n }\n const uri = bucket.uri;\n const response = await fetch(uri);\n\n if (!response.ok) {\n throw new Error(`Failed to download report from signed URI: HTTP ${response.status}`);\n }\n\n return response.text();\n}\n","import type { UsersApiClient, User, DeveloperPermission, Grant } from \"@gpc-cli/api\";\nimport { paginateAll } from \"@gpc-cli/api\";\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 Error(\n `Invalid grant format \"${grantStr}\". Expected <packageName>:<PERMISSION>[,<PERMISSION>...]`,\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\";\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 Error(`No valid email addresses found in ${csvPath}.`);\n }\n\n const testers = await addTesters(client, packageName, track, emails);\n return { added: emails.length, testers };\n}\n","import { resolve, normalize } from \"node:path\";\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 Error(`Path \"${userPath}\" resolves outside the expected directory \"${baseDir}\"`);\n }\n\n return resolved;\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 } 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 \"key\",\n \"keyFile\",\n \"key-file\",\n \"serviceAccount\",\n \"service-account\",\n \"token\",\n \"password\",\n \"secret\",\n \"credentials\",\n \"private_key\",\n \"client_secret\",\n]);\n\nfunction 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"],"mappings":"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","names":["edit","stat","extname","formatSize","readFile","stat","readdir","readFile","stat","extname","join","stat","formatSize","stat","upload","paginateAll","readdir","readFile","join","paginateAll","paginateAll","paginateAll","readFile","mkdir","writeFile","join","mkdir","join"]}
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/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/utils/safe-path.ts","../src/utils/sort.ts","../src/commands/plugin-scaffold.ts","../src/audit.ts","../src/utils/webhooks.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 default:\n return formatJson(safe);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Sensitive field redaction\n// ---------------------------------------------------------------------------\n\nconst 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]);\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\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) => String(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) => String(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) => String(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) => String(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","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 } 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","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 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, 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}\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 // 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} file (${formatSize(fileResult.sizeBytes)})`\n : fileResult.errors.join(\"; \"),\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 };\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\nfunction buildQuery(options?: VitalsQueryOptions): MetricSetQuery {\n const query: MetricSetQuery = {\n metrics: [\"errorReportCount\", \"distinctUsers\"],\n };\n\n if (options?.dimension) {\n query.dimensions = [options.dimension];\n }\n\n if (options?.days) {\n const end = new Date();\n const start = new Date();\n start.setDate(start.getDate() - options.days);\n query.timelineSpec = {\n aggregationPeriod: options.aggregation ?? \"DAILY\",\n startTime: {\n year: start.getFullYear(),\n month: start.getMonth() + 1,\n day: start.getDate(),\n },\n endTime: {\n year: end.getFullYear(),\n month: end.getMonth() + 1,\n day: end.getDate(),\n },\n };\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(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 [\"vitals.crashrate\", \"crashRate\"],\n [\"vitals.anrrate\", \"anrRate\"],\n [\"vitals.slowstartrate\", \"slowStartRate\"],\n [\"vitals.slowrenderingrate\", \"slowRenderingRate\"],\n [\"vitals.excessivewakeuprate\", \"excessiveWakeupRate\"],\n [\"vitals.stuckbackgroundwakelockrate\", \"stuckWakelockRate\"],\n ];\n\n const results = await Promise.allSettled(\n metricSets.map(([metric]) =>\n reporting.queryMetricSet(packageName, metric, {\n metrics: [\"errorReportCount\", \"distinctUsers\"],\n }),\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, \"vitals.crashrate\", options);\n}\n\nexport async function getVitalsAnr(\n reporting: ReportingApiClient,\n packageName: string,\n options?: VitalsQueryOptions,\n): Promise<MetricSetResponse> {\n return queryMetric(reporting, packageName, \"vitals.anrrate\", options);\n}\n\nexport async function getVitalsStartup(\n reporting: ReportingApiClient,\n packageName: string,\n options?: VitalsQueryOptions,\n): Promise<MetricSetResponse> {\n return queryMetric(reporting, packageName, \"vitals.slowstartrate\", options);\n}\n\nexport async function getVitalsRendering(\n reporting: ReportingApiClient,\n packageName: string,\n options?: VitalsQueryOptions,\n): Promise<MetricSetResponse> {\n return queryMetric(reporting, packageName, \"vitals.slowrenderingrate\", options);\n}\n\nexport async function getVitalsBattery(\n reporting: ReportingApiClient,\n packageName: string,\n options?: VitalsQueryOptions,\n): Promise<MetricSetResponse> {\n return queryMetric(reporting, packageName, \"vitals.excessivewakeuprate\", options);\n}\n\nexport async function getVitalsMemory(\n reporting: ReportingApiClient,\n packageName: string,\n options?: VitalsQueryOptions,\n): Promise<MetricSetResponse> {\n return queryMetric(reporting, packageName, \"vitals.stuckbackgroundwakelockrate\", 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 now = new Date();\n\n // Current period\n const currentEnd = new Date(now);\n const currentStart = new Date(now);\n currentStart.setDate(currentStart.getDate() - days);\n\n // Previous period\n const previousEnd = new Date(currentStart);\n const previousStart = new Date(previousEnd);\n previousStart.setDate(previousStart.getDate() - days);\n\n const makeQuery = (start: Date, end: Date): MetricSetQuery => ({\n metrics: [\"errorReportCount\", \"distinctUsers\"],\n timelineSpec: {\n aggregationPeriod: \"DAILY\",\n startTime: { year: start.getFullYear(), month: start.getMonth() + 1, day: start.getDate() },\n endTime: { year: end.getFullYear(), month: end.getMonth() + 1, day: end.getDate() },\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} from \"@gpc-cli/api\";\nimport { paginateAll } from \"@gpc-cli/api\";\n\nexport interface ListSubscriptionsOptions {\n pageToken?: string;\n pageSize?: number;\n limit?: number;\n nextPage?: string;\n}\n\nexport async function listSubscriptions(\n client: PlayApiClient,\n packageName: string,\n options?: ListSubscriptionsOptions,\n): Promise<{ subscriptions: Subscription[]; nextPageToken?: string }> {\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 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 return client.subscriptions.create(packageName, data);\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 return client.subscriptions.update(packageName, productId, data, updateMask);\n}\n\nexport async function deleteSubscription(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n): Promise<void> {\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 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 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 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 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 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 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 return client.subscriptions.createOffer(packageName, productId, basePlanId, data);\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 return client.subscriptions.updateOffer(\n packageName,\n productId,\n basePlanId,\n offerId,\n data,\n updateMask,\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 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 return client.subscriptions.activateOffer(packageName, productId, basePlanId, offerId);\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 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 } 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 files = await readdir(dir);\n const jsonFiles = files.filter((f) => f.endsWith(\".json\"));\n\n if (jsonFiles.length === 0) {\n return { created: 0, updated: 0, unchanged: 0, skus: [] };\n }\n\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\n const response = await client.inappproducts.list(packageName);\n const remoteSkus = new Set((response.inappproduct || []).map((p) => p.sku));\n\n let created = 0;\n let updated = 0;\n const unchanged = 0;\n const skus: string[] = [];\n\n for (const product of localProducts) {\n skus.push(product.sku);\n if (remoteSkus.has(product.sku)) {\n if (!options?.dryRun) {\n await client.inappproducts.update(packageName, product.sku, product);\n }\n updated++;\n } else {\n if (!options?.dryRun) {\n await client.inappproducts.create(packageName, product);\n }\n created++;\n }\n }\n\n return { created, updated, unchanged, skus };\n}\n","import type {\n PlayApiClient,\n ProductPurchase,\n SubscriptionPurchaseV2,\n SubscriptionDeferResponse,\n} from \"@gpc-cli/api\";\n\nexport async function getProductPurchase(\n client: PlayApiClient,\n packageName: string,\n productId: string,\n token: string,\n): Promise<ProductPurchase> {\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 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 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 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 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 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 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 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 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, NetworkError } 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 const response = await client.reports.list(packageName, reportType, year, month);\n return response.reports || [];\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 const reports = await listReports(client, packageName, reportType, year, month);\n\n const monthPadded = String(month).padStart(2, \"0\");\n if (reports.length === 0) {\n throw new GpcError(\n `No ${reportType} reports found for ${year}-${monthPadded}.`,\n \"REPORT_NOT_FOUND\",\n 1,\n `Reports may not be available yet for this period. Financial reports are typically available a few days after the month ends. Try a different month or report type.`,\n );\n }\n\n // Download the first report bucket (signed URI — no auth needed)\n const bucket = reports[0];\n if (!bucket) {\n throw new GpcError(\n `No ${reportType} reports found for ${year}-${monthPadded}.`,\n \"REPORT_NOT_FOUND\",\n 1,\n `Reports may not be available yet for this period. Try a different month or report type.`,\n );\n }\n const uri = bucket.uri;\n const response = await fetch(uri);\n\n if (!response.ok) {\n throw new NetworkError(\n `Failed to download report from signed URI: HTTP ${response.status}`,\n \"The signed download URL may have expired. Retry the command to generate a fresh URL.\",\n );\n }\n\n return response.text();\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}\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): string {\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\n if (text.length > maxLength) {\n text = text.slice(0, maxLength - 3) + \"...\";\n }\n\n return text;\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 };\n }\n\n const subjects = logOutput.split(\"\\n\").filter((line) => line.length > 0);\n const commits = subjects.map(parseConventionalCommit);\n const text = formatNotes(commits, maxLength);\n\n return {\n language,\n text,\n commitCount: subjects.length,\n since,\n };\n}\n","import type { PlayApiClient, AppRecoveryAction } from \"@gpc-cli/api\";\n\nexport async function listRecoveryActions(\n client: PlayApiClient,\n packageName: string,\n): Promise<AppRecoveryAction[]> {\n return client.appRecovery.list(packageName);\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","import type { PlayApiClient, DataSafety } from \"@gpc-cli/api\";\nimport { readFile, writeFile } from \"node:fs/promises\";\n\nexport async function getDataSafety(\n client: PlayApiClient,\n packageName: string,\n): Promise<DataSafety> {\n const edit = await client.edits.insert(packageName);\n try {\n const dataSafety = await client.dataSafety.get(packageName, edit.id);\n await client.edits.delete(packageName, edit.id);\n return dataSafety;\n } catch (error) {\n await client.edits.delete(packageName, edit.id).catch(() => {});\n throw error;\n }\n}\n\nexport async function updateDataSafety(\n client: PlayApiClient,\n packageName: string,\n data: DataSafety,\n): Promise<DataSafety> {\n const edit = await client.edits.insert(packageName);\n try {\n const result = await client.dataSafety.update(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\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 Error(`Failed to parse data safety JSON from \"${filePath}\"`);\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 { 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 } 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 \"key\",\n \"keyFile\",\n \"key-file\",\n \"serviceAccount\",\n \"service-account\",\n \"token\",\n \"password\",\n \"secret\",\n \"credentials\",\n \"private_key\",\n \"client_secret\",\n]);\n\nfunction 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","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"],"mappings":"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","names":["edit","stat","extname","formatSize","readFile","stat","readdir","readFile","stat","extname","join","readdir","extname","join","stat","readFile","stat","formatSize","stat","upload","paginateAll","readdir","readFile","join","paginateAll","paginateAll","readdir","readFile","join","paginateAll","paginateAll","paginateAll","readFile","readFile","readFile","writeFile","mkdir","writeFile","join","mkdir","join"]}