nsbp-cli 0.2.27 → 0.2.30

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 (40) hide show
  1. package/README.md +1 -1
  2. package/bin/nsbp.js +97 -74
  3. package/package.json +1 -1
  4. package/templates/basic/.husky/README.md +47 -0
  5. package/templates/basic/.husky/commit-msg +17 -0
  6. package/templates/basic/.husky/pre-commit +4 -0
  7. package/templates/basic/.husky/pre-push +4 -0
  8. package/templates/basic/.prettierrc.js +13 -0
  9. package/templates/basic/README.md +43 -0
  10. package/templates/basic/docs/DEVELOPMENT_GUIDE.md +290 -0
  11. package/templates/basic/docs/ESLINT_AND_PRETTIER.md +184 -0
  12. package/templates/basic/docs/HUSKY_9_UPGRADE.md +76 -0
  13. package/templates/basic/docs/HUSKY_ESLINT_SETUP.md +293 -0
  14. package/templates/basic/docs/SETUP_GIT_HOOKS.md +106 -0
  15. package/templates/basic/eslint.config.js +98 -0
  16. package/templates/basic/gitignore +3 -0
  17. package/templates/basic/package.json +27 -3
  18. package/templates/basic/scripts/setup-husky.js +24 -0
  19. package/templates/basic/src/Routers.tsx +4 -5
  20. package/templates/basic/src/client/index.tsx +5 -1
  21. package/templates/basic/src/component/Header.tsx +10 -10
  22. package/templates/basic/src/component/Layout.tsx +9 -3
  23. package/templates/basic/src/component/Theme.tsx +5 -1
  24. package/templates/basic/src/containers/Home.tsx +141 -76
  25. package/templates/basic/src/containers/Photo.tsx +30 -18
  26. package/templates/basic/src/externals/window.d.ts +3 -1
  27. package/templates/basic/src/reducers/photo.ts +7 -2
  28. package/templates/basic/src/server/index.ts +35 -26
  29. package/templates/basic/src/server/photo.ts +14 -7
  30. package/templates/basic/src/server/utils.tsx +9 -7
  31. package/templates/basic/src/services/home.ts +1 -1
  32. package/templates/basic/src/services/photo.ts +28 -30
  33. package/templates/basic/src/store/constants.ts +1 -1
  34. package/templates/basic/src/store/index.ts +2 -1
  35. package/templates/basic/src/styled/component/header.ts +5 -1
  36. package/templates/basic/src/styled/home.ts +100 -24
  37. package/templates/basic/src/styled/photo.ts +2 -2
  38. package/templates/basic/src/utils/config.ts +1 -1
  39. package/templates/basic/src/utils/fetch.ts +4 -8
  40. package/templates/basic/src/utils/index.ts +1 -1
package/README.md CHANGED
@@ -147,7 +147,7 @@ node ./bin/nsbp.js --help # Test CLI locally
147
147
 
148
148
  - **Package Name**: `nsbp-cli`
149
149
  - **Bin Command**: `nsbp` (install globally and run `nsbp --help`)
150
- - **Version**: `0.2.27`
150
+ - **Version**: `0.2.30`
151
151
  - **Dependencies**: chalk, commander, fs-extra, inquirer
152
152
  - **Package Manager**: Uses pnpm (also compatible with npm)
153
153
  - **Node Version**: >=16.0.0
package/bin/nsbp.js CHANGED
@@ -1,55 +1,59 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- const { Command } = require('commander');
4
- const chalk = require('chalk');
5
- const fs = require('fs-extra');
6
- const path = require('path');
7
- const { execSync } = require('child_process');
8
- const inquirer = require('inquirer');
3
+ const { Command } = require('commander')
4
+ const chalk = require('chalk')
5
+ const fs = require('fs-extra')
6
+ const path = require('path')
7
+ const { execSync } = require('child_process')
8
+ const inquirer = require('inquirer')
9
9
 
10
10
  // Read version from package.json dynamically
11
- const packageJson = require('../package.json');
11
+ const packageJson = require('../package.json')
12
12
 
