@zalify/cli 0.25.0 → 0.26.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 (3) hide show
  1. package/README.md +8 -0
  2. package/dist/cli.js +98 -51
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -58,6 +58,14 @@ API keys — list and revoke them in **Settings → Developer**. One login
58
58
  covers every workspace; `zalify workspace set` switches between them
59
59
  locally, no re-login.
60
60
 
61
+ **Inside a brand checkout, the folder decides.** `ads` commands read the
62
+ checkout's own workspace (its `.zalify/brand-repo.json` stamp, or
63
+ `identity.yaml` for folders AdsBuddy downloaded) and act as that
64
+ workspace — no `workspace set` first, and no risk of pulling one
65
+ brand's campaigns into another's folder. `workspace set` still matters
66
+ for commands run outside any checkout, and for `ads create`, which
67
+ provisions a NEW brand into the workspace you chose.
68
+
61
69
  ## Command reference
62
70
 
63
71
  ### Auth & workspace
package/dist/cli.js CHANGED
@@ -18259,7 +18259,7 @@ function updateNotifier(options) {
18259
18259
 
18260
18260
  // src/cli.ts
18261
18261
  import { createRequire as createRequire2 } from "node:module";
18262
- import { dirname as dirname3, join as join14 } from "node:path";
18262
+ import { dirname as dirname4, join as join14 } from "node:path";
18263
18263
  import { fileURLToPath as fileURLToPath3 } from "node:url";
18264
18264
 
18265
18265
  // src/auth.ts
@@ -18271,7 +18271,7 @@ import { spawn as spawn2 } from "node:child_process";
18271
18271
  // src/config.ts
18272
18272
  import { readFileSync, writeFileSync as writeFileSync2, mkdirSync, rmSync, existsSync } from "node:fs";
18273
18273
  import { homedir } from "node:os";
18274
- import { join } from "node:path";
18274
+ import { dirname, join, resolve } from "node:path";
18275
18275
  var dir = join(homedir(), ".zalify");
18276
18276
  var file = join(dir, "config.json");
18277
18277
  function migrate(raw) {
@@ -18339,16 +18339,60 @@ function enforceWorkspaceLink(root, auth) {
18339
18339
  return;
18340
18340
  }
18341
18341
  if (ws.id !== auth.workspaceId) {
18342
- throw new Error(`This checkout belongs to workspace "${ws.name ?? ws.slug ?? ws.id}" ` + `but the active workspace is "${auth.workspaceName}" (${auth.workspaceSlug}).
18343
- ` + `Run \`zalify workspace set ${ws.slug ?? ws.id}\` first.`);
18342
+ throw new Error(`This checkout belongs to workspace "${ws.name ?? ws.slug ?? ws.id}" ` + `but the command is running as "${auth.workspaceName}" (${auth.workspaceSlug}).`);
18344
18343
  }
18345
18344
  }
18346
- function requireActive() {
18345
+ function checkoutWorkspace(startDir) {
18346
+ let cur = resolve(startDir ?? process.cwd());
18347
+ for (let up = 0;up < 12; up += 1) {
18348
+ const stamp = join(cur, ".zalify", "brand-repo.json");
18349
+ if (existsSync(stamp)) {
18350
+ try {
18351
+ const link = JSON.parse(readFileSync(stamp, "utf8"));
18352
+ const ws = link.workspace;
18353
+ if (ws?.id) {
18354
+ return {
18355
+ root: cur,
18356
+ id: ws.id,
18357
+ name: ws.name ?? ws.slug ?? ws.id,
18358
+ slug: ws.slug ?? ws.id
18359
+ };
18360
+ }
18361
+ } catch {}
18362
+ }
18363
+ const identity = join(cur, "identity.yaml");
18364
+ if (existsSync(identity)) {
18365
+ const text = readFileSync(identity, "utf8");
18366
+ const id = /^workspace_id:\s*(\S+)\s*$/m.exec(text)?.[1];
18367
+ const slug = /^brand_slug:\s*(\S+)\s*$/m.exec(text)?.[1];
18368
+ if (id)
18369
+ return { root: cur, id, name: slug ?? id, slug: slug ?? id };
18370
+ }
18371
+ const parent = dirname(cur);
18372
+ if (parent === cur)
18373
+ break;
18374
+ cur = parent;
18375
+ }
18376
+ return null;
18377
+ }
18378
+ function requireActive(opts) {
18347
18379
  const config = readConfig();
18348
18380
  if (!config) {
18349
18381
  throw new Error("Not logged in. Run `zalify login` first.");
18350
18382
  }
18383
+ const here = opts?.global ? null : checkoutWorkspace();
18351
18384
  if (config.version === 3) {
18385
+ if (here) {
18386
+ const known = config.workspacesCache?.find((w) => w.id === here.id) ?? null;
18387
+ return {
18388
+ appUrl: config.appUrl,
18389
+ key: config.userKey,
18390
+ workspaceId: here.id,
18391
+ workspaceName: known?.name ?? here.name,
18392
+ workspaceSlug: known?.slug ?? here.slug,
18393
+ config
18394
+ };
18395
+ }
18352
18396
  if (!config.active) {
18353
18397
  throw new Error("No active workspace. Run `zalify workspace list` then `zalify workspace set <slug>`.");
18354
18398
  }
@@ -18365,7 +18409,10 @@ function requireActive() {
18365
18409
  if (ids.length === 0) {
18366
18410
  throw new Error("Not logged in. Run `zalify login` first.");
18367
18411
  }
18368
- const workspaceId = config.activeWorkspaceId && config.workspaces[config.activeWorkspaceId] ? config.activeWorkspaceId : ids[0];
18412
+ if (here && !config.workspaces[here.id]) {
18413
+ throw new Error(`This folder belongs to workspace "${here.slug}" but your login has no key for it. ` + "Run `zalify login` again to refresh your credentials.");
18414
+ }
18415
+ const workspaceId = here?.id ?? (config.activeWorkspaceId && config.workspaces[config.activeWorkspaceId] ? config.activeWorkspaceId : ids[0]);
18369
18416
  const entry = config.workspaces[workspaceId];
18370
18417
  return {
18371
18418
  appUrl: config.appUrl,
@@ -18610,10 +18657,10 @@ async function whoami() {
18610
18657
  // src/assets.ts
18611
18658
  init_hash();
18612
18659
  import { readFileSync as readFileSync2, writeFileSync as writeFileSync3, existsSync as existsSync2, readdirSync } from "node:fs";
18613
- import { join as join2, resolve } from "node:path";
18660
+ import { join as join2, resolve as resolve2 } from "node:path";
18614
18661
  var BATCH = 10;
18615
18662
  function imagesDirFor(storeDir) {
18616
- const dir2 = join2(resolve(storeDir), "images");
18663
+ const dir2 = join2(resolve2(storeDir), "images");
18617
18664
  if (!existsSync2(dir2))
18618
18665
  throw new Error(`No images/ directory in ${storeDir}`);
18619
18666
  return dir2;
@@ -18947,7 +18994,7 @@ async function workspaceSet(slugOrId) {
18947
18994
  // src/images.ts
18948
18995
  init_hash();
18949
18996
  import { readFileSync as readFileSync3, writeFileSync as writeFileSync4, existsSync as existsSync4, rmSync as rmSync2 } from "node:fs";
18950
- import { join as join4, resolve as resolve2 } from "node:path";
18997
+ import { join as join4, resolve as resolve3 } from "node:path";
18951
18998
  var MAX_JOBS_PER_REQUEST = 40;
18952
18999
  var POLL_INTERVAL_MS = 5000;
18953
19000
  var POLL_TIMEOUT_MS = 30 * 60 * 1000;
@@ -19112,7 +19159,7 @@ async function streamingGenerate(auth, manifest, missing, imagesDir, indexPath,
19112
19159
  }
19113
19160
  async function imagesGenerate(storeDir) {
19114
19161
  const auth = requireActive();
19115
- const imagesDir = join4(resolve2(storeDir), "images");
19162
+ const imagesDir = join4(resolve3(storeDir), "images");
19116
19163
  const manifestPath = join4(imagesDir, "manifest.json");
19117
19164
  if (!existsSync4(manifestPath)) {
19118
19165
  throw new Error(`No images/manifest.json in ${storeDir}`);
@@ -19155,12 +19202,12 @@ async function imagesGenerate(storeDir) {
19155
19202
 
19156
19203
  // src/shopify.ts
19157
19204
  import { readFileSync as readFileSync6, existsSync as existsSync7 } from "node:fs";
19158
- import { basename as basename3, join as join7, resolve as resolve5 } from "node:path";
19205
+ import { basename as basename3, join as join7, resolve as resolve6 } from "node:path";
19159
19206
 
19160
19207
  // src/shop.ts
19161
19208
  import { spawn as spawn3, spawnSync as spawnSync3 } from "node:child_process";
19162
19209
  import { existsSync as existsSync6, readFileSync as readFileSync5, writeFileSync as writeFileSync6 } from "node:fs";
19163
- import { basename as basename2, join as join6, resolve as resolve4 } from "node:path";
19210
+ import { basename as basename2, join as join6, resolve as resolve5 } from "node:path";
19164
19211
 
19165
19212
  // src/theme.ts
19166
19213
  init_hash();
@@ -19180,7 +19227,7 @@ import {
19180
19227
  writeFileSync as writeFileSync5
19181
19228
  } from "node:fs";
19182
19229
  import { tmpdir } from "node:os";
19183
- import { basename, dirname, join as join5, resolve as resolve3 } from "node:path";
19230
+ import { basename, dirname as dirname2, join as join5, resolve as resolve4 } from "node:path";
19184
19231
  var TEMPLATES_PKG = "@zalify/theme-templates";
19185
19232
  var REGISTRY = "https://registry.npmjs.org";
19186
19233
  var MANIFEST_PATH = ".zalify/theme.json";
@@ -19212,7 +19259,7 @@ async function downloadTarball(url) {
19212
19259
  }
19213
19260
  function extractTarball(file2) {
19214
19261
  const dir2 = mkdtempSync(join5(tmpdir(), "zalify-theme-x-"));
19215
- const result = spawnSync2("tar", ["-xzf", resolve3(file2), "-C", dir2], {
19262
+ const result = spawnSync2("tar", ["-xzf", resolve4(file2), "-C", dir2], {
19216
19263
  encoding: "utf8"
19217
19264
  });
19218
19265
  if (result.error || result.status !== 0) {
@@ -19280,7 +19327,7 @@ function writeJson(path9, value) {
19280
19327
  `);
19281
19328
  }
19282
19329
  async function themeCreate(dir2, opts) {
19283
- const targetDir = resolve3(dir2);
19330
+ const targetDir = resolve4(dir2);
19284
19331
  if (existsSync5(targetDir) && readdirSync2(targetDir).length > 0) {
19285
19332
  throw new Error(`${dir2} already exists and is not empty`);
19286
19333
  }
@@ -19364,7 +19411,7 @@ Runs on mock.shop demo data out of the box — edit .env to connect your store.`
19364
19411
  console.log("Your theme customizations live in theme/ — see theme/README.md.");
19365
19412
  }
19366
19413
  function themeStatus(dir2 = ".") {
19367
- const projectDir = resolve3(dir2);
19414
+ const projectDir = resolve4(dir2);
19368
19415
  const manifest = readProjectManifest(projectDir);
19369
19416
  console.log(`${manifest.template} theme, ${TEMPLATES_PKG}@${manifest.version}` + (manifest.variant === "editor" ? " (editor variant)" : ""));
19370
19417
  let clean = 0;
@@ -19392,7 +19439,7 @@ function looksBinary(...buffers) {
19392
19439
  return buffers.some((b) => b.subarray(0, 8000).includes(0));
19393
19440
  }
19394
19441
  async function themeUpgrade(dir2 = ".", opts = {}) {
19395
- const projectDir = resolve3(dir2);
19442
+ const projectDir = resolve4(dir2);
19396
19443
  const local = readProjectManifest(projectDir);
19397
19444
  const variant = local.variant ?? "default";
19398
19445
  const target = await acquireTemplatePkg(opts.tarball, opts.to);
@@ -19432,7 +19479,7 @@ async function themeUpgrade(dir2 = ".", opts = {}) {
19432
19479
  const write = (bytes) => {
19433
19480
  if (opts.dryRun)
19434
19481
  return;
19435
- mkdirSync2(dirname(localPath), { recursive: true });
19482
+ mkdirSync2(dirname2(localPath), { recursive: true });
19436
19483
  writeFileSync5(localPath, bytes);
19437
19484
  };
19438
19485
  if (oldHash && newHash) {
@@ -19656,7 +19703,7 @@ async function pollUntilReady(auth, id) {
19656
19703
  }
19657
19704
  async function shopCreate(dir2, opts) {
19658
19705
  const auth = requireActive();
19659
- const slug = basename2(resolve4(dir2)).toLowerCase().replaceAll(/[^a-z0-9-]+/g, "-").replaceAll(/^-+|-+$/g, "") || "site";
19706
+ const slug = basename2(resolve5(dir2)).toLowerCase().replaceAll(/[^a-z0-9-]+/g, "-").replaceAll(/^-+|-+$/g, "") || "site";
19660
19707
  console.log(`Provisioning shop "${slug}" (workspace "${auth.workspaceName}")`);
19661
19708
  const created = await request(auth, "POST", "/api/sites", {
19662
19709
  slug,
@@ -19677,17 +19724,17 @@ async function shopCreate(dir2, opts) {
19677
19724
  install: opts.install,
19678
19725
  git: opts.git
19679
19726
  });
19680
- writeFileSync6(join6(resolve4(dir2), ".zalify", "site.json"), JSON.stringify({ id: siteId, slug: view.slug, domain: view.domain, repo: view.githubRepo }, null, 2) + `
19727
+ writeFileSync6(join6(resolve5(dir2), ".zalify", "site.json"), JSON.stringify({ id: siteId, slug: view.slug, domain: view.domain, repo: view.githubRepo }, null, 2) + `
19681
19728
  `);
19682
- writeFileSync6(join6(resolve4(dir2), "theme", "pixel.json"), JSON.stringify({ workspaceId: auth.workspaceId }, null, 2) + `
19729
+ writeFileSync6(join6(resolve5(dir2), "theme", "pixel.json"), JSON.stringify({ workspaceId: auth.workspaceId }, null, 2) + `
19683
19730
  `);
19684
19731
  if (opts.git !== false && view.githubRepo) {
19685
19732
  const { token, repo } = await request(auth, "POST", `/api/sites/${siteId}/push-token`, {});
19686
- const run = (args) => spawnSync3("git", args, { cwd: resolve4(dir2), stdio: "ignore" });
19733
+ const run = (args) => spawnSync3("git", args, { cwd: resolve5(dir2), stdio: "ignore" });
19687
19734
  run(["add", ".zalify/site.json", "theme/pixel.json"]);
19688
19735
  run(["commit", "-m", "Link site record", "--no-verify"]);
19689
19736
  run(["remote", "add", "origin", `https://github.com/${repo}.git`]);
19690
- const push = spawnSync3("git", ["push", `https://x-access-token:${token}@github.com/${repo}.git`, "main"], { cwd: resolve4(dir2), stdio: "inherit" });
19737
+ const push = spawnSync3("git", ["push", `https://x-access-token:${token}@github.com/${repo}.git`, "main"], { cwd: resolve5(dir2), stdio: "inherit" });
19691
19738
  if (push.status !== 0) {
19692
19739
  throw new Error(`git push to ${repo} failed — resolve and push manually.`);
19693
19740
  }
@@ -19735,8 +19782,8 @@ async function resolveSite(auth, slugOrDir) {
19735
19782
  return null;
19736
19783
  };
19737
19784
  let slug = null;
19738
- if (slugOrDir && existsSync6(resolve4(slugOrDir)))
19739
- slug = fromDir(resolve4(slugOrDir));
19785
+ if (slugOrDir && existsSync6(resolve5(slugOrDir)))
19786
+ slug = fromDir(resolve5(slugOrDir));
19740
19787
  if (!slug && slugOrDir)
19741
19788
  slug = slugOrDir;
19742
19789
  if (!slug)
@@ -19796,7 +19843,7 @@ async function maybeRefreshShops(auth, brandDir, siteSlugOverride) {
19796
19843
  try {
19797
19844
  let slug = siteSlugOverride ?? null;
19798
19845
  if (!slug) {
19799
- const storeJson = join6(resolve4(brandDir), "store.json");
19846
+ const storeJson = join6(resolve5(brandDir), "store.json");
19800
19847
  if (existsSync6(storeJson)) {
19801
19848
  slug = JSON.parse(readFileSync5(storeJson, "utf8")).slug ?? null;
19802
19849
  }
@@ -19881,7 +19928,7 @@ async function findProductId(auth, handle) {
19881
19928
  }
19882
19929
  async function shopifyImport(storeDir, options = {}) {
19883
19930
  const auth = requireActive();
19884
- const dir2 = resolve5(storeDir);
19931
+ const dir2 = resolve6(storeDir);
19885
19932
  const catalog = readJson(join7(dir2, "catalog.json"), "catalog.json");
19886
19933
  const { locations } = await gql(auth, `{ locations(first: 1) { nodes { id name } } }`);
19887
19934
  const locationId = locations.nodes[0]?.id;
@@ -20090,7 +20137,7 @@ async function shopifyImport(storeDir, options = {}) {
20090
20137
  }
20091
20138
  async function shopifyUploadImages(storeDir, options = {}) {
20092
20139
  const auth = requireActive();
20093
- const dir2 = resolve5(storeDir);
20140
+ const dir2 = resolve6(storeDir);
20094
20141
  const manifest = readJson(join7(dir2, "images", "manifest.json"), "images/manifest.json");
20095
20142
  console.log(`Uploading images to the Shopify store connected to workspace "${auth.workspaceName}"`);
20096
20143
  for (const entry of manifest.images) {
@@ -20172,7 +20219,7 @@ async function shopifyUploadImages(storeDir, options = {}) {
20172
20219
  // src/ads.ts
20173
20220
  import { spawnSync as spawnSync4 } from "node:child_process";
20174
20221
  import { existsSync as existsSync8, mkdirSync as mkdirSync3, readdirSync as readdirSync3, writeFileSync as writeFileSync7 } from "node:fs";
20175
- import { basename as basename4, join as join8, relative, resolve as resolve6 } from "node:path";
20222
+ import { basename as basename4, join as join8, relative, resolve as resolve7 } from "node:path";
20176
20223
  import { createInterface } from "node:readline/promises";
20177
20224
  function apiError3(status, json) {
20178
20225
  if (json.code === "SLUG_TAKEN") {
@@ -20224,7 +20271,7 @@ async function pollUntilReady2(auth, id) {
20224
20271
  throw new Error("Provisioning timed out after 5 minutes — check the Temporal UI.");
20225
20272
  }
20226
20273
  function scaffoldStarter(dir2, slug, workspaceId) {
20227
- const root = resolve6(dir2);
20274
+ const root = resolve7(dir2);
20228
20275
  const write = (rel, content) => {
20229
20276
  const abs = join8(root, rel);
20230
20277
  mkdirSync3(join8(abs, ".."), { recursive: true });
@@ -20277,15 +20324,15 @@ mirrors decisions into \`decisions/\` and daily signal digests into
20277
20324
  `);
20278
20325
  }
20279
20326
  async function adsCreate(dir2) {
20280
- const auth = requireActive();
20281
- const slug = basename4(resolve6(dir2)).toLowerCase().replaceAll(/[^a-z0-9-]+/g, "-").replaceAll(/^-+|-+$/g, "") || "brand";
20327
+ const auth = requireActive({ global: true });
20328
+ const slug = basename4(resolve7(dir2)).toLowerCase().replaceAll(/[^a-z0-9-]+/g, "-").replaceAll(/^-+|-+$/g, "") || "brand";
20282
20329
  console.log(`Provisioning brand instance "${slug}" (workspace "${auth.workspaceName}")`);
20283
20330
  const created = await request2(auth, "POST", "/api/repos", { slug });
20284
20331
  const view = await pollUntilReady2(auth, created.repoId);
20285
20332
  console.log(` ✓ provisioned: ${view.githubRepo}`);
20286
20333
  scaffoldStarter(dir2, slug, auth.workspaceId);
20287
- mkdirSync3(join8(resolve6(dir2), ".zalify"), { recursive: true });
20288
- writeFileSync7(join8(resolve6(dir2), ".zalify", "brand-repo.json"), JSON.stringify({
20334
+ mkdirSync3(join8(resolve7(dir2), ".zalify"), { recursive: true });
20335
+ writeFileSync7(join8(resolve7(dir2), ".zalify", "brand-repo.json"), JSON.stringify({
20289
20336
  id: created.repoId,
20290
20337
  slug: view.slug,
20291
20338
  repo: view.githubRepo,
@@ -20298,12 +20345,12 @@ async function adsCreate(dir2) {
20298
20345
  `);
20299
20346
  if (view.githubRepo) {
20300
20347
  const { token, repo } = await request2(auth, "POST", `/api/repos/${created.repoId}/push-token`, {});
20301
- const run = (args) => spawnSync4("git", args, { cwd: resolve6(dir2), stdio: "ignore" });
20348
+ const run = (args) => spawnSync4("git", args, { cwd: resolve7(dir2), stdio: "ignore" });
20302
20349
  run(["init", "-b", "main"]);
20303
20350
  run(["add", "-A"]);
20304
20351
  run(["commit", "-m", "Scaffold brand instance", "--no-verify"]);
20305
20352
  run(["remote", "add", "origin", `https://github.com/${repo}.git`]);
20306
- const push = spawnSync4("git", ["push", `https://x-access-token:${token}@github.com/${repo}.git`, "main"], { cwd: resolve6(dir2), stdio: "inherit" });
20353
+ const push = spawnSync4("git", ["push", `https://x-access-token:${token}@github.com/${repo}.git`, "main"], { cwd: resolve7(dir2), stdio: "inherit" });
20307
20354
  if (push.status !== 0) {
20308
20355
  throw new Error(`git push to ${repo} failed — resolve and push manually.`);
20309
20356
  }
@@ -20320,7 +20367,7 @@ Next steps:
20320
20367
  }
20321
20368
  var CAMPAIGN_NAME_RE = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
20322
20369
  function campaignParent(account) {
20323
- const cwd = resolve6(".");
20370
+ const cwd = resolve7(".");
20324
20371
  const inCheckout = existsSync8(join8(cwd, ".zalify", "brand-repo.json")) || existsSync8(join8(cwd, "accounts"));
20325
20372
  if (!inCheckout) {
20326
20373
  throw new Error("Not inside a brand-instance checkout — run from the repo `zalify ads create` made.");
@@ -20378,7 +20425,7 @@ ad_sets:
20378
20425
  age: 18-65
20379
20426
  advantage: true
20380
20427
  `);
20381
- console.log(`✓ ${relative(resolve6("."), dir2)}/ is ready`);
20428
+ console.log(`✓ ${relative(resolve7("."), dir2)}/ is ready`);
20382
20429
  console.log(" 1. drag images into creatives/");
20383
20430
  console.log(" 2. fill primary_text and link in campaign.yaml");
20384
20431
  console.log(" 3. `zalify ads sync` when it lands — validate, diff, apply");
@@ -20417,7 +20464,7 @@ import {
20417
20464
  readFileSync as readFileSync8,
20418
20465
  writeFileSync as writeFileSync9
20419
20466
  } from "node:fs";
20420
- import { join as join10, resolve as resolve7 } from "node:path";
20467
+ import { join as join10, resolve as resolve8 } from "node:path";
20421
20468
  import { createInterface as createInterface2 } from "node:readline/promises";
20422
20469
 
20423
20470
  // node_modules/yaml/dist/index.js
@@ -20579,7 +20626,7 @@ async function adsCreativeGenerate(opts) {
20579
20626
 
20580
20627
  // src/ads-diff.ts
20581
20628
  function root() {
20582
- const cwd = resolve7(".");
20629
+ const cwd = resolve8(".");
20583
20630
  if (existsSync10(join10(cwd, ".zalify", "brand-repo.json")) || existsSync10(join10(cwd, "campaigns"))) {
20584
20631
  return cwd;
20585
20632
  }
@@ -20748,10 +20795,10 @@ import {
20748
20795
  readFileSync as readFileSync9,
20749
20796
  writeFileSync as writeFileSync10
20750
20797
  } from "node:fs";
20751
- import { dirname as dirname2, join as join11, resolve as resolve8 } from "node:path";
20798
+ import { dirname as dirname3, join as join11, resolve as resolve9 } from "node:path";
20752
20799
  var sha = (s) => createHash2("sha256").update(s).digest("hex");
20753
20800
  function checkoutRoot() {
20754
- const cwd = resolve8(".");
20801
+ const cwd = resolve9(".");
20755
20802
  if (existsSync11(join11(cwd, ".zalify", "brand-repo.json")) || existsSync11(join11(cwd, "accounts")) || existsSync11(join11(cwd, "campaigns"))) {
20756
20803
  return cwd;
20757
20804
  }
@@ -20823,7 +20870,7 @@ async function adsPull(opts) {
20823
20870
  continue;
20824
20871
  }
20825
20872
  }
20826
- mkdirSync5(dirname2(abs), { recursive: true });
20873
+ mkdirSync5(dirname3(abs), { recursive: true });
20827
20874
  writeFileSync10(abs, f.yaml);
20828
20875
  bindings.pulled[f.path] = nextHash;
20829
20876
  written += 1;
@@ -20837,7 +20884,7 @@ async function adsPull(opts) {
20837
20884
  bindings.nodes[key] = v;
20838
20885
  }
20839
20886
  const bindingsPath = join11(root2, "accounts", ".bindings.json");
20840
- mkdirSync5(dirname2(bindingsPath), { recursive: true });
20887
+ mkdirSync5(dirname3(bindingsPath), { recursive: true });
20841
20888
  writeFileSync10(bindingsPath, `${JSON.stringify(bindings, null, 2)}
20842
20889
  `);
20843
20890
  const exported = new Set(result.files.map((f) => f.path));
@@ -20863,7 +20910,7 @@ Review with git diff; commit when it reads right.`);
20863
20910
  // src/ads-read.ts
20864
20911
  import { spawn as spawn4 } from "node:child_process";
20865
20912
  import { existsSync as existsSync12, readFileSync as readFileSync10 } from "node:fs";
20866
- import { join as join12, resolve as resolve9 } from "node:path";
20913
+ import { join as join12, resolve as resolve10 } from "node:path";
20867
20914
  async function serviceGet(auth, path9) {
20868
20915
  const res = await fetch(`${auth.appUrl}/api/autopilot/${path9}`, {
20869
20916
  headers: {
@@ -20951,7 +20998,7 @@ account changes: not tracked for this platform yet` : `
20951
20998
  account changes: ${a.byPerson} by people, ${a.byMeta} automated`);
20952
20999
  }
20953
21000
  function adsDigest(dir2) {
20954
- const root2 = resolve9(dir2 ?? ".");
21001
+ const root2 = resolve10(dir2 ?? ".");
20955
21002
  const path9 = join12(root2, "signals", "latest.json");
20956
21003
  if (!existsSync12(path9)) {
20957
21004
  throw new Error("signals/latest.json not found — run from a brand-instance checkout " + "(and pull: the service commits a digest daily).");
@@ -20995,7 +21042,7 @@ function adsOpen() {
20995
21042
  }
20996
21043
  async function adsDoctor(dir2) {
20997
21044
  const auth = requireActive();
20998
- const root2 = resolve9(dir2 ?? ".");
21045
+ const root2 = resolve10(dir2 ?? ".");
20999
21046
  let failed = 0;
21000
21047
  const ok = (msg) => console.log(` ✓ ${msg}`);
21001
21048
  const bad = (msg) => {
@@ -21081,7 +21128,7 @@ ${failed} problem${failed > 1 ? "s" : ""}.`);
21081
21128
 
21082
21129
  // src/brand.ts
21083
21130
  import { existsSync as existsSync13, mkdirSync as mkdirSync6, readdirSync as readdirSync6, readFileSync as readFileSync11, writeFileSync as writeFileSync11 } from "node:fs";
21084
- import { basename as basename5, join as join13, resolve as resolve10 } from "node:path";
21131
+ import { basename as basename5, join as join13, resolve as resolve11 } from "node:path";
21085
21132
  var AUTHORING_MD = `# Brand authoring guide
21086
21133
 
21087
21134
  The rules for filling in this folder. An author — human or AI agent —
@@ -21382,7 +21429,7 @@ var MANIFEST_JSON = JSON.stringify({
21382
21429
  }, null, 2) + `
21383
21430
  `;
21384
21431
  function brandInit(dir2 = ".", opts = {}) {
21385
- const target = resolve10(dir2);
21432
+ const target = resolve11(dir2);
21386
21433
  const slug = basename5(target).toLowerCase().replaceAll(/[^a-z0-9-]+/g, "-").replaceAll(/^-+|-+$/g, "");
21387
21434
  if (existsSync13(target) && readdirSync6(target).length > 0) {
21388
21435
  throw new Error(`${dir2} already exists and is not empty`);
@@ -21405,7 +21452,7 @@ Author in this order: brand.md → catalog.json → images/manifest.json` + `
21405
21452
  }
21406
21453
  var MANIFEST_SIZES = new Set(["1024x1024", "1536x1024", "1024x1536"]);
21407
21454
  function brandValidate(dir2 = ".") {
21408
- const target = resolve10(dir2);
21455
+ const target = resolve11(dir2);
21409
21456
  const problems = [];
21410
21457
  const warnings = [];
21411
21458
  const readJson2 = (rel) => {
@@ -21595,7 +21642,7 @@ function brandValidate(dir2 = ".") {
21595
21642
  }
21596
21643
 
21597
21644
  // src/cli.ts
21598
- var __dirname4 = dirname3(fileURLToPath3(import.meta.url));
21645
+ var __dirname4 = dirname4(fileURLToPath3(import.meta.url));
21599
21646
  var require2 = createRequire2(import.meta.url);
21600
21647
  var pkg = require2(join14(__dirname4, "..", "package.json"));
21601
21648
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zalify/cli",
3
- "version": "0.25.0",
3
+ "version": "0.26.0",
4
4
  "description": "Zalify CLI - command-line interface for Zalify",
5
5
  "type": "module",
6
6
  "main": "dist/cli.js",