@nerdsnipe-inc/apple-ads-mcp-server 0.0.0-stage → 1.0.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/.env.example +20 -0
- package/CHANGELOG.md +15 -0
- package/LICENSE +21 -0
- package/README.md +534 -2
- package/bin/apple-ads-mcp-server.js +2 -0
- package/dist/client.d.ts +100 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +352 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +47 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +134 -0
- package/dist/config.js.map +1 -0
- package/dist/errors.d.ts +24 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +96 -0
- package/dist/errors.js.map +1 -0
- package/dist/generated/schemas.d.ts +8434 -0
- package/dist/generated/schemas.d.ts.map +1 -0
- package/dist/generated/schemas.js +477 -0
- package/dist/generated/schemas.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +72 -0
- package/dist/index.js.map +1 -0
- package/dist/redact.d.ts +6 -0
- package/dist/redact.d.ts.map +1 -0
- package/dist/redact.js +32 -0
- package/dist/redact.js.map +1 -0
- package/dist/registry.d.ts +12 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +59 -0
- package/dist/registry.js.map +1 -0
- package/dist/server.d.ts +23 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +54 -0
- package/dist/server.js.map +1 -0
- package/dist/tooling.d.ts +55 -0
- package/dist/tooling.d.ts.map +1 -0
- package/dist/tooling.js +146 -0
- package/dist/tooling.js.map +1 -0
- package/dist/tools/accounts.d.ts +2 -0
- package/dist/tools/accounts.d.ts.map +1 -0
- package/dist/tools/accounts.js +107 -0
- package/dist/tools/accounts.js.map +1 -0
- package/dist/tools/ad_groups.d.ts +2 -0
- package/dist/tools/ad_groups.d.ts.map +1 -0
- package/dist/tools/ad_groups.js +87 -0
- package/dist/tools/ad_groups.js.map +1 -0
- package/dist/tools/ads.d.ts +2 -0
- package/dist/tools/ads.d.ts.map +1 -0
- package/dist/tools/ads.js +87 -0
- package/dist/tools/ads.js.map +1 -0
- package/dist/tools/apps.d.ts +2 -0
- package/dist/tools/apps.d.ts.map +1 -0
- package/dist/tools/apps.js +61 -0
- package/dist/tools/apps.js.map +1 -0
- package/dist/tools/assets.d.ts +2 -0
- package/dist/tools/assets.d.ts.map +1 -0
- package/dist/tools/assets.js +76 -0
- package/dist/tools/assets.js.map +1 -0
- package/dist/tools/brands.d.ts +2 -0
- package/dist/tools/brands.d.ts.map +1 -0
- package/dist/tools/brands.js +122 -0
- package/dist/tools/brands.js.map +1 -0
- package/dist/tools/budget_orders.d.ts +2 -0
- package/dist/tools/budget_orders.d.ts.map +1 -0
- package/dist/tools/budget_orders.js +87 -0
- package/dist/tools/budget_orders.js.map +1 -0
- package/dist/tools/bulk.d.ts +2 -0
- package/dist/tools/bulk.d.ts.map +1 -0
- package/dist/tools/bulk.js +65 -0
- package/dist/tools/bulk.js.map +1 -0
- package/dist/tools/campaigns.d.ts +2 -0
- package/dist/tools/campaigns.d.ts.map +1 -0
- package/dist/tools/campaigns.js +102 -0
- package/dist/tools/campaigns.js.map +1 -0
- package/dist/tools/change_history.d.ts +2 -0
- package/dist/tools/change_history.d.ts.map +1 -0
- package/dist/tools/change_history.js +44 -0
- package/dist/tools/change_history.js.map +1 -0
- package/dist/tools/creatives.d.ts +2 -0
- package/dist/tools/creatives.d.ts.map +1 -0
- package/dist/tools/creatives.js +87 -0
- package/dist/tools/creatives.js.map +1 -0
- package/dist/tools/eligibility.d.ts +2 -0
- package/dist/tools/eligibility.d.ts.map +1 -0
- package/dist/tools/eligibility.js +58 -0
- package/dist/tools/eligibility.js.map +1 -0
- package/dist/tools/geo.d.ts +2 -0
- package/dist/tools/geo.d.ts.map +1 -0
- package/dist/tools/geo.js +47 -0
- package/dist/tools/geo.js.map +1 -0
- package/dist/tools/index.d.ts +4 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +48 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/insights.d.ts +2 -0
- package/dist/tools/insights.d.ts.map +1 -0
- package/dist/tools/insights.js +46 -0
- package/dist/tools/insights.js.map +1 -0
- package/dist/tools/keywords.d.ts +2 -0
- package/dist/tools/keywords.d.ts.map +1 -0
- package/dist/tools/keywords.js +87 -0
- package/dist/tools/keywords.js.map +1 -0
- package/dist/tools/location_groups.d.ts +2 -0
- package/dist/tools/location_groups.d.ts.map +1 -0
- package/dist/tools/location_groups.js +87 -0
- package/dist/tools/location_groups.js.map +1 -0
- package/dist/tools/meta.d.ts +7 -0
- package/dist/tools/meta.d.ts.map +1 -0
- package/dist/tools/meta.js +158 -0
- package/dist/tools/meta.js.map +1 -0
- package/dist/tools/negative_keywords.d.ts +2 -0
- package/dist/tools/negative_keywords.d.ts.map +1 -0
- package/dist/tools/negative_keywords.js +87 -0
- package/dist/tools/negative_keywords.js.map +1 -0
- package/dist/tools/product_pages.d.ts +2 -0
- package/dist/tools/product_pages.d.ts.map +1 -0
- package/dist/tools/product_pages.js +76 -0
- package/dist/tools/product_pages.js.map +1 -0
- package/dist/tools/recommendations.d.ts +2 -0
- package/dist/tools/recommendations.d.ts.map +1 -0
- package/dist/tools/recommendations.js +103 -0
- package/dist/tools/recommendations.js.map +1 -0
- package/dist/tools/reports_apps.d.ts +2 -0
- package/dist/tools/reports_apps.d.ts.map +1 -0
- package/dist/tools/reports_apps.js +114 -0
- package/dist/tools/reports_apps.js.map +1 -0
- package/dist/tools/reports_brands.d.ts +2 -0
- package/dist/tools/reports_brands.d.ts.map +1 -0
- package/dist/tools/reports_brands.js +114 -0
- package/dist/tools/reports_brands.js.map +1 -0
- package/dist/tools/suggestions.d.ts +2 -0
- package/dist/tools/suggestions.d.ts.map +1 -0
- package/dist/tools/suggestions.js +77 -0
- package/dist/tools/suggestions.js.map +1 -0
- package/dist/types.d.ts +43 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/version.d.ts +4 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +26 -0
- package/dist/version.js.map +1 -0
- package/docs/COVERAGE.md +144 -0
- package/docs/DECISIONS.md +16 -0
- package/docs/coverage.json +1028 -0
- package/package.json +76 -4
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { createAppleAdsApi, type AppleAdsApi } from "@apple/apple-ads-platform";
|
|
2
|
+
import { type ServerConfig } from "./config.js";
|
|
3
|
+
export declare const DEFAULT_BASE_URL = "https://api.ads.apple.com/v1";
|
|
4
|
+
export declare const DEFAULT_AUTH_BASE_URL = "https://appleid.apple.com/";
|
|
5
|
+
export interface RateLimitState {
|
|
6
|
+
limit?: number;
|
|
7
|
+
remaining?: number;
|
|
8
|
+
/** epoch ms when the current window resets */
|
|
9
|
+
resetAtMs?: number;
|
|
10
|
+
observedAtMs?: number;
|
|
11
|
+
last429?: {
|
|
12
|
+
atMs: number;
|
|
13
|
+
retryAfterMs?: number;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export interface ClientDeps {
|
|
17
|
+
/** Replace the SDK factory (tests). */
|
|
18
|
+
createApi?: typeof createAppleAdsApi;
|
|
19
|
+
sleep?: (ms: number) => Promise<void>;
|
|
20
|
+
now?: () => number;
|
|
21
|
+
stderr?: (line: string) => void;
|
|
22
|
+
}
|
|
23
|
+
export interface InvokeOptions {
|
|
24
|
+
/** Safe to retry on 5xx / network failures (reads, PUT, DELETE). 429 is always retried. */
|
|
25
|
+
idempotent: boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface AdAccountSummary {
|
|
28
|
+
id: string;
|
|
29
|
+
name?: string;
|
|
30
|
+
orgId?: string;
|
|
31
|
+
}
|
|
32
|
+
/** Normalise APPLE_ADS_BASE_URL: strip trailing slashes (SDK paths already start with "/"). */
|
|
33
|
+
export declare function normalizeBaseUrl(url: string | undefined): string;
|
|
34
|
+
/**
|
|
35
|
+
* APPLE_ADS_TOKEN_URL may be an auth base URL ("https://host/") or the full token URL
|
|
36
|
+
* (".../auth/oauth2/token"). The SDK wants the base with a trailing slash.
|
|
37
|
+
*/
|
|
38
|
+
export declare function normalizeAuthBaseUrl(url: string | undefined): string;
|
|
39
|
+
/** Retry-After is either delta-seconds or an HTTP date. */
|
|
40
|
+
export declare function parseRetryAfter(value: string | undefined, nowMs: number): number | undefined;
|
|
41
|
+
export declare class AppleAdsClient {
|
|
42
|
+
readonly config: ServerConfig;
|
|
43
|
+
private apiPromise?;
|
|
44
|
+
private aclPromise?;
|
|
45
|
+
private mePromise?;
|
|
46
|
+
private readonly sleep;
|
|
47
|
+
private readonly now;
|
|
48
|
+
private readonly createApi;
|
|
49
|
+
private readonly stderr;
|
|
50
|
+
readonly rate: RateLimitState;
|
|
51
|
+
constructor(config: ServerConfig, deps?: ClientDeps);
|
|
52
|
+
/** Values that must never appear in output. */
|
|
53
|
+
secrets(): string[];
|
|
54
|
+
/** Lazily build (and memoise) the SDK client. A failed attempt is not cached. */
|
|
55
|
+
getApi(): Promise<AppleAdsApi>;
|
|
56
|
+
/** Drop the cached SDK client (forces a fresh token fetch on next use). */
|
|
57
|
+
resetApi(): void;
|
|
58
|
+
private log;
|
|
59
|
+
private buildApi;
|
|
60
|
+
/** Record RateLimit-* / Retry-After headers from any response. */
|
|
61
|
+
observe(headers: unknown, status: number): void;
|
|
62
|
+
private throttle;
|
|
63
|
+
private backoffMs;
|
|
64
|
+
/**
|
|
65
|
+
* Run `fn` with 429 / 5xx / network retries.
|
|
66
|
+
* - 401 is handled inside the SDK (token refresh + one retry).
|
|
67
|
+
* - 429 always retries, honouring Retry-After (then RateLimit-Reset, then capped exponential backoff).
|
|
68
|
+
* - 5xx and transient network errors retry only when `idempotent`.
|
|
69
|
+
*/
|
|
70
|
+
withRetries<T>(fn: () => Promise<T>, opts: InvokeOptions): Promise<T>;
|
|
71
|
+
/** Call an SDK operation by its method name with positional SDK arguments. */
|
|
72
|
+
invoke(operationId: string, args: unknown[], opts: InvokeOptions): Promise<{
|
|
73
|
+
status: number;
|
|
74
|
+
data: unknown;
|
|
75
|
+
}>;
|
|
76
|
+
/** Raw authenticated request through the SDK's axios instance (auth + 401 refresh + error mapping included). */
|
|
77
|
+
raw(method: string, apiPath: string, o: {
|
|
78
|
+
query?: Record<string, unknown>;
|
|
79
|
+
body?: unknown;
|
|
80
|
+
context?: string;
|
|
81
|
+
}): Promise<{
|
|
82
|
+
status: number;
|
|
83
|
+
data: unknown;
|
|
84
|
+
}>;
|
|
85
|
+
/** "123" -> "adAccountId=123"; an explicit "adAccountId=123" / "orgId=..." string passes through. */
|
|
86
|
+
static formatContext(id: string | number): string;
|
|
87
|
+
/** Extract the numeric/string ad account id from a context header value. */
|
|
88
|
+
static adAccountIdFromContext(ctx: string | undefined): string | undefined;
|
|
89
|
+
/** Ad accounts the API user can access (GET /acls), cached for 5 minutes. */
|
|
90
|
+
listAdAccounts(): Promise<AdAccountSummary[]>;
|
|
91
|
+
/**
|
|
92
|
+
* Resolve the X-AP-Context header value.
|
|
93
|
+
* explicit arg -> APPLE_ADS_AD_ACCOUNT_ID -> (if `required`) the only accessible ad account
|
|
94
|
+
* (narrowed by APPLE_ADS_ORG_ID when set).
|
|
95
|
+
*/
|
|
96
|
+
resolveContext(adAccountId: string | number | undefined, required: boolean): Promise<string | undefined>;
|
|
97
|
+
/** orgId argument -> APPLE_ADS_ORG_ID -> orgId from GET /me. */
|
|
98
|
+
resolveOrgId(orgId: string | number | undefined): Promise<string>;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,iBAAiB,EAEjB,KAAK,WAAW,EACjB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAGpE,eAAO,MAAM,gBAAgB,iCAAiC,CAAC;AAC/D,eAAO,MAAM,qBAAqB,+BAA+B,CAAC;AAGlE,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACnD;AAED,MAAM,WAAW,UAAU;IACzB,uCAAuC;IACvC,SAAS,CAAC,EAAE,OAAO,iBAAiB,CAAC;IACrC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAED,MAAM,WAAW,aAAa;IAC5B,2FAA2F;IAC3F,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAKD,+FAA+F;AAC/F,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAEhE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAKpE;AAUD,2DAA2D;AAC3D,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAO5F;AAED,qBAAa,cAAc;IAWvB,QAAQ,CAAC,MAAM,EAAE,YAAY;IAV/B,OAAO,CAAC,UAAU,CAAC,CAAuB;IAC1C,OAAO,CAAC,UAAU,CAAC,CAAiD;IACpE,OAAO,CAAC,SAAS,CAAC,CAA+C;IACjE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgC;IACtD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA2B;IACrD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;IAChD,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAM;gBAGxB,MAAM,EAAE,YAAY,EAC7B,IAAI,GAAE,UAAe;IAQvB,+CAA+C;IAC/C,OAAO,IAAI,MAAM,EAAE;IAMnB,iFAAiF;IACjF,MAAM,IAAI,OAAO,CAAC,WAAW,CAAC;IAU9B,2EAA2E;IAC3E,QAAQ,IAAI,IAAI;IAIhB,OAAO,CAAC,GAAG;YAOG,QAAQ;IA6EtB,kEAAkE;IAClE,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;YAgBjC,QAAQ;IAatB,OAAO,CAAC,SAAS;IAKjB;;;;;OAKG;IACG,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,CAAC,CAAC;IAiC3E,8EAA8E;IACxE,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC;IAWnH,gHAAgH;IAC1G,GAAG,CACP,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GACvE,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC;IA0B7C,qGAAqG;IACrG,MAAM,CAAC,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM;IAKjD,4EAA4E;IAC5E,MAAM,CAAC,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS;IAM1E,6EAA6E;IACvE,cAAc,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAqBnD;;;;OAIG;IACG,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAqB9G,gEAAgE;IAC1D,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC;CAiBxE"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { createAppleAdsApi, ApiRequestError, } from "@apple/apple-ads-platform";
|
|
5
|
+
import { ConfigError, AppleAdsToolError } from "./errors.js";
|
|
6
|
+
import { missingCredentials } from "./config.js";
|
|
7
|
+
import { redact } from "./redact.js";
|
|
8
|
+
export const DEFAULT_BASE_URL = "https://api.ads.apple.com/v1";
|
|
9
|
+
export const DEFAULT_AUTH_BASE_URL = "https://appleid.apple.com/";
|
|
10
|
+
const TOKEN_PATH = "auth/oauth2/token";
|
|
11
|
+
const NETWORK_RETRY_CODES = new Set(["ECONNRESET", "ETIMEDOUT", "ECONNABORTED", "EAI_AGAIN", "EPIPE"]);
|
|
12
|
+
const defaultSleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
13
|
+
/** Normalise APPLE_ADS_BASE_URL: strip trailing slashes (SDK paths already start with "/"). */
|
|
14
|
+
export function normalizeBaseUrl(url) {
|
|
15
|
+
return (url ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* APPLE_ADS_TOKEN_URL may be an auth base URL ("https://host/") or the full token URL
|
|
19
|
+
* (".../auth/oauth2/token"). The SDK wants the base with a trailing slash.
|
|
20
|
+
*/
|
|
21
|
+
export function normalizeAuthBaseUrl(url) {
|
|
22
|
+
if (!url)
|
|
23
|
+
return DEFAULT_AUTH_BASE_URL;
|
|
24
|
+
let u = url.trim();
|
|
25
|
+
if (u.endsWith(TOKEN_PATH))
|
|
26
|
+
u = u.slice(0, -TOKEN_PATH.length);
|
|
27
|
+
return u.endsWith("/") ? u : u + "/";
|
|
28
|
+
}
|
|
29
|
+
function headerValue(headers, name) {
|
|
30
|
+
if (!headers)
|
|
31
|
+
return undefined;
|
|
32
|
+
const h = headers;
|
|
33
|
+
const v = typeof h.get === "function" ? h.get(name) : (h[name] ?? h[name.toLowerCase()]);
|
|
34
|
+
if (v === undefined || v === null)
|
|
35
|
+
return undefined;
|
|
36
|
+
return Array.isArray(v) ? String(v[0]) : String(v);
|
|
37
|
+
}
|
|
38
|
+
/** Retry-After is either delta-seconds or an HTTP date. */
|
|
39
|
+
export function parseRetryAfter(value, nowMs) {
|
|
40
|
+
if (!value)
|
|
41
|
+
return undefined;
|
|
42
|
+
const secs = Number(value);
|
|
43
|
+
if (Number.isFinite(secs) && secs >= 0)
|
|
44
|
+
return Math.round(secs * 1000);
|
|
45
|
+
const date = Date.parse(value);
|
|
46
|
+
if (!Number.isNaN(date))
|
|
47
|
+
return Math.max(0, date - nowMs);
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
export class AppleAdsClient {
|
|
51
|
+
config;
|
|
52
|
+
apiPromise;
|
|
53
|
+
aclPromise;
|
|
54
|
+
mePromise;
|
|
55
|
+
sleep;
|
|
56
|
+
now;
|
|
57
|
+
createApi;
|
|
58
|
+
stderr;
|
|
59
|
+
rate = {};
|
|
60
|
+
constructor(config, deps = {}) {
|
|
61
|
+
this.config = config;
|
|
62
|
+
this.sleep = deps.sleep ?? defaultSleep;
|
|
63
|
+
this.now = deps.now ?? Date.now;
|
|
64
|
+
this.createApi = deps.createApi ?? createAppleAdsApi;
|
|
65
|
+
this.stderr = deps.stderr ?? ((l) => process.stderr.write(l + "\n"));
|
|
66
|
+
}
|
|
67
|
+
/** Values that must never appear in output. */
|
|
68
|
+
secrets() {
|
|
69
|
+
return [this.config.privateKey, this.config.clientId, this.config.keyId, this.config.teamId].filter(Boolean);
|
|
70
|
+
}
|
|
71
|
+
// ───────────────────────── authentication / SDK client ─────────────────────────
|
|
72
|
+
/** Lazily build (and memoise) the SDK client. A failed attempt is not cached. */
|
|
73
|
+
getApi() {
|
|
74
|
+
if (!this.apiPromise) {
|
|
75
|
+
this.apiPromise = this.buildApi().catch((e) => {
|
|
76
|
+
this.apiPromise = undefined;
|
|
77
|
+
throw e;
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
return this.apiPromise;
|
|
81
|
+
}
|
|
82
|
+
/** Drop the cached SDK client (forces a fresh token fetch on next use). */
|
|
83
|
+
resetApi() {
|
|
84
|
+
this.apiPromise = undefined;
|
|
85
|
+
}
|
|
86
|
+
log(level, message, meta) {
|
|
87
|
+
const order = ["debug", "info", "warn", "error", "silent"];
|
|
88
|
+
if (order.indexOf(level) < order.indexOf(this.config.logLevel))
|
|
89
|
+
return;
|
|
90
|
+
const extra = meta === undefined ? "" : " " + redact(meta instanceof Error ? meta.message : meta, this.secrets());
|
|
91
|
+
this.stderr(`[apple-ads-mcp ${level}] ${redact(message, this.secrets())}${extra}`);
|
|
92
|
+
}
|
|
93
|
+
async buildApi() {
|
|
94
|
+
const c = this.config;
|
|
95
|
+
const missing = missingCredentials(c);
|
|
96
|
+
if (missing.length) {
|
|
97
|
+
throw new ConfigError(`Apple Ads credentials are not configured. Missing environment variable(s): ${missing.join("; ")}.`, "Set them in your MCP client config (env block) or a .env file. See the README section 'Create Apple Ads API credentials'.");
|
|
98
|
+
}
|
|
99
|
+
let keyPath = c.privateKeyPath;
|
|
100
|
+
let tmpDir;
|
|
101
|
+
if (keyPath) {
|
|
102
|
+
if (!fs.existsSync(keyPath)) {
|
|
103
|
+
throw new ConfigError(`Private key file not found: ${keyPath}`, "Check APPLE_ADS_PRIVATE_KEY_PATH (a leading ~ is expanded). Use an absolute path.");
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
// Inline PEM: the SDK's 'key' mode reads a file once at construction time, so we
|
|
108
|
+
// write the key to a 0600 temp file for the duration of createAppleAdsApi() only.
|
|
109
|
+
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "apple-ads-key-"));
|
|
110
|
+
keyPath = path.join(tmpDir, "private-key.pem");
|
|
111
|
+
fs.writeFileSync(keyPath, c.privateKey, { mode: 0o600 });
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
return await this.createApi({
|
|
115
|
+
authMode: "key",
|
|
116
|
+
clientId: c.clientId,
|
|
117
|
+
teamId: c.teamId,
|
|
118
|
+
keyId: c.keyId,
|
|
119
|
+
privateKeyPath: keyPath,
|
|
120
|
+
baseUrl: normalizeBaseUrl(c.baseUrl),
|
|
121
|
+
authBaseUrl: normalizeAuthBaseUrl(c.tokenUrl),
|
|
122
|
+
apiTimeout: c.timeoutMs,
|
|
123
|
+
authTimeout: c.timeoutMs,
|
|
124
|
+
// The SDK's default logger is `console`, which writes to stdout and would corrupt
|
|
125
|
+
// the stdio MCP stream. Route everything to stderr, redacted.
|
|
126
|
+
logger: {
|
|
127
|
+
debug: (m, meta) => this.log("debug", m, meta),
|
|
128
|
+
info: (m, meta) => this.log("info", m, meta),
|
|
129
|
+
warn: (m, meta) => this.log("warn", m, meta),
|
|
130
|
+
error: (m, meta) => this.log("error", m, meta),
|
|
131
|
+
},
|
|
132
|
+
requestLogLevel: "debug",
|
|
133
|
+
errorLogLevel: "debug",
|
|
134
|
+
apiAxiosCustomizer: (instance) => {
|
|
135
|
+
// Registered before the SDK's own interceptors, so it sees the raw axios
|
|
136
|
+
// response/error (with headers) before the SDK flattens errors.
|
|
137
|
+
instance.interceptors.response.use((res) => {
|
|
138
|
+
this.observe(res.headers, res.status);
|
|
139
|
+
return res;
|
|
140
|
+
}, (err) => {
|
|
141
|
+
if (err?.response)
|
|
142
|
+
this.observe(err.response.headers, err.response.status);
|
|
143
|
+
return Promise.reject(err);
|
|
144
|
+
});
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
finally {
|
|
149
|
+
if (tmpDir) {
|
|
150
|
+
try {
|
|
151
|
+
fs.unlinkSync(keyPath);
|
|
152
|
+
fs.rmdirSync(tmpDir);
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
/* best effort */
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// ───────────────────────── rate limiting ─────────────────────────
|
|
161
|
+
/** Record RateLimit-* / Retry-After headers from any response. */
|
|
162
|
+
observe(headers, status) {
|
|
163
|
+
const now = this.now();
|
|
164
|
+
const limit = Number(headerValue(headers, "RateLimit-Limit"));
|
|
165
|
+
const remaining = Number(headerValue(headers, "RateLimit-Remaining"));
|
|
166
|
+
const reset = Number(headerValue(headers, "RateLimit-Reset"));
|
|
167
|
+
if (Number.isFinite(limit))
|
|
168
|
+
this.rate.limit = limit;
|
|
169
|
+
if (Number.isFinite(remaining))
|
|
170
|
+
this.rate.remaining = remaining;
|
|
171
|
+
if (Number.isFinite(reset))
|
|
172
|
+
this.rate.resetAtMs = now + reset * 1000;
|
|
173
|
+
this.rate.observedAtMs = now;
|
|
174
|
+
if (status === 429) {
|
|
175
|
+
const retryAfter = parseRetryAfter(headerValue(headers, "Retry-After"), now);
|
|
176
|
+
const resetMs = Number.isFinite(reset) ? reset * 1000 : undefined;
|
|
177
|
+
this.rate.last429 = { atMs: now, retryAfterMs: retryAfter ?? resetMs };
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
async throttle() {
|
|
181
|
+
if (!this.config.proactiveThrottle)
|
|
182
|
+
return;
|
|
183
|
+
const { remaining, resetAtMs } = this.rate;
|
|
184
|
+
if (remaining !== undefined && remaining <= 0 && resetAtMs !== undefined) {
|
|
185
|
+
const wait = resetAtMs - this.now();
|
|
186
|
+
if (wait > 0) {
|
|
187
|
+
const capped = Math.min(wait, 30_000);
|
|
188
|
+
this.log("info", `rate limit window exhausted; pausing ${capped}ms`);
|
|
189
|
+
await this.sleep(capped);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
backoffMs(attempt) {
|
|
194
|
+
const { retryBaseMs, retryMaxMs } = this.config;
|
|
195
|
+
return Math.min(retryBaseMs * 2 ** attempt, retryMaxMs);
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Run `fn` with 429 / 5xx / network retries.
|
|
199
|
+
* - 401 is handled inside the SDK (token refresh + one retry).
|
|
200
|
+
* - 429 always retries, honouring Retry-After (then RateLimit-Reset, then capped exponential backoff).
|
|
201
|
+
* - 5xx and transient network errors retry only when `idempotent`.
|
|
202
|
+
*/
|
|
203
|
+
async withRetries(fn, opts) {
|
|
204
|
+
const max = this.config.maxRetries;
|
|
205
|
+
for (let attempt = 0;; attempt++) {
|
|
206
|
+
await this.throttle();
|
|
207
|
+
const startedAt = this.now();
|
|
208
|
+
try {
|
|
209
|
+
return await fn();
|
|
210
|
+
}
|
|
211
|
+
catch (e) {
|
|
212
|
+
const err = e;
|
|
213
|
+
const isApi = e instanceof ApiRequestError || err?.name === "ApiRequestError";
|
|
214
|
+
if (!isApi || attempt >= max)
|
|
215
|
+
throw e;
|
|
216
|
+
let wait;
|
|
217
|
+
if (err.status === 429) {
|
|
218
|
+
const rl = this.rate.last429;
|
|
219
|
+
const hinted = rl && rl.atMs >= startedAt ? rl.retryAfterMs : undefined;
|
|
220
|
+
// Retry-After (or RateLimit-Reset) is authoritative; otherwise capped exponential backoff.
|
|
221
|
+
wait = hinted !== undefined ? Math.min(hinted, 120_000) : this.backoffMs(attempt);
|
|
222
|
+
}
|
|
223
|
+
else if (opts.idempotent && err.status !== undefined && err.status >= 500 && err.status !== 501) {
|
|
224
|
+
wait = this.backoffMs(attempt);
|
|
225
|
+
}
|
|
226
|
+
else if (opts.idempotent && err.status === undefined && err.code && NETWORK_RETRY_CODES.has(err.code)) {
|
|
227
|
+
wait = this.backoffMs(attempt);
|
|
228
|
+
}
|
|
229
|
+
if (wait === undefined)
|
|
230
|
+
throw e;
|
|
231
|
+
this.log("warn", `retrying after ${err.status ?? err.code} (attempt ${attempt + 1}/${max}) in ${wait}ms`);
|
|
232
|
+
await this.sleep(wait);
|
|
233
|
+
// The wait already covered the exhausted window; do not pause a second time proactively.
|
|
234
|
+
if (err.status === 429)
|
|
235
|
+
this.rate.remaining = undefined;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
// ───────────────────────── SDK invocation ─────────────────────────
|
|
240
|
+
/** Call an SDK operation by its method name with positional SDK arguments. */
|
|
241
|
+
async invoke(operationId, args, opts) {
|
|
242
|
+
const api = await this.getApi();
|
|
243
|
+
const fn = api[operationId];
|
|
244
|
+
if (typeof fn !== "function")
|
|
245
|
+
throw new AppleAdsToolError(`SDK operation ${operationId} does not exist`, { code: "UNKNOWN_OPERATION" });
|
|
246
|
+
const res = (await this.withRetries(() => fn.apply(api, args), opts));
|
|
247
|
+
return { status: res.status, data: res.data };
|
|
248
|
+
}
|
|
249
|
+
/** Raw authenticated request through the SDK's axios instance (auth + 401 refresh + error mapping included). */
|
|
250
|
+
async raw(method, apiPath, o) {
|
|
251
|
+
const api = await this.getApi();
|
|
252
|
+
const a = api;
|
|
253
|
+
const idempotent = ["GET", "PUT", "DELETE", "HEAD"].includes(method) || (method === "POST" && /\/query$/.test(apiPath));
|
|
254
|
+
const headers = { Accept: "application/json" };
|
|
255
|
+
if (o.context)
|
|
256
|
+
headers["X-Ap-Context"] = o.context;
|
|
257
|
+
if (o.body !== undefined)
|
|
258
|
+
headers["Content-Type"] = "application/json";
|
|
259
|
+
const res = await this.withRetries(() => a.axios.request({
|
|
260
|
+
method,
|
|
261
|
+
url: a.basePath.replace(/\/+$/, "") + apiPath,
|
|
262
|
+
params: o.query,
|
|
263
|
+
data: o.body,
|
|
264
|
+
headers,
|
|
265
|
+
}), { idempotent });
|
|
266
|
+
return { status: res.status, data: res.data };
|
|
267
|
+
}
|
|
268
|
+
// ───────────────────────── context resolution ─────────────────────────
|
|
269
|
+
/** "123" -> "adAccountId=123"; an explicit "adAccountId=123" / "orgId=..." string passes through. */
|
|
270
|
+
static formatContext(id) {
|
|
271
|
+
const s = String(id).trim();
|
|
272
|
+
return s.includes("=") ? s.replace(/;+\s*$/, "") : `adAccountId=${s}`;
|
|
273
|
+
}
|
|
274
|
+
/** Extract the numeric/string ad account id from a context header value. */
|
|
275
|
+
static adAccountIdFromContext(ctx) {
|
|
276
|
+
if (!ctx)
|
|
277
|
+
return undefined;
|
|
278
|
+
const m = ctx.match(/adAccountId\s*=\s*([^;,\s]+)/);
|
|
279
|
+
return m ? m[1] : undefined;
|
|
280
|
+
}
|
|
281
|
+
/** Ad accounts the API user can access (GET /acls), cached for 5 minutes. */
|
|
282
|
+
async listAdAccounts() {
|
|
283
|
+
const nowMs = this.now();
|
|
284
|
+
if (!this.aclPromise || nowMs - this.aclPromise.at > 5 * 60_000) {
|
|
285
|
+
const p = this.invoke("getUserAcls", [], { idempotent: true }).then((res) => {
|
|
286
|
+
const acls = (res.data?.result?.acls ?? []);
|
|
287
|
+
return acls
|
|
288
|
+
.filter((a) => a.adAccount?.id !== undefined)
|
|
289
|
+
.map((a) => ({
|
|
290
|
+
id: String(a.adAccount?.id),
|
|
291
|
+
name: a.adAccount?.name,
|
|
292
|
+
orgId: a.adAccount?.orgId !== undefined ? String(a.adAccount.orgId) : undefined,
|
|
293
|
+
}));
|
|
294
|
+
});
|
|
295
|
+
p.catch(() => {
|
|
296
|
+
if (this.aclPromise?.p === p)
|
|
297
|
+
this.aclPromise = undefined;
|
|
298
|
+
});
|
|
299
|
+
this.aclPromise = { at: nowMs, p };
|
|
300
|
+
}
|
|
301
|
+
return this.aclPromise.p;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Resolve the X-AP-Context header value.
|
|
305
|
+
* explicit arg -> APPLE_ADS_AD_ACCOUNT_ID -> (if `required`) the only accessible ad account
|
|
306
|
+
* (narrowed by APPLE_ADS_ORG_ID when set).
|
|
307
|
+
*/
|
|
308
|
+
async resolveContext(adAccountId, required) {
|
|
309
|
+
const explicit = adAccountId ?? this.config.adAccountId;
|
|
310
|
+
if (explicit !== undefined && String(explicit).trim() !== "")
|
|
311
|
+
return AppleAdsClient.formatContext(explicit);
|
|
312
|
+
if (!required)
|
|
313
|
+
return undefined;
|
|
314
|
+
const all = await this.listAdAccounts();
|
|
315
|
+
const candidates = this.config.orgId ? all.filter((a) => !a.orgId || a.orgId === this.config.orgId) : all;
|
|
316
|
+
if (candidates.length === 1)
|
|
317
|
+
return AppleAdsClient.formatContext(candidates[0].id);
|
|
318
|
+
const list = candidates.map((a) => `${a.id}${a.name ? ` (${a.name})` : ""}`).join(", ");
|
|
319
|
+
if (candidates.length === 0) {
|
|
320
|
+
throw new AppleAdsToolError("No ad account is accessible to this API user, so no X-AP-Context can be chosen.", {
|
|
321
|
+
code: "NO_AD_ACCOUNT",
|
|
322
|
+
hint: "Create an ad account (apple_ads_create_ad_account) or ask an Apple Ads admin to grant your API user access, then set APPLE_ADS_AD_ACCOUNT_ID.",
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
throw new AppleAdsToolError(`This API user can access several ad accounts: ${list}. Pass adAccountId or set APPLE_ADS_AD_ACCOUNT_ID.`, {
|
|
326
|
+
code: "AMBIGUOUS_AD_ACCOUNT",
|
|
327
|
+
details: { adAccounts: candidates },
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
/** orgId argument -> APPLE_ADS_ORG_ID -> orgId from GET /me. */
|
|
331
|
+
async resolveOrgId(orgId) {
|
|
332
|
+
const explicit = orgId ?? this.config.orgId;
|
|
333
|
+
if (explicit !== undefined && String(explicit).trim() !== "")
|
|
334
|
+
return String(explicit);
|
|
335
|
+
if (!this.mePromise) {
|
|
336
|
+
const p = this.invoke("getMe", [], { idempotent: true }).then((r) => {
|
|
337
|
+
const result = r.data?.result ?? {};
|
|
338
|
+
return { userId: result.userId !== undefined ? String(result.userId) : undefined, orgId: result.orgId !== undefined ? String(result.orgId) : undefined };
|
|
339
|
+
});
|
|
340
|
+
p.catch(() => {
|
|
341
|
+
if (this.mePromise === p)
|
|
342
|
+
this.mePromise = undefined;
|
|
343
|
+
});
|
|
344
|
+
this.mePromise = p;
|
|
345
|
+
}
|
|
346
|
+
const me = await this.mePromise;
|
|
347
|
+
if (!me.orgId)
|
|
348
|
+
throw new AppleAdsToolError("Could not determine the orgId from GET /me. Pass orgId explicitly.", { code: "NO_ORG" });
|
|
349
|
+
return me.orgId;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/** Names of every tool group. Kept in sync with scripts/curated.mjs (checked by tests). */
|
|
2
|
+
export declare const GROUP_NAMES: readonly ["accounts", "apps", "eligibility", "brands", "location_groups", "campaigns", "ad_groups", "ads", "creatives", "assets", "keywords", "negative_keywords", "bulk", "geo", "product_pages", "budget_orders", "reports_apps", "reports_brands", "insights", "recommendations", "suggestions", "change_history", "meta"];
|
|
3
|
+
export type LogLevel = "debug" | "info" | "warn" | "error" | "silent";
|
|
4
|
+
export interface ServerConfig {
|
|
5
|
+
clientId?: string;
|
|
6
|
+
teamId?: string;
|
|
7
|
+
keyId?: string;
|
|
8
|
+
/** Path to the .pem private key (~ expanded). */
|
|
9
|
+
privateKeyPath?: string;
|
|
10
|
+
/** Inline PEM private key (alternative to a path). */
|
|
11
|
+
privateKey?: string;
|
|
12
|
+
/** Default ad account (X-AP-Context: adAccountId=...). */
|
|
13
|
+
adAccountId?: string;
|
|
14
|
+
/** Default organization. Used by apple_ads_get_org and to narrow ad account auto-discovery. */
|
|
15
|
+
orgId?: string;
|
|
16
|
+
readOnly: boolean;
|
|
17
|
+
enabledGroups?: string[];
|
|
18
|
+
disabledGroups: string[];
|
|
19
|
+
/** TEST-ONLY: override https://api.ads.apple.com/v1 */
|
|
20
|
+
baseUrl?: string;
|
|
21
|
+
/** TEST-ONLY: override https://appleid.apple.com/ (or the full token URL). */
|
|
22
|
+
tokenUrl?: string;
|
|
23
|
+
timeoutMs: number;
|
|
24
|
+
maxRetries: number;
|
|
25
|
+
retryBaseMs: number;
|
|
26
|
+
retryMaxMs: number;
|
|
27
|
+
proactiveThrottle: boolean;
|
|
28
|
+
logLevel: LogLevel;
|
|
29
|
+
}
|
|
30
|
+
export interface LoadedConfig {
|
|
31
|
+
config: ServerConfig;
|
|
32
|
+
/** Environment variables that must be set for API calls to work (empty when fully configured). */
|
|
33
|
+
missing: string[];
|
|
34
|
+
/** Non-fatal configuration problems (unknown group names, bad numbers, ...). */
|
|
35
|
+
problems: string[];
|
|
36
|
+
}
|
|
37
|
+
type Env = Record<string, string | undefined>;
|
|
38
|
+
export declare function parseGroupList(raw: string | undefined, problems: string[], varName: string): string[] | undefined;
|
|
39
|
+
/** Expand a leading ~ to the home directory. */
|
|
40
|
+
export declare function expandHome(p: string): string;
|
|
41
|
+
/** Normalise a PEM supplied through an environment variable (handles literal "\n"). */
|
|
42
|
+
export declare function normalizePem(raw: string): string;
|
|
43
|
+
export declare function loadConfig(env?: Env): LoadedConfig;
|
|
44
|
+
/** Human-readable list of the env vars still needed (primary names with aliases). */
|
|
45
|
+
export declare function missingCredentials(c: Pick<ServerConfig, "clientId" | "teamId" | "keyId" | "privateKeyPath" | "privateKey">): string[];
|
|
46
|
+
export {};
|
|
47
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,2FAA2F;AAC3F,eAAO,MAAM,WAAW,+TAwBd,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEtE,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sDAAsD;IACtD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+FAA+F;IAC/F,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,YAAY,CAAC;IACrB,kGAAkG;IAClG,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,gFAAgF;IAChF,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AA2B9C,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAYjH;AAED,gDAAgD;AAChD,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAI5C;AAED,uFAAuF;AACvF,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAIhD;AAED,wBAAgB,UAAU,CAAC,GAAG,GAAE,GAAiB,GAAG,YAAY,CAwC/D;AAED,qFAAqF;AACrF,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,gBAAgB,GAAG,YAAY,CAAC,GAAG,MAAM,EAAE,CASrI"}
|