📝 Table of Contents
Densky is a backend framework based on file-routing and an optimized build step. The build step is the most important feature because it makes the app super fast without complex code. This is expected to be deployed on the edge Deno Deploy
- Deno deploy: Support for Deno Deploy.
- Rust core: All the core code is written in Rust, which makes the app blazing fast.
- File routing: This solves the organization problem without import hell.
- Optimized Router: There's an algorithm to reduce the cost of routing using simple if statements and minimized loops, avoiding complex regex.
- Route Params: The route parameters can be used with
$
at the start of the filename. - 🚧 Websockets: Support websockets with zero configuration and file routing for message topics.
- 🚧 DB ORM: Own ORM with auto-generated endpoints specified on the model.
Initialize the project:
$ densky init
Run in dev mode:
$ densky dev
Production:
$ densky build # Build .densky, the main.ts is always there
$ densky preview
The router's algorithm tries to create the most compact tree. Here's the decision tree of the algorithm:
Super simplified abstract version:
- There's brother on container?
- Expand it, and join to him
- Join as unique son
The result can be visualized with the following graph:
Optimized | Others |
---|---|
There's a significant reduction in nodes that translates to fewer validations, but it has more to offer. The type of validations used is with a simple if statement.
Here's an example of the output code for a simple node:
export default function(req) {
if (req.__accomulator__.path === "route-a") {
// Update the accumulator for next nodes
req.__accumulator__.segments = req.__accumulator__.segments.slice(1);
req.__accumulator__.path = req.__accumulator__.segments.join("/");
// ...
}
}
The route parameters are also supported by the same router. At the tree level, they are treated like any other node, but the compiler changes the validation. Here's an example of the output code for a route parameter node:
const __matcher_serial = [{
raw: "$varname",
isVar: true,
varname: "varname"
}];
const __matcher_start = (/* ... */) => Densky.Runtime.matcherStart(__matcher_serial, /* ... */);
export default function(req) {
if (__matcher_start(req.__accumulator__.segments, new Map(), req.params)) {
// Update the accumulator for next nodes
req.__accumulator__.segments = req.__accumulator__.segments.slice(1);
req.__accumulator__.path = req.__accumulator__.segments.join("/");
// Now can use the param
req.params.get("varname"); // OK
// ...
}
}