@koda-sl/baker-cli 0.173.0-dev.6ecd65d29 → 0.173.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -2
- package/dist/{chunk-K424D3CY.js → chunk-CG6OTNUU.js} +4 -4
- package/dist/chunk-CG6OTNUU.js.map +1 -0
- package/dist/cli.js +111 -30
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-K424D3CY.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
toModelSafeImage,
|
|
37
37
|
ulid,
|
|
38
38
|
validateCanvasDeep
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-CG6OTNUU.js";
|
|
40
40
|
import {
|
|
41
41
|
csvOrJson,
|
|
42
42
|
daysAgoIso,
|
|
@@ -3063,6 +3063,13 @@ var hubspotContactLookupResponseSchema = z10.object({
|
|
|
3063
3063
|
createdAt: z10.string().nullable()
|
|
3064
3064
|
}).nullable(),
|
|
3065
3065
|
deals: z10.array(z10.object({ id: z10.string(), stage: z10.string().nullable(), pipeline: z10.string().nullable() })),
|
|
3066
|
+
/**
|
|
3067
|
+
* False when the connection never granted deal access, which makes an empty
|
|
3068
|
+
* `deals` unknown rather than absent. Deal access is granted separately from
|
|
3069
|
+
* contact access, so one can be present without the other — and "no deals"
|
|
3070
|
+
* is the headline finding of this command, so it must not be guessed.
|
|
3071
|
+
*/
|
|
3072
|
+
dealsReadable: z10.boolean(),
|
|
3066
3073
|
/**
|
|
3067
3074
|
* The account the contact was filed under. In B2B a workflow usually
|
|
3068
3075
|
* creates it on contact creation, so its absence is a finding — but only
|
|
@@ -4977,6 +4984,19 @@ var ASSET_FIELD_TYPES = [
|
|
|
4977
4984
|
"MARKETING_IMAGE",
|
|
4978
4985
|
"BUSINESS_NAME"
|
|
4979
4986
|
];
|
|
4987
|
+
var ASSET_GROUP_ASSET_FIELD_TYPES = [
|
|
4988
|
+
"MARKETING_IMAGE",
|
|
4989
|
+
"SQUARE_MARKETING_IMAGE",
|
|
4990
|
+
"PORTRAIT_MARKETING_IMAGE",
|
|
4991
|
+
"LOGO",
|
|
4992
|
+
"LANDSCAPE_LOGO",
|
|
4993
|
+
"YOUTUBE_VIDEO",
|
|
4994
|
+
"HEADLINE",
|
|
4995
|
+
"LONG_HEADLINE",
|
|
4996
|
+
"DESCRIPTION",
|
|
4997
|
+
"BUSINESS_NAME",
|
|
4998
|
+
"CALL_TO_ACTION_SELECTION"
|
|
4999
|
+
];
|
|
4980
5000
|
var DEVICE_TYPES = ["MOBILE", "TABLET", "DESKTOP", "CONNECTED_TV", "OTHER"];
|
|
4981
5001
|
var DAYS_OF_WEEK = ["MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", "SUNDAY"];
|
|
4982
5002
|
var CAMPAIGN_OBJECTIVES = [
|
|
@@ -5353,9 +5373,15 @@ var assetGroupCreateSchema = z15.object({
|
|
|
5353
5373
|
businessName: z15.string().min(1).max(GOOGLE_ADS_LIMITS.assetGroup.businessNameMax),
|
|
5354
5374
|
imageAssets: z15.array(refSchema).optional(),
|
|
5355
5375
|
squareImageAssets: z15.array(refSchema).optional(),
|
|
5376
|
+
portraitImageAssets: z15.array(refSchema).optional(),
|
|
5356
5377
|
logoAssets: z15.array(refSchema).optional(),
|
|
5357
5378
|
status: z15.enum(["ENABLED", "PAUSED"]).default("PAUSED")
|
|
5358
5379
|
});
|
|
5380
|
+
var assetGroupAssetAttachSchema = z15.object({
|
|
5381
|
+
assetGroup: refSchema,
|
|
5382
|
+
asset: refSchema,
|
|
5383
|
+
fieldType: z15.enum(ASSET_GROUP_ASSET_FIELD_TYPES)
|
|
5384
|
+
});
|
|
5359
5385
|
var assetGroupUpdateSchema = z15.object({
|
|
5360
5386
|
name: z15.string().min(1).max(GOOGLE_ADS_LIMITS.assetGroup.nameMax).optional(),
|
|
5361
5387
|
finalUrls: z15.array(httpsUrlSchema2).min(1).optional(),
|
|
@@ -5526,6 +5552,8 @@ var GOOGLE_DRAFT_OP_KINDS = [
|
|
|
5526
5552
|
"google.assetLink.detach",
|
|
5527
5553
|
"google.assetGroup.create",
|
|
5528
5554
|
"google.assetGroup.update",
|
|
5555
|
+
"google.assetGroupAsset.attach",
|
|
5556
|
+
"google.assetGroupAsset.detach",
|
|
5529
5557
|
"google.audience.create",
|
|
5530
5558
|
"google.audienceCriterion.attach",
|
|
5531
5559
|
"google.audienceCriterion.detach",
|
|
@@ -5583,6 +5611,8 @@ var googleDraftOpInputSchema = z15.discriminatedUnion("kind", [
|
|
|
5583
5611
|
targetOp("google.assetLink.detach"),
|
|
5584
5612
|
createOp2("google.assetGroup.create", assetGroupCreateSchema),
|
|
5585
5613
|
updateOp2("google.assetGroup.update", assetGroupUpdateSchema),
|
|
5614
|
+
createOp2("google.assetGroupAsset.attach", assetGroupAssetAttachSchema),
|
|
5615
|
+
targetOp("google.assetGroupAsset.detach"),
|
|
5586
5616
|
createOp2("google.audience.create", audienceCreateSchema2),
|
|
5587
5617
|
createOp2("google.audienceCriterion.attach", audienceCriterionAttachSchema),
|
|
5588
5618
|
targetOp("google.audienceCriterion.detach"),
|
|
@@ -9553,8 +9583,15 @@ var assetGroupsCommand = defineCommand30({
|
|
|
9553
9583
|
"long-headlines": { type: "string", description: "Comma-separated long headlines (1\u20135, \u226490 chars)" },
|
|
9554
9584
|
descriptions: { type: "string", description: "Comma-separated descriptions (2\u20135, \u226490 chars)" },
|
|
9555
9585
|
"business-name": { type: "string" },
|
|
9556
|
-
"image-assets": { type: "string", description: "Comma-separated marketing image asset refs" },
|
|
9557
|
-
"square-image-assets": {
|
|
9586
|
+
"image-assets": { type: "string", description: "Comma-separated marketing image asset refs (1.91:1)" },
|
|
9587
|
+
"square-image-assets": {
|
|
9588
|
+
type: "string",
|
|
9589
|
+
description: "Comma-separated square marketing image asset refs (1:1)"
|
|
9590
|
+
},
|
|
9591
|
+
"portrait-image-assets": {
|
|
9592
|
+
type: "string",
|
|
9593
|
+
description: "Comma-separated portrait marketing image asset refs (4:5)"
|
|
9594
|
+
},
|
|
9558
9595
|
"logo-assets": { type: "string", description: "Comma-separated logo image asset refs" },
|
|
9559
9596
|
status: { type: "string", description: "ENABLED | PAUSED (default PAUSED)" }
|
|
9560
9597
|
},
|
|
@@ -9573,6 +9610,7 @@ var assetGroupsCommand = defineCommand30({
|
|
|
9573
9610
|
businessName: args["business-name"],
|
|
9574
9611
|
imageAssets: listFlag(args["image-assets"]),
|
|
9575
9612
|
squareImageAssets: listFlag(args["square-image-assets"]),
|
|
9613
|
+
portraitImageAssets: listFlag(args["portrait-image-assets"]),
|
|
9576
9614
|
logoAssets: listFlag(args["logo-assets"]),
|
|
9577
9615
|
status: args.status
|
|
9578
9616
|
});
|
|
@@ -9598,7 +9636,40 @@ var assetGroupsCommand = defineCommand30({
|
|
|
9598
9636
|
});
|
|
9599
9637
|
await stageUpdate("google.assetGroup.update", customerId, target, payload);
|
|
9600
9638
|
}
|
|
9601
|
-
})
|
|
9639
|
+
}),
|
|
9640
|
+
attach: defineCommand30({
|
|
9641
|
+
meta: {
|
|
9642
|
+
name: "attach",
|
|
9643
|
+
description: "Add one existing asset to an existing asset group. Start here to refresh a live PMax group's creatives: attach the new image, then `detach` the old one \u2014 never detach first."
|
|
9644
|
+
},
|
|
9645
|
+
args: {
|
|
9646
|
+
...customerIdArg,
|
|
9647
|
+
...fileArg,
|
|
9648
|
+
"asset-group-ref": { type: "string", description: "Asset group ref (g_temp_*, id, or resource name)" },
|
|
9649
|
+
"asset-ref": { type: "string", description: "Asset ref (g_temp_*, id, or resource name)" },
|
|
9650
|
+
"field-type": {
|
|
9651
|
+
type: "string",
|
|
9652
|
+
description: `Slot the asset fills: ${ASSET_GROUP_ASSET_FIELD_TYPES.join(" | ")}`
|
|
9653
|
+
}
|
|
9654
|
+
},
|
|
9655
|
+
run: async ({ args }) => {
|
|
9656
|
+
const customerId = requireCustomerId(args);
|
|
9657
|
+
const payload = mergePayload(loadJsonFileArg(args.file), {
|
|
9658
|
+
assetGroup: args["asset-group-ref"],
|
|
9659
|
+
asset: args["asset-ref"],
|
|
9660
|
+
fieldType: args["field-type"]
|
|
9661
|
+
});
|
|
9662
|
+
await stageCreate("google.assetGroupAsset.attach", customerId, payload, [
|
|
9663
|
+
"Swapping a creative? Stage the matching `asset-groups detach` for the image this one replaces \u2014 an attach alone grows the group instead of refreshing it.",
|
|
9664
|
+
"The field type must match the image's real ratio (1.91:1 \u2192 MARKETING_IMAGE, 1:1 \u2192 SQUARE_MARKETING_IMAGE, 4:5 \u2192 PORTRAIT_MARKETING_IMAGE); Google rejects a mismatch at publish.",
|
|
9665
|
+
"Slots have ceilings as well as minimums: BUSINESS_NAME and CALL_TO_ACTION_SELECTION hold 1, LOGO 5, LONG_HEADLINE and DESCRIPTION 5, HEADLINE 15, YOUTUBE_VIDEO 15, images 20. Adding to a full slot is rejected exactly like removing below an empty one, so count what the group already holds (`SELECT asset_group_asset.field_type FROM asset_group_asset WHERE asset_group.id = \u2026`) and stage the detach alongside when it is full."
|
|
9666
|
+
]);
|
|
9667
|
+
}
|
|
9668
|
+
}),
|
|
9669
|
+
detach: statusCommand2("google.assetGroupAsset.detach", "asset group asset", [
|
|
9670
|
+
"Stage order is execution order \u2014 if you are replacing this image, its `asset-groups attach` must already be staged BEFORE this detach, or Google sees the group below its per-ratio minimum and rejects the removal.",
|
|
9671
|
+
"Pass the full composite resource name (customers/{cid}/assetGroupAssets/{assetGroupId}~{assetId}~{FIELD_TYPE}) \u2014 read it from `asset_group_asset.resource_name` via `ads google query`."
|
|
9672
|
+
])
|
|
9602
9673
|
}
|
|
9603
9674
|
});
|
|
9604
9675
|
function fileCreateCommand(name, kind, description, hints) {
|
|
@@ -26708,7 +26779,7 @@ registerSchema({
|
|
|
26708
26779
|
});
|
|
26709
26780
|
registerSchema({
|
|
26710
26781
|
command: "hubspot.contacts.lookup",
|
|
26711
|
-
description: "One contact by email: its lifecycle stage, whether anyone is assigned, the account (company) it was filed under, and any deals it is attached to with their stage. Use it to settle whether a specific lead was picked up. `found: false` means the lead never reached the CRM at all \u2014 that is a finding, not an error. `companyReadable: false`
|
|
26782
|
+
description: "One contact by email: its lifecycle stage, whether anyone is assigned, the account (company) it was filed under, and any deals it is attached to with their stage. Use it to settle whether a specific lead was picked up. `found: false` means the lead never reached the CRM at all \u2014 that is a finding, not an error. `dealsReadable: false` / `companyReadable: false` mean deals or account details were not readable on this connection, so an empty deals list or a null company is unknown rather than absent.",
|
|
26712
26783
|
args: {
|
|
26713
26784
|
email: { type: "positional", description: "The contact's email address", required: true }
|
|
26714
26785
|
}
|
|
@@ -27078,6 +27149,35 @@ var contactsSummaryCommand = defineCommand114({
|
|
|
27078
27149
|
}
|
|
27079
27150
|
}
|
|
27080
27151
|
});
|
|
27152
|
+
function contactLookupHints(data) {
|
|
27153
|
+
const { found, contact, deals, dealsReadable, company, companyReadable } = data;
|
|
27154
|
+
if (!found) {
|
|
27155
|
+
return [
|
|
27156
|
+
"No contact with that email. The lead never reached the CRM \u2014 check the form's submissions before assuming the CRM lost it."
|
|
27157
|
+
];
|
|
27158
|
+
}
|
|
27159
|
+
const hints = [];
|
|
27160
|
+
if (contact?.ownerId === null) {
|
|
27161
|
+
hints.push("Nobody is assigned to this contact.");
|
|
27162
|
+
}
|
|
27163
|
+
if (!dealsReadable) {
|
|
27164
|
+
hints.push(
|
|
27165
|
+
"Deals were not read: this HubSpot connection does not cover them. Do not report the lead as having no deal \u2014 you cannot tell. The user can enable it by reconnecting HubSpot."
|
|
27166
|
+
);
|
|
27167
|
+
} else if (deals.length === 0) {
|
|
27168
|
+
hints.push("No deal is associated, so this contact was never taken into the pipeline.");
|
|
27169
|
+
}
|
|
27170
|
+
if (!companyReadable) {
|
|
27171
|
+
hints.push(
|
|
27172
|
+
"Account details were not read: this HubSpot connection does not cover them. Do not report the lead as having no account \u2014 you cannot tell. The user can enable it by reconnecting HubSpot."
|
|
27173
|
+
);
|
|
27174
|
+
} else if (company === null) {
|
|
27175
|
+
hints.push(
|
|
27176
|
+
"No account is associated either. Most B2B setups create one automatically when a contact arrives, so this usually means the lead was never processed at all \u2014 not that the account is missing."
|
|
27177
|
+
);
|
|
27178
|
+
}
|
|
27179
|
+
return hints;
|
|
27180
|
+
}
|
|
27081
27181
|
var contactsLookupCommand = defineCommand114({
|
|
27082
27182
|
meta: {
|
|
27083
27183
|
name: "lookup",
|
|
@@ -27091,31 +27191,12 @@ var contactsLookupCommand = defineCommand114({
|
|
|
27091
27191
|
const response = await apiPost("/api/hubspot/contacts/lookup", {
|
|
27092
27192
|
email: args.email
|
|
27093
27193
|
});
|
|
27094
|
-
const
|
|
27095
|
-
|
|
27096
|
-
|
|
27097
|
-
|
|
27098
|
-
|
|
27099
|
-
|
|
27100
|
-
} else {
|
|
27101
|
-
if (contact?.ownerId === null) {
|
|
27102
|
-
hints.push("Nobody is assigned to this contact.");
|
|
27103
|
-
}
|
|
27104
|
-
if (deals.length === 0) {
|
|
27105
|
-
hints.push("No deal is associated, so this contact was never taken into the pipeline.");
|
|
27106
|
-
}
|
|
27107
|
-
if (companyReadable && company === null) {
|
|
27108
|
-
hints.push(
|
|
27109
|
-
"No account is associated either. Most B2B setups create one automatically when a contact arrives, so this usually means the lead was never processed at all \u2014 not that the account is missing."
|
|
27110
|
-
);
|
|
27111
|
-
}
|
|
27112
|
-
if (!companyReadable) {
|
|
27113
|
-
hints.push(
|
|
27114
|
-
"Account details were not read: this HubSpot connection does not cover them. Do not report the lead as having no account \u2014 you cannot tell. The user can enable it by reconnecting HubSpot."
|
|
27115
|
-
);
|
|
27116
|
-
}
|
|
27117
|
-
}
|
|
27118
|
-
writeJson({ ...response, meta: { count: found ? 1 : 0 }, ...hints.length > 0 ? { hints } : {} });
|
|
27194
|
+
const hints = contactLookupHints(response.data);
|
|
27195
|
+
writeJson({
|
|
27196
|
+
...response,
|
|
27197
|
+
meta: { count: response.data.found ? 1 : 0 },
|
|
27198
|
+
...hints.length > 0 ? { hints } : {}
|
|
27199
|
+
});
|
|
27119
27200
|
} catch (err) {
|
|
27120
27201
|
failNotConnected(err);
|
|
27121
27202
|
}
|