@component-hook/create-app 1.1.5 → 1.2.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.
package/bin/index.js CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import '../dist/index.js';
3
+ import '../dist/index.mjs';
@@ -0,0 +1 @@
1
+ export { };
package/dist/index.mjs ADDED
@@ -0,0 +1,254 @@
1
+ import { existsSync, readdirSync, statSync } from "node:fs";
2
+ import { readFile, readdir, writeFile } from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import artTemplate from "art-template";
6
+ import { copy, ensureDirSync, remove } from "fs-extra/esm";
7
+ import minimist from "minimist";
8
+ import ora from "ora";
9
+ import colors from "picocolors";
10
+ import prompts from "prompts";
11
+
12
+ //#region src/constants.ts
13
+ const DEFAULT_PROJECT_NAME = "basic-project";
14
+ const TEMPLATES = ["vue", "react"];
15
+ const GITHUB_ACTIONS = "GitHub Actions";
16
+ const GITLAB_CI = "GitLab CI";
17
+
18
+ //#endregion
19
+ //#region src/utils.ts
20
+ function formatTargetDir(targetDir) {
21
+ if (!targetDir) return targetDir;
22
+ targetDir = targetDir.trim();
23
+ if (targetDir[0] === "/") targetDir = targetDir.slice(1);
24
+ if (targetDir.at(-1) === "/") targetDir = targetDir.slice(0, -1);
25
+ return targetDir;
26
+ }
27
+ function getProjectName(targetDir) {
28
+ if (!targetDir) return DEFAULT_PROJECT_NAME;
29
+ return path.basename(path.resolve(targetDir));
30
+ }
31
+ function isValidPackageName(projectName) {
32
+ return /^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test(projectName);
33
+ }
34
+ function toValidPackageName(projectName) {
35
+ return projectName.trim().toLowerCase().replaceAll(/\s+/g, "-").replace(/^[._]/, "").replaceAll(/[^a-z\d\-~]+/g, "-");
36
+ }
37
+ function toUpperCasePackageName(projectName) {
38
+ return projectName.split("-").map((str) => `${str[0].toUpperCase()}${str.slice(1)}`).join(" ");
39
+ }
40
+ function getPkgManagerInfo() {
41
+ const userAgent = process.env.npm_config_user_agent;
42
+ if (!userAgent) return;
43
+ const [pkgManager] = userAgent.split(" ");
44
+ const [name, version] = pkgManager.split("/");
45
+ return {
46
+ name,
47
+ version
48
+ };
49
+ }
50
+ function isEmptyFolder(dir) {
51
+ const files = readdirSync(dir);
52
+ return files.length === 0 || files.length === 1 && files[0] === ".git";
53
+ }
54
+ function clearFolder(dir) {
55
+ if (!existsSync(dir)) return;
56
+ const files = readdirSync(dir).filter((file) => file !== ".git");
57
+ return Promise.all(files.map((file) => remove(path.resolve(dir, file))));
58
+ }
59
+
60
+ //#endregion
61
+ //#region src/prompts.ts
62
+ function builtinTemplate(template) {
63
+ return template && TEMPLATES.includes(template);
64
+ }
65
+ function onCancel() {
66
+ throw new Error(`${colors.red("✖")} Operation cancelled`);
67
+ }
68
+ function styleTitle(title) {
69
+ return colors.bold(colors.magenta(title));
70
+ }
71
+ function operationPrompts({ targetDir, template }) {
72
+ return prompts([
73
+ {
74
+ type: targetDir ? null : "text",
75
+ name: "projectName",
76
+ message: styleTitle("Project name:"),
77
+ initial: DEFAULT_PROJECT_NAME
78
+ },
79
+ {
80
+ type: (nameAnswer) => {
81
+ return existsSync(nameAnswer) && !isEmptyFolder(nameAnswer) ? "select" : null;
82
+ },
83
+ name: "overwrite",
84
+ message: (nameAnswer) => {
85
+ return styleTitle(`${nameAnswer === "." ? "current directory" : `Target directory "${targetDir}"`} is not empty. Please choose how to proceed:`);
86
+ },
87
+ initial: 0,
88
+ choices: [
89
+ {
90
+ title: "Cancel operation",
91
+ value: "cancel"
92
+ },
93
+ {
94
+ title: "Remove existing files and continue",
95
+ value: "overwrite"
96
+ },
97
+ {
98
+ title: "Ignore files and continue",
99
+ value: "ignore"
100
+ }
101
+ ]
102
+ },
103
+ {
104
+ type: (overwriteAnswer) => {
105
+ if (overwriteAnswer === "cancel") onCancel();
106
+ return null;
107
+ },
108
+ name: "overwriteChecker"
109
+ },
110
+ {
111
+ type: (_, { projectName: nameAnswer }) => {
112
+ return isValidPackageName(getProjectName(nameAnswer)) ? null : "text";
113
+ },
114
+ name: "packageName",
115
+ message: styleTitle("Package name:"),
116
+ initial: (_, { projectName: nameAnswer }) => toValidPackageName(getProjectName(nameAnswer)),
117
+ validate: (name) => {
118
+ return isValidPackageName(name) || "Invalid package.json name";
119
+ }
120
+ },
121
+ {
122
+ type: builtinTemplate(template) ? null : "select",
123
+ name: "framework",
124
+ message: template ? styleTitle(`${colors.red(template)} isn't a valid template. Please choose from below:`) : styleTitle("Select a framework:"),
125
+ initial: 0,
126
+ choices: [{
127
+ title: colors.green("Vue"),
128
+ value: "vue"
129
+ }, {
130
+ title: colors.blue("React"),
131
+ value: "react"
132
+ }]
133
+ }
134
+ ], { onCancel });
135
+ }
136
+
137
+ //#endregion
138
+ //#region src/index.ts
139
+ const cwd = process.cwd();
140
+ const argv = minimist(process.argv.slice(2), {
141
+ default: {
142
+ gitlab: false,
143
+ help: false
144
+ },
145
+ alias: {
146
+ t: "template",
147
+ l: "gitlab",
148
+ h: "help"
149
+ },
150
+ string: ["_"]
151
+ });
152
+ const renameFiles = {
153
+ _gitignore: ".gitignore",
154
+ "_gitlab-ci.yml": ".gitlab-ci.yml"
155
+ };
156
+ const helpMessage = `
157
+ Usage: create-component-hook [project name] [options]
158
+
159
+ Create a new project in TypeScript.
160
+ With no arguments, start the CLI in interactive mode.
161
+
162
+ Options:
163
+ -t, --template [name] Choose a framework template
164
+ -l, --gitlab Use Gitlab CI/CD, default is Github CI/CD
165
+ -h, --help Display this help message
166
+
167
+ Available templates:
168
+ ${colors.green("vue")}
169
+ ${colors.blue("react")}
170
+ `;
171
+ async function writePackageJson(root, dir, packageName) {
172
+ const pkgJson = await readFile(path.join(dir, "package.json"), "utf8");
173
+ const pkg = JSON.parse(pkgJson);
174
+ const targetPath = path.join(root, "package.json");
175
+ pkg.name = packageName;
176
+ return writeFile(targetPath, `${JSON.stringify(pkg, null, 2)}\n`);
177
+ }
178
+ async function copyFolder(root, dir, packageName) {
179
+ const isGitlab = argv.l || argv.gitlab;
180
+ const filterFiles = (await readdir(dir)).filter((file) => {
181
+ return file !== "package.json" && file !== (isGitlab ? ".github" : ".gitlab") && file !== (isGitlab ? "" : "_gitlab-ci.yml");
182
+ });
183
+ const rewriteOrCopyFile = (file) => {
184
+ const targetPath = path.join(root, renameFiles?.[file] ?? file);
185
+ const templatePath = path.join(dir, file);
186
+ if (file.endsWith(".art")) {
187
+ const name = file.endsWith(".js.art") || file.endsWith(".ts.art") ? packageName : toUpperCasePackageName(packageName);
188
+ const replacedPath = targetPath.replace(".art", "");
189
+ const renderedResult = artTemplate(templatePath, {
190
+ projectName: name,
191
+ gitRepository: isGitlab ? GITLAB_CI : GITHUB_ACTIONS
192
+ });
193
+ ensureDirSync(path.dirname(replacedPath));
194
+ return writeFile(replacedPath, renderedResult);
195
+ }
196
+ if (statSync(templatePath).isDirectory()) {
197
+ const rewriteOrCopySubFilePromises = readdirSync(templatePath).map((subFile) => rewriteOrCopyFile(path.join(file, subFile)));
198
+ return Promise.all(rewriteOrCopySubFilePromises).then(() => {});
199
+ } else return copy(templatePath, targetPath);
200
+ };
201
+ return Promise.all(filterFiles.map((file) => rewriteOrCopyFile(file)));
202
+ }
203
+ async function createApp() {
204
+ if (argv.h || argv.help) {
205
+ console.log(helpMessage);
206
+ return;
207
+ }
208
+ const targetDir = formatTargetDir(argv._[0]);
209
+ const template = argv.t || argv.template;
210
+ const result = await operationPrompts({
211
+ targetDir,
212
+ template
213
+ });
214
+ const packageName = result.packageName || getProjectName(result.projectName);
215
+ const framework = result.framework || template;
216
+ const root = path.join(cwd, result.projectName);
217
+ const pkgManager = getPkgManagerInfo()?.name ?? "npm";
218
+ const spinner = ora();
219
+ console.log();
220
+ spinner.start(colors.yellow(`Scaffolding project...`));
221
+ if (result.overwrite === "overwrite") await clearFolder(root);
222
+ else ensureDirSync(root);
223
+ const filePath = fileURLToPath(import.meta.url);
224
+ const sharedDir = path.resolve(filePath, "../..", "template-shared");
225
+ const templateDir = path.resolve(filePath, "../..", `template-${framework}`);
226
+ Promise.all([
227
+ copyFolder(root, sharedDir, packageName),
228
+ copyFolder(root, templateDir, packageName),
229
+ writePackageJson(root, templateDir, packageName),
230
+ new Promise((resolve) => setTimeout(resolve, 300))
231
+ ]).then(() => {
232
+ const cdProjectName = path.relative(cwd, root);
233
+ const formattedCdProjectName = cdProjectName.includes(" ") ? `"${cdProjectName}"` : cdProjectName;
234
+ spinner.succeed(`${colors.green("Scaffolded project in")} ${root}`);
235
+ console.log(`\n${colors.green("Done. Now run:")}\n`);
236
+ console.log(colors.cyan(` cd ${formattedCdProjectName}`));
237
+ if (pkgManager === "yarn") {
238
+ console.log(colors.cyan(` yarn`));
239
+ console.log(colors.cyan(` yarn dev`));
240
+ } else {
241
+ console.log(colors.cyan(` ${pkgManager} install`));
242
+ console.log(colors.cyan(` ${pkgManager} run dev`));
243
+ }
244
+ console.log();
245
+ }).catch(() => {
246
+ spinner.fail(colors.red("Failed to scaffold project"));
247
+ });
248
+ }
249
+ createApp().catch((error) => {
250
+ console.error(colors.red(error.message));
251
+ });
252
+
253
+ //#endregion
254
+ export { };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@component-hook/create-app",
3
- "version": "1.1.5",
3
+ "version": "1.2.0",
4
4
  "description": "Scaffolding a basic typescript project",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -14,7 +14,7 @@
