Routing

Basic routing concept

Dotpress provides you with a defineRoute function to declare your endpoints. Let's see the example below:

defineRoute({
  path: '/articles',
  method: 'get', // Optional, default: get. Allowed values: get | post | put | delete
  handler: async ({ req, res }) => {
    // It's your main handler function.
    // Handler context receives req and res: Request and Response objects from Express.

    // returned Value will be sent to client as JSON by default
    return [
      { title: 'Intro', href: '/intro' },
      { title: 'Quickstart', href: '/quickstart' },
    ]
  }
})

Splitting your routes

Of course, you will not have all of your routes defined in a single index.ts file. You will probably split them in multiple files, organized by entity types or by features.

When you are calling defineRoute, your route is automatically registered in a router registry. Therefore, unlike standard express application, you don't need to import a router or whatsoever.

However, you still need to make sure to import all files declaring routes before starting your app.

Let's consider the following project structure:

/src
  /handlers
    auth.ts
    articles.ts
    authors.ts
    members.ts
  routes.ts
  index.ts

Your setup will look like:

// index.ts
import { createApp, defineRoute } from 'dotpress'
import './routes'

const app = await createApp({
  // Optional app options here...
})

app.listen(3000, () => {
  console.log('Server listening on port 3000')
})

// routes.ts
import './handlers/auth.ts'
import './handlers/articles.ts'
import './handlers/authors.ts'
import './handlers/members.ts'

Route Groups

Dotpress allows you to group your routes in order to apply common prefix and/or middlewares. It can be useful

Dotpress allows you to group routes using a shared URL prefix and common middlewares. This is especially useful to organize your application by domain (e.g. /admin, /auth, /billing) or to version your API (e.g. /v1, /v2).

Basic usage:

const adminGroup = createRouteGroup('/admin', [requireAdminRole]);

adminGroup.defineRoute({
  method: 'get',
  path: '/users',
  handler: async () => [{ id: 1, name: 'Alice' }]
});

This will create a route accessible at /admin/users with the requireAdminRole middleware applied.

You can also define nested groups using group.createGroup():

const adminGroup = createRouteGroup('/admin', [requireAdminRole]);
const billingGroup = adminGroup.createGroup('/billing', [requireBillingAccess])

billingGroup.defineRoute({
  method: 'post',
  path: '/invoices',
  handler: async () => ({ created: true })
});

This will result in a route: POST /admin/billing/invoices with middlewares: [requireAdminRole, requireBillingAccess].