storemeta 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.release.example +8 -0
- package/LICENSE +21 -0
- package/README.md +94 -0
- package/dist/auth/apple/credential-state.js +14 -0
- package/dist/auth/apple/jwt.js +56 -0
- package/dist/auth/apple/load-credentials.js +36 -0
- package/dist/auth/credential-state.js +6 -0
- package/dist/auth/google/credential-state.js +10 -0
- package/dist/auth/google/load-credentials.js +18 -0
- package/dist/auth/google/service-account-auth.js +25 -0
- package/dist/auth/redact.js +17 -0
- package/dist/cli/auth-check.js +46 -0
- package/dist/cli/config-doctor.js +40 -0
- package/dist/cli/context.js +23 -0
- package/dist/cli/errors.js +10 -0
- package/dist/cli/exit-code.js +6 -0
- package/dist/cli/init.js +60 -0
- package/dist/cli/locales-list.js +37 -0
- package/dist/cli/metadata-diff.js +57 -0
- package/dist/cli/metadata-pull.js +52 -0
- package/dist/cli/metadata-push.js +95 -0
- package/dist/cli/render.js +57 -0
- package/dist/cli/result-types.js +1 -0
- package/dist/cli/scaffold.js +76 -0
- package/dist/cli/screenshots-diff.js +65 -0
- package/dist/cli/screenshots-pull.js +72 -0
- package/dist/cli/screenshots-push.js +96 -0
- package/dist/cli/validate.js +74 -0
- package/dist/cli.js +222 -0
- package/dist/config/apps.js +21 -0
- package/dist/config/load-config.js +30 -0
- package/dist/config/schema.js +97 -0
- package/dist/config/select-app.js +10 -0
- package/dist/config/select-platforms.js +17 -0
- package/dist/config/single-app.js +16 -0
- package/dist/config/types.js +1 -0
- package/dist/config/validate-base-dirs.js +33 -0
- package/dist/config/validate-credential-env-names.js +32 -0
- package/dist/config/validate-platform-identifiers.js +24 -0
- package/dist/formats/load-metadata.js +38 -0
- package/dist/formats/metadata-types.js +1 -0
- package/dist/formats/screenshot-types.js +1 -0
- package/dist/formats/serialize-metadata.js +20 -0
- package/dist/locales/groups.js +12 -0
- package/dist/locales/map.js +15 -0
- package/dist/locales/normalize.js +22 -0
- package/dist/locales/types.js +1 -0
- package/dist/locales/validate-groups.js +14 -0
- package/dist/platforms/apple/client.js +109 -0
- package/dist/platforms/apple/metadata/pull.js +120 -0
- package/dist/platforms/apple/metadata/push.js +272 -0
- package/dist/platforms/apple/metadata/types.js +1 -0
- package/dist/platforms/apple/screenshots/pull.js +160 -0
- package/dist/platforms/apple/screenshots/push.js +418 -0
- package/dist/platforms/google/client.js +42 -0
- package/dist/platforms/google/edits.js +38 -0
- package/dist/platforms/google/metadata/pull.js +23 -0
- package/dist/platforms/google/metadata/push.js +73 -0
- package/dist/platforms/google/metadata/types.js +1 -0
- package/dist/platforms/google/screenshots/pull.js +129 -0
- package/dist/platforms/google/screenshots/push.js +252 -0
- package/dist/platforms/google/screenshots/types.js +7 -0
- package/dist/validation/metadata/apple.js +31 -0
- package/dist/validation/metadata/files.js +58 -0
- package/dist/validation/metadata/google.js +46 -0
- package/dist/validation/screenshots/extensions.js +17 -0
- package/dist/validation/screenshots/files.js +55 -0
- package/dist/validation/screenshots/folders.js +41 -0
- package/dist/validation/screenshots/order.js +25 -0
- package/dist/writers/ensure-directory.js +16 -0
- package/dist/writers/order-screenshots.js +19 -0
- package/dist/writers/resolve-screenshot-path.js +8 -0
- package/dist/writers/resolve-within-base-dir.js +17 -0
- package/dist/writers/write-metadata.js +17 -0
- package/docs/API_EDITABLE_METADATA_SURFACE.md +319 -0
- package/docs/AUTH_SETUP.md +67 -0
- package/docs/DOCUMENTATION.md +285 -0
- package/docs/PROJECT_PLAN.md +687 -0
- package/docs/RELEASE_VERIFICATION.md +70 -0
- package/docs/TODO.md +308 -0
- package/examples/README.md +8 -0
- package/examples/metadata/apple/en-US.yml +11 -0
- package/examples/metadata/apple/tr.yml +11 -0
- package/examples/metadata/google/en-US.yml +6 -0
- package/examples/metadata/google/tr.yml +6 -0
- package/examples/screenshots/apple/en-US/APP_IPHONE_65/1.png +1 -0
- package/examples/screenshots/apple/tr/APP_IPHONE_65/1.png +1 -0
- package/examples/screenshots/google/en-US/phoneScreenshots/1.png +1 -0
- package/examples/screenshots/google/tr/phoneScreenshots/1.png +1 -0
- package/examples/storemeta.yml +29 -0
- package/package.json +55 -0
- package/storemeta.release.example.yml +27 -0
|
@@ -0,0 +1,687 @@
|
|
|
1
|
+
# storemeta Project Plan
|
|
2
|
+
|
|
3
|
+
`storemeta` is a TypeScript CLI for pulling, validating, and pushing App Store Connect and Google Play metadata and screenshots.
|
|
4
|
+
|
|
5
|
+
This document is the implementation plan and historical project specification for v1. For current user-facing behavior and config reference, see [`DOCUMENTATION.md`](DOCUMENTATION.md).
|
|
6
|
+
|
|
7
|
+
## 1. Project Status
|
|
8
|
+
|
|
9
|
+
Current stage:
|
|
10
|
+
- core CLI implemented with automated tests passing
|
|
11
|
+
- remaining work is release verification against real Apple and Google test apps
|
|
12
|
+
|
|
13
|
+
Locked decisions:
|
|
14
|
+
- language: TypeScript
|
|
15
|
+
- initial distribution: npm only
|
|
16
|
+
- npm package name: `storemeta`
|
|
17
|
+
- primary CLI binary name: `storemeta`
|
|
18
|
+
- default config file name: `storemeta.yml`
|
|
19
|
+
- scope: metadata + screenshots
|
|
20
|
+
- sync direction: both pull and push
|
|
21
|
+
- command style: noun-first
|
|
22
|
+
- config: one root YAML file
|
|
23
|
+
- metadata file support: `.yml`, `.yaml`, and `.md` files whose contents are YAML
|
|
24
|
+
- validation: strict by default
|
|
25
|
+
- license: MIT
|
|
26
|
+
|
|
27
|
+
Still flexible:
|
|
28
|
+
- public-release hardening based on real App Store Connect and Google Play verification
|
|
29
|
+
|
|
30
|
+
Naming note:
|
|
31
|
+
- `sm` is intentionally not the primary command because it is too short and more likely to collide with other tools
|
|
32
|
+
|
|
33
|
+
## 2. Why This Project Exists
|
|
34
|
+
|
|
35
|
+
Managing App Store Connect and Google Play metadata is repetitive, error-prone, and difficult to standardize across apps and locales.
|
|
36
|
+
|
|
37
|
+
What is needed is a dedicated CLI that provides:
|
|
38
|
+
- a stable command surface
|
|
39
|
+
- a documented config format
|
|
40
|
+
- deterministic pull and push behavior
|
|
41
|
+
- strong validation before writes
|
|
42
|
+
- a clean npm distribution story
|
|
43
|
+
|
|
44
|
+
The goal of `storemeta` is to provide that reusable open source workflow.
|
|
45
|
+
|
|
46
|
+
## 3. Goals
|
|
47
|
+
|
|
48
|
+
V1 goals:
|
|
49
|
+
- pull App Store and Google Play metadata into local files
|
|
50
|
+
- push local metadata to App Store and Google Play
|
|
51
|
+
- pull store screenshots into a local directory layout
|
|
52
|
+
- push local screenshots from a local directory layout
|
|
53
|
+
- validate content before upload
|
|
54
|
+
- support explicit locale mapping and screenshot grouping
|
|
55
|
+
- keep secrets out of the repository
|
|
56
|
+
|
|
57
|
+
V1 non-goals:
|
|
58
|
+
- Homebrew distribution
|
|
59
|
+
- in-place image editing or screenshot generation
|
|
60
|
+
- translation workflows
|
|
61
|
+
- release submission automation outside metadata and screenshot management
|
|
62
|
+
|
|
63
|
+
## 4. Platform And Product Requirements
|
|
64
|
+
|
|
65
|
+
The CLI must cover both App Store Connect and Google Play with one consistent user experience.
|
|
66
|
+
|
|
67
|
+
### Platform Requirements
|
|
68
|
+
|
|
69
|
+
Google Play requirements:
|
|
70
|
+
- authenticate with a service account
|
|
71
|
+
- perform write operations through an edit session
|
|
72
|
+
- commit the edit after successful changes
|
|
73
|
+
- support listing metadata and screenshots
|
|
74
|
+
|
|
75
|
+
App Store Connect requirements:
|
|
76
|
+
- authenticate with JWT-based API credentials
|
|
77
|
+
- handle the split between app info localization fields and version localization fields
|
|
78
|
+
- support screenshot set creation and upload completion flows
|
|
79
|
+
- support listing metadata and screenshots
|
|
80
|
+
|
|
81
|
+
### Product Requirements
|
|
82
|
+
|
|
83
|
+
The product must provide:
|
|
84
|
+
- shared config instead of inline constants
|
|
85
|
+
- shared auth loading instead of command-local credential logic
|
|
86
|
+
- shared locale normalization and grouping
|
|
87
|
+
- deterministic filesystem layout
|
|
88
|
+
- YAML parsing for metadata files
|
|
89
|
+
- reusable platform adapters
|
|
90
|
+
- strict validation before write operations
|
|
91
|
+
|
|
92
|
+
### Required Implementation Patterns
|
|
93
|
+
|
|
94
|
+
These behaviors are part of the intended design:
|
|
95
|
+
- Google write operations should share one edit-session helper
|
|
96
|
+
- Apple metadata mapping should explicitly model separate localization resource types
|
|
97
|
+
- Apple screenshot uploads should use a reserve-upload-commit pipeline
|
|
98
|
+
- screenshot files should be processed in deterministic numeric order
|
|
99
|
+
- locale grouping should be config-driven
|
|
100
|
+
- dry-run mode should exist for destructive operations
|
|
101
|
+
- commands should print per-locale progress and final summaries
|
|
102
|
+
|
|
103
|
+
### Behaviors To Avoid
|
|
104
|
+
|
|
105
|
+
The product must avoid:
|
|
106
|
+
- embedded secrets
|
|
107
|
+
- hardcoded credential paths
|
|
108
|
+
- regex parsing for structured metadata content
|
|
109
|
+
- duplicated locale logic across commands
|
|
110
|
+
- typo-dependent folder conventions
|
|
111
|
+
- hardcoded screenshot type assumptions with no override path
|
|
112
|
+
- mixing config parsing, API transport, validation, and output formatting in one module
|
|
113
|
+
|
|
114
|
+
### Product Gaps To Close Before Public Release
|
|
115
|
+
|
|
116
|
+
These capabilities should be verified before the first public release:
|
|
117
|
+
- metadata pull and push against a real Apple test app
|
|
118
|
+
- metadata pull and push against a real Google Play test app
|
|
119
|
+
- screenshot pull and push against real Apple and Google test apps
|
|
120
|
+
- no secrets in logs, package contents, examples, docs, or git history
|
|
121
|
+
- npm package install and binary execution from the packed tarball
|
|
122
|
+
|
|
123
|
+
## 5. Architecture Direction
|
|
124
|
+
|
|
125
|
+
The CLI is implemented as a TypeScript Node.js project.
|
|
126
|
+
|
|
127
|
+
Recommended internal modules:
|
|
128
|
+
- `cli`
|
|
129
|
+
- `config`
|
|
130
|
+
- `formats/yaml`
|
|
131
|
+
- `locales`
|
|
132
|
+
- `writers`
|
|
133
|
+
- `validation/metadata`
|
|
134
|
+
- `validation/screenshots`
|
|
135
|
+
- `auth/apple`
|
|
136
|
+
- `auth/google`
|
|
137
|
+
- `platforms/apple/metadata`
|
|
138
|
+
- `platforms/apple/screenshots`
|
|
139
|
+
- `platforms/google/metadata`
|
|
140
|
+
- `platforms/google/screenshots`
|
|
141
|
+
|
|
142
|
+
Tooling choices:
|
|
143
|
+
- CLI parser: `commander`
|
|
144
|
+
- HTTP client: native `fetch` from Node.js 20+
|
|
145
|
+
- Test runner: `vitest`
|
|
146
|
+
- Linting and formatting: still deferred
|
|
147
|
+
|
|
148
|
+
High-level design:
|
|
149
|
+
- one unified CLI surface
|
|
150
|
+
- one root config file
|
|
151
|
+
- two platform adapters: Apple and Google
|
|
152
|
+
- local normalized file layout
|
|
153
|
+
- strict validation for loaded inputs before write operations
|
|
154
|
+
|
|
155
|
+
Implementation guidance:
|
|
156
|
+
- Google commands should share one edit-session helper
|
|
157
|
+
- Apple metadata should share one mapper that understands both localization resource types
|
|
158
|
+
- Apple screenshots should share one upload pipeline abstraction
|
|
159
|
+
- all pull commands should write through one deterministic file writer layer
|
|
160
|
+
- all locale mapping should flow through one normalization module
|
|
161
|
+
|
|
162
|
+
## 6. CLI Specification
|
|
163
|
+
|
|
164
|
+
The CLI follows a noun-first structure.
|
|
165
|
+
|
|
166
|
+
### Command Tree
|
|
167
|
+
|
|
168
|
+
```text
|
|
169
|
+
storemeta init
|
|
170
|
+
storemeta validate
|
|
171
|
+
storemeta metadata pull
|
|
172
|
+
storemeta metadata push
|
|
173
|
+
storemeta screenshots pull
|
|
174
|
+
storemeta screenshots push
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Global Options
|
|
178
|
+
|
|
179
|
+
Available to all commands unless a command narrows them:
|
|
180
|
+
- `--config <path>`
|
|
181
|
+
- `--app <id>`
|
|
182
|
+
- `--platform <apple|google|all>`
|
|
183
|
+
- `--locale <code>`
|
|
184
|
+
- `--dry-run`
|
|
185
|
+
- `--verbose`
|
|
186
|
+
|
|
187
|
+
### `storemeta init`
|
|
188
|
+
|
|
189
|
+
Purpose:
|
|
190
|
+
- create a starter `storemeta.yml`
|
|
191
|
+
- create example metadata and screenshots directories
|
|
192
|
+
|
|
193
|
+
Behavior:
|
|
194
|
+
- do not overwrite existing files unless a future `--force` is added
|
|
195
|
+
|
|
196
|
+
Examples:
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
storemeta init
|
|
200
|
+
storemeta --config ./apps/demo/storemeta.yml init
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### `storemeta validate`
|
|
204
|
+
|
|
205
|
+
Purpose:
|
|
206
|
+
- validate local config, metadata files, screenshot layout, and platform-specific limits
|
|
207
|
+
|
|
208
|
+
Validation scope:
|
|
209
|
+
- config schema validity
|
|
210
|
+
- required credentials presence
|
|
211
|
+
- locale mapping consistency
|
|
212
|
+
- file existence
|
|
213
|
+
- metadata length rules
|
|
214
|
+
- screenshot folder and file naming rules
|
|
215
|
+
|
|
216
|
+
Exit behavior:
|
|
217
|
+
- exit `0` on success
|
|
218
|
+
- exit non-zero when blocking issues exist
|
|
219
|
+
|
|
220
|
+
Examples:
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
storemeta validate
|
|
224
|
+
storemeta validate --platform apple
|
|
225
|
+
storemeta validate --app example-app --platform all
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### `storemeta metadata pull`
|
|
229
|
+
|
|
230
|
+
Purpose:
|
|
231
|
+
- fetch metadata from stores into the local file layout
|
|
232
|
+
|
|
233
|
+
Behavior:
|
|
234
|
+
- fetch all target locales or requested locale subsets
|
|
235
|
+
- normalize platform data into local schema
|
|
236
|
+
- write one file per locale per platform
|
|
237
|
+
- preserve deterministic key ordering
|
|
238
|
+
|
|
239
|
+
Implementation status:
|
|
240
|
+
- implemented as a first-class CLI command for Apple and Google metadata
|
|
241
|
+
|
|
242
|
+
Examples:
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
storemeta metadata pull --platform apple
|
|
246
|
+
storemeta metadata pull --platform google --locale en-US
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### `storemeta metadata push`
|
|
250
|
+
|
|
251
|
+
Purpose:
|
|
252
|
+
- push local metadata files to stores
|
|
253
|
+
|
|
254
|
+
Behavior:
|
|
255
|
+
- validate loaded metadata documents before upload
|
|
256
|
+
- respect `--dry-run`
|
|
257
|
+
- update existing localizations when present
|
|
258
|
+
- create missing localizations when the platform allows it
|
|
259
|
+
- print per-locale results
|
|
260
|
+
|
|
261
|
+
Examples:
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
storemeta metadata push --platform google --dry-run
|
|
265
|
+
storemeta metadata push --platform apple --locale tr
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### `storemeta screenshots pull`
|
|
269
|
+
|
|
270
|
+
Purpose:
|
|
271
|
+
- fetch screenshots from stores into the local screenshot layout
|
|
272
|
+
|
|
273
|
+
Behavior:
|
|
274
|
+
- fetch by locale and display type where supported
|
|
275
|
+
- write deterministic file names such as `1.png`, `2.png`, `3.png`
|
|
276
|
+
|
|
277
|
+
Implementation status:
|
|
278
|
+
- implemented as a first-class CLI command for Apple and Google screenshots
|
|
279
|
+
|
|
280
|
+
### `storemeta screenshots push`
|
|
281
|
+
|
|
282
|
+
Purpose:
|
|
283
|
+
- push local screenshots to stores
|
|
284
|
+
|
|
285
|
+
Behavior:
|
|
286
|
+
- validate loaded screenshot sets before upload
|
|
287
|
+
- respect `--dry-run`
|
|
288
|
+
- replace existing screenshots in target sets only when `--replace` is supplied
|
|
289
|
+
- print per-locale summaries
|
|
290
|
+
|
|
291
|
+
Examples:
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
storemeta screenshots push --platform apple --dry-run
|
|
295
|
+
storemeta screenshots push --platform apple --replace
|
|
296
|
+
storemeta screenshots push --platform google --locale en-US
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Output Rules
|
|
300
|
+
|
|
301
|
+
Default output should be human-readable:
|
|
302
|
+
- command header
|
|
303
|
+
- selected app and platform
|
|
304
|
+
- validation summary
|
|
305
|
+
- per-locale progress
|
|
306
|
+
- final totals
|
|
307
|
+
|
|
308
|
+
Possible later extension:
|
|
309
|
+
- `--json` output for CI
|
|
310
|
+
|
|
311
|
+
### Failure Rules
|
|
312
|
+
|
|
313
|
+
- invalid config: fail before network work
|
|
314
|
+
- missing credentials: fail before network work
|
|
315
|
+
- validation failure on push: fail before writes
|
|
316
|
+
- current behavior: blocking failures throw and return non-zero
|
|
317
|
+
- future behavior: aggregate partial failures and print a clear summary
|
|
318
|
+
|
|
319
|
+
### Reserved Future Commands
|
|
320
|
+
|
|
321
|
+
Not in v1, but the tree should allow for:
|
|
322
|
+
- `storemeta auth check`
|
|
323
|
+
- `storemeta locales list`
|
|
324
|
+
- `storemeta config doctor`
|
|
325
|
+
- `storemeta metadata diff`
|
|
326
|
+
- `storemeta screenshots diff`
|
|
327
|
+
|
|
328
|
+
## 7. Config Specification
|
|
329
|
+
|
|
330
|
+
### Root Config File
|
|
331
|
+
|
|
332
|
+
Default file name:
|
|
333
|
+
|
|
334
|
+
```text
|
|
335
|
+
storemeta.yml
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
Override:
|
|
339
|
+
|
|
340
|
+
```bash
|
|
341
|
+
storemeta --config ./path/to/storemeta.yml validate
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### Root Config Format
|
|
345
|
+
|
|
346
|
+
The root config file is YAML.
|
|
347
|
+
|
|
348
|
+
Metadata content files may use:
|
|
349
|
+
- `.yml`
|
|
350
|
+
- `.yaml`
|
|
351
|
+
- `.md`
|
|
352
|
+
|
|
353
|
+
For `.md` files in v1, the file contents are parsed as YAML. Mixed markdown prose is out of scope for v1.
|
|
354
|
+
|
|
355
|
+
### Implemented Root Shape
|
|
356
|
+
|
|
357
|
+
```yaml
|
|
358
|
+
version: 1
|
|
359
|
+
|
|
360
|
+
project:
|
|
361
|
+
name: example-project
|
|
362
|
+
defaultApp: example-app
|
|
363
|
+
|
|
364
|
+
apps:
|
|
365
|
+
example-app:
|
|
366
|
+
metadata:
|
|
367
|
+
baseDir: metadata
|
|
368
|
+
format: yaml
|
|
369
|
+
screenshots:
|
|
370
|
+
baseDir: screenshots
|
|
371
|
+
|
|
372
|
+
apple:
|
|
373
|
+
appId: "0000000000"
|
|
374
|
+
credentials:
|
|
375
|
+
issuerIdEnv: STORE_APPLE_ISSUER_ID
|
|
376
|
+
keyIdEnv: STORE_APPLE_KEY_ID
|
|
377
|
+
privateKeyPathEnv: STORE_APPLE_PRIVATE_KEY_PATH
|
|
378
|
+
locales:
|
|
379
|
+
default: [en-US]
|
|
380
|
+
map:
|
|
381
|
+
zh-CN: zh-Hans
|
|
382
|
+
zh-TW: zh-Hant
|
|
383
|
+
|
|
384
|
+
google:
|
|
385
|
+
packageName: com.example.app
|
|
386
|
+
credentials:
|
|
387
|
+
serviceAccountPathEnv: STORE_GOOGLE_SERVICE_ACCOUNT_PATH
|
|
388
|
+
locales:
|
|
389
|
+
default: [en-US]
|
|
390
|
+
map:
|
|
391
|
+
en_US: en-US
|
|
392
|
+
iw-IL: he-IL
|
|
393
|
+
screenshots:
|
|
394
|
+
groups:
|
|
395
|
+
english:
|
|
396
|
+
locales: [en-US, en-GB, en-AU, en-CA]
|
|
397
|
+
spanish:
|
|
398
|
+
locales: [es-ES, es-419, es-US]
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### App Model
|
|
402
|
+
|
|
403
|
+
The config intentionally supports both single-app and multi-app usage.
|
|
404
|
+
|
|
405
|
+
Single-app usage:
|
|
406
|
+
- define one entry under `apps`
|
|
407
|
+
- set `project.defaultApp`
|
|
408
|
+
- omit `--app` in normal usage
|
|
409
|
+
|
|
410
|
+
Multi-app usage:
|
|
411
|
+
- define multiple app entries
|
|
412
|
+
- use `--app <id>` when needed
|
|
413
|
+
|
|
414
|
+
This avoids blocking the implementation on a final app model decision.
|
|
415
|
+
|
|
416
|
+
### Metadata File Layout
|
|
417
|
+
|
|
418
|
+
Recommended:
|
|
419
|
+
|
|
420
|
+
```text
|
|
421
|
+
metadata/
|
|
422
|
+
apple/
|
|
423
|
+
en-US.yml
|
|
424
|
+
tr.yml
|
|
425
|
+
google/
|
|
426
|
+
en-US.yml
|
|
427
|
+
tr-TR.yml
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
Allowed alternative:
|
|
431
|
+
|
|
432
|
+
```text
|
|
433
|
+
metadata/
|
|
434
|
+
apple/
|
|
435
|
+
en-US.md
|
|
436
|
+
google/
|
|
437
|
+
en-US.md
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
### Metadata Schema
|
|
441
|
+
|
|
442
|
+
#### Apple
|
|
443
|
+
|
|
444
|
+
```yaml
|
|
445
|
+
locale: en-US
|
|
446
|
+
app_name: Example App
|
|
447
|
+
subtitle: Short subtitle
|
|
448
|
+
keywords: one,two,three
|
|
449
|
+
promotional_text: Optional promo text
|
|
450
|
+
description: |
|
|
451
|
+
Long description text.
|
|
452
|
+
whats_new: |
|
|
453
|
+
What changed in this version.
|
|
454
|
+
support_url: https://example.com/support
|
|
455
|
+
marketing_url: https://example.com
|
|
456
|
+
privacy_policy_url: https://example.com/privacy
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
#### Google
|
|
460
|
+
|
|
461
|
+
```yaml
|
|
462
|
+
locale: en-US
|
|
463
|
+
title: Example App
|
|
464
|
+
short_description: Short description
|
|
465
|
+
full_description: |
|
|
466
|
+
Long description text.
|
|
467
|
+
video: https://example.com/video
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
### Screenshot Layout
|
|
471
|
+
|
|
472
|
+
Recommended:
|
|
473
|
+
|
|
474
|
+
```text
|
|
475
|
+
screenshots/
|
|
476
|
+
apple/
|
|
477
|
+
en-US/
|
|
478
|
+
APP_IPHONE_65/
|
|
479
|
+
1.png
|
|
480
|
+
2.png
|
|
481
|
+
google/
|
|
482
|
+
en-US/
|
|
483
|
+
phoneScreenshots/
|
|
484
|
+
1.png
|
|
485
|
+
2.png
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
Canonical stored values should match platform display types and image types.
|
|
489
|
+
|
|
490
|
+
The product should normalize pulled assets into locale-specific folders while still allowing config-driven grouping for push behavior.
|
|
491
|
+
|
|
492
|
+
### Credentials
|
|
493
|
+
|
|
494
|
+
Secrets must never be committed.
|
|
495
|
+
|
|
496
|
+
Recommended environment variables:
|
|
497
|
+
|
|
498
|
+
Apple:
|
|
499
|
+
- `STORE_APPLE_ISSUER_ID`
|
|
500
|
+
- `STORE_APPLE_KEY_ID`
|
|
501
|
+
- `STORE_APPLE_PRIVATE_KEY_PATH`
|
|
502
|
+
|
|
503
|
+
Possible later support:
|
|
504
|
+
- `STORE_APPLE_PRIVATE_KEY`
|
|
505
|
+
|
|
506
|
+
Google:
|
|
507
|
+
- `STORE_GOOGLE_SERVICE_ACCOUNT_PATH`
|
|
508
|
+
|
|
509
|
+
Possible later support:
|
|
510
|
+
- `STORE_GOOGLE_SERVICE_ACCOUNT_JSON`
|
|
511
|
+
|
|
512
|
+
### Auth Troubleshooting
|
|
513
|
+
|
|
514
|
+
Apple:
|
|
515
|
+
- confirm `STORE_APPLE_ISSUER_ID`, `STORE_APPLE_KEY_ID`, and `STORE_APPLE_PRIVATE_KEY_PATH` are set in the shell that runs `storemeta`
|
|
516
|
+
- confirm the `.p8` file exists at `STORE_APPLE_PRIVATE_KEY_PATH`
|
|
517
|
+
- confirm the key belongs to App Store Connect API access, not another Apple credential type
|
|
518
|
+
- confirm the API key has access to the target app in App Store Connect
|
|
519
|
+
- if the CLI reports a missing Apple credential env var, fix the env var name or shell export first before checking API behavior
|
|
520
|
+
|
|
521
|
+
Google:
|
|
522
|
+
- confirm `STORE_GOOGLE_SERVICE_ACCOUNT_PATH` points to a readable service account JSON file
|
|
523
|
+
- confirm the service account has Play Console access to the target app
|
|
524
|
+
- confirm the configured `packageName` matches the Play Console app exactly
|
|
525
|
+
- if the CLI reports a missing Google credential env var, fix the env var export first before checking API behavior
|
|
526
|
+
|
|
527
|
+
General:
|
|
528
|
+
- run `storemeta validate` before any push command
|
|
529
|
+
- keep credentials out of `storemeta.yml`
|
|
530
|
+
- prefer absolute credential file paths in local environment exports to avoid path confusion across shells and CI jobs
|
|
531
|
+
|
|
532
|
+
### Validation Rules
|
|
533
|
+
|
|
534
|
+
The config validator should enforce:
|
|
535
|
+
- `version` exists and is supported
|
|
536
|
+
- `project.defaultApp` points to a real app key
|
|
537
|
+
- each selected platform has required identifiers
|
|
538
|
+
- each selected platform has credentials configured
|
|
539
|
+
- base directories are relative and valid
|
|
540
|
+
- locale overrides are explicit and deterministic
|
|
541
|
+
|
|
542
|
+
### Backward Compatibility
|
|
543
|
+
|
|
544
|
+
The config version must be explicit. Breaking changes should bump `version`.
|
|
545
|
+
|
|
546
|
+
## 8. Validation Requirements
|
|
547
|
+
|
|
548
|
+
Validation is a first-class feature, not an afterthought.
|
|
549
|
+
|
|
550
|
+
The validator should check:
|
|
551
|
+
- config schema
|
|
552
|
+
- credentials presence
|
|
553
|
+
- metadata required fields
|
|
554
|
+
- metadata length rules
|
|
555
|
+
- locale mapping consistency
|
|
556
|
+
- screenshot path structure
|
|
557
|
+
- screenshot file ordering and supported extensions
|
|
558
|
+
|
|
559
|
+
Examples of platform-specific validation:
|
|
560
|
+
|
|
561
|
+
Google Play metadata:
|
|
562
|
+
- title length
|
|
563
|
+
- short description length
|
|
564
|
+
- full description length
|
|
565
|
+
|
|
566
|
+
Apple metadata:
|
|
567
|
+
- presence and validity of locale-specific fields
|
|
568
|
+
- future support for field length validation where practical
|
|
569
|
+
|
|
570
|
+
Screenshot validation:
|
|
571
|
+
- required directories exist
|
|
572
|
+
- files are ordered deterministically
|
|
573
|
+
- extensions are supported
|
|
574
|
+
- display type and image type folder names are valid
|
|
575
|
+
|
|
576
|
+
Additional validation rules for v1:
|
|
577
|
+
- destructive screenshot replacement must require a fully valid source set
|
|
578
|
+
- locale groups must resolve deterministically to target locales
|
|
579
|
+
- excluded screenshot files, if configured, should be applied predictably before upload planning
|
|
580
|
+
- Apple upload plans should validate the existence of required screenshot set display types before write operations where possible
|
|
581
|
+
|
|
582
|
+
## 9. Release Plan
|
|
583
|
+
|
|
584
|
+
### Initial Distribution
|
|
585
|
+
|
|
586
|
+
Initial release target:
|
|
587
|
+
- npm only
|
|
588
|
+
|
|
589
|
+
Deferred:
|
|
590
|
+
- Homebrew
|
|
591
|
+
|
|
592
|
+
### Planned Package Shape
|
|
593
|
+
|
|
594
|
+
- package name: `storemeta`
|
|
595
|
+
- executable name: `storemeta`
|
|
596
|
+
- compiled output in `dist/`
|
|
597
|
+
- npm package exports the CLI through the `bin` field
|
|
598
|
+
|
|
599
|
+
### Open Source Defaults
|
|
600
|
+
|
|
601
|
+
- public GitHub repository
|
|
602
|
+
- MIT license
|
|
603
|
+
- semantic versioning
|
|
604
|
+
- `0.x` while config and commands are still changing
|
|
605
|
+
- `1.0.0` only after config and command stability
|
|
606
|
+
|
|
607
|
+
### Minimum Release Checklist
|
|
608
|
+
|
|
609
|
+
Before the first public release:
|
|
610
|
+
|
|
611
|
+
1. rotate and remove any preexisting development credentials before publishing
|
|
612
|
+
2. remove secret-bearing files and code
|
|
613
|
+
3. ensure no secrets remain in git history before publishing
|
|
614
|
+
4. add `.gitignore`
|
|
615
|
+
5. add `package.json`
|
|
616
|
+
6. add TypeScript config and build scripts
|
|
617
|
+
7. implement the documented CLI surface
|
|
618
|
+
8. add smoke-level automated tests
|
|
619
|
+
9. add example config and fake example metadata files
|
|
620
|
+
10. verify npm install and CLI execution
|
|
621
|
+
11. verify the CLI against one real Apple app and one real Google Play app using rotated credentials only
|
|
622
|
+
|
|
623
|
+
### Suggested Repository Files
|
|
624
|
+
|
|
625
|
+
Minimum:
|
|
626
|
+
- `README.md`
|
|
627
|
+
- `docs/DOCUMENTATION.md`
|
|
628
|
+
- `docs/PROJECT_PLAN.md`
|
|
629
|
+
- `LICENSE`
|
|
630
|
+
- `SECURITY.md`
|
|
631
|
+
- `package.json`
|
|
632
|
+
- `tsconfig.json`
|
|
633
|
+
- `src/`
|
|
634
|
+
|
|
635
|
+
Likely next:
|
|
636
|
+
- `.gitignore`
|
|
637
|
+
- package `files` allowlist
|
|
638
|
+
- `CHANGELOG.md`
|
|
639
|
+
- `CONTRIBUTING.md`
|
|
640
|
+
- GitHub Actions workflows
|
|
641
|
+
|
|
642
|
+
## 10. Security
|
|
643
|
+
|
|
644
|
+
Any development credentials that have ever been stored locally in this project must be treated as exposed until rotated.
|
|
645
|
+
|
|
646
|
+
Required actions before publishing:
|
|
647
|
+
- rotate the exposed App Store Connect keys
|
|
648
|
+
- remove or replace all secret-bearing code
|
|
649
|
+
- ensure secrets are not present in git history
|
|
650
|
+
- move all runtime credentials to environment variables or ignored local files
|
|
651
|
+
|
|
652
|
+
Secret handling rules for this project:
|
|
653
|
+
- never commit private keys
|
|
654
|
+
- never commit service account JSON files
|
|
655
|
+
- never commit real `.env` files
|
|
656
|
+
- use fake values in examples and tests
|
|
657
|
+
- prefer environment variables over inline config
|
|
658
|
+
|
|
659
|
+
## 11. Feasibility
|
|
660
|
+
|
|
661
|
+
This project is feasible now.
|
|
662
|
+
|
|
663
|
+
The required integrations are within scope:
|
|
664
|
+
- App Store Connect JWT auth
|
|
665
|
+
- App Store metadata reads and writes
|
|
666
|
+
- App Store screenshot upload flow
|
|
667
|
+
- Google Play edits flow
|
|
668
|
+
- Google Play metadata reads and writes
|
|
669
|
+
- Google Play screenshot upload flow
|
|
670
|
+
|
|
671
|
+
The remaining work is release verification:
|
|
672
|
+
- run the CLI against real Apple and Google test apps
|
|
673
|
+
- confirm no secret material is present in docs, logs, package contents, or git history
|
|
674
|
+
- publish the first npm package once verification is complete
|
|
675
|
+
|
|
676
|
+
The largest residual risk is real-store API behavior that unit tests cannot fully model.
|
|
677
|
+
|
|
678
|
+
## 12. Recommended Next Steps
|
|
679
|
+
|
|
680
|
+
Release work should continue in this order:
|
|
681
|
+
|
|
682
|
+
1. verify Apple metadata pull and push with a real test app
|
|
683
|
+
2. verify Google metadata pull and push with a real test app
|
|
684
|
+
3. verify Apple screenshot pull and push with a real test app
|
|
685
|
+
4. verify Google screenshot pull and push with a real test app
|
|
686
|
+
5. inspect packed package contents and git history for secrets
|
|
687
|
+
6. publish and tag the first release
|