14
14
  "dist"
15
15
  ],
16
16
  "engines": {
17
- "node": ">=20.19.4"
17
+ "node": ">=20.19.5"
18
18
  },
19
19
  "repository": {
20
20
  "type": "git",
@@ -27,7 +27,7 @@
27
27
  "homepage": "https://github.com/tzuyi0817/component-hook/tree/master/packages/create-app#readme",
28
28
  "dependencies": {
29
29
  "art-template": "^4.13.4",
30
- "fs-extra": "^11.3.1",
30
+ "fs-extra": "^11.3.2",
31
31
  "minimist": "^1.2.8",
32
32
  "ora": "^8.2.0",
33
33
  "picocolors": "^1.1.1",
@@ -39,8 +39,8 @@
39
39
  "@types/prompts": "^2.4.9"
40
40
  },
41
41
  "scripts": {
42
- "dev": "tsup --watch",
43
- "build": "tsup",
42
+ "dev": "tsdown --watch",
43
+ "build": "tsdown",
44
44
  "typecheck": "tsc --noEmit"
45
45
  }
46
46
  }
@@ -3,7 +3,7 @@
3
3
  "private": true,
4
4
  "version": "0.0.0",
5
5
  "type": "module",
6
- "packageManager": "pnpm@10.15.0",
6
+ "packageManager": "pnpm@10.20.0",
7
7
  "scripts": {
8
8
  "dev": "vite",
9
9
  "dev:mock": "MOCK=true vite",
@@ -18,47 +18,47 @@
18
18
  "preview": "vite preview"
19
19
  },
