adapty 0.8.4-beta.1 → 0.8.5
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/README.md +133 -3
- package/bin/dev.js +2 -2
- package/bin/run.js +2 -2
- package/dist/commands/access-levels/create.js +1 -1
- package/dist/commands/access-levels/list.d.ts +1 -1
- package/dist/commands/apps/create.js +9 -6
- package/dist/commands/apps/list.d.ts +1 -1
- package/dist/commands/apps/update.js +7 -4
- package/dist/commands/asa/ad-groups/create.js +9 -7
- package/dist/commands/asa/ad-groups/get.js +3 -2
- package/dist/commands/asa/ad-groups/list.d.ts +1 -1
- package/dist/commands/asa/ad-groups/list.js +1 -1
- package/dist/commands/asa/ad-groups/update.js +22 -12
- package/dist/commands/asa/ads/create.js +7 -5
- package/dist/commands/asa/ads/get.js +3 -2
- package/dist/commands/asa/ads/list.d.ts +1 -1
- package/dist/commands/asa/ads/list.js +1 -1
- package/dist/commands/asa/ads/update.js +9 -5
- package/dist/commands/asa/apps/list.d.ts +1 -1
- package/dist/commands/asa/apps/list.js +1 -1
- package/dist/commands/asa/automations/create.d.ts +9 -0
- package/dist/commands/asa/automations/create.js +26 -7
- package/dist/commands/asa/automations/get.js +3 -2
- package/dist/commands/asa/automations/list.d.ts +1 -1
- package/dist/commands/asa/automations/list.js +1 -1
- package/dist/commands/asa/automations/run.js +5 -3
- package/dist/commands/asa/automations/runs.d.ts +1 -1
- package/dist/commands/asa/automations/runs.js +4 -4
- package/dist/commands/asa/automations/update.d.ts +9 -0
- package/dist/commands/asa/automations/update.js +36 -12
- package/dist/commands/asa/campaigns/bulk-create.js +31 -18
- package/dist/commands/asa/campaigns/bulk-list.js +7 -5
- package/dist/commands/asa/campaigns/bulk-status.js +3 -2
- package/dist/commands/asa/campaigns/create.js +10 -8
- package/dist/commands/asa/campaigns/get.js +3 -2
- package/dist/commands/asa/campaigns/list.d.ts +1 -1
- package/dist/commands/asa/campaigns/list.js +1 -1
- package/dist/commands/asa/campaigns/update.js +25 -15
- package/dist/commands/asa/competitors/summary.js +5 -5
- package/dist/commands/asa/connect.js +5 -3
- package/dist/commands/asa/creatives/list.d.ts +1 -1
- package/dist/commands/asa/creatives/list.js +1 -1
- package/dist/commands/asa/keywords/add.js +13 -10
- package/dist/commands/asa/keywords/list.d.ts +1 -1
- package/dist/commands/asa/keywords/list.js +1 -1
- package/dist/commands/asa/keywords/update.js +15 -10
- package/dist/commands/asa/metrics/index.d.ts +6 -3
- package/dist/commands/asa/metrics/index.js +38 -14
- package/dist/commands/asa/metrics/overview.js +3 -3
- package/dist/commands/asa/negative-keywords/add.js +10 -7
- package/dist/commands/asa/negative-keywords/list.d.ts +1 -1
- package/dist/commands/asa/negative-keywords/list.js +1 -1
- package/dist/commands/asa/orgs/list.d.ts +1 -1
- package/dist/commands/asa/orgs/list.js +1 -1
- package/dist/commands/asa/product-pages/list.d.ts +1 -1
- package/dist/commands/asa/product-pages/list.js +1 -1
- package/dist/commands/asa/product-pages/sync.js +1 -1
- package/dist/commands/asa/search-terms/list.d.ts +1 -1
- package/dist/commands/asa/search-terms/list.js +1 -1
- package/dist/commands/asa/whoami.js +7 -2
- package/dist/commands/auth/login.js +3 -1
- package/dist/commands/flows/config/get.js +2 -2
- package/dist/commands/flows/config/preview.d.ts +2 -2
- package/dist/commands/flows/config/preview.js +6 -4
- package/dist/commands/flows/config/update.js +5 -3
- package/dist/commands/flows/config/validate.js +5 -3
- package/dist/commands/flows/list.d.ts +1 -1
- package/dist/commands/flows/media/upload.js +1 -1
- package/dist/commands/flows/publish.js +5 -5
- package/dist/commands/paywalls/create.js +1 -1
- package/dist/commands/paywalls/list.d.ts +1 -1
- package/dist/commands/paywalls/placements.d.ts +2 -2
- package/dist/commands/paywalls/update.js +1 -1
- package/dist/commands/placements/create.js +17 -12
- package/dist/commands/placements/list.d.ts +1 -1
- package/dist/commands/placements/update.js +20 -15
- package/dist/commands/products/create.js +20 -13
- package/dist/commands/products/list.d.ts +1 -1
- package/dist/commands/products/update.js +1 -1
- package/dist/commands/segments/list.d.ts +1 -1
- package/dist/lib/api-client.d.ts +10 -6
- package/dist/lib/api-client.js +56 -35
- package/dist/lib/api-schemas.d.ts +56 -56
- package/dist/lib/app-url.js +2 -1
- package/dist/lib/asa-client.d.ts +13 -8
- package/dist/lib/asa-client.js +9 -4
- package/dist/lib/asa-flags.d.ts +37 -13
- package/dist/lib/asa-flags.js +87 -20
- package/dist/lib/asa-keyword-action.d.ts +18 -0
- package/dist/lib/asa-keyword-action.js +175 -0
- package/dist/lib/asa-schemas.d.ts +100 -80
- package/dist/lib/auth.js +2 -1
- package/dist/lib/client-from-config.d.ts +1 -1
- package/dist/lib/client-from-config.js +2 -1
- package/dist/lib/config.d.ts +2 -2
- package/dist/lib/confirm.d.ts +4 -4
- package/dist/lib/confirm.js +12 -7
- package/dist/lib/errors.d.ts +18 -18
- package/dist/lib/errors.js +14 -10
- package/dist/lib/flags.d.ts +3 -3
- package/dist/lib/flags.js +2 -1
- package/dist/lib/flow-help.js +11 -6
- package/dist/lib/output.js +23 -12
- package/dist/lib/preview.d.ts +5 -5
- package/dist/lib/preview.js +2 -1
- package/oclif.manifest.json +372 -200
- package/package.json +10 -8
package/dist/lib/errors.d.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
export
|
|
2
|
-
detail?: string;
|
|
3
|
-
error?: string;
|
|
4
|
-
error_code?: string;
|
|
5
|
-
errors?: Record<string, string[]
|
|
6
|
-
retry_after_seconds?: number;
|
|
7
|
-
status_code?: number;
|
|
8
|
-
}
|
|
1
|
+
export type ApiErrorBody = {
|
|
2
|
+
detail?: string | undefined;
|
|
3
|
+
error?: string | undefined;
|
|
4
|
+
error_code?: string | undefined;
|
|
5
|
+
errors?: Record<string, string[]> | undefined;
|
|
6
|
+
retry_after_seconds?: number | undefined;
|
|
7
|
+
status_code?: number | undefined;
|
|
8
|
+
};
|
|
9
9
|
export type ApiErrorFormat = 'asa' | 'developer';
|
|
10
|
-
export
|
|
11
|
-
detail?: string;
|
|
12
|
-
retryAfterSeconds?: number;
|
|
13
|
-
}
|
|
14
|
-
export
|
|
10
|
+
export type ApiErrorOptions = {
|
|
11
|
+
detail?: string | undefined;
|
|
12
|
+
retryAfterSeconds?: number | undefined;
|
|
13
|
+
};
|
|
14
|
+
export type ListedError = {
|
|
15
15
|
apple_error_code?: null | string;
|
|
16
16
|
apple_error_message?: null | string;
|
|
17
17
|
error_code?: string;
|
|
@@ -20,18 +20,18 @@ export interface ListedError {
|
|
|
20
20
|
message?: string;
|
|
21
21
|
validation_error_code?: string;
|
|
22
22
|
validation_error_message?: string;
|
|
23
|
-
}
|
|
23
|
+
};
|
|
24
24
|
export declare function describeListedError(error: ListedError): {
|
|
25
25
|
code: string | undefined;
|
|
26
26
|
text: string;
|
|
27
27
|
};
|
|
28
28
|
export declare class ApiError extends Error {
|
|
29
|
-
|
|
29
|
+
code?: string | undefined;
|
|
30
|
+
detail?: string | undefined;
|
|
30
31
|
errorCode: string;
|
|
31
32
|
fieldErrors: Record<string, string[]>;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
retryAfterSeconds?: number;
|
|
33
|
+
retryAfterSeconds?: number | undefined;
|
|
34
|
+
statusCode: number;
|
|
35
35
|
constructor(statusCode: number, errorCode: string, fieldErrors: Record<string, string[]>, opts?: ApiErrorOptions);
|
|
36
36
|
private static humanMessage;
|
|
37
37
|
toHuman(): string;
|
package/dist/lib/errors.js
CHANGED
|
@@ -2,33 +2,36 @@ export function describeListedError(error) {
|
|
|
2
2
|
const code = error.error_code ?? error.apple_error_code ?? error.validation_error_code ?? undefined;
|
|
3
3
|
const reason = error.message ?? error.apple_error_message ?? error.validation_error_message ?? code ?? 'rejected';
|
|
4
4
|
const position = error.input_ref === null || error.input_ref === undefined ? '' : ` (item ${error.input_ref + 1})`;
|
|
5
|
-
|
|
5
|
+
const field = error.field_name ? `${error.field_name}: ` : '';
|
|
6
|
+
return { code, text: `${field}${reason}${position}` };
|
|
6
7
|
}
|
|
7
8
|
export class ApiError extends Error {
|
|
8
|
-
statusCode;
|
|
9
|
-
errorCode;
|
|
10
|
-
fieldErrors;
|
|
11
9
|
// Read by oclif's prettyPrint to render a `Code: ...` line under the message.
|
|
12
10
|
code;
|
|
13
11
|
detail;
|
|
12
|
+
errorCode;
|
|
13
|
+
fieldErrors;
|
|
14
14
|
retryAfterSeconds;
|
|
15
|
+
statusCode;
|
|
15
16
|
constructor(statusCode, errorCode, fieldErrors, opts = {}) {
|
|
16
17
|
// `message` is what oclif's default error renderer prints. Prefer the server's human text (an ASA
|
|
17
18
|
// `detail` or the developer API's field errors) over the bare code, which reads as gibberish on its own.
|
|
18
19
|
super(ApiError.humanMessage(errorCode, fieldErrors, opts.detail));
|
|
20
|
+
this.name = 'ApiError';
|
|
19
21
|
this.statusCode = statusCode;
|
|
20
22
|
this.errorCode = errorCode;
|
|
21
23
|
this.fieldErrors = fieldErrors;
|
|
22
|
-
this.name = 'ApiError';
|
|
23
24
|
this.detail = opts.detail;
|
|
24
25
|
this.retryAfterSeconds = opts.retryAfterSeconds;
|
|
25
26
|
// Surface real server codes as a secondary line; hide synthetic `http_<status>` fallbacks.
|
|
26
|
-
if (!errorCode.startsWith('http_'))
|
|
27
|
+
if (!errorCode.startsWith('http_')) {
|
|
27
28
|
this.code = errorCode;
|
|
29
|
+
}
|
|
28
30
|
}
|
|
29
31
|
static humanMessage(errorCode, fieldErrors, detail) {
|
|
30
|
-
if (detail)
|
|
32
|
+
if (detail) {
|
|
31
33
|
return detail;
|
|
34
|
+
}
|
|
32
35
|
const parts = [];
|
|
33
36
|
for (const [field, msgs] of Object.entries(fieldErrors)) {
|
|
34
37
|
for (const msg of msgs) {
|
|
@@ -85,8 +88,8 @@ function parseListedErrors(errors, statusCode, opts) {
|
|
|
85
88
|
fieldErrors[item.field_name] = [...(fieldErrors[item.field_name] ?? []), item.message];
|
|
86
89
|
}
|
|
87
90
|
}
|
|
88
|
-
const described = errors.map(
|
|
89
|
-
const detail = described.map(
|
|
91
|
+
const described = errors.map(item => describeListedError(item));
|
|
92
|
+
const detail = described.map(item => item.text).join('; ');
|
|
90
93
|
return new ApiError(statusCode, described[0]?.code ?? `http_${statusCode}`, fieldErrors, {
|
|
91
94
|
...opts,
|
|
92
95
|
detail: detail || undefined,
|
|
@@ -110,8 +113,9 @@ export function parseApiError(statusCode, body, opts = {}, format = 'developer')
|
|
|
110
113
|
const fieldErrors = {};
|
|
111
114
|
for (const item of parsed.detail) {
|
|
112
115
|
const field = (item.loc ?? []).slice(1).join('.') || 'body';
|
|
113
|
-
if (item.msg)
|
|
116
|
+
if (item.msg) {
|
|
114
117
|
fieldErrors[field] = [...(fieldErrors[field] ?? []), item.msg];
|
|
118
|
+
}
|
|
115
119
|
}
|
|
116
120
|
return new ApiError(statusCode, `http_${statusCode}`, fieldErrors, opts);
|
|
117
121
|
}
|
package/dist/lib/flags.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export declare function isValidUuid(value: string): boolean;
|
|
|
2
2
|
export declare const appFlag: {
|
|
3
3
|
app: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
4
4
|
};
|
|
5
|
-
export
|
|
5
|
+
export type PaginatedResponse<T> = {
|
|
6
6
|
data: T[];
|
|
7
7
|
meta: {
|
|
8
8
|
pagination: {
|
|
@@ -11,12 +11,12 @@ export interface PaginatedResponse<T> {
|
|
|
11
11
|
pages: number;
|
|
12
12
|
};
|
|
13
13
|
};
|
|
14
|
-
}
|
|
14
|
+
};
|
|
15
15
|
export declare const paginationFlags: {
|
|
16
16
|
page: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
17
|
'page-size': import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
18
|
};
|
|
19
19
|
export declare function paginationParams(flags: {
|
|
20
|
-
page: number;
|
|
20
|
+
'page': number;
|
|
21
21
|
'page-size': number;
|
|
22
22
|
}): Record<string, string>;
|
package/dist/lib/flags.js
CHANGED
|
@@ -6,6 +6,7 @@ export function isValidUuid(value) {
|
|
|
6
6
|
export const appFlag = {
|
|
7
7
|
app: Flags.string({
|
|
8
8
|
description: 'App ID (UUID)',
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/require-await -- FIXME if you see this
|
|
9
10
|
async parse(input) {
|
|
10
11
|
if (!isValidUuid(input)) {
|
|
11
12
|
throw new Error('Invalid app ID format. Run `adapty apps list` to find your app ID.');
|
|
@@ -16,7 +17,7 @@ export const appFlag = {
|
|
|
16
17
|
}),
|
|
17
18
|
};
|
|
18
19
|
export const paginationFlags = {
|
|
19
|
-
page: Flags.integer({
|
|
20
|
+
'page': Flags.integer({
|
|
20
21
|
default: 1,
|
|
21
22
|
description: 'Page number',
|
|
22
23
|
min: 1,
|
package/dist/lib/flow-help.js
CHANGED
|
@@ -17,11 +17,16 @@ const DRAFT_FLOW_MARKER = 'Flow must be published before placing in a placement'
|
|
|
17
17
|
* `flowId` is taken from the single flow audience, or `<FLOW_ID>` when it is ambiguous.
|
|
18
18
|
*/
|
|
19
19
|
export function draftFlowError(error, app, audiences) {
|
|
20
|
-
if (!(error instanceof ApiError) || !error.message.includes(DRAFT_FLOW_MARKER))
|
|
20
|
+
if (!(error instanceof ApiError) || !error.message.includes(DRAFT_FLOW_MARKER)) {
|
|
21
21
|
return null;
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
}
|
|
23
|
+
const flowIds = (audiences ?? [])
|
|
24
|
+
.filter(a => a.content_type === 'flow')
|
|
25
|
+
.map(a => a.flow_id)
|
|
26
|
+
.filter((id) => typeof id === 'string');
|
|
27
|
+
const onlyFlowId = flowIds.length === 1 ? flowIds[0] : undefined;
|
|
28
|
+
const flowId = onlyFlowId ?? '<FLOW_ID>';
|
|
29
|
+
return ('Cannot attach a draft flow to a placement — publish it first.\n'
|
|
30
|
+
+ `Publish: adapty flows publish --app ${app} ${flowId}\n`
|
|
31
|
+
+ flowFixLinks(flowId));
|
|
27
32
|
}
|
package/dist/lib/output.js
CHANGED
|
@@ -3,10 +3,12 @@ function formatLabel(snakeKey) {
|
|
|
3
3
|
return snakeKey
|
|
4
4
|
.split('_')
|
|
5
5
|
.map((w) => {
|
|
6
|
-
if (w === 'ids')
|
|
6
|
+
if (w === 'ids') {
|
|
7
7
|
return 'IDs';
|
|
8
|
-
|
|
8
|
+
}
|
|
9
|
+
if (UPPER_WORDS.has(w)) {
|
|
9
10
|
return w.toUpperCase();
|
|
11
|
+
}
|
|
10
12
|
return w.charAt(0).toUpperCase() + w.slice(1);
|
|
11
13
|
})
|
|
12
14
|
.join(' ');
|
|
@@ -18,19 +20,22 @@ function renderArrayItems(items, indent) {
|
|
|
18
20
|
const childIndent = indent + ' ';
|
|
19
21
|
const lines = [];
|
|
20
22
|
for (const item of items) {
|
|
21
|
-
if (item === undefined || item === null)
|
|
23
|
+
if (item === undefined || item === null) {
|
|
22
24
|
continue;
|
|
25
|
+
}
|
|
23
26
|
if (Array.isArray(item)) {
|
|
24
27
|
lines.push(...renderArrayItems(item, childIndent));
|
|
25
28
|
}
|
|
26
29
|
else if (isScalar(item)) {
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string -- FIXME if you see this
|
|
27
31
|
lines.push(`${indent}- ${String(item)}`);
|
|
28
32
|
}
|
|
29
33
|
else {
|
|
30
|
-
const
|
|
31
|
-
if (
|
|
34
|
+
const [head, ...rest] = renderObject(item, childIndent);
|
|
35
|
+
if (head === undefined) {
|
|
32
36
|
continue;
|
|
33
|
-
|
|
37
|
+
}
|
|
38
|
+
lines.push(`${indent}- ${head.slice(childIndent.length)}`, ...rest);
|
|
34
39
|
}
|
|
35
40
|
}
|
|
36
41
|
return lines;
|
|
@@ -38,13 +43,15 @@ function renderArrayItems(items, indent) {
|
|
|
38
43
|
function renderObject(data, indent) {
|
|
39
44
|
const lines = [];
|
|
40
45
|
for (const [key, value] of Object.entries(data)) {
|
|
41
|
-
if (value === undefined || value === null)
|
|
46
|
+
if (value === undefined || value === null) {
|
|
42
47
|
continue;
|
|
48
|
+
}
|
|
43
49
|
const label = `${indent}${formatLabel(key)}:`;
|
|
44
50
|
if (Array.isArray(value)) {
|
|
45
|
-
if (value.length === 0)
|
|
51
|
+
if (value.length === 0) {
|
|
46
52
|
continue;
|
|
47
|
-
|
|
53
|
+
}
|
|
54
|
+
if (value.every(v => isScalar(v))) {
|
|
48
55
|
lines.push(`${label} ${value.map(String).join(', ')}`);
|
|
49
56
|
}
|
|
50
57
|
else {
|
|
@@ -52,25 +59,29 @@ function renderObject(data, indent) {
|
|
|
52
59
|
}
|
|
53
60
|
}
|
|
54
61
|
else if (isScalar(value)) {
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string -- FIXME if you see this
|
|
55
63
|
lines.push(`${label} ${String(value)}`);
|
|
56
64
|
}
|
|
57
65
|
else {
|
|
58
66
|
const nested = renderObject(value, indent + ' ');
|
|
59
|
-
if (nested.length > 0)
|
|
67
|
+
if (nested.length > 0) {
|
|
60
68
|
lines.push(label, ...nested);
|
|
69
|
+
}
|
|
61
70
|
}
|
|
62
71
|
}
|
|
63
72
|
return lines;
|
|
64
73
|
}
|
|
65
74
|
export function printResponse(data, log) {
|
|
66
|
-
for (const line of renderObject(data, ''))
|
|
75
|
+
for (const line of renderObject(data, '')) {
|
|
67
76
|
log(line);
|
|
77
|
+
}
|
|
68
78
|
}
|
|
69
79
|
export function printList(items, log, pagination) {
|
|
70
80
|
for (const [i, item] of items.entries()) {
|
|
71
81
|
printResponse(item, log);
|
|
72
|
-
if (i < items.length - 1)
|
|
82
|
+
if (i < items.length - 1) {
|
|
73
83
|
log('---');
|
|
84
|
+
}
|
|
74
85
|
}
|
|
75
86
|
if (pagination) {
|
|
76
87
|
log('');
|
package/dist/lib/preview.d.ts
CHANGED
|
@@ -5,10 +5,10 @@ export declare const DEFAULT_DEVICE_ID = "iphone-14";
|
|
|
5
5
|
export declare const ORIENTATIONS: readonly ["landscape", "portrait"];
|
|
6
6
|
export declare const DEFAULT_ORIENTATION = "portrait";
|
|
7
7
|
/** Payload the render page expects. Wire format shared with the UI, hence camelCase. */
|
|
8
|
-
export
|
|
8
|
+
export type PreviewPayload = {
|
|
9
9
|
flow: Record<string, unknown>;
|
|
10
10
|
remoteConfigs: unknown[];
|
|
11
|
-
}
|
|
11
|
+
};
|
|
12
12
|
/**
|
|
13
13
|
* Accepts either a dashboard-api envelope (`{config, remote_configs, ...}`) or a bare
|
|
14
14
|
* builder config, and returns the shape the render page injects.
|
|
@@ -18,10 +18,10 @@ export interface PreviewPayload {
|
|
|
18
18
|
* rejected there instead — better to say so here, against the file the user named.
|
|
19
19
|
*/
|
|
20
20
|
export declare function normalizePreviewConfig(raw: unknown): PreviewPayload;
|
|
21
|
-
export
|
|
21
|
+
export type RenderTarget = {
|
|
22
22
|
device: string;
|
|
23
23
|
orientation: string;
|
|
24
24
|
/** Omitted lets the render page fall back to the flow's first screen. */
|
|
25
|
-
screen?: string;
|
|
26
|
-
}
|
|
25
|
+
screen?: string | undefined;
|
|
26
|
+
};
|
|
27
27
|
export declare function buildRenderUrl(target: RenderTarget, payload: PreviewPayload): string;
|
package/dist/lib/preview.js
CHANGED
|
@@ -39,8 +39,9 @@ function encodeConfigFragment(payload) {
|
|
|
39
39
|
}
|
|
40
40
|
export function buildRenderUrl(target, payload) {
|
|
41
41
|
const url = appUrl(PREVIEW_PATH);
|
|
42
|
-
if (target.screen)
|
|
42
|
+
if (target.screen) {
|
|
43
43
|
url.searchParams.set('screen', target.screen);
|
|
44
|
+
}
|
|
44
45
|
url.searchParams.set('device', target.device);
|
|
45
46
|
url.searchParams.set('orientation', target.orientation);
|
|
46
47
|
url.hash = `config=${encodeConfigFragment(payload)}`;
|