Onboarding live apps without owner questions for what the stores and the code prove: storebound onboard imports the live products and subscriptions with USD / base prices (catalog diff clean), contact values, the App Review contact and demo account (credentials.json, masked), sign-in for review from Apple's review detail and auth code, and the account deletion page from the app's site; App Store keywords count characters (live fields up to 265 bytes accepted); validate accepts the 6.5-inch iPhone set and Play's default-language graphics fallback; Play Reporting API off gives the project's enable link and apps list falls back to local apps; accounts default <profile>; store-only apps (apps add --store --app-id) shown read-only in the desktop (pitfalls 43-52)
This commit is contained in:
parent
d2ce185441
commit
e5f148e534
55 changed files with 1648 additions and 158 deletions
|
|
@ -146,6 +146,32 @@ export function appleCheck(outcome: { apps: number } | { error: unknown }): Acco
|
|||
return { store: 'ios', status: 'error', principal: null, apps: null, message: `Could not reach App Store Connect: ${msg}`, fix: 'Check the connection and try again.', docs: null };
|
||||
}
|
||||
|
||||
/**
|
||||
* Where to switch the Play Developer Reporting API on for the caller's Cloud project: the project from Google's 403
|
||||
* ("has not been used in project 123…", consumer "projects/123…", activationUrl "?project=…"), else from the service
|
||||
* account e-mail (<name>@<project-id>.iam.gserviceaccount.com). Pure.
|
||||
*/
|
||||
export function reportingEnableUrl(errorText: string, principal: string | null): { project: string | null; url: string } {
|
||||
const project = /[?&]project=([a-z0-9-]+)/i.exec(errorText)?.[1] ?? /projects\/([a-z0-9-]+)/i.exec(errorText)?.[1] ?? /in project ([a-z0-9-]+)/i.exec(errorText)?.[1]
|
||||
?? (principal ? /@([a-z][a-z0-9-]{4,61}[a-z0-9])\.iam\.gserviceaccount\.com$/.exec(principal)?.[1] : undefined) ?? null;
|
||||
return { project, url: `${REPORTING_API_URL}${project ? `?project=${project}` : ''}` };
|
||||
}
|
||||
|
||||
/** Is this error Google's "API not enabled in the Cloud project" 403 (SERVICE_DISABLED)? */
|
||||
export const isServiceDisabled = (e: unknown): boolean => {
|
||||
const full = String((e as Error)?.message ?? e);
|
||||
return statusOf(e) === 403 && /SERVICE_DISABLED|has not been used|is disabled|accessNotConfigured/i.test(full);
|
||||
};
|
||||
|
||||
/** Play apps known on this machine without the Reporting API: the package names of the app folders' configs and the
|
||||
* store-only Play entries of ~/.storebound/projects.json. Unverified on the store (marked in `sku`). Pure. */
|
||||
export function localPlayApps(known: { packageName: string; name: string; source: string }[]): StoreApp[] {
|
||||
const out: StoreApp[] = [];
|
||||
for (const k of known) if (k.packageName && !out.some(a => a.id === k.packageName))
|
||||
out.push({ store: 'android', id: k.packageName, bundleId: k.packageName, name: k.name || k.packageName, platforms: ['ANDROID'], sku: null, primaryLocale: null, latest: null, icon: null });
|
||||
return out.sort((x, y) => x.name.localeCompare(y.name));
|
||||
}
|
||||
|
||||
/** Play service account health from the token exchange and an `apps:search` outcome. */
|
||||
export function playCheck(principal: string | null, outcome: { apps: number } | { error: unknown }): AccountCheck {
|
||||
const who = principal ?? 'the service account';
|
||||
|
|
@ -156,9 +182,11 @@ export function playCheck(principal: string | null, outcome: { apps: number } |
|
|||
: { store: 'android', status: 'permission', principal, apps: 0, message: 'The key works, but no developer account has invited this service account (it sees no apps).', fix: invite, docs: PLAY_USERS_URL };
|
||||
}
|
||||
const code = statusOf(outcome.error), msg = short(outcome.error), full = String((outcome.error as Error)?.message ?? outcome.error);
|
||||
if (code === 403 && /SERVICE_DISABLED|has not been used|is disabled|accessNotConfigured/i.test(full))
|
||||
return { store: 'android', status: 'api-disabled', principal, apps: null, message: 'The Google Play Developer Reporting API is off in this service account\'s Google Cloud project.',
|
||||
fix: 'Google Cloud console > APIs & Services > Library: enable "Google Play Developer Reporting API" (and "Google Play Android Developer API") in the service account\'s project, wait a few minutes, test again.', docs: REPORTING_API_URL };
|
||||
if (code === 403 && /SERVICE_DISABLED|has not been used|is disabled|accessNotConfigured/i.test(full)) {
|
||||
const on = reportingEnableUrl(full, principal);
|
||||
return { store: 'android', status: 'api-disabled', principal, apps: null, message: `The Google Play Developer Reporting API is off in this service account's Google Cloud project${on.project ? ` (${on.project})` : ''}.`,
|
||||
fix: `Enable "Google Play Developer Reporting API" for that project: ${on.url} (press Enable; also "Google Play Android Developer API" if it is off), wait a few minutes, test again.`, docs: on.url };
|
||||
}
|
||||
if (code === null && /invalid_grant|Invalid JWT|account not found|disabled/i.test(full))
|
||||
return { store: 'android', status: 'revoked', principal, apps: null, message: `Google refused the key: ${msg}`,
|
||||
fix: 'The JSON key was deleted or the service account disabled. Google Cloud console > IAM & Admin > Service accounts > Keys: add a new JSON key, then add it here again.', docs: null };
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue