@wix/cli
Version:
CLI tool for building Wix sites and applications
442 lines (430 loc) • 12.3 kB
JavaScript
import { createRequire as _createRequire } from 'node:module';
const require = _createRequire(import.meta.url);
import {
execaCommand
} from "./chunk-NMCF7XG5.js";
import {
pathExists,
readJson,
writeJson
} from "./chunk-TLLAD5LU.js";
import {
external_exports
} from "./chunk-SDLCFZRL.js";
import {
CliError,
CliErrorCode,
require_lib
} from "./chunk-CO5A7CZG.js";
import {
__toESM,
init_esm_shims
} from "./chunk-EXLZF52D.js";
// ../package-manager/src/index.ts
init_esm_shims();
// ../package-manager/src/package-manager.ts
init_esm_shims();
import { env } from "node:process";
import { join as join3 } from "node:path";
var import_variant4 = __toESM(require_lib(), 1);
// ../package-manager/src/adapters/npm.ts
init_esm_shims();
var import_variant2 = __toESM(require_lib(), 1);
// ../package-manager/src/shell/index.ts
init_esm_shims();
// ../package-manager/src/shell/shell-client.ts
init_esm_shims();
async function runCommand(command, opts) {
const commandProcess = execaCommand(command, {
/**
* DO NOT USE `shell: true`!
* It's a security risk that leads to injections and should be avoided.
* ref: https://github.com/sindresorhus/execa/tree/main#shell
*/
shell: false,
cwd: opts?.cwd,
env: opts?.env
});
if (opts?.output) {
commandProcess.stdout?.pipe(opts.output);
}
const { stdout } = await commandProcess;
return stdout;
}
// ../package-manager/src/repo-type.ts
init_esm_shims();
var import_variant = __toESM(require_lib(), 1);
import { join } from "node:path";
// ../package-manager/src/git-service.ts
init_esm_shims();
function isInsideGitRepo(cwd) {
return runCommand("git rev-parse --is-inside-work-tree", { cwd }).then(() => true).catch(() => false);
}
async function getGitRoot(cwd) {
return runCommand("git rev-parse --show-toplevel", { cwd });
}
async function getGitLatestCommitHash(cwd) {
try {
return await runCommand("git rev-parse --verify HEAD", { cwd });
} catch {
}
}
async function gitInit(cwd, branch = "main") {
await runCommand(`git init -b ${branch.trim()}`, { cwd });
}
async function gitCommit(cwd) {
await runCommand("git add -A", { cwd });
await runCommand(
`git commit -m Initial\\ commit\\ from\\ Create\\ Wix\\ App --no-verify`,
{ cwd }
);
}
async function gitClone(url, path, branch) {
await runCommand(
`git clone --depth 1 ${branch ? `-b ${branch}` : ""} ${url} ${path}`,
{
env: {
/*
* This is to prevent git from prompting for credentials.
* `git clone` uses a subprocess for the authentication, so we can't attach the main process to its stdio.
* This leads to:
* - the spinners "swallow" its output.
* - after answering with the username and pressing "Enter", the first line of the output is being duplicated.
* That's why we're disabling the prompt, so user should be pre-authenticated.
*/
GIT_TERMINAL_PROMPT: "0"
}
}
);
}
async function gitGetCurrentBranch(cwd) {
return runCommand("git rev-parse --abbrev-ref HEAD", { cwd });
}
async function gitHasRemote(cwd, remoteName) {
try {
await runCommand(`git remote get-url ${remoteName}`, { cwd });
return true;
} catch {
return false;
}
}
async function gitSetRemoteUrl(cwd, remoteName = "origin", remoteUrl) {
const hasRemote = await gitHasRemote(cwd, remoteName);
if (hasRemote) {
await runCommand(`git remote set-url ${remoteName} ${remoteUrl}`, { cwd });
} else {
await runCommand(`git remote add ${remoteName} ${remoteUrl}`, { cwd });
}
}
async function gitPush(cwd, remoteName = "origin", options = {}) {
const branch = await gitGetCurrentBranch(cwd);
const forceFlag = options.force ? "--force" : "";
await runCommand(`git push -u ${forceFlag} ${remoteName} ${branch}`, {
cwd,
env: {
// Prevent git from prompting for credentials
GIT_TERMINAL_PROMPT: "0"
}
});
}
async function gitGetUserInfo(cwd) {
const [name, email] = await Promise.all([
runCommand("git config user.name", { cwd }),
runCommand("git config user.email", { cwd })
]);
return { name, email };
}
// ../package-manager/src/repo-type.ts
var RepoType = (0, import_variant.variant)({
None: {},
Polyrepo: (0, import_variant.fields)(),
Monorepo: (0, import_variant.fields)()
});
async function getRepoType(targetParentFolder) {
if (!await isInsideGitRepo(targetParentFolder)) {
return RepoType.None();
}
const rootDir = await getGitRoot(targetParentFolder);
if (await isUsingWorkspaces(rootDir)) {
return RepoType.Monorepo({
rootDir
});
}
return RepoType.Polyrepo({
rootDir
});
}
async function isUsingWorkspaces(rootDir) {
return readJson(join(rootDir, "package.json")).then((pkgJson) => Boolean(pkgJson.workspaces)).catch(() => false);
}
// ../package-manager/src/adapters/npm.ts
var NPM = class {
constructor(repoType) {
this.repoType = repoType;
}
name = "npm";
getUsage(name) {
return `npm init ${name.replace("create-", "")}`;
}
getInstallCmd() {
return "npm install";
}
getRunCmd() {
return "npm run";
}
getRunBinaryCmd(args) {
return {
file: "npx",
args: ["--no-install"].concat(args)
};
}
async setup(_cwd) {
if ((0, import_variant2.isType)(this.repoType, RepoType.Monorepo)) {
throw new CliError({
code: CliErrorCode.UnsupportedPackageManagerWorkspaces({
packageManagerName: this.name
}),
cause: null
});
}
}
async runInstall(cwd) {
try {
await runCommand(this.getInstallCmd(), { cwd });
} catch (e) {
throw new CliError({
code: CliErrorCode.FailedToInstallPackages(),
info: { packageManager: this.name },
cause: e
});
}
}
async runInstallPackage(cwd, packageName) {
try {
await runCommand(`npm install ${packageName}`, { cwd });
} catch (e) {
throw new CliError({
code: CliErrorCode.FailedToInstallPackage({ packageName }),
info: { packageManager: this.name },
cause: e
});
}
}
async runUninstallPackage(cwd, packageName) {
try {
await runCommand(`npm uninstall ${packageName}`, { cwd });
} catch (e) {
throw new CliError({
code: CliErrorCode.FailedToUninstallPackage({ packageName }),
info: { packageManager: this.name },
cause: e
});
}
}
};
// ../package-manager/src/adapters/yarn.ts
init_esm_shims();
var import_variant3 = __toESM(require_lib(), 1);
import { join as join2, relative } from "node:path";
import { EOL } from "node:os";
import { writeFile } from "node:fs/promises";
async function resolveYarnVersion(cwd) {
const stdout = await runCommand("yarn --version", { cwd });
return stdout.trim();
}
var Yarn = class {
constructor(repoType, name) {
this.repoType = repoType;
this.name = name;
}
getUsage(name) {
return `yarn create ${name.replace("create-", "")}`;
}
getInstallCmd() {
return "yarn install";
}
getRunCmd() {
return "yarn";
}
getRunBinaryCmd(args) {
return {
file: "yarn",
args: ["run"].concat(args)
};
}
async setup(packageFolder) {
return (0, import_variant3.matcher)(this.repoType).when(["None", "Polyrepo"], async () => {
if (this.name === "yarn-berry") {
await writeFile(join2(packageFolder, "yarn.lock"), "");
}
}).when("Monorepo", async ({ rootDir }) => {
try {
await addPackageToWorkspaces({
rootDir,
packageFolder,
yarnVersion: this.name
});
} catch (error) {
throw new CliError({
code: CliErrorCode.FailedAddingPackageToWorkspace(),
cause: error
});
}
}).complete();
}
async runInstall(cwd) {
try {
await runCommand(this.getInstallCmd(), { cwd });
} catch (e) {
throw new CliError({
code: CliErrorCode.FailedToInstallPackages(),
info: { packageManager: this.name },
cause: e
});
}
}
async runInstallPackage(cwd, packageName) {
try {
await runCommand(`yarn add ${packageName}`, { cwd });
} catch (e) {
throw new CliError({
code: CliErrorCode.FailedToInstallPackage({ packageName }),
info: { packageManager: this.name },
cause: e
});
}
}
async runUninstallPackage(cwd, packageName) {
try {
await runCommand(`yarn remove ${packageName}`, { cwd });
} catch (e) {
throw new CliError({
code: CliErrorCode.FailedToUninstallPackage({ packageName }),
info: { packageManager: this.name },
cause: e
});
}
}
};
async function getPackagesRelativePaths(rootDir, yarnVersion) {
const workspacesSchema = external_exports.array(
external_exports.object({
location: external_exports.string()
})
);
if (yarnVersion === "yarn-berry") {
const packages2 = await runCommand("yarn workspaces list --json", {
cwd: rootDir
});
const parsedPackages2 = workspacesSchema.parse(
packages2.split(EOL).filter(Boolean).map((pkg) => JSON.parse(pkg))
);
return parsedPackages2.map((pkg) => pkg.location);
}
const packages = await runCommand("yarn --json workspaces info", {
cwd: rootDir
});
const parsedPackages = workspacesSchema.parse(
Object.values(JSON.parse(JSON.parse(packages).data))
);
return parsedPackages.map((pkg) => pkg.location);
}
async function addPackageToWorkspaces({
rootDir,
packageFolder,
yarnVersion
}) {
const relativePackagePath = relative(rootDir, packageFolder);
const packages = await getPackagesRelativePaths(rootDir, yarnVersion);
if (packages.includes(relativePackagePath)) {
return;
}
const packageJson = await readJson(
join2(rootDir, "package.json")
);
if (Array.isArray(packageJson.workspaces)) {
packageJson.workspaces.push(relativePackagePath);
} else if (typeof packageJson.workspaces === "object") {
packageJson.workspaces = {
...packageJson.workspaces,
packages: [
...packageJson.workspaces.packages ?? [],
relativePackagePath
]
};
} else {
throw new Error(
`Failed to read workspaces structure. Expected an array or object but got ${JSON.stringify(
packageJson.workspaces
)}`
);
}
await writeJson(join2(rootDir, "package.json"), packageJson, { spaces: 2 });
}
// ../package-manager/src/package-manager.ts
async function createPackageManager(repoType) {
const packageManagerName = await getPackageManagerName(repoType);
switch (packageManagerName) {
case "yarn-berry":
return new Yarn(repoType, "yarn-berry");
case "yarn":
return new Yarn(repoType, "yarn");
case "npm":
return new NPM(repoType);
}
}
async function getPackageManagerName(repoType) {
const getByEnv = () => {
if (env.npm_config_user_agent?.startsWith("yarn/1")) {
return "yarn";
}
if (env.npm_config_user_agent?.startsWith("yarn")) {
return "yarn-berry";
}
if (env.npm_config_user_agent?.startsWith("npm")) {
return "npm";
}
throw new CliError({
code: CliErrorCode.UnsupportedPackageManager({
packageManagerName: env.npm_config_user_agent
}),
cause: null
});
};
return (0, import_variant4.matcher)(repoType).when(RepoType.None, getByEnv).when(
[RepoType.Polyrepo, RepoType.Monorepo],
async ({ rootDir }) => {
const [hasYarnRc, hasYarnLock, hasPackageLock] = await Promise.all([
pathExists(join3(rootDir, ".yarnrc.yml")),
pathExists(join3(rootDir, "yarn.lock")),
pathExists(join3(rootDir, "package-lock.json"))
]);
if (hasYarnRc || hasYarnLock) {
const yarnVersion = await resolveYarnVersion(rootDir);
return yarnVersion.startsWith("1") ? "yarn" : "yarn-berry";
}
if (hasPackageLock) {
return "npm";
}
return getByEnv();
}
).complete();
}
export {
runCommand,
isInsideGitRepo,
getGitLatestCommitHash,
gitInit,
gitCommit,
gitClone,
gitGetCurrentBranch,
gitSetRemoteUrl,
gitPush,
gitGetUserInfo,
RepoType,
getRepoType,
NPM,
Yarn,
createPackageManager
};
//# sourceMappingURL=chunk-7QJUAJW3.js.map