df-hono-generator 1.0.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.
Files changed (44) hide show
  1. package/bin/create.cjs +61 -0
  2. package/package.json +50 -0
  3. package/template/.env.example +25 -0
  4. package/template/LICENSE +21 -0
  5. package/template/README.md +327 -0
  6. package/template/docker-compose.yml +8 -0
  7. package/template/drizzle.config.ts +10 -0
  8. package/template/eslint.config.js +9 -0
  9. package/template/package.json +50 -0
  10. package/template/src/app.ts +26 -0
  11. package/template/src/db/dev.db +0 -0
  12. package/template/src/db/index.ts +8 -0
  13. package/template/src/db/migrations/0000_outgoing_gamora.sql +6 -0
  14. package/template/src/db/migrations/0001_minor_phantom_reporter.sql +118 -0
  15. package/template/src/db/migrations/0002_same_the_spike.sql +6 -0
  16. package/template/src/db/migrations/meta/0000_snapshot.json +57 -0
  17. package/template/src/db/migrations/meta/0001_snapshot.json +841 -0
  18. package/template/src/db/migrations/meta/0002_snapshot.json +880 -0
  19. package/template/src/db/migrations/meta/_journal.json +27 -0
  20. package/template/src/db/schema.ts +162 -0
  21. package/template/src/db/seeds/index.ts +32 -0
  22. package/template/src/env.ts +42 -0
  23. package/template/src/index.ts +10 -0
  24. package/template/src/lib/configure-open-api.ts +30 -0
  25. package/template/src/lib/create-app.ts +44 -0
  26. package/template/src/lib/http-status-codes.ts +354 -0
  27. package/template/src/lib/json-content.ts +14 -0
  28. package/template/src/lib/response.ts +50 -0
  29. package/template/src/lib/types.ts +13 -0
  30. package/template/src/middleware/auth.ts +127 -0
  31. package/template/src/middleware/pino-logger.ts +13 -0
  32. package/template/src/public/favicon.ico +0 -0
  33. package/template/src/routes/auth/auth.handler.ts +72 -0
  34. package/template/src/routes/auth/auth.index.ts +9 -0
  35. package/template/src/routes/auth/auth.routes.ts +76 -0
  36. package/template/src/routes/oss/alioss.handler.ts +27 -0
  37. package/template/src/routes/oss/alioss.index.ts +8 -0
  38. package/template/src/routes/oss/alioss.routes.ts +41 -0
  39. package/template/src/routes/oss/alioss.service.ts +101 -0
  40. package/template/src/routes/oss/schema/oss.schemas.ts +21 -0
  41. package/template/src/utils/jwt.ts +212 -0
  42. package/template/src/utils/passwordAuth.ts +30 -0
  43. package/template/src/utils/redis.cache.ts +65 -0
  44. package/template/tsconfig.json +23 -0
