@hono-filebased-route/core 0.4.1 → 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.
- package/CHANGELOG.md +7 -0
- package/README.md +183 -183
- package/build.ts +8 -10
- package/dist/index.d.ts +0 -2
- package/dist/index.js +5753 -133
- package/dist/index.js.map +7 -0
- package/index.ts +3 -3
- package/package.json +52 -52
- package/scripts/generate-routes.ts +4 -2
- package/utils/load-routes-utils.ts +43 -27
- package/utils/logger.ts +10 -12
package/index.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from './utils/load-routes-utils'
|
|
2
|
-
export * from './scripts/generate-routes'
|
|
3
|
-
export * from './utils/logger'
|
|
1
|
+
export * from './utils/load-routes-utils'
|
|
2
|
+
export * from './scripts/generate-routes'
|
|
3
|
+
export * from './utils/logger'
|
package/package.json
CHANGED
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@hono-filebased-route/core",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"type": "module",
|
|
5
|
-
"description": "A core utility for file-based routing in Hono applications.",
|
|
6
|
-
"author": "HM Suiji <hmsuiji@gmail.com>",
|
|
7
|
-
"keywords": [
|
|
8
|
-
"hono",
|
|
9
|
-
"router",
|
|
10
|
-
"file-based",
|
|
11
|
-
"routing",
|
|
12
|
-
"backend",
|
|
13
|
-
"framework",
|
|
14
|
-
"typescript",
|
|
15
|
-
"file-based-route"
|
|
16
|
-
],
|
|
17
|
-
"license": "MIT",
|
|
18
|
-
"repository": {
|
|
19
|
-
"type": "git",
|
|
20
|
-
"url": "https://github.com/HM-Suiji/hono-filebased-route.git"
|
|
21
|
-
},
|
|
22
|
-
"main": "dist/index.js",
|
|
23
|
-
"types": "dist/index.d.ts",
|
|
24
|
-
"scripts": {
|
|
25
|
-
"build": "bun run build.ts",
|
|
26
|
-
"clean": "rm -rf dist"
|
|
27
|
-
},
|
|
28
|
-
"dependencies": {
|
|
29
|
-
"fast-glob": "^3.3.3",
|
|
30
|
-
"fs": "0.0.1-security",
|
|
31
|
-
"hono": "^4.9.2",
|
|
32
|
-
"path": "^0.12.7",
|
|
33
|
-
"pino": "^9.9.0"
|
|
34
|
-
},
|
|
35
|
-
"devDependencies": {
|
|
36
|
-
"@types/bun": "^1.2.20",
|
|
37
|
-
"@types/node": "^24.3.0",
|
|
38
|
-
"pino-pretty": "^13.1.1",
|
|
39
|
-
"bun-plugin-dts": "^0.3.0",
|
|
40
|
-
"typescript": "^5.0.0"
|
|
41
|
-
},
|
|
42
|
-
"peerDependenciesMeta": {
|
|
43
|
-
"hono": {
|
|
44
|
-
"optional": false
|
|
45
|
-
},
|
|
46
|
-
"typescript": {
|
|
47
|
-
"optional": false
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
"publishConfig": {
|
|
51
|
-
"access": "public"
|
|
52
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@hono-filebased-route/core",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "A core utility for file-based routing in Hono applications.",
|
|
6
|
+
"author": "HM Suiji <hmsuiji@gmail.com>",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"hono",
|
|
9
|
+
"router",
|
|
10
|
+
"file-based",
|
|
11
|
+
"routing",
|
|
12
|
+
"backend",
|
|
13
|
+
"framework",
|
|
14
|
+
"typescript",
|
|
15
|
+
"file-based-route"
|
|
16
|
+
],
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "https://github.com/HM-Suiji/hono-filebased-route.git"
|
|
21
|
+
},
|
|
22
|
+
"main": "dist/index.js",
|
|
23
|
+
"types": "dist/index.d.ts",
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "bun run build.ts",
|
|
26
|
+
"clean": "rm -rf dist"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"fast-glob": "^3.3.3",
|
|
30
|
+
"fs": "0.0.1-security",
|
|
31
|
+
"hono": "^4.9.2",
|
|
32
|
+
"path": "^0.12.7",
|
|
33
|
+
"pino": "^9.9.0"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@types/bun": "^1.2.20",
|
|
37
|
+
"@types/node": "^24.3.0",
|
|
38
|
+
"pino-pretty": "^13.1.1",
|
|
39
|
+
"bun-plugin-dts": "^0.3.0",
|
|
40
|
+
"typescript": "^5.0.0"
|
|
41
|
+
},
|
|
42
|
+
"peerDependenciesMeta": {
|
|
43
|
+
"hono": {
|
|
44
|
+
"optional": false
|
|
45
|
+
},
|
|
46
|
+
"typescript": {
|
|
47
|
+
"optional": false
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public"
|
|
52
|
+
}
|
|
53
53
|
}
|
|
@@ -43,6 +43,8 @@ export async function generateRoutesFile(config?: Partial<Config>) {
|
|
|
43
43
|
|
|
44
44
|
const exportedMethods = getExportedHttpMethods(file)
|
|
45
45
|
const middlewareHandler = getExportedMiddlewareHandler(file)
|
|
46
|
+
logger.info(`Exported methods: ${JSON.stringify(exportedMethods)}`)
|
|
47
|
+
logger.info(`Middleware handler: ${JSON.stringify(middlewareHandler)}`)
|
|
46
48
|
|
|
47
49
|
if (!exportedMethods.GET && !exportedMethods.POST) continue
|
|
48
50
|
|
|
@@ -61,14 +63,14 @@ export async function generateRoutesFile(config?: Partial<Config>) {
|
|
|
61
63
|
)
|
|
62
64
|
else
|
|
63
65
|
routeDefinitions.push(
|
|
64
|
-
` ${tempHonoVar}.${method.toLowerCase()}('/', ${moduleName}.config
|
|
66
|
+
` ${tempHonoVar}.${method.toLowerCase()}('/', ${moduleName}.config.${method}, async (c) => ${moduleName}.${method}(c, c.req.path.substring(${len}).split('/')));`
|
|
65
67
|
)
|
|
66
68
|
} else {
|
|
67
69
|
if (!middlewareHandler[method])
|
|
68
70
|
routeDefinitions.push(` ${tempHonoVar}.${method.toLowerCase()}('/', ${moduleName}.${method});`)
|
|
69
71
|
else
|
|
70
72
|
routeDefinitions.push(
|
|
71
|
-
` ${tempHonoVar}.${method.toLowerCase()}('/', ${moduleName}.config
|
|
73
|
+
` ${tempHonoVar}.${method.toLowerCase()}('/', ${moduleName}.config.${method}, ${moduleName}.${method});`
|
|
72
74
|
)
|
|
73
75
|
}
|
|
74
76
|
logger.info(`Generated route: ${method} ${routePath}`)
|
|
@@ -3,13 +3,17 @@ import fg from 'fast-glob'
|
|
|
3
3
|
import { readFileSync } from 'fs'
|
|
4
4
|
import { ExportedMethods, Method, METHODS } from '../types'
|
|
5
5
|
import {
|
|
6
|
-
createSourceFile,
|
|
7
|
-
ScriptTarget,
|
|
8
|
-
isVariableStatement,
|
|
9
|
-
isFunctionDeclaration,
|
|
10
|
-
SyntaxKind,
|
|
11
|
-
isIdentifier,
|
|
12
|
-
|
|
6
|
+
createSourceFile,
|
|
7
|
+
ScriptTarget,
|
|
8
|
+
isVariableStatement,
|
|
9
|
+
isFunctionDeclaration,
|
|
10
|
+
SyntaxKind,
|
|
11
|
+
isIdentifier,
|
|
12
|
+
isObjectLiteralExpression,
|
|
13
|
+
isPropertyAssignment,
|
|
14
|
+
isShorthandPropertyAssignment,
|
|
15
|
+
isStringLiteral,
|
|
16
|
+
} from 'typescript'
|
|
13
17
|
|
|
14
18
|
/**
|
|
15
19
|
* 遍历指定目录并获取所有文件路径
|
|
@@ -86,23 +90,35 @@ export function getExportedHttpMethods(filePath: string): ExportedMethods {
|
|
|
86
90
|
* @param filePath 文件的绝对路径
|
|
87
91
|
* @returns 是否导出 MiddlewareHandler
|
|
88
92
|
*/
|
|
89
|
-
export function getExportedMiddlewareHandler(filePath: string): ExportedMethods {
|
|
90
|
-
const fileContent = readFileSync(filePath, 'utf8')
|
|
91
|
-
const sourceFile = createSourceFile(filePath, fileContent, ScriptTarget.ESNext, true)
|
|
92
|
-
const methodConfigs: ExportedMethods = {} as ExportedMethods
|
|
93
|
-
sourceFile.forEachChild(node => {
|
|
94
|
-
// 寻找 export const
|
|
95
|
-
if (isVariableStatement(node) && node.modifiers && node.modifiers.some(m => m.kind === SyntaxKind.ExportKeyword)) {
|
|
96
|
-
for (const declaration of node.declarationList.declarations) {
|
|
97
|
-
if (
|
|
98
|
-
isIdentifier(declaration.name) &&
|
|
99
|
-
declaration.name.text
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
93
|
+
export function getExportedMiddlewareHandler(filePath: string): ExportedMethods {
|
|
94
|
+
const fileContent = readFileSync(filePath, 'utf8')
|
|
95
|
+
const sourceFile = createSourceFile(filePath, fileContent, ScriptTarget.ESNext, true)
|
|
96
|
+
const methodConfigs: ExportedMethods = {} as ExportedMethods
|
|
97
|
+
sourceFile.forEachChild(node => {
|
|
98
|
+
// 寻找 export const config = { GET: ..., POST: ... }
|
|
99
|
+
if (isVariableStatement(node) && node.modifiers && node.modifiers.some(m => m.kind === SyntaxKind.ExportKeyword)) {
|
|
100
|
+
for (const declaration of node.declarationList.declarations) {
|
|
101
|
+
if (
|
|
102
|
+
isIdentifier(declaration.name) &&
|
|
103
|
+
declaration.name.text === 'config' &&
|
|
104
|
+
declaration.initializer &&
|
|
105
|
+
isObjectLiteralExpression(declaration.initializer)
|
|
106
|
+
) {
|
|
107
|
+
for (const prop of declaration.initializer.properties) {
|
|
108
|
+
let key: string | undefined
|
|
109
|
+
if (isPropertyAssignment(prop)) {
|
|
110
|
+
if (isIdentifier(prop.name)) key = prop.name.text
|
|
111
|
+
else if (isStringLiteral(prop.name)) key = prop.name.text
|
|
112
|
+
} else if (isShorthandPropertyAssignment(prop)) {
|
|
113
|
+
key = prop.name.text
|
|
114
|
+
}
|
|
115
|
+
if (key && METHODS.includes(key as Method)) {
|
|
116
|
+
methodConfigs[key as Method] = true
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
})
|
|
123
|
+
return methodConfigs
|
|
124
|
+
}
|
package/utils/logger.ts
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import pino, { Logger } from 'pino'
|
|
2
|
-
|
|
2
|
+
import pinoPretty from 'pino-pretty'
|
|
3
|
+
|
|
3
4
|
export const createLogger = (verbose: boolean = false) =>
|
|
4
5
|
verbose
|
|
5
|
-
? pino(
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
},
|
|
11
|
-
},
|
|
12
|
-
})
|
|
6
|
+
? pino(
|
|
7
|
+
pinoPretty({
|
|
8
|
+
colorize: true,
|
|
9
|
+
})
|
|
10
|
+
)
|
|
13
11
|
: ({
|
|
14
12
|
info: () => { },
|
|
15
13
|
debug: () => { },
|
|
16
|
-
error: () => { },
|
|
17
|
-
warn: () => { },
|
|
18
|
-
} as unknown as Logger)
|
|
14
|
+
error: () => { },
|
|
15
|
+
warn: () => { },
|
|
16
|
+
} as unknown as Logger)
|