@appeeky/spec 0.0.0-stage → 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/.github/assets/cover.gif +0 -0
- package/LICENSE +110 -0
- package/README.md +483 -2
- package/dist/ads.d.ts +39 -0
- package/dist/ads.js +67 -0
- package/dist/appeeky-api.d.ts +62 -0
- package/dist/appeeky-api.js +240 -0
- package/dist/attribution-setup.d.ts +28 -0
- package/dist/attribution-setup.js +65 -0
- package/dist/attribution.d.ts +121 -0
- package/dist/attribution.js +170 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +4 -0
- package/dist/category.d.ts +71 -0
- package/dist/category.js +198 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +1387 -0
- package/dist/competitors.d.ts +74 -0
- package/dist/competitors.js +143 -0
- package/dist/control.d.ts +21 -0
- package/dist/control.js +53 -0
- package/dist/core.d.ts +15 -0
- package/dist/core.js +15 -0
- package/dist/coverage.d.ts +46 -0
- package/dist/coverage.js +115 -0
- package/dist/data.d.ts +48 -0
- package/dist/data.js +298 -0
- package/dist/diff.d.ts +11 -0
- package/dist/diff.js +33 -0
- package/dist/experiments.d.ts +115 -0
- package/dist/experiments.js +85 -0
- package/dist/files.d.ts +27 -0
- package/dist/files.js +129 -0
- package/dist/history.d.ts +43 -0
- package/dist/history.js +55 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +24 -0
- package/dist/limits.d.ts +15 -0
- package/dist/limits.js +30 -0
- package/dist/lint.d.ts +16 -0
- package/dist/lint.js +159 -0
- package/dist/loops.d.ts +37 -0
- package/dist/loops.js +197 -0
- package/dist/measure.d.ts +40 -0
- package/dist/measure.js +159 -0
- package/dist/metrics.d.ts +270 -0
- package/dist/metrics.js +250 -0
- package/dist/output.d.ts +21 -0
- package/dist/output.js +79 -0
- package/dist/project.d.ts +19 -0
- package/dist/project.js +35 -0
- package/dist/report.d.ts +5 -0
- package/dist/report.js +71 -0
- package/dist/reviews.d.ts +130 -0
- package/dist/reviews.js +287 -0
- package/dist/schema.d.ts +519 -0
- package/dist/schema.js +218 -0
- package/dist/screenshots.d.ts +23 -0
- package/dist/screenshots.js +116 -0
- package/dist/setup.d.ts +45 -0
- package/dist/setup.js +226 -0
- package/dist/storefronts.d.ts +15 -0
- package/dist/storefronts.js +89 -0
- package/dist/stores/app-store.d.ts +33 -0
- package/dist/stores/app-store.js +159 -0
- package/dist/stores/google-play.d.ts +13 -0
- package/dist/stores/google-play.js +61 -0
- package/dist/stores/types.d.ts +34 -0
- package/dist/stores/types.js +2 -0
- package/dist/suggest.d.ts +73 -0
- package/dist/suggest.js +135 -0
- package/dist/text.d.ts +18 -0
- package/dist/text.js +55 -0
- package/dist/transport.d.ts +98 -0
- package/dist/transport.js +170 -0
- package/dist/verify.d.ts +70 -0
- package/dist/verify.js +134 -0
- package/dist/visibility.d.ts +149 -0
- package/dist/visibility.js +239 -0
- package/package.json +76 -4
- package/skills/appeeky-spec/SKILL.md +146 -0
- package/skills/appeeky-spec-experiments/SKILL.md +83 -0
- package/skills/appeeky-spec-localize/SKILL.md +52 -0
- package/skills/appeeky-spec-review/SKILL.md +75 -0
- package/skills/appeeky-spec-targets/SKILL.md +66 -0
- package/skills/appeeky-spec-visibility/SKILL.md +79 -0
package/dist/schema.d.ts
ADDED
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** Stores a spec can describe. The ids double as folder names under `appeeky/store/`. */
|
|
3
|
+
export declare const STORES: readonly ["app-store", "google-play"];
|
|
4
|
+
export type StoreId = (typeof STORES)[number];
|
|
5
|
+
/** How a store is reached: the local store CLI with your own key, or Appeeky's hosted gateway. */
|
|
6
|
+
export declare const transportMode: z.ZodEnum<["auto", "local", "hosted"]>;
|
|
7
|
+
export type TransportMode = z.infer<typeof transportMode>;
|
|
8
|
+
/** Store charts a category rank is read from. */
|
|
9
|
+
export declare const CHARTS: readonly ["top-free", "top-paid", "top-grossing"];
|
|
10
|
+
export type Chart = (typeof CHARTS)[number];
|
|
11
|
+
/** `appeeky.spec.yaml`: who the app is, where it ships, and what it should be found for. */
|
|
12
|
+
export declare const specFileSchema: z.ZodObject<{
|
|
13
|
+
version: z.ZodLiteral<1>;
|
|
14
|
+
app: z.ZodObject<{
|
|
15
|
+
name: z.ZodString;
|
|
16
|
+
/** Locale the store falls back to when a storefront has no localization of its own. */
|
|
17
|
+
primaryLocale: z.ZodDefault<z.ZodString>;
|
|
18
|
+
}, "strict", z.ZodTypeAny, {
|
|
19
|
+
name: string;
|
|
20
|
+
primaryLocale: string;
|
|
21
|
+
}, {
|
|
22
|
+
name: string;
|
|
23
|
+
primaryLocale?: string | undefined;
|
|
24
|
+
}>;
|
|
25
|
+
stores: z.ZodDefault<z.ZodObject<{
|
|
26
|
+
appStore: z.ZodOptional<z.ZodObject<{
|
|
27
|
+
/** Numeric App Store id (or a bundle id; the local CLI resolves it). */
|
|
28
|
+
appId: z.ZodString;
|
|
29
|
+
platform: z.ZodDefault<z.ZodEnum<["IOS", "MAC_OS", "TV_OS", "VISION_OS"]>>;
|
|
30
|
+
via: z.ZodDefault<z.ZodEnum<["auto", "local", "hosted"]>>;
|
|
31
|
+
/** Named account of the local `appstore` CLI. */
|
|
32
|
+
account: z.ZodOptional<z.ZodString>;
|
|
33
|
+
}, "strict", z.ZodTypeAny, {
|
|
34
|
+
appId: string;
|
|
35
|
+
platform: "IOS" | "MAC_OS" | "TV_OS" | "VISION_OS";
|
|
36
|
+
via: "auto" | "local" | "hosted";
|
|
37
|
+
account?: string | undefined;
|
|
38
|
+
}, {
|
|
39
|
+
appId: string;
|
|
40
|
+
platform?: "IOS" | "MAC_OS" | "TV_OS" | "VISION_OS" | undefined;
|
|
41
|
+
via?: "auto" | "local" | "hosted" | undefined;
|
|
42
|
+
account?: string | undefined;
|
|
43
|
+
}>>;
|
|
44
|
+
googlePlay: z.ZodOptional<z.ZodObject<{
|
|
45
|
+
packageName: z.ZodString;
|
|
46
|
+
via: z.ZodDefault<z.ZodEnum<["auto", "local", "hosted"]>>;
|
|
47
|
+
/** Named account of the local `gps` CLI (`gps accounts add`). */
|
|
48
|
+
account: z.ZodOptional<z.ZodString>;
|
|
49
|
+
/** Old name for `account`. */
|
|
50
|
+
profile: z.ZodOptional<z.ZodString>;
|
|
51
|
+
}, "strict", z.ZodTypeAny, {
|
|
52
|
+
via: "auto" | "local" | "hosted";
|
|
53
|
+
packageName: string;
|
|
54
|
+
account?: string | undefined;
|
|
55
|
+
profile?: string | undefined;
|
|
56
|
+
}, {
|
|
57
|
+
packageName: string;
|
|
58
|
+
via?: "auto" | "local" | "hosted" | undefined;
|
|
59
|
+
account?: string | undefined;
|
|
60
|
+
profile?: string | undefined;
|
|
61
|
+
}>>;
|
|
62
|
+
}, "strict", z.ZodTypeAny, {
|
|
63
|
+
appStore?: {
|
|
64
|
+
appId: string;
|
|
65
|
+
platform: "IOS" | "MAC_OS" | "TV_OS" | "VISION_OS";
|
|
66
|
+
via: "auto" | "local" | "hosted";
|
|
67
|
+
account?: string | undefined;
|
|
68
|
+
} | undefined;
|
|
69
|
+
googlePlay?: {
|
|
70
|
+
via: "auto" | "local" | "hosted";
|
|
71
|
+
packageName: string;
|
|
72
|
+
account?: string | undefined;
|
|
73
|
+
profile?: string | undefined;
|
|
74
|
+
} | undefined;
|
|
75
|
+
}, {
|
|
76
|
+
appStore?: {
|
|
77
|
+
appId: string;
|
|
78
|
+
platform?: "IOS" | "MAC_OS" | "TV_OS" | "VISION_OS" | undefined;
|
|
79
|
+
via?: "auto" | "local" | "hosted" | undefined;
|
|
80
|
+
account?: string | undefined;
|
|
81
|
+
} | undefined;
|
|
82
|
+
googlePlay?: {
|
|
83
|
+
packageName: string;
|
|
84
|
+
via?: "auto" | "local" | "hosted" | undefined;
|
|
85
|
+
account?: string | undefined;
|
|
86
|
+
profile?: string | undefined;
|
|
87
|
+
} | undefined;
|
|
88
|
+
}>>;
|
|
89
|
+
/** Target keywords per storefront: the searches this app should be found for. */
|
|
90
|
+
targets: z.ZodDefault<z.ZodRecord<z.ZodEffects<z.ZodString, string, string>, z.ZodDefault<z.ZodArray<z.ZodString, "many">>>>;
|
|
91
|
+
/** Override which listing locales a storefront indexes (App Store). */
|
|
92
|
+
storefronts: z.ZodDefault<z.ZodRecord<z.ZodEffects<z.ZodString, string, string>, z.ZodArray<z.ZodString, "many">>>;
|
|
93
|
+
/**
|
|
94
|
+
* Paid channels outside the store. Apple Search Ads needs nothing here: it is
|
|
95
|
+
* matched to the app in Appeeky. Meta and TikTok campaigns are listed by id.
|
|
96
|
+
*/
|
|
97
|
+
ads: z.ZodDefault<z.ZodObject<{
|
|
98
|
+
meta: z.ZodOptional<z.ZodObject<{
|
|
99
|
+
/** Ad account (act_…); defaults to the one picked in Appeeky. */
|
|
100
|
+
adAccount: z.ZodOptional<z.ZodString>;
|
|
101
|
+
campaigns: z.ZodArray<z.ZodString, "many">;
|
|
102
|
+
}, "strict", z.ZodTypeAny, {
|
|
103
|
+
campaigns: string[];
|
|
104
|
+
adAccount?: string | undefined;
|
|
105
|
+
}, {
|
|
106
|
+
campaigns: string[];
|
|
107
|
+
adAccount?: string | undefined;
|
|
108
|
+
}>>;
|
|
109
|
+
tiktok: z.ZodOptional<z.ZodObject<{
|
|
110
|
+
/** Advertiser id; defaults to the one picked in Appeeky. */
|
|
111
|
+
advertiser: z.ZodOptional<z.ZodString>;
|
|
112
|
+
campaigns: z.ZodArray<z.ZodString, "many">;
|
|
113
|
+
}, "strict", z.ZodTypeAny, {
|
|
114
|
+
campaigns: string[];
|
|
115
|
+
advertiser?: string | undefined;
|
|
116
|
+
}, {
|
|
117
|
+
campaigns: string[];
|
|
118
|
+
advertiser?: string | undefined;
|
|
119
|
+
}>>;
|
|
120
|
+
}, "strict", z.ZodTypeAny, {
|
|
121
|
+
meta?: {
|
|
122
|
+
campaigns: string[];
|
|
123
|
+
adAccount?: string | undefined;
|
|
124
|
+
} | undefined;
|
|
125
|
+
tiktok?: {
|
|
126
|
+
campaigns: string[];
|
|
127
|
+
advertiser?: string | undefined;
|
|
128
|
+
} | undefined;
|
|
129
|
+
}, {
|
|
130
|
+
meta?: {
|
|
131
|
+
campaigns: string[];
|
|
132
|
+
adAccount?: string | undefined;
|
|
133
|
+
} | undefined;
|
|
134
|
+
tiktok?: {
|
|
135
|
+
campaigns: string[];
|
|
136
|
+
advertiser?: string | undefined;
|
|
137
|
+
} | undefined;
|
|
138
|
+
}>>;
|
|
139
|
+
/** Apps you compete with. `competitors pull` writes each one to appeeky/competitors/. */
|
|
140
|
+
competitors: z.ZodDefault<z.ZodArray<z.ZodEffects<z.ZodObject<{
|
|
141
|
+
name: z.ZodOptional<z.ZodString>;
|
|
142
|
+
appStore: z.ZodOptional<z.ZodString>;
|
|
143
|
+
googlePlay: z.ZodOptional<z.ZodString>;
|
|
144
|
+
}, "strict", z.ZodTypeAny, {
|
|
145
|
+
name?: string | undefined;
|
|
146
|
+
appStore?: string | undefined;
|
|
147
|
+
googlePlay?: string | undefined;
|
|
148
|
+
}, {
|
|
149
|
+
name?: string | undefined;
|
|
150
|
+
appStore?: string | undefined;
|
|
151
|
+
googlePlay?: string | undefined;
|
|
152
|
+
}>, {
|
|
153
|
+
name?: string | undefined;
|
|
154
|
+
appStore?: string | undefined;
|
|
155
|
+
googlePlay?: string | undefined;
|
|
156
|
+
}, {
|
|
157
|
+
name?: string | undefined;
|
|
158
|
+
appStore?: string | undefined;
|
|
159
|
+
googlePlay?: string | undefined;
|
|
160
|
+
}>, "many">>;
|
|
161
|
+
/**
|
|
162
|
+
* Install attribution from Appeeky Analytics: organic search, Search Ads keywords,
|
|
163
|
+
* smart links, with the revenue each led to. `via: self` reads your own server on
|
|
164
|
+
* Cloudflare (`url`, ATTRIBUTION_TOKEN); `via: hosted` reads Appeeky's (APPEEKY_API_KEY).
|
|
165
|
+
*/
|
|
166
|
+
attribution: z.ZodOptional<z.ZodEffects<z.ZodObject<{
|
|
167
|
+
via: z.ZodDefault<z.ZodEnum<["self", "hosted"]>>;
|
|
168
|
+
url: z.ZodOptional<z.ZodString>;
|
|
169
|
+
/**
|
|
170
|
+
* The app's id in Appeeky Analytics. An app there is one platform, so an app on both
|
|
171
|
+
* stores gives one per store: `{ app-store: …, google-play: … }`.
|
|
172
|
+
*/
|
|
173
|
+
app: z.ZodUnion<[z.ZodString, z.ZodEffects<z.ZodObject<{
|
|
174
|
+
"app-store": z.ZodOptional<z.ZodString>;
|
|
175
|
+
"google-play": z.ZodOptional<z.ZodString>;
|
|
176
|
+
}, "strict", z.ZodTypeAny, {
|
|
177
|
+
"app-store"?: string | undefined;
|
|
178
|
+
"google-play"?: string | undefined;
|
|
179
|
+
}, {
|
|
180
|
+
"app-store"?: string | undefined;
|
|
181
|
+
"google-play"?: string | undefined;
|
|
182
|
+
}>, {
|
|
183
|
+
"app-store"?: string | undefined;
|
|
184
|
+
"google-play"?: string | undefined;
|
|
185
|
+
}, {
|
|
186
|
+
"app-store"?: string | undefined;
|
|
187
|
+
"google-play"?: string | undefined;
|
|
188
|
+
}>]>;
|
|
189
|
+
}, "strict", z.ZodTypeAny, {
|
|
190
|
+
via: "hosted" | "self";
|
|
191
|
+
app: string | {
|
|
192
|
+
"app-store"?: string | undefined;
|
|
193
|
+
"google-play"?: string | undefined;
|
|
194
|
+
};
|
|
195
|
+
url?: string | undefined;
|
|
196
|
+
}, {
|
|
197
|
+
app: string | {
|
|
198
|
+
"app-store"?: string | undefined;
|
|
199
|
+
"google-play"?: string | undefined;
|
|
200
|
+
};
|
|
201
|
+
via?: "hosted" | "self" | undefined;
|
|
202
|
+
url?: string | undefined;
|
|
203
|
+
}>, {
|
|
204
|
+
via: "hosted" | "self";
|
|
205
|
+
app: string | {
|
|
206
|
+
"app-store"?: string | undefined;
|
|
207
|
+
"google-play"?: string | undefined;
|
|
208
|
+
};
|
|
209
|
+
url?: string | undefined;
|
|
210
|
+
}, {
|
|
211
|
+
app: string | {
|
|
212
|
+
"app-store"?: string | undefined;
|
|
213
|
+
"google-play"?: string | undefined;
|
|
214
|
+
};
|
|
215
|
+
via?: "hosted" | "self" | undefined;
|
|
216
|
+
url?: string | undefined;
|
|
217
|
+
}>>;
|
|
218
|
+
/**
|
|
219
|
+
* Where `data pull` writes store analytics, ads and revenue. They are your private
|
|
220
|
+
* business numbers, so by default they stay in .appeeky/data/ (gitignored).
|
|
221
|
+
* `commit: true` writes them to appeeky/data/ so they are versioned with the spec.
|
|
222
|
+
*/
|
|
223
|
+
data: z.ZodDefault<z.ZodObject<{
|
|
224
|
+
commit: z.ZodDefault<z.ZodBoolean>;
|
|
225
|
+
}, "strict", z.ZodTypeAny, {
|
|
226
|
+
commit: boolean;
|
|
227
|
+
}, {
|
|
228
|
+
commit?: boolean | undefined;
|
|
229
|
+
}>>;
|
|
230
|
+
/**
|
|
231
|
+
* Whether ChatGPT, Claude, Gemini and Perplexity name the app when people ask
|
|
232
|
+
* for one like it. Intents are what people want ("fall asleep to rain sounds"),
|
|
233
|
+
* prompts are how they ask; both are tracked per storefront in Appeeky AI Visibility.
|
|
234
|
+
*/
|
|
235
|
+
aiVisibility: z.ZodOptional<z.ZodObject<{
|
|
236
|
+
/** Which app to watch when it is on both stores; defaults to the App Store app. */
|
|
237
|
+
store: z.ZodOptional<z.ZodEnum<["app-store", "google-play"]>>;
|
|
238
|
+
/** Storefronts to watch; defaults to the first storefront under targets. */
|
|
239
|
+
countries: z.ZodOptional<z.ZodArray<z.ZodEffects<z.ZodString, string, string>, "many">>;
|
|
240
|
+
/** What people ask AI assistants, per storefront. `visibility sync` sends them to Appeeky. */
|
|
241
|
+
intents: z.ZodDefault<z.ZodRecord<z.ZodEffects<z.ZodString, string, string>, z.ZodArray<z.ZodObject<{
|
|
242
|
+
label: z.ZodString;
|
|
243
|
+
description: z.ZodOptional<z.ZodString>;
|
|
244
|
+
prompts: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
245
|
+
}, "strict", z.ZodTypeAny, {
|
|
246
|
+
label: string;
|
|
247
|
+
prompts: string[];
|
|
248
|
+
description?: string | undefined;
|
|
249
|
+
}, {
|
|
250
|
+
label: string;
|
|
251
|
+
description?: string | undefined;
|
|
252
|
+
prompts?: string[] | undefined;
|
|
253
|
+
}>, "many">>>;
|
|
254
|
+
}, "strict", z.ZodTypeAny, {
|
|
255
|
+
intents: Record<string, {
|
|
256
|
+
label: string;
|
|
257
|
+
prompts: string[];
|
|
258
|
+
description?: string | undefined;
|
|
259
|
+
}[]>;
|
|
260
|
+
store?: "app-store" | "google-play" | undefined;
|
|
261
|
+
countries?: string[] | undefined;
|
|
262
|
+
}, {
|
|
263
|
+
store?: "app-store" | "google-play" | undefined;
|
|
264
|
+
countries?: string[] | undefined;
|
|
265
|
+
intents?: Record<string, {
|
|
266
|
+
label: string;
|
|
267
|
+
description?: string | undefined;
|
|
268
|
+
prompts?: string[] | undefined;
|
|
269
|
+
}[]> | undefined;
|
|
270
|
+
}>>;
|
|
271
|
+
/** Rank in the app's category chart (top 100), recorded daily by `category pull`. */
|
|
272
|
+
category: z.ZodOptional<z.ZodObject<{
|
|
273
|
+
/** App Store genre id, e.g. "6013" for Health & Fitness; read from the app when left out. */
|
|
274
|
+
appStore: z.ZodOptional<z.ZodString>;
|
|
275
|
+
/** Google Play category, e.g. HEALTH_AND_FITNESS. */
|
|
276
|
+
googlePlay: z.ZodOptional<z.ZodString>;
|
|
277
|
+
/** Defaults to top-paid for a paid App Store app, top-free otherwise. */
|
|
278
|
+
chart: z.ZodOptional<z.ZodEnum<["top-free", "top-paid", "top-grossing"]>>;
|
|
279
|
+
/** Storefronts to record; defaults to the storefronts under targets. */
|
|
280
|
+
countries: z.ZodOptional<z.ZodArray<z.ZodEffects<z.ZodString, string, string>, "many">>;
|
|
281
|
+
}, "strict", z.ZodTypeAny, {
|
|
282
|
+
appStore?: string | undefined;
|
|
283
|
+
googlePlay?: string | undefined;
|
|
284
|
+
countries?: string[] | undefined;
|
|
285
|
+
chart?: "top-free" | "top-paid" | "top-grossing" | undefined;
|
|
286
|
+
}, {
|
|
287
|
+
appStore?: string | undefined;
|
|
288
|
+
googlePlay?: string | undefined;
|
|
289
|
+
countries?: string[] | undefined;
|
|
290
|
+
chart?: "top-free" | "top-paid" | "top-grossing" | undefined;
|
|
291
|
+
}>>;
|
|
292
|
+
/** Who the app is for. Experiments, screenshots and UGC refer to these by id. */
|
|
293
|
+
personas: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
294
|
+
id: z.ZodString;
|
|
295
|
+
name: z.ZodString;
|
|
296
|
+
description: z.ZodOptional<z.ZodString>;
|
|
297
|
+
/** How this persona searches: seeds for targets and keyword ideas. */
|
|
298
|
+
searches: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
299
|
+
}, "strict", z.ZodTypeAny, {
|
|
300
|
+
name: string;
|
|
301
|
+
id: string;
|
|
302
|
+
searches: string[];
|
|
303
|
+
description?: string | undefined;
|
|
304
|
+
}, {
|
|
305
|
+
name: string;
|
|
306
|
+
id: string;
|
|
307
|
+
description?: string | undefined;
|
|
308
|
+
searches?: string[] | undefined;
|
|
309
|
+
}>, "many">>;
|
|
310
|
+
}, "strict", z.ZodTypeAny, {
|
|
311
|
+
version: 1;
|
|
312
|
+
app: {
|
|
313
|
+
name: string;
|
|
314
|
+
primaryLocale: string;
|
|
315
|
+
};
|
|
316
|
+
stores: {
|
|
317
|
+
appStore?: {
|
|
318
|
+
appId: string;
|
|
319
|
+
platform: "IOS" | "MAC_OS" | "TV_OS" | "VISION_OS";
|
|
320
|
+
via: "auto" | "local" | "hosted";
|
|
321
|
+
account?: string | undefined;
|
|
322
|
+
} | undefined;
|
|
323
|
+
googlePlay?: {
|
|
324
|
+
via: "auto" | "local" | "hosted";
|
|
325
|
+
packageName: string;
|
|
326
|
+
account?: string | undefined;
|
|
327
|
+
profile?: string | undefined;
|
|
328
|
+
} | undefined;
|
|
329
|
+
};
|
|
330
|
+
targets: Record<string, string[]>;
|
|
331
|
+
storefronts: Record<string, string[]>;
|
|
332
|
+
ads: {
|
|
333
|
+
meta?: {
|
|
334
|
+
campaigns: string[];
|
|
335
|
+
adAccount?: string | undefined;
|
|
336
|
+
} | undefined;
|
|
337
|
+
tiktok?: {
|
|
338
|
+
campaigns: string[];
|
|
339
|
+
advertiser?: string | undefined;
|
|
340
|
+
} | undefined;
|
|
341
|
+
};
|
|
342
|
+
competitors: {
|
|
343
|
+
name?: string | undefined;
|
|
344
|
+
appStore?: string | undefined;
|
|
345
|
+
googlePlay?: string | undefined;
|
|
346
|
+
}[];
|
|
347
|
+
data: {
|
|
348
|
+
commit: boolean;
|
|
349
|
+
};
|
|
350
|
+
personas: {
|
|
351
|
+
name: string;
|
|
352
|
+
id: string;
|
|
353
|
+
searches: string[];
|
|
354
|
+
description?: string | undefined;
|
|
355
|
+
}[];
|
|
356
|
+
attribution?: {
|
|
357
|
+
via: "hosted" | "self";
|
|
358
|
+
app: string | {
|
|
359
|
+
"app-store"?: string | undefined;
|
|
360
|
+
"google-play"?: string | undefined;
|
|
361
|
+
};
|
|
362
|
+
url?: string | undefined;
|
|
363
|
+
} | undefined;
|
|
364
|
+
aiVisibility?: {
|
|
365
|
+
intents: Record<string, {
|
|
366
|
+
label: string;
|
|
367
|
+
prompts: string[];
|
|
368
|
+
description?: string | undefined;
|
|
369
|
+
}[]>;
|
|
370
|
+
store?: "app-store" | "google-play" | undefined;
|
|
371
|
+
countries?: string[] | undefined;
|
|
372
|
+
} | undefined;
|
|
373
|
+
category?: {
|
|
374
|
+
appStore?: string | undefined;
|
|
375
|
+
googlePlay?: string | undefined;
|
|
376
|
+
countries?: string[] | undefined;
|
|
377
|
+
chart?: "top-free" | "top-paid" | "top-grossing" | undefined;
|
|
378
|
+
} | undefined;
|
|
379
|
+
}, {
|
|
380
|
+
version: 1;
|
|
381
|
+
app: {
|
|
382
|
+
name: string;
|
|
383
|
+
primaryLocale?: string | undefined;
|
|
384
|
+
};
|
|
385
|
+
stores?: {
|
|
386
|
+
appStore?: {
|
|
387
|
+
appId: string;
|
|
388
|
+
platform?: "IOS" | "MAC_OS" | "TV_OS" | "VISION_OS" | undefined;
|
|
389
|
+
via?: "auto" | "local" | "hosted" | undefined;
|
|
390
|
+
account?: string | undefined;
|
|
391
|
+
} | undefined;
|
|
392
|
+
googlePlay?: {
|
|
393
|
+
packageName: string;
|
|
394
|
+
via?: "auto" | "local" | "hosted" | undefined;
|
|
395
|
+
account?: string | undefined;
|
|
396
|
+
profile?: string | undefined;
|
|
397
|
+
} | undefined;
|
|
398
|
+
} | undefined;
|
|
399
|
+
targets?: Record<string, string[] | undefined> | undefined;
|
|
400
|
+
storefronts?: Record<string, string[]> | undefined;
|
|
401
|
+
ads?: {
|
|
402
|
+
meta?: {
|
|
403
|
+
campaigns: string[];
|
|
404
|
+
adAccount?: string | undefined;
|
|
405
|
+
} | undefined;
|
|
406
|
+
tiktok?: {
|
|
407
|
+
campaigns: string[];
|
|
408
|
+
advertiser?: string | undefined;
|
|
409
|
+
} | undefined;
|
|
410
|
+
} | undefined;
|
|
411
|
+
competitors?: {
|
|
412
|
+
name?: string | undefined;
|
|
413
|
+
appStore?: string | undefined;
|
|
414
|
+
googlePlay?: string | undefined;
|
|
415
|
+
}[] | undefined;
|
|
416
|
+
attribution?: {
|
|
417
|
+
app: string | {
|
|
418
|
+
"app-store"?: string | undefined;
|
|
419
|
+
"google-play"?: string | undefined;
|
|
420
|
+
};
|
|
421
|
+
via?: "hosted" | "self" | undefined;
|
|
422
|
+
url?: string | undefined;
|
|
423
|
+
} | undefined;
|
|
424
|
+
data?: {
|
|
425
|
+
commit?: boolean | undefined;
|
|
426
|
+
} | undefined;
|
|
427
|
+
aiVisibility?: {
|
|
428
|
+
store?: "app-store" | "google-play" | undefined;
|
|
429
|
+
countries?: string[] | undefined;
|
|
430
|
+
intents?: Record<string, {
|
|
431
|
+
label: string;
|
|
432
|
+
description?: string | undefined;
|
|
433
|
+
prompts?: string[] | undefined;
|
|
434
|
+
}[]> | undefined;
|
|
435
|
+
} | undefined;
|
|
436
|
+
category?: {
|
|
437
|
+
appStore?: string | undefined;
|
|
438
|
+
googlePlay?: string | undefined;
|
|
439
|
+
countries?: string[] | undefined;
|
|
440
|
+
chart?: "top-free" | "top-paid" | "top-grossing" | undefined;
|
|
441
|
+
} | undefined;
|
|
442
|
+
personas?: {
|
|
443
|
+
name: string;
|
|
444
|
+
id: string;
|
|
445
|
+
description?: string | undefined;
|
|
446
|
+
searches?: string[] | undefined;
|
|
447
|
+
}[] | undefined;
|
|
448
|
+
}>;
|
|
449
|
+
export type SpecFile = z.infer<typeof specFileSchema>;
|
|
450
|
+
export type SpecFileInput = z.input<typeof specFileSchema>;
|
|
451
|
+
/**
|
|
452
|
+
* One App Store locale: `appeeky/store/app-store/<locale>.yaml`.
|
|
453
|
+
* A field left out is not managed by the spec: it is never diffed or pushed.
|
|
454
|
+
*/
|
|
455
|
+
export declare const appStoreListingSchema: z.ZodObject<{
|
|
456
|
+
name: z.ZodOptional<z.ZodString>;
|
|
457
|
+
subtitle: z.ZodOptional<z.ZodString>;
|
|
458
|
+
keywords: z.ZodOptional<z.ZodString>;
|
|
459
|
+
promotionalText: z.ZodOptional<z.ZodString>;
|
|
460
|
+
description: z.ZodOptional<z.ZodString>;
|
|
461
|
+
whatsNew: z.ZodOptional<z.ZodString>;
|
|
462
|
+
marketingUrl: z.ZodOptional<z.ZodString>;
|
|
463
|
+
supportUrl: z.ZodOptional<z.ZodString>;
|
|
464
|
+
}, "strict", z.ZodTypeAny, {
|
|
465
|
+
description?: string | undefined;
|
|
466
|
+
name?: string | undefined;
|
|
467
|
+
subtitle?: string | undefined;
|
|
468
|
+
keywords?: string | undefined;
|
|
469
|
+
promotionalText?: string | undefined;
|
|
470
|
+
whatsNew?: string | undefined;
|
|
471
|
+
marketingUrl?: string | undefined;
|
|
472
|
+
supportUrl?: string | undefined;
|
|
473
|
+
}, {
|
|
474
|
+
description?: string | undefined;
|
|
475
|
+
name?: string | undefined;
|
|
476
|
+
subtitle?: string | undefined;
|
|
477
|
+
keywords?: string | undefined;
|
|
478
|
+
promotionalText?: string | undefined;
|
|
479
|
+
whatsNew?: string | undefined;
|
|
480
|
+
marketingUrl?: string | undefined;
|
|
481
|
+
supportUrl?: string | undefined;
|
|
482
|
+
}>;
|
|
483
|
+
export type AppStoreListing = z.infer<typeof appStoreListingSchema>;
|
|
484
|
+
/** One Google Play language: `appeeky/store/google-play/<language>.yaml`. */
|
|
485
|
+
export declare const googlePlayListingSchema: z.ZodObject<{
|
|
486
|
+
title: z.ZodOptional<z.ZodString>;
|
|
487
|
+
shortDescription: z.ZodOptional<z.ZodString>;
|
|
488
|
+
fullDescription: z.ZodOptional<z.ZodString>;
|
|
489
|
+
video: z.ZodOptional<z.ZodString>;
|
|
490
|
+
}, "strict", z.ZodTypeAny, {
|
|
491
|
+
title?: string | undefined;
|
|
492
|
+
shortDescription?: string | undefined;
|
|
493
|
+
fullDescription?: string | undefined;
|
|
494
|
+
video?: string | undefined;
|
|
495
|
+
}, {
|
|
496
|
+
title?: string | undefined;
|
|
497
|
+
shortDescription?: string | undefined;
|
|
498
|
+
fullDescription?: string | undefined;
|
|
499
|
+
video?: string | undefined;
|
|
500
|
+
}>;
|
|
501
|
+
export type GooglePlayListing = z.infer<typeof googlePlayListingSchema>;
|
|
502
|
+
export type Listing = AppStoreListing | GooglePlayListing;
|
|
503
|
+
export declare const APP_STORE_FIELDS: readonly ["name", "subtitle", "keywords", "promotionalText", "description", "whatsNew", "marketingUrl", "supportUrl"];
|
|
504
|
+
export declare const GOOGLE_PLAY_FIELDS: readonly ["title", "shortDescription", "fullDescription", "video"];
|
|
505
|
+
export type AppStoreField = (typeof APP_STORE_FIELDS)[number];
|
|
506
|
+
export type GooglePlayField = (typeof GOOGLE_PLAY_FIELDS)[number];
|
|
507
|
+
export declare function fieldsFor(store: StoreId): readonly string[];
|
|
508
|
+
/** Listings of one store, keyed by locale. */
|
|
509
|
+
export type StoreListings<T extends Listing = Listing> = Record<string, T>;
|
|
510
|
+
/** A whole spec as loaded from disk. */
|
|
511
|
+
export interface Project {
|
|
512
|
+
/** Folder that holds `appeeky.spec.yaml`. */
|
|
513
|
+
root: string;
|
|
514
|
+
spec: SpecFile;
|
|
515
|
+
listings: {
|
|
516
|
+
"app-store": StoreListings<AppStoreListing>;
|
|
517
|
+
"google-play": StoreListings<GooglePlayListing>;
|
|
518
|
+
};
|
|
519
|
+
}
|