adapty 0.6.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/README.md +28 -0
- package/dist/commands/asa/campaigns/bulk-list.d.ts +16 -0
- package/dist/commands/asa/campaigns/bulk-list.js +54 -0
- package/dist/commands/auth/login.d.ts +2 -0
- package/dist/commands/auth/login.js +13 -2
- package/dist/commands/flows/config/preview.d.ts +18 -0
- package/dist/commands/flows/config/preview.js +74 -0
- package/dist/lib/app-url.d.ts +10 -0
- package/dist/lib/app-url.js +33 -0
- package/dist/lib/asa-flags.d.ts +1 -0
- package/dist/lib/asa-flags.js +1 -1
- package/dist/lib/asa-schemas.d.ts +15 -0
- package/dist/lib/preview.d.ts +27 -0
- package/dist/lib/preview.js +48 -0
- package/oclif.manifest.json +405 -250
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -256,6 +256,33 @@ and the outcome shows up in `adapty asa automations runs`.
|
|
|
256
256
|
| `--page` | Page number (default: 1) |
|
|
257
257
|
| `--page-size` | Items per page (default: 20, max: 100; `asa` commands: default 100, max 1000) |
|
|
258
258
|
|
|
259
|
+
## Paywall Preview
|
|
260
|
+
|
|
261
|
+
`adapty flows config preview <config_file>` turns a local flow config into a render URL. On a TTY it opens the
|
|
262
|
+
browser; piped or with `--json` it prints the URL alone. Screenshotting is the caller's job — the CLI only
|
|
263
|
+
builds the URL.
|
|
264
|
+
|
|
265
|
+
> **Small configs only.** This is a quick-look escape hatch. The config travels in the URL fragment, and past
|
|
266
|
+
> roughly **32KB of pretty-printed JSON** the render page becomes slow and unreliable. Trim to the screen you
|
|
267
|
+
> care about, or preview the saved flow in the dashboard builder instead.
|
|
268
|
+
|
|
269
|
+
> **That URL is huge.** Even a config the page renders happily produces thousands of characters, and a 668KB
|
|
270
|
+
> flow yields ~113,000. Nobody should read it — **agents especially should never let it into their context.**
|
|
271
|
+
> Pipe it into whatever captures the screenshot:
|
|
272
|
+
>
|
|
273
|
+
> ```sh
|
|
274
|
+
> adapty flows config preview flow.json --screen scr_abc | node capture.mjs --out shot.png
|
|
275
|
+
>
|
|
276
|
+
> # or, for a tool that wants a flag instead of stdin:
|
|
277
|
+
> node capture.mjs --url "$(adapty flows config preview flow.json --screen scr_abc)" --out shot.png
|
|
278
|
+
> ```
|
|
279
|
+
>
|
|
280
|
+
> Prefer the pipe: it has no size limit, while an argument is capped by the shell (~1MB, so a config around
|
|
281
|
+
> 6MB).
|
|
282
|
+
|
|
283
|
+
See [skills/adapty-cli/references/cli-commands.md](skills/adapty-cli/references/cli-commands.md#preview) for
|
|
284
|
+
the flags and the size ceiling.
|
|
285
|
+
|
|
259
286
|
## Environment Variables
|
|
260
287
|
|
|
261
288
|
| Variable | Description |
|
|
@@ -263,6 +290,7 @@ and the outcome shows up in `adapty asa automations runs`.
|
|
|
263
290
|
| `ADAPTY_TOKEN` | Override stored auth token |
|
|
264
291
|
| `ADAPTY_API_URL` | Override Developer API base URL (default: `https://api-admin.adapty.io/api/v1/developer`) |
|
|
265
292
|
| `ADAPTY_ASA_API_URL` | Override Apple Search Ads base URL (default: `https://api-asa-admin.adapty.io/api/v1/cli`) |
|
|
293
|
+
| `ADAPTY_APP_URL` | Override dashboard base URL (default: `https://app.adapty.io`). Used by `flows config preview` for the fixed `/flow-preview` route, and by `auth login` to keep the verification link on that host |
|
|
266
294
|
|
|
267
295
|
The two API URLs are independent: pointing `ADAPTY_API_URL` at a staging host leaves `adapty asa` on the ASA
|
|
268
296
|
default, and the other way round.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import type { AsaBulkOperationListDTO } from '../../../lib/asa-schemas.js';
|
|
3
|
+
export default class AsaCampaignsBulkList extends Command {
|
|
4
|
+
static description: string;
|
|
5
|
+
static enableJsonFlag: boolean;
|
|
6
|
+
static examples: string[];
|
|
7
|
+
static flags: {
|
|
8
|
+
app: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
'created-from': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
'created-to': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
status: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
page: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
'page-size': import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
};
|
|
15
|
+
run(): Promise<AsaBulkOperationListDTO>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Command, Flags } from '@oclif/core';
|
|
2
|
+
import { createAsaClient } from '../../../lib/asa-client.js';
|
|
3
|
+
import { asaPaginationFlags, parseDate } from '../../../lib/asa-flags.js';
|
|
4
|
+
import { isValidUuid, paginationParams } from '../../../lib/flags.js';
|
|
5
|
+
import { printList } from '../../../lib/output.js';
|
|
6
|
+
async function parseAppId(input) {
|
|
7
|
+
if (!isValidUuid(input))
|
|
8
|
+
throw new Error('Invalid app ID format. Run `adapty asa apps list` to find your app ID.');
|
|
9
|
+
return input;
|
|
10
|
+
}
|
|
11
|
+
export default class AsaCampaignsBulkList extends Command {
|
|
12
|
+
static description = "This company's bulk operations, newest first; inspect one with bulk-status";
|
|
13
|
+
static enableJsonFlag = true;
|
|
14
|
+
static examples = [
|
|
15
|
+
'<%= config.bin %> asa campaigns bulk-list',
|
|
16
|
+
'<%= config.bin %> asa campaigns bulk-list --status partial --status failed',
|
|
17
|
+
'<%= config.bin %> asa campaigns bulk-list --created-from 2026-08-01 --created-to 2026-08-20',
|
|
18
|
+
];
|
|
19
|
+
static flags = {
|
|
20
|
+
...asaPaginationFlags,
|
|
21
|
+
app: Flags.string({ description: 'Keep only operations of this app (UUID)', parse: parseAppId }),
|
|
22
|
+
'created-from': Flags.string({
|
|
23
|
+
description: 'Keep only operations created on or after this date (YYYY-MM-DD)',
|
|
24
|
+
parse: parseDate,
|
|
25
|
+
}),
|
|
26
|
+
'created-to': Flags.string({
|
|
27
|
+
description: 'Keep only operations created on or before this date (YYYY-MM-DD)',
|
|
28
|
+
parse: parseDate,
|
|
29
|
+
}),
|
|
30
|
+
status: Flags.string({
|
|
31
|
+
description: 'Keep only operations in this state; repeatable',
|
|
32
|
+
multiple: true,
|
|
33
|
+
options: ['failed', 'partial', 'pending', 'running', 'success'],
|
|
34
|
+
}),
|
|
35
|
+
};
|
|
36
|
+
async run() {
|
|
37
|
+
const { flags } = await this.parse(AsaCampaignsBulkList);
|
|
38
|
+
const client = await createAsaClient(this.config);
|
|
39
|
+
const result = await client.get('/bulk-operations', {
|
|
40
|
+
...paginationParams(flags),
|
|
41
|
+
app_id: flags.app,
|
|
42
|
+
created_from: flags['created-from'],
|
|
43
|
+
created_to: flags['created-to'],
|
|
44
|
+
status: flags.status,
|
|
45
|
+
});
|
|
46
|
+
const pages = Math.max(1, Math.ceil(result.total / result.limit));
|
|
47
|
+
printList(result.items, this.log.bind(this), {
|
|
48
|
+
count: result.total,
|
|
49
|
+
page: flags.page,
|
|
50
|
+
pages,
|
|
51
|
+
});
|
|
52
|
+
return result;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
2
|
import open from 'open';
|
|
3
3
|
import { ApiClient } from '../../lib/api-client.js';
|
|
4
|
+
import { onAppHost } from '../../lib/app-url.js';
|
|
4
5
|
import { buildUserAgent } from '../../lib/client-from-config.js';
|
|
5
6
|
import { readConfig, writeConfig } from '../../lib/config.js';
|
|
6
7
|
import { ApiError } from '../../lib/errors.js';
|
|
@@ -27,11 +28,12 @@ export default class AuthLogin extends Command {
|
|
|
27
28
|
catch (error) {
|
|
28
29
|
this.error(error instanceof Error ? error.message : 'Failed to initiate auth flow', { exit: 1 });
|
|
29
30
|
}
|
|
31
|
+
const verificationUrl = this.verificationUrl(device.verification_uri_complete);
|
|
30
32
|
this.log(`\nYour code: ${device.user_code}\n`);
|
|
31
|
-
this.log(`If browser doesn't open, visit: ${
|
|
33
|
+
this.log(`If browser doesn't open, visit: ${verificationUrl}\n`);
|
|
32
34
|
if (process.stdin.isTTY === true) {
|
|
33
35
|
try {
|
|
34
|
-
await open(
|
|
36
|
+
await open(verificationUrl);
|
|
35
37
|
}
|
|
36
38
|
catch {
|
|
37
39
|
// browser open failed silently — URL already printed
|
|
@@ -106,4 +108,13 @@ export default class AuthLogin extends Command {
|
|
|
106
108
|
process.removeListener('SIGINT', onSignal);
|
|
107
109
|
}
|
|
108
110
|
}
|
|
111
|
+
/** Keeps the browser on the configured dashboard host, when ADAPTY_APP_URL asks for one. */
|
|
112
|
+
verificationUrl(issuedUrl) {
|
|
113
|
+
try {
|
|
114
|
+
return onAppHost(issuedUrl);
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
this.error(error instanceof Error ? error.message : String(error), { exit: 2 });
|
|
118
|
+
}
|
|
119
|
+
}
|
|
109
120
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export interface PreviewResult {
|
|
3
|
+
render_url: string;
|
|
4
|
+
}
|
|
5
|
+
export default class FlowsConfigPreview extends Command {
|
|
6
|
+
static args: {
|
|
7
|
+
config_file: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
8
|
+
};
|
|
9
|
+
static description: string;
|
|
10
|
+
static enableJsonFlag: boolean;
|
|
11
|
+
static examples: string[];
|
|
12
|
+
static flags: {
|
|
13
|
+
device: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
orientation: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
+
screen: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
+
};
|
|
17
|
+
run(): Promise<PreviewResult>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import { resolve } from 'node:path';
|
|
4
|
+
import open from 'open';
|
|
5
|
+
import { APP_URL_ENV_VAR } from '../../../lib/app-url.js';
|
|
6
|
+
import { buildRenderUrl, DEFAULT_DEVICE_ID, DEFAULT_ORIENTATION, normalizePreviewConfig, ORIENTATIONS, } from '../../../lib/preview.js';
|
|
7
|
+
function describeError(error) {
|
|
8
|
+
return error instanceof Error ? error.message : String(error);
|
|
9
|
+
}
|
|
10
|
+
export default class FlowsConfigPreview extends Command {
|
|
11
|
+
static args = {
|
|
12
|
+
config_file: Args.string({ description: 'Path to a local flow config JSON file', required: true }),
|
|
13
|
+
};
|
|
14
|
+
static description = `Build a render URL for a local flow config and open it. A quick-look escape hatch for small configs: the whole config rides in the URL fragment, and past roughly 32KB of pretty-printed JSON the render page gets slow and unreliable. Opens the browser on a TTY; when piped or with --json, prints the URL alone — and that URL is long (~113K characters for a 668KB flow), so pipe it into whatever takes the screenshot ("| node capture.mjs") or pass it with --url and command substitution. Never print or read it: agents burn context for zero information. The render host comes from $${APP_URL_ENV_VAR}.`;
|
|
15
|
+
static enableJsonFlag = true;
|
|
16
|
+
static examples = [
|
|
17
|
+
'<%= config.bin %> flows config preview ./config.json',
|
|
18
|
+
'<%= config.bin %> flows config preview ./config.json --screen welcome --device ipad-pro --orientation landscape',
|
|
19
|
+
'# pipe the URL straight into a screenshot tool, never print it\n<%= config.bin %> flows config preview ./config.json | node capture.mjs --out shot.png',
|
|
20
|
+
'# or pass it as an argument, for tools that want a flag\nnode capture.mjs --url "$(<%= config.bin %> flows config preview ./config.json)" --out shot.png',
|
|
21
|
+
];
|
|
22
|
+
static flags = {
|
|
23
|
+
device: Flags.string({ default: DEFAULT_DEVICE_ID, description: 'Device frame to render in' }),
|
|
24
|
+
orientation: Flags.string({
|
|
25
|
+
default: DEFAULT_ORIENTATION,
|
|
26
|
+
description: 'Device orientation to render in',
|
|
27
|
+
options: [...ORIENTATIONS],
|
|
28
|
+
}),
|
|
29
|
+
screen: Flags.string({ description: "Screen ID to render (default: the flow's first screen)" }),
|
|
30
|
+
};
|
|
31
|
+
async run() {
|
|
32
|
+
const { args, flags } = await this.parse(FlowsConfigPreview);
|
|
33
|
+
const configPath = resolve(args.config_file);
|
|
34
|
+
let raw;
|
|
35
|
+
try {
|
|
36
|
+
raw = JSON.parse(await readFile(configPath, 'utf8'));
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
this.error(`Could not read config file ${configPath}: ${describeError(error)}`, { exit: 2 });
|
|
40
|
+
}
|
|
41
|
+
let payload;
|
|
42
|
+
try {
|
|
43
|
+
payload = normalizePreviewConfig(raw);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
this.error(describeError(error), { exit: 2 });
|
|
47
|
+
}
|
|
48
|
+
let renderUrl;
|
|
49
|
+
try {
|
|
50
|
+
renderUrl = buildRenderUrl({ device: flags.device, orientation: flags.orientation, screen: flags.screen }, payload);
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
this.error(describeError(error), { exit: 2 });
|
|
54
|
+
}
|
|
55
|
+
const result = { render_url: renderUrl };
|
|
56
|
+
if (this.jsonEnabled())
|
|
57
|
+
return result;
|
|
58
|
+
// Piped output stays a bare URL so it composes — the whole config rides in the fragment, which
|
|
59
|
+
// is why a TTY gets the browser opened instead of a screenful of base64.
|
|
60
|
+
if (process.stdout.isTTY !== true) {
|
|
61
|
+
this.log(renderUrl);
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
const target = [flags.screen ?? 'first screen', flags.device, flags.orientation].join(', ');
|
|
65
|
+
try {
|
|
66
|
+
await open(renderUrl);
|
|
67
|
+
this.log(`Opened the preview in your browser (${target}).`);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
this.log(renderUrl);
|
|
71
|
+
}
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const APP_URL_ENV_VAR = "ADAPTY_APP_URL";
|
|
2
|
+
export declare const DEFAULT_APP_URL = "https://app.adapty.io";
|
|
3
|
+
/** Builds a dashboard URL for a fixed route, e.g. the flow preview page. */
|
|
4
|
+
export declare function appUrl(path: string): URL;
|
|
5
|
+
/**
|
|
6
|
+
* Moves a link the API issued (the device-flow verification URI) onto the configured dashboard
|
|
7
|
+
* host, so pointing the CLI at a local or staging dashboard keeps the browser there too. Without
|
|
8
|
+
* ADAPTY_APP_URL the link is left exactly as issued — the API is free to serve it from any host.
|
|
9
|
+
*/
|
|
10
|
+
export declare function onAppHost(issuedUrl: string): string;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export const APP_URL_ENV_VAR = 'ADAPTY_APP_URL';
|
|
2
|
+
export const DEFAULT_APP_URL = 'https://app.adapty.io';
|
|
3
|
+
/** Dashboard origin: ADAPTY_APP_URL when set, production otherwise. Only its origin is used. */
|
|
4
|
+
function appBaseUrl() {
|
|
5
|
+
const base = process.env[APP_URL_ENV_VAR] ?? DEFAULT_APP_URL;
|
|
6
|
+
try {
|
|
7
|
+
return new URL(base);
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
throw new Error(`Invalid ${APP_URL_ENV_VAR}: ${base}`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/** Builds a dashboard URL for a fixed route, e.g. the flow preview page. */
|
|
14
|
+
export function appUrl(path) {
|
|
15
|
+
return new URL(path, appBaseUrl());
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Moves a link the API issued (the device-flow verification URI) onto the configured dashboard
|
|
19
|
+
* host, so pointing the CLI at a local or staging dashboard keeps the browser there too. Without
|
|
20
|
+
* ADAPTY_APP_URL the link is left exactly as issued — the API is free to serve it from any host.
|
|
21
|
+
*/
|
|
22
|
+
export function onAppHost(issuedUrl) {
|
|
23
|
+
if (!process.env[APP_URL_ENV_VAR])
|
|
24
|
+
return issuedUrl;
|
|
25
|
+
let issued;
|
|
26
|
+
try {
|
|
27
|
+
issued = new URL(issuedUrl);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return issuedUrl;
|
|
31
|
+
}
|
|
32
|
+
return appUrl(`${issued.pathname}${issued.search}${issued.hash}`).toString();
|
|
33
|
+
}
|
package/dist/lib/asa-flags.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export declare const asaPaginationFlags: {
|
|
|
11
11
|
export declare const byDaysFlag: {
|
|
12
12
|
'by-days': import("@oclif/core/interfaces").OptionFlag<number[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
13
|
};
|
|
14
|
+
export declare function parseDate(input: string): Promise<string>;
|
|
14
15
|
export declare const periodFlags: {
|
|
15
16
|
'date-from': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
17
|
'date-to': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
package/dist/lib/asa-flags.js
CHANGED
|
@@ -314,6 +314,21 @@ export interface AsaBulkOperationStateDTO {
|
|
|
314
314
|
started_at: null | string;
|
|
315
315
|
status: AsaBulkOperationStatus;
|
|
316
316
|
}
|
|
317
|
+
export interface AsaBulkOperationListItemDTO {
|
|
318
|
+
app_id: string;
|
|
319
|
+
created_at: string;
|
|
320
|
+
error: null | string;
|
|
321
|
+
finished_at: null | string;
|
|
322
|
+
operation_id: string;
|
|
323
|
+
started_at: null | string;
|
|
324
|
+
status: AsaBulkOperationStatus;
|
|
325
|
+
}
|
|
326
|
+
export interface AsaBulkOperationListDTO {
|
|
327
|
+
items: AsaBulkOperationListItemDTO[];
|
|
328
|
+
limit: number;
|
|
329
|
+
offset: number;
|
|
330
|
+
total: number;
|
|
331
|
+
}
|
|
317
332
|
export interface AsaTemplateIssueDTO {
|
|
318
333
|
column: null | string;
|
|
319
334
|
message: string;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** The render route is fixed; only its host is configurable, via ADAPTY_APP_URL. */
|
|
2
|
+
export declare const PREVIEW_PATH = "/flow-preview";
|
|
3
|
+
export declare const DEFAULT_DEVICE_ID = "iphone-14";
|
|
4
|
+
/** Orientations the render page accepts; anything else falls back to its own default. */
|
|
5
|
+
export declare const ORIENTATIONS: readonly ["landscape", "portrait"];
|
|
6
|
+
export declare const DEFAULT_ORIENTATION = "portrait";
|
|
7
|
+
/** Payload the render page expects. Wire format shared with the UI, hence camelCase. */
|
|
8
|
+
export interface PreviewPayload {
|
|
9
|
+
flow: Record<string, unknown>;
|
|
10
|
+
remoteConfigs: unknown[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Accepts either a dashboard-api envelope (`{config, remote_configs, ...}`) or a bare
|
|
14
|
+
* builder config, and returns the shape the render page injects.
|
|
15
|
+
*
|
|
16
|
+
* `screens` must be an array: that is exactly what the page's own payload guard checks
|
|
17
|
+
* before it treats the payload as a builder draft, so a config without it would be
|
|
18
|
+
* rejected there instead — better to say so here, against the file the user named.
|
|
19
|
+
*/
|
|
20
|
+
export declare function normalizePreviewConfig(raw: unknown): PreviewPayload;
|
|
21
|
+
export interface RenderTarget {
|
|
22
|
+
device: string;
|
|
23
|
+
orientation: string;
|
|
24
|
+
/** Omitted lets the render page fall back to the flow's first screen. */
|
|
25
|
+
screen?: string;
|
|
26
|
+
}
|
|
27
|
+
export declare function buildRenderUrl(target: RenderTarget, payload: PreviewPayload): string;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { gzipSync } from 'node:zlib';
|
|
2
|
+
import { appUrl } from './app-url.js';
|
|
3
|
+
/** The render route is fixed; only its host is configurable, via ADAPTY_APP_URL. */
|
|
4
|
+
export const PREVIEW_PATH = '/flow-preview';
|
|
5
|
+
export const DEFAULT_DEVICE_ID = 'iphone-14';
|
|
6
|
+
/** Orientations the render page accepts; anything else falls back to its own default. */
|
|
7
|
+
export const ORIENTATIONS = ['landscape', 'portrait'];
|
|
8
|
+
export const DEFAULT_ORIENTATION = 'portrait';
|
|
9
|
+
function isRecord(value) {
|
|
10
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Accepts either a dashboard-api envelope (`{config, remote_configs, ...}`) or a bare
|
|
14
|
+
* builder config, and returns the shape the render page injects.
|
|
15
|
+
*
|
|
16
|
+
* `screens` must be an array: that is exactly what the page's own payload guard checks
|
|
17
|
+
* before it treats the payload as a builder draft, so a config without it would be
|
|
18
|
+
* rejected there instead — better to say so here, against the file the user named.
|
|
19
|
+
*/
|
|
20
|
+
export function normalizePreviewConfig(raw) {
|
|
21
|
+
if (!isRecord(raw)) {
|
|
22
|
+
throw new Error('Config file must contain a JSON object.');
|
|
23
|
+
}
|
|
24
|
+
const envelopeConfig = isRecord(raw.config) ? raw.config : null;
|
|
25
|
+
const flow = envelopeConfig ?? raw;
|
|
26
|
+
if (!Array.isArray(flow.screens)) {
|
|
27
|
+
throw new TypeError('Unrecognized config file. Expected a dashboard-api envelope with a `config` object, or a bare builder config — either way `screens` must be an array.');
|
|
28
|
+
}
|
|
29
|
+
const remoteConfigs = envelopeConfig && Array.isArray(raw.remote_configs) ? raw.remote_configs : [];
|
|
30
|
+
return { flow, remoteConfigs };
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Fragment wire format shared with the render page: bare `base64url(gzip(utf8(JSON)))`, no
|
|
34
|
+
* prefix — the page compresses unconditionally too, so there is no plain shape to mark it
|
|
35
|
+
* apart from. Node's base64url already omits the `=` padding the page strips.
|
|
36
|
+
*/
|
|
37
|
+
function encodeConfigFragment(payload) {
|
|
38
|
+
return gzipSync(Buffer.from(JSON.stringify(payload), 'utf8')).toString('base64url');
|
|
39
|
+
}
|
|
40
|
+
export function buildRenderUrl(target, payload) {
|
|
41
|
+
const url = appUrl(PREVIEW_PATH);
|
|
42
|
+
if (target.screen)
|
|
43
|
+
url.searchParams.set('screen', target.screen);
|
|
44
|
+
url.searchParams.set('device', target.device);
|
|
45
|
+
url.searchParams.set('orientation', target.orientation);
|
|
46
|
+
url.hash = `config=${encodeConfigFragment(payload)}`;
|
|
47
|
+
return url.toString();
|
|
48
|
+
}
|
package/oclif.manifest.json
CHANGED
|
@@ -1322,6 +1322,108 @@
|
|
|
1322
1322
|
"update.js"
|
|
1323
1323
|
]
|
|
1324
1324
|
},
|
|
1325
|
+
"segments:get": {
|
|
1326
|
+
"aliases": [],
|
|
1327
|
+
"args": {
|
|
1328
|
+
"segment_id": {
|
|
1329
|
+
"description": "Segment ID (UUID)",
|
|
1330
|
+
"name": "segment_id",
|
|
1331
|
+
"required": true
|
|
1332
|
+
}
|
|
1333
|
+
},
|
|
1334
|
+
"description": "Get segment details",
|
|
1335
|
+
"examples": [
|
|
1336
|
+
"<%= config.bin %> segments get --app UUID 550e8400-e29b-41d4-a716-446655440000"
|
|
1337
|
+
],
|
|
1338
|
+
"flags": {
|
|
1339
|
+
"json": {
|
|
1340
|
+
"description": "Format output as json.",
|
|
1341
|
+
"helpGroup": "GLOBAL",
|
|
1342
|
+
"name": "json",
|
|
1343
|
+
"allowNo": false,
|
|
1344
|
+
"type": "boolean"
|
|
1345
|
+
},
|
|
1346
|
+
"app": {
|
|
1347
|
+
"description": "App ID (UUID)",
|
|
1348
|
+
"name": "app",
|
|
1349
|
+
"required": true,
|
|
1350
|
+
"hasDynamicHelp": false,
|
|
1351
|
+
"multiple": false,
|
|
1352
|
+
"type": "option"
|
|
1353
|
+
}
|
|
1354
|
+
},
|
|
1355
|
+
"hasDynamicHelp": false,
|
|
1356
|
+
"hiddenAliases": [],
|
|
1357
|
+
"id": "segments:get",
|
|
1358
|
+
"pluginAlias": "adapty",
|
|
1359
|
+
"pluginName": "adapty",
|
|
1360
|
+
"pluginType": "core",
|
|
1361
|
+
"strict": true,
|
|
1362
|
+
"enableJsonFlag": true,
|
|
1363
|
+
"isESM": true,
|
|
1364
|
+
"relativePath": [
|
|
1365
|
+
"dist",
|
|
1366
|
+
"commands",
|
|
1367
|
+
"segments",
|
|
1368
|
+
"get.js"
|
|
1369
|
+
]
|
|
1370
|
+
},
|
|
1371
|
+
"segments:list": {
|
|
1372
|
+
"aliases": [],
|
|
1373
|
+
"args": {},
|
|
1374
|
+
"description": "List segments for an app",
|
|
1375
|
+
"examples": [
|
|
1376
|
+
"<%= config.bin %> segments list --app 550e8400-..."
|
|
1377
|
+
],
|
|
1378
|
+
"flags": {
|
|
1379
|
+
"json": {
|
|
1380
|
+
"description": "Format output as json.",
|
|
1381
|
+
"helpGroup": "GLOBAL",
|
|
1382
|
+
"name": "json",
|
|
1383
|
+
"allowNo": false,
|
|
1384
|
+
"type": "boolean"
|
|
1385
|
+
},
|
|
1386
|
+
"app": {
|
|
1387
|
+
"description": "App ID (UUID)",
|
|
1388
|
+
"name": "app",
|
|
1389
|
+
"required": true,
|
|
1390
|
+
"hasDynamicHelp": false,
|
|
1391
|
+
"multiple": false,
|
|
1392
|
+
"type": "option"
|
|
1393
|
+
},
|
|
1394
|
+
"page": {
|
|
1395
|
+
"description": "Page number",
|
|
1396
|
+
"name": "page",
|
|
1397
|
+
"default": 1,
|
|
1398
|
+
"hasDynamicHelp": false,
|
|
1399
|
+
"multiple": false,
|
|
1400
|
+
"type": "option"
|
|
1401
|
+
},
|
|
1402
|
+
"page-size": {
|
|
1403
|
+
"description": "Items per page (max 100)",
|
|
1404
|
+
"name": "page-size",
|
|
1405
|
+
"default": 20,
|
|
1406
|
+
"hasDynamicHelp": false,
|
|
1407
|
+
"multiple": false,
|
|
1408
|
+
"type": "option"
|
|
1409
|
+
}
|
|
1410
|
+
},
|
|
1411
|
+
"hasDynamicHelp": false,
|
|
1412
|
+
"hiddenAliases": [],
|
|
1413
|
+
"id": "segments:list",
|
|
1414
|
+
"pluginAlias": "adapty",
|
|
1415
|
+
"pluginName": "adapty",
|
|
1416
|
+
"pluginType": "core",
|
|
1417
|
+
"strict": true,
|
|
1418
|
+
"enableJsonFlag": true,
|
|
1419
|
+
"isESM": true,
|
|
1420
|
+
"relativePath": [
|
|
1421
|
+
"dist",
|
|
1422
|
+
"commands",
|
|
1423
|
+
"segments",
|
|
1424
|
+
"list.js"
|
|
1425
|
+
]
|
|
1426
|
+
},
|
|
1325
1427
|
"products:create": {
|
|
1326
1428
|
"aliases": [],
|
|
1327
1429
|
"args": {},
|
|
@@ -1606,108 +1708,6 @@
|
|
|
1606
1708
|
"update.js"
|
|
1607
1709
|
]
|
|
1608
1710
|
},
|
|
1609
|
-
"segments:get": {
|
|
1610
|
-
"aliases": [],
|
|
1611
|
-
"args": {
|
|
1612
|
-
"segment_id": {
|
|
1613
|
-
"description": "Segment ID (UUID)",
|
|
1614
|
-
"name": "segment_id",
|
|
1615
|
-
"required": true
|
|
1616
|
-
}
|
|
1617
|
-
},
|
|
1618
|
-
"description": "Get segment details",
|
|
1619
|
-
"examples": [
|
|
1620
|
-
"<%= config.bin %> segments get --app UUID 550e8400-e29b-41d4-a716-446655440000"
|
|
1621
|
-
],
|
|
1622
|
-
"flags": {
|
|
1623
|
-
"json": {
|
|
1624
|
-
"description": "Format output as json.",
|
|
1625
|
-
"helpGroup": "GLOBAL",
|
|
1626
|
-
"name": "json",
|
|
1627
|
-
"allowNo": false,
|
|
1628
|
-
"type": "boolean"
|
|
1629
|
-
},
|
|
1630
|
-
"app": {
|
|
1631
|
-
"description": "App ID (UUID)",
|
|
1632
|
-
"name": "app",
|
|
1633
|
-
"required": true,
|
|
1634
|
-
"hasDynamicHelp": false,
|
|
1635
|
-
"multiple": false,
|
|
1636
|
-
"type": "option"
|
|
1637
|
-
}
|
|
1638
|
-
},
|
|
1639
|
-
"hasDynamicHelp": false,
|
|
1640
|
-
"hiddenAliases": [],
|
|
1641
|
-
"id": "segments:get",
|
|
1642
|
-
"pluginAlias": "adapty",
|
|
1643
|
-
"pluginName": "adapty",
|
|
1644
|
-
"pluginType": "core",
|
|
1645
|
-
"strict": true,
|
|
1646
|
-
"enableJsonFlag": true,
|
|
1647
|
-
"isESM": true,
|
|
1648
|
-
"relativePath": [
|
|
1649
|
-
"dist",
|
|
1650
|
-
"commands",
|
|
1651
|
-
"segments",
|
|
1652
|
-
"get.js"
|
|
1653
|
-
]
|
|
1654
|
-
},
|
|
1655
|
-
"segments:list": {
|
|
1656
|
-
"aliases": [],
|
|
1657
|
-
"args": {},
|
|
1658
|
-
"description": "List segments for an app",
|
|
1659
|
-
"examples": [
|
|
1660
|
-
"<%= config.bin %> segments list --app 550e8400-..."
|
|
1661
|
-
],
|
|
1662
|
-
"flags": {
|
|
1663
|
-
"json": {
|
|
1664
|
-
"description": "Format output as json.",
|
|
1665
|
-
"helpGroup": "GLOBAL",
|
|
1666
|
-
"name": "json",
|
|
1667
|
-
"allowNo": false,
|
|
1668
|
-
"type": "boolean"
|
|
1669
|
-
},
|
|
1670
|
-
"app": {
|
|
1671
|
-
"description": "App ID (UUID)",
|
|
1672
|
-
"name": "app",
|
|
1673
|
-
"required": true,
|
|
1674
|
-
"hasDynamicHelp": false,
|
|
1675
|
-
"multiple": false,
|
|
1676
|
-
"type": "option"
|
|
1677
|
-
},
|
|
1678
|
-
"page": {
|
|
1679
|
-
"description": "Page number",
|
|
1680
|
-
"name": "page",
|
|
1681
|
-
"default": 1,
|
|
1682
|
-
"hasDynamicHelp": false,
|
|
1683
|
-
"multiple": false,
|
|
1684
|
-
"type": "option"
|
|
1685
|
-
},
|
|
1686
|
-
"page-size": {
|
|
1687
|
-
"description": "Items per page (max 100)",
|
|
1688
|
-
"name": "page-size",
|
|
1689
|
-
"default": 20,
|
|
1690
|
-
"hasDynamicHelp": false,
|
|
1691
|
-
"multiple": false,
|
|
1692
|
-
"type": "option"
|
|
1693
|
-
}
|
|
1694
|
-
},
|
|
1695
|
-
"hasDynamicHelp": false,
|
|
1696
|
-
"hiddenAliases": [],
|
|
1697
|
-
"id": "segments:list",
|
|
1698
|
-
"pluginAlias": "adapty",
|
|
1699
|
-
"pluginName": "adapty",
|
|
1700
|
-
"pluginType": "core",
|
|
1701
|
-
"strict": true,
|
|
1702
|
-
"enableJsonFlag": true,
|
|
1703
|
-
"isESM": true,
|
|
1704
|
-
"relativePath": [
|
|
1705
|
-
"dist",
|
|
1706
|
-
"commands",
|
|
1707
|
-
"segments",
|
|
1708
|
-
"list.js"
|
|
1709
|
-
]
|
|
1710
|
-
},
|
|
1711
1711
|
"asa:ad-groups:create": {
|
|
1712
1712
|
"aliases": [],
|
|
1713
1713
|
"args": {},
|
|
@@ -2361,6 +2361,56 @@
|
|
|
2361
2361
|
"update.js"
|
|
2362
2362
|
]
|
|
2363
2363
|
},
|
|
2364
|
+
"asa:apps:list": {
|
|
2365
|
+
"aliases": [],
|
|
2366
|
+
"args": {},
|
|
2367
|
+
"description": "List the apps promoted by this company in Apple Search Ads",
|
|
2368
|
+
"examples": [
|
|
2369
|
+
"<%= config.bin %> asa apps list",
|
|
2370
|
+
"<%= config.bin %> asa apps list --page 2 --page-size 50"
|
|
2371
|
+
],
|
|
2372
|
+
"flags": {
|
|
2373
|
+
"json": {
|
|
2374
|
+
"description": "Format output as json.",
|
|
2375
|
+
"helpGroup": "GLOBAL",
|
|
2376
|
+
"name": "json",
|
|
2377
|
+
"allowNo": false,
|
|
2378
|
+
"type": "boolean"
|
|
2379
|
+
},
|
|
2380
|
+
"page": {
|
|
2381
|
+
"description": "Page number",
|
|
2382
|
+
"name": "page",
|
|
2383
|
+
"default": 1,
|
|
2384
|
+
"hasDynamicHelp": false,
|
|
2385
|
+
"multiple": false,
|
|
2386
|
+
"type": "option"
|
|
2387
|
+
},
|
|
2388
|
+
"page-size": {
|
|
2389
|
+
"description": "Items per page (max 1000); prefer one big page over a pagination loop",
|
|
2390
|
+
"name": "page-size",
|
|
2391
|
+
"default": 100,
|
|
2392
|
+
"hasDynamicHelp": false,
|
|
2393
|
+
"multiple": false,
|
|
2394
|
+
"type": "option"
|
|
2395
|
+
}
|
|
2396
|
+
},
|
|
2397
|
+
"hasDynamicHelp": false,
|
|
2398
|
+
"hiddenAliases": [],
|
|
2399
|
+
"id": "asa:apps:list",
|
|
2400
|
+
"pluginAlias": "adapty",
|
|
2401
|
+
"pluginName": "adapty",
|
|
2402
|
+
"pluginType": "core",
|
|
2403
|
+
"strict": true,
|
|
2404
|
+
"enableJsonFlag": true,
|
|
2405
|
+
"isESM": true,
|
|
2406
|
+
"relativePath": [
|
|
2407
|
+
"dist",
|
|
2408
|
+
"commands",
|
|
2409
|
+
"asa",
|
|
2410
|
+
"apps",
|
|
2411
|
+
"list.js"
|
|
2412
|
+
]
|
|
2413
|
+
},
|
|
2364
2414
|
"asa:automations:create": {
|
|
2365
2415
|
"aliases": [],
|
|
2366
2416
|
"args": {},
|
|
@@ -2712,15 +2762,113 @@
|
|
|
2712
2762
|
"update.js"
|
|
2713
2763
|
]
|
|
2714
2764
|
},
|
|
2715
|
-
"asa:campaigns:bulk-create": {
|
|
2765
|
+
"asa:campaigns:bulk-create": {
|
|
2766
|
+
"aliases": [],
|
|
2767
|
+
"args": {},
|
|
2768
|
+
"description": "Create a whole campaign structure (campaigns → ad groups → keywords/negative keywords/ads) in one bulk operation",
|
|
2769
|
+
"examples": [
|
|
2770
|
+
"<%= config.bin %> asa campaigns bulk-create --file structure.json",
|
|
2771
|
+
"cat structure.json | <%= config.bin %> asa campaigns bulk-create --file -",
|
|
2772
|
+
"<%= config.bin %> asa campaigns bulk-create --from-file Campaign_And_Adgroup_Template.xlsx --org-id 1234567",
|
|
2773
|
+
"<%= config.bin %> asa campaigns bulk-create --from-file keywords_template.csv --org-id 1234567 --preview"
|
|
2774
|
+
],
|
|
2775
|
+
"flags": {
|
|
2776
|
+
"json": {
|
|
2777
|
+
"description": "Format output as json.",
|
|
2778
|
+
"helpGroup": "GLOBAL",
|
|
2779
|
+
"name": "json",
|
|
2780
|
+
"allowNo": false,
|
|
2781
|
+
"type": "boolean"
|
|
2782
|
+
},
|
|
2783
|
+
"yes": {
|
|
2784
|
+
"char": "y",
|
|
2785
|
+
"description": "Apply without asking; required when the output is piped or --json is used",
|
|
2786
|
+
"name": "yes",
|
|
2787
|
+
"allowNo": false,
|
|
2788
|
+
"type": "boolean"
|
|
2789
|
+
},
|
|
2790
|
+
"idempotency-key": {
|
|
2791
|
+
"description": "Idempotency key for this write; re-running with the same key replays the stored result instead of applying twice",
|
|
2792
|
+
"name": "idempotency-key",
|
|
2793
|
+
"hasDynamicHelp": false,
|
|
2794
|
+
"multiple": false,
|
|
2795
|
+
"type": "option"
|
|
2796
|
+
},
|
|
2797
|
+
"file": {
|
|
2798
|
+
"description": "JSON file with the campaign structure (the POST /bulk-operations/ body); use \"-\" for stdin",
|
|
2799
|
+
"name": "file",
|
|
2800
|
+
"hasDynamicHelp": false,
|
|
2801
|
+
"multiple": false,
|
|
2802
|
+
"type": "option"
|
|
2803
|
+
},
|
|
2804
|
+
"from-file": {
|
|
2805
|
+
"description": "Apple Ads bulk template (Campaign_And_Adgroup_Template.xlsx or keywords .csv) to convert and submit",
|
|
2806
|
+
"name": "from-file",
|
|
2807
|
+
"hasDynamicHelp": false,
|
|
2808
|
+
"multiple": false,
|
|
2809
|
+
"type": "option"
|
|
2810
|
+
},
|
|
2811
|
+
"org-id": {
|
|
2812
|
+
"description": "Apple org id (campaign_group_id) the converted template will target; required with --from-file",
|
|
2813
|
+
"name": "org-id",
|
|
2814
|
+
"hasDynamicHelp": false,
|
|
2815
|
+
"multiple": false,
|
|
2816
|
+
"type": "option"
|
|
2817
|
+
},
|
|
2818
|
+
"poll-interval": {
|
|
2819
|
+
"description": "Seconds between progress polls",
|
|
2820
|
+
"name": "poll-interval",
|
|
2821
|
+
"default": 5,
|
|
2822
|
+
"hasDynamicHelp": false,
|
|
2823
|
+
"multiple": false,
|
|
2824
|
+
"type": "option"
|
|
2825
|
+
},
|
|
2826
|
+
"preview": {
|
|
2827
|
+
"description": "With --from-file: print the converted request and stop, nothing is created",
|
|
2828
|
+
"name": "preview",
|
|
2829
|
+
"allowNo": false,
|
|
2830
|
+
"type": "boolean"
|
|
2831
|
+
},
|
|
2832
|
+
"timeout": {
|
|
2833
|
+
"description": "Max seconds to wait for the operation to finish",
|
|
2834
|
+
"name": "timeout",
|
|
2835
|
+
"default": 900,
|
|
2836
|
+
"hasDynamicHelp": false,
|
|
2837
|
+
"multiple": false,
|
|
2838
|
+
"type": "option"
|
|
2839
|
+
},
|
|
2840
|
+
"wait": {
|
|
2841
|
+
"description": "Poll the operation until it finishes; --no-wait returns the operation id immediately",
|
|
2842
|
+
"name": "wait",
|
|
2843
|
+
"allowNo": true,
|
|
2844
|
+
"type": "boolean"
|
|
2845
|
+
}
|
|
2846
|
+
},
|
|
2847
|
+
"hasDynamicHelp": false,
|
|
2848
|
+
"hiddenAliases": [],
|
|
2849
|
+
"id": "asa:campaigns:bulk-create",
|
|
2850
|
+
"pluginAlias": "adapty",
|
|
2851
|
+
"pluginName": "adapty",
|
|
2852
|
+
"pluginType": "core",
|
|
2853
|
+
"strict": true,
|
|
2854
|
+
"enableJsonFlag": true,
|
|
2855
|
+
"isESM": true,
|
|
2856
|
+
"relativePath": [
|
|
2857
|
+
"dist",
|
|
2858
|
+
"commands",
|
|
2859
|
+
"asa",
|
|
2860
|
+
"campaigns",
|
|
2861
|
+
"bulk-create.js"
|
|
2862
|
+
]
|
|
2863
|
+
},
|
|
2864
|
+
"asa:campaigns:bulk-list": {
|
|
2716
2865
|
"aliases": [],
|
|
2717
2866
|
"args": {},
|
|
2718
|
-
"description": "
|
|
2867
|
+
"description": "This company's bulk operations, newest first; inspect one with bulk-status",
|
|
2719
2868
|
"examples": [
|
|
2720
|
-
"<%= config.bin %> asa campaigns bulk-
|
|
2721
|
-
"
|
|
2722
|
-
"<%= config.bin %> asa campaigns bulk-
|
|
2723
|
-
"<%= config.bin %> asa campaigns bulk-create --from-file keywords_template.csv --org-id 1234567 --preview"
|
|
2869
|
+
"<%= config.bin %> asa campaigns bulk-list",
|
|
2870
|
+
"<%= config.bin %> asa campaigns bulk-list --status partial --status failed",
|
|
2871
|
+
"<%= config.bin %> asa campaigns bulk-list --created-from 2026-08-01 --created-to 2026-08-20"
|
|
2724
2872
|
],
|
|
2725
2873
|
"flags": {
|
|
2726
2874
|
"json": {
|
|
@@ -2730,73 +2878,61 @@
|
|
|
2730
2878
|
"allowNo": false,
|
|
2731
2879
|
"type": "boolean"
|
|
2732
2880
|
},
|
|
2733
|
-
"
|
|
2734
|
-
"
|
|
2735
|
-
"
|
|
2736
|
-
"
|
|
2737
|
-
"allowNo": false,
|
|
2738
|
-
"type": "boolean"
|
|
2739
|
-
},
|
|
2740
|
-
"idempotency-key": {
|
|
2741
|
-
"description": "Idempotency key for this write; re-running with the same key replays the stored result instead of applying twice",
|
|
2742
|
-
"name": "idempotency-key",
|
|
2881
|
+
"page": {
|
|
2882
|
+
"description": "Page number",
|
|
2883
|
+
"name": "page",
|
|
2884
|
+
"default": 1,
|
|
2743
2885
|
"hasDynamicHelp": false,
|
|
2744
2886
|
"multiple": false,
|
|
2745
2887
|
"type": "option"
|
|
2746
2888
|
},
|
|
2747
|
-
"
|
|
2748
|
-
"description": "
|
|
2749
|
-
"name": "
|
|
2889
|
+
"page-size": {
|
|
2890
|
+
"description": "Items per page (max 1000); prefer one big page over a pagination loop",
|
|
2891
|
+
"name": "page-size",
|
|
2892
|
+
"default": 100,
|
|
2750
2893
|
"hasDynamicHelp": false,
|
|
2751
2894
|
"multiple": false,
|
|
2752
2895
|
"type": "option"
|
|
2753
2896
|
},
|
|
2754
|
-
"
|
|
2755
|
-
"description": "
|
|
2756
|
-
"name": "
|
|
2897
|
+
"app": {
|
|
2898
|
+
"description": "Keep only operations of this app (UUID)",
|
|
2899
|
+
"name": "app",
|
|
2757
2900
|
"hasDynamicHelp": false,
|
|
2758
2901
|
"multiple": false,
|
|
2759
2902
|
"type": "option"
|
|
2760
2903
|
},
|
|
2761
|
-
"
|
|
2762
|
-
"description": "
|
|
2763
|
-
"name": "
|
|
2904
|
+
"created-from": {
|
|
2905
|
+
"description": "Keep only operations created on or after this date (YYYY-MM-DD)",
|
|
2906
|
+
"name": "created-from",
|
|
2764
2907
|
"hasDynamicHelp": false,
|
|
2765
2908
|
"multiple": false,
|
|
2766
2909
|
"type": "option"
|
|
2767
2910
|
},
|
|
2768
|
-
"
|
|
2769
|
-
"description": "
|
|
2770
|
-
"name": "
|
|
2771
|
-
"default": 5,
|
|
2911
|
+
"created-to": {
|
|
2912
|
+
"description": "Keep only operations created on or before this date (YYYY-MM-DD)",
|
|
2913
|
+
"name": "created-to",
|
|
2772
2914
|
"hasDynamicHelp": false,
|
|
2773
2915
|
"multiple": false,
|
|
2774
2916
|
"type": "option"
|
|
2775
2917
|
},
|
|
2776
|
-
"
|
|
2777
|
-
"description": "
|
|
2778
|
-
"name": "
|
|
2779
|
-
"allowNo": false,
|
|
2780
|
-
"type": "boolean"
|
|
2781
|
-
},
|
|
2782
|
-
"timeout": {
|
|
2783
|
-
"description": "Max seconds to wait for the operation to finish",
|
|
2784
|
-
"name": "timeout",
|
|
2785
|
-
"default": 900,
|
|
2918
|
+
"status": {
|
|
2919
|
+
"description": "Keep only operations in this state; repeatable",
|
|
2920
|
+
"name": "status",
|
|
2786
2921
|
"hasDynamicHelp": false,
|
|
2787
|
-
"multiple":
|
|
2922
|
+
"multiple": true,
|
|
2923
|
+
"options": [
|
|
2924
|
+
"failed",
|
|
2925
|
+
"partial",
|
|
2926
|
+
"pending",
|
|
2927
|
+
"running",
|
|
2928
|
+
"success"
|
|
2929
|
+
],
|
|
2788
2930
|
"type": "option"
|
|
2789
|
-
},
|
|
2790
|
-
"wait": {
|
|
2791
|
-
"description": "Poll the operation until it finishes; --no-wait returns the operation id immediately",
|
|
2792
|
-
"name": "wait",
|
|
2793
|
-
"allowNo": true,
|
|
2794
|
-
"type": "boolean"
|
|
2795
2931
|
}
|
|
2796
2932
|
},
|
|
2797
2933
|
"hasDynamicHelp": false,
|
|
2798
2934
|
"hiddenAliases": [],
|
|
2799
|
-
"id": "asa:campaigns:bulk-
|
|
2935
|
+
"id": "asa:campaigns:bulk-list",
|
|
2800
2936
|
"pluginAlias": "adapty",
|
|
2801
2937
|
"pluginName": "adapty",
|
|
2802
2938
|
"pluginType": "core",
|
|
@@ -2808,7 +2944,7 @@
|
|
|
2808
2944
|
"commands",
|
|
2809
2945
|
"asa",
|
|
2810
2946
|
"campaigns",
|
|
2811
|
-
"bulk-
|
|
2947
|
+
"bulk-list.js"
|
|
2812
2948
|
]
|
|
2813
2949
|
},
|
|
2814
2950
|
"asa:campaigns:bulk-status": {
|
|
@@ -4111,55 +4247,6 @@
|
|
|
4111
4247
|
"list.js"
|
|
4112
4248
|
]
|
|
4113
4249
|
},
|
|
4114
|
-
"asa:orgs:list": {
|
|
4115
|
-
"aliases": [],
|
|
4116
|
-
"args": {},
|
|
4117
|
-
"description": "List the Apple Search Ads organizations this company can spend from",
|
|
4118
|
-
"examples": [
|
|
4119
|
-
"<%= config.bin %> asa orgs list"
|
|
4120
|
-
],
|
|
4121
|
-
"flags": {
|
|
4122
|
-
"json": {
|
|
4123
|
-
"description": "Format output as json.",
|
|
4124
|
-
"helpGroup": "GLOBAL",
|
|
4125
|
-
"name": "json",
|
|
4126
|
-
"allowNo": false,
|
|
4127
|
-
"type": "boolean"
|
|
4128
|
-
},
|
|
4129
|
-
"page": {
|
|
4130
|
-
"description": "Page number",
|
|
4131
|
-
"name": "page",
|
|
4132
|
-
"default": 1,
|
|
4133
|
-
"hasDynamicHelp": false,
|
|
4134
|
-
"multiple": false,
|
|
4135
|
-
"type": "option"
|
|
4136
|
-
},
|
|
4137
|
-
"page-size": {
|
|
4138
|
-
"description": "Items per page (max 1000); prefer one big page over a pagination loop",
|
|
4139
|
-
"name": "page-size",
|
|
4140
|
-
"default": 100,
|
|
4141
|
-
"hasDynamicHelp": false,
|
|
4142
|
-
"multiple": false,
|
|
4143
|
-
"type": "option"
|
|
4144
|
-
}
|
|
4145
|
-
},
|
|
4146
|
-
"hasDynamicHelp": false,
|
|
4147
|
-
"hiddenAliases": [],
|
|
4148
|
-
"id": "asa:orgs:list",
|
|
4149
|
-
"pluginAlias": "adapty",
|
|
4150
|
-
"pluginName": "adapty",
|
|
4151
|
-
"pluginType": "core",
|
|
4152
|
-
"strict": true,
|
|
4153
|
-
"enableJsonFlag": true,
|
|
4154
|
-
"isESM": true,
|
|
4155
|
-
"relativePath": [
|
|
4156
|
-
"dist",
|
|
4157
|
-
"commands",
|
|
4158
|
-
"asa",
|
|
4159
|
-
"orgs",
|
|
4160
|
-
"list.js"
|
|
4161
|
-
]
|
|
4162
|
-
},
|
|
4163
4250
|
"asa:product-pages:list": {
|
|
4164
4251
|
"aliases": [],
|
|
4165
4252
|
"args": {},
|
|
@@ -4378,6 +4465,55 @@
|
|
|
4378
4465
|
"list.js"
|
|
4379
4466
|
]
|
|
4380
4467
|
},
|
|
4468
|
+
"asa:orgs:list": {
|
|
4469
|
+
"aliases": [],
|
|
4470
|
+
"args": {},
|
|
4471
|
+
"description": "List the Apple Search Ads organizations this company can spend from",
|
|
4472
|
+
"examples": [
|
|
4473
|
+
"<%= config.bin %> asa orgs list"
|
|
4474
|
+
],
|
|
4475
|
+
"flags": {
|
|
4476
|
+
"json": {
|
|
4477
|
+
"description": "Format output as json.",
|
|
4478
|
+
"helpGroup": "GLOBAL",
|
|
4479
|
+
"name": "json",
|
|
4480
|
+
"allowNo": false,
|
|
4481
|
+
"type": "boolean"
|
|
4482
|
+
},
|
|
4483
|
+
"page": {
|
|
4484
|
+
"description": "Page number",
|
|
4485
|
+
"name": "page",
|
|
4486
|
+
"default": 1,
|
|
4487
|
+
"hasDynamicHelp": false,
|
|
4488
|
+
"multiple": false,
|
|
4489
|
+
"type": "option"
|
|
4490
|
+
},
|
|
4491
|
+
"page-size": {
|
|
4492
|
+
"description": "Items per page (max 1000); prefer one big page over a pagination loop",
|
|
4493
|
+
"name": "page-size",
|
|
4494
|
+
"default": 100,
|
|
4495
|
+
"hasDynamicHelp": false,
|
|
4496
|
+
"multiple": false,
|
|
4497
|
+
"type": "option"
|
|
4498
|
+
}
|
|
4499
|
+
},
|
|
4500
|
+
"hasDynamicHelp": false,
|
|
4501
|
+
"hiddenAliases": [],
|
|
4502
|
+
"id": "asa:orgs:list",
|
|
4503
|
+
"pluginAlias": "adapty",
|
|
4504
|
+
"pluginName": "adapty",
|
|
4505
|
+
"pluginType": "core",
|
|
4506
|
+
"strict": true,
|
|
4507
|
+
"enableJsonFlag": true,
|
|
4508
|
+
"isESM": true,
|
|
4509
|
+
"relativePath": [
|
|
4510
|
+
"dist",
|
|
4511
|
+
"commands",
|
|
4512
|
+
"asa",
|
|
4513
|
+
"orgs",
|
|
4514
|
+
"list.js"
|
|
4515
|
+
]
|
|
4516
|
+
},
|
|
4381
4517
|
"flows:config:get": {
|
|
4382
4518
|
"aliases": [],
|
|
4383
4519
|
"args": {
|
|
@@ -4425,6 +4561,75 @@
|
|
|
4425
4561
|
"get.js"
|
|
4426
4562
|
]
|
|
4427
4563
|
},
|
|
4564
|
+
"flows:config:preview": {
|
|
4565
|
+
"aliases": [],
|
|
4566
|
+
"args": {
|
|
4567
|
+
"config_file": {
|
|
4568
|
+
"description": "Path to a local flow config JSON file",
|
|
4569
|
+
"name": "config_file",
|
|
4570
|
+
"required": true
|
|
4571
|
+
}
|
|
4572
|
+
},
|
|
4573
|
+
"description": "Build a render URL for a local flow config and open it. A quick-look escape hatch for small configs: the whole config rides in the URL fragment, and past roughly 32KB of pretty-printed JSON the render page gets slow and unreliable. Opens the browser on a TTY; when piped or with --json, prints the URL alone — and that URL is long (~113K characters for a 668KB flow), so pipe it into whatever takes the screenshot (\"| node capture.mjs\") or pass it with --url and command substitution. Never print or read it: agents burn context for zero information. The render host comes from $ADAPTY_APP_URL.",
|
|
4574
|
+
"examples": [
|
|
4575
|
+
"<%= config.bin %> flows config preview ./config.json",
|
|
4576
|
+
"<%= config.bin %> flows config preview ./config.json --screen welcome --device ipad-pro --orientation landscape",
|
|
4577
|
+
"# pipe the URL straight into a screenshot tool, never print it\n<%= config.bin %> flows config preview ./config.json | node capture.mjs --out shot.png",
|
|
4578
|
+
"# or pass it as an argument, for tools that want a flag\nnode capture.mjs --url \"$(<%= config.bin %> flows config preview ./config.json)\" --out shot.png"
|
|
4579
|
+
],
|
|
4580
|
+
"flags": {
|
|
4581
|
+
"json": {
|
|
4582
|
+
"description": "Format output as json.",
|
|
4583
|
+
"helpGroup": "GLOBAL",
|
|
4584
|
+
"name": "json",
|
|
4585
|
+
"allowNo": false,
|
|
4586
|
+
"type": "boolean"
|
|
4587
|
+
},
|
|
4588
|
+
"device": {
|
|
4589
|
+
"description": "Device frame to render in",
|
|
4590
|
+
"name": "device",
|
|
4591
|
+
"default": "iphone-14",
|
|
4592
|
+
"hasDynamicHelp": false,
|
|
4593
|
+
"multiple": false,
|
|
4594
|
+
"type": "option"
|
|
4595
|
+
},
|
|
4596
|
+
"orientation": {
|
|
4597
|
+
"description": "Device orientation to render in",
|
|
4598
|
+
"name": "orientation",
|
|
4599
|
+
"default": "portrait",
|
|
4600
|
+
"hasDynamicHelp": false,
|
|
4601
|
+
"multiple": false,
|
|
4602
|
+
"options": [
|
|
4603
|
+
"landscape",
|
|
4604
|
+
"portrait"
|
|
4605
|
+
],
|
|
4606
|
+
"type": "option"
|
|
4607
|
+
},
|
|
4608
|
+
"screen": {
|
|
4609
|
+
"description": "Screen ID to render (default: the flow's first screen)",
|
|
4610
|
+
"name": "screen",
|
|
4611
|
+
"hasDynamicHelp": false,
|
|
4612
|
+
"multiple": false,
|
|
4613
|
+
"type": "option"
|
|
4614
|
+
}
|
|
4615
|
+
},
|
|
4616
|
+
"hasDynamicHelp": false,
|
|
4617
|
+
"hiddenAliases": [],
|
|
4618
|
+
"id": "flows:config:preview",
|
|
4619
|
+
"pluginAlias": "adapty",
|
|
4620
|
+
"pluginName": "adapty",
|
|
4621
|
+
"pluginType": "core",
|
|
4622
|
+
"strict": true,
|
|
4623
|
+
"enableJsonFlag": true,
|
|
4624
|
+
"isESM": true,
|
|
4625
|
+
"relativePath": [
|
|
4626
|
+
"dist",
|
|
4627
|
+
"commands",
|
|
4628
|
+
"flows",
|
|
4629
|
+
"config",
|
|
4630
|
+
"preview.js"
|
|
4631
|
+
]
|
|
4632
|
+
},
|
|
4428
4633
|
"flows:config:update": {
|
|
4429
4634
|
"aliases": [],
|
|
4430
4635
|
"args": {
|
|
@@ -4501,57 +4706,7 @@
|
|
|
4501
4706
|
"config",
|
|
4502
4707
|
"update.js"
|
|
4503
4708
|
]
|
|
4504
|
-
},
|
|
4505
|
-
"asa:apps:list": {
|
|
4506
|
-
"aliases": [],
|
|
4507
|
-
"args": {},
|
|
4508
|
-
"description": "List the apps promoted by this company in Apple Search Ads",
|
|
4509
|
-
"examples": [
|
|
4510
|
-
"<%= config.bin %> asa apps list",
|
|
4511
|
-
"<%= config.bin %> asa apps list --page 2 --page-size 50"
|
|
4512
|
-
],
|
|
4513
|
-
"flags": {
|
|
4514
|
-
"json": {
|
|
4515
|
-
"description": "Format output as json.",
|
|
4516
|
-
"helpGroup": "GLOBAL",
|
|
4517
|
-
"name": "json",
|
|
4518
|
-
"allowNo": false,
|
|
4519
|
-
"type": "boolean"
|
|
4520
|
-
},
|
|
4521
|
-
"page": {
|
|
4522
|
-
"description": "Page number",
|
|
4523
|
-
"name": "page",
|
|
4524
|
-
"default": 1,
|
|
4525
|
-
"hasDynamicHelp": false,
|
|
4526
|
-
"multiple": false,
|
|
4527
|
-
"type": "option"
|
|
4528
|
-
},
|
|
4529
|
-
"page-size": {
|
|
4530
|
-
"description": "Items per page (max 1000); prefer one big page over a pagination loop",
|
|
4531
|
-
"name": "page-size",
|
|
4532
|
-
"default": 100,
|
|
4533
|
-
"hasDynamicHelp": false,
|
|
4534
|
-
"multiple": false,
|
|
4535
|
-
"type": "option"
|
|
4536
|
-
}
|
|
4537
|
-
},
|
|
4538
|
-
"hasDynamicHelp": false,
|
|
4539
|
-
"hiddenAliases": [],
|
|
4540
|
-
"id": "asa:apps:list",
|
|
4541
|
-
"pluginAlias": "adapty",
|
|
4542
|
-
"pluginName": "adapty",
|
|
4543
|
-
"pluginType": "core",
|
|
4544
|
-
"strict": true,
|
|
4545
|
-
"enableJsonFlag": true,
|
|
4546
|
-
"isESM": true,
|
|
4547
|
-
"relativePath": [
|
|
4548
|
-
"dist",
|
|
4549
|
-
"commands",
|
|
4550
|
-
"asa",
|
|
4551
|
-
"apps",
|
|
4552
|
-
"list.js"
|
|
4553
|
-
]
|
|
4554
4709
|
}
|
|
4555
4710
|
},
|
|
4556
|
-
"version": "0.
|
|
4711
|
+
"version": "0.7.0"
|
|
4557
4712
|
}
|