@component-hook/create-app 1.1.2 → 1.1.4

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.
Files changed (68) hide show
  1. package/README.md +6 -4
  2. package/dist/index.js +27 -23
  3. package/package.json +3 -3
  4. package/template-react/.vscode/extensions.json +9 -0
  5. package/template-react/.vscode/settings.json +24 -0
  6. package/template-react/README.md.art +86 -0
  7. package/template-react/eslint.config.js +18 -0
  8. package/template-react/index.html.art +13 -0
  9. package/template-react/lint-staged.config.js +6 -0
  10. package/template-react/package.json +68 -0
  11. package/template-react/pnpm-lock.yaml +9897 -0
  12. package/template-react/public/vite.svg +1 -0
  13. package/template-react/src/App.tsx +6 -0
  14. package/template-react/src/__tests__/e2e/home.spec.ts +40 -0
  15. package/template-react/src/__tests__/unit/pages/home/components/HelloWorld.test.tsx +45 -0
  16. package/template-react/src/__tests__/unit/pages/home/index.test.tsx +19 -0
  17. package/template-react/src/__tests__/unit/render/index.tsx +15 -0
  18. package/template-react/src/assets/svg-icons/react.svg +1 -0
  19. package/template-react/src/components/common/index.ts +1 -0
  20. package/template-react/src/components/common/svg-icon/index.ts +1 -0
  21. package/template-react/src/components/common/svg-icon/src/index.tsx +23 -0
  22. package/template-react/src/main.tsx +26 -0
  23. package/template-react/src/mocks/browser.ts +4 -0
  24. package/template-react/src/mocks/handlers/index.ts +1 -0
  25. package/template-react/src/mocks/server.ts +4 -0
  26. package/template-react/src/pages/home/components/hello-world/index.tsx +47 -0
  27. package/template-react/src/pages/home/index.module.css +8 -0
  28. package/template-react/src/pages/home/index.tsx +37 -0
  29. package/template-react/src/plugins/i18n/index.ts +15 -0
  30. package/template-react/src/plugins/i18n/locales/en-US.json +3 -0
  31. package/template-react/src/plugins/i18n/locales/zh-TW.json +3 -0
  32. package/template-react/src/router/index.tsx +22 -0
  33. package/template-react/src/stores/constants.ts +1 -0
  34. package/template-react/src/stores/index.ts +1 -0
  35. package/template-react/src/stores/middleware.ts +17 -0
  36. package/template-react/src/stores/modules/config.ts +25 -0
  37. package/template-react/src/styles/base.css +68 -0
  38. package/template-react/src/styles/common/all.css +1 -0
  39. package/template-react/src/styles/common/button.css +26 -0
  40. package/template-react/src/styles/index.css +3 -0
  41. package/template-react/src/styles/tailwind.css +14 -0
  42. package/template-react/src/vite-env.d.ts +9 -0
  43. package/template-react/tsconfig.app.json +32 -0
  44. package/template-react/tsconfig.vitest.json +10 -0
  45. package/template-react/vite.config.ts +50 -0
  46. package/template-react/vitest.config.ts +18 -0
  47. package/template-react/vitest.setup.ts +13 -0
  48. package/{template-vue → template-shared}/.github/actions/setup-environment/action.yml +1 -1
  49. package/{template-vue → template-shared}/.github/workflows/ci.yml +1 -1
  50. package/{template-vue → template-shared}/.github/workflows/deploy.yml +1 -1
  51. package/{template-vue → template-shared}/.github/workflows/preview.yml +1 -1
  52. package/template-vue/README.md.art +1 -1
  53. package/template-vue/package.json +20 -20
  54. package/template-vue/src/styles/base.css +14 -3
  55. /package/{template-vue → template-shared}/.browserslistrc +0 -0
  56. /package/{template-vue → template-shared}/.github/renovate.json +0 -0
  57. /package/{template-vue → template-shared}/.gitlab/setup.yml +0 -0
  58. /package/{template-vue → template-shared}/.husky/commit-msg +0 -0
  59. /package/{template-vue → template-shared}/.husky/pre-commit +0 -0
  60. /package/{template-vue → template-shared}/LICENSE +0 -0
  61. /package/{template-vue → template-shared}/_gitignore +0 -0
  62. /package/{template-vue → template-shared}/_gitlab-ci.yml +0 -0
  63. /package/{template-vue → template-shared}/commitlint.config.js +0 -0
  64. /package/{template-vue → template-shared}/playwright.config.ts +0 -0
  65. /package/{template-vue → template-shared}/postcss.config.js +0 -0
  66. /package/{template-vue → template-shared}/prettier.config.js +0 -0
  67. /package/{template-vue → template-shared}/tsconfig.json +0 -0
  68. /package/{template-vue → template-shared}/tsconfig.node.json +0 -0
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  Scaffolding a basic `typescript` project.
4
4
 
