@koda-sl/baker-cli 0.526.0 → 0.528.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/README.md +2 -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-6ESCXPHK.js} +3 -3
  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/{performance-L3Q57H4H.js → performance-6XFKDJGY.js} +11 -2
  52. package/dist/performance-6XFKDJGY.js.map +1 -0
  53. package/dist/{pixels-AZCIWWXK.js → pixels-QOSEYXCP.js} +3 -3
  54. package/dist/pixels-QOSEYXCP.js.map +1 -0
  55. package/dist/{preview-BIEVHIDJ.js → preview-X6EJGPAY.js} +2 -2
  56. package/dist/{rule-writes-QLZNJ7CT.js → rule-writes-A4BFYHPA.js} +7 -7
  57. package/dist/rule-writes-A4BFYHPA.js.map +1 -0
  58. package/dist/{rules-FJHYG4SJ.js → rules-HLREXY2M.js} +11 -11
  59. package/dist/rules-HLREXY2M.js.map +1 -0
  60. package/dist/{shared-HY2VP7PT.js → shared-I3SB77VH.js} +2 -2
  61. package/dist/{studies-Z2ZIWLTO.js → studies-IGOCWM7F.js} +7 -7
  62. package/dist/{studies-Z2ZIWLTO.js.map → studies-IGOCWM7F.js.map} +1 -1
  63. package/dist/{study-writes-V7BXLTQG.js → study-writes-Z5P2W7JH.js} +6 -6
  64. package/dist/study-writes-Z5P2W7JH.js.map +1 -0
  65. package/dist/{targeting-YBIWD27C.js → targeting-7HXKBXWY.js} +12 -12
  66. package/dist/targeting-7HXKBXWY.js.map +1 -0
  67. package/dist/{write-commands-R5SN6CVQ.js → write-commands-CY734U34.js} +22 -22
  68. package/dist/write-commands-CY734U34.js.map +1 -0
  69. package/package.json +1 -1
  70. package/dist/account-assets-TAUEBCY5.js.map +0 -1
  71. package/dist/account-level-2MYDHOID.js.map +0 -1
  72. package/dist/ads-NNKUR4HG.js.map +0 -1
  73. package/dist/adsets-VO5C7PDM.js.map +0 -1
  74. package/dist/audience-writes-QDDADCYE.js.map +0 -1
  75. package/dist/audiences-TQ5ZEWIR.js.map +0 -1
  76. package/dist/campaigns-IQYYYD2S.js.map +0 -1
  77. package/dist/catalogs-PLBY32BE.js.map +0 -1
  78. package/dist/chunk-5LN7GWRE.js.map +0 -1
  79. package/dist/chunk-HPAGYPAF.js.map +0 -1
  80. package/dist/chunk-OEJNZSJG.js.map +0 -1
  81. package/dist/creatives-GTRQAZSB.js.map +0 -1
  82. package/dist/page-photos-SHIGXDYE.js.map +0 -1
  83. package/dist/performance-L3Q57H4H.js.map +0 -1
  84. package/dist/pixels-AZCIWWXK.js.map +0 -1
  85. package/dist/rule-writes-QLZNJ7CT.js.map +0 -1
  86. package/dist/rules-FJHYG4SJ.js.map +0 -1
  87. package/dist/study-writes-V7BXLTQG.js.map +0 -1
  88. package/dist/targeting-YBIWD27C.js.map +0 -1
  89. package/dist/write-commands-R5SN6CVQ.js.map +0 -1
  90. /package/dist/{accounts-VIAQC3PA.js.map → accounts-KRW3JNCW.js.map} +0 -0
  91. /package/dist/{ads-O4RL4JXD.js.map → ads-6ESCXPHK.js.map} +0 -0
  92. /package/dist/{asset-writes-PQNENVYY.js.map → asset-writes-SSI3CO2A.js.map} +0 -0
  93. /package/dist/{businesses-CW4RB36R.js.map → businesses-DXRDQIFP.js.map} +0 -0
  94. /package/dist/{chunk-XB2FODWU.js.map → chunk-TKDOVFO6.js.map} +0 -0
  95. /package/dist/{draft-ME4TNPO7.js.map → draft-G432FJ7N.js.map} +0 -0
  96. /package/dist/{insights-INIFHYR7.js.map → insights-IVW6W5CP.js.map} +0 -0
  97. /package/dist/{media-23IW442U.js.map → media-HDHZULQ7.js.map} +0 -0
  98. /package/dist/{meta-H3KBPU33.js.map → meta-MOSJVYIE.js.map} +0 -0
  99. /package/dist/{pages-XJF3FBOJ.js.map → pages-BAUS7LQM.js.map} +0 -0
  100. /package/dist/{preview-BIEVHIDJ.js.map → preview-X6EJGPAY.js.map} +0 -0
  101. /package/dist/{shared-HY2VP7PT.js.map → shared-I3SB77VH.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/ads/meta/catalogs.ts"],"sourcesContent":["import { retailerIdFilter } from \"@baker/api/ads-meta/catalogs\";\nimport { defineCommand } from \"citty\";\nimport { NO_CACHE_ARG } from \"../../../cache-flag.ts\";\nimport { apiGet } from \"../../../client.ts\";\nimport { repeatedValues } from \"../../../lib/repeatedFlags.ts\";\nimport { registerSchema } from \"../../../schemas.ts\";\nimport { writeAdsJson, writeAdsOutput, writeJsonEnvelope } from \"../output.ts\";\nimport { csvOrJson, handleMetaError } from \"./shared.ts\";\nimport {\n bareAccountId,\n failWriteValidation,\n loadJsonFileArg,\n mergePayload,\n numberFlag,\n requireTarget,\n stageOp,\n upper,\n} from \"./write-shared.ts\";\n\n/**\n * Product catalogs and what is in them — products, product sets, feeds — read\n * live and changed through this chat's draft (applied at publish). Changing a\n * catalog needs the Catalog permission for Meta (a per-company switch); Baker\n * changes only catalogs the ad account's own Business owns.\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 outputArg = { type: \"string\", description: \"json|csv|jsonl|md\", default: \"json\" } as const;\nconst accountArg = {\n type: \"string\",\n description: \"Numeric account ID or act_N (whose Business owns the catalog)\",\n} as const;\nconst schemaAccount = { type: \"string\", description: \"Ad account the change is staged under\", required: false };\nconst schemaOutput = { type: \"string\", description: \"json|csv|jsonl|md\", required: false, default: \"json\" };\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\nfunction requireCatalogId(args: Args): string {\n const id = args[\"catalog-id\"];\n if (typeof id !== \"string\" || id.length === 0) {\n failWriteValidation(\"pass --catalog-id (from `baker ads meta catalogs --business-id <id>`, or a meta_temp_* ref)\");\n }\n return id;\n}\n\nfunction stringArg(value: unknown): string | undefined {\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\nfunction jsonArg(value: unknown, flag: string): Record<string, unknown> | undefined {\n if (typeof value !== \"string\" || value.length === 0) return undefined;\n try {\n return JSON.parse(value) as Record<string, unknown>;\n } catch {\n failWriteValidation(`--${flag} takes JSON, e.g. '{\"brand\":{\"eq\":\"Acme\"}}'`);\n }\n}\n\nasync function contents(edge: \"products\" | \"feeds\" | \"diagnostics\", args: Args): Promise<Row[]> {\n const params: Record<string, string> = { \"catalog-id\": requireCatalogId(args), edge };\n if (args.full) params.full = \"true\";\n if (stringArg(args[\"retailer-id\"])) params[\"retailer-id\"] = String(args[\"retailer-id\"]);\n return await apiGet<Row[]>(\"/api/ads/meta/catalog-contents\", params);\n}\n\n// --- Catalogs (list, create, rename, delete) ---\n\nregisterSchema({\n command: \"ads.meta.catalogs\",\n description:\n \"Product catalogs a Business owns (for catalog / Advantage+ catalog ads), or one catalog's product sets with --catalog-id.\",\n args: {\n \"business-id\": { type: \"string\", description: \"Business ID (baker ads meta businesses)\", required: false },\n \"catalog-id\": { type: \"string\", description: \"List this catalog's product sets\", required: false },\n \"no-cache\": { type: \"boolean\", description: \"Bypass the cache\", required: false },\n output: schemaOutput,\n },\n});\n\nconst catalogsListCommand = defineCommand({\n meta: {\n name: \"list\",\n description:\n \"Product catalogs on a Business, or a catalog's product sets. Runs by default. Example: baker ads meta catalogs --business-id 601050769212882; --catalog-id <id> for its sets\",\n },\n args: {\n \"business-id\": { type: \"string\", description: \"Business ID — from `baker ads meta businesses`\" },\n \"catalog-id\": { type: \"string\", description: \"List the product sets of this catalog\" },\n \"no-cache\": NO_CACHE_ARG,\n output: outputArg,\n },\n run: async ({ args }) => {\n try {\n const cache: Record<string, string> = args[\"no-cache\"] ? { \"skip-cache\": \"true\" } : {};\n if (args[\"catalog-id\"]) {\n const rows = await apiGet<Row[]>(\"/api/ads/meta/product-sets\", {\n \"catalog-id\": args[\"catalog-id\"] as string,\n ...cache,\n });\n emit(rows, args, [\n 'A catalog ad set promotes one product set: promoted_object {\"product_set_id\":\"<id>\"}; product_count 0 means the set\\'s filter matches nothing yet. Read just after a publish with --no-cache.',\n ]);\n return;\n }\n if (!args[\"business-id\"]) {\n writeAdsJson({\n ok: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: \"pass --business-id (from `baker ads meta businesses`) or --catalog-id\",\n },\n });\n process.exit(1);\n }\n const rows = await apiGet<Row[]>(\"/api/ads/meta/catalogs\", {\n \"business-id\": args[\"business-id\"] as string,\n ...cache,\n });\n emit(\n rows,\n args,\n rows.length === 0\n ? [\n \"This Business owns no product catalogs. Stage one with `baker ads meta catalogs create --name …`, or — for a catalog another Business shares with it — ask for its id and read it with `catalogs --catalog-id <id>` (shared catalogs are read, never changed).\",\n ]\n : [\n \"`catalogs --catalog-id <id>` lists a catalog's product sets; `catalogs products --catalog-id <id>` its products.\",\n ],\n );\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n\nregisterSchema({\n command: \"ads.meta.catalogs.create\",\n description:\n \"Stage a new product catalog on the ad account's own Business, made at publish. Needs the Catalog permission for Meta.\",\n args: {\n \"account-id\": schemaAccount,\n name: { type: \"string\", description: \"Catalog name\", required: true },\n pixel: { type: \"string\", description: \"Pixel to connect (repeatable) — catalog ads need one\", required: false },\n },\n});\n\nconst catalogCreateCommand = defineCommand({\n meta: {\n name: \"create\",\n description: `Stage a new product catalog on the ad account's own Business. ${STAGED_NOTE}\nConnect the account's pixel with --pixel (\\`baker ads meta pixels\\`): Meta runs catalog ads only on a catalog with one.\nThen add products (\\`catalogs products create --catalog-id meta_temp_…\\`) and a product set to advertise.\nExample: baker ads meta catalogs create --account-id act_123 --name \"Spring shop\" --pixel 1275507706837548`,\n },\n args: {\n \"account-id\": accountArg,\n name: { type: \"string\", description: \"Catalog name\" },\n pixel: { type: \"string\", description: \"Pixel to connect once it exists (repeatable) — catalog ads need one\" },\n },\n run: async ({ args, rawArgs }) => {\n const pixels = repeatedValues(rawArgs, \"pixel\", args.pixel);\n await stageOp(\n {\n kind: \"productCatalog.create\",\n accountId: bareAccountId(args as Args),\n payload: { name: args.name, event_sources: pixels.length > 0 ? pixels : undefined },\n },\n [\n \"Add products with `catalogs products create --catalog-id <ref>` and a set with `catalogs sets create --catalog-id <ref>`.\",\n ],\n );\n },\n});\n\nregisterSchema({\n command: \"ads.meta.catalogs.update\",\n description:\n \"Stage a change to a product catalog the ad account's Business owns: a new name, pixels to connect (catalog ads need one) or disconnect.\",\n args: {\n id: { type: \"positional\", description: \"Catalog id\", required: true },\n \"account-id\": schemaAccount,\n name: { type: \"string\", description: \"New name\", required: false },\n pixel: { type: \"string\", description: \"Pixel to connect (repeatable)\", required: false },\n \"unlink-pixel\": { type: \"string\", description: \"Pixel to disconnect (repeatable)\", required: false },\n },\n});\n\nconst catalogUpdateCommand = defineCommand({\n meta: {\n name: \"update\",\n description: `Rename a product catalog, or connect / disconnect pixels. ${STAGED_NOTE}\nExample: baker ads meta catalogs update 1798573158016525 --account-id act_123 --pixel 1275507706837548`,\n },\n args: {\n id: { type: \"positional\", description: \"Catalog id\", required: true },\n \"account-id\": accountArg,\n name: { type: \"string\", description: \"New name\" },\n pixel: { type: \"string\", description: \"Pixel to connect (repeatable) — from `baker ads meta pixels`\" },\n \"unlink-pixel\": { type: \"string\", description: \"Pixel to disconnect (repeatable)\" },\n },\n run: async ({ args, rawArgs }) => {\n const pixels = repeatedValues(rawArgs, \"pixel\", args.pixel);\n const unlink = repeatedValues(rawArgs, \"unlink-pixel\", args[\"unlink-pixel\"]);\n await stageOp({\n kind: \"productCatalog.update\",\n accountId: bareAccountId(args as Args),\n target: requireTarget(args as Args, \"catalog\"),\n payload: {\n name: args.name,\n event_sources: pixels.length > 0 ? pixels : undefined,\n unlink_event_sources: unlink.length > 0 ? unlink : undefined,\n },\n });\n },\n});\n\nregisterSchema({\n command: \"ads.meta.catalogs.delete\",\n description:\n \"Stage deleting a product catalog with every product, product set and feed in it. Delete the ads, ad sets and campaigns that use it in the same chat.\",\n args: { id: { type: \"positional\", description: \"Catalog id\", required: true }, \"account-id\": schemaAccount },\n});\n\nconst catalogDeleteCommand = defineCommand({\n meta: {\n name: \"delete\",\n description: `Delete a product catalog and everything in it — runs after every other change in the publish. ${STAGED_NOTE}\nExample: baker ads meta catalogs delete 1798573158016525 --account-id act_123`,\n },\n args: { id: { type: \"positional\", description: \"Catalog id\", required: true }, \"account-id\": accountArg },\n run: async ({ args }) => {\n await stageOp({\n kind: \"productCatalog.update\",\n accountId: bareAccountId(args as Args),\n target: requireTarget(args as Args, \"catalog\"),\n payload: { status: \"DELETED\" },\n });\n },\n});\n\n// --- Products ---\n\nconst productFieldArgs = {\n name: { type: \"string\", description: \"Title shoppers see\" },\n description: { type: \"string\", description: \"Description\" },\n price: { type: \"string\", description: 'Price in major units, e.g. \"19.99\"' },\n \"sale-price\": { type: \"string\", description: \"Sale price in major units\" },\n currency: { type: \"string\", description: \"Three-letter currency code, e.g. EUR (needed with a price)\" },\n availability: {\n type: \"string\",\n description: '\"in stock\" (default), \"out of stock\", \"preorder\", \"available for order\", \"discontinued\"',\n },\n condition: { type: \"string\", description: \"new (default), refurbished, used\" },\n url: { type: \"string\", description: \"The product's own page (https) — where its ad sends people\" },\n \"image-url\": {\n type: \"string\",\n description: \"Public https picture Meta fetches (a library image's address works)\",\n },\n \"additional-image-url\": { type: \"string\", description: \"More pictures (repeatable)\" },\n brand: { type: \"string\", description: \"Brand\" },\n} as const;\n\nconst productFieldSchema = Object.fromEntries(\n Object.entries(productFieldArgs).map(([key, arg]) => [key, { ...arg, required: false }]),\n);\n\n/** The product fields given on the command line, in Meta's vocabulary. */\nexport function productFieldsFromArgs(args: Args, rawArgs: readonly string[] | undefined): Record<string, unknown> {\n const extra = repeatedValues(rawArgs, \"additional-image-url\", args[\"additional-image-url\"]);\n return {\n name: args.name,\n description: args.description,\n price: stringArg(args.price),\n sale_price: stringArg(args[\"sale-price\"]),\n currency: upper(args.currency),\n availability: stringArg(args.availability)?.toLowerCase(),\n condition: stringArg(args.condition)?.toLowerCase(),\n url: args.url,\n image_url: args[\"image-url\"],\n additional_image_urls: extra.length > 0 ? extra : undefined,\n brand: args.brand,\n };\n}\n\nregisterSchema({\n command: \"ads.meta.catalogs.products\",\n description:\n \"A catalog's products, compact (id, retailer id, name, price, availability, review status); --full for every field and Meta's errors on each.\",\n args: {\n \"catalog-id\": { type: \"string\", description: \"Catalog id\", required: true },\n \"retailer-id\": { type: \"string\", description: \"Only the product with this retailer id\", required: false },\n full: { type: \"boolean\", description: \"Every field, and Meta's errors on each product\", required: false },\n output: schemaOutput,\n },\n});\n\nconst productsListCommand = defineCommand({\n meta: {\n name: \"list\",\n description:\n \"A catalog's products (up to 500). Runs by default. Example: baker ads meta catalogs products --catalog-id 1798573158016525\",\n },\n args: {\n \"catalog-id\": { type: \"string\", description: \"Catalog id\" },\n \"retailer-id\": { type: \"string\", description: \"Only the product with this retailer id\" },\n full: { type: \"boolean\", description: \"Every field, and Meta's errors on each product\" },\n output: outputArg,\n },\n run: async ({ args }) => {\n try {\n const rows = await contents(\"products\", args as Args);\n const rejected = rows.filter((row) => row.review_status === \"rejected\").length;\n emit(rows, args as Args, [\n ...(rows.length === 0 ? [\"No products yet — stage some with `catalogs products create`.\"] : []),\n ...(rejected > 0\n ? [\n `${rejected} product(s) were rejected by Meta's review — \\`--full\\` shows why; a rejected product is never shown in an ad.`,\n ]\n : []),\n ]);\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n\nregisterSchema({\n command: \"ads.meta.catalogs.products.create\",\n description:\n \"Stage a product in a catalog (or one this chat creates), added at publish. Fake or real, every product needs a retailer id, name, description, price + currency, page URL and picture URL.\",\n args: {\n \"account-id\": schemaAccount,\n \"catalog-id\": { type: \"string\", description: \"Catalog id or meta_temp_* ref\", required: true },\n \"retailer-id\": { type: \"string\", description: \"Your own id for the product (SKU)\", required: true },\n ...productFieldSchema,\n file: { type: \"string\", description: \"JSON file with the whole payload\", required: false },\n },\n});\n\nconst productCreateCommand = defineCommand({\n meta: {\n name: \"create\",\n description: `Stage a product in a catalog. ${STAGED_NOTE}\nExample: baker ads meta catalogs products create --account-id act_123 --catalog-id meta_temp_… --retailer-id SKU-1 --name \"Solar panel\" --description \"400 W panel\" --price 199.00 --currency EUR --url https://shop.example/panel --image-url https://shop.example/panel.jpg`,\n },\n args: {\n \"account-id\": accountArg,\n \"catalog-id\": { type: \"string\", description: \"Catalog id, or meta_temp_* of a catalog this chat creates\" },\n \"retailer-id\": { type: \"string\", description: \"Your own id for the product (SKU) — what product sets filter on\" },\n ...productFieldArgs,\n file: { type: \"string\", description: \"JSON file with the whole payload\" },\n },\n run: async ({ args, rawArgs }) => {\n const payload = mergePayload(loadJsonFileArg(args.file), {\n catalog_id: args[\"catalog-id\"],\n retailer_id: args[\"retailer-id\"],\n ...productFieldsFromArgs(args as Args, rawArgs),\n });\n await stageOp({ kind: \"product.create\", accountId: bareAccountId(args as Args), payload }, [\n \"Group products for an ad with `catalogs sets create --catalog-id <id> --retailer-id <sku> …`.\",\n ]);\n },\n});\n\nregisterSchema({\n command: \"ads.meta.catalogs.products.update\",\n description: \"Stage changes to a product's fields (a price names its currency).\",\n args: {\n id: { type: \"positional\", description: \"Product id\", required: true },\n \"account-id\": schemaAccount,\n ...productFieldSchema,\n },\n});\n\nconst productUpdateCommand = defineCommand({\n meta: {\n name: \"update\",\n description: `Change a product's fields. ${STAGED_NOTE}\nExample: baker ads meta catalogs products update 39108967418750368 --account-id act_123 --price 179.00 --currency EUR --availability \"out of stock\"`,\n },\n args: {\n id: { type: \"positional\", description: \"Product id\", required: true },\n \"account-id\": accountArg,\n ...productFieldArgs,\n },\n run: async ({ args, rawArgs }) => {\n await stageOp({\n kind: \"product.update\",\n accountId: bareAccountId(args as Args),\n target: requireTarget(args as Args, \"product\"),\n payload: productFieldsFromArgs(args as Args, rawArgs),\n });\n },\n});\n\nregisterSchema({\n command: \"ads.meta.catalogs.products.delete\",\n description: \"Stage deleting a product from its catalog.\",\n args: { id: { type: \"positional\", description: \"Product id\", required: true }, \"account-id\": schemaAccount },\n});\n\nconst productDeleteCommand = defineCommand({\n meta: {\n name: \"delete\",\n description: `Delete a product from its catalog. ${STAGED_NOTE}\nExample: baker ads meta catalogs products delete 39108967418750368 --account-id act_123`,\n },\n args: { id: { type: \"positional\", description: \"Product id\", required: true }, \"account-id\": accountArg },\n run: async ({ args }) => {\n await stageOp({\n kind: \"product.update\",\n accountId: bareAccountId(args as Args),\n target: requireTarget(args as Args, \"product\"),\n payload: { status: \"DELETED\" },\n });\n },\n});\n\nconst productsCommand = defineCommand({\n meta: {\n name: \"products\",\n description: `A catalog's products.\n baker ads meta catalogs products --catalog-id <id> [--full] — list\n baker ads meta catalogs products create --catalog-id <id> --retailer-id SKU-1 --name … --price 19.99 --currency EUR …\n baker ads meta catalogs products update <id> --price 17.99 --currency EUR\n baker ads meta catalogs products delete <id>`,\n },\n subCommands: {\n list: productsListCommand,\n create: productCreateCommand,\n update: productUpdateCommand,\n delete: productDeleteCommand,\n },\n args: {\n \"catalog-id\": { type: \"string\", description: \"Catalog id\" },\n \"retailer-id\": { type: \"string\", description: \"Only the product with this retailer id\" },\n full: { type: \"boolean\", description: \"Every field, and Meta's errors on each product\" },\n output: outputArg,\n },\n default: \"list\",\n});\n\n// --- Product sets ---\n\n/** A set's rule: --filter JSON, or the products by retailer id. */\nexport function productSetFilterFromArgs(args: Args, rawArgs: readonly string[] | undefined): unknown {\n const retailerIds = repeatedValues(rawArgs, \"retailer-id\", args[\"retailer-id\"])\n .flatMap((value) => value.split(\",\"))\n .map((value) => value.trim())\n .filter(Boolean);\n const filter = jsonArg(args.filter, \"filter\");\n if (filter && retailerIds.length > 0) failWriteValidation(\"pass --filter or --retailer-id, not both\");\n return filter ?? (retailerIds.length > 0 ? retailerIdFilter(retailerIds) : undefined);\n}\n\nconst setRuleArgs = {\n \"retailer-id\": {\n type: \"string\",\n description: \"A product in the set, by retailer id (repeatable, or comma-separated)\",\n },\n filter: {\n type: \"string\",\n description:\n 'Meta\\'s rule as JSON, e.g. \\'{\"and\":[{\"brand\":{\"eq\":\"Acme\"}},{\"price\":{\"lt\":5000}}]}\\' — operators: is_any, is_not_any, eq, neq, contains, not_contains, i_contains, i_not_contains, starts_with, lt, lte, gt, gte (a price in minor units)',\n },\n} as const;\n\nregisterSchema({\n command: \"ads.meta.catalogs.sets\",\n description: \"A catalog's product sets, with how many products each matches.\",\n args: {\n \"catalog-id\": { type: \"string\", description: \"Catalog id\", required: true },\n \"no-cache\": { type: \"boolean\", description: \"Bypass the cache\", required: false },\n output: schemaOutput,\n },\n});\n\nconst setsListCommand = defineCommand({\n meta: {\n name: \"list\",\n description:\n \"A catalog's product sets. Runs by default. Example: baker ads meta catalogs sets --catalog-id 1798573158016525\",\n },\n args: { \"catalog-id\": { type: \"string\", description: \"Catalog id\" }, \"no-cache\": NO_CACHE_ARG, output: outputArg },\n run: async ({ args }) => {\n try {\n const params: Record<string, string> = { \"catalog-id\": requireCatalogId(args as Args) };\n if (args[\"no-cache\"]) params[\"skip-cache\"] = \"true\";\n const rows = await apiGet<Row[]>(\"/api/ads/meta/product-sets\", params);\n emit(rows, args as Args, [\n \"An ad set shows one set (`adsets create --product-set-id <id>`); a catalog creative names it too (`creatives create --type catalog --product-set-id <id>`).\",\n ]);\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n\nregisterSchema({\n command: \"ads.meta.catalogs.sets.create\",\n description:\n \"Stage a product set — the products an Advantage+ catalog ad or a collection shows — by retailer id or Meta's filter rule. Without either it holds the whole catalog.\",\n args: {\n \"account-id\": schemaAccount,\n \"catalog-id\": { type: \"string\", description: \"Catalog id or meta_temp_* ref\", required: true },\n name: { type: \"string\", description: \"Set name\", required: true },\n \"retailer-id\": { type: \"string\", description: \"Retailer id of a product (repeatable)\", required: false },\n filter: { type: \"string\", description: \"Meta's filter rule as JSON\", required: false },\n },\n});\n\nconst setCreateCommand = defineCommand({\n meta: {\n name: \"create\",\n description: `Stage a product set. ${STAGED_NOTE}\nExample: baker ads meta catalogs sets create --account-id act_123 --catalog-id meta_temp_… --name \"Panels\" --retailer-id SKU-1 --retailer-id SKU-2\nRule: --filter '{\"brand\":{\"eq\":\"Acme\"}}'. Without --retailer-id or --filter the set holds the whole catalog.`,\n },\n args: {\n \"account-id\": accountArg,\n \"catalog-id\": { type: \"string\", description: \"Catalog id, or meta_temp_* of a catalog this chat creates\" },\n name: { type: \"string\", description: \"Set name\" },\n ...setRuleArgs,\n },\n run: async ({ args, rawArgs }) => {\n await stageOp(\n {\n kind: \"productSet.create\",\n accountId: bareAccountId(args as Args),\n payload: {\n catalog_id: args[\"catalog-id\"],\n name: args.name,\n filter: productSetFilterFromArgs(args as Args, rawArgs),\n },\n },\n [\n \"Advertise it: `adsets create --product-set-id <ref>` under a campaign with `--catalog-id`, then `creatives create --type catalog --product-set-id <ref>`.\",\n ],\n );\n },\n});\n\nregisterSchema({\n command: \"ads.meta.catalogs.sets.update\",\n description: \"Stage a new name or a new rule for a product set (the whole rule is replaced).\",\n args: {\n id: { type: \"positional\", description: \"Product set id\", required: true },\n \"account-id\": schemaAccount,\n name: { type: \"string\", description: \"New name\", required: false },\n \"retailer-id\": { type: \"string\", description: \"Retailer id of a product (repeatable)\", required: false },\n filter: { type: \"string\", description: \"Meta's filter rule as JSON\", required: false },\n },\n});\n\nconst setUpdateCommand = defineCommand({\n meta: {\n name: \"update\",\n description: `Rename a product set or replace its rule. ${STAGED_NOTE}\nExample: baker ads meta catalogs sets update 1748674113031942 --account-id act_123 --retailer-id SKU-1 --retailer-id SKU-3`,\n },\n args: {\n id: { type: \"positional\", description: \"Product set id\", required: true },\n \"account-id\": accountArg,\n name: { type: \"string\", description: \"New name\" },\n ...setRuleArgs,\n },\n run: async ({ args, rawArgs }) => {\n await stageOp({\n kind: \"productSet.update\",\n accountId: bareAccountId(args as Args),\n target: requireTarget(args as Args, \"product set\"),\n payload: { name: args.name, filter: productSetFilterFromArgs(args as Args, rawArgs) },\n });\n },\n});\n\nregisterSchema({\n command: \"ads.meta.catalogs.sets.delete\",\n description:\n \"Stage deleting a product set. Delete or repoint the ad sets and creatives that show it in the same chat.\",\n args: { id: { type: \"positional\", description: \"Product set id\", required: true }, \"account-id\": schemaAccount },\n});\n\nconst setDeleteCommand = defineCommand({\n meta: {\n name: \"delete\",\n description: `Delete a product set — after the ads, ad sets and creatives this chat deletes. ${STAGED_NOTE}\nExample: baker ads meta catalogs sets delete 1748674113031942 --account-id act_123`,\n },\n args: { id: { type: \"positional\", description: \"Product set id\", required: true }, \"account-id\": accountArg },\n run: async ({ args }) => {\n await stageOp({\n kind: \"productSet.update\",\n accountId: bareAccountId(args as Args),\n target: requireTarget(args as Args, \"product set\"),\n payload: { status: \"DELETED\" },\n });\n },\n});\n\nconst setsCommand = defineCommand({\n meta: {\n name: \"sets\",\n description: `A catalog's product sets.\n baker ads meta catalogs sets --catalog-id <id> — list\n baker ads meta catalogs sets create --catalog-id <id> --name … --retailer-id SKU-1 [--filter '<json>']\n baker ads meta catalogs sets update <id> --name …\n baker ads meta catalogs sets delete <id>`,\n },\n subCommands: { list: setsListCommand, create: setCreateCommand, update: setUpdateCommand, delete: setDeleteCommand },\n args: { \"catalog-id\": { type: \"string\", description: \"Catalog id\" }, \"no-cache\": NO_CACHE_ARG, output: outputArg },\n default: \"list\",\n});\n\n// --- Feeds ---\n\nconst scheduleArgs = {\n url: { type: \"string\", description: \"https address of the feed file (CSV, TSV, XML) Meta fetches\" },\n interval: { type: \"string\", description: \"HOURLY, DAILY or WEEKLY\" },\n hour: { type: \"string\", description: \"Hour of day 0–23\" },\n day: { type: \"string\", description: \"Day for a WEEKLY schedule, e.g. MONDAY\" },\n} as const;\n\n/** A feed schedule from the flags, or nothing when no flag names one. */\nexport function feedScheduleFromArgs(args: Args): Record<string, unknown> | undefined {\n if (args.url === undefined && args.interval === undefined && args.hour === undefined && args.day === undefined) {\n return undefined;\n }\n return {\n url: args.url,\n interval: upper(args.interval) ?? \"DAILY\",\n hour: numberFlag(args.hour, \"--hour\"),\n day_of_week: upper(args.day),\n };\n}\n\nregisterSchema({\n command: \"ads.meta.catalogs.feeds\",\n description: \"A catalog's data feeds: each one's schedule and its last upload's errors and warnings.\",\n args: { \"catalog-id\": { type: \"string\", description: \"Catalog id\", required: true }, output: schemaOutput },\n});\n\nconst feedsListCommand = defineCommand({\n meta: {\n name: \"list\",\n description:\n \"A catalog's feeds. Runs by default. Example: baker ads meta catalogs feeds --catalog-id 1798573158016525\",\n },\n args: { \"catalog-id\": { type: \"string\", description: \"Catalog id\" }, output: outputArg },\n run: async ({ args }) => {\n try {\n emit(await contents(\"feeds\", args as Args), args as Args, []);\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n\nregisterSchema({\n command: \"ads.meta.catalogs.feeds.create\",\n description:\n \"Stage a data feed in a catalog: a file Meta fetches on a schedule and replaces the catalog's products from. Without --url it waits for uploads.\",\n args: {\n \"account-id\": schemaAccount,\n \"catalog-id\": { type: \"string\", description: \"Catalog id or meta_temp_* ref\", required: true },\n name: { type: \"string\", description: \"Feed name\", required: true },\n url: { type: \"string\", description: \"Feed file address (https)\", required: false },\n interval: { type: \"string\", description: \"HOURLY, DAILY (default) or WEEKLY\", required: false },\n hour: { type: \"string\", description: \"Hour 0–23\", required: false },\n day: { type: \"string\", description: \"Day for WEEKLY\", required: false },\n },\n});\n\nconst feedCreateCommand = defineCommand({\n meta: {\n name: \"create\",\n description: `Stage a scheduled data feed in a catalog. ${STAGED_NOTE}\nExample: baker ads meta catalogs feeds create --account-id act_123 --catalog-id 1798573158016525 --name \"Daily feed\" --url https://shop.example/feed.csv --interval DAILY --hour 3`,\n },\n args: {\n \"account-id\": accountArg,\n \"catalog-id\": { type: \"string\", description: \"Catalog id, or meta_temp_* of a catalog this chat creates\" },\n name: { type: \"string\", description: \"Feed name\" },\n ...scheduleArgs,\n },\n run: async ({ args }) => {\n await stageOp({\n kind: \"productFeed.create\",\n accountId: bareAccountId(args as Args),\n payload: { catalog_id: args[\"catalog-id\"], name: args.name, schedule: feedScheduleFromArgs(args as Args) },\n });\n },\n});\n\nregisterSchema({\n command: \"ads.meta.catalogs.feeds.update\",\n description: \"Stage a new name or schedule for a feed (the whole schedule is replaced).\",\n args: {\n id: { type: \"positional\", description: \"Feed id\", required: true },\n \"account-id\": schemaAccount,\n name: { type: \"string\", description: \"New name\", required: false },\n url: { type: \"string\", description: \"Feed file address (https)\", required: false },\n interval: { type: \"string\", description: \"HOURLY, DAILY or WEEKLY\", required: false },\n hour: { type: \"string\", description: \"Hour 0–23\", required: false },\n day: { type: \"string\", description: \"Day for WEEKLY\", required: false },\n },\n});\n\nconst feedUpdateCommand = defineCommand({\n meta: {\n name: \"update\",\n description: `Rename a feed or replace its schedule. ${STAGED_NOTE}\nExample: baker ads meta catalogs feeds update 1157910959893469 --account-id act_123 --url https://shop.example/feed.csv --interval WEEKLY --day MONDAY --hour 4`,\n },\n args: {\n id: { type: \"positional\", description: \"Feed id\", required: true },\n \"account-id\": accountArg,\n name: { type: \"string\", description: \"New name\" },\n ...scheduleArgs,\n },\n run: async ({ args }) => {\n await stageOp({\n kind: \"productFeed.update\",\n accountId: bareAccountId(args as Args),\n target: requireTarget(args as Args, \"feed\"),\n payload: { name: args.name, schedule: feedScheduleFromArgs(args as Args) },\n });\n },\n});\n\nregisterSchema({\n command: \"ads.meta.catalogs.feeds.delete\",\n description: \"Stage deleting a feed. Its products stay in the catalog.\",\n args: { id: { type: \"positional\", description: \"Feed id\", required: true }, \"account-id\": schemaAccount },\n});\n\nconst feedDeleteCommand = defineCommand({\n meta: {\n name: \"delete\",\n description: `Delete a data feed; its products stay in the catalog. ${STAGED_NOTE}\nExample: baker ads meta catalogs feeds delete 1157910959893469 --account-id act_123`,\n },\n args: { id: { type: \"positional\", description: \"Feed id\", required: true }, \"account-id\": accountArg },\n run: async ({ args }) => {\n await stageOp({\n kind: \"productFeed.update\",\n accountId: bareAccountId(args as Args),\n target: requireTarget(args as Args, \"feed\"),\n payload: { status: \"DELETED\" },\n });\n },\n});\n\nconst feedsCommand = defineCommand({\n meta: {\n name: \"feeds\",\n description: `A catalog's data feeds.\n baker ads meta catalogs feeds --catalog-id <id> — list, with the last upload's errors\n baker ads meta catalogs feeds create --catalog-id <id> --name … --url https://… --interval DAILY\n baker ads meta catalogs feeds update <id> --interval WEEKLY --day MONDAY --url https://…\n baker ads meta catalogs feeds delete <id>`,\n },\n subCommands: {\n list: feedsListCommand,\n create: feedCreateCommand,\n update: feedUpdateCommand,\n delete: feedDeleteCommand,\n },\n args: { \"catalog-id\": { type: \"string\", description: \"Catalog id\" }, output: outputArg },\n default: \"list\",\n});\n\n// --- Diagnostics ---\n\nregisterSchema({\n command: \"ads.meta.catalogs.diagnostics\",\n description:\n \"Meta's diagnostics for a catalog — product problems (missing fields, rejected pictures) and event-matching issues, grouped by type.\",\n args: { \"catalog-id\": { type: \"string\", description: \"Catalog id\", required: true }, output: schemaOutput },\n});\n\nconst diagnosticsCommand = defineCommand({\n meta: {\n name: \"diagnostics\",\n description:\n \"What Meta says is wrong with a catalog. Example: baker ads meta catalogs diagnostics --catalog-id 1798573158016525\",\n },\n args: { \"catalog-id\": { type: \"string\", description: \"Catalog id\" }, output: outputArg },\n run: async ({ args }) => {\n try {\n const rows = await contents(\"diagnostics\", args as Args);\n emit(rows, args as Args, rows.length === 0 ? [\"Meta reports no problems with this catalog.\"] : []);\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n\nexport const catalogsCommand = defineCommand({\n meta: {\n name: \"catalogs\",\n description: `Product catalogs — what Advantage+ catalog and collection ads show. Reading is open; changing needs the Catalog permission for Meta, and Baker changes only catalogs the ad account's own Business owns.\n baker ads meta catalogs --business-id <id> — catalogs; --catalog-id <id> for its product sets\n baker ads meta catalogs create --name … --pixel <id> | update <id> --name … --pixel <id> | delete <id>\n baker ads meta catalogs products … | sets … | feeds … | diagnostics --catalog-id <id>`,\n },\n subCommands: {\n list: catalogsListCommand,\n create: catalogCreateCommand,\n update: catalogUpdateCommand,\n delete: catalogDeleteCommand,\n products: productsCommand,\n sets: setsCommand,\n feeds: feedsCommand,\n diagnostics: diagnosticsCommand,\n },\n args: {\n \"business-id\": { type: \"string\", description: \"Business ID\" },\n \"catalog-id\": { type: \"string\", description: \"Catalog id\" },\n \"no-cache\": NO_CACHE_ARG,\n output: outputArg,\n },\n default: \"list\",\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,SAAS,qBAAqB;AA4B9B,IAAM,cAAc;AACpB,IAAM,YAAY,EAAE,MAAM,UAAU,aAAa,qBAAqB,SAAS,OAAO;AACtF,IAAM,aAAa;AAAA,EACjB,MAAM;AAAA,EACN,aAAa;AACf;AACA,IAAM,gBAAgB,EAAE,MAAM,UAAU,aAAa,yCAAyC,UAAU,MAAM;AAC9G,IAAM,eAAe,EAAE,MAAM,UAAU,aAAa,qBAAqB,UAAU,OAAO,SAAS,OAAO;AAE1G,SAAS,KAAK,MAAa,MAAY,OAAuB;AAC5D,QAAM,MAAM,UAAU,IAAI;AAC1B,MAAI,QAAQ,QAAQ;AAClB,mBAAe,MAAM,KAAK,QAAW,KAAK;AAC1C;AAAA,EACF;AACA,oBAAkB,MAAM,SAAS,IAAI,EAAE,IAAI,MAAM,MAAM,MAAM,MAAM,IAAI,EAAE,IAAI,MAAM,MAAM,KAAK,CAAC;AACjG;AAEA,SAAS,iBAAiB,MAAoB;AAC5C,QAAM,KAAK,KAAK,YAAY;AAC5B,MAAI,OAAO,OAAO,YAAY,GAAG,WAAW,GAAG;AAC7C,wBAAoB,6FAA6F;AAAA,EACnH;AACA,SAAO;AACT;AAEA,SAAS,UAAU,OAAoC;AACrD,SAAO,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,QAAQ;AACjE;AAEA,SAAS,QAAQ,OAAgB,MAAmD;AAClF,MAAI,OAAO,UAAU,YAAY,MAAM,WAAW,EAAG,QAAO;AAC5D,MAAI;AACF,WAAO,KAAK,MAAM,KAAK;AAAA,EACzB,QAAQ;AACN,wBAAoB,KAAK,IAAI,6CAA6C;AAAA,EAC5E;AACF;AAEA,eAAe,SAAS,MAA4C,MAA4B;AAC9F,QAAM,SAAiC,EAAE,cAAc,iBAAiB,IAAI,GAAG,KAAK;AACpF,MAAI,KAAK,KAAM,QAAO,OAAO;AAC7B,MAAI,UAAU,KAAK,aAAa,CAAC,EAAG,QAAO,aAAa,IAAI,OAAO,KAAK,aAAa,CAAC;AACtF,SAAO,MAAM,OAAc,kCAAkC,MAAM;AACrE;AAIA,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aACE;AAAA,EACF,MAAM;AAAA,IACJ,eAAe,EAAE,MAAM,UAAU,aAAa,2CAA2C,UAAU,MAAM;AAAA,IACzG,cAAc,EAAE,MAAM,UAAU,aAAa,oCAAoC,UAAU,MAAM;AAAA,IACjG,YAAY,EAAE,MAAM,WAAW,aAAa,oBAAoB,UAAU,MAAM;AAAA,IAChF,QAAQ;AAAA,EACV;AACF,CAAC;AAED,IAAM,sBAAsB,cAAc;AAAA,EACxC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aACE;AAAA,EACJ;AAAA,EACA,MAAM;AAAA,IACJ,eAAe,EAAE,MAAM,UAAU,aAAa,sDAAiD;AAAA,IAC/F,cAAc,EAAE,MAAM,UAAU,aAAa,wCAAwC;AAAA,IACrF,YAAY;AAAA,IACZ,QAAQ;AAAA,EACV;AAAA,EACA,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,QAAI;AACF,YAAM,QAAgC,KAAK,UAAU,IAAI,EAAE,cAAc,OAAO,IAAI,CAAC;AACrF,UAAI,KAAK,YAAY,GAAG;AACtB,cAAMA,QAAO,MAAM,OAAc,8BAA8B;AAAA,UAC7D,cAAc,KAAK,YAAY;AAAA,UAC/B,GAAG;AAAA,QACL,CAAC;AACD,aAAKA,OAAM,MAAM;AAAA,UACf;AAAA,QACF,CAAC;AACD;AAAA,MACF;AACA,UAAI,CAAC,KAAK,aAAa,GAAG;AACxB,qBAAa;AAAA,UACX,IAAI;AAAA,UACJ,OAAO;AAAA,YACL,MAAM;AAAA,YACN,SAAS;AAAA,UACX;AAAA,QACF,CAAC;AACD,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA,YAAM,OAAO,MAAM,OAAc,0BAA0B;AAAA,QACzD,eAAe,KAAK,aAAa;AAAA,QACjC,GAAG;AAAA,MACL,CAAC;AACD;AAAA,QACE;AAAA,QACA;AAAA,QACA,KAAK,WAAW,IACZ;AAAA,UACE;AAAA,QACF,IACA;AAAA,UACE;AAAA,QACF;AAAA,MACN;AAAA,IACF,SAAS,KAAK;AACZ,sBAAgB,GAAG;AAAA,IACrB;AAAA,EACF;AACF,CAAC;AAED,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aACE;AAAA,EACF,MAAM;AAAA,IACJ,cAAc;AAAA,IACd,MAAM,EAAE,MAAM,UAAU,aAAa,gBAAgB,UAAU,KAAK;AAAA,IACpE,OAAO,EAAE,MAAM,UAAU,aAAa,6DAAwD,UAAU,MAAM;AAAA,EAChH;AACF,CAAC;AAED,IAAM,uBAAuB,cAAc;AAAA,EACzC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa,iEAAiE,WAAW;AAAA;AAAA;AAAA;AAAA,EAI3F;AAAA,EACA,MAAM;AAAA,IACJ,cAAc;AAAA,IACd,MAAM,EAAE,MAAM,UAAU,aAAa,eAAe;AAAA,IACpD,OAAO,EAAE,MAAM,UAAU,aAAa,2EAAsE;AAAA,EAC9G;AAAA,EACA,KAAK,OAAO,EAAE,MAAM,QAAQ,MAAM;AAChC,UAAM,SAAS,eAAe,SAAS,SAAS,KAAK,KAAK;AAC1D,UAAM;AAAA,MACJ;AAAA,QACE,MAAM;AAAA,QACN,WAAW,cAAc,IAAY;AAAA,QACrC,SAAS,EAAE,MAAM,KAAK,MAAM,eAAe,OAAO,SAAS,IAAI,SAAS,OAAU;AAAA,MACpF;AAAA,MACA;AAAA,QACE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF,CAAC;AAED,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aACE;AAAA,EACF,MAAM;AAAA,IACJ,IAAI,EAAE,MAAM,cAAc,aAAa,cAAc,UAAU,KAAK;AAAA,IACpE,cAAc;AAAA,IACd,MAAM,EAAE,MAAM,UAAU,aAAa,YAAY,UAAU,MAAM;AAAA,IACjE,OAAO,EAAE,MAAM,UAAU,aAAa,iCAAiC,UAAU,MAAM;AAAA,IACvF,gBAAgB,EAAE,MAAM,UAAU,aAAa,oCAAoC,UAAU,MAAM;AAAA,EACrG;AACF,CAAC;AAED,IAAM,uBAAuB,cAAc;AAAA,EACzC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa,6DAA6D,WAAW;AAAA;AAAA,EAEvF;AAAA,EACA,MAAM;AAAA,IACJ,IAAI,EAAE,MAAM,cAAc,aAAa,cAAc,UAAU,KAAK;AAAA,IACpE,cAAc;AAAA,IACd,MAAM,EAAE,MAAM,UAAU,aAAa,WAAW;AAAA,IAChD,OAAO,EAAE,MAAM,UAAU,aAAa,oEAA+D;AAAA,IACrG,gBAAgB,EAAE,MAAM,UAAU,aAAa,mCAAmC;AAAA,EACpF;AAAA,EACA,KAAK,OAAO,EAAE,MAAM,QAAQ,MAAM;AAChC,UAAM,SAAS,eAAe,SAAS,SAAS,KAAK,KAAK;AAC1D,UAAM,SAAS,eAAe,SAAS,gBAAgB,KAAK,cAAc,CAAC;AAC3E,UAAM,QAAQ;AAAA,MACZ,MAAM;AAAA,MACN,WAAW,cAAc,IAAY;AAAA,MACrC,QAAQ,cAAc,MAAc,SAAS;AAAA,MAC7C,SAAS;AAAA,QACP,MAAM,KAAK;AAAA,QACX,eAAe,OAAO,SAAS,IAAI,SAAS;AAAA,QAC5C,sBAAsB,OAAO,SAAS,IAAI,SAAS;AAAA,MACrD;AAAA,IACF,CAAC;AAAA,EACH;AACF,CAAC;AAED,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aACE;AAAA,EACF,MAAM,EAAE,IAAI,EAAE,MAAM,cAAc,aAAa,cAAc,UAAU,KAAK,GAAG,cAAc,cAAc;AAC7G,CAAC;AAED,IAAM,uBAAuB,cAAc;AAAA,EACzC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa,sGAAiG,WAAW;AAAA;AAAA,EAE3H;AAAA,EACA,MAAM,EAAE,IAAI,EAAE,MAAM,cAAc,aAAa,cAAc,UAAU,KAAK,GAAG,cAAc,WAAW;AAAA,EACxG,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,UAAM,QAAQ;AAAA,MACZ,MAAM;AAAA,MACN,WAAW,cAAc,IAAY;AAAA,MACrC,QAAQ,cAAc,MAAc,SAAS;AAAA,MAC7C,SAAS,EAAE,QAAQ,UAAU;AAAA,IAC/B,CAAC;AAAA,EACH;AACF,CAAC;AAID,IAAM,mBAAmB;AAAA,EACvB,MAAM,EAAE,MAAM,UAAU,aAAa,qBAAqB;AAAA,EAC1D,aAAa,EAAE,MAAM,UAAU,aAAa,cAAc;AAAA,EAC1D,OAAO,EAAE,MAAM,UAAU,aAAa,qCAAqC;AAAA,EAC3E,cAAc,EAAE,MAAM,UAAU,aAAa,4BAA4B;AAAA,EACzE,UAAU,EAAE,MAAM,UAAU,aAAa,6DAA6D;AAAA,EACtG,cAAc;AAAA,IACZ,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA,EACA,WAAW,EAAE,MAAM,UAAU,aAAa,mCAAmC;AAAA,EAC7E,KAAK,EAAE,MAAM,UAAU,aAAa,kEAA6D;AAAA,EACjG,aAAa;AAAA,IACX,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA,EACA,wBAAwB,EAAE,MAAM,UAAU,aAAa,6BAA6B;AAAA,EACpF,OAAO,EAAE,MAAM,UAAU,aAAa,QAAQ;AAChD;AAEA,IAAM,qBAAqB,OAAO;AAAA,EAChC,OAAO,QAAQ,gBAAgB,EAAE,IAAI,CAAC,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,GAAG,KAAK,UAAU,MAAM,CAAC,CAAC;AACzF;AAGO,SAAS,sBAAsB,MAAY,SAAiE;AACjH,QAAM,QAAQ,eAAe,SAAS,wBAAwB,KAAK,sBAAsB,CAAC;AAC1F,SAAO;AAAA,IACL,MAAM,KAAK;AAAA,IACX,aAAa,KAAK;AAAA,IAClB,OAAO,UAAU,KAAK,KAAK;AAAA,IAC3B,YAAY,UAAU,KAAK,YAAY,CAAC;AAAA,IACxC,UAAU,MAAM,KAAK,QAAQ;AAAA,IAC7B,cAAc,UAAU,KAAK,YAAY,GAAG,YAAY;AAAA,IACxD,WAAW,UAAU,KAAK,SAAS,GAAG,YAAY;AAAA,IAClD,KAAK,KAAK;AAAA,IACV,WAAW,KAAK,WAAW;AAAA,IAC3B,uBAAuB,MAAM,SAAS,IAAI,QAAQ;AAAA,IAClD,OAAO,KAAK;AAAA,EACd;AACF;AAEA,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aACE;AAAA,EACF,MAAM;AAAA,IACJ,cAAc,EAAE,MAAM,UAAU,aAAa,cAAc,UAAU,KAAK;AAAA,IAC1E,eAAe,EAAE,MAAM,UAAU,aAAa,0CAA0C,UAAU,MAAM;AAAA,IACxG,MAAM,EAAE,MAAM,WAAW,aAAa,kDAAkD,UAAU,MAAM;AAAA,IACxG,QAAQ;AAAA,EACV;AACF,CAAC;AAED,IAAM,sBAAsB,cAAc;AAAA,EACxC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aACE;AAAA,EACJ;AAAA,EACA,MAAM;AAAA,IACJ,cAAc,EAAE,MAAM,UAAU,aAAa,aAAa;AAAA,IAC1D,eAAe,EAAE,MAAM,UAAU,aAAa,yCAAyC;AAAA,IACvF,MAAM,EAAE,MAAM,WAAW,aAAa,iDAAiD;AAAA,IACvF,QAAQ;AAAA,EACV;AAAA,EACA,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,QAAI;AACF,YAAM,OAAO,MAAM,SAAS,YAAY,IAAY;AACpD,YAAM,WAAW,KAAK,OAAO,CAAC,QAAQ,IAAI,kBAAkB,UAAU,EAAE;AACxE,WAAK,MAAM,MAAc;AAAA,QACvB,GAAI,KAAK,WAAW,IAAI,CAAC,oEAA+D,IAAI,CAAC;AAAA,QAC7F,GAAI,WAAW,IACX;AAAA,UACE,GAAG,QAAQ;AAAA,QACb,IACA,CAAC;AAAA,MACP,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,sBAAgB,GAAG;AAAA,IACrB;AAAA,EACF;AACF,CAAC;AAED,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aACE;AAAA,EACF,MAAM;AAAA,IACJ,cAAc;AAAA,IACd,cAAc,EAAE,MAAM,UAAU,aAAa,iCAAiC,UAAU,KAAK;AAAA,IAC7F,eAAe,EAAE,MAAM,UAAU,aAAa,qCAAqC,UAAU,KAAK;AAAA,IAClG,GAAG;AAAA,IACH,MAAM,EAAE,MAAM,UAAU,aAAa,oCAAoC,UAAU,MAAM;AAAA,EAC3F;AACF,CAAC;AAED,IAAM,uBAAuB,cAAc;AAAA,EACzC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa,iCAAiC,WAAW;AAAA;AAAA,EAE3D;AAAA,EACA,MAAM;AAAA,IACJ,cAAc;AAAA,IACd,cAAc,EAAE,MAAM,UAAU,aAAa,4DAA4D;AAAA,IACzG,eAAe,EAAE,MAAM,UAAU,aAAa,uEAAkE;AAAA,IAChH,GAAG;AAAA,IACH,MAAM,EAAE,MAAM,UAAU,aAAa,mCAAmC;AAAA,EAC1E;AAAA,EACA,KAAK,OAAO,EAAE,MAAM,QAAQ,MAAM;AAChC,UAAM,UAAU,aAAa,gBAAgB,KAAK,IAAI,GAAG;AAAA,MACvD,YAAY,KAAK,YAAY;AAAA,MAC7B,aAAa,KAAK,aAAa;AAAA,MAC/B,GAAG,sBAAsB,MAAc,OAAO;AAAA,IAChD,CAAC;AACD,UAAM,QAAQ,EAAE,MAAM,kBAAkB,WAAW,cAAc,IAAY,GAAG,QAAQ,GAAG;AAAA,MACzF;AAAA,IACF,CAAC;AAAA,EACH;AACF,CAAC;AAED,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aAAa;AAAA,EACb,MAAM;AAAA,IACJ,IAAI,EAAE,MAAM,cAAc,aAAa,cAAc,UAAU,KAAK;AAAA,IACpE,cAAc;AAAA,IACd,GAAG;AAAA,EACL;AACF,CAAC;AAED,IAAM,uBAAuB,cAAc;AAAA,EACzC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa,8BAA8B,WAAW;AAAA;AAAA,EAExD;AAAA,EACA,MAAM;AAAA,IACJ,IAAI,EAAE,MAAM,cAAc,aAAa,cAAc,UAAU,KAAK;AAAA,IACpE,cAAc;AAAA,IACd,GAAG;AAAA,EACL;AAAA,EACA,KAAK,OAAO,EAAE,MAAM,QAAQ,MAAM;AAChC,UAAM,QAAQ;AAAA,MACZ,MAAM;AAAA,MACN,WAAW,cAAc,IAAY;AAAA,MACrC,QAAQ,cAAc,MAAc,SAAS;AAAA,MAC7C,SAAS,sBAAsB,MAAc,OAAO;AAAA,IACtD,CAAC;AAAA,EACH;AACF,CAAC;AAED,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aAAa;AAAA,EACb,MAAM,EAAE,IAAI,EAAE,MAAM,cAAc,aAAa,cAAc,UAAU,KAAK,GAAG,cAAc,cAAc;AAC7G,CAAC;AAED,IAAM,uBAAuB,cAAc;AAAA,EACzC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa,sCAAsC,WAAW;AAAA;AAAA,EAEhE;AAAA,EACA,MAAM,EAAE,IAAI,EAAE,MAAM,cAAc,aAAa,cAAc,UAAU,KAAK,GAAG,cAAc,WAAW;AAAA,EACxG,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,UAAM,QAAQ;AAAA,MACZ,MAAM;AAAA,MACN,WAAW,cAAc,IAAY;AAAA,MACrC,QAAQ,cAAc,MAAc,SAAS;AAAA,MAC7C,SAAS,EAAE,QAAQ,UAAU;AAAA,IAC/B,CAAC;AAAA,EACH;AACF,CAAC;AAED,IAAM,kBAAkB,cAAc;AAAA,EACpC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA,EAKf;AAAA,EACA,aAAa;AAAA,IACX,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AAAA,EACA,MAAM;AAAA,IACJ,cAAc,EAAE,MAAM,UAAU,aAAa,aAAa;AAAA,IAC1D,eAAe,EAAE,MAAM,UAAU,aAAa,yCAAyC;AAAA,IACvF,MAAM,EAAE,MAAM,WAAW,aAAa,iDAAiD;AAAA,IACvF,QAAQ;AAAA,EACV;AAAA,EACA,SAAS;AACX,CAAC;AAKM,SAAS,yBAAyB,MAAY,SAAiD;AACpG,QAAM,cAAc,eAAe,SAAS,eAAe,KAAK,aAAa,CAAC,EAC3E,QAAQ,CAAC,UAAU,MAAM,MAAM,GAAG,CAAC,EACnC,IAAI,CAAC,UAAU,MAAM,KAAK,CAAC,EAC3B,OAAO,OAAO;AACjB,QAAM,SAAS,QAAQ,KAAK,QAAQ,QAAQ;AAC5C,MAAI,UAAU,YAAY,SAAS,EAAG,qBAAoB,0CAA0C;AACpG,SAAO,WAAW,YAAY,SAAS,IAAI,iBAAiB,WAAW,IAAI;AAC7E;AAEA,IAAM,cAAc;AAAA,EAClB,eAAe;AAAA,IACb,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA,EACA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,aACE;AAAA,EACJ;AACF;AAEA,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aAAa;AAAA,EACb,MAAM;AAAA,IACJ,cAAc,EAAE,MAAM,UAAU,aAAa,cAAc,UAAU,KAAK;AAAA,IAC1E,YAAY,EAAE,MAAM,WAAW,aAAa,oBAAoB,UAAU,MAAM;AAAA,IAChF,QAAQ;AAAA,EACV;AACF,CAAC;AAED,IAAM,kBAAkB,cAAc;AAAA,EACpC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aACE;AAAA,EACJ;AAAA,EACA,MAAM,EAAE,cAAc,EAAE,MAAM,UAAU,aAAa,aAAa,GAAG,YAAY,cAAc,QAAQ,UAAU;AAAA,EACjH,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,QAAI;AACF,YAAM,SAAiC,EAAE,cAAc,iBAAiB,IAAY,EAAE;AACtF,UAAI,KAAK,UAAU,EAAG,QAAO,YAAY,IAAI;AAC7C,YAAM,OAAO,MAAM,OAAc,8BAA8B,MAAM;AACrE,WAAK,MAAM,MAAc;AAAA,QACvB;AAAA,MACF,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,sBAAgB,GAAG;AAAA,IACrB;AAAA,EACF;AACF,CAAC;AAED,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aACE;AAAA,EACF,MAAM;AAAA,IACJ,cAAc;AAAA,IACd,cAAc,EAAE,MAAM,UAAU,aAAa,iCAAiC,UAAU,KAAK;AAAA,IAC7F,MAAM,EAAE,MAAM,UAAU,aAAa,YAAY,UAAU,KAAK;AAAA,IAChE,eAAe,EAAE,MAAM,UAAU,aAAa,yCAAyC,UAAU,MAAM;AAAA,IACvG,QAAQ,EAAE,MAAM,UAAU,aAAa,8BAA8B,UAAU,MAAM;AAAA,EACvF;AACF,CAAC;AAED,IAAM,mBAAmB,cAAc;AAAA,EACrC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa,wBAAwB,WAAW;AAAA;AAAA;AAAA,EAGlD;AAAA,EACA,MAAM;AAAA,IACJ,cAAc;AAAA,IACd,cAAc,EAAE,MAAM,UAAU,aAAa,4DAA4D;AAAA,IACzG,MAAM,EAAE,MAAM,UAAU,aAAa,WAAW;AAAA,IAChD,GAAG;AAAA,EACL;AAAA,EACA,KAAK,OAAO,EAAE,MAAM,QAAQ,MAAM;AAChC,UAAM;AAAA,MACJ;AAAA,QACE,MAAM;AAAA,QACN,WAAW,cAAc,IAAY;AAAA,QACrC,SAAS;AAAA,UACP,YAAY,KAAK,YAAY;AAAA,UAC7B,MAAM,KAAK;AAAA,UACX,QAAQ,yBAAyB,MAAc,OAAO;AAAA,QACxD;AAAA,MACF;AAAA,MACA;AAAA,QACE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF,CAAC;AAED,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aAAa;AAAA,EACb,MAAM;AAAA,IACJ,IAAI,EAAE,MAAM,cAAc,aAAa,kBAAkB,UAAU,KAAK;AAAA,IACxE,cAAc;AAAA,IACd,MAAM,EAAE,MAAM,UAAU,aAAa,YAAY,UAAU,MAAM;AAAA,IACjE,eAAe,EAAE,MAAM,UAAU,aAAa,yCAAyC,UAAU,MAAM;AAAA,IACvG,QAAQ,EAAE,MAAM,UAAU,aAAa,8BAA8B,UAAU,MAAM;AAAA,EACvF;AACF,CAAC;AAED,IAAM,mBAAmB,cAAc;AAAA,EACrC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa,6CAA6C,WAAW;AAAA;AAAA,EAEvE;AAAA,EACA,MAAM;AAAA,IACJ,IAAI,EAAE,MAAM,cAAc,aAAa,kBAAkB,UAAU,KAAK;AAAA,IACxE,cAAc;AAAA,IACd,MAAM,EAAE,MAAM,UAAU,aAAa,WAAW;AAAA,IAChD,GAAG;AAAA,EACL;AAAA,EACA,KAAK,OAAO,EAAE,MAAM,QAAQ,MAAM;AAChC,UAAM,QAAQ;AAAA,MACZ,MAAM;AAAA,MACN,WAAW,cAAc,IAAY;AAAA,MACrC,QAAQ,cAAc,MAAc,aAAa;AAAA,MACjD,SAAS,EAAE,MAAM,KAAK,MAAM,QAAQ,yBAAyB,MAAc,OAAO,EAAE;AAAA,IACtF,CAAC;AAAA,EACH;AACF,CAAC;AAED,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aACE;AAAA,EACF,MAAM,EAAE,IAAI,EAAE,MAAM,cAAc,aAAa,kBAAkB,UAAU,KAAK,GAAG,cAAc,cAAc;AACjH,CAAC;AAED,IAAM,mBAAmB,cAAc;AAAA,EACrC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa,uFAAkF,WAAW;AAAA;AAAA,EAE5G;AAAA,EACA,MAAM,EAAE,IAAI,EAAE,MAAM,cAAc,aAAa,kBAAkB,UAAU,KAAK,GAAG,cAAc,WAAW;AAAA,EAC5G,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,UAAM,QAAQ;AAAA,MACZ,MAAM;AAAA,MACN,WAAW,cAAc,IAAY;AAAA,MACrC,QAAQ,cAAc,MAAc,aAAa;AAAA,MACjD,SAAS,EAAE,QAAQ,UAAU;AAAA,IAC/B,CAAC;AAAA,EACH;AACF,CAAC;AAED,IAAM,cAAc,cAAc;AAAA,EAChC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA,EAKf;AAAA,EACA,aAAa,EAAE,MAAM,iBAAiB,QAAQ,kBAAkB,QAAQ,kBAAkB,QAAQ,iBAAiB;AAAA,EACnH,MAAM,EAAE,cAAc,EAAE,MAAM,UAAU,aAAa,aAAa,GAAG,YAAY,cAAc,QAAQ,UAAU;AAAA,EACjH,SAAS;AACX,CAAC;AAID,IAAM,eAAe;AAAA,EACnB,KAAK,EAAE,MAAM,UAAU,aAAa,8DAA8D;AAAA,EAClG,UAAU,EAAE,MAAM,UAAU,aAAa,0BAA0B;AAAA,EACnE,MAAM,EAAE,MAAM,UAAU,aAAa,wBAAmB;AAAA,EACxD,KAAK,EAAE,MAAM,UAAU,aAAa,yCAAyC;AAC/E;AAGO,SAAS,qBAAqB,MAAiD;AACpF,MAAI,KAAK,QAAQ,UAAa,KAAK,aAAa,UAAa,KAAK,SAAS,UAAa,KAAK,QAAQ,QAAW;AAC9G,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,KAAK,KAAK;AAAA,IACV,UAAU,MAAM,KAAK,QAAQ,KAAK;AAAA,IAClC,MAAM,WAAW,KAAK,MAAM,QAAQ;AAAA,IACpC,aAAa,MAAM,KAAK,GAAG;AAAA,EAC7B;AACF;AAEA,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aAAa;AAAA,EACb,MAAM,EAAE,cAAc,EAAE,MAAM,UAAU,aAAa,cAAc,UAAU,KAAK,GAAG,QAAQ,aAAa;AAC5G,CAAC;AAED,IAAM,mBAAmB,cAAc;AAAA,EACrC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aACE;AAAA,EACJ;AAAA,EACA,MAAM,EAAE,cAAc,EAAE,MAAM,UAAU,aAAa,aAAa,GAAG,QAAQ,UAAU;AAAA,EACvF,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,QAAI;AACF,WAAK,MAAM,SAAS,SAAS,IAAY,GAAG,MAAc,CAAC,CAAC;AAAA,IAC9D,SAAS,KAAK;AACZ,sBAAgB,GAAG;AAAA,IACrB;AAAA,EACF;AACF,CAAC;AAED,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aACE;AAAA,EACF,MAAM;AAAA,IACJ,cAAc;AAAA,IACd,cAAc,EAAE,MAAM,UAAU,aAAa,iCAAiC,UAAU,KAAK;AAAA,IAC7F,MAAM,EAAE,MAAM,UAAU,aAAa,aAAa,UAAU,KAAK;AAAA,IACjE,KAAK,EAAE,MAAM,UAAU,aAAa,6BAA6B,UAAU,MAAM;AAAA,IACjF,UAAU,EAAE,MAAM,UAAU,aAAa,qCAAqC,UAAU,MAAM;AAAA,IAC9F,MAAM,EAAE,MAAM,UAAU,aAAa,kBAAa,UAAU,MAAM;AAAA,IAClE,KAAK,EAAE,MAAM,UAAU,aAAa,kBAAkB,UAAU,MAAM;AAAA,EACxE;AACF,CAAC;AAED,IAAM,oBAAoB,cAAc;AAAA,EACtC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa,6CAA6C,WAAW;AAAA;AAAA,EAEvE;AAAA,EACA,MAAM;AAAA,IACJ,cAAc;AAAA,IACd,cAAc,EAAE,MAAM,UAAU,aAAa,4DAA4D;AAAA,IACzG,MAAM,EAAE,MAAM,UAAU,aAAa,YAAY;AAAA,IACjD,GAAG;AAAA,EACL;AAAA,EACA,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,UAAM,QAAQ;AAAA,MACZ,MAAM;AAAA,MACN,WAAW,cAAc,IAAY;AAAA,MACrC,SAAS,EAAE,YAAY,KAAK,YAAY,GAAG,MAAM,KAAK,MAAM,UAAU,qBAAqB,IAAY,EAAE;AAAA,IAC3G,CAAC;AAAA,EACH;AACF,CAAC;AAED,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aAAa;AAAA,EACb,MAAM;AAAA,IACJ,IAAI,EAAE,MAAM,cAAc,aAAa,WAAW,UAAU,KAAK;AAAA,IACjE,cAAc;AAAA,IACd,MAAM,EAAE,MAAM,UAAU,aAAa,YAAY,UAAU,MAAM;AAAA,IACjE,KAAK,EAAE,MAAM,UAAU,aAAa,6BAA6B,UAAU,MAAM;AAAA,IACjF,UAAU,EAAE,MAAM,UAAU,aAAa,2BAA2B,UAAU,MAAM;AAAA,IACpF,MAAM,EAAE,MAAM,UAAU,aAAa,kBAAa,UAAU,MAAM;AAAA,IAClE,KAAK,EAAE,MAAM,UAAU,aAAa,kBAAkB,UAAU,MAAM;AAAA,EACxE;AACF,CAAC;AAED,IAAM,oBAAoB,cAAc;AAAA,EACtC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa,0CAA0C,WAAW;AAAA;AAAA,EAEpE;AAAA,EACA,MAAM;AAAA,IACJ,IAAI,EAAE,MAAM,cAAc,aAAa,WAAW,UAAU,KAAK;AAAA,IACjE,cAAc;AAAA,IACd,MAAM,EAAE,MAAM,UAAU,aAAa,WAAW;AAAA,IAChD,GAAG;AAAA,EACL;AAAA,EACA,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,UAAM,QAAQ;AAAA,MACZ,MAAM;AAAA,MACN,WAAW,cAAc,IAAY;AAAA,MACrC,QAAQ,cAAc,MAAc,MAAM;AAAA,MAC1C,SAAS,EAAE,MAAM,KAAK,MAAM,UAAU,qBAAqB,IAAY,EAAE;AAAA,IAC3E,CAAC;AAAA,EACH;AACF,CAAC;AAED,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aAAa;AAAA,EACb,MAAM,EAAE,IAAI,EAAE,MAAM,cAAc,aAAa,WAAW,UAAU,KAAK,GAAG,cAAc,cAAc;AAC1G,CAAC;AAED,IAAM,oBAAoB,cAAc;AAAA,EACtC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa,yDAAyD,WAAW;AAAA;AAAA,EAEnF;AAAA,EACA,MAAM,EAAE,IAAI,EAAE,MAAM,cAAc,aAAa,WAAW,UAAU,KAAK,GAAG,cAAc,WAAW;AAAA,EACrG,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,UAAM,QAAQ;AAAA,MACZ,MAAM;AAAA,MACN,WAAW,cAAc,IAAY;AAAA,MACrC,QAAQ,cAAc,MAAc,MAAM;AAAA,MAC1C,SAAS,EAAE,QAAQ,UAAU;AAAA,IAC/B,CAAC;AAAA,EACH;AACF,CAAC;AAED,IAAM,eAAe,cAAc;AAAA,EACjC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA,EAKf;AAAA,EACA,aAAa;AAAA,IACX,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AAAA,EACA,MAAM,EAAE,cAAc,EAAE,MAAM,UAAU,aAAa,aAAa,GAAG,QAAQ,UAAU;AAAA,EACvF,SAAS;AACX,CAAC;AAID,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aACE;AAAA,EACF,MAAM,EAAE,cAAc,EAAE,MAAM,UAAU,aAAa,cAAc,UAAU,KAAK,GAAG,QAAQ,aAAa;AAC5G,CAAC;AAED,IAAM,qBAAqB,cAAc;AAAA,EACvC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aACE;AAAA,EACJ;AAAA,EACA,MAAM,EAAE,cAAc,EAAE,MAAM,UAAU,aAAa,aAAa,GAAG,QAAQ,UAAU;AAAA,EACvF,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,QAAI;AACF,YAAM,OAAO,MAAM,SAAS,eAAe,IAAY;AACvD,WAAK,MAAM,MAAc,KAAK,WAAW,IAAI,CAAC,6CAA6C,IAAI,CAAC,CAAC;AAAA,IACnG,SAAS,KAAK;AACZ,sBAAgB,GAAG;AAAA,IACrB;AAAA,EACF;AACF,CAAC;AAEM,IAAM,kBAAkB,cAAc;AAAA,EAC3C,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA;AAAA,EAIf;AAAA,EACA,aAAa;AAAA,IACX,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,EACf;AAAA,EACA,MAAM;AAAA,IACJ,eAAe,EAAE,MAAM,UAAU,aAAa,cAAc;AAAA,IAC5D,cAAc,EAAE,MAAM,UAAU,aAAa,aAAa;AAAA,IAC1D,YAAY;AAAA,IACZ,QAAQ;AAAA,EACV;AAAA,EACA,SAAS;AACX,CAAC;","names":["rows"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/ads/meta/asset-writes.ts"],"sourcesContent":["import { type ArgsDef, type CommandDef, defineCommand } from \"citty\";\nimport { repeatedValues } from \"../../../lib/repeatedFlags.ts\";\nimport { registerSchema } from \"../../../schemas.ts\";\nimport { bareAccountId, failWriteValidation, numberFlag, requireTarget, stageOp, stageOps } from \"./write-shared.ts\";\n\n/**\n * Staged writes on the account's own assets: deleting a creative or an image,\n * changing or deleting a Custom Conversion, and ad labels — creating, renaming,\n * deleting them, and filing campaigns, ad sets, ads and creatives under them.\n * Nothing reaches Meta until the chat publishes.\n */\n\nconst STAGED_NOTE = \"Staged until publish — review with `baker ads meta draft`.\";\nconst accountArg = { type: \"string\", description: \"Meta ad account ID (act_123)\" } as const;\nconst schemaId = (what: string) => ({ type: \"positional\", description: what, required: true });\n\nexport function command(input: {\n schema: string;\n name: string;\n description: string;\n schemaDescription: string;\n args: Record<string, { type: string; description: string; required?: boolean }>;\n run: (args: Record<string, unknown>, rawArgs: readonly string[] | undefined) => Promise<void>;\n}): CommandDef<ArgsDef> {\n registerSchema({\n command: input.schema,\n description: input.schemaDescription,\n args: Object.fromEntries(\n Object.entries(input.args).map(([key, arg]) => [\n key,\n { type: arg.type, description: arg.description, required: arg.required === true },\n ]),\n ),\n });\n return defineCommand<ArgsDef>({\n meta: { name: input.name, description: `${input.description} ${STAGED_NOTE}` },\n args: input.args as ArgsDef,\n run: async ({ args, rawArgs }) => {\n await input.run(args as Record<string, unknown>, rawArgs);\n },\n });\n}\n\n// --- Creatives ---\n\nexport const creativesDeleteCommand = command({\n schema: \"ads.meta.creatives.delete\",\n name: \"delete\",\n description:\n \"Stage deleting an ad creative. Meta deletes only a creative no ad runs — repoint or delete the ad first. Permanent.\",\n schemaDescription:\n \"Stage deleting a Meta ad creative (status DELETED) — applied at publish, permanent. Meta refuses a creative an ad still runs.\",\n args: { id: { type: \"positional\", description: \"Creative id\", required: true }, \"account-id\": accountArg },\n run: async (args) => {\n await stageOp({\n kind: \"adCreative.update\",\n accountId: bareAccountId(args),\n target: requireTarget(args, \"creative\"),\n payload: { status: \"DELETED\" },\n });\n },\n});\n\n// --- Images ---\n\nexport const mediaDeleteCommand = command({\n schema: \"ads.meta.media.delete\",\n name: \"delete\",\n description:\n \"Stage taking an image out of the ad account's image library, by its hash (`baker ads meta images`), or one of its videos by id (`--video-id`, from `baker ads meta media`). Meta refuses an image a creative still uses.\",\n schemaDescription:\n \"Stage deleting an image from a Meta ad account's image library by hash, or a video from its video library by id — applied at publish. Meta refuses an image a creative uses.\",\n args: {\n \"account-id\": accountArg,\n \"image-hash\": { type: \"string\", description: \"The image's hash\" },\n \"video-id\": { type: \"string\", description: \"Or a video of the ad account, by id\" },\n },\n run: async (args) => {\n const imageHash = typeof args[\"image-hash\"] === \"string\" ? args[\"image-hash\"] : undefined;\n const videoId = typeof args[\"video-id\"] === \"string\" ? args[\"video-id\"] : undefined;\n if ((imageHash === undefined) === (videoId === undefined)) {\n failWriteValidation(\"pass --image-hash (from `baker ads meta images`) or --video-id — one of them\");\n }\n await stageOp({ kind: \"media.delete\", accountId: bareAccountId(args), payload: { imageHash, videoId } });\n },\n});\n\n// --- Custom conversions ---\n\nexport const customConversionsUpdateCommand = command({\n schema: \"ads.meta.custom-conversions.update\",\n name: \"update\",\n description:\n \"Stage renaming a Custom Conversion, its description or its value per conversion. Meta keeps a conversion's rule and event category for good — a conversion that counts something else is a new one.\",\n schemaDescription:\n \"Stage a change to a Meta Custom Conversion: --name, --description, --value (value per conversion, account currency). The rule and event category cannot change (Meta accepts and ignores them).\",\n args: {\n id: { type: \"positional\", description: \"Custom conversion id\", required: true },\n \"account-id\": accountArg,\n name: { type: \"string\", description: \"New name\" },\n description: { type: \"string\", description: \"New description\" },\n value: { type: \"string\", description: \"Value of one conversion, in the account currency\" },\n },\n run: async (args) => {\n const payload = Object.fromEntries(\n Object.entries({\n name: args.name,\n description: args.description,\n default_conversion_value: numberFlag(args.value, \"--value\"),\n }).filter(([, value]) => value !== undefined),\n );\n await stageOp({\n kind: \"customConversion.update\",\n accountId: bareAccountId(args),\n target: requireTarget(args, \"custom conversion\"),\n payload,\n });\n },\n});\n\nexport const customConversionsDeleteCommand = command({\n schema: \"ads.meta.custom-conversions.delete\",\n name: \"delete\",\n description:\n \"Stage deleting a Custom Conversion. Meta archives it: it stops counting and leaves the active list, and still uses one of the account's slots. Ad sets optimizing toward it stop finding conversions.\",\n schemaDescription:\n \"Stage deleting (archiving) a Meta Custom Conversion — applied at publish. Not reversible; it keeps its slot in the account's cap.\",\n args: { id: schemaId(\"Custom conversion id\"), \"account-id\": accountArg },\n run: async (args) => {\n await stageOp({\n kind: \"customConversion.update\",\n accountId: bareAccountId(args),\n target: requireTarget(args, \"custom conversion\"),\n payload: { status: \"DELETED\" },\n });\n },\n});\n\n// --- Labels ---\n\nexport const labelsCreateCommand = command({\n schema: \"ads.meta.labels.create\",\n name: \"create\",\n description:\n 'Stage a new ad label. File things under it with `labels attach <ref> --campaigns …` in the same chat. Example: baker ads meta labels create --name \"Q4 launch\"',\n schemaDescription: \"Stage a new Meta ad label (created at publish). Returns a meta_temp_* ref `labels attach` takes.\",\n args: { \"account-id\": accountArg, name: { type: \"string\", description: \"Label name\" } },\n run: async (args) => {\n await stageOp({ kind: \"adLabel.create\", accountId: bareAccountId(args), payload: { name: args.name } });\n },\n});\n\nexport const labelsRenameCommand = command({\n schema: \"ads.meta.labels.rename\",\n name: \"rename\",\n description: \"Stage renaming an ad label.\",\n schemaDescription: \"Stage renaming a Meta ad label.\",\n args: { id: schemaId(\"Label id\"), \"account-id\": accountArg, name: { type: \"string\", description: \"New name\" } },\n run: async (args) => {\n await stageOp({\n kind: \"adLabel.update\",\n accountId: bareAccountId(args),\n target: requireTarget(args, \"label\"),\n payload: { name: args.name },\n });\n },\n});\n\nexport const labelsDeleteCommand = command({\n schema: \"ads.meta.labels.delete\",\n name: \"delete\",\n description: \"Stage deleting an ad label. Everything filed under it keeps running, unlabelled.\",\n schemaDescription: \"Stage deleting a Meta ad label — applied at publish; labelled objects keep running.\",\n args: { id: schemaId(\"Label id\"), \"account-id\": accountArg },\n run: async (args) => {\n await stageOp({\n kind: \"adLabel.update\",\n accountId: bareAccountId(args),\n target: requireTarget(args, \"label\"),\n payload: { status: \"DELETED\" },\n });\n },\n});\n\nconst LABELLED = [\n [\"campaigns\", \"campaign.update\"],\n [\"adsets\", \"adSet.update\"],\n [\"ads\", \"ad.update\"],\n [\"creatives\", \"adCreative.update\"],\n] as const;\n\nconst targetArgs = {\n campaigns: { type: \"string\", description: \"Campaign ids (comma-separated or repeated)\" },\n adsets: { type: \"string\", description: \"Ad set ids\" },\n ads: { type: \"string\", description: \"Ad ids\" },\n creatives: {\n type: \"string\",\n description: \"Creative ids (live ones — a creative created in this chat is labelled later)\",\n },\n} as const;\n\nfunction idsOf(rawArgs: readonly string[] | undefined, flag: string, parsed: unknown): string[] {\n return repeatedValues(rawArgs, flag, parsed)\n .flatMap((value) => value.split(\",\"))\n .map((value) => value.trim())\n .filter(Boolean);\n}\n\n/**\n * One staged update per object. Each names only the label to add or take\n * away; staging reads the labels the object has now and stages the whole set,\n * because Meta replaces an object's labels with the set it is sent.\n */\nasync function stageLabelChange(\n verb: \"addLabels\" | \"removeLabels\",\n args: Record<string, unknown>,\n rawArgs: readonly string[] | undefined,\n): Promise<void> {\n const accountId = bareAccountId(args);\n const label = requireTarget(args, \"label\");\n const targets = LABELLED.flatMap(([flag, kind]) => idsOf(rawArgs, flag, args[flag]).map((id) => ({ kind, id })));\n if (targets.length === 0) {\n failWriteValidation(\"name what to label: --campaigns, --adsets, --ads or --creatives\");\n }\n await stageOps(\n targets.map((target) => ({ kind: target.kind, accountId, target: target.id, payload: { [verb]: [label] } })),\n );\n}\n\nexport const labelsAttachCommand = command({\n schema: \"ads.meta.labels.attach\",\n name: \"attach\",\n description:\n \"Stage filing campaigns, ad sets, ads or creatives under a label (a label id, or a meta_temp_* ref from `labels create`). Their other labels stay. Example: baker ads meta labels attach 120249 --campaigns 6123,6124\",\n schemaDescription:\n \"Stage adding a Meta ad label to campaigns/ad sets/ads/creatives (--campaigns, --adsets, --ads, --creatives; comma-separated). One staged change per object; other labels kept.\",\n args: { id: schemaId(\"Label id or meta_temp_* ref\"), \"account-id\": accountArg, ...targetArgs },\n run: async (args, rawArgs) => {\n await stageLabelChange(\"addLabels\", args, rawArgs);\n },\n});\n\nexport const labelsDetachCommand = command({\n schema: \"ads.meta.labels.detach\",\n name: \"detach\",\n description: \"Stage taking a label off campaigns, ad sets, ads or creatives. Their other labels stay.\",\n schemaDescription:\n \"Stage removing a Meta ad label from campaigns/ad sets/ads/creatives (--campaigns, --adsets, --ads, --creatives). Other labels kept.\",\n args: { id: schemaId(\"Label id\"), \"account-id\": accountArg, ...targetArgs },\n run: async (args, rawArgs) => {\n await stageLabelChange(\"removeLabels\", args, rawArgs);\n },\n});\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../api/src/ads-meta/permissionGates.ts","../src/commands/ads/meta/shared.ts"],"sourcesContent":["/**\n * The refusals Baker writes for Meta work that needs a permission the baseline\n * connection does not ask for — managing catalogs (`catalog_management`) and\n * posting to a Facebook Page (`pages_manage_posts`). Shared verbatim by the\n * backend that throws them and the CLI that explains them, for the same reason\n * as `leadAds.ts`: these name their own cause and remedy, so the CLI must not\n * append Meta's ambiguous \"maybe reconnect, maybe an unassigned asset\" advice.\n */\n\nexport type MetaPermissionGate = \"catalog\" | \"pagePosts\";\n\n/** Everything a person or the agent can see about one per-company Meta permission. */\nexport interface MetaPermissionState {\n /** A Baker admin switched it on for this company, so the consent screen asks for it. */\n enabled: boolean;\n /** The current Meta connection holds it. */\n granted: boolean;\n /** Switched on, but the connection predates it — reconnecting Meta is the fix. */\n reconnectNeeded: boolean;\n}\n\nexport type MetaPermissionStates = Record<\"leadAds\" | MetaPermissionGate, MetaPermissionState>;\n\nexport const META_PERMISSION_NOT_ENABLED_MESSAGE: Record<MetaPermissionGate, string> = {\n catalog:\n \"Catalog changes need the Catalog permission for Meta — ask a Baker admin to turn it on, then reconnect Meta. \" +\n \"Everything else on Meta keeps working: tell the user, and carry on with the rest of the job.\",\n pagePosts:\n \"Facebook Page posts need the Page posts permission for Meta — ask a Baker admin to turn it on, then reconnect \" +\n \"Meta. Everything else on Meta keeps working: tell the user, and carry on with the rest of the job.\",\n};\n\nexport const META_PERMISSION_RECONNECT_MESSAGE: Record<MetaPermissionGate, string> = {\n catalog:\n \"Catalog changes need the Catalog permission for Meta. It is turned on for this company, but this Meta \" +\n \"connection was made before, so it does not hold it — ask the user to reconnect Meta in the dashboard, then \" +\n \"try again. Everything else on Meta keeps working meanwhile.\",\n pagePosts:\n \"Facebook Page posts need the Page posts permission for Meta. It is turned on for this company, but this Meta \" +\n \"connection was made before, so it does not hold it — ask the user to reconnect Meta in the dashboard, then \" +\n \"try again. Everything else on Meta keeps working meanwhile.\",\n};\n\n/**\n * Work that needs a Meta permission Baker's connection does not ask for at all\n * (no switch turns it on): reading and moderating comments on ads\n * (`pages_read_user_content`, `pages_manage_engagement`) and listing an\n * Instagram account's posts (`instagram_basic`). Live on v26.0 (2026-10-15)\n * Meta refused both with code 10.\n */\nexport const META_UNREQUESTED_PERMISSION_MESSAGE = {\n comments:\n \"Reading and moderating comments on ads needs Meta permissions Baker's Meta connection does not ask for yet \" +\n \"(reading people's comments and managing them on the Page). Tell the user that comment moderation happens in \" +\n \"Meta Business Suite for now, and carry on with the rest of the job.\",\n instagramMedia:\n \"Listing an Instagram account's posts needs a Meta permission Baker's Meta connection does not ask for yet. \" +\n \"Ask the user for the post's link or id instead, or boost it from Meta Business Suite, and carry on.\",\n} as const;\n\nconst META_PAGE_ADS_PERMISSION_REMEDY =\n \"A Baker admin turns it on with the lead ads switch for this company; then the user reconnects Meta in the dashboard. \" +\n \"Tell the user, and carry on with the rest of the job.\";\n\n/**\n * Click-to-message ads and Instant Experiences need Meta's Page ads permission\n * (`pages_manage_ads`), which only the lead ads switch adds to the consent\n * screen. `work` names what was refused (\"Click-to-message ads\").\n */\nexport function metaPageAdsPermissionMessage(work: string): string {\n return `${work} need Meta's Page ads permission, and this Meta connection does not have it. ${META_PAGE_ADS_PERMISSION_REMEDY}`;\n}\n\n/**\n * Whether a `FORBIDDEN` message carries one of these refusals. `includes`, not\n * equality: a stage-time refusal may lead with what the op was trying to do.\n */\nexport function isMetaPermissionGateRefusal(message: string): boolean {\n return [\n ...Object.values(META_PERMISSION_NOT_ENABLED_MESSAGE),\n ...Object.values(META_PERMISSION_RECONNECT_MESSAGE),\n ...Object.values(META_UNREQUESTED_PERMISSION_MESSAGE),\n META_PAGE_ADS_PERMISSION_REMEDY,\n ].some((refusal) => message.includes(refusal));\n}\n","import { isMetaPermissionGateRefusal } from \"@baker/api/ads-meta/permissionGates\";\nimport { ApiError } from \"../../../client.ts\";\nimport { getEnv } from \"../../../env.ts\";\nimport { handleConnectionError, isOrganizationReadRefusal, needsConnectionFix } from \"../../../error-handler.ts\";\nimport { writeAdsJson, writeJsonEnvelope } from \"../output.ts\";\nimport { termsRefusalFix } from \"../terms-output.ts\";\nimport type { AdsErrorEnvelope, QueryFix } from \"../types.ts\";\n\nconst DAY_MS = 86_400_000;\n\n/**\n * Meta answers a permission refusal (Graph codes 200/10/294) with a bare\n * \"Permissions error\" that covers two causes needing opposite remedies: a\n * consent grant the connection never got — nothing validates Meta's granted\n * scopes after connect, unlike HubSpot's `requireCapability` — or a role the\n * user lacks on one asset, since a Pixel/Dataset, Page or catalog lives in a\n * Business and is assigned separately from the ad account. Only the blast radius\n * separates them, so hand the agent that test rather than a verdict: guessing\n * \"reconnect\" wastes the user's time on an unassigned asset, and ruling it out\n * strands a connection that really is short a scope.\n */\nexport function metaForbiddenFix(message: string): QueryFix {\n // Baker's own refusal already names the switch or the reconnect; Meta's\n // two-cause advice under it would contradict it.\n if (isMetaPermissionGateRefusal(message)) {\n return { action: \"reject\", explanation: message };\n }\n if (message.includes(\"has not accepted Meta's Lead Generation Terms\")) {\n return {\n action: \"reject\",\n explanation: `${message}\\n\\nMeta confirmed the Page's terms status using its Page access. Give the Page owner the terms link in the error and ask them to accept it before trying the form or lead ad set again. Do not suggest reconnecting Meta for this refusal; continue with other work that does not require the form or ad set.`,\n };\n }\n return {\n action: \"reject\",\n explanation: [\n message,\n \"This is a permission refusal, not a dead connection, and Meta returns the same code for two causes with opposite remedies. Tell them apart by how much else works before you answer.\",\n \"If other reads on this account are ALSO refused (campaigns, ad sets, insights), the connection is short a permission it was never granted. Only the user can widen it, by reconnecting Meta from the dashboard.\",\n \"If those reads work and only this object is refused, the asset (pixel/dataset, Page, or catalog) belongs to a Business the connected user holds no role in. Ad-account access does not carry asset access and reconnecting cannot grant it — the client assigns that asset to the connected user or partner in Meta Business settings, under the asset's own section (Data sources → Datasets for a pixel).\",\n \"Either way do not retry the same call, and do not abort the wider job. Continue with what you can read, and state in your answer that this specific check could not run and why — never present the task as verified when this step was skipped.\",\n ].join(\"\\n\\n\"),\n };\n}\n\nexport function handleMetaError(err: unknown): never {\n if (err instanceof ApiError) {\n if (needsConnectionFix(err.code, err.message)) {\n handleConnectionError(\"meta_ads\", err.message);\n }\n const terms = termsRefusalFix(err.code, err.message);\n if (terms) {\n writeJsonEnvelope({\n ok: false,\n error: { code: terms.code, message: err.message, fix: terms.fix, retryable: false },\n });\n process.exit(1);\n }\n const envelope: AdsErrorEnvelope = {\n ok: false,\n error: {\n code: err.code,\n message: err.message,\n fix:\n err.code === \"FORBIDDEN\" && !isOrganizationReadRefusal(err.message)\n ? metaForbiddenFix(err.message)\n : { action: \"reject\", explanation: err.message },\n retryable: err.code === \"RATE_LIMITED\" || err.code === \"UNAVAILABLE\" || err.code === \"INTERNAL_ERROR\",\n },\n };\n writeAdsJson(envelope);\n process.exit(1);\n }\n const message = err instanceof Error ? err.message : \"Unexpected error\";\n writeAdsJson({ ok: false, error: { code: \"NETWORK_ERROR\", message } });\n process.exit(1);\n}\n\nconst ACCOUNT_ID_RE = /^(act_)?[0-9]+$/;\n\n/** Pull the default Meta ad account ID from `--account-id` arg or `BAKER_META_AD_ACCOUNT_ID` env. */\nexport function resolveAccountIdArg(args: Record<string, unknown>): string {\n const fromArgs = args[\"account-id\"] as string | undefined;\n const id = fromArgs || getEnv().BAKER_META_AD_ACCOUNT_ID;\n if (!id) {\n writeAdsJson({\n ok: false,\n error: {\n code: \"MISSING_ACCOUNT_ID\",\n message: \"Pass --account-id or set BAKER_META_AD_ACCOUNT_ID. Run `baker ads meta accounts` to find IDs.\",\n },\n });\n process.exit(1);\n }\n if (!ACCOUNT_ID_RE.test(id)) {\n writeAdsJson({\n ok: false,\n error: {\n code: \"INVALID_ACCOUNT_ID\",\n message: `Invalid account ID \"${id}\". Expected numeric ID, optionally prefixed with \"act_\".`,\n },\n });\n process.exit(1);\n }\n return id.startsWith(\"act_\") ? id : `act_${id}`;\n}\n\nexport function getDateRange(args: Record<string, unknown>): { datePreset?: string; since?: string; until?: string } {\n const datePreset = args[\"date-preset\"] as string | undefined;\n const since = args.since as string | undefined;\n const until = args.until as string | undefined;\n if (since && until) return { since, until };\n return { datePreset: datePreset ?? \"last_7d\" };\n}\n\nexport function todayIso(): string {\n return new Date().toISOString().slice(0, 10);\n}\n\nexport function daysAgoIso(days: number): string {\n return new Date(Date.now() - days * DAY_MS).toISOString().slice(0, 10);\n}\n\nexport function csvOrJson(args: Record<string, unknown>): string {\n return (args.output as string | undefined) ?? \"json\";\n}\n\n/**\n * Matched by Meta itself, so finding one entity by name reads only the rows that\n * match instead of the whole account.\n */\nexport const NAME_CONTAINS_ARG = {\n type: \"string\",\n description:\n \"Only rows whose name contains this text, matched by Meta before anything is returned. Start here to find one entity by name: --name-contains octubre --all-statuses\",\n} as const;\n\n/**\n * Default to ACTIVE-only on listings — that's almost always what an AI agent or\n * a human glance wants. Pass `--effective-status ACTIVE,PAUSED` to override, or\n * `--all-statuses` to drop the filter entirely.\n */\nexport function resolveEffectiveStatus(args: Record<string, unknown>): string | undefined {\n if (args[\"all-statuses\"]) {\n return undefined;\n }\n const explicit = args[\"effective-status\"] as string | undefined;\n if (explicit) {\n return explicit;\n }\n return \"ACTIVE\";\n}\n\n/**\n * An empty listing under a status filter reads exactly like \"nothing exists\":\n * a paused campaign's ad sets are CAMPAIGN_PAUSED, so the ACTIVE default hides\n * every one of them. Say which filter produced the empty list and how to widen it.\n */\nexport function statusFilterHints(\n rows: ReadonlyArray<unknown>,\n effectiveStatus: string | undefined,\n noun: string,\n): string[] {\n if (rows.length > 0 || effectiveStatus === undefined) return [];\n if (effectiveStatus === \"ACTIVE\") {\n return [\n `No ACTIVE ${noun}. The ACTIVE filter hides paused, archived and in-review ones (under a paused campaign or ad set that is all of them), so this does NOT mean none exist. Re-run with --all-statuses before concluding there are none.`,\n ];\n }\n return [\n `No ${noun} with effective_status ${effectiveStatus}. Re-run with --all-statuses to see every status before concluding there are none.`,\n ];\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/ads/meta/write-shared.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { type MetaDraftStageResponse, metaDraftOpInputSchema } from \"@baker/api/ads-meta\";\nimport { apiPost } from \"../../../client.ts\";\nimport { requireChatId } from \"../../../env.ts\";\nimport { repeatedValues } from \"../../../lib/repeatedFlags.ts\";\nimport { capabilityFix } from \"../../capabilities/fix.ts\";\nimport { booleanWordPositionalError } from \"../boolean-word-positional.ts\";\nimport { adCopyHints } from \"../copy-hints.ts\";\nimport { withHints } from \"../hints.ts\";\nimport { writeJsonEnvelope } from \"../output.ts\";\nimport { handleMetaError, resolveAccountIdArg } from \"./shared.ts\";\n\n/**\n * Shared plumbing for the staged Meta write commands. Writes NEVER hit Meta\n * directly: every command stages an op against this chat's draft\n * (`/api/ads/meta/draft/stage`), the dashboard shows it as a pending Meta\n * change, and it applies when the chat is published.\n */\n\n/** Backend account ids are bare numeric — strip the `act_` prefix resolveAccountIdArg adds. */\nexport function bareAccountId(args: Record<string, unknown>): string {\n return resolveAccountIdArg(args).replace(/^act_/, \"\");\n}\n\nexport function failWriteValidation(message: string): never {\n writeJsonEnvelope({ ok: false, error: { code: \"VALIDATION_ERROR\", message } });\n process.exit(1);\n}\n\n/** Deleting is permanent, so it only stages through `delete`, whose description carries that warning. */\nexport function refuseDeleteByUpdate(payload: Record<string, unknown>, group: \"campaigns\" | \"adsets\" | \"ads\"): void {\n if (payload.status === \"DELETED\") {\n failWriteValidation(\n `update does not delete — deleting is permanent. Use \\`baker ads meta ${group} delete <id>\\` if the user asked to delete; otherwise pause or archive.`,\n );\n }\n}\n\n/**\n * `--file`: a JSON file path, or the JSON itself when it starts with `{` — the shape Google's\n * `--file` already takes and the one an agent writes first for a short payload (a customer list of\n * a few people).\n */\nexport function loadJsonFileArg(path: unknown): Record<string, unknown> {\n if (typeof path !== \"string\" || path.length === 0) {\n return {};\n }\n const inline = /^\\s*\\{/.test(path);\n const source = inline ? \"inline JSON\" : path;\n try {\n const parsed = JSON.parse(inline ? path : readFileSync(path, \"utf8\")) as unknown;\n if (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n failWriteValidation(`${source} must contain a JSON object`);\n }\n return parsed as Record<string, unknown>;\n } catch (err) {\n if (err instanceof SyntaxError) {\n failWriteValidation(`${source} is not valid JSON: ${err.message}`);\n }\n throw err;\n }\n}\n\n/** Flags override file keys — the file is the base, flags are the overrides. */\nexport function mergePayload(file: Record<string, unknown>, flags: Record<string, unknown>): Record<string, unknown> {\n const merged: Record<string, unknown> = { ...file };\n for (const [key, value] of Object.entries(flags)) {\n if (value !== undefined) {\n merged[key] = value;\n }\n }\n return merged;\n}\n\nexport function parseMoneyFlag(\n amount: unknown,\n currency: unknown,\n flag: string,\n): { amount: string; currencyCode?: string } | undefined {\n if (amount === undefined || amount === null || amount === \"\") {\n return undefined;\n }\n if (currency === undefined || currency === null || currency === \"\") {\n // Meta ad accounts are single-currency — the backend fills it in.\n return { amount: String(amount) };\n }\n if (typeof currency !== \"string\" || currency.length !== 3) {\n failWriteValidation(`${flag} got an invalid --currency (expected a 3-letter code like USD)`);\n }\n return { amount: String(amount), currencyCode: currency.toUpperCase() };\n}\n\n/** Accepts ISO dates (2026-07-10), ISO datetimes, or epoch millis. */\nexport function parseDateFlag(value: unknown, flag: string): number | undefined {\n if (value === undefined || value === null || value === \"\") {\n return undefined;\n }\n const raw = String(value);\n if (/^\\d{10,}$/.test(raw)) {\n return Number(raw);\n }\n const parsed = Date.parse(raw);\n if (Number.isNaN(parsed)) {\n failWriteValidation(`${flag} must be an ISO date (2026-07-10) or epoch milliseconds`);\n }\n return parsed;\n}\n\n/** Split a comma-separated flag into a trimmed, non-empty array. */\nexport function listFlag(value: unknown): string[] | undefined {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n return undefined;\n }\n const items = value\n .split(\",\")\n .map((item) => item.trim())\n .filter(Boolean);\n return items.length > 0 ? items : undefined;\n}\n\n/**\n * A list flag that may be repeated as well as comma-separated\n * (`--countries ES,FR --countries DE`). citty keeps only a repeated flag's last\n * value, so the values are read from the command line (`repeatedValues`).\n */\nexport function repeatedListFlag(\n rawArgs: readonly string[] | undefined,\n flag: string,\n parsed: unknown,\n): string[] | undefined {\n const items = repeatedValues(rawArgs, flag, parsed)\n .flatMap((value) => value.split(\",\"))\n .map((item) => item.trim())\n .filter(Boolean);\n return items.length > 0 ? items : undefined;\n}\n\nexport function upper(value: unknown): string | undefined {\n return typeof value === \"string\" && value.length > 0 ? value.toUpperCase() : undefined;\n}\n\nexport function numberFlag(value: unknown, flag: string): number | undefined {\n if (value === undefined || value === null || value === \"\") {\n return undefined;\n }\n const n = Number(value);\n if (!Number.isFinite(n)) {\n failWriteValidation(`${flag} must be a number`);\n }\n return n;\n}\n\n/**\n * Accepts whichever positional the command declared (`id`, `target`, `ref`) or the raw positional.\n *\n * `--flag false` is refused first: citty turns it into the flag set to TRUE plus a stray positional,\n * so on `campaigns duplicate 6123 --replace false` the copy stages AND the live original is staged\n * for pause — the opposite of what was typed, with an \"ok\" receipt. This is the only place on this\n * surface that reads positionals, and every target-taking command goes through it.\n */\nexport function requireTarget(args: Record<string, unknown>, entity: string): string {\n const inverted = booleanWordPositionalError(args, entity);\n if (inverted !== undefined) {\n failWriteValidation(inverted);\n }\n const positional = Array.isArray(args._) ? args._[0] : undefined;\n const target = args.id ?? args.target ?? args.ref ?? positional;\n if (typeof target !== \"string\" || target.length === 0) {\n failWriteValidation(`pass the ${entity} id as the positional argument`);\n }\n return target;\n}\n\ninterface StageEnvelope extends Record<string, unknown> {\n ok: true;\n data: MetaDraftStageResponse;\n}\n\n/**\n * Preflight-validates the op against the shared `@baker/api/ads-meta` contract\n * (same schema the backend enforces), then stages it. Prints the staged\n * envelope — ref, mode (always `live`: publishing reaches the real ad account),\n * summary, warnings.\n */\n/** The op parsed against the shared contract, or the validation envelope printed and the process ended. */\nfunction preflightOp(raw: Record<string, unknown>) {\n const preflight = metaDraftOpInputSchema.safeParse(raw);\n if (!preflight.success) {\n const fields = preflight.error.issues.map((issue) => ({ path: issue.path.join(\".\"), message: issue.message }));\n writeJsonEnvelope({\n ok: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: fields.map((field) => (field.path ? `${field.path}: ${field.message}` : field.message)).join(\"; \"),\n fields,\n fix: capabilityFix(\"meta-ads\"),\n },\n });\n process.exit(1);\n }\n return preflight.data;\n}\n\nexport async function stageOp(raw: Record<string, unknown>, extraHints: readonly string[] = []): Promise<void> {\n const op = preflightOp(raw);\n try {\n const chatId = requireChatId();\n const response = await apiPost<StageEnvelope>(\"/api/ads/meta/draft/stage\", { chatId, op });\n const copyHints = await adCopyHints(op);\n writeJsonEnvelope(withHints(response, [...copyHints, ...extraHints]));\n } catch (err) {\n handleMetaError(err);\n }\n}\n\n/**\n * Stage several ops as one command and print one envelope: each staged op's\n * receipt, in order. Stops at the first refusal, which names the op it was —\n * the ones before it stay staged, and the envelope says which.\n */\nexport async function stageOps(raws: readonly Record<string, unknown>[]): Promise<void> {\n const ops = raws.map(preflightOp);\n const chatId = requireChatId();\n const staged: MetaDraftStageResponse[] = [];\n for (const op of ops) {\n try {\n const response = await apiPost<StageEnvelope>(\"/api/ads/meta/draft/stage\", { chatId, op });\n staged.push(response.data);\n } catch (err) {\n if (staged.length > 0) {\n process.stderr.write(`staged before the refusal: ${staged.map((entry) => entry.ref).join(\", \")}\\n`);\n }\n handleMetaError(err);\n }\n }\n writeJsonEnvelope({ ok: true, data: staged });\n}\n\nexport async function stageStatusChange(input: {\n kind: \"campaign.update\" | \"adSet.update\" | \"adCreative.update\" | \"ad.update\" | \"customAudience.update\";\n accountId: string;\n target: string;\n status: \"ACTIVE\" | \"PAUSED\" | \"ARCHIVED\" | \"DELETED\";\n}): Promise<void> {\n await stageOp({\n kind: input.kind,\n accountId: input.accountId,\n target: input.target,\n payload: { status: input.status },\n });\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/ads/meta/creatives.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport { NO_CACHE_ARG } from \"../../../cache-flag.ts\";\nimport { apiGet } from \"../../../client.ts\";\nimport { writeAdsJson, writeAdsOutput } from \"../output.ts\";\nimport { csvOrJson, handleMetaError, resolveAccountIdArg } from \"./shared.ts\";\n\nconst listArgs = {\n \"account-id\": { type: \"string\", description: \"Meta ad account ID (required if no --creative-id)\" },\n \"creative-id\": { type: \"string\", description: \"Single creative ID\" },\n limit: { type: \"string\", description: \"Max rows (default 500)\" },\n \"no-cache\": NO_CACHE_ARG,\n output: { type: \"string\", description: \"Output format\", default: \"json\" },\n} as const;\n\nconst listCommand = defineCommand({\n meta: {\n name: \"list\",\n description:\n \"List ad creatives, or fetch one by ID. Runs by default when no subcommand is given. Example: baker ads meta creatives --account-id act_123\",\n },\n args: listArgs,\n run: async ({ args }) => {\n try {\n const params: Record<string, string> = {};\n if (args[\"creative-id\"]) {\n params[\"creative-id\"] = args[\"creative-id\"] as string;\n } else {\n const accountId = resolveAccountIdArg(args);\n params[\"account-id\"] = accountId;\n }\n if (args.limit) params.limit = args.limit as string;\n if (args[\"no-cache\"]) params[\"skip-cache\"] = \"true\";\n const data = await apiGet<unknown>(\"/api/ads/meta/creatives\", params);\n const fmt = csvOrJson(args);\n if (Array.isArray(data) && fmt !== \"json\") {\n writeAdsOutput(data as Array<Record<string, unknown>>, fmt);\n return;\n }\n writeAdsJson({ ok: true, data });\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n\nexport const creativesCommand = defineCommand({\n meta: {\n name: \"creatives\",\n description: `List ad creatives, fetch one by ID, or stage writes (create/update). Write subcommands stage ops on this chat's draft.\n\nImportant: Meta creatives are effectively immutable once attached to an ad. Editing copy/image/CTA = create\na new creative + repoint the ad (baker ads meta ads update <adId> --creative <ref>).\n\nExamples:\n baker ads meta creatives --account-id act_123\n baker ads meta creatives --creative-id 23842... # fetch one\n baker ads meta creatives create --page 555 --message \"Save now\" --link https://x.com --image-hash abc… --cta SHOP_NOW`,\n },\n subCommands: {\n list: listCommand,\n create: () => import(\"./write-commands.ts\").then((m) => m.adCreativesCreateCommand),\n update: () => import(\"./write-commands.ts\").then((m) => m.adCreativesUpdateCommand),\n delete: () => import(\"./asset-writes.ts\").then((m) => m.creativesDeleteCommand),\n },\n // `args` stays even though the parent has no `run`: citty scans rawArgs for the\n // subcommand name using THIS command's arg defs, so without them `--account-id act_1`\n // would read `act_1` as a subcommand. `default` (not `run`) dispatches the bare\n // invocation — citty falls through to `run` after a subcommand, double-executing it.\n args: listArgs,\n default: \"list\",\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,qBAAqB;AAM9B,IAAM,WAAW;AAAA,EACf,cAAc,EAAE,MAAM,UAAU,aAAa,oDAAoD;AAAA,EACjG,eAAe,EAAE,MAAM,UAAU,aAAa,qBAAqB;AAAA,EACnE,OAAO,EAAE,MAAM,UAAU,aAAa,yBAAyB;AAAA,EAC/D,YAAY;AAAA,EACZ,QAAQ,EAAE,MAAM,UAAU,aAAa,iBAAiB,SAAS,OAAO;AAC1E;AAEA,IAAM,cAAc,cAAc;AAAA,EAChC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aACE;AAAA,EACJ;AAAA,EACA,MAAM;AAAA,EACN,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,QAAI;AACF,YAAM,SAAiC,CAAC;AACxC,UAAI,KAAK,aAAa,GAAG;AACvB,eAAO,aAAa,IAAI,KAAK,aAAa;AAAA,MAC5C,OAAO;AACL,cAAM,YAAY,oBAAoB,IAAI;AAC1C,eAAO,YAAY,IAAI;AAAA,MACzB;AACA,UAAI,KAAK,MAAO,QAAO,QAAQ,KAAK;AACpC,UAAI,KAAK,UAAU,EAAG,QAAO,YAAY,IAAI;AAC7C,YAAM,OAAO,MAAM,OAAgB,2BAA2B,MAAM;AACpE,YAAM,MAAM,UAAU,IAAI;AAC1B,UAAI,MAAM,QAAQ,IAAI,KAAK,QAAQ,QAAQ;AACzC,uBAAe,MAAwC,GAAG;AAC1D;AAAA,MACF;AACA,mBAAa,EAAE,IAAI,MAAM,KAAK,CAAC;AAAA,IACjC,SAAS,KAAK;AACZ,sBAAgB,GAAG;AAAA,IACrB;AAAA,EACF;AACF,CAAC;AAEM,IAAM,mBAAmB,cAAc;AAAA,EAC5C,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASf;AAAA,EACA,aAAa;AAAA,IACX,MAAM;AAAA,IACN,QAAQ,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,wBAAwB;AAAA,IAClF,QAAQ,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,wBAAwB;AAAA,IAClF,QAAQ,MAAM,OAAO,4BAAmB,EAAE,KAAK,CAAC,MAAM,EAAE,sBAAsB;AAAA,EAChF;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM;AAAA,EACN,SAAS;AACX,CAAC;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/ads/meta/page-photos.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport { registerSchema } from \"../../../schemas.ts\";\nimport { bareAccountId, failWriteValidation, requireTarget, stageOp } from \"./write-shared.ts\";\n\n/**\n * Photos put on a Facebook Page without posting them — what an Instant\n * Experience's photo element takes, and what a collection ad's four-photo\n * experience is built from. Needs the Page posts permission for Meta.\n */\n\nconst STAGED_NOTE = \"Staged until publish — review with `baker ads meta draft`.\";\ntype Args = Record<string, unknown>;\n\nregisterSchema({\n command: \"ads.meta.page-photos.upload\",\n description:\n \"Stage a photo upload to a Facebook Page, NOT posted to its timeline, made at publish — for Instant Experience photo elements (`instant-experiences create --photo-id <ref>`). Needs the Page posts permission for Meta.\",\n args: {\n \"account-id\": { type: \"string\", description: \"Ad account the change is staged under\", required: false },\n \"page-id\": { type: \"string\", description: \"The Facebook Page\", required: true },\n \"image-id\": { type: \"string\", description: \"Baker library image id\", required: false },\n url: { type: \"string\", description: \"Or a public https picture address\", required: false },\n caption: { type: \"string\", description: \"Caption kept with the photo (never posted)\", required: false },\n },\n});\n\nconst uploadCommand = defineCommand({\n meta: {\n name: \"upload\",\n description: `Put a photo on a Facebook Page without posting it. ${STAGED_NOTE}\nExample: baker ads meta page-photos upload --account-id act_123 --page-id 904238019441800 --image-id <library image id>\nThen: baker ads meta instant-experiences create --page-id 904238019441800 --photo-id meta_temp_… …`,\n },\n args: {\n \"account-id\": { type: \"string\", description: \"Numeric account ID or act_N\" },\n \"page-id\": { type: \"string\", description: \"The Facebook Page — from `baker ads meta pages`\" },\n \"image-id\": { type: \"string\", description: \"Baker library image id (`baker images library …`)\" },\n url: { type: \"string\", description: \"Or a public https picture address Meta can fetch\" },\n caption: { type: \"string\", description: \"Caption kept with the photo; it is never posted\" },\n },\n run: async ({ args }) => {\n if (!args[\"image-id\"] && !args.url) failWriteValidation(\"pass --image-id (a library image) or --url\");\n await stageOp(\n {\n kind: \"pagePhoto.create\",\n accountId: bareAccountId(args as Args),\n payload: {\n page_id: args[\"page-id\"],\n bakerImageId: args[\"image-id\"],\n url: args.url,\n caption: args.caption,\n },\n },\n [\"Use it in an Instant Experience with `instant-experiences create --photo-id <ref>`.\"],\n );\n },\n});\n\nregisterSchema({\n command: \"ads.meta.page-photos.delete\",\n description: \"Stage deleting a photo from a Facebook Page. An Instant Experience already made with it keeps it.\",\n args: {\n id: { type: \"positional\", description: \"Page photo id\", required: true },\n \"account-id\": { type: \"string\", description: \"Ad account the change is staged under\", required: false },\n },\n});\n\nconst deleteCommand = defineCommand({\n meta: {\n name: \"delete\",\n description: `Delete a photo from its Facebook Page. ${STAGED_NOTE}\nExample: baker ads meta page-photos delete 122142489045161003 --account-id act_123`,\n },\n args: {\n id: { type: \"positional\", description: \"Page photo 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: \"pagePhoto.update\",\n accountId: bareAccountId(args as Args),\n target: requireTarget(args as Args, \"Page photo\"),\n payload: { status: \"DELETED\" },\n });\n },\n});\n\nexport const pagePhotosCommand = defineCommand({\n meta: {\n name: \"page-photos\",\n description: `Photos on a Facebook Page that are never posted — for Instant Experiences and collection ads. Needs the Page posts permission for Meta.\n baker ads meta page-photos upload --page-id <id> --image-id <library id>\n baker ads meta page-photos delete <photo id>`,\n },\n subCommands: { upload: uploadCommand, delete: deleteCommand },\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,qBAAqB;AAU9B,IAAM,cAAc;AAGpB,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aACE;AAAA,EACF,MAAM;AAAA,IACJ,cAAc,EAAE,MAAM,UAAU,aAAa,yCAAyC,UAAU,MAAM;AAAA,IACtG,WAAW,EAAE,MAAM,UAAU,aAAa,qBAAqB,UAAU,KAAK;AAAA,IAC9E,YAAY,EAAE,MAAM,UAAU,aAAa,0BAA0B,UAAU,MAAM;AAAA,IACrF,KAAK,EAAE,MAAM,UAAU,aAAa,qCAAqC,UAAU,MAAM;AAAA,IACzF,SAAS,EAAE,MAAM,UAAU,aAAa,8CAA8C,UAAU,MAAM;AAAA,EACxG;AACF,CAAC;AAED,IAAM,gBAAgB,cAAc;AAAA,EAClC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa,sDAAsD,WAAW;AAAA;AAAA;AAAA,EAGhF;AAAA,EACA,MAAM;AAAA,IACJ,cAAc,EAAE,MAAM,UAAU,aAAa,8BAA8B;AAAA,IAC3E,WAAW,EAAE,MAAM,UAAU,aAAa,uDAAkD;AAAA,IAC5F,YAAY,EAAE,MAAM,UAAU,aAAa,yDAAoD;AAAA,IAC/F,KAAK,EAAE,MAAM,UAAU,aAAa,mDAAmD;AAAA,IACvF,SAAS,EAAE,MAAM,UAAU,aAAa,kDAAkD;AAAA,EAC5F;AAAA,EACA,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,QAAI,CAAC,KAAK,UAAU,KAAK,CAAC,KAAK,IAAK,qBAAoB,4CAA4C;AACpG,UAAM;AAAA,MACJ;AAAA,QACE,MAAM;AAAA,QACN,WAAW,cAAc,IAAY;AAAA,QACrC,SAAS;AAAA,UACP,SAAS,KAAK,SAAS;AAAA,UACvB,cAAc,KAAK,UAAU;AAAA,UAC7B,KAAK,KAAK;AAAA,UACV,SAAS,KAAK;AAAA,QAChB;AAAA,MACF;AAAA,MACA,CAAC,qFAAqF;AAAA,IACxF;AAAA,EACF;AACF,CAAC;AAED,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aAAa;AAAA,EACb,MAAM;AAAA,IACJ,IAAI,EAAE,MAAM,cAAc,aAAa,iBAAiB,UAAU,KAAK;AAAA,IACvE,cAAc,EAAE,MAAM,UAAU,aAAa,yCAAyC,UAAU,MAAM;AAAA,EACxG;AACF,CAAC;AAED,IAAM,gBAAgB,cAAc;AAAA,EAClC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa,0CAA0C,WAAW;AAAA;AAAA,EAEpE;AAAA,EACA,MAAM;AAAA,IACJ,IAAI,EAAE,MAAM,cAAc,aAAa,iBAAiB,UAAU,KAAK;AAAA,IACvE,cAAc,EAAE,MAAM,UAAU,aAAa,8BAA8B;AAAA,EAC7E;AAAA,EACA,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,UAAM,QAAQ;AAAA,MACZ,MAAM;AAAA,MACN,WAAW,cAAc,IAAY;AAAA,MACrC,QAAQ,cAAc,MAAc,YAAY;AAAA,MAChD,SAAS,EAAE,QAAQ,UAAU;AAAA,IAC/B,CAAC;AAAA,EACH;AACF,CAAC;AAEM,IAAM,oBAAoB,cAAc;AAAA,EAC7C,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA,EAGf;AAAA,EACA,aAAa,EAAE,QAAQ,eAAe,QAAQ,cAAc;AAC9D,CAAC;","names":[]}