@gpc-cli/cli 0.9.64 → 0.9.66
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -12
- package/dist/bin.js +2 -2
- package/dist/{changelog-EHQYZP22.js → changelog-STYBBYDC.js} +8 -2
- package/dist/changelog-STYBBYDC.js.map +1 -0
- package/dist/{chunk-I3SFXLIY.js → chunk-IUG4225Q.js} +11 -11
- package/dist/{config-SK7BOURM.js → config-DDZMNYOB.js} +2 -2
- package/dist/{docs-WVJCDX5X.js → docs-OU6LSSJD.js} +16 -7
- package/dist/{docs-WVJCDX5X.js.map → docs-OU6LSSJD.js.map} +1 -1
- package/dist/{doctor-FSUI44DD.js → doctor-QRHXY3FC.js} +181 -10
- package/dist/doctor-QRHXY3FC.js.map +1 -0
- package/dist/{feedback-PDQU5E6S.js → feedback-C2BA7CK6.js} +2 -2
- package/dist/generated/docs-bundle.json +1 -1
- package/dist/index.js +1 -1
- package/dist/{preflight-KIWZPFTX.js → preflight-BL67VGUX.js} +54 -1
- package/dist/preflight-BL67VGUX.js.map +1 -0
- package/dist/{update-E4VGHQUR.js → update-GEH352BE.js} +2 -2
- package/dist/verify-O2PSBTIC.js +330 -0
- package/dist/verify-O2PSBTIC.js.map +1 -0
- package/dist/{version-HXUIOHCL.js → version-2RUEWMPK.js} +2 -2
- package/package.json +4 -4
- package/dist/changelog-EHQYZP22.js.map +0 -1
- package/dist/doctor-FSUI44DD.js.map +0 -1
- package/dist/preflight-KIWZPFTX.js.map +0 -1
- package/dist/verify-H4ZUVHMZ.js +0 -98
- package/dist/verify-H4ZUVHMZ.js.map +0 -1
- /package/dist/{chunk-I3SFXLIY.js.map → chunk-IUG4225Q.js.map} +0 -0
- /package/dist/{config-SK7BOURM.js.map → config-DDZMNYOB.js.map} +0 -0
- /package/dist/{feedback-PDQU5E6S.js.map → feedback-C2BA7CK6.js.map} +0 -0
- /package/dist/{update-E4VGHQUR.js.map → update-GEH352BE.js.map} +0 -0
- /package/dist/{version-HXUIOHCL.js.map → version-2RUEWMPK.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/doctor.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport { loadConfig, getCacheDir, getConfigDir } from \"@gpc-cli/config\";\nimport { green, red, yellow } from \"../colors.js\";\nimport { resolveAuth, AuthError } from \"@gpc-cli/auth\";\nimport { existsSync, accessSync, statSync, constants } from \"node:fs\";\nimport { readFile, stat, statfs } from \"node:fs/promises\";\nimport { resolve, join } from \"node:path\";\nimport { lookup } from \"node:dns/promises\";\nimport { isNewerVersion } from \"../update-check.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface CheckResult {\n name: string;\n status: \"pass\" | \"fail\" | \"warn\" | \"info\";\n message: string;\n suggestion?: string;\n /** Structured data for applyFix — avoids fragile regex on suggestion text. */\n fixData?: Record<string, string>;\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst PASS = \"\\u2713\";\nconst FAIL = \"\\u2717\";\nconst WARN = \"\\u26A0\";\nconst INFO = \"-\";\n\nconst ANDROID_PACKAGE_RE = /^[a-zA-Z][a-zA-Z0-9_]*(\\.[a-zA-Z][a-zA-Z0-9_]*)+$/;\n\n/** All user-facing keys accepted in .gpcrc.json / config.json. */\nconst KNOWN_CONFIG_KEYS = new Set([\n \"app\",\n \"output\",\n \"profile\",\n \"auth\",\n \"developerId\",\n \"plugins\",\n \"profiles\",\n \"approvedPlugins\",\n \"webhooks\",\n \"debug\",\n \"train\",\n]);\n\nconst NPM_REGISTRY_URL = \"https://registry.npmjs.org/@gpc-cli/cli/latest\";\nconst API_HOST = \"androidpublisher.googleapis.com\";\nconst REPORTING_HOST = \"playdeveloperreporting.googleapis.com\";\nconst SA_KEY_ROTATION_DAYS = 90;\n\n// ---------------------------------------------------------------------------\n// Display helpers\n// ---------------------------------------------------------------------------\n\nfunction icon(status: CheckResult[\"status\"]): string {\n switch (status) {\n case \"pass\":\n return green(PASS);\n case \"fail\":\n return red(FAIL);\n case \"warn\":\n return yellow(WARN);\n case \"info\":\n return INFO;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Pure, testable check helpers\n// ---------------------------------------------------------------------------\n\nexport function checkNodeVersion(nodeVersion: string): CheckResult {\n const major = parseInt(nodeVersion.split(\".\")[0] ?? \"0\", 10);\n return major >= 20\n ? { name: \"node\", status: \"pass\", message: `Node.js ${nodeVersion}` }\n : {\n name: \"node\",\n status: \"fail\",\n message: `Node.js ${nodeVersion} (requires >=20)`,\n suggestion: \"Upgrade Node.js to v20 or later: https://nodejs.org\",\n };\n}\n\nexport function checkPackageName(app: string | undefined): CheckResult | null {\n if (!app) return null;\n return ANDROID_PACKAGE_RE.test(app)\n ? { name: \"package-name\", status: \"pass\", message: `Package name format OK: ${app}` }\n : {\n name: \"package-name\",\n status: \"warn\",\n message: `Package name may be invalid: ${app}`,\n suggestion:\n \"Android package names must have 2+ dot-separated segments, each starting with a letter (e.g. com.example.app)\",\n };\n}\n\nexport function checkProxy(url: string | undefined): CheckResult | null {\n if (!url) return null;\n try {\n new URL(url);\n return { name: \"proxy\", status: \"pass\", message: `Proxy configured: ${url}` };\n } catch {\n return {\n name: \"proxy\",\n status: \"warn\",\n message: `Invalid proxy URL: ${url}`,\n suggestion: \"Set HTTPS_PROXY to a valid URL (e.g. http://proxy.example.com:8080)\",\n };\n }\n}\n\nexport function checkDeveloperId(id: string | undefined): CheckResult | null {\n if (!id) return null;\n if (/^\\d+$/.test(id)) {\n return { name: \"developer-id\", status: \"pass\", message: `Developer ID: ${id}` };\n }\n return {\n name: \"developer-id\",\n status: \"warn\",\n message: `Developer ID may be invalid: ${id}`,\n suggestion:\n \"Developer IDs are numeric. Find yours at: Play Console → Settings → Developer account → Developer ID\",\n };\n}\n\nexport function checkConflictingCredentials(configSaPath?: string): CheckResult | null {\n const sources: string[] = [];\n if (configSaPath) sources.push(\"config file (auth.serviceAccount)\");\n if (process.env[\"GPC_SERVICE_ACCOUNT\"]) sources.push(\"GPC_SERVICE_ACCOUNT env var\");\n if (process.env[\"GOOGLE_APPLICATION_CREDENTIALS\"])\n sources.push(\"GOOGLE_APPLICATION_CREDENTIALS env var\");\n\n if (sources.length <= 1) return null;\n return {\n name: \"credentials-conflict\",\n status: \"warn\",\n message: `Multiple credential sources: ${sources.join(\", \")}`,\n suggestion:\n \"GPC uses the first match: config file → GPC_SERVICE_ACCOUNT → GOOGLE_APPLICATION_CREDENTIALS → ADC. Remove unused sources to avoid confusion.\",\n };\n}\n\nexport function checkConfigKeys(config: Record<string, unknown>): CheckResult | null {\n const unknown = Object.keys(config).filter((k) => !KNOWN_CONFIG_KEYS.has(k));\n if (unknown.length === 0) return null;\n return {\n name: \"config-keys\",\n status: \"warn\",\n message: `Unknown config key${unknown.length > 1 ? \"s\" : \"\"}: ${unknown.join(\", \")}`,\n suggestion: `Valid keys: ${[...KNOWN_CONFIG_KEYS].sort().join(\", \")}`,\n fixData: { keys: unknown.join(\", \") },\n };\n}\n\nexport function checkCiEnvironment(): CheckResult | null {\n if (!process.env[\"CI\"]) return null;\n\n let platform = \"Unknown CI\";\n if (process.env[\"GITHUB_ACTIONS\"]) platform = \"GitHub Actions\";\n else if (process.env[\"GITLAB_CI\"]) platform = \"GitLab CI\";\n else if (process.env[\"BITBUCKET_PIPELINE_UUID\"]) platform = \"Bitbucket Pipelines\";\n else if (process.env[\"CIRCLECI\"]) platform = \"CircleCI\";\n else if (process.env[\"JENKINS_URL\"]) platform = \"Jenkins\";\n else if (process.env[\"TRAVIS\"]) platform = \"Travis CI\";\n else if (process.env[\"CODEBUILD_BUILD_ID\"]) platform = \"AWS CodeBuild\";\n else if (process.env[\"BUILD_BUILDID\"]) platform = \"Azure Pipelines\";\n\n const tips: string[] = [];\n if (!process.env[\"GPC_NO_COLOR\"]) tips.push(\"Set GPC_NO_COLOR=1 for clean logs\");\n if (!process.env[\"GPC_NO_UPDATE_CHECK\"])\n tips.push(\"Set GPC_NO_UPDATE_CHECK=1 to skip update checks\");\n\n return {\n name: \"ci\",\n status: \"info\",\n message: `CI detected: ${platform}`,\n suggestion: tips.length > 0 ? tips.join(\". \") : undefined,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Async check helpers\n// ---------------------------------------------------------------------------\n\nasync function checkGpcVersion(): Promise<CheckResult> {\n const currentVersion = process.env[\"__GPC_VERSION\"] ?? \"0.0.0\";\n if (currentVersion === \"0.0.0\") {\n return { name: \"version\", status: \"info\", message: \"GPC development build\" };\n }\n try {\n const resp = await fetch(NPM_REGISTRY_URL, {\n signal: AbortSignal.timeout(3000),\n });\n if (!resp.ok) return { name: \"version\", status: \"pass\", message: `GPC v${currentVersion}` };\n const body = (await resp.json()) as { version?: string };\n if (!body.version)\n return { name: \"version\", status: \"pass\", message: `GPC v${currentVersion}` };\n\n if (isNewerVersion(currentVersion, body.version)) {\n return {\n name: \"version\",\n status: \"warn\",\n message: `GPC v${currentVersion} (v${body.version} available)`,\n suggestion: \"Run: gpc update\",\n };\n }\n return {\n name: \"version\",\n status: \"pass\",\n message: `GPC v${currentVersion} (up to date)`,\n };\n } catch {\n return { name: \"version\", status: \"pass\", message: `GPC v${currentVersion}` };\n }\n}\n\nasync function checkDiskSpace(dir: string): Promise<CheckResult> {\n try {\n const stats = await statfs(dir);\n const availableGB = (Number(stats.bavail) * Number(stats.bsize)) / 1024 ** 3;\n if (availableGB < 0.1) {\n return {\n name: \"disk-space\",\n status: \"warn\",\n message: `Low disk space: ${availableGB.toFixed(1)} GB available`,\n suggestion: \"Free up disk space — AAB uploads can be up to 2 GB\",\n };\n }\n return {\n name: \"disk-space\",\n status: \"pass\",\n message: `Disk space: ${availableGB.toFixed(1)} GB available`,\n };\n } catch {\n // statfs may fail on some filesystems (network mounts, etc.)\n return { name: \"disk-space\", status: \"info\", message: \"Could not check disk space\" };\n }\n}\n\nasync function checkSaKeyAge(saPath: string): Promise<CheckResult | null> {\n try {\n const stats = await stat(saPath);\n const ageDays = Math.floor((Date.now() - stats.mtimeMs) / (1000 * 60 * 60 * 24));\n if (ageDays > SA_KEY_ROTATION_DAYS) {\n return {\n name: \"service-account-age\",\n status: \"warn\",\n message: `Service account key is ${ageDays} days old`,\n suggestion: `Google recommends rotating service account keys every ${SA_KEY_ROTATION_DAYS} days`,\n };\n }\n return null; // Don't clutter output when key is fresh\n } catch {\n return null;\n }\n}\n\nasync function checkTokenCache(cacheDir: string): Promise<CheckResult | null> {\n const cachePath = join(cacheDir, \"token-cache.json\");\n try {\n if (!existsSync(cachePath)) return null;\n const content = await readFile(cachePath, \"utf-8\");\n JSON.parse(content);\n return { name: \"token-cache\", status: \"pass\", message: \"Token cache OK\" };\n } catch {\n return {\n name: \"token-cache\",\n status: \"warn\",\n message: \"Token cache is corrupt\",\n suggestion: \"Clear with: gpc cache clear\",\n fixData: { path: cachePath },\n };\n }\n}\n\nasync function probeHttps(\n host: string,\n timeoutMs = 5000,\n): Promise<{ ok: boolean; latencyMs: number; error?: string }> {\n // Use fetch (undici under the hood) instead of raw tls.connect so the probe\n // exercises the same HTTP stack as every real API call the rest of GPC\n // makes. A raw tls.connect would bypass any configured undici dispatcher,\n // HTTPS_PROXY, NODE_EXTRA_CA_CERTS injection, or TLS-intercepting corporate\n // proxy — and report a misleading \"self-signed certificate\" failure on\n // hosts that the actual API calls reach fine. Any HTTP response (including\n // 4xx/5xx) proves we successfully talked to the host; only fetch-level\n // errors (network, DNS, TLS) indicate real connectivity problems.\n const start = performance.now();\n try {\n const response = await fetch(`https://${host}/`, {\n method: \"HEAD\",\n signal: AbortSignal.timeout(timeoutMs),\n redirect: \"manual\",\n });\n // Consume (and discard) any response body to let the connection close\n // cleanly without leaking the stream.\n await response.body?.cancel?.().catch(() => {});\n const latencyMs = Math.round(performance.now() - start);\n return { ok: true, latencyMs };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n // AbortSignal.timeout fires with a TimeoutError name.\n const isTimeout =\n err instanceof Error && (err.name === \"TimeoutError\" || /timeout/i.test(err.message));\n return {\n ok: false,\n latencyMs: 0,\n error: isTimeout ? \"Connection timed out\" : message,\n };\n }\n}\n\nasync function checkAppAccess(packageName: string, accessToken: string): Promise<CheckResult> {\n try {\n const insertResp = await fetch(\n `https://${API_HOST}/androidpublisher/v3/applications/${encodeURIComponent(packageName)}/edits`,\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${accessToken}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({}),\n signal: AbortSignal.timeout(10_000),\n },\n );\n\n if (!insertResp.ok) {\n const body = (await insertResp.json().catch(() => ({}))) as {\n error?: { message?: string; status?: string };\n };\n\n // API not enabled in GCP project\n if (\n body.error?.status === \"PERMISSION_DENIED\" &&\n body.error?.message?.includes(\"has not been used\")\n ) {\n return {\n name: \"app-access\",\n status: \"fail\",\n message: \"Google Play Android Developer API is not enabled\",\n suggestion:\n \"Enable it: https://console.cloud.google.com/apis/api/androidpublisher.googleapis.com\",\n };\n }\n\n if (insertResp.status === 403) {\n return {\n name: \"app-access\",\n status: \"fail\",\n message: `No access to ${packageName}`,\n suggestion:\n \"Grant the service account access in Google Play Console → Users and permissions\",\n };\n }\n if (insertResp.status === 404) {\n return {\n name: \"app-access\",\n status: \"fail\",\n message: `App not found: ${packageName}`,\n suggestion: \"Check the package name with: gpc config get app\",\n };\n }\n return {\n name: \"app-access\",\n status: \"fail\",\n message: `App access check failed: HTTP ${insertResp.status}`,\n suggestion: body.error?.message ?? \"Check your credentials and app configuration\",\n };\n }\n\n // Clean up the test edit\n const edit = (await insertResp.json()) as { id?: string };\n if (edit.id) {\n await fetch(\n `https://${API_HOST}/androidpublisher/v3/applications/${encodeURIComponent(packageName)}/edits/${edit.id}`,\n {\n method: \"DELETE\",\n headers: { Authorization: `Bearer ${accessToken}` },\n signal: AbortSignal.timeout(5000),\n },\n ).catch(() => {});\n }\n\n return {\n name: \"app-access\",\n status: \"pass\",\n message: `App access verified: ${packageName}`,\n };\n } catch (err) {\n return {\n name: \"app-access\",\n status: \"warn\",\n message: `Could not verify app access: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Enterprise / Play Custom App Publishing API probe\n// ---------------------------------------------------------------------------\n\n/**\n * Best-effort probe of the Play Custom App Publishing API.\n *\n * The Custom App API only exposes `accounts.customApps.create` (POST). There's\n * no read-only endpoint to probe with, so we issue a GET against the collection\n * URL — which the API doesn't support. The response code reveals what we can\n * and can't do:\n *\n * - 400 / 404 / 405 → API reachable, auth working, permission likely present\n * - 403 → \"create and publish private apps\" permission is missing\n * - 401 → auth misconfigured (already caught by other doctor checks)\n * - network/timeout → inconclusive, return info status\n *\n * This is best-effort. A passing result doesn't guarantee `gpc enterprise publish`\n * will succeed against a specific enterprise — that also depends on organization\n * membership. A failing result is a reliable signal that setup is incomplete.\n */\nasync function checkEnterpriseAccess(accessToken: string): Promise<CheckResult> {\n try {\n // Use account ID \"1\" as a harmless syntactic placeholder. We expect this\n // to be rejected (404 or 400), which tells us the API is reachable and\n // our auth is recognized.\n const response = await fetch(\n \"https://playcustomapp.googleapis.com/playcustomapp/v1/accounts/1/customApps\",\n {\n method: \"GET\",\n headers: { Authorization: `Bearer ${accessToken}` },\n signal: AbortSignal.timeout(10_000),\n },\n );\n\n if (response.status === 403) {\n const body = (await response.json().catch(() => ({}))) as {\n error?: { message?: string; status?: string };\n };\n\n // API not enabled in this Google Cloud project\n if (body.error?.message?.includes(\"has not been used\")) {\n return {\n name: \"enterprise-access\",\n status: \"warn\",\n message: \"Play Custom App Publishing API is not enabled for this project\",\n suggestion:\n \"Enable it (only required for `gpc enterprise publish`): https://console.cloud.google.com/apis/library/playcustomapp.googleapis.com\",\n };\n }\n\n return {\n name: \"enterprise-access\",\n status: \"warn\",\n message: \"Service account is missing the 'create and publish private apps' permission\",\n suggestion:\n \"In Play Console → Users and permissions, grant this service account the 'create and publish private apps' account-level permission. Only required if you use `gpc enterprise publish`.\",\n };\n }\n\n // 400 / 404 / 405 = API reachable, auth working, permission likely present.\n // Google returns 400 for invalid account IDs once it gets past auth/permission.\n if (response.status === 400 || response.status === 404 || response.status === 405) {\n return {\n name: \"enterprise-access\",\n status: \"pass\",\n message: \"Play Custom App Publishing API is reachable\",\n };\n }\n\n // 401 = auth problem; let other doctor checks flag that.\n if (response.status === 401) {\n return {\n name: \"enterprise-access\",\n status: \"info\",\n message: \"Enterprise API probe skipped (auth not ready)\",\n };\n }\n\n // Any other status — inconclusive, don't fail the doctor run.\n return {\n name: \"enterprise-access\",\n status: \"info\",\n message: `Enterprise API probe inconclusive (HTTP ${response.status})`,\n suggestion: \"This probe is best-effort. Run `gpc enterprise publish` to verify end-to-end.\",\n };\n } catch (err) {\n return {\n name: \"enterprise-access\",\n status: \"info\",\n message: `Enterprise API probe skipped: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Verification deadline check\n// ---------------------------------------------------------------------------\n\nconst VERIFICATION_ENFORCEMENT = new Date(\"2026-09-01\");\n\nexport function checkVerificationDeadline(): CheckResult {\n if (Date.now() < VERIFICATION_ENFORCEMENT.getTime()) {\n return {\n name: \"verification\",\n status: \"warn\",\n message: \"Android developer verification enforcement begins September 2026 (BR, ID, SG, TH)\",\n suggestion: \"Run 'gpc verify' for details and resources\",\n };\n }\n return {\n name: \"verification\",\n status: \"info\",\n message: \"Android developer verification is being enforced. Ensure your account is verified.\",\n suggestion: \"Run 'gpc verify' to check your status\",\n };\n}\n\n// ---------------------------------------------------------------------------\n// Auto-fix\n// ---------------------------------------------------------------------------\n\nasync function applyFix(check: CheckResult): Promise<string | null> {\n switch (check.name) {\n case \"config-dir\":\n case \"cache-dir\": {\n const dirMatch = check.message.match(/: (.+)$/);\n if (!dirMatch?.[1]) return null;\n const { mkdir } = await import(\"node:fs/promises\");\n await mkdir(dirMatch[1], {\n recursive: true,\n mode: check.name === \"cache-dir\" ? 0o700 : 0o755,\n });\n return `Created ${dirMatch[1]}`;\n }\n case \"service-account-permissions\": {\n const saPath = check.fixData?.[\"path\"];\n if (!saPath) return null;\n const { chmod } = await import(\"node:fs/promises\");\n await chmod(saPath, 0o600);\n return `Fixed permissions on ${saPath}`;\n }\n case \"token-cache\": {\n const cachePath = check.fixData?.[\"path\"];\n if (!cachePath) return null;\n const { unlink } = await import(\"node:fs/promises\");\n await unlink(cachePath);\n return `Cleared corrupt token cache`;\n }\n case \"config\": {\n const { initConfig } = await import(\"@gpc-cli/config\");\n await initConfig({});\n return \"Initialized config file\";\n }\n case \"version\": {\n // Suggest running gpc update\n return \"Run: gpc update\";\n }\n case \"auth\": {\n // Guide user to authenticate\n return \"Run: gpc auth login --service-account <path/to/key.json>\";\n }\n case \"config-keys\": {\n const keys = check.fixData?.[\"keys\"];\n if (!keys) return null;\n const { deleteConfigValue } = await import(\"@gpc-cli/config\");\n for (const key of keys.split(\",\")) {\n await deleteConfigValue(key.trim());\n }\n return `Removed unknown keys: ${keys}`;\n }\n default:\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Command registration\n// ---------------------------------------------------------------------------\n\nexport function registerDoctorCommand(program: Command): void {\n program\n .command(\"doctor\")\n .description(\"Verify setup and connectivity\")\n .option(\"--fix\", \"Attempt to auto-fix failing checks\")\n .action(async (opts, cmd) => {\n const results: CheckResult[] = [];\n const parentOpts = cmd.parent?.opts() ?? {};\n const jsonMode = !!(parentOpts[\"json\"] || parentOpts[\"output\"] === \"json\");\n\n // -----------------------------------------------------------------------\n // 1. Node.js version\n // -----------------------------------------------------------------------\n results.push(checkNodeVersion(process.versions.node));\n\n // -----------------------------------------------------------------------\n // 2. GPC version (non-blocking — catches internally)\n // -----------------------------------------------------------------------\n results.push(await checkGpcVersion());\n\n // -----------------------------------------------------------------------\n // 3. CI environment (info only)\n // -----------------------------------------------------------------------\n const ciResult = checkCiEnvironment();\n if (ciResult) results.push(ciResult);\n\n // -----------------------------------------------------------------------\n // 4. Config file + dependent checks\n // -----------------------------------------------------------------------\n let config;\n try {\n config = await loadConfig();\n results.push({ name: \"config\", status: \"pass\", message: \"Configuration loaded\" });\n\n // 4b. Unknown config keys\n const keysCheck = checkConfigKeys(config as unknown as Record<string, unknown>);\n if (keysCheck) results.push(keysCheck);\n\n // 4c. Default app\n if (config.app) {\n results.push({\n name: \"default-app\",\n status: \"pass\",\n message: `Default app: ${config.app}`,\n });\n const pkgCheck = checkPackageName(config.app);\n if (pkgCheck) results.push(pkgCheck);\n } else {\n results.push({\n name: \"default-app\",\n status: \"info\",\n message: \"No default app configured\",\n suggestion: \"Use --app flag or run: gpc config set app <package>\",\n });\n }\n\n // 4d. Developer ID\n const devIdCheck = checkDeveloperId(config.developerId);\n if (devIdCheck) results.push(devIdCheck);\n } catch {\n results.push({\n name: \"config\",\n status: \"fail\",\n message: \"Configuration could not be loaded\",\n suggestion:\n \"Run gpc config init to create a config file, or check .gpcrc.json for syntax errors\",\n });\n }\n\n // -----------------------------------------------------------------------\n // 5. Config directory permissions\n // -----------------------------------------------------------------------\n const configDir = getConfigDir();\n try {\n if (existsSync(configDir)) {\n accessSync(configDir, constants.R_OK | constants.W_OK);\n results.push({\n name: \"config-dir\",\n status: \"pass\",\n message: `Config directory: ${configDir}`,\n });\n } else {\n results.push({\n name: \"config-dir\",\n status: \"info\",\n message: `Config directory does not exist yet: ${configDir}`,\n });\n }\n } catch {\n results.push({\n name: \"config-dir\",\n status: \"warn\",\n message: `Config directory not writable: ${configDir}`,\n suggestion: `Fix permissions: chmod 755 ${configDir}`,\n });\n }\n\n // -----------------------------------------------------------------------\n // 6. Cache directory permissions\n // -----------------------------------------------------------------------\n const cacheDir = getCacheDir();\n try {\n if (existsSync(cacheDir)) {\n accessSync(cacheDir, constants.R_OK | constants.W_OK);\n results.push({\n name: \"cache-dir\",\n status: \"pass\",\n message: `Cache directory: ${cacheDir}`,\n });\n } else {\n results.push({\n name: \"cache-dir\",\n status: \"info\",\n message: `Cache directory does not exist yet: ${cacheDir}`,\n });\n }\n } catch {\n results.push({\n name: \"cache-dir\",\n status: \"warn\",\n message: `Cache directory not writable: ${cacheDir}`,\n suggestion: `Fix permissions: chmod 700 ${cacheDir}`,\n });\n }\n\n // -----------------------------------------------------------------------\n // 7. Disk space\n // -----------------------------------------------------------------------\n const spaceDir = existsSync(cacheDir) ? cacheDir : configDir;\n if (existsSync(spaceDir)) {\n results.push(await checkDiskSpace(spaceDir));\n }\n\n // -----------------------------------------------------------------------\n // 8. Service account file + permissions\n // -----------------------------------------------------------------------\n let saFilePath: string | undefined;\n if (config?.auth?.serviceAccount) {\n const saValue = config.auth.serviceAccount;\n const looksLikePath = !saValue.trim().startsWith(\"{\");\n if (looksLikePath) {\n saFilePath = resolve(saValue);\n if (existsSync(saFilePath)) {\n try {\n accessSync(saFilePath, constants.R_OK);\n results.push({\n name: \"service-account-file\",\n status: \"pass\",\n message: `Service account file: ${saFilePath}`,\n });\n } catch {\n results.push({\n name: \"service-account-file\",\n status: \"fail\",\n message: `Service account file not readable: ${saFilePath}`,\n suggestion: `Fix permissions: chmod 600 ${saFilePath}`,\n });\n }\n\n // 8b. SA key file permissions (Unix only)\n if (process.platform !== \"win32\") {\n try {\n const mode = statSync(saFilePath).mode;\n const groupRead = (mode & 0o040) !== 0;\n const worldRead = (mode & 0o004) !== 0;\n if (groupRead || worldRead) {\n results.push({\n name: \"service-account-permissions\",\n status: \"warn\",\n message: `Service account file is group/world-readable (mode: ${(mode & 0o777).toString(8)})`,\n suggestion: `Restrict permissions: chmod 600 ${saFilePath}`,\n fixData: { path: saFilePath },\n });\n } else {\n results.push({\n name: \"service-account-permissions\",\n status: \"pass\",\n message: `Service account file permissions OK (mode: ${(mode & 0o777).toString(8)})`,\n });\n }\n } catch {\n // stat failed — skip permission check\n }\n }\n\n // 8c. SA key age\n const ageResult = await checkSaKeyAge(saFilePath);\n if (ageResult) results.push(ageResult);\n } else {\n results.push({\n name: \"service-account-file\",\n status: \"fail\",\n message: `Service account file not found: ${saFilePath}`,\n suggestion: \"Check the path in your config or GPC_SERVICE_ACCOUNT env var\",\n });\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // 9. Conflicting credentials\n // -----------------------------------------------------------------------\n const conflictCheck = checkConflictingCredentials(saFilePath);\n if (conflictCheck) results.push(conflictCheck);\n\n // -----------------------------------------------------------------------\n // 10. Token cache health\n // -----------------------------------------------------------------------\n const cacheResult = await checkTokenCache(cacheDir);\n if (cacheResult) results.push(cacheResult);\n\n // -----------------------------------------------------------------------\n // 11. Profile validation\n // -----------------------------------------------------------------------\n const gpcProfile = process.env[\"GPC_PROFILE\"];\n if (gpcProfile && config) {\n if (config.profiles && gpcProfile in config.profiles) {\n results.push({\n name: \"profile\",\n status: \"pass\",\n message: `Profile \"${gpcProfile}\" found`,\n });\n } else {\n const available = config.profiles ? Object.keys(config.profiles).join(\", \") : \"\";\n results.push({\n name: \"profile\",\n status: \"fail\",\n message: `Profile \"${gpcProfile}\" not found`,\n suggestion: available\n ? `Available profiles: ${available}. Create with: gpc auth login --profile ${gpcProfile}`\n : `No profiles defined. Create one with: gpc auth login --profile ${gpcProfile}`,\n });\n }\n }\n\n // -----------------------------------------------------------------------\n // 12. Proxy configuration\n // -----------------------------------------------------------------------\n const proxyUrl =\n process.env[\"HTTPS_PROXY\"] ||\n process.env[\"https_proxy\"] ||\n process.env[\"HTTP_PROXY\"] ||\n process.env[\"http_proxy\"];\n const proxyCheck = checkProxy(proxyUrl);\n if (proxyCheck) results.push(proxyCheck);\n\n // -----------------------------------------------------------------------\n // 13. CA certificate\n // -----------------------------------------------------------------------\n const caCert = process.env[\"GPC_CA_CERT\"] || process.env[\"NODE_EXTRA_CA_CERTS\"];\n if (caCert) {\n if (existsSync(caCert)) {\n results.push({\n name: \"ca-cert\",\n status: \"pass\",\n message: `CA certificate: ${caCert}`,\n });\n } else {\n results.push({\n name: \"ca-cert\",\n status: \"warn\",\n message: `CA certificate file not found: ${caCert}`,\n suggestion: \"Check that GPC_CA_CERT points to an existing PEM file\",\n });\n }\n }\n\n // -----------------------------------------------------------------------\n // 14. DNS resolution — with latency\n // -----------------------------------------------------------------------\n const dnsHosts = [API_HOST, REPORTING_HOST];\n const dnsPassedHosts: string[] = [];\n\n for (const host of dnsHosts) {\n const label = host.split(\".\")[0]!;\n try {\n const start = performance.now();\n await lookup(host);\n const ms = Math.round(performance.now() - start);\n results.push({\n name: `dns-${label}`,\n status: \"pass\",\n message: `DNS: ${host} (${ms}ms)`,\n });\n dnsPassedHosts.push(host);\n } catch {\n results.push({\n name: `dns-${label}`,\n status: \"fail\",\n message: `Cannot resolve ${host}`,\n suggestion: \"Check your DNS settings and network connection\",\n });\n }\n }\n\n // -----------------------------------------------------------------------\n // 15. HTTPS connectivity probe — only for hosts that passed DNS\n // -----------------------------------------------------------------------\n for (const host of dnsPassedHosts) {\n const label = host.split(\".\")[0]!;\n const probe = await probeHttps(host);\n if (probe.ok) {\n results.push({\n name: `https-${label}`,\n status: \"pass\",\n message: `HTTPS: ${host} (${probe.latencyMs}ms)`,\n });\n } else {\n results.push({\n name: `https-${label}`,\n status: \"fail\",\n message: `HTTPS connection failed: ${host}`,\n suggestion: probe.error\n ? `Error: ${probe.error}. Check firewall rules and proxy settings.`\n : \"Check firewall rules and proxy settings\",\n });\n }\n }\n\n // -----------------------------------------------------------------------\n // 16. Authentication + API connectivity\n // -----------------------------------------------------------------------\n let accessToken: string | undefined;\n\n try {\n const authConfig = config ?? (await loadConfig());\n const client = await resolveAuth({\n serviceAccountPath: authConfig.auth?.serviceAccount,\n });\n results.push({\n name: \"auth\",\n status: \"pass\",\n message: `Authenticated as ${client.getClientEmail()}`,\n });\n\n accessToken = await client.getAccessToken();\n results.push({\n name: \"api-connectivity\",\n status: \"pass\",\n message: \"API connectivity verified\",\n });\n } catch (error) {\n if (error instanceof AuthError) {\n results.push({\n name: \"auth\",\n status: \"fail\",\n message: `Authentication: ${error.message}`,\n suggestion: error.suggestion,\n });\n } else {\n const detail = error instanceof Error ? error.message : String(error);\n results.push({\n name: \"api-connectivity\",\n status: \"fail\",\n message: `API connectivity failed: ${detail}`,\n suggestion: \"Check your network connection and credentials\",\n });\n }\n }\n\n // -----------------------------------------------------------------------\n // 17. App access (only if auth succeeded and app is configured)\n // -----------------------------------------------------------------------\n if (accessToken && config?.app) {\n results.push(await checkAppAccess(config.app, accessToken));\n }\n\n // -----------------------------------------------------------------------\n // 17b. Enterprise / Play Custom App Publishing API probe (best-effort)\n // -----------------------------------------------------------------------\n if (accessToken) {\n results.push(await checkEnterpriseAccess(accessToken));\n }\n\n // -----------------------------------------------------------------------\n // 18. Developer ID format validation (info only)\n // -----------------------------------------------------------------------\n if (config?.developerId) {\n const devId = String(config.developerId);\n if (/^\\d{10,}$/.test(devId)) {\n results.push({\n name: \"developer-id\",\n status: \"pass\",\n message: `Developer ID: ${devId}`,\n });\n } else {\n results.push({\n name: \"developer-id\",\n status: \"warn\",\n message: `Developer ID \"${devId}\" may be invalid — expected a long numeric string`,\n suggestion:\n \"Find your Developer ID in Play Console → Settings → Developer account → Developer ID.\",\n });\n }\n }\n\n // -----------------------------------------------------------------------\n // 19. Developer verification deadline\n // -----------------------------------------------------------------------\n results.push(checkVerificationDeadline());\n\n // -----------------------------------------------------------------------\n // Output\n // -----------------------------------------------------------------------\n\n // Auto-fix failing checks if --fix was passed\n if (opts[\"fix\"]) {\n for (const r of results) {\n if (r.status === \"fail\" || r.status === \"warn\") {\n try {\n const fixMsg = await applyFix(r);\n if (fixMsg) {\n console.log(` ${green(\"\\u2192\")} Fixed: ${fixMsg}`);\n r.status = \"pass\";\n r.message += \" (fixed)\";\n }\n } catch (err) {\n console.error(\n ` ${red(\"\\u2717\")} Could not fix \"${r.name}\": ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n }\n }\n\n const errors = results.filter((r) => r.status === \"fail\").length;\n const warnings = results.filter((r) => r.status === \"warn\").length;\n const passed = results.filter((r) => r.status === \"pass\").length;\n\n if (jsonMode) {\n // Strip fixData from JSON output\n const cleanResults = results.map(({ fixData: _, ...rest }) => rest);\n console.log(\n JSON.stringify(\n { success: errors === 0, errors, warnings, checks: cleanResults },\n null,\n 2,\n ),\n );\n process.exitCode = errors > 0 ? 1 : 0;\n return;\n }\n\n console.log(\"GPC Doctor\\n\");\n for (const r of results) {\n console.log(` ${icon(r.status)} ${r.message}`);\n if (r.suggestion && r.status !== \"pass\") {\n console.log(` ${r.suggestion}`);\n }\n }\n\n console.log(\n `\\n ${green(PASS)} ${passed} passed ${yellow(WARN)} ${warnings} warning${warnings !== 1 ? \"s\" : \"\"} ${red(FAIL)} ${errors} failed`,\n );\n\n if (errors > 0) {\n console.log(\"\\nSome checks failed. Fix the issues above and run again.\");\n process.exitCode = 1;\n } else if (warnings > 0) {\n console.log(\"\\nAll checks passed with warnings.\");\n } else {\n console.log(`\\n${green(\"\\u2713\")} Ready. Try: gpc status`);\n }\n });\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/preflight.ts"],"sourcesContent":["// Named exports only. No default export.\n\nimport type { Command } from \"commander\";\nimport { runPreflight, getAllScannerNames, formatOutput, GpcError } from \"@gpc-cli/core\";\nimport type { FindingSeverity } from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { green, red, yellow, dim, bold } from \"../colors.js\";\n\nconst SEVERITY_ICONS: Record<FindingSeverity, string> = {\n critical: \"✗\",\n error: \"✗\",\n warning: \"⚠\",\n info: \"ℹ\",\n};\n\nfunction severityColor(severity: FindingSeverity, text: string): string {\n switch (severity) {\n case \"critical\":\n return bold(red(text));\n case \"error\":\n return red(text);\n case \"warning\":\n return yellow(text);\n case \"info\":\n return dim(text);\n }\n}\n\nexport function registerPreflightCommand(program: Command): void {\n const cmd = program\n .command(\"preflight [file]\")\n .description(\"Pre-submission compliance scanner for AAB files (offline)\")\n .option(\n \"--fail-on <severity>\",\n \"Fail if any finding meets or exceeds severity: critical, error, warning, info\",\n \"error\",\n )\n .option(\"--scanners <names>\", \"Comma-separated scanner names to run (default: all)\")\n .option(\"--metadata <dir>\", \"Path to metadata directory (Fastlane format) for listing checks\")\n .option(\"--source <dir>\", \"Path to source directory for code scanning\")\n .option(\"--config <path>\", \"Path to .preflightrc.json config file\")\n .action(async (file: string | undefined, options) => {\n await runPreflightAction(program, file, options);\n });\n\n // Subcommand: preflight manifest\n cmd\n .command(\"manifest <file>\")\n .description(\"Run manifest scanner only\")\n .option(\"--fail-on <severity>\", \"Fail threshold\", \"error\")\n .action(async (file: string, options) => {\n await runPreflightAction(program, file, { ...options, scanners: \"manifest\" });\n });\n\n // Subcommand: preflight permissions\n cmd\n .command(\"permissions <file>\")\n .description(\"Run permissions scanner only\")\n .option(\"--fail-on <severity>\", \"Fail threshold\", \"error\")\n .action(async (file: string, options) => {\n await runPreflightAction(program, file, { ...options, scanners: \"permissions\" });\n });\n\n // Subcommand: preflight metadata\n cmd\n .command(\"metadata <dir>\")\n .description(\"Run metadata scanner on a listings directory\")\n .option(\"--fail-on <severity>\", \"Fail threshold\", \"error\")\n .action(async (dir: string, options) => {\n await runPreflightAction(program, undefined, {\n ...options,\n metadata: dir,\n scanners: \"metadata\",\n });\n });\n\n // Subcommand: preflight codescan\n cmd\n .command(\"codescan <dir>\")\n .description(\"Run code scanners (secrets, billing, privacy) on source directory\")\n .option(\"--fail-on <severity>\", \"Fail threshold\", \"error\")\n .action(async (dir: string, options) => {\n await runPreflightAction(program, undefined, {\n ...options,\n source: dir,\n scanners: \"secrets,billing,privacy\",\n });\n });\n}\n\nasync function runPreflightAction(\n program: Command,\n file: string | undefined,\n options: Record<string, string | undefined>,\n): Promise<void> {\n if (!file && !options[\"metadata\"] && !options[\"source\"]) {\n throw new GpcError(\n \"Provide an AAB file, --metadata <dir>, or --source <dir>\",\n \"MISSING_INPUT\",\n 2,\n \"gpc preflight app.aab\",\n );\n }\n\n const failOn = options[\"failOn\"] as FindingSeverity | undefined;\n const validSeverities = new Set([\"critical\", \"error\", \"warning\", \"info\"]);\n if (failOn && !validSeverities.has(failOn)) {\n throw new GpcError(\n `Invalid --fail-on value \"${failOn}\". Use: critical, error, warning, info`,\n \"INVALID_OPTION\",\n 2,\n );\n }\n\n const scannerNames = options[\"scanners\"]?.split(\",\").map((s) => s.trim());\n if (scannerNames) {\n const known = new Set(getAllScannerNames());\n const unknown = scannerNames.filter((s) => !known.has(s));\n if (unknown.length > 0) {\n throw new GpcError(\n `Unknown scanner(s): ${unknown.join(\", \")}. Available: ${getAllScannerNames().join(\", \")}`,\n \"UNKNOWN_SCANNER\",\n 2,\n );\n }\n }\n\n const config = await loadConfig();\n const format = getOutputFormat(program, config);\n\n const result = await runPreflight({\n aabPath: file,\n metadataDir: options[\"metadata\"],\n sourceDir: options[\"source\"],\n scanners: scannerNames,\n failOn,\n configPath: options[\"config\"],\n });\n\n if (format === \"json\") {\n console.log(formatOutput(result, format));\n } else {\n // Header\n console.log(bold(\"GPC Preflight Scanner\"));\n if (file) console.log(dim(`File: ${file}`));\n console.log(dim(`Scanners: ${result.scanners.join(\", \")}`));\n console.log(\"\");\n\n if (result.findings.length === 0) {\n console.log(green(\"✓ No issues found\"));\n } else {\n // Group by severity\n for (const finding of result.findings) {\n const icon = SEVERITY_ICONS[finding.severity];\n const label = severityColor(finding.severity, `${icon} ${finding.severity.toUpperCase()}`);\n console.log(`${label} ${finding.title}`);\n console.log(` ${dim(finding.message)}`);\n if (finding.suggestion) {\n console.log(` ${dim(\"→\")} ${finding.suggestion}`);\n }\n if (finding.policyUrl) {\n console.log(` ${dim(finding.policyUrl)}`);\n }\n console.log(\"\");\n }\n }\n\n // Summary line\n const parts: string[] = [];\n if (result.summary.critical > 0) parts.push(bold(red(`${result.summary.critical} critical`)));\n if (result.summary.error > 0) parts.push(red(`${result.summary.error} error`));\n if (result.summary.warning > 0) parts.push(yellow(`${result.summary.warning} warning`));\n if (result.summary.info > 0) parts.push(dim(`${result.summary.info} info`));\n\n const summaryLine = parts.length > 0 ? parts.join(\", \") : green(\"0 issues\");\n const passedLabel = result.passed ? green(\"✓ PASSED\") : red(\"✗ FAILED\");\n console.log(`${passedLabel} ${summaryLine} ${dim(`(${result.durationMs}ms)`)}`);\n\n // Verification deadline awareness (auto-expires Sep 2026)\n if (Date.now() < new Date(\"2026-09-01\").getTime()) {\n console.log(\"\");\n console.log(\n dim(\"Note: Apps must be registered by a verified developer to be installable on\"),\n );\n console.log(dim(\"certified Android devices after Sep 2026. Run 'gpc verify' for details.\"));\n }\n }\n\n if (!result.passed) {\n process.exitCode = 6;\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/verify-H4ZUVHMZ.js
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
bold,
|
|
4
|
-
dim,
|
|
5
|
-
green,
|
|
6
|
-
yellow
|
|
7
|
-
} from "./chunk-FAN4ZITI.js";
|
|
8
|
-
|
|
9
|
-
// src/commands/verify.ts
|
|
10
|
-
import { resolveAuth } from "@gpc-cli/auth";
|
|
11
|
-
import { loadConfig } from "@gpc-cli/config";
|
|
12
|
-
var ENFORCEMENT_DATE = /* @__PURE__ */ new Date("2026-09-01");
|
|
13
|
-
var ENFORCEMENT_REGIONS = ["Brazil", "Indonesia", "Singapore", "Thailand"];
|
|
14
|
-
var ENFORCEMENT_REGION_CODES = ["BR", "ID", "SG", "TH"];
|
|
15
|
-
var RESOURCES = {
|
|
16
|
-
overview: "https://developer.android.com/developer-verification",
|
|
17
|
-
playConsole: "https://developer.android.com/developer-verification/guides/google-play-console",
|
|
18
|
-
androidConsole: "https://developer.android.com/developer-verification/guides/android-developer-console",
|
|
19
|
-
limitedDistribution: "https://developer.android.com/developer-verification/guides/limited-distribution"
|
|
20
|
-
};
|
|
21
|
-
function isBeforeEnforcement() {
|
|
22
|
-
return Date.now() < ENFORCEMENT_DATE.getTime();
|
|
23
|
-
}
|
|
24
|
-
function formatDeadline() {
|
|
25
|
-
return isBeforeEnforcement() ? `Enforcement begins September 2026 (${ENFORCEMENT_REGION_CODES.join(", ")})` : `Enforcement active \u2014 verify your account is compliant`;
|
|
26
|
-
}
|
|
27
|
-
async function openUrl(url) {
|
|
28
|
-
const { execFile } = await import("child_process");
|
|
29
|
-
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open";
|
|
30
|
-
const args = process.platform === "win32" ? ["/c", "start", "", url] : [url];
|
|
31
|
-
execFile(cmd, args);
|
|
32
|
-
}
|
|
33
|
-
function registerVerifyCommand(program) {
|
|
34
|
-
program.command("verify").description("Android developer verification status and resources").option("--open", "Open the verification page in your browser").action(async (opts, cmd) => {
|
|
35
|
-
const parentOpts = cmd.parent?.opts() ?? {};
|
|
36
|
-
const jsonMode = !!(parentOpts["json"] || parentOpts["output"] === "json");
|
|
37
|
-
let accountEmail = "unknown";
|
|
38
|
-
try {
|
|
39
|
-
const config = await loadConfig();
|
|
40
|
-
const client = await resolveAuth({
|
|
41
|
-
serviceAccountPath: config.auth?.serviceAccount
|
|
42
|
-
});
|
|
43
|
-
accountEmail = client.getClientEmail();
|
|
44
|
-
} catch {
|
|
45
|
-
}
|
|
46
|
-
if (opts["open"]) {
|
|
47
|
-
await openUrl(RESOURCES.overview);
|
|
48
|
-
if (jsonMode) {
|
|
49
|
-
console.log(JSON.stringify({ opened: RESOURCES.overview }));
|
|
50
|
-
} else {
|
|
51
|
-
console.log(`Opened ${RESOURCES.overview}`);
|
|
52
|
-
}
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
if (jsonMode) {
|
|
56
|
-
console.log(
|
|
57
|
-
JSON.stringify({
|
|
58
|
-
enforcement: {
|
|
59
|
-
date: "2026-09",
|
|
60
|
-
regions: ENFORCEMENT_REGIONS,
|
|
61
|
-
active: !isBeforeEnforcement()
|
|
62
|
-
},
|
|
63
|
-
account: accountEmail,
|
|
64
|
-
resources: RESOURCES
|
|
65
|
-
})
|
|
66
|
-
);
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
console.log("");
|
|
70
|
-
console.log(bold("Android Developer Verification"));
|
|
71
|
-
console.log("");
|
|
72
|
-
console.log(
|
|
73
|
-
` Status: ${isBeforeEnforcement() ? yellow(formatDeadline()) : green(formatDeadline())}`
|
|
74
|
-
);
|
|
75
|
-
console.log(` Account: ${accountEmail}`);
|
|
76
|
-
console.log(` Console: Play Console (auto-registered for Play apps)`);
|
|
77
|
-
console.log("");
|
|
78
|
-
console.log(" What you need to do:");
|
|
79
|
-
console.log(
|
|
80
|
-
` 1. Confirm identity verification in Play Console ${dim("\u2192 Settings \u2192 Developer Account")}`
|
|
81
|
-
);
|
|
82
|
-
console.log(` 2. Check auto-registration results above your app list`);
|
|
83
|
-
console.log(` 3. Register any non-Play apps within Play Console`);
|
|
84
|
-
console.log("");
|
|
85
|
-
console.log(" Resources:");
|
|
86
|
-
console.log(` ${dim("\u2192")} ${RESOURCES.overview}`);
|
|
87
|
-
console.log(` ${dim("\u2192")} ${RESOURCES.playConsole}`);
|
|
88
|
-
console.log(` ${dim("\u2192")} ${RESOURCES.limitedDistribution}`);
|
|
89
|
-
console.log("");
|
|
90
|
-
console.log(dim(" Run 'gpc verify --open' to open the verification page in your browser."));
|
|
91
|
-
console.log(dim(" Full guide: gpc docs developer-verification"));
|
|
92
|
-
console.log("");
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
export {
|
|
96
|
-
registerVerifyCommand
|
|
97
|
-
};
|
|
98
|
-
//# sourceMappingURL=verify-H4ZUVHMZ.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/verify.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { green, yellow, dim, bold } from \"../colors.js\";\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst ENFORCEMENT_DATE = new Date(\"2026-09-01\");\nconst ENFORCEMENT_REGIONS = [\"Brazil\", \"Indonesia\", \"Singapore\", \"Thailand\"];\nconst ENFORCEMENT_REGION_CODES = [\"BR\", \"ID\", \"SG\", \"TH\"];\n\nconst RESOURCES = {\n overview: \"https://developer.android.com/developer-verification\",\n playConsole: \"https://developer.android.com/developer-verification/guides/google-play-console\",\n androidConsole:\n \"https://developer.android.com/developer-verification/guides/android-developer-console\",\n limitedDistribution:\n \"https://developer.android.com/developer-verification/guides/limited-distribution\",\n};\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction isBeforeEnforcement(): boolean {\n return Date.now() < ENFORCEMENT_DATE.getTime();\n}\n\nfunction formatDeadline(): string {\n return isBeforeEnforcement()\n ? `Enforcement begins September 2026 (${ENFORCEMENT_REGION_CODES.join(\", \")})`\n : `Enforcement active — verify your account is compliant`;\n}\n\nasync function openUrl(url: string): Promise<void> {\n const { execFile } = await import(\"node:child_process\");\n const cmd =\n process.platform === \"darwin\" ? \"open\" : process.platform === \"win32\" ? \"cmd\" : \"xdg-open\";\n const args = process.platform === \"win32\" ? [\"/c\", \"start\", \"\", url] : [url];\n execFile(cmd, args);\n}\n\n// ---------------------------------------------------------------------------\n// Command registration\n// ---------------------------------------------------------------------------\n\nexport function registerVerifyCommand(program: Command): void {\n program\n .command(\"verify\")\n .description(\"Android developer verification status and resources\")\n .option(\"--open\", \"Open the verification page in your browser\")\n .action(async (opts, cmd) => {\n const parentOpts = cmd.parent?.opts() ?? {};\n const jsonMode = !!(parentOpts[\"json\"] || parentOpts[\"output\"] === \"json\");\n\n // Try to get account email (non-blocking)\n let accountEmail = \"unknown\";\n try {\n const config = await loadConfig();\n const client = await resolveAuth({\n serviceAccountPath: config.auth?.serviceAccount,\n });\n accountEmail = client.getClientEmail();\n } catch {\n // Auth not configured — that's fine for this command\n }\n\n if (opts[\"open\"]) {\n await openUrl(RESOURCES.overview);\n if (jsonMode) {\n console.log(JSON.stringify({ opened: RESOURCES.overview }));\n } else {\n console.log(`Opened ${RESOURCES.overview}`);\n }\n return;\n }\n\n if (jsonMode) {\n console.log(\n JSON.stringify({\n enforcement: {\n date: \"2026-09\",\n regions: ENFORCEMENT_REGIONS,\n active: !isBeforeEnforcement(),\n },\n account: accountEmail,\n resources: RESOURCES,\n }),\n );\n return;\n }\n\n // Table output\n console.log(\"\");\n console.log(bold(\"Android Developer Verification\"));\n console.log(\"\");\n console.log(\n ` Status: ${isBeforeEnforcement() ? yellow(formatDeadline()) : green(formatDeadline())}`,\n );\n console.log(` Account: ${accountEmail}`);\n console.log(` Console: Play Console (auto-registered for Play apps)`);\n console.log(\"\");\n console.log(\" What you need to do:\");\n console.log(\n ` 1. Confirm identity verification in Play Console ${dim(\"→ Settings → Developer Account\")}`,\n );\n console.log(` 2. Check auto-registration results above your app list`);\n console.log(` 3. Register any non-Play apps within Play Console`);\n console.log(\"\");\n console.log(\" Resources:\");\n console.log(` ${dim(\"→\")} ${RESOURCES.overview}`);\n console.log(` ${dim(\"→\")} ${RESOURCES.playConsole}`);\n console.log(` ${dim(\"→\")} ${RESOURCES.limitedDistribution}`);\n console.log(\"\");\n console.log(dim(\" Run 'gpc verify --open' to open the verification page in your browser.\"));\n console.log(dim(\" Full guide: gpc docs developer-verification\"));\n console.log(\"\");\n });\n}\n"],"mappings":"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","names":[]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|