rajt 0.0.99 → 0.0.100

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.99",
4
+ "version": "0.0.100",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
7
7
  "files": ["bin", "src"],
@@ -42,7 +42,7 @@
42
42
  "chokidar": "^3.5.2",
43
43
  "citty": "^0.1.6",
44
44
  "consola": "^3.4.2",
45
- "cripta": "^0.1.10",
45
+ "cripta": "^0.1.11",
46
46
  "dotenv": "^16.5.0",
47
47
  "esbuild": "^0.25.2",
48
48
  "forj": "^0.1.8",
@@ -19,7 +19,7 @@ export class Ability {
19
19
  }
20
20
 
21
21
  static fromAction(target: any): string {
22
- return !target ? '' : this.format(target.name.length > 3 ? target.name : (target?.p || ''))
22
+ return !target ? '' : this.format(typeof target == 'string' ? target : (target.name.length > 3 ? target.name : (target?.p || '')))
23
23
  }
24
24
 
25
25
  static format(path: string) {
package/src/auth/index.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export { Ability } from './ability'
2
2
  export { Authnz } from './authnz'
3
3
  export { Token } from './token'
4
+ export { Autorized } from './middlewares'
4
5
 
5
6
  export * from './types'
@@ -0,0 +1,23 @@
1
+ import { Ability } from './ability'
2
+ import response from '../response'
3
+ import { GET_REQUEST } from '../request'
4
+ import Config from '../config'
5
+ import { verbAlias } from '../http'
6
+ import type {
7
+ Context, Next,
8
+ IRequest,
9
+ } from '../types'
10
+
11
+ export async function Autorized(c: Context, next: Next) {
12
+ const req = c.get(GET_REQUEST as unknown as string) as IRequest
13
+ const ability = Ability.fromAction(Config.get(`routes.${req.routePath}$`+ verbAlias[req.method.toLowerCase()]))
14
+
15
+ if (!req?.user || !ability || req.cant(ability))
16
+ return response.unauthorized()
17
+
18
+ await next()
19
+ }
20
+
21
+ // export function Unautorized() {
22
+
23
+ // }
@@ -3,6 +3,7 @@ import { spawn, type ChildProcess } from 'node:child_process'
3
3
 
4
4
  import { defineCommand } from 'citty'
5
5
  import type { Miniflare } from 'miniflare'
6
+ import type { WranglerConfig } from 'localflare-core'
6
7
  import {
7
8
  build, wait, watch, normalizePlatform, platformError, getRuntime,
8
9
  wranglerConfig, createMiniflare, localflareManifest,
@@ -161,21 +162,12 @@ export default defineCommand({
161
162
  })
162
163
  case 'cf':
163
164
  return withPort(desiredPort, async (port) => {
164
- started(port)
165
- let worker: Miniflare | null = null
166
- let localflare: Miniflare | null = null
167
- const startWorker = async () => {
168
- if (worker) await worker.dispose()
169
- if (localflare) await localflare.dispose()
165
+ started(port)
170
166
 
171
- // await wait(500)
167
+ let localflare: Miniflare | null = null
168
+ const startLocalflare = async (workerConfig: WranglerConfig) => {
169
+ if (localflare) return
172
170
 
173
- const workerConfig = await wranglerConfig()
174
- workerConfig.host = host
175
- workerConfig.liveReload = false
176
-
177
- worker = createMiniflare({ ...workerConfig, port })
178
- await worker.ready
179
171
  localflare = createMiniflare({
180
172
  ...workerConfig,
181
173
  vars: {
@@ -185,8 +177,23 @@ export default defineCommand({
185
177
  main: '.rajt/localfire.js',
186
178
  port: 8788,
187
179
  inspectorPort: 9230,
188
- })
180
+ })
181
+
189
182
  await localflare.ready
183
+ }
184
+
185
+ let worker: Miniflare | null = null
186
+ const startWorker = async () => {
187
+ if (worker) await worker.dispose()
188
+
189
+ const workerConfig = await wranglerConfig() // @ts-ignore
190
+ workerConfig.host = host // @ts-ignore
191
+ workerConfig.liveReload = false
192
+
193
+ worker = createMiniflare({ ...workerConfig, port })
194
+ await worker.ready
195
+
196
+ if (!localflare) await startLocalflare(workerConfig)
190
197
  }
191
198
 
192
199
  await startApp(startWorker)
@@ -31,7 +31,7 @@ export default defineCommand({
31
31
  try {
32
32
  const migrations = await Migrator.dir(database).queue()
33
33
  const pending = migrations.pending
34
- const migrated = migrations.migrated
34
+ const migrated = migrations.migrated
35
35
 
36
36
  switch (action) {
37
37
  case 'migrate':
package/src/cli/utils.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import ts from 'typescript'
1
2
  import esbuild from 'esbuild'
2
3
  import { Miniflare } from 'miniflare'
3
4
  import { mkdirSync, existsSync, statSync, readdirSync, rmSync, unlinkSync, copyFileSync, writeFileSync } from 'node:fs'
@@ -69,6 +70,52 @@ const nodeModules = [
69
70
  'async_hooks', 'console', 'fsevents',
70
71
  ].flatMap(lib => ['node:'+ lib, lib])
71
72
 
73
+ const printer = ts.createPrinter()
74
+ function stripDecorators(source: string) {
75
+ const sourceFile = ts.createSourceFile(
76
+ 'tmp.ts', source, ts.ScriptTarget.ESNext, false
77
+ )
78
+
79
+ const transformer: ts.TransformerFactory<ts.SourceFile> = (context) => {
80
+ const visit: ts.Visitor = (node) => {
81
+ if (ts.isClassDeclaration(node) && node.modifiers?.length) {
82
+ let hasDecorator = false
83
+ const modifiers = []
84
+
85
+ for (const m of node.modifiers) {
86
+ if (m.kind === ts.SyntaxKind.Decorator) {
87
+ hasDecorator = true
88
+ continue
89
+ }
90
+ modifiers.push(m)
91
+ }
92
+
93
+ if (hasDecorator) {
94
+ return ts.factory.updateClassDeclaration(
95
+ node,
96
+ modifiers.length ? modifiers : undefined,
97
+ node.name,
98
+ node.typeParameters,
99
+ node.heritageClauses,
100
+ node.members
101
+ )
102
+ }
103
+ }
104
+
105
+ return ts.visitEachChild(node, visit, context)
106
+ }
107
+
108
+ return (node) => ts.visitNode(node, visit) as ts.SourceFile
109
+ }
110
+
111
+ const result = ts.transform(sourceFile, [transformer])
112
+ const code = printer.printFile(result.transformed[0])
113
+
114
+ result.dispose()
115
+
116
+ return code
117
+ }
118
+
72
119
  const dist = '.rajt/dist'
73
120
  export const build = async (platform: Platform) => {
74
121
  const startTime = Date.now()
@@ -86,6 +133,10 @@ export const build = async (platform: Platform) => {
86
133
 
87
134
  if (['bun', 'vercel'].includes(platform)) platform = 'cf'
88
135
 
136
+ const USE_STRICT_RE = /(["'`])\s*use strict\s*\1;?/g
137
+ const decoder = new TextDecoder()
138
+ const encoder = new TextEncoder()
139
+
89
140
  // @ts-ignore
90
141
  platform = platform != 'node' ? '-'+ platform : ''
91
142
  const opts = {
@@ -112,54 +163,45 @@ export const build = async (platform: Platform) => {
112
163
  // define: {
113
164
  // 'process.env.NODE_ENV': '"development"'
114
165
  // },
115
- // loader: {
116
- // '.ts': 'ts',
117
- // '.js': 'js'
118
- // },
119
166
  // tsconfig: join(_root, 'tsconfig.json'),
120
167
  // sourcemap: true,
121
168
  // logLevel: 'info',
122
169
  plugins: [
123
170
  {
124
- name: 'rajt-resolver',
171
+ name: 'rajt',
125
172
  setup(build) {
126
173
  build.onResolve({ filter: /\.rajt[\/\\]/ }, args => ({ path: join(_root, args.path) }))
127
- }
128
- },
129
- {
130
- name: 'preserve-class-names',
131
- setup(build) {
132
- build.onLoad(
133
- { filter: /(actions|features|routes)\/.*\.ts$/ },
134
- async (args) => {
135
- const contents = await readFile(args.path, 'utf8')
136
- const result = await esbuild.transform(contents, {
137
- loader: 'ts',
138
- minify: true,
139
- keepNames: true
140
- })
141
- return { contents: result.code, loader: 'ts' }
142
- }
143
- )
144
- },
145
- },
146
- {
147
- name: 'remove-use-strict',
148
- setup(build) {
174
+
175
+ // strip decorators
176
+ build.onLoad({ filter: /\.ts$/ }, async (args) => {
177
+ const source = await readFile(args.path, 'utf8')
178
+ return { contents: stripDecorators(source), loader: 'ts' }
179
+ })
180
+
181
+ // remove "use strict"
182
+ const write = build.initialOptions.write
149
183
  build.onEnd(async (result) => {
150
- if (!result.outputFiles) return
151
-
152
- const files = result.outputFiles.filter(file => file.path.endsWith('.js'))
153
- await Promise.all(files.map(async file => {
154
- if (!file.path.endsWith('.js')) return
155
-
156
- await writeFile(
157
- file.path,
158
- new TextDecoder()
159
- .decode(file.contents)
160
- .replace(/(["'`])\s*use strict\s*\1;?|`use strict`;?/g, '')
161
- )
162
- }))
184
+ const files = result.outputFiles
185
+ if (!files) return
186
+
187
+ const tasks: Promise<void>[] = []
188
+
189
+ for (const file of files) {
190
+ if (!file.path.endsWith('.js')) continue
191
+
192
+ let code = decoder.decode(file.contents)
193
+
194
+ if (USE_STRICT_RE.test(code))
195
+ code = code.replace(USE_STRICT_RE, '')
196
+
197
+ if (write) {
198
+ file.contents = encoder.encode(code)
199
+ } else {
200
+ tasks.push(writeFile(file.path, code))
201
+ }
202
+ }
203
+
204
+ if (tasks.length) await Promise.all(tasks)
163
205
  })
164
206
  }
165
207
  },
package/src/create-app.ts CHANGED
@@ -7,13 +7,14 @@ import type {
7
7
  HTTPResponseError,
8
8
  ServerOptions,
9
9
  } from './types'
10
- import { resolve, resolveMiddleware, mw } from './utils/resolve'
11
- import { getMiddlewares, getHandler } from './register'
10
+ import { resolve, resolveMiddleware } from './utils/resolve'
11
+ import { getMiddlewares } from './register'
12
12
  import request, { GET_REQUEST } from './request'
13
13
  import response from './response'
14
14
  import { isDev } from './utils/environment'
15
15
  import { gray } from 't0n/color'
16
16
  import { Route } from './types'
17
+ import { getVerb } from './http'
17
18
 
18
19
  const NFHandler = () => response.notFound()
19
20
  const EHandler = async (e: Error | HTTPResponseError) => {
@@ -96,11 +97,14 @@ export const createApp = <E extends Env>(options?: ServerOptions<E>) => {
96
97
  if (c.env) Envir.add(c.env)
97
98
  await next()
98
99
  })
99
- getMiddlewares().forEach(mw => {
100
+
101
+ const middlewares = getMiddlewares()
102
+ for (const mw of middlewares) {
100
103
  const h = async (c: Context, next: Next) => await resolveMiddleware(mw)(c.get(GET_REQUEST as unknown as string), next)
101
104
  // @ts-ignore
102
105
  mw?.path ? app.use(String(mw.path), h) : app.use(h)
103
- })
106
+ }
107
+
104
108
  // @ts-ignore
105
109
  app.onError(options?.onError || EHandler)
106
110
  // @ts-ignore
@@ -111,9 +115,9 @@ export const createApp = <E extends Env>(options?: ServerOptions<E>) => {
111
115
  const routes = options?.routes || [] // @ts-ignore
112
116
  const routeRegister = options?.routeRegister ? options.routeRegister : (_: Hono, route: Route) => { // @ts0ignore
113
117
  if (Array.isArray(route)) { // @ts-ignore
114
- _[route[0]](route[1], ...mw(route[2], route[3]), ...resolve(getHandler(route[3]), route[3]))
118
+ _[getVerb[route[0]]](route[1], ...resolve(...route[2], route[3]))
115
119
  } else { // @ts-ignore
116
- _[route.method](route.path, ...mw(route.middlewares, route.name), ...resolve(route.handle, route.name))
120
+ _[route.method](route.path, ...resolve(...route.middlewares), route.handle)
117
121
  }
118
122
  }
119
123
 
package/src/dev.ts CHANGED
@@ -7,12 +7,11 @@ import { registerOpenAPI } from './open-api/register'
7
7
  import createApp from './create-app'
8
8
  import { Ability } from 'rajt/auth'
9
9
  import { setEnv, detectEnvironment } from 'rajt/env'
10
+ import { _root } from './utils/paths'
10
11
 
11
12
  setEnv(detectEnvironment())
12
13
 
13
- const __dirname = join(dirname(new URL(import.meta.url).pathname), '../../../')
14
-
15
- config({ path: join(__dirname, '.env.dev') })
14
+ config({ path: join(_root, '.env.dev') })
16
15
 
17
16
  Config.add(await getConfigs())
18
17
 
package/src/http.ts CHANGED
@@ -1,14 +1,33 @@
1
- import { MiddlewareType } from './middleware'
2
- import response from './response'
3
- import { GET_REQUEST } from './request'
4
- import { Ability } from './auth'
5
- import mergeMiddleware from './utils/merge-middleware'
1
+ import { Autorized } from './auth'
2
+ import { type MiddlewareType, mergeMiddleware } from './middleware'
6
3
  import type {
7
- Context, Next,
8
- IRequest,
9
4
  DescribeRouteOptions,
10
5
  } from './types'
11
6
 
7
+ export const verbAlias = {
8
+ get: 0,
9
+ post: 1,
10
+ put: 2,
11
+ patch: 3,
12
+ delete: 4,
13
+ head: 5,
14
+ options: 6,
15
+ connect: 7,
16
+ trace: 8,
17
+ } as Record<string, number>
18
+
19
+ export const getVerb = [
20
+ 'get',
21
+ 'post',
22
+ 'put',
23
+ 'patch',
24
+ 'delete',
25
+ 'head',
26
+ 'options',
27
+ 'connect',
28
+ 'trace',
29
+ ]
30
+
12
31
  function method(method: string, ...args: any[]): void | ClassDecorator {
13
32
  if (args.length == 1 && typeof args[0] == 'function')
14
33
  return _method(method, '/', args[0])
@@ -112,15 +131,7 @@ function _auth(target: Function | any) {
112
131
  if (!target.d?.responses) target.d.responses = {}
113
132
  target.d.responses[401] = {description: 'Unauthorized'}
114
133
 
115
- mergeMiddleware(target, async (c: Context, next: Next) => {
116
- const req = c.get(GET_REQUEST as unknown as string) as IRequest
117
- const ability = Ability.fromAction(target)
118
-
119
- if (!req?.user || !ability || req.cant(ability))
120
- return response.unauthorized()
121
-
122
- await next()
123
- })
134
+ mergeMiddleware(target, Autorized)
124
135
  }
125
136
 
126
137
  function _describe(spec: DescribeRouteOptions): ClassDecorator{
package/src/middleware.ts CHANGED
@@ -15,3 +15,7 @@ export class Middleware {
15
15
  }
16
16
 
17
17
  export const toHonoMiddleware = (mw: MiddlewareHandler) => async (req: IRequest, next: Next) => await mw(req.cx, next)
18
+
19
+ export function mergeMiddleware(target: Function | any, ...handlers: MiddlewareType[]) {
20
+ target.mw = [...target?.mw, ...handlers.flat()]
21
+ }
package/src/register.ts CHANGED
@@ -1,9 +1,6 @@
1
1
  export const handlers: Record<string, Function> = {}
2
2
 
3
3
  export function registerHandler(id: string, handler: any) {
4
- // if (id in handlers)
5
- // console.warn(`Handler "${id}" has already been registered`)
6
-
7
4
  handlers[id] = handler
8
5
  }
9
6
 
package/src/request.ts CHANGED
@@ -27,7 +27,7 @@ export default class $Request {
27
27
  #u: Authnz<any> | null = null
28
28
 
29
29
  #host: string
30
- #routePath: string
30
+ #routePath?: string
31
31
  #matchedRoutes: RouterRoute[]
32
32
 
33
33
  constructor(c: Context) {
@@ -38,7 +38,6 @@ export default class $Request {
38
38
  const url = new URL(c.req.raw.url)
39
39
  this.#host = url.protocol +'//'+ url.host
40
40
 
41
- this.#routePath = routePath(c)
42
41
  this.#matchedRoutes = matchedRoutes(c)
43
42
  }
44
43
 
@@ -91,10 +90,6 @@ export default class $Request {
91
90
  return this.#c.req.header('user-agent')
92
91
  }
93
92
 
94
- get routePath() {
95
- return this.#routePath
96
- }
97
-
98
93
  get url() {
99
94
  return this.#c.req.raw.url
100
95
  }
@@ -116,6 +111,15 @@ export default class $Request {
116
111
  return this.#c.req.raw.method
117
112
  }
118
113
 
114
+ get routePath() {
115
+ this.#routePath ??= routePath(this.#c)
116
+ return this.#routePath
117
+ }
118
+
119
+ get routeIndex() {
120
+ return this.#c.req.routeIndex
121
+ }
122
+
119
123
  get matchedRoutes() {
120
124
  return this.#matchedRoutes
121
125
  }
package/src/routes.ts CHANGED
@@ -1,27 +1,27 @@
1
1
  import { copyFileSync, existsSync, readdirSync, statSync, writeFileSync } from 'node:fs'
2
2
  import { join, resolve, relative } from 'pathe'
3
3
 
4
+ import { IMPORT } from 't0n'
4
5
  import glob from 'tiny-glob'
5
6
  import { config } from 'dotenv'
6
-
7
- import { IMPORT } from 't0n'
7
+ import { describeRoute, resolver } from 'hono-openapi'
8
+ import { mimes } from 'hono/utils/mime'
9
+ import { STATUS_CODES } from 'node:http'
8
10
  import { registerHandler, registerMiddleware } from './register'
9
11
  import createApp from './create-app'
10
12
  import { isAnonFn } from './utils/func'
11
13
  import ensureDir from './utils/ensuredir'
12
14
  import versionSHA from './utils/version-sha'
13
- import type { Routes, StandardSchemaV1 } from './types'
14
15
  import { rn, substep, warn } from './utils/log'
15
- import { _root } from './utils/paths'
16
+ import { _root, _rajt } from './utils/paths'
16
17
  import { generateOpenAPI } from './open-api/spec'
17
- import type * as z from 'zod'
18
- import { describeRoute, resolver } from 'hono-openapi'
19
- import { mimes } from 'hono/utils/mime'
20
- import { STATUS_CODES } from 'node:http'
21
- import { mw, resolve as _resolve } from './utils/resolve'
22
-
18
+ import { verbAlias } from './http'
19
+ import { resolve as _resolve } from './utils/resolve'
23
20
  import { highlightedMethod, highlightedURI } from './cli/utils'
24
21
 
22
+ import type * as z from 'zod'
23
+ import type { Routes, StandardSchemaV1 } from './types'
24
+
25
25
  const importName = (name?: string) => (name || 'Fn'+ Math.random().toString(36).substring(2)).replace(/\.ts$/, '')
26
26
  const walk = async (dir: string, baseDir: string, fn: Function, parentMw: string[] = []): Promise<void> => {
27
27
  if (!existsSync(dir)) return
@@ -61,7 +61,7 @@ function isZodSchema(obj: any): obj is z.ZodType {
61
61
  }
62
62
 
63
63
  function ResolveDescribeSchema(obj: any, deep: boolean = false) {
64
- if (!obj || typeof obj !== 'object') return obj
64
+ if (!obj || typeof obj != 'object') return obj
65
65
  if (isZodSchema(obj))
66
66
  return { content: {'application/json': { schema: resolver(obj as unknown as StandardSchemaV1) }} }
67
67
 
@@ -134,12 +134,16 @@ export async function getRoutes(
134
134
  }
135
135
  }
136
136
 
137
+ const mw = (handle.mw?.length ? [...handle.mw, ...middlewares] : middlewares).flatMap(obj => {
138
+ return typeof obj == 'string' ? obj : obj?.name || null
139
+ }).filter(Boolean) as Function[]
140
+
137
141
  routes.push({
138
142
  method, path: uri,
139
143
  name,
140
144
  file,
141
145
  // @ts-ignore
142
- middlewares,
146
+ middlewares: mw,
143
147
  handle,
144
148
  desc,
145
149
  })
@@ -339,13 +343,24 @@ export async function cacheRoutes() {
339
343
 
340
344
  const middlewares = await getMiddlewares()
341
345
  const configs = await getConfigs()
346
+ const handlers = [
347
+ ['auth/middlewares', 'Autorized', 'Autorized'],
348
+ ]
349
+
350
+ for (const r of routes)
351
+ registerHandler(r.name, r.handle)
342
352
 
343
- routes.forEach(r => registerHandler(r.name, r.handle))
344
- middlewares.forEach(mw => registerMiddleware(mw.handle))
353
+ for (const mw of middlewares)
354
+ registerMiddleware(mw.handle)
355
+
356
+ for (const h of handlers) {
357
+ const mod = await IMPORT(join(_rajt, h[0]))
358
+ registerHandler(h[1], mod[h[1]])
359
+ }
345
360
 
346
361
  // @ts-ignore
347
362
  const openApi = await generateOpenAPI(createApp({ routes, routeRegister: (app: Hono, route: Route) => {
348
- app[route.method](route.path, describeRoute(route.desc), ...mw(route.middlewares, route.name), ..._resolve(route.handle, route.name))
363
+ app[route.method](route.path, describeRoute(route.desc), ..._resolve(...route.middlewares), route.handle)
349
364
  } }), configs?.rajt || {})
350
365
 
351
366
  const iPath = join(_root, '.rajt/imports.mjs')
@@ -355,13 +370,18 @@ export async function cacheRoutes() {
355
370
  copyFileSync(localfireEntry, join(_root, '.rajt/localfire.js'))
356
371
 
357
372
  const _rajtDir = await dependencyPath('rajt')
373
+
374
+ stringifyToJS(Object.fromEntries(routes.map(r => ([r.path + r.method, r.name]))))
375
+
358
376
  writeFileSync(iPath, `// AUTO-GENERATED FILE - DO NOT EDIT
359
377
  ${env?.length ? `import { Envir } from '${await dependencyPath('t0n')}/dist/index'\nEnvir.add({${env.map(([key, val]) => key +':'+ stringifyToJS(val)).join(',')}})` : ''}
360
378
  ${Object.entries(configs)?.length ? `import Config from '${_rajtDir}/src/config'\nConfig.add(${stringifyToJS(configs)})` : ''}
361
379
 
362
380
  import { registerHandler, registerMiddleware } from '${_rajtDir}/src/register'
381
+ ${handlers.map(([file, name, _export]) => `\nimport ${_export ? `{ ${name} }` : name} from '${_rajtDir}/src/${file}'\nregisterHandler('${name}', ${name})`).join('\n')}
363
382
 
364
383
  ${Object.entries(openApi)?.length ? `registerHandler('RAJT_OPENAPI', ${stringifyToJS(openApi)})` : ''}
384
+ Config.set('routes', ${stringifyToJS(Object.fromEntries(routes.map(r => ([r.path+'$'+verbAlias[r.method], r.name]))))})
365
385
 
366
386
  ${routes.map(r => `import ${r.name} from '../${normalizeImportPath(r.file)}'`).join('\n')}
367
387
  ${middlewares.map(r => `import ${r.name} from '../${normalizeImportPath(r.file)}'`).join('\n')}
@@ -370,9 +390,7 @@ try {
370
390
  const handlers = {${routes.map(r => r.name).join()}}
371
391
 
372
392
  for (const [name, handler] of Object.entries(handlers)) {
373
- if (typeof handler == 'function' || handler.prototype?.handle) {
374
- registerHandler(name, handler)
375
- }
393
+ registerHandler(name, handler)
376
394
  }
377
395
 
378
396
  const middlewares = {${middlewares.map(r => r.name).join()}}
@@ -388,7 +406,7 @@ try {
388
406
  const rPath = join(_root, '.rajt/routes.json')
389
407
  ensureDir(rPath)
390
408
  writeFileSync(rPath, JSON.stringify(routes.filter(r => r.method && r.path).map(route => [
391
- route.method,
409
+ verbAlias[route.method],
392
410
  route.path,
393
411
  route.middlewares,
394
412
  route.name,
package/src/types.ts CHANGED
@@ -11,6 +11,7 @@ import type { OpenAPIV3_1, OpenAPIV3 } from 'openapi-types'
11
11
  import type { StandardSchemaV1 } from '@standard-schema/spec'
12
12
  import type { DescribeRouteOptions as RawDescribeRouteOptions, ResolverReturnType } from 'hono-openapi'
13
13
  import type * as z from 'zod'
14
+ import type zm from 'zod/mini'
14
15
  import Action from './action'
15
16
  import request from './request'
16
17
  import response from './response'
@@ -33,6 +34,7 @@ export type {
33
34
  } from 'hono/utils/http-status'
34
35
  export type { BaseMime, StandardSchemaV1 }
35
36
 
37
+ export type zObject = z.ZodTypeAny | zm.ZodMiniObject
36
38
  type PublicMethods<T> = {
37
39
  [K in keyof T]: K extends `#${string}` | `$${string}` | symbol | 'prototype' ? never : K
38
40
  }[keyof T]
@@ -42,11 +44,12 @@ export type IResponse = Pick<typeof response, PublicMethods<typeof response>>
42
44
 
43
45
  export type IValidator = Pick<typeof validator, PublicMethods<typeof validator>>
44
46
  export type Rule = {
45
- schema: z.ZodObject<any>
47
+ schema: zObject
46
48
  target: keyof ValidationTargets
47
49
  eTarget?: 'fieldErrors' | 'formErrors'
48
50
  }
49
51
  export type Rules = Rule[] | Rule | null
52
+ export type RuleFn = (schema: zObject) => Rule
50
53
 
51
54
  export type StandardSchema = StandardSchemaV1 | OpenAPIV3_1.ReferenceObject
52
55
  export type DescribeRouteOptions = Omit<RawDescribeRouteOptions, 'responses'> & {
@@ -1,23 +1,36 @@
1
1
  import { getHandler } from '../register'
2
2
 
3
- export function resolve(obj: any, id: string) {
4
- if (typeof obj == 'function' && obj?.length == 2)
5
- return [obj]
6
-
7
- if (obj?.run)
8
- return obj.run()
9
-
10
- if (obj?.handle)
11
- return obj.handle()
12
-
13
- const instance = new obj()
14
- if (obj?.prototype?.run)
15
- return instance.run()
16
-
17
- if (obj?.prototype?.handle)
18
- return [instance.handle]
19
-
20
- throw new Error(`Invalid action "${id}" - unsupported type`)
3
+ export function resolve(...objs: any[]) {
4
+ const _ = []
5
+ for (let obj of objs) {
6
+ if (typeof obj == 'string')
7
+ obj = getHandler(obj)
8
+
9
+ if (typeof obj == 'function' && obj?.length == 2) {
10
+
11
+ } else if (obj?.run) {
12
+ _.push(...obj.run())
13
+ continue
14
+ } else if (obj?.handle) {
15
+ obj = obj.handle
16
+ } else if (obj?.factory) {
17
+ obj = obj?.opts ? obj.factory(...Array.isArray(obj.opts) ? obj.opts : [obj.opts]) : obj.factory()
18
+ } else {
19
+ const instance = new obj()
20
+ if (obj?.prototype?.run) {
21
+ _.push(...instance.run())
22
+ continue
23
+ } else if (obj?.prototype?.handle) {
24
+ obj = instance.handle
25
+ }
26
+
27
+ throw new Error(`Invalid action "${obj?.name || String(obj)}" - unsupported type`)
28
+ }
29
+
30
+ obj && _.push(obj)
31
+ }
32
+
33
+ return _
21
34
  }
22
35
 
23
36
  export function resolveMiddleware(obj: any) {
@@ -35,11 +48,3 @@ export function resolveMiddleware(obj: any) {
35
48
 
36
49
  throw new Error('Invalid middleware provided. Must be a Hono middleware function or MiddlewareClass instance/constructor')
37
50
  }
38
-
39
- export function mw(...objs: string[]): Function[] {
40
- return objs.flatMap(obj => {
41
- if (typeof obj != 'string') return null
42
- // @ts-ignore
43
- return getHandler(obj)?.mw || null
44
- }).flat().filter(Boolean)
45
- }
package/src/validator.ts CHANGED
@@ -1,17 +1,17 @@
1
- import type * as z from 'zod'
2
1
  import { zValidator } from '@hono/zod-validator'
3
2
  import response from './response'
4
3
  import type {
5
- Rule, Rules,
4
+ Rule, Rules, RuleFn,
6
5
  ValidationTargets,
6
+ zObject,
7
7
  } from './types'
8
8
 
9
9
  export default class $Validator {
10
- private static cache = new Map<string, (schema: z.ZodObject<any>) => Rule>()
10
+ private static cache = new Map<string, RuleFn>()
11
11
 
12
12
  private static createRule<T extends keyof ValidationTargets>(
13
13
  target: T,
14
- schema: z.ZodObject<any>
14
+ schema: zObject
15
15
  ): Rule {
16
16
  return {
17
17
  target,
@@ -24,7 +24,7 @@ export default class $Validator {
24
24
  if (this.cache.has(target))
25
25
  return this.cache.get(target)
26
26
 
27
- const fn = (schema: z.ZodObject<any>) => this.createRule(target, schema)
27
+ const fn = (schema: zObject) => this.createRule(target, schema)
28
28
  this.cache.set(target, fn)
29
29
  return fn
30
30
  }
@@ -1,14 +0,0 @@
1
- import { readFileSync } from 'node:fs'
2
- import { dirname, join } from 'pathe'
3
-
4
- export default function jsonImport<T = any>(filePath: string, defaultValue: T = {} as T): T {
5
- const __dirname = dirname(new URL(import.meta.url).pathname)
6
-
7
- try {
8
- const fullPath = join(__dirname, filePath)
9
- const fileContent = readFileSync(fullPath, 'utf-8')
10
- return JSON.parse(fileContent) as T
11
- } catch (error) {
12
- return defaultValue
13
- }
14
- }
@@ -1,9 +0,0 @@
1
- import type { MiddlewareHandler } from 'hono'
2
- import { MiddlewareType } from '../middleware'
3
- import { resolveMiddleware } from './resolve'
4
-
5
- export default function mergeMiddleware(target: Function | any, ...handlers: MiddlewareType[]) {
6
- const existingMiddlewares: MiddlewareHandler[] = target?.mw || []
7
- const allMiddlewares = [...existingMiddlewares, ...handlers.flat().map(handler => resolveMiddleware(handler))]
8
- target.mw = allMiddlewares
9
- }