var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// src/index.ts
var src_exports = {};
__export(src_exports, {
  default: () => src_default
});
module.exports = __toCommonJS(src_exports);
var clackPrompts = __toESM(require("@winner-fed/clack-prompts"));
var import_utils = require("@winner-fed/utils");
var import_fs = require("fs");
var import_path = require("path");
var import_template = require("./template");
var devCommands = {
  pnpm: "pnpm dev",
  yarn: "yarn dev",
  npm: "npm run dev",
  bun: "bun run dev"
};
function parseStr(str) {
  return str.replace(/-(\w)/g, function(_$0, $1) {
    return $1.toUpperCase();
  });
}
function getUUID() {
  return Number(Math.random().toString().substr(2)).toString(36);
}
function generateOnlyContainer(str) {
  return `${parseStr(str)}${getUUID()}`;
}
var pkg = require("../package");
var DEFAULT_DATA = {
  pluginName: "winjs-plugin-demo",
  projectName: "winjs-template",
  email: "i@domain.com",
  author: "winjs",
  appContainerName: "root",
  version: pkg.version,
  npmClient: "pnpm" /* pnpm */,
  registry: import_template.ERegistry.npm,
  withHusky: false,
  extraNpmrc: "",
  appTemplate: "app" /* app */
};
var src_default = async ({
  cwd,
  args,
  defaultData = DEFAULT_DATA
}) => {
  let [name] = args._;
  let npmClient = "pnpm" /* pnpm */;
  let registry = import_template.ERegistry.npm;
  let appTemplate = (defaultData == null ? void 0 : defaultData.appTemplate) || "app" /* app */;
  const { username, email } = await (0, import_utils.getGitInfo)();
  const author = email && username ? `${username} <${email}>` : "";
  let pluginName = `winjs-plugin-${name || "demo"}`;
  let projectName = `winjs-template-${name || "demo"}`;
  const appContainerName = generateOnlyContainer(projectName);
  let target = name ? (0, import_path.join)(cwd, name) : cwd;
  const { isCancel, text, select, intro, outro, box, taskLog } = clackPrompts;
  const exitPrompt = () => {
    outro(import_utils.chalk.red("Exit create-win"));
    process.exit(1);
  };
  const setName = async () => {
    name = await text({
      message: "What's the target folder name?",
      initialValue: name || "my-app",
      validate: (value) => {
        if (!value.length) {
          return "Please input project name";
        }
        if (value != "." && import_utils.fsExtra.existsSync((0, import_path.join)(cwd, value))) {
          return `Folder ${value} already exists`;
        }
      }
    });
  };
  const selectAppTemplate = async () => {
    appTemplate = await select({
      message: "Pick WinJS App Template",
      options: [
        { label: "Simple App", value: "sample" /* sample */ },
        {
          label: "PC Web",
          value: "pc" /* pc */,
          hint: "for pc web"
        },
        { label: "H5 App", value: "app" /* app */ },
        {
          label: "WinJS Plugin",
          value: "plugin" /* plugin */,
          hint: "for plugin development"
        }
      ],
      initialValue: "sample" /* sample */
    });
  };
  const selectNpmClient = async () => {
    npmClient = await select({
      message: "Pick Npm Client",
      options: [
        { label: "npm" /* npm */, value: "npm" /* npm */ },
        { label: "yarn" /* yarn */, value: "yarn" /* yarn */, hint: "recommended" },
        { label: "pnpm" /* pnpm */, value: "pnpm" /* pnpm */ }
      ],
      initialValue: "yarn" /* yarn */
    });
  };
  const selectRegistry = async () => {
    registry = await select({
      message: "Pick Npm Registry",
      options: [
        {
          label: "npm",
          value: import_template.ERegistry.npm
        },
        {
          label: "taobao",
          value: import_template.ERegistry.taobao,
          hint: "recommended for China"
        }
      ],
      initialValue: import_template.ERegistry.taobao
    });
  };
  const internalTemplatePrompts = async () => {
    intro("Creating a new WinJS project...");
    await setName();
    if (isCancel(name)) {
      exitPrompt();
    }
    target = (0, import_path.join)(cwd, name);
    await selectAppTemplate();
    if (isCancel(appTemplate)) {
      exitPrompt();
    }
    await selectNpmClient();
    if (isCancel(npmClient)) {
      exitPrompt();
    }
    await selectRegistry();
    if (isCancel(registry)) {
      exitPrompt();
    }
    const isPlugin = appTemplate === "plugin" /* plugin */;
    if (isPlugin) {
      pluginName = await text({
        message: `What's the plugin name?`,
        placeholder: pluginName,
        validate: (value) => {
          if (!(value == null ? void 0 : value.length)) {
            return "Please input plugin name";
          }
        }
      });
      if (isCancel(pluginName)) {
        exitPrompt();
      }
    }
  };
  const useDefaultData = !!args.default;
  const useExternalTemplate = !!args.template;
  switch (true) {
    case useExternalTemplate:
      await selectNpmClient();
      if (isCancel(npmClient)) {
        exitPrompt();
      }
      await selectRegistry();
      if (isCancel(registry)) {
        exitPrompt();
      }
      await (0, import_template.unpackTemplate)({
        template: args.template,
        dest: target,
        registry
      });
      break;
    default:
      if (!useDefaultData) {
        await internalTemplatePrompts();
      }
  }
  const version = pkg.version;
  const monorepoRoot = await detectMonorepoRoot({ target });
  const inMonorepo = !!monorepoRoot;
  const projectRoot = inMonorepo ? monorepoRoot : target;
  const shouldInitGit = args.git !== false;
  const withHusky = shouldInitGit && !inMonorepo;
  let pnpmExtraNpmrc = "";
  const isPnpm = npmClient === "pnpm" /* pnpm */;
  let pnpmMajorVersion;
  if (isPnpm) {
    pnpmMajorVersion = await getPnpmMajorVersion();
    if (pnpmMajorVersion === 7) {
      pnpmExtraNpmrc = `strict-peer-dependencies=false`;
    }
  }
  const injectInternalTemplateFiles = async () => {
    const generator = new import_utils.BaseGenerator({
      path: (0, import_path.join)(__dirname, "..", "templates", appTemplate),
      target,
      slient: true,
      data: useDefaultData ? defaultData : {
        version: version.includes("-canary.") ? version : `^${version}`,
        npmClient,
        registry,
        author,
        email,
        withHusky,
        extraNpmrc: isPnpm ? pnpmExtraNpmrc : "",
        pluginName,
        projectName,
        appContainerName
      }
    });
    await generator.run();
  };
  if (!useExternalTemplate) {
    await injectInternalTemplateFiles();
  }
  const context = {
    inMonorepo,
    target,
    projectRoot
  };
  if (!withHusky) {
    await removeHusky(context);
  }
  if (inMonorepo) {
    await moveNpmrc(context);
  }
  if (shouldInitGit) {
    await initGit(context);
  } else {
    import_utils.logger.info(`Skip Git init`);
  }
  const isPnpm8 = pnpmMajorVersion === 8;
  if (!useDefaultData && args.install !== false) {
    const installTask = taskLog(`Installing dependencies with ${npmClient}...`);
    if (isPnpm8) {
      await installWithPnpm8(target);
    } else {
      const isYarn = npmClient === "yarn" /* yarn */;
      try {
        await execute(npmClient, [isYarn ? "" : "install"], {
          cwd: target,
          onData: (data) => {
            installTask.text = data;
          }
        });
      } catch (error) {
        installTask.fail(`Failed to install dependencies with ${npmClient}`);
        throw error;
      }
    }
    installTask.success(`Installed dependencies with ${npmClient}`);
  } else {
    import_utils.logger.info(`Skip install deps`);
    if (isPnpm8) {
      import_utils.logger.warn(
        import_utils.chalk.yellow(
          `You current using pnpm v8, it will install minimal version of dependencies`
        )
      );
      import_utils.logger.warn(
        import_utils.chalk.green(
          `Recommended that you run ${import_utils.chalk.bold.cyan(
            "pnpm up -L"
          )} to install latest version of dependencies`
        )
      );
    }
  }
  if ((0, import_fs.existsSync)((0, import_path.join)(target, ".husky/pre-commit"))) {
    if (process.platform !== "win32") {
      import_utils.execa.execaCommandSync(`chmod +x ${(0, import_path.join)(target, ".husky/pre-commit")}`);
      import_utils.logger.info(`Chmod ${(0, import_path.join)(target, ".husky/pre-commit")} successful`);
    }
  }
  if ((0, import_fs.existsSync)((0, import_path.join)(target, ".husky/commit-msg"))) {
    if (process.platform !== "win32") {
      import_utils.execa.execaCommandSync(`chmod +x ${(0, import_path.join)(target, ".husky/commit-msg")}`);
      import_utils.logger.info(`Chmod ${(0, import_path.join)(target, ".husky/commit-msg")} successful`);
    }
  }
  box(
    `
1: ${import_utils.chalk.bold(import_utils.chalk.cyan(`cd ${target}`))}
2: ${import_utils.chalk.bold(import_utils.chalk.cyan(devCommands[npmClient]))}

To close the dev server, hit ${import_utils.chalk.bold(import_utils.chalk.cyan("Ctrl+C"))}
    `.trim(),
    "Next Steps"
  );
  outro(import_utils.chalk.green(`Create success!`));
};
async function detectMonorepoRoot(opts) {
  const { target } = opts;
  const rootPkg = await import_utils.pkgUp.pkgUp({ cwd: (0, import_path.dirname)(target) });
  if (!rootPkg) {
    return null;
  }
  const rootDir = (0, import_path.dirname)(rootPkg);
  if ((0, import_utils.tryPaths)([
    (0, import_path.join)(rootDir, "lerna.json"),
    (0, import_path.join)(rootDir, "pnpm-workspace.yaml")
  ])) {
    return rootDir;
  }
  return null;
}
async function moveNpmrc(opts) {
  const { target, projectRoot } = opts;
  const sourceNpmrc = (0, import_path.join)(target, "./.npmrc");
  const targetNpmrc = (0, import_path.join)(projectRoot, "./.npmrc");
  if (!(0, import_fs.existsSync)(targetNpmrc)) {
    await import_utils.fsExtra.copyFile(sourceNpmrc, targetNpmrc);
  }
  await import_utils.fsExtra.remove(sourceNpmrc);
}
async function initGit(opts) {
  const { projectRoot } = opts;
  const isGit = (0, import_fs.existsSync)((0, import_path.join)(projectRoot, ".git"));
  if (isGit) return;
  try {
    await import_utils.execa.execa("git", ["init"], { cwd: projectRoot });
  } catch {
    import_utils.logger.error(`Initial the git repo failed`);
  }
}
async function removeHusky(opts) {
  const dir = (0, import_path.join)(opts.target, "./.husky");
  if ((0, import_fs.existsSync)(dir)) {
    await import_utils.fsExtra.remove(dir);
  }
}
async function installWithPnpm8(cwd) {
  await import_utils.execa.execa("pnpm", ["up", "-L"], { cwd, stdio: "inherit" });
}
async function getPnpmMajorVersion() {
  try {
    const { stdout } = await import_utils.execa.execa("pnpm", ["--version"]);
    return parseInt(stdout.trim().split(".")[0], 10);
  } catch (e) {
    throw new Error("Please install pnpm first", { cause: e });
  }
}
async function execute(cmd, args, options) {
  const child = import_utils.execa.execa(cmd, args, {
    stdio: "pipe",
    cwd: options.cwd
  });
  return new Promise((resolve, reject) => {
    var _a, _b;
    (_a = child.stdout) == null ? void 0 : _a.on("data", (data) => {
      options.onData(data);
    });
    (_b = child.stderr) == null ? void 0 : _b.on("data", (data) => {
      options.onData(data);
    });
    child.on("close", (code) => {
      resolve(code);
    });
    child.on("error", (error) => {
      reject(error);
    });
  });
}
