koa3-cli 1.0.9 → 1.1.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/RELEASE.md ADDED
@@ -0,0 +1,159 @@
1
+ # Release Guide
2
+
3
+ 本文档用于记录 Koa3 CLI 的发版流程,目标是让每次发布都能复现、可检查、可回滚。
4
+
5
+ ## 发布前检查
6
+
7
+ 1. 确认当前分支是 `master`,并且工作区干净。
8
+
9
+ ```bash
10
+ git status --short --branch
11
+ ```
12
+
13
+ 2. 安装依赖并确认锁文件可用。
14
+
15
+ ```bash
16
+ npm ci
17
+ ```
18
+
19
+ 3. 检查依赖安全风险。
20
+
21
+ ```bash
22
+ npm audit
23
+ ```
24
+
25
+ 4. 运行自动化测试。
26
+
27
+ ```bash
28
+ npm test
29
+ ```
30
+
31
+ 5. 检查 npm 发布包内容。
32
+
33
+ ```bash
34
+ npm pack --dry-run
35
+ ```
36
+
37
+ 6. 确认 README、CHANGELOG 和文档站内容已经同步。
38
+
39
+ ## 版本更新
40
+
41
+ 根据变更范围选择版本类型:
42
+
43
+ - `patch`:bug 修复、依赖补丁、文档修正。
44
+ - `minor`:新增向后兼容能力,例如新模板、新命令、CI 或工程化能力。
45
+ - `major`:不兼容的 CLI、模板结构或运行时行为变更。
46
+
47
+ 更新版本号:
48
+
49
+ ```bash
50
+ npm version patch --no-git-tag-version
51
+ npm version minor --no-git-tag-version
52
+ npm version major --no-git-tag-version
53
+ ```
54
+
55
+ 如果需要指定版本:
56
+
57
+ ```bash
58
+ npm version 1.1.0 --no-git-tag-version
59
+ ```
60
+
61
+ 版本号更新后,需要同步修改 `CHANGELOG.md`。
62
+
63
+ ## 提交与标签
64
+
65
+ 1. 提交版本变更。
66
+
67
+ ```bash
68
+ git add package.json package-lock.json CHANGELOG.md RELEASE.md README.md
69
+ git commit -m "chore: release v1.1.0"
70
+ ```
71
+
72
+ 2. 创建 Git tag。
73
+
74
+ ```bash
75
+ git tag v1.1.0
76
+ ```
77
+
78
+ 3. 推送到 GitHub 和 Gitee。
79
+
80
+ ```bash
81
+ git push github master
82
+ git push github v1.1.0
83
+ git push origin master
84
+ git push origin v1.1.0
85
+ ```
86
+
87
+ ## 发布 npm
88
+
89
+ 发布前再次确认包内容:
90
+
91
+ ```bash
92
+ npm pack --dry-run
93
+ ```
94
+
95
+ 发布到 npm:
96
+
97
+ ```bash
98
+ npm publish
99
+ ```
100
+
101
+ 发布后确认 npm 最新版本:
102
+
103
+ ```bash
104
+ npm view koa3-cli version
105
+ ```
106
+
107
+ ## GitHub Release
108
+
109
+ 在 GitHub 仓库创建 Release:
110
+
111
+ - Tag:`v1.1.0`
112
+ - Title:`v1.1.0`
113
+ - Release notes:参考 `CHANGELOG.md` 对应版本内容
114
+
115
+ 建议 release notes 包含:
116
+
117
+ - 本次新增能力
118
+ - 依赖或安全修复
119
+ - 迁移说明
120
+ - 已知问题
121
+
122
+ ## 发布后验证
123
+
124
+ 1. 使用 npx 创建项目。
125
+
126
+ ```bash
127
+ npx koa3-cli create koa3-release-test
128
+ cd koa3-release-test
129
+ npm install
130
+ npm run dev
131
+ ```
132
+
133
+ 2. 验证基础接口。
134
+
135
+ ```bash
136
+ curl http://localhost:3000/api/user
137
+ ```
138
+
139
+ 3. 验证文档站。
140
+
141
+ ```text
142
+ https://hikerw.github.io/koa3-cli/
143
+ ```
144
+
145
+ 4. 确认 GitHub Actions 和 GitHub Pages 部署均成功。
146
+
147
+ ## 回滚策略
148
+
149
+ 如果 npm 发布后发现严重问题:
150
+
151
+ 1. 立即在 GitHub Release 说明中标记问题。
152
+ 2. 优先发布修复版,例如 `1.1.1`。
153
+ 3. 如必须撤回 npm 版本,需谨慎使用:
154
+
155
+ ```bash
156
+ npm unpublish koa3-cli@1.1.0
157
+ ```
158
+
159
+ 注意:npm unpublish 有时间和生态限制,常规情况下更推荐发布修复版本。
package/app/setup.js CHANGED
@@ -4,6 +4,7 @@
4
4
  */
