galbe 0.4.1 → 0.5.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/docs/plugins.md +36 -36
- package/package.json +1 -1
- package/src/routes.ts +3 -3
- package/src/util.ts +21 -2
package/docs/plugins.md
CHANGED
|
@@ -17,7 +17,7 @@ type GalbePlugin = {
|
|
|
17
17
|
|
|
18
18
|
**name**
|
|
19
19
|
|
|
20
|
-
The name should be a Unique Plugin Identifier. It should be chosen to be unique to avoid conflicts with other potential plugins.
|
|
20
|
+
The name should be a Unique Plugin Identifier. It should be chosen to be unique to avoid conflicts with other potential plugins. Ideally, it will have the form of `com.example.myplugin`.
|
|
21
21
|
|
|
22
22
|
**init**
|
|
23
23
|
|
|
@@ -62,44 +62,44 @@ Here is an example of a plugin implementation that handles routes tagged with `@
|
|
|
62
62
|
|
|
63
63
|
```ts
|
|
64
64
|
// myPlugin.ts
|
|
65
|
-
|
|
66
|
-
import {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
65
|
+
import type { GalbePlugin } from 'galbe'
|
|
66
|
+
import { walkMetaRoutes } from 'galbe/utils'
|
|
67
|
+
|
|
68
|
+
const PLUGIN_ID = 'dev.galbe.deprecated'
|
|
69
|
+
|
|
70
|
+
export default () => {
|
|
71
|
+
let deprecateds = new Set<string>()
|
|
72
|
+
return {
|
|
73
|
+
name: PLUGIN_ID,
|
|
74
|
+
// Init the plugin, check for deprecated metadata tags
|
|
75
|
+
init(_config, galbe) {
|
|
76
|
+
if (galbe.meta) {
|
|
77
|
+
walkMetaRoutes(galbe.meta, (method, path, meta) => {
|
|
78
|
+
if (meta.deprecated) deprecateds.add(JSON.stringify({ method, path }))
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
// Check if the current route is deprecated; if so, flag it as such and log it
|
|
83
|
+
onRoute(context) {
|
|
84
|
+
let r = context.route
|
|
85
|
+
if (!r) return
|
|
86
|
+
if (deprecateds.has(JSON.stringify({ method: r.method, path: r.path }))) {
|
|
87
|
+
context.state[PLUGIN_ID] = { deprecated: true }
|
|
88
|
+
console.warn(`Call to deprecated route "${r.method} ${r.path}"`)
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
// Add a header to the response if the route has been flagged as deprecated
|
|
92
|
+
afterHandle(response, context) {
|
|
93
|
+
let r = context.route
|
|
94
|
+
if (!r) return
|
|
95
|
+
console.log('yooo', r.method, r.path)
|
|
96
|
+
if (deprecateds.has(JSON.stringify({ method: r.method, path: r.path }))) {
|
|
97
|
+
console.log('OK...')
|
|
98
|
+
response.headers.set('x-deprecated', 'true')
|
|
83
99
|
}
|
|
84
100
|
}
|
|
85
|
-
}
|
|
86
|
-
// Check if the current route is deprecated; if so, flag it as such and log it
|
|
87
|
-
onRoute(context: Context) {
|
|
88
|
-
let route = context.route
|
|
89
|
-
if (this.deprecated?.[route.method]?.includes(route.path)) {
|
|
90
|
-
context.state[this.name] = { deprecated: true }
|
|
91
|
-
console.warn(`Call to deprecated route [${route.method}]${route.path}`)
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
// Add a header if the request has previously been flagged as deprecated
|
|
95
|
-
afterHandle(response: Response, context: Context) {
|
|
96
|
-
if (context.state?.[this.name]?.deprecated) {
|
|
97
|
-
response.headers.set('x-deprecated', 'true')
|
|
98
|
-
}
|
|
99
|
-
}
|
|
101
|
+
} as GalbePlugin
|
|
100
102
|
}
|
|
101
|
-
|
|
102
|
-
export default new MyPlugin()
|
|
103
103
|
```
|
|
104
104
|
|
|
105
105
|
```ts
|
package/package.json
CHANGED
package/src/routes.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { GalbeConfig, Route } from './types'
|
|
1
|
+
import type { GalbeConfig, Method, Route } from './types'
|
|
2
2
|
|
|
3
3
|
import { readdir, lstat } from 'fs/promises'
|
|
4
4
|
import { extname } from 'path'
|
|
@@ -13,7 +13,7 @@ export const DEFAULT_ROUTE_PATTERN = 'src/**/*.route.{js,ts}'
|
|
|
13
13
|
export type RouteMeta = { head?: string } & Record<string, boolean | string | string[]>
|
|
14
14
|
export type RoutesMeta = {
|
|
15
15
|
header: Record<string, boolean | string | string[]>
|
|
16
|
-
routes: Record<string, Record<
|
|
16
|
+
routes: Record<string, Partial<Record<Method, RouteMeta>>>
|
|
17
17
|
}
|
|
18
18
|
export type RouteInstanciationCallback = <T extends 'add' | 'error'>(event: {
|
|
19
19
|
type: T
|
|
@@ -204,7 +204,7 @@ export const metaAnalysis = async (filePath: string): Promise<RoutesMeta> => {
|
|
|
204
204
|
// @ts-ignore
|
|
205
205
|
const path = node.arguments[0].value
|
|
206
206
|
// @ts-ignore
|
|
207
|
-
const method = node.callee.property.name
|
|
207
|
+
const method = node.callee.property.name as Method
|
|
208
208
|
const line = node.loc?.start.line || -1
|
|
209
209
|
const col = node.loc?.start.column || -1
|
|
210
210
|
const com = comments?.[line]?.[col - 1] ? comments[line][col - 1] : ''
|
package/src/util.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Route, RouteNode } from '.'
|
|
2
|
-
import type { RouteMeta } from './routes'
|
|
1
|
+
import type { Method, Route, RouteNode } from '.'
|
|
2
|
+
import type { RouteFileMeta, RouteMeta } from './routes'
|
|
3
3
|
|
|
4
4
|
const METHOD_COLOR: Record<string, string> = {
|
|
5
5
|
get: '\x1b[32m',
|
|
@@ -24,12 +24,31 @@ export const logRoute = (
|
|
|
24
24
|
)
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Walk over the routes tree. A callback is called for each route with Route infos.
|
|
29
|
+
*/
|
|
27
30
|
export const walkRoutes = (node: RouteNode, cb: (route: Route) => void) => {
|
|
28
31
|
if (node?.routes) Object.values(node.routes).forEach(r => cb(r))
|
|
29
32
|
for (let c of Object.values(node?.children || {})) walkRoutes(c, cb)
|
|
30
33
|
if (node?.param) walkRoutes(node.param, cb)
|
|
31
34
|
}
|
|
32
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Walk over the routes metadata tree. A callback is called for each route metadata with RouteMeta infos.
|
|
38
|
+
*/
|
|
39
|
+
export const walkMetaRoutes = (
|
|
40
|
+
meta: RouteFileMeta[],
|
|
41
|
+
cb: (method: Method, path: string, routeMeta: RouteMeta) => void
|
|
42
|
+
) => {
|
|
43
|
+
for (const f of meta) {
|
|
44
|
+
for (const [path, methods] of Object.entries(f.routes)) {
|
|
45
|
+
for (const [method, meta] of Object.entries(methods)) {
|
|
46
|
+
cb(method as Method, path, meta)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
33
52
|
export const isIterator = (obj: any) => typeof obj?.next === 'function'
|
|
34
53
|
|
|
35
54
|
export const HttpStatus = {
|