The building blocks
Everything starts from somewhere,
- Routes are the entry-point for your application, and they are defined through page components or middleware.
- The
Requestobject is available through thejamrock:connmodule, it provides most stuff for common chores. - The
Responseis calculated by the framework, but you can also provide your own (this is what theredirect()helper does).
Routes
Files ending with +page.html will be used to declare routes.
They're transformed using the following rules:
| Filename | Route |
|---|---|
index+page.html |
/ |
login+page.html |
/login |
(lang).blog+page.html |
/:lang?/blog |
hello.[name]+page.html |
/hello/:name |
posts/$post_id+page.html |
/posts/:post_id |
_site/sitemap[.xml]+page.html |
/sitemap.xml |
_site/articles/[...slug]+page.html |
/articles/*slug |
Path parameters can be declared as
$paramor[param], optional parameters use parentheses (e.g.(param)), and catch-all parameters as[...param].Segments are taken from nested folders or
.separators, any of them starting with_are just ignored from final paths.File extensions are preserved by using the
[.ext]syntax.
Handlers
Pages can declare its own route handlers through the export default object.
They can be set as boolean, to enable some methods, or functions to handle the whole request, e.g.
Example of module handlers
<script>
export default {
// middleware to invoke, see below
use: ['csrf'],
// allow for POST requests, no action
POST: true,
// action for DELETE requests
DELETE() {
// do something
},
// route-handlers for this component
['GET /:article_id']({ article_id }) {
console.log({ article_id });
},
catch(e) {
// handle errors
},
finally() {
// this always run
},
someAction() {
// used on form actions
},
};
</script>By default all pages will respond to GET requests, depending on their handlers they can respond to other methods.
If you don't want to execute a page through the GET method just use GET: false to disable it.
Handlers using the syntax
['METHOD /path/with/:params']are also registered as routes for the page, all declared parameters will be passed as arguments.If you declare a
catchorfinallyhandler they'll be called as result of evaluating the requested handlers.Additional handlers may be invoked if they match a requested action, e.g.
<form action="?/someAction" method="POST">.
Middleware
In some cases you may want to run some code prior executing your handlers, to enable such behavior you must declare a use property.
This is how you can define some middleware functions in a +server.mjs script, e.g.
Example of middleware module
export function http(conn) {
// `http` handler executes on every request!
}
export function csrf(conn) {
conn.req.csrfProtect();
}
export default {
use: ['http'],
['GET /some/:stuff']({ params }) {
console.log('Got', params.stuff);
},
catch(e, conn) {
// do something
},
finally(response) {
return response;
}
}Exported functions are registered as middleware by name,
these +server.mjs scripts are loaded automatically by the framework:
- Routes declared on the
export defaultobject are evaluated if they match, here is where you need to place api-routes as they don't require a page to exist. - The
+server.mjsfile can be placed at any level within the pages directory, following the same strategy as+layout.htmlor+error.htmlresolution. - These functions will receive the
jamrock:connobject as their first argument, any other values will be passed as the second argument, etc. Extra options should be set like this, e.g.use: [['csrf', ...]]
Declared catch and finally handlers on this object will receive
the error and response, with the jamrock:conn object as the last argument.
Make sure you return the given or modified
responseargument in yourfinallyhandler, the framework relies on this value to build the final response.Avoid errors within
catchhandlers, otherwise they might not be handled et all!
Request
To access the request you'll need the jamrock:conn module:
Example of request handling
<script>
import { method, headers, redirect } from 'jamrock:conn';
if (method === 'GET' && !headers.has('token')) {
redirect('/login');
}
</script>
<h1>It works.</h1>Requests to page components will always render something,
however redirect calls can stop any further rendering.
This is because setting a response on the
connobject tell the framework to stop its execution pipeline.
Response
Page components will produce an AST that can be rendered as HTML or sent as JSON.
The framework will handle the response for you in such cases.
Any value returned from actions, handlers or middleware will be used to produce a response.