adapty 0.8.3 → 0.8.4-beta.1
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 +2 -132
- package/dist/commands/asa/ad-groups/create.js +1 -1
- package/dist/commands/asa/ad-groups/update.js +1 -1
- package/dist/commands/asa/ads/create.js +1 -1
- package/dist/commands/asa/ads/update.js +1 -1
- package/dist/commands/asa/automations/create.d.ts +0 -9
- package/dist/commands/asa/automations/create.js +3 -19
- package/dist/commands/asa/automations/run.js +1 -1
- package/dist/commands/asa/automations/update.d.ts +0 -9
- package/dist/commands/asa/automations/update.js +6 -22
- package/dist/commands/asa/campaigns/bulk-create.js +1 -1
- package/dist/commands/asa/campaigns/create.js +1 -1
- package/dist/commands/asa/campaigns/update.js +1 -1
- package/dist/commands/asa/keywords/add.js +1 -1
- package/dist/commands/asa/keywords/update.js +1 -1
- package/dist/commands/asa/metrics/index.d.ts +1 -4
- package/dist/commands/asa/metrics/index.js +8 -18
- package/dist/commands/asa/negative-keywords/add.js +1 -1
- package/dist/commands/asa/product-pages/sync.js +1 -1
- package/dist/commands/flows/config/get.js +2 -1
- package/dist/commands/flows/publish.d.ts +15 -0
- package/dist/commands/flows/publish.js +52 -0
- package/dist/commands/flows/update.d.ts +15 -0
- package/dist/commands/flows/update.js +28 -0
- package/dist/commands/placements/create.js +29 -4
- package/dist/commands/placements/update.js +29 -4
- package/dist/lib/api-schemas.d.ts +20 -1
- package/dist/lib/asa-flags.d.ts +0 -24
- package/dist/lib/asa-flags.js +0 -54
- package/dist/lib/errors.js +1 -2
- package/dist/lib/flow-help.d.ts +12 -0
- package/dist/lib/flow-help.js +27 -0
- package/dist/lib/placement-audiences.d.ts +6 -0
- package/dist/lib/placement-audiences.js +25 -0
- package/oclif.manifest.json +601 -664
- package/package.json +3 -2
- package/dist/lib/asa-keyword-action.d.ts +0 -18
- package/dist/lib/asa-keyword-action.js +0 -160
- /package/dist/lib/{asa-confirm.d.ts → confirm.d.ts} +0 -0
- /package/dist/lib/{asa-confirm.js → confirm.js} +0 -0
package/README.md
CHANGED
|
@@ -199,142 +199,12 @@ adapty asa product-pages sync [--adam-id 123456]
|
|
|
199
199
|
|
|
200
200
|
adapty asa automations list
|
|
201
201
|
adapty asa automations get AUTOMATION_ID
|
|
202
|
-
adapty asa automations create --file rule.json [--run-now]
|
|
203
|
-
adapty asa automations update AUTOMATION_ID [--stop] [--start] [--name "..."] [--file rule.json]
|
|
202
|
+
adapty asa automations create --file rule.json [--run-now]
|
|
203
|
+
adapty asa automations update AUTOMATION_ID [--stop] [--start] [--name "..."] [--file rule.json]
|
|
204
204
|
adapty asa automations run AUTOMATION_ID [--dry-run]
|
|
205
205
|
adapty asa automations runs AUTOMATION_ID
|
|
206
206
|
```
|
|
207
207
|
|
|
208
|
-
A rule file carries the whole rule: `name`, `status` (1 active, 0 stopped), `operate_with` (what the
|
|
209
|
-
rule iterates over), `apply_to` (where it looks), exactly one condition, exactly one action and a
|
|
210
|
-
`run_frequency`. The API stores one action and one condition per rule and rejects anything else.
|
|
211
|
-
|
|
212
|
-
| Field | Shape |
|
|
213
|
-
| --------------- | ------------------------------------------------------------------------------------------- |
|
|
214
|
-
| `operate_with` | `search-term`, `targeting-keyword`, `campaign`, `ad-group` |
|
|
215
|
-
| `apply_to[]` | `{"internal_id": UUID, "type": "campaign-group" \| "app" \| "campaign" \| "ad-group" \| "targeting-keywords"}` |
|
|
216
|
-
| `conditions[0]` | `{"operator": ..., "args": number, "operand": {...}}`, or `{"operator": "and" \| "or", "args": [condition, ...]}` |
|
|
217
|
-
| `operator` | `eq`, `neq`, `gt`, `gte`, `lt`, `lte` for a leaf; `and`, `or` to nest |
|
|
218
|
-
| `operand.field` | a metric name in dashboard nomenclature — the same vocabulary `asa metrics --metric` takes |
|
|
219
|
-
| `date_range_type` | `today`, `yesterday`, `last_1_d`, `last_3_d`, `last_7_d`, `last_14_d`, `last_28_d`, `last_30_d`, `last_60_d`, `last_90_d`, `custom` |
|
|
220
|
-
| `run_frequency` | `{"type": "daily", "hour": 8}`, `{"type": "hour", "value": 24, "start_time": 8}`, `{"type": "weekly", "weekdays": ["monday"], "hour": 8}`, `{"type": "monthly", "days": [1], "hour": 8}`, `{"type": "once", "date_time": "2026-10-01T09:00:00Z"}` — `hour` and `start_time` are UTC |
|
|
221
|
-
|
|
222
|
-
The `add-as-keyword-to` action promotes what the rule found into a keyword in one or more target ad
|
|
223
|
-
groups. Its `params` differ by `operate_with`, and the API picks the variant by shape without a
|
|
224
|
-
discriminator: a key that belongs to another variant makes it silently choose that variant and drop
|
|
225
|
-
the rest, which is how a rule ends up as "Add as keyword to 0 ad groups". `negate` and
|
|
226
|
-
`skip_enable_duplicate_keywords` exist only on a `search-term` rule, `pause_in_original_ad_group`
|
|
227
|
-
only on a `targeting-keyword` one, and `targets` holds `internal_ids` — never `ids`.
|
|
228
|
-
|
|
229
|
-
A full `search-term` rule — every term with 10+ taps over the last week becomes an exact keyword in
|
|
230
|
-
the target ad group at the term's own CPT, and is negated in the ad group it came from:
|
|
231
|
-
|
|
232
|
-
```json
|
|
233
|
-
{
|
|
234
|
-
"name": "Search term harvester",
|
|
235
|
-
"status": 1,
|
|
236
|
-
"operate_with": "search-term",
|
|
237
|
-
"apply_to": [{"internal_id": "CAMPAIGN_UUID", "type": "campaign"}],
|
|
238
|
-
"conditions": [
|
|
239
|
-
{
|
|
240
|
-
"operator": "gte",
|
|
241
|
-
"args": 10,
|
|
242
|
-
"operand": {
|
|
243
|
-
"field": "taps",
|
|
244
|
-
"field_type": "base_field",
|
|
245
|
-
"date_range_type": "last_7_d",
|
|
246
|
-
"date_range_size": 0,
|
|
247
|
-
"date_range_offset": 0,
|
|
248
|
-
"by_days": null
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
],
|
|
252
|
-
"actions": [
|
|
253
|
-
{
|
|
254
|
-
"type": "add-as-keyword-to",
|
|
255
|
-
"params": {
|
|
256
|
-
"targets": {"type": "ad-group", "internal_ids": ["AD_GROUP_UUID"]},
|
|
257
|
-
"cpt_bid": {"type": "search_term_current_cpt", "value": null},
|
|
258
|
-
"match_type": "EXACT",
|
|
259
|
-
"negate": {"enabled": true, "type": "ad-group"},
|
|
260
|
-
"skip_enable_duplicate_keywords": false
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
],
|
|
264
|
-
"run_frequency": {"type": "daily", "hour": 8}
|
|
265
|
-
}
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
The same action on a `targeting-keyword` rule — a broad keyword that has earned installs graduates
|
|
269
|
-
into the exact ad group at its current bid and is paused where it was:
|
|
270
|
-
|
|
271
|
-
```json
|
|
272
|
-
{
|
|
273
|
-
"name": "Graduate broad keywords to exact",
|
|
274
|
-
"status": 1,
|
|
275
|
-
"operate_with": "targeting-keyword",
|
|
276
|
-
"apply_to": [{"internal_id": "SOURCE_AD_GROUP_UUID", "type": "ad-group"}],
|
|
277
|
-
"conditions": [
|
|
278
|
-
{
|
|
279
|
-
"operator": "gte",
|
|
280
|
-
"args": 3,
|
|
281
|
-
"operand": {
|
|
282
|
-
"field": "total_installs",
|
|
283
|
-
"field_type": "base_field",
|
|
284
|
-
"date_range_type": "last_14_d",
|
|
285
|
-
"date_range_size": 0,
|
|
286
|
-
"date_range_offset": 0,
|
|
287
|
-
"by_days": null
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
],
|
|
291
|
-
"actions": [
|
|
292
|
-
{
|
|
293
|
-
"type": "add-as-keyword-to",
|
|
294
|
-
"params": {
|
|
295
|
-
"targets": {"type": "ad-group", "internal_ids": ["EXACT_AD_GROUP_UUID"]},
|
|
296
|
-
"cpt_bid": {"type": "keyword_current_bid", "value": null},
|
|
297
|
-
"match_type": "EXACT",
|
|
298
|
-
"pause_in_original_ad_group": true
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
],
|
|
302
|
-
"run_frequency": {"type": "daily", "hour": 8}
|
|
303
|
-
}
|
|
304
|
-
```
|
|
305
|
-
|
|
306
|
-
Rather than hand-writing that `params` block, pass the action flags — they fill in or override
|
|
307
|
-
`actions[0].params` in the file, and the CLI refuses a rule the API would have quietly accepted and
|
|
308
|
-
broken:
|
|
309
|
-
|
|
310
|
-
```sh
|
|
311
|
-
adapty asa automations create --file rule.json --target-ad-group AD_GROUP_UUID \
|
|
312
|
-
--match-type EXACT --cpt-bid-type search_term_current_cpt --negate ad-group
|
|
313
|
-
adapty asa automations create --file rule.json --target-ad-group AD_GROUP_UUID \
|
|
314
|
-
--match-type BROAD --cpt-bid-type set_to --cpt-bid 1.50 --no-negate --skip-enable-duplicates
|
|
315
|
-
adapty asa automations update AUTOMATION_ID --target-ad-group AD_GROUP_UUID \
|
|
316
|
-
--match-type EXACT --cpt-bid-type search_term_current_cpt
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
| Flag | Where it lands |
|
|
320
|
-
| -------------------------- | --------------------------------------------------------------------- |
|
|
321
|
-
| `--target-ad-group` | `targets.internal_ids`, repeatable; a rule without one does nothing |
|
|
322
|
-
| `--match-type` | `match_type`: `BROAD` or `EXACT` |
|
|
323
|
-
| `--cpt-bid-type` | `cpt_bid.type`: `ad_group_default_bid`, `set_to`, `search_term_current_cpt`, `keyword_current_bid` |
|
|
324
|
-
| `--cpt-bid` | `cpt_bid.value`: the bid itself with `set_to` (required), a percent markup on the entity's own bid with `search_term_current_cpt` / `keyword_current_bid`, rejected with `ad_group_default_bid` |
|
|
325
|
-
| `--negate` / `--no-negate` | `negate` (search-term rules): `ad-group` or `campaign`, or off |
|
|
326
|
-
| `--skip-enable-duplicates` | `skip_enable_duplicate_keywords` (search-term rules) |
|
|
327
|
-
| `--pause-original` | `pause_in_original_ad_group` (targeting-keyword rules) |
|
|
328
|
-
|
|
329
|
-
`--cpt-bid-type` and `--match-type` have no defaults, here or in the API: a bid and a match type are
|
|
330
|
-
a spend decision and a reach decision, so when `params` are built from scratch the CLI asks for them
|
|
331
|
-
instead of guessing. On `update`, an action flag turns the call into a read-modify-write — the rule
|
|
332
|
-
is read, `actions[0].params` is rebuilt and the whole `actions` list is written back, since the API
|
|
333
|
-
replaces it wholesale. That also repairs a rule whose stored `params` carry the wrong shape: only
|
|
334
|
-
the keys that fit are kept, the strays are dropped, and anything missing has to come from a flag. A
|
|
335
|
-
dashboard edit made between the read and the write is overwritten.
|
|
336
|
-
|
|
337
|
-
|
|
338
208
|
Metrics take an entity level, a period and an optional metric selection. Rows come back one per entity,
|
|
339
209
|
aggregated and sorted server-side, so a top-N or a breakdown is a single call — use `--order-by` with a small
|
|
340
210
|
`--page-size` for rankings, `metrics overview` for account totals and time series, and one big page (up to
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Command, Flags } from '@oclif/core';
|
|
2
2
|
import { asaWrite, createAsaClient, noteReplay } from '../../../lib/asa-client.js';
|
|
3
|
-
import { confirmFlags, confirmMutation } from '../../../lib/asa-confirm.js';
|
|
4
3
|
import { currencyFlag, idempotencyFlags, money, moneyFlag, pricingModelFlag, scheduleFlags, startOfDayUtc, todayUtc, } from '../../../lib/asa-flags.js';
|
|
4
|
+
import { confirmFlags, confirmMutation } from '../../../lib/confirm.js';
|
|
5
5
|
import { isValidUuid } from '../../../lib/flags.js';
|
|
6
6
|
import { printResponse } from '../../../lib/output.js';
|
|
7
7
|
export default class AsaAdGroupsCreate extends Command {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Args, Command, Flags } from '@oclif/core';
|
|
2
2
|
import { asaWrite, createAsaClient, noteReplay } from '../../../lib/asa-client.js';
|
|
3
|
-
import { confirmFlags, confirmMutation } from '../../../lib/asa-confirm.js';
|
|
4
3
|
import { currencyFlag, idempotencyFlags, money, moneyFlag, scheduleFlags, startOfDayUtc } from '../../../lib/asa-flags.js';
|
|
4
|
+
import { confirmFlags, confirmMutation } from '../../../lib/confirm.js';
|
|
5
5
|
import { isValidUuid } from '../../../lib/flags.js';
|
|
6
6
|
import { printResponse } from '../../../lib/output.js';
|
|
7
7
|
export default class AsaAdGroupsUpdate extends Command {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Command, Flags } from '@oclif/core';
|
|
2
2
|
import { asaWrite, createAsaClient, noteReplay } from '../../../lib/asa-client.js';
|
|
3
|
-
import { confirmFlags, confirmMutation } from '../../../lib/asa-confirm.js';
|
|
4
3
|
import { idempotencyFlags } from '../../../lib/asa-flags.js';
|
|
4
|
+
import { confirmFlags, confirmMutation } from '../../../lib/confirm.js';
|
|
5
5
|
import { isValidUuid } from '../../../lib/flags.js';
|
|
6
6
|
import { printResponse } from '../../../lib/output.js';
|
|
7
7
|
export default class AsaAdsCreate extends Command {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Args, Command, Flags } from '@oclif/core';
|
|
2
2
|
import { asaWrite, createAsaClient, noteReplay } from '../../../lib/asa-client.js';
|
|
3
|
-
import { confirmFlags, confirmMutation } from '../../../lib/asa-confirm.js';
|
|
4
3
|
import { idempotencyFlags } from '../../../lib/asa-flags.js';
|
|
4
|
+
import { confirmFlags, confirmMutation } from '../../../lib/confirm.js';
|
|
5
5
|
import { isValidUuid } from '../../../lib/flags.js';
|
|
6
6
|
import { printResponse } from '../../../lib/output.js';
|
|
7
7
|
export default class AsaAdsUpdate extends Command {
|
|
@@ -9,17 +9,8 @@ export default class AsaAutomationsCreate extends Command {
|
|
|
9
9
|
'run-now': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
10
|
'idempotency-key': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
11
|
yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
-
'cpt-bid': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
-
'cpt-bid-type': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
-
'match-type': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
-
negate: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
-
'no-negate': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
17
|
-
'pause-original': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
18
|
-
'skip-enable-duplicates': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
19
|
-
'target-ad-group': import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
20
12
|
};
|
|
21
13
|
run(): Promise<AsaAutomationMutationDTO>;
|
|
22
|
-
private applyActionFlags;
|
|
23
14
|
private readRule;
|
|
24
15
|
private readStdin;
|
|
25
16
|
}
|
|
@@ -1,21 +1,17 @@
|
|
|
1
1
|
import { Command, Flags } from '@oclif/core';
|
|
2
2
|
import { readFile } from 'node:fs/promises';
|
|
3
3
|
import { asaWrite, createAsaClient, noteReplay } from '../../../lib/asa-client.js';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { hasAddKeywordActionFlags, rebuildAddKeywordAction, requireSingleAction, } from '../../../lib/asa-keyword-action.js';
|
|
4
|
+
import { idempotencyFlags } from '../../../lib/asa-flags.js';
|
|
5
|
+
import { confirmFlags, confirmMutation } from '../../../lib/confirm.js';
|
|
7
6
|
import { printResponse } from '../../../lib/output.js';
|
|
8
7
|
export default class AsaAutomationsCreate extends Command {
|
|
9
|
-
static description = 'Create an automation rule from a JSON rule file
|
|
8
|
+
static description = 'Create an automation rule from a JSON rule file';
|
|
10
9
|
static enableJsonFlag = true;
|
|
11
10
|
static examples = [
|
|
12
11
|
'<%= config.bin %> asa automations create --file rule.json',
|
|
13
12
|
'<%= config.bin %> asa automations create --file rule.json --run-now',
|
|
14
|
-
'<%= config.bin %> asa automations create --file rule.json --target-ad-group AD_GROUP_ID --match-type EXACT --cpt-bid-type search_term_current_cpt',
|
|
15
|
-
'<%= config.bin %> asa automations create --file rule.json --target-ad-group AD_GROUP_ID --match-type EXACT --cpt-bid-type set_to --cpt-bid 1.50 --negate ad-group',
|
|
16
13
|
];
|
|
17
14
|
static flags = {
|
|
18
|
-
...addKeywordActionFlags,
|
|
19
15
|
...confirmFlags,
|
|
20
16
|
...idempotencyFlags,
|
|
21
17
|
file: Flags.string({ description: 'JSON file with the rule body, or - to read stdin', required: true }),
|
|
@@ -26,7 +22,6 @@ export default class AsaAutomationsCreate extends Command {
|
|
|
26
22
|
const body = await this.readRule(flags.file);
|
|
27
23
|
if (flags['run-now'])
|
|
28
24
|
body.run_immediately = true;
|
|
29
|
-
this.applyActionFlags(body, flags);
|
|
30
25
|
const summary = flags['run-now'] ? 'Create automation rule and run it immediately' : 'Create automation rule';
|
|
31
26
|
await confirmMutation(this, { body, method: 'POST', path: '/automations/', summary }, flags.yes);
|
|
32
27
|
const client = await createAsaClient(this.config);
|
|
@@ -41,17 +36,6 @@ export default class AsaAutomationsCreate extends Command {
|
|
|
41
36
|
printResponse(result, this.log.bind(this));
|
|
42
37
|
return result;
|
|
43
38
|
}
|
|
44
|
-
applyActionFlags(body, flags) {
|
|
45
|
-
try {
|
|
46
|
-
requireSingleAction(body.actions);
|
|
47
|
-
if (!hasAddKeywordActionFlags(flags))
|
|
48
|
-
return;
|
|
49
|
-
body.actions = rebuildAddKeywordAction(body.actions, body.operate_with, flags);
|
|
50
|
-
}
|
|
51
|
-
catch (error) {
|
|
52
|
-
this.error(error instanceof Error ? error.message : String(error), { exit: 2 });
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
39
|
async readRule(path) {
|
|
56
40
|
let raw;
|
|
57
41
|
try {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Args, Command, Flags } from '@oclif/core';
|
|
2
2
|
import { asaWrite, createAsaClient, noteReplay } from '../../../lib/asa-client.js';
|
|
3
|
-
import { confirmFlags, confirmMutation } from '../../../lib/asa-confirm.js';
|
|
4
3
|
import { idempotencyFlags } from '../../../lib/asa-flags.js';
|
|
4
|
+
import { confirmFlags, confirmMutation } from '../../../lib/confirm.js';
|
|
5
5
|
import { isValidUuid } from '../../../lib/flags.js';
|
|
6
6
|
export default class AsaAutomationsRun extends Command {
|
|
7
7
|
static args = {
|
|
@@ -14,17 +14,8 @@ export default class AsaAutomationsUpdate extends Command {
|
|
|
14
14
|
stop: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
15
|
'idempotency-key': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
16
|
yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
17
|
-
'cpt-bid': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
|
-
'cpt-bid-type': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
19
|
-
'match-type': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
20
|
-
negate: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
21
|
-
'no-negate': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
22
|
-
'pause-original': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
23
|
-
'skip-enable-duplicates': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
24
|
-
'target-ad-group': import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
25
17
|
};
|
|
26
18
|
run(): Promise<AsaAutomationMutationDTO>;
|
|
27
19
|
private readRule;
|
|
28
20
|
private readStdin;
|
|
29
|
-
private rebuildAction;
|
|
30
21
|
}
|
|
@@ -1,24 +1,21 @@
|
|
|
1
1
|
import { Args, Command, Flags } from '@oclif/core';
|
|
2
2
|
import { readFile } from 'node:fs/promises';
|
|
3
3
|
import { asaWrite, createAsaClient, noteReplay } from '../../../lib/asa-client.js';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { hasAddKeywordActionFlags, rebuildAddKeywordAction, } from '../../../lib/asa-keyword-action.js';
|
|
4
|
+
import { idempotencyFlags } from '../../../lib/asa-flags.js';
|
|
5
|
+
import { confirmFlags, confirmMutation } from '../../../lib/confirm.js';
|
|
7
6
|
import { isValidUuid } from '../../../lib/flags.js';
|
|
8
7
|
import { printResponse } from '../../../lib/output.js';
|
|
9
8
|
export default class AsaAutomationsUpdate extends Command {
|
|
10
9
|
static args = {
|
|
11
10
|
automation_id: Args.string({ description: 'Automation rule ID (UUID)', required: true }),
|
|
12
11
|
};
|
|
13
|
-
static description = 'Change an automation rule: stop it, rename it, or replace parts of the rule
|
|
12
|
+
static description = 'Change an automation rule: stop it, rename it, or replace parts of the rule';
|
|
14
13
|
static enableJsonFlag = true;
|
|
15
14
|
static examples = [
|
|
16
15
|
'<%= config.bin %> asa automations update UUID --stop',
|
|
17
16
|
'<%= config.bin %> asa automations update UUID --file rule.json',
|
|
18
|
-
'<%= config.bin %> asa automations update UUID --target-ad-group AD_GROUP_ID --match-type EXACT --cpt-bid-type search_term_current_cpt',
|
|
19
17
|
];
|
|
20
18
|
static flags = {
|
|
21
|
-
...addKeywordActionFlags,
|
|
22
19
|
...confirmFlags,
|
|
23
20
|
...idempotencyFlags,
|
|
24
21
|
file: Flags.string({ description: 'JSON file with the parts to change, or - to read stdin' }),
|
|
@@ -37,17 +34,14 @@ export default class AsaAutomationsUpdate extends Command {
|
|
|
37
34
|
body.status = 1;
|
|
38
35
|
if (flags.stop)
|
|
39
36
|
body.status = 0;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
this.error('Nothing to change. Pass --stop, --start, --name, --file or an action flag.', { exit: 2 });
|
|
37
|
+
if (Object.keys(body).length === 0) {
|
|
38
|
+
this.error('Nothing to change. Pass --stop, --start, --name or --file.', { exit: 2 });
|
|
43
39
|
}
|
|
44
40
|
if ('internal_id' in body) {
|
|
45
41
|
this.error('Remove internal_id from the file: the rule ID comes from the command line.', { exit: 2 });
|
|
46
42
|
}
|
|
47
|
-
const client = await createAsaClient(this.config);
|
|
48
|
-
if (actionFlags)
|
|
49
|
-
await this.rebuildAction(client, args.automation_id, body, flags);
|
|
50
43
|
await confirmMutation(this, { body, method: 'PUT', path: `/automations/${args.automation_id}/`, summary: 'Update automation rule' }, flags.yes);
|
|
44
|
+
const client = await createAsaClient(this.config);
|
|
51
45
|
const { replayed, result } = await asaWrite(client, 'put', `/automations/${args.automation_id}`, { body, idempotencyKey: flags['idempotency-key'] });
|
|
52
46
|
noteReplay(replayed, this.log.bind(this));
|
|
53
47
|
if (result.automation && !replayed)
|
|
@@ -76,14 +70,4 @@ export default class AsaAutomationsUpdate extends Command {
|
|
|
76
70
|
chunks.push(chunk);
|
|
77
71
|
return Buffer.concat(chunks).toString('utf8');
|
|
78
72
|
}
|
|
79
|
-
// Read-modify-write: the API replaces `actions` wholesale, so the whole list has to be sent back.
|
|
80
|
-
async rebuildAction(client, automationId, body, flags) {
|
|
81
|
-
const rule = await client.get(`/automations/${automationId}`);
|
|
82
|
-
try {
|
|
83
|
-
body.actions = rebuildAddKeywordAction(body.actions ?? rule.actions, body.operate_with ?? rule.operate_with, flags);
|
|
84
|
-
}
|
|
85
|
-
catch (error) {
|
|
86
|
-
this.error(error instanceof Error ? error.message : String(error), { exit: 2 });
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
73
|
}
|
|
@@ -2,8 +2,8 @@ import { Command, Flags } from '@oclif/core';
|
|
|
2
2
|
import { readFile } from 'node:fs/promises';
|
|
3
3
|
import { basename } from 'node:path';
|
|
4
4
|
import { asaWrite, createAsaClient, noteReplay } from '../../../lib/asa-client.js';
|
|
5
|
-
import { confirmFlags, confirmMutation } from '../../../lib/asa-confirm.js';
|
|
6
5
|
import { idempotencyFlags } from '../../../lib/asa-flags.js';
|
|
6
|
+
import { confirmFlags, confirmMutation } from '../../../lib/confirm.js';
|
|
7
7
|
import { printResponse } from '../../../lib/output.js';
|
|
8
8
|
const TERMINAL_STATUSES = new Set(['failed', 'partial', 'success']);
|
|
9
9
|
export default class AsaCampaignsBulkCreate extends Command {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Command, Flags } from '@oclif/core';
|
|
2
2
|
import { asaWrite, createAsaClient, noteReplay } from '../../../lib/asa-client.js';
|
|
3
|
-
import { confirmFlags, confirmMutation } from '../../../lib/asa-confirm.js';
|
|
4
3
|
import { currencyFlag, idempotencyFlags, invoiceFlags, locInvoiceDetails, money, moneyFlag, reportServingState, } from '../../../lib/asa-flags.js';
|
|
4
|
+
import { confirmFlags, confirmMutation } from '../../../lib/confirm.js';
|
|
5
5
|
import { isValidUuid } from '../../../lib/flags.js';
|
|
6
6
|
import { printResponse } from '../../../lib/output.js';
|
|
7
7
|
export default class AsaCampaignsCreate extends Command {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Args, Command, Flags } from '@oclif/core';
|
|
2
2
|
import { asaWrite, createAsaClient, noteReplay } from '../../../lib/asa-client.js';
|
|
3
|
-
import { confirmFlags, confirmMutation } from '../../../lib/asa-confirm.js';
|
|
4
3
|
import { currencyFlag, idempotencyFlags, invoiceFlags, locInvoiceDetails, money, moneyFlag, reportServingState, } from '../../../lib/asa-flags.js';
|
|
4
|
+
import { confirmFlags, confirmMutation } from '../../../lib/confirm.js';
|
|
5
5
|
import { isValidUuid } from '../../../lib/flags.js';
|
|
6
6
|
import { printResponse } from '../../../lib/output.js';
|
|
7
7
|
export default class AsaCampaignsUpdate extends Command {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Command, Flags } from '@oclif/core';
|
|
2
2
|
import { readFile } from 'node:fs/promises';
|
|
3
3
|
import { asaWrite, createAsaClient, noteReplay } from '../../../lib/asa-client.js';
|
|
4
|
-
import { confirmFlags, confirmMutation } from '../../../lib/asa-confirm.js';
|
|
5
4
|
import { currencyFlag, idempotencyFlags, MAX_BULK_ITEMS, money, moneyFlag, reportBulkOutcome } from '../../../lib/asa-flags.js';
|
|
5
|
+
import { confirmFlags, confirmMutation } from '../../../lib/confirm.js';
|
|
6
6
|
import { isValidUuid } from '../../../lib/flags.js';
|
|
7
7
|
export default class AsaKeywordsAdd extends Command {
|
|
8
8
|
static description = 'Add targeting keywords to an ad group';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Args, Command, Flags } from '@oclif/core';
|
|
2
2
|
import { asaWrite, createAsaClient, noteReplay } from '../../../lib/asa-client.js';
|
|
3
|
-
import { confirmFlags, confirmMutation } from '../../../lib/asa-confirm.js';
|
|
4
3
|
import { currencyFlag, idempotencyFlags, money, moneyFlag, reportBulkOutcome } from '../../../lib/asa-flags.js';
|
|
4
|
+
import { confirmFlags, confirmMutation } from '../../../lib/confirm.js';
|
|
5
5
|
import { isValidUuid } from '../../../lib/flags.js';
|
|
6
6
|
export default class AsaKeywordsUpdate extends Command {
|
|
7
7
|
static args = {
|
|
@@ -9,13 +9,10 @@ export default class AsaMetrics extends Command {
|
|
|
9
9
|
'date-to': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
10
|
entity: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
11
|
'group-by': import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
-
metric: import("@oclif/core/interfaces").OptionFlag<string[], import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
metric: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
13
|
order: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
14
|
'order-by': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
15
|
'order-by-day': import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
-
'ad-group': import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
|
-
app: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
|
-
campaign: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
19
16
|
'by-days': import("@oclif/core/interfaces").OptionFlag<number[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
20
17
|
page: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
21
18
|
'page-size': import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Command, Flags } from '@oclif/core';
|
|
2
2
|
import { asaWrite, createAsaClient } from '../../../lib/asa-client.js';
|
|
3
|
-
import { ASA_GROUP_BY_DIMENSIONS, ASA_METRIC_ENTITIES, asaPaginationFlags, byDaysFlag, MAX_BY_DAYS
|
|
3
|
+
import { ASA_GROUP_BY_DIMENSIONS, ASA_METRIC_ENTITIES, asaPaginationFlags, byDaysFlag, MAX_BY_DAYS } from '../../../lib/asa-flags.js';
|
|
4
4
|
import { paginationParams } from '../../../lib/flags.js';
|
|
5
5
|
import { printList } from '../../../lib/output.js';
|
|
6
6
|
export default class AsaMetrics extends Command {
|
|
@@ -10,29 +10,21 @@ One row per entity, already aggregated server-side and sorted by --order-by, so
|
|
|
10
10
|
call with --order-by and --page-size N — never sum pages yourself. Account-level totals are one call to
|
|
11
11
|
asa metrics overview instead. The date window is capped by the finest --group-by period: 28 days when
|
|
12
12
|
day is grouped, 90 with no period grouping, 180 by week, 365 by month and coarser — widen the window by
|
|
13
|
-
coarsening the grouping, not by splitting into more calls. Each page is also capped at
|
|
13
|
+
coarsening the grouping, not by splitting into more calls. Each page is also capped at 20000 breakdown
|
|
14
14
|
rows (entities × countries × periods); over it the call fails with 422 cli_response_too_large — coarsen
|
|
15
15
|
the grouping, narrow the window, or reduce page[size]. Budget: 5 metrics calls per minute, at most
|
|
16
|
-
2 per 10 seconds, one at a time
|
|
17
|
-
|
|
18
|
-
--metric is required and every metric named is computed over the whole entity set, so ask for the
|
|
19
|
-
columns you actually read. subscribers and paid_subscribers (and arppu / arpas, which derive from them)
|
|
20
|
-
count unique profiles per entity and cost roughly seventeen times the rest; whatever the --entity, they
|
|
21
|
-
are refused unless --campaign or --ad-group scopes the call. Those scope flags are also the cheapest way
|
|
22
|
-
to make any call fast, since cost follows the number of entities aggregated, not the page size.`;
|
|
16
|
+
2 per 10 seconds, one at a time.`;
|
|
23
17
|
static enableJsonFlag = true;
|
|
24
18
|
static examples = [
|
|
25
|
-
'<%= config.bin %> asa metrics --entity campaign --date-from 2026-07-01 --date-to 2026-07-31
|
|
26
|
-
'<%= config.bin %> asa metrics --entity campaign --date-from 2026-07-01 --date-to 2026-07-31 --
|
|
27
|
-
'<%= config.bin %> asa metrics --entity campaign --date-from 2026-07-01 --date-to 2026-07-31 --
|
|
19
|
+
'<%= config.bin %> asa metrics --entity campaign --date-from 2026-07-01 --date-to 2026-07-31',
|
|
20
|
+
'<%= config.bin %> asa metrics --entity campaign --date-from 2026-07-01 --date-to 2026-07-31 --order-by spend --page-size 5',
|
|
21
|
+
'<%= config.bin %> asa metrics --entity campaign --date-from 2026-07-01 --date-to 2026-07-31 --group-by country --page-size 1000',
|
|
28
22
|
'<%= config.bin %> asa metrics --entity keyword --date-from 2026-07-01 --date-to 2026-07-31 --metric spend --metric roas',
|
|
29
23
|
'<%= config.bin %> asa metrics --entity campaign --date-from 2026-07-01 --date-to 2026-07-31 --metric roas --by-days 7 --by-days 90',
|
|
30
|
-
'<%= config.bin %> asa metrics --entity keyword --date-from 2026-07-01 --date-to 2026-07-31 --metric arpas --campaign 0f0e...',
|
|
31
24
|
];
|
|
32
25
|
static flags = {
|
|
33
26
|
...asaPaginationFlags,
|
|
34
27
|
...byDaysFlag,
|
|
35
|
-
...metricsScopeFlags,
|
|
36
28
|
'date-from': Flags.string({ description: 'Start of the period (YYYY-MM-DD)', required: true }),
|
|
37
29
|
'date-to': Flags.string({ description: 'End of the period (YYYY-MM-DD)', required: true }),
|
|
38
30
|
entity: Flags.string({ description: 'What to report on', options: ASA_METRIC_ENTITIES, required: true }),
|
|
@@ -42,9 +34,8 @@ to make any call fast, since cost follows the number of entities aggregated, not
|
|
|
42
34
|
options: ASA_GROUP_BY_DIMENSIONS,
|
|
43
35
|
}),
|
|
44
36
|
metric: Flags.string({
|
|
45
|
-
description: 'Metric name (dashboard nomenclature, e.g. spend, taps, gross_roas), repeatable
|
|
37
|
+
description: 'Metric name (dashboard nomenclature, e.g. spend, taps, gross_roas), repeatable; omit for every metric; a wrong name fails listing all valid ones',
|
|
46
38
|
multiple: true,
|
|
47
|
-
required: true,
|
|
48
39
|
}),
|
|
49
40
|
order: Flags.string({ default: 'desc', description: 'Sort direction', options: ['asc', 'desc'] }),
|
|
50
41
|
'order-by': Flags.string({
|
|
@@ -65,9 +56,8 @@ to make any call fast, since cost follows the number of entities aggregated, not
|
|
|
65
56
|
date_from: flags['date-from'],
|
|
66
57
|
date_to: flags['date-to'],
|
|
67
58
|
entity: flags.entity,
|
|
68
|
-
metrics: flags.metric,
|
|
69
59
|
order: flags.order,
|
|
70
|
-
...
|
|
60
|
+
...(flags.metric === undefined ? {} : { metrics: flags.metric }),
|
|
71
61
|
...(flags['by-days'] === undefined ? {} : { by_days: flags['by-days'] }),
|
|
72
62
|
...(flags['group-by'] === undefined ? {} : { group_by: flags['group-by'] }),
|
|
73
63
|
...(flags['order-by'] === undefined ? {} : { order_by: flags['order-by'] }),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Command, Flags } from '@oclif/core';
|
|
2
2
|
import { asaWrite, createAsaClient, noteReplay } from '../../../lib/asa-client.js';
|
|
3
|
-
import { confirmFlags, confirmMutation } from '../../../lib/asa-confirm.js';
|
|
4
3
|
import { idempotencyFlags, MAX_BULK_ITEMS, reportBulkOutcome } from '../../../lib/asa-flags.js';
|
|
4
|
+
import { confirmFlags, confirmMutation } from '../../../lib/confirm.js';
|
|
5
5
|
import { isValidUuid } from '../../../lib/flags.js';
|
|
6
6
|
export default class AsaNegativeKeywordsAdd extends Command {
|
|
7
7
|
static description = 'Add negative keywords to an ad group or across a campaign';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Command, Flags } from '@oclif/core';
|
|
2
2
|
import { asaWrite, createAsaClient } from '../../../lib/asa-client.js';
|
|
3
|
-
import { confirmFlags, confirmMutation } from '../../../lib/asa-confirm.js';
|
|
4
3
|
import { idempotencyFlags } from '../../../lib/asa-flags.js';
|
|
4
|
+
import { confirmFlags, confirmMutation } from '../../../lib/confirm.js';
|
|
5
5
|
import { printResponse } from '../../../lib/output.js';
|
|
6
6
|
export default class AsaProductPagesSync extends Command {
|
|
7
7
|
static description = 'Refresh custom product pages from Apple';
|
|
@@ -6,7 +6,8 @@ export default class FlowsConfigGet extends Command {
|
|
|
6
6
|
static args = {
|
|
7
7
|
flow_id: Args.string({ description: 'Flow ID (UUID)', required: true }),
|
|
8
8
|
};
|
|
9
|
-
static description = 'Read the flow builder config (404 until the config has been written at least once)'
|
|
9
|
+
static description = 'Read the flow builder config (404 until the config has been written at least once). ' +
|
|
10
|
+
'On a failed publish, `publication_status`, `transform_error` and `publication_error` show why.';
|
|
10
11
|
static enableJsonFlag = true;
|
|
11
12
|
static examples = ['<%= config.bin %> flows config get --app UUID 550e8400-e29b-41d4-a716-446655440000'];
|
|
12
13
|
static flags = {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import type { FlowDTO } from '../../lib/api-schemas.js';
|
|
3
|
+
export default class FlowsPublish extends Command {
|
|
4
|
+
static args: {
|
|
5
|
+
flow_id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
|
+
};
|
|
7
|
+
static description: string;
|
|
8
|
+
static enableJsonFlag: boolean;
|
|
9
|
+
static examples: string[];
|
|
10
|
+
static flags: {
|
|
11
|
+
yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
app: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
};
|
|
14
|
+
run(): Promise<FlowDTO>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Args, Command } from '@oclif/core';
|
|
2
|
+
import { createAuthenticatedClient } from '../../lib/client-from-config.js';
|
|
3
|
+
import { confirmFlags, confirmMutation } from '../../lib/confirm.js';
|
|
4
|
+
import { ApiError } from '../../lib/errors.js';
|
|
5
|
+
import { appFlag, isValidUuid } from '../../lib/flags.js';
|
|
6
|
+
import { flowFixLinks } from '../../lib/flow-help.js';
|
|
7
|
+
import { printResponse } from '../../lib/output.js';
|
|
8
|
+
export default class FlowsPublish extends Command {
|
|
9
|
+
static args = {
|
|
10
|
+
flow_id: Args.string({ description: 'Flow ID (UUID)', required: true }),
|
|
11
|
+
};
|
|
12
|
+
static description = 'Publish a flow (async — publication completes in the background). ' +
|
|
13
|
+
'Publishing is async: returns status `publishing`. Poll `adapty flows get <flow_id>` for `published`/`publication_failed`; on failure, `adapty flows config get <flow_id>` shows why.';
|
|
14
|
+
static enableJsonFlag = true;
|
|
15
|
+
static examples = ['<%= config.bin %> flows publish --app UUID 550e8400-e29b-41d4-a716-446655440000'];
|
|
16
|
+
static flags = {
|
|
17
|
+
...appFlag,
|
|
18
|
+
...confirmFlags,
|
|
19
|
+
};
|
|
20
|
+
async run() {
|
|
21
|
+
const { args, flags } = await this.parse(FlowsPublish);
|
|
22
|
+
if (!isValidUuid(args.flow_id)) {
|
|
23
|
+
this.error('Invalid flow ID format.', { exit: 2 });
|
|
24
|
+
}
|
|
25
|
+
const client = await createAuthenticatedClient(this.config);
|
|
26
|
+
const flow = await client.get(`/apps/${flags.app}/flows/${args.flow_id}/`);
|
|
27
|
+
await confirmMutation(this, {
|
|
28
|
+
method: 'POST',
|
|
29
|
+
path: `/apps/${flags.app}/flows/${args.flow_id}/publish/`,
|
|
30
|
+
summary: `Publish flow "${flow.name}" live to end users`,
|
|
31
|
+
}, flags.yes);
|
|
32
|
+
let result;
|
|
33
|
+
try {
|
|
34
|
+
result = await client.post(`/apps/${flags.app}/flows/${args.flow_id}/publish/`);
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
if (error instanceof ApiError && (error.statusCode === 400 || error.errorCode === 'validation_error')) {
|
|
38
|
+
this.error(`Flow publish failed: ${error.message}\n` +
|
|
39
|
+
'Publishing needs a flow with a valid config. Fix it, then run `adapty flows publish` again:\n' +
|
|
40
|
+
flowFixLinks(args.flow_id), { exit: 1 });
|
|
41
|
+
}
|
|
42
|
+
throw error;
|
|
43
|
+
}
|
|
44
|
+
if (!this.jsonEnabled()) {
|
|
45
|
+
this.log('Publishing started — status: publishing. This is asynchronous; the flow is NOT published yet.');
|
|
46
|
+
this.log(`Check progress: adapty flows get --app ${flags.app} ${args.flow_id} (wait for status 'published' or 'publication_failed')`);
|
|
47
|
+
this.log(`If it fails: adapty flows config get --app ${flags.app} ${args.flow_id} (shows why)`);
|
|
48
|
+
}
|
|
49
|
+
printResponse(result, this.log.bind(this));
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import type { FlowDTO } from '../../lib/api-schemas.js';
|
|
3
|
+
export default class FlowsUpdate extends Command {
|
|
4
|
+
static args: {
|
|
5
|
+
flow_id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
|
+
};
|
|
7
|
+
static description: string;
|
|
8
|
+
static enableJsonFlag: boolean;
|
|
9
|
+
static examples: string[];
|
|
10
|
+
static flags: {
|
|
11
|
+
name: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
app: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
};
|
|
14
|
+
run(): Promise<FlowDTO>;
|
|
15
|
+
}
|