xerus v0.0.46
Xerus
A tiny http library for Bun šæļø
Hello, World!
let app = new Xerus()
app.get('/', async (c) => {
c.jsx(
<h1>Hello, World!</h1>
)
})
await app.run(8080)
Dynamic Paths
To declare a dynamic path, use braces {}
app.get('/user/{id}', async (c) => {
let id = c.dyn('id') // access the dynamic id
c.text(id)
})
Query Params
To access a url parameter
app.get('/', async (c) => {
// if we visit /?some_param=xerus, param will equal 'xerus'
// if no param is in the url, it will equal ''
let param = c.param('some_param')
c.text(param)
})
Redirecting
Redirect with ease
app.get('/', async (c) => {
c.redirect('/seeya')
})
Global Context
Access variables across all handlers
let app = new Xerus()
let myGlobalVar = 'yoooooo'
app.global('myvar', myGlobalVar)
app.get('/', async (c) => {
c.text(c.getGlobal('myvar')) // returns 'yoooooo'
})
Form Data
Access form data
app.post("/", async (c) => {
let data = await c.form();
let username = data.get('username')
c.text(username)
});
Trigger the endpoint
curl -X POST http://localhost:8080/ -d "username=your_username"
Request Timeouts
Xerus can handle network timeouts using a provided middleware. The default timeout duration is 5000 milliseconds.
Adjusting the timeout duration to 3000 milliseconds and use the middleware on all routes
app.setTimeoutDuration(3000);
app.use('*', timeout)
Logging
Xerus also provides a logger
app.use('*', logger)
Custom Middleware
Here is the skeleton of a custom middleware. This middleware will log 'hello' before our handler is invoked and 'world' after our handler is invoked.
export async function customMiddleware(c, next) {
console.log('hello')
await next();
console.log('world')
}
Using Middleware
Xerus uses 3 types of middleware and they execute in the following order
- Global Middleware
- Prefix Middleware
- Route-Specific Middleware
Global Middleware
To apply your middleware globally
app.use('*', customMiddleware)
Prefix Middleware
To apply your middleware to all routes starting with '/user'
app.use('/user', customMiddleware)
Route-Specific Middleware
To apply your middleware to a single route
app.get('/', async (c) => {
c.text('Hello, World!')
}, customMiddleware) // <===== chain on your middleware here
File Based Route
Xerus comes with a file-based router, enabling your directory structure to generate your routes, thus reducing code for your application.
const app = new Xerus();
const fbr = new FileBasedRouter(app);
let err = await fbr.mount();
if (err) {
// handle the err
}
await app.run(8080);
App Directory
By defualt, Xerus will check for your routes in ./app
. As of now, you cannot define a custom directory for your routes.
File Based Route - Hello World
In the root of your project, use the following command to create the files needed for a hello, world
example.
If you plan to use JSX
as your templating solution, run:
mkdir app; cd app; touch +page.tsx
If you are going to use an alternative templating solution, run:
mkdir app; cd app; touch +page.ts
Both .ts
and .tsx
files are supported. As of now, .js
and .jsx
are not supported.
In ./app/+page.tsx
add the following code (you will also need to import XerusRoute
and XerusContext
from xerus
):
import React from "react";
export const get: XerusRoute = new XerusRoute(async (c: XerusContext) => {
c.jsx(<h1>Hello, World</h1>);
});
The above code will basically be interpreted as:
app.get("/", async (c: XerusContext) => {
c.jsx(<h1>Hello, World</h1>);
});
Using a different http method
If you want to use a different http method like POST
just export a const named post
instead of get
export const post: XerusRoute = new XerusRoute(async (c: XerusContext) => {
c.jsx(<h1>Hello, Post World</h1>);
});
Dynamic File Based Endpoints
You can make a file based endpoint dynamic by doing the following.
Create a few directories inside of ./app
mkdir app/user/{id}; cd app/user/{id}; touch +page.tsx
Now in /app/user/{id}/+page.tsx
export const get: XerusRoute = new XerusRoute(async (c: XerusContext) => {
c.jsx(<h1>{c.dyn("id")}</h1>);
});
The above code will and the following code have the same result
app.get('/user/{id}', async (c) => {
c.jsx(<h1>{c.dyn("id")}</h1>);
})
Using middleware inside of file-based routes
Remember, we have global middleware, prefix middleware, and route-specific middleware. All can be utilized in our file based routing system.
- Global Middleware
All global middleware will be applied to the application prior to mounting the file based router. For example:
const app: Xerus = new Xerus();
app.use("*", timeout, logger); // setup global middleware PRIOR to mounting the router
const router = new FileBasedRouter(app);
let err = await router.mount();
if (err) {
console.log(err);
}
await app.run(8080);
- Prefix Middleware
Prefix middleware is established inside of +page.tsx
files by exporting a const named use
.
The following example will make all routes which start with /about
apply the logger middleware.
Keep in mind, you need to actually import the logger to use it.
/app/about/+page.tsx
export const use: XerusMiddleware[] = [logger]
export const get: XerusRoute = new XerusRoute(async (c: XerusContext) => {
c.jsx(<h1>About me!</h1>);
});
- Route Specific Middleware
Route specific middleware can be simply chained onto the end of a XerusRoute
like so.
export async function hello(c: XerusContext, next: XerusHandler) {
c.text("hello from middleware");
await next(c);
}
export const get: XerusRoute = new XerusRoute(async (c: XerusContext) => {
c.jsx(<h1>You wont get to see me because the middleware will exit the endpoint early!</h1>);
}, hello); // <========== we chain our route-specific middleware on here
Markdown Content Ease of Loading
Xerus has taken into account you may want to use markdown content in your application.
Xerus uses Marked under to hood.
As of now, All I've done is wrapped the basic usage of marked
in a function call like so:
app.get('/', async (c) => {
let html = await c.md("./path/to/markdown/content.md")
c.html(html)
})
Here is the real kicker, you can pre-load your markdown content in the FileBasedRouter
by using +content.md
files.
Let's assuming your file-based routes are located in the default ./app
directory.
./app
āāā +page.tsx
āāā +content.md
With the above example, the markdown content inside of +content.md
is tranformed into html during the route-building process.
The markdown content can then be accessed using c.md()
with no args passed to the function. Like so:
export const get: XerusRoute = new XerusRoute(async (c: XerusContext) => {
let mdContent = await c.md(); // <===== no arg passed
c.html(mdContent);
});
This makes it very easy to utilize markdown content in your application without having to worry about file paths.
Just place a +content.md
right next to your +page.tsx
and you're good to go.
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
10 months ago
10 months ago
10 months ago
10 months ago
9 months ago
9 months ago
9 months ago
9 months ago
10 months ago
10 months ago
9 months ago
9 months ago
9 months ago
9 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
1 year ago