Custom Adapter
Overview
Custom adapters allow you to extend the functionality of the SDK by adding an ability to interact with certain environments. This guide will walk you through the process of creating a custom adapter.
The adapter is a function that consists of so-called hooks. Each hook is a function that is called at a certain point in the lifecycle of the adapter.
Creating a Custom Adapter
Storona exports all of the essential types and functions via storona/adapter
scope.
To create a custom adapter, you need to call createAdapter
function and pass an object with hooks as an argument:
import { createAdapter } from "storona/adapter";
export const adapter = createAdapter((instance, opts = {}) => {
// instance - instance of the adapter e.g. express app
// opts - options passed to the adapter
return {
// Version of Storona API, it is always "1.0.0"
version: "1.0.0",
on: {
// Called once adapter is initialized by storona itself
init: () => {},
// Parse route path structure (route + method)
route: (structure) => structure,
// Registering a route by the provided instance
register: (importData) => {},
// Called once all routes were registered
ready: (status) => {},
},
};
});
The createAdapter
function returns an object with hooks that will be called at a certain point in the lifecycle of the adapter.
TIP
It is safe to throw exceptions in the hooks, they will be caught by Storona and logged to the console.
On Init
The init
hook is called once the adapter is initialized by Storona itself:
init: () => {
// ...
},
On Route
The route
hook is called to parse/modify the route path structure (route + method):
route: (structure) => {
// Do the validation here
// Always return the modified structure
return structure;
},
On Register
The register
hook is called to register a route by the provided instance:
register: (importData) => {
// ...
console.log(importData.route, importData.method, importData.handler);
// To access all the imports, use importData.data object
},
On Ready
The ready
hook is called once all routes were registered. It receives a status array with register/unregistered routes:
ready: (status) => {
// ...
},
For more information regarding status array, see returned value of createRouter
Defining Types
To define types for the adapter, you can use generic types:
import { createAdapter } from "storona/adapter";
import type { Express } from "express";
// Handler
type H = () => void;
// Methods
type M = "get" | "post" | "put" | "delete";
// Route
type R = string | RegExp;
// Instance
type I = Express;
// Options
type O = {
prefix?: string;
};
export const adapter = createAdapter<H, M, R, I, O>((instance, opts = {}) => {
// ...
});
As you can see, you can define types for handler, method, route, instance, and options. These types will be used in various parts of the adapter.
Defining a Signature Function
You're free to define a signature function however you want, except it should be named define
for more consistent usage:
// Handler
type H = () => void;
export function define(cb: H): H {
return cb;
}
Signature function should return the handler type. It is used to define the handler in the route.
Publishing Adapter Package
If you're willing to publish the adapter as a package, you need to export 2 functions - adapter & define:
import { createAdapter } from "storona/adapter";
export const adapter = createAdapter((instance, opts = {}) => {
// ...
});
type H = () => void;
export function define(cb: H): H {
return cb;
}
After that add storona
as a peer dependency in the package.json
:
{
"peerDependencies": {
"storona": "^1.0.0"
}
}
This is essentially all you need to publish the adapter as a package.
Using the Custom Adapter
To use a custom adapter, you need to pass it to adapter
field:
import { createRouter } from "storona";
import { adapter } from "./adapter";
// Instance of the adapter
const app = {};
await createRouter(app, {
directory: "routes",
adapter: adapter({
// ...opts here
}),
});
import { define } from "./adapter";
export default define(() => {});
Example
For more detailed information, see the implementation of Express adapter in the official repository.