desktop editors: edit in place what App Store Connect and Play Console let the owner edit (listings per language for both stores with live counters and the check / scan rules, store details, App info, age rating, App Review, Play store settings, Data safety and App Privacy answers, promotion blocks, catalog names / prices / offers, TestFlight information, scene order); storebound edit (project.edit) saves into the config by path keeping comments and formatting, the listing files and the review contact, dry run with the diff and the checks first; Apply shows each store's dry run in the window; unsaved edits survive tab switches with undo / redo; tests/edit.test.ts, apps/desktop/tests/edits.test.ts, boot check editor case

This commit is contained in:
CRTkafa 2026-10-14 00:35:29 +08:00
parent 714352ec18
commit 3cea2af4e1
37 changed files with 3020 additions and 54 deletions

View file

@ -13,15 +13,8 @@ import { type ItemPlan, itemLines, planItem } from '../lib/listing-plan';
import { done, log, printJson, warn } from '../lib/log';
import { ascClient } from './asc';
/** Every question of the current age rating declaration at its "nothing" answer. */
export const AGE_RATING_NONE: Record<string, string | boolean | null> = {
advertising: false, ageAssurance: false, alcoholTobaccoOrDrugUseOrReferences: 'NONE', contests: 'NONE', gambling: false,
gamblingSimulated: 'NONE', gunsOrOtherWeapons: 'NONE', healthOrWellnessTopics: false, horrorOrFearThemes: 'NONE', lootBox: false,
matureOrSuggestiveThemes: 'NONE', medicalOrTreatmentInformation: 'NONE', messagingAndChat: false, parentalControls: false,
profanityOrCrudeHumor: 'NONE', socialMedia: false, socialMediaAgeRestricted: false, sexualContentGraphicAndNudity: 'NONE', sexualContentOrNudity: 'NONE', unrestrictedWebAccess: false,
userGeneratedContent: false, violenceCartoonOrFantasy: 'NONE', violenceRealistic: 'NONE',
violenceRealisticProlongedGraphicOrSadistic: 'NONE', kidsAgeBand: null,
};
export { AGE_RATING_NONE } from '../lib/store-catalogs';
import { AGE_RATING_NONE } from '../lib/store-catalogs';
const CATEGORY_RELS = ['primaryCategory', 'primarySubcategoryOne', 'primarySubcategoryTwo', 'secondaryCategory'] as const;
const str = (v: unknown): string => (v === null || v === undefined ? '' : String(v));