@zalify/cli 0.13.0 → 0.14.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/dist/cli.js +48 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -12836,6 +12836,34 @@ async function shopifyImport(storeDir, options = {}) {
|
|
|
12836
12836
|
console.log(` ✓ pruned ${node.handle}`);
|
|
12837
12837
|
}
|
|
12838
12838
|
}
|
|
12839
|
+
for (const disc of catalog.discounts ?? []) {
|
|
12840
|
+
const existing = await gql(auth, `query($q: String!) { codeDiscountNodes(first: 1, query: $q) { nodes { id } } }`, { q: `code:${disc.code}` });
|
|
12841
|
+
if (existing.codeDiscountNodes.nodes.length) {
|
|
12842
|
+
console.log(` - discount ${disc.code} exists, skipped`);
|
|
12843
|
+
continue;
|
|
12844
|
+
}
|
|
12845
|
+
const res = await gql(auth, `mutation($discount: DiscountCodeBasicInput!) {
|
|
12846
|
+
discountCodeBasicCreate(basicCodeDiscount: $discount) {
|
|
12847
|
+
userErrors { field message }
|
|
12848
|
+
}
|
|
12849
|
+
}`, {
|
|
12850
|
+
discount: {
|
|
12851
|
+
title: disc.title ?? `${disc.code} — ${disc.percentOff}% off`,
|
|
12852
|
+
code: disc.code,
|
|
12853
|
+
startsAt: new Date().toISOString(),
|
|
12854
|
+
customerSelection: { all: true },
|
|
12855
|
+
customerGets: {
|
|
12856
|
+
value: { percentage: disc.percentOff / 100 },
|
|
12857
|
+
items: { all: true }
|
|
12858
|
+
}
|
|
12859
|
+
}
|
|
12860
|
+
});
|
|
12861
|
+
const errs = res.discountCodeBasicCreate.userErrors;
|
|
12862
|
+
if (errs.length)
|
|
12863
|
+
console.error(` ✗ discount ${disc.code}: ${joinErrors(errs)}`);
|
|
12864
|
+
else
|
|
12865
|
+
console.log(` ✓ discount ${disc.code} created (${disc.percentOff}% off)`);
|
|
12866
|
+
}
|
|
12839
12867
|
for (const pg of catalog.pages ?? []) {
|
|
12840
12868
|
const existing = await gql(auth, `query($q: String!) { pages(first: 1, query: $q) { nodes { id handle } } }`, { q: `handle:${pg.handle}` });
|
|
12841
12869
|
const node = existing.pages.nodes[0];
|
|
@@ -13076,6 +13104,10 @@ alone. Validate anytime with \`zalify brand validate\` (defaults to cwd).
|
|
|
13076
13104
|
privacy-policy, terms-of-service); write \`bodyHtml\` in the brand
|
|
13077
13105
|
voice (simple HTML: h2/p/ul/li). The \`contact\` page already exists in
|
|
13078
13106
|
every Shopify store — link it, don't create it.
|
|
13107
|
+
- **Discounts** (\`discounts\`): code discounts created by \`brand push\`
|
|
13108
|
+
(\`{ code, percentOff, title? }\`). Keep the scaffold's \`WELCOME20\` —
|
|
13109
|
+
it is the code the theme's cart voucher banner shows by default, so
|
|
13110
|
+
Apply actually works. Codes: 4-20 uppercase letters/digits.
|
|
13079
13111
|
- **Menus** (\`menus\`): \`main-menu\` (header nav) and \`footer\`, upserted
|
|
13080
13112
|
by \`brand push\`; the catalog is the source of truth (a push replaces
|
|
13081
13113
|
the menu's items). Items are \`{ title, url, items? }\`, max 3 levels.
|
|
@@ -13238,6 +13270,13 @@ var CATALOG_JSON = (vendor, currency) => JSON.stringify({
|
|
|
13238
13270
|
bodyHtml: "<p><Plain-language terms: orders, pricing, liability, governing law.></p>"
|
|
13239
13271
|
}
|
|
13240
13272
|
],
|
|
13273
|
+
discounts: [
|
|
13274
|
+
{
|
|
13275
|
+
code: "WELCOME20",
|
|
13276
|
+
percentOff: 20,
|
|
13277
|
+
title: "Welcome — 20% off the first order"
|
|
13278
|
+
}
|
|
13279
|
+
],
|
|
13241
13280
|
menus: {
|
|
13242
13281
|
"main-menu": [
|
|
13243
13282
|
{ title: "New in", url: "/collections/all" },
|
|
@@ -13478,6 +13517,15 @@ function brandValidate(dir2 = ".") {
|
|
|
13478
13517
|
for (const [menuHandle, nodes] of Object.entries(catalog.menus ?? {})) {
|
|
13479
13518
|
checkMenu(nodes ?? [], menuHandle, 1);
|
|
13480
13519
|
}
|
|
13520
|
+
for (const disc of catalog.discounts ?? []) {
|
|
13521
|
+
const where = `discount "${disc.code ?? "?"}"`;
|
|
13522
|
+
if (!disc.code || !/^[A-Z0-9]{4,20}$/.test(disc.code)) {
|
|
13523
|
+
problems.push(`${where}: code must be 4-20 uppercase letters/digits`);
|
|
13524
|
+
}
|
|
13525
|
+
if (typeof disc.percentOff !== "number" || !Number.isInteger(disc.percentOff) || disc.percentOff < 1 || disc.percentOff > 99) {
|
|
13526
|
+
problems.push(`${where}: percentOff must be an integer 1-99`);
|
|
13527
|
+
}
|
|
13528
|
+
}
|
|
13481
13529
|
}
|
|
13482
13530
|
const manifest = readJson2("images/manifest.json");
|
|
13483
13531
|
if (manifest) {
|