games: one config section for Game Center and Play Games Services (shared leaderboards and achievements); apple game-center (gameCenterDetails, gameCenterAppVersions, leaderboards, achievements and localizations, upsert by vendor id, read back); play games (Games Configuration API upsert, no POST retry); signing ensure adds GAME_CENTER when games.gameCenter

This commit is contained in:
CRTkafa 2026-10-21 04:59:51 +07:00
parent eebb3a830b
commit ca7289b173
8 changed files with 653 additions and 6 deletions

View file

@ -1,5 +1,6 @@
// Per-project config (storebound.config.ts at the project root). Everything app-specific lives here; credentials never
// do (see credentials.ts). The file default-exports a plain object; `import type { ShipConfig }` is optional.
import { type GamesConfig, validateGames } from './game-services';
import { consoleIdsFromConfig, consoleLink, setConsoleIds } from './console-links';
import { existsSync } from 'node:fs';
import { dirname, isAbsolute, join, resolve } from 'node:path';
@ -555,6 +556,9 @@ export interface ShipConfig {
/** What players / users can do with each other (chat, sharing, friends). Answers the Play IARC questionnaire's
* Miscellaneous > user interaction questions (`console plan play-content-rating`). */
social?: SocialConfig;
/** Game Center and Play Games Services: the switches per store and ONE list of leaderboards and achievements mapped
* to both (`storebound apple game-center`, `storebound play games`; game-services skill). */
games?: GamesConfig;
languages: Language[];
play?: {
packageName: string; defaultLanguage?: string; listing?: string; icon?: string;
@ -1102,6 +1106,7 @@ export function validateConfig(c: unknown): string[] {
e.push(`accounts.signUp: a list of ${ACCOUNT_SIGN_UPS.map(x => `'${x}'`).join(' | ')}`);
}
if (cfg.reviewAccess && typeof cfg.reviewAccess.signInRequired !== 'boolean') e.push('reviewAccess.signInRequired: true | false');
e.push(...validateGames(cfg.games, cfg.languages ?? []));
if (cfg.social !== undefined) {
if (!cfg.social || typeof cfg.social.interaction !== 'boolean') e.push('social.interaction: true | false');
else for (const k of ['block', 'report', 'moderation', 'friendsOnly', 'sharesLocation'] as const) if (cfg.social[k] !== undefined && typeof cfg.social[k] !== 'boolean') e.push(`social.${k}: true | false`);