Skip to content

Commit

Permalink
Add missing generics to Router stages (in options) (#241)
Browse files Browse the repository at this point in the history
* checking in stuff

* updated type sandbox

* cleaned up global request type

* updated CHANGELOG

* released v5.0.13 - fixed types: router and autorouter stages should use router-level generics

* linting
  • Loading branch information
kwhitley committed Apr 14, 2024
1 parent b5c4f7f commit ca742e4
Show file tree
Hide file tree
Showing 18 changed files with 157 additions and 58 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
## Changelog

- **v5.0.11**
- **v5.0.13**
- fixed: Router/AutoRouter stages were not connected to router-level generics
- **v5.0.12**
- fixed: ./types was not being properly exported
- **v5.0.10**
- fixed: response formatters in finally stage could still cross pollute headers in Node
Expand Down
15 changes: 5 additions & 10 deletions examples/types/additional-arguments.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { RequestHandler } from '../../src/types'
import { IRequestStrict } from '../../src/types'
import { Router } from '../../src/Router'
import { IttyRouter } from '../../src/IttyRouter'
import { AutoRouter } from '../../src/AutoRouter'
import { IRequest } from 'itty-router'
import { IRequest, IRequestStrict, RequestHandler } from '../../src/types'

// we define our environment
type Environment = { age: number }
Expand All @@ -27,19 +23,18 @@ router
// before middleware
.get('/', (request, env) => {
request.user = 'kevin' // invalid (strict)
env.whatever = 123 // valid (any)
env.age = 123 // valid (any)
env.age = 123 // valid
})

// route-level overrides
.get<IRequest, Args>('/', (request, env) => {
request.foo = 'bar' // invalid
request.foo = 'bar' // valid
env.whatever = 123 // invalid
env.age = 123 // valid
})
// route-level overrides
.get<IRequest, AlternativeArgs>('/', (request, env) => {
request.foo = 'bar' // invalid
request.foo = 'bar' // valid
env.age = 123 // invalid
env.name = 'Mittens' // valid
})
Expand All @@ -52,5 +47,5 @@ router
})

.get('/', (request, env) => {
env.age = 'foo' // valid (any)
env.age = 'foo' // invalid
})
33 changes: 33 additions & 0 deletions examples/types/generics-router-stages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { error } from 'console'
import { Router } from '../../src/Router'
import { withParams } from '../../src/withParams'
import { IRequest, IRequestStrict, RequestHandler } from '../../src/types'

// we define our environment
type Environment = { age: number }
type Pet = { name: string }

// and now both args combined (that Workers send to the .fetch())
type Args = [Environment]
type AlternativeArgs = [Pet]

const router = Router<IRequestStrict, Args, Response>({
before: [
(request, env) => {
env.age = 123 // valid
env.foo // invalid
request.foo // invalid
request.body // valid
},
withParams,
],
catch: error,
finally: [
(response, request, env) => {
response.whatever // valid (any)
env.age = 123 // valid
env.foo // invalid
request.foo // invalid
},
]
})
51 changes: 51 additions & 0 deletions examples/types/ittyrouter-generics.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { IttyRouter } from '../../src/IttyRouter'
import { IRequest, IRequestStrict, RequestHandler } from '../../src/types'

// we define our environment
type Environment = { age: number }
type Pet = { name: string }

// and now both args combined (that Workers send to the .fetch())
type Args = [Environment]
type AlternativeArgs = [Pet]

// creating some middleware that needs access to CF variables
export const withUser: RequestHandler<IRequest, Args> =
(request, env) => {
request.user = 'Kevin'
env.age = 123
env.name = 'Kevin' // invalid
}

const router = IttyRouter<IRequestStrict, Args>()

router
// before middleware
.get('/', (request, env) => {
request.user = 'kevin' // invalid (strict)
env.age = 123 // valid
})

// route-level overrides
.get<IRequest, Args>('/', (request, env) => {
request.foo = 'bar' // valid
env.whatever = 123 // invalid
env.age = 123 // valid
})
// route-level overrides
.get<IRequest, AlternativeArgs>('/', (request, env) => {
request.foo = 'bar' // valid
env.age = 123 // invalid
env.name = 'Mittens' // valid
})

// after middleware
.get('/', withUser, (request, env) => {
request.user = 'Kevin'
env.age = 123 // valid
env.whatever = 123 // invalid
})