13
- const program = new Command();
13
+ const program = new Command()
14
14
 
15
15
  program
16
16
  .name('nsbp')
17
17
  .description('CLI tool to create NSBP (Node React SSR by Webpack) projects')
18
- .version(packageJson.version);
18
+ .version(packageJson.version)
19
19
 
20
20
  program
21
21
  .command('create <project-name>')
22
22
  .description('Create a new NSBP project')
23
- .option('-t, --template <template>', 'Specify template (basic, blog, ecommerce)', 'basic')
23
+ .option(
24
+ '-t, --template <template>',
25
+ 'Specify template (basic, blog, ecommerce)',
26
+ 'basic'
27
+ )
24
28
  .option('--skip-install', 'Skip pnpm install')
25
29
  .action(async (projectName, options) => {
26
- console.log(chalk.cyan(`🚀 Creating NSBP project: ${projectName}`));
27
-
30
+ console.log(chalk.cyan(`🚀 Creating NSBP project: ${projectName}`))
31
+
28
32
  try {
29
33
  // Check if directory already exists
30
- const targetDir = path.join(process.cwd(), projectName);
34
+ const targetDir = path.join(process.cwd(), projectName)
31
35
  if (fs.existsSync(targetDir)) {
32
36
  const { overwrite } = await inquirer.prompt([
33
37
  {
34
38
  type: 'confirm',
35
39
  name: 'overwrite',
36
40
  message: `Directory "${projectName}" already exists. Overwrite?`,
37
- default: false,
38
- },
39
- ]);
41
+ default: false
42
+ }
43
+ ])
40
44
  if (!overwrite) {
41
- console.log(chalk.yellow('Operation cancelled.'));
42
- process.exit(0);
45
+ console.log(chalk.yellow('Operation cancelled.'))
46
+ process.exit(0)
43
47
  }
44
- fs.removeSync(targetDir);
48
+ fs.removeSync(targetDir)
45
49
  }
46
50
 
47
51
  // Create project directory
48
- fs.ensureDirSync(targetDir);
52
+ fs.ensureDirSync(targetDir)
49
53
 
50
54
  // Get template source path from built-in templates
51
- const templateSource = path.join(__dirname, '../templates/basic');
52
-
55
+ const templateSource = path.join(__dirname, '../templates/basic')
56
+
53
57
  // List of files/directories to copy
54
58
  const copyItems = [
55
59
  'src',
@@ -64,115 +68,134 @@ program
64
68
  'tsconfig.json',
65
69
  '.prettierrc',
66
70
  '.prettierignore',
71
+ '.prettierrc.js',
72
+ 'eslint.config.js',
73
+ '.husky',
67
74
  'gitignore',
68
75
  'Makefile',
69
76
  'README.md'
70
- ];
77
+ ]
71
78
 
72
79
  // Copy each item
73
- console.log(chalk.cyan('📦 Copying project files...'));
80
+ console.log(chalk.cyan('📦 Copying project files...'))
74
81
  for (const item of copyItems) {
75
- const source = path.join(templateSource, item);
76
- const target = path.join(targetDir, item);
82
+ const source = path.join(templateSource, item)
83
+ const target = path.join(targetDir, item)
77
84
  if (fs.existsSync(source)) {
78
85
  if (fs.statSync(source).isDirectory()) {
79
86
  fs.copySync(source, target, {
80
87
  filter: (src) => {
81
88
  // Exclude node_modules, build, .temp_cache, etc.
82
89
  // Use relative path to avoid matching parent directory names
83
- const relativePath = path.relative(source, src);
84
- const segments = relativePath.split(path.sep);
85
- const excluded = ['node_modules', '.temp_cache', 'build', '.git', '.DS_Store', '.serena'];
86
- return !segments.some(seg => excluded.includes(seg));
90
+ const relativePath = path.relative(source, src)
91
+ const segments = relativePath.split(path.sep)
92
+ const excluded = [
93
+ 'node_modules',
94
+ '.temp_cache',
95
+ 'build',
96
+ '.git',
97
+ '.DS_Store',
98
+ '.serena'
99
+ ]
100
+ return !segments.some((seg) => excluded.includes(seg))
87
101
  }
88
- });
102
+ })
89
103
  } else {
90
- fs.copySync(source, target);
104
+ fs.copySync(source, target)
91
105
  }
