// The Play Console ids an app's links use, from every place this machine keeps them (first one wins): // developer id: play.developerId (config) > STOREBOUND_PLAY_DEVELOPER_ID (a workspace account, `ws`) > // PLAY_DEVELOPER_ID of the credential profile (`storebound accounts play-developer`, the desktop's // Accounts screen) > the id `console fill` remembered for the package (~/.storebound/console-accounts.json) // app id: play.appId (config) > the remembered app id for the package // Never a guess: an id that is not digits is skipped. The links themselves: console-links.ts (playAppUrl). import { existsSync, readFileSync } from 'node:fs'; import { homedir } from 'node:os'; import { join } from 'node:path'; import { pickConsoleId } from './console-links'; import { credentialValue } from './credentials'; const consoleAccountsFile = (): string => process.env.STOREBOUND_CONSOLE_ACCOUNTS || join(homedir(), '.storebound', 'console-accounts.json'); /** What `console fill` remembered for a package ({ developerId, appId? }); {} when nothing or unreadable. */ export function rememberedPlay(pkg: string | null | undefined, file = consoleAccountsFile()): { developerId?: string; appId?: string } { if (!pkg || !existsSync(file)) return {}; try { const e = (JSON.parse(readFileSync(file, 'utf8')) as { play?: Record }).play?.[pkg]; return { developerId: typeof e?.developerId === 'string' ? e.developerId : undefined, appId: typeof e?.appId === 'string' ? e.appId : undefined }; } catch { return {}; } } export interface PlayIdSources { config?: { developerId?: string | null; appId?: string | null; packageName?: string | null } | null; workspace?: string | null; profile?: string | null; remembered?: { developerId?: string | null; appId?: string | null }; } export function resolvePlayIds(s: PlayIdSources): { developerId: string | null; appId: string | null } { return { developerId: pickConsoleId(s.config?.developerId, s.workspace, s.profile, s.remembered?.developerId), appId: pickConsoleId(s.config?.appId, s.remembered?.appId), }; } /** The ids for a loaded config (every source above). */ export function playIdsOf(config: { play?: { developerId?: string; appId?: string; packageName?: string } }, root: string): { developerId: string | null; appId: string | null } { let profile: string | null = null; try { profile = credentialValue(root, 'PLAY_DEVELOPER_ID') ?? null; } catch { /* unreadable profile: no id from it */ } return resolvePlayIds({ config: config.play ?? null, workspace: process.env.STOREBOUND_PLAY_DEVELOPER_ID, profile, remembered: rememberedPlay(config.play?.packageName) }); }