@adport/provider-apple 0.5.2 → 0.6.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/dist/index.d.ts +2 -0
- package/dist/index.js +13 -7
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ interface AppleCredentials {
|
|
|
6
6
|
keyId: string;
|
|
7
7
|
/** PEM contents of the .p8 EC private key. */
|
|
8
8
|
privateKeyPem: string;
|
|
9
|
+
/** Delegated service-provider grant. Omit for a self-managed API user. */
|
|
10
|
+
refreshToken?: string;
|
|
9
11
|
}
|
|
10
12
|
/** Apple Ads Platform API v1. The legacy Campaign Management API v5 retires 2027-01-26. */
|
|
11
13
|
declare const APPLE_ADS_BASE = "https://api.ads.apple.com/v1";
|
package/dist/index.js
CHANGED
|
@@ -39,21 +39,27 @@ var AppleAdsClient = class {
|
|
|
39
39
|
return this.accessToken.token;
|
|
40
40
|
}
|
|
41
41
|
const clientSecret = createClientSecret(this.credentials);
|
|
42
|
+
const tokenParams = new URLSearchParams(this.credentials.refreshToken ? {
|
|
43
|
+
grant_type: "refresh_token",
|
|
44
|
+
client_id: this.credentials.clientId,
|
|
45
|
+
client_secret: clientSecret,
|
|
46
|
+
refresh_token: this.credentials.refreshToken
|
|
47
|
+
} : {
|
|
48
|
+
grant_type: "client_credentials",
|
|
49
|
+
client_id: this.credentials.clientId,
|
|
50
|
+
client_secret: clientSecret,
|
|
51
|
+
scope: "searchadsorg"
|
|
52
|
+
});
|
|
42
53
|
const response = await this.fetchImpl(TOKEN_URL, {
|
|
43
54
|
method: "POST",
|
|
44
55
|
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
45
|
-
body:
|
|
46
|
-
grant_type: "client_credentials",
|
|
47
|
-
client_id: this.credentials.clientId,
|
|
48
|
-
client_secret: clientSecret,
|
|
49
|
-
scope: "searchadsorg"
|
|
50
|
-
})
|
|
56
|
+
body: tokenParams
|
|
51
57
|
});
|
|
52
58
|
const raw = await response.text();
|
|
53
59
|
if (!response.ok) {
|
|
54
60
|
throw new AdportError(
|
|
55
61
|
"PROVIDER_ERROR",
|
|
56
|
-
`Apple Ads OAuth failed (${response.status}). Check
|
|
62
|
+
`Apple Ads OAuth failed (${response.status}). Check the client identity, uploaded public key, and delegated account access.`,
|
|
57
63
|
safeJson(raw)
|
|
58
64
|
);
|
|
59
65
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client.ts","../src/jwt.ts","../src/provider.ts","../src/tools.ts","../src/index.ts"],"sourcesContent":["import { AdportError } from '@adport/core';\nimport { createClientSecret } from './jwt.js';\n\nexport interface AppleCredentials {\n clientId: string;\n teamId: string;\n keyId: string;\n /** PEM contents of the .p8 EC private key. */\n privateKeyPem: string;\n}\n\nconst TOKEN_URL = 'https://appleid.apple.com/auth/oauth2/token';\n\n/** Apple Ads Platform API v1. The legacy Campaign Management API v5 retires 2027-01-26. */\nexport const APPLE_ADS_BASE = 'https://api.ads.apple.com/v1';\n\nexport interface AppleEnvelope<T> {\n result: T;\n pagination?: { offset?: number; pageSize?: number; totalCount?: number } | null;\n error?: {\n code?: string;\n message?: string;\n details?: Array<{ code?: string; message?: string }>;\n } | null;\n}\n\nexport class AppleAdsClient {\n private accessToken?: { token: string; expiresAt: number };\n\n constructor(\n private readonly credentials: AppleCredentials,\n private readonly fetchImpl: typeof fetch = fetch,\n ) {}\n\n async getAccessToken(): Promise<string> {\n if (this.accessToken && this.accessToken.expiresAt > Date.now()) {\n return this.accessToken.token;\n }\n // Mint a fresh short-lived client secret per request — no 180-day rotation to manage.\n const clientSecret = createClientSecret(this.credentials);\n const response = await this.fetchImpl(TOKEN_URL, {\n method: 'POST',\n headers: { 'content-type': 'application/x-www-form-urlencoded' },\n body: new URLSearchParams({\n grant_type: 'client_credentials',\n client_id: this.credentials.clientId,\n client_secret: clientSecret,\n scope: 'searchadsorg',\n }),\n });\n const raw = await response.text();\n if (!response.ok) {\n throw new AdportError(\n 'PROVIDER_ERROR',\n `Apple Ads OAuth failed (${response.status}). Check clientId/teamId/keyId and that the public key is uploaded in Account Settings > API.`,\n safeJson(raw),\n );\n }\n const data = JSON.parse(raw) as { access_token: string; expires_in: number };\n this.accessToken = { token: data.access_token, expiresAt: Date.now() + (data.expires_in - 60) * 1000 };\n return this.accessToken.token;\n }\n\n /** adAccountId context is required on account-scoped endpoints. */\n async request<T>(\n method: 'GET' | 'POST' | 'PUT' | 'DELETE',\n path: string,\n options: { adAccountId?: string; body?: unknown; form?: FormData } = {},\n ): Promise<AppleEnvelope<T>> {\n const token = await this.getAccessToken();\n if (options.body !== undefined && options.form !== undefined) {\n throw new AdportError('INVALID_INPUT', 'Apple Ads request cannot contain both JSON and multipart bodies');\n }\n const response = await this.fetchImpl(`${APPLE_ADS_BASE}/${path.replace(/^\\//, '')}`, {\n method,\n headers: {\n authorization: `Bearer ${token}`,\n accept: 'application/json',\n ...(options.adAccountId ? { 'X-AP-Context': `adAccountId=${options.adAccountId}` } : {}),\n ...(options.body !== undefined ? { 'content-type': 'application/json' } : {}),\n },\n body: options.form ?? (options.body === undefined ? undefined : JSON.stringify(options.body)),\n });\n const raw = await response.text();\n if (!response.ok) {\n throw new AdportError('PROVIDER_ERROR', formatAppleError(response.status, raw), safeJson(raw));\n }\n return (raw ? JSON.parse(raw) : { result: undefined }) as AppleEnvelope<T>;\n }\n}\n\nfunction safeJson(raw: string): unknown {\n try {\n return JSON.parse(raw);\n } catch {\n return raw;\n }\n}\n\n/** v1 error shape: {\"error\":{\"code\",\"message\",\"details\":[{\"code\",\"message\"}]}}. */\nexport function formatAppleError(status: number, raw: string): string {\n const parsed = safeJson(raw) as {\n error?: { code?: string; message?: string; details?: Array<{ code?: string; message?: string }> };\n };\n const head = `Apple Ads API error (HTTP ${status})`;\n const error = parsed?.error;\n if (!error) return head;\n const lines = [\n error.code || error.message ? `${error.code ?? '?'}: ${error.message ?? ''}` : undefined,\n ...(error.details ?? []).map((detail) => `${detail.code ?? '?'}: ${detail.message ?? ''}`),\n ].filter((line): line is string => Boolean(line));\n const hint = status === 401 ? '\\n Token or ad-account access problem — check credentials and account roles.' : '';\n return lines.length > 0 ? `${head}\\n ${lines.join('\\n ')}${hint}` : `${head}${hint}`;\n}\n","import { createPrivateKey, sign } from 'node:crypto';\n\nexport interface ClientSecretInput {\n /** SEARCHADS.<uuid> */\n clientId: string;\n /** SEARCHADS.<uuid> — equals clientId for self-managed orgs. */\n teamId: string;\n /** keyId of the public key uploaded in the Apple Ads UI. */\n keyId: string;\n /** EC prime256v1 private key, PEM (.p8 contents). */\n privateKeyPem: string;\n /** Secret lifetime in seconds; Apple caps exp at iat + 180 days. */\n lifetimeSeconds?: number;\n}\n\nfunction b64url(data: Buffer | string): string {\n return Buffer.from(data).toString('base64url');\n}\n\n/**\n * Apple Ads client secret: a self-signed ES256 JWT (header {alg, kid}; claims\n * iss=teamId, sub=clientId, aud=https://appleid.apple.com, iat, exp≤iat+180d).\n * We mint a short-lived secret per token request instead of storing one.\n */\nexport function createClientSecret(input: ClientSecretInput, now = new Date()): string {\n const iat = Math.floor(now.getTime() / 1000);\n const lifetime = Math.min(input.lifetimeSeconds ?? 3600, 180 * 86_400 - 60);\n const header = { alg: 'ES256', kid: input.keyId };\n const payload = {\n iss: input.teamId,\n iat,\n exp: iat + lifetime,\n aud: 'https://appleid.apple.com',\n sub: input.clientId,\n };\n const signingInput = `${b64url(JSON.stringify(header))}.${b64url(JSON.stringify(payload))}`;\n const key = createPrivateKey(input.privateKeyPem);\n // JWS ES256 requires the raw r||s signature form, not ASN.1/DER.\n const signature = sign('sha256', Buffer.from(signingInput), { key, dsaEncoding: 'ieee-p1363' });\n return `${signingInput}.${b64url(signature)}`;\n}\n","import {\n AdportError,\n resolveDateRange,\n type Account,\n type AdProvider,\n type MetricName,\n type NormalizedQuery,\n type ProviderCapabilities,\n type Report,\n type ReportRow,\n type StandardActions,\n type WriteGuard,\n type WriteOperation,\n type WritePreview,\n type WriteResult,\n} from '@adport/core';\nimport { createHash } from 'node:crypto';\nimport { readFile } from 'node:fs/promises';\nimport { basename, extname } from 'node:path';\nimport { AppleAdsClient } from './client.js';\n\n/** Apple Money amounts are strings in whole currency units. */\nexport const UNITS_TO_MICROS = 1_000_000;\n\ninterface Money {\n amount: string;\n currency: string;\n}\n\ninterface AppleCampaign {\n id: number;\n adAccountId?: number;\n name: string;\n status: 'ENABLED' | 'PAUSED';\n systemStatus?: string;\n displayStatus?: string;\n dailyBudget?: { value?: Money };\n promotedObjectId?: string;\n promotedObjectType?: string;\n billingEvent?: string;\n targeting?: Record<string, unknown>;\n}\n\ninterface SpendRow {\n impressions?: number;\n taps?: number;\n ttr?: number;\n totalInstalls?: number;\n localSpend?: Money;\n tapInstallCPI?: Money;\n tapInstallRate?: number;\n}\n\ninterface ReportingRow {\n totalMetrics?: SpendRow;\n metadata?: { id?: number; name?: string; status?: string };\n}\n\ninterface WritePlan {\n summary: string;\n changes: string[];\n coercions: string[];\n budgetDeltas: WritePreview['budgetDeltas'];\n execute: () => Promise<string[]>;\n}\n\ninterface AppleRecommendation {\n id?: string;\n campaignId?: number;\n campaignName?: string;\n dailyBudget?: Money;\n suggestedDailyBudgetAmount?: Money;\n bidStrategy?: { bidAmount?: Money };\n recommendedTargetCPA?: Money;\n}\n\ninterface AppleBiddableResource {\n id?: number;\n name?: string;\n bid?: Money;\n bidStrategy?: { bidStrategyType?: string; bidStrategyGoal?: string; bid?: Money };\n}\n\nconst APPLE_READ_GET_ROOTS = /^(?:acls|me|advertiser-resources|ad-accounts\\/[^/?]+|adgroups\\/[^/?]+|ads\\/[^/?]+|apps\\/[^/?]+|assets\\/[^/?]+|business-brands\\/[^/?]+|business-categories\\/[^/?]+|campaigns\\/[^/?]+(?:\\/legacy-app-limited-status-reason-details)?|change-history\\/[^/?]+|creatives\\/[^/?]+|keywords\\/[^/?]+|location-groups\\/[^/?]+|locations\\/[^/?]+|negative-keywords\\/[^/?]+|orgs\\/[^/?]+|product-pages\\/[^/?]+|rejection-reasons\\/apps\\/[^/?]+|shared-budgets\\/[^/?]+|search\\/(?:apps|geo))(?:\\?.*)?$/;\nconst APPLE_READ_POST_ROOTS = /^(?:(?:adgroups|ads|assets|business-brands|business-categories|campaigns|change-history|creatives|eligibilities\\/apps|insights\\/apps\\/(?:impression-share|search-term-popularity)|keywords|location-groups|locations|metadata\\/apps\\/supported-languages|negative-keywords|product-pages(?:\\/locale-details)?|recommendations\\/(?:daily-budgets|target-cpas)|rejection-reasons\\/(?:apps|business-brands)|reports\\/(?:apps|business-brands)\\/(?:adgroups|ads|campaigns|keywords|searchterms)|shared-budgets|suggestions\\/(?:categories|keywords|phrases|target-cpas))\\/query|apps\\/[^/?]+\\/locale-details\\/query|search\\/geo)$/;\nconst APPLE_CREATE_PATHS = /^(?:ad-accounts|adgroups|ads|campaigns|creatives|keywords|keywords\\/bulk-create|location-groups|negative-keywords|negative-keywords\\/bulk-create|shared-budgets)$/;\nconst APPLE_UPDATE_PATHS = /^(?:ad-accounts|adgroups|ads|campaigns|creatives|keywords|location-groups|negative-keywords|shared-budgets)\\/[^/?]+$|^(?:keywords|negative-keywords)\\/bulk-update$/;\nconst APPLE_DELETE_PATHS = /^(?:adgroups|ads|assets|campaigns|creatives|keywords|location-groups|negative-keywords|shared-budgets)\\/[^/?]+$/;\n\nexport class AppleAdsProvider implements AdProvider {\n readonly id = 'apple';\n\n constructor(private readonly client: AppleAdsClient) {}\n\n capabilities(): ProviderCapabilities {\n // The Platform API has no validate-only mode — previews remain client-side.\n return { serverDryRun: false };\n }\n\n standardActions(): StandardActions {\n return {\n pauseCampaign: (accountId, campaignId) => ({\n tool: 'apple_set_campaign_status',\n input: { account_id: accountId, campaign_id: campaignId, status: 'PAUSED' },\n }),\n };\n }\n\n /** v1 exposes one ACL entry per ad account. */\n async listAccounts(): Promise<Account[]> {\n const envelope = await this.client.request<{\n acls?: Array<{ adAccount?: { id?: number; name?: string; orgId?: number }; roles?: string[] }>;\n }>('GET', 'acls');\n return (envelope.result?.acls ?? []).flatMap((acl) => (acl.adAccount?.id === undefined ? [] : [{\n provider: this.id,\n id: String(acl.adAccount.id),\n name: acl.adAccount.name ?? String(acl.adAccount.id),\n status: acl.roles?.join(',') || undefined,\n }]));\n }\n\n async listCampaigns(adAccountId: string, limit = 100): Promise<AppleCampaign[]> {\n const envelope = await this.client.request<AppleCampaign[]>('POST', 'campaigns/query', {\n adAccountId,\n body: { pagination: { offset: 0, pageSize: limit, fetchTotalCount: false } },\n });\n return envelope.result ?? [];\n }\n\n async getCampaign(adAccountId: string, campaignId: string): Promise<AppleCampaign> {\n const envelope = await this.client.request<AppleCampaign>('GET', `campaigns/${campaignId}`, { adAccountId });\n const campaign = envelope.result;\n if (!campaign) {\n throw new AdportError('PROVIDER_ERROR', `apple: campaign ${campaignId} not found in ad account ${adAccountId}`);\n }\n return campaign;\n }\n\n /**\n * Safe low-level access to the documented read surface. Apple uses POST for\n * selectors and reports, so method alone cannot determine mutability.\n */\n async apiRead(input: {\n account_id?: string;\n method: 'GET' | 'POST';\n path: string;\n body?: Record<string, unknown>;\n }): Promise<unknown> {\n const path = normalizeApiPath(input.path);\n const allowed = input.method === 'GET' ? APPLE_READ_GET_ROOTS.test(path) : APPLE_READ_POST_ROOTS.test(path);\n if (!allowed) {\n throw new AdportError('INVALID_INPUT', `apple: unsupported read path \"${path}\"`);\n }\n const envelope = await this.client.request(input.method, path, {\n ...(input.account_id ? { adAccountId: input.account_id } : {}),\n ...(input.body ? { body: input.body } : {}),\n });\n return envelope;\n }\n\n async report(query: NormalizedQuery): Promise<Report> {\n if (query.level !== 'campaign' && query.level !== 'account') {\n throw new AdportError('INVALID_INPUT', 'apple: report supports campaign and account levels in v0');\n }\n const range = resolveDateRange(query.dateRange);\n const accountIds = query.accountIds ?? (await this.listAccounts()).map((a) => a.id);\n const rows: ReportRow[] = [];\n for (const adAccountId of accountIds) {\n const envelope = await this.client.request<{ rows?: ReportingRow[] }>(\n 'POST',\n 'reports/apps/campaigns/query',\n {\n adAccountId,\n body: {\n pagination: { offset: 0, pageSize: Math.min(query.limit ?? 200, 5000) },\n sorting: [{ field: 'id', order: 'ASC' }],\n timeRange: { start: range.start, end: range.end, timeZone: 'UTC' },\n options: { includeRows: ['GRAND_TOTAL'] },\n },\n },\n );\n const providerRows = (envelope.result?.rows ?? []).map((row) =>\n this.toReportRow(row, adAccountId, query),\n );\n if (query.level === 'account') {\n if (providerRows.length > 0) rows.push(aggregateAccountRows(providerRows, this.id, adAccountId));\n } else {\n rows.push(...providerRows);\n }\n }\n return { rows };\n }\n\n private toReportRow(row: ReportingRow, adAccountId: string, query: NormalizedQuery): ReportRow {\n const total = row.totalMetrics ?? {};\n const spend = Number(total.localSpend?.amount ?? 0);\n const impressions = total.impressions ?? 0;\n // Apple has taps, not clicks; installs are the conversion event. No revenue metric exists.\n const clicks = total.taps ?? 0;\n const conversions = total.totalInstalls ?? 0;\n const all: Record<MetricName, number> = {\n spend: round2(spend),\n impressions,\n clicks,\n conversions,\n conversion_value: 0,\n ctr: impressions > 0 ? round2((clicks / impressions) * 100) : 0,\n cpc: clicks > 0 ? round2(spend / clicks) : 0,\n cpm: impressions > 0 ? round2((spend / impressions) * 1000) : 0,\n cpa: conversions > 0 ? round2(spend / conversions) : 0,\n roas: 0,\n };\n return {\n provider: this.id,\n accountId: adAccountId,\n entity: {\n level: 'campaign',\n id: String(row.metadata?.id ?? ''),\n name: row.metadata?.name ?? '',\n status: row.metadata?.status,\n },\n metrics: Object.fromEntries(query.metrics.map((m) => [m, all[m]])),\n };\n }\n\n async previewWrite(op: WriteOperation, guard: WriteGuard): Promise<WritePreview> {\n const plan = await this.plan(op, guard);\n return {\n summary: plan.summary,\n changes: plan.changes,\n coercions: plan.coercions,\n budgetDeltas: plan.budgetDeltas,\n serverValidated: false,\n };\n }\n\n async applyWrite(op: WriteOperation, guard: WriteGuard): Promise<WriteResult> {\n const plan = await this.plan(op, guard);\n const resourceIds = await plan.execute();\n return { applied: true, resourceIds };\n }\n\n private async plan(op: WriteOperation, guard: WriteGuard): Promise<WritePlan> {\n const payload = op.payload as never;\n switch (op.tool) {\n case 'apple_create_campaign':\n return this.planCreateCampaign(op.accountId, payload, guard);\n case 'apple_create_ad_group':\n return this.planCreateAdGroup(op.accountId, payload, guard);\n case 'apple_create_keyword':\n return this.planCreateKeyword(op.accountId, payload, guard);\n case 'apple_set_campaign_status':\n return this.planSetStatus(op.accountId, payload);\n case 'apple_set_budget':\n return this.planSetBudget(op.accountId, payload);\n case 'apple_api_create':\n return this.planApiCreate(op.accountId, payload, guard);\n case 'apple_api_update':\n return this.planApiUpdate(op.accountId, payload);\n case 'apple_api_delete':\n return this.planApiDelete(op.accountId, payload);\n case 'apple_upload_asset':\n return this.planUploadAsset(op.accountId, payload);\n case 'apple_apply_recommendations':\n return this.planApplyRecommendations(op.accountId, payload);\n case 'apple_dismiss_recommendations':\n return this.planDismissRecommendations(op.accountId, payload);\n case 'apple_set_bid':\n return this.planSetBid(op.accountId, payload);\n case 'apple_set_shared_budget':\n return this.planSetSharedBudget(op.accountId, payload);\n default:\n throw new AdportError('PROVIDER_ERROR', `apple: unsupported write tool ${op.tool}`);\n }\n }\n\n private async planCreateCampaign(\n adAccountId: string,\n payload: {\n name: string;\n adam_id: number;\n countries_or_regions: string[];\n daily_budget: number;\n currency: string;\n status?: string;\n },\n guard: WriteGuard,\n ): Promise<WritePlan> {\n const coercions: string[] = [];\n let status = payload.status ?? 'ENABLED';\n if (guard.forcePausedCreation && status === 'ENABLED') {\n status = 'PAUSED';\n coercions.push('status coerced to PAUSED by policy (paused_creation)');\n }\n const body = {\n adAccountId: Number(adAccountId),\n name: payload.name,\n promotedObjectType: 'APPSTORE_APP',\n promotedObjectId: String(payload.adam_id),\n dailyBudget: { value: { amount: String(payload.daily_budget), currency: payload.currency } },\n billingEvent: 'TAPS',\n bidStrategy: { bidStrategyType: 'MANUAL_CPT', bidStrategyGoal: 'TAP' },\n targeting: {\n countryOrRegion: { include: payload.countries_or_regions },\n supplyPlacement: { include: ['APPSTORE_SEARCH_RESULTS'] },\n },\n status,\n };\n return {\n summary: `Create Apple Ads campaign \"${payload.name}\" (${status}) — daily budget ${payload.daily_budget} ${payload.currency}`,\n changes: [\n `+ campaign \"${payload.name}\" app=${payload.adam_id} regions=[${payload.countries_or_regions.join(', ')}] status=${status}`,\n ],\n coercions,\n budgetDeltas: [\n { target: `new campaign \"${payload.name}\" daily budget`, toMicros: payload.daily_budget * UNITS_TO_MICROS },\n ],\n execute: async () => {\n const envelope = await this.client.request<AppleCampaign>('POST', 'campaigns', { adAccountId, body });\n return envelope.result?.id ? [String(envelope.result.id)] : [];\n },\n };\n }\n\n private async planSetStatus(\n adAccountId: string,\n payload: { campaign_id: string; status: 'ENABLED' | 'PAUSED' },\n ): Promise<WritePlan> {\n const current = await this.getCampaign(adAccountId, payload.campaign_id);\n return {\n summary: `Set Apple campaign \"${current.name}\" status ${current.status} → ${payload.status}`,\n changes: [`~ campaign ${payload.campaign_id} status ${current.status} → ${payload.status}`],\n coercions: [],\n budgetDeltas: [],\n execute: async () => {\n await this.client.request('PUT', `campaigns/${payload.campaign_id}`, {\n adAccountId,\n body: { status: payload.status },\n });\n return [payload.campaign_id];\n },\n };\n }\n\n private async planCreateAdGroup(\n adAccountId: string,\n payload: {\n campaign_id: string;\n name: string;\n bid: number;\n currency: string;\n status?: 'ENABLED' | 'PAUSED';\n device_classes?: Array<'IPHONE' | 'IPAD'>;\n automated_keywords_opt_in?: boolean;\n start_time?: string;\n end_time?: string;\n },\n guard: WriteGuard,\n ): Promise<WritePlan> {\n const coercions: string[] = [];\n let status = payload.status ?? 'ENABLED';\n if (guard.forcePausedCreation && status === 'ENABLED') {\n status = 'PAUSED';\n coercions.push('status coerced to PAUSED by policy (paused_creation)');\n }\n const body = {\n campaignId: Number(payload.campaign_id),\n name: payload.name,\n pricingModel: 'CPT',\n status,\n bidStrategy: {\n bidStrategyType: 'MANUAL_CPT',\n bidStrategyGoal: 'TAP',\n bid: { amount: String(payload.bid), currency: payload.currency },\n },\n ...(payload.device_classes?.length\n ? { targeting: { deviceClass: { include: payload.device_classes } } }\n : {}),\n ...(payload.automated_keywords_opt_in !== undefined\n ? { automatedKeywordsOptIn: payload.automated_keywords_opt_in }\n : {}),\n ...(payload.start_time ? { startTime: payload.start_time } : {}),\n ...(payload.end_time ? { endTime: payload.end_time } : {}),\n };\n return {\n summary: `Create Apple Ads ad group \"${payload.name}\" (${status}) — bid ${payload.bid} ${payload.currency}`,\n changes: [`+ ad group \"${payload.name}\" campaign=${payload.campaign_id} status=${status}`],\n coercions,\n budgetDeltas: [{\n target: `new ad group \"${payload.name}\" bid`,\n toMicros: payload.bid * UNITS_TO_MICROS,\n }],\n execute: async () => {\n const envelope = await this.client.request<{ id?: number }>('POST', 'adgroups', { adAccountId, body });\n return envelope.result?.id ? [String(envelope.result.id)] : [];\n },\n };\n }\n\n private async planCreateKeyword(\n adAccountId: string,\n payload: {\n ad_group_id: string;\n text: string;\n match_type: 'BROAD' | 'EXACT';\n bid?: number;\n currency?: string;\n status?: 'ENABLED' | 'PAUSED';\n },\n guard: WriteGuard,\n ): Promise<WritePlan> {\n const coercions: string[] = [];\n let status = payload.status ?? 'ENABLED';\n if (guard.forcePausedCreation && status === 'ENABLED') {\n status = 'PAUSED';\n coercions.push('status coerced to PAUSED by policy (paused_creation)');\n }\n if ((payload.bid === undefined) !== (payload.currency === undefined)) {\n throw new AdportError('INVALID_INPUT', 'apple: keyword bid and currency must be provided together');\n }\n const body = {\n adGroupId: Number(payload.ad_group_id),\n text: payload.text,\n matchType: payload.match_type,\n status,\n ...(payload.bid !== undefined && payload.currency\n ? { bid: { amount: String(payload.bid), currency: payload.currency } }\n : {}),\n };\n return {\n summary: `Create Apple Ads ${payload.match_type.toLowerCase()} keyword \"${payload.text}\" (${status})`,\n changes: [`+ keyword \"${payload.text}\" adGroup=${payload.ad_group_id} match=${payload.match_type} status=${status}`],\n coercions,\n budgetDeltas: payload.bid === undefined ? [] : [{\n target: `new keyword \"${payload.text}\" bid`,\n toMicros: payload.bid * UNITS_TO_MICROS,\n }],\n execute: async () => {\n const envelope = await this.client.request<{ id?: number }>('POST', 'keywords', { adAccountId, body });\n return envelope.result?.id ? [String(envelope.result.id)] : [];\n },\n };\n }\n\n private async planSetBudget(\n adAccountId: string,\n payload: { campaign_id: string; daily_budget: number },\n ): Promise<WritePlan> {\n const current = await this.getCampaign(adAccountId, payload.campaign_id);\n const fromAmount = current.dailyBudget?.value ? Number(current.dailyBudget.value.amount) : undefined;\n const currency = current.dailyBudget?.value?.currency ?? 'USD';\n return {\n summary: `Change Apple campaign \"${current.name}\" daily budget ${fromAmount ?? '(unset)'} → ${payload.daily_budget} ${currency}`,\n changes: [`~ campaign ${payload.campaign_id} dailyBudget.value ${fromAmount ?? '(unset)'} → ${payload.daily_budget}`],\n coercions: [],\n budgetDeltas: [\n {\n target: `campaign \"${current.name}\" daily budget`,\n ...(fromAmount !== undefined ? { fromMicros: fromAmount * UNITS_TO_MICROS } : {}),\n toMicros: payload.daily_budget * UNITS_TO_MICROS,\n },\n ],\n execute: async () => {\n await this.client.request('PUT', `campaigns/${payload.campaign_id}`, {\n adAccountId,\n body: { dailyBudget: { value: { amount: String(payload.daily_budget), currency } } },\n });\n return [payload.campaign_id];\n },\n };\n }\n\n private async planApiCreate(\n adAccountId: string,\n payload: { path: string; body: Record<string, unknown> },\n guard: WriteGuard,\n ): Promise<WritePlan> {\n const path = validateMutationPath(payload.path, 'create');\n const body = structuredClone(payload.body);\n const coercions: string[] = [];\n if (guard.forcePausedCreation) coerceCreatedStatuses(body, coercions);\n const budgetDeltas = collectCreatedMoney(body);\n return {\n summary: `Create Apple Ads resource via POST /${path}`,\n changes: [`+ POST /${path} ${JSON.stringify(body)}`],\n coercions,\n budgetDeltas,\n execute: async () => {\n // Ad-account creation is org-scoped. Apple explicitly rejects the\n // account context used by every other create endpoint.\n const envelope = await this.client.request<unknown>('POST', path, {\n ...(path === 'ad-accounts' ? {} : { adAccountId }),\n body,\n });\n return extractResourceIds(envelope.result);\n },\n };\n }\n\n private async planApiUpdate(\n adAccountId: string,\n payload: { path: string; body: Record<string, unknown> },\n ): Promise<WritePlan> {\n const path = validateMutationPath(payload.path, 'update');\n if (containsMoneyField(payload.body)) {\n throw new AdportError(\n 'INVALID_INPUT',\n 'apple: monetary updates require a typed budget or bid tool so current and proposed values can be policy-checked',\n );\n }\n return {\n summary: `Update Apple Ads resource via PUT /${path}`,\n changes: [`~ PUT /${path} ${JSON.stringify(payload.body)}`],\n coercions: [],\n budgetDeltas: [],\n execute: async () => {\n const method = path.endsWith('/bulk-update') ? 'POST' : 'PUT';\n const envelope = await this.client.request<unknown>(method, path, { adAccountId, body: payload.body });\n return extractResourceIds(envelope.result, path);\n },\n };\n }\n\n private async planApiDelete(adAccountId: string, payload: { path: string }): Promise<WritePlan> {\n const path = validateMutationPath(payload.path, 'delete');\n return {\n summary: `Delete Apple Ads resource via DELETE /${path}`,\n changes: [`- DELETE /${path}`],\n coercions: [],\n budgetDeltas: [],\n execute: async () => {\n await this.client.request('DELETE', path, { adAccountId });\n return [path.split('/').at(-1)!];\n },\n };\n }\n\n private async planUploadAsset(\n adAccountId: string,\n payload: {\n file_path: string;\n expected_sha256: string;\n promoted_object_id: string;\n promoted_object_type: 'BUSINESS_BRAND';\n },\n ): Promise<WritePlan> {\n const file = await readFile(payload.file_path);\n const actualSha256 = createHash('sha256').update(file).digest('hex');\n if (actualSha256 !== payload.expected_sha256.toLowerCase()) {\n throw new AdportError(\n 'INVALID_INPUT',\n `apple: asset SHA-256 mismatch for ${payload.file_path}; expected ${payload.expected_sha256}, got ${actualSha256}`,\n );\n }\n const contentType = assetContentType(payload.file_path);\n return {\n summary: `Upload Apple Ads asset ${basename(payload.file_path)} (${file.byteLength} bytes)`,\n changes: [`+ asset sha256=${actualSha256} promotedObject=${payload.promoted_object_id}`],\n coercions: [],\n budgetDeltas: [],\n execute: async () => {\n const form = new FormData();\n form.append('file', new Blob([file], { type: contentType }), basename(payload.file_path));\n form.append('promotedObjectId', payload.promoted_object_id);\n form.append('promotedObjectType', payload.promoted_object_type);\n const envelope = await this.client.request<unknown>('POST', 'assets/upload', { adAccountId, form });\n return extractResourceIds(envelope.result);\n },\n };\n }\n\n private async planApplyRecommendations(\n adAccountId: string,\n payload: {\n category: 'daily_budget' | 'target_cpa';\n promoted_object_id: string;\n promoted_object_type: 'APPSTORE_APP' | 'BUSINESS_BRAND';\n recommendations: Array<{ id: string; applied_amount?: number; currency?: string }>;\n },\n ): Promise<WritePlan> {\n const apiCategory = payload.category === 'daily_budget' ? 'daily-budgets' : 'target-cpas';\n const envelope = await this.client.request<AppleRecommendation[]>('POST', `recommendations/${apiCategory}/query`, {\n adAccountId,\n body: {\n filters: [\n { field: 'promotedObjectId', operator: 'EQUALS', value: [payload.promoted_object_id] },\n { field: 'promotedObjectType', operator: 'EQUALS', value: [payload.promoted_object_type] },\n ],\n pagination: { offset: 0, pageSize: 100 },\n },\n });\n const byId = new Map((envelope.result ?? []).map((recommendation) => [recommendation.id, recommendation]));\n const budgetDeltas: WritePreview['budgetDeltas'] = [];\n const requestBody = payload.recommendations.map((item) => {\n const recommendation = byId.get(item.id);\n if (!recommendation) {\n throw new AdportError('INVALID_INPUT', `apple: recommendation ${item.id} was not returned by the current v1 query`);\n }\n const current = payload.category === 'daily_budget'\n ? recommendation.dailyBudget\n : recommendation.bidStrategy?.bidAmount;\n const suggested = payload.category === 'daily_budget'\n ? recommendation.suggestedDailyBudgetAmount\n : recommendation.recommendedTargetCPA;\n const amount = item.applied_amount ?? Number(suggested?.amount);\n const currency = item.currency ?? suggested?.currency ?? current?.currency;\n if (!Number.isFinite(amount) || amount <= 0 || !currency) {\n throw new AdportError('INVALID_INPUT', `apple: recommendation ${item.id} has no usable proposed Money value`);\n }\n budgetDeltas.push({\n target: `${payload.category} recommendation ${item.id}${recommendation.campaignName ? ` (${recommendation.campaignName})` : ''}`,\n ...(current?.amount !== undefined ? { fromMicros: Number(current.amount) * UNITS_TO_MICROS } : {}),\n toMicros: amount * UNITS_TO_MICROS,\n });\n return {\n id: item.id,\n promotedObjectId: payload.promoted_object_id,\n promotedObjectType: payload.promoted_object_type,\n ...(payload.category === 'daily_budget'\n ? { appliedDailyBudget: { amount: String(amount), currency } }\n : { appliedTargetCPA: { amount: String(amount), currency } }),\n };\n });\n return {\n summary: `Apply ${requestBody.length} Apple Ads ${payload.category.replace('_', ' ')} recommendation(s)`,\n changes: requestBody.map((item) => `~ apply recommendation ${item.id}`),\n coercions: [],\n budgetDeltas,\n execute: async () => {\n const applied = await this.client.request<unknown[]>('POST', `recommendations/${apiCategory}/apply`, {\n adAccountId,\n body: requestBody,\n });\n return extractResourceIds(applied.result).length > 0\n ? extractResourceIds(applied.result)\n : requestBody.map((item) => item.id);\n },\n };\n }\n\n private async planDismissRecommendations(\n adAccountId: string,\n payload: {\n category: 'daily_budget' | 'target_cpa';\n promoted_object_id: string;\n promoted_object_type: 'APPSTORE_APP' | 'BUSINESS_BRAND';\n recommendation_ids: string[];\n },\n ): Promise<WritePlan> {\n const apiCategory = payload.category === 'daily_budget' ? 'daily-budgets' : 'target-cpas';\n const body = payload.recommendation_ids.map((id) => ({\n id,\n promotedObjectId: payload.promoted_object_id,\n promotedObjectType: payload.promoted_object_type,\n }));\n return {\n summary: `Dismiss ${body.length} Apple Ads ${payload.category.replace('_', ' ')} recommendation(s)`,\n changes: body.map((item) => `~ dismiss recommendation ${item.id}`),\n coercions: [],\n budgetDeltas: [],\n execute: async () => {\n await this.client.request('POST', `recommendations/${apiCategory}/dismiss`, { adAccountId, body });\n return payload.recommendation_ids;\n },\n };\n }\n\n private async planSetBid(\n adAccountId: string,\n payload: {\n resource_type: 'campaign' | 'ad_group' | 'keyword';\n resource_id: string;\n amount: number;\n currency?: string;\n },\n ): Promise<WritePlan> {\n const collection = payload.resource_type === 'ad_group' ? 'adgroups' : `${payload.resource_type}s`;\n const envelope = await this.client.request<AppleBiddableResource>('GET', `${collection}/${payload.resource_id}`, {\n adAccountId,\n });\n const current = envelope.result;\n if (!current) throw new AdportError('PROVIDER_ERROR', `apple: ${payload.resource_type} ${payload.resource_id} not found`);\n const currentMoney = payload.resource_type === 'keyword' ? current.bid : current.bidStrategy?.bid;\n const currency = payload.currency ?? currentMoney?.currency;\n if (!currency) {\n throw new AdportError('INVALID_INPUT', 'apple: currency is required when the resource has no existing bid');\n }\n const money = { amount: String(payload.amount), currency };\n const body = payload.resource_type === 'keyword'\n ? { bid: money }\n : { bidStrategy: { ...current.bidStrategy, bid: money } };\n return {\n summary: `Change Apple ${payload.resource_type.replace('_', ' ')} \"${current.name ?? payload.resource_id}\" bid ${currentMoney?.amount ?? '(unset)'} → ${payload.amount} ${currency}`,\n changes: [`~ ${collection}/${payload.resource_id} bid ${currentMoney?.amount ?? '(unset)'} → ${payload.amount}`],\n coercions: [],\n budgetDeltas: [{\n target: `${payload.resource_type} ${payload.resource_id} bid`,\n ...(currentMoney?.amount !== undefined ? { fromMicros: Number(currentMoney.amount) * UNITS_TO_MICROS } : {}),\n toMicros: payload.amount * UNITS_TO_MICROS,\n }],\n execute: async () => {\n await this.client.request('PUT', `${collection}/${payload.resource_id}`, { adAccountId, body });\n return [payload.resource_id];\n },\n };\n }\n\n private async planSetSharedBudget(\n adAccountId: string,\n payload: { shared_budget_id: string; amount: number; currency?: string },\n ): Promise<WritePlan> {\n const envelope = await this.client.request<{ id?: number; name?: string; value?: Money }>(\n 'GET', `shared-budgets/${payload.shared_budget_id}`, { adAccountId },\n );\n const current = envelope.result;\n if (!current) throw new AdportError('PROVIDER_ERROR', `apple: shared budget ${payload.shared_budget_id} not found`);\n const currency = payload.currency ?? current.value?.currency;\n if (!currency) throw new AdportError('INVALID_INPUT', 'apple: currency is required when the shared budget has no existing value');\n return {\n summary: `Change Apple shared budget \"${current.name ?? payload.shared_budget_id}\" ${current.value?.amount ?? '(unset)'} → ${payload.amount} ${currency}`,\n changes: [`~ shared-budgets/${payload.shared_budget_id} value ${current.value?.amount ?? '(unset)'} → ${payload.amount}`],\n coercions: [],\n budgetDeltas: [{\n target: `shared budget ${payload.shared_budget_id}`,\n ...(current.value?.amount !== undefined ? { fromMicros: Number(current.value.amount) * UNITS_TO_MICROS } : {}),\n toMicros: payload.amount * UNITS_TO_MICROS,\n }],\n execute: async () => {\n await this.client.request('PUT', `shared-budgets/${payload.shared_budget_id}`, {\n adAccountId,\n body: { value: { amount: String(payload.amount), currency } },\n });\n return [payload.shared_budget_id];\n },\n };\n }\n}\n\nfunction assetContentType(path: string): string {\n switch (extname(path).toLowerCase()) {\n case '.png': return 'image/png';\n case '.jpg':\n case '.jpeg': return 'image/jpeg';\n case '.heic': return 'image/heic';\n default:\n throw new AdportError('INVALID_INPUT', 'apple: asset file must be PNG, JPG/JPEG, or HEIC');\n }\n}\n\nfunction normalizeApiPath(path: string): string {\n const normalized = path.replace(/^\\/+/, '').trim();\n if (!normalized || normalized.includes('://') || normalized.includes('..') || normalized.includes('#')) {\n throw new AdportError('INVALID_INPUT', 'apple: path must be a relative API path without traversal or fragments');\n }\n return normalized;\n}\n\nfunction validateMutationPath(path: string, operation: 'create' | 'update' | 'delete'): string {\n const normalized = normalizeApiPath(path);\n const allowed = operation === 'create'\n ? APPLE_CREATE_PATHS.test(normalized)\n : operation === 'update'\n ? APPLE_UPDATE_PATHS.test(normalized)\n : APPLE_DELETE_PATHS.test(normalized);\n if (!allowed) {\n throw new AdportError('INVALID_INPUT', `apple: unsupported mutation path \"${normalized}\"`);\n }\n return normalized;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction coerceCreatedStatuses(value: unknown, coercions: string[], path = 'body'): void {\n if (Array.isArray(value)) {\n value.forEach((item, index) => coerceCreatedStatuses(item, coercions, `${path}[${index}]`));\n return;\n }\n if (!isRecord(value)) return;\n for (const [key, child] of Object.entries(value)) {\n if ((key === 'status' || key === 'campaignStatus' || key === 'adGroupStatus') && child === 'ENABLED') {\n value[key] = 'PAUSED';\n coercions.push(`${path}.${key} coerced to PAUSED by policy (paused_creation)`);\n } else {\n coerceCreatedStatuses(child, coercions, `${path}.${key}`);\n }\n }\n}\n\nfunction isMoneyKey(key: string): boolean {\n return /(budget|bidAmount|cpaGoal)/i.test(key);\n}\n\nfunction isMoneyRecord(value: unknown): value is Record<string, unknown> & { amount: string | number } {\n return isRecord(value) && (typeof value.amount === 'string' || typeof value.amount === 'number') &&\n (value.currency === undefined || typeof value.currency === 'string');\n}\n\nfunction containsMoneyField(value: unknown): boolean {\n if (Array.isArray(value)) return value.some(containsMoneyField);\n if (!isRecord(value)) return false;\n if (isMoneyRecord(value)) return true;\n return Object.entries(value).some(([key, child]) => isMoneyKey(key) || containsMoneyField(child));\n}\n\nfunction collectCreatedMoney(value: unknown, path = 'body'): WritePreview['budgetDeltas'] {\n const deltas: WritePreview['budgetDeltas'] = [];\n if (Array.isArray(value)) {\n value.forEach((item, index) => deltas.push(...collectCreatedMoney(item, `${path}[${index}]`)));\n return deltas;\n }\n if (!isRecord(value)) return deltas;\n if (isMoneyRecord(value)) {\n const amount = Number(value.amount);\n return Number.isFinite(amount) && amount >= 0\n ? [{ target: path, toMicros: Math.round(amount * UNITS_TO_MICROS) }]\n : [];\n }\n for (const [key, child] of Object.entries(value)) {\n const childPath = `${path}.${key}`;\n if (isMoneyKey(key) && !isMoneyRecord(child)) {\n const amount = isRecord(child) ? Number(child.amount) : Number(child);\n if (Number.isFinite(amount) && amount >= 0) {\n deltas.push({ target: childPath, toMicros: Math.round(amount * UNITS_TO_MICROS) });\n }\n }\n deltas.push(...collectCreatedMoney(child, childPath));\n }\n return deltas;\n}\n\nfunction extractResourceIds(value: unknown, fallback?: string): string[] {\n const ids: string[] = [];\n const visit = (item: unknown) => {\n if (Array.isArray(item)) return item.forEach(visit);\n if (!isRecord(item)) return;\n if (item.id !== undefined) ids.push(String(item.id));\n for (const child of Object.values(item)) visit(child);\n };\n visit(value);\n return ids.length > 0 ? [...new Set(ids)] : fallback ? [fallback.split('/').at(-1)!] : [];\n}\n\nfunction aggregateAccountRows(rows: ReportRow[], provider: string, accountId: string): ReportRow {\n const metrics = Object.fromEntries(\n Object.keys(rows[0]!.metrics).map((metric) => [\n metric,\n round2(rows.reduce((sum, row) => sum + (row.metrics[metric as MetricName] ?? 0), 0)),\n ]),\n ) as Partial<Record<MetricName, number>>;\n const spend = metrics.spend ?? 0;\n const impressions = metrics.impressions ?? 0;\n const clicks = metrics.clicks ?? 0;\n const conversions = metrics.conversions ?? 0;\n const conversionValue = metrics.conversion_value ?? 0;\n if ('ctr' in metrics) metrics.ctr = impressions > 0 ? round2((clicks / impressions) * 100) : 0;\n if ('cpc' in metrics) metrics.cpc = clicks > 0 ? round2(spend / clicks) : 0;\n if ('cpm' in metrics) metrics.cpm = impressions > 0 ? round2((spend / impressions) * 1000) : 0;\n if ('cpa' in metrics) metrics.cpa = conversions > 0 ? round2(spend / conversions) : 0;\n if ('roas' in metrics) metrics.roas = spend > 0 ? round2(conversionValue / spend) : 0;\n return { provider, accountId, entity: { level: 'account', id: accountId, name: accountId }, metrics };\n}\n\nfunction round2(n: number): number {\n return Math.round(n * 100) / 100;\n}\n","import { defineTool, guardedWriteTool, type AnyToolDefinition } from '@adport/core';\nimport { z } from 'zod';\nimport type { AppleAdsProvider } from './provider.js';\n\nconst statusSchema = z.enum(['ENABLED', 'PAUSED']);\n\nexport function appleTools(provider: AppleAdsProvider): AnyToolDefinition[] {\n return [\n defineTool({\n name: 'apple_api_read',\n namespace: 'apple',\n description:\n 'Call any documented Apple Ads Platform API v1 read, query, insight, suggestion, recommendation-query, or report endpoint.',\n input: z.object({\n account_id: z.string().optional().describe('Apple Ads adAccountId; omit only for unscoped endpoints such as acls and me'),\n method: z.enum(['GET', 'POST']).default('GET'),\n path: z.string().min(1).describe('Relative v1 path, for example campaigns/query or reports/apps/campaigns/query'),\n body: z.record(z.string(), z.unknown()).optional().describe('Query, reporting, insight, or suggestion request for POST reads'),\n }),\n annotations: { readOnly: true },\n async handler(input) {\n return provider.apiRead(input);\n },\n }),\n defineTool({\n name: 'apple_campaigns',\n namespace: 'apple',\n description:\n 'List Apple Ads Platform API v1 campaigns for an ad account.',\n input: z.object({\n account_id: z.string().describe('Apple Ads ad account id (adAccountId)'),\n limit: z.number().int().positive().max(5000).default(100),\n }),\n annotations: { readOnly: true },\n async handler(input) {\n const campaigns = await provider.listCampaigns(input.account_id, input.limit);\n return { campaigns };\n },\n }),\n guardedWriteTool({\n name: 'apple_create_campaign',\n namespace: 'apple',\n description:\n 'Create an Apple Ads Platform API v1 App Store campaign (search results, TAPS billing). ' +\n 'daily_budget is a float in whole currency units; adam_id is the App Store app id. ' +\n 'Apple has no dry run — previews are client-side diffs.',\n provider: 'apple',\n kind: 'create',\n payload: z.object({\n name: z.string().min(1),\n adam_id: z.number().int().positive().describe('App Store app id (adamId)'),\n countries_or_regions: z.array(z.string().length(2)).min(1),\n daily_budget: z.number().positive(),\n currency: z.string().length(3).describe('Org currency, e.g. USD/EUR'),\n status: statusSchema.optional(),\n }),\n }),\n guardedWriteTool({\n name: 'apple_set_campaign_status',\n namespace: 'apple',\n description: 'Enable or pause an Apple Ads campaign.',\n provider: 'apple',\n kind: 'update',\n payload: z.object({ campaign_id: z.string(), status: statusSchema }),\n }),\n guardedWriteTool({\n name: 'apple_create_ad_group',\n namespace: 'apple',\n description:\n 'Create an Apple Ads Platform API v1 App Store ad group using CPT pricing and a MANUAL_CPT/TAP bid strategy. The typed tool emits the documented bidStrategy.bid Money shape.',\n provider: 'apple',\n kind: 'create',\n payload: z.object({\n campaign_id: z.string().min(1),\n name: z.string().min(1),\n bid: z.number().positive(),\n currency: z.string().length(3),\n status: statusSchema.optional(),\n device_classes: z.array(z.enum(['IPHONE', 'IPAD'])).min(1).optional(),\n automated_keywords_opt_in: z.boolean().optional(),\n start_time: z.string().min(1).optional(),\n end_time: z.string().min(1).optional(),\n }),\n }),\n guardedWriteTool({\n name: 'apple_create_keyword',\n namespace: 'apple',\n description:\n 'Create a documented Apple Ads Platform API v1 keyword. Omit bid and currency together to inherit the ad-group bid.',\n provider: 'apple',\n kind: 'create',\n payload: z.object({\n ad_group_id: z.string().min(1),\n text: z.string().min(1),\n match_type: z.enum(['BROAD', 'EXACT']),\n bid: z.number().positive().optional(),\n currency: z.string().length(3).optional(),\n status: statusSchema.optional(),\n }).refine((value) => (value.bid === undefined) === (value.currency === undefined), {\n message: 'bid and currency must be provided together',\n }),\n }),\n guardedWriteTool({\n name: 'apple_set_budget',\n namespace: 'apple',\n description: \"Change an Apple Ads campaign's daily budget (float, whole currency units).\",\n provider: 'apple',\n kind: 'update',\n payload: z.object({ campaign_id: z.string(), daily_budget: z.number().positive() }),\n }),\n guardedWriteTool({\n name: 'apple_api_create',\n namespace: 'apple',\n description:\n 'Create a documented Apple Ads Platform API v1 entity using a relative endpoint and API-shaped body. ' +\n 'For adgroups, v1 requires pricingModel and bidStrategy.bid Money; defaultBid and defaultBidAmount are not v1 fields. ' +\n 'Also supports keyword and negative-keyword bulk-create. Created ENABLED statuses are coerced to PAUSED; budget/bid Money fields are reported to policy.',\n provider: 'apple',\n kind: 'create',\n payload: z.object({\n path: z.string().min(1),\n body: z.record(z.string(), z.unknown()),\n }),\n }),\n guardedWriteTool({\n name: 'apple_api_update',\n namespace: 'apple',\n description:\n 'Update a documented non-monetary Apple Ads Platform API v1 entity. Also supports keyword and negative-keyword bulk-update. Budget/bid changes are rejected here and require typed tools with current-value policy checks.',\n provider: 'apple',\n kind: 'update',\n payload: z.object({\n path: z.string().min(1),\n body: z.record(z.string(), z.unknown()),\n }),\n }),\n guardedWriteTool({\n name: 'apple_api_delete',\n namespace: 'apple',\n description: 'Delete a documented Apple Ads Platform API v1 campaign-management entity by relative path.',\n provider: 'apple',\n kind: 'remove',\n destructive: true,\n payload: z.object({ path: z.string().min(1) }),\n }),\n guardedWriteTool({\n name: 'apple_upload_asset',\n namespace: 'apple',\n description:\n 'Upload a PNG, JPG/JPEG, or HEIC creative asset for a Business Brand. The required SHA-256 binds the exact local file contents to the preview/apply approval.',\n provider: 'apple',\n kind: 'create',\n payload: z.object({\n file_path: z.string().min(1),\n expected_sha256: z.string().regex(/^[a-fA-F0-9]{64}$/),\n promoted_object_id: z.string().min(1),\n promoted_object_type: z.literal('BUSINESS_BRAND').default('BUSINESS_BRAND'),\n }),\n }),\n guardedWriteTool({\n name: 'apple_apply_recommendations',\n namespace: 'apple',\n description:\n 'Apply Apple Ads v1 daily-budget or target-CPA recommendations. The provider re-queries every recommendation and policy-checks the current and proposed Money values before apply.',\n provider: 'apple',\n kind: 'update',\n payload: z.object({\n category: z.enum(['daily_budget', 'target_cpa']),\n promoted_object_id: z.string().min(1),\n promoted_object_type: z.enum(['APPSTORE_APP', 'BUSINESS_BRAND']),\n recommendations: z.array(z.object({\n id: z.string().min(1),\n applied_amount: z.number().positive().optional(),\n currency: z.string().length(3).optional(),\n })).min(1),\n }),\n }),\n guardedWriteTool({\n name: 'apple_dismiss_recommendations',\n namespace: 'apple',\n description: 'Dismiss Apple Ads v1 daily-budget or target-CPA recommendations through the normal preview/apply gate.',\n provider: 'apple',\n kind: 'update',\n payload: z.object({\n category: z.enum(['daily_budget', 'target_cpa']),\n promoted_object_id: z.string().min(1),\n promoted_object_type: z.enum(['APPSTORE_APP', 'BUSINESS_BRAND']),\n recommendation_ids: z.array(z.string().min(1)).min(1),\n }),\n }),\n guardedWriteTool({\n name: 'apple_set_bid',\n namespace: 'apple',\n description:\n 'Change a v1 campaign, ad-group, or keyword bid after fetching the current Money value for policy enforcement.',\n provider: 'apple',\n kind: 'update',\n payload: z.object({\n resource_type: z.enum(['campaign', 'ad_group', 'keyword']),\n resource_id: z.string().min(1),\n amount: z.number().positive(),\n currency: z.string().length(3).optional(),\n }),\n }),\n guardedWriteTool({\n name: 'apple_set_shared_budget',\n namespace: 'apple',\n description: 'Change an Apple Ads v1 shared-budget value after fetching its current Money value.',\n provider: 'apple',\n kind: 'update',\n payload: z.object({\n shared_budget_id: z.string().min(1),\n amount: z.number().positive(),\n currency: z.string().length(3).optional(),\n }),\n }),\n ];\n}\n","import type { CredentialStore, ProviderModule } from '@adport/core';\nimport { AppleAdsClient, type AppleCredentials } from './client.js';\nimport { AppleAdsProvider } from './provider.js';\nimport { appleTools } from './tools.js';\n\nexport { AppleAdsClient, APPLE_ADS_BASE, formatAppleError, type AppleCredentials, type AppleEnvelope } from './client.js';\nexport { createClientSecret, type ClientSecretInput } from './jwt.js';\nexport { AppleAdsProvider, UNITS_TO_MICROS } from './provider.js';\nexport { appleTools } from './tools.js';\n\nexport async function resolveAppleCredentials(store: CredentialStore): Promise<AppleCredentials | undefined> {\n const record = await store.get('apple');\n if (record?.data.client_id && record.data.team_id && record.data.key_id && record.data.private_key) {\n return {\n clientId: record.data.client_id,\n teamId: record.data.team_id,\n keyId: record.data.key_id,\n privateKeyPem: record.data.private_key,\n };\n }\n const env = process.env;\n if (env.APPLE_ADS_CLIENT_ID && env.APPLE_ADS_TEAM_ID && env.APPLE_ADS_KEY_ID && env.APPLE_ADS_PRIVATE_KEY) {\n return {\n clientId: env.APPLE_ADS_CLIENT_ID,\n teamId: env.APPLE_ADS_TEAM_ID,\n keyId: env.APPLE_ADS_KEY_ID,\n privateKeyPem: env.APPLE_ADS_PRIVATE_KEY,\n };\n }\n return undefined;\n}\n\nexport async function createAppleModule(store: CredentialStore): Promise<ProviderModule | undefined> {\n const credentials = await resolveAppleCredentials(store);\n if (!credentials) return undefined;\n const provider = new AppleAdsProvider(new AppleAdsClient(credentials));\n return { provider, tools: appleTools(provider) };\n}\n"],"mappings":"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","names":["AdportError"]}
|
|
1
|
+
{"version":3,"sources":["../src/client.ts","../src/jwt.ts","../src/provider.ts","../src/tools.ts","../src/index.ts"],"sourcesContent":["import { AdportError } from '@adport/core';\nimport { createClientSecret } from './jwt.js';\n\nexport interface AppleCredentials {\n clientId: string;\n teamId: string;\n keyId: string;\n /** PEM contents of the .p8 EC private key. */\n privateKeyPem: string;\n /** Delegated service-provider grant. Omit for a self-managed API user. */\n refreshToken?: string;\n}\n\nconst TOKEN_URL = 'https://appleid.apple.com/auth/oauth2/token';\n\n/** Apple Ads Platform API v1. The legacy Campaign Management API v5 retires 2027-01-26. */\nexport const APPLE_ADS_BASE = 'https://api.ads.apple.com/v1';\n\nexport interface AppleEnvelope<T> {\n result: T;\n pagination?: { offset?: number; pageSize?: number; totalCount?: number } | null;\n error?: {\n code?: string;\n message?: string;\n details?: Array<{ code?: string; message?: string }>;\n } | null;\n}\n\nexport class AppleAdsClient {\n private accessToken?: { token: string; expiresAt: number };\n\n constructor(\n private readonly credentials: AppleCredentials,\n private readonly fetchImpl: typeof fetch = fetch,\n ) {}\n\n async getAccessToken(): Promise<string> {\n if (this.accessToken && this.accessToken.expiresAt > Date.now()) {\n return this.accessToken.token;\n }\n // Mint a fresh short-lived client secret per request — no stored client-secret rotation.\n const clientSecret = createClientSecret(this.credentials);\n const tokenParams = new URLSearchParams(this.credentials.refreshToken\n ? {\n grant_type: 'refresh_token',\n client_id: this.credentials.clientId,\n client_secret: clientSecret,\n refresh_token: this.credentials.refreshToken,\n }\n : {\n grant_type: 'client_credentials',\n client_id: this.credentials.clientId,\n client_secret: clientSecret,\n scope: 'searchadsorg',\n });\n const response = await this.fetchImpl(TOKEN_URL, {\n method: 'POST',\n headers: { 'content-type': 'application/x-www-form-urlencoded' },\n body: tokenParams,\n });\n const raw = await response.text();\n if (!response.ok) {\n throw new AdportError(\n 'PROVIDER_ERROR',\n `Apple Ads OAuth failed (${response.status}). Check the client identity, uploaded public key, and delegated account access.`,\n safeJson(raw),\n );\n }\n const data = JSON.parse(raw) as { access_token: string; expires_in: number };\n this.accessToken = { token: data.access_token, expiresAt: Date.now() + (data.expires_in - 60) * 1000 };\n return this.accessToken.token;\n }\n\n /** adAccountId context is required on account-scoped endpoints. */\n async request<T>(\n method: 'GET' | 'POST' | 'PUT' | 'DELETE',\n path: string,\n options: { adAccountId?: string; body?: unknown; form?: FormData } = {},\n ): Promise<AppleEnvelope<T>> {\n const token = await this.getAccessToken();\n if (options.body !== undefined && options.form !== undefined) {\n throw new AdportError('INVALID_INPUT', 'Apple Ads request cannot contain both JSON and multipart bodies');\n }\n const response = await this.fetchImpl(`${APPLE_ADS_BASE}/${path.replace(/^\\//, '')}`, {\n method,\n headers: {\n authorization: `Bearer ${token}`,\n accept: 'application/json',\n ...(options.adAccountId ? { 'X-AP-Context': `adAccountId=${options.adAccountId}` } : {}),\n ...(options.body !== undefined ? { 'content-type': 'application/json' } : {}),\n },\n body: options.form ?? (options.body === undefined ? undefined : JSON.stringify(options.body)),\n });\n const raw = await response.text();\n if (!response.ok) {\n throw new AdportError('PROVIDER_ERROR', formatAppleError(response.status, raw), safeJson(raw));\n }\n return (raw ? JSON.parse(raw) : { result: undefined }) as AppleEnvelope<T>;\n }\n}\n\nfunction safeJson(raw: string): unknown {\n try {\n return JSON.parse(raw);\n } catch {\n return raw;\n }\n}\n\n/** v1 error shape: {\"error\":{\"code\",\"message\",\"details\":[{\"code\",\"message\"}]}}. */\nexport function formatAppleError(status: number, raw: string): string {\n const parsed = safeJson(raw) as {\n error?: { code?: string; message?: string; details?: Array<{ code?: string; message?: string }> };\n };\n const head = `Apple Ads API error (HTTP ${status})`;\n const error = parsed?.error;\n if (!error) return head;\n const lines = [\n error.code || error.message ? `${error.code ?? '?'}: ${error.message ?? ''}` : undefined,\n ...(error.details ?? []).map((detail) => `${detail.code ?? '?'}: ${detail.message ?? ''}`),\n ].filter((line): line is string => Boolean(line));\n const hint = status === 401 ? '\\n Token or ad-account access problem — check credentials and account roles.' : '';\n return lines.length > 0 ? `${head}\\n ${lines.join('\\n ')}${hint}` : `${head}${hint}`;\n}\n","import { createPrivateKey, sign } from 'node:crypto';\n\nexport interface ClientSecretInput {\n /** SEARCHADS.<uuid> */\n clientId: string;\n /** SEARCHADS.<uuid> — equals clientId for self-managed orgs. */\n teamId: string;\n /** keyId of the public key uploaded in the Apple Ads UI. */\n keyId: string;\n /** EC prime256v1 private key, PEM (.p8 contents). */\n privateKeyPem: string;\n /** Secret lifetime in seconds; Apple caps exp at iat + 180 days. */\n lifetimeSeconds?: number;\n}\n\nfunction b64url(data: Buffer | string): string {\n return Buffer.from(data).toString('base64url');\n}\n\n/**\n * Apple Ads client secret: a self-signed ES256 JWT (header {alg, kid}; claims\n * iss=teamId, sub=clientId, aud=https://appleid.apple.com, iat, exp≤iat+180d).\n * We mint a short-lived secret per token request instead of storing one.\n */\nexport function createClientSecret(input: ClientSecretInput, now = new Date()): string {\n const iat = Math.floor(now.getTime() / 1000);\n const lifetime = Math.min(input.lifetimeSeconds ?? 3600, 180 * 86_400 - 60);\n const header = { alg: 'ES256', kid: input.keyId };\n const payload = {\n iss: input.teamId,\n iat,\n exp: iat + lifetime,\n aud: 'https://appleid.apple.com',\n sub: input.clientId,\n };\n const signingInput = `${b64url(JSON.stringify(header))}.${b64url(JSON.stringify(payload))}`;\n const key = createPrivateKey(input.privateKeyPem);\n // JWS ES256 requires the raw r||s signature form, not ASN.1/DER.\n const signature = sign('sha256', Buffer.from(signingInput), { key, dsaEncoding: 'ieee-p1363' });\n return `${signingInput}.${b64url(signature)}`;\n}\n","import {\n AdportError,\n resolveDateRange,\n type Account,\n type AdProvider,\n type MetricName,\n type NormalizedQuery,\n type ProviderCapabilities,\n type Report,\n type ReportRow,\n type StandardActions,\n type WriteGuard,\n type WriteOperation,\n type WritePreview,\n type WriteResult,\n} from '@adport/core';\nimport { createHash } from 'node:crypto';\nimport { readFile } from 'node:fs/promises';\nimport { basename, extname } from 'node:path';\nimport { AppleAdsClient } from './client.js';\n\n/** Apple Money amounts are strings in whole currency units. */\nexport const UNITS_TO_MICROS = 1_000_000;\n\ninterface Money {\n amount: string;\n currency: string;\n}\n\ninterface AppleCampaign {\n id: number;\n adAccountId?: number;\n name: string;\n status: 'ENABLED' | 'PAUSED';\n systemStatus?: string;\n displayStatus?: string;\n dailyBudget?: { value?: Money };\n promotedObjectId?: string;\n promotedObjectType?: string;\n billingEvent?: string;\n targeting?: Record<string, unknown>;\n}\n\ninterface SpendRow {\n impressions?: number;\n taps?: number;\n ttr?: number;\n totalInstalls?: number;\n localSpend?: Money;\n tapInstallCPI?: Money;\n tapInstallRate?: number;\n}\n\ninterface ReportingRow {\n totalMetrics?: SpendRow;\n metadata?: { id?: number; name?: string; status?: string };\n}\n\ninterface WritePlan {\n summary: string;\n changes: string[];\n coercions: string[];\n budgetDeltas: WritePreview['budgetDeltas'];\n execute: () => Promise<string[]>;\n}\n\ninterface AppleRecommendation {\n id?: string;\n campaignId?: number;\n campaignName?: string;\n dailyBudget?: Money;\n suggestedDailyBudgetAmount?: Money;\n bidStrategy?: { bidAmount?: Money };\n recommendedTargetCPA?: Money;\n}\n\ninterface AppleBiddableResource {\n id?: number;\n name?: string;\n bid?: Money;\n bidStrategy?: { bidStrategyType?: string; bidStrategyGoal?: string; bid?: Money };\n}\n\nconst APPLE_READ_GET_ROOTS = /^(?:acls|me|advertiser-resources|ad-accounts\\/[^/?]+|adgroups\\/[^/?]+|ads\\/[^/?]+|apps\\/[^/?]+|assets\\/[^/?]+|business-brands\\/[^/?]+|business-categories\\/[^/?]+|campaigns\\/[^/?]+(?:\\/legacy-app-limited-status-reason-details)?|change-history\\/[^/?]+|creatives\\/[^/?]+|keywords\\/[^/?]+|location-groups\\/[^/?]+|locations\\/[^/?]+|negative-keywords\\/[^/?]+|orgs\\/[^/?]+|product-pages\\/[^/?]+|rejection-reasons\\/apps\\/[^/?]+|shared-budgets\\/[^/?]+|search\\/(?:apps|geo))(?:\\?.*)?$/;\nconst APPLE_READ_POST_ROOTS = /^(?:(?:adgroups|ads|assets|business-brands|business-categories|campaigns|change-history|creatives|eligibilities\\/apps|insights\\/apps\\/(?:impression-share|search-term-popularity)|keywords|location-groups|locations|metadata\\/apps\\/supported-languages|negative-keywords|product-pages(?:\\/locale-details)?|recommendations\\/(?:daily-budgets|target-cpas)|rejection-reasons\\/(?:apps|business-brands)|reports\\/(?:apps|business-brands)\\/(?:adgroups|ads|campaigns|keywords|searchterms)|shared-budgets|suggestions\\/(?:categories|keywords|phrases|target-cpas))\\/query|apps\\/[^/?]+\\/locale-details\\/query|search\\/geo)$/;\nconst APPLE_CREATE_PATHS = /^(?:ad-accounts|adgroups|ads|campaigns|creatives|keywords|keywords\\/bulk-create|location-groups|negative-keywords|negative-keywords\\/bulk-create|shared-budgets)$/;\nconst APPLE_UPDATE_PATHS = /^(?:ad-accounts|adgroups|ads|campaigns|creatives|keywords|location-groups|negative-keywords|shared-budgets)\\/[^/?]+$|^(?:keywords|negative-keywords)\\/bulk-update$/;\nconst APPLE_DELETE_PATHS = /^(?:adgroups|ads|assets|campaigns|creatives|keywords|location-groups|negative-keywords|shared-budgets)\\/[^/?]+$/;\n\nexport class AppleAdsProvider implements AdProvider {\n readonly id = 'apple';\n\n constructor(private readonly client: AppleAdsClient) {}\n\n capabilities(): ProviderCapabilities {\n // The Platform API has no validate-only mode — previews remain client-side.\n return { serverDryRun: false };\n }\n\n standardActions(): StandardActions {\n return {\n pauseCampaign: (accountId, campaignId) => ({\n tool: 'apple_set_campaign_status',\n input: { account_id: accountId, campaign_id: campaignId, status: 'PAUSED' },\n }),\n };\n }\n\n /** v1 exposes one ACL entry per ad account. */\n async listAccounts(): Promise<Account[]> {\n const envelope = await this.client.request<{\n acls?: Array<{ adAccount?: { id?: number; name?: string; orgId?: number }; roles?: string[] }>;\n }>('GET', 'acls');\n return (envelope.result?.acls ?? []).flatMap((acl) => (acl.adAccount?.id === undefined ? [] : [{\n provider: this.id,\n id: String(acl.adAccount.id),\n name: acl.adAccount.name ?? String(acl.adAccount.id),\n status: acl.roles?.join(',') || undefined,\n }]));\n }\n\n async listCampaigns(adAccountId: string, limit = 100): Promise<AppleCampaign[]> {\n const envelope = await this.client.request<AppleCampaign[]>('POST', 'campaigns/query', {\n adAccountId,\n body: { pagination: { offset: 0, pageSize: limit, fetchTotalCount: false } },\n });\n return envelope.result ?? [];\n }\n\n async getCampaign(adAccountId: string, campaignId: string): Promise<AppleCampaign> {\n const envelope = await this.client.request<AppleCampaign>('GET', `campaigns/${campaignId}`, { adAccountId });\n const campaign = envelope.result;\n if (!campaign) {\n throw new AdportError('PROVIDER_ERROR', `apple: campaign ${campaignId} not found in ad account ${adAccountId}`);\n }\n return campaign;\n }\n\n /**\n * Safe low-level access to the documented read surface. Apple uses POST for\n * selectors and reports, so method alone cannot determine mutability.\n */\n async apiRead(input: {\n account_id?: string;\n method: 'GET' | 'POST';\n path: string;\n body?: Record<string, unknown>;\n }): Promise<unknown> {\n const path = normalizeApiPath(input.path);\n const allowed = input.method === 'GET' ? APPLE_READ_GET_ROOTS.test(path) : APPLE_READ_POST_ROOTS.test(path);\n if (!allowed) {\n throw new AdportError('INVALID_INPUT', `apple: unsupported read path \"${path}\"`);\n }\n const envelope = await this.client.request(input.method, path, {\n ...(input.account_id ? { adAccountId: input.account_id } : {}),\n ...(input.body ? { body: input.body } : {}),\n });\n return envelope;\n }\n\n async report(query: NormalizedQuery): Promise<Report> {\n if (query.level !== 'campaign' && query.level !== 'account') {\n throw new AdportError('INVALID_INPUT', 'apple: report supports campaign and account levels in v0');\n }\n const range = resolveDateRange(query.dateRange);\n const accountIds = query.accountIds ?? (await this.listAccounts()).map((a) => a.id);\n const rows: ReportRow[] = [];\n for (const adAccountId of accountIds) {\n const envelope = await this.client.request<{ rows?: ReportingRow[] }>(\n 'POST',\n 'reports/apps/campaigns/query',\n {\n adAccountId,\n body: {\n pagination: { offset: 0, pageSize: Math.min(query.limit ?? 200, 5000) },\n sorting: [{ field: 'id', order: 'ASC' }],\n timeRange: { start: range.start, end: range.end, timeZone: 'UTC' },\n options: { includeRows: ['GRAND_TOTAL'] },\n },\n },\n );\n const providerRows = (envelope.result?.rows ?? []).map((row) =>\n this.toReportRow(row, adAccountId, query),\n );\n if (query.level === 'account') {\n if (providerRows.length > 0) rows.push(aggregateAccountRows(providerRows, this.id, adAccountId));\n } else {\n rows.push(...providerRows);\n }\n }\n return { rows };\n }\n\n private toReportRow(row: ReportingRow, adAccountId: string, query: NormalizedQuery): ReportRow {\n const total = row.totalMetrics ?? {};\n const spend = Number(total.localSpend?.amount ?? 0);\n const impressions = total.impressions ?? 0;\n // Apple has taps, not clicks; installs are the conversion event. No revenue metric exists.\n const clicks = total.taps ?? 0;\n const conversions = total.totalInstalls ?? 0;\n const all: Record<MetricName, number> = {\n spend: round2(spend),\n impressions,\n clicks,\n conversions,\n conversion_value: 0,\n ctr: impressions > 0 ? round2((clicks / impressions) * 100) : 0,\n cpc: clicks > 0 ? round2(spend / clicks) : 0,\n cpm: impressions > 0 ? round2((spend / impressions) * 1000) : 0,\n cpa: conversions > 0 ? round2(spend / conversions) : 0,\n roas: 0,\n };\n return {\n provider: this.id,\n accountId: adAccountId,\n entity: {\n level: 'campaign',\n id: String(row.metadata?.id ?? ''),\n name: row.metadata?.name ?? '',\n status: row.metadata?.status,\n },\n metrics: Object.fromEntries(query.metrics.map((m) => [m, all[m]])),\n };\n }\n\n async previewWrite(op: WriteOperation, guard: WriteGuard): Promise<WritePreview> {\n const plan = await this.plan(op, guard);\n return {\n summary: plan.summary,\n changes: plan.changes,\n coercions: plan.coercions,\n budgetDeltas: plan.budgetDeltas,\n serverValidated: false,\n };\n }\n\n async applyWrite(op: WriteOperation, guard: WriteGuard): Promise<WriteResult> {\n const plan = await this.plan(op, guard);\n const resourceIds = await plan.execute();\n return { applied: true, resourceIds };\n }\n\n private async plan(op: WriteOperation, guard: WriteGuard): Promise<WritePlan> {\n const payload = op.payload as never;\n switch (op.tool) {\n case 'apple_create_campaign':\n return this.planCreateCampaign(op.accountId, payload, guard);\n case 'apple_create_ad_group':\n return this.planCreateAdGroup(op.accountId, payload, guard);\n case 'apple_create_keyword':\n return this.planCreateKeyword(op.accountId, payload, guard);\n case 'apple_set_campaign_status':\n return this.planSetStatus(op.accountId, payload);\n case 'apple_set_budget':\n return this.planSetBudget(op.accountId, payload);\n case 'apple_api_create':\n return this.planApiCreate(op.accountId, payload, guard);\n case 'apple_api_update':\n return this.planApiUpdate(op.accountId, payload);\n case 'apple_api_delete':\n return this.planApiDelete(op.accountId, payload);\n case 'apple_upload_asset':\n return this.planUploadAsset(op.accountId, payload);\n case 'apple_apply_recommendations':\n return this.planApplyRecommendations(op.accountId, payload);\n case 'apple_dismiss_recommendations':\n return this.planDismissRecommendations(op.accountId, payload);\n case 'apple_set_bid':\n return this.planSetBid(op.accountId, payload);\n case 'apple_set_shared_budget':\n return this.planSetSharedBudget(op.accountId, payload);\n default:\n throw new AdportError('PROVIDER_ERROR', `apple: unsupported write tool ${op.tool}`);\n }\n }\n\n private async planCreateCampaign(\n adAccountId: string,\n payload: {\n name: string;\n adam_id: number;\n countries_or_regions: string[];\n daily_budget: number;\n currency: string;\n status?: string;\n },\n guard: WriteGuard,\n ): Promise<WritePlan> {\n const coercions: string[] = [];\n let status = payload.status ?? 'ENABLED';\n if (guard.forcePausedCreation && status === 'ENABLED') {\n status = 'PAUSED';\n coercions.push('status coerced to PAUSED by policy (paused_creation)');\n }\n const body = {\n adAccountId: Number(adAccountId),\n name: payload.name,\n promotedObjectType: 'APPSTORE_APP',\n promotedObjectId: String(payload.adam_id),\n dailyBudget: { value: { amount: String(payload.daily_budget), currency: payload.currency } },\n billingEvent: 'TAPS',\n bidStrategy: { bidStrategyType: 'MANUAL_CPT', bidStrategyGoal: 'TAP' },\n targeting: {\n countryOrRegion: { include: payload.countries_or_regions },\n supplyPlacement: { include: ['APPSTORE_SEARCH_RESULTS'] },\n },\n status,\n };\n return {\n summary: `Create Apple Ads campaign \"${payload.name}\" (${status}) — daily budget ${payload.daily_budget} ${payload.currency}`,\n changes: [\n `+ campaign \"${payload.name}\" app=${payload.adam_id} regions=[${payload.countries_or_regions.join(', ')}] status=${status}`,\n ],\n coercions,\n budgetDeltas: [\n { target: `new campaign \"${payload.name}\" daily budget`, toMicros: payload.daily_budget * UNITS_TO_MICROS },\n ],\n execute: async () => {\n const envelope = await this.client.request<AppleCampaign>('POST', 'campaigns', { adAccountId, body });\n return envelope.result?.id ? [String(envelope.result.id)] : [];\n },\n };\n }\n\n private async planSetStatus(\n adAccountId: string,\n payload: { campaign_id: string; status: 'ENABLED' | 'PAUSED' },\n ): Promise<WritePlan> {\n const current = await this.getCampaign(adAccountId, payload.campaign_id);\n return {\n summary: `Set Apple campaign \"${current.name}\" status ${current.status} → ${payload.status}`,\n changes: [`~ campaign ${payload.campaign_id} status ${current.status} → ${payload.status}`],\n coercions: [],\n budgetDeltas: [],\n execute: async () => {\n await this.client.request('PUT', `campaigns/${payload.campaign_id}`, {\n adAccountId,\n body: { status: payload.status },\n });\n return [payload.campaign_id];\n },\n };\n }\n\n private async planCreateAdGroup(\n adAccountId: string,\n payload: {\n campaign_id: string;\n name: string;\n bid: number;\n currency: string;\n status?: 'ENABLED' | 'PAUSED';\n device_classes?: Array<'IPHONE' | 'IPAD'>;\n automated_keywords_opt_in?: boolean;\n start_time?: string;\n end_time?: string;\n },\n guard: WriteGuard,\n ): Promise<WritePlan> {\n const coercions: string[] = [];\n let status = payload.status ?? 'ENABLED';\n if (guard.forcePausedCreation && status === 'ENABLED') {\n status = 'PAUSED';\n coercions.push('status coerced to PAUSED by policy (paused_creation)');\n }\n const body = {\n campaignId: Number(payload.campaign_id),\n name: payload.name,\n pricingModel: 'CPT',\n status,\n bidStrategy: {\n bidStrategyType: 'MANUAL_CPT',\n bidStrategyGoal: 'TAP',\n bid: { amount: String(payload.bid), currency: payload.currency },\n },\n ...(payload.device_classes?.length\n ? { targeting: { deviceClass: { include: payload.device_classes } } }\n : {}),\n ...(payload.automated_keywords_opt_in !== undefined\n ? { automatedKeywordsOptIn: payload.automated_keywords_opt_in }\n : {}),\n ...(payload.start_time ? { startTime: payload.start_time } : {}),\n ...(payload.end_time ? { endTime: payload.end_time } : {}),\n };\n return {\n summary: `Create Apple Ads ad group \"${payload.name}\" (${status}) — bid ${payload.bid} ${payload.currency}`,\n changes: [`+ ad group \"${payload.name}\" campaign=${payload.campaign_id} status=${status}`],\n coercions,\n budgetDeltas: [{\n target: `new ad group \"${payload.name}\" bid`,\n toMicros: payload.bid * UNITS_TO_MICROS,\n }],\n execute: async () => {\n const envelope = await this.client.request<{ id?: number }>('POST', 'adgroups', { adAccountId, body });\n return envelope.result?.id ? [String(envelope.result.id)] : [];\n },\n };\n }\n\n private async planCreateKeyword(\n adAccountId: string,\n payload: {\n ad_group_id: string;\n text: string;\n match_type: 'BROAD' | 'EXACT';\n bid?: number;\n currency?: string;\n status?: 'ENABLED' | 'PAUSED';\n },\n guard: WriteGuard,\n ): Promise<WritePlan> {\n const coercions: string[] = [];\n let status = payload.status ?? 'ENABLED';\n if (guard.forcePausedCreation && status === 'ENABLED') {\n status = 'PAUSED';\n coercions.push('status coerced to PAUSED by policy (paused_creation)');\n }\n if ((payload.bid === undefined) !== (payload.currency === undefined)) {\n throw new AdportError('INVALID_INPUT', 'apple: keyword bid and currency must be provided together');\n }\n const body = {\n adGroupId: Number(payload.ad_group_id),\n text: payload.text,\n matchType: payload.match_type,\n status,\n ...(payload.bid !== undefined && payload.currency\n ? { bid: { amount: String(payload.bid), currency: payload.currency } }\n : {}),\n };\n return {\n summary: `Create Apple Ads ${payload.match_type.toLowerCase()} keyword \"${payload.text}\" (${status})`,\n changes: [`+ keyword \"${payload.text}\" adGroup=${payload.ad_group_id} match=${payload.match_type} status=${status}`],\n coercions,\n budgetDeltas: payload.bid === undefined ? [] : [{\n target: `new keyword \"${payload.text}\" bid`,\n toMicros: payload.bid * UNITS_TO_MICROS,\n }],\n execute: async () => {\n const envelope = await this.client.request<{ id?: number }>('POST', 'keywords', { adAccountId, body });\n return envelope.result?.id ? [String(envelope.result.id)] : [];\n },\n };\n }\n\n private async planSetBudget(\n adAccountId: string,\n payload: { campaign_id: string; daily_budget: number },\n ): Promise<WritePlan> {\n const current = await this.getCampaign(adAccountId, payload.campaign_id);\n const fromAmount = current.dailyBudget?.value ? Number(current.dailyBudget.value.amount) : undefined;\n const currency = current.dailyBudget?.value?.currency ?? 'USD';\n return {\n summary: `Change Apple campaign \"${current.name}\" daily budget ${fromAmount ?? '(unset)'} → ${payload.daily_budget} ${currency}`,\n changes: [`~ campaign ${payload.campaign_id} dailyBudget.value ${fromAmount ?? '(unset)'} → ${payload.daily_budget}`],\n coercions: [],\n budgetDeltas: [\n {\n target: `campaign \"${current.name}\" daily budget`,\n ...(fromAmount !== undefined ? { fromMicros: fromAmount * UNITS_TO_MICROS } : {}),\n toMicros: payload.daily_budget * UNITS_TO_MICROS,\n },\n ],\n execute: async () => {\n await this.client.request('PUT', `campaigns/${payload.campaign_id}`, {\n adAccountId,\n body: { dailyBudget: { value: { amount: String(payload.daily_budget), currency } } },\n });\n return [payload.campaign_id];\n },\n };\n }\n\n private async planApiCreate(\n adAccountId: string,\n payload: { path: string; body: Record<string, unknown> },\n guard: WriteGuard,\n ): Promise<WritePlan> {\n const path = validateMutationPath(payload.path, 'create');\n const body = structuredClone(payload.body);\n const coercions: string[] = [];\n if (guard.forcePausedCreation) coerceCreatedStatuses(body, coercions);\n const budgetDeltas = collectCreatedMoney(body);\n return {\n summary: `Create Apple Ads resource via POST /${path}`,\n changes: [`+ POST /${path} ${JSON.stringify(body)}`],\n coercions,\n budgetDeltas,\n execute: async () => {\n // Ad-account creation is org-scoped. Apple explicitly rejects the\n // account context used by every other create endpoint.\n const envelope = await this.client.request<unknown>('POST', path, {\n ...(path === 'ad-accounts' ? {} : { adAccountId }),\n body,\n });\n return extractResourceIds(envelope.result);\n },\n };\n }\n\n private async planApiUpdate(\n adAccountId: string,\n payload: { path: string; body: Record<string, unknown> },\n ): Promise<WritePlan> {\n const path = validateMutationPath(payload.path, 'update');\n if (containsMoneyField(payload.body)) {\n throw new AdportError(\n 'INVALID_INPUT',\n 'apple: monetary updates require a typed budget or bid tool so current and proposed values can be policy-checked',\n );\n }\n return {\n summary: `Update Apple Ads resource via PUT /${path}`,\n changes: [`~ PUT /${path} ${JSON.stringify(payload.body)}`],\n coercions: [],\n budgetDeltas: [],\n execute: async () => {\n const method = path.endsWith('/bulk-update') ? 'POST' : 'PUT';\n const envelope = await this.client.request<unknown>(method, path, { adAccountId, body: payload.body });\n return extractResourceIds(envelope.result, path);\n },\n };\n }\n\n private async planApiDelete(adAccountId: string, payload: { path: string }): Promise<WritePlan> {\n const path = validateMutationPath(payload.path, 'delete');\n return {\n summary: `Delete Apple Ads resource via DELETE /${path}`,\n changes: [`- DELETE /${path}`],\n coercions: [],\n budgetDeltas: [],\n execute: async () => {\n await this.client.request('DELETE', path, { adAccountId });\n return [path.split('/').at(-1)!];\n },\n };\n }\n\n private async planUploadAsset(\n adAccountId: string,\n payload: {\n file_path: string;\n expected_sha256: string;\n promoted_object_id: string;\n promoted_object_type: 'BUSINESS_BRAND';\n },\n ): Promise<WritePlan> {\n const file = await readFile(payload.file_path);\n const actualSha256 = createHash('sha256').update(file).digest('hex');\n if (actualSha256 !== payload.expected_sha256.toLowerCase()) {\n throw new AdportError(\n 'INVALID_INPUT',\n `apple: asset SHA-256 mismatch for ${payload.file_path}; expected ${payload.expected_sha256}, got ${actualSha256}`,\n );\n }\n const contentType = assetContentType(payload.file_path);\n return {\n summary: `Upload Apple Ads asset ${basename(payload.file_path)} (${file.byteLength} bytes)`,\n changes: [`+ asset sha256=${actualSha256} promotedObject=${payload.promoted_object_id}`],\n coercions: [],\n budgetDeltas: [],\n execute: async () => {\n const form = new FormData();\n form.append('file', new Blob([file], { type: contentType }), basename(payload.file_path));\n form.append('promotedObjectId', payload.promoted_object_id);\n form.append('promotedObjectType', payload.promoted_object_type);\n const envelope = await this.client.request<unknown>('POST', 'assets/upload', { adAccountId, form });\n return extractResourceIds(envelope.result);\n },\n };\n }\n\n private async planApplyRecommendations(\n adAccountId: string,\n payload: {\n category: 'daily_budget' | 'target_cpa';\n promoted_object_id: string;\n promoted_object_type: 'APPSTORE_APP' | 'BUSINESS_BRAND';\n recommendations: Array<{ id: string; applied_amount?: number; currency?: string }>;\n },\n ): Promise<WritePlan> {\n const apiCategory = payload.category === 'daily_budget' ? 'daily-budgets' : 'target-cpas';\n const envelope = await this.client.request<AppleRecommendation[]>('POST', `recommendations/${apiCategory}/query`, {\n adAccountId,\n body: {\n filters: [\n { field: 'promotedObjectId', operator: 'EQUALS', value: [payload.promoted_object_id] },\n { field: 'promotedObjectType', operator: 'EQUALS', value: [payload.promoted_object_type] },\n ],\n pagination: { offset: 0, pageSize: 100 },\n },\n });\n const byId = new Map((envelope.result ?? []).map((recommendation) => [recommendation.id, recommendation]));\n const budgetDeltas: WritePreview['budgetDeltas'] = [];\n const requestBody = payload.recommendations.map((item) => {\n const recommendation = byId.get(item.id);\n if (!recommendation) {\n throw new AdportError('INVALID_INPUT', `apple: recommendation ${item.id} was not returned by the current v1 query`);\n }\n const current = payload.category === 'daily_budget'\n ? recommendation.dailyBudget\n : recommendation.bidStrategy?.bidAmount;\n const suggested = payload.category === 'daily_budget'\n ? recommendation.suggestedDailyBudgetAmount\n : recommendation.recommendedTargetCPA;\n const amount = item.applied_amount ?? Number(suggested?.amount);\n const currency = item.currency ?? suggested?.currency ?? current?.currency;\n if (!Number.isFinite(amount) || amount <= 0 || !currency) {\n throw new AdportError('INVALID_INPUT', `apple: recommendation ${item.id} has no usable proposed Money value`);\n }\n budgetDeltas.push({\n target: `${payload.category} recommendation ${item.id}${recommendation.campaignName ? ` (${recommendation.campaignName})` : ''}`,\n ...(current?.amount !== undefined ? { fromMicros: Number(current.amount) * UNITS_TO_MICROS } : {}),\n toMicros: amount * UNITS_TO_MICROS,\n });\n return {\n id: item.id,\n promotedObjectId: payload.promoted_object_id,\n promotedObjectType: payload.promoted_object_type,\n ...(payload.category === 'daily_budget'\n ? { appliedDailyBudget: { amount: String(amount), currency } }\n : { appliedTargetCPA: { amount: String(amount), currency } }),\n };\n });\n return {\n summary: `Apply ${requestBody.length} Apple Ads ${payload.category.replace('_', ' ')} recommendation(s)`,\n changes: requestBody.map((item) => `~ apply recommendation ${item.id}`),\n coercions: [],\n budgetDeltas,\n execute: async () => {\n const applied = await this.client.request<unknown[]>('POST', `recommendations/${apiCategory}/apply`, {\n adAccountId,\n body: requestBody,\n });\n return extractResourceIds(applied.result).length > 0\n ? extractResourceIds(applied.result)\n : requestBody.map((item) => item.id);\n },\n };\n }\n\n private async planDismissRecommendations(\n adAccountId: string,\n payload: {\n category: 'daily_budget' | 'target_cpa';\n promoted_object_id: string;\n promoted_object_type: 'APPSTORE_APP' | 'BUSINESS_BRAND';\n recommendation_ids: string[];\n },\n ): Promise<WritePlan> {\n const apiCategory = payload.category === 'daily_budget' ? 'daily-budgets' : 'target-cpas';\n const body = payload.recommendation_ids.map((id) => ({\n id,\n promotedObjectId: payload.promoted_object_id,\n promotedObjectType: payload.promoted_object_type,\n }));\n return {\n summary: `Dismiss ${body.length} Apple Ads ${payload.category.replace('_', ' ')} recommendation(s)`,\n changes: body.map((item) => `~ dismiss recommendation ${item.id}`),\n coercions: [],\n budgetDeltas: [],\n execute: async () => {\n await this.client.request('POST', `recommendations/${apiCategory}/dismiss`, { adAccountId, body });\n return payload.recommendation_ids;\n },\n };\n }\n\n private async planSetBid(\n adAccountId: string,\n payload: {\n resource_type: 'campaign' | 'ad_group' | 'keyword';\n resource_id: string;\n amount: number;\n currency?: string;\n },\n ): Promise<WritePlan> {\n const collection = payload.resource_type === 'ad_group' ? 'adgroups' : `${payload.resource_type}s`;\n const envelope = await this.client.request<AppleBiddableResource>('GET', `${collection}/${payload.resource_id}`, {\n adAccountId,\n });\n const current = envelope.result;\n if (!current) throw new AdportError('PROVIDER_ERROR', `apple: ${payload.resource_type} ${payload.resource_id} not found`);\n const currentMoney = payload.resource_type === 'keyword' ? current.bid : current.bidStrategy?.bid;\n const currency = payload.currency ?? currentMoney?.currency;\n if (!currency) {\n throw new AdportError('INVALID_INPUT', 'apple: currency is required when the resource has no existing bid');\n }\n const money = { amount: String(payload.amount), currency };\n const body = payload.resource_type === 'keyword'\n ? { bid: money }\n : { bidStrategy: { ...current.bidStrategy, bid: money } };\n return {\n summary: `Change Apple ${payload.resource_type.replace('_', ' ')} \"${current.name ?? payload.resource_id}\" bid ${currentMoney?.amount ?? '(unset)'} → ${payload.amount} ${currency}`,\n changes: [`~ ${collection}/${payload.resource_id} bid ${currentMoney?.amount ?? '(unset)'} → ${payload.amount}`],\n coercions: [],\n budgetDeltas: [{\n target: `${payload.resource_type} ${payload.resource_id} bid`,\n ...(currentMoney?.amount !== undefined ? { fromMicros: Number(currentMoney.amount) * UNITS_TO_MICROS } : {}),\n toMicros: payload.amount * UNITS_TO_MICROS,\n }],\n execute: async () => {\n await this.client.request('PUT', `${collection}/${payload.resource_id}`, { adAccountId, body });\n return [payload.resource_id];\n },\n };\n }\n\n private async planSetSharedBudget(\n adAccountId: string,\n payload: { shared_budget_id: string; amount: number; currency?: string },\n ): Promise<WritePlan> {\n const envelope = await this.client.request<{ id?: number; name?: string; value?: Money }>(\n 'GET', `shared-budgets/${payload.shared_budget_id}`, { adAccountId },\n );\n const current = envelope.result;\n if (!current) throw new AdportError('PROVIDER_ERROR', `apple: shared budget ${payload.shared_budget_id} not found`);\n const currency = payload.currency ?? current.value?.currency;\n if (!currency) throw new AdportError('INVALID_INPUT', 'apple: currency is required when the shared budget has no existing value');\n return {\n summary: `Change Apple shared budget \"${current.name ?? payload.shared_budget_id}\" ${current.value?.amount ?? '(unset)'} → ${payload.amount} ${currency}`,\n changes: [`~ shared-budgets/${payload.shared_budget_id} value ${current.value?.amount ?? '(unset)'} → ${payload.amount}`],\n coercions: [],\n budgetDeltas: [{\n target: `shared budget ${payload.shared_budget_id}`,\n ...(current.value?.amount !== undefined ? { fromMicros: Number(current.value.amount) * UNITS_TO_MICROS } : {}),\n toMicros: payload.amount * UNITS_TO_MICROS,\n }],\n execute: async () => {\n await this.client.request('PUT', `shared-budgets/${payload.shared_budget_id}`, {\n adAccountId,\n body: { value: { amount: String(payload.amount), currency } },\n });\n return [payload.shared_budget_id];\n },\n };\n }\n}\n\nfunction assetContentType(path: string): string {\n switch (extname(path).toLowerCase()) {\n case '.png': return 'image/png';\n case '.jpg':\n case '.jpeg': return 'image/jpeg';\n case '.heic': return 'image/heic';\n default:\n throw new AdportError('INVALID_INPUT', 'apple: asset file must be PNG, JPG/JPEG, or HEIC');\n }\n}\n\nfunction normalizeApiPath(path: string): string {\n const normalized = path.replace(/^\\/+/, '').trim();\n if (!normalized || normalized.includes('://') || normalized.includes('..') || normalized.includes('#')) {\n throw new AdportError('INVALID_INPUT', 'apple: path must be a relative API path without traversal or fragments');\n }\n return normalized;\n}\n\nfunction validateMutationPath(path: string, operation: 'create' | 'update' | 'delete'): string {\n const normalized = normalizeApiPath(path);\n const allowed = operation === 'create'\n ? APPLE_CREATE_PATHS.test(normalized)\n : operation === 'update'\n ? APPLE_UPDATE_PATHS.test(normalized)\n : APPLE_DELETE_PATHS.test(normalized);\n if (!allowed) {\n throw new AdportError('INVALID_INPUT', `apple: unsupported mutation path \"${normalized}\"`);\n }\n return normalized;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction coerceCreatedStatuses(value: unknown, coercions: string[], path = 'body'): void {\n if (Array.isArray(value)) {\n value.forEach((item, index) => coerceCreatedStatuses(item, coercions, `${path}[${index}]`));\n return;\n }\n if (!isRecord(value)) return;\n for (const [key, child] of Object.entries(value)) {\n if ((key === 'status' || key === 'campaignStatus' || key === 'adGroupStatus') && child === 'ENABLED') {\n value[key] = 'PAUSED';\n coercions.push(`${path}.${key} coerced to PAUSED by policy (paused_creation)`);\n } else {\n coerceCreatedStatuses(child, coercions, `${path}.${key}`);\n }\n }\n}\n\nfunction isMoneyKey(key: string): boolean {\n return /(budget|bidAmount|cpaGoal)/i.test(key);\n}\n\nfunction isMoneyRecord(value: unknown): value is Record<string, unknown> & { amount: string | number } {\n return isRecord(value) && (typeof value.amount === 'string' || typeof value.amount === 'number') &&\n (value.currency === undefined || typeof value.currency === 'string');\n}\n\nfunction containsMoneyField(value: unknown): boolean {\n if (Array.isArray(value)) return value.some(containsMoneyField);\n if (!isRecord(value)) return false;\n if (isMoneyRecord(value)) return true;\n return Object.entries(value).some(([key, child]) => isMoneyKey(key) || containsMoneyField(child));\n}\n\nfunction collectCreatedMoney(value: unknown, path = 'body'): WritePreview['budgetDeltas'] {\n const deltas: WritePreview['budgetDeltas'] = [];\n if (Array.isArray(value)) {\n value.forEach((item, index) => deltas.push(...collectCreatedMoney(item, `${path}[${index}]`)));\n return deltas;\n }\n if (!isRecord(value)) return deltas;\n if (isMoneyRecord(value)) {\n const amount = Number(value.amount);\n return Number.isFinite(amount) && amount >= 0\n ? [{ target: path, toMicros: Math.round(amount * UNITS_TO_MICROS) }]\n : [];\n }\n for (const [key, child] of Object.entries(value)) {\n const childPath = `${path}.${key}`;\n if (isMoneyKey(key) && !isMoneyRecord(child)) {\n const amount = isRecord(child) ? Number(child.amount) : Number(child);\n if (Number.isFinite(amount) && amount >= 0) {\n deltas.push({ target: childPath, toMicros: Math.round(amount * UNITS_TO_MICROS) });\n }\n }\n deltas.push(...collectCreatedMoney(child, childPath));\n }\n return deltas;\n}\n\nfunction extractResourceIds(value: unknown, fallback?: string): string[] {\n const ids: string[] = [];\n const visit = (item: unknown) => {\n if (Array.isArray(item)) return item.forEach(visit);\n if (!isRecord(item)) return;\n if (item.id !== undefined) ids.push(String(item.id));\n for (const child of Object.values(item)) visit(child);\n };\n visit(value);\n return ids.length > 0 ? [...new Set(ids)] : fallback ? [fallback.split('/').at(-1)!] : [];\n}\n\nfunction aggregateAccountRows(rows: ReportRow[], provider: string, accountId: string): ReportRow {\n const metrics = Object.fromEntries(\n Object.keys(rows[0]!.metrics).map((metric) => [\n metric,\n round2(rows.reduce((sum, row) => sum + (row.metrics[metric as MetricName] ?? 0), 0)),\n ]),\n ) as Partial<Record<MetricName, number>>;\n const spend = metrics.spend ?? 0;\n const impressions = metrics.impressions ?? 0;\n const clicks = metrics.clicks ?? 0;\n const conversions = metrics.conversions ?? 0;\n const conversionValue = metrics.conversion_value ?? 0;\n if ('ctr' in metrics) metrics.ctr = impressions > 0 ? round2((clicks / impressions) * 100) : 0;\n if ('cpc' in metrics) metrics.cpc = clicks > 0 ? round2(spend / clicks) : 0;\n if ('cpm' in metrics) metrics.cpm = impressions > 0 ? round2((spend / impressions) * 1000) : 0;\n if ('cpa' in metrics) metrics.cpa = conversions > 0 ? round2(spend / conversions) : 0;\n if ('roas' in metrics) metrics.roas = spend > 0 ? round2(conversionValue / spend) : 0;\n return { provider, accountId, entity: { level: 'account', id: accountId, name: accountId }, metrics };\n}\n\nfunction round2(n: number): number {\n return Math.round(n * 100) / 100;\n}\n","import { defineTool, guardedWriteTool, type AnyToolDefinition } from '@adport/core';\nimport { z } from 'zod';\nimport type { AppleAdsProvider } from './provider.js';\n\nconst statusSchema = z.enum(['ENABLED', 'PAUSED']);\n\nexport function appleTools(provider: AppleAdsProvider): AnyToolDefinition[] {\n return [\n defineTool({\n name: 'apple_api_read',\n namespace: 'apple',\n description:\n 'Call any documented Apple Ads Platform API v1 read, query, insight, suggestion, recommendation-query, or report endpoint.',\n input: z.object({\n account_id: z.string().optional().describe('Apple Ads adAccountId; omit only for unscoped endpoints such as acls and me'),\n method: z.enum(['GET', 'POST']).default('GET'),\n path: z.string().min(1).describe('Relative v1 path, for example campaigns/query or reports/apps/campaigns/query'),\n body: z.record(z.string(), z.unknown()).optional().describe('Query, reporting, insight, or suggestion request for POST reads'),\n }),\n annotations: { readOnly: true },\n async handler(input) {\n return provider.apiRead(input);\n },\n }),\n defineTool({\n name: 'apple_campaigns',\n namespace: 'apple',\n description:\n 'List Apple Ads Platform API v1 campaigns for an ad account.',\n input: z.object({\n account_id: z.string().describe('Apple Ads ad account id (adAccountId)'),\n limit: z.number().int().positive().max(5000).default(100),\n }),\n annotations: { readOnly: true },\n async handler(input) {\n const campaigns = await provider.listCampaigns(input.account_id, input.limit);\n return { campaigns };\n },\n }),\n guardedWriteTool({\n name: 'apple_create_campaign',\n namespace: 'apple',\n description:\n 'Create an Apple Ads Platform API v1 App Store campaign (search results, TAPS billing). ' +\n 'daily_budget is a float in whole currency units; adam_id is the App Store app id. ' +\n 'Apple has no dry run — previews are client-side diffs.',\n provider: 'apple',\n kind: 'create',\n payload: z.object({\n name: z.string().min(1),\n adam_id: z.number().int().positive().describe('App Store app id (adamId)'),\n countries_or_regions: z.array(z.string().length(2)).min(1),\n daily_budget: z.number().positive(),\n currency: z.string().length(3).describe('Org currency, e.g. USD/EUR'),\n status: statusSchema.optional(),\n }),\n }),\n guardedWriteTool({\n name: 'apple_set_campaign_status',\n namespace: 'apple',\n description: 'Enable or pause an Apple Ads campaign.',\n provider: 'apple',\n kind: 'update',\n payload: z.object({ campaign_id: z.string(), status: statusSchema }),\n }),\n guardedWriteTool({\n name: 'apple_create_ad_group',\n namespace: 'apple',\n description:\n 'Create an Apple Ads Platform API v1 App Store ad group using CPT pricing and a MANUAL_CPT/TAP bid strategy. The typed tool emits the documented bidStrategy.bid Money shape.',\n provider: 'apple',\n kind: 'create',\n payload: z.object({\n campaign_id: z.string().min(1),\n name: z.string().min(1),\n bid: z.number().positive(),\n currency: z.string().length(3),\n status: statusSchema.optional(),\n device_classes: z.array(z.enum(['IPHONE', 'IPAD'])).min(1).optional(),\n automated_keywords_opt_in: z.boolean().optional(),\n start_time: z.string().min(1).optional(),\n end_time: z.string().min(1).optional(),\n }),\n }),\n guardedWriteTool({\n name: 'apple_create_keyword',\n namespace: 'apple',\n description:\n 'Create a documented Apple Ads Platform API v1 keyword. Omit bid and currency together to inherit the ad-group bid.',\n provider: 'apple',\n kind: 'create',\n payload: z.object({\n ad_group_id: z.string().min(1),\n text: z.string().min(1),\n match_type: z.enum(['BROAD', 'EXACT']),\n bid: z.number().positive().optional(),\n currency: z.string().length(3).optional(),\n status: statusSchema.optional(),\n }).refine((value) => (value.bid === undefined) === (value.currency === undefined), {\n message: 'bid and currency must be provided together',\n }),\n }),\n guardedWriteTool({\n name: 'apple_set_budget',\n namespace: 'apple',\n description: \"Change an Apple Ads campaign's daily budget (float, whole currency units).\",\n provider: 'apple',\n kind: 'update',\n payload: z.object({ campaign_id: z.string(), daily_budget: z.number().positive() }),\n }),\n guardedWriteTool({\n name: 'apple_api_create',\n namespace: 'apple',\n description:\n 'Create a documented Apple Ads Platform API v1 entity using a relative endpoint and API-shaped body. ' +\n 'For adgroups, v1 requires pricingModel and bidStrategy.bid Money; defaultBid and defaultBidAmount are not v1 fields. ' +\n 'Also supports keyword and negative-keyword bulk-create. Created ENABLED statuses are coerced to PAUSED; budget/bid Money fields are reported to policy.',\n provider: 'apple',\n kind: 'create',\n payload: z.object({\n path: z.string().min(1),\n body: z.record(z.string(), z.unknown()),\n }),\n }),\n guardedWriteTool({\n name: 'apple_api_update',\n namespace: 'apple',\n description:\n 'Update a documented non-monetary Apple Ads Platform API v1 entity. Also supports keyword and negative-keyword bulk-update. Budget/bid changes are rejected here and require typed tools with current-value policy checks.',\n provider: 'apple',\n kind: 'update',\n payload: z.object({\n path: z.string().min(1),\n body: z.record(z.string(), z.unknown()),\n }),\n }),\n guardedWriteTool({\n name: 'apple_api_delete',\n namespace: 'apple',\n description: 'Delete a documented Apple Ads Platform API v1 campaign-management entity by relative path.',\n provider: 'apple',\n kind: 'remove',\n destructive: true,\n payload: z.object({ path: z.string().min(1) }),\n }),\n guardedWriteTool({\n name: 'apple_upload_asset',\n namespace: 'apple',\n description:\n 'Upload a PNG, JPG/JPEG, or HEIC creative asset for a Business Brand. The required SHA-256 binds the exact local file contents to the preview/apply approval.',\n provider: 'apple',\n kind: 'create',\n payload: z.object({\n file_path: z.string().min(1),\n expected_sha256: z.string().regex(/^[a-fA-F0-9]{64}$/),\n promoted_object_id: z.string().min(1),\n promoted_object_type: z.literal('BUSINESS_BRAND').default('BUSINESS_BRAND'),\n }),\n }),\n guardedWriteTool({\n name: 'apple_apply_recommendations',\n namespace: 'apple',\n description:\n 'Apply Apple Ads v1 daily-budget or target-CPA recommendations. The provider re-queries every recommendation and policy-checks the current and proposed Money values before apply.',\n provider: 'apple',\n kind: 'update',\n payload: z.object({\n category: z.enum(['daily_budget', 'target_cpa']),\n promoted_object_id: z.string().min(1),\n promoted_object_type: z.enum(['APPSTORE_APP', 'BUSINESS_BRAND']),\n recommendations: z.array(z.object({\n id: z.string().min(1),\n applied_amount: z.number().positive().optional(),\n currency: z.string().length(3).optional(),\n })).min(1),\n }),\n }),\n guardedWriteTool({\n name: 'apple_dismiss_recommendations',\n namespace: 'apple',\n description: 'Dismiss Apple Ads v1 daily-budget or target-CPA recommendations through the normal preview/apply gate.',\n provider: 'apple',\n kind: 'update',\n payload: z.object({\n category: z.enum(['daily_budget', 'target_cpa']),\n promoted_object_id: z.string().min(1),\n promoted_object_type: z.enum(['APPSTORE_APP', 'BUSINESS_BRAND']),\n recommendation_ids: z.array(z.string().min(1)).min(1),\n }),\n }),\n guardedWriteTool({\n name: 'apple_set_bid',\n namespace: 'apple',\n description:\n 'Change a v1 campaign, ad-group, or keyword bid after fetching the current Money value for policy enforcement.',\n provider: 'apple',\n kind: 'update',\n payload: z.object({\n resource_type: z.enum(['campaign', 'ad_group', 'keyword']),\n resource_id: z.string().min(1),\n amount: z.number().positive(),\n currency: z.string().length(3).optional(),\n }),\n }),\n guardedWriteTool({\n name: 'apple_set_shared_budget',\n namespace: 'apple',\n description: 'Change an Apple Ads v1 shared-budget value after fetching its current Money value.',\n provider: 'apple',\n kind: 'update',\n payload: z.object({\n shared_budget_id: z.string().min(1),\n amount: z.number().positive(),\n currency: z.string().length(3).optional(),\n }),\n }),\n ];\n}\n","import type { CredentialStore, ProviderModule } from '@adport/core';\nimport { AppleAdsClient, type AppleCredentials } from './client.js';\nimport { AppleAdsProvider } from './provider.js';\nimport { appleTools } from './tools.js';\n\nexport { AppleAdsClient, APPLE_ADS_BASE, formatAppleError, type AppleCredentials, type AppleEnvelope } from './client.js';\nexport { createClientSecret, type ClientSecretInput } from './jwt.js';\nexport { AppleAdsProvider, UNITS_TO_MICROS } from './provider.js';\nexport { appleTools } from './tools.js';\n\nexport async function resolveAppleCredentials(store: CredentialStore): Promise<AppleCredentials | undefined> {\n const record = await store.get('apple');\n if (record?.data.client_id && record.data.team_id && record.data.key_id && record.data.private_key) {\n return {\n clientId: record.data.client_id,\n teamId: record.data.team_id,\n keyId: record.data.key_id,\n privateKeyPem: record.data.private_key,\n };\n }\n const env = process.env;\n if (env.APPLE_ADS_CLIENT_ID && env.APPLE_ADS_TEAM_ID && env.APPLE_ADS_KEY_ID && env.APPLE_ADS_PRIVATE_KEY) {\n return {\n clientId: env.APPLE_ADS_CLIENT_ID,\n teamId: env.APPLE_ADS_TEAM_ID,\n keyId: env.APPLE_ADS_KEY_ID,\n privateKeyPem: env.APPLE_ADS_PRIVATE_KEY,\n };\n }\n return undefined;\n}\n\nexport async function createAppleModule(store: CredentialStore): Promise<ProviderModule | undefined> {\n const credentials = await resolveAppleCredentials(store);\n if (!credentials) return undefined;\n const provider = new AppleAdsProvider(new AppleAdsClient(credentials));\n return { provider, tools: appleTools(provider) };\n}\n"],"mappings":"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","names":["AdportError"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adport/provider-apple",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Apple Ads Platform API v1 provider for adport with ES256 OAuth",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
],
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"zod": "^4.4.3",
|
|
20
|
-
"@adport/core": "0.
|
|
20
|
+
"@adport/core": "0.6.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@types/node": "^26.1.2",
|