20
20
  "dependencies": {
21
- "axios": "^1.11.0",
22
- "i18next": "^25.4.0",
23
- "react": "^19.1.1",
24
- "react-dom": "^19.1.1",
25
- "react-i18next": "^15.7.1",
26
- "react-router-dom": "^7.8.1",
21
+ "axios": "^1.13.2",
22
+ "i18next": "^25.6.0",
23
+ "react": "^19.2.0",
24
+ "react-dom": "^19.2.0",
25
+ "react-i18next": "^15.7.4",
26
+ "react-router-dom": "^7.9.5",
27
27
  "zustand": "^5.0.8"
28
28
  },
29
29
  "devDependencies": {
30
- "@component-hook/eslint-plugin": "^1.1.3",
31
- "@playwright/test": "^1.55.0",
32
- "@tailwindcss/vite": "^4.1.12",
33
- "@testing-library/jest-dom": "^6.8.0",
30
+ "@component-hook/eslint-plugin": "^1.1.5",
31
+ "@playwright/test": "^1.56.1",
32
+ "@tailwindcss/vite": "^4.1.16",
33
+ "@testing-library/jest-dom": "^6.9.1",
34
34
  "@testing-library/react": "^16.3.0",
35
35
  "@testing-library/user-event": "^14.6.1",
36
36
  "@tsconfig/node22": "^22.0.2",
37
- "@types/node": "^22.17.2",
38
- "@types/react": "^19.1.10",
39
- "@types/react-dom": "^19.1.7",
40
- "@vitejs/plugin-react-swc": "^4.0.1",
37
+ "@types/node": "^22.19.0",
38
+ "@types/react": "^19.2.2",
39
+ "@types/react-dom": "^19.2.2",
40
+ "@vitejs/plugin-react-swc": "^4.2.1",
41
41
  "@vitest/coverage-v8": "^3.2.4",
42
42
  "autoprefixer": "^10.4.21",
43
- "cssnano": "^7.1.0",
44
- "eslint": "^9.33.0",
45
- "jsdom": "^26.1.0",
46
- "msw": "^2.10.5",
43
+ "cssnano": "^7.1.2",
44
+ "eslint": "^9.39.1",
45
+ "jsdom": "^27.1.0",
46
+ "msw": "^2.12.0",
47
47
  "postcss": "^8.5.6",
48
- "postcss-preset-env": "^10.2.4",
48
+ "postcss-preset-env": "^10.4.0",
49
49
  "postcss-pxtorem": "^6.1.0",
50
50
  "prettier": "^3.6.2",
51
- "tailwindcss": "^4.1.12",
52
- "typescript": "^5.9.2",
53
- "vite": "^7.1.3",
51
+ "tailwindcss": "^4.1.16",
52
+ "typescript": "^5.9.3",
53
+ "vite": "^7.2.1",
54
54
  "vite-plugin-svg-icons": "^2.0.1",
55
55
  "vitest": "^3.2.4"
56
56
  },
