Stone.jsDocs
Paradigm

Routing

Matching & precedence

When a cause arrives, the router finds the one route that answers it. Knowing how that choice is made, and how to make it unambiguous, is what keeps a growing route table predictable.

#How a route is chosen

Matching considers, in effect: the HTTP method, then the path pattern, with more specific patterns preferred over catch-alls, then any constraints (rules) that must hold, and finally host (domain) and scheme (protocol) if declared. A route that fails any of these is skipped, and the next candidate is tried.

CriterionTypeDescription
methodexactThe verb must match (or the route must be @Any / list the method).
path specificitystatic > param > catch-allA literal segment beats :param, which beats :rest*.
rulesmust passA parameter constraint that fails removes the route from contention.
domain / protocoloptional filterRestrict a route to a host or scheme.
strictbooleanWhen on, trailing-slash and case differences stop a match.

#Keeping the table unambiguous

Order-independence is the goal: two routes should never both be able to match the same request. Use constraints to separate look-alike paths, and reserve catch-alls for genuine fallbacks.

app/routes.tsts
@Get('/tasks/:id', { rules: { id: /\d+/ } })   // /tasks/42
@Get('/tasks/:slug')                            // /tasks/ship-the-docs
// The constraint keeps these two from ever competing for the same URL.

#Domain & subdomain routing

A route can be scoped to a host, and the host can itself carry parameters. A subdomain parameter turns multi-tenancy into routing: capture the tenant from the host and read it on the event like any other value.

app/routes.tsts
@Get('/', { domain: 'admin.example.com' })          // only on that exact host

@EventHandler('/', { domain: '{tenant}.example.com' })   // capture a subdomain
export class TenantController {
  @Get('/dashboard')
  dashboard (event: IncomingHttpEvent) {
    const tenant = event.get<string>('tenant')      // from the host, not the path
    return this.tenants.dashboard(tenant)
  }
}

Host parameters take constraints too (rules), and a whole group can share a domain, so an admin subdomain and a tenant subdomain are two groups over the same routes.

#Scheme

app/routes.tsts
@Post('/hook', { protocol: 'https' })              // only over https

Stone.js

Your app exists in every runtime. Until you run it.

An open-source project by Stone Foundation
Created by Mr. Stone (Evens Pierre)