92
106
  }
93
107
  }
94
108
 
95
109
  // Rename gitignore to .gitignore
96
- const gitignorePath = path.join(targetDir, 'gitignore');
110
+ const gitignorePath = path.join(targetDir, 'gitignore')
97
111
  if (fs.existsSync(gitignorePath)) {
98
- fs.renameSync(gitignorePath, path.join(targetDir, '.gitignore'));
112
+ fs.renameSync(gitignorePath, path.join(targetDir, '.gitignore'))
99
113
  }
100
114
 
101
115
  // Create package.json for new project
102
- const originalPackage = require(path.join(templateSource, 'package.json'));
116
+ const originalPackage = require(path.join(templateSource, 'package.json'))
103
117
  const newPackage = {
104
118
  ...originalPackage,
105
119
  name: projectName,
106
120
  version: '1.0.0',
107
121
  description: `NSBP project: ${projectName}`
108
- };
122
+ }
109
123
 
110
124
  fs.writeFileSync(
111
125
  path.join(targetDir, 'package.json'),
112
126
  JSON.stringify(newPackage, null, 2)
113
- );
127
+ )
114
128
 
115
129
  // Remove package-lock.json if exists (use pnpm instead)
116
- const packageLockPath = path.join(targetDir, 'package-lock.json');
130
+ const packageLockPath = path.join(targetDir, 'package-lock.json')
117
131
  if (fs.existsSync(packageLockPath)) {
118
- fs.removeSync(packageLockPath);
132
+ fs.removeSync(packageLockPath)
119
133
  }
120
134
 
121
135
  // Create .npmignore to prevent package-lock.json from being committed
122
- const npmignorePath = path.join(targetDir, '.npmignore');
136
+ const npmignorePath = path.join(targetDir, '.npmignore')
123
137
  if (!fs.existsSync(npmignorePath)) {
124
- fs.writeFileSync(npmignorePath, 'package-lock.json\n');
138
+ fs.writeFileSync(npmignorePath, 'package-lock.json\n')
125
139
  }
126
140
 
127
141
  // Optionally install dependencies
128
142
  if (!options.skipInstall) {
129
143
  // Check if pnpm is available
130
144
  try {
131
- execSync('which pnpm', { stdio: 'ignore' });
145
+ execSync('which pnpm', { stdio: 'ignore' })
132
146
  } catch {
133
- console.error(chalk.red('❌ pnpm is not installed or not available in PATH.'));
134
- console.error(chalk.yellow('Please install pnpm before continuing:'));
135
- console.error(chalk.cyan(' npm install -g pnpm'));
136
- console.error(chalk.yellow('Or use --skip-install flag to skip dependency installation.'));
137
- process.exit(1);
147
+ console.error(
148
+ chalk.red(' pnpm is not installed or not available in PATH.')
149
+ )
150
+ console.error(chalk.yellow('Please install pnpm before continuing:'))
151
+ console.error(chalk.cyan(' npm install -g pnpm'))
152
+ console.error(
153
+ chalk.yellow(
154
+ 'Or use --skip-install flag to skip dependency installation.'
155
+ )
156
+ )
157
+ process.exit(1)
138
158
  }
139
-
140
- console.log(chalk.cyan('📦 Installing dependencies...'));
141
- process.chdir(targetDir);
142
- execSync('pnpm install', { stdio: 'inherit' });
159
+
160
+ console.log(chalk.cyan('📦 Installing dependencies...'))
161
+ process.chdir(targetDir)
162
+ execSync('pnpm install', { stdio: 'inherit' })
143
163
  }
144
164
 
