diff --git a/cheetah.ts b/cheetah.ts index 6dcca29..0cc739b 100644 --- a/cheetah.ts +++ b/cheetah.ts @@ -69,6 +69,7 @@ export class cheetah extends base() { #proxy #routes: Set<[Uppercase, string, RegExp, HandlerOrSchema[]]> #runtime: 'deno' | 'cloudflare' + #onPlugIn constructor({ base, @@ -109,6 +110,7 @@ export class cheetah extends base() { this.#runtime = typeof globalThis?.Deno?.serve !== 'function' ? 'cloudflare' : 'deno' + this.#onPlugIn = false } /* use ---------------------------------------------------------------------- */ @@ -242,6 +244,32 @@ export class cheetah extends base() { let body: Response | void = undefined for (const e of this.#extensions.values()) { + if (this.#onPlugIn === true && e[1].onPlugIn !== undefined) { + await e[1].onPlugIn({ + env: __app.env, + routes: this.#routes, + runtime: this.#runtime, + setRoute: (method, pathname, ...handlers) => { + this.#routes.add([ + method.toUpperCase() as Uppercase, + pathname, + RegExp( + `^${ + (pathname + .replace(/\/+(\/|$)/g, '$1')) + .replace(/(\/?\.?):(\w+)\+/g, '($1(?<$2>*))') + .replace(/(\/?\.?):(\w+)/g, '($1(?<$2>[^$1/]+?))') + .replace(/\./g, '\\.') + .replace(/(\/?)\*/g, '($1.*)?') + }/*$`, + ), + // @ts-ignore: + handlers, + ]) + }, + }) + } + if ( e[0] !== '*' && __app.request.pathname.indexOf(e[0]) !== 0 @@ -249,10 +277,12 @@ export class cheetah extends base() { continue } - const { onRequest } = e[1] - - if (onRequest !== undefined) { - const result = await onRequest({ app: __app, req, _: e[1].__config }) + if (e[1].onRequest !== undefined) { + const result = await e[1].onRequest({ + app: __app, + req, + _: e[1].__config, + }) if (result !== undefined) { body = result @@ -260,6 +290,10 @@ export class cheetah extends base() { } } + if (this.#onPlugIn) { + this.#onPlugIn = false + } + if (body !== undefined) { return body } diff --git a/extensions.ts b/extensions.ts index 5e52253..66d8f96 100644 --- a/extensions.ts +++ b/extensions.ts @@ -1,5 +1,8 @@ // Copyright 2023 Samuel Kopp. All rights reserved. Apache-2.0 license. +import { ZodString, ZodUnion } from 'https://deno.land/x/zod@v3.21.4/types.ts' +import { Handler, ObjectType } from './handler.ts' import { AppContext, Context } from './mod.ts' +import { Method } from './base.ts' type HasRequired = Partial extends T ? false : true @@ -10,6 +13,76 @@ export type Extension< Config extends Record | unknown = never, > = { __config: Config | undefined + onPlugIn: HasRequired extends true ? ((context: { + env: AppContext['env'] + routes: AppContext['routes'] + runtime: AppContext['runtime'] + setRoute: < + Pathname extends `/${string}`, + // deno-lint-ignore no-explicit-any + ValidatedBody extends ObjectType | ZodString | ZodUnion, + ValidatedCookies extends ObjectType, + ValidatedHeaders extends ObjectType, + ValidatedQuery extends ObjectType, + >( + method: Method, + pathname: Pathname, + ...handler: ( + | { + body?: ValidatedBody + cookies?: ValidatedCookies + headers?: ValidatedHeaders + query?: ValidatedQuery + /** @deprecated please pass this option to the `c.req.body()` method! */ + transform?: boolean // TODO remove at v2.0 + cors?: string + } + | Handler< + Pathname, + ValidatedBody, + ValidatedCookies, + ValidatedHeaders, + ValidatedQuery + > + )[] + ) => void | Promise + settings: Config + }) => void | Promise) + : ((context: { + env: AppContext['env'] + routes: AppContext['routes'] + runtime: AppContext['runtime'] + setRoute: < + Pathname extends `/${string}`, + // deno-lint-ignore no-explicit-any + ValidatedBody extends ObjectType | ZodString | ZodUnion, + ValidatedCookies extends ObjectType, + ValidatedHeaders extends ObjectType, + ValidatedQuery extends ObjectType, + >( + method: Method, + pathname: Pathname, + ...handlers: ( + | { + body?: ValidatedBody + cookies?: ValidatedCookies + headers?: ValidatedHeaders + query?: ValidatedQuery + /** @deprecated please pass this option to the `c.req.body()` method! */ + transform?: boolean // TODO remove at v2.0 + cors?: string + } + | Handler< + Pathname, + ValidatedBody, + ValidatedCookies, + ValidatedHeaders, + ValidatedQuery + > + )[] + ) => void + settings?: Config + }) => void | Promise) onRequest?: HasRequired extends true ? ((context: { app: AppContext req: Request @@ -51,15 +124,18 @@ export function validExtension(ext: Record) { export function createExtension< Config extends Record | unknown = unknown, >({ + onPlugIn, onRequest, onResponse, }: { + onPlugIn?: Extension['onPlugIn'] onRequest?: Extension['onRequest'] onResponse?: Extension['onResponse'] }) { return ((__config?: Config) => { return { __config, + onPlugIn, onRequest, onResponse, [Symbol('cheetah.extension')]: 'v1.0',