fetch-router v0.6.0
-
BREAKING CHANGE: Rename
-
resource('...', { routeNames })
toresource('...', { names })
-
resources('...', { routeNames })
toresources('...', { names })
-
formAction('...', { routeNames })
toformAction('...', { names })
-
formAction('...', { submitMethod })
toformAction('...', { formMethod })
-
-
Integrate form data handling directly into the router, along with support for method override and file uploads. The
methodOverride
field overrides the request method used for matching with the value submitted in the request body. This makes it possible to use HTML forms to simulate RESTful API request methods like PUT and DELETE.let router = createRouter({ // Options for parsing form data, or `false` to disable parseFormData: { maxFiles: 5, // Maximum number of files that can be uploaded in a single request maxFileSize: 10 * 1024 * 1024, // 10MB maximum size of each file maxHeaderSize: 1024 * 1024, // 1MB maximum size of the header }, // A function that handles file uploads. It receives a `FileUpload` object and may return any value that is valid in a `FormData` object uploadHandler(file: FileUpload) { // save the file to disk/storage... return '/uploads/file.jpg' }, // The name of the form field to check for method override, or `false` to disable methodOverride: '_method', })
-
Export
InferRouteHandler
andInferRequestHandler
types -
Re-export
FormDataParseError
,FileUpload
, andFileUploadHandler
from@remix-run/form-data-parser
-
Fix an issue where per-route middleware was not being applied to a route handler nested inside a route map with its own middleware
fetch-router v0.5.0
-
Add
formData
middleware for parsingFormData
objects from the request bodyimport { formData } from '@remix-run/fetch-router/form-data-middleware' let router = createRouter() router.use(formData()) router.map('/', ({ formData, files }) => { console.log(formData) // FormData from the request body console.log(files) // Record<string, File> from the request body return new Response('Home') })
-
Add
storage.has(key)
for checking if a value is stored for a given key -
Add
next(moreContext)
API for passing additional context to the next middleware or handler in the chain -
Move
logger
middleware to@remix-run/fetch-router/logger-middleware
export -
Add
json
andredirect
response helpersimport { json, redirect, createRouter } from '@remix-run/fetch-router' let router = createRouter() router.map('/api', () => { return json({ message: 'Hello, world!' }) }) router.map('/*path/', ({ params }) => { // Strip all trailing slashes from URL paths return redirect(`/${params.path}`, 301) })
redirect
also accepts aRoute
object for type-safe redirects:let routes = createRoutes({ home: '/', }) let response = redirect(routes.home)
Note: the route must support
GET
(orANY
) for redirects and must not have any required params, so the helper can safely construct the redirect URL.
form-data-parser v0.11.0
- Make
options
optional inparseFormData
signature - Export
ParseFormDataOptions
type
fetch-router v0.4.0
-
BREAKING CHANGE: Remove "middleware as an optional 2nd arg" from all router methods and introduced support for defining middleware inline in route handler definitions. This greatly reduces the number of overloads required in the router API and also provides a means whereby middleware may be coupled to request handler definitions
// before router.map('/', [middleware], () => { return new Response('Home') }) // after router.map('/', { use: [middleware], handler(ctx) { return new Response('Home') }, })
-
Add
routeNames
option tocreateResource
andcreateResources
for customizing the names of the resource routes. This is a map of the default route name to a custom name.let books = createResources('books', { routeNames: { index: 'list', show: 'view' }, }) books.list // Route<'GET', '/books'> books.view // Route<'GET', '/books/:id'>
-
Add
route
shorthand forcreateRoutes
to public exports -
Add support for any
BodyInit
inhtml(body)
response helper -
Add
createFormAction
(also exported asformAction
for short) for creating route maps withindex
(GET
) andaction
(POST
) routes. This is well-suited to showing a standard HTML<form>
and handling its submit action at the same URL. -
Export
RouteHandlers
andRouteHandler
types
node-fetch-server v0.10.0
- Fire
close
andfinish
listeners only once (#10757)
headers v0.13.0
- Drop support for TypeScript < 5.7
route-pattern v0.14.0
-
Add
Matcher
andMatchResult
interfaces. These are new public APIs for matching sets of patterns. -
Add
RegExpMatcher
andTrieMatcher
concrete implementations of theMatcher
interface-
RegExpMatcher
is a simple array-based matcher that compiles route patterns to regular expressions. -
TrieMatcher
is a trie-based matcher optimized for large route sets and long-running server applications.
import { TrieMatcher } from '@remix-run/route-pattern' let matcher = new TrieMatcher<{ name: string }>() matcher.add('users/:id', { name: 'user' }) matcher.add('posts/:id', { name: 'post' }) let match = matcher.match('https://example.com/users/123') // { data: { name: 'user' }, params: { id: '123' }, url: ... }
-
fetch-router v0.3.0
-
Add
router.map()
for registering routes and middleware either one at a time or in bulkOne at a time:
let router = createRouter() router.map('/', () => new Response('Home')) router.map('/blog', () => new Response('Blog'))
In bulk:
let routes = createRoutes({ home: '/', blog: '/blog', }) let router = createRouter() router.map(routes, { home() { return new Response('Home') }, blog() { return new Response('Blog') }, })
-
Add
createResource
andcreateResources
functions for creating resource-based route mapsimport { resource, resources, createRoutes } from '@remix-run/fetch-router' let routes = createRoutes({ home: '/', books: resources('books'), // Plural resources profile: resource('profile'), // Singleton resource }) let router = createRouter() // Plural resources router.map(routes.books, { // GET /books index() { return new Response('Books Index') }, // POST /books create() { return new Response('Book Created', { status: 201 }) }, // GET /books/new new() { return new Response('New Book') }, // GET /books/:id show({ params }) { return new Response(`Book ${params.id}`) }, // GET /books/:id/edit edit({ params }) { return new Response(`Edit Book ${params.id}`) }, // PUT /books/:id update({ params }) { return new Response(`Updated Book ${params.id}`) }, // DELETE /books/:id destroy({ params }) { return new Response(`Destroyed Book ${params.id}`) }, }) // Singleton resource router.map(routes.profile, { // GET /profile/:id show({ params }) { return new Response(`Profile ${params.id}`) }, // GET /profile/new new() { return new Response('New Profile') }, // POST /profile create() { return new Response('Profile Created', { status: 201 }) }, // GET /profile/:id/edit edit({ params }) { return new Response(`Edit Profile ${params.id}`) }, // PUT /profile/:id update({ params }) { return new Response(`Updated Profile ${params.id}`) }, // DELETE /profile/:id destroy({ params }) { return new Response(`Destroyed Profile ${params.id}`) }, })
fetch-router v0.2.0
-
Add
router.mount(prefix, router)
method for mounting a router at a given pathname prefix in another routerlet apiRouter = createRouter() apiRouter.get('/', () => new Response('API')) let router = createRouter() router.mount('/api', apiRouter) let response = await router.fetch('https://remix.run/api') assert.equal(response.status, 200) assert.equal(await response.text(), 'API')
fetch-router v0.1.0
- Initial release