package/bin/create.cjs ADDED
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env node
2
+ const fs = require('node:fs')
3
+ const path = require('node:path')
4
+ const process = require('node:process')
5
+
6
+ const [, , rawTarget] = process.argv
7
+ const targetName = rawTarget || 'my-hono-app'
8
+ const targetDir = path.resolve(process.cwd(), targetName)
9
+ const packageRoot = path.resolve(__dirname, '..')
10
+ const templateRoot = path.join(packageRoot, 'template')
11
+
12
+ function copyDirectory(srcDir, destDir) {
13
+ fs.mkdirSync(destDir, { recursive: true })
14
+ const entries = fs.readdirSync(srcDir, { withFileTypes: true })
15
+
16
+ for (const entry of entries) {
17
+ const srcPath = path.join(srcDir, entry.name)
18
+ const destPath = path.join(destDir, entry.name)
19
+
20
+ if (entry.isDirectory()) {
21
+ copyDirectory(srcPath, destPath)
22
+ continue
23
+ }
24
+
25
+ fs.copyFileSync(srcPath, destPath)
26
+ }
27
+ }
28
+
29
+ if (!fs.existsSync(templateRoot)) {
30
+ console.error(`❌ 未找到模板目录: ${templateRoot}`)
31
+ process.exit(1)
32
+ }
33
+
34
+ if (fs.existsSync(targetDir)) {
35
+ const files = fs.readdirSync(targetDir)
36
+ if (files.length > 0) {
37
+ console.error(`❌ 目标目录已存在且非空: ${targetDir}`)
38
+ process.exit(1)
39
+ }
40
+ }
41
+
42
+ // 1) 复制 template 到目标目录
43
+ copyDirectory(templateRoot, targetDir)
44
+
45
+ // 2) 修改目标 package.json
46
+ const targetPkgPath = path.join(targetDir, 'package.json')
47
+ if (!fs.existsSync(targetPkgPath)) {
48
+ console.error(`❌ 未找到模板 package.json: ${targetPkgPath}`)
49
+ process.exit(1)
50
+ }
51
+
52
+ const targetPkg = JSON.parse(fs.readFileSync(targetPkgPath, 'utf8'))
53
+ targetPkg.name = targetName
54
+ delete targetPkg.bin
55
+ fs.writeFileSync(targetPkgPath, `${JSON.stringify(targetPkg, null, 2)}\n`, 'utf8')
56
+
57
+ console.log(`\n✅ 项目已创建: ${targetDir}`)
58
+ console.log('\n下一步:')
59
+ console.log(` cd ${path.relative(process.cwd(), targetDir) || '.'}`)
60
+ console.log(' pnpm install')
61
+ console.log(' pnpm run dev\n')
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "df-hono-generator",
3
+ "type": "module",
4
+ "version": "v1.0.0",
5
+ "license": "MIT",
6
+ "bin": { "df-hono-generator": "bin/create.cjs" },
7
+ "files": ["bin", "template"],
8
+ "scripts": {
9
+ "dev": "tsx watch src/index.ts",
10
+ "build": "tsc",
11
+ "start": "node dist/index.js",
12
+ "lint": "eslint .",
13
+ "lint:fix": "eslint . --fix",
14
+ "test": "node --import tsx --test test/**/*.test.ts"
15
+ },
16
+ "dependencies": {
17
+ "@hono/node-server": "^1.19.9",
18
+ "@hono/zod-openapi": "^1.2.2",
19
+ "@scalar/hono-api-reference": "^0.9.46",
20
+ "ali-oss": "^6.23.0",
21
+ "bcryptjs": "^3.0.3",
22
+ "better-sqlite3": "^12.6.2",
23
+ "dotenv": "^17.3.1",
24
+ "dotenv-expand": "^12.0.3",
25
+ "drizzle-orm": "^0.45.1",
26
+ "drizzle-seed": "^0.3.1",
27
+ "hono": "^4.12.3",
28
+ "hono-pino": "^0.10.3",
29
+ "pino": "^10.3.1",
30
+ "pino-pretty": "^13.1.3",
31
+ "redis": "^5.11.0",
32
+ "zod": "^4.3.6"
33
+ },
34
+ "devDependencies": {
35
+ "@antfu/eslint-config": "^7.6.1",
36
+ "@types/ali-oss": "^6.23.3",
37
+ "@types/better-sqlite3": "^7.6.13",
38
+ "@types/node": "^20.11.17",
39
+ "drizzle-kit": "^0.31.9",
40
+ "eslint": "^10.0.2",
41
+ "eslint-plugin-format": "^2.0.1",
42
+ "tsx": "^4.7.1",
43
+ "typescript": "^5.8.3"
44
+ },
45
+ "pnpm": {
46
+ "onlyBuiltDependencies": [
47
+ "better-sqlite3"
48
+ ]
49
+ }
50
+ }
@@ -0,0 +1,25 @@
1
+ # 环境变量
2
+ # 环境变量 NODE_ENV 可选值:development, production
3
+ NODE_ENV=development
4
+ # 端口
5
+ PORT=3000
6
+
7
+ # OSS 配置
8
+ OSS_ACCESS_KEY_ID=你自己的阿里云的 ACCESS_KEY_ID
9
+ OSS_ACCESS_KEY_SECRET=你自己的阿里云的 OSS_ACCESS_KEY_SECRET
10
+ OSS_BUCKET=阿里云 OSS 的 Bucket 名称
11
+ OSS_REGION=阿里云 OSS Bucket 所在地域名称
12
+ OSS_BASE_URL=阿里云 OSS Bucket 域名
13
+
14
+ # 数据库配置
15
+ # 本地 SQLite 数据库文件路径(也可以像 mysql 一样使用远程数据库)
16
+ DB_FILE_URL=./src/db/dev.db
17
+
18
+ # Redis 配置
19
+ REDIS_SERVER=redis://default:123456@localhost:6379
20
+
21
+ # JWT 配置
22
+ JWT_ADMIN_SECRET=abcdefghijklmnopqrstuvwxyz
23
+ JWT_ADMIN_EXPIRES_IN_SECONDS=86400
24
+ JWT_CLIENT_SECRET=zyxwvutsrqponmlkjihgfedcba
25
+ JWT_CLIENT_EXPIRES_IN_SECONDS=86400
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 South Sound
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,327 @@
1
+ # South Sound Server
2
+
3
+ 基于 `Hono + TypeScript + Zod OpenAPI` 的后端服务模板。
4
+
5
+ 这份文档定位为长期复用的项目手册,包含:
6
+
7
+ - 快速启动
8
+ - 环境变量规范
9
+ - 目录与命名约定
10
+ - 路由与返回体规范
11
+ - 错误码规范
12
+ - 测试与部署流程
13
+
14
+ ## 1. 快速开始
15
+
16
+ ### 1.1 环境要求
17
+
18
+ - Node.js `>= 20`
19
+ - pnpm `>= 8`
20
+
21
+ ### 1.2 安装依赖
22
+
23
+ ```bash
24
+ pnpm install
25
+ ```
26
+
27
+ ### 1.3 配置环境变量
28
+
29
+ ```bash
30
+ cp .env.example .env
31
+ ```
32
+
33
+ 按下文「环境变量说明」补齐配置。
34
+
35
+ ### 1.4 本地开发
36
+
37
+ ```bash
38
+ pnpm run dev
39
+ ```
40
+
41
+ 默认地址:`http://localhost:3000`
42
+
43
+ ### 1.5 API 文档
44
+
45
+ - OpenAPI JSON: `GET /doc`
46
+ - Scalar UI: `GET /scalar`
47
+
48
+ ## 2. 环境变量说明
49
+
50
+ 环境变量由 [`src/env.ts`](src/env.ts) 使用 Zod 在启动时校验,不满足要求会直接退出进程。
51
+
52
+ | 变量名 | 必填 | 默认值 | 说明 |
53
+ | ------------------------------- | ---- | ------------------------------------ | ---------------------------------- |
54
+ | `NODE_ENV` | 否 | `development` | 运行环境 |
55
+ | `PORT` | 否 | `3000` | 服务端口 |
56
+ | `OSS_ACCESS_KEY_ID` | 是 | - | 阿里云 OSS AccessKey ID |
57
+ | `OSS_ACCESS_KEY_SECRET` | 是 | - | 阿里云 OSS AccessKey Secret |
58
+ | `OSS_BUCKET` | 是 | - | OSS Bucket 名称 |
59
+ | `OSS_REGION` | 是 | - | OSS Region,例如 `oss-cn-hangzhou` |
60
+ | `OSS_BASE_URL` | 是 | - | OSS 对外访问基础地址 |
61
+ | `DB_FILE_URL` | 否 | `./src/db/dev.db` | SQLite 文件路径 |
62
+ | `REDIS_SERVER` | 否 | `redis://user:123456@localhost:6379` | Redis 连接串 |
63
+ | `JWT_ADMIN_SECRET` | 是 | - | 管理端 JWT 密钥 |
64
+ | `JWT_ADMIN_EXPIRES_IN_SECONDS` | 否 | `86400` | 管理端 JWT 过期秒数(最小 60) |
65
+ | `JWT_CLIENT_SECRET` | 是 | - | 客户端 JWT 密钥 |
66
+ | `JWT_CLIENT_EXPIRES_IN_SECONDS` | 否 | `86400` | 客户端 JWT 过期秒数(最小 60) |
67
+
68
+ 说明:
69
+
70
+ - “必填”以 [`src/env.ts`](src/env.ts) 的 Zod schema 是否提供默认值为准。
71
+ - 即使有默认值,生产环境也建议显式配置,避免不同环境行为不一致。
72
+
73
+ 示例:
74
+
75
+ ```env
76
+ # 基本信息
77
+ NODE_ENV=development
78
+ PORT=3000
79
+
80
+ # OSS 配置
81
+ OSS_ACCESS_KEY_ID=your_key_id
82
+ OSS_ACCESS_KEY_SECRET=your_key_secret
83
+ OSS_BUCKET=your_bucket
84
+ OSS_REGION=oss-cn-hangzhou
85
+ OSS_BASE_URL=https://your-bucket.oss-cn-hangzhou.aliyuncs.com
86
+
87
+ # 数据库配置
88
+ DB_FILE_URL=./src/db/dev.db
89
+
90
+ # Redis 配置
91
+ REDIS_SERVER=redis://user:123456@localhost:6379
92
+
93
+ # JWT 配置
94
+ JWT_ADMIN_SECRET=abcdefghijklmnopqrstuvwxyz
95
+ JWT_ADMIN_EXPIRES_IN_SECONDS=86400
96
+ JWT_CLIENT_SECRET=zyxwvutsrqponmlkjihgfedcba
97
+ JWT_CLIENT_EXPIRES_IN_SECONDS=86400
98
+ ```
99
+
100
+ ## 3. 常用命令
101
+
102
+ ```bash
103
+ pnpm run dev # 开发模式(tsx watch)
104
+ pnpm run build # TypeScript 构建到 dist
105
+ pnpm run start # 运行构建产物
106
+ pnpm run lint # 代码检查
107
+ pnpm run lint:fix # 自动修复格式与部分 lint 问题
108
+ pnpm run test # 运行测试(node:test + tsx)
109
+ ```
110
+
111
+ ## 4. 目录约定
112
+
113
+ ```text
114
+ src/
115
+ app.ts # 应用入口,统一挂载业务路由
116
+ index.ts # 启动 HTTP 服务
117
+ env.ts # 环境变量加载与校验
118
+ lib/ # 基础库(app factory、响应封装、状态码等)
119
+ middleware/ # 中间件
120
+ routes/
121
+ <module>/
122
+ <module>.routes.ts # 路由声明(createRoute + schema)
123
+ <module>.handler.ts # 业务处理逻辑
124
+ <module>.index.ts # 模块路由聚合(router.openapi)
125
+
126
+ test/
127
+ *.test.ts # 集成/接口测试
128
+ ```
129
+
130
+ 新增业务模块时,建议沿用三件套:
131
+
132
+ - `xxx.routes.ts`
133
+ - `xxx.handler.ts`
134
+ - `xxx.index.ts`
135
+
136
+ 并在 [`src/app.ts`](src/app.ts) 中统一注册:
137
+
138
+ ```ts
139
+ app.route('/prefix', xxxRouter)
140
+ ```
141
+
142
+ ## 5. 路由规范
143
+
144
+ ### 5.1 设计原则
145
+
146
+ - 使用 `@hono/zod-openapi` 的 `createRoute` 声明路由。
147
+ - 每个接口必须声明:`path`、`method`、`tags`、`responses`。
148
+ - 有请求体时必须提供 Zod schema(便于自动校验与文档生成)。
149
+
150
+ ### 5.2 文件职责
151
+
152
+ - `*.routes.ts`:只做协议层定义(请求/响应 schema)。
153
+ - `*.handler.ts`:只做业务逻辑与调用外部服务。
154
+ - `*.index.ts`:路由与 handler 绑定。
155
+
156
+ ### 5.3 命名建议
157
+
158
+ - 路由对象名使用业务语义,例如 `list`, `create`, `detail`, `update`, `remove`。
159
+ - handler 与 route 对象同名,减少映射负担。
160
+
161
+ ### 5.4 URL 约定
162
+
163
+ - 模块级前缀在 `app.ts` 中统一挂载。
164
+ - 具体接口 path 在 `*.routes.ts` 中定义。
165
+ - 建议采用资源化命名,避免动词堆叠。
166
+
167
+ ## 6. 响应与错误码规范
168
+
169
+ ### 6.1 成功响应
170
+
171
+ 统一通过 [`src/lib/response.ts`](src/lib/response.ts) 的 `ok()` 返回:
172
+
173
+ ```json
174
+ {
175
+ "success": true,
176
+ "code": 0,
177
+ "message": "操作成功",
178
+ "data": {}
179
+ }
180
+ ```
181
+
182
+ 约定:
183
+
184
+ - `success = true`
185
+ - `code = 0`(业务成功码)
186
+ - HTTP 状态码通常为 `200`
187
+
188
+ ### 6.2 失败响应
189
+
190
+ 统一通过 `fail()` 返回:
191
+
192
+ ```json
193
+ {
194
+ "success": false,
195
+ "code": 400,
196
+ "message": "参数校验失败",
197
+ "error": {}
198
+ }
199
+ ```
200
+
201
+ 约定:
202
+
203
+ - `success = false`
204
+ - `code` 与 HTTP 状态码/错误标识一致
205
+ - `message` 为可读错误信息
206
+ - `error` 仅在需要排障时提供结构化详情
207
+
208
+ ### 6.3 当前全局错误处理
209
+
210
+ 在 [`src/lib/create-app.ts`](src/lib/create-app.ts) 中已内置:
211
+
212
+ - 参数校验失败:`400 BAD_REQUEST`
213
+ - 路由不存在:`404 NOT_FOUND`
214
+ - 未捕获异常:`500 INTERNAL_SERVER_ERROR`
215
+
216
+ 建议新增业务错误时使用:
217
+
218
+ - `400` 参数错误
219
+ - `401` 未认证
220
+ - `403` 无权限
221
+ - `404` 资源不存在
222
+ - `409` 资源冲突
223
+ - `422` 语义校验失败
224
+ - `500` 服务内部错误
225
+
226
+ ## 7. 测试规范
227
+
228
+ 项目当前使用 `node:test` + `tsx`。
229
+
230
+ ### 7.1 存放约定
231
+
232
+ - 测试文件放在根目录 `test/`
233
+ - 文件命名:`*.test.ts`
234
+
235
+ ### 7.2 运行测试
236
+
237
+ ```bash
238
+ pnpm run test
239
+ ```
240
+
241
+ ### 7.3 测试目标建议
242
+
243
+ - 每个路由至少覆盖:
244
+ - 1 个成功用例
245
+ - 1 个参数校验失败用例
246
+ - 关键异常路径(如外部服务失败)
247
+ - 断言内容至少包括:
248
+ - HTTP 状态码
249
+ - `success/code/message/data(error)` 结构
250
+
251
+ ## 8. 部署步骤(通用)
252
+
253
+ 以下流程适用于 Linux 服务器(systemd/pm2 均可复用)。
254
+
255
+ ### 8.1 拉取代码并安装依赖
256
+
257
+ ```bash
258
+ pnpm install --frozen-lockfile
259
+ ```
260
+
261
+ ### 8.2 配置生产环境变量
262
+
263
+ ```bash
264
+ cp .env.example .env
265
+ # 编辑 .env,填入生产值
266
+ ```
267
+
268
+ 建议至少设置:
269
+
270
+ - `NODE_ENV=production`
271
+ - `PORT=<生产端口>`
272
+ - OSS 相关全部变量
273
+ - `DB_FILE_URL`
274
+ - `REDIS_SERVER`
275
+ - JWT 相关全部变量(`JWT_ADMIN_SECRET`、`JWT_CLIENT_SECRET` 等)
276
+
277
+ ### 8.3 构建
278
+
279
+ ```bash
280
+ pnpm run build
281
+ ```
282
+
283
+ ### 8.4 启动
284
+
285
+ ```bash
286
+ pnpm run start
287
+ ```
288
+
289
+ ### 8.5 进程守护(推荐)
290
+
291
+ 可用 `pm2` 示例:
292
+
293
+ ```bash
294
+ pm2 start dist/src/index.js --name south-sound-server
295
+ pm2 save
296
+ pm2 startup
297
+ ```
298
+
299
+ ### 8.6 反向代理(可选)
300
+
301
+ 建议在 Nginx/Caddy 前置:
302
+
303
+ - 统一 TLS
304
+ - 统一域名与路由
305
+ - 限流与日志聚合
306
+
307
+ ## 9. 新增模块 Checklist
308
+
309
+ - 新建 `src/routes/<module>/` 三件套文件
310
+ - 在 `*.routes.ts` 完成 schema 与响应声明
311
+ - 在 `*.handler.ts` 实现业务逻辑
312
+ - 在 `src/app.ts` 注册路由前缀
313
+ - 为核心接口补充 `test/*.test.ts`
314
+ - 本地通过 `pnpm run lint && pnpm run test`
315
+
316
+ ## 10. 已知注意事项
317
+
318
+ - 环境变量缺失会在启动时直接退出(预期行为)。
319
+ - 测试中如果导入 `app` 依赖 `env`,需要在测试前准备必要的 `process.env`。
320
+ - 建议保持返回结构稳定,避免前端联调频繁改动。
321
+
322
+ ## 11. License
323
+
324
+ This project is licensed under the [MIT License](./LICENSE).
325
+
326
+ You are free to use, modify, distribute, and use this project commercially,
327
+ as long as the original copyright and license notice are retained.
@@ -0,0 +1,8 @@
1
+ services:
2
+ redis:
3
+ image: redis:7.4
4
+ command: [redis-server, --requirepass, '${REDIS_PASSWORD}']
5
+ environment:
6
+ - REDIS_PASSWORD=123456
7
+ ports:
8
+ - '6379:6379'
@@ -0,0 +1,10 @@
1
+ import process from 'node:process'
2
+
3
+ export default {
4
+ schema: './src/db/schema.ts', // 表定义
5
+ out: './src/db/migrations', // 迁移文件输出目录
6
+ dialect: 'sqlite',
7
+ dbCredentials: {
8
+ url: process.env.DB_FILE_URL ?? 'file:./dev.db', // 数据库文件路径
9
+ },
10
+ }
@@ -0,0 +1,9 @@
1
+ import antfu from '@antfu/eslint-config'
2
+
3
+ export default antfu({
4
+ formatters: true,
5
+ rules: {
6
+ 'test/no-import-node-test': 'off',
7
+ 'no-console': ['error', { allow: ['warn', 'error', 'log'] }],
8
+ },
9
+ })
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "df-hono-generator",
3
+ "type": "module",
4
+ "version": "v1.0.0",
5
+ "license": "MIT",
6
+ "bin": { "df-hono-generator": "bin/create.cjs" },
7
+ "files": ["bin", "template"],
8
+ "scripts": {
9
+ "dev": "tsx watch src/index.ts",
10
+ "build": "tsc",
11
+ "start": "node dist/index.js",
12
+ "lint": "eslint .",
13
+ "lint:fix": "eslint . --fix",
14
+ "test": "node --import tsx --test test/**/*.test.ts"
15
+ },
16
+ "dependencies": {
17
+ "@hono/node-server": "^1.19.9",
18
+ "@hono/zod-openapi": "^1.2.2",
19
+ "@scalar/hono-api-reference": "^0.9.46",
20
+ "ali-oss": "^6.23.0",
21
+ "bcryptjs": "^3.0.3",
22
+ "better-sqlite3": "^12.6.2",
23
+ "dotenv": "^17.3.1",
24
+ "dotenv-expand": "^12.0.3",
25
+ "drizzle-orm": "^0.45.1",
26
+ "drizzle-seed": "^0.3.1",
27
+ "hono": "^4.12.3",
28
+ "hono-pino": "^0.10.3",
29
+ "pino": "^10.3.1",
30
+ "pino-pretty": "^13.1.3",
31
+ "redis": "^5.11.0",
32
+ "zod": "^4.3.6"
33
+ },
34
+ "devDependencies": {
35
+ "@antfu/eslint-config": "^7.6.1",
36
+ "@types/ali-oss": "^6.23.3",
37
+ "@types/better-sqlite3": "^7.6.13",
38
+ "@types/node": "^20.11.17",
39
+ "drizzle-kit": "^0.31.9",
40
+ "eslint": "^10.0.2",
41
+ "eslint-plugin-format": "^2.0.1",
42
+ "tsx": "^4.7.1",
43
+ "typescript": "^5.8.3"
44
+ },
45
+ "pnpm": {
46
+ "onlyBuiltDependencies": [
47
+ "better-sqlite3"
48
+ ]
49
+ }
50
+ }
@@ -0,0 +1,26 @@
1
+ import { configureOpenAPI } from '@/lib/configure-open-api.js'
2
+ import createApp from '@/lib/create-app.js'
3
+ import adminAuth from '@/routes/auth/auth.index.js'
4
+ import alioss from '@/routes/oss/alioss.index.js'
5
+ import { requireAdminAuth, requireEitherAuth } from './middleware/auth.js'
6
+
7
+ const app = createApp()
8
+
9
+ configureOpenAPI(app)
10
+
11
+ // 启用中间件
12
+ app.use('/admin/*', requireAdminAuth())
13
+ app.use('/oss/*', requireEitherAuth())
14
+
15
+ // 定义路由数组
16
+ const routes = [
17
+ { path: '/oss', router: alioss },
18
+ { path: '/admin/auth', router: adminAuth },
19
+ ]
20
+
21
+ // 注册所有路由
22
+ routes.forEach(({ path, router }) => {
23
+ app.route(path, router)
24
+ })
25
+
26
+ export default app
Binary file
@@ -0,0 +1,8 @@
1
+ import Database from 'better-sqlite3'
2
+ import { drizzle } from 'drizzle-orm/better-sqlite3'
3
+ import env from '@/env.js'
4
+
5
+ const sqlite = new Database(env.DB_FILE_URL)
6
+ const db = drizzle({ client: sqlite })
7
+
8
+ export default db
@@ -0,0 +1,6 @@
1
+ CREATE TABLE `test` (
2
+ `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
3
+ `username` text NOT NULL,
4
+ `gender` integer DEFAULT 0 NOT NULL,
5
+ `created_at` integer NOT NULL
6
+ );