Open in Google Play Console deep-links the app: Play developer id per credential profile (accounts play-developer, desktop Accounts), shared playAppUrl builder for desktop, CLI and watch; developer chooser instead of the console root

This commit is contained in:
CRTkafa 2026-10-23 09:20:35 +08:00
parent 7c769c18f4
commit 4a74989a95
33 changed files with 311 additions and 40 deletions

View file

@ -10,13 +10,17 @@
// contact and demo account stay in the project
// storebound accounts use <profile> [--dir <project>] this project uses that profile ("account" in its
// .storebound/credentials.json)
// storebound accounts play-developer <profile> <id> | --clear
// the profile's Play developer account id (the digits in
// play.google.com/console/u/0/developers/<id>): Play
// Console links open the app's own page
// storebound accounts default <profile> | --clear the machine's default profile (a pointer file in the
// credentials folder). Order: env > a profile the project
// names > the project's own keys > this default > the only
// profile (or the one named "default")
import { resolve } from 'node:path';
import type { Args } from './lib/args';
import { applyImport, describeProfiles, planImport } from './lib/accounts';
import { applyImport, describeProfiles, planImport, setPlayDeveloperId } from './lib/accounts';
import { activeProfile, defaultPointer, defaultProfile, profileDir, setDefaultPointer } from './lib/credentials';
import { confirm, type Ctx } from './lib/ctx';
import { textTable } from './lib/table';
@ -38,7 +42,7 @@ export async function run(args: Args): Promise<void> {
console.log(`no store accounts on this machine yet (${tilde(profileDir())}).\n From a project that has its keys in .storebound/credentials.json: storebound accounts import\n Or add them in the desktop app (Accounts).`);
return;
}
console.log(textTable(['profile', 'App Store Connect', 'Google Play', 'vendor no.', 'default'], rows.map(r => [r.profile, r.error ? `unreadable: ${r.error}` : r.apple ? 'key' : '-', r.play ? r.playAccount ?? 'service account' : '-', r.vendor ? 'yes' : '-', r.profile === def ? (def === pointer ? 'yes (accounts default)' : 'yes') : ''])));
console.log(textTable(['profile', 'App Store Connect', 'Google Play', 'Play developer id', 'vendor no.', 'default'], rows.map(r => [r.profile, r.error ? `unreadable: ${r.error}` : r.apple ? 'key' : '-', r.play ? r.playAccount ?? 'service account' : '-', r.playDeveloperId ?? '-', r.vendor ? 'yes' : '-', r.profile === def ? (def === pointer ? 'yes (accounts default)' : 'yes') : ''])));
if (pointer && pointer !== def) console.log(`note: the default pointer names "${pointer}", which is not a profile here (storebound accounts default <profile>)`);
console.log(`\n${tilde(profileDir())}: shared by the CLI and the desktop app`);
console.log(active ? `this folder uses "${active.name}" (${{ env: '--account / STOREBOUND_PROFILE', config: 'account in the config', project: '"account" in .storebound/credentials.json', default: 'the default profile' }[active.from]})` : 'this folder uses no profile (several profiles and no default: storebound accounts default <profile>, or accounts use <profile> in the project)');
@ -69,6 +73,15 @@ export async function run(args: Args): Promise<void> {
console.log(`${tilde(f)}: "account": "${name}"`);
return;
}
if (sub === 'play-developer') {
const name = args._[1];
if (!name) throw new Error('storebound accounts play-developer <profile> <id> | --clear');
const id = args.has('clear') ? null : args._[2] ?? null;
if (!args.has('clear') && !id) throw new Error('storebound accounts play-developer <profile> <id>: the digits in play.google.com/console/u/0/developers/<id>');
const f = setPlayDeveloperId(name, id);
console.log(id ? `${tilde(f)}: PLAY_DEVELOPER_ID ${id} (Play Console links of this account's apps open the app's page)` : `${tilde(f)}: Play developer id removed`);
return;
}
if (sub === 'default') {
if (args.has('clear')) { setDefaultPointer(null); console.log('default profile pointer removed (default: the only profile, or the one named "default")'); return; }
const name = args._[1];
@ -77,5 +90,5 @@ export async function run(args: Args): Promise<void> {
console.log(`${tilde(f)}: default profile "${name}" (used by every folder that names no profile and has no keys of its own)`);
return;
}
throw new Error('usage: storebound accounts [list | import [--dir <project>] [--name <profile>] [--dry] [--yes] | use <profile> | default <profile> | default --clear]');
throw new Error('usage: storebound accounts [list | import [--dir <project>] [--name <profile>] [--dry] [--yes] | use <profile> | play-developer <profile> <id> | default <profile> | default --clear]');
}