← Files WixARCHIVED FILE
skills/wix-headless-templates/shared/seed/wix-cli.mjs
2.65 KB · Oct 8, 2026 · 12:02 UTC
// The Wix CLI the seeds call for a site token and for `wix env pull`.
//
// Order: the project's own copy (node_modules/.bin/wix, installed with the template's lock), then
// a `wix` on PATH, then `npx -y @wix/cli@<pinned>` — which installs the CLI before running it, 20 to
// 60 s and a wall of npm output on a fresh machine. The first two take under two seconds.
import { existsSync } from "node:fs";
import { delimiter, join } from "node:path";
import { execFileSync, spawnSync } from "node:child_process";
// The CLI version the fallback installs; equal to `@wix/cli` in wix-headless-kit/install/pins.json.
const WIX_CLI_VERSION = "1.1.258";
export function resolveWixCli(cwd = process.cwd()) {
const bin = process.platform === "win32" ? "wix.cmd" : "wix";
const local = join(cwd, "node_modules", ".bin", bin);
// The project's copy counts only once its install has finished: the seed runs beside a detached
// npm install, and mid-install the .bin shim can exist before the package it points at does
// (seen live: "Cannot find module node_modules/.bin/wix"). npm writes node_modules/.package-lock.json
// last, the same marker the kit's install step syncs on.
const installed = existsSync(join(cwd, "node_modules", ".package-lock.json")) && existsSync(join(cwd, "node_modules", "@wix", "cli", "package.json"));
if (installed && existsSync(local)) return { file: local, prefix: [] };
for (const dir of (process.env.PATH ?? "").split(delimiter)) {
if (dir && existsSync(join(dir, bin))) return { file: join(dir, bin), prefix: [] };
}
return { file: "npx", prefix: ["-y", `@wix/cli@${WIX_CLI_VERSION}`] };
}
/**
* A site token for the API calls. Throws when the CLI is not logged in. The CLI may print a
* notice (an update box, a project warning) around the token, so the token is extracted from
* the output rather than taken whole.
*/
export function wixToken(siteId, cwd = process.cwd()) {
const cli = resolveWixCli(cwd);
const out = execFileSync(cli.file, [...cli.prefix, "token", "--site", siteId], { encoding: "utf8", cwd });
// An older CLI starts its "update available" box on the token's own line, so a line split is
// not enough: the token is the first long run of token characters.
const token = out.match(/[A-Za-z0-9._-]{40,}/)?.[0];
if (!token) throw new Error(`The Wix CLI returned no token — run \`wix login\` (or \`npx @wix/cli@${WIX_CLI_VERSION} login\`) first.`);
return token;
}
/** Runs a Wix CLI command synchronously; same return shape as spawnSync. */
export function runWix(args, { cwd = process.cwd(), ...opts } = {}) {
const cli = resolveWixCli(cwd);
return spawnSync(cli.file, [...cli.prefix, ...args], { cwd, ...opts });
}
SHA-256: f9a4b69dc9e71280e58ebc261ae8cfcab4d1dcfdf99ff535ac725a82203f6d78