Skip to content

Commit cdd99cc

Browse files
committed
chore: wip
1 parent d2a86bb commit cdd99cc

14 files changed

+849
-78
lines changed

packages/bun-router/src/config.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -311,9 +311,9 @@ let _config: RouterConfig | null = null
311311
export async function getConfig(): Promise<RouterConfig> {
312312
if (!_config) {
313313
_config = await loadConfig({
314-
name: 'router',
315-
defaultConfig,
316-
})
314+
name: 'router',
315+
defaultConfig,
316+
})
317317
}
318318
return _config
319319
}

packages/bun-router/src/router/fluent-router.ts

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type {
1212
RouteHandler,
1313
} from '../types'
1414
import type { Router } from './router'
15+
import { matchPath } from '../utils'
1516

1617
// ============================================================================
1718
// Types
@@ -177,8 +178,10 @@ export class FluentRouter {
177178
handler: resolvedHandler,
178179
middleware,
179180
domain: this.currentDomain || undefined,
181+
pattern: this.createPattern(fullPath),
180182
}
181-
this.router.addRoute(route)
183+
// Use direct push to routes array to avoid conflict with http-methods.ts addRoute
184+
this.router.routes.push(route)
182185
}
183186

184187
return new FluentRouteBuilder(this.router, fullPath, methods[0])
@@ -191,11 +194,11 @@ export class FluentRouter {
191194
/**
192195
* Register a resource controller
193196
*/
194-
resource(name: string, controller: ControllerClass, options: ResourceOptions = {}): this {
197+
resource(name: string, Controller: ControllerClass, options: ResourceOptions = {}): this {
195198
const methods = this.getResourceMethods(options)
196199
const paramName = options.parameters?.[name] || 'id'
197200

198-
const controllerInstance = new controller()
201+
const controllerInstance = new Controller()
199202

200203
for (const method of methods) {
201204
const { httpMethod, path, handlerName } = this.getResourceRoute(name, method, paramName)
@@ -212,8 +215,13 @@ export class FluentRouter {
212215
middleware: this.buildMiddleware(options.middleware),
213216
name: this.currentNamePrefix + routeName,
214217
domain: this.currentDomain || undefined,
218+
pattern: this.createPattern(fullPath),
219+
}
220+
// Use direct push to routes array to avoid conflict with http-methods.ts addRoute
221+
this.router.routes.push(route)
222+
if (route.name) {
223+
this.router.namedRoutes.set(route.name, route)
215224
}
216-
this.router.addRoute(route)
217225
}
218226
}
219227

@@ -235,9 +243,9 @@ export class FluentRouter {
235243
/**
236244
* Register a singleton resource (no index, create, store, destroy)
237245
*/
238-
singleton(name: string, controller: ControllerClass, options: ResourceOptions = {}): this {
246+
singleton(name: string, Controller: ControllerClass, options: ResourceOptions = {}): this {
239247
const singletonMethods: SingletonMethod[] = ['show', 'edit', 'update']
240-
const controllerInstance = new controller()
248+
const controllerInstance = new Controller()
241249

242250
for (const method of singletonMethods) {
243251
if (options.except?.includes(method))
@@ -259,8 +267,13 @@ export class FluentRouter {
259267
middleware: this.buildMiddleware(options.middleware),
260268
name: this.currentNamePrefix + routeName,
261269
domain: this.currentDomain || undefined,
270+
pattern: this.createPattern(fullPath),
271+
}
272+
// Use direct push to routes array to avoid conflict with http-methods.ts addRoute
273+
this.router.routes.push(route)
274+
if (route.name) {
275+
this.router.namedRoutes.set(route.name, route)
262276
}
263-
this.router.addRoute(route)
264277
}
265278
}
266279

@@ -410,12 +423,39 @@ export class FluentRouter {
410423
handler: resolvedHandler,
411424
middleware,
412425
domain: this.currentDomain || undefined,
426+
pattern: this.createPattern(fullPath),
413427
}
414428

415-
this.router.addRoute(route)
429+
// Use direct push to routes array to avoid conflict with http-methods.ts addRoute
430+
this.router.routes.push(route)
431+
if (route.name) {
432+
this.router.namedRoutes.set(route.name, route)
433+
}
416434
return new FluentRouteBuilder(this.router, fullPath, method)
417435
}
418436

437+
/**
438+
* Create a pattern object for route matching
439+
*/
440+
private createPattern(routePath: string): { exec: (url: URL) => { pathname: { groups: Record<string, string> } } | null } {
441+
return {
442+
exec: (url: URL): { pathname: { groups: Record<string, string> } } | null => {
443+
const params: Record<string, string> = {}
444+
const isMatch = matchPath(routePath, url.pathname, params)
445+
446+
if (!isMatch) {
447+
return null
448+
}
449+
450+
return {
451+
pathname: {
452+
groups: params,
453+
},
454+
}
455+
},
456+
}
457+
}
458+
419459
private buildPath(path: string): string {
420460
if (this.currentPrefix) {
421461
return `${this.currentPrefix}${path.startsWith('/') ? path : `/${path}`}`
@@ -433,7 +473,8 @@ export class FluentRouter {
433473
private resolveHandler(handler: RouteHandler | string): ActionHandler {
434474
if (typeof handler === 'string') {
435475
if (this.currentController) {
436-
const controllerInstance = new this.currentController()
476+
const ControllerClass = this.currentController
477+
const controllerInstance = new ControllerClass()
437478
const method = controllerInstance[handler] as RouteHandler | undefined
438479
if (method) {
439480
return method.bind(controllerInstance)

packages/bun-router/src/router/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { ActionHandler, MiddlewareHandler, Route } from '../types'
1+
import type { ActionHandler, Route } from '../types'
22
import { Dependencies, globalMiddlewarePipeline, MiddlewareFactory, MiddlewarePipeline, SkipConditions } from '../middleware/pipeline'
33
import { registerFileStreaming } from './file-streaming'
44
import { FluentRouteBuilder, FluentRouter, RouteFactory, router, RouterUtils } from './fluent-routing'

packages/bun-router/src/router/router.ts

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { Server } from 'bun'
22
import type { MiddlewareDependency, MiddlewarePipeline, MiddlewarePipelineStats, MiddlewareSkipCondition } from '../middleware/pipeline'
33
import type {
44
ActionHandler,
5+
CookieOptions,
56
EnhancedRequest,
67
MiddlewareHandler,
78
NextFunction,
@@ -490,19 +491,15 @@ export class Router {
490491
// Invalidate route cache before starting server
491492
this.invalidateCache()
492493

493-
// Create server options
494-
const serverOptions: any = {
494+
// Create server options - use type assertion for Bun.serve compatibility
495+
const serverOptions = {
495496
...options,
496497
fetch: this.handleRequest.bind(this),
497-
}
498-
499-
// Apply WebSocket configuration if provided
500-
if (this.wsConfig) {
501-
serverOptions.websocket = this.wsConfig
502-
}
498+
websocket: this.wsConfig,
499+
} as Parameters<typeof Bun.serve>[0]
503500

504501
// Start the server
505-
this.serverInstance = Bun.serve(serverOptions)
502+
this.serverInstance = Bun.serve(serverOptions) as Server<WebSocketData>
506503

507504
if (this.config.verbose) {
508505
const port = this.serverInstance.port
@@ -563,7 +560,7 @@ export class Router {
563560
}
564561

565562
// Create a final middleware that executes the route handler
566-
const routeHandlerMiddleware = async (req: EnhancedRequest, _next: any) => {
563+
const routeHandlerMiddleware = async (req: EnhancedRequest, _next: NextFunction) => {
567564
return await this.resolveHandler(match.route.handler, req)
568565
}
569566

@@ -742,14 +739,14 @@ export class Router {
742739
// Create cookie utilities with lazy parsing
743740
const cookies = {
744741
get: (name: string) => getCookies()[name],
745-
set: (name: string, value: string, options: any = {}) => {
742+
set: (name: string, value: string, options: CookieOptions = {}) => {
746743
const enhancedRequest = req as EnhancedRequest
747744
if (!enhancedRequest._cookiesToSet) {
748745
enhancedRequest._cookiesToSet = []
749746
}
750747
enhancedRequest._cookiesToSet.push({ name, value, options })
751748
},
752-
delete: (name: string, options: any = {}) => {
749+
delete: (name: string, options: CookieOptions = {}) => {
753750
const enhancedRequest = req as EnhancedRequest
754751
if (!enhancedRequest._cookiesToDelete) {
755752
enhancedRequest._cookiesToDelete = []
@@ -811,7 +808,7 @@ export class Router {
811808
/**
812809
* Serialize a cookie for the Set-Cookie header
813810
*/
814-
serializeCookie(name: string, value: string, options: any = {}): string {
811+
serializeCookie(name: string, value: string, options: CookieOptions = {}): string {
815812
let cookie = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`
816813

817814
if (options.maxAge !== undefined) {
@@ -899,22 +896,22 @@ export class Router {
899896
/**
900897
* Resolve an action handler
901898
*/
902-
async resolveHandler(handler: any, req: EnhancedRequest): Promise<Response> {
899+
async resolveHandler(handler: ActionHandler, req: EnhancedRequest): Promise<Response> {
903900
// If it's a function, call it with the request
904-
if (typeof handler === 'function' && !handler.prototype?.handle) {
905-
return await handler(req)
901+
if (typeof handler === 'function' && !(handler as { prototype?: { handle?: unknown } }).prototype?.handle) {
902+
return await (handler as (req: EnhancedRequest) => Response | Promise<Response>)(req)
906903
}
907904

908905
// If it's a class constructor, instantiate it and call handle
909-
if (typeof handler === 'function' && handler.prototype && typeof handler.prototype.handle === 'function') {
910-
const HandlerClass = handler
906+
if (typeof handler === 'function' && (handler as { prototype?: { handle?: unknown } }).prototype?.handle) {
907+
const HandlerClass = handler as new () => { handle: (req: EnhancedRequest) => Response | Promise<Response> }
911908
const handlerInstance = new HandlerClass()
912909
return await handlerInstance.handle(req)
913910
}
914911

915912
// If it's an object with a handle method
916-
if (handler && typeof handler.handle === 'function') {
917-
return await handler.handle(req)
913+
if (handler && typeof (handler as unknown as { handle?: unknown }).handle === 'function') {
914+
return await (handler as unknown as { handle: (req: EnhancedRequest) => Response | Promise<Response> }).handle(req)
918915
}
919916

920917
throw new Error(`Invalid action handler: ${typeof handler}`)

packages/bun-router/test/basic-middleware.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ describe('Bun Router - Middleware Tests', () => {
2626
}
2727

2828
// Create a route that uses the middleware
29-
await router.get('/middleware-test', async (req) => {
29+
await router.get('/middleware-test', async (req: EnhancedRequest) => {
3030
return new Response(`Request ID: ${req.requestId}`, {
3131
status: 200,
3232
})

packages/bun-router/test/cli.test.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { EnhancedRequest } from '../src/types'
12
import { beforeEach, describe, expect, it } from 'bun:test'
23
import { Router } from '../src/router/index'
34

@@ -26,7 +27,7 @@ describe('CLI Commands', () => {
2627
await router.get('/test', () => new Response('test'))
2728
await router.post('/users', () => new Response('create user'))
2829
await router.get('/admin/dashboard', () => new Response('admin'), 'web', 'admin.dashboard')
29-
await router.get('/users/{id}', req => new Response(`User ${req.params.id}`)) // Dynamic route
30+
await router.get('/users/{id}', (req: EnhancedRequest) => new Response(`User ${req.params.id}`)) // Dynamic route
3031

3132
// Verify routes were added
3233
expect(router.routes.length).toBe(4)
@@ -158,7 +159,7 @@ describe('CLI Commands', () => {
158159

159160
describe('Route Debugging Logic', () => {
160161
it('should match routes successfully', async () => {
161-
await router.get('/users/{id}', req => new Response(`User ${req.params.id}`), 'web', 'users.show')
162+
await router.get('/users/{id}', (req: EnhancedRequest) => new Response(`User ${req.params.id}`), 'web', 'users.show')
162163

163164
// Test route matching functionality
164165
expect(router.matchRoute).toBeDefined()
@@ -188,7 +189,7 @@ describe('CLI Commands', () => {
188189
})
189190

190191
it('should handle routes with optional parameters', async () => {
191-
await router.get('/products/{category}/{id?}', (req) => {
192+
await router.get('/products/{category}/{id?}', (req: EnhancedRequest) => {
192193
if (req.params.id) {
193194
return new Response(`Product ${req.params.id} in ${req.params.category}`)
194195
}

0 commit comments

Comments
 (0)