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.
- package/README.md +1 -1
- package/bin/nsbp.js +97 -74
- package/package.json +1 -1
- package/templates/basic/.husky/README.md +47 -0
- package/templates/basic/.husky/commit-msg +17 -0
- package/templates/basic/.husky/pre-commit +4 -0
- package/templates/basic/.husky/pre-push +4 -0
- package/templates/basic/.prettierrc.js +13 -0
- package/templates/basic/README.md +43 -0
- package/templates/basic/docs/DEVELOPMENT_GUIDE.md +290 -0
- package/templates/basic/docs/ESLINT_AND_PRETTIER.md +184 -0
- package/templates/basic/docs/HUSKY_9_UPGRADE.md +76 -0
- package/templates/basic/docs/HUSKY_ESLINT_SETUP.md +293 -0
- package/templates/basic/docs/SETUP_GIT_HOOKS.md +106 -0
- package/templates/basic/eslint.config.js +98 -0
- package/templates/basic/gitignore +3 -0
- package/templates/basic/package.json +27 -3
- package/templates/basic/scripts/setup-husky.js +24 -0
- package/templates/basic/src/Routers.tsx +4 -5
- package/templates/basic/src/client/index.tsx +5 -1
- package/templates/basic/src/component/Header.tsx +10 -10
- package/templates/basic/src/component/Layout.tsx +9 -3
- package/templates/basic/src/component/Theme.tsx +5 -1
- package/templates/basic/src/containers/Home.tsx +141 -76
- package/templates/basic/src/containers/Photo.tsx +30 -18
- package/templates/basic/src/externals/window.d.ts +3 -1
- package/templates/basic/src/reducers/photo.ts +7 -2
- package/templates/basic/src/server/index.ts +35 -26
- package/templates/basic/src/server/photo.ts +14 -7
- package/templates/basic/src/server/utils.tsx +9 -7
- package/templates/basic/src/services/home.ts +1 -1
- package/templates/basic/src/services/photo.ts +28 -30
- package/templates/basic/src/store/constants.ts +1 -1
- package/templates/basic/src/store/index.ts +2 -1
- package/templates/basic/src/styled/component/header.ts +5 -1
- package/templates/basic/src/styled/home.ts +100 -24
- package/templates/basic/src/styled/photo.ts +2 -2
- package/templates/basic/src/utils/config.ts +1 -1
- package/templates/basic/src/utils/fetch.ts +4 -8
- 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.
|
|
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(
|
|
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 = [
|
|
86
|
-
|
|
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(
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
console.error(chalk.yellow('
|
|
137
|
-
|
|
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(
|
|
146
|
-
|
|
147
|
-
|
|
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(
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
console.log('
|
|
169
|
-
console.log('
|
|
170
|
-
console.log(' •
|
|
171
|
-
console.log(' •
|
|
172
|
-
console.log('')
|
|
173
|
-
console.log(
|
|
174
|
-
console.log(
|
|
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
|
@@ -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,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
|
### 快速开始
|