rajt 0.0.58 → 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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "rajt",
3
3
  "description": "A serverless bundler layer, fully typed for AWS Lambda (Node.js and LLRT) and Cloudflare Workers.",
4
- "version": "0.0.58",
4
+ "version": "0.0.59",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "bin": {
@@ -10,8 +10,11 @@
10
10
  "exports": {
11
11
  ".": "./src/index.ts",
12
12
  "./auth": "./src/auth/index.ts",
13
- "./dynamodb": "./src/dynamodb/index.ts",
14
- "./dynamodb/types": "./src/dynamodb/types.ts",
13
+ "./d1": "./src/db/d1.ts",
14
+ "./d1/types": "./src/db.d.ts",
15
+ "./dynamodb": "./src/db/dynamodb.ts",
16
+ "./dynamodb/types": "./src/db/dynamodb.d.ts",
17
+ "./enum": "./src/enum.ts",
15
18
  "./http": "./src/http.ts",
16
19
  "./types": "./src/types.ts",
17
20
  "./env": "./src/utils/environment.ts",
@@ -48,12 +51,10 @@
48
51
  "start": "node ../../dist/index.js"
49
52
  },
50
53
  "dependencies": {
51
- "@aws-sdk/client-dynamodb": "3.817.0",
52
- "@aws-sdk/lib-dynamodb": "3.817.0",
53
54
  "@hono/zod-validator": "^0.4.3",
54
55
  "cripta": "^0.1",
56
+ "forj": "^0.0.2",
55
57
  "hono": "^4.7.6",
56
- "pluralize": "^8.0",
57
58
  "t0n": "^0.1.5",
58
59
  "ua-parser-js": "^2.0.4"
59
60
  },
@@ -71,7 +72,6 @@
71
72
  "@miniflare/storage-file": "^2.14.4",
72
73
  "@miniflare/web-sockets": "^2.14.4",
73
74
  "@types/node": "^20.11.0",
74
- "@types/pluralize": "^0.0.33",
75
75
  "bun-types": "^1.2.14",
76
76
  "chokidar-cli": "^3.0.0",
77
77
  "citty": "^0.1.6",
@@ -0,0 +1,72 @@
1
+ // import { Context, Handler, HonoRequest, MiddlewareHandler, Next, ValidationTargets } from 'hono'
2
+ // import { JSONValue } from 'hono/utils/types'
3
+ import { Context, Handler, ValidationTargets } from 'hono'
4
+ import { z, ZodObject } from 'zod'
5
+ import { zValidator } from '@hono/zod-validator'
6
+ import response from './response'
7
+ import cx from './context'
8
+
9
+ export type ActionType = Function | Handler | Action | (new () => Action)
10
+
11
+ type RuleDefinition = {
12
+ schema: z.ZodObject<any>
13
+ target: keyof ValidationTargets
14
+ eTarget?: 'fieldErrors' | 'formErrors'
15
+ }
16
+
17
+ export default class Action {
18
+ static rule<T extends keyof ValidationTargets>(target: T): { schema: (schema: ZodObject<any>) => RuleDefinition }
19
+ static rule<T extends keyof ValidationTargets>(target: T, schema: ZodObject<any>): RuleDefinition
20
+ static rule<T extends keyof ValidationTargets>(target: T, schema?: ZodObject<any>):
21
+ | { schema: (schema: ZodObject<any>) => RuleDefinition }
22
+ | RuleDefinition
23
+ {
24
+ if (schema !== undefined) {
25
+ return {
26
+ target,
27
+ schema,
28
+ eTarget: 'fieldErrors' // | 'formErrors'
29
+ } satisfies RuleDefinition
30
+ }
31
+
32
+ return {
33
+ schema: (schema: ZodObject<any>) => ({
34
+ target,
35
+ schema,
36
+ eTarget: 'fieldErrors' // | 'formErrors'
37
+ })
38
+ }
39
+ }
40
+
41
+ static validate() {
42
+ const rules = this.rules()
43
+ const h = async (c: Context) => {
44
+ return await this.handle(cx.cx)
45
+ }
46
+ if (!rules) return [h]
47
+
48
+ const rulesArray: Function[] = (Array.isArray(rules) ? rules : [rules])
49
+ // @ts-ignore
50
+ .map(rule => zValidator(rule.target, rule.schema, (result, c) => {
51
+ if (!result.success) {
52
+ // @ts-ignore
53
+ return response.badRequest({ ...result.error.flatten()[rule.eTarget] })
54
+ }
55
+ }))
56
+
57
+ rulesArray.push(h)
58
+ return rulesArray
59
+ }
60
+
61
+ static run() {
62
+ return this.validate()
63
+ }
64
+
65
+ static rules(): RuleDefinition[] | RuleDefinition | null {
66
+ return null
67
+ }
68
+
69
+ static async handle(c: Context): Promise<Response> {
70
+ return Promise.resolve(response.raw(200, 'Action handle not implemented'))
71
+ }
72
+ }
package/src/action.ts CHANGED
@@ -1,72 +1,23 @@
1
- // import { Context, Handler, HonoRequest, MiddlewareHandler, Next, ValidationTargets } from 'hono'
2
- // import { JSONValue } from 'hono/utils/types'
3
- import { Context, Handler, ValidationTargets } from 'hono'
4
- import { z, ZodObject } from 'zod'
5
- import { zValidator } from '@hono/zod-validator'
6
- import Response from './response'
7
- import cx from './context'
8
-
9
- export type ActionType = Function | Handler | Action | (new () => Action)
10
-
11
- type RuleDefinition = {
12
- schema: z.ZodObject<any>
13
- target: keyof ValidationTargets
14
- eTarget?: 'fieldErrors' | 'formErrors'
15
- }
1
+ import response from './response'
2
+ import validator from './validator'
3
+ import type { Context, IRequest, IResponse, IValidator, Rules } from './types'
16
4
 
17
5
  export default class Action {
18
- static rule<T extends keyof ValidationTargets>(target: T): { schema: (schema: ZodObject<any>) => RuleDefinition }
19
- static rule<T extends keyof ValidationTargets>(target: T, schema: ZodObject<any>): RuleDefinition
20
- static rule<T extends keyof ValidationTargets>(target: T, schema?: ZodObject<any>):
21
- | { schema: (schema: ZodObject<any>) => RuleDefinition }
22
- | RuleDefinition
23
- {
24
- if (schema !== undefined) {
25
- return {
26
- target,
27
- schema,
28
- eTarget: 'fieldErrors' // | 'formErrors'
29
- } satisfies RuleDefinition
30
- }
31
-
32
- return {
33
- schema: (schema: ZodObject<any>) => ({
34
- target,
35
- schema,
36
- eTarget: 'fieldErrors' // | 'formErrors'
37
- })
38
- }
39
- }
40
-
41
- static validate() {
42
- const rules = this.rules()
43
- const h = async (c: Context) => {
44
- return await this.handle(cx.cx)
45
- }
6
+ static run() {
7
+ const rules = this.rules(validator)
8
+ const h = async (c: Context) => await this.handle(c.get('_'), response)
46
9
  if (!rules) return [h]
47
10
 
48
- const rulesArray: Function[] = (Array.isArray(rules) ? rules : [rules])
49
- // @ts-ignore
50
- .map(rule => zValidator(rule.target, rule.schema, (result, c) => {
51
- if (!result.success) {
52
- // @ts-ignore
53
- return Response.badRequest({ ...result.error.flatten()[rule.eTarget] })
54
- }
55
- }))
56
-
57
- rulesArray.push(h)
58
- return rulesArray
59
- }
60
-
61
- static run() {
62
- return this.validate()
11
+ const pipe = validator.parse(rules)
12
+ pipe.push(h)
13
+ return pipe
63
14
  }
64
15
 
65
- static rules(): RuleDefinition[] | RuleDefinition | null {
16
+ static rules(v: IValidator): Rules {
66
17
  return null
67
18
  }
68
19
 
69
- static async handle(c: Context): Promise<Response> {
70
- return Promise.resolve(Response.raw(200, 'Action handle not implemented'))
20
+ static async handle(req: IRequest, res: IResponse): Promise<Response> {
21
+ return Promise.resolve(res.raw(200, 'Action handle not implemented'))
71
22
  }
72
23
  }
@@ -16,8 +16,8 @@ export class Ability {
16
16
  const paths = actions?.map(a => Array.isArray(a) ? a[0] + a[1] : a.method + a.path) || []
17
17
  const items = new Set(paths)
18
18
 
19
- if (items.size !== actions.length)
20
- throw new Error(`Duplicate routes detected: "${paths.filter((path, index) => paths.indexOf(path) !== index).join('", "')}"`)
19
+ if (items.size != actions.length)
20
+ throw new Error(`Duplicate routes detected: "${paths.filter((path, index) => paths.indexOf(path) != index).join('", "')}"`)
21
21
 
22
22
  this.#abilities = Array.from(new Set(actions?.map(a => Array.isArray(a) ? a[3] : a.name) || []))
23
23
  .map(a => this.format(a))
@@ -79,4 +79,7 @@ export class Authnz<T extends object> {
79
79
  get data() {
80
80
  return this.#data
81
81
  }
82
+ get user() {
83
+ return this.#data
84
+ }
82
85
  }
package/src/auth/index.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  export { Ability } from './ability'
2
- export { Auth, Auth as Gate } from './auth'
3
2
  export { Authnz } from './authnz'
4
3
  export { Token } from './token'
5
4
 
package/src/auth/token.ts CHANGED
@@ -1,19 +1,20 @@
1
1
  import { Envir } from 't0n'
2
2
  import { Token as Factory } from 'cripta'
3
3
  import { UAParser } from 'ua-parser-js'
4
- import c from '../context'
4
+ import type { IRequest } from '@/types'
5
5
 
6
6
  export class Token {
7
+ static #cookieName: string = '__auth_'
7
8
  static #name: string = 'Authorization'
8
9
  static #prefix: string = 'bearer'
9
10
 
10
- static fromRequest() {
11
- const token = this.fromCookie() || this.fromHeader()
12
- return token ? this.parse(token) : null
11
+ static fromRequest(req: IRequest) {
12
+ const token = this.fromCookie(req) || this.fromHeader(req)
13
+ return token ? this.parse(req, token) : null
13
14
  }
14
15
 
15
- static fromHeader(): string | null {
16
- const header = c.cx.req.header(this.#name) || c.cx.req.header('HTTP_AUTHORIZATION') || c.cx.req.header('REDIRECT_HTTP_AUTHORIZATION') || null
16
+ static fromHeader(req: IRequest): string | null {
17
+ const header = req.header(this.#name) || req.header('HTTP_AUTHORIZATION') || req.header('REDIRECT_HTTP_AUTHORIZATION') || null
17
18
 
18
19
  if (header) {
19
20
  const pos = header.toLowerCase().indexOf(this.#prefix.toLowerCase())
@@ -29,39 +30,39 @@ export class Token {
29
30
  return null
30
31
  }
31
32
 
32
- static fromCookie(): string | null {
33
- const uid = c.cx.req.header('uid')
33
+ static fromCookie(req: IRequest): string | null {
34
+ const uid = req.header('uid')
34
35
 
35
36
  if (uid) {
36
- const auth = c.cookie.get('__auth_' + uid)
37
+ const auth = req.cookie.get(this.#cookieName + uid)
37
38
  return auth ? auth : null
38
39
  }
39
40
 
40
41
  return null
41
42
  }
42
43
 
43
- static parse(token: string) {
44
- const host = this.host()
44
+ static parse(req: IRequest, token: string) {
45
+ const host = this.host(req)
45
46
  const serveHost = Envir.get('FLOW_SERVER', host) as string
46
47
 
47
48
  return Factory.parse(token)
48
49
  .issuedBy(serveHost)
49
50
  .permittedFor(host)
50
- .withClaim('u', this.userAgent())
51
- .withClaim('i', this.ip())
51
+ .withClaim('u', this.userAgent(req))
52
+ .withClaim('i', this.ip(req))
52
53
  }
53
54
 
54
- static create(user: any, exp: number = 7200) {
55
+ static create(req: IRequest, user: any, exp: number = 7200) {
55
56
  const time = Math.floor(Date.now() / 1000)
56
- const host = this.host(c.cx.req.header('host') || '')
57
+ const host = this.host(req)
57
58
 
58
59
  return Factory.create()
59
60
  .issuedBy(host)
60
61
  .permittedFor(host)
61
62
  .issuedAt(time)
62
63
  .expiresAt(time + exp)
63
- .withClaim('u', this.userAgent())
64
- .withClaim('i', this.ip())
64
+ .withClaim('u', this.userAgent(req))
65
+ .withClaim('i', this.ip(req))
65
66
  .body(user)
66
67
  }
67
68
 
@@ -73,8 +74,9 @@ export class Token {
73
74
  this.#name = name
74
75
  }
75
76
 
76
- static host(url?: string | null | undefined): string {
77
- if (!url) url = c.cx.req.url || c.cx.req.header('host') || ''
77
+ static host(req: IRequest): string {
78
+ const url = req.url || req.header('host')
79
+ if (!url) return ''
78
80
 
79
81
  let formattedUrl = String(url)
80
82
  if (!formattedUrl.startsWith('http'))
@@ -88,13 +90,14 @@ export class Token {
88
90
  }
89
91
  }
90
92
 
91
- static userAgent() {
92
- if (!c?.userAgent) return 0
93
- const { browser, device, os } = UAParser(c.userAgent)
93
+ static userAgent(req: IRequest) {
94
+ const ua = req?.userAgent
95
+ if (!ua) return 0
96
+ const { browser, device, os } = UAParser(ua)
94
97
  return (browser?.name || '') + (browser?.major || '') + (device?.model || '') + (os?.name || '')
95
98
  }
96
99
 
97
- static ip() {
98
- return c?.ip || 0
100
+ static ip(req: IRequest) {
101
+ return req?.ip || 0
99
102
  }
100
103
  }
package/src/bin/rajt.js CHANGED
@@ -35,7 +35,7 @@ Consider using a Node.js version manager such as https://volta.sh or https://git
35
35
 
36
36
  let tsxPath;
37
37
  for (const pathOption of tsxPaths) {
38
- if (pathOption === "tsx" || existsSync(pathOption)) {
38
+ if (pathOption == "tsx" || existsSync(pathOption)) {
39
39
  tsxPath = pathOption;
40
40
  break;
41
41
  }
@@ -72,7 +72,7 @@ Consider using a Node.js version manager such as https://volta.sh or https://git
72
72
  }
73
73
  )
74
74
  .on("exit", (code) =>
75
- process.exit(code === undefined || code === null ? 0 : code)
75
+ process.exit(code == null ? 0 : code)
76
76
  )
77
77
  .on("message", (message) => {
78
78
  if (process.send) {
@@ -103,7 +103,7 @@ export default defineCommand({
103
103
  }
104
104
  ).on('exit', code => {
105
105
  logger.step(`Lambda process exited with code ${code ?? 0}`)
106
- if (code !== 0 && code !== null)
106
+ if (code != 0 && code != null)
107
107
  logger.error('Lambda process crashed, waiting for restart...')
108
108
 
109
109
  lambda = null
@@ -277,7 +277,7 @@ async function wait(ms: number) {
277
277
  function getDockerHost() {
278
278
  const platform = process.platform
279
279
 
280
- if (platform === 'darwin') {
280
+ if (platform == 'darwin') {
281
281
  for (const socket of [
282
282
  '/Users/'+ process.env.USER +'/.docker/run/docker.sock',
283
283
  '/var/run/docker.sock',
@@ -6,6 +6,8 @@ import { mkdirSync, existsSync, readdirSync, rmSync, copyFileSync } from 'node:f
6
6
  import { readFile, stat, writeFile } from 'node:fs/promises'
7
7
  import { basename, dirname, join, relative } from 'node:path'
8
8
 
9
+ import { cacheRoutes } from '../../../routes'
10
+
9
11
  const __dirname = join(dirname(fileURLToPath(import.meta.url)), '../../../../../../')
10
12
  const __rajt = join(__dirname, 'node_modules/rajt/src')
11
13
 
@@ -113,6 +115,10 @@ export const build = async (platform: 'aws' | 'cf' | 'node') => {
113
115
  ],
114
116
  }
115
117
 
118
+ await cacheRoutes()
119
+
120
+ logger.step('Routes cached')
121
+
116
122
  const result = await esbuild.build(opts)
117
123
  if (!result?.metafile) throw Error('build fail')
118
124
 
@@ -164,10 +170,13 @@ export async function createMiniflare(options = {}, configPath = 'wrangler.toml'
164
170
 
165
171
  d1Databases: Object.fromEntries(config.d1_databases.map(db => [db.binding, db.database_id])),
166
172
 
167
- modules: true,
168
- modulesRules: [
169
- { type: 'ESModule', include: ['**/*.js', '**/*.ts'] },
173
+ modules: [
174
+ { type: "ESModule", path: "dist/index.js" },
170
175
  ],
176
+ // modules: true,
177
+ // modulesRules: [
178
+ // { type: 'ESModule', include: ['**/*.js', '**/*.ts'] },
179
+ // ],
171
180
 
172
181
  kvPersist: join(__dirname, '.wrangler/state/v3/kv'),
173
182
  cachePersist: join(__dirname, '.wrangler/state/v3/cache'),
package/src/create-app.ts CHANGED
@@ -7,15 +7,15 @@ import type { Env, Context, ErrorHandler, NotFoundHandler, Next } from 'hono'
7
7
  // import type { H, Handler, HandlerResponse } from 'hono/types'
8
8
  import type { HTTPResponseError } from 'hono/types'
9
9
  import colors from 'picocolors'
10
+ import { Envir } from 't0n'
10
11
  import type { Routes } from './types'
11
12
  import { BadRequest, Unauthorized } from './exceptions'
12
13
  import { resolve, resolveMiddleware } from './utils/resolve'
13
14
  import { getMiddlewares, getHandler } from './register'
14
15
  import { isDev } from './utils/environment'
15
16
  import localDate from './utils/local-date'
16
- import { Auth } from './auth'
17
+ import request from './request'
17
18
  import response from './response'
18
- import cx from './context'
19
19
 
20
20
  type InitFunction<E extends Env = Env> = (app: Hono<E>) => void
21
21
 
@@ -40,7 +40,7 @@ const EHandler = async (e: Error | HTTPResponseError) => {
40
40
  case e instanceof BadRequest:
41
41
  case 'status' in e && e.status == 400:
42
42
  // @ts-ignore
43
- return response.badRequest(undefined, e?.message)
43
+ return response.badRequest(null, e?.message)
44
44
 
45
45
  default:
46
46
  return response.internalError(
@@ -85,12 +85,12 @@ export const createApp = <E extends Env>(options?: ServerOptions<E>) => {
85
85
  app.use('*', logger((...args: any[]) => console.log(colors.gray(localDate()), ...args)))
86
86
 
87
87
  app.use(async (c: Context, next: Next) => {
88
- cx.setContext(c)
89
- Auth.resolve()
88
+ c.set('_', new request(c))
89
+ if (c.env) Envir.add(c.env)
90
90
  await next()
91
91
  })
92
92
  getMiddlewares().forEach(mw => {
93
- const h = async (c: Context, next: Next) => await resolveMiddleware(mw)(cx.cx, next)
93
+ const h = async (c: Context, next: Next) => await resolveMiddleware(mw)(c.get('_'), next)
94
94
  // @ts-ignore
95
95
  mw?.path ? app.use(String(mw.path), h) : app.use(h)
96
96
  })
@@ -117,7 +117,7 @@ export const createApp = <E extends Env>(options?: ServerOptions<E>) => {
117
117
 
118
118
  function mw(...objs: string[]): Function[] {
119
119
  return objs.flatMap(obj => {
120
- if (typeof obj !== 'string') return null
120
+ if (typeof obj != 'string') return null
121
121
  // @ts-ignore
122
122
  return getHandler(obj)?.mw || null
123
123
  }).flat().filter(Boolean)
package/src/db/d1.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from 'forj/d1/types'
package/src/db/d1.ts ADDED
@@ -0,0 +1 @@
1
+ export * from 'forj/d1'
package/src/enum.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { Enum } from 't0n'
2
+ export type { EnumStatic, EnumValue, EnumType } from 't0n'
package/src/http.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import type { Context, Next } from 'hono'
2
2
  import { MiddlewareType } from './middleware'
3
- import Response from './response'
4
- import { Ability, Auth as Gate } from './auth'
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
9
  if (args.length == 1 && typeof args[0] == 'function')
@@ -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 user = Gate.user
105
+ const req = c.get('_') as IRequest
105
106
  const ability = Ability.fromAction(target)
106
107
 
107
- if (!user || !ability || Gate.cant(ability))
108
- return Response.unauthorized()
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
4
  export { Enum } from 't0n'
@@ -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
+ }