Skip to content

Commit

Permalink
feat(wobe): add custom context type (#28)
Browse files Browse the repository at this point in the history
  • Loading branch information
coratgerl authored Jul 23, 2024
1 parent cb8a8ca commit 61b799c
Show file tree
Hide file tree
Showing 11 changed files with 55 additions and 38 deletions.
6 changes: 3 additions & 3 deletions packages/wobe/src/Context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ export class Context {
public requestStartTimeInMs: number | undefined = undefined
public getIpAdress: () => string = () => ''

public handler: WobeHandler | undefined = undefined
public beforeHandlerHook: Array<WobeHandler> = []
public afterHandlerHook: Array<WobeHandler> = []
public handler: WobeHandler<any> | undefined = undefined
public beforeHandlerHook: Array<WobeHandler<any>> = []
public afterHandlerHook: Array<WobeHandler<any>> = []

constructor(request: Request, router?: RadixTree) {
this.request = request
Expand Down
22 changes: 21 additions & 1 deletion packages/wobe/src/Wobe.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { bearerAuth, csrf, logger } from './hooks'
import { WobeStore } from './tools'

describe('Wobe', () => {
let wobe: Wobe
let wobe: Wobe<any>
const mockHookOnSpecificRoute = mock(() => {})
const mockHook = mock(() => {})
const mockSecondHook = mock(() => {})
Expand Down Expand Up @@ -252,6 +252,26 @@ describe('Wobe', () => {
},
)

it('should create wobe app with custom context', async () => {
const wobeWithContext = new Wobe<{
customType: string
}>().get('/test', (ctx) => {
ctx.customType = 'test'

return ctx.res.send(ctx.customType)
})

const port = await getPort()

wobeWithContext.listen(port)

const res = await fetch(`http://127.0.0.1:${port}/test`)

expect(await res.text()).toEqual('test')

wobeWithContext.stop()
})

it('should call callback on listen', async () => {
const localPort = await getPort()

Expand Down
39 changes: 18 additions & 21 deletions packages/wobe/src/Wobe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,6 @@ import type { Context } from './Context'

export type MaybePromise<T> = T | Promise<T>

export type Routes = Array<{
path: string
handler: WobeHandler
method: HttpMethod
}>

export interface WobeOptions {
hostname?: string
onError?: (error: Error) => void
Expand All @@ -31,9 +25,9 @@ export type WobeHandlerOutput =
| Response
| Promise<Response>

export type WobeHandler = (ctx: Context) => WobeHandlerOutput
export type WobeHandler<T> = (ctx: Context & T) => WobeHandlerOutput

export type WobePlugin = (wobe: Wobe) => void
export type WobePlugin = (wobe: Wobe<any>) => void

/**
* Hook is the state of the request, it can be before the handler, after the handler or both
Expand Down Expand Up @@ -61,7 +55,7 @@ export interface WobeWebSocket {
idleTimeout?: number
backpressureLimit?: number
closeOnBackpressureLimit?: boolean
beforeWebSocketUpgrade?: Array<WobeHandler>
beforeWebSocketUpgrade?: Array<WobeHandler<any>>
onOpen?(ws: ServerWebSocket<any>): void
onMessage?(ws: ServerWebSocket<any>, message: string | Buffer): void
onClose?(
Expand All @@ -82,12 +76,12 @@ const factoryOfRuntime = (): RuntimeAdapter => {
/**
* Wobe is the main class of the framework
*/
export class Wobe {
export class Wobe<T> {
private options?: WobeOptions
private server: Server | null
private hooks: Array<{
pathname: string
handler: WobeHandler
handler: WobeHandler<T>
hook: Hook
method: HttpMethod
}>
Expand Down Expand Up @@ -119,7 +113,7 @@ export class Wobe {
* @param handler The handler of the request
* @param hook The hook of the request (optional)
*/
get(path: string, handler: WobeHandler, hook?: WobeHandler) {
get(path: string, handler: WobeHandler<T>, hook?: WobeHandler<T>) {
if (hook) this._addHook('beforeHandler', 'GET')(path, hook)

this.router.addRoute('GET', path, handler)
Expand All @@ -133,7 +127,7 @@ export class Wobe {
* @param handler The handler of the request
* @param hook The hook of the request (optional)
*/
post(path: string, handler: WobeHandler, hook?: WobeHandler) {
post(path: string, handler: WobeHandler<T>, hook?: WobeHandler<T>) {
if (hook) this._addHook('beforeHandler', 'POST')(path, hook)

this.router.addRoute('POST', path, handler)
Expand All @@ -147,7 +141,7 @@ export class Wobe {
* @param handler The handler of the request
* @param hook The hook of the request (optional)
*/
put(path: string, handler: WobeHandler, hook?: WobeHandler) {
put(path: string, handler: WobeHandler<T>, hook?: WobeHandler<T>) {
if (hook) this._addHook('beforeHandler', 'PUT')(path, hook)

this.router.addRoute('PUT', path, handler)
Expand All @@ -161,7 +155,7 @@ export class Wobe {
* @param handler The handler of the request
* @param hook The hook of the request (optional)
*/
delete(path: string, handler: WobeHandler, hook?: WobeHandler) {
delete(path: string, handler: WobeHandler<T>, hook?: WobeHandler<T>) {
if (hook) this._addHook('beforeHandler', 'DELETE')(path, hook)

this.router.addRoute('DELETE', path, handler)
Expand All @@ -175,7 +169,7 @@ export class Wobe {
* @param handler The handler of the request
* @param hook The hook of the request (optional)
*/
all(path: string, handler: WobeHandler, hook?: WobeHandler) {
all(path: string, handler: WobeHandler<T>, hook?: WobeHandler<T>) {
if (hook) {
this.httpMethods.map((method) =>
this._addHook('beforeHandler', method)(path, hook),
Expand All @@ -189,7 +183,7 @@ export class Wobe {

private _addHook =
(hook: Hook, method: HttpMethod) =>
(arg1: string | WobeHandler, ...handlers: WobeHandler[]) => {
(arg1: string | WobeHandler<T>, ...handlers: WobeHandler<T>[]) => {
let path = arg1

if (typeof arg1 !== 'string') {
Expand All @@ -216,8 +210,8 @@ export class Wobe {
* @param handlers The handlers of the request
*/
beforeAndAfterHandler(
arg1: string | WobeHandler,
...handlers: WobeHandler[]
arg1: string | WobeHandler<T>,
...handlers: WobeHandler<T>[]
) {
this.httpMethods.map((method) =>
this._addHook('beforeAndAfterHandler', method)(arg1, ...handlers),
Expand All @@ -231,7 +225,10 @@ export class Wobe {
* @param arg1 The path of the request or the handler
* @param handlers The handlers of the request
*/
beforeHandler(arg1: string | WobeHandler, ...handlers: WobeHandler[]) {
beforeHandler(
arg1: string | WobeHandler<T>,
...handlers: WobeHandler<T>[]
) {
this.httpMethods.map((method) =>
this._addHook('beforeHandler', method)(arg1, ...handlers),
)
Expand All @@ -244,7 +241,7 @@ export class Wobe {
* @param arg1 The path of the request or the handler
* @param handlers The handlers of the request
*/
afterHandler(arg1: string | WobeHandler, ...handlers: WobeHandler[]) {
afterHandler(arg1: string | WobeHandler<T>, ...handlers: WobeHandler<T>[]) {
this.httpMethods.map((method) =>
this._addHook('afterHandler', method)(arg1, ...handlers),
)
Expand Down
2 changes: 1 addition & 1 deletion packages/wobe/src/hooks/bearerAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const bearerAuth = ({
token,
hashFunction = defaultHash,
realm = '',
}: BearerAuthOptions): WobeHandler => {
}: BearerAuthOptions): WobeHandler<any> => {
return (ctx) => {
const requestAuthorization = ctx.request.headers.get('Authorization')

Expand Down
2 changes: 1 addition & 1 deletion packages/wobe/src/hooks/bodyLimit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ interface BodyLimitOptions {
/**
* bodyLimit is a hook that checks if the request body is too large
*/
export const bodyLimit = (options: BodyLimitOptions): WobeHandler => {
export const bodyLimit = (options: BodyLimitOptions): WobeHandler<any> => {
return (ctx) => {
// The content-length header is not always present
if (ctx.request.headers.get('Content-Length')) {
Expand Down
2 changes: 1 addition & 1 deletion packages/wobe/src/hooks/cors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export interface CorsOptions {
/**
* cors is a hook that adds the necessary headers to enable CORS
*/
export const cors = (options?: CorsOptions): WobeHandler => {
export const cors = (options?: CorsOptions): WobeHandler<any> => {
const defaults: CorsOptions = {
origin: '*',
allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
Expand Down
2 changes: 1 addition & 1 deletion packages/wobe/src/hooks/csrf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const isSameOrigin = (optsOrigin: Origin, requestOrigin: string) => {
/**
* csrf is a hook that checks if the request has a valid CSRF token
*/
export const csrf = (options: CsrfOptions): WobeHandler => {
export const csrf = (options: CsrfOptions): WobeHandler<any> => {
return (ctx) => {
const requestOrigin = ctx.request.headers.get('origin') || ''

Expand Down
2 changes: 1 addition & 1 deletion packages/wobe/src/hooks/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const logger = (
{ loggerFunction }: LoggerOptions = {
loggerFunction: defaultLoggerFunction,
},
): WobeHandler => {
): WobeHandler<any> => {
return (ctx) => {
const { state, request } = ctx

Expand Down
2 changes: 1 addition & 1 deletion packages/wobe/src/hooks/rateLimit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export interface RateLimitOptions {
export const rateLimit = ({
interval,
numberOfRequests,
}: RateLimitOptions): WobeHandler => {
}: RateLimitOptions): WobeHandler<any> => {
const store = new WobeStore<number>({
interval,
})
Expand Down
2 changes: 1 addition & 1 deletion packages/wobe/src/hooks/secureHeaders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export const secureHeaders = ({
strictTransportSecurity = ['max-age=31536000; includeSubDomains'],
xContentTypeOptions = 'nosniff',
xDownloadOptions = 'noopen',
}: SecureHeadersOptions): WobeHandler => {
}: SecureHeadersOptions): WobeHandler<any> => {
return (ctx) => {
if (contentSecurityPolicy) {
const formatContentSecurityPolicy = Object.entries(
Expand Down
12 changes: 6 additions & 6 deletions packages/wobe/src/router/RadixTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import type { Hook, HttpMethod, WobeHandler } from '../Wobe'
export interface Node {
name: string
children: Array<Node>
handler?: WobeHandler
beforeHandlerHook?: Array<WobeHandler>
afterHandlerHook?: Array<WobeHandler>
handler?: WobeHandler<any>
beforeHandlerHook?: Array<WobeHandler<any>>
afterHandlerHook?: Array<WobeHandler<any>>
method?: HttpMethod
isParameterNode?: boolean
isWildcardNode?: boolean
Expand All @@ -16,7 +16,7 @@ export class RadixTree {
public root: Node = { name: '/', children: [] }
private isOptimized = false

addRoute(method: HttpMethod, path: string, handler: WobeHandler) {
addRoute(method: HttpMethod, path: string, handler: WobeHandler<any>) {
const pathParts = path.split('/').filter(Boolean)

let currentNode = this.root
Expand Down Expand Up @@ -57,7 +57,7 @@ export class RadixTree {
currentNode.method = method
}

_addHookToNode(node: Node, hook: Hook, handler: WobeHandler) {
_addHookToNode(node: Node, hook: Hook, handler: WobeHandler<any>) {
switch (hook) {
case 'beforeHandler': {
if (!node.beforeHandlerHook) node.beforeHandlerHook = []
Expand Down Expand Up @@ -89,7 +89,7 @@ export class RadixTree {
addHook(
hook: Hook,
path: string,
handler: WobeHandler,
handler: WobeHandler<any>,
method: HttpMethod,
node?: Node,
) {
Expand Down

0 comments on commit 61b799c

Please sign in to comment.