145
- console.log(chalk.green(`✅ NSBP project "${projectName}" created successfully!`));
146
- console.log(chalk.yellow('\nNext steps:'));
147
- console.log(` cd ${projectName}`);
165
+ console.log(
166
+ chalk.green(`✅ NSBP project "${projectName}" created successfully!`)
167
+ )
168
+ console.log(chalk.yellow('\nNext steps:'))
169
+ console.log(` cd ${projectName}`)
148
170
  if (options.skipInstall) {
149
- console.log(' pnpm install');
171
+ console.log(' pnpm install')
150
172
  }
151
- console.log(' pnpm run dev');
152
- console.log(chalk.cyan('\nHappy coding! 🎉'));
153
-
173
+ console.log(' pnpm run dev')
174
+ console.log(chalk.cyan('\nHappy coding! 🎉'))
154
175
  } catch (error) {
155
- console.error(chalk.red(`❌ Error creating project: ${error.message}`));
156
- process.exit(1);
176
+ console.error(chalk.red(`❌ Error creating project: ${error.message}`))
177
+ process.exit(1)
157
178
  }
158
- });
179
+ })
159
180
 
160
181
  program
161
182
  .command('info')
162
183
  .description('Display information about NSBP')
163
184
  .action(() => {
164
- console.log(chalk.cyan('NSBP - Node React SSR by Webpack'));
165
- console.log(chalk.gray('A lightweight React SSR framework with full Webpack control.'));
166
- console.log('');
167
- console.log(chalk.yellow('Key Features:'));
168
- console.log(' • ~60% less resource usage than Next.js');
169
- console.log(' Full Webpack configuration control');
170
- console.log(' • TypeScript support out of the box');
171
- console.log(' • Built-in image service');
172
- console.log('');
173
- console.log(chalk.cyan('Website: ') + 'https://github.com/nsbp/nsbp');
174
- console.log(chalk.cyan('Usage: ') + 'nsbp create my-app');
175
- });
185
+ console.log(chalk.cyan('NSBP - Node React SSR by Webpack'))
186
+ console.log(
187
+ chalk.gray('A lightweight React SSR framework with full Webpack control.')
188
+ )
189
+ console.log('')
190
+ console.log(chalk.yellow('Key Features:'))
191
+ console.log(' • Lightweight and flexible')
192
+ console.log(' • Full Webpack configuration control')
193
+ console.log(' • TypeScript support out of the box')
194
+ console.log(' Built-in image service')
195
+ console.log('')
196
+ console.log(chalk.cyan('Website: ') + 'https://github.com/nsbp/nsbp')
197
+ console.log(chalk.cyan('Usage: ') + 'nsbp create my-app')
198
+ })
176
199
 
177
200
  // Parse command line arguments
178
- program.parse();
201
+ program.parse()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nsbp-cli",
3
- "version": "0.2.27",
3
+ "version": "0.2.30",
4
4
  "description": "CLI tool for creating NSBP (Node React SSR by Webpack) projects",
5
5
  "main": "index.js",
6
6
  "homepage": "https://nsbp.erishen.cn/",
@@ -0,0 +1,47 @@
1
+ # Husky Git Hooks
2
+
3
+ This directory contains Git hooks configured by Husky.
4
+
5
+ ## Available Hooks
6
+
7
+ - **pre-commit**: Runs linting on staged files before commit
8
+ - **pre-push**: Runs full lint check before pushing
9
+ - **commit-msg**: Validates commit message format
10
+
11
+ ## Commit Message Format
12
+
13
+ Follow the Conventional Commits specification:
14
+
15
+ ```
16
+ <type>(<scope>): <subject>
17
+
18
+ <body>
19
+
20
+ <footer>
21
+ ```
22
+
23
+ ### Types
24
+
25
+ - `feat`: A new feature
26
+ - `fix`: A bug fix
27
+ - `docs`: Documentation only changes
28
+ - `style`: Code style changes (formatting, etc.)
29
+ - `refactor`: Code change that neither fixes a bug nor adds a feature
30
+ - `test`: Adding missing tests or correcting existing tests
31
+ - `chore`: Maintenance tasks
32
+ - `build`: Changes that affect the build system
33
+ - `ci`: Changes to CI configuration files
34
+ - `perf`: Performance improvements
35
+ - `revert`: Reverts a previous commit
36
+
37
+ ### Example
38
+
39
+ ```
40
+ feat(core): add SSR data preloading support
41
+
42
+ - Implement loadData in route config
43
+ - Add server-side data fetching utilities
44
+ - Update hydration logic
45
+
46
+ Closes #123
47
+ ```
@@ -0,0 +1,17 @@
1
+ #!/bin/sh
2
+ . "$(dirname "$0")/_/husky.sh"
3
+
4
+ # Validate commit message format
5
+ commit_regex='^(feat|fix|docs|style|refactor|test|chore|build|ci|perf|revert|BREAKING CHANGE)(\(.+\))?: .{1,50}'
6
+
7
+ if ! grep -qE "$commit_regex" "$1"; then
8
+ echo ""
9
+ echo "❌ Invalid commit message format."
10
+ echo ""
11
+ echo "Valid format: <type>(<scope>): <subject>"
12
+ echo ""
13
+ echo "Types: feat, fix, docs, style, refactor, test, chore, build, ci, perf, revert"
14
+ echo "Example: feat(components): add new button component"
15
+ echo ""
16
+ exit 1
17
+ fi
@@ -0,0 +1,4 @@
1
+ #!/bin/sh
2
+ . "$(dirname "$0")/_/husky.sh"
3
+
4
+ npx lint-staged
@@ -0,0 +1,4 @@
1
+ #!/bin/sh
2
+ . "$(dirname "$0")/_/husky.sh"
3
+
4
+ pnpm run lint
@@ -0,0 +1,13 @@
1
+ export default {
2
+ semi: false,
3
+ singleQuote: true,
4
+ tabWidth: 2,
5
+ trailingComma: 'es5',
6
+ printWidth: 100,
7
+ arrowParens: 'always',
8
+ endOfLine: 'lf',
9
+ plugins: ['prettier-plugin-organize-imports'],
10
+ importOrder: ['^react', '^@/(.*)$', '^[./]'],
11
+ importOrderSeparation: true,
12
+ importOrderSortSpecifiers: true
13
+ }
@@ -2,6 +2,49 @@
2
2
 
3
3
  🌐 **Online Demo**: [https://nsbp.erishen.cn/](https://nsbp.erishen.cn/)
4
4
 
5
+ ## 🚀 快速开始
6
+
7
+ ```bash
8
+ # 1. 安装依赖
9
+ pnpm install
10
+
11
+ # 2. 初始化 Git hooks(代码质量检查)
12
+ pnpm run prepare
13
+
14
+ # 3. 配置环境变量
15
+ cp .env.example .env
16
+
17
+ # 4. 启动开发环境
18
+ pnpm run dev
19
+ ```
20
+
21
+ ## 📝 开发工具
22
+
23
+ 本项目配置了完整的代码质量检查工具:
24
+
25
+ - **ESLint**: TypeScript + React 代码质量检查
26
+ - **Prettier**: 自动代码格式化
27
+ - **Husky**: Git hooks 自动化
28
+
29
+ ### 代码检查命令
30
+
31
+ ```bash
32
+ pnpm run lint # Lint 检查
33
+ pnpm run lint:fix # Lint 自动修复
34
+ pnpm run format # 格式化代码
35
+ ```
36
+
37
+ ### Git Hooks
38
+
39
+ - `pre-commit`: 提交前自动 lint 和格式化
40
+ - `pre-push`: 推送前运行完整 lint 检查
41
+ - `commit-msg`: 验证提交信息格式(Conventional Commits)
42
+
43
+ 详细配置请查看:
44
+ - [docs/ESLINT_AND_PRETTIER.md](./docs/ESLINT_AND_PRETTIER.md) - ESLint 和 Prettier 配置
45
+ - [docs/SETUP_GIT_HOOKS.md](./docs/SETUP_GIT_HOOKS.md) - Git hooks 配置
46
+ - [docs/DEVELOPMENT_GUIDE.md](./docs/DEVELOPMENT_GUIDE.md) - 完整开发指南
47
+
5
48
  ## 环境变量配置
6
49
 
7
50
  ### 快速开始