jax-hono 1.0.14 → 1.0.15
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 +3 -1
- package/build/generate-registry.ts +45 -31
- package/docs/agent.md +105 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@ const controllerGroups: ControllerGroup[] = [
|
|
|
30
30
|
{ name: 'backend', dirs: ['backend', 'controllers/backend', 'controller/backend', 'modules'], suffix: '.backend' },
|
|
31
31
|
{ name: 'open', dirs: ['open', 'controllers/open', 'controller/open', 'modules'], suffix: '.open' },
|
|
32
32
|
{ name: 'client', dirs: ['client', 'controllers/client', 'controller/client', 'modules'], suffix: '.client' },
|
|
33
|
-
{ name: 'controller', dirs: ['controllers', 'controller'] },
|
|
33
|
+
{ name: 'controller', dirs: ['controllers', 'controller', 'modules'], suffix: '.controller' },
|
|
34
34
|
]
|
|
35
35
|
|
|
36
36
|
const scopedControllerGroups = new Set(
|
|
@@ -126,15 +126,25 @@ function stripKnownSuffix(modulePath: string, suffixes: string[]) {
|
|
|
126
126
|
return modulePath
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
-
function normalizeModulePath(modulePath: string) {
|
|
130
|
-
const parts = modulePath.split('/')
|
|
131
|
-
const last = parts.at(-1)
|
|
132
|
-
const parent = parts.at(-2)
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
129
|
+
function normalizeModulePath(modulePath: string) {
|
|
130
|
+
const parts = modulePath.split('/')
|
|
131
|
+
const last = parts.at(-1)
|
|
132
|
+
const parent = parts.at(-2)
|
|
133
|
+
|
|
134
|
+
if (!last || !parent) {
|
|
135
|
+
return modulePath
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (last === parent) {
|
|
139
|
+
return parts.slice(0, -1).join('/')
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (last.startsWith(`${parent}-`) || last.startsWith(`${parent}_`)) {
|
|
143
|
+
return [...parts.slice(0, -2), last].join('/')
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return modulePath
|
|
147
|
+
}
|
|
138
148
|
|
|
139
149
|
function toModulePath(baseDir: string, filePath: string, suffixes: string[] = []) {
|
|
140
150
|
const modulePath = relative(join(srcDir, baseDir), filePath)
|
|
@@ -170,13 +180,13 @@ function isSuffixedModuleFile(filePath: string, suffix: string) {
|
|
|
170
180
|
.endsWith(suffix)
|
|
171
181
|
}
|
|
172
182
|
|
|
173
|
-
function isModuleFeatureFile(filePath: string, suffix: string) {
|
|
174
|
-
return !isFileInDir(filePath, 'modules') || isSuffixedModuleFile(filePath, suffix)
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
function hasDefaultExport(filePath: string) {
|
|
178
|
-
return /\bexport\s+default\b/.test(readFileSync(filePath, 'utf8'))
|
|
179
|
-
}
|
|
183
|
+
function isModuleFeatureFile(filePath: string, suffix: string) {
|
|
184
|
+
return !isFileInDir(filePath, 'modules') || isSuffixedModuleFile(filePath, suffix)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function hasDefaultExport(filePath: string) {
|
|
188
|
+
return /\bexport\s+default\b/.test(readFileSync(filePath, 'utf8'))
|
|
189
|
+
}
|
|
180
190
|
|
|
181
191
|
function indentObject(content: string, spaces = 2) {
|
|
182
192
|
if (!content) {
|
|
@@ -226,18 +236,18 @@ function generateControllersRegistry() {
|
|
|
226
236
|
const groupLines: string[] = []
|
|
227
237
|
|
|
228
238
|
for (const group of controllerGroups) {
|
|
229
|
-
const entries = getFilesFromDirs(group.dirs)
|
|
230
|
-
.filter((filePath) => basename(filePath) !== 'index.ts')
|
|
231
|
-
.filter((filePath) => !group.suffix || isModuleFeatureFile(filePath, group.suffix))
|
|
232
|
-
.filter(hasDefaultExport)
|
|
233
|
-
.map((filePath, index) => {
|
|
234
|
-
const baseDir = group.dirs.find((dirName) => {
|
|
235
|
-
return isFileInDir(filePath, dirName)
|
|
236
|
-
}) ?? group.dirs[0]
|
|
237
|
-
const modulePath = toModulePath(baseDir, filePath, group.suffix ? [group.suffix] : [])
|
|
238
|
-
const importName = toIdentifier([group.name, modulePath, String(index), 'Controller'])
|
|
239
|
-
|
|
240
|
-
return { modulePath, importName, filePath }
|
|
239
|
+
const entries = getFilesFromDirs(group.dirs)
|
|
240
|
+
.filter((filePath) => basename(filePath) !== 'index.ts')
|
|
241
|
+
.filter((filePath) => !group.suffix || isModuleFeatureFile(filePath, group.suffix))
|
|
242
|
+
.filter(hasDefaultExport)
|
|
243
|
+
.map((filePath, index) => {
|
|
244
|
+
const baseDir = group.dirs.find((dirName) => {
|
|
245
|
+
return isFileInDir(filePath, dirName)
|
|
246
|
+
}) ?? group.dirs[0]
|
|
247
|
+
const modulePath = toModulePath(baseDir, filePath, group.suffix ? [group.suffix] : [])
|
|
248
|
+
const importName = toIdentifier([group.name, modulePath, String(index), 'Controller'])
|
|
249
|
+
|
|
250
|
+
return { modulePath, importName, filePath }
|
|
241
251
|
})
|
|
242
252
|
.filter((entry) => {
|
|
243
253
|
if (group.name !== 'controller') {
|
|
@@ -274,8 +284,12 @@ function generateControllersRegistry() {
|
|
|
274
284
|
4,
|
|
275
285
|
)
|
|
276
286
|
|
|
277
|
-
|
|
278
|
-
|
|
287
|
+
if (group.name === 'controller') {
|
|
288
|
+
groupLines.push(objectBody)
|
|
289
|
+
} else {
|
|
290
|
+
groupLines.push(` ${group.name}: {\n${objectBody}\n },`)
|
|
291
|
+
}
|
|
292
|
+
}
|
|
279
293
|
|
|
280
294
|
const helperImport = imports.length > 0
|
|
281
295
|
? `import { createController } from 'jax-hono/core/controller'\n`
|
package/docs/agent.md
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Agent 维护说明
|
|
2
|
+
|
|
3
|
+
这份文档给 Codex、Claude 或其他代码代理阅读,用来说明维护 `jax-hono` 时的默认规则。
|
|
4
|
+
|
|
5
|
+
## 本地 link 规则
|
|
6
|
+
|
|
7
|
+
`jax-hono` 是用户自己维护的框架,常通过 `jax link` 链接到业务工程的 `node_modules/jax-hono`。
|
|
8
|
+
|
|
9
|
+
如果在业务工程中需要修改 `jax-hono` 行为,先检查依赖是否已经 link 到本地源码目录。不要把它当成一次性的第三方 `node_modules` 临时补丁。
|
|
10
|
+
|
|
11
|
+
在 Windows PowerShell 中,可以在业务仓库根目录查找所有 `jax-hono` 依赖:
|
|
12
|
+
|
|
13
|
+
```powershell
|
|
14
|
+
Get-ChildItem -Path . -Directory -Recurse -Filter jax-hono |
|
|
15
|
+
Where-Object { $_.FullName -match '\\node_modules\\jax-hono$' } |
|
|
16
|
+
Format-List LinkType,Target,FullName
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
如果 `LinkType` 是 `Junction` 或 `SymbolicLink`,直接修改 `Target` 指向的 `jax-hono` 源码目录。
|
|
20
|
+
|
|
21
|
+
如果没有 link,先执行:
|
|
22
|
+
|
|
23
|
+
```powershell
|
|
24
|
+
jax link
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
然后再次确认 link 状态,再修改框架源码。
|
|
28
|
+
|
|
29
|
+
## 修改生成器后的验证
|
|
30
|
+
|
|
31
|
+
修改 `build/generate-registry.ts`、`build/generate-config.ts` 等生成逻辑后,需要在使用方工程里重新生成。
|
|
32
|
+
|
|
33
|
+
常见命令:
|
|
34
|
+
|
|
35
|
+
```powershell
|
|
36
|
+
bun run setup
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
然后检查业务工程中的生成结果,例如:
|
|
40
|
+
|
|
41
|
+
```text
|
|
42
|
+
generated/controllers.generated.ts
|
|
43
|
+
generated/models.generated.ts
|
|
44
|
+
generated/services.generated.ts
|
|
45
|
+
generated/middlewares.generated.ts
|
|
46
|
+
generated/plugins.generated.ts
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
如果业务仓库里有多个工程都依赖 `jax-hono`,分别查看各工程的 `package.json`,运行它们自己的 setup/build 命令。
|
|
50
|
+
|
|
51
|
+
## Controller 注册约定
|
|
52
|
+
|
|
53
|
+
生成器需要保持不同命名空间的边界清晰:
|
|
54
|
+
|
|
55
|
+
- `*.backend.ts` 注册到 `controllers.backend`
|
|
56
|
+
- `*.api.ts` 注册到 `controllers.api`
|
|
57
|
+
- `*.open.ts` 注册到 `controllers.open`
|
|
58
|
+
- `*.client.ts` 注册到 `controllers.client`
|
|
59
|
+
- `*.controller.ts` 注册到 `controllers` 根对象
|
|
60
|
+
|
|
61
|
+
`.controller.ts` 表示通用 Controller,供 backend/api/open/client 等不同路由复用,不应自动归入 `controllers.backend`。
|
|
62
|
+
|
|
63
|
+
例如:
|
|
64
|
+
|
|
65
|
+
```text
|
|
66
|
+
src/modules/oss/oss.controller.ts
|
|
67
|
+
src/modules/oss/oss-bucket.controller.ts
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
应生成:
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
controllers.oss
|
|
74
|
+
controllers.ossBucket
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
如果需要后台专用 Controller,使用:
|
|
78
|
+
|
|
79
|
+
```text
|
|
80
|
+
src/modules/foo/foo.backend.ts
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
应生成:
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
controllers.backend.foo
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## 模块路径命名
|
|
90
|
+
|
|
91
|
+
模块内文件名如果以模块目录名开头,生成 key 时可以去掉重复前缀:
|
|
92
|
+
|
|
93
|
+
```text
|
|
94
|
+
src/modules/oss/oss.controller.ts -> controllers.oss
|
|
95
|
+
src/modules/oss/oss-bucket.controller.ts -> controllers.ossBucket
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
不要生成成:
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
controllers.oss.oss
|
|
102
|
+
controllers.oss.ossBucket
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
这样业务侧调用会更自然,也更适合在不同路由层复用。
|