Skip to content

Quick spin-up

In this article, we'll introduce some of the basics for URN Framework.

If you just want to learn how to use this framework then click here

Reading time before u reach #spin-up-a-new-project: EST > 2hrs

Purpose

So, why do this framework even existed, you may wanna ask.

ElysiaJS is great, but not such friendly for a large project.

You gotta manually load lots of things.

To do this, you got 2 options

  1. Make a super long method chaining

This is accecpted for some medium or small projects, but when your application got hundreds of confs, that won't be nice.

  1. Separate routing groups into different instance then use these instance as plugins in the main Instance

While this is acceptable, by doing so, you got to creating each instance separately, and this could lead to some serious problems, like a slow development and conflicts.

And that's where the URN framework kicks in

URN Framework allows you to do Declarative Route Loading (DRL).

In simple words, you code gateway, schemas, routing rules and handlers, put 'em into an Object, combine these Objects into an Array, then call a method, done, your application is ready-to-go, sounds like magic, doesn't it?

Besides, URN framework is also an SDK, which means you got all your needs for backend development, which is good for efficiency.

Stages

We'll talk about the structure of URN Framework in this chapter.

This Framework is built upon ElysiaJS, and that's why the core is still an Elysia Instance.

In short, you createInstance(), loadInstance(), igniteInstance()

Create Instance

Here, you can init the Elysia Instance with some 3rd-party plugins if you wish, or just do some small tricks to the Instance.

I need to metion that you must do it with method chaining like this

typescript
const urn = new URN()
const instance = urn.createInstance().use(ip()).use(swagger())
urn.instance = instance // store the instance back

Btw, as you can see we stored the modified instance back into the urn obj, and that's because we need it for the following loading and igniting stage.

also, you can extract the type of instance['decorator'] for future usage, like when coding your handlers

typescript
export type ROPT = MRequestOPT<typeof instance['decorator']>
export const postEchoHandler = (contents: ROPT) => {}

load Instance

Next, we need to create an Array of Modules (Module is a concept, a group of your schemas, handlers and routes)

typescript
const Modules: Module[] = [
    ServerRoot // Imported from somewhere else
]

/**
 * @param modules An array of modules
 * @param conflictCheck You wanna check for conflicted routes?
 * @param gateway A function that acts as gateway
 */
urn.instnace = urn.loadInstance(Modules, false, gateway)
// Must Store the instance back

ignite Instance

In this stage, we ignite the engine, and take off!

typescript
const serverConf: IgniteConf = {
    hostname: '127.0.0.1',
    port: 9901
}

urn.igniteInstance(serverConf)

Tips: If you wanna ignite a differenet instance, just call it like this

typescript
const serverConf: IgniteConf = {
    hostname: '127.0.0.1',
    port: 9901
}
/**
 * 
 * @param conf Ignite Configuration
 * @param callback ListenCallback
 * @param instance Instance required to ignite, can be undefined
 * 
 */
urn.igniteInstance(serverConf, undefined, meow)

Module

A complete module is consisted of schemas, handlers and declarative

Schemas

To validate data out of to box to ensure that the data is in the correct format.

Validation in elysiajs

An example of Schemas in URN framework

Convert schemas into typescript types for intellsense/ Read .2

Handlers

A function that responds to the request for each route.

Handlers in elysiajs

An example of Handlers in URN framework

Declarative

Confs for Declarative Route Loading (DRL)

An example of declarative

Routing

The Model URN Framework utilizes a single gateway for managing access to handlers.

Please, take a look on this diagram

routing.svg

*Handler is treated as a callback func in gateway

*Gateway can pass custom parameters to handlers, you can catch them or ignore them as you wished

Type

Ref -> here

There're two typing system at least

  1. for contents parameter of the handler
ts
MRequestOPT<typeof instance['decorator']>
  1. types that are converted from schmeas into typescript types
ts
const body = contents.body as Sch2Ts<typeof postEchoSch>

Spin-up a new project

Setup bun.sh

Ref to bun.sh document

Bootstrap a new URN project

sh
bunx ashes-urn-spinup project_name

And...

You're done! Please read the comments inside this template to learn how this thing works.

To run development server, do this

ts
bun run dev

Don't forget we got db interfaces and a bunch of gadgets for y'all, check "Database" and "Utils" at the navbar for more.