57
57
  "optionalDependencies": {
58
- "@commitlint/cli": "^19.8.1",
59
- "@commitlint/config-conventional": "^19.8.1",
58
+ "@commitlint/cli": "^20.1.0",
59
+ "@commitlint/config-conventional": "^20.0.0",
60
60
  "husky": "^9.1.7",
61
- "lint-staged": "^16.1.5"
61
+ "lint-staged": "^16.2.6"
62
62
  },
63
63
  "msw": {
64
64
  "workerDirectory": [
@@ -6,9 +6,9 @@ runs:
6
6
  using: composite
7
7
  steps:
8
8
  - name: install Node.js
9
- uses: actions/setup-node@v4
9
+ uses: actions/setup-node@v6
10
10
  with:
11
- node-version: 20.19.4
11
+ node-version: 20.19.5
12
12
 
13
13
  - name: install pnpm
14
14
  uses: pnpm/action-setup@v4
@@ -3,7 +3,7 @@
3
3
  "version": "0.0.0",
4
4
  "private": true,
5
5
  "type": "module",
6
- "packageManager": "pnpm@10.15.0",
6
+ "packageManager": "pnpm@10.20.0",
7
7
  "scripts": {
8
8
  "dev": "vite",
9
9
  "dev:mock": "MOCK=true vite",
@@ -18,50 +18,50 @@
18
18
  "preview": "vite preview"
19
19
  },
20
20
  "dependencies": {
21
- "axios": "^1.11.0",
22
- "pinia": "^3.0.3",
23
- "pinia-plugin-persistedstate": "^4.5.0",
24
- "vue": "^3.5.19",
25
- "vue-i18n": "^11.1.11",
26
- "vue-router": "^4.5.1"
21
+ "axios": "^1.13.2",
22
+ "pinia": "^3.0.4",
23
+ "pinia-plugin-persistedstate": "^4.7.1",
24
+ "vue": "^3.5.23",
25
+ "vue-i18n": "^11.1.12",
26
+ "vue-router": "^4.6.3"
27
27
  },
28
28
  "devDependencies": {
29
- "@component-hook/eslint-plugin": "1.1.3",
30
- "@intlify/unplugin-vue-i18n": "^6.0.8",
31
- "@playwright/test": "^1.55.0",
32
- "@tailwindcss/vite": "^4.1.12",
33
- "@testing-library/jest-dom": "^6.8.0",
29
+ "@component-hook/eslint-plugin": "^1.1.5",
30
+ "@intlify/unplugin-vue-i18n": "^11.0.1",
31
+ "@playwright/test": "^1.56.1",
32
+ "@tailwindcss/vite": "^4.1.16",
33
+ "@testing-library/jest-dom": "^6.9.1",
34
34
  "@testing-library/user-event": "^14.6.1",
35
35
  "@testing-library/vue": "^8.1.0",
36
36
  "@tsconfig/node22": "^22.0.2",
37
- "@types/node": "^22.17.2",
37
+ "@types/node": "^22.19.0",
38
38
  "@vitejs/plugin-vue": "^6.0.1",
39
39
  "@vitest/coverage-v8": "^3.2.4",
40
40
  "@vue/tsconfig": "^0.8.1",
41
41
  "autoprefixer": "^10.4.21",
42
- "cssnano": "^7.1.0",
43
- "eslint": "^9.33.0",
44
- "jsdom": "^26.1.0",
45
- "msw": "^2.10.5",
42
+ "cssnano": "^7.1.2",
43
+ "eslint": "^9.39.1",
44
+ "jsdom": "^27.1.0",
45
+ "msw": "^2.12.0",
46
46
  "postcss": "^8.5.6",
47
- "postcss-preset-env": "^10.2.4",
47
+ "postcss-preset-env": "^10.4.0",
48
48
  "postcss-pxtorem": "^6.1.0",
49
49
  "prettier": "^3.6.2",
50
- "rollup-plugin-visualizer": "^6.0.3",
51
- "tailwindcss": "^4.1.12",
52
- "typescript": "^5.9.2",
53
- "vite": "^7.1.3",
50
+ "rollup-plugin-visualizer": "^6.0.5",
51
+ "tailwindcss": "^4.1.16",
52
+ "typescript": "^5.9.3",
53
+ "vite": "^7.2.1",
54
54
  "vite-plugin-svg-icons": "^2.0.1",
55
55
  "vitest": "^3.2.4",
56
- "vue-tsc": "^3.0.6"
56
+ "vue-tsc": "^3.1.3"
57
57
  },
58
58
  "msw": {
59
59
  "workerDirectory": "public"
60
60
  },
61
61
  "optionalDependencies": {
62
- "@commitlint/cli": "^19.8.1",
63
- "@commitlint/config-conventional": "^19.8.1",
62
+ "@commitlint/cli": "^20.1.0",
63
+ "@commitlint/config-conventional": "^20.0.0",
64
64
  "husky": "^9.1.7",
65
- "lint-staged": "^16.1.5"
65
+ "lint-staged": "^16.2.6"
66
66
  }
67
67
  }
package/dist/index.d.ts DELETED
@@ -1,2 +0,0 @@
1
-
2
- export { }
package/dist/index.js DELETED
@@ -1,255 +0,0 @@
1
- // src/index.ts
2
- import { readdirSync as readdirSync2, statSync } from "fs";
3
- import { readdir, readFile, writeFile } from "fs/promises";
4
- import path2 from "path";
5
- import { fileURLToPath } from "url";
6
- import artTemplate from "art-template";
7
- import { copy, ensureDirSync } from "fs-extra/esm";
8
- import minimist from "minimist";
9
- import ora from "ora";
10
- import colors2 from "picocolors";
11
-
12
- // src/constants.ts
13
- var DEFAULT_PROJECT_NAME = "basic-project";
14
- var TEMPLATES = ["vue", "react"];
15
- var GITHUB_ACTIONS = "GitHub Actions";
16
- var GITLAB_CI = "GitLab CI";
17
-
18
- // src/prompts.ts
19
- import { existsSync as existsSync2 } from "fs";
20
- import colors from "picocolors";
21
- import prompts from "prompts";
22
-
23
- // src/utils.ts
24
- import { existsSync, readdirSync } from "fs";
25
- import path from "path";
26
- import { remove } from "fs-extra/esm";
27
- function formatTargetDir(targetDir) {
28
- if (!targetDir) return targetDir;
29
- targetDir = targetDir.trim();
30
- if (targetDir[0] === "/") {
31
- targetDir = targetDir.slice(1);
32
- }
33
- if (targetDir.at(-1) === "/") {
34
- targetDir = targetDir.slice(0, -1);
35
- }
36
- return targetDir;
37
- }
38
- function getProjectName(targetDir) {
39
- if (!targetDir) {
40
- return DEFAULT_PROJECT_NAME;
41
- }
42
- return path.basename(path.resolve(targetDir));
43
- }
44
- function isValidPackageName(projectName) {
45
- return /^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test(projectName);
46
- }
47
- function toValidPackageName(projectName) {
48
- return projectName.trim().toLowerCase().replaceAll(/\s+/g, "-").replace(/^[._]/, "").replaceAll(/[^a-z\d\-~]+/g, "-");
49
- }
50
- function toUpperCasePackageName(projectName) {
51
- return projectName.split("-").map((str) => `${str[0].toUpperCase()}${str.slice(1)}`).join(" ");
52
- }
53
- function getPkgManagerInfo() {
54
- const userAgent = process.env.npm_config_user_agent;
55
- if (!userAgent) return;
56
- const [pkgManager] = userAgent.split(" ");
57
- const [name, version] = pkgManager.split("/");
58
- return { name, version };
59
- }
60
- function isEmptyFolder(dir) {
61
- const files = readdirSync(dir);
62
- return files.length === 0 || files.length === 1 && files[0] === ".git";
63
- }
64
- function clearFolder(dir) {
65
- if (!existsSync(dir)) return;
66
- const files = readdirSync(dir).filter((file) => file !== ".git");
67
- return Promise.all(files.map((file) => remove(path.resolve(dir, file))));
68
- }
69
-
70
- // src/prompts.ts
71
- function builtinTemplate(template) {
72
- return template && TEMPLATES.includes(template);
73
- }
74
- function onCancel() {
75
- throw new Error(`${colors.red("\u2716")} Operation cancelled`);
76
- }
77
- function styleTitle(title) {
78
- return colors.bold(colors.magenta(title));
79
- }
80
- function operationPrompts({ targetDir, template }) {
81
- const projectName = {
82
- type: targetDir ? null : "text",
83
- name: "projectName",
84
- message: styleTitle("Project name:"),
85
- initial: DEFAULT_PROJECT_NAME
86
- };
87
- const overwrite = {
88
- type: (nameAnswer) => {
89
- return existsSync2(nameAnswer) && !isEmptyFolder(nameAnswer) ? "select" : null;
90
- },
91
- name: "overwrite",
92
- message: (nameAnswer) => {
93
- const isCurrentDir = nameAnswer === ".";
94
- const dir = isCurrentDir ? "current directory" : `Target directory "${targetDir}"`;
95
- return styleTitle(`${dir} is not empty. Please choose how to proceed:`);
96
- },
97
- initial: 0,
98
- choices: [
99
- { title: "Cancel operation", value: "cancel" },
100
- { title: "Remove existing files and continue", value: "overwrite" },
101
- { title: "Ignore files and continue", value: "ignore" }
102
- ]
103
- };
104
- const overwriteChecker = {
105
- type: (overwriteAnswer) => {
106
- if (overwriteAnswer === "cancel") onCancel();
107
- return null;
108
- },
109
- name: "overwriteChecker"
110
- };
111
- const packageName = {
112
- type: (_, { projectName: nameAnswer }) => {
113
- return isValidPackageName(getProjectName(nameAnswer)) ? null : "text";
114
- },
115
- name: "packageName",
116
- message: styleTitle("Package name:"),
117
- initial: (_, { projectName: nameAnswer }) => toValidPackageName(getProjectName(nameAnswer)),
118
- validate: (name) => {
119
- return isValidPackageName(name) || "Invalid package.json name";
120
- }
121
- };
122
- const framework = {
123
- type: builtinTemplate(template) ? null : "select",
124
- name: "framework",
125
- message: template ? styleTitle(`${colors.red(template)} isn't a valid template. Please choose from below:`) : styleTitle("Select a framework:"),
126
- initial: 0,
127
- choices: [
128
- { title: colors.green("Vue"), value: "vue" },
129
- { title: colors.blue("React"), value: "react" }
130
- ]
131
- };
132
- return prompts([projectName, overwrite, overwriteChecker, packageName, framework], { onCancel });
133
- }
134
-
135
- // src/index.ts
136
- var cwd = process.cwd();
137
- var argv = minimist(process.argv.slice(2), {
138
- default: { gitlab: false, help: false },
139
- alias: { t: "template", l: "gitlab", h: "help" },
140
- string: ["_"]
141
- });
142
- var renameFiles = {
143
- _gitignore: ".gitignore",
144
- "_gitlab-ci.yml": ".gitlab-ci.yml"
145
- };
146
- var helpMessage = `
147
- Usage: create-component-hook [project name] [options]
148
-
149
- Create a new project in TypeScript.
150
- With no arguments, start the CLI in interactive mode.
151
-
152
- Options:
153
- -t, --template [name] Choose a framework template
154
- -l, --gitlab Use Gitlab CI/CD, default is Github CI/CD
155
- -h, --help Display this help message
156
-
157
- Available templates:
158
- ${colors2.green("vue")}
159
- ${colors2.blue("react")}
160
- `;
161
- async function writePackageJson(root, dir, packageName) {
162
- const pkgJson = await readFile(path2.join(dir, "package.json"), "utf-8");
163
- const pkg = JSON.parse(pkgJson);
164
- const targetPath = path2.join(root, "package.json");
165
- pkg.name = packageName;
166
- return writeFile(targetPath, `${JSON.stringify(pkg, null, 2)}
167
- `);
168
- }
169
- async function copyFolder(root, dir, packageName) {
170
- const isGitlab = argv.l || argv.gitlab;
171
- const files = await readdir(dir);
172
- const filterFiles = files.filter((file) => {
173
- const filterCi = isGitlab ? ".github" : ".gitlab";
174
- const filterCiYml = isGitlab ? "" : "_gitlab-ci.yml";
175
- return file !== "package.json" && file !== filterCi && file !== filterCiYml;
176
- });
177
- const rewriteOrCopyFile = (file) => {
178
- const targetPath = path2.join(root, renameFiles?.[file] ?? file);
179
- const templatePath = path2.join(dir, file);
180
- if (file.endsWith(".art")) {
181
- const isScript = file.endsWith(".js.art") || file.endsWith(".ts.art");
182
- const name = isScript ? packageName : toUpperCasePackageName(packageName);
183
- const replacedPath = targetPath.replace(".art", "");
184
- const renderedResult = artTemplate(templatePath, {
185
- projectName: name,
186
- gitRepository: isGitlab ? GITLAB_CI : GITHUB_ACTIONS
187
- });
188
- ensureDirSync(path2.dirname(replacedPath));
189
- return writeFile(replacedPath, renderedResult);
190
- }
191
- if (statSync(templatePath).isDirectory()) {
192
- const subFiles = readdirSync2(templatePath);
193
- const rewriteOrCopySubFilePromises = subFiles.map((subFile) => rewriteOrCopyFile(path2.join(file, subFile)));
194
- return Promise.all(rewriteOrCopySubFilePromises).then(() => {
195
- });
196
- } else {
197
- return copy(templatePath, targetPath);
198
- }
199
- };
200
- return Promise.all(filterFiles.map((file) => rewriteOrCopyFile(file)));
201
- }
202
- async function createApp() {
203
- const help = argv.h || argv.help;
204
- if (help) {
205
- console.log(helpMessage);
206
- return;
207
- }
208
- const targetDir = formatTargetDir(argv._[0]);
209
- const template = argv.t || argv.template;
210
- const result = await operationPrompts({ targetDir, template });
211
- const packageName = result.packageName || getProjectName(result.projectName);
212
- const framework = result.framework || template;
213
- const root = path2.join(cwd, result.projectName);
214
- const pkgManagerInfo = getPkgManagerInfo();
215
- const pkgManager = pkgManagerInfo?.name ?? "npm";
216
- const spinner = ora();
217
- console.log();
218
- spinner.start(colors2.yellow(`Scaffolding project...`));
219
- if (result.overwrite === "overwrite") {
220
- await clearFolder(root);
221
- } else {
222
- ensureDirSync(root);
223
- }
224
- const filePath = fileURLToPath(import.meta.url);
225
- const sharedDir = path2.resolve(filePath, "../..", "template-shared");
226
- const templateDir = path2.resolve(filePath, "../..", `template-${framework}`);
227
- const copyPromises = Promise.all([
228
- copyFolder(root, sharedDir, packageName),
229
- copyFolder(root, templateDir, packageName),
230
- writePackageJson(root, templateDir, packageName),
231
- new Promise((resolve) => setTimeout(resolve, 300))
232
- ]);
233
- copyPromises.then(() => {
234
- const cdProjectName = path2.relative(cwd, root);
235
- const formattedCdProjectName = cdProjectName.includes(" ") ? `"${cdProjectName}"` : cdProjectName;
236
- spinner.succeed(`${colors2.green("Scaffolded project in")} ${root}`);
237
- console.log(`
238
- ${colors2.green("Done. Now run:")}
239
- `);
240
- console.log(colors2.cyan(` cd ${formattedCdProjectName}`));
241
- if (pkgManager === "yarn") {
242
- console.log(colors2.cyan(` yarn`));
243
- console.log(colors2.cyan(` yarn dev`));
244
- } else {
245
- console.log(colors2.cyan(` ${pkgManager} install`));
246
- console.log(colors2.cyan(` ${pkgManager} run dev`));
247
- }
248
- console.log();
249
- }).catch(() => {
250
- spinner.fail(colors2.red("Failed to scaffold project"));
251
- });
252
- }
253
- createApp().catch((error) => {
254
- console.error(colors2.red(error.message));
255
- });