Skip to content

Releases: kwhitley/itty-router

Release v5.0.17

28 Apr 15:30
Compare
Choose a tag to compare

Release v5.0.16

20 Apr 04:54
Compare
Choose a tag to compare

Release v5.0.13

14 Apr 19:49
Compare
Choose a tag to compare

see CHANGELOG for notes

v5.0.4

29 Mar 20:57
Compare
Choose a tag to compare

itty-router v5

This represents a large shift in the ecosystem. While mostly backwards compatible, a few small tweaks will be needed to swap in the new Router or AutoRouter.

See https://itty.dev/itty-router/migrations/v4-v5 for migration guide and details.

Changes in v5

  • BREAKING router.fetch replaces router.handle to enable cleaner exports.
  • BREAKING createCors() has been replaced with the improved cors().
  • BREAKING RouteHandler (type) has been replaced with RequestHandler.
  • added previous Router is now preserved as IttyRouter.
  • added new Router (backwards-compatible) adds support for stages.
  • added new batteries-included AutoRouter adds default settings to Router.
  • added TypeScript support has been improved in all of the routers, allowing router-level generics AND route-level generic overrides in the same router.

v4.0.0

26 May 19:49
Compare
Choose a tag to compare

This is an extensive v4.x update, bringing a series of quality of life additions, as well as a potentially breaking change for TypeScript users:

!Breaking Changes!

  • TYPES HAVE CHANGED FOR THE ROUTER. The core TypeScript and exposed types for the Router itself have been completely retooled to allow much better, strong type support throughout your routes. Previously this required complex custom setups to work around the lack of internal typing. Now it's included out of the box, but you'll need to follow the instructions.

    This was not an easy change to commit to, but was long overdue. The solution finally settled on allows for a more flexible (yet boiler-platey) approach, or a more rigid one... but allows for many more scenarios than the previous types did.

Other Changes

  • added: nearly all the extras from itty-router-extras have moved in-house to the core library. This library will be deprecated as a result.
  • added: createCors from itty-cors has moved into the core library as well
  • feature: withParams middleware (previously from itty-router-extras) is now possible to use as upstream middleware (e.g. globally) to reduce boilerplate. Previously this was not possible.

Official Documentation Site

We've just launched a itty.dev to house documentation for all the itty projects going forward. Previously, we auto-generated docs from the README, but clearly the documentation needs far outweighed what could feasibly fit within a single long README. See the itty-router section for more details!

See the migration guide for complete details.

v2.4.0

10 Aug 05:49
Compare
Choose a tag to compare

Notable Changes

  • preserve existing signature (no second param) to matching any existing introspection schemes - maybe cost a few characters, but it's a bit more future-proof/robust to potential future options we add.
  • Router options are now:
    • base?: string - optional base path
    • routes?: any[] - optional array of routes (for introspection or preloading with advanced regex)
    • unrelated: adds a bit of added interface for the internal Request definition to address #47
    • unrelated: export TS interfaces to address #38
    • thanks to the @taralx refactor, we can now support preloading routes, which means those rare edge cases of crazy regex (previously not possible) requirements, can now be force-fed into the router (at config stage, or even after... also thanks to the more exposed router.routes array. Pretty sick!

Example of manual loading routes:

// EXAMPLE 1 mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
it('allows preloading advanced routes', async () => {
  const basicHandler = jest.fn(req => req.params)
  const customHandler = jest.fn(req => req.params)

  const router = Router({
                  routes: [
                    [ 'GET', /^\/test\.(?<x>[^/]+)\/*$/, [basicHandler] ],
                    [ 'GET', /^\/custom-(?<custom>\d{2,4})$/, [customHandler] ], // match 2 to 4 digits only
                  ]
                })

  await router.handle(buildRequest({ path: '/test.a.b' }))
  expect(basicHandler).toHaveReturnedWith({ x: 'a.b' })

  await router.handle(buildRequest({ path: '/custom-12345' }))
  expect(customHandler).not.toHaveBeenCalled() // custom route mismatch

  await router.handle(buildRequest({ path: '/custom-123' }))
  expect(customHandler).toHaveReturnedWith({ custom: '123' }) // custom route hit
})


// EXAMPLE 2 mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
it('allows loading advanced routes after config', async () => {
  const handler = jest.fn(req => req.params)

  const router = Router()

  // allows manual loading (after config)
  router.routes.push([ 'GET', /^\/custom2-(?<custom>\w\d{3})$/, [handler] ])

  await router.handle(buildRequest({ path: '/custom2-a456' }))
  expect(handler).toHaveReturnedWith({ custom: 'a456' }) // custom route hit
})

DISCUSSION: If we change r to routes, and prevent the prebuild.js from mangling it, the filesize does grow (405b --> 409b), but so does the legibility around this weird introspection. Thoughts? I'm all for absolute minimum filesize, but... legibility. Torn. Don't think we would have to count the decision on this one as a breaking change (if we opt for "routes"), because the existing pattern isn't documented, and is hopefully only used in debugging patterns at most. Regardless of the path chosen here, documentation will be added to disclose this functionality.

UPDATE: unless there's strong objection, I'm opting for readability over ultimate filesize... router.routes it is

Filesize Comparison (pretty sure this includes the type declaration, so appears artificially inflated a bit)

v2.3.9

30 May 05:32
Compare
Choose a tag to compare
released v2.3.9 - developer QOL fixes <3

v2.1.9

06 Mar 01:55
Compare
Choose a tag to compare

Migrating from 1.x to 2.x

TLDR; Most people will not be affected at all and can upgrade without issue

In 2.x, itty changed the handling of the *all channel from executing before all other methods (effectively an upstream catch-all method), to handling in-order like all other routes, just bypassing the method match (therefore matching any method type). While this could technically be considered a fix, the behavior COULD have been planned around intentionally in the previous release, thus the need for a breaking change/major release.

The following example demonstrates the changes in the all channel execution:

v1.x

router
  .all('*', middleware) // applied before
  .get('/foo', () => new Response('middleware is applied'))

// is equivalent to this "backwards" example, because the "all" is executed first

router
  .get('/foo', () => new Response('middleware is applied'))
  .all('*', middleware) // applied before, despite being registered afterwards

// leading to this weird behavior... where a final "catch-all" will in fact intercept all previous routes...

router
  .all('*', middleware) // still applies first...
  .get('/foo', () => new Response('This route will NEVER match... RIP.'))
  .all('*', () => new Response('Not found', { status: 404 })) // will catch everything before the previous line

v2.x

router
  .all('*', middleware) // still applies first...
  .get('/foo', () => new Response('This route WILL properly match!  woohoo!... RIP'))
  .all('*', () => new Response('Not found', { status: 404 })) // will only catch if no previous match... as expected.

v1.1.0

29 May 04:57
Compare
Choose a tag to compare

Changelog

Features

  • Added single config option to Router({ base: '/some/path' }) for route prefixing
  • Verified wildcards work in the middle of path (e.g. /foo/*/end matches /foo/bar/baz/end)

Fixes

  • trailing wildcards (often used in middleware or for sub routers) now properly routes without requiring trailing slash (e.g. /foo/* should match /foo)