storebound/cli/play/app-id.ts

64 lines
4.4 KiB
TypeScript

// The Play Console app id of this app (play.appId), found by package name. Read-only on Play Console.
// storebound play app-id [--json] the id when known, else the agent's steps
// storebound play app-id --from-text <file|-> [--write] [--json] find it in captured app list pages
// Known: play.appId, or the id storebound remembered when a Play form was open (~/.storebound/console-accounts.json).
// Otherwise it is an agent step: the agent opens the developer account's app list (10 apps per page, a new app is not
// on page 1; verified 2026-10-13), searches the package name or walks the pages, runs the capture snippet and pipes
// the captures here; storebound finds the row with the package name and reads the id from its /app/<id>/ link. The
// play.appId change is shown as a dry diff; --write saves it into storebound.config.ts (an upsert). Right after
// Create app, `storebound console verify play-app-record --url <url> --write` takes it from the redirect instead.
// Pure logic in cli/lib/play-app-id.ts.
import { readFileSync } from 'node:fs';
import { basename } from 'node:path';
import type { Ctx } from '../lib/ctx';
import { log, printJson } from '../lib/log';
import { APP_LIST_CAPTURE, appIdChange, appIdDiff, appIdSteps, findPlayAppId, parseAppListPages, writePlayAppId } from '../lib/play-app-id';
import * as rt from '../lib/rt';
export async function run(ctx: Ctx): Promise<void> {
const { config, path } = ctx.loaded;
const args = ctx.args, json = args.has('json');
const pkg = config.play?.packageName;
if (!pkg) throw new Error('play app-id: play.packageName is not set');
const from = args.get('from-text');
const { readAccounts, withAccountIds } = await import('../console/accounts');
const cfg = withAccountIds(config);
const cached = readAccounts().play[pkg];
const dev = cfg.play?.developerId ?? cached?.developerId ?? null;
const file = basename(path || 'storebound.config.ts');
if (from === undefined) {
const known = config.play?.appId ?? cached?.appId ?? null;
const source = config.play?.appId ? 'play.appId' : cached?.appId ? 'remembered from an open Play form (~/.storebound/console-accounts.json)' : null;
const change = known && !config.play?.appId ? appIdChange(config, known) : null;
if (json) return printJson({ packageName: pkg, appId: known, source, steps: known ? [] : appIdSteps(cfg, dev), capture: APP_LIST_CAPTURE, ...(change ? { change } : {}) });
if (known) {
console.log(`${pkg}: Play Console app id ${known} (${source})`);
if (change) console.log(`${appIdDiff(change, file)} (dry: add it with \`storebound play app-id --from-text\` and --write, or put appId: '${known}' into play)`);
return;
}
console.log(`${pkg}: the Play Console app id is not known yet. Find it in the console (read-only), then pipe the captures here:\n`);
appIdSteps(cfg, dev).forEach((s, i) => console.log(` ${i + 1}. ${s}`));
console.log(`\nCapture snippet (one evaluate call in the app list page):\n${APP_LIST_CAPTURE}`);
return;
}
const raw = from === '-' || from === 'true' ? await rt.stdinText() : readFileSync(from, 'utf8');
const pages = parseAppListPages(raw);
const r = findPlayAppId(pages, pkg);
if (!r.found) {
const why = r.ambiguous ? `several rows hold ${pkg} (app ids ${r.ambiguous.join(', ')}): search the exact package name and capture again`
: r.hasNext ? `not on the ${r.pages} captured page(s) and the list has a next page: press "Next page", capture again and pipe every capture (a JSON array or one per line)`
: `not on the ${r.pages} captured page(s), and the list has no next page: is this the developer account that has the app? (search ${pkg} in the list's search box)`;
if (json) printJson({ packageName: pkg, appId: null, ...r, next: why }); else console.log(`${pkg}: ${why}`);
process.exitCode = 1;
return;
}
const change = appIdChange(config, r.appId);
const write = args.has('write') && !args.has('dry');
const wrote = write && path ? writePlayAppId(path, config, r.appId) : false;
if (json) return printJson({ packageName: pkg, appId: r.appId, page: r.page, change, written: wrote });
console.log(`${pkg}: Play Console app id ${r.appId} (page ${r.page} of the captures)`);
console.log(appIdDiff(change, file));
if (!change.changed) return;
if (wrote) log('play', `wrote play.appId '${r.appId}' into ${file}`);
else console.log('dry: run the same command with --write to save it');
}