adapty 0.9.3 → 0.9.4
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 +6 -0
- package/dist/commands/asa/change-history/get.d.ts +14 -0
- package/dist/commands/asa/change-history/get.js +39 -0
- package/dist/commands/asa/change-history/list.d.ts +27 -0
- package/dist/commands/asa/change-history/list.js +102 -0
- package/dist/lib/asa-schemas.d.ts +47 -0
- package/oclif.manifest.json +1682 -1479
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -365,8 +365,14 @@ adapty asa negative-keywords add --ad-group UUID --text free
|
|
|
365
365
|
adapty asa negative-keywords add --campaign UUID [--all-ad-groups] --text free
|
|
366
366
|
|
|
367
367
|
adapty asa search-terms list [--date-from ... --date-to ...]
|
|
368
|
+
|
|
369
|
+
adapty asa change-history list --campaign-group UUID [--date-from ... --date-to ...] [--entity-type Campaign --event-type UPDATE]
|
|
370
|
+
adapty asa change-history list --campaign-group UUID --fields # flat rows: field, old values, new values (page size 10)
|
|
371
|
+
adapty asa change-history get Campaign.444555666.TXN_ID --campaign-group UUID # detail_id comes from the list
|
|
368
372
|
```
|
|
369
373
|
|
|
374
|
+
Change history is read live from Apple (proxied from the Apple Ads Platform API; Apple keeps 6 months). Its id filters (`--campaign`, `--ad-group`, `--entity-id`, `--user`, `--txn`) take Apple's own ids, not UUIDs; `modified_by` is an Apple user id, not an email.
|
|
375
|
+
|
|
370
376
|
Product pages and rule-based automations:
|
|
371
377
|
|
|
372
378
|
```sh
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import type { AsaChangeHistoryDetailDTO } from '../../../lib/asa-schemas.js';
|
|
3
|
+
export default class AsaChangeHistoryGet extends Command {
|
|
4
|
+
static args: {
|
|
5
|
+
detail_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
|
+
'campaign-group': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<AsaChangeHistoryDetailDTO>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Args, Command, Flags } 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
|
+
const DETAIL_ID_REGEX = /^[A-Za-z]+\.[\w-]+\.[\w-]+$/;
|
|
6
|
+
export default class AsaChangeHistoryGet extends Command {
|
|
7
|
+
static args = {
|
|
8
|
+
detail_id: Args.string({
|
|
9
|
+
description: 'Detail ID from asa change-history list (EntityType.entityId.txnId)',
|
|
10
|
+
required: true,
|
|
11
|
+
}),
|
|
12
|
+
};
|
|
13
|
+
static description = 'Field-level before/after of one change (proxied from the Apple Ads Platform API)';
|
|
14
|
+
static enableJsonFlag = true;
|
|
15
|
+
static examples = ['<%= config.bin %> asa change-history get Campaign.444555666.TXN_ID --campaign-group <uuid>'];
|
|
16
|
+
static flags = {
|
|
17
|
+
'campaign-group': Flags.string({
|
|
18
|
+
description: 'Organization the change belongs to (UUID; take campaign_group_id from the list row)',
|
|
19
|
+
required: true,
|
|
20
|
+
}),
|
|
21
|
+
};
|
|
22
|
+
async run() {
|
|
23
|
+
const { args, flags } = await this.parse(AsaChangeHistoryGet);
|
|
24
|
+
if (!DETAIL_ID_REGEX.test(args.detail_id)) {
|
|
25
|
+
this.error('Invalid detail ID format. Take it from `adapty asa change-history list` (EntityType.entityId.txnId).', {
|
|
26
|
+
exit: 2,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
if (!isValidUuid(flags['campaign-group'])) {
|
|
30
|
+
this.error('Invalid campaign group ID format. Run `adapty asa orgs list` to find it.', { exit: 2 });
|
|
31
|
+
}
|
|
32
|
+
const client = await createAsaClient(this);
|
|
33
|
+
const result = await client.get(`/change-history/${args.detail_id}`, {
|
|
34
|
+
campaign_group_id: flags['campaign-group'],
|
|
35
|
+
});
|
|
36
|
+
printResponse(result, this.log.bind(this));
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import type { AsaChangeHistoryEventDTO, AsaChangeHistoryFieldEventDTO } from '../../../lib/asa-schemas.js';
|
|
3
|
+
import type { PaginatedResponse } from '../../../lib/flags.js';
|
|
4
|
+
type ChangeHistoryPage = PaginatedResponse<AsaChangeHistoryEventDTO> | PaginatedResponse<AsaChangeHistoryFieldEventDTO>;
|
|
5
|
+
export default class AsaChangeHistoryList extends Command {
|
|
6
|
+
static description: string;
|
|
7
|
+
static enableJsonFlag: boolean;
|
|
8
|
+
static examples: string[];
|
|
9
|
+
static flags: {
|
|
10
|
+
'ad-group': import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
campaign: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
'campaign-group': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
'date-from': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
'date-to': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
+
'entity-id': import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
+
'entity-type': import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
|
+
'event-type': import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
|
+
fields: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
19
|
+
txn: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
20
|
+
user: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
21
|
+
'user-type': import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
22
|
+
page: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
23
|
+
'page-size': import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
24
|
+
};
|
|
25
|
+
run(): Promise<ChangeHistoryPage>;
|
|
26
|
+
}
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { Command, Flags } from '@oclif/core';
|
|
2
|
+
import { createAsaClient } from '../../../lib/asa-client.js';
|
|
3
|
+
import { asaPaginationFlags, parseDate, periodParams } from '../../../lib/asa-flags.js';
|
|
4
|
+
import { isValidUuid, paginationParams } from '../../../lib/flags.js';
|
|
5
|
+
import { printList } from '../../../lib/output.js';
|
|
6
|
+
const FIELDS_MAX_PAGE_SIZE = 10;
|
|
7
|
+
const MAX_SPAN_DAYS = 14;
|
|
8
|
+
const MS_PER_DAY = 86_400_000;
|
|
9
|
+
export default class AsaChangeHistoryList extends Command {
|
|
10
|
+
static description = 'Apple Ads change history of one organization, read live from Apple (proxied from the Apple Ads Platform API)';
|
|
11
|
+
static enableJsonFlag = true;
|
|
12
|
+
static examples = [
|
|
13
|
+
'<%= config.bin %> asa change-history list --campaign-group <uuid>',
|
|
14
|
+
'<%= config.bin %> asa change-history list --campaign-group <uuid> --date-from 2026-09-01 --entity-type Campaign --event-type UPDATE',
|
|
15
|
+
'<%= config.bin %> asa change-history list --campaign-group <uuid> --fields',
|
|
16
|
+
];
|
|
17
|
+
static flags = {
|
|
18
|
+
...asaPaginationFlags,
|
|
19
|
+
'ad-group': Flags.string({
|
|
20
|
+
description: 'Keep only changes inside these Apple ad group ids (not UUIDs); repeatable',
|
|
21
|
+
multiple: true,
|
|
22
|
+
}),
|
|
23
|
+
'campaign': Flags.string({
|
|
24
|
+
description: 'Keep only changes inside these Apple campaign ids (not UUIDs); repeatable',
|
|
25
|
+
multiple: true,
|
|
26
|
+
}),
|
|
27
|
+
'campaign-group': Flags.string({
|
|
28
|
+
description: 'Organization to read (UUID from asa orgs list); one organization per call',
|
|
29
|
+
required: true,
|
|
30
|
+
}),
|
|
31
|
+
'date-from': Flags.string({
|
|
32
|
+
description: 'Start of the period (YYYY-MM-DD), defaults to 7 days ago; at most 14 days per call, Apple keeps 6 months',
|
|
33
|
+
parse: parseDate,
|
|
34
|
+
}),
|
|
35
|
+
'date-to': Flags.string({
|
|
36
|
+
description: 'End of the period (YYYY-MM-DD), defaults to today',
|
|
37
|
+
parse: parseDate,
|
|
38
|
+
}),
|
|
39
|
+
'entity-id': Flags.string({
|
|
40
|
+
description: 'Keep only changes of these Apple entity ids (not UUIDs); repeatable',
|
|
41
|
+
multiple: true,
|
|
42
|
+
}),
|
|
43
|
+
'entity-type': Flags.string({
|
|
44
|
+
description: 'Keep only changes of this entity type; repeatable. Default is the campaign domain (Campaign, AdGroup, Keyword, NegativeKeyword, Ad, Creative, LocationGroup); Org and AdAccount cannot be mixed with it',
|
|
45
|
+
multiple: true,
|
|
46
|
+
options: ['Ad', 'AdAccount', 'AdGroup', 'Campaign', 'Creative', 'Keyword', 'LocationGroup', 'NegativeKeyword', 'Org'],
|
|
47
|
+
}),
|
|
48
|
+
'event-type': Flags.string({
|
|
49
|
+
description: 'Keep only this operation; repeatable',
|
|
50
|
+
multiple: true,
|
|
51
|
+
options: ['CREATE', 'DELETE', 'UPDATE'],
|
|
52
|
+
}),
|
|
53
|
+
'fields': Flags.boolean({
|
|
54
|
+
description: `Expand into flat field-level rows (field, old values, new values); page size defaults to ${FIELDS_MAX_PAGE_SIZE} and may not exceed it`,
|
|
55
|
+
}),
|
|
56
|
+
'txn': Flags.string({ description: 'Keep only these Apple transaction ids; repeatable', multiple: true }),
|
|
57
|
+
'user': Flags.string({
|
|
58
|
+
description: 'Keep only changes made by these Apple user ids (not emails); repeatable',
|
|
59
|
+
multiple: true,
|
|
60
|
+
}),
|
|
61
|
+
'user-type': Flags.string({
|
|
62
|
+
description: 'Keep only changes by this actor category; repeatable',
|
|
63
|
+
multiple: true,
|
|
64
|
+
options: ['APPLE_SUPPORT', 'CUSTOMER', 'CUSTOMER_API'],
|
|
65
|
+
}),
|
|
66
|
+
};
|
|
67
|
+
async run() {
|
|
68
|
+
const { flags } = await this.parse(AsaChangeHistoryList);
|
|
69
|
+
const isPageSizeGiven = this.argv.some(arg => arg === '--page-size' || arg.startsWith('--page-size='));
|
|
70
|
+
if (flags.fields && isPageSizeGiven && flags['page-size'] > FIELDS_MAX_PAGE_SIZE) {
|
|
71
|
+
this.error(`--fields allows --page-size up to ${FIELDS_MAX_PAGE_SIZE}.`, { exit: 2 });
|
|
72
|
+
}
|
|
73
|
+
if (!isValidUuid(flags['campaign-group'])) {
|
|
74
|
+
this.error('Invalid campaign group ID format. Run `adapty asa orgs list` to find it.', { exit: 2 });
|
|
75
|
+
}
|
|
76
|
+
const dateFrom = flags['date-from'];
|
|
77
|
+
const dateTo = flags['date-to'];
|
|
78
|
+
if (dateFrom !== undefined
|
|
79
|
+
&& dateTo !== undefined
|
|
80
|
+
&& (Date.parse(dateTo) - Date.parse(dateFrom)) / MS_PER_DAY >= MAX_SPAN_DAYS) {
|
|
81
|
+
this.error(`--date-from/--date-to may span at most ${MAX_SPAN_DAYS} days.`, { exit: 2 });
|
|
82
|
+
}
|
|
83
|
+
const client = await createAsaClient(this);
|
|
84
|
+
const result = await client.get('/change-history', {
|
|
85
|
+
...paginationParams(flags),
|
|
86
|
+
...(flags.fields && !isPageSizeGiven ? { 'page[size]': String(FIELDS_MAX_PAGE_SIZE) } : {}),
|
|
87
|
+
...periodParams(flags),
|
|
88
|
+
ad_group_id: flags['ad-group'],
|
|
89
|
+
campaign_group_id: flags['campaign-group'],
|
|
90
|
+
campaign_id: flags.campaign,
|
|
91
|
+
entity_id: flags['entity-id'],
|
|
92
|
+
entity_type: flags['entity-type'],
|
|
93
|
+
event_type: flags['event-type'],
|
|
94
|
+
fields: flags.fields ? 'true' : undefined,
|
|
95
|
+
txn_id: flags.txn,
|
|
96
|
+
user_id: flags.user,
|
|
97
|
+
user_type: flags['user-type'],
|
|
98
|
+
});
|
|
99
|
+
printList(result.data, this.log.bind(this), result.meta.pagination);
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -424,3 +424,50 @@ export type AsaCompetitorBrandKeywordPoolDTO = {
|
|
|
424
424
|
export type AsaCompetitorBrandKeywordPoolsDTO = {
|
|
425
425
|
pools: AsaCompetitorBrandKeywordPoolDTO[];
|
|
426
426
|
};
|
|
427
|
+
export type AsaChangeHistoryEntityRefDTO = {
|
|
428
|
+
detail_id: string;
|
|
429
|
+
entity_id: string;
|
|
430
|
+
entity_name: null | string;
|
|
431
|
+
};
|
|
432
|
+
export type AsaChangeHistoryEventDTO = {
|
|
433
|
+
campaign_group_id: string;
|
|
434
|
+
changes_count: number;
|
|
435
|
+
entities: AsaChangeHistoryEntityRefDTO[];
|
|
436
|
+
entity_type: string;
|
|
437
|
+
event_time: string;
|
|
438
|
+
event_type: string;
|
|
439
|
+
modified_by: null | string;
|
|
440
|
+
transaction_id: string;
|
|
441
|
+
user_type: string;
|
|
442
|
+
};
|
|
443
|
+
export type AsaFieldChangeDTO = {
|
|
444
|
+
field: string;
|
|
445
|
+
new_values: string[];
|
|
446
|
+
old_values: string[];
|
|
447
|
+
};
|
|
448
|
+
export type AsaChangeHistoryDetailDTO = {
|
|
449
|
+
campaign_group_id: string;
|
|
450
|
+
changes: AsaFieldChangeDTO[];
|
|
451
|
+
detail_id: string;
|
|
452
|
+
entity_id: string;
|
|
453
|
+
entity_metadata: Record<string, unknown>;
|
|
454
|
+
entity_type: string;
|
|
455
|
+
event_time: string;
|
|
456
|
+
event_type: string;
|
|
457
|
+
modified_by: null | string;
|
|
458
|
+
user_type: string;
|
|
459
|
+
};
|
|
460
|
+
export type AsaChangeHistoryFieldEventDTO = {
|
|
461
|
+
campaign_group_id: string;
|
|
462
|
+
entity_id: string;
|
|
463
|
+
entity_name: null | string;
|
|
464
|
+
entity_type: string;
|
|
465
|
+
event_time: string;
|
|
466
|
+
event_type: string;
|
|
467
|
+
field: string;
|
|
468
|
+
modified_by: null | string;
|
|
469
|
+
new_values: string[];
|
|
470
|
+
old_values: string[];
|
|
471
|
+
transaction_id: string;
|
|
472
|
+
user_type: string;
|
|
473
|
+
};
|