5
5
  const path = require('path');
6
6
  const fs = require('fs');
7
+ const cors = require('@koa/cors');
7
8
  const bodyParser = require('koa-bodyparser');
8
9
  const serveStatic = require('koa-static');
9
10
  const views = require('@ladjs/koa-views');
@@ -16,44 +17,44 @@ const router = require('./router');
16
17
 
17
18
  const rootDir = path.join(__dirname, '..');
18
19
 
19
- /**
20
- * 生成静态资源缓存配置。
21
- *
22
- * SPA 的入口 index.html 会引用最新一批带 hash 的 JS/CSS 文件,如果入口文件被浏览器或 CDN
23
- * 长时间缓存,用户发布后仍会拿到旧入口,进而继续加载旧资源。这里仅禁止 index.html 缓存,
24
- * 其他静态资源继续使用配置里的 maxAge,保证发布更新及时生效且不影响资源缓存性能。
25
- *
26
- * @param {Object} staticOptions koa-static 原始配置项
27
- * @returns {Object} 注入 index.html 不缓存策略后的 koa-static 配置项
28
- */
29
- function createStaticOptions(staticOptions = {}) {
30
- const userSetHeaders = staticOptions.setHeaders;
31
-
32
- return {
33
- ...staticOptions,
34
- setHeaders(res, filePath, stats) {
35
- if (typeof userSetHeaders === 'function') {
36
- userSetHeaders(res, filePath, stats);
37
- }
38
-
39
- // koa-send 在启用 gzip/brotli 时传入的是 index.html.gz / index.html.br,
40
- // 需要去掉压缩扩展名后再判断,避免预压缩入口文件继续被长缓存。
41
- const normalizedFileName = path.basename(filePath).replace(/\.(br|gz)$/i, '');
42
- if (normalizedFileName === 'index.html') {
43
- res.setHeader('Cache-Control', INDEX_HTML_CACHE_CONTROL);
44
- res.setHeader('Pragma', 'no-cache');
45
- res.setHeader('Expires', '0');
46
- }
47
- }
48
- };
20
+ /**
21
+ * 生成静态资源缓存配置。
22
+ *
23
+ * SPA 的入口 index.html 会引用最新一批带 hash 的 JS/CSS 文件,如果入口文件被浏览器或 CDN
24
+ * 长时间缓存,用户发布后仍会拿到旧入口,进而继续加载旧资源。这里仅禁止 index.html 缓存,
25
+ * 其他静态资源继续使用配置里的 maxAge,保证发布更新及时生效且不影响资源缓存性能。
26
+ *
27
+ * @param {Object} staticOptions koa-static 原始配置项
28
+ * @returns {Object} 注入 index.html 不缓存策略后的 koa-static 配置项
29
+ */
30
+ function createStaticOptions(staticOptions = {}) {
31
+ const userSetHeaders = staticOptions.setHeaders;
32
+
33
+ return {
34
+ ...staticOptions,
35
+ setHeaders(res, filePath, stats) {
36
+ if (typeof userSetHeaders === 'function') {
37
+ userSetHeaders(res, filePath, stats);
38
+ }
39
+
40
+ // koa-send 在启用 gzip/brotli 时传入的是 index.html.gz / index.html.br,
41
+ // 需要去掉压缩扩展名后再判断,避免预压缩入口文件继续被长缓存。
42
+ const normalizedFileName = path.basename(filePath).replace(/\.(br|gz)$/i, '');
43
+ if (normalizedFileName === 'index.html') {
44
+ res.setHeader('Cache-Control', INDEX_HTML_CACHE_CONTROL);
45
+ res.setHeader('Pragma', 'no-cache');
46
+ res.setHeader('Expires', '0');
47
+ }
48
+ }
49
+ };
49
50
  }
50
51
 
51
52
  function setup(app, config, logger) {
52
53
  // 静态资源
53
54
  if (config.static && config.static.enable !== false) {
54
55
  const staticPath = path.join(rootDir, config.static.dir || 'public');
55
- if (fs.existsSync(staticPath)) {
56
- app.use(serveStatic(staticPath, createStaticOptions(config.static.options || {})));
56
+ if (fs.existsSync(staticPath)) {
57
+ app.use(serveStatic(staticPath, createStaticOptions(config.static.options || {})));
57
58
  }
58
59
  }
59
60
 
@@ -65,6 +66,12 @@ function setup(app, config, logger) {
65
66
  }
66
67
  }
67
68
 
69
+ // CORS 默认关闭,避免脚手架生成的项目在未明确授权时开放跨域。
70
+ // 需要给前端应用或第三方调用方开放接口时,可通过 config.cors.enable 或 CORS_ENABLE 开启。
71
+ if (config.cors && config.cors.enable === true) {
72
+ app.use(cors(config.cors.options || {}));
73
+ }
74
+
68
75
  app.use(bodyParser(config.bodyParser || {}));
69
76
  app.use(createRequestLogger(logger));
70
77
 
package/bin/cli.js CHANGED
@@ -25,7 +25,7 @@ Koa3 CLI - 快速创建 Koa3 项目脚手架
25
25
  示例:
26
26
  koa3-cli create my-app
27
27
 
28
- 更多信息: https://gitee.com/wangziwl/koa3-cli
28
+ 更多信息: https://github.com/hikerw/koa3-cli
29
29
  `);
30
30
  }
31
31
 
@@ -180,7 +180,7 @@ function createProject(projectName) {
180
180
  console.log(` cd ${projectName}`);
181
181
  console.log(' npm install');
182
182
  console.log(' npm run dev\n');
183
- console.log('📖 文档: https://atwzc.cn/');
183
+ console.log('📖 文档: https://hikerw.github.io/koa3-cli/');
184
184
  console.log('🔗 Gitee: https://gitee.com/wangziwl/koa3-cli\n');
185
185
 
186
186
  } catch (error) {
@@ -14,6 +14,16 @@ module.exports = {
14
14
  // Cookie signing keys
15
15
  keys: process.env.KEYS ? process.env.KEYS.split(',') : ['koa3-cli-secret-key'],
16
16
 
17
+ // CORS configuration
18
+ // 默认关闭跨域,避免新项目在没有明确安全边界时暴露给任意来源。
19
+ // 如需开放给前端应用,可设置 CORS_ENABLE=true,并用 CORS_ORIGIN 指定允许的来源。
20
+ cors: {
21
+ enable: process.env.CORS_ENABLE === 'true',
22
+ options: {
23
+ origin: process.env.CORS_ORIGIN || '*'
24
+ }
25
+ },
26
+
17
27
  // Static assets
18
28
  static: {
19
29
  enable: true,
package/env.example CHANGED
@@ -10,6 +10,11 @@ PORT=3000
10
10
  # 应用密钥(多个密钥用逗号分隔)
11
11
  KEYS=your-secret-key-1,your-secret-key-2
12
12
 
13
+ # 跨域配置
14
+ # 默认关闭跨域;如果前端和接口不在同一域名下,可设置为 true 并限制允许来源。
15
+ CORS_ENABLE=false
16
+ CORS_ORIGIN=*
17
+
13
18
  # 数据库配置
14
19
  DB_HOST=localhost
15
20
  DB_PORT=3306
package/package.json CHANGED
@@ -1,38 +1,63 @@
1
1
  {
2
2
  "name": "koa3-cli",
3
- "version": "1.0.9",
4
- "description": "Koa3脚手架",
3
+ "version": "1.1.0",
4
+ "description": "面向 Koa 3 的现代 Node.js API 项目脚手架",
5
5
  "main": "app.js",
6
6
  "bin": {
7
7
  "koa3-cli": "bin/cli.js"
8
8
  },
9
+ "files": [
10
+ "app",
11
+ "bin",
12
+ "config",
13
+ "public",
14
+ "app.js",
15
+ "env.example",
16
+ "README.md",
17
+ "CHANGELOG.md",
18
+ "RELEASE.md",
19
+ "LICENSE",
20
+ ".gitignore",
21
+ ".npmignore"
22
+ ],
9
23
  "preferGlobal": true,
10
24
  "scripts": {
11
25
  "start": "node app.js",
12
26
  "dev": "nodemon app.js",
13
- "test": "echo \"Error: no test specified\" && exit 1"
27
+ "test": "node --test"
14
28
  },
15
29
  "keywords": [
16
30
  "koa3",
31
+ "koa",
32
+ "koa-cli",
33
+ "nodejs",
34
+ "backend",
35
+ "rest-api",
17
36
  "scaffold",
18
37
  "cli"
19
38
  ],
20
39
  "author": "hikerw <965366906@qq.com>",
21
40
  "repository": {
22
41
  "type": "git",
23
- "url": "https://gitee.com/wangziwl/koa3-cli"
42
+ "url": "git+https://github.com/hikerw/koa3-cli.git"
43
+ },
44
+ "bugs": {
45
+ "url": "https://github.com/hikerw/koa3-cli/issues"
24
46
  },
25
- "homepage": "https://atwzc.cn/",
47
+ "homepage": "https://hikerw.github.io/koa3-cli/",
26
48
  "license": "MIT",
49
+ "engines": {
50
+ "node": ">=20"
51
+ },
27
52
  "dependencies": {
28
- "@koa/router": "^15.3.1",
53
+ "@koa/cors": "^5.0.0",
54
+ "@koa/router": "^15.6.0",
29
55
  "@ladjs/koa-views": "^9.0.0",
30
- "dotenv": "^17.3.1",
56
+ "dotenv": "^17.4.2",
31
57
  "ejs": "^4.0.1",
32
- "joi": "^17.13.3",
33
- "koa": "^3.1.2",
58
+ "joi": "^17.13.4",
59
+ "koa": "^3.2.1",
34
60
  "koa-bodyparser": "^4.4.1",
35
- "koa-cors": "^0.0.16",
36
61
  "koa-static": "^5.0.0"
37
62
  },
38
63
  "devDependencies": {
@@ -0,0 +1,180 @@
1
+ /* ============================================
2
+ Koa3 CLI 文档内容数据文件
3
+ 修改此文件来更新文档内容和导航菜单
4
+ ============================================ */
5
+
6
+ /**
7
+ * 导航菜单配置
8
+ * 修改此配置来调整侧边栏导航
9
+ */
10
+ const DOCS_NAVIGATION = [
11
+ {
12
+ title: '指南',
13
+ items: [
14
+ { id: 'home', label: '首页' },
15
+ { id: 'getting-started', label: '快速开始' },
16
+ { id: 'project-structure', label: '项目结构' },
17
+ { id: 'configuration', label: '配置说明' },
18
+ { id: 'development', label: '开发指南' }
19
+ ]
20
+ },
21
+ {
22
+ title: 'API',
23
+ items: [
24
+ { id: 'api-readme', label: 'API 文档' },
25
+ { id: 'api-user', label: '用户接口' }
26
+ ]
27
+ }
28
+ ];
29
+
30
+ /**
31
+ * 文档内容配置
32
+ * 修改此配置来更新文档内容
33
+ */
34
+ const DOCS_CONTENT = {
35
+ 'home': {
36
+ title: 'Koa3 CLI',
37
+ subtitle: '基于 Koa3 的脚手架项目',
38
+ description: '2025年4月28日,Node.js 生态圈迎来了一场重磅升级——Koa.js 3.0 正式发布!自2017年启动开发计划,历经8年长跑,由 Express 原班人马打造的经典轻量级 Web 框架,终于以全新姿态回归视野。Koa 3.0 不仅是一次版本号的跃迁,更是 Node.js 现代化进程的重要里程碑。',
39
+ actionButton: {
40
+ text: '快速开始 →',
41
+ target: 'getting-started'
42
+ },
43
+ features: [
44
+ { icon: '🚀', title: '轻量高效', description: '基于 Koa3,性能优异,代码简洁' },
45
+ { icon: '📁', title: '清晰结构', description: '规范统一,易于维护' },
46
+ { icon: '🔧', title: '多环境配置', description: '支持 development/production 环境配置' },
47
+ { icon: '🏗️', title: 'MVC 架构', description: 'Controller/Service/Model 分层清晰' },
48
+ { icon: '🔌', title: '中间件支持', description: '灵活的中间件系统,易于扩展' },
49
+ { icon: '✅', title: '错误处理', description: '统一的错误处理机制' }
50
+ ]
51
+ },
52
+ 'getting-started': {
53
+ title: '快速开始',
54
+ sections: [
55
+ {
56
+ type: 'h2',
57
+ content: '安装依赖'
58
+ },
59
+ {
60
+ type: 'code',
61
+ language: 'bash',
62
+ content: 'npm install'
63
+ },
64
+ {
65
+ type: 'h2',
66
+ content: '启动项目'
67
+ },
68
+ {
69
+ type: 'h3',
70
+ content: '开发环境'
71
+ },
72
+ {
73
+ type: 'p',
74
+ content: '使用 nodemon 自动重启:'
75
+ },
76
+ {
77
+ type: 'code',
78
+ language: 'bash',
79
+ content: 'npm run dev'
80
+ },
81
+ {
82
+ type: 'h3',
83
+ content: '生产环境'
84
+ },
85
+ {
86
+ type: 'code',
87
+ language: 'bash',
88
+ content: 'npm start'
89
+ },
90
+ {
91
+ type: 'h2',
92
+ content: '访问应用'
93
+ },
94
+ {
95
+ type: 'p',
96
+ content: '启动成功后,你可以访问:'
97
+ },
98
+ {
99
+ type: 'list',
100
+ items: [
101
+ '<strong>首页</strong>: http://localhost:3000',
102
+ '<strong>API 示例</strong>: http://localhost:3000/api/user',
103
+ '<strong>文档</strong>: http://localhost:3000/index.html'
104
+ ]
105
+ },
106
+ {
107
+ type: 'h2',
108
+ content: '环境配置'
109
+ },
110
+ {
111
+ type: 'p',
112
+ content: '项目支持多环境配置,通过 <code>NODE_ENV</code> 环境变量控制:'
113
+ },
114
+ {
115
+ type: 'list',
116
+ items: [
117
+ '<code>development</code> 或 <code>local</code>: 加载 <code>config.local.js</code>',
118
+ '<code>production</code>: 加载 <code>config.prod.js</code>',
119
+ '默认: 加载 <code>config.default.js</code>'
120
+ ]
121
+ },
122
+ {
123
+ type: 'p',
124
+ content: '可以通过 <code>.env</code> 文件配置环境变量(参考 <code>env.example</code>)。'
125
+ },
126
+ {
127
+ type: 'h2',
128
+ content: '下一步'
129
+ },
130
+ {
131
+ type: 'list',
132
+ items: [
133
+ '了解 <a href="#" onclick="showContent(\'project-structure\'); return false;">项目结构</a>',
134
+ '查看 <a href="#" onclick="showContent(\'configuration\'); return false;">配置说明</a>',
135
+ '阅读 <a href="#" onclick="showContent(\'development\'); return false;">开发指南</a>'
136
+ ]
137
+ }
138
+ ]
139
+ },
140
+ // 其他内容可以继续添加...
141
+ // 为了简化,这里只展示结构,实际使用时可以将完整的 HTML 内容放在这里
142
+ };
143
+
144
+ /**
145
+ * 渲染导航菜单
146
+ */
147
+ function renderNavigation() {
148
+ const sidebar = document.getElementById('sidebar');
149
+ if (!sidebar) return;
150
+
151
+ let html = '';
152
+ DOCS_NAVIGATION.forEach(group => {
153
+ html += '<div class="sidebar-group">';
154
+ html += `<div class="sidebar-group-title">${group.title}</div>`;
155
+ group.items.forEach(item => {
156
+ const isActive = item.id === 'home' ? 'active' : '';
157
+ html += `<a href="#" class="sidebar-link ${isActive}" onclick="showContent('${item.id}'); return false;">${item.label}</a>`;
158
+ });
159
+ html += '</div>';
160
+ });
161
+ sidebar.innerHTML = html;
162
+ }
163
+
164
+ /**
165
+ * 渲染文档内容
166
+ * 注意:由于内容较长,这里提供一个简化的渲染函数
167
+ * 实际使用时,可以将完整的 HTML 内容直接放在 HTML 文件中,或者使用模板引擎
168
+ */
169
+ function renderContent() {
170
+ // 这个方法可以根据 DOCS_CONTENT 配置动态生成内容
171
+ // 但为了简单和性能,建议直接在 HTML 中写内容
172
+ // 这里只是提供一个结构示例
173
+ }
174
+
175
+ // 页面加载时渲染导航
176
+ if (document.readyState === 'loading') {
177
+ document.addEventListener('DOMContentLoaded', renderNavigation);
178
+ } else {
179
+ renderNavigation();
180
+ }