.get('/', (request, env) => {
env.age = 'foo' // invalid
})
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "itty-router",
"version": "5.0.12",
"version": "5.0.13",
"description": "A tiny, zero-dependency router, designed to make beautiful APIs in any environment.",
"main": "./index.js",
"module": "./index.mjs",
Expand Down
1 change: 0 additions & 1 deletion rollup.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ const files = (await globby('./src/*.ts', {
types: path.replace('/src/', '/dist/').replace('.ts', '.d.ts'),
})).sort((a, b) => a.shortPath.toLowerCase() < b.shortPath.toLowerCase() ? -1 : 1)


// read original package.json
const pkg = await fs.readJSON('./package.json')

Expand Down
9 changes: 6 additions & 3 deletions src/AutoRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,20 @@ export const AutoRouter = <
missing = () => error(404),
finally: f = [],
before = [],
...options }: AutoRouterOptions = {}
): AutoRouterType<RequestType, Args, ResponseType> => Router({
...options }: AutoRouterOptions<RequestType, Args, ResponseType> = {}
) => Router<RequestType, Args, ResponseType>({
before: [
// @ts-ignore
withParams,
...before
],
// @ts-ignore
catch: error,
finally: [
// @ts-ignore
(r: any, ...args) => r ?? missing(r, ...args),
format,
...f,
],
...options,
})
}) as AutoRouterType<RequestType, Args, ResponseType>
5 changes: 2 additions & 3 deletions src/IttyRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,13 @@ export const IttyRouter = <
RequestType extends IRequest = IRequest,
Args extends any[] = any[],
ResponseType = any,
GlobalRequestType = RequestType,
>({ base = '', routes = [], ...other }: IttyRouterOptions = {}): IttyRouterType<RequestType, Args, ResponseType, GlobalRequestType> =>
>({ base = '', routes = [], ...other }: IttyRouterOptions = {}): IttyRouterType<RequestType, Args, ResponseType> =>
// @ts-ignore
({
__proto__: new Proxy({}, {
// @ts-expect-error (we're adding an expected prop "path" to the get)
get: (target: any, prop: string, receiver: object, path: string) =>
(route: string, ...handlers: RequestHandler<GlobalRequestType, Args>[]) =>
(route: string, ...handlers: RequestHandler<RequestType, Args>[]) =>
routes.push(
[
prop.toUpperCase(),
Expand Down
4 changes: 2 additions & 2 deletions src/Router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const Router = <
RequestType = IRequest,
Args extends any[] = any[],
ResponseType = any
>({ base = '', routes = [], ...other }: RouterOptions = {}): RouterType<RequestType, Args, ResponseType> =>
>({ base = '', routes = [], ...other }: RouterOptions<RequestType, Args> = {}): RouterType<RequestType, Args, ResponseType> =>
({
__proto__: new Proxy({}, {
// @ts-expect-error (we're adding an expected prop "path" to the get)
Expand Down Expand Up @@ -72,4 +72,4 @@ export const Router = <

return response
},
} as RouterType<RequestType, Args>)
} as RouterType<RequestType, Args, ResponseType>)
10 changes: 7 additions & 3 deletions src/types/AutoRouterOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import { RequestHandler } from './RequestHandler'
import { ResponseHandler } from './ResponseHandler'
import { RouterOptions } from './RouterOptions'

export type AutoRouterOptions = {
missing?: RequestHandler
export type AutoRouterOptions<
RequestType,
Args extends any[],
ResponseType
> = {
missing?: RequestHandler<RequestType, Args>
format?: ResponseHandler
} & RouterOptions
} & RouterOptions<RequestType, Args, ResponseType>
6 changes: 3 additions & 3 deletions src/types/AutoRouterType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { ResponseHandler } from './ResponseHandler'
import { RouterType } from './RouterType'

export type AutoRouterType<
R = IRequest,
RequestType = IRequest,
Args extends any[] = any[],
ResponseType = any
> = {
missing?: RequestHandler
missing?: RequestHandler<RequestType, Args>
format?: ResponseHandler
} & RouterType<R, Args, ResponseType>
} & RouterType<RequestType, Args, ResponseType>
3 changes: 2 additions & 1 deletion src/types/ErrorHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ import { IRequest } from './IRequest'

export type ErrorHandler<
ErrorType extends Error = StatusError,
RequestType = IRequest, Args extends any[] = any[]
RequestType = IRequest,
Args extends any[] = any[]
> = (error: ErrorType, request: RequestType, ...args: Args) => any
27 changes: 13 additions & 14 deletions src/types/IttyRouterType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,19 @@ import { RouteEntry } from './RouteEntry'
import { CustomRoutes } from './CustomRoutes'

export type IttyRouterType<
R = IRequest,
A extends any[] = any[],
RequestType = IRequest,
Args extends any[] = any[],
ResponseType = any,
GlobalRequestType = R,
> = {
__proto__: IttyRouterType<R>
__proto__: IttyRouterType<RequestType, Args, ResponseType>
routes: RouteEntry[]
fetch: <Args extends any[] = A>(request: RequestLike, ...extra: Args) => Promise<ResponseType>
all: Route<GlobalRequestType, A>
delete: Route<GlobalRequestType, A>
get: Route<GlobalRequestType, A>
head: Route<GlobalRequestType, A>
options: Route<GlobalRequestType, A>
patch: Route<GlobalRequestType, A>
post: Route<GlobalRequestType, A>
put: Route<GlobalRequestType, A>
} & CustomRoutes<Route<GlobalRequestType, A>> & GenericTraps
fetch: <A extends any[] = Args>(request: RequestLike, ...extra: A) => Promise<ResponseType>
all: Route<RequestType, Args>
delete: Route<RequestType, Args>
get: Route<RequestType, Args>
head: Route<RequestType, Args>
options: Route<RequestType, Args>
patch: Route<RequestType, Args>
post: Route<RequestType, Args>
put: Route<RequestType, Args>
} & CustomRoutes<Route<RequestType, Args>> & GenericTraps
6 changes: 4 additions & 2 deletions src/types/RequestHandler.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { IRequest } from './IRequest'

export type RequestHandler<R = IRequest, Args extends Array<any> = any[]> =
(request: R, ...args: Args) => any
export type RequestHandler<
RequestType = IRequest,
Args extends Array<any> = any[]
> = (request: RequestType, ...args: Args) => any
6 changes: 3 additions & 3 deletions src/types/ResponseHandler.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { IRequest } from './IRequest'

export type ResponseHandler<
ResponseType = Response,
ResponseType = any,
RequestType = IRequest,
Args extends any[] = any[]
> = (
response: ResponseType & any,
request: RequestType & any,
response: ResponseType,
request: RequestType,
...args: Args
) => any
5 changes: 3 additions & 2 deletions src/types/RouteEntry.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { IRequest } from './IRequest'
import { RequestHandler } from './RequestHandler'

export type RouteEntry = [
export type RouteEntry<RequestType = IRequest, Args extends any[] = any[]> = [
httpMethod: string,
match: RegExp,
handlers: RequestHandler[],
handlers: RequestHandler<RequestType, Args>[],
path?: string,
]
13 changes: 9 additions & 4 deletions src/types/RouterOptions.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { StatusError } from 'StatusError'
import { ErrorHandler } from './ErrorHandler'
import { IRequest } from './IRequest'
import { IttyRouterOptions } from './IttyRouterOptions'
import { RequestHandler } from './RequestHandler'
import { ResponseHandler } from './ResponseHandler'

export type RouterOptions = {
before?: RequestHandler<any>[]
catch?: ErrorHandler
finally?: ResponseHandler[]
export type RouterOptions<
RequestType = IRequest,
Args extends any[] = [],
> = {
before?: RequestHandler<RequestType, Args>[]
catch?: ErrorHandler<StatusError, RequestType, Args>
finally?: ResponseHandler<any, RequestType, Args>[]
} & IttyRouterOptions
15 changes: 10 additions & 5 deletions src/types/RouterType.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import { StatusError } from 'StatusError'
import { ErrorHandler } from './ErrorHandler'
import { IRequest } from './IRequest'
import { IttyRouterType } from './IttyRouterType'
import { RequestHandler } from './RequestHandler'
import { ResponseHandler } from './ResponseHandler'

export type RouterType<R = IRequest, Args extends any[] = any[], ResponseType = any> = {
before?: RequestHandler<any>[]
catch?: ErrorHandler
finally?: ResponseHandler[]
} & IttyRouterType<R, Args, ResponseType>
export type RouterType<
RequestType = IRequest,
Args extends any[] = any[],
ResponseType = any
> = {
before?: RequestHandler<RequestType, Args>[]
catch?: ErrorHandler<StatusError, RequestType, Args>
finally?: ResponseHandler<any, RequestType, Args>[]
} & IttyRouterType<RequestType, Args, ResponseType>

0 comments on commit ca742e4

Please sign in to comment.