vydanne 0.5.0 → 0.7.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/GETTING_STARTED.md +69 -40
- package/README.md +161 -23
- package/SKILL.md +158 -26
- package/bin/vydanne.mjs +67 -13
- package/package.json +4 -3
- package/src/client.mjs +78 -7
- package/src/commands/accessibility.mjs +13 -0
- package/src/commands/ageRating.mjs +94 -21
- package/src/commands/bridge.mjs +328 -0
- package/src/commands/compliance.mjs +78 -9
- package/src/commands/diff.mjs +63 -19
- package/src/commands/fill.mjs +85 -13
- package/src/commands/inspect.mjs +4 -2
- package/src/commands/preflight.mjs +65 -6
- package/src/commands/prepare.mjs +220 -0
- package/src/commands/prerelease.mjs +25 -5
- package/src/commands/previews.mjs +43 -5
- package/src/commands/privacy.mjs +75 -5
- package/src/commands/push.mjs +118 -0
- package/src/commands/reviewContact.mjs +65 -14
- package/src/config.mjs +55 -4
- package/src/crossStore.mjs +151 -0
- package/src/index.mjs +60 -3
- package/src/locales.mjs +27 -5
- package/src/play/aab.mjs +133 -0
- package/src/play/client.mjs +6 -3
- package/src/play/commands/diff.mjs +40 -0
- package/src/play/commands/fill.mjs +32 -24
- package/src/play/commands/preflight.mjs +5 -0
- package/src/play/commands/prerelease.mjs +96 -22
- package/src/play/images.mjs +67 -0
- package/src/registry.mjs +27 -9
- package/src/screenshots.mjs +112 -0
- package/src/upload.mjs +6 -1
- package/types/index.d.ts +240 -10
- package/vydanne.config.example.mjs +54 -1
package/types/index.d.ts
CHANGED
|
@@ -5,6 +5,19 @@ export type Platform = 'IOS' | 'MAC_OS';
|
|
|
5
5
|
|
|
6
6
|
/** Every vydanne CLI command (kept in sync with src/registry.mjs by scripts/check-types.mjs). */
|
|
7
7
|
export type CommandName =
|
|
8
|
+
/**
|
|
9
|
+
* Create (or reuse) the App Store version being prepared and attach the newest build to it.
|
|
10
|
+
* Lands in PREPARE_FOR_SUBMISSION with `releaseType: MANUAL` — it does not submit for review.
|
|
11
|
+
* Required first on an app with a version already on sale: only then does a draft exist for
|
|
12
|
+
* `fill` to write into. Override the version with VYDANNE_VERSION.
|
|
13
|
+
*/
|
|
14
|
+
| 'prepare'
|
|
15
|
+
/**
|
|
16
|
+
* The whole release pipeline in its one working order: prepare → fill → previews → age-rating →
|
|
17
|
+
* review-contact → accessibility → preflight. Dry-run without --apply; stops at the first failure;
|
|
18
|
+
* never submits — Add to Review and Submit stay manual.
|
|
19
|
+
*/
|
|
20
|
+
| 'push'
|
|
8
21
|
| 'fill'
|
|
9
22
|
| 'age-rating'
|
|
10
23
|
| 'review-contact'
|
|
@@ -13,6 +26,12 @@ export type CommandName =
|
|
|
13
26
|
| 'previews'
|
|
14
27
|
| 'iap'
|
|
15
28
|
| 'compliance'
|
|
29
|
+
/**
|
|
30
|
+
* Map zdymak's output (`store-assets/<locale>/<target>/NN-name.png`) onto the folders `fill`
|
|
31
|
+
* uploads from — ASC locale codes, device-slot filename prefixes, and the Play read paths.
|
|
32
|
+
* Local files only; `--dry-run` previews. Run after `zdymak screenshots`/`build`, before `fill`.
|
|
33
|
+
*/
|
|
34
|
+
| 'bridge'
|
|
16
35
|
| 'inspect'
|
|
17
36
|
| 'diff'
|
|
18
37
|
| 'preflight'
|
|
@@ -97,10 +116,103 @@ export interface GoogleConfig {
|
|
|
97
116
|
defaultLocale?: string;
|
|
98
117
|
/** `.aab` for `prerelease` — a file, or a directory whose NEWEST .aab is taken. Override: VYDANNE_AAB. */
|
|
99
118
|
aab?: string;
|
|
100
|
-
/**
|
|
101
|
-
|
|
119
|
+
/**
|
|
120
|
+
* Testing track for `prerelease`. 'internal' (default), 'alpha', 'beta', or the name of any closed
|
|
121
|
+
* track you created in Play Console. Only 'production' is refused — that release is a human's.
|
|
122
|
+
*/
|
|
123
|
+
track?: string;
|
|
124
|
+
/**
|
|
125
|
+
* Play image type -> local source path. Merged over the defaults, so declare only what differs.
|
|
126
|
+
* A type whose source does not exist is skipped; a missing local set never deletes the live one.
|
|
127
|
+
*/
|
|
128
|
+
images?: Partial<Record<PlayImageType, string>>;
|
|
129
|
+
/**
|
|
130
|
+
* Locales to upload graphics to. Play holds images per language; the default is one set at
|
|
131
|
+
* `defaultLocale`. Pass a list, or '*' for every local listing folder. A `<source>/<lang>`
|
|
132
|
+
* subdirectory, when present, overrides the shared source for that language.
|
|
133
|
+
*/
|
|
134
|
+
imageLocales?: string[] | "*";
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** Play listing image slots. */
|
|
138
|
+
export type PlayImageType =
|
|
139
|
+
| "icon"
|
|
140
|
+
| "featureGraphic"
|
|
141
|
+
| "tvBanner"
|
|
142
|
+
| "phoneScreenshots"
|
|
143
|
+
| "sevenInchScreenshots"
|
|
144
|
+
| "tenInchScreenshots"
|
|
145
|
+
| "wearScreenshots"
|
|
146
|
+
| "tvScreenshots";
|
|
147
|
+
|
|
148
|
+
/** Where `bridge` reads zdymak's output from, and which directory feeds which store slot. */
|
|
149
|
+
export interface BridgeConfig {
|
|
150
|
+
/** zdymak's output root. Read from zdymak.config.mjs when absent; './store-assets' otherwise. */
|
|
151
|
+
out?: string;
|
|
152
|
+
/**
|
|
153
|
+
* Screenshot slot token -> the zdymak output directory it comes from (a name, or names in
|
|
154
|
+
* preference order). Defaults cover zdymak's own target names; override when `dir:` in
|
|
155
|
+
* zdymak.config.mjs makes the directory name differ from the target name.
|
|
156
|
+
*/
|
|
157
|
+
apple?: Record<string, string | string[]>;
|
|
158
|
+
/** Play image type -> the zdymak output directory it comes from. Same shape and reason. */
|
|
159
|
+
play?: Partial<Record<PlayImageType, string | string[]>>;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** Overrides for the App Review contact. The PII itself stays in gitignored .txt files. */
|
|
163
|
+
export interface ReviewContactConfig {
|
|
164
|
+
/**
|
|
165
|
+
* Whether App Review needs a demo account. Inferred from the presence of
|
|
166
|
+
* `<metadataDir>/review_information/demo_user.txt` when omitted — set it only to disagree.
|
|
167
|
+
*/
|
|
168
|
+
demoAccountRequired?: boolean;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** `push` defaults. `--skip` adds to this per invocation. */
|
|
172
|
+
export interface PushConfig {
|
|
173
|
+
/** Steps this app never runs. 'prepare' and 'preflight' cannot be skipped. */
|
|
174
|
+
skip?: CommandName[];
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Age-rating content descriptors, for any rating other than '4+'.
|
|
179
|
+
*
|
|
180
|
+
* Merged over an all-NONE base, so declare only what applies. Apple computes the rating band from
|
|
181
|
+
* these — you describe the content, it decides the number. Enum keys take
|
|
182
|
+
* 'NONE' | 'INFREQUENT_OR_MILD' | 'FREQUENT_OR_INTENSE'; the rest are booleans.
|
|
183
|
+
*/
|
|
184
|
+
export interface AgeRatingConfig {
|
|
185
|
+
advertising?: boolean;
|
|
186
|
+
alcoholTobaccoOrDrugUseOrReferences?: AgeRatingLevel;
|
|
187
|
+
contests?: AgeRatingLevel;
|
|
188
|
+
gambling?: boolean;
|
|
189
|
+
gamblingSimulated?: AgeRatingLevel;
|
|
190
|
+
gunsOrOtherWeapons?: AgeRatingLevel;
|
|
191
|
+
healthOrWellnessTopics?: boolean;
|
|
192
|
+
kidsAgeBand?: "FIVE_AND_UNDER" | "SIX_TO_EIGHT" | "NINE_TO_ELEVEN" | null;
|
|
193
|
+
lootBox?: boolean;
|
|
194
|
+
medicalOrTreatmentInformation?: AgeRatingLevel;
|
|
195
|
+
messagingAndChat?: boolean;
|
|
196
|
+
parentalControls?: boolean;
|
|
197
|
+
profanityOrCrudeHumor?: AgeRatingLevel;
|
|
198
|
+
ageAssurance?: boolean;
|
|
199
|
+
sexualContentGraphicAndNudity?: AgeRatingLevel;
|
|
200
|
+
sexualContentOrNudity?: AgeRatingLevel;
|
|
201
|
+
socialMedia?: boolean;
|
|
202
|
+
socialMediaAgeRestricted?: boolean;
|
|
203
|
+
horrorOrFearThemes?: AgeRatingLevel;
|
|
204
|
+
matureOrSuggestiveThemes?: AgeRatingLevel;
|
|
205
|
+
unrestrictedWebAccess?: boolean;
|
|
206
|
+
userGeneratedContent?: boolean;
|
|
207
|
+
violenceCartoonOrFantasy?: AgeRatingLevel;
|
|
208
|
+
violenceRealisticProlongedGraphicOrSadistic?: AgeRatingLevel;
|
|
209
|
+
violenceRealistic?: AgeRatingLevel;
|
|
210
|
+
ageRatingOverrideV2?: AgeRatingLevel;
|
|
211
|
+
koreaAgeRatingOverride?: AgeRatingLevel;
|
|
102
212
|
}
|
|
103
213
|
|
|
214
|
+
export type AgeRatingLevel = "NONE" | "INFREQUENT_OR_MILD" | "FREQUENT_OR_INTENSE";
|
|
215
|
+
|
|
104
216
|
export interface ExportConfig {
|
|
105
217
|
/** 'standard' → self-classify (ECCN 5D002, ENC 740.17(b)(1)); else no compliance doc is generated. */
|
|
106
218
|
encryption: string;
|
|
@@ -109,6 +221,19 @@ export interface ExportConfig {
|
|
|
109
221
|
appName?: string;
|
|
110
222
|
version?: string;
|
|
111
223
|
teamId?: string;
|
|
224
|
+
/**
|
|
225
|
+
* The app's cryptography inventory: [purpose, algorithm, keySize] per row. REQUIRED when
|
|
226
|
+
* `encryption` is 'standard' — `compliance` will not invent one, because the PDF it generates makes
|
|
227
|
+
* factual claims to a US export authority.
|
|
228
|
+
*/
|
|
229
|
+
algorithms?: Array<[string, string, string?]>;
|
|
230
|
+
/** The statement paragraph, in your own words. REQUIRED when `encryption` is 'standard'. */
|
|
231
|
+
statement?: string;
|
|
232
|
+
/**
|
|
233
|
+
* Set true only once the report has ACTUALLY been emailed to BIS and the NSA. When false (default)
|
|
234
|
+
* the generated PDF does not claim it was submitted.
|
|
235
|
+
*/
|
|
236
|
+
filed?: boolean;
|
|
112
237
|
}
|
|
113
238
|
|
|
114
239
|
/** The `vydanne.config.mjs` default export. */
|
|
@@ -126,9 +251,23 @@ export interface VydanneConfig {
|
|
|
126
251
|
platforms?: Platform[];
|
|
127
252
|
/** App UI locales; mapped to ASC codes (unsupported ones fall back to primary). */
|
|
128
253
|
uiLocales?: string[];
|
|
254
|
+
/**
|
|
255
|
+
* App locale code -> App Store locale code, for codes Apple spells differently or does not know.
|
|
256
|
+
* Merged over the built-in table, so declare only your exceptions. An override naming a code Apple
|
|
257
|
+
* does not have is reported by `locales` and `preflight` rather than silently ignored.
|
|
258
|
+
*/
|
|
259
|
+
localeMap?: Record<string, string>;
|
|
129
260
|
metadataDir?: string;
|
|
130
|
-
/**
|
|
261
|
+
/**
|
|
262
|
+
* Where each platform's screenshots live. Defaults to fastlane's supply convention
|
|
263
|
+
* ('fastlane/screenshots' and 'fastlane/screenshots-macos'). Read by `fill`, `diff`, `preflight`
|
|
264
|
+
* and written by `bridge`.
|
|
265
|
+
*/
|
|
266
|
+
screenshots?: { IOS?: string; MAC_OS?: string };
|
|
267
|
+
/** e.g. '4+'. Anything else needs `ageRating` to say what makes it that. */
|
|
131
268
|
rating?: string;
|
|
269
|
+
/** Content descriptors for a rating above '4+'. Merged over an all-NONE base. */
|
|
270
|
+
ageRating?: AgeRatingConfig;
|
|
132
271
|
privacy?: PrivacyConfig;
|
|
133
272
|
iaps?: IapConfig[];
|
|
134
273
|
previews?: PreviewSpec[];
|
|
@@ -139,31 +278,122 @@ export interface VydanneConfig {
|
|
|
139
278
|
ios?: IosConfig;
|
|
140
279
|
/** Google Play (`--store google`): listings, screenshots, feature graphic via the Edits API. */
|
|
141
280
|
google?: GoogleConfig;
|
|
281
|
+
/** Where `bridge` reads zdymak's output from, and which directory feeds which store slot. */
|
|
282
|
+
bridge?: BridgeConfig;
|
|
283
|
+
/** `push` defaults — steps this app never runs. */
|
|
284
|
+
push?: PushConfig;
|
|
285
|
+
/** App Review contact overrides (the PII itself stays in gitignored .txt files). */
|
|
286
|
+
reviewContact?: ReviewContactConfig;
|
|
287
|
+
/**
|
|
288
|
+
* Terms the cross-store check must not flag for this app.
|
|
289
|
+
*
|
|
290
|
+
* `preflight` and `fill` refuse listing text that names the OTHER mobile platform — App Review
|
|
291
|
+
* guideline 2.3.10 and Google Play's Store Listing and Promotion policy both reject it. Use this
|
|
292
|
+
* only for a word that genuinely belongs in your copy (a game about fruit really does say
|
|
293
|
+
* "apple"); it is not a way to ship a store name.
|
|
294
|
+
*/
|
|
295
|
+
allowCrossStoreTerms?: string[];
|
|
142
296
|
}
|
|
143
297
|
|
|
144
298
|
/** Thin ASC REST client (native fetch + ES256 JWT). */
|
|
145
299
|
export declare class Client {
|
|
146
|
-
constructor(opts: { keyId: string; issuerId: string });
|
|
300
|
+
constructor(opts: { keyId: string; issuerId: string; dryRun?: boolean });
|
|
147
301
|
token: string;
|
|
148
302
|
appId?: string;
|
|
149
303
|
app?: unknown;
|
|
304
|
+
/** When true, no POST/PATCH/PUT/DELETE leaves the process — each is recorded in `planned` instead. */
|
|
305
|
+
dryRun: boolean;
|
|
306
|
+
/** The mutations a real run would have sent, in order. Populated only while `dryRun`. */
|
|
307
|
+
planned: Array<{ method: string; path: string; attributes: Record<string, unknown> }>;
|
|
150
308
|
findApp(bundleId: string): Promise<unknown>;
|
|
151
309
|
get(path: string, opts?: { iris?: boolean }): Promise<{ status: number; json: any }>;
|
|
152
310
|
post(path: string, body: unknown): Promise<{ status: number; json: any }>;
|
|
153
311
|
patch(path: string, body: unknown): Promise<{ status: number; json: any }>;
|
|
154
|
-
|
|
155
|
-
|
|
312
|
+
del(path: string): Promise<{ status: number; json: any }>;
|
|
313
|
+
/**
|
|
314
|
+
* The version being prepared, or null when none exists. `allowLive` (read-only commands only) falls
|
|
315
|
+
* back to the version on sale; writes must never target it.
|
|
316
|
+
*/
|
|
317
|
+
editVersion(platform: Platform, opts?: { allowLive?: boolean }): Promise<any>;
|
|
318
|
+
/**
|
|
319
|
+
* The app-info being prepared (name/subtitle, age rating), or null when none exists. `allowLive`
|
|
320
|
+
* (read-only commands only) falls back to the live record; writes must never target it.
|
|
321
|
+
*/
|
|
322
|
+
appInfo(opts?: { allowLive?: boolean }): Promise<any>;
|
|
156
323
|
versionLocalizations(versionId: string): Promise<any[]>;
|
|
157
324
|
localization(id: string, kind?: string): Promise<Record<string, unknown>>;
|
|
158
325
|
}
|
|
159
326
|
|
|
160
|
-
|
|
327
|
+
/** Play Developer Edits API client. Every mutation happens inside an Edit; an uncommitted Edit is a no-op. */
|
|
328
|
+
export declare class PlayClient {
|
|
329
|
+
static create(opts: { keyPath: string; packageName: string; dryRun?: boolean }): Promise<PlayClient>;
|
|
330
|
+
dryRun: boolean;
|
|
331
|
+
newEdit(): Promise<string>;
|
|
332
|
+
validate(editId: string): Promise<{ status: number; json: any }>;
|
|
333
|
+
commit(editId: string): Promise<{ status: number; json: any }>;
|
|
334
|
+
deleteEdit(editId: string): Promise<unknown>;
|
|
335
|
+
getListings(editId: string): Promise<{ status: number; json: any }>;
|
|
336
|
+
putListing(editId: string, lang: string, body: Record<string, unknown>): Promise<{ status: number; json: any }>;
|
|
337
|
+
listImages(editId: string, lang: string, type: string): Promise<{ status: number; json: any }>;
|
|
338
|
+
deleteAllImages(editId: string, lang: string, type: string): Promise<unknown>;
|
|
339
|
+
uploadImage(editId: string, lang: string, type: string, file: string): Promise<unknown>;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
export type Store = "apple" | "google";
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Run one command, the way the CLI runs it — minus argv parsing and process.exit.
|
|
346
|
+
*
|
|
347
|
+
* `apply` defaults to FALSE, the same safety gate `--apply` drives: a caller that forgets it gets a
|
|
348
|
+
* dry run, never a write. `planned` is the machine-readable form of the writes a dry run withheld.
|
|
349
|
+
*/
|
|
350
|
+
export declare function runCommand(
|
|
351
|
+
name: string,
|
|
352
|
+
opts?: {
|
|
353
|
+
config?: VydanneConfig;
|
|
354
|
+
configPath?: string;
|
|
355
|
+
store?: Store;
|
|
356
|
+
apply?: boolean;
|
|
357
|
+
},
|
|
358
|
+
): Promise<{ ok: boolean; planned: Array<{ method: string; path: string; attributes: Record<string, unknown> }> }>;
|
|
359
|
+
|
|
360
|
+
export declare function loadConfig(path?: string): Promise<ResolvedConfig>;
|
|
161
361
|
export declare function makeToken(opts: { keyId: string; issuerId: string; keyPath?: string }): string;
|
|
162
|
-
export declare function resolveLocales(uiCodes: string[]
|
|
163
|
-
export declare function toAsc(code: string): string | null;
|
|
362
|
+
export declare function resolveLocales(uiCodes: string[], extra?: Record<string, string>): ResolvedLocales;
|
|
363
|
+
export declare function toAsc(code: string, extra?: Record<string, string>): string | null;
|
|
164
364
|
export declare const VALID: Set<string>;
|
|
365
|
+
export declare const UI_TO_ASC: Record<string, string>;
|
|
165
366
|
export declare const CONFIG_KEYS: readonly string[];
|
|
166
367
|
export declare const COMMAND_NAMES: readonly CommandName[];
|
|
167
|
-
export declare const COMMANDS: Record<string, { mod: string; client: boolean }>;
|
|
168
368
|
|
|
369
|
+
/** Screenshot filename prefix -> ASC display type, per platform. */
|
|
370
|
+
export declare const IOS_DEVICE: Record<string, string>;
|
|
371
|
+
export declare const MAC_DEVICE: Record<string, string>;
|
|
372
|
+
export declare const DEFAULT_SCREENSHOT_BASE: { IOS: string; MAC_OS: string };
|
|
373
|
+
/** Where this platform's screenshots live: `screenshots` in the config, else the supply convention. */
|
|
374
|
+
export declare function screenshotBase(platform: Platform, config?: VydanneConfig): string;
|
|
375
|
+
|
|
376
|
+
export declare const DEFAULT_PLAY_IMAGES: Partial<Record<PlayImageType, string>>;
|
|
377
|
+
export declare const PLAY_IMAGE_KIND: Record<PlayImageType, "file" | "dir">;
|
|
378
|
+
/** The resolved Play image table for one app: [type, localSource, kind][]. */
|
|
379
|
+
export declare function playImages(config: VydanneConfig): Array<[string, string, "file" | "dir"]>;
|
|
380
|
+
|
|
381
|
+
/** `writes` marks a command that mutates the STORE — those are dry-run unless the CLI gets `--apply`.
|
|
382
|
+
* `credentials` marks the one command (prerelease) whose altool child authenticates itself. */
|
|
383
|
+
export declare const COMMANDS: Record<string, { mod: string; client?: boolean; credentials?: boolean; writes?: boolean }>;
|
|
384
|
+
/** The same, for `--store google`. Same names, different backend. */
|
|
385
|
+
export declare const PLAY_COMMANDS: Record<string, { mod: string; writes?: boolean }>;
|
|
386
|
+
|
|
387
|
+
export interface ResolvedLocales {
|
|
388
|
+
supported: Record<string, string>;
|
|
389
|
+
/** Codes with no App Store language — they fall back to the primary listing. */
|
|
390
|
+
unsupported: string[];
|
|
391
|
+
/** `localeMap` entries pointing at a code Apple does not have. A config mistake, not a missing language. */
|
|
392
|
+
invalid: string[];
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
export type ResolvedConfig = VydanneConfig & { resolvedLocales: ResolvedLocales };
|
|
396
|
+
|
|
397
|
+
// NOTE: this is a TYPE-only default export — `import type cfg from "vydanne"`. There is no runtime
|
|
398
|
+
// default export, so `import cfg from "vydanne"` in JS gets undefined. Import the named values.
|
|
169
399
|
export default VydanneConfig;
|
|
@@ -12,9 +12,23 @@ export default {
|
|
|
12
12
|
// The app's UI locales. vydanne maps each to its ASC App Store code (de -> de-DE, ar -> ar-SA …) and
|
|
13
13
|
// flags any with no App Store language (e.g. Belarusian `be`) so you never abort an upload on a bad name.
|
|
14
14
|
uiLocales: ["en", "de", "es", "fr", "ja", "zh-Hans"],
|
|
15
|
+
// Only for codes the built-in table doesn't cover — e.g. if your resource folders use Android's
|
|
16
|
+
// spellings. Merged over the defaults, and an entry naming a code Apple doesn't have is reported.
|
|
17
|
+
// localeMap: { nb: "no", iw: "he" },
|
|
15
18
|
metadataDir: "fastlane/metadata",
|
|
19
|
+
// Defaults to fastlane's supply convention; set it if your repo puts them somewhere else.
|
|
20
|
+
// screenshots: { IOS: "fastlane/screenshots", MAC_OS: "fastlane/screenshots-macos" },
|
|
16
21
|
|
|
17
22
|
rating: "4+",
|
|
23
|
+
// Only needed when `rating` is above 4+. Describe the CONTENT — Apple computes the band from it.
|
|
24
|
+
// Merged over an all-NONE base, so declare just what applies. Enum keys take
|
|
25
|
+
// NONE | INFREQUENT_OR_MILD | FREQUENT_OR_INTENSE; the rest are booleans.
|
|
26
|
+
// ageRating: { violenceCartoonOrFantasy: "INFREQUENT_OR_MILD", userGeneratedContent: false },
|
|
27
|
+
|
|
28
|
+
// App Review contact. The PII stays in the gitignored fastlane/metadata/review_information/*.txt —
|
|
29
|
+
// including demo_user.txt / demo_password.txt, which is how vydanne decides whether a demo account is
|
|
30
|
+
// required. Set this only to disagree with what's on disk.
|
|
31
|
+
// reviewContact: { demoAccountRequired: false },
|
|
18
32
|
|
|
19
33
|
// Honest, minimal privacy — "accesses" is not "collects"; E2EE content the developer can't read is not
|
|
20
34
|
// collected. Declare only what actually leaves the device to you.
|
|
@@ -36,7 +50,38 @@ export default {
|
|
|
36
50
|
{ platform: "IOS", type: "IPHONE_67", file: "marketing/out/appstore-preview.mp4", poster: "00:00:05:00", locales: ["en-GB", "en-US"] },
|
|
37
51
|
],
|
|
38
52
|
|
|
39
|
-
|
|
53
|
+
// Export compliance. `algorithms` and `statement` are REQUIRED when encryption is "standard" — this
|
|
54
|
+
// generates a US export-compliance PDF that makes factual claims, so it will not guess them for you.
|
|
55
|
+
// `filed` stays false until you have actually emailed the report to BIS and the NSA; while it is
|
|
56
|
+
// false the PDF does not claim it was submitted.
|
|
57
|
+
export: {
|
|
58
|
+
encryption: "standard",
|
|
59
|
+
france: true,
|
|
60
|
+
appName: "Example",
|
|
61
|
+
version: "1.0",
|
|
62
|
+
teamId: "ABCDE12345",
|
|
63
|
+
algorithms: [
|
|
64
|
+
["Transport", "TLS 1.2 / 1.3", "standard"],
|
|
65
|
+
],
|
|
66
|
+
statement:
|
|
67
|
+
"The product uses TLS for network transport only. It is a mass-market consumer application " +
|
|
68
|
+
"distributed through public app stores, uses only standard published algorithms, and qualifies " +
|
|
69
|
+
"for export under License Exception ENC, EAR 740.17(b)(1), ECCN 5D002.",
|
|
70
|
+
filed: false,
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
// `bridge` maps zdymak's output onto the folders `fill` reads. Defaults cover zdymak's own directory
|
|
74
|
+
// names; override only when a `dir:` in zdymak.config.mjs makes the folder name differ from the
|
|
75
|
+
// target name (e.g. Play's 7" slot, which can only exist as `{ target: 'play-tablet', dir: … }`).
|
|
76
|
+
// bridge: {
|
|
77
|
+
// out: "./store-assets",
|
|
78
|
+
// apple: { iphone69: "appstore-iphone-6.9" },
|
|
79
|
+
// play: { sevenInchScreenshots: "play-tablet7-plain" },
|
|
80
|
+
// },
|
|
81
|
+
|
|
82
|
+
// Pipeline steps this app never runs. `--skip` adds to it per invocation; either way every skip is
|
|
83
|
+
// reported at the end, so a green `push` never overstates what it checked.
|
|
84
|
+
// push: { skip: ["accessibility"] },
|
|
40
85
|
|
|
41
86
|
// Google Play (optional). Add this block + set PLAY_JSON_KEY_FILE to the service-account JSON, then run
|
|
42
87
|
// any command with `--store google`. Package-SCOPED: vydanne only ever touches THIS packageName — a
|
|
@@ -52,5 +97,13 @@ export default {
|
|
|
52
97
|
packageName: "com.example.app",
|
|
53
98
|
metadataDir: "fastlane/metadata/android",
|
|
54
99
|
defaultLocale: "en-GB",
|
|
100
|
+
// 'internal' (default), 'alpha', 'beta', or the name of any closed track you made in Play Console.
|
|
101
|
+
// Only 'production' is refused.
|
|
102
|
+
// track: "internal",
|
|
103
|
+
// Play image type -> local source. Merged over the defaults, so override only what differs.
|
|
104
|
+
// images: { icon: "brand/icons/play/icon-512.png", phoneScreenshots: "marketing/out/play-phone-plain" },
|
|
105
|
+
// Play holds graphics PER LANGUAGE. Default is one set at `defaultLocale`; list locales (or "*")
|
|
106
|
+
// to localize them, and put per-language files in `<source>/<lang>/`.
|
|
107
|
+
// imageLocales: ["en-GB", "de-DE"],
|
|
55
108
|
},
|
|
56
109
|
};
|