adapty 0.3.0 → 0.4.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 +134 -5
- package/dist/commands/asa/ad-groups/create.d.ts +22 -0
- package/dist/commands/asa/ad-groups/create.js +54 -0
- package/dist/commands/asa/ad-groups/get.d.ts +11 -0
- package/dist/commands/asa/ad-groups/get.js +21 -0
- package/dist/commands/asa/ad-groups/list.d.ts +18 -0
- package/dist/commands/asa/ad-groups/list.js +24 -0
- package/dist/commands/asa/ad-groups/update.d.ts +23 -0
- package/dist/commands/asa/ad-groups/update.js +62 -0
- package/dist/commands/asa/ads/create.d.ts +16 -0
- package/dist/commands/asa/ads/create.js +41 -0
- package/dist/commands/asa/ads/get.d.ts +11 -0
- package/dist/commands/asa/ads/get.js +21 -0
- package/dist/commands/asa/ads/list.d.ts +18 -0
- package/dist/commands/asa/ads/list.js +24 -0
- package/dist/commands/asa/ads/update.d.ts +17 -0
- package/dist/commands/asa/ads/update.js +44 -0
- package/dist/commands/asa/apps/list.d.ts +13 -0
- package/dist/commands/asa/apps/list.js +18 -0
- package/dist/commands/asa/automations/create.d.ts +16 -0
- package/dist/commands/asa/automations/create.js +60 -0
- package/dist/commands/asa/automations/get.d.ts +11 -0
- package/dist/commands/asa/automations/get.js +21 -0
- package/dist/commands/asa/automations/list.d.ts +13 -0
- package/dist/commands/asa/automations/list.js +18 -0
- package/dist/commands/asa/automations/run.d.ts +16 -0
- package/dist/commands/asa/automations/run.js +41 -0
- package/dist/commands/asa/automations/runs.d.ts +16 -0
- package/dist/commands/asa/automations/runs.js +24 -0
- package/dist/commands/asa/automations/update.d.ts +21 -0
- package/dist/commands/asa/automations/update.js +73 -0
- package/dist/commands/asa/campaigns/create.d.ts +25 -0
- package/dist/commands/asa/campaigns/create.js +67 -0
- package/dist/commands/asa/campaigns/get.d.ts +11 -0
- package/dist/commands/asa/campaigns/get.js +21 -0
- package/dist/commands/asa/campaigns/list.d.ts +17 -0
- package/dist/commands/asa/campaigns/list.js +24 -0
- package/dist/commands/asa/campaigns/update.d.ts +23 -0
- package/dist/commands/asa/campaigns/update.js +66 -0
- package/dist/commands/asa/competitors/summary.d.ts +11 -0
- package/dist/commands/asa/competitors/summary.js +56 -0
- package/dist/commands/asa/connect.d.ts +12 -0
- package/dist/commands/asa/connect.js +39 -0
- package/dist/commands/asa/creatives/list.d.ts +15 -0
- package/dist/commands/asa/creatives/list.js +24 -0
- package/dist/commands/asa/keywords/add.d.ts +20 -0
- package/dist/commands/asa/keywords/add.js +73 -0
- package/dist/commands/asa/keywords/list.d.ts +19 -0
- package/dist/commands/asa/keywords/list.js +24 -0
- package/dist/commands/asa/keywords/update.d.ts +21 -0
- package/dist/commands/asa/keywords/update.js +64 -0
- package/dist/commands/asa/metrics/index.d.ts +21 -0
- package/dist/commands/asa/metrics/index.js +68 -0
- package/dist/commands/asa/metrics/overview.d.ts +15 -0
- package/dist/commands/asa/metrics/overview.js +51 -0
- package/dist/commands/asa/negative-keywords/add.d.ts +18 -0
- package/dist/commands/asa/negative-keywords/add.js +70 -0
- package/dist/commands/asa/negative-keywords/list.d.ts +19 -0
- package/dist/commands/asa/negative-keywords/list.js +29 -0
- package/dist/commands/asa/orgs/list.d.ts +13 -0
- package/dist/commands/asa/orgs/list.js +18 -0
- package/dist/commands/asa/product-pages/list.d.ts +15 -0
- package/dist/commands/asa/product-pages/list.js +24 -0
- package/dist/commands/asa/product-pages/sync.d.ts +13 -0
- package/dist/commands/asa/product-pages/sync.js +28 -0
- package/dist/commands/asa/search-terms/list.d.ts +20 -0
- package/dist/commands/asa/search-terms/list.js +25 -0
- package/dist/commands/asa/whoami.d.ts +8 -0
- package/dist/commands/asa/whoami.js +22 -0
- package/dist/lib/api-client.d.ts +15 -3
- package/dist/lib/api-client.js +49 -17
- package/dist/lib/asa-client.d.ts +16 -0
- package/dist/lib/asa-client.js +46 -0
- package/dist/lib/asa-confirm.d.ts +18 -0
- package/dist/lib/asa-confirm.js +41 -0
- package/dist/lib/asa-flags.d.ts +88 -0
- package/dist/lib/asa-flags.js +137 -0
- package/dist/lib/asa-schemas.d.ts +287 -0
- package/dist/lib/asa-schemas.js +1 -0
- package/dist/lib/errors.d.ts +25 -2
- package/dist/lib/errors.js +48 -7
- package/dist/lib/output.js +45 -15
- package/oclif.manifest.json +2802 -157
- package/package.json +40 -1
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import type { AsaAutomationMutationDTO } from '../../../lib/asa-schemas.js';
|
|
3
|
+
export default class AsaAutomationsCreate extends Command {
|
|
4
|
+
static description: string;
|
|
5
|
+
static enableJsonFlag: boolean;
|
|
6
|
+
static examples: string[];
|
|
7
|
+
static flags: {
|
|
8
|
+
file: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
'run-now': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
'idempotency-key': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<AsaAutomationMutationDTO>;
|
|
14
|
+
private readRule;
|
|
15
|
+
private readStdin;
|
|
16
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Command, Flags } from '@oclif/core';
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import { asaWrite, createAsaClient, noteReplay } from '../../../lib/asa-client.js';
|
|
4
|
+
import { confirmFlags, confirmMutation } from '../../../lib/asa-confirm.js';
|
|
5
|
+
import { idempotencyFlags } from '../../../lib/asa-flags.js';
|
|
6
|
+
import { printResponse } from '../../../lib/output.js';
|
|
7
|
+
export default class AsaAutomationsCreate extends Command {
|
|
8
|
+
static description = 'Create an automation rule from a JSON rule file';
|
|
9
|
+
static enableJsonFlag = true;
|
|
10
|
+
static examples = [
|
|
11
|
+
'<%= config.bin %> asa automations create --file rule.json',
|
|
12
|
+
'<%= config.bin %> asa automations create --file rule.json --run-now',
|
|
13
|
+
];
|
|
14
|
+
static flags = {
|
|
15
|
+
...confirmFlags,
|
|
16
|
+
...idempotencyFlags,
|
|
17
|
+
file: Flags.string({ description: 'JSON file with the rule body, or - to read stdin', required: true }),
|
|
18
|
+
'run-now': Flags.boolean({ description: 'Queue the first run right after the rule is stored' }),
|
|
19
|
+
};
|
|
20
|
+
async run() {
|
|
21
|
+
const { flags } = await this.parse(AsaAutomationsCreate);
|
|
22
|
+
const body = await this.readRule(flags.file);
|
|
23
|
+
if (flags['run-now'])
|
|
24
|
+
body.run_immediately = true;
|
|
25
|
+
const summary = flags['run-now'] ? 'Create automation rule and run it immediately' : 'Create automation rule';
|
|
26
|
+
await confirmMutation(this, { body, method: 'POST', path: '/automations/', summary }, flags.yes);
|
|
27
|
+
const client = await createAsaClient(this.config);
|
|
28
|
+
const { replayed, result } = await asaWrite(client, 'post', '/automations', {
|
|
29
|
+
body,
|
|
30
|
+
idempotencyKey: flags['idempotency-key'],
|
|
31
|
+
});
|
|
32
|
+
noteReplay(replayed, this.log.bind(this));
|
|
33
|
+
if (result.automation && !replayed) {
|
|
34
|
+
this.log(flags['run-now'] ? 'Automation created and the first run queued!' : 'Automation created!');
|
|
35
|
+
}
|
|
36
|
+
printResponse(result, this.log.bind(this));
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
async readRule(path) {
|
|
40
|
+
let raw;
|
|
41
|
+
try {
|
|
42
|
+
raw = path === '-' ? await this.readStdin() : await readFile(path, 'utf8');
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
this.error(`Could not read ${path}.`, { exit: 2 });
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
return JSON.parse(raw);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
this.error(`${path} is not valid JSON.`, { exit: 2 });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
async readStdin() {
|
|
55
|
+
const chunks = [];
|
|
56
|
+
for await (const chunk of process.stdin)
|
|
57
|
+
chunks.push(chunk);
|
|
58
|
+
return Buffer.concat(chunks).toString('utf8');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import type { AsaAutomationDTO } from '../../../lib/asa-schemas.js';
|
|
3
|
+
export default class AsaAutomationsGet extends Command {
|
|
4
|
+
static args: {
|
|
5
|
+
automation_id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
|
+
};
|
|
7
|
+
static description: string;
|
|
8
|
+
static enableJsonFlag: boolean;
|
|
9
|
+
static examples: string[];
|
|
10
|
+
run(): Promise<AsaAutomationDTO>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Args, Command } from '@oclif/core';
|
|
2
|
+
import { createAsaClient } from '../../../lib/asa-client.js';
|
|
3
|
+
import { isValidUuid } from '../../../lib/flags.js';
|
|
4
|
+
import { printResponse } from '../../../lib/output.js';
|
|
5
|
+
export default class AsaAutomationsGet extends Command {
|
|
6
|
+
static args = {
|
|
7
|
+
automation_id: Args.string({ description: 'Automation rule ID (UUID)', required: true }),
|
|
8
|
+
};
|
|
9
|
+
static description = 'Show one automation rule with its conditions and actions';
|
|
10
|
+
static enableJsonFlag = true;
|
|
11
|
+
static examples = ['<%= config.bin %> asa automations get 550e8400-e29b-41d4-a716-446655440000'];
|
|
12
|
+
async run() {
|
|
13
|
+
const { args } = await this.parse(AsaAutomationsGet);
|
|
14
|
+
if (!isValidUuid(args.automation_id))
|
|
15
|
+
this.error('Invalid automation ID format.', { exit: 2 });
|
|
16
|
+
const client = await createAsaClient(this.config);
|
|
17
|
+
const result = await client.get(`/automations/${args.automation_id}`);
|
|
18
|
+
printResponse(result, this.log.bind(this));
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import type { AsaAutomationDTO } from '../../../lib/asa-schemas.js';
|
|
3
|
+
import { type PaginatedResponse } from '../../../lib/flags.js';
|
|
4
|
+
export default class AsaAutomationsList extends Command {
|
|
5
|
+
static description: string;
|
|
6
|
+
static enableJsonFlag: boolean;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {
|
|
9
|
+
page: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
'page-size': import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
};
|
|
12
|
+
run(): Promise<PaginatedResponse<AsaAutomationDTO>>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import { createAsaClient } from '../../../lib/asa-client.js';
|
|
3
|
+
import { asaPaginationFlags } from '../../../lib/asa-flags.js';
|
|
4
|
+
import { paginationParams } from '../../../lib/flags.js';
|
|
5
|
+
import { printList } from '../../../lib/output.js';
|
|
6
|
+
export default class AsaAutomationsList extends Command {
|
|
7
|
+
static description = 'List automation rules; status 1 is active, 0 is stopped';
|
|
8
|
+
static enableJsonFlag = true;
|
|
9
|
+
static examples = ['<%= config.bin %> asa automations list'];
|
|
10
|
+
static flags = { ...asaPaginationFlags };
|
|
11
|
+
async run() {
|
|
12
|
+
const { flags } = await this.parse(AsaAutomationsList);
|
|
13
|
+
const client = await createAsaClient(this.config);
|
|
14
|
+
const result = await client.get('/automations', paginationParams(flags));
|
|
15
|
+
printList(result.data, this.log.bind(this), result.meta.pagination);
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import type { AsaAutomationRunEnqueuedDTO } from '../../../lib/asa-schemas.js';
|
|
3
|
+
export default class AsaAutomationsRun extends Command {
|
|
4
|
+
static args: {
|
|
5
|
+
automation_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
|
+
'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
'idempotency-key': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
|
+
};
|
|
15
|
+
run(): Promise<AsaAutomationRunEnqueuedDTO>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
2
|
+
import { asaWrite, createAsaClient, noteReplay } from '../../../lib/asa-client.js';
|
|
3
|
+
import { confirmFlags, confirmMutation } from '../../../lib/asa-confirm.js';
|
|
4
|
+
import { idempotencyFlags } from '../../../lib/asa-flags.js';
|
|
5
|
+
import { isValidUuid } from '../../../lib/flags.js';
|
|
6
|
+
export default class AsaAutomationsRun extends Command {
|
|
7
|
+
static args = {
|
|
8
|
+
automation_id: Args.string({ description: 'Automation rule ID (UUID)', required: true }),
|
|
9
|
+
};
|
|
10
|
+
static description = 'Run an automation rule now; the run is queued, not awaited';
|
|
11
|
+
static enableJsonFlag = true;
|
|
12
|
+
static examples = [
|
|
13
|
+
'<%= config.bin %> asa automations run UUID',
|
|
14
|
+
'<%= config.bin %> asa automations run UUID --dry-run',
|
|
15
|
+
];
|
|
16
|
+
static flags = {
|
|
17
|
+
...confirmFlags,
|
|
18
|
+
...idempotencyFlags,
|
|
19
|
+
'dry-run': Flags.boolean({ description: 'Evaluate and log the rule without touching Apple' }),
|
|
20
|
+
};
|
|
21
|
+
async run() {
|
|
22
|
+
const { args, flags } = await this.parse(AsaAutomationsRun);
|
|
23
|
+
if (!isValidUuid(args.automation_id))
|
|
24
|
+
this.error('Invalid automation ID format.', { exit: 2 });
|
|
25
|
+
if (!flags['dry-run']) {
|
|
26
|
+
await confirmMutation(this, {
|
|
27
|
+
method: 'POST',
|
|
28
|
+
path: `/automations/${args.automation_id}/run/`,
|
|
29
|
+
summary: 'Run the rule for real — it applies its actions to Apple',
|
|
30
|
+
}, flags.yes);
|
|
31
|
+
}
|
|
32
|
+
const client = await createAsaClient(this.config);
|
|
33
|
+
const { replayed, result } = await asaWrite(client, 'post', `/automations/${args.automation_id}/run`, { idempotencyKey: flags['idempotency-key'], params: flags['dry-run'] ? { dry_run: 'true' } : undefined });
|
|
34
|
+
noteReplay(replayed, this.log.bind(this));
|
|
35
|
+
if (!replayed)
|
|
36
|
+
this.log(flags['dry-run'] ? 'Dry run queued.' : 'Run queued.');
|
|
37
|
+
this.log(`Run ID: ${result.run_id ?? 'unknown'}`);
|
|
38
|
+
this.log(`Follow it with: ${this.config.bin} asa automations runs ${args.automation_id}`);
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import type { AsaAutomationRunDTO } from '../../../lib/asa-schemas.js';
|
|
3
|
+
import { type PaginatedResponse } from '../../../lib/flags.js';
|
|
4
|
+
export default class AsaAutomationsRuns extends Command {
|
|
5
|
+
static args: {
|
|
6
|
+
automation_id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
|
+
};
|
|
8
|
+
static description: string;
|
|
9
|
+
static enableJsonFlag: boolean;
|
|
10
|
+
static examples: string[];
|
|
11
|
+
static flags: {
|
|
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<PaginatedResponse<AsaAutomationRunDTO>>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Args, Command } from '@oclif/core';
|
|
2
|
+
import { createAsaClient } from '../../../lib/asa-client.js';
|
|
3
|
+
import { asaPaginationFlags } from '../../../lib/asa-flags.js';
|
|
4
|
+
import { isValidUuid } from '../../../lib/flags.js';
|
|
5
|
+
import { paginationParams } from '../../../lib/flags.js';
|
|
6
|
+
import { printList } from '../../../lib/output.js';
|
|
7
|
+
export default class AsaAutomationsRuns extends Command {
|
|
8
|
+
static args = {
|
|
9
|
+
automation_id: Args.string({ description: 'Automation rule ID (UUID)', required: true }),
|
|
10
|
+
};
|
|
11
|
+
static description = 'List past runs of an automation rule, including dry runs';
|
|
12
|
+
static enableJsonFlag = true;
|
|
13
|
+
static examples = ['<%= config.bin %> asa automations runs 550e8400-e29b-41d4-a716-446655440000'];
|
|
14
|
+
static flags = { ...asaPaginationFlags };
|
|
15
|
+
async run() {
|
|
16
|
+
const { args, flags } = await this.parse(AsaAutomationsRuns);
|
|
17
|
+
if (!isValidUuid(args.automation_id))
|
|
18
|
+
this.error('Invalid automation ID format.', { exit: 2 });
|
|
19
|
+
const client = await createAsaClient(this.config);
|
|
20
|
+
const result = await client.get(`/automations/${args.automation_id}/runs`, paginationParams(flags));
|
|
21
|
+
printList(result.data, this.log.bind(this), result.meta.pagination);
|
|
22
|
+
return result;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import type { AsaAutomationMutationDTO } from '../../../lib/asa-schemas.js';
|
|
3
|
+
export default class AsaAutomationsUpdate extends Command {
|
|
4
|
+
static args: {
|
|
5
|
+
automation_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
|
+
file: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
name: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
start: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
|
+
stop: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
|
+
'idempotency-key': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
+
yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
17
|
+
};
|
|
18
|
+
run(): Promise<AsaAutomationMutationDTO>;
|
|
19
|
+
private readRule;
|
|
20
|
+
private readStdin;
|
|
21
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import { asaWrite, createAsaClient, noteReplay } from '../../../lib/asa-client.js';
|
|
4
|
+
import { confirmFlags, confirmMutation } from '../../../lib/asa-confirm.js';
|
|
5
|
+
import { idempotencyFlags } from '../../../lib/asa-flags.js';
|
|
6
|
+
import { isValidUuid } from '../../../lib/flags.js';
|
|
7
|
+
import { printResponse } from '../../../lib/output.js';
|
|
8
|
+
export default class AsaAutomationsUpdate extends Command {
|
|
9
|
+
static args = {
|
|
10
|
+
automation_id: Args.string({ description: 'Automation rule ID (UUID)', required: true }),
|
|
11
|
+
};
|
|
12
|
+
static description = 'Change an automation rule: stop it, rename it, or replace parts of the rule';
|
|
13
|
+
static enableJsonFlag = true;
|
|
14
|
+
static examples = [
|
|
15
|
+
'<%= config.bin %> asa automations update UUID --stop',
|
|
16
|
+
'<%= config.bin %> asa automations update UUID --file rule.json',
|
|
17
|
+
];
|
|
18
|
+
static flags = {
|
|
19
|
+
...confirmFlags,
|
|
20
|
+
...idempotencyFlags,
|
|
21
|
+
file: Flags.string({ description: 'JSON file with the parts to change, or - to read stdin' }),
|
|
22
|
+
name: Flags.string({ description: 'Rule name' }),
|
|
23
|
+
start: Flags.boolean({ description: 'Activate the rule', exclusive: ['stop'] }),
|
|
24
|
+
stop: Flags.boolean({ description: 'Stop the rule and clear its next run', exclusive: ['start'] }),
|
|
25
|
+
};
|
|
26
|
+
async run() {
|
|
27
|
+
const { args, flags } = await this.parse(AsaAutomationsUpdate);
|
|
28
|
+
if (!isValidUuid(args.automation_id))
|
|
29
|
+
this.error('Invalid automation ID format.', { exit: 2 });
|
|
30
|
+
const body = flags.file ? await this.readRule(flags.file) : {};
|
|
31
|
+
if (flags.name !== undefined)
|
|
32
|
+
body.name = flags.name;
|
|
33
|
+
if (flags.start)
|
|
34
|
+
body.status = 1;
|
|
35
|
+
if (flags.stop)
|
|
36
|
+
body.status = 0;
|
|
37
|
+
if (Object.keys(body).length === 0) {
|
|
38
|
+
this.error('Nothing to change. Pass --stop, --start, --name or --file.', { exit: 2 });
|
|
39
|
+
}
|
|
40
|
+
if ('internal_id' in body) {
|
|
41
|
+
this.error('Remove internal_id from the file: the rule ID comes from the command line.', { exit: 2 });
|
|
42
|
+
}
|
|
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);
|
|
45
|
+
const { replayed, result } = await asaWrite(client, 'put', `/automations/${args.automation_id}`, { body, idempotencyKey: flags['idempotency-key'] });
|
|
46
|
+
noteReplay(replayed, this.log.bind(this));
|
|
47
|
+
if (result.automation && !replayed)
|
|
48
|
+
this.log('Automation updated!');
|
|
49
|
+
printResponse(result, this.log.bind(this));
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
async readRule(path) {
|
|
53
|
+
let raw;
|
|
54
|
+
try {
|
|
55
|
+
raw = path === '-' ? await this.readStdin() : await readFile(path, 'utf8');
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
this.error(`Could not read ${path}.`, { exit: 2 });
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
return JSON.parse(raw);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
this.error(`${path} is not valid JSON.`, { exit: 2 });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async readStdin() {
|
|
68
|
+
const chunks = [];
|
|
69
|
+
for await (const chunk of process.stdin)
|
|
70
|
+
chunks.push(chunk);
|
|
71
|
+
return Buffer.concat(chunks).toString('utf8');
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import type { AsaCampaignMutationDTO } from '../../../lib/asa-schemas.js';
|
|
3
|
+
export default class AsaCampaignsCreate extends Command {
|
|
4
|
+
static description: string;
|
|
5
|
+
static enableJsonFlag: boolean;
|
|
6
|
+
static examples: string[];
|
|
7
|
+
static flags: {
|
|
8
|
+
'ad-channel-type': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
'adam-id': import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
'bidding-strategy': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
'billing-event': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
budget: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
country: import("@oclif/core/interfaces").OptionFlag<string[], import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
'daily-budget': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
+
name: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
+
org: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
|
+
status: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
|
+
'supply-source': import("@oclif/core/interfaces").OptionFlag<string[], import("@oclif/core/interfaces").CustomOptions>;
|
|
19
|
+
'target-cpa': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
20
|
+
'idempotency-key': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
21
|
+
yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
22
|
+
currency: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
23
|
+
};
|
|
24
|
+
run(): Promise<AsaCampaignMutationDTO>;
|
|
25
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Command, Flags } from '@oclif/core';
|
|
2
|
+
import { asaWrite, createAsaClient, noteReplay } from '../../../lib/asa-client.js';
|
|
3
|
+
import { confirmFlags, confirmMutation } from '../../../lib/asa-confirm.js';
|
|
4
|
+
import { currencyFlag, idempotencyFlags, money, moneyFlag } from '../../../lib/asa-flags.js';
|
|
5
|
+
import { isValidUuid } from '../../../lib/flags.js';
|
|
6
|
+
import { printResponse } from '../../../lib/output.js';
|
|
7
|
+
export default class AsaCampaignsCreate extends Command {
|
|
8
|
+
static description = 'Create a campaign in Apple Search Ads';
|
|
9
|
+
static enableJsonFlag = true;
|
|
10
|
+
static examples = [
|
|
11
|
+
'<%= config.bin %> asa campaigns create --org UUID --name "Winter push" --adam-id 123456 --country US --daily-budget 50',
|
|
12
|
+
];
|
|
13
|
+
static flags = {
|
|
14
|
+
...currencyFlag,
|
|
15
|
+
...confirmFlags,
|
|
16
|
+
...idempotencyFlags,
|
|
17
|
+
'ad-channel-type': Flags.string({ default: 'SEARCH', description: 'Ad channel type', options: ['DISPLAY', 'SEARCH'] }),
|
|
18
|
+
'adam-id': Flags.integer({ description: 'App Store app ID (adam_id)', required: true }),
|
|
19
|
+
'bidding-strategy': Flags.string({
|
|
20
|
+
description: 'Bidding strategy; Apple defaults to MANUAL_CPT when omitted',
|
|
21
|
+
options: ['MANUAL_CPT', 'MAX_CONVERSIONS'],
|
|
22
|
+
}),
|
|
23
|
+
'billing-event': Flags.string({ default: 'TAPS', description: 'Billing event', options: ['IMPRESSIONS', 'TAPS'] }),
|
|
24
|
+
budget: moneyFlag('Lifetime budget'),
|
|
25
|
+
country: Flags.string({ description: 'Country or region code, repeatable', multiple: true, required: true }),
|
|
26
|
+
'daily-budget': moneyFlag('Daily budget', { required: true }),
|
|
27
|
+
name: Flags.string({ description: 'Campaign name', required: true }),
|
|
28
|
+
org: Flags.string({ description: 'Campaign group ID (UUID) — see `adapty asa orgs list`', required: true }),
|
|
29
|
+
status: Flags.string({ description: 'Initial status', options: ['ENABLED', 'PAUSED'] }),
|
|
30
|
+
'supply-source': Flags.string({
|
|
31
|
+
default: ['APPSTORE_SEARCH_RESULTS'],
|
|
32
|
+
description: 'Supply source, repeatable',
|
|
33
|
+
multiple: true,
|
|
34
|
+
}),
|
|
35
|
+
'target-cpa': moneyFlag('Target CPA'),
|
|
36
|
+
};
|
|
37
|
+
async run() {
|
|
38
|
+
const { flags } = await this.parse(AsaCampaignsCreate);
|
|
39
|
+
if (!isValidUuid(flags.org))
|
|
40
|
+
this.error('Invalid org ID format.', { exit: 2 });
|
|
41
|
+
const body = {
|
|
42
|
+
ad_channel_type: flags['ad-channel-type'],
|
|
43
|
+
adam_id: flags['adam-id'],
|
|
44
|
+
bidding_strategy: flags['bidding-strategy'],
|
|
45
|
+
billing_event: flags['billing-event'],
|
|
46
|
+
budget_amount: money(flags.budget, flags.currency),
|
|
47
|
+
campaign_group_id: flags.org,
|
|
48
|
+
countries_or_regions: flags.country,
|
|
49
|
+
daily_budget_amount: money(flags['daily-budget'], flags.currency),
|
|
50
|
+
name: flags.name,
|
|
51
|
+
status: flags.status,
|
|
52
|
+
supply_sources: flags['supply-source'],
|
|
53
|
+
target_cpa: money(flags['target-cpa'], flags.currency),
|
|
54
|
+
};
|
|
55
|
+
await confirmMutation(this, { body, method: 'POST', path: '/campaigns/', summary: `Create campaign ${flags.name}` }, flags.yes);
|
|
56
|
+
const client = await createAsaClient(this.config);
|
|
57
|
+
const { replayed, result } = await asaWrite(client, 'post', '/campaigns', {
|
|
58
|
+
body,
|
|
59
|
+
idempotencyKey: flags['idempotency-key'],
|
|
60
|
+
});
|
|
61
|
+
noteReplay(replayed, this.log.bind(this));
|
|
62
|
+
if (result.campaign && !replayed)
|
|
63
|
+
this.log('Campaign created!');
|
|
64
|
+
printResponse(result, this.log.bind(this));
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import type { AsaCampaignDTO } from '../../../lib/asa-schemas.js';
|
|
3
|
+
export default class AsaCampaignsGet extends Command {
|
|
4
|
+
static args: {
|
|
5
|
+
campaign_id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
|
+
};
|
|
7
|
+
static description: string;
|
|
8
|
+
static enableJsonFlag: boolean;
|
|
9
|
+
static examples: string[];
|
|
10
|
+
run(): Promise<AsaCampaignDTO>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Args, Command } from '@oclif/core';
|
|
2
|
+
import { createAsaClient } from '../../../lib/asa-client.js';
|
|
3
|
+
import { isValidUuid } from '../../../lib/flags.js';
|
|
4
|
+
import { printResponse } from '../../../lib/output.js';
|
|
5
|
+
export default class AsaCampaignsGet extends Command {
|
|
6
|
+
static args = {
|
|
7
|
+
campaign_id: Args.string({ description: 'Campaign ID (UUID)', required: true }),
|
|
8
|
+
};
|
|
9
|
+
static description = 'Show one campaign; read numbers with asa metrics';
|
|
10
|
+
static enableJsonFlag = true;
|
|
11
|
+
static examples = ['<%= config.bin %> asa campaigns get 550e8400-e29b-41d4-a716-446655440000'];
|
|
12
|
+
async run() {
|
|
13
|
+
const { args } = await this.parse(AsaCampaignsGet);
|
|
14
|
+
if (!isValidUuid(args.campaign_id))
|
|
15
|
+
this.error('Invalid campaign ID format.', { exit: 2 });
|
|
16
|
+
const client = await createAsaClient(this.config);
|
|
17
|
+
const result = await client.get(`/campaigns/${args.campaign_id}`);
|
|
18
|
+
printResponse(result, this.log.bind(this));
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import type { AsaCampaignDTO } from '../../../lib/asa-schemas.js';
|
|
3
|
+
import { type PaginatedResponse } from '../../../lib/flags.js';
|
|
4
|
+
export default class AsaCampaignsList extends Command {
|
|
5
|
+
static description: string;
|
|
6
|
+
static enableJsonFlag: boolean;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {
|
|
9
|
+
status: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
search: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
app: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
'campaign-group': import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
page: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
'page-size': import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
+
};
|
|
16
|
+
run(): Promise<PaginatedResponse<AsaCampaignDTO>>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import { createAsaClient } from '../../../lib/asa-client.js';
|
|
3
|
+
import { asaPaginationFlags, orgScopeFlags, scopeParams, statusFilter } from '../../../lib/asa-flags.js';
|
|
4
|
+
import { paginationParams } from '../../../lib/flags.js';
|
|
5
|
+
import { printList } from '../../../lib/output.js';
|
|
6
|
+
export default class AsaCampaignsList extends Command {
|
|
7
|
+
static description = 'List Apple Search Ads campaigns; read numbers with asa metrics';
|
|
8
|
+
static enableJsonFlag = true;
|
|
9
|
+
static examples = [
|
|
10
|
+
'<%= config.bin %> asa campaigns list',
|
|
11
|
+
'<%= config.bin %> asa campaigns list --app APP_UUID --status PAUSED',
|
|
12
|
+
];
|
|
13
|
+
static flags = { ...asaPaginationFlags, ...orgScopeFlags, ...statusFilter(['ENABLED', 'PAUSED']) };
|
|
14
|
+
async run() {
|
|
15
|
+
const { flags } = await this.parse(AsaCampaignsList);
|
|
16
|
+
const client = await createAsaClient(this.config);
|
|
17
|
+
const result = await client.get('/campaigns', {
|
|
18
|
+
...paginationParams(flags),
|
|
19
|
+
...scopeParams(flags),
|
|
20
|
+
});
|
|
21
|
+
printList(result.data, this.log.bind(this), result.meta.pagination);
|
|
22
|
+
return result;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import type { AsaCampaignMutationDTO } from '../../../lib/asa-schemas.js';
|
|
3
|
+
export default class AsaCampaignsUpdate extends Command {
|
|
4
|
+
static args: {
|
|
5
|
+
campaign_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
|
+
'bidding-strategy': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
budget: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
country: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
'daily-budget': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
+
name: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
+
status: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
|
+
'target-cpa': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
|
+
'idempotency-key': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
19
|
+
yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
20
|
+
currency: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
21
|
+
};
|
|
22
|
+
run(): Promise<AsaCampaignMutationDTO>;
|
|
23
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
2
|
+
import { asaWrite, createAsaClient, noteReplay } from '../../../lib/asa-client.js';
|
|
3
|
+
import { confirmFlags, confirmMutation } from '../../../lib/asa-confirm.js';
|
|
4
|
+
import { currencyFlag, idempotencyFlags, money, moneyFlag } from '../../../lib/asa-flags.js';
|
|
5
|
+
import { isValidUuid } from '../../../lib/flags.js';
|
|
6
|
+
import { printResponse } from '../../../lib/output.js';
|
|
7
|
+
export default class AsaCampaignsUpdate extends Command {
|
|
8
|
+
static args = {
|
|
9
|
+
campaign_id: Args.string({ description: 'Campaign ID (UUID)', required: true }),
|
|
10
|
+
};
|
|
11
|
+
static description = 'Change a campaign: budgets, countries, status or schedule';
|
|
12
|
+
static enableJsonFlag = true;
|
|
13
|
+
static examples = [
|
|
14
|
+
'<%= config.bin %> asa campaigns update UUID --status PAUSED',
|
|
15
|
+
'<%= config.bin %> asa campaigns update UUID --daily-budget 80',
|
|
16
|
+
];
|
|
17
|
+
static flags = {
|
|
18
|
+
...currencyFlag,
|
|
19
|
+
...confirmFlags,
|
|
20
|
+
...idempotencyFlags,
|
|
21
|
+
'bidding-strategy': Flags.string({
|
|
22
|
+
description: 'Bidding strategy',
|
|
23
|
+
options: ['MANUAL_CPT', 'MAX_CONVERSIONS'],
|
|
24
|
+
}),
|
|
25
|
+
budget: moneyFlag('Lifetime budget'),
|
|
26
|
+
country: Flags.string({ description: 'Replace the country list, repeatable', multiple: true }),
|
|
27
|
+
'daily-budget': moneyFlag('Daily budget'),
|
|
28
|
+
name: Flags.string({ description: 'Campaign name' }),
|
|
29
|
+
status: Flags.string({ description: 'Campaign status', options: ['ENABLED', 'PAUSED'] }),
|
|
30
|
+
'target-cpa': moneyFlag('Target CPA'),
|
|
31
|
+
};
|
|
32
|
+
async run() {
|
|
33
|
+
const { args, flags } = await this.parse(AsaCampaignsUpdate);
|
|
34
|
+
if (!isValidUuid(args.campaign_id))
|
|
35
|
+
this.error('Invalid campaign ID format.', { exit: 2 });
|
|
36
|
+
const body = {};
|
|
37
|
+
if (flags.name !== undefined)
|
|
38
|
+
body.name = flags.name;
|
|
39
|
+
if (flags.status !== undefined)
|
|
40
|
+
body.status = flags.status;
|
|
41
|
+
if (flags.country !== undefined)
|
|
42
|
+
body.countries_or_regions = flags.country;
|
|
43
|
+
if (flags['daily-budget'] !== undefined)
|
|
44
|
+
body.daily_budget_amount = money(flags['daily-budget'], flags.currency);
|
|
45
|
+
if (flags.budget !== undefined)
|
|
46
|
+
body.budget_amount = money(flags.budget, flags.currency);
|
|
47
|
+
if (flags['target-cpa'] !== undefined)
|
|
48
|
+
body.target_cpa = money(flags['target-cpa'], flags.currency);
|
|
49
|
+
if (flags['bidding-strategy'] !== undefined)
|
|
50
|
+
body.bidding_strategy = flags['bidding-strategy'];
|
|
51
|
+
if (Object.keys(body).length === 0) {
|
|
52
|
+
this.error('Nothing to change. Pass at least one field, e.g. --status PAUSED.', { exit: 2 });
|
|
53
|
+
}
|
|
54
|
+
await confirmMutation(this, { body, method: 'PUT', path: `/campaigns/${args.campaign_id}/`, summary: 'Update campaign' }, flags.yes);
|
|
55
|
+
const client = await createAsaClient(this.config);
|
|
56
|
+
const { replayed, result } = await asaWrite(client, 'put', `/campaigns/${args.campaign_id}`, {
|
|
57
|
+
body,
|
|
58
|
+
idempotencyKey: flags['idempotency-key'],
|
|
59
|
+
});
|
|
60
|
+
noteReplay(replayed, this.log.bind(this));
|
|
61
|
+
if (result.campaign && !replayed)
|
|
62
|
+
this.log('Campaign updated!');
|
|
63
|
+
printResponse(result, this.log.bind(this));
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import type { AsaCompetitorsSummaryDTO } from '../../../lib/asa-schemas.js';
|
|
3
|
+
export default class AsaCompetitorsSummary extends Command {
|
|
4
|
+
static description: string;
|
|
5
|
+
static enableJsonFlag: boolean;
|
|
6
|
+
static examples: string[];
|
|
7
|
+
static flags: {
|
|
8
|
+
'app-ids': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
};
|
|
10
|
+
run(): Promise<AsaCompetitorsSummaryDTO>;
|
|
11
|
+
}
|