create-dage-backend-cli 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #!/usr/bin/env node
  2. const { program } = require("commander");
  3. const fs = require("fs");
  4. const path = require("path");
  5. const clc = require("cli-color");
  6. const { promisify } = require("util");
  7. const cliProgress = require("cli-progress");
  8. const ncp = promisify(require("ncp").ncp);
  9. const { exec, execSync } = require("child_process");
  10. const pkg = require("./package.json");
  11. process.stdout.setEncoding("utf8");
  12. program
  13. .version(pkg.version)
  14. .arguments("<projectName>")
  15. .option("--no-role", "Skip role management feature")
  16. .action(async (projectName, options) => {
  17. const enableRole = options.role;
  18. const projectDir = path.join(process.cwd(), projectName);
  19. if (fs.existsSync(projectDir)) {
  20. console.log(clc.red("当前目录下已存在" + projectName));
  21. return;
  22. }
  23. fs.mkdirSync(projectDir);
  24. const templateDir = path.join(__dirname, "template");
  25. const files = await promisify(fs.readdir)(templateDir);
  26. const progressBar = new cliProgress.SingleBar({
  27. format: "Progress [{bar}] {percentage}% | {value}/{total}",
  28. barCompleteChar: "\u001b[42m \u001b[0m",
  29. barIncompleteChar: "\u001b[40m \u001b[0m",
  30. hideCursor: true,
  31. });
  32. progressBar.start(files.length, 0);
  33. await copyTemplateFiles(
  34. templateDir,
  35. projectDir,
  36. enableRole,
  37. progressBar,
  38. projectName
  39. );
  40. progressBar.stop();
  41. const npmrcPath = path.join(projectDir, ".npmrc");
  42. const npmrcContent = `
  43. registry=https://registry.npmmirror.com/
  44. @dage:registry=http://192.168.20.245:4873/
  45. `;
  46. fs.writeFileSync(npmrcPath, npmrcContent.trim() + "\n");
  47. console.log(clc.blue("=====执行初始化====="));
  48. const installCommand = "pnpm i || yarn || npm i";
  49. try {
  50. await new Promise((resolve, reject) => {
  51. const childProcess = exec(
  52. installCommand,
  53. { cwd: projectDir },
  54. (error) => {
  55. if (error) {
  56. reject(error);
  57. } else {
  58. resolve();
  59. }
  60. }
  61. );
  62. childProcess.stdout.on("data", (data) => {
  63. console.log(data.trim());
  64. });
  65. });
  66. console.log(clc.green("=====初始化完成====="));
  67. } catch (error) {
  68. console.log(
  69. clc.red(`Error executing installation command: ${error.message}`)
  70. );
  71. }
  72. });
  73. program.parse(process.argv);
  74. function getPackageVersion(pkgName) {
  75. let version = "1.0.0";
  76. try {
  77. const componentsVersion = execSync(
  78. "npm info " + pkgName + " version --registry http://192.168.20.245:4873"
  79. );
  80. version = componentsVersion.toString().trim();
  81. } catch (err) {
  82. console.log(clc.red("获取 " + pkgName + " 版本号失败"));
  83. }
  84. return version;
  85. }
  86. async function copyTemplateFiles(
  87. src,
  88. dest,
  89. enableRole,
  90. progressBar,
  91. projectName
  92. ) {
  93. const entries = await fs.promises.readdir(src, { withFileTypes: true });
  94. const exclusions = [
  95. "build",
  96. "node_modules",
  97. "package-lock.json",
  98. "_withoutRole.tsx",
  99. ];
  100. for (const entry of entries) {
  101. if (exclusions.includes(entry.name)) continue;
  102. const srcPath = path.join(src, entry.name);
  103. const destPath = path.join(dest, entry.name);
  104. if (entry.isDirectory()) {
  105. await fs.promises.mkdir(destPath, { recursive: true });
  106. await copyTemplateFiles(srcPath, destPath, enableRole, progressBar);
  107. } else {
  108. if (
  109. srcPath.includes("src\\router\\index.tsx") ||
  110. srcPath.includes("src\\pages\\Layout\\index.tsx") ||
  111. srcPath.includes("src\\pages\\User\\components\\UserAdd\\index.tsx")
  112. ) {
  113. const routeContent = enableRole
  114. ? await fs.promises.readFile(path.join(src, "index.tsx"), "utf8")
  115. : await fs.promises.readFile(
  116. path.join(src, "_withoutRole.tsx"),
  117. "utf8"
  118. );
  119. await fs.promises.writeFile(destPath, routeContent);
  120. } else {
  121. await ncp(srcPath, destPath);
  122. }
  123. // 处理 package.json(保留原有逻辑)
  124. if (entry.name === "package.json") {
  125. const packageJsonPath = path.join(destPath);
  126. const packageJson = JSON.parse(
  127. fs.readFileSync(packageJsonPath, "utf8")
  128. );
  129. packageJson.name = projectName;
  130. packageJson.version = pkg.version;
  131. Object.keys(packageJson.dependencies).forEach((key) => {
  132. if (key.startsWith("@dage")) {
  133. packageJson.dependencies[key] = "^" + getPackageVersion(key);
  134. }
  135. });
  136. fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
  137. }
  138. progressBar.increment();
  139. }
  140. }
  141. }