serverstruct
Version:
Type safe and modular servers with H3
237 lines (236 loc) • 7.33 kB
text/typescript
import * as h30 from "h3";
import { EventHandlerObject, EventHandlerRequest, H3, H3Event, Middleware, serve, serve as serve$1 } from "h3";
import { Box, Constructor } from "getbox";
//#region src/index.d.ts
type Server = ReturnType<typeof serve$1>;
type ServeOptions = Parameters<typeof serve$1>[1];
type MaybePromise<T = unknown> = T | Promise<T>;
/**
* Creates an H3 application.
*
* @param setup - Function that configures the app. Receives a fresh H3 instance
* and Box instance. Can add routes to the provided app, or create
* and return a new H3 instance.
* @param box - Optional Box instance. If not provided, creates a new one.
* @returns H3 instance.
*
* @example
* ```typescript
* import { application, serve } from "serverstruct";
*
* const app = application((app) => {
* app.get("/", () => "Hello world!");
* });
*
* serve(app, { port: 3000 });
* ```
*
* @example With dependency injection
* ```typescript
* import { application, serve } from "serverstruct";
*
* const app = application((app, box) => {
* app.get("/ping", () => "pong");
* app.mount("/users", box.get(usersController));
* });
*
* serve(app, { port: 3000 });
* ```
*/
declare function application(setup: (app: H3, box: Box) => H3 | void, box?: Box): H3;
/**
* Creates an H3 app constructor.
*
* @param setup - Function that configures the app.
* @returns A Constructor that produces an H3 app. Not cached by Box.
*
* @example
* ```typescript
* import { application, controller } from "serverstruct";
*
* class Database {
* getUsers() { return ["Alice", "Bob"]; }
* }
*
* // Define a controller
* const usersController = controller((app, box) => {
* const db = box.get(Database);
* app.get("/", () => db.getUsers());
* });
*
* // Use it in your app
* const app = application((app, box) => {
* app.mount("/users", box.get(usersController));
* });
* ```
*/
declare function controller(setup: (app: H3, box: Box) => H3 | void): Constructor<H3>;
/**
* Creates a handler constructor.
*
* @param setup - Handler function that receives the event and Box instance.
* @returns A Constructor that produces an H3 handler. Not cached by Box.
*
* @example
* ```typescript
* import { application, handler } from "serverstruct";
*
* class UserService {
* getUser(id: string) { return { id, name: "Alice" }; }
* }
*
* // Define a handler
* const getUserHandler = handler((event, box) => {
* const userService = box.get(UserService);
* const id = event.context.params?.id;
* return userService.getUser(id);
* });
*
* // Use it in your app
* const app = application((app, box) => {
* app.get("/users/:id", box.get(getUserHandler));
* });
* ```
*/
declare function handler<Res = unknown, Req extends EventHandlerRequest = EventHandlerRequest>(setup: (event: H3Event<Req>, box: Box) => Res): Constructor<h30.EventHandlerWithFetch<Req, Res>>;
/**
* Creates an event handler constructor from a setup function.
*
* @param setup - Function that receives Box instance and returns an event handler object.
* @returns A Constructor that produces an H3 event handler. Not cached by Box.
*
* @example
* ```typescript
* import { application, eventHandler } from "serverstruct";
*
* class UserService {
* getUser(id: string) { return { id, name: "Alice" }; }
* }
*
* // Define an event handler
* const getUserHandler = eventHandler((box) => ({
* handler(event) {
* const userService = box.get(UserService);
* const id = event.context.params?.id;
* return userService.getUser(id);
* },
* meta: { auth: true }
* }));
*
* // Use it in your app
* const app = application((app, box) => {
* app.get("/users/:id", box.get(getUserHandler));
* });
* ```
*/
declare function eventHandler<Res = unknown, Req extends EventHandlerRequest = EventHandlerRequest>(setup: (box: Box) => EventHandlerObject<Req, Res>): Constructor<h30.EventHandlerWithFetch<Req, Res>>;
/**
* Creates a middleware constructor.
*
* @param setup - Middleware function that receives the event, next function, and Box instance.
* @returns A Constructor that produces an H3 middleware. Not cached by Box.
*
* @example
* ```typescript
* import { application, middleware } from "serverstruct";
*
* class AuthService {
* validateToken(token: string) { return token === "valid"; }
* }
*
* // Define a middleware
* const authMiddleware = middleware((event, next, box) => {
* const authService = box.get(AuthService);
* const token = event.headers.get("authorization");
* if (!token || !authService.validateToken(token)) {
* throw new Error("Unauthorized");
* }
* });
*
* // Use it in your app
* const app = application((app, box) => {
* app.use(box.get(authMiddleware));
* app.get("/", () => "Hello world!");
* });
* ```
*/
declare function middleware(setup: (event: H3Event, next: () => MaybePromise<unknown | undefined>, box: Box) => MaybePromise<unknown | undefined>): Constructor<Middleware>;
/**
* A request-scoped context store for associating values with H3 events.
*
* Each request gets its own isolated context that is automatically cleaned up
* when the request completes. Uses a WeakMap internally to ensure values are
* garbage collected with their events.
*
* @example
* ```typescript
* import { application, Context } from "serverstruct";
*
* const userContext = new Context<User>();
*
* const app = application((app) => {
* app.use((event) => {
* userContext.set(event, { id: "123", name: "Alice" });
* });
* app.get("/user", (event) => {
* const user = userContext.get(event);
* return user;
* });
* });
* ```
*/
declare class Context<T> {
#private;
private options?;
/**
* @param options.onError - Custom error message thrown by `get()` when no value is set for the event.
*/
constructor(options?: {
onError?: string;
} | undefined);
/**
* Sets a value for the given event.
*/
set(event: H3Event<any>, value: T): void;
/**
* Gets the value for the given event.
* @throws Error if no value is set for the event.
*/
get(event: H3Event<any>): T;
/**
* Gets the value for the given event, or undefined if not set.
*/
lookup(event: H3Event<any>): T | undefined;
}
/**
* Creates a request-scoped context store for associating values with H3 events.
*
* Each request gets its own isolated context that is automatically cleaned up
* when the request completes. Uses a WeakMap internally to ensure values are
* garbage collected with their events.
*
* @param options.onError - Custom error message thrown by `get()` when no value is set for the event.
* @returns A Context instance.
*
* @example
* ```typescript
* import { application, context } from "serverstruct";
*
* const userContext = context<User>();
*
* const app = application((app) => {
* app.use((event) => {
* userContext.set(event, { id: "123", name: "Alice" });
* });
* app.get("/user", (event) => {
* const user = userContext.get(event);
* return user;
* });
* });
* ```
*/
declare function context<T>(options?: {
onError?: string;
}): Context<T>;
//#endregion
export { Context, ServeOptions, Server, application, context, controller, eventHandler, handler, middleware, serve };