@zalify/cli 0.14.0 → 0.16.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 +64 -76
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -12064,7 +12064,7 @@ async function imagesGenerate(storeDir) {
|
|
|
12064
12064
|
import { readFileSync as readFileSync6, existsSync as existsSync6 } from "node:fs";
|
|
12065
12065
|
import { basename as basename3, join as join6, resolve as resolve5 } from "node:path";
|
|
12066
12066
|
|
|
12067
|
-
// src/
|
|
12067
|
+
// src/shop.ts
|
|
12068
12068
|
import { spawn as spawn3, spawnSync as spawnSync3 } from "node:child_process";
|
|
12069
12069
|
import { existsSync as existsSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync6 } from "node:fs";
|
|
12070
12070
|
import { basename as basename2, join as join5, resolve as resolve4 } from "node:path";
|
|
@@ -12493,11 +12493,11 @@ function mergePackageJson(projectDir, oldDir, newDir, dryRun) {
|
|
|
12493
12493
|
return depsChanged;
|
|
12494
12494
|
}
|
|
12495
12495
|
|
|
12496
|
-
// src/
|
|
12496
|
+
// src/shop.ts
|
|
12497
12497
|
function apiError2(status, json, appUrl) {
|
|
12498
12498
|
if (status === 402) {
|
|
12499
12499
|
return new Error(`${json.error ?? "Upgrade required"}
|
|
12500
|
-
` + `
|
|
12500
|
+
` + ` Shop hosting is a paid feature — upgrade the workspace in ${appUrl}`);
|
|
12501
12501
|
}
|
|
12502
12502
|
if (json.code === "NO_CONNECTION") {
|
|
12503
12503
|
return new Error(`${json.error}
|
|
@@ -12560,10 +12560,10 @@ async function pollUntilReady(auth, id) {
|
|
|
12560
12560
|
}
|
|
12561
12561
|
throw new Error("Provisioning timed out after 10 minutes — check the Temporal UI.");
|
|
12562
12562
|
}
|
|
12563
|
-
async function
|
|
12563
|
+
async function shopCreate(dir2, opts) {
|
|
12564
12564
|
const auth = requireActive();
|
|
12565
12565
|
const slug = basename2(resolve4(dir2)).toLowerCase().replaceAll(/[^a-z0-9-]+/g, "-").replaceAll(/^-+|-+$/g, "") || "site";
|
|
12566
|
-
console.log(`Provisioning
|
|
12566
|
+
console.log(`Provisioning shop "${slug}" (workspace "${auth.workspaceName}")`);
|
|
12567
12567
|
const created = await request(auth, "POST", "/api/sites", {
|
|
12568
12568
|
slug,
|
|
12569
12569
|
theme: opts.theme ?? "nextjs",
|
|
@@ -12584,11 +12584,13 @@ async function siteCreate(dir2, opts) {
|
|
|
12584
12584
|
git: opts.git
|
|
12585
12585
|
});
|
|
12586
12586
|
writeFileSync6(join5(resolve4(dir2), ".zalify", "site.json"), JSON.stringify({ id: siteId, slug: view.slug, domain: view.domain, repo: view.githubRepo }, null, 2) + `
|
|
12587
|
+
`);
|
|
12588
|
+
writeFileSync6(join5(resolve4(dir2), "theme", "pixel.json"), JSON.stringify({ workspaceId: auth.workspaceId }, null, 2) + `
|
|
12587
12589
|
`);
|
|
12588
12590
|
if (opts.git !== false && view.githubRepo) {
|
|
12589
12591
|
const { token, repo } = await request(auth, "POST", `/api/sites/${siteId}/push-token`, {});
|
|
12590
12592
|
const run = (args) => spawnSync3("git", args, { cwd: resolve4(dir2), stdio: "ignore" });
|
|
12591
|
-
run(["add", ".zalify/site.json"]);
|
|
12593
|
+
run(["add", ".zalify/site.json", "theme/pixel.json"]);
|
|
12592
12594
|
run(["commit", "-m", "Link site record", "--no-verify"]);
|
|
12593
12595
|
run(["remote", "add", "origin", `https://github.com/${repo}.git`]);
|
|
12594
12596
|
const push = spawnSync3("git", ["push", `https://x-access-token:${token}@github.com/${repo}.git`, "main"], { cwd: resolve4(dir2), stdio: "inherit" });
|
|
@@ -12619,7 +12621,7 @@ Live: https://${view.domain}`);
|
|
|
12619
12621
|
Next steps:
|
|
12620
12622
|
` + ` - author your theme in ${dir2}/theme/ (see theme/README.md), commit + push
|
|
12621
12623
|
` + ` - zalify brand push <brand-dir> --prune # catalog (auto-refreshes this site)
|
|
12622
|
-
` + ` - zalify
|
|
12624
|
+
` + ` - zalify shop open ${slug} # see it live
|
|
12623
12625
|
` + ` - zalify theme status ${dir2} # drift check anytime`);
|
|
12624
12626
|
}
|
|
12625
12627
|
async function resolveSite(auth, slugOrDir) {
|
|
@@ -12650,18 +12652,18 @@ async function resolveSite(auth, slugOrDir) {
|
|
|
12650
12652
|
const match = sites.find((s) => s.slug === slug);
|
|
12651
12653
|
if (match)
|
|
12652
12654
|
return match;
|
|
12653
|
-
throw new Error(`No
|
|
12654
|
-
` + `
|
|
12655
|
+
throw new Error(`No shop "${slug}" in workspace "${auth.workspaceName}".
|
|
12656
|
+
` + ` Shops here: ${sites.map((s) => s.slug).join(", ") || "(none)"}`);
|
|
12655
12657
|
}
|
|
12656
12658
|
if (sites.length === 1)
|
|
12657
12659
|
return sites[0];
|
|
12658
|
-
throw new Error(sites.length === 0 ? `No
|
|
12660
|
+
throw new Error(sites.length === 0 ? `No shops in workspace "${auth.workspaceName}" — create one with \`zalify shop create <dir>\`.` : `Multiple shops in this workspace — name one: ${sites.map((s) => s.slug).join(", ")}`);
|
|
12659
12661
|
}
|
|
12660
|
-
async function
|
|
12662
|
+
async function shopList() {
|
|
12661
12663
|
const auth = requireActive();
|
|
12662
12664
|
const sites = await listSites(auth);
|
|
12663
12665
|
if (!sites.length) {
|
|
12664
|
-
console.log(`No
|
|
12666
|
+
console.log(`No shops in workspace "${auth.workspaceName}".`);
|
|
12665
12667
|
return;
|
|
12666
12668
|
}
|
|
12667
12669
|
for (const s of sites) {
|
|
@@ -12669,23 +12671,34 @@ async function siteList() {
|
|
|
12669
12671
|
console.log(`${s.status === "READY" ? "✓" : s.status === "FAILED" ? "✗" : "…"} ${s.slug} ${url} (${s.status.toLowerCase()}${s.githubRepo ? `, ${s.githubRepo}` : ""})`);
|
|
12670
12672
|
}
|
|
12671
12673
|
}
|
|
12672
|
-
async function
|
|
12674
|
+
async function shopRefresh(slugOrDir) {
|
|
12673
12675
|
const auth = requireActive();
|
|
12674
12676
|
const site = await resolveSite(auth, slugOrDir);
|
|
12675
12677
|
await request(auth, "POST", `/api/sites/${site.id}/revalidate`, {});
|
|
12676
12678
|
console.log(`✓ refreshed https://${site.domain}`);
|
|
12677
12679
|
}
|
|
12678
|
-
async function
|
|
12680
|
+
async function shopOpen(slugOrDir) {
|
|
12679
12681
|
const auth = requireActive();
|
|
12680
12682
|
const site = await resolveSite(auth, slugOrDir);
|
|
12681
12683
|
if (!site.domain)
|
|
12682
|
-
throw new Error(`
|
|
12684
|
+
throw new Error(`Shop "${site.slug}" has no domain yet.`);
|
|
12683
12685
|
const url = `https://${site.domain}`;
|
|
12684
12686
|
const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
12685
12687
|
spawn3(opener, [url], { detached: true, stdio: "ignore" }).unref();
|
|
12686
12688
|
console.log(url);
|
|
12687
12689
|
}
|
|
12688
|
-
async function
|
|
12690
|
+
async function shopDomainSync(slugOrDir) {
|
|
12691
|
+
const auth = requireActive();
|
|
12692
|
+
const site = await resolveSite(auth, slugOrDir);
|
|
12693
|
+
const before = site.domain;
|
|
12694
|
+
const result = await request(auth, "POST", `/api/sites/${site.id}/domains`, {});
|
|
12695
|
+
if (!result.changed) {
|
|
12696
|
+
console.log(`Already in sync: https://${result.site.domain}`);
|
|
12697
|
+
return;
|
|
12698
|
+
}
|
|
12699
|
+
console.log(`✓ ${site.slug}: https://${before} → https://${result.site.domain} (old domain 308s)`);
|
|
12700
|
+
}
|
|
12701
|
+
async function maybeRefreshShops(auth, brandDir, siteSlugOverride) {
|
|
12689
12702
|
try {
|
|
12690
12703
|
let slug = siteSlugOverride ?? null;
|
|
12691
12704
|
if (!slug) {
|
|
@@ -12699,7 +12712,7 @@ async function maybeRefreshSites(auth, brandDir, siteSlugOverride) {
|
|
|
12699
12712
|
const sites = (await listSites(auth)).filter((s) => s.slug === slug && s.status === "READY");
|
|
12700
12713
|
for (const site of sites) {
|
|
12701
12714
|
await request(auth, "POST", `/api/sites/${site.id}/revalidate`, {});
|
|
12702
|
-
console.log(`✓
|
|
12715
|
+
console.log(`✓ shop refreshed (https://${site.domain})`);
|
|
12703
12716
|
}
|
|
12704
12717
|
} catch {}
|
|
12705
12718
|
}
|
|
@@ -12979,7 +12992,7 @@ async function shopifyImport(storeDir, options = {}) {
|
|
|
12979
12992
|
console.warn(` ! could not publish to Online Store (write_publications scope missing?): ${e instanceof Error ? e.message : String(e)}`);
|
|
12980
12993
|
}
|
|
12981
12994
|
console.log("Done.");
|
|
12982
|
-
await
|
|
12995
|
+
await maybeRefreshShops(auth, dir2, options.site);
|
|
12983
12996
|
}
|
|
12984
12997
|
async function shopifyUploadImages(storeDir, options = {}) {
|
|
12985
12998
|
const auth = requireActive();
|
|
@@ -13059,7 +13072,7 @@ async function shopifyUploadImages(storeDir, options = {}) {
|
|
|
13059
13072
|
console.log(` ✓ ${entry.file}`);
|
|
13060
13073
|
}
|
|
13061
13074
|
console.log("Done.");
|
|
13062
|
-
await
|
|
13075
|
+
await maybeRefreshShops(auth, dir2, options.site);
|
|
13063
13076
|
}
|
|
13064
13077
|
|
|
13065
13078
|
// src/brand.ts
|
|
@@ -13153,7 +13166,7 @@ alone. Validate anytime with \`zalify brand validate\` (defaults to cwd).
|
|
|
13153
13166
|
zalify brand validate # lint this folder (cwd)
|
|
13154
13167
|
# create the Shopify dev store + Zalify workspace, then:
|
|
13155
13168
|
zalify workspace set <workspace-slug>
|
|
13156
|
-
zalify
|
|
13169
|
+
zalify shop create <slug> # hosted shop: repo + deploy + domain + token
|
|
13157
13170
|
zalify brand push --prune # catalog → your Shopify store
|
|
13158
13171
|
zalify brand images generate # create the manifest's shots
|
|
13159
13172
|
zalify brand images attach # attach them to the products
|
|
@@ -13588,12 +13601,12 @@ try {
|
|
|
13588
13601
|
});
|
|
13589
13602
|
} catch {}
|
|
13590
13603
|
var program2 = new Command;
|
|
13591
|
-
program2.name("zalify").description("Zalify CLI — author a brand, launch its
|
|
13604
|
+
program2.name("zalify").description("Zalify CLI — author a brand, launch its shop, keep the theme current").version(pkg.version, "-v, --version", "output the current version");
|
|
13592
13605
|
program2.addHelpText("after", `
|
|
13593
13606
|
The golden path (new brand, start to live):
|
|
13594
13607
|
1. zalify brand init stores/acme author the data (no login needed)
|
|
13595
13608
|
2. zalify login && zalify workspace set <workspace>
|
|
13596
|
-
3. zalify
|
|
13609
|
+
3. zalify shop create acme live at acme.z1.shop in ~4 minutes
|
|
13597
13610
|
4. cd stores/acme && zalify brand push --prune
|
|
13598
13611
|
5. zalify brand images generate && zalify brand images attach
|
|
13599
13612
|
6. zalify theme status | upgrade stay current, keep your edits
|
|
@@ -13620,15 +13633,15 @@ brand.command("init [dir]").description("Scaffold a brand folder (catalog, voice
|
|
|
13620
13633
|
brand.command("validate [dir]").description("Lint the brand folder against the authoring rules").action((dir2) => {
|
|
13621
13634
|
brandValidate(dir2);
|
|
13622
13635
|
});
|
|
13623
|
-
brand.command("push [dir]").description("Push catalog.json to your connected Shopify store (products, smart collections, publish; idempotent)").option("--prune", "delete store products (by catalog vendor) absent from catalog.json").option("--
|
|
13624
|
-
await shopifyImport(dir2 ?? ".", options);
|
|
13636
|
+
brand.command("push [dir]").description("Push catalog.json to your connected Shopify store (products, smart collections, publish; idempotent)").option("--prune", "delete store products (by catalog vendor) absent from catalog.json").option("--shop <slug>", "refresh only this shop afterwards (default: every shop matching the brand)").option("--site <slug>", "(old spelling of --shop)", undefined).action(async (dir2, options) => {
|
|
13637
|
+
await shopifyImport(dir2 ?? ".", { prune: options.prune, site: options.shop ?? options.site });
|
|
13625
13638
|
});
|
|
13626
13639
|
var brandImages = brand.command("images").description("The brand's imagery pipeline: generate → attach → push/pull masters");
|
|
13627
13640
|
brandImages.command("generate [dir]").description("Generate the manifest's missing images on Zalify infrastructure (resumable)").action(async (dir2) => {
|
|
13628
13641
|
await imagesGenerate(dir2 ?? ".");
|
|
13629
13642
|
});
|
|
13630
|
-
brandImages.command("attach [dir]").description("Attach generated images to their Shopify products per the manifest (skips already-attached)").option("--
|
|
13631
|
-
await shopifyUploadImages(dir2 ?? ".", options);
|
|
13643
|
+
brandImages.command("attach [dir]").description("Attach generated images to their Shopify products per the manifest (skips already-attached)").option("--shop <slug>", "refresh only this shop afterwards").option("--site <slug>", "(old spelling of --shop)", undefined).action(async (dir2, options) => {
|
|
13644
|
+
await shopifyUploadImages(dir2 ?? ".", { site: options.shop ?? options.site });
|
|
13632
13645
|
});
|
|
13633
13646
|
brandImages.command("push [dir]").description("Upload image masters to the Zalify asset library (sha256 dedup, writes assets.json)").action(async (dir2) => {
|
|
13634
13647
|
await assetsPush(dir2 ?? ".");
|
|
@@ -13636,18 +13649,21 @@ brandImages.command("push [dir]").description("Upload image masters to the Zalif
|
|
|
13636
13649
|
brandImages.command("pull [dir]").description("Download masters listed in images/assets.json (fresh-clone restore)").action(async (dir2) => {
|
|
13637
13650
|
await assetsPull(dir2 ?? ".");
|
|
13638
13651
|
});
|
|
13639
|
-
var
|
|
13640
|
-
|
|
13641
|
-
await
|
|
13652
|
+
var shop = program2.command("shop").description("Hosted shops at <slug>.z1.shop — Zalify provisions the repo, deployment, and domain");
|
|
13653
|
+
shop.command("create <dir>").description("One-command launch: provision repo + deployment + domain + storefront token, scaffold locally, push, go live").option("-t, --theme <name>", "theme", "nextjs").option("--editor", "include the Zalify canvas-editor (z1) wiring").option("--to <version>", "theme version (default: latest)").option("--no-install", "skip dependency install").option("--no-git", "skip git init/push").action(async (dir2, options) => {
|
|
13654
|
+
await shopCreate(dir2, options);
|
|
13642
13655
|
});
|
|
13643
|
-
|
|
13644
|
-
await
|
|
13656
|
+
shop.command("list", { isDefault: true }).description("List the workspace's hosted shops").action(async () => {
|
|
13657
|
+
await shopList();
|
|
13645
13658
|
});
|
|
13646
|
-
|
|
13647
|
-
await
|
|
13659
|
+
shop.command("refresh [slug-or-dir]").description("Refresh the live shop's data cache (defaults to the shop linked to cwd)").action(async (slugOrDir) => {
|
|
13660
|
+
await shopRefresh(slugOrDir);
|
|
13648
13661
|
});
|
|
13649
|
-
|
|
13650
|
-
await
|
|
13662
|
+
shop.command("open [slug-or-dir]").description("Open the live shop in your browser (defaults to the shop linked to cwd)").action(async (slugOrDir) => {
|
|
13663
|
+
await shopOpen(slugOrDir);
|
|
13664
|
+
});
|
|
13665
|
+
shop.command("domain-sync [slug-or-dir]").description("Re-point the shop at the current root domain (the old domain 308-redirects)").action(async (slugOrDir) => {
|
|
13666
|
+
await shopDomainSync(slugOrDir);
|
|
13651
13667
|
});
|
|
13652
13668
|
var theme = program2.command("theme").description("Theme source code — scaffold a copy and upgrade it without losing your edits");
|
|
13653
13669
|
theme.command("create <dir>").description("Scaffold only — no Zalify hosting (self-host path; `site create` is the fully-hosted launch)").option("-t, --template <name>", "liquid | hydrogen | nextjs", "nextjs").option("--editor", "include the Zalify canvas-editor (z1) wiring").option("--store-domain <domain>", "your-store.myshopify.com (default: mock.shop demo data)").option("--storefront-token <token>", "public Storefront API access token").option("--to <version>", "theme version (default: latest)").option("--no-install", "skip dependency install").option("--no-git", "skip git init + initial commit").option("--tarball <path>", "use a local @zalify/theme-templates .tgz instead of npm").action(async (dir2, options) => {
|
|
@@ -13680,50 +13696,22 @@ A new version (${update.latest}) is available. Run "zalify self-update" to updat
|
|
|
13680
13696
|
}
|
|
13681
13697
|
} catch {}
|
|
13682
13698
|
});
|
|
13683
|
-
var
|
|
13684
|
-
|
|
13685
|
-
moved("
|
|
13686
|
-
|
|
13687
|
-
});
|
|
13688
|
-
legacyStore.command("validate <dir>").action((dir2) => {
|
|
13689
|
-
moved("brand validate");
|
|
13690
|
-
brandValidate(dir2);
|
|
13691
|
-
});
|
|
13692
|
-
var legacyShopify = program2.command("shopify", { hidden: true });
|
|
13693
|
-
legacyShopify.command("import <store-dir>").option("--prune").action(async (storeDir, options) => {
|
|
13694
|
-
moved("brand push");
|
|
13695
|
-
await shopifyImport(storeDir, options);
|
|
13696
|
-
});
|
|
13697
|
-
legacyShopify.command("upload-images <store-dir>").action(async (storeDir) => {
|
|
13698
|
-
moved("brand images attach");
|
|
13699
|
-
await shopifyUploadImages(storeDir);
|
|
13700
|
-
});
|
|
13701
|
-
var legacyImages = program2.command("images", { hidden: true });
|
|
13702
|
-
legacyImages.command("generate <store-dir>").action(async (storeDir) => {
|
|
13703
|
-
moved("brand images generate");
|
|
13704
|
-
await imagesGenerate(storeDir);
|
|
13705
|
-
});
|
|
13706
|
-
var legacyAssets = program2.command("assets", { hidden: true });
|
|
13707
|
-
legacyAssets.command("push <store-dir>").action(async (storeDir) => {
|
|
13708
|
-
moved("brand images push");
|
|
13709
|
-
await assetsPush(storeDir);
|
|
13710
|
-
});
|
|
13711
|
-
legacyAssets.command("pull <store-dir>").action(async (storeDir) => {
|
|
13712
|
-
moved("brand images pull");
|
|
13713
|
-
await assetsPull(storeDir);
|
|
13699
|
+
var legacySite = program2.command("site", { hidden: true });
|
|
13700
|
+
legacySite.command("create <dir>").option("-t, --theme <name>", "", "nextjs").option("--editor").option("--to <version>").option("--no-install").option("--no-git").action(async (dir2, options) => {
|
|
13701
|
+
moved("shop create");
|
|
13702
|
+
await shopCreate(dir2, options);
|
|
13714
13703
|
});
|
|
13715
|
-
|
|
13716
|
-
|
|
13717
|
-
|
|
13718
|
-
await siteCreate(dir2, options);
|
|
13704
|
+
legacySite.command("list", { isDefault: true }).action(async () => {
|
|
13705
|
+
moved("shop list");
|
|
13706
|
+
await shopList();
|
|
13719
13707
|
});
|
|
13720
|
-
|
|
13721
|
-
moved("
|
|
13722
|
-
await
|
|
13708
|
+
legacySite.command("refresh [slug-or-dir]").action(async (slugOrDir) => {
|
|
13709
|
+
moved("shop refresh");
|
|
13710
|
+
await shopRefresh(slugOrDir);
|
|
13723
13711
|
});
|
|
13724
|
-
|
|
13725
|
-
moved("
|
|
13726
|
-
await
|
|
13712
|
+
legacySite.command("open [slug-or-dir]").action(async (slugOrDir) => {
|
|
13713
|
+
moved("shop open");
|
|
13714
|
+
await shopOpen(slugOrDir);
|
|
13727
13715
|
});
|
|
13728
13716
|
program2.parseAsync().catch((err) => {
|
|
13729
13717
|
console.error(`Error: ${err instanceof Error ? err.message : String(err)}`);
|