rajt 0.0.57 → 0.0.59
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 +10 -7
- package/package.json +35 -15
- package/src/action-old.ts +72 -0
- package/src/action.ts +12 -61
- package/src/auth/ability.ts +2 -2
- package/src/auth/authnz.ts +3 -0
- package/src/auth/index.ts +0 -1
- package/src/auth/token.ts +27 -24
- package/src/bin/rajt.js +123 -0
- package/src/cli/commands/dev/index.ts +294 -0
- package/src/cli/commands/dev/utils.ts +215 -0
- package/src/cli/index.ts +69 -0
- package/src/cli/types.ts +1 -0
- package/src/create-app.ts +15 -9
- package/src/db/d1.d.ts +1 -0
- package/src/db/d1.ts +1 -0
- package/src/dev.ts +18 -15
- package/src/enum.ts +2 -75
- package/src/esbuild.mjs +11 -9
- package/src/http.ts +9 -8
- package/src/index.ts +1 -3
- package/src/prod-aws.ts +2 -17
- package/src/prod-cf.ts +1 -18
- package/src/prod.ts +16 -0
- package/src/request-old.ts +98 -0
- package/src/request.ts +152 -71
- package/src/response.ts +71 -26
- package/src/routes.ts +66 -2
- package/src/scripts/cache-routes.ts +1 -64
- package/src/types.ts +24 -4
- package/src/utils/environment.ts +3 -2
- package/src/utils/func.ts +2 -2
- package/src/utils/local-date.ts +13 -0
- package/src/utils/logger.ts +61 -0
- package/src/utils/port.ts +1 -3
- package/src/utils/resolve.ts +4 -3
- package/src/utils/shutdown.ts +19 -0
- package/src/validator.ts +68 -0
- package/src/auth/auth.ts +0 -33
- package/src/dynamodb/client.ts +0 -125
- package/src/dynamodb/compact.ts +0 -205
- package/src/dynamodb/decorators.ts +0 -126
- package/src/dynamodb/index.ts +0 -4
- package/src/dynamodb/model.ts +0 -258
- package/src/dynamodb/query-builder.ts +0 -174
- package/src/dynamodb/repository.ts +0 -31
- package/src/dynamodb/schema.ts +0 -107
- package/src/dynamodb/types.ts +0 -32
- package/src/utils/lenght.ts +0 -32
package/src/dev.ts
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
|
+
import { fileURLToPath } from 'node:url'
|
|
2
|
+
import { dirname, join } from 'node:path'
|
|
1
3
|
import { config } from 'dotenv'
|
|
2
|
-
import { serve } from '@hono/node-server'
|
|
4
|
+
import { serve, type ServerType } from '@hono/node-server'
|
|
3
5
|
import createApp from './create-app'
|
|
4
6
|
import { getRoutes, getMiddlewares } from './routes'
|
|
5
7
|
import { registerHandler, registerMiddleware } from './register'
|
|
6
8
|
import { Ability } from './auth'
|
|
7
|
-
import { getAvailablePort } from './utils/port'
|
|
8
9
|
import jsonImport from './utils/json-import'
|
|
9
10
|
import { setEnv, detectEnvironment } from './utils/environment'
|
|
11
|
+
import shutdown from './utils/shutdown'
|
|
10
12
|
|
|
11
13
|
setEnv(detectEnvironment())
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
const __dirname = join(dirname(fileURLToPath(import.meta.url)), '../../../')
|
|
16
|
+
|
|
17
|
+
config({ path: join(__dirname, '.env.dev') })
|
|
14
18
|
|
|
15
19
|
let routes = await getRoutes()
|
|
16
20
|
routes.forEach(r => registerHandler(r.name, r.handle))
|
|
@@ -20,18 +24,17 @@ const middlewares = await getMiddlewares()
|
|
|
20
24
|
middlewares.forEach(mw => registerMiddleware(mw.handle))
|
|
21
25
|
|
|
22
26
|
Ability.fromRoutes(routes)
|
|
23
|
-
Ability.roles = jsonImport('
|
|
27
|
+
Ability.roles = jsonImport(join(__dirname, 'roles.json'))
|
|
24
28
|
|
|
25
29
|
const fetch = createApp({ routes }).fetch
|
|
26
30
|
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
})
|
|
31
|
+
const port = process.env?.PORT ? Number(process.env.PORT) : 3000
|
|
32
|
+
|
|
33
|
+
let server: ServerType | null = serve({ fetch, port })
|
|
34
|
+
|
|
35
|
+
shutdown(() => {
|
|
36
|
+
if (server) {
|
|
37
|
+
server?.close()
|
|
38
|
+
server = null
|
|
39
|
+
}
|
|
40
|
+
})
|
package/src/enum.ts
CHANGED
|
@@ -1,75 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
: T extends Record<string, string | number>
|
|
4
|
-
? T
|
|
5
|
-
: never
|
|
6
|
-
|
|
7
|
-
type EnumValue<T> = T extends string[]
|
|
8
|
-
? T[number]
|
|
9
|
-
: T extends Record<string, infer V>
|
|
10
|
-
? V
|
|
11
|
-
: never
|
|
12
|
-
|
|
13
|
-
type EnumStatic<T> = {
|
|
14
|
-
has(search: string | number): boolean
|
|
15
|
-
key(search: string | number): string | null
|
|
16
|
-
value(search: string | number): EnumValue<T> | null
|
|
17
|
-
readonly keys: string[]
|
|
18
|
-
readonly values: Array<EnumValue<T>>
|
|
19
|
-
toObject(): EnumType<T>
|
|
20
|
-
} & EnumType<T>
|
|
21
|
-
|
|
22
|
-
export default function Enum<T extends string[] | Record<string, string | number>>(definition: T): EnumStatic<T> {
|
|
23
|
-
const enumObj = Array.isArray(definition)
|
|
24
|
-
? Object.fromEntries(definition.map(key => [key, key])) as EnumType<T>
|
|
25
|
-
: definition as EnumType<T>
|
|
26
|
-
|
|
27
|
-
const keyToValueMap = new Map<string | number, string | number>()
|
|
28
|
-
const valueToKeyMap = new Map<string | number, string>()
|
|
29
|
-
|
|
30
|
-
Object.entries(enumObj).forEach(([key, value]) => {
|
|
31
|
-
keyToValueMap.set(key, value)
|
|
32
|
-
valueToKeyMap.set(String(value), key)
|
|
33
|
-
if (typeof value === 'number') valueToKeyMap.set(value.toString(), key)
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
const GeneratedEnum = class {
|
|
37
|
-
static has(search: string | number): boolean {
|
|
38
|
-
return keyToValueMap.has(search as string) || valueToKeyMap.has(String(search))
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
static key(search: string | number): string | null {
|
|
42
|
-
if (keyToValueMap.has(search as string))
|
|
43
|
-
return search as string
|
|
44
|
-
|
|
45
|
-
return valueToKeyMap.get(String(search)) || null
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
static value(search: string | number): EnumValue<T> | null {
|
|
49
|
-
if (keyToValueMap.has(search as string))
|
|
50
|
-
return keyToValueMap.get(search as string) as EnumValue<T>
|
|
51
|
-
|
|
52
|
-
return valueToKeyMap.has(String(search))
|
|
53
|
-
? keyToValueMap.get(valueToKeyMap.get(String(search))!) as EnumValue<T>
|
|
54
|
-
: null
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
static get keys(): string[] {
|
|
58
|
-
return Object.keys(enumObj)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
static get values(): Array<EnumValue<T>> {
|
|
62
|
-
return Object.values(enumObj) as Array<EnumValue<T>>
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
static toObject(): EnumType<T> {
|
|
66
|
-
return { ...enumObj }
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
Object.entries(enumObj).forEach(([key, value]) => {
|
|
71
|
-
(GeneratedEnum as any)[key] = value
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
return GeneratedEnum as unknown as EnumStatic<T>
|
|
75
|
-
}
|
|
1
|
+
export { Enum } from 't0n'
|
|
2
|
+
export type { EnumStatic, EnumValue, EnumType } from 't0n'
|
package/src/esbuild.mjs
CHANGED
|
@@ -34,7 +34,7 @@ const buildOptions = {
|
|
|
34
34
|
bundle: true,
|
|
35
35
|
minify: true,
|
|
36
36
|
outfile: join(__dirname, '../../../dist/index.js'),
|
|
37
|
-
platform: isCF ? 'browser' : '
|
|
37
|
+
platform: isCF ? 'browser' : 'node',
|
|
38
38
|
target: isCF ? 'es2022' : 'node20',
|
|
39
39
|
conditions: isCF ? ['worker', 'browser'] : [],
|
|
40
40
|
format: 'esm',
|
|
@@ -44,8 +44,8 @@ const buildOptions = {
|
|
|
44
44
|
'@aws-sdk', '@smithy',
|
|
45
45
|
...(isCF ? [
|
|
46
46
|
'cloudflare:workers',
|
|
47
|
-
'node:crypto',
|
|
48
|
-
'
|
|
47
|
+
'node:crypto', 'crypto',
|
|
48
|
+
'node:buffer', 'buffer',
|
|
49
49
|
] : []),
|
|
50
50
|
],
|
|
51
51
|
metafile: true,
|
|
@@ -102,12 +102,14 @@ existsSync(distDir)
|
|
|
102
102
|
for (const file of await readdirSync(distDir))
|
|
103
103
|
await rmSync(join(distDir, file))
|
|
104
104
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
105
|
+
if (isCF) {
|
|
106
|
+
for (let file of [
|
|
107
|
+
'wrangler.toml',
|
|
108
|
+
]) {
|
|
109
|
+
file = join(cwd, file)
|
|
110
|
+
if (existsSync(file))
|
|
111
|
+
copyFileSync(file, join(cwd, 'dist', basename(file)))
|
|
112
|
+
}
|
|
111
113
|
}
|
|
112
114
|
|
|
113
115
|
esbuild.build(buildOptions)
|
package/src/http.ts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import type { Context, Next } from 'hono'
|
|
2
2
|
import { MiddlewareType } from './middleware'
|
|
3
|
-
import
|
|
4
|
-
import { Ability
|
|
3
|
+
import response from './response'
|
|
4
|
+
import { Ability } from './auth'
|
|
5
5
|
import mergeMiddleware from './utils/merge-middleware'
|
|
6
|
+
import { IRequest } from './types'
|
|
6
7
|
|
|
7
8
|
function method(method: string, ...args: any[]): void | ClassDecorator {
|
|
8
|
-
if (args.length
|
|
9
|
+
if (args.length == 1 && typeof args[0] == 'function')
|
|
9
10
|
return _method(method, '/', args[0])
|
|
10
11
|
|
|
11
|
-
const path = typeof args[0]
|
|
12
|
+
const path = typeof args[0] == 'string' ? args[0] : '/'
|
|
12
13
|
return (target: Function) => _method(method, path, target)
|
|
13
14
|
}
|
|
14
15
|
|
|
@@ -93,7 +94,7 @@ export function Middlewares(...handlers: MiddlewareType[]) {
|
|
|
93
94
|
export function Auth(target: Function): void
|
|
94
95
|
export function Auth(): ClassDecorator
|
|
95
96
|
export function Auth(...args: any[]): void | ClassDecorator {
|
|
96
|
-
if (args.length
|
|
97
|
+
if (args.length == 1 && typeof args[0] == 'function')
|
|
97
98
|
return _auth(args[0])
|
|
98
99
|
|
|
99
100
|
return (target: any) => _auth(target)
|
|
@@ -101,11 +102,11 @@ export function Auth(...args: any[]): void | ClassDecorator {
|
|
|
101
102
|
|
|
102
103
|
function _auth(target: Function | any) {
|
|
103
104
|
mergeMiddleware(target, async (c: Context, next: Next) => {
|
|
104
|
-
const
|
|
105
|
+
const req = c.get('_') as IRequest
|
|
105
106
|
const ability = Ability.fromAction(target)
|
|
106
107
|
|
|
107
|
-
if (!user || !ability ||
|
|
108
|
-
return
|
|
108
|
+
if (!req?.user || !ability || req.cant(ability))
|
|
109
|
+
return response.unauthorized()
|
|
109
110
|
|
|
110
111
|
await next()
|
|
111
112
|
})
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
export { default as Action } from './action'
|
|
2
|
-
export { Auth, Auth as Gate } from './auth/auth'
|
|
3
2
|
export { default as Middleware } from './middleware'
|
|
4
|
-
export { default as Request } from './request'
|
|
5
3
|
export { default as Response } from './response'
|
|
6
|
-
export {
|
|
4
|
+
export { Enum } from 't0n'
|
package/src/prod-aws.ts
CHANGED
|
@@ -1,19 +1,4 @@
|
|
|
1
1
|
import { handle } from 'hono/aws-lambda'
|
|
2
|
-
import
|
|
3
|
-
import { Ability } from './auth'
|
|
2
|
+
import { app } from './prod'
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
await import('../../../tmp/import-routes.mjs')
|
|
7
|
-
|
|
8
|
-
// @ts-ignore
|
|
9
|
-
const routes = (await import('../../../tmp/routes.json')).default
|
|
10
|
-
|
|
11
|
-
// @ts-ignore
|
|
12
|
-
Ability.roles = (await import('../../../roles.json')).default
|
|
13
|
-
// @ts-ignore
|
|
14
|
-
Ability.fromRoutes(routes)
|
|
15
|
-
|
|
16
|
-
// @ts-ignore
|
|
17
|
-
const app = createApp({ routes })
|
|
18
|
-
|
|
19
|
-
export const handler = handle(app) // AWS Lambda (LLRT)
|
|
4
|
+
export const handler = handle(app)
|
package/src/prod-cf.ts
CHANGED
|
@@ -1,18 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { Ability } from './auth'
|
|
3
|
-
|
|
4
|
-
// @ts-ignore
|
|
5
|
-
await import('../../../tmp/import-routes.mjs')
|
|
6
|
-
|
|
7
|
-
// @ts-ignore
|
|
8
|
-
const routes = (await import('../../../tmp/routes.json')).default
|
|
9
|
-
|
|
10
|
-
// @ts-ignore
|
|
11
|
-
Ability.roles = (await import('../../../roles.json')).default
|
|
12
|
-
// @ts-ignore
|
|
13
|
-
Ability.fromRoutes(routes)
|
|
14
|
-
|
|
15
|
-
// @ts-ignore
|
|
16
|
-
const app = createApp({ routes })
|
|
17
|
-
|
|
18
|
-
export default app
|
|
1
|
+
export { app as default } from './prod'
|
package/src/prod.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import createApp from './create-app'
|
|
2
|
+
import { Ability } from './auth'
|
|
3
|
+
|
|
4
|
+
// @ts-ignore
|
|
5
|
+
await import('../../../tmp/import-routes.mjs')
|
|
6
|
+
|
|
7
|
+
// @ts-ignore
|
|
8
|
+
const routes = (await import('../../../tmp/routes.json')).default
|
|
9
|
+
|
|
10
|
+
// @ts-ignore
|
|
11
|
+
Ability.roles = (await import('../../../roles.json')).default
|
|
12
|
+
// @ts-ignore
|
|
13
|
+
Ability.fromRoutes(routes)
|
|
14
|
+
|
|
15
|
+
// @ts-ignore
|
|
16
|
+
export const app = createApp({ routes })
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { bufferToFormData } from 'hono/utils/buffer'
|
|
2
|
+
import { HTTPException } from 'hono/http-exception'
|
|
3
|
+
import type { BodyData } from 'hono/utils/body'
|
|
4
|
+
import Response from './response'
|
|
5
|
+
import c from './context'
|
|
6
|
+
|
|
7
|
+
export default class Request {
|
|
8
|
+
static param(key: string) {
|
|
9
|
+
return c.cx.req.param(key)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
static query() {
|
|
13
|
+
return c.cx.req.query()
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
static async form(cType?: string) {
|
|
17
|
+
cType ??= c.cx.req.header('Content-Type')
|
|
18
|
+
if (!cType) return {}
|
|
19
|
+
|
|
20
|
+
let formData: FormData
|
|
21
|
+
|
|
22
|
+
if (c.cx.req.bodyCache.formData) {
|
|
23
|
+
formData = await c.cx.req.bodyCache.formData
|
|
24
|
+
} else {
|
|
25
|
+
try {
|
|
26
|
+
const arrayBuffer = await c.cx.req.arrayBuffer()
|
|
27
|
+
formData = await bufferToFormData(arrayBuffer, cType)
|
|
28
|
+
c.cx.req.bodyCache.formData = formData
|
|
29
|
+
} catch (e) {
|
|
30
|
+
throw new HTTPException(400, {
|
|
31
|
+
message: 'Malformed FormData request.'
|
|
32
|
+
+ (e instanceof Error ? ` ${e.message}` : ` ${String(e)}`)
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const form: BodyData<{ all: true }> = {}
|
|
38
|
+
formData.forEach((value, key) => {
|
|
39
|
+
if (key.endsWith('[]')) {
|
|
40
|
+
;((form[key] ??= []) as unknown[]).push(value)
|
|
41
|
+
} else if (Array.isArray(form[key])) {
|
|
42
|
+
;(form[key] as unknown[]).push(value)
|
|
43
|
+
} else if (key in form) {
|
|
44
|
+
form[key] = [form[key] as string | File, value]
|
|
45
|
+
} else {
|
|
46
|
+
form[key] = value
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
return form
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
static async json<E>() {
|
|
54
|
+
try {
|
|
55
|
+
return await c.cx.req.json<E>()
|
|
56
|
+
} catch {
|
|
57
|
+
throw new HTTPException(400, { message: 'Malformed JSON in request body' })
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
static async body<E>() {
|
|
62
|
+
const cType = c.cx.req.header('Content-Type')
|
|
63
|
+
if (!cType) return {} as E
|
|
64
|
+
|
|
65
|
+
if (/^application\/([a-z-\.]+\+)?json(;\s*[a-zA-Z0-9\-]+\=([^;]+))*$/.test(cType)) {
|
|
66
|
+
return await Request.json<E>()
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (
|
|
70
|
+
/^multipart\/form-data(;\s?boundary=[a-zA-Z0-9'"()+_,\-./:=?]+)?$/.test(cType)
|
|
71
|
+
&& ! /^application\/x-www-form-urlencoded(;\s*[a-zA-Z0-9\-]+\=([^;]+))*$/.test(cType)
|
|
72
|
+
) {
|
|
73
|
+
return await Request.form() as E
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return {} as E
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
static get response() {
|
|
80
|
+
return Response
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
static get cx() {
|
|
84
|
+
return c.cx
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
static get cookie() {
|
|
88
|
+
return c.cookie
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
static get ip() {
|
|
92
|
+
return c.ip
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
static get userAgent() {
|
|
96
|
+
return c.userAgent
|
|
97
|
+
}
|
|
98
|
+
}
|
package/src/request.ts
CHANGED
|
@@ -1,98 +1,179 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getCookie, getSignedCookie, setCookie, setSignedCookie, deleteCookie } from 'hono/cookie'
|
|
2
2
|
import { HTTPException } from 'hono/http-exception'
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
throw new HTTPException(400, {
|
|
31
|
-
message: 'Malformed FormData request.'
|
|
32
|
-
+ (e instanceof Error ? ` ${e.message}` : ` ${String(e)}`)
|
|
33
|
-
})
|
|
34
|
-
}
|
|
35
|
-
}
|
|
3
|
+
import { Authnz, Token } from './auth'
|
|
4
|
+
|
|
5
|
+
import type { Context } from 'hono'
|
|
6
|
+
import type { CookieOptions, CookiePrefixOptions } from 'hono/utils/cookie'
|
|
7
|
+
import type { CustomHeader, RequestHeader } from 'hono/utils/headers'
|
|
8
|
+
import type { BodyData, ParseBodyOptions } from 'hono/utils/body'
|
|
9
|
+
|
|
10
|
+
const cookieWrapper = (c: Context) => ({
|
|
11
|
+
all: () => getCookie(c),
|
|
12
|
+
allSigned: (secret: string) => getSignedCookie(c, secret),
|
|
13
|
+
get: (name: string, prefixOptions?: CookiePrefixOptions) => prefixOptions ? getCookie(c, name, prefixOptions) : getCookie(c, name),
|
|
14
|
+
getSigned: (secret: string, name: string, prefixOptions?: CookiePrefixOptions) => prefixOptions ? getSignedCookie(c, secret, name, prefixOptions) : getSignedCookie(c, secret, name),
|
|
15
|
+
set: (name: string, value: string, opt?: CookieOptions) => setCookie(c, name, value, opt),
|
|
16
|
+
setSigned: (name: string, value: string, secret: string, opt?: CookieOptions) => setSignedCookie(c, name, value, secret, opt),
|
|
17
|
+
delete: (name: string, opt?: CookieOptions) => deleteCookie(c, name, opt)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
export default class $Request {
|
|
21
|
+
#c!: Context
|
|
22
|
+
#cookie: ReturnType<typeof cookieWrapper>
|
|
23
|
+
#u: Authnz<any> | null = null
|
|
24
|
+
|
|
25
|
+
constructor(c: Context) {
|
|
26
|
+
this.#c = c
|
|
27
|
+
this.#cookie = cookieWrapper(c)
|
|
28
|
+
this.#u = Authnz.fromToken(Token.fromRequest(this))
|
|
29
|
+
}
|
|
36
30
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
;((form[key] ??= []) as unknown[]).push(value)
|
|
41
|
-
} else if (Array.isArray(form[key])) {
|
|
42
|
-
;(form[key] as unknown[]).push(value)
|
|
43
|
-
} else if (key in form) {
|
|
44
|
-
form[key] = [form[key] as string | File, value]
|
|
45
|
-
} else {
|
|
46
|
-
form[key] = value
|
|
47
|
-
}
|
|
48
|
-
})
|
|
31
|
+
get user() {
|
|
32
|
+
return this.#u ? this.#u?.data : null
|
|
33
|
+
}
|
|
49
34
|
|
|
50
|
-
|
|
35
|
+
get auth() {
|
|
36
|
+
return this.#u
|
|
51
37
|
}
|
|
52
38
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
39
|
+
can(...abilities: string[]) {
|
|
40
|
+
return this.#u ? this.#u.can(...abilities) : false
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
cant(...abilities: string[]) {
|
|
44
|
+
return !this.can(...abilities)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
hasRole(...roles: string[]) {
|
|
48
|
+
return this.#u ? this.#u.hasRole(...roles) : false
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
has(prop: string, value: any = null) {
|
|
52
|
+
return this.#u ? this.#u.has(prop, value) : false
|
|
53
|
+
}
|
|
54
|
+
hasValue(prop: string, value: any = null) {
|
|
55
|
+
return this.has(prop, value)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
get cx() {
|
|
59
|
+
return this.#c
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
get cookie() {
|
|
63
|
+
return this.#cookie
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
get ip(): string | undefined {
|
|
67
|
+
return this.#c.req.header('cf-connecting-ip')
|
|
68
|
+
|| this.#c.req.header('x-forwarded-for')?.split(',')[0]?.trim()
|
|
69
|
+
|| this.#c.env?.aws?.lambda?.event?.requestContext?.identity?.sourceIp
|
|
70
|
+
|| this.#c.req.header('x-real-ip')
|
|
71
|
+
|| this.#c.env?.remoteAddr?.hostname
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
get userAgent(): string | undefined {
|
|
75
|
+
return this.#c.req.header('user-agent')
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
get routePath() {
|
|
79
|
+
return this.#c.req.routePath
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
get path() {
|
|
83
|
+
return this.#c.req.path
|
|
59
84
|
}
|
|
60
85
|
|
|
61
|
-
|
|
62
|
-
|
|
86
|
+
get url() {
|
|
87
|
+
return this.#c.req.raw.url
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
get method() {
|
|
91
|
+
return this.#c.req.raw.method
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
get matchedRoutes() {
|
|
95
|
+
return this.#c.req.matchedRoutes
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
get raw() {
|
|
99
|
+
return this.#c.req.raw
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
header(name: RequestHeader): string | undefined
|
|
103
|
+
header(name: string): string | undefined
|
|
104
|
+
header(): Record<RequestHeader | (string & CustomHeader), string>
|
|
105
|
+
header(name?: string) { // @ts-ignore
|
|
106
|
+
return this.#c.req.header(name)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
param(key?: string) { // @ts-ignore
|
|
110
|
+
return this.#c.req.param(key)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
query(): Record<string, string>
|
|
114
|
+
query(key: string): string | undefined
|
|
115
|
+
query(key?: string) { // @ts-ignore
|
|
116
|
+
return this.#c.req.query(key)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
queries(): Record<string, string[]>
|
|
120
|
+
queries(key: string):string[] | undefined
|
|
121
|
+
queries(key?: string) { // @ts-ignore
|
|
122
|
+
return this.#c.req.queries(key)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async body<E>() {
|
|
126
|
+
const cType = this.#c.req.header('Content-Type')
|
|
63
127
|
if (!cType) return {} as E
|
|
64
128
|
|
|
65
|
-
if (/^application\/([a-z-\.]+\+)?json(;\s*[a-zA-Z0-9\-]+\=([^;]+))*$/.test(cType))
|
|
66
|
-
return await
|
|
67
|
-
}
|
|
129
|
+
if (/^application\/([a-z-\.]+\+)?json(;\s*[a-zA-Z0-9\-]+\=([^;]+))*$/.test(cType))
|
|
130
|
+
return await this.json<E>()
|
|
68
131
|
|
|
69
132
|
if (
|
|
70
|
-
|
|
71
|
-
|
|
133
|
+
cType?.startsWith('multipart/form-data')
|
|
134
|
+
|| cType?.startsWith('application/x-www-form-urlencoded')
|
|
72
135
|
) {
|
|
73
|
-
|
|
136
|
+
return await this.parseBody() as E
|
|
74
137
|
}
|
|
75
138
|
|
|
76
139
|
return {} as E
|
|
77
140
|
}
|
|
78
141
|
|
|
79
|
-
|
|
80
|
-
|
|
142
|
+
async parseBody<Options extends Partial<ParseBodyOptions>, T extends BodyData<Options>>(
|
|
143
|
+
options?: Options
|
|
144
|
+
): Promise<T>
|
|
145
|
+
async parseBody<T extends BodyData>(options?: Partial<ParseBodyOptions>): Promise<T>
|
|
146
|
+
async parseBody(options?: Partial<ParseBodyOptions>) {
|
|
147
|
+
try {
|
|
148
|
+
return await this.#c.req.parseBody(options)
|
|
149
|
+
} catch (e) {
|
|
150
|
+
throw new HTTPException(400, {
|
|
151
|
+
message: 'Malformed FormData request.'+ (e instanceof Error ? ` ${e.message}` : ` ${String(e)}`)
|
|
152
|
+
})
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async json<E>() {
|
|
157
|
+
try {
|
|
158
|
+
return await this.#c.req.json<E>()
|
|
159
|
+
} catch {
|
|
160
|
+
throw new HTTPException(400, { message: 'Malformed JSON in request body' })
|
|
161
|
+
}
|
|
81
162
|
}
|
|
82
163
|
|
|
83
|
-
|
|
84
|
-
return c.
|
|
164
|
+
text() {
|
|
165
|
+
return this.#c.req.text()
|
|
85
166
|
}
|
|
86
167
|
|
|
87
|
-
|
|
88
|
-
return c.
|
|
168
|
+
arrayBuffer() {
|
|
169
|
+
return this.#c.req.arrayBuffer()
|
|
89
170
|
}
|
|
90
171
|
|
|
91
|
-
|
|
92
|
-
return c.
|
|
172
|
+
blob() {
|
|
173
|
+
return this.#c.req.blob()
|
|
93
174
|
}
|
|
94
175
|
|
|
95
|
-
|
|
96
|
-
return c.
|
|
176
|
+
formData() {
|
|
177
|
+
return this.#c.req.formData()
|
|
97
178
|
}
|
|
98
179
|
}
|