@koda-sl/baker-cli 0.526.0 → 0.528.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/{account-APMJVG2F.js → account-CQJFUII3.js} +3 -3
- package/dist/{account-APMJVG2F.js.map → account-CQJFUII3.js.map} +1 -1
- package/dist/{account-assets-TAUEBCY5.js → account-assets-IDVG4DGK.js} +12 -12
- package/dist/account-assets-IDVG4DGK.js.map +1 -0
- package/dist/{account-level-2MYDHOID.js → account-level-GK7M2MMQ.js} +14 -14
- package/dist/account-level-GK7M2MMQ.js.map +1 -0
- package/dist/{accounts-VIAQC3PA.js → accounts-KRW3JNCW.js} +2 -2
- package/dist/{activities-MJMAV3SI.js → activities-2RAJXP3J.js} +3 -3
- package/dist/{activities-MJMAV3SI.js.map → activities-2RAJXP3J.js.map} +1 -1
- package/dist/{ads-O4RL4JXD.js → ads-6ESCXPHK.js} +3 -3
- package/dist/{ads-NNKUR4HG.js → ads-JVBLNTBF.js} +20 -15
- package/dist/ads-JVBLNTBF.js.map +1 -0
- package/dist/{adsets-VO5C7PDM.js → adsets-FN5ZWSYF.js} +11 -11
- package/dist/adsets-FN5ZWSYF.js.map +1 -0
- package/dist/{asset-writes-PQNENVYY.js → asset-writes-SSI3CO2A.js} +4 -4
- package/dist/{audience-writes-QDDADCYE.js → audience-writes-G64754LR.js} +6 -6
- package/dist/audience-writes-G64754LR.js.map +1 -0
- package/dist/{audiences-TQ5ZEWIR.js → audiences-JAVNJ5NC.js} +8 -8
- package/dist/audiences-JAVNJ5NC.js.map +1 -0
- package/dist/{businesses-CW4RB36R.js → businesses-DXRDQIFP.js} +2 -2
- package/dist/{campaigns-IQYYYD2S.js → campaigns-GQWFSKGC.js} +11 -11
- package/dist/campaigns-GQWFSKGC.js.map +1 -0
- package/dist/{catalogs-PLBY32BE.js → catalogs-TBRONC2D.js} +15 -15
- package/dist/catalogs-TBRONC2D.js.map +1 -0
- package/dist/{chunk-OEJNZSJG.js → chunk-4XXA4WCS.js} +4 -4
- package/dist/chunk-4XXA4WCS.js.map +1 -0
- package/dist/{chunk-HPAGYPAF.js → chunk-BN4TDL5L.js} +65 -23
- package/dist/chunk-BN4TDL5L.js.map +1 -0
- package/dist/{chunk-5LN7GWRE.js → chunk-GEFZVG4P.js} +10 -10
- package/dist/chunk-GEFZVG4P.js.map +1 -0
- package/dist/{chunk-XB2FODWU.js → chunk-TKDOVFO6.js} +2 -2
- package/dist/cli.js +1 -1
- package/dist/{copy-writes-GZ744FHU.js → copy-writes-EUFEVWDW.js} +5 -5
- package/dist/{copy-writes-GZ744FHU.js.map → copy-writes-EUFEVWDW.js.map} +1 -1
- package/dist/{creatives-GTRQAZSB.js → creatives-6VJDUHEY.js} +6 -6
- package/dist/creatives-6VJDUHEY.js.map +1 -0
- package/dist/{custom-conversions-VQ3LBWYV.js → custom-conversions-NDY5RHSM.js} +6 -6
- package/dist/{custom-conversions-VQ3LBWYV.js.map → custom-conversions-NDY5RHSM.js.map} +1 -1
- package/dist/{draft-ME4TNPO7.js → draft-G432FJ7N.js} +2 -2
- package/dist/{insights-INIFHYR7.js → insights-IVW6W5CP.js} +2 -2
- package/dist/{instant-experiences-NMJUWNP3.js → instant-experiences-6F6GXZ67.js} +5 -5
- package/dist/{instant-experiences-NMJUWNP3.js.map → instant-experiences-6F6GXZ67.js.map} +1 -1
- package/dist/{leads-QBWR7FKT.js → leads-CJKRKB2Q.js} +6 -6
- package/dist/{leads-QBWR7FKT.js.map → leads-CJKRKB2Q.js.map} +1 -1
- package/dist/{media-23IW442U.js → media-HDHZULQ7.js} +3 -3
- package/dist/{meta-H3KBPU33.js → meta-MOSJVYIE.js} +38 -38
- package/dist/{page-photos-SHIGXDYE.js → page-photos-4JTIKXAW.js} +5 -5
- package/dist/page-photos-4JTIKXAW.js.map +1 -0
- package/dist/{pages-XJF3FBOJ.js → pages-BAUS7LQM.js} +2 -2
- package/dist/{performance-L3Q57H4H.js → performance-6XFKDJGY.js} +11 -2
- package/dist/performance-6XFKDJGY.js.map +1 -0
- package/dist/{pixels-AZCIWWXK.js → pixels-QOSEYXCP.js} +3 -3
- package/dist/pixels-QOSEYXCP.js.map +1 -0
- package/dist/{preview-BIEVHIDJ.js → preview-X6EJGPAY.js} +2 -2
- package/dist/{rule-writes-QLZNJ7CT.js → rule-writes-A4BFYHPA.js} +7 -7
- package/dist/rule-writes-A4BFYHPA.js.map +1 -0
- package/dist/{rules-FJHYG4SJ.js → rules-HLREXY2M.js} +11 -11
- package/dist/rules-HLREXY2M.js.map +1 -0
- package/dist/{shared-HY2VP7PT.js → shared-I3SB77VH.js} +2 -2
- package/dist/{studies-Z2ZIWLTO.js → studies-IGOCWM7F.js} +7 -7
- package/dist/{studies-Z2ZIWLTO.js.map → studies-IGOCWM7F.js.map} +1 -1
- package/dist/{study-writes-V7BXLTQG.js → study-writes-Z5P2W7JH.js} +6 -6
- package/dist/study-writes-Z5P2W7JH.js.map +1 -0
- package/dist/{targeting-YBIWD27C.js → targeting-7HXKBXWY.js} +12 -12
- package/dist/targeting-7HXKBXWY.js.map +1 -0
- package/dist/{write-commands-R5SN6CVQ.js → write-commands-CY734U34.js} +22 -22
- package/dist/write-commands-CY734U34.js.map +1 -0
- package/package.json +1 -1
- package/dist/account-assets-TAUEBCY5.js.map +0 -1
- package/dist/account-level-2MYDHOID.js.map +0 -1
- package/dist/ads-NNKUR4HG.js.map +0 -1
- package/dist/adsets-VO5C7PDM.js.map +0 -1
- package/dist/audience-writes-QDDADCYE.js.map +0 -1
- package/dist/audiences-TQ5ZEWIR.js.map +0 -1
- package/dist/campaigns-IQYYYD2S.js.map +0 -1
- package/dist/catalogs-PLBY32BE.js.map +0 -1
- package/dist/chunk-5LN7GWRE.js.map +0 -1
- package/dist/chunk-HPAGYPAF.js.map +0 -1
- package/dist/chunk-OEJNZSJG.js.map +0 -1
- package/dist/creatives-GTRQAZSB.js.map +0 -1
- package/dist/page-photos-SHIGXDYE.js.map +0 -1
- package/dist/performance-L3Q57H4H.js.map +0 -1
- package/dist/pixels-AZCIWWXK.js.map +0 -1
- package/dist/rule-writes-QLZNJ7CT.js.map +0 -1
- package/dist/rules-FJHYG4SJ.js.map +0 -1
- package/dist/study-writes-V7BXLTQG.js.map +0 -1
- package/dist/targeting-YBIWD27C.js.map +0 -1
- package/dist/write-commands-R5SN6CVQ.js.map +0 -1
- /package/dist/{accounts-VIAQC3PA.js.map → accounts-KRW3JNCW.js.map} +0 -0
- /package/dist/{ads-O4RL4JXD.js.map → ads-6ESCXPHK.js.map} +0 -0
- /package/dist/{asset-writes-PQNENVYY.js.map → asset-writes-SSI3CO2A.js.map} +0 -0
- /package/dist/{businesses-CW4RB36R.js.map → businesses-DXRDQIFP.js.map} +0 -0
- /package/dist/{chunk-XB2FODWU.js.map → chunk-TKDOVFO6.js.map} +0 -0
- /package/dist/{draft-ME4TNPO7.js.map → draft-G432FJ7N.js.map} +0 -0
- /package/dist/{insights-INIFHYR7.js.map → insights-IVW6W5CP.js.map} +0 -0
- /package/dist/{media-23IW442U.js.map → media-HDHZULQ7.js.map} +0 -0
- /package/dist/{meta-H3KBPU33.js.map → meta-MOSJVYIE.js.map} +0 -0
- /package/dist/{pages-XJF3FBOJ.js.map → pages-BAUS7LQM.js.map} +0 -0
- /package/dist/{preview-BIEVHIDJ.js.map → preview-X6EJGPAY.js.map} +0 -0
- /package/dist/{shared-HY2VP7PT.js.map → shared-I3SB77VH.js.map} +0 -0
package/README.md
CHANGED
|
@@ -44,6 +44,7 @@ export BAKER_CHAT_ID="<chat-id>"
|
|
|
44
44
|
- `BAKER_GOOGLE_ADS_CUSTOMER_ID` — default Google Ads customer ID (10 digits). Used when `--customer-id` is not passed. If neither is set and the account has exactly one Google Ads customer, it is auto-selected.
|
|
45
45
|
- `BAKER_GA4_PROPERTY_ID` — default GA4 property ID. Used when `--property-id` is not passed. If neither is set and exactly one property is connected, it is auto-selected.
|
|
46
46
|
- `BAKER_GSC_SITE_URL` — default GSC site URL. Used when `--site-url` is not passed. If neither is set and exactly one site is verified, it is auto-selected.
|
|
47
|
+
- `BAKER_META_AD_ACCOUNT_ID` — default Meta ad account ID (`act_<n>` or the bare number). Used when `--account-id` is not passed. If neither is set and exactly one Meta ad account is connected, it is auto-selected; with several, the command refuses with `MISSING_ACCOUNT_ID` and lists them.
|
|
47
48
|
- `BAKER_X_ADS_ACCOUNT_ID` — default X Ads account ID (base36). Used when `--account-id` is not passed. If neither is set and exactly one X Ads account is connected, it is auto-selected.
|
|
48
49
|
- `BAKER_CHAT_ID` — chat context for staged Work Action commands and staged Scheduled agent create/update/delete/unstage. `scheduled-agents run` does not require it. When set, it is also sent as an `x-baker-chat-id` header on every request, so library additions that apply immediately (images, videos, followed brands) are listed in that chat's changes as already applied.
|
|
49
50
|
- `BAKER_THREAD_ID` — set per turn by the sandbox. Sent as an `x-baker-thread-id` header alongside the chat header, so the tools a command reports or changes are those of whoever sent this turn, even while someone else writes in another thread of the same chat.
|
|
@@ -217,6 +218,7 @@ baker ads performance currency # the reporting currency, why
|
|
|
217
218
|
baker ads performance currency set USD # staged: the default currency for everyone (--clear to go back)
|
|
218
219
|
baker ads performance entities --level ad --sort cost_per_result
|
|
219
220
|
baker ads performance entities --level ad --entity-ids <id,id> # only these rows
|
|
221
|
+
baker ads performance entities --level campaign --include-idle # serving: whether each really delivers (a paused parent, nothing on below); below: its children, on and live
|
|
220
222
|
baker ads performance entities --platforms google --compare # each row against the settled days before; what stopped, and who stopped it
|
|
221
223
|
baker ads performance entity <id> --platform meta --level ad_group # one entity + verdict before changing it
|
|
222
224
|
baker ads performance changes --days 14
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
handleMetaError,
|
|
3
3
|
resolveAccountIdArg
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-BN4TDL5L.js";
|
|
5
5
|
import "./chunk-QALAJNBG.js";
|
|
6
6
|
import {
|
|
7
7
|
writeJsonEnvelope
|
|
@@ -101,7 +101,7 @@ Examples:
|
|
|
101
101
|
"no-cache": NO_CACHE_ARG
|
|
102
102
|
},
|
|
103
103
|
run: async ({ args }) => {
|
|
104
|
-
const accountId = resolveAccountIdArg(args);
|
|
104
|
+
const accountId = await resolveAccountIdArg(args);
|
|
105
105
|
try {
|
|
106
106
|
const params = { "account-id": accountId };
|
|
107
107
|
if (args["no-cache"]) params["skip-cache"] = "true";
|
|
@@ -136,4 +136,4 @@ export {
|
|
|
136
136
|
accountDeliveryHints,
|
|
137
137
|
accountPermissionHints
|
|
138
138
|
};
|
|
139
|
-
//# sourceMappingURL=account-
|
|
139
|
+
//# sourceMappingURL=account-CQJFUII3.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../api/src/ads-meta/accountHealth.ts","../src/commands/ads/meta/account.ts"],"sourcesContent":["/**\n * Whether a Meta ad account can deliver at all — read off the account node.\n *\n * Meta stages and publishes ads on an account that cannot pay or is disabled\n * without a word: the docs say an account with no funding source can \"still\n * create ads but these ads will get no delivery\", and they sit in\n * PENDING_BILLING_INFO. Nothing in the publish answer says so, so the only\n * place to catch it is a read of the account before something goes live.\n */\n\n/** The account fields this reads (all in `ACCOUNT_FIELDS`). */\nexport interface MetaAccountHealthFields {\n account_status?: number;\n disable_reason?: number;\n funding_source?: string;\n funding_source_details?: { id?: string; display_string?: string; type?: number } | null;\n is_prepay_account?: boolean;\n /** Minor units as a string; \"0\" is no limit. */\n spend_cap?: string;\n amount_spent?: string;\n /** What the person whose connection Baker uses may do on the account (MANAGE, ADVERTISE, ANALYZE, DRAFT). */\n user_tasks?: string[];\n}\n\n/** `account_status` values, from the Ad Account reference (v25.0). 1 is the only one that delivers. */\nconst ACCOUNT_STATUS: Readonly<Record<number, string>> = {\n 1: \"ACTIVE\",\n 2: \"DISABLED\",\n 3: \"UNSETTLED\",\n 7: \"PENDING_RISK_REVIEW\",\n 8: \"PENDING_SETTLEMENT\",\n 9: \"IN_GRACE_PERIOD\",\n 100: \"PENDING_CLOSURE\",\n 101: \"CLOSED\",\n 201: \"ANY_ACTIVE\",\n 202: \"ANY_CLOSED\",\n};\n\n/** Why an account is disabled, when it is (`disable_reason`). */\nconst DISABLE_REASON: Readonly<Record<number, string>> = {\n 1: \"ads integrity policy\",\n 2: \"ads IP review\",\n 3: \"payment risk\",\n 4: \"gray account shut down\",\n 5: \"ads AFC review\",\n 6: \"business integrity review\",\n 7: \"permanently closed\",\n 8: \"unused reseller account\",\n 9: \"unused account\",\n 10: \"umbrella ad account\",\n 11: \"Business Manager integrity policy\",\n 12: \"misrepresented ad account\",\n 13: \"legal entity de-share\",\n 14: \"thread review\",\n 15: \"compromised ad account\",\n};\n\n/**\n * In grace period, Meta still delivers while a failed payment is retried, so\n * it is a warning that delivery is about to stop rather than a stop.\n */\nconst DELIVERS_ANYWAY = new Set([1, 9]);\n\nfunction statusBlocker(account: MetaAccountHealthFields): string | undefined {\n const status = account.account_status;\n if (status === undefined || status === 1) return undefined;\n const name = ACCOUNT_STATUS[status] ?? `status ${status}`;\n const reason = account.disable_reason ? DISABLE_REASON[account.disable_reason] : undefined;\n const why = reason ? ` (${reason})` : \"\";\n if (DELIVERS_ANYWAY.has(status)) {\n return `the ad account is ${name}${why}: a payment failed and Meta stops delivery when the grace period ends — the account owner settles it in Meta Billing`;\n }\n return `the ad account is ${name}${why}, so nothing on it delivers — only the account owner can resolve that with Meta (Account Quality / Billing)`;\n}\n\n/**\n * Plain reasons this account will not deliver, empty when it can. Each names\n * who can fix it, since nothing Baker stages can.\n */\nexport function metaAccountDeliveryBlockers(account: MetaAccountHealthFields): string[] {\n const blockers: string[] = [];\n const status = statusBlocker(account);\n if (status) blockers.push(status);\n const hasFunding = Boolean(account.funding_source || account.funding_source_details?.id);\n if (!hasFunding && !account.is_prepay_account) {\n blockers.push(\n \"the ad account has no payment method, so Meta accepts its ads but delivers none (they wait in PENDING_BILLING_INFO) — the account owner adds one in Meta Billing\",\n );\n }\n if (spendCapReached(account)) {\n blockers.push(\n \"the ad account has reached its spending limit, so Meta stops delivering every ad on it — an admin raises or removes the limit in Meta Billing → Payment settings, or Baker can change it as part of a chat\",\n );\n }\n return blockers;\n}\n\n/** `spend_cap` \"0\" (or absent) is no limit; a limit reached stops all delivery until it is raised. */\nfunction spendCapReached(account: MetaAccountHealthFields): boolean {\n const cap = Number(account.spend_cap ?? \"0\");\n const spent = Number(account.amount_spent ?? \"0\");\n return Number.isFinite(cap) && Number.isFinite(spent) && cap > 0 && spent >= cap;\n}\n\n/** Statuses on which Meta takes no new ads or edits: only the account owner and Meta can change them. */\nconst REFUSES_WRITES = new Set([2, 101]);\n\n/** Where an account owner reads why Meta restricted an account and asks for a review. */\nexport const META_ACCOUNT_QUALITY_URL = \"https://www.facebook.com/accountquality\";\n\n/**\n * Why Meta will refuse this change on this account at publish, or `undefined`.\n *\n * Only explicit evidence refuses: an account whose status is missing from the\n * read says nothing. A `removal` (a delete, a pause) is let through, because it\n * takes nothing live and is what someone cleaning up a disabled account does.\n */\nexport function metaAccountWriteRefusal(\n account: MetaAccountHealthFields,\n change: \"change\" | \"removal\",\n): string | undefined {\n return accessRefusal(account.user_tasks) ?? statusRefusal(account, change);\n}\n\n/** Tasks that let a person publish changes on an ad account; ANALYZE and DRAFT do not. */\nconst PUBLISHING_TASKS = new Set([\"MANAGE\", \"ADVERTISE\"]);\n\nfunction accessRefusal(tasks: readonly string[] | undefined): string | undefined {\n if (!tasks || tasks.length === 0 || tasks.some((task) => PUBLISHING_TASKS.has(task))) return undefined;\n return 'the person who connected Meta to Baker can only view this ad account, so Meta refuses every change Baker would publish on it — an admin of the ad account gives them the \"Manage campaigns\" permission in Meta Business settings → Ad accounts (https://business.facebook.com/settings/ad-accounts), then this can be staged again';\n}\n\nfunction statusRefusal(account: MetaAccountHealthFields, change: \"change\" | \"removal\"): string | undefined {\n const status = account.account_status;\n if (status === undefined || !REFUSES_WRITES.has(status) || change === \"removal\") return undefined;\n const reason = account.disable_reason ? DISABLE_REASON[account.disable_reason] : undefined;\n const why = reason ? ` (${reason})` : \"\";\n return `the ad account is ${ACCOUNT_STATUS[status]}${why}, so Meta refuses new ads and edits on it — only the account owner can resolve that with Meta, in Account Quality (${META_ACCOUNT_QUALITY_URL}); nothing can be staged here until then`;\n}\n","import { type MetaAccountHealthFields, metaAccountDeliveryBlockers } from \"@baker/api/ads-meta/accountHealth\";\nimport type { MetaPermissionStates } from \"@baker/api/ads-meta/permissionGates\";\nimport { defineCommand } from \"citty\";\nimport { NO_CACHE_ARG } from \"../../../cache-flag.ts\";\nimport { apiGet } from \"../../../client.ts\";\nimport { writeJsonEnvelope } from \"../output.ts\";\nimport { handleMetaError, resolveAccountIdArg } from \"./shared.ts\";\n\nexport const accountCommand = defineCommand({\n meta: {\n name: \"account\",\n description: `Show single Meta ad account detail (currency, timezone, balance, business) and whether it can deliver:\na hint names a disabled account or a missing payment method, which Meta never refuses at publish — its ads just never run.\n\\`bakerPermissions\\` says which per-company Meta permissions (leadAds, catalog, pagePosts) are switched on for this\ncompany and held by the connection; a hint names any that still needs the user to reconnect Meta.\n\nExamples:\n baker ads meta account --account-id act_123\n BAKER_META_AD_ACCOUNT_ID=act_123 baker ads meta account`,\n },\n args: {\n \"account-id\": { type: \"string\", description: \"Meta ad account ID (act_...)\" },\n \"no-cache\": NO_CACHE_ARG,\n },\n run: async ({ args }) => {\n const accountId = resolveAccountIdArg(args);\n try {\n const params: Record<string, string> = { \"account-id\": accountId };\n if (args[\"no-cache\"]) params[\"skip-cache\"] = \"true\";\n const data = await apiGet<\n Record<string, unknown> & MetaAccountHealthFields & { bakerPermissions?: MetaPermissionStates }\n >(\"/api/ads/meta/account\", params);\n const permissionHints = data.bakerPermissions ? accountPermissionHints(data.bakerPermissions) : [];\n writeJsonEnvelope({ ok: true, data, hints: [...accountDeliveryHints(data), ...permissionHints] });\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n\n/** Whether ads on this account can run at all, said once, in the words staging warns with. */\nexport function accountDeliveryHints(account: MetaAccountHealthFields): string[] {\n const blockers = metaAccountDeliveryBlockers(account);\n if (blockers.length === 0) return [\"The account can deliver: it is active and has a payment method.\"];\n return [\n ...blockers.map((blocker) => `Cannot deliver: ${blocker}.`),\n \"Staging still works and publishing still applies the changes, but nothing serves until this is fixed — tell the user before they publish anything they expect to run.\",\n ];\n}\n\nconst PERMISSION_LABEL: Record<keyof MetaPermissionStates, string> = {\n leadAds: \"Lead ads (instant forms and their leads)\",\n catalog: \"Catalog changes\",\n pagePosts: \"Facebook Page posts\",\n};\n\n/** One hint per permission switched on for this company that the current Meta connection does not hold yet. */\nexport function accountPermissionHints(permissions: MetaPermissionStates): string[] {\n return (Object.keys(PERMISSION_LABEL) as (keyof MetaPermissionStates)[])\n .filter((key) => permissions[key].reconnectNeeded)\n .map(\n (key) =>\n `${PERMISSION_LABEL[key]}: switched on for this company, but this Meta connection predates it — ask the user to reconnect Meta in the dashboard before relying on it.`,\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../api/src/ads-meta/accountHealth.ts","../src/commands/ads/meta/account.ts"],"sourcesContent":["/**\n * Whether a Meta ad account can deliver at all — read off the account node.\n *\n * Meta stages and publishes ads on an account that cannot pay or is disabled\n * without a word: the docs say an account with no funding source can \"still\n * create ads but these ads will get no delivery\", and they sit in\n * PENDING_BILLING_INFO. Nothing in the publish answer says so, so the only\n * place to catch it is a read of the account before something goes live.\n */\n\n/** The account fields this reads (all in `ACCOUNT_FIELDS`). */\nexport interface MetaAccountHealthFields {\n account_status?: number;\n disable_reason?: number;\n funding_source?: string;\n funding_source_details?: { id?: string; display_string?: string; type?: number } | null;\n is_prepay_account?: boolean;\n /** Minor units as a string; \"0\" is no limit. */\n spend_cap?: string;\n amount_spent?: string;\n /** What the person whose connection Baker uses may do on the account (MANAGE, ADVERTISE, ANALYZE, DRAFT). */\n user_tasks?: string[];\n}\n\n/** `account_status` values, from the Ad Account reference (v25.0). 1 is the only one that delivers. */\nconst ACCOUNT_STATUS: Readonly<Record<number, string>> = {\n 1: \"ACTIVE\",\n 2: \"DISABLED\",\n 3: \"UNSETTLED\",\n 7: \"PENDING_RISK_REVIEW\",\n 8: \"PENDING_SETTLEMENT\",\n 9: \"IN_GRACE_PERIOD\",\n 100: \"PENDING_CLOSURE\",\n 101: \"CLOSED\",\n 201: \"ANY_ACTIVE\",\n 202: \"ANY_CLOSED\",\n};\n\n/** Why an account is disabled, when it is (`disable_reason`). */\nconst DISABLE_REASON: Readonly<Record<number, string>> = {\n 1: \"ads integrity policy\",\n 2: \"ads IP review\",\n 3: \"payment risk\",\n 4: \"gray account shut down\",\n 5: \"ads AFC review\",\n 6: \"business integrity review\",\n 7: \"permanently closed\",\n 8: \"unused reseller account\",\n 9: \"unused account\",\n 10: \"umbrella ad account\",\n 11: \"Business Manager integrity policy\",\n 12: \"misrepresented ad account\",\n 13: \"legal entity de-share\",\n 14: \"thread review\",\n 15: \"compromised ad account\",\n};\n\n/**\n * In grace period, Meta still delivers while a failed payment is retried, so\n * it is a warning that delivery is about to stop rather than a stop.\n */\nconst DELIVERS_ANYWAY = new Set([1, 9]);\n\nfunction statusBlocker(account: MetaAccountHealthFields): string | undefined {\n const status = account.account_status;\n if (status === undefined || status === 1) return undefined;\n const name = ACCOUNT_STATUS[status] ?? `status ${status}`;\n const reason = account.disable_reason ? DISABLE_REASON[account.disable_reason] : undefined;\n const why = reason ? ` (${reason})` : \"\";\n if (DELIVERS_ANYWAY.has(status)) {\n return `the ad account is ${name}${why}: a payment failed and Meta stops delivery when the grace period ends — the account owner settles it in Meta Billing`;\n }\n return `the ad account is ${name}${why}, so nothing on it delivers — only the account owner can resolve that with Meta (Account Quality / Billing)`;\n}\n\n/**\n * Plain reasons this account will not deliver, empty when it can. Each names\n * who can fix it, since nothing Baker stages can.\n */\nexport function metaAccountDeliveryBlockers(account: MetaAccountHealthFields): string[] {\n const blockers: string[] = [];\n const status = statusBlocker(account);\n if (status) blockers.push(status);\n const hasFunding = Boolean(account.funding_source || account.funding_source_details?.id);\n if (!hasFunding && !account.is_prepay_account) {\n blockers.push(\n \"the ad account has no payment method, so Meta accepts its ads but delivers none (they wait in PENDING_BILLING_INFO) — the account owner adds one in Meta Billing\",\n );\n }\n if (spendCapReached(account)) {\n blockers.push(\n \"the ad account has reached its spending limit, so Meta stops delivering every ad on it — an admin raises or removes the limit in Meta Billing → Payment settings, or Baker can change it as part of a chat\",\n );\n }\n return blockers;\n}\n\n/** `spend_cap` \"0\" (or absent) is no limit; a limit reached stops all delivery until it is raised. */\nfunction spendCapReached(account: MetaAccountHealthFields): boolean {\n const cap = Number(account.spend_cap ?? \"0\");\n const spent = Number(account.amount_spent ?? \"0\");\n return Number.isFinite(cap) && Number.isFinite(spent) && cap > 0 && spent >= cap;\n}\n\n/** Statuses on which Meta takes no new ads or edits: only the account owner and Meta can change them. */\nconst REFUSES_WRITES = new Set([2, 101]);\n\n/** Where an account owner reads why Meta restricted an account and asks for a review. */\nexport const META_ACCOUNT_QUALITY_URL = \"https://www.facebook.com/accountquality\";\n\n/**\n * Why Meta will refuse this change on this account at publish, or `undefined`.\n *\n * Only explicit evidence refuses: an account whose status is missing from the\n * read says nothing. A `removal` (a delete, a pause) is let through, because it\n * takes nothing live and is what someone cleaning up a disabled account does.\n */\nexport function metaAccountWriteRefusal(\n account: MetaAccountHealthFields,\n change: \"change\" | \"removal\",\n): string | undefined {\n return accessRefusal(account.user_tasks) ?? statusRefusal(account, change);\n}\n\n/** Tasks that let a person publish changes on an ad account; ANALYZE and DRAFT do not. */\nconst PUBLISHING_TASKS = new Set([\"MANAGE\", \"ADVERTISE\"]);\n\nfunction accessRefusal(tasks: readonly string[] | undefined): string | undefined {\n if (!tasks || tasks.length === 0 || tasks.some((task) => PUBLISHING_TASKS.has(task))) return undefined;\n return 'the person who connected Meta to Baker can only view this ad account, so Meta refuses every change Baker would publish on it — an admin of the ad account gives them the \"Manage campaigns\" permission in Meta Business settings → Ad accounts (https://business.facebook.com/settings/ad-accounts), then this can be staged again';\n}\n\nfunction statusRefusal(account: MetaAccountHealthFields, change: \"change\" | \"removal\"): string | undefined {\n const status = account.account_status;\n if (status === undefined || !REFUSES_WRITES.has(status) || change === \"removal\") return undefined;\n const reason = account.disable_reason ? DISABLE_REASON[account.disable_reason] : undefined;\n const why = reason ? ` (${reason})` : \"\";\n return `the ad account is ${ACCOUNT_STATUS[status]}${why}, so Meta refuses new ads and edits on it — only the account owner can resolve that with Meta, in Account Quality (${META_ACCOUNT_QUALITY_URL}); nothing can be staged here until then`;\n}\n","import { type MetaAccountHealthFields, metaAccountDeliveryBlockers } from \"@baker/api/ads-meta/accountHealth\";\nimport type { MetaPermissionStates } from \"@baker/api/ads-meta/permissionGates\";\nimport { defineCommand } from \"citty\";\nimport { NO_CACHE_ARG } from \"../../../cache-flag.ts\";\nimport { apiGet } from \"../../../client.ts\";\nimport { writeJsonEnvelope } from \"../output.ts\";\nimport { handleMetaError, resolveAccountIdArg } from \"./shared.ts\";\n\nexport const accountCommand = defineCommand({\n meta: {\n name: \"account\",\n description: `Show single Meta ad account detail (currency, timezone, balance, business) and whether it can deliver:\na hint names a disabled account or a missing payment method, which Meta never refuses at publish — its ads just never run.\n\\`bakerPermissions\\` says which per-company Meta permissions (leadAds, catalog, pagePosts) are switched on for this\ncompany and held by the connection; a hint names any that still needs the user to reconnect Meta.\n\nExamples:\n baker ads meta account --account-id act_123\n BAKER_META_AD_ACCOUNT_ID=act_123 baker ads meta account`,\n },\n args: {\n \"account-id\": { type: \"string\", description: \"Meta ad account ID (act_...)\" },\n \"no-cache\": NO_CACHE_ARG,\n },\n run: async ({ args }) => {\n const accountId = await resolveAccountIdArg(args);\n try {\n const params: Record<string, string> = { \"account-id\": accountId };\n if (args[\"no-cache\"]) params[\"skip-cache\"] = \"true\";\n const data = await apiGet<\n Record<string, unknown> & MetaAccountHealthFields & { bakerPermissions?: MetaPermissionStates }\n >(\"/api/ads/meta/account\", params);\n const permissionHints = data.bakerPermissions ? accountPermissionHints(data.bakerPermissions) : [];\n writeJsonEnvelope({ ok: true, data, hints: [...accountDeliveryHints(data), ...permissionHints] });\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n\n/** Whether ads on this account can run at all, said once, in the words staging warns with. */\nexport function accountDeliveryHints(account: MetaAccountHealthFields): string[] {\n const blockers = metaAccountDeliveryBlockers(account);\n if (blockers.length === 0) return [\"The account can deliver: it is active and has a payment method.\"];\n return [\n ...blockers.map((blocker) => `Cannot deliver: ${blocker}.`),\n \"Staging still works and publishing still applies the changes, but nothing serves until this is fixed — tell the user before they publish anything they expect to run.\",\n ];\n}\n\nconst PERMISSION_LABEL: Record<keyof MetaPermissionStates, string> = {\n leadAds: \"Lead ads (instant forms and their leads)\",\n catalog: \"Catalog changes\",\n pagePosts: \"Facebook Page posts\",\n};\n\n/** One hint per permission switched on for this company that the current Meta connection does not hold yet. */\nexport function accountPermissionHints(permissions: MetaPermissionStates): string[] {\n return (Object.keys(PERMISSION_LABEL) as (keyof MetaPermissionStates)[])\n .filter((key) => permissions[key].reconnectNeeded)\n .map(\n (key) =>\n `${PERMISSION_LABEL[key]}: switched on for this company, but this Meta connection predates it — ask the user to reconnect Meta in the dashboard before relying on it.`,\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
csvOrJson,
|
|
3
3
|
handleMetaError,
|
|
4
4
|
resolveAccountIdArg
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-BN4TDL5L.js";
|
|
6
6
|
import "./chunk-QALAJNBG.js";
|
|
7
7
|
import {
|
|
8
8
|
writeAdsOutput,
|
|
@@ -78,7 +78,7 @@ var instagramAccountsCommand = defineCommand({
|
|
|
78
78
|
},
|
|
79
79
|
args: { "account-id": accountArg, "no-cache": NO_CACHE_ARG, output: outputArg },
|
|
80
80
|
run: async ({ args }) => {
|
|
81
|
-
const accountId = resolveAccountIdArg(args);
|
|
81
|
+
const accountId = await resolveAccountIdArg(args);
|
|
82
82
|
try {
|
|
83
83
|
const rows = await read(
|
|
84
84
|
"/api/ads/meta/instagram-accounts",
|
|
@@ -107,7 +107,7 @@ var appsCommand = defineCommand({
|
|
|
107
107
|
},
|
|
108
108
|
args: { "account-id": accountArg, "no-cache": NO_CACHE_ARG, output: outputArg },
|
|
109
109
|
run: async ({ args }) => {
|
|
110
|
-
const accountId = resolveAccountIdArg(args);
|
|
110
|
+
const accountId = await resolveAccountIdArg(args);
|
|
111
111
|
try {
|
|
112
112
|
const rows = await read(
|
|
113
113
|
"/api/ads/meta/apps",
|
|
@@ -140,7 +140,7 @@ var dsaRecommendationsCommand = defineCommand({
|
|
|
140
140
|
},
|
|
141
141
|
args: { "account-id": accountArg, "no-cache": NO_CACHE_ARG },
|
|
142
142
|
run: async ({ args }) => {
|
|
143
|
-
const accountId = resolveAccountIdArg(args);
|
|
143
|
+
const accountId = await resolveAccountIdArg(args);
|
|
144
144
|
try {
|
|
145
145
|
const names = await read("/api/ads/meta/dsa-recommendations", { "account-id": accountId }, args);
|
|
146
146
|
writeJsonEnvelope({
|
|
@@ -191,7 +191,7 @@ var imagesCommand = defineCommand({
|
|
|
191
191
|
output: outputArg
|
|
192
192
|
},
|
|
193
193
|
run: async ({ args }) => {
|
|
194
|
-
const accountId = resolveAccountIdArg(args);
|
|
194
|
+
const accountId = await resolveAccountIdArg(args);
|
|
195
195
|
const params = { "account-id": accountId };
|
|
196
196
|
if (args.hash) params.hash = args.hash;
|
|
197
197
|
if (args.limit) params.limit = args.limit;
|
|
@@ -221,11 +221,11 @@ var labelsCommand = defineCommand({
|
|
|
221
221
|
},
|
|
222
222
|
subCommands: {
|
|
223
223
|
list: () => labelsListCommand,
|
|
224
|
-
create: () => import("./asset-writes-
|
|
225
|
-
rename: () => import("./asset-writes-
|
|
226
|
-
delete: () => import("./asset-writes-
|
|
227
|
-
attach: () => import("./asset-writes-
|
|
228
|
-
detach: () => import("./asset-writes-
|
|
224
|
+
create: () => import("./asset-writes-SSI3CO2A.js").then((m) => m.labelsCreateCommand),
|
|
225
|
+
rename: () => import("./asset-writes-SSI3CO2A.js").then((m) => m.labelsRenameCommand),
|
|
226
|
+
delete: () => import("./asset-writes-SSI3CO2A.js").then((m) => m.labelsDeleteCommand),
|
|
227
|
+
attach: () => import("./asset-writes-SSI3CO2A.js").then((m) => m.labelsAttachCommand),
|
|
228
|
+
detach: () => import("./asset-writes-SSI3CO2A.js").then((m) => m.labelsDetachCommand)
|
|
229
229
|
},
|
|
230
230
|
args: labelsListArgs,
|
|
231
231
|
default: "list"
|
|
@@ -237,7 +237,7 @@ var labelsListCommand = defineCommand({
|
|
|
237
237
|
},
|
|
238
238
|
args: labelsListArgs,
|
|
239
239
|
run: async ({ args }) => {
|
|
240
|
-
const accountId = resolveAccountIdArg(args);
|
|
240
|
+
const accountId = await resolveAccountIdArg(args);
|
|
241
241
|
try {
|
|
242
242
|
const rows = await read("/api/ads/meta/labels", { "account-id": accountId }, args);
|
|
243
243
|
emit(rows, args, rows.length === 0 ? ["This account has no ad labels."] : []);
|
|
@@ -287,4 +287,4 @@ export {
|
|
|
287
287
|
instagramIdentityHints,
|
|
288
288
|
labelsCommand
|
|
289
289
|
};
|
|
290
|
-
//# sourceMappingURL=account-assets-
|
|
290
|
+
//# sourceMappingURL=account-assets-IDVG4DGK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/ads/meta/account-assets.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport { NO_CACHE_ARG } from \"../../../cache-flag.ts\";\nimport { apiGet } from \"../../../client.ts\";\nimport { registerSchema } from \"../../../schemas.ts\";\nimport { writeAdsOutput, writeJsonEnvelope } from \"../output.ts\";\nimport { csvOrJson, handleMetaError, resolveAccountIdArg } from \"./shared.ts\";\n\n/**\n * The account's identities and libraries an ad is built from — reads that used\n * to exist only as backend routes. They were left off the CLI as \"rarely\n * needed in isolation\", but each answers a question staging otherwise answers\n * with a refusal: which Instagram account an ad can run as, which apps it can\n * promote, whom an EU ad names, what an image hash or label id is, which\n * product sets a catalog ad can use, what an A/B test found.\n */\n\ntype Row = Record<string, unknown>;\ntype Args = Record<string, unknown>;\n\nfunction emit(rows: Row[], args: Args, hints: string[]): void {\n const fmt = csvOrJson(args);\n if (fmt !== \"json\") {\n writeAdsOutput(rows, fmt, undefined, hints);\n return;\n }\n writeJsonEnvelope(hints.length > 0 ? { ok: true, data: rows, hints } : { ok: true, data: rows });\n}\n\nasync function read<T>(path: string, params: Record<string, string>, args: Args): Promise<T> {\n if (args[\"no-cache\"]) params[\"skip-cache\"] = \"true\";\n return await apiGet<T>(path, params);\n}\n\nconst outputArg = { type: \"string\", description: \"json|csv|jsonl|md\", default: \"json\" } as const;\nconst accountArg = { type: \"string\", description: \"Meta ad account ID (act_...)\" } as const;\nconst schemaAccount = { type: \"string\", description: \"Meta ad account ID (act_123)\", required: false };\nconst schemaNoCache = { type: \"boolean\", description: \"Bypass the cache\", required: false };\nconst schemaOutput = { type: \"string\", description: \"json|csv|jsonl|md\", required: false, default: \"json\" };\n\n// --- Instagram identities ---\n\nexport interface MetaInstagramIdentity {\n id: string;\n username?: string;\n sources: Array<\"ad_account\" | \"connected\" | \"page\" | \"page_backed\">;\n pageId?: string;\n pageName?: string;\n}\n\nexport function instagramIdentityHints(rows: readonly MetaInstagramIdentity[]): string[] {\n if (rows.length === 0) {\n return [\n \"No Instagram account is linked to this ad account or its Pages. A creative without --instagram-user cannot run in Instagram feeds, Stories or Reels — the account owner links one in Meta Business settings (Accounts → Instagram accounts) and assigns it to the ad account.\",\n ];\n }\n const listed = rows.filter((row) => row.sources.includes(\"ad_account\") || row.sources.includes(\"connected\"));\n const hints = [\"Pass the id as `creatives create --instagram-user <id>`.\"];\n if (listed.length > 0 && listed.length < rows.length) {\n hints.push(\n `Use one listed on the ad account (${listed.map((row) => row.username ?? row.id).join(\", \")}): when the account lists any, staging refuses an identity it does not list.`,\n );\n } else if (listed.length === 0) {\n hints.push(\n \"Only Page identities are listed (page = the Page's linked Instagram account, page_backed = an Instagram presence Meta made for a Page with none). Meta accepts either as --instagram-user; a page_backed one shows the Page's name and picture on Instagram.\",\n );\n }\n if (new Set(rows.map((row) => row.pageId).filter(Boolean)).size > 1) {\n hints.push(\"Several Pages are involved — use the identity of the Page the creative runs from (--page).\");\n }\n return hints;\n}\n\nregisterSchema({\n command: \"ads.meta.instagram-accounts\",\n description:\n \"The Instagram accounts an ad on this account can run as — the id `creatives create --instagram-user` takes. Lists accounts assigned or connected to the ad account and each promotable Page's linked or page-backed one.\",\n args: {\n \"account-id\": schemaAccount,\n \"no-cache\": schemaNoCache,\n output: { type: \"string\", description: \"json|csv\", required: false, default: \"json\" },\n },\n});\n\nexport const instagramAccountsCommand = defineCommand({\n meta: {\n name: \"instagram-accounts\",\n description:\n \"Instagram identities an ad can run as (the --instagram-user id). Start here before creatives create: baker ads meta instagram-accounts --account-id act_123\",\n },\n args: { \"account-id\": accountArg, \"no-cache\": NO_CACHE_ARG, output: outputArg },\n run: async ({ args }) => {\n const accountId = await resolveAccountIdArg(args);\n try {\n const rows = await read<MetaInstagramIdentity[]>(\n \"/api/ads/meta/instagram-accounts\",\n { \"account-id\": accountId },\n args,\n );\n emit(\n rows.map((row) => ({ ...row, sources: row.sources.join(\",\") })),\n args,\n instagramIdentityHints(rows),\n );\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n\n// --- Apps ---\n\nregisterSchema({\n command: \"ads.meta.apps\",\n description:\n \"The apps this ad account can promote (app installs / app engagement), with their store URLs — the application_id and object_store_url an app ad set's promoted_object takes.\",\n args: { \"account-id\": schemaAccount, \"no-cache\": schemaNoCache, output: schemaOutput },\n});\n\nexport const appsCommand = defineCommand({\n meta: {\n name: \"apps\",\n description:\n \"Apps the ad account can promote, for an app ad set's promoted_object. Example: baker ads meta apps --account-id act_123\",\n },\n args: { \"account-id\": accountArg, \"no-cache\": NO_CACHE_ARG, output: outputArg },\n run: async ({ args }) => {\n const accountId = await resolveAccountIdArg(args);\n try {\n const rows = await read<Array<{ id: string; name?: string; object_store_urls?: Record<string, string> }>>(\n \"/api/ads/meta/apps\",\n { \"account-id\": accountId },\n args,\n );\n emit(\n rows.map((row) => ({ ...row })),\n args,\n rows.length > 0\n ? [\n 'An app ad set promotes one: promoted_object {\"application_id\":\"<id>\",\"object_store_url\":\"<store url>\"}. Use a real store URL (itunes / google_play); fb_canvas and instant_game are not app stores.',\n ]\n : [\n \"No promotable apps. The app has to be registered in Meta for Developers and its owner has to add this ad account under the app's Advanced settings → Advertising accounts.\",\n ],\n );\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n\n// --- DSA ---\n\nregisterSchema({\n command: \"ads.meta.dsa-recommendations\",\n description:\n \"Names Meta suggests for the EU Digital Services Act disclosure (who benefits from and who pays for an ad) on this account.\",\n args: { \"account-id\": schemaAccount, \"no-cache\": schemaNoCache },\n});\n\nexport const dsaRecommendationsCommand = defineCommand({\n meta: {\n name: \"dsa-recommendations\",\n description:\n \"Meta's suggested DSA beneficiary/payor names for EU ad sets. Example: baker ads meta dsa-recommendations --account-id act_123\",\n },\n args: { \"account-id\": accountArg, \"no-cache\": NO_CACHE_ARG },\n run: async ({ args }) => {\n const accountId = await resolveAccountIdArg(args);\n try {\n const names = await read<string[]>(\"/api/ads/meta/dsa-recommendations\", { \"account-id\": accountId }, args);\n writeJsonEnvelope({\n ok: true,\n data: names,\n hints: [\n \"An ad set reaching the EU needs dsa_beneficiary and dsa_payor. When they are missing Baker fills both from the ad account's saved EU advertiser and payer, else the first of these, else the business name; pass one of these instead when the user names someone else (an agency paying for a client).\",\n ],\n });\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n\n// --- Images and labels ---\n\nfunction compactImage(row: Row): Row {\n return {\n hash: row.hash,\n name: row.name,\n width: row.width,\n height: row.height,\n status: row.status,\n created_time: row.created_time,\n };\n}\n\nregisterSchema({\n command: \"ads.meta.images\",\n description:\n \"The ad account's image library — each image_hash a creative can reuse without uploading again. --hash looks one up.\",\n args: {\n \"account-id\": schemaAccount,\n hash: { type: \"string\", description: \"One image hash\", required: false },\n limit: { type: \"string\", description: \"Max rows (default 500)\", required: false },\n full: { type: \"boolean\", description: \"URLs, permalink and which creatives use it\", required: false },\n \"no-cache\": schemaNoCache,\n output: schemaOutput,\n },\n});\n\nexport const imagesCommand = defineCommand({\n meta: {\n name: \"images\",\n description:\n \"Image library of the ad account (image hashes). Example: baker ads meta images --account-id act_123 --limit 20; --hash <hash> for one\",\n },\n args: {\n \"account-id\": accountArg,\n hash: { type: \"string\", description: \"Look up one image hash\" },\n limit: { type: \"string\", description: \"Max rows (default 500)\" },\n full: { type: \"boolean\", description: \"Every field: url, permalink_url, creatives\" },\n \"no-cache\": NO_CACHE_ARG,\n output: outputArg,\n },\n run: async ({ args }) => {\n const accountId = await resolveAccountIdArg(args);\n const params: Record<string, string> = { \"account-id\": accountId };\n if (args.hash) params.hash = args.hash as string;\n if (args.limit) params.limit = args.limit as string;\n try {\n const rows = await read<Row[]>(\"/api/ads/meta/images\", params, args);\n emit(args.full ? rows : rows.map(compactImage), args, [\n \"A creative reuses one with its hash (the `image_hash` of a creative file). To push a Baker-library image, stage `media upload` instead.\",\n ]);\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n\nregisterSchema({\n command: \"ads.meta.labels\",\n description: \"Ad labels defined on the account (Meta's tags for campaigns, ad sets, ads and creatives).\",\n args: { \"account-id\": schemaAccount, \"no-cache\": schemaNoCache, output: schemaOutput },\n});\n\nconst labelsListArgs = { \"account-id\": accountArg, \"no-cache\": NO_CACHE_ARG, output: outputArg };\n\nexport const labelsCommand = defineCommand({\n meta: {\n name: \"labels\",\n description: `Ad labels on the account (list), or stage label writes: create, rename, delete, attach (file campaigns/ad sets/ads/creatives under one), detach.\n baker ads meta labels --account-id act_123\n baker ads meta labels create --name \"Q4 launch\"\n baker ads meta labels attach <labelId|meta_temp_…> --campaigns 6123,6124 --ads 6125`,\n },\n subCommands: {\n list: () => labelsListCommand,\n create: () => import(\"./asset-writes.ts\").then((m) => m.labelsCreateCommand),\n rename: () => import(\"./asset-writes.ts\").then((m) => m.labelsRenameCommand),\n delete: () => import(\"./asset-writes.ts\").then((m) => m.labelsDeleteCommand),\n attach: () => import(\"./asset-writes.ts\").then((m) => m.labelsAttachCommand),\n detach: () => import(\"./asset-writes.ts\").then((m) => m.labelsDetachCommand),\n },\n args: labelsListArgs,\n default: \"list\",\n});\n\nconst labelsListCommand = defineCommand({\n meta: {\n name: \"list\",\n description: \"Ad labels on the account. Runs by default. Example: baker ads meta labels --account-id act_123\",\n },\n args: labelsListArgs,\n run: async ({ args }) => {\n const accountId = await resolveAccountIdArg(args);\n try {\n const rows = await read<Row[]>(\"/api/ads/meta/labels\", { \"account-id\": accountId }, args);\n emit(rows, args, rows.length === 0 ? [\"This account has no ad labels.\"] : []);\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n\n// --- High-demand periods ---\n\nregisterSchema({\n command: \"ads.meta.high-demand-periods\",\n description: \"The budget boosts (high-demand periods) set on a campaign or ad set: when each runs and by how much.\",\n args: {\n \"campaign-id\": { type: \"string\", description: \"Campaign or ad set ID\", required: true },\n \"no-cache\": schemaNoCache,\n output: schemaOutput,\n },\n});\n\nexport const highDemandPeriodsCommand = defineCommand({\n meta: {\n name: \"high-demand-periods\",\n description:\n \"Budget boosts on a campaign or ad set. Example: baker ads meta high-demand-periods --campaign-id 6123 (stage new ones with --budget-boost on campaigns or adsets create|update)\",\n },\n args: {\n \"campaign-id\": { type: \"string\", description: \"Campaign (or ad set) ID\", required: true },\n \"no-cache\": NO_CACHE_ARG,\n output: outputArg,\n },\n run: async ({ args }) => {\n try {\n const rows = await read<Row[]>(\n \"/api/ads/meta/high-demand-periods\",\n { \"campaign-id\": args[\"campaign-id\"] as string },\n args,\n );\n emit(rows, args, rows.length === 0 ? [\"No budget boosts on this campaign.\"] : []);\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n"],"mappings":"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","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
dayPartingFromFlags
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-TKDOVFO6.js";
|
|
4
4
|
import {
|
|
5
5
|
bareAccountId,
|
|
6
6
|
failWriteValidation,
|
|
@@ -8,12 +8,12 @@ import {
|
|
|
8
8
|
numberFlag,
|
|
9
9
|
requireTarget,
|
|
10
10
|
stageOp
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-4XXA4WCS.js";
|
|
12
12
|
import "./chunk-GC5P4KWY.js";
|
|
13
13
|
import "./chunk-GDFJOCDO.js";
|
|
14
14
|
import {
|
|
15
15
|
handleMetaError
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-BN4TDL5L.js";
|
|
17
17
|
import {
|
|
18
18
|
repeatedValues
|
|
19
19
|
} from "./chunk-ERSX3MKH.js";
|
|
@@ -110,7 +110,7 @@ The EU (DSA) advertiser and payer new ad sets start with \u2014 both together, n
|
|
|
110
110
|
"clear-default-eu": { type: "boolean", description: "Clear both the default EU advertiser and payer" }
|
|
111
111
|
},
|
|
112
112
|
run: async ({ args }) => {
|
|
113
|
-
const accountId = bareAccountId(args);
|
|
113
|
+
const accountId = await bareAccountId(args);
|
|
114
114
|
if (args["remove-spending-limit"] && args["reset-spending-limit"]) {
|
|
115
115
|
failWriteValidation("pass --remove-spending-limit OR --reset-spending-limit");
|
|
116
116
|
}
|
|
@@ -149,7 +149,7 @@ var blockListsListCommand = defineCommand({
|
|
|
149
149
|
},
|
|
150
150
|
run: async ({ args }) => {
|
|
151
151
|
try {
|
|
152
|
-
const params = { edge: "block-lists", "account-id": bareAccountId(args) };
|
|
152
|
+
const params = { edge: "block-lists", "account-id": await bareAccountId(args) };
|
|
153
153
|
if (args.full) params.full = "true";
|
|
154
154
|
const rows = await readEdge(params);
|
|
155
155
|
emit(rows, [
|
|
@@ -193,7 +193,7 @@ Then keep ad sets off it: baker ads meta adsets update <id> --block-list meta_te
|
|
|
193
193
|
run: async ({ args, rawArgs }) => {
|
|
194
194
|
await stageOp({
|
|
195
195
|
kind: "publisherBlockList.create",
|
|
196
|
-
accountId: bareAccountId(args),
|
|
196
|
+
accountId: await bareAccountId(args),
|
|
197
197
|
payload: { name: args.name, urls: urlsFrom(args, rawArgs) }
|
|
198
198
|
});
|
|
199
199
|
}
|
|
@@ -223,7 +223,7 @@ Example: baker ads meta block-lists add 120249500506120208 --account-id act_123
|
|
|
223
223
|
run: async ({ args, rawArgs }) => {
|
|
224
224
|
await stageOp({
|
|
225
225
|
kind: "publisherBlockList.update",
|
|
226
|
-
accountId: bareAccountId(args),
|
|
226
|
+
accountId: await bareAccountId(args),
|
|
227
227
|
target: requireTarget(args, "block list"),
|
|
228
228
|
payload: { addUrls: urlsFrom(args, rawArgs) }
|
|
229
229
|
});
|
|
@@ -247,7 +247,7 @@ Example: baker ads meta block-lists delete 120249500506120208 --account-id act_1
|
|
|
247
247
|
run: async ({ args }) => {
|
|
248
248
|
await stageOp({
|
|
249
249
|
kind: "publisherBlockList.update",
|
|
250
|
-
accountId: bareAccountId(args),
|
|
250
|
+
accountId: await bareAccountId(args),
|
|
251
251
|
target: requireTarget(args, "block list"),
|
|
252
252
|
payload: { status: "DELETED" }
|
|
253
253
|
});
|
|
@@ -286,7 +286,7 @@ var reachFrequencyListCommand = defineCommand({
|
|
|
286
286
|
args: { "account-id": { type: "string", description: "Numeric account ID or act_N" } },
|
|
287
287
|
run: async ({ args }) => {
|
|
288
288
|
try {
|
|
289
|
-
const rows = await readEdge({ edge: "reach-frequency", "account-id": bareAccountId(args) });
|
|
289
|
+
const rows = await readEdge({ edge: "reach-frequency", "account-id": await bareAccountId(args) });
|
|
290
290
|
emit(rows, [
|
|
291
291
|
"Budgets here are in the account currency's minor units (cents). Reserve a quote with `reach-frequency reserve <id>`; a reserved campaign is `campaigns create --buying-type RESERVED` and its ad set `adsets create --reservation <reservation id>`."
|
|
292
292
|
]);
|
|
@@ -380,7 +380,7 @@ Example: baker ads meta reach-frequency predict --account-id act_123 --page-id 9
|
|
|
380
380
|
const reach = numberFlag(args.reach, "--reach");
|
|
381
381
|
const instreamPackages = repeatedValues(rawArgs, "instream-package", args["instream-package"]).flatMap((value) => value.split(",")).map((value) => value.trim().toUpperCase()).filter(Boolean);
|
|
382
382
|
const body = {
|
|
383
|
-
accountId: bareAccountId(args),
|
|
383
|
+
accountId: await bareAccountId(args),
|
|
384
384
|
solveFor: reach !== void 0 ? "budget" : "reach",
|
|
385
385
|
budget: args.budget,
|
|
386
386
|
reach,
|
|
@@ -431,7 +431,7 @@ Example: baker ads meta reach-frequency reserve 120249500564540208 --account-id
|
|
|
431
431
|
run: async ({ args }) => {
|
|
432
432
|
await stageOp({
|
|
433
433
|
kind: "reachFrequencyReservation.create",
|
|
434
|
-
accountId: bareAccountId(args),
|
|
434
|
+
accountId: await bareAccountId(args),
|
|
435
435
|
payload: { prediction_id: requireTarget(args, "quote") }
|
|
436
436
|
});
|
|
437
437
|
}
|
|
@@ -454,7 +454,7 @@ Example: baker ads meta reach-frequency cancel 120249500569290208 --account-id a
|
|
|
454
454
|
run: async ({ args }) => {
|
|
455
455
|
await stageOp({
|
|
456
456
|
kind: "reachFrequencyReservation.update",
|
|
457
|
-
accountId: bareAccountId(args),
|
|
457
|
+
accountId: await bareAccountId(args),
|
|
458
458
|
target: requireTarget(args, "reservation"),
|
|
459
459
|
payload: { status: "CANCELLED" }
|
|
460
460
|
});
|
|
@@ -592,7 +592,7 @@ Example: baker ads meta account-details --account-id act_123 --show users
|
|
|
592
592
|
failWriteValidation(`--show takes ${Object.keys(ACCOUNT_DETAILS).join(", ")}`);
|
|
593
593
|
}
|
|
594
594
|
try {
|
|
595
|
-
const rows = await readEdge({ edge: show, "account-id": bareAccountId(args) });
|
|
595
|
+
const rows = await readEdge({ edge: show, "account-id": await bareAccountId(args) });
|
|
596
596
|
emit(rows, rows.length === 0 ? [`No ${show} on this ad account.`] : []);
|
|
597
597
|
} catch (err) {
|
|
598
598
|
handleMetaError(err);
|
|
@@ -608,4 +608,4 @@ export {
|
|
|
608
608
|
pagePostsCommand,
|
|
609
609
|
reachFrequencyCommand
|
|
610
610
|
};
|
|
611
|
-
//# sourceMappingURL=account-level-
|
|
611
|
+
//# sourceMappingURL=account-level-GK7M2MMQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/ads/meta/account-level.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport { apiGet, apiPost } from \"../../../client.ts\";\nimport { repeatedValues } from \"../../../lib/repeatedFlags.ts\";\nimport { registerSchema } from \"../../../schemas.ts\";\nimport { writeJsonEnvelope } from \"../output.ts\";\nimport { dayPartingFromFlags } from \"./delivery-flags.ts\";\nimport { handleMetaError } from \"./shared.ts\";\nimport {\n bareAccountId,\n failWriteValidation,\n loadJsonFileArg,\n numberFlag,\n requireTarget,\n stageOp,\n} from \"./write-shared.ts\";\n\n/**\n * What belongs to the ad account itself rather than to a campaign: its own\n * settings (name, account spending limit), its publisher block lists, and its\n * reach-and-frequency quotes and reservations — plus the posts an ad can boost\n * and the comments on an ad's post. Changes stage on this chat's draft and are\n * made at publish; reads are live.\n */\n\ntype Row = Record<string, unknown>;\ntype Args = Record<string, unknown>;\n\nconst STAGED_NOTE = \"Staged until publish — review with `baker ads meta draft`.\";\nconst schemaAccount = { type: \"string\", description: \"Numeric account ID or act_N\", required: false };\n\nfunction emit(data: unknown, hints: string[] = []): void {\n writeJsonEnvelope(hints.length > 0 ? { ok: true, data, hints } : { ok: true, data });\n}\n\nasync function readEdge(params: Record<string, string>): Promise<Row[]> {\n return await apiGet<Row[]>(\"/api/ads/meta/account-edges\", params);\n}\n\n// --- Account settings ---\n\nregisterSchema({\n command: \"ads.meta.account-settings\",\n description:\n \"Stage a change to the ad account's own settings: its name or its account spending limit (set, remove, or count again from zero). Made at publish.\",\n args: {\n \"account-id\": schemaAccount,\n name: { type: \"string\", description: \"New account name\", required: false },\n \"spending-limit\": {\n type: \"string\",\n description: \"Account spending limit, major units (e.g. 5000)\",\n required: false,\n },\n \"remove-spending-limit\": { type: \"boolean\", description: \"Remove the spending limit\", required: false },\n \"reset-spending-limit\": { type: \"boolean\", description: \"Count toward the limit again from zero\", required: false },\n \"default-eu-advertiser\": {\n type: \"string\",\n description: \"Default EU (DSA) advertiser — who the ads are for — for new ad sets; pass with --default-eu-payer\",\n required: false,\n },\n \"default-eu-payer\": {\n type: \"string\",\n description: \"Default EU (DSA) payer for new ad sets; pass with --default-eu-advertiser\",\n required: false,\n },\n \"clear-default-eu\": {\n type: \"boolean\",\n description: \"Clear both the default EU advertiser and payer\",\n required: false,\n },\n },\n});\n\nexport const accountSettingsCommand = defineCommand({\n meta: {\n name: \"account-settings\",\n description: `Change the ad account's own settings — its name or its account spending limit. ${STAGED_NOTE}\nThe limit counts spend from the moment it is set (Meta starts the count again), and every campaign on the account stops when it is reached. Ask the user before touching it — it is account-wide.\nStart here: baker ads meta account --account-id act_123 (shows spend_cap and amount_spent, in minor units)\nExample: baker ads meta account-settings --account-id act_123 --spending-limit 5000\n baker ads meta account-settings --account-id act_123 --remove-spending-limit\nThe EU (DSA) advertiser and payer new ad sets start with — both together, names from \\`baker ads meta dsa-recommendations\\` confirmed with the user:\n baker ads meta account-settings --account-id act_123 --default-eu-advertiser \"Acme SL\" --default-eu-payer \"Acme SL\"`,\n },\n args: {\n \"account-id\": { type: \"string\", description: \"Numeric account ID or act_N — the account itself\" },\n name: { type: \"string\", description: \"New account name\" },\n \"spending-limit\": { type: \"string\", description: \"Account spending limit in the account currency, e.g. 5000\" },\n \"remove-spending-limit\": { type: \"boolean\", description: \"Take the account spending limit away\" },\n \"reset-spending-limit\": { type: \"boolean\", description: \"Keep the limit and count spend toward it from zero\" },\n \"default-eu-advertiser\": {\n type: \"string\",\n description: \"Default EU (DSA) advertiser for new ad sets — with --default-eu-payer (Meta keeps both or neither)\",\n },\n \"default-eu-payer\": { type: \"string\", description: \"Default EU (DSA) payer for new ad sets\" },\n \"clear-default-eu\": { type: \"boolean\", description: \"Clear both the default EU advertiser and payer\" },\n },\n run: async ({ args }) => {\n const accountId = await bareAccountId(args as Args);\n if (args[\"remove-spending-limit\"] && args[\"reset-spending-limit\"]) {\n failWriteValidation(\"pass --remove-spending-limit OR --reset-spending-limit\");\n }\n const action = args[\"remove-spending-limit\"] ? \"remove\" : args[\"reset-spending-limit\"] ? \"reset\" : undefined;\n await stageOp({\n kind: \"adAccount.update\",\n accountId,\n target: accountId,\n payload: {\n name: args.name,\n spendCap: args[\"spending-limit\"] ? { amount: String(args[\"spending-limit\"]) } : undefined,\n spendCapAction: action,\n defaultDsaBeneficiary: args[\"default-eu-advertiser\"],\n defaultDsaPayor: args[\"default-eu-payer\"],\n clearDefaultDsa: args[\"clear-default-eu\"] ? true : undefined,\n },\n });\n },\n});\n\n// --- Block lists ---\n\nregisterSchema({\n command: \"ads.meta.block-lists\",\n description:\n \"The ad account's publisher block lists — websites and apps its ads stay off (Audience Network, in-stream). --full lists each list's sites.\",\n args: {\n \"account-id\": schemaAccount,\n full: { type: \"boolean\", description: \"Include each list's sites and apps\", required: false },\n },\n});\n\nconst blockListsListCommand = defineCommand({\n meta: {\n name: \"list\",\n description:\n \"Block lists on the ad account. Runs by default. Example: baker ads meta block-lists --account-id act_123 --full\",\n },\n args: {\n \"account-id\": { type: \"string\", description: \"Numeric account ID or act_N\" },\n full: { type: \"boolean\", description: \"Include each list's sites and apps\" },\n },\n run: async ({ args }) => {\n try {\n const params: Record<string, string> = { edge: \"block-lists\", \"account-id\": await bareAccountId(args as Args) };\n if (args.full) params.full = \"true\";\n const rows = await readEdge(params);\n emit(rows, [\n \"Keep an ad set off a list with `adsets create|update --block-list <id>` (repeatable); add sites with `block-lists add <id> --url …`. Meta takes no site off a list and renames none — make a new list instead.\",\n ]);\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n\nregisterSchema({\n command: \"ads.meta.block-lists.create\",\n description: \"Stage a new publisher block list on the ad account, with its sites and apps. Made at publish.\",\n args: {\n \"account-id\": schemaAccount,\n name: { type: \"string\", description: \"List name\", required: true },\n url: { type: \"string\", description: \"A site (example.com) or app store address — repeatable\", required: false },\n file: { type: \"string\", description: 'JSON file {\"urls\": [...]} for long lists', required: false },\n },\n});\n\nfunction urlsFrom(args: Args, rawArgs: readonly string[]): string[] {\n const file = loadJsonFileArg(args.file);\n const fromFile = Array.isArray(file.urls) ? file.urls.filter((u): u is string => typeof u === \"string\") : [];\n const urls = [...repeatedValues(rawArgs, \"url\", args.url), ...fromFile];\n if (urls.length === 0) failWriteValidation('pass --url (repeatable) or --file with {\"urls\": [...]}');\n return urls;\n}\n\nconst blockListsCreateCommand = defineCommand({\n meta: {\n name: \"create\",\n description: `Create a publisher block list. ${STAGED_NOTE}\nExample: baker ads meta block-lists create --account-id act_123 --name \"No gambling sites\" --url casino.example --url bets.example\nThen keep ad sets off it: baker ads meta adsets update <id> --block-list meta_temp_…`,\n },\n args: {\n \"account-id\": { type: \"string\", description: \"Numeric account ID or act_N\" },\n name: { type: \"string\", description: \"List name\", required: true },\n url: { type: \"string\", description: \"A site (example.com) or app store address — repeatable\" },\n file: { type: \"string\", description: 'JSON file {\"urls\": [...]} for a long list (up to 10,000)' },\n },\n run: async ({ args, rawArgs }) => {\n await stageOp({\n kind: \"publisherBlockList.create\",\n accountId: await bareAccountId(args as Args),\n payload: { name: args.name, urls: urlsFrom(args as Args, rawArgs) },\n });\n },\n});\n\nregisterSchema({\n command: \"ads.meta.block-lists.add\",\n description: \"Stage adding sites and apps to a block list. Meta takes none off a list.\",\n args: {\n id: { type: \"positional\", description: \"Block list id\", required: true },\n \"account-id\": schemaAccount,\n url: { type: \"string\", description: \"A site or app store address — repeatable\", required: false },\n file: { type: \"string\", description: 'JSON file {\"urls\": [...]}', required: false },\n },\n});\n\nconst blockListsAddCommand = defineCommand({\n meta: {\n name: \"add\",\n description: `Add sites and apps to a block list. ${STAGED_NOTE}\nExample: baker ads meta block-lists add 120249500506120208 --account-id act_123 --url spam.example`,\n },\n args: {\n id: { type: \"positional\", description: \"Block list id\", required: true },\n \"account-id\": { type: \"string\", description: \"Numeric account ID or act_N\" },\n url: { type: \"string\", description: \"A site or app store address — repeatable\" },\n file: { type: \"string\", description: 'JSON file {\"urls\": [...]}' },\n },\n run: async ({ args, rawArgs }) => {\n await stageOp({\n kind: \"publisherBlockList.update\",\n accountId: await bareAccountId(args as Args),\n target: requireTarget(args as Args, \"block list\"),\n payload: { addUrls: urlsFrom(args as Args, rawArgs) },\n });\n },\n});\n\nregisterSchema({\n command: \"ads.meta.block-lists.delete\",\n description: \"Stage deleting a block list. Ad sets that used it can show on its sites again.\",\n args: { id: { type: \"positional\", description: \"Block list id\", required: true }, \"account-id\": schemaAccount },\n});\n\nconst blockListsDeleteCommand = defineCommand({\n meta: {\n name: \"delete\",\n description: `Delete a block list — ad sets that used it can show on its sites and apps again. ${STAGED_NOTE}\nExample: baker ads meta block-lists delete 120249500506120208 --account-id act_123`,\n },\n args: {\n id: { type: \"positional\", description: \"Block list id\", required: true },\n \"account-id\": { type: \"string\", description: \"Numeric account ID or act_N\" },\n },\n run: async ({ args }) => {\n await stageOp({\n kind: \"publisherBlockList.update\",\n accountId: await bareAccountId(args as Args),\n target: requireTarget(args as Args, \"block list\"),\n payload: { status: \"DELETED\" },\n });\n },\n});\n\nexport const blockListsCommand = defineCommand({\n meta: {\n name: \"block-lists\",\n description: `Publisher block lists — websites and apps the ad account's ads stay off (Audience Network, in-stream).\n baker ads meta block-lists --account-id act_123 [--full]\n baker ads meta block-lists create --name … --url … | add <id> --url … | delete <id>\nAn ad set uses a list with \\`adsets create|update --block-list <id>\\`; \\`--content-filter FEED_STRICT\\` and \\`--exclude-publisher-category gambling\\` set the rest of its brand safety.`,\n },\n subCommands: {\n list: blockListsListCommand,\n create: blockListsCreateCommand,\n add: blockListsAddCommand,\n delete: blockListsDeleteCommand,\n },\n args: {\n \"account-id\": { type: \"string\", description: \"Numeric account ID or act_N\" },\n full: { type: \"boolean\", description: \"Include each list's sites and apps\" },\n },\n default: \"list\",\n});\n\n// --- Reach and frequency ---\n\nregisterSchema({\n command: \"ads.meta.reach-frequency\",\n description:\n \"The ad account's reach-and-frequency quotes and reservations: reach, budget, dates, frequency cap, whether reserved and until when.\",\n args: { \"account-id\": schemaAccount },\n});\n\nconst reachFrequencyListCommand = defineCommand({\n meta: {\n name: \"list\",\n description:\n \"Reach-and-frequency quotes on the ad account (reservation_status 1 = reserved, until expiration_time). Runs by default. Example: baker ads meta reach-frequency --account-id act_123\",\n },\n args: { \"account-id\": { type: \"string\", description: \"Numeric account ID or act_N\" } },\n run: async ({ args }) => {\n try {\n const rows = await readEdge({ edge: \"reach-frequency\", \"account-id\": await bareAccountId(args as Args) });\n emit(rows, [\n \"Budgets here are in the account currency's minor units (cents). Reserve a quote with `reach-frequency reserve <id>`; a reserved campaign is `campaigns create --buying-type RESERVED` and its ad set `adsets create --reservation <reservation id>`.\",\n ]);\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n\nregisterSchema({\n command: \"ads.meta.reach-frequency.predict\",\n description:\n \"Ask Meta for a reach-and-frequency quote: how many people a budget reaches (or what a reach costs) over fixed dates in one country, at a frequency cap. A forecast — holds nothing and spends nothing.\",\n args: {\n \"account-id\": schemaAccount,\n \"page-id\": { type: \"string\", description: \"Facebook Page the ads run as\", required: true },\n budget: { type: \"string\", description: \"Lifetime budget, major units (solves for reach)\", required: false },\n reach: { type: \"string\", description: \"People to reach (solves for budget)\", required: false },\n start: { type: \"string\", description: \"Start, ISO date-time\", required: true },\n end: { type: \"string\", description: \"End, ISO date-time\", required: true },\n \"frequency-cap\": {\n type: \"string\",\n description: \"Most times one person sees it per --frequency-days\",\n required: false,\n },\n \"frequency-days\": { type: \"string\", description: \"Days the cap counts over (default 7)\", required: false },\n objective: { type: \"string\", description: \"REACH (default) | BRAND_AWARENESS | VIDEO_VIEWS | …\", required: false },\n \"optimization-goal\": { type: \"string\", description: \"Optional optimization goal\", required: false },\n \"instagram-user\": { type: \"string\", description: \"Instagram account the ads run as\", required: false },\n \"targeting-file\": { type: \"string\", description: \"Targeting JSON — ONE country\", required: true },\n schedule: { type: \"string\", description: 'Hours to run in, repeatable: \"Mon-Fri 09-18\"', required: false },\n \"target-frequency\": {\n type: \"string\",\n description: \"Balanced frequency: views per person per --target-frequency-days (OUTCOME_AWARENESS + REACH)\",\n required: false,\n },\n \"target-frequency-days\": {\n type: \"string\",\n description: \"Days the target counts over (default 7)\",\n required: false,\n },\n \"instream-package\": {\n type: \"string\",\n description: \"In-stream video packages, repeatable: NORMAL | PREMIUM | SPORTS | …\",\n required: false,\n },\n },\n});\n\nfunction unixSeconds(value: unknown, flag: string): number {\n const ms = typeof value === \"string\" ? Date.parse(value) : Number.NaN;\n if (!Number.isFinite(ms)) failWriteValidation(`${flag} takes an ISO date-time, e.g. 2026-11-01T00:00:00Z`);\n return Math.floor(ms / 1000);\n}\n\nconst reachFrequencyPredictCommand = defineCommand({\n meta: {\n name: \"predict\",\n description: `Ask Meta what a reach-and-frequency buy would reach (or cost). A forecast: nothing is held or spent, and the quote expires on its own.\nStart here: baker ads meta account --account-id act_123 (the account needs CAN_USE_REACH_AND_FREQUENCY; Meta's floor is about 200,000 people per country)\nExample: baker ads meta reach-frequency predict --account-id act_123 --page-id 904238019441800 --budget 1000 --start 2026-11-01T00:00:00Z --end 2026-11-08T00:00:00Z --frequency-cap 2 --targeting-file t.json`,\n },\n args: {\n \"account-id\": { type: \"string\", description: \"Numeric account ID or act_N\" },\n \"page-id\": { type: \"string\", description: \"Facebook Page the ads run as — from `baker ads meta pages`\" },\n \"instagram-user\": { type: \"string\", description: \"Instagram account the ads run as\" },\n budget: { type: \"string\", description: \"Lifetime budget in the account currency (solves for reach)\" },\n reach: { type: \"string\", description: \"People to reach (solves for budget)\" },\n start: { type: \"string\", description: \"Start, ISO date-time\" },\n end: { type: \"string\", description: \"End, ISO date-time (at most 90 days after the start)\" },\n \"frequency-cap\": { type: \"string\", description: \"Most times one person sees the ads per --frequency-days\" },\n \"frequency-days\": { type: \"string\", description: \"Days the cap counts over (default 7)\" },\n objective: {\n type: \"string\",\n description:\n \"REACH (default) | BRAND_AWARENESS | VIDEO_VIEWS | POST_ENGAGEMENT | LINK_CLICKS | OUTCOME_AWARENESS | OUTCOME_ENGAGEMENT\",\n },\n \"optimization-goal\": { type: \"string\", description: \"Optional optimization goal\" },\n \"targeting-file\": { type: \"string\", description: \"Targeting JSON (as for adsets create) — ONE country\" },\n schedule: {\n type: \"string\",\n description:\n 'Run only in these hours, repeatable: \"<days> <from>-<to>\", e.g. \"Mon-Fri 09-18\". Live, Meta stored day-parted quotes but answered status 18 (no reach) for them',\n },\n \"target-frequency\": {\n type: \"string\",\n description:\n \"Balanced frequency: aim each person at this many views per --target-frequency-days (default 7) instead of a cap — needs --objective OUTCOME_AWARENESS and --optimization-goal REACH\",\n },\n \"target-frequency-days\": { type: \"string\", description: \"Days the target frequency counts over (default 7)\" },\n \"instream-package\": {\n type: \"string\",\n description:\n \"In-stream video packages the ads may run in, repeatable: NORMAL | PREMIUM | SPORTS | ENTERTAINMENT | …\",\n },\n },\n run: async ({ args, rawArgs }) => {\n if (!args[\"targeting-file\"]) failWriteValidation(\"pass --targeting-file (one country)\");\n const reach = numberFlag(args.reach, \"--reach\");\n const instreamPackages = repeatedValues(rawArgs, \"instream-package\", args[\"instream-package\"])\n .flatMap((value) => value.split(\",\"))\n .map((value) => value.trim().toUpperCase())\n .filter(Boolean);\n const body = {\n accountId: await bareAccountId(args as Args),\n solveFor: reach !== undefined ? \"budget\" : \"reach\",\n budget: args.budget,\n reach,\n start_time: unixSeconds(args.start, \"--start\"),\n end_time: unixSeconds(args.end, \"--end\"),\n frequencyCap: numberFlag(args[\"frequency-cap\"], \"--frequency-cap\"),\n frequencyCapDays: numberFlag(args[\"frequency-days\"], \"--frequency-days\"),\n objective: args.objective,\n optimization_goal: args[\"optimization-goal\"],\n page_id: args[\"page-id\"],\n instagram_user_id: args[\"instagram-user\"],\n targeting: loadJsonFileArg(args[\"targeting-file\"]),\n targetFrequency: numberFlag(args[\"target-frequency\"], \"--target-frequency\"),\n targetFrequencyDays: numberFlag(args[\"target-frequency-days\"], \"--target-frequency-days\"),\n day_parting_schedule: dayPartingFromFlags(args as Args, rawArgs),\n instream_packages: instreamPackages.length > 0 ? instreamPackages : undefined,\n };\n try {\n const quote = await apiPost<Row>(\"/api/ads/meta/reach-frequency/predict\", body);\n const unanswered =\n quote.status === 1\n ? []\n : [\n `Meta did not quote this (status ${String(quote.status)}, reach 0) — nothing to reserve. Live, a run ending before 6 AM account time on its last day came back this way: move --end later in the day, or widen the audience (Meta's floor is about 200,000 people), and ask again.`,\n ];\n emit(quote, [\n ...unanswered,\n \"external_reach / external_impression are what Meta forecasts; external_budget and the min/max bounds are in minor units (cents). To hold this price, `reach-frequency reserve <id>` (staged, made at publish).\",\n ]);\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n\nregisterSchema({\n command: \"ads.meta.reach-frequency.reserve\",\n description:\n \"Stage reserving a reach-and-frequency quote: Meta holds its price for about two weeks. Made at publish.\",\n args: { id: { type: \"positional\", description: \"Quote id\", required: true }, \"account-id\": schemaAccount },\n});\n\nconst reachFrequencyReserveCommand = defineCommand({\n meta: {\n name: \"reserve\",\n description: `Reserve a reach-and-frequency quote — Meta holds its price until the reservation expires. ${STAGED_NOTE}\nThen buy on it: campaigns create --buying-type RESERVED …, adsets create --reservation meta_temp_… (no budget — it comes from the quote).\nExample: baker ads meta reach-frequency reserve 120249500564540208 --account-id act_123`,\n },\n args: {\n id: { type: \"positional\", description: \"Quote id (from `reach-frequency predict` or the list)\", required: true },\n \"account-id\": { type: \"string\", description: \"Numeric account ID or act_N\" },\n },\n run: async ({ args }) => {\n await stageOp({\n kind: \"reachFrequencyReservation.create\",\n accountId: await bareAccountId(args as Args),\n payload: { prediction_id: requireTarget(args as Args, \"quote\") },\n });\n },\n});\n\nregisterSchema({\n command: \"ads.meta.reach-frequency.cancel\",\n description: \"Stage cancelling a reach-and-frequency reservation, releasing its price. Made at publish.\",\n args: { id: { type: \"positional\", description: \"Reservation id\", required: true }, \"account-id\": schemaAccount },\n});\n\nconst reachFrequencyCancelCommand = defineCommand({\n meta: {\n name: \"cancel\",\n description: `Cancel a reach-and-frequency reservation. ${STAGED_NOTE}\nExample: baker ads meta reach-frequency cancel 120249500569290208 --account-id act_123`,\n },\n args: {\n id: { type: \"positional\", description: \"Reservation id\", required: true },\n \"account-id\": { type: \"string\", description: \"Numeric account ID or act_N\" },\n },\n run: async ({ args }) => {\n await stageOp({\n kind: \"reachFrequencyReservation.update\",\n accountId: await bareAccountId(args as Args),\n target: requireTarget(args as Args, \"reservation\"),\n payload: { status: \"CANCELLED\" },\n });\n },\n});\n\nexport const reachFrequencyCommand = defineCommand({\n meta: {\n name: \"reach-frequency\",\n description: `Reach and frequency buying (Reservation): a fixed reach at a fixed price over fixed dates.\n baker ads meta reach-frequency --account-id act_123 — quotes and reservations\n baker ads meta reach-frequency predict --budget 1000 --start … --end … --targeting-file t.json — a quote (holds nothing)\n baker ads meta reach-frequency reserve <quote id> | cancel <reservation id> — staged, made at publish`,\n },\n subCommands: {\n list: reachFrequencyListCommand,\n predict: reachFrequencyPredictCommand,\n reserve: reachFrequencyReserveCommand,\n cancel: reachFrequencyCancelCommand,\n },\n args: { \"account-id\": { type: \"string\", description: \"Numeric account ID or act_N\" } },\n default: \"list\",\n});\n\n// --- Posts an ad can boost, and comments on ads ---\n\nregisterSchema({\n command: \"ads.meta.page-posts\",\n description:\n \"A Facebook Page's recent posts, with is_eligible_for_promotion — the posts a `creatives create --type existing_post --post-id` can boost.\",\n args: { \"page-id\": { type: \"string\", description: \"Facebook Page id\", required: true } },\n});\n\nexport const pagePostsCommand = defineCommand({\n meta: {\n name: \"page-posts\",\n description: `A Facebook Page's recent posts, for boosting one as an ad (keeps its likes and comments).\nExample: baker ads meta page-posts --page-id 904238019441800\nThen: baker ads meta creatives create --type existing_post --post-id <id> (only a post with is_eligible_for_promotion: true)`,\n },\n args: { \"page-id\": { type: \"string\", description: \"Facebook Page id — from `baker ads meta pages`\" } },\n run: async ({ args }) => {\n if (!args[\"page-id\"]) failWriteValidation(\"pass --page-id (from `baker ads meta pages`)\");\n try {\n const rows = await readEdge({ edge: \"page-posts\", \"page-id\": String(args[\"page-id\"]) });\n emit(rows, [\n \"Boost one with `creatives create --type existing_post --post-id <id>`; is_eligible_for_promotion false means Meta will not run it as an ad.\",\n ]);\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n\nregisterSchema({\n command: \"ads.meta.instagram-media\",\n description:\n \"An Instagram account's posts, for boosting one as an ad (`creatives create --type existing_post --instagram-media-id`).\",\n args: { \"instagram-user\": { type: \"string\", description: \"Instagram account id\", required: true } },\n});\n\nexport const instagramMediaCommand = defineCommand({\n meta: {\n name: \"instagram-media\",\n description: `An Instagram account's posts, for boosting one as an ad.\nExample: baker ads meta instagram-media --instagram-user 17841478810711864\nThen: baker ads meta creatives create --type existing_post --instagram-media-id <id> --page <brand page> --instagram-user <id>`,\n },\n args: {\n \"instagram-user\": {\n type: \"string\",\n description: \"Instagram account id — from `baker ads meta instagram-accounts`\",\n },\n },\n run: async ({ args }) => {\n if (!args[\"instagram-user\"])\n failWriteValidation(\"pass --instagram-user (from `baker ads meta instagram-accounts`)\");\n try {\n emit(await readEdge({ edge: \"instagram-media\", \"instagram-user\": String(args[\"instagram-user\"]) }));\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n\nregisterSchema({\n command: \"ads.meta.comments\",\n description:\n \"The comments on an ad's post (Facebook). Needs Meta permissions the connection may not hold — a refusal says so; moderation then happens in Meta Business Suite.\",\n args: {\n \"ad-id\": { type: \"string\", description: \"Ad id\", required: true },\n full: { type: \"boolean\", description: \"Include who wrote each and its replies count\", required: false },\n },\n});\n\nexport const commentsCommand = defineCommand({\n meta: {\n name: \"comments\",\n description: `The comments people left on an ad's post.\nExample: baker ads meta comments --ad-id 120211234567890\nReading needs a Meta permission Baker's connection does not ask for yet; when Meta refuses, say moderation happens in Meta Business Suite and carry on.`,\n },\n args: {\n \"ad-id\": { type: \"string\", description: \"Ad id — from `baker ads meta ads`\" },\n full: { type: \"boolean\", description: \"Include who wrote each comment\" },\n },\n run: async ({ args }) => {\n if (!args[\"ad-id\"]) failWriteValidation(\"pass --ad-id (from `baker ads meta ads`)\");\n try {\n const params: Record<string, string> = { \"ad-id\": String(args[\"ad-id\"]) };\n if (args.full) params.full = \"true\";\n emit(await apiGet<Row[]>(\"/api/ads/meta/ad-comments\", params));\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n\n// --- What else hangs off the account (reads) ---\n\nconst ACCOUNT_DETAILS = {\n recommendations: \"Meta's suggestions for the account (often empty)\",\n users: \"the people on the account and their tasks (MANAGE, ADVERTISE, ANALYZE, DRAFT) — read only\",\n \"account-controls\":\n \"account-wide Advantage+ controls: the minimum age, locations and placements every Advantage+ campaign keeps to — read only\",\n playables: \"playable ads (HTML) uploaded for app ads — read only\",\n \"place-page-sets\": \"store-location page sets for local ads — read only\",\n} as const;\ntype AccountDetail = keyof typeof ACCOUNT_DETAILS;\n\nregisterSchema({\n command: \"ads.meta.account-details\",\n description: `What else belongs to the ad account, read live — --show one of: ${Object.entries(ACCOUNT_DETAILS)\n .map(([name, what]) => `${name} (${what})`)\n .join(\"; \")}.`,\n args: {\n \"account-id\": schemaAccount,\n show: { type: \"string\", description: Object.keys(ACCOUNT_DETAILS).join(\"|\"), required: true },\n },\n});\n\nexport const accountDetailsCommand = defineCommand({\n meta: {\n name: \"account-details\",\n description: `What else belongs to the ad account, read live. Nothing here is changed by Baker.\nExample: baker ads meta account-details --account-id act_123 --show users\n--show ${Object.keys(ACCOUNT_DETAILS).join(\" | \")}`,\n },\n args: {\n \"account-id\": { type: \"string\", description: \"Numeric account ID or act_N\" },\n show: { type: \"string\", description: Object.keys(ACCOUNT_DETAILS).join(\" | \") },\n },\n run: async ({ args }) => {\n const show = String(args.show ?? \"\");\n if (!(show in ACCOUNT_DETAILS)) {\n failWriteValidation(`--show takes ${Object.keys(ACCOUNT_DETAILS).join(\", \")}`);\n }\n try {\n const rows = await readEdge({ edge: show as AccountDetail, \"account-id\": await bareAccountId(args as Args) });\n emit(rows, rows.length === 0 ? [`No ${show} on this ad account.`] : []);\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,qBAAqB;AA2B9B,IAAM,cAAc;AACpB,IAAM,gBAAgB,EAAE,MAAM,UAAU,aAAa,+BAA+B,UAAU,MAAM;AAEpG,SAAS,KAAK,MAAe,QAAkB,CAAC,GAAS;AACvD,oBAAkB,MAAM,SAAS,IAAI,EAAE,IAAI,MAAM,MAAM,MAAM,IAAI,EAAE,IAAI,MAAM,KAAK,CAAC;AACrF;AAEA,eAAe,SAAS,QAAgD;AACtE,SAAO,MAAM,OAAc,+BAA+B,MAAM;AAClE;AAIA,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aACE;AAAA,EACF,MAAM;AAAA,IACJ,cAAc;AAAA,IACd,MAAM,EAAE,MAAM,UAAU,aAAa,oBAAoB,UAAU,MAAM;AAAA,IACzE,kBAAkB;AAAA,MAChB,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,IACZ;AAAA,IACA,yBAAyB,EAAE,MAAM,WAAW,aAAa,6BAA6B,UAAU,MAAM;AAAA,IACtG,wBAAwB,EAAE,MAAM,WAAW,aAAa,0CAA0C,UAAU,MAAM;AAAA,IAClH,yBAAyB;AAAA,MACvB,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,IACZ;AAAA,IACA,oBAAoB;AAAA,MAClB,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,IACZ;AAAA,IACA,oBAAoB;AAAA,MAClB,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,IACZ;AAAA,EACF;AACF,CAAC;AAEM,IAAM,yBAAyB,cAAc;AAAA,EAClD,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa,uFAAkF,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO5G;AAAA,EACA,MAAM;AAAA,IACJ,cAAc,EAAE,MAAM,UAAU,aAAa,wDAAmD;AAAA,IAChG,MAAM,EAAE,MAAM,UAAU,aAAa,mBAAmB;AAAA,IACxD,kBAAkB,EAAE,MAAM,UAAU,aAAa,4DAA4D;AAAA,IAC7G,yBAAyB,EAAE,MAAM,WAAW,aAAa,uCAAuC;AAAA,IAChG,wBAAwB,EAAE,MAAM,WAAW,aAAa,qDAAqD;AAAA,IAC7G,yBAAyB;AAAA,MACvB,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAAA,IACA,oBAAoB,EAAE,MAAM,UAAU,aAAa,yCAAyC;AAAA,IAC5F,oBAAoB,EAAE,MAAM,WAAW,aAAa,iDAAiD;AAAA,EACvG;AAAA,EACA,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,UAAM,YAAY,MAAM,cAAc,IAAY;AAClD,QAAI,KAAK,uBAAuB,KAAK,KAAK,sBAAsB,GAAG;AACjE,0BAAoB,wDAAwD;AAAA,IAC9E;AACA,UAAM,SAAS,KAAK,uBAAuB,IAAI,WAAW,KAAK,sBAAsB,IAAI,UAAU;AACnG,UAAM,QAAQ;AAAA,MACZ,MAAM;AAAA,MACN;AAAA,MACA,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,MAAM,KAAK;AAAA,QACX,UAAU,KAAK,gBAAgB,IAAI,EAAE,QAAQ,OAAO,KAAK,gBAAgB,CAAC,EAAE,IAAI;AAAA,QAChF,gBAAgB;AAAA,QAChB,uBAAuB,KAAK,uBAAuB;AAAA,QACnD,iBAAiB,KAAK,kBAAkB;AAAA,QACxC,iBAAiB,KAAK,kBAAkB,IAAI,OAAO;AAAA,MACrD;AAAA,IACF,CAAC;AAAA,EACH;AACF,CAAC;AAID,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aACE;AAAA,EACF,MAAM;AAAA,IACJ,cAAc;AAAA,IACd,MAAM,EAAE,MAAM,WAAW,aAAa,sCAAsC,UAAU,MAAM;AAAA,EAC9F;AACF,CAAC;AAED,IAAM,wBAAwB,cAAc;AAAA,EAC1C,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aACE;AAAA,EACJ;AAAA,EACA,MAAM;AAAA,IACJ,cAAc,EAAE,MAAM,UAAU,aAAa,8BAA8B;AAAA,IAC3E,MAAM,EAAE,MAAM,WAAW,aAAa,qCAAqC;AAAA,EAC7E;AAAA,EACA,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,QAAI;AACF,YAAM,SAAiC,EAAE,MAAM,eAAe,cAAc,MAAM,cAAc,IAAY,EAAE;AAC9G,UAAI,KAAK,KAAM,QAAO,OAAO;AAC7B,YAAM,OAAO,MAAM,SAAS,MAAM;AAClC,WAAK,MAAM;AAAA,QACT;AAAA,MACF,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,sBAAgB,GAAG;AAAA,IACrB;AAAA,EACF;AACF,CAAC;AAED,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aAAa;AAAA,EACb,MAAM;AAAA,IACJ,cAAc;AAAA,IACd,MAAM,EAAE,MAAM,UAAU,aAAa,aAAa,UAAU,KAAK;AAAA,IACjE,KAAK,EAAE,MAAM,UAAU,aAAa,+DAA0D,UAAU,MAAM;AAAA,IAC9G,MAAM,EAAE,MAAM,UAAU,aAAa,4CAA4C,UAAU,MAAM;AAAA,EACnG;AACF,CAAC;AAED,SAAS,SAAS,MAAY,SAAsC;AAClE,QAAM,OAAO,gBAAgB,KAAK,IAAI;AACtC,QAAM,WAAW,MAAM,QAAQ,KAAK,IAAI,IAAI,KAAK,KAAK,OAAO,CAAC,MAAmB,OAAO,MAAM,QAAQ,IAAI,CAAC;AAC3G,QAAM,OAAO,CAAC,GAAG,eAAe,SAAS,OAAO,KAAK,GAAG,GAAG,GAAG,QAAQ;AACtE,MAAI,KAAK,WAAW,EAAG,qBAAoB,wDAAwD;AACnG,SAAO;AACT;AAEA,IAAM,0BAA0B,cAAc;AAAA,EAC5C,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa,kCAAkC,WAAW;AAAA;AAAA;AAAA,EAG5D;AAAA,EACA,MAAM;AAAA,IACJ,cAAc,EAAE,MAAM,UAAU,aAAa,8BAA8B;AAAA,IAC3E,MAAM,EAAE,MAAM,UAAU,aAAa,aAAa,UAAU,KAAK;AAAA,IACjE,KAAK,EAAE,MAAM,UAAU,aAAa,8DAAyD;AAAA,IAC7F,MAAM,EAAE,MAAM,UAAU,aAAa,2DAA2D;AAAA,EAClG;AAAA,EACA,KAAK,OAAO,EAAE,MAAM,QAAQ,MAAM;AAChC,UAAM,QAAQ;AAAA,MACZ,MAAM;AAAA,MACN,WAAW,MAAM,cAAc,IAAY;AAAA,MAC3C,SAAS,EAAE,MAAM,KAAK,MAAM,MAAM,SAAS,MAAc,OAAO,EAAE;AAAA,IACpE,CAAC;AAAA,EACH;AACF,CAAC;AAED,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aAAa;AAAA,EACb,MAAM;AAAA,IACJ,IAAI,EAAE,MAAM,cAAc,aAAa,iBAAiB,UAAU,KAAK;AAAA,IACvE,cAAc;AAAA,IACd,KAAK,EAAE,MAAM,UAAU,aAAa,iDAA4C,UAAU,MAAM;AAAA,IAChG,MAAM,EAAE,MAAM,UAAU,aAAa,6BAA6B,UAAU,MAAM;AAAA,EACpF;AACF,CAAC;AAED,IAAM,uBAAuB,cAAc;AAAA,EACzC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa,uCAAuC,WAAW;AAAA;AAAA,EAEjE;AAAA,EACA,MAAM;AAAA,IACJ,IAAI,EAAE,MAAM,cAAc,aAAa,iBAAiB,UAAU,KAAK;AAAA,IACvE,cAAc,EAAE,MAAM,UAAU,aAAa,8BAA8B;AAAA,IAC3E,KAAK,EAAE,MAAM,UAAU,aAAa,gDAA2C;AAAA,IAC/E,MAAM,EAAE,MAAM,UAAU,aAAa,4BAA4B;AAAA,EACnE;AAAA,EACA,KAAK,OAAO,EAAE,MAAM,QAAQ,MAAM;AAChC,UAAM,QAAQ;AAAA,MACZ,MAAM;AAAA,MACN,WAAW,MAAM,cAAc,IAAY;AAAA,MAC3C,QAAQ,cAAc,MAAc,YAAY;AAAA,MAChD,SAAS,EAAE,SAAS,SAAS,MAAc,OAAO,EAAE;AAAA,IACtD,CAAC;AAAA,EACH;AACF,CAAC;AAED,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aAAa;AAAA,EACb,MAAM,EAAE,IAAI,EAAE,MAAM,cAAc,aAAa,iBAAiB,UAAU,KAAK,GAAG,cAAc,cAAc;AAChH,CAAC;AAED,IAAM,0BAA0B,cAAc;AAAA,EAC5C,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa,yFAAoF,WAAW;AAAA;AAAA,EAE9G;AAAA,EACA,MAAM;AAAA,IACJ,IAAI,EAAE,MAAM,cAAc,aAAa,iBAAiB,UAAU,KAAK;AAAA,IACvE,cAAc,EAAE,MAAM,UAAU,aAAa,8BAA8B;AAAA,EAC7E;AAAA,EACA,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,UAAM,QAAQ;AAAA,MACZ,MAAM;AAAA,MACN,WAAW,MAAM,cAAc,IAAY;AAAA,MAC3C,QAAQ,cAAc,MAAc,YAAY;AAAA,MAChD,SAAS,EAAE,QAAQ,UAAU;AAAA,IAC/B,CAAC;AAAA,EACH;AACF,CAAC;AAEM,IAAM,oBAAoB,cAAc;AAAA,EAC7C,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA;AAAA,EAIf;AAAA,EACA,aAAa;AAAA,IACX,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,QAAQ;AAAA,EACV;AAAA,EACA,MAAM;AAAA,IACJ,cAAc,EAAE,MAAM,UAAU,aAAa,8BAA8B;AAAA,IAC3E,MAAM,EAAE,MAAM,WAAW,aAAa,qCAAqC;AAAA,EAC7E;AAAA,EACA,SAAS;AACX,CAAC;AAID,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aACE;AAAA,EACF,MAAM,EAAE,cAAc,cAAc;AACtC,CAAC;AAED,IAAM,4BAA4B,cAAc;AAAA,EAC9C,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aACE;AAAA,EACJ;AAAA,EACA,MAAM,EAAE,cAAc,EAAE,MAAM,UAAU,aAAa,8BAA8B,EAAE;AAAA,EACrF,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,QAAI;AACF,YAAM,OAAO,MAAM,SAAS,EAAE,MAAM,mBAAmB,cAAc,MAAM,cAAc,IAAY,EAAE,CAAC;AACxG,WAAK,MAAM;AAAA,QACT;AAAA,MACF,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,sBAAgB,GAAG;AAAA,IACrB;AAAA,EACF;AACF,CAAC;AAED,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aACE;AAAA,EACF,MAAM;AAAA,IACJ,cAAc;AAAA,IACd,WAAW,EAAE,MAAM,UAAU,aAAa,gCAAgC,UAAU,KAAK;AAAA,IACzF,QAAQ,EAAE,MAAM,UAAU,aAAa,mDAAmD,UAAU,MAAM;AAAA,IAC1G,OAAO,EAAE,MAAM,UAAU,aAAa,uCAAuC,UAAU,MAAM;AAAA,IAC7F,OAAO,EAAE,MAAM,UAAU,aAAa,wBAAwB,UAAU,KAAK;AAAA,IAC7E,KAAK,EAAE,MAAM,UAAU,aAAa,sBAAsB,UAAU,KAAK;AAAA,IACzE,iBAAiB;AAAA,MACf,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,IACZ;AAAA,IACA,kBAAkB,EAAE,MAAM,UAAU,aAAa,wCAAwC,UAAU,MAAM;AAAA,IACzG,WAAW,EAAE,MAAM,UAAU,aAAa,4DAAuD,UAAU,MAAM;AAAA,IACjH,qBAAqB,EAAE,MAAM,UAAU,aAAa,8BAA8B,UAAU,MAAM;AAAA,IAClG,kBAAkB,EAAE,MAAM,UAAU,aAAa,oCAAoC,UAAU,MAAM;AAAA,IACrG,kBAAkB,EAAE,MAAM,UAAU,aAAa,qCAAgC,UAAU,KAAK;AAAA,IAChG,UAAU,EAAE,MAAM,UAAU,aAAa,gDAAgD,UAAU,MAAM;AAAA,IACzG,oBAAoB;AAAA,MAClB,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,IACZ;AAAA,IACA,yBAAyB;AAAA,MACvB,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,IACZ;AAAA,IACA,oBAAoB;AAAA,MAClB,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,IACZ;AAAA,EACF;AACF,CAAC;AAED,SAAS,YAAY,OAAgB,MAAsB;AACzD,QAAM,KAAK,OAAO,UAAU,WAAW,KAAK,MAAM,KAAK,IAAI,OAAO;AAClE,MAAI,CAAC,OAAO,SAAS,EAAE,EAAG,qBAAoB,GAAG,IAAI,oDAAoD;AACzG,SAAO,KAAK,MAAM,KAAK,GAAI;AAC7B;AAEA,IAAM,+BAA+B,cAAc;AAAA,EACjD,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA,EAGf;AAAA,EACA,MAAM;AAAA,IACJ,cAAc,EAAE,MAAM,UAAU,aAAa,8BAA8B;AAAA,IAC3E,WAAW,EAAE,MAAM,UAAU,aAAa,kEAA6D;AAAA,IACvG,kBAAkB,EAAE,MAAM,UAAU,aAAa,mCAAmC;AAAA,IACpF,QAAQ,EAAE,MAAM,UAAU,aAAa,6DAA6D;AAAA,IACpG,OAAO,EAAE,MAAM,UAAU,aAAa,sCAAsC;AAAA,IAC5E,OAAO,EAAE,MAAM,UAAU,aAAa,uBAAuB;AAAA,IAC7D,KAAK,EAAE,MAAM,UAAU,aAAa,uDAAuD;AAAA,IAC3F,iBAAiB,EAAE,MAAM,UAAU,aAAa,0DAA0D;AAAA,IAC1G,kBAAkB,EAAE,MAAM,UAAU,aAAa,uCAAuC;AAAA,IACxF,WAAW;AAAA,MACT,MAAM;AAAA,MACN,aACE;AAAA,IACJ;AAAA,IACA,qBAAqB,EAAE,MAAM,UAAU,aAAa,6BAA6B;AAAA,IACjF,kBAAkB,EAAE,MAAM,UAAU,aAAa,2DAAsD;AAAA,IACvG,UAAU;AAAA,MACR,MAAM;AAAA,MACN,aACE;AAAA,IACJ;AAAA,IACA,oBAAoB;AAAA,MAClB,MAAM;AAAA,MACN,aACE;AAAA,IACJ;AAAA,IACA,yBAAyB,EAAE,MAAM,UAAU,aAAa,oDAAoD;AAAA,IAC5G,oBAAoB;AAAA,MAClB,MAAM;AAAA,MACN,aACE;AAAA,IACJ;AAAA,EACF;AAAA,EACA,KAAK,OAAO,EAAE,MAAM,QAAQ,MAAM;AAChC,QAAI,CAAC,KAAK,gBAAgB,EAAG,qBAAoB,qCAAqC;AACtF,UAAM,QAAQ,WAAW,KAAK,OAAO,SAAS;AAC9C,UAAM,mBAAmB,eAAe,SAAS,oBAAoB,KAAK,kBAAkB,CAAC,EAC1F,QAAQ,CAAC,UAAU,MAAM,MAAM,GAAG,CAAC,EACnC,IAAI,CAAC,UAAU,MAAM,KAAK,EAAE,YAAY,CAAC,EACzC,OAAO,OAAO;AACjB,UAAM,OAAO;AAAA,MACX,WAAW,MAAM,cAAc,IAAY;AAAA,MAC3C,UAAU,UAAU,SAAY,WAAW;AAAA,MAC3C,QAAQ,KAAK;AAAA,MACb;AAAA,MACA,YAAY,YAAY,KAAK,OAAO,SAAS;AAAA,MAC7C,UAAU,YAAY,KAAK,KAAK,OAAO;AAAA,MACvC,cAAc,WAAW,KAAK,eAAe,GAAG,iBAAiB;AAAA,MACjE,kBAAkB,WAAW,KAAK,gBAAgB,GAAG,kBAAkB;AAAA,MACvE,WAAW,KAAK;AAAA,MAChB,mBAAmB,KAAK,mBAAmB;AAAA,MAC3C,SAAS,KAAK,SAAS;AAAA,MACvB,mBAAmB,KAAK,gBAAgB;AAAA,MACxC,WAAW,gBAAgB,KAAK,gBAAgB,CAAC;AAAA,MACjD,iBAAiB,WAAW,KAAK,kBAAkB,GAAG,oBAAoB;AAAA,MAC1E,qBAAqB,WAAW,KAAK,uBAAuB,GAAG,yBAAyB;AAAA,MACxF,sBAAsB,oBAAoB,MAAc,OAAO;AAAA,MAC/D,mBAAmB,iBAAiB,SAAS,IAAI,mBAAmB;AAAA,IACtE;AACA,QAAI;AACF,YAAM,QAAQ,MAAM,QAAa,yCAAyC,IAAI;AAC9E,YAAM,aACJ,MAAM,WAAW,IACb,CAAC,IACD;AAAA,QACE,mCAAmC,OAAO,MAAM,MAAM,CAAC;AAAA,MACzD;AACN,WAAK,OAAO;AAAA,QACV,GAAG;AAAA,QACH;AAAA,MACF,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,sBAAgB,GAAG;AAAA,IACrB;AAAA,EACF;AACF,CAAC;AAED,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aACE;AAAA,EACF,MAAM,EAAE,IAAI,EAAE,MAAM,cAAc,aAAa,YAAY,UAAU,KAAK,GAAG,cAAc,cAAc;AAC3G,CAAC;AAED,IAAM,+BAA+B,cAAc;AAAA,EACjD,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa,kGAA6F,WAAW;AAAA;AAAA;AAAA,EAGvH;AAAA,EACA,MAAM;AAAA,IACJ,IAAI,EAAE,MAAM,cAAc,aAAa,yDAAyD,UAAU,KAAK;AAAA,IAC/G,cAAc,EAAE,MAAM,UAAU,aAAa,8BAA8B;AAAA,EAC7E;AAAA,EACA,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,UAAM,QAAQ;AAAA,MACZ,MAAM;AAAA,MACN,WAAW,MAAM,cAAc,IAAY;AAAA,MAC3C,SAAS,EAAE,eAAe,cAAc,MAAc,OAAO,EAAE;AAAA,IACjE,CAAC;AAAA,EACH;AACF,CAAC;AAED,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aAAa;AAAA,EACb,MAAM,EAAE,IAAI,EAAE,MAAM,cAAc,aAAa,kBAAkB,UAAU,KAAK,GAAG,cAAc,cAAc;AACjH,CAAC;AAED,IAAM,8BAA8B,cAAc;AAAA,EAChD,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa,6CAA6C,WAAW;AAAA;AAAA,EAEvE;AAAA,EACA,MAAM;AAAA,IACJ,IAAI,EAAE,MAAM,cAAc,aAAa,kBAAkB,UAAU,KAAK;AAAA,IACxE,cAAc,EAAE,MAAM,UAAU,aAAa,8BAA8B;AAAA,EAC7E;AAAA,EACA,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,UAAM,QAAQ;AAAA,MACZ,MAAM;AAAA,MACN,WAAW,MAAM,cAAc,IAAY;AAAA,MAC3C,QAAQ,cAAc,MAAc,aAAa;AAAA,MACjD,SAAS,EAAE,QAAQ,YAAY;AAAA,IACjC,CAAC;AAAA,EACH;AACF,CAAC;AAEM,IAAM,wBAAwB,cAAc;AAAA,EACjD,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA;AAAA,EAIf;AAAA,EACA,aAAa;AAAA,IACX,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS;AAAA,IACT,QAAQ;AAAA,EACV;AAAA,EACA,MAAM,EAAE,cAAc,EAAE,MAAM,UAAU,aAAa,8BAA8B,EAAE;AAAA,EACrF,SAAS;AACX,CAAC;AAID,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aACE;AAAA,EACF,MAAM,EAAE,WAAW,EAAE,MAAM,UAAU,aAAa,oBAAoB,UAAU,KAAK,EAAE;AACzF,CAAC;AAEM,IAAM,mBAAmB,cAAc;AAAA,EAC5C,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA,EAGf;AAAA,EACA,MAAM,EAAE,WAAW,EAAE,MAAM,UAAU,aAAa,sDAAiD,EAAE;AAAA,EACrG,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,QAAI,CAAC,KAAK,SAAS,EAAG,qBAAoB,8CAA8C;AACxF,QAAI;AACF,YAAM,OAAO,MAAM,SAAS,EAAE,MAAM,cAAc,WAAW,OAAO,KAAK,SAAS,CAAC,EAAE,CAAC;AACtF,WAAK,MAAM;AAAA,QACT;AAAA,MACF,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,sBAAgB,GAAG;AAAA,IACrB;AAAA,EACF;AACF,CAAC;AAED,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aACE;AAAA,EACF,MAAM,EAAE,kBAAkB,EAAE,MAAM,UAAU,aAAa,wBAAwB,UAAU,KAAK,EAAE;AACpG,CAAC;AAEM,IAAM,wBAAwB,cAAc;AAAA,EACjD,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA,EAGf;AAAA,EACA,MAAM;AAAA,IACJ,kBAAkB;AAAA,MAChB,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,QAAI,CAAC,KAAK,gBAAgB;AACxB,0BAAoB,kEAAkE;AACxF,QAAI;AACF,WAAK,MAAM,SAAS,EAAE,MAAM,mBAAmB,kBAAkB,OAAO,KAAK,gBAAgB,CAAC,EAAE,CAAC,CAAC;AAAA,IACpG,SAAS,KAAK;AACZ,sBAAgB,GAAG;AAAA,IACrB;AAAA,EACF;AACF,CAAC;AAED,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aACE;AAAA,EACF,MAAM;AAAA,IACJ,SAAS,EAAE,MAAM,UAAU,aAAa,SAAS,UAAU,KAAK;AAAA,IAChE,MAAM,EAAE,MAAM,WAAW,aAAa,gDAAgD,UAAU,MAAM;AAAA,EACxG;AACF,CAAC;AAEM,IAAM,kBAAkB,cAAc;AAAA,EAC3C,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA,EAGf;AAAA,EACA,MAAM;AAAA,IACJ,SAAS,EAAE,MAAM,UAAU,aAAa,yCAAoC;AAAA,IAC5E,MAAM,EAAE,MAAM,WAAW,aAAa,iCAAiC;AAAA,EACzE;AAAA,EACA,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,QAAI,CAAC,KAAK,OAAO,EAAG,qBAAoB,0CAA0C;AAClF,QAAI;AACF,YAAM,SAAiC,EAAE,SAAS,OAAO,KAAK,OAAO,CAAC,EAAE;AACxE,UAAI,KAAK,KAAM,QAAO,OAAO;AAC7B,WAAK,MAAM,OAAc,6BAA6B,MAAM,CAAC;AAAA,IAC/D,SAAS,KAAK;AACZ,sBAAgB,GAAG;AAAA,IACrB;AAAA,EACF;AACF,CAAC;AAID,IAAM,kBAAkB;AAAA,EACtB,iBAAiB;AAAA,EACjB,OAAO;AAAA,EACP,oBACE;AAAA,EACF,WAAW;AAAA,EACX,mBAAmB;AACrB;AAGA,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aAAa,wEAAmE,OAAO,QAAQ,eAAe,EAC3G,IAAI,CAAC,CAAC,MAAM,IAAI,MAAM,GAAG,IAAI,KAAK,IAAI,GAAG,EACzC,KAAK,IAAI,CAAC;AAAA,EACb,MAAM;AAAA,IACJ,cAAc;AAAA,IACd,MAAM,EAAE,MAAM,UAAU,aAAa,OAAO,KAAK,eAAe,EAAE,KAAK,GAAG,GAAG,UAAU,KAAK;AAAA,EAC9F;AACF,CAAC;AAEM,IAAM,wBAAwB,cAAc;AAAA,EACjD,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA,SAER,OAAO,KAAK,eAAe,EAAE,KAAK,KAAK,CAAC;AAAA,EAC/C;AAAA,EACA,MAAM;AAAA,IACJ,cAAc,EAAE,MAAM,UAAU,aAAa,8BAA8B;AAAA,IAC3E,MAAM,EAAE,MAAM,UAAU,aAAa,OAAO,KAAK,eAAe,EAAE,KAAK,KAAK,EAAE;AAAA,EAChF;AAAA,EACA,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,UAAM,OAAO,OAAO,KAAK,QAAQ,EAAE;AACnC,QAAI,EAAE,QAAQ,kBAAkB;AAC9B,0BAAoB,gBAAgB,OAAO,KAAK,eAAe,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,IAC/E;AACA,QAAI;AACF,YAAM,OAAO,MAAM,SAAS,EAAE,MAAM,MAAuB,cAAc,MAAM,cAAc,IAAY,EAAE,CAAC;AAC5G,WAAK,MAAM,KAAK,WAAW,IAAI,CAAC,MAAM,IAAI,sBAAsB,IAAI,CAAC,CAAC;AAAA,IACxE,SAAS,KAAK;AACZ,sBAAgB,GAAG;AAAA,IACrB;AAAA,EACF;AACF,CAAC;","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
csvOrJson,
|
|
3
3
|
handleMetaError
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-BN4TDL5L.js";
|
|
5
5
|
import "./chunk-QALAJNBG.js";
|
|
6
6
|
import {
|
|
7
7
|
connectedResourceHints
|
|
@@ -73,4 +73,4 @@ Examples:
|
|
|
73
73
|
export {
|
|
74
74
|
accountsCommand
|
|
75
75
|
};
|
|
76
|
-
//# sourceMappingURL=accounts-
|
|
76
|
+
//# sourceMappingURL=accounts-KRW3JNCW.js.map
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
csvOrJson,
|
|
9
9
|
handleMetaError,
|
|
10
10
|
resolveAccountIdArg
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-BN4TDL5L.js";
|
|
12
12
|
import "./chunk-QALAJNBG.js";
|
|
13
13
|
import "./chunk-HPDGVK6R.js";
|
|
14
14
|
import {
|
|
@@ -55,7 +55,7 @@ Examples:
|
|
|
55
55
|
},
|
|
56
56
|
args: listArgs,
|
|
57
57
|
run: async ({ args }) => {
|
|
58
|
-
const accountId = resolveAccountIdArg(args);
|
|
58
|
+
const accountId = await resolveAccountIdArg(args);
|
|
59
59
|
try {
|
|
60
60
|
const params = { "account-id": accountId };
|
|
61
61
|
if (args.days) params.days = args.days;
|
|
@@ -72,4 +72,4 @@ Examples:
|
|
|
72
72
|
export {
|
|
73
73
|
activitiesCommand
|
|
74
74
|
};
|
|
75
|
-
//# sourceMappingURL=activities-
|
|
75
|
+
//# sourceMappingURL=activities-2RAJXP3J.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/ads/meta/activities.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport { NO_CACHE_ARG } from \"../../../cache-flag.ts\";\nimport { apiGet } from \"../../../client.ts\";\nimport { META_LIST_SHAPE_ARGS, registerMetaListSchema, shapeMetaListRows, writeMetaListRows } from \"./list-rows.ts\";\nimport { csvOrJson, handleMetaError, resolveAccountIdArg } from \"./shared.ts\";\n\nconst listArgs = {\n \"account-id\": { type: \"string\", description: \"Meta ad account ID\" },\n days: { type: \"string\", description: \"Lookback days (default 7)\" },\n limit: { type: \"string\", description: \"Max rows\" },\n \"no-cache\": NO_CACHE_ARG,\n ...META_LIST_SHAPE_ARGS,\n} as const;\n\nregisterMetaListSchema(\n \"activities\",\n \"Account change log, as a table by default, one row per event: event_time, event_type, actor_name, object_type, object_name, object_id, and change ('old → new' when the change is a single value). Start here: baker ads meta activities --account-id act_123 --days 2. --fields event_time,object_name,extra_data or --full for the raw change payload; --output json returns the rows in the envelope.\",\n listArgs,\n);\n\nexport const activitiesCommand = defineCommand({\n meta: {\n name: \"activities\",\n description: `Audit log of recent ad-account changes (created, paused, edited). Default lookback 7 days,\n~90 day retention server-side.\n\nA table by default, one row per event: event_time, event_type, actor_name, object_type,\nobject_name, object_id, and change (\"old → new\" when the change is a single value: status,\nname, budget, goal). --fields takes dotted paths (extra_data holds the raw change); --full returns\nevery field Meta sent; --output json returns the rows as JSON.\n\nExamples:\n baker ads meta activities --account-id act_123 --days 14\n baker ads meta activities --account-id act_123 --days 2 --output json\n baker ads meta activities --account-id act_123 --fields event_time,object_name,extra_data`,\n },\n args: listArgs,\n run: async ({ args }) => {\n const accountId = resolveAccountIdArg(args);\n try {\n const params: Record<string, string> = { \"account-id\": accountId };\n if (args.days) params.days = args.days as string;\n if (args.limit) params.limit = args.limit as string;\n if (args[\"no-cache\"]) params[\"skip-cache\"] = \"true\";\n const data = await apiGet<Array<Record<string, unknown>>>(\"/api/ads/meta/activities\", params);\n const shaped = shapeMetaListRows(\"activities\", data, args);\n writeMetaListRows(\"activities\", shaped, csvOrJson(args));\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,qBAAqB;AAM9B,IAAM,WAAW;AAAA,EACf,cAAc,EAAE,MAAM,UAAU,aAAa,qBAAqB;AAAA,EAClE,MAAM,EAAE,MAAM,UAAU,aAAa,4BAA4B;AAAA,EACjE,OAAO,EAAE,MAAM,UAAU,aAAa,WAAW;AAAA,EACjD,YAAY;AAAA,EACZ,GAAG;AACL;AAEA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,oBAAoB,cAAc;AAAA,EAC7C,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYf;AAAA,EACA,MAAM;AAAA,EACN,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,UAAM,YAAY,oBAAoB,IAAI;
|
|
1
|
+
{"version":3,"sources":["../src/commands/ads/meta/activities.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport { NO_CACHE_ARG } from \"../../../cache-flag.ts\";\nimport { apiGet } from \"../../../client.ts\";\nimport { META_LIST_SHAPE_ARGS, registerMetaListSchema, shapeMetaListRows, writeMetaListRows } from \"./list-rows.ts\";\nimport { csvOrJson, handleMetaError, resolveAccountIdArg } from \"./shared.ts\";\n\nconst listArgs = {\n \"account-id\": { type: \"string\", description: \"Meta ad account ID\" },\n days: { type: \"string\", description: \"Lookback days (default 7)\" },\n limit: { type: \"string\", description: \"Max rows\" },\n \"no-cache\": NO_CACHE_ARG,\n ...META_LIST_SHAPE_ARGS,\n} as const;\n\nregisterMetaListSchema(\n \"activities\",\n \"Account change log, as a table by default, one row per event: event_time, event_type, actor_name, object_type, object_name, object_id, and change ('old → new' when the change is a single value). Start here: baker ads meta activities --account-id act_123 --days 2. --fields event_time,object_name,extra_data or --full for the raw change payload; --output json returns the rows in the envelope.\",\n listArgs,\n);\n\nexport const activitiesCommand = defineCommand({\n meta: {\n name: \"activities\",\n description: `Audit log of recent ad-account changes (created, paused, edited). Default lookback 7 days,\n~90 day retention server-side.\n\nA table by default, one row per event: event_time, event_type, actor_name, object_type,\nobject_name, object_id, and change (\"old → new\" when the change is a single value: status,\nname, budget, goal). --fields takes dotted paths (extra_data holds the raw change); --full returns\nevery field Meta sent; --output json returns the rows as JSON.\n\nExamples:\n baker ads meta activities --account-id act_123 --days 14\n baker ads meta activities --account-id act_123 --days 2 --output json\n baker ads meta activities --account-id act_123 --fields event_time,object_name,extra_data`,\n },\n args: listArgs,\n run: async ({ args }) => {\n const accountId = await resolveAccountIdArg(args);\n try {\n const params: Record<string, string> = { \"account-id\": accountId };\n if (args.days) params.days = args.days as string;\n if (args.limit) params.limit = args.limit as string;\n if (args[\"no-cache\"]) params[\"skip-cache\"] = \"true\";\n const data = await apiGet<Array<Record<string, unknown>>>(\"/api/ads/meta/activities\", params);\n const shaped = shapeMetaListRows(\"activities\", data, args);\n writeMetaListRows(\"activities\", shaped, csvOrJson(args));\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,qBAAqB;AAM9B,IAAM,WAAW;AAAA,EACf,cAAc,EAAE,MAAM,UAAU,aAAa,qBAAqB;AAAA,EAClE,MAAM,EAAE,MAAM,UAAU,aAAa,4BAA4B;AAAA,EACjE,OAAO,EAAE,MAAM,UAAU,aAAa,WAAW;AAAA,EACjD,YAAY;AAAA,EACZ,GAAG;AACL;AAEA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,oBAAoB,cAAc;AAAA,EAC7C,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYf;AAAA,EACA,MAAM;AAAA,EACN,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,UAAM,YAAY,MAAM,oBAAoB,IAAI;AAChD,QAAI;AACF,YAAM,SAAiC,EAAE,cAAc,UAAU;AACjE,UAAI,KAAK,KAAM,QAAO,OAAO,KAAK;AAClC,UAAI,KAAK,MAAO,QAAO,QAAQ,KAAK;AACpC,UAAI,KAAK,UAAU,EAAG,QAAO,YAAY,IAAI;AAC7C,YAAM,OAAO,MAAM,OAAuC,4BAA4B,MAAM;AAC5F,YAAM,SAAS,kBAAkB,cAAc,MAAM,IAAI;AACzD,wBAAkB,cAAc,QAAQ,UAAU,IAAI,CAAC;AAAA,IACzD,SAAS,KAAK;AACZ,sBAAgB,GAAG;AAAA,IACrB;AAAA,EACF;AACF,CAAC;","names":[]}
|
|
@@ -34,15 +34,15 @@ Full guides: __tooling__/docs/tools/baker/ads-<platform>.md (google|meta|linkedi
|
|
|
34
34
|
},
|
|
35
35
|
subCommands: {
|
|
36
36
|
google: () => import("./google-FZVOB7HW.js").then((m) => m.googleCommand),
|
|
37
|
-
meta: () => import("./meta-
|
|
37
|
+
meta: () => import("./meta-MOSJVYIE.js").then((m) => m.metaCommand),
|
|
38
38
|
linkedin: () => import("./linkedin-5PYG5HEM.js").then((m) => m.linkedinCommand),
|
|
39
39
|
x: () => import("./x-EMLFCHSG.js").then((m) => m.xCommand),
|
|
40
40
|
chatgpt: () => import("./chatgpt-S5EVEKYV.js").then((m) => m.chatgptCommand),
|
|
41
|
-
performance: () => import("./performance-
|
|
41
|
+
performance: () => import("./performance-6XFKDJGY.js").then((m) => m.performanceCommand),
|
|
42
42
|
terms: () => import("./terms-X4OJWTQH.js").then((m) => m.termsCommand)
|
|
43
43
|
}
|
|
44
44
|
});
|
|
45
45
|
export {
|
|
46
46
|
adsCommand
|
|
47
47
|
};
|
|
48
|
-
//# sourceMappingURL=ads-
|
|
48
|
+
//# sourceMappingURL=ads-6ESCXPHK.js.map
|