5
5
  > **Compatibility Note:**
6
- > Requires [Node.js](https://nodejs.org/en/) version 20+. However, some templates require a higher Node.js version to work, please upgrade if your package manager warns about it.
6
+ > Requires [Node.js](https://nodejs.org/en/) version 20.19+. However, some templates require a higher Node.js version to work, please upgrade if your package manager warns about it.
7
7
 
8
8
  <p>
9
9
  <a href="https://npm-stat.com/charts.html?package=@component-hook/create-app">
@@ -43,6 +43,7 @@ $ pnpm create @component-hook/app basic-app --template vue
43
43
  Currently supported template presets include:
44
44
 
45
45
  - `vue`
46
+ - `react`
46
47
 
47
48
  ## Project Features Overview
48
49
 
@@ -50,9 +51,9 @@ This project leverages modern frontend practices and tooling, covering developme
50
51
 
51
52
  ### Development Experience
52
53
 
53
- - **Written in TypeScript**: Provides type safety and better maintainability.
54
- - **Styled with Tailwind CSS**: Utility-first CSS framework for fast and consistent UI styling.
55
- - **SVG Support**: Integrated [`vite-plugin-svg-icons`](https://github.com/vbenjs/vite-plugin-svg-icons) to use SVGs as Vue components.
54
+ - `Written in TypeScript`: Provides type safety and better maintainability.
55
+ - `Styled with Tailwind CSS`: Utility-first CSS framework for fast and consistent UI styling.
56
+ - `SVG Support`: Integrated [`vite-plugin-svg-icons`](https://github.com/vbenjs/vite-plugin-svg-icons) to use SVGs as Vue components.
56
57
 
57
58
  ### API & Mocking
58
59
 
@@ -76,6 +77,7 @@ This project leverages modern frontend practices and tooling, covering developme
76
77
 
77
78
  - Minifies CSS with `cssnano`.
78
79
  - Converts px to rem using `postcss-pxtorem` for responsive design.
80
+ - Convert modern CSS into something most browsers can understand with `postcss-preset-env`.
79
81
  - Uses `rollup-plugin-visualizer` to analyze bundle sizes.
80
82
 
81
83
  ### CI / CD
package/dist/index.js CHANGED
@@ -11,7 +11,7 @@ import colors2 from "picocolors";
11
11
 
12
12
  // src/constants.ts
13
13
  var DEFAULT_PROJECT_NAME = "basic-project";
14
- var TEMPLATES = ["vue"];
14
+ var TEMPLATES = ["vue", "react"];
15
15
  var GITHUB_ACTIONS = "GitHub Actions";
16
16
  var GITLAB_CI = "GitLab CI";
17
17
 
@@ -125,8 +125,8 @@ function operationPrompts({ targetDir, template }) {
125
125
  message: template ? styleTitle(`${colors.red(template)} isn't a valid template. Please choose from below:`) : styleTitle("Select a framework:"),
126
126
  initial: 0,
127
127
  choices: [
128
- { title: colors.green("Vue"), value: "vue" }
129
- // { title: 'colors.blue('React'), value: 'react' },
128
+ { title: colors.green("Vue"), value: "vue" },
129
+ { title: colors.blue("React"), value: "react" }
130
130
  ]
131
131
  };
132
132
  return prompts([projectName, overwrite, overwriteChecker, packageName, framework], { onCancel });
@@ -156,25 +156,27 @@ Options:
156
156
 
157
157
  Available templates:
158
158
  ${colors2.green("vue")}
159
+ ${colors2.blue("react")}
159
160
  `;
160
- async function copyTemplateFolder(root, templateDir, packageName) {
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) {
161
170
  const isGitlab = argv.l || argv.gitlab;
162
- const [files, pkgJson] = await Promise.all([
163
- readdir(templateDir),
164
- readFile(path2.join(templateDir, "package.json"), "utf-8")
165
- ]);
171
+ const files = await readdir(dir);
166
172
  const filterFiles = files.filter((file) => {
167
173
  const filterCi = isGitlab ? ".github" : ".gitlab";
168
174
  const filterCiYml = isGitlab ? "" : "_gitlab-ci.yml";
169
175
  return file !== "package.json" && file !== filterCi && file !== filterCiYml;
170
176
  });
171
- const pkg = JSON.parse(pkgJson);
172
- const rewriteOrCopyFile = (file, content) => {
177
+ const rewriteOrCopyFile = (file) => {
173
178
  const targetPath = path2.join(root, renameFiles?.[file] ?? file);
174
- if (content) {
175
- return writeFile(targetPath, content);
176
- }
177
- const templatePath = path2.join(templateDir, file);
179
+ const templatePath = path2.join(dir, file);
178
180
  if (file.endsWith(".art")) {
179
181
  const isScript = file.endsWith(".js.art") || file.endsWith(".ts.art");
180
182
  const name = isScript ? packageName : toUpperCasePackageName(packageName);
@@ -195,13 +197,7 @@ async function copyTemplateFolder(root, templateDir, packageName) {
195
197
  return copy(templatePath, targetPath);
196
198
  }
197
199
  };
198
- pkg.name = packageName;
199
- return Promise.all([
200
- ...filterFiles.map((file) => rewriteOrCopyFile(file)),
201
- rewriteOrCopyFile("package.json", `${JSON.stringify(pkg, null, 2)}
202
- `),
203
- new Promise((resolve) => setTimeout(resolve, 300))
204
- ]);
200
+ return Promise.all(filterFiles.map((file) => rewriteOrCopyFile(file)));
205
201
  }
206
202
  async function createApp() {
207
203
  const help = argv.h || argv.help;
@@ -225,8 +221,16 @@ async function createApp() {
225
221
  } else {
226
222
  ensureDirSync(root);
227
223
  }
228
- const templateDir = path2.resolve(fileURLToPath(import.meta.url), "../..", `template-${framework}`);
229
- copyTemplateFolder(root, templateDir, packageName).then(() => {
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(() => {
230
234
  const cdProjectName = path2.relative(cwd, root);
231
235
  const formattedCdProjectName = cdProjectName.includes(" ") ? `"${cdProjectName}"` : cdProjectName;
232
236
  spinner.succeed(`${colors2.green("Scaffolded project in")} ${root}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@component-hook/create-app",
3
- "version": "1.1.2",
3
+ "version": "1.1.4",
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.3"
17
+ "node": ">=20.19.4"
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.0",
30
+ "fs-extra": "^11.3.1",
31
31
  "minimist": "^1.2.8",
32
32
  "ora": "^8.2.0",
33
33
  "picocolors": "^1.1.1",
@@ -0,0 +1,9 @@
1
+ {
2
+ "recommendations": [
3
+ "bradlc.vscode-tailwindcss",
4
+ "esbenp.prettier-vscode",
5
+ "csstools.postcss",
6
+ "cpylua.language-postcss",
7
+ "streetsidesoftware.code-spell-checker"
8
+ ]
9
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "[nginx]": {
3
+ "editor.defaultFormatter": "raynigon.nginx-formatter"
4
+ },
5
+ "editor.tabSize": 2,
6
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
7
+ "debug.javascript.autoAttachFilter": "smart",
8
+ "editor.formatOnSave": true,
9
+ "[dart]": {
10
+ "editor.formatOnSave": true,
11
+ "editor.formatOnType": true,
12
+ "editor.rulers": [120],
13
+ "editor.selectionHighlight": false,
14
+ "editor.suggest.snippetsPreventQuickSuggestions": false,
15
+ "editor.suggestSelection": "first",
16
+ "editor.tabCompletion": "onlySnippets",
17
+ "editor.wordBasedSuggestions": "off"
18
+ },
19
+ "workbench.editor.splitInGroupLayout": "vertical",
20
+ "terminal.integrated.shellIntegration.enabled": true,
21
+ "files.associations": {},
22
+ "typescript.tsdk": "node_modules/typescript/lib",
23
+ "cSpell.words": ["dotenv", "unplugin", "Sonarjs", "typecheck", "pxtorem", "norem", "partialize"]
24
+ }
@@ -0,0 +1,86 @@
1
+ # {{projectName}}
2
+
3
+ This project is built with [react](https://react.dev/) + [vite](https://vite.dev/), using [pnpm](https://pnpm.io/) for package management and [zustand](https://zustand-demo.pmnd.rs/) for state management.
4
+
5
+ ## Features
6
+
7
+ - **Development Experience**: Written in [typeScript](https://www.typescriptlang.org/), styled with [tailwindcss](https://tailwindcss.com/), and structured with [react-router-dom](https://reactrouter.com/), and [react-i18next](https://react.i18next.com/). Supports SVGs ([vite-plugin-svg-icons](https://github.com/vbenjs/vite-plugin-svg-icons)).
8
+ - **API & Mocking**: Handles requests with [axios](https://axios-http.com/docs/intro) and mocks APIs using [msw](https://mswjs.io/).
9
+ - **Code Quality**: Enforces standards with [eslint](https://eslint.org/) and [prettier](https://prettier.io/), with [husky](https://www.npmjs.com/package/husky), [commitlint](https://commitlint.js.org/#/), and [lint-staged](https://github.com/okonet/lint-staged) for commit validation.
10
+ - **Testing**: Uses [vitest](https://vitest.dev/) + [testing-library](https://testing-library.com/) for unit testing and [playwright](https://playwright.dev/) for E2E testing.
11
+ - **Optimization**: Compresses CSS with [cssnano](https://cssnano.github.io/cssnano/), converts units with [postcss-pxtorem](https://www.npmjs.com/package/postcss-pxtorem), convert modern CSS into something most browsers can understand with [postcss-preset-env](https://www.npmjs.com/package/postcss-preset-env), and analyzes assets with [rollup-plugin-visualizer](https://github.com/btd/rollup-plugin-visualizer).
12
+ - **CI/CD**: Integrates `{{gitRepository}}` for automated testing and deployment.
13
+
14
+ ## Code Features / Opinions
15
+
16
+ - Project root aliased as `@` to `<project_root>/src`
17
+ - ESlint plugin use [@component-hook/eslint-plugin](https://www.npmjs.com/package/@component-hook/eslint-plugin?activeTab=readme)
18
+ - if encounter npx: command not found, can execute `ln -s $(which npx) /usr/local/bin/npx` in zsh
19
+ - Predefined and fully typed global variables:
20
+ - `VITE_APP_VERSION` is read from `package.json` version at build time
21
+ - `VITE_APP_BUILD_EPOCH` is populated as `new Date().getTime()` at build time
22
+ - `VITE_APP_MOCK` is use mock environment
23
+
24
+ ## Project Files
25
+
26
+ ```text
27
+ src/
28
+ ├── __tests__/
29
+ │ ├── __mocks__/
30
+ │ ├── e2e/*
31
+ │ └── unit/*
32
+ ├── assets/*
33
+ │ └── svg-icons
34
+ │ └── react.svg
35
+ ├── components/
36
+ │ └── common
37
+ │ ├── svg-icon/
38
+ │ │ ├── src
39
+ │ │ │ └── index.tsx
40
+ │ │ └── index.ts
41
+ │ └── index.ts
42
+ ├── constants/*
43
+ ├── hooks/*
44
+ ├── locales/
45
+ │ ├── en-US.json
46
+ │ └── zh-CN.json
47
+ ├── mocks/
48
+ │ ├── handlers/*
49
+ │ │ ├── modules/*
50
+ │ │ └── index.ts
51
+ │ │── browser.ts
52
+ │ └── server.ts
53
+ ├── pages/
54
+ │ └── home/
55
+ │ ├── components
56
+ │ │ └── hello-world
57
+ │ │ └── index.tsx
58
+ │ ├── index.module.css
59
+ │ └── index.tsx
60
+ ├── plugins/
61
+ │ └── i18n
62
+ │ ├── locales
63
+ │ │ ├── es-US.json
64
+ │ │ └── zh-TW.json
65
+ │ └── index.ts
66
+ ├── router/
67
+ │ └── index.tsx
68
+ ├── stores/
69
+ │ ├── modules
70
+ │ │ └── config.ts
71
+ │ ├── constants.ts
72
+ │ ├── index.ts
73
+ │ └── middleware.ts
74
+ ├── styles/
75
+ │ ├── common/
76
+ | │ ├── all.css
77
+ | │ └── button.css
78
+ │ ├── base.css
79
+ │ ├── index.css
80
+ │ └── tailwind.css
81
+ ├── types/*
82
+ ├── utils/*
83
+ ├── App.tsx
84
+ ├── vite-env.d.ts
85
+ └── main.tsx
86
+ ```
@@ -0,0 +1,18 @@
1
+ import componentHookPlugin from '@component-hook/eslint-plugin';
2
+
3
+ export default [
4
+ ...componentHookPlugin.configs.basic,
5
+ ...componentHookPlugin.configs.react,
6
+ componentHookPlugin.configs.prettier,
7
+ ...componentHookPlugin.configs.sonarjs,
8
+ componentHookPlugin.configs.security,
9
+ ...componentHookPlugin.configs.markdown,
10
+ {
11
+ files: ['**/__tests__/unit/**/*.test.[jt]s?(x)'],
12
+ ...componentHookPlugin.configs['testing-library/react'],
13
+ },
14
+ {
15
+ files: ['**/__tests__/e2e/**/*.spec.[jt]s?(x)'],
16
+ ...componentHookPlugin.configs.playwright,
17
+ },
18
+ ];
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>{{projectName}}</title>
8
+ </head>
9
+ <body>
10
+ <div id="root"></div>
11
+ <script type="module" src="/src/main.tsx"></script>
12
+ </body>
13
+ </html>
@@ -0,0 +1,6 @@
1
+ /** @type {import('lint-staged').Configuration} */
2
+
3
+ export default {
4
+ '*.{ts,tsx}': () => 'pnpm typecheck',
5
+ '*.{ts,js,tsx,jsx}': () => 'pnpm lint',
6
+ };
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "react-starter",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "type": "module",
6
+ "packageManager": "pnpm@10.15.0",
7
+ "scripts": {
8
+ "dev": "vite",
9
+ "dev:mock": "MOCK=true vite",
10
+ "build": "pnpm typecheck && vite build",
11
+ "lint": "eslint --fix .",
12
+ "test:unit": "vitest --coverage",
13
+ "test:e2e": "playwright test --headed",
14
+ "test:ui-e2e": "playwright test --ui",
15
+ "test:ci-e2e": "playwright test",
16
+ "typecheck": "tsc --noEmit",
17
+ "prepare": "husky",
18
+ "preview": "vite preview"
19
+ },
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",
27
+ "zustand": "^5.0.8"
28
+ },
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",
34
+ "@testing-library/react": "^16.3.0",
35
+ "@testing-library/user-event": "^14.6.1",
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",
41
+ "@vitest/coverage-v8": "^3.2.4",
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",
47
+ "postcss": "^8.5.6",
48
+ "postcss-preset-env": "^10.2.4",
49
+ "postcss-pxtorem": "^6.1.0",
50
+ "prettier": "^3.6.2",
51
+ "tailwindcss": "^4.1.12",
52
+ "typescript": "^5.9.2",
53
+ "vite": "^7.1.3",
54
+ "vite-plugin-svg-icons": "^2.0.1",
55
+ "vitest": "^3.2.4"
56
+ },
57
+ "optionalDependencies": {
58
+ "@commitlint/cli": "^19.8.1",
59
+ "@commitlint/config-conventional": "^19.8.1",
60
+ "husky": "^9.1.7",
61
+ "lint-staged": "^16.1.5"
62
+ },
63
+ "msw": {
64
+ "workerDirectory": [
65
+ "public"
66
+ ]
67
+ }
68
+ }