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:
parent
714352ec18
commit
3cea2af4e1
37 changed files with 3020 additions and 54 deletions
10
cli/serve.ts
10
cli/serve.ts
|
|
@ -51,12 +51,12 @@ export const FORBIDDEN_METHOD_WORDS = /submit|release|publish|rollout|resume|com
|
|||
/** Read tools whose command prints a structured result with --json. */
|
||||
export const JSON_TOOLS = new Set(['check', 'check_aso', 'aso_audit', 'aso_suggest', 'aso_competitors', 'scan', 'validate', 'health', 'health_issue', 'reviews_list', 'prices_diff', 'analytics_compare', 'apple_status',
|
||||
'apple_next_build', 'play_status', 'play_next_version_code', 'shots_check', 'apple_testflight_status', 'apple_ppo_status', 'catalog_diff',
|
||||
'project_icon', 'project_listings', 'reviews_drafts', 'project_declarations', 'project_listing_text', 'project_renders', 'project_render', 'prices_current']);
|
||||
'project_icon', 'project_listings', 'reviews_drafts', 'project_declarations', 'project_listing_text', 'project_renders', 'project_render', 'prices_current', 'project_editable']);
|
||||
|
||||
/** Console forms `storebound console fill` knows (cli/console/fill.ts). */
|
||||
export const CONSOLE_FORMS = ['apple-app-record', 'apple-age-rating', 'apple-app-privacy', 'play-app-record', 'play-content-rating', 'play-target-audience'];
|
||||
/** Write tools that print a structured result with --json in the dry run and the real run (console.fill: the answers). */
|
||||
export const JSON_WRITES = new Set(['console_fill', 'owner_apple_submit', 'owner_apple_resubmit']);
|
||||
export const JSON_WRITES = new Set(['console_fill', 'owner_apple_submit', 'owner_apple_resubmit', 'project_edit']);
|
||||
/** Write tools whose command may ask its own question (confirm()): a verified host token answers it, as for owner actions. */
|
||||
const TOKEN_ANSWERS = new Set(['console_fill']);
|
||||
|
||||
|
|
@ -98,6 +98,12 @@ export const DESKTOP_ONLY: ToolDef[] = [
|
|||
description: 'One rendered image of the renders folder as a data: URL (at most 12 MB), for the desktop gallery.',
|
||||
props: { file: { type: 'string', pattern: RENDER_FILE_RE.source, description: 'Path relative to the renders folder, as project.renders names it' } },
|
||||
required: ['file'], args: i => ['--render', String(i.file)] },
|
||||
{ name: 'project_editable', title: 'Editable values', command: ['edit', '--show'], write: false, network: false,
|
||||
description: 'What the editors show: listing fields per store and language as the listing files hold them, the config sections the editors change, the App Review contact (masked), the store limits and whether the files are uncommitted in git.' },
|
||||
{ name: 'project_edit', title: 'Save edits to the app folder', command: ['edit'], write: true, network: false, idempotent: true,
|
||||
description: 'Writes edits of the app folder\'s sources of truth: config values by path (the rest of the file, comments and formatting kept), listing fields per store and language (store/listing.md, store/appstore.md), the App Review contact (.storebound/credentials.json). The dry run shows old -> new, the diff per file and the checks (store limits, required fields, keyword and metadata rules, the whole config validated); an error stops the write. Nothing goes to a store and nothing is committed.',
|
||||
props: { ops: { type: 'string', pattern: '^[\\[{][\\s\\S]{1,400000}$', description: 'The edits as JSON (one edit or a list; see `storebound edit`)' } },
|
||||
required: ['ops'], args: i => ['--ops', String(i.ops)] },
|
||||
{ name: 'console_fill', title: 'Fill in a console form', command: ['console', 'fill'], write: true, network: true,
|
||||
description: 'Fills one store console form that has no API (App Store app record, age rating, App Privacy; Play content rating, target audience) from the config in a visible Chromium the owner signs in to; uncertain fields are highlighted. It moves through the pages itself (Next; App Privacy: Get Started, Edit, each data type and the draft Save in its dialogs; content rating: Save draft) and never submits or publishes: the owner reviews every field and presses the final button (Publish, Submit, Save or Create). The dry run lists the answers; the real run lasts until the owner closes the browser.',
|
||||
props: { form: { type: 'string', enum: CONSOLE_FORMS, description: 'The console form' }, store: { type: 'string', enum: ['apple', 'play'], description: 'Default: from the form' },
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue