diff --git a/example/types/global-and-route-level-request.ts b/example/types/global-and-route-level-request.ts new file mode 100644 index 0000000..5bbc7e5 --- /dev/null +++ b/example/types/global-and-route-level-request.ts @@ -0,0 +1,17 @@ +import { IRequestStrict } from 'IttyRouter' +import { Router } from 'Router' + +const router = Router() + +type FooRequest = { + foo: string +} & IRequestStrict + +router + .get('/basic', () => new Response('Success!')) + .get('/text', () => 'Success!') + // .get('/params/:foo', ({ foo }) => foo) // should NOT work + .get('/params/:foo', ({ foo }) => foo) // should work + .get('/json', () => ({ foo: 'bar' })) + +export default router diff --git a/example/types/global-request.ts b/example/types/global-request.ts new file mode 100644 index 0000000..5107c58 --- /dev/null +++ b/example/types/global-request.ts @@ -0,0 +1,16 @@ +import { IRequestStrict } from 'IttyRouter' +import { Router } from 'Router' + +type FooRequest = { + foo: string +} & IRequestStrict + +const router = Router() + +router + .get('/', (request) => { + request.foo // should work + // request.bar // should NOT work + }) + +export default router diff --git a/example/types/middleware.ts b/example/types/middleware.ts new file mode 100644 index 0000000..59eca13 --- /dev/null +++ b/example/types/middleware.ts @@ -0,0 +1,36 @@ +import { IRequestStrict, IRequest, IttyRouter, RequestHandler } from 'IttyRouter' + +type UserRequest = { + user: string +} & IRequestStrict + +const router = IttyRouter() + +const withUser: RequestHandler = (request) => { + request.user = 'Kevin' +} + +router + // upstream request sees the request as IRequest (default), so anything goes + .get('/', (request) => { + request.user = 123 // allowed because IRequest + }) + + // then we add the middleware defined above as + .all('*', withUser) + + // and now downstream requests expect a UserRequest + .get('/', (request) => { + request.user = 123 // NOT VALID + }) + + // and if we ever need to restore control, add the generic back in + .get('/', (request) => { + request.user = 123 // now this is ok + }) + + .get('/', (request) => { + request.user = 123 // and so is this + }) + +export default router diff --git a/example/types/route-level-request.ts b/example/types/route-level-request.ts new file mode 100644 index 0000000..b5f75d6 --- /dev/null +++ b/example/types/route-level-request.ts @@ -0,0 +1,16 @@ +import { IRequestStrict } from 'IttyRouter' +import { Router } from 'Router' + +type FooRequest = { + foo: string +} & IRequestStrict + +const router = Router() + +router + .get('/', (request) => { + request.foo // should work + // request.bar // should NOT work + }) + +export default router diff --git a/src/IttyRouter.ts b/src/IttyRouter.ts index 73af174..b58919d 100644 --- a/src/IttyRouter.ts +++ b/src/IttyRouter.ts @@ -1,21 +1,21 @@ export type GenericTraps = Record export type RequestLike = { - method: string, - url: string, + method: string + url: string } & GenericTraps export type IRequestStrict = { - method: string, - url: string, - route: string, + method: string + url: string + route: string params: { - [key: string]: string, - }, + [key: string]: string + } query: { - [key: string]: string | string[] | undefined, - }, - proxy?: any, + [key: string]: string | string[] | undefined + } + proxy?: any } & Request export type IRequest = IRequestStrict & GenericTraps @@ -43,32 +43,22 @@ export type Route = any[]> = [] ) => IttyRouterType -// this is an alternative UniveralRoute, accepting generics (from upstream), but without -// per-route overrides -// export type UniversalRoute = ( -// path: string, -// ...handlers: RequestHandler[] -// ) => IttyRouterType, Args> - -// helper function to detect equality in types (used to detect custom Request on router) -export type Equal = (() => T extends X ? 1 : 2) extends (() => T extends Y ? 1 : 2) ? true : false; - export type CustomRoutes = { - [key: string]: R, + [key: string]: R } export type IttyRouterType = { - __proto__: IttyRouterType, - routes: RouteEntry[], + __proto__: IttyRouterType + routes: RouteEntry[] fetch: (request: RequestLike, ...extra: Args) => Promise - all: Route, - delete: Route, - get: Route, - head: Route, - options: Route, - patch: Route, - post: Route, - put: Route, + all: Route + delete: Route + get: Route + head: Route + options: Route + patch: Route + post: Route + put: Route } & CustomRoutes> export const IttyRouter = <