remix-run/remix
 Watch   
 Star   
 Fork   
3 days ago
remix

fetch-router v0.6.0

  • BREAKING CHANGE: Rename

    • resource('...', { routeNames }) to resource('...', { names })
    • resources('...', { routeNames }) to resources('...', { names })
    • formAction('...', { routeNames }) to formAction('...', { names })
    • formAction('...', { submitMethod }) to formAction('...', { 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 and InferRequestHandler types

  • Re-export FormDataParseError, FileUpload, and FileUploadHandler 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

8 days ago
remix

fetch-router v0.5.0

  • Add formData middleware for parsing FormData objects from the request body

    import { 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 and redirect response helpers

    import { 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 a Route object for type-safe redirects:

    let routes = createRoutes({
      home: '/',
    })
    
    let response = redirect(routes.home)

    Note: the route must support GET (or ANY) for redirects and must not have any required params, so the helper can safely construct the redirect URL.

8 days ago
remix

form-data-parser v0.11.0

  • Make options optional in parseFormData signature
  • Export ParseFormDataOptions type
9 days ago
remix

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 to createResource and createResources 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 for createRoutes to public exports

  • Add support for any BodyInit in html(body) response helper

  • Add createFormAction (also exported as formAction for short) for creating route maps with index (GET) and action (POST) routes. This is well-suited to showing a standard HTML <form> and handling its submit action at the same URL.

  • Export RouteHandlers and RouteHandler types

9 days ago
remix

node-fetch-server v0.10.0

  • Fire close and finish listeners only once (#10757)
9 days ago
remix

headers v0.13.0

  • Drop support for TypeScript < 5.7
9 days ago
remix

route-pattern v0.14.0

  • Add Matcher and MatchResult interfaces. These are new public APIs for matching sets of patterns.

  • Add RegExpMatcher and TrieMatcher concrete implementations of the Matcher 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: ... }
10 days ago
remix

fetch-router v0.3.0

  • Add router.map() for registering routes and middleware either one at a time or in bulk

    One 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 and createResources functions for creating resource-based route maps

    import { 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}`)
      },
    })
11 days ago
remix

fetch-router v0.2.0

  • Add router.mount(prefix, router) method for mounting a router at a given pathname prefix in another router

    let 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')
11 days ago
remix

fetch-router v0.1.0

  • Initial release