@koda-sl/baker-cli 0.526.0 → 0.527.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.
Files changed (98) hide show
  1. package/README.md +1 -0
  2. package/dist/{account-APMJVG2F.js → account-CQJFUII3.js} +3 -3
  3. package/dist/{account-APMJVG2F.js.map → account-CQJFUII3.js.map} +1 -1
  4. package/dist/{account-assets-TAUEBCY5.js → account-assets-IDVG4DGK.js} +12 -12
  5. package/dist/account-assets-IDVG4DGK.js.map +1 -0
  6. package/dist/{account-level-2MYDHOID.js → account-level-GK7M2MMQ.js} +14 -14
  7. package/dist/account-level-GK7M2MMQ.js.map +1 -0
  8. package/dist/{accounts-VIAQC3PA.js → accounts-KRW3JNCW.js} +2 -2
  9. package/dist/{activities-MJMAV3SI.js → activities-2RAJXP3J.js} +3 -3
  10. package/dist/{activities-MJMAV3SI.js.map → activities-2RAJXP3J.js.map} +1 -1
  11. package/dist/{ads-O4RL4JXD.js → ads-F2PURRHL.js} +2 -2
  12. package/dist/{ads-NNKUR4HG.js → ads-JVBLNTBF.js} +20 -15
  13. package/dist/ads-JVBLNTBF.js.map +1 -0
  14. package/dist/{adsets-VO5C7PDM.js → adsets-FN5ZWSYF.js} +11 -11
  15. package/dist/adsets-FN5ZWSYF.js.map +1 -0
  16. package/dist/{asset-writes-PQNENVYY.js → asset-writes-SSI3CO2A.js} +4 -4
  17. package/dist/{audience-writes-QDDADCYE.js → audience-writes-G64754LR.js} +6 -6
  18. package/dist/audience-writes-G64754LR.js.map +1 -0
  19. package/dist/{audiences-TQ5ZEWIR.js → audiences-JAVNJ5NC.js} +8 -8
  20. package/dist/audiences-JAVNJ5NC.js.map +1 -0
  21. package/dist/{businesses-CW4RB36R.js → businesses-DXRDQIFP.js} +2 -2
  22. package/dist/{campaigns-IQYYYD2S.js → campaigns-GQWFSKGC.js} +11 -11
  23. package/dist/campaigns-GQWFSKGC.js.map +1 -0
  24. package/dist/{catalogs-PLBY32BE.js → catalogs-TBRONC2D.js} +15 -15
  25. package/dist/catalogs-TBRONC2D.js.map +1 -0
  26. package/dist/{chunk-OEJNZSJG.js → chunk-4XXA4WCS.js} +4 -4
  27. package/dist/chunk-4XXA4WCS.js.map +1 -0
  28. package/dist/{chunk-HPAGYPAF.js → chunk-BN4TDL5L.js} +65 -23
  29. package/dist/chunk-BN4TDL5L.js.map +1 -0
  30. package/dist/{chunk-5LN7GWRE.js → chunk-GEFZVG4P.js} +10 -10
  31. package/dist/chunk-GEFZVG4P.js.map +1 -0
  32. package/dist/{chunk-XB2FODWU.js → chunk-TKDOVFO6.js} +2 -2
  33. package/dist/cli.js +1 -1
  34. package/dist/{copy-writes-GZ744FHU.js → copy-writes-EUFEVWDW.js} +5 -5
  35. package/dist/{copy-writes-GZ744FHU.js.map → copy-writes-EUFEVWDW.js.map} +1 -1
  36. package/dist/{creatives-GTRQAZSB.js → creatives-6VJDUHEY.js} +6 -6
  37. package/dist/creatives-6VJDUHEY.js.map +1 -0
  38. package/dist/{custom-conversions-VQ3LBWYV.js → custom-conversions-NDY5RHSM.js} +6 -6
  39. package/dist/{custom-conversions-VQ3LBWYV.js.map → custom-conversions-NDY5RHSM.js.map} +1 -1
  40. package/dist/{draft-ME4TNPO7.js → draft-G432FJ7N.js} +2 -2
  41. package/dist/{insights-INIFHYR7.js → insights-IVW6W5CP.js} +2 -2
  42. package/dist/{instant-experiences-NMJUWNP3.js → instant-experiences-6F6GXZ67.js} +5 -5
  43. package/dist/{instant-experiences-NMJUWNP3.js.map → instant-experiences-6F6GXZ67.js.map} +1 -1
  44. package/dist/{leads-QBWR7FKT.js → leads-CJKRKB2Q.js} +6 -6
  45. package/dist/{leads-QBWR7FKT.js.map → leads-CJKRKB2Q.js.map} +1 -1
  46. package/dist/{media-23IW442U.js → media-HDHZULQ7.js} +3 -3
  47. package/dist/{meta-H3KBPU33.js → meta-MOSJVYIE.js} +38 -38
  48. package/dist/{page-photos-SHIGXDYE.js → page-photos-4JTIKXAW.js} +5 -5
  49. package/dist/page-photos-4JTIKXAW.js.map +1 -0
  50. package/dist/{pages-XJF3FBOJ.js → pages-BAUS7LQM.js} +2 -2
  51. package/dist/{pixels-AZCIWWXK.js → pixels-QOSEYXCP.js} +3 -3
  52. package/dist/pixels-QOSEYXCP.js.map +1 -0
  53. package/dist/{preview-BIEVHIDJ.js → preview-X6EJGPAY.js} +2 -2
  54. package/dist/{rule-writes-QLZNJ7CT.js → rule-writes-A4BFYHPA.js} +7 -7
  55. package/dist/rule-writes-A4BFYHPA.js.map +1 -0
  56. package/dist/{rules-FJHYG4SJ.js → rules-HLREXY2M.js} +11 -11
  57. package/dist/rules-HLREXY2M.js.map +1 -0
  58. package/dist/{shared-HY2VP7PT.js → shared-I3SB77VH.js} +2 -2
  59. package/dist/{studies-Z2ZIWLTO.js → studies-IGOCWM7F.js} +7 -7
  60. package/dist/{studies-Z2ZIWLTO.js.map → studies-IGOCWM7F.js.map} +1 -1
  61. package/dist/{study-writes-V7BXLTQG.js → study-writes-Z5P2W7JH.js} +6 -6
  62. package/dist/study-writes-Z5P2W7JH.js.map +1 -0
  63. package/dist/{targeting-YBIWD27C.js → targeting-7HXKBXWY.js} +12 -12
  64. package/dist/targeting-7HXKBXWY.js.map +1 -0
  65. package/dist/{write-commands-R5SN6CVQ.js → write-commands-CY734U34.js} +22 -22
  66. package/dist/write-commands-CY734U34.js.map +1 -0
  67. package/package.json +1 -1
  68. package/dist/account-assets-TAUEBCY5.js.map +0 -1
  69. package/dist/account-level-2MYDHOID.js.map +0 -1
  70. package/dist/ads-NNKUR4HG.js.map +0 -1
  71. package/dist/adsets-VO5C7PDM.js.map +0 -1
  72. package/dist/audience-writes-QDDADCYE.js.map +0 -1
  73. package/dist/audiences-TQ5ZEWIR.js.map +0 -1
  74. package/dist/campaigns-IQYYYD2S.js.map +0 -1
  75. package/dist/catalogs-PLBY32BE.js.map +0 -1
  76. package/dist/chunk-5LN7GWRE.js.map +0 -1
  77. package/dist/chunk-HPAGYPAF.js.map +0 -1
  78. package/dist/chunk-OEJNZSJG.js.map +0 -1
  79. package/dist/creatives-GTRQAZSB.js.map +0 -1
  80. package/dist/page-photos-SHIGXDYE.js.map +0 -1
  81. package/dist/pixels-AZCIWWXK.js.map +0 -1
  82. package/dist/rule-writes-QLZNJ7CT.js.map +0 -1
  83. package/dist/rules-FJHYG4SJ.js.map +0 -1
  84. package/dist/study-writes-V7BXLTQG.js.map +0 -1
  85. package/dist/targeting-YBIWD27C.js.map +0 -1
  86. package/dist/write-commands-R5SN6CVQ.js.map +0 -1
  87. /package/dist/{accounts-VIAQC3PA.js.map → accounts-KRW3JNCW.js.map} +0 -0
  88. /package/dist/{ads-O4RL4JXD.js.map → ads-F2PURRHL.js.map} +0 -0
  89. /package/dist/{asset-writes-PQNENVYY.js.map → asset-writes-SSI3CO2A.js.map} +0 -0
  90. /package/dist/{businesses-CW4RB36R.js.map → businesses-DXRDQIFP.js.map} +0 -0
  91. /package/dist/{chunk-XB2FODWU.js.map → chunk-TKDOVFO6.js.map} +0 -0
  92. /package/dist/{draft-ME4TNPO7.js.map → draft-G432FJ7N.js.map} +0 -0
  93. /package/dist/{insights-INIFHYR7.js.map → insights-IVW6W5CP.js.map} +0 -0
  94. /package/dist/{media-23IW442U.js.map → media-HDHZULQ7.js.map} +0 -0
  95. /package/dist/{meta-H3KBPU33.js.map → meta-MOSJVYIE.js.map} +0 -0
  96. /package/dist/{pages-XJF3FBOJ.js.map → pages-BAUS7LQM.js.map} +0 -0
  97. /package/dist/{preview-BIEVHIDJ.js.map → preview-X6EJGPAY.js.map} +0 -0
  98. /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.
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  handleMetaError,
3
3
  resolveAccountIdArg
4
- } from "./chunk-HPAGYPAF.js";
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-APMJVG2F.js.map
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-HPAGYPAF.js";
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-PQNENVYY.js").then((m) => m.labelsCreateCommand),
225
- rename: () => import("./asset-writes-PQNENVYY.js").then((m) => m.labelsRenameCommand),
226
- delete: () => import("./asset-writes-PQNENVYY.js").then((m) => m.labelsDeleteCommand),
227
- attach: () => import("./asset-writes-PQNENVYY.js").then((m) => m.labelsAttachCommand),
228
- detach: () => import("./asset-writes-PQNENVYY.js").then((m) => m.labelsDetachCommand)
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-TAUEBCY5.js.map
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-XB2FODWU.js";
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-OEJNZSJG.js";
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-HPAGYPAF.js";
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-2MYDHOID.js.map
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":"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","names":[]}
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  csvOrJson,
3
3
  handleMetaError
4
- } from "./chunk-HPAGYPAF.js";
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-VIAQC3PA.js.map
76
+ //# sourceMappingURL=accounts-KRW3JNCW.js.map
@@ -8,7 +8,7 @@ import {
8
8
  csvOrJson,
9
9
  handleMetaError,
10
10
  resolveAccountIdArg
11
- } from "./chunk-HPAGYPAF.js";
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-MJMAV3SI.js.map
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;AAC1C,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":[]}
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,7 +34,7 @@ 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-H3KBPU33.js").then((m) => m.metaCommand),
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),
@@ -45,4 +45,4 @@ Full guides: __tooling__/docs/tools/baker/ads-<platform>.md (google|meta|linkedi
45
45
  export {
46
46
  adsCommand
47
47
  };
48
- //# sourceMappingURL=ads-O4RL4JXD.js.map
48
+ //# sourceMappingURL=ads-F2PURRHL.js.map
@@ -11,7 +11,7 @@ import {
11
11
  resolveAccountIdArg,
12
12
  resolveEffectiveStatus,
13
13
  statusFilterHints
14
- } from "./chunk-HPAGYPAF.js";
14
+ } from "./chunk-BN4TDL5L.js";
15
15
  import "./chunk-QALAJNBG.js";
16
16
  import "./chunk-HPDGVK6R.js";
17
17
  import {
@@ -28,8 +28,12 @@ import "./chunk-YQSBHWOI.js";
28
28
 
29
29
  // src/commands/ads/meta/ads.ts
30
30
  import { defineCommand } from "citty";
31
+ var ACCOUNT_SELECTION = "Account: --account-id, else BAKER_META_AD_ACCOUNT_ID, else the company's only connected Meta ad account. With several connected it refuses with MISSING_ACCOUNT_ID listing each \u2014 re-run naming one.";
31
32
  var listArgs = {
32
- "account-id": { type: "string", description: "Meta ad account ID" },
33
+ "account-id": {
34
+ type: "string",
35
+ description: "Meta ad account ID (act_123). Optional when the company connected only one account (or BAKER_META_AD_ACCOUNT_ID is set); required when several are connected."
36
+ },
33
37
  "adset-id": { type: "string", description: "Filter to one adset" },
34
38
  "campaign-id": { type: "string", description: "Filter to one campaign" },
35
39
  "effective-status": { type: "string", description: "Comma-separated effective_status filter (overrides default)" },
@@ -41,17 +45,17 @@ var listArgs = {
41
45
  };
42
46
  registerMetaListSchema(
43
47
  "ads",
44
- "List ads in a Meta ad account, as a table by default: id, name, adset_id, campaign_id, effective_status, creative_id, issues (why an ad is WITH_ISSUES), created_time. Start here: baker ads meta ads --adset-id 6123. --fields takes dotted paths (e.g. id,tracking_specs); --full returns every field Meta sent; --output json returns the rows in the envelope.",
48
+ `List ads in a Meta ad account, as a table by default: id, name, adset_id, campaign_id, effective_status, creative_id, issues (why an ad is WITH_ISSUES), created_time. Start here: baker ads meta ads --adset-id 6123. --fields takes dotted paths (e.g. id,tracking_specs); --full returns every field Meta sent; --output json returns the rows in the envelope. ${ACCOUNT_SELECTION}`,
45
49
  listArgs
46
50
  );
47
51
  var listCommand = defineCommand({
48
52
  meta: {
49
53
  name: "list",
50
- description: "List ads in a Meta ad account. Runs by default when no subcommand is given. Example: baker ads meta ads --account-id act_123"
54
+ description: `List ads in a Meta ad account. Runs by default when no subcommand is given. ${ACCOUNT_SELECTION} Example: baker ads meta ads --account-id act_123`
51
55
  },
52
56
  args: listArgs,
53
57
  run: async ({ args }) => {
54
- const accountId = resolveAccountIdArg(args);
58
+ const accountId = await resolveAccountIdArg(args);
55
59
  const effectiveStatus = resolveEffectiveStatus(args);
56
60
  try {
57
61
  const params = { "account-id": accountId };
@@ -74,6 +78,7 @@ var adsListCommand = defineCommand({
74
78
  name: "ads",
75
79
  description: `List ads in a Meta ad account, or stage writes (create/update/pause/resume/archive/delete/duplicate/copy/retag).
76
80
  Defaults to ACTIVE only \u2014 pass --all-statuses to widen. Write subcommands stage ops on this chat's draft.
81
+ ${ACCOUNT_SELECTION}
77
82
 
78
83
  The dashboard shows effective_status (e.g. WITH_ISSUES, PENDING_REVIEW, DISAPPROVED, ADSET_PAUSED), not status.
79
84
 
@@ -92,15 +97,15 @@ Examples:
92
97
  },
93
98
  subCommands: {
94
99
  list: listCommand,
95
- create: () => import("./write-commands-R5SN6CVQ.js").then((m) => m.adsCreateCommand),
96
- update: () => import("./write-commands-R5SN6CVQ.js").then((m) => m.adsUpdateCommand),
97
- pause: () => import("./write-commands-R5SN6CVQ.js").then((m) => m.adsPauseCommand),
98
- resume: () => import("./write-commands-R5SN6CVQ.js").then((m) => m.adsResumeCommand),
99
- archive: () => import("./write-commands-R5SN6CVQ.js").then((m) => m.adsArchiveCommand),
100
- delete: () => import("./write-commands-R5SN6CVQ.js").then((m) => m.adsDeleteCommand),
101
- duplicate: () => import("./write-commands-R5SN6CVQ.js").then((m) => m.adsDuplicateCommand),
102
- copy: () => import("./copy-writes-GZ744FHU.js").then((m) => m.adsCopyCommand),
103
- retag: () => import("./write-commands-R5SN6CVQ.js").then((m) => m.adsRetagCommand)
100
+ create: () => import("./write-commands-CY734U34.js").then((m) => m.adsCreateCommand),
101
+ update: () => import("./write-commands-CY734U34.js").then((m) => m.adsUpdateCommand),
102
+ pause: () => import("./write-commands-CY734U34.js").then((m) => m.adsPauseCommand),
103
+ resume: () => import("./write-commands-CY734U34.js").then((m) => m.adsResumeCommand),
104
+ archive: () => import("./write-commands-CY734U34.js").then((m) => m.adsArchiveCommand),
105
+ delete: () => import("./write-commands-CY734U34.js").then((m) => m.adsDeleteCommand),
106
+ duplicate: () => import("./write-commands-CY734U34.js").then((m) => m.adsDuplicateCommand),
107
+ copy: () => import("./copy-writes-EUFEVWDW.js").then((m) => m.adsCopyCommand),
108
+ retag: () => import("./write-commands-CY734U34.js").then((m) => m.adsRetagCommand)
104
109
  },
105
110
  // `args` stays even though the parent has no `run`: citty scans rawArgs for the
106
111
  // subcommand name using THIS command's arg defs, so without them `--account-id act_1`
@@ -112,4 +117,4 @@ Examples:
112
117
  export {
113
118
  adsListCommand
114
119
  };
115
- //# sourceMappingURL=ads-NNKUR4HG.js.map
120
+ //# sourceMappingURL=ads-JVBLNTBF.js.map