--- url: /api/@minimajs/auth/README.md --- [**Minima.js API**](../../README.md) *** [Minima.js API](../../README.md) / @minimajs/auth # @minimajs/auth ## Classes | Class | Description | | ------ | ------ | | [ForbiddenError](classes/ForbiddenError.md) | Represents the response body of an HTTP error. Can be either a simple string message or a dictionary object with custom error data. | | [UnauthorizedError](classes/UnauthorizedError.md) | Represents the response body of an HTTP error. Can be either a simple string message or a dictionary object with custom error data. | ## Interfaces | Interface | Description | | ------ | ------ | | [AuthOption](interfaces/AuthOption.md) | - | | [AuthResourceOptional](interfaces/AuthResourceOptional.md) | - | | [AuthResourceWithRequired](interfaces/AuthResourceWithRequired.md) | - | ## Type Aliases | Type Alias | Description | | ------ | ------ | | [AuthCallback](type-aliases/AuthCallback.md) | - | | [GuardCallback](type-aliases/GuardCallback.md) | - | | [GuardMessageCallback](type-aliases/GuardMessageCallback.md) | - | ## Functions | Function | Description | | ------ | ------ | | [createAuth](functions/createAuth.md) | Creates an authentication middleware plugin and resource accessor for Minima.js applications. | --- --- url: /api/@minimajs/cookie/README.md --- [**Minima.js API**](../../README.md) *** [Minima.js API](../../README.md) / @minimajs/cookie # @minimajs/cookie @minimajs/cookie - Type-safe cookie management ## Example ```typescript import { cookies } from "@minimajs/cookie"; // Get all cookies const allCookies = cookies(); // Get a specific cookie const theme = cookies.get("theme"); // Set a cookie cookies.set("theme", "dark", { httpOnly: true }); // Remove a cookie cookies.remove("theme"); ``` ## Namespaces | Namespace | Description | | ------ | ------ | | [cookies](namespaces/cookies/README.md) | Cookie management utilities | ## Functions | Function | Description | | ------ | ------ | | [cookies](functions/cookies.md) | Retrieves all cookies from the current request as a typed record. | --- --- url: /api/@minimajs/multipart/@minimajs/multipart/README.md --- [**Minima.js API**](../../../../README.md) *** [Minima.js API](../../../../README.md) / [@minimajs/multipart](../../README.md) / @minimajs/multipart # @minimajs/multipart Collection of multipart form data handling utilities including file uploads and schema validation. ## Example ```ts import { multipart, helpers } from "@minimajs/multipart"; const file = await multipart.file('avatar'); console.log(file.name); await helpers.save(file, '/uploads/avatars'); ``` ## Namespaces | Namespace | Description | | ------ | ------ | | [helpers](namespaces/helpers/README.md) | - | | [multipart](namespaces/multipart/README.md) | - | | [raw](namespaces/raw/README.md) | - | | [streaming](namespaces/streaming/README.md) | - | ## Interfaces | Interface | Description | | ------ | ------ | | [MultipartRawField](interfaces/MultipartRawField.md) | - | | [MultipartRawFile](interfaces/MultipartRawFile.md) | - | ## Type Aliases | Type Alias | Description | | ------ | ------ | | [MultipartOptions](type-aliases/MultipartOptions.md) | - | | [MultipartRawResult](type-aliases/MultipartRawResult.md) | - | --- --- url: /api/@minimajs/multipart/README.md --- [**Minima.js API**](../../README.md) *** [Minima.js API](../../README.md) / @minimajs/multipart # @minimajs/multipart ## Modules | Module | Description | | ------ | ------ | | [@minimajs/multipart](@minimajs/multipart/README.md) | Collection of multipart form data handling utilities including file uploads and schema validation. | | [@minimajs/multipart/schema](@minimajs/multipart/schema/README.md) | Type-safe multipart form data parsing with Zod schema validation. | --- --- url: /api/@minimajs/multipart/@minimajs/multipart/schema/README.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / @minimajs/multipart/schema # @minimajs/multipart/schema Type-safe multipart form data parsing with Zod schema validation. This module provides schema-based validation for multipart uploads using Zod. Files are automatically saved to disk as TempFile instances (memory-efficient), while text fields are validated according to your schema. ## Remarks Key features: * Full TypeScript type inference from Zod schemas * Automatic file size validation with `.max()` and `.min()` * Disk-backed file storage (TempFile) to avoid memory issues * Native File API compatibility * Supports single and multiple file uploads * Built-in MIME type validation with `.mime()` ## Examples ```ts import { z } from 'zod'; import { createMultipart } from "@minimajs/multipart/schema"; import { helpers } from "@minimajs/multipart"; const upload = createMultipart({ name: z.string().min(3).max(30), avatar: z.file().max(2 * 1024 * 1024), // 2MB max }); const data = await upload(); console.log(data.name); // Type-safe access await helpers.save(data.avatar, "./uploads/avatars"); ``` ```ts import { createMultipart } from "@minimajs/multipart/schema"; const upload = createMultipart({ email: z.string().email(), photos: z.array(z.file().max(5 * 1024 * 1024)).max(10), // Max 10 photos, 5MB each }); const data = await upload(); for (const photo of data.photos) { await helpers.save(photo, "./uploads/photos"); } ``` ```ts const upload = createMultipart({ avatar: z.file() .max(2 * 1024 * 1024) .mime(['image/jpeg', 'image/png']), }); ``` ## Classes | Class | Description | | ------ | ------ | | [TempFile](classes/TempFile.md) | - | ## Interfaces | Interface | Description | | ------ | ------ | | [TempFileInit](interfaces/TempFileInit.md) | - | | [UploadOption](interfaces/UploadOption.md) | Configuration options for multipart upload handling. | ## Functions | Function | Description | | ------ | ------ | | [createMultipart](functions/createMultipart.md) | Creates a type-safe multipart form data parser with Zod schema validation. Returns a function that parses and validates incoming multipart requests, providing TempFile instances for uploaded files (disk-backed, memory-efficient). | | [isUploadedFile](functions/isUploadedFile.md) | - | --- --- url: /api/@minimajs/openapi/README.md --- [**Minima.js API**](../../README.md) *** [Minima.js API](../../README.md) / @minimajs/openapi # @minimajs/openapi ## Namespaces | Namespace | Description | | ------ | ------ | | [OpenAPI](namespaces/OpenAPI/README.md) | - | ## Interfaces | Interface | Description | | ------ | ------ | | [OpenAPIPluginOptions](interfaces/OpenAPIPluginOptions.md) | - | ## Functions | Function | Description | | ------ | ------ | | [cleanJSONSchema](functions/cleanJSONSchema.md) | Cleans JSON Schema for OpenAPI compatibility. Removes properties that are valid in JSON Schema but not in OpenAPI. | | [describe](functions/describe.md) | Adds OpenAPI operation metadata to a route. | | [generateOpenAPIDocument](functions/generateOpenAPIDocument.md) | - | | [internal](functions/internal.md) | Marks a route as internal, excluding it from the OpenAPI spec. | | [openapi](functions/openapi.md) | - | --- --- url: /api/@minimajs/schema/README.md --- [**Minima.js API**](../../README.md) *** [Minima.js API](../../README.md) / @minimajs/schema # @minimajs/schema ## Modules | Module | Description | | ------ | ------ | | [](README.md) | - | | [validation](validation/README.md) | - | --- --- url: /api/@minimajs/server/@minimajs/server/README.md --- [**Minima.js API**](../../../../README.md) *** [Minima.js API](../../../../README.md) / [@minimajs/server](../../README.md) / @minimajs/server # @minimajs/server @minimajs/server - High-performance HTTP framework ## Example ```typescript import { createApp } from "@minimajs/server"; const app = createApp(); app.get("/", () => ({ message: "Hello World" })); app.listen({ port: 3000 }); ``` ## Namespaces | Namespace | Description | | ------ | ------ | | [abort](namespaces/abort/README.md) | Utility functions for working with request aborts and errors | | [compose](namespaces/compose/README.md) | - | | [controller](namespaces/controller/README.md) | - | | [headers](namespaces/headers/README.md) | Utility functions for working with HTTP headers | | [hook](namespaces/hook/README.md) | - | | [params](namespaces/params/README.md) | Utility functions for working with route parameters | | [plugin](namespaces/plugin/README.md) | Plugin utilities namespace providing helper functions for creating and composing plugins. | | [request](namespaces/request/README.md) | Request utilities for accessing request data | | [response](namespaces/response/README.md) | Response utilities for managing HTTP responses | | [runHooks](namespaces/runHooks/README.md) | - | | [searchParams](namespaces/searchParams/README.md) | Utility functions for working with URL search parameters (query string) | ## Classes | Class | Description | | ------ | ------ | | [Server](classes/Server.md) | - | ## Interfaces | Interface | Description | | ------ | ------ | | [AddressInfo](interfaces/AddressInfo.md) | Information about the server's network address and binding. | | [App](interfaces/App.md) | - | | [Context](interfaces/Context.md) | - | | [ContextLocals](interfaces/ContextLocals.md) | - | | [ContextMetadata](interfaces/ContextMetadata.md) | - | | [ImportedModule](interfaces/ImportedModule.md) | - | | [ListenOptions](interfaces/ListenOptions.md) | Options for starting a server listener. | | [ListenResult](interfaces/ListenResult.md) | Result returned when a server starts listening. Contains the native server instance and address information. | | [Meta](interfaces/Meta.md) | - | | [Module](interfaces/Module.md) | - | | [ModuleDiscoveryOptions](interfaces/ModuleDiscoveryOptions.md) | - | | [Plugin](interfaces/Plugin.md) | - | | [PluginSync](interfaces/PluginSync.md) | - | | [RemoteAddr](interfaces/RemoteAddr.md) | - | | [ResponseOptions](interfaces/ResponseOptions.md) | - | | [ResponseState](interfaces/ResponseState.md) | - | | [Route](interfaces/Route.md) | - | | [RouteConfig](interfaces/RouteConfig.md) | - | | [RouteFindResult](interfaces/RouteFindResult.md) | - | | [RouteOptions](interfaces/RouteOptions.md) | - | | [ServerAdapter](interfaces/ServerAdapter.md) | Adapter interface for different server implementations. Abstracts the underlying server runtime (Bun, Node, Deno, etc). | | [ServerOptions](interfaces/ServerOptions.md) | - | ## Type Aliases | Type Alias | Description | | ------ | ------ | | [Container](type-aliases/Container.md) | - | | [Dict](type-aliases/Dict.md) | - | | [ErrorHandler](type-aliases/ErrorHandler.md) | - | | [GenericCallback](type-aliases/GenericCallback.md) | - | | [GenericHookCallback](type-aliases/GenericHookCallback.md) | - | | [Handler](type-aliases/Handler.md) | - | | [HeadersInit](type-aliases/HeadersInit.md) | - | | [HookFactoryCallback](type-aliases/HookFactoryCallback.md) | - | | [HookStore](type-aliases/HookStore.md) | - | | [HttpCodes](type-aliases/HttpCodes.md) | - | | [HttpHeader](type-aliases/HttpHeader.md) | - | | [HttpHeaderIncoming](type-aliases/HttpHeaderIncoming.md) | - | | [LifecycleHook](type-aliases/LifecycleHook.md) | - | | [LifeSpanCleanupCallback](type-aliases/LifeSpanCleanupCallback.md) | - | | [Middleware](type-aliases/Middleware.md) | - | | [MiddlewareNext](type-aliases/MiddlewareNext.md) | - | | [ModuleScanner](type-aliases/ModuleScanner.md) | - | | [Next](type-aliases/Next.md) | - | | [OnceCallback](type-aliases/OnceCallback.md) | - | | [OnCloseHook](type-aliases/OnCloseHook.md) | - | | [OnErrorHook](type-aliases/OnErrorHook.md) | - | | [OnListenHook](type-aliases/OnListenHook.md) | - | | [OnReadyHook](type-aliases/OnReadyHook.md) | - | | [OnRegisterHook](type-aliases/OnRegisterHook.md) | - | | [OnRequestHook](type-aliases/OnRequestHook.md) | - | | [OnSendHook](type-aliases/OnSendHook.md) | - | | [OnTimeoutHook](type-aliases/OnTimeoutHook.md) | - | | [OnTransformHook](type-aliases/OnTransformHook.md) | - | | [PluginCallback](type-aliases/PluginCallback.md) | - | | [PluginOptions](type-aliases/PluginOptions.md) | - | | [Registerable](type-aliases/Registerable.md) | - | | [RegisterOptions](type-aliases/RegisterOptions.md) | - | | [RequestHandler](type-aliases/RequestHandler.md) | Handler function that processes HTTP requests. Takes a Web standard Request and returns a Web standard Response. | | [RequestHandlerContext](type-aliases/RequestHandlerContext.md) | - | | [ResponseBody](type-aliases/ResponseBody.md) | - | | [RouteMetadata](type-aliases/RouteMetadata.md) | - | | [RouteMetaDescriptor](type-aliases/RouteMetaDescriptor.md) | - | | [Routes](type-aliases/Routes.md) | - | | [Serializer](type-aliases/Serializer.md) | - | | [Signals](type-aliases/Signals.md) | - | | [StatusCode](type-aliases/StatusCode.md) | - | ## Variables | Variable | Description | | ------ | ------ | | [executionContext](variables/executionContext.md) | - | ## Functions | Function | Description | | ------ | ------ | | [abort](functions/abort.md) | Aborts the request with the given response and status code. | | [body](functions/body.md) | Retrieves the request body. Requires bodyParser plugin to be registered. | | [compose](functions/compose.md) | Composes multiple plugins/modules into a single plugin that registers all of them sequentially. | | [context](functions/context.md) | - | | [controller](functions/controller.md) | - | | [createContext](functions/createContext.md) | Creates a context for sharing data within a request's scope. | | [createHooksStore](functions/createHooksStore.md) | Creates a new HookStore with proper cloning support for module isolation | | [handler](functions/handler.md) | - | | [headers](functions/headers.md) | Retrieves the request headers. | | [hook](functions/hook.md) | Creates a plugin that registers a lifecycle hook | | [maybeContext](functions/maybeContext.md) | - | | [middleware](functions/middleware.md) | - | | [params](functions/params.md) | Retrieves the request params. | | [plugin](functions/plugin.md) | Wraps a plain function into a Plugin with automatic kPluginSkipOverride This prevents the plugin from being encapsulated and allows direct registration | | [redirect](functions/redirect.md) | Redirects to the specified path. | | [request](functions/request.md) | Retrieves the HTTP request object. | | [response](functions/response.md) | Creates an HTTP response with serialized body, optional status code, and headers. | | [runHooks](functions/runHooks.md) | Runs all hooks for a given lifecycle event with automatic order detection - Parent → Child hooks run in FIFO order (normal) - Child → Parent hooks run in LIFO order (reversed) | | [safe](functions/safe.md) | - | | [searchParams](functions/searchParams.md) | Retrieves the search params (query string). | ## References ### createApp Re-exports [createApp](node/functions/createApp.md) *** ### defer Re-exports [defer](plugins/functions/defer.md) *** ### DeferCallback Re-exports [DeferCallback](plugins/type-aliases/DeferCallback.md) *** ### ErrorCallback Re-exports [ErrorCallback](plugins/type-aliases/ErrorCallback.md) *** ### logger Re-exports [logger](logger/variables/logger.md) *** ### onError Re-exports [onError](plugins/functions/onError.md) --- --- url: /api/@minimajs/server/README.md --- [**Minima.js API**](../../README.md) *** [Minima.js API](../../README.md) / @minimajs/server # @minimajs/server ## Modules | Module | Description | | ------ | ------ | | [@minimajs/server](@minimajs/server/README.md) | @minimajs/server - High-performance HTTP framework | | [@minimajs/server/bun](@minimajs/server/bun/README.md) | Bun runtime server adapter for Minima.js. | | [@minimajs/server/core](@minimajs/server/core/README.md) | Core server implementation internals. | | [@minimajs/server/error](@minimajs/server/error/README.md) | Error handling utilities | | [@minimajs/server/logger](@minimajs/server/logger/README.md) | Logging utilities | | [@minimajs/server/mock](@minimajs/server/mock/README.md) | @minimajs/server/mock - Testing utilities | | [@minimajs/server/node](@minimajs/server/node/README.md) | Node.js runtime server adapter for Minima.js. | | [@minimajs/server/plugins](@minimajs/server/plugins/README.md) | Built-in plugins for Minima.js framework. | | [@minimajs/server/symbols](@minimajs/server/symbols/README.md) | Symbols used throughout Minima.js framework. | --- --- url: /api/@minimajs/server/@minimajs/server/bun/README.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / @minimajs/server/bun # @minimajs/server/bun Bun runtime server adapter for Minima.js. This module provides the main entry point for creating Minima.js applications that run on the Bun runtime. It wraps the base server functionality with Bun-specific server adapter. ## Example ```typescript import { createApp } from '@minimajs/server/bun'; const app = createApp(); app.get('/hello', () => { return { message: 'Hello from Bun!' }; }); app.listen({ port: 1234 }) ``` ## Interfaces | Interface | Description | | ------ | ------ | | [BunAppOptions](interfaces/BunAppOptions.md) | Configuration options for creating a Bun-based Minima.js application. | ## Type Aliases | Type Alias | Description | | ------ | ------ | | [BunServeOptions](type-aliases/BunServeOptions.md) | - | ## Functions | Function | Description | | ------ | ------ | | [createApp](functions/createApp.md) | Creates a new Minima.js application using the Bun runtime adapter. | --- --- url: /api/@minimajs/server/@minimajs/server/core/README.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / @minimajs/server/core # @minimajs/server/core Core server implementation internals. This module exposes the internal Server class and related utilities. Most users should use the App interface through createApp() instead. ## Example ```typescript import { Server } from '@minimajs/server/core'; // Advanced usage - most users don't need this const server = new Server(adapter, options); ``` ## Interfaces | Interface | Description | | ------ | ------ | | [CreateBaseSeverOptions](interfaces/CreateBaseSeverOptions.md) | Configuration options for creating a base server instance. | ## Functions | Function | Description | | ------ | ------ | | [createBaseServer](functions/createBaseServer.md) | Creates a Minima.js application instance using a custom runtime adapter. | ## References ### Server Re-exports [Server](../classes/Server.md) *** ### ServerOptions Re-exports [ServerOptions](../interfaces/ServerOptions.md) --- --- url: /api/@minimajs/server/@minimajs/server/error/README.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / @minimajs/server/error # @minimajs/server/error Error handling utilities Provides error handling classes and utilities for HTTP error responses. Includes base error classes, error decorators, and utilities for working with HTTP status codes. ## Example ```typescript import { HttpError, NotFoundError } from '@minimajs/server/error'; throw new NotFoundError('Resource not found'); throw new HttpError('Custom error', 400); ``` ## Classes | Class | Description | | ------ | ------ | | [BaseHttpError](classes/BaseHttpError.md) | Represents the response body of an HTTP error. Can be either a simple string message or a dictionary object with custom error data. | | [HttpError](classes/HttpError.md) | Represents the response body of an HTTP error. Can be either a simple string message or a dictionary object with custom error data. | | [NotFoundError](classes/NotFoundError.md) | Represents the response body of an HTTP error. Can be either a simple string message or a dictionary object with custom error data. | | [RedirectError](classes/RedirectError.md) | Represents the response body of an HTTP error. Can be either a simple string message or a dictionary object with custom error data. | | [ValidationError](classes/ValidationError.md) | Represents the response body of an HTTP error. Can be either a simple string message or a dictionary object with custom error data. | ## Interfaces | Interface | Description | | ------ | ------ | | [HttpErrorOptions](interfaces/HttpErrorOptions.md) | - | --- --- url: /api/@minimajs/server/@minimajs/server/logger/README.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / @minimajs/server/logger # @minimajs/server/logger Logging utilities Provides logging utilities built on Pino with pretty printing support. Includes context-aware logging with automatic module name enrichment. ## Example ```typescript import { logger } from '@minimajs/server/logger'; const log = logger(); log.info('Request received'); log.error({ err }, 'Error occurred'); ``` ## Variables | Variable | Description | | ------ | ------ | | [logger](variables/logger.md) | - | | [loggerOptions](variables/loggerOptions.md) | - | ## Functions | Function | Description | | ------ | ------ | | [createLogger](functions/createLogger.md) | Creates a Pino logger instance with merged default options and mixin support. Combines default logger options with user-provided options and adds module name context. | | [mixin](functions/mixin.md) | Mixin function for Pino logger that enriches log data with module name context. Automatically adds the current module name to log entries if not already present. | --- --- url: /api/@minimajs/server/@minimajs/server/mock/README.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / @minimajs/server/mock # @minimajs/server/mock @minimajs/server/mock - Testing utilities Provides lightweight utilities for creating mock requests in tests. For full integration tests, use `app.handle()` directly. ## Example ```typescript import { createRequest } from '@minimajs/server/mock'; // Create a mock request const request = createRequest('/users', { method: 'POST', body: { name: 'John' } }); // Use with app.handle const response = await app.handle(request); expect(response.status).toBe(200); ``` ## Interfaces | Interface | Description | | ------ | ------ | | [MockContextOptions](interfaces/MockContextOptions.md) | Creates a mock Request object for testing. | | [MockRequestOptions](interfaces/MockRequestOptions.md) | Creates a mock Request object for testing. | ## Type Aliases | Type Alias | Description | | ------ | ------ | | [MockContextCallback](type-aliases/MockContextCallback.md) | - | ## Functions | Function | Description | | ------ | ------ | | [createRequest](functions/createRequest.md) | - | | [mockContext](functions/mockContext.md) | Creates a mock context for testing context-based functions. This allows you to test route handlers and context functions in isolation. | --- --- url: /api/@minimajs/server/@minimajs/server/node/README.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / @minimajs/server/node # @minimajs/server/node Node.js runtime server adapter for Minima.js. This module provides the main entry point for creating Minima.js applications that run on Node.js runtime. It wraps the base server functionality with Node.js-specific HTTP/HTTPS server adapter. ## Example ```typescript import { createApp } from '@minimajs/server/node'; const app = createApp(); app.get('/hello', () => { return { message: 'Hello from Node.js!' }; }); app.listen({ port: 3000 }); ``` ## Interfaces | Interface | Description | | ------ | ------ | | [NodeAppOptions](interfaces/NodeAppOptions.md) | Configuration options for creating a Node.js-based Minima.js application. | ## Type Aliases | Type Alias | Description | | ------ | ------ | | [NodeServerOptions](type-aliases/NodeServerOptions.md) | - | ## Functions | Function | Description | | ------ | ------ | | [createApp](functions/createApp.md) | Creates a new Minima.js application for Node.js runtime. | --- --- url: /api/@minimajs/server/@minimajs/server/plugins/README.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / @minimajs/server/plugins # @minimajs/server/plugins Built-in plugins for Minima.js framework. Provides essential plugins for common web server functionality including body parsing, CORS, routing, and graceful shutdown. ## Example ```typescript import { bodyParser, cors, shutdown } from '@minimajs/server/plugins'; const app = createApp(); // Register plugins app.register(bodyParser()); app.register(cors({ origin: 'https://example.com' })); app.register(shutdown()); ``` ## Namespaces | Namespace | Description | | ------ | ------ | | [bodyParser](namespaces/bodyParser/README.md) | - | | [proxy](namespaces/proxy/README.md) | - | ## Interfaces | Interface | Description | | ------ | ------ | | [BodyParserOptions](interfaces/BodyParserOptions.md) | Options for body parser plugin | | [CorsOptions](interfaces/CorsOptions.md) | - | | [HostSettings](interfaces/HostSettings.md) | - | | [IpSettings](interfaces/IpSettings.md) | - | | [ProtoSettings](interfaces/ProtoSettings.md) | - | | [ProxyIpPluginOptions](interfaces/ProxyIpPluginOptions.md) | - | | [ProxyOptions](interfaces/ProxyOptions.md) | - | | [RouteLoggerOptions](interfaces/RouteLoggerOptions.md) | - | | [ShutdownOptions](interfaces/ShutdownOptions.md) | - | | [TrustProxyConfig](interfaces/TrustProxyConfig.md) | - | ## Type Aliases | Type Alias | Description | | ------ | ------ | | [BodyParserType](type-aliases/BodyParserType.md) | - | | [DeferCallback](type-aliases/DeferCallback.md) | - | | [ErrorCallback](type-aliases/ErrorCallback.md) | - | | [ExpressCallback](type-aliases/ExpressCallback.md) | - | | [HostExtractor](type-aliases/HostExtractor.md) | - | | [IpExtractor](type-aliases/IpExtractor.md) | - | | [IpStrategy](type-aliases/IpStrategy.md) | - | | [ProtoExtractor](type-aliases/ProtoExtractor.md) | - | | [QuitHandler](type-aliases/QuitHandler.md) | - | ## Functions | Function | Description | | ------ | ------ | | [bodyParser](functions/bodyParser.md) | - | | [contextProvider](functions/contextProvider.md) | - | | [cors](functions/cors.md) | Creates a CORS plugin that handles Cross-Origin Resource Sharing. Uses the send hook to set CORS headers on responses. | | [defer](functions/defer.md) | Registers a callback to execute after the response. Useful for cleanup tasks, logging, or post-response processing. | | [deferrer](functions/deferrer.md) | Creates a plugin that enables defer and onError functionality. This plugin registers hooks to run deferred callbacks after response is sent and error callbacks when an error occurs. | | [descriptor](functions/descriptor.md) | Creates a plugin that adds metadata to all routes registered within its scope. | | [express](functions/express.md) | Integrates an Express-style middleware into the request lifecycle. | | [moduleDiscovery](functions/moduleDiscovery.md) | Module discovery plugin Uses Node.js's built-in import caching for performance | | [onError](functions/onError.md) | Registers an error handling callback for the current request context. Called when an error occurs during request processing. | | [proxy](functions/proxy.md) | Proxy plugin that extracts client information from proxy headers. Useful when your application is behind a reverse proxy or load balancer. | | [routeLogger](functions/routeLogger.md) | Displays a formatted tree of all routes with their HTTP methods and paths. Useful for debugging and understanding the application's route structure during development. | | [shutdown](functions/shutdown.md) | Creates a plugin for graceful server shutdown. | --- --- url: /api/@minimajs/server/@minimajs/server/symbols/README.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / @minimajs/server/symbols # @minimajs/server/symbols Symbols used throughout Minima.js framework. Provides well-known symbols for internal framework operations and plugin metadata. Using Symbol() allows cross-realm access and debugging. ## Example ```typescript import { kPluginName, kPluginSync } from '@minimajs/server/symbols'; function myPlugin() { return { [kPluginName]: 'my-plugin', [kPluginSync]: true, // plugin implementation }; } ``` ## Variables | Variable | Description | | ------ | ------ | | [kBody](variables/kBody.md) | Symbol for request body storage in context. Used by body parser plugin to store parsed body. | | [kBodySkip](variables/kBodySkip.md) | Symbol to mark requests that should skip body parsing. Used to opt-out of automatic body parsing for specific routes. | | [kHandlerDescriptor](variables/kHandlerDescriptor.md) | - | | [kHooks](variables/kHooks.md) | Symbol for accessing registered hooks. | | [kIpAddr](variables/kIpAddr.md) | - | | [kMiddlewares](variables/kMiddlewares.md) | - | | [kModuleName](variables/kModuleName.md) | Symbol for plugin name metadata. Used to identify plugins for debugging and error messages. | | [kModulesChain](variables/kModulesChain.md) | Symbol for maintaining module chain (root -> ... -> child) in container. | | [kPlugin](variables/kPlugin.md) | Symbol to mark plugins that should skip context override. Used for plugins that need to maintain parent context. | | [kPluginSync](variables/kPluginSync.md) | Symbol to mark synchronous plugins. Used for plugins that don't require async initialization. | | [kRequestSchema](variables/kRequestSchema.md) | - | | [kResponseSchema](variables/kResponseSchema.md) | - | --- --- url: /tutorials/task-board-api/01-setup.md --- # Step 1: Project Setup ## Step Outcome After this step, you will have: * a running Minima.js app on port `3000` * a generated Prisma client * the full initial database schema migrated to SQLite ## Install Dependencies ::: code-group ```bash [Terminal] mkdir task-board && cd task-board npm init -y npm install @minimajs/server @minimajs/auth @minimajs/cookie @minimajs/schema @minimajs/multipart @minimajs/openapi npm install prisma @prisma/client zod jsonwebtoken bcryptjs npm install -D typescript tsc-watch @types/node @types/jsonwebtoken @types/bcryptjs npx prisma init --datasource-provider sqlite ``` ::: Update `package.json`: ::: code-group ```json [package.json] { "type": "module", "scripts": { "build": "tsc -p tsconfig.json", "dev": "tsc-watch --onSuccess \"node dist/index.js\"", "start": "node dist/index.js" } } ``` ::: Create `tsconfig.json`: ::: code-group ```json [tsconfig.json] { "compilerOptions": { "target": "ESNext", "module": "NodeNext", "moduleResolution": "NodeNext", "strict": true, "rootDir": "src", "outDir": "dist" }, "include": ["src"] } ``` ::: ## Prisma Schema Replace `prisma/schema.prisma` with: ::: code-group ```prisma [prisma/schema.prisma] generator client { provider = "prisma-client-js" } datasource db { provider = "sqlite" url = env("DATABASE_URL") } model User { id Int @id @default(autoincrement()) email String @unique name String passwordHash String createdAt DateTime @default(now()) memberships Member[] tasks Task[] @relation("AssignedTasks") } model Workspace { id Int @id @default(autoincrement()) name String createdAt DateTime @default(now()) members Member[] boards Board[] } model Member { id Int @id @default(autoincrement()) role String @default("member") // "owner" | "admin" | "member" userId Int workspaceId Int user User @relation(fields: [userId], references: [id]) workspace Workspace @relation(fields: [workspaceId], references: [id]) @@unique([userId, workspaceId]) } model Board { id Int @id @default(autoincrement()) name String workspaceId Int createdAt DateTime @default(now()) workspace Workspace @relation(fields: [workspaceId], references: [id]) tasks Task[] } model Task { id Int @id @default(autoincrement()) title String description String? status String @default("todo") // "todo" | "in_progress" | "done" assigneeId Int? boardId Int createdAt DateTime @default(now()) updatedAt DateTime @updatedAt board Board @relation(fields: [boardId], references: [id]) assignee User? @relation("AssignedTasks", fields: [assigneeId], references: [id]) attachments Attachment[] } model Attachment { id Int @id @default(autoincrement()) filename String savedAs String size Int mimeType String taskId Int createdAt DateTime @default(now()) task Task @relation(fields: [taskId], references: [id]) } ``` ::: Run the migration: ::: code-group ```bash [Terminal] npx prisma migrate dev --name init ``` ::: Optional: open Prisma Studio to inspect your tables: ::: code-group ```bash [Terminal] npx prisma studio ``` ::: ## Entry Point Create `src/index.ts`: ::: code-group ```typescript [src/index.ts] import { createApp } from "@minimajs/server/node"; const app = createApp(); const address = await app.listen({ port: 3000 }); console.log(`Task Board API running at ${address}`); ``` ::: At this point `npm run dev` should start without errors. The `createApp()` call auto-discovers all `module.ts` files under `src/` — we'll add those next. ## Smoke Check Run: ::: code-group ```bash [Terminal] npm run dev ``` ::: Expected output: ::: code-group ```text [Output] Task Board API running at http://localhost:3000 ``` ::: And in a second terminal: ::: code-group ```bash [Terminal] curl -i http://localhost:3000/ ``` ::: Any HTTP response here is fine for now. The important part is that the process boots cleanly. ## Troubleshooting * `prisma: command not found`: use `npx prisma ...` (not global prisma). * ESM import errors: ensure `"type": "module"` is present in `package.json`. * SQLite file issues: check `DATABASE_URL` in `.env` created by `prisma init`. *** Next: [Database & Root Module](./02-database.md) --- --- url: /tutorials/task-board-api/02-database.md --- # Step 2: Database & Root Module ## Step Outcome After this step, your app has global runtime behavior: * database lifecycle management * CORS policy * request logging * graceful shutdown handling * generated OpenAPI document at `/openapi.json` ## Database Module Create `src/database.ts` — a single Prisma instance shared across the entire app, with a `hook.lifespan` that connects on startup and disconnects on shutdown: ::: code-group ```typescript [src/database.ts] import { PrismaClient } from "@prisma/client"; import { hook } from "@minimajs/server"; export const prisma = new PrismaClient(); export const dbLifespan = hook.lifespan(async () => { await prisma.$connect(); console.log("Database connected"); return async () => { await prisma.$disconnect(); console.log("Database disconnected"); }; }); ``` ::: `hook.lifespan` runs the setup function when the app starts and the returned cleanup function when `app.close()` is called. This is the idiomatic way to manage resources in Minima.js. ## Root Module The root module (`src/module.ts`) is the first module discovered. Anything registered here applies globally to every route in the app. Create `src/module.ts`: ::: code-group ```typescript [src/module.ts] import { type Meta } from "@minimajs/server"; import { cors, shutdown } from "@minimajs/server/plugins"; import { dbLifespan } from "./database.js"; export const meta: Meta = { plugins: [ // Database lifecycle dbLifespan, // Allow browser clients cors({ origin: process.env.ALLOWED_ORIGIN ?? "*", credentials: true, allowedHeaders: ["Content-Type", "Authorization"], }), // Graceful shutdown on SIGTERM / SIGINT shutdown(), ], }; ``` ::: > **Why the root module?** > `meta.plugins` registered here run for every request in every child module. CORS and the DB connection are app-wide concerns, so this is the right place for them. ## Request Logger Add a request logger to the root module so every route is logged: ::: code-group ```typescript [src/module.ts] import { type Meta, hook } from "@minimajs/server"; import { cors, shutdown } from "@minimajs/server/plugins"; import { openapi } from "@minimajs/openapi"; import { dbLifespan } from "./database.js"; export const meta: Meta = { plugins: [ dbLifespan, cors({ origin: process.env.ALLOWED_ORIGIN ?? "*", credentials: true, allowedHeaders: ["Content-Type", "Authorization"], }), shutdown(), // Log every request hook("request", ({ request, pathname }) => { console.log(`[${new Date().toISOString()}] ${request.method} ${pathname}`); }), // OpenAPI spec at GET /openapi.json openapi({ info: { title: "Task Board API", version: "1.0.0", description: "A task management API built with Minima.js", }, tags: [ { name: "Auth", description: "Authentication and session management" }, { name: "Workspaces", description: "Workspace management" }, { name: "Boards", description: "Board management within workspaces" }, { name: "Tasks", description: "Task management within boards" }, { name: "Members", description: "Workspace membership and roles" }, ], }), ], }; ``` ::: ## Verify Run `npm run dev`. You should see: ::: code-group ```text [Output] Database connected Task Board API running at http://localhost:3000 ``` ::: Every request will now be logged, CORS headers will be set, and the database will be cleanly disconnected when the process exits. Quick checks: ::: code-group ```bash [Terminal] curl http://localhost:3000/openapi.json | head curl -i -X OPTIONS http://localhost:3000/workspaces \ -H "Origin: http://localhost:5173" \ -H "Access-Control-Request-Method: GET" ``` ::: ## Troubleshooting * No `/openapi.json`: confirm `openapi(...)` is included in root `meta.plugins`. * CORS headers missing: ensure `cors(...)` is in `src/module.ts` (not a child module). * Shutdown hook not running: use `Ctrl+C` and verify `Database disconnected` appears. *** Next: [Authentication](./03-auth.md) --- --- url: /tutorials/task-board-api/03-auth.md --- # Step 3: Authentication We'll implement JWT authentication with access tokens (short-lived, in `Authorization` header) and refresh tokens (long-lived, in an `httpOnly` cookie). ## Step Outcome After this step, you can: * register and login users * issue short-lived access tokens * persist refresh tokens in secure cookies * refresh access tokens without forcing re-login * enforce auth in any module with `authenticated()` ## Auth Setup Create `src/auth/index.ts`: ::: code-group ```typescript [src/auth/index.ts] import { headers } from "@minimajs/server"; import { createAuth, UnauthorizedError } from "@minimajs/auth"; import jwt from "jsonwebtoken"; import { prisma } from "../database.js"; const ACCESS_SECRET = process.env.ACCESS_SECRET ?? "access-secret-change-in-prod"; const REFRESH_SECRET = process.env.REFRESH_SECRET ?? "refresh-secret-change-in-prod"; export interface AuthUser { id: number; email: string; name: string; } // --- Token helpers --- export function signAccessToken(user: AuthUser): string { return jwt.sign(user, ACCESS_SECRET, { expiresIn: "15m" }); } export function signRefreshToken(userId: number): string { return jwt.sign({ id: userId }, REFRESH_SECRET, { expiresIn: "7d" }); } // --- Auth plugin --- // Reads the Bearer token from Authorization header, verifies it, // and loads the user from the database. export const [authPlugin, getUser] = createAuth(async () => { const authHeader = headers.get("authorization"); if (!authHeader?.startsWith("Bearer ")) { throw new UnauthorizedError("Missing or invalid Authorization header"); } const token = authHeader.slice(7); let payload: AuthUser; try { payload = jwt.verify(token, ACCESS_SECRET) as AuthUser; } catch { throw new UnauthorizedError("Invalid or expired access token"); } const user = await prisma.user.findUnique({ where: { id: payload.id } }); if (!user) { throw new UnauthorizedError("User no longer exists"); } return { id: user.id, email: user.email, name: user.name }; }); export { ACCESS_SECRET, REFRESH_SECRET }; ``` ::: ## Auth Guards Create `src/auth/guards.ts`: ::: code-group ```typescript [src/auth/guards.ts] import { getUser } from "./index.js"; import { ForbiddenError } from "@minimajs/auth"; import { prisma } from "../database.js"; import { params, abort } from "@minimajs/server"; // Requires a valid access token export function authenticated() { getUser.required(); } // Requires membership in the workspace from :workspaceId param export async function workspaceMember() { const user = getUser.required(); const workspaceId = Number(params.get("workspaceId")); const member = await prisma.member.findUnique({ where: { userId_workspaceId: { userId: user.id, workspaceId } }, }); if (!member) { throw new ForbiddenError("You are not a member of this workspace"); } return member; } // For routes scoped by :boardId (e.g. /boards/:boardId/tasks), // resolve board -> workspace and then reuse membership check logic. export async function boardMember() { const user = getUser.required(); const boardId = Number(params.get("boardId")); const board = await prisma.board.findUnique({ where: { id: boardId }, select: { workspaceId: true }, }); if (!board) { abort.notFound("Board not found"); } const member = await prisma.member.findUnique({ where: { userId_workspaceId: { userId: user.id, workspaceId: board.workspaceId, }, }, }); if (!member) { throw new ForbiddenError("You are not a member of this workspace"); } return member; } // Requires admin or owner role in the workspace export async function workspaceAdmin() { const member = await workspaceMember(); if (!["owner", "admin"].includes(member.role)) { throw new ForbiddenError("Admin access required"); } return member; } ``` ::: ## Auth Routes Create `src/auth/module.ts`: ::: code-group ```typescript [src/auth/module.ts] import { type Routes, abort } from "@minimajs/server"; import { cookies } from "@minimajs/cookie"; import { createBody } from "@minimajs/schema"; import { z } from "zod"; import jwt from "jsonwebtoken"; import { prisma } from "../database.js"; import { signAccessToken, signRefreshToken, REFRESH_SECRET, } from "./index.js"; import bcrypt from "bcryptjs"; const loginSchema = z.object({ email: z.string().email(), password: z.string().min(1), }); const registerSchema = z.object({ name: z.string().min(2), email: z.string().email(), password: z.string().min(8), }); const getLoginBody = createBody(loginSchema); const getRegisterBody = createBody(registerSchema); async function register() { const { name, email, password } = getRegisterBody(); const existing = await prisma.user.findUnique({ where: { email } }); if (existing) { abort.badRequest("Email already in use"); } const passwordHash = await bcrypt.hash(password, 10); const user = await prisma.user.create({ data: { name, email, passwordHash }, }); const accessToken = signAccessToken({ id: user.id, email: user.email, name: user.name }); const refreshToken = signRefreshToken(user.id); cookies.set("refresh_token", refreshToken, { httpOnly: true, secure: process.env.NODE_ENV === "production", sameSite: "strict", maxAge: 60 * 60 * 24 * 7, // 7 days }); return { accessToken, user: { id: user.id, name: user.name, email: user.email } }; } async function login() { const { email, password } = getLoginBody(); const user = await prisma.user.findUnique({ where: { email } }); if (!user || !(await bcrypt.compare(password, user.passwordHash))) { abort.unauthorized("Invalid email or password"); } const accessToken = signAccessToken({ id: user.id, email: user.email, name: user.name }); const refreshToken = signRefreshToken(user.id); cookies.set("refresh_token", refreshToken, { httpOnly: true, secure: process.env.NODE_ENV === "production", sameSite: "strict", maxAge: 60 * 60 * 24 * 7, }); return { accessToken, user: { id: user.id, name: user.name, email: user.email } }; } async function refresh() { const token = cookies.get("refresh_token"); if (!token) { abort.unauthorized("No refresh token"); } let payload: { id: number }; try { payload = jwt.verify(token, REFRESH_SECRET) as { id: number }; } catch { abort.unauthorized("Invalid or expired refresh token"); } const user = await prisma.user.findUnique({ where: { id: payload.id } }); if (!user) { abort.unauthorized("User not found"); } const accessToken = signAccessToken({ id: user.id, email: user.email, name: user.name }); return { accessToken }; } function logout() { cookies.remove("refresh_token"); return { success: true }; } export const routes: Routes = { "POST /register": register, "POST /login": login, "POST /refresh": refresh, "POST /logout": logout, }; ``` ::: ### Register the auth plugin globally Update `src/module.ts` to register the `authPlugin` so it runs on every request (but only throws in routes that call `getUser.required()`): ::: code-group ```typescript [src/module.ts] import { type Meta, hook } from "@minimajs/server"; import { cors, shutdown } from "@minimajs/server/plugins"; import { authPlugin } from "./auth/index.js"; import { dbLifespan } from "./database.js"; export const meta: Meta = { plugins: [ dbLifespan, cors({ origin: process.env.ALLOWED_ORIGIN ?? "*", credentials: true, allowedHeaders: ["Content-Type", "Authorization"], }), shutdown(), hook("request", ({ request, pathname }) => { console.log(`[${new Date().toISOString()}] ${request.method} ${pathname}`); }), // Auth runs on every request but only enforced where needed authPlugin, ], }; ``` ::: ## Dependency Note ::: code-group ```bash [Terminal] # If you skipped Step 1's full install list: npm install bcryptjs npm install -D @types/bcryptjs ``` ::: ## Test It ::: code-group ```bash [Terminal] # Register curl -X POST http://localhost:3000/auth/register \ -H "Content-Type: application/json" \ -d '{"name":"Alice","email":"alice@example.com","password":"secret123"}' # Login curl -X POST http://localhost:3000/auth/login \ -H "Content-Type: application/json" \ -d '{"email":"alice@example.com","password":"secret123"}' # → { "accessToken": "eyJ...", "user": { ... } } ``` ::: Full refresh-cookie flow: ::: code-group ```bash [Terminal] # Save cookie jar curl -c cookies.txt -X POST http://localhost:3000/auth/login \ -H "Content-Type: application/json" \ -d '{"email":"alice@example.com","password":"secret123"}' # Use refresh token from cookie jar curl -b cookies.txt -X POST http://localhost:3000/auth/refresh ``` ::: ## Troubleshooting * Always unauthorized: check `Authorization: Bearer ` format. * Refresh fails: verify cookie name is exactly `refresh_token`. * Invalid signature errors: make sure `ACCESS_SECRET`/`REFRESH_SECRET` are stable between restarts. *** Next: [Workspaces](./04-workspaces.md) --- --- url: /tutorials/task-board-api/04-workspaces.md --- # Step 4: Workspaces Workspaces are the top-level container. Only authenticated users can create workspaces, and only workspace members can access their boards and tasks. ## Step Outcome After this step, authenticated users can fully manage workspaces: * list only their own workspaces * create a workspace (creator becomes `owner`) * update/delete workspace if `owner` or `admin` ## Module Everything lives in a single `src/workspaces/module.ts`. The handler functions are defined in the file, and `export const routes` wires them to HTTP methods and paths. ::: code-group ```typescript [src/workspaces/module.ts] import { type Meta, type Routes, hook, params, abort } from "@minimajs/server"; import { descriptor } from "@minimajs/server/plugins"; import { describe } from "@minimajs/openapi"; import { createBody } from "@minimajs/schema"; import { z } from "zod"; import { prisma } from "../database.js"; import { getUser } from "../auth/index.js"; import { authenticated } from "../auth/guards.js"; const workspaceBody = createBody( z.object({ name: z.string().min(1).max(100) }) ); async function list() { const user = getUser.required(); const memberships = await prisma.member.findMany({ where: { userId: user.id }, include: { workspace: true }, }); return memberships.map((m) => ({ ...m.workspace, role: m.role })); } async function find() { const id = Number(params.get("id")); const user = getUser.required(); const member = await prisma.member.findUnique({ where: { userId_workspaceId: { userId: user.id, workspaceId: id } }, include: { workspace: true }, }); if (!member) abort.notFound("Workspace not found"); return { ...member.workspace, role: member.role }; } async function create() { const user = getUser.required(); const { name } = workspaceBody(); const workspace = await prisma.workspace.create({ data: { name } }); // Creator becomes the owner await prisma.member.create({ data: { userId: user.id, workspaceId: workspace.id, role: "owner" }, }); return workspace; } async function update() { const id = Number(params.get("id")); const user = getUser.required(); const { name } = workspaceBody(); const membership = await prisma.member.findUnique({ where: { userId_workspaceId: { userId: user.id, workspaceId: id } }, }); if (!membership || !["owner", "admin"].includes(membership.role)) { abort.forbidden("Admin access required"); } return prisma.workspace.update({ where: { id }, data: { name } }); } async function remove() { const id = Number(params.get("id")); const user = getUser.required(); const membership = await prisma.member.findUnique({ where: { userId_workspaceId: { userId: user.id, workspaceId: id } }, }); if (!membership || !["owner", "admin"].includes(membership.role)) { abort.forbidden("Admin access required"); } await prisma.workspace.delete({ where: { id } }); return { success: true }; } export const meta: Meta = { plugins: [ hook("request", authenticated), descriptor(describe({ tags: ["Workspaces"] })), ], }; export const routes: Routes = { "GET /": list, "GET /:id": find, "POST /": create, "PATCH /:id": update, "DELETE /:id": remove, }; ``` ::: Notice how `hook("request", authenticated)` in `meta.plugins` runs before every route in this module. The admin check for `update` and `remove` is done inline in each handler since they need access to `:id` as the workspace ID. ## Test It ::: code-group ```bash [Terminal] # Create a workspace (use the access token from login) curl -X POST http://localhost:3000/workspaces \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"name":"My Project"}' # List your workspaces curl http://localhost:3000/workspaces \ -H "Authorization: Bearer " ``` ::: Expected create response shape: ::: code-group ```json [Response] { "id": 1, "name": "My Project", "createdAt": "2026-01-01T00:00:00.000Z" } ``` ::: ## Troubleshooting * `403 Admin access required` on update/delete: your user is not `owner`/`admin` in that workspace. * `404 Workspace not found` on `GET /:id`: this endpoint is intentionally membership-scoped. *** Next: [Boards & Tasks](./05-boards-tasks.md) --- --- url: /tutorials/task-board-api/05-boards-tasks.md --- # Step 5: Boards & Tasks Boards live inside workspaces, and tasks live inside boards. This step also introduces file uploads for task attachments. ## Step Outcome After this step, you will support: * nested board routes under workspaces * nested task routes under boards * task pagination + status filtering * attachment upload per task * workspace membership checks for board-scoped task APIs ## Boards Create `src/boards/module.ts`: ::: code-group ```typescript [src/boards/module.ts] import { type Meta, type Routes, hook, params, abort } from "@minimajs/server"; import { descriptor } from "@minimajs/server/plugins"; import { describe } from "@minimajs/openapi"; import { createBody } from "@minimajs/schema"; import { z } from "zod"; import { prisma } from "../database.js"; import { authenticated, workspaceMember, workspaceAdmin } from "../auth/guards.js"; const boardBody = createBody( z.object({ name: z.string().min(1).max(100) }) ); async function list() { const workspaceId = Number(params.get("workspaceId")); return prisma.board.findMany({ where: { workspaceId } }); } async function find() { const id = Number(params.get("id")); const workspaceId = Number(params.get("workspaceId")); const board = await prisma.board.findFirst({ where: { id, workspaceId } }); if (!board) abort.notFound("Board not found"); return board; } async function create() { const workspaceId = Number(params.get("workspaceId")); const { name } = boardBody(); return prisma.board.create({ data: { name, workspaceId } }); } async function update() { await workspaceAdmin(); const id = Number(params.get("id")); const workspaceId = Number(params.get("workspaceId")); const { name } = boardBody(); const board = await prisma.board.findFirst({ where: { id, workspaceId } }); if (!board) abort.notFound("Board not found"); return prisma.board.update({ where: { id }, data: { name } }); } async function remove() { await workspaceAdmin(); const id = Number(params.get("id")); const workspaceId = Number(params.get("workspaceId")); const board = await prisma.board.findFirst({ where: { id, workspaceId } }); if (!board) abort.notFound("Board not found"); await prisma.board.delete({ where: { id } }); return { success: true }; } export const meta: Meta = { prefix: "/workspaces/:workspaceId/boards", plugins: [ hook("request", authenticated), hook("request", workspaceMember), descriptor(describe({ tags: ["Boards"] })), ], }; export const routes: Routes = { "GET /": list, "GET /:id": find, "POST /": create, "PATCH /:id": update, "DELETE /:id": remove, }; ``` ::: Because this module exports `routes` (instead of a default registration function), keep module discovery enabled and use `meta.prefix` for nesting. The `prefix` above mounts this module at `/workspaces/:workspaceId/boards`. Do the same for tasks in the next section. ## Tasks Create `src/tasks/module.ts`: ::: code-group ```typescript [src/tasks/module.ts] import { type Meta, type Routes, hook, params, abort } from "@minimajs/server"; import { descriptor } from "@minimajs/server/plugins"; import { describe } from "@minimajs/openapi"; import { createBody, createSearchParams } from "@minimajs/schema"; import { z } from "zod"; import { multipart, helpers } from "@minimajs/multipart"; import { prisma } from "../database.js"; import { authenticated, boardMember } from "../auth/guards.js"; const taskBody = createBody( z.object({ title: z.string().min(1).max(200), description: z.string().optional(), status: z.enum(["todo", "in_progress", "done"]).default("todo"), assigneeId: z.number().int().optional(), }) ); const paginationParams = createSearchParams( z.object({ page: z.number({ coerce: true }).int().positive().default(1), limit: z.number({ coerce: true }).int().positive().max(100).default(20), status: z.enum(["todo", "in_progress", "done"]).optional(), }) ); async function list() { const boardId = Number(params.get("boardId")); const { page, limit, status } = paginationParams(); const where = { boardId, ...(status ? { status } : {}) }; const [tasks, total] = await Promise.all([ prisma.task.findMany({ where, include: { assignee: { select: { id: true, name: true } }, attachments: true }, skip: (page - 1) * limit, take: limit, orderBy: { createdAt: "desc" }, }), prisma.task.count({ where }), ]); return { tasks, total, page, limit }; } async function find() { const boardId = Number(params.get("boardId")); const id = Number(params.get("id")); const task = await prisma.task.findFirst({ where: { id, boardId }, include: { assignee: { select: { id: true, name: true } }, attachments: true }, }); if (!task) abort.notFound("Task not found"); return task; } async function create() { const boardId = Number(params.get("boardId")); const data = taskBody(); return prisma.task.create({ data: { ...data, boardId }, include: { assignee: { select: { id: true, name: true } } }, }); } async function update() { const boardId = Number(params.get("boardId")); const id = Number(params.get("id")); const data = taskBody(); const existing = await prisma.task.findFirst({ where: { id, boardId } }); if (!existing) abort.notFound("Task not found"); return prisma.task.update({ where: { id }, data, include: { assignee: { select: { id: true, name: true } } }, }); } async function remove() { const boardId = Number(params.get("boardId")); const id = Number(params.get("id")); const existing = await prisma.task.findFirst({ where: { id, boardId } }); if (!existing) abort.notFound("Task not found"); await prisma.task.delete({ where: { id } }); return { success: true }; } async function uploadAttachment() { const boardId = Number(params.get("boardId")); const taskId = Number(params.get("id")); const task = await prisma.task.findFirst({ where: { id: taskId, boardId } }); if (!task) abort.notFound("Task not found"); const file = await multipart.file("file"); if (!file) abort.badRequest("No file uploaded"); const uploadDir = await helpers.ensurePath("./uploads", "attachments"); const savedAs = await helpers.save(file, uploadDir); return prisma.attachment.create({ data: { taskId, filename: file.name, savedAs, size: file.size, mimeType: file.type, }, }); } export const meta: Meta = { prefix: "/boards/:boardId/tasks", plugins: [ hook("request", authenticated), hook("request", boardMember), descriptor(describe({ tags: ["Tasks"] })), ], }; export const routes: Routes = { "GET /": list, "GET /:id": find, "POST /": create, "PATCH /:id": update, "DELETE /:id": remove, "POST /:id/attachments": uploadAttachment, }; ``` ::: ## What We Just Used | Pattern | Where | |---|---| | `export const routes: Routes` | All handlers wired directly in the module | | `createBody` with Zod | Request body validation in every handler | | `createSearchParams` | Pagination and filtering in `list()` | | `multipart.file()` | Single file upload in `uploadAttachment()` | | `helpers.save()` | Persist file to disk with UUID filename | | `abort.notFound()` | Return 404 when a resource doesn't exist | | `meta.prefix` | Mount module under nested resource paths | | `hook("request", boardMember)` | Enforce workspace membership for board-scoped task routes | ## Smoke Check ::: code-group ```bash [Terminal] # Create board in a workspace curl -X POST http://localhost:3000/workspaces/1/boards \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"name":"Backend"}' # Create task in board curl -X POST http://localhost:3000/boards/1/tasks \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"title":"Design schema","status":"todo"}' # List tasks with pagination curl "http://localhost:3000/boards/1/tasks?page=1&limit=10&status=todo" \ -H "Authorization: Bearer " # Upload attachment curl -X POST http://localhost:3000/boards/1/tasks/1/attachments \ -H "Authorization: Bearer " \ -F "file=@./README.md" ``` ::: ## Troubleshooting * `404 Board not found` while creating tasks: check `boardId` exists and belongs to expected workspace. * Upload fails with missing file: field name must be exactly `file`. * Unexpected empty task lists: verify `status` filter and `boardId` are correct. *** Next: [Members & Roles](./06-members.md) --- --- url: /tutorials/task-board-api/06-members.md --- # Step 6: Members & Roles Members connect users to workspaces. Only workspace admins and owners can add or remove members. ## Step Outcome After this step, each workspace supports team management: * list all members (for any member) * invite users by email (admin/owner only) * change member role between `admin` and `member` * remove non-owner members ## Module Create `src/members/module.ts`: ::: code-group ```typescript [src/members/module.ts] import { type Meta, type Routes, hook, params, abort } from "@minimajs/server"; import { descriptor } from "@minimajs/server/plugins"; import { describe } from "@minimajs/openapi"; import { createBody } from "@minimajs/schema"; import { z } from "zod"; import { prisma } from "../database.js"; import { authenticated, workspaceMember, workspaceAdmin } from "../auth/guards.js"; const inviteBody = createBody( z.object({ email: z.string().email(), role: z.enum(["admin", "member"]).default("member"), }) ); const updateRoleBody = createBody( z.object({ role: z.enum(["admin", "member"]) }) ); async function list() { const workspaceId = Number(params.get("workspaceId")); return prisma.member.findMany({ where: { workspaceId }, include: { user: { select: { id: true, name: true, email: true } } }, }); } async function invite() { await workspaceAdmin(); // only admins/owners can invite const workspaceId = Number(params.get("workspaceId")); const { email, role } = inviteBody(); const user = await prisma.user.findUnique({ where: { email } }); if (!user) abort.notFound("No user with that email address"); const existing = await prisma.member.findUnique({ where: { userId_workspaceId: { userId: user.id, workspaceId } }, }); if (existing) abort.badRequest("User is already a member"); return prisma.member.create({ data: { userId: user.id, workspaceId, role }, include: { user: { select: { id: true, name: true, email: true } } }, }); } async function updateRole() { await workspaceAdmin(); const workspaceId = Number(params.get("workspaceId")); const memberId = Number(params.get("id")); const { role } = updateRoleBody(); const member = await prisma.member.findUnique({ where: { id: memberId } }); if (!member) abort.notFound("Member not found"); // Prevent demoting the last owner if (member.role === "owner") { const ownerCount = await prisma.member.count({ where: { workspaceId, role: "owner" }, }); if (ownerCount <= 1) abort.badRequest("Cannot change role of the last owner"); } return prisma.member.update({ where: { id: memberId }, data: { role }, include: { user: { select: { id: true, name: true, email: true } } }, }); } async function remove() { await workspaceAdmin(); const memberId = Number(params.get("id")); const member = await prisma.member.findUnique({ where: { id: memberId } }); if (!member) abort.notFound("Member not found"); if (member.role === "owner") { abort.forbidden("Cannot remove a workspace owner"); } await prisma.member.delete({ where: { id: memberId } }); return { success: true }; } export const meta: Meta = { plugins: [ hook("request", authenticated), hook("request", workspaceMember), descriptor(describe({ tags: ["Members"] })), ], }; export const routes: Routes = { "GET /": list, "POST /": invite, "PATCH /:id": updateRole, "DELETE /:id": remove, }; ``` ::: `list` is available to any workspace member. The `invite`, `updateRole`, and `remove` handlers call `await workspaceAdmin()` themselves — this is the idiomatic way to apply per-handler authorization without splitting routes into separate modules. ## Smoke Check ::: code-group ```bash [Terminal] # List members curl http://localhost:3000/workspaces/1/members \ -H "Authorization: Bearer " # Invite a member curl -X POST http://localhost:3000/workspaces/1/members \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"email":"bob@example.com","role":"member"}' # Promote member (replace :id) curl -X PATCH http://localhost:3000/workspaces/1/members/:id \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"role":"admin"}' ``` ::: ## Troubleshooting * `404 No user with that email address`: invite target must register first. * `403 Admin access required`: caller lacks admin/owner role in that workspace. * Last owner protections are intentional to prevent orphaned workspaces. *** Next: [Error Handling & Polish](./07-errors-polish.md) --- --- url: /tutorials/task-board-api/07-errors-polish.md --- # Step 7: Error Handling & Polish ## Step Outcome After this step, your API has production-facing polish: * consistent error response shape * centralized unhandled error logging * validation issue normalization * complete, coherent API surface for demos and onboarding ## Centralized Error Format By default, `abort` errors render themselves. To give every error response a consistent shape across the API, override `HttpError.toJSON` once at startup. Add this to `src/index.ts` before `app.listen`: ::: code-group ```typescript [src/index.ts] import { createApp } from "@minimajs/server/node"; import { HttpError } from "@minimajs/server/error"; // Consistent error shape for the entire API HttpError.toJSON = (err) => ({ success: false, error: { message: err.response, statusCode: err.status, }, }); const app = createApp(); const address = await app.listen({ port: 3000 }); console.log(`Task Board API running at ${address}`); ``` ::: Now every HTTP error — whether from `abort.notFound()`, `abort.unauthorized()`, or a validation failure — returns: ::: code-group ```json [Error Response] { "success": false, "error": { "message": "Workspace not found", "statusCode": 404 } } ``` ::: ## Global Error Hook For logging errors and catching unhandled exceptions, add an `error` hook to the root module: ::: code-group ```typescript [src/module.ts] // src/module.ts import { type Meta, hook, abort } from "@minimajs/server"; import { cors, shutdown } from "@minimajs/server/plugins"; import { authPlugin } from "./auth/index.js"; import { dbLifespan } from "./database.js"; export const meta: Meta = { plugins: [ dbLifespan, cors({ origin: process.env.ALLOWED_ORIGIN ?? "*", credentials: true, allowedHeaders: ["Content-Type", "Authorization"], }), shutdown(), hook("request", ({ request, pathname }) => { console.log(`[${new Date().toISOString()}] ${request.method} ${pathname}`); }), authPlugin, // Centralized error handling hook("error", (error) => { // Let expected HTTP errors use the standard serializer. if (abort.is(error)) { throw error; } console.error("[Unhandled Error]", error); abort({ message: "Internal server error" }, 500); }), ], }; ``` ::: ## Validation Error Format Override the validation error shape from `@minimajs/schema` to match the same API format: ::: code-group ```typescript [src/index.ts] // src/index.ts import { ValidationError } from "@minimajs/schema/error"; ValidationError.toJSON = (err) => ({ success: false, error: { message: "Validation failed", statusCode: 400, issues: err.issues?.map((issue) => ({ field: issue.path.join("."), message: issue.message, })), }, }); ``` ::: ## Final Project Structure ::: code-group ```text [Project Tree] src/ ├── index.ts # Entry + error format overrides ├── module.ts # Global plugins: CORS, auth, DB, logging, error hook ├── database.ts # Prisma instance + lifespan hook ├── auth/ │ ├── index.ts # createAuth, token helpers │ ├── guards.ts # authenticated, workspaceMember, boardMember, workspaceAdmin │ └── module.ts # /auth/register, /login, /refresh, /logout ├── workspaces/ │ └── module.ts # GET|POST|PATCH|DELETE /workspaces ├── boards/ │ └── module.ts # /workspaces/:workspaceId/boards ├── tasks/ │ └── module.ts # /boards/:boardId/tasks + attachments └── members/ └── module.ts # /workspaces/:workspaceId/members ``` ::: ## Complete API Surface | Method | Path | Auth | Description | |---|---|---|---| | `POST` | `/auth/register` | — | Create account | | `POST` | `/auth/login` | — | Get access + refresh token | | `POST` | `/auth/refresh` | cookie | Rotate access token | | `POST` | `/auth/logout` | — | Clear refresh token cookie | | `GET` | `/workspaces` | ✓ | List user's workspaces | | `POST` | `/workspaces` | ✓ | Create workspace | | `GET` | `/workspaces/:id` | ✓ member | Get workspace | | `PATCH` | `/workspaces/:id` | ✓ admin | Update workspace | | `DELETE` | `/workspaces/:id` | ✓ admin | Delete workspace | | `GET` | `/workspaces/:workspaceId/members` | ✓ member | List members | | `POST` | `/workspaces/:workspaceId/members` | ✓ admin | Invite member | | `PATCH` | `/workspaces/:workspaceId/members/:id` | ✓ admin | Update role | | `DELETE` | `/workspaces/:workspaceId/members/:id` | ✓ admin | Remove member | | `GET` | `/workspaces/:workspaceId/boards` | ✓ member | List boards | | `POST` | `/workspaces/:workspaceId/boards` | ✓ member | Create board | | `PATCH` | `/workspaces/:workspaceId/boards/:id` | ✓ admin | Update board | | `DELETE` | `/workspaces/:workspaceId/boards/:id` | ✓ admin | Delete board | | `GET` | `/boards/:boardId/tasks` | ✓ member | List tasks (paginated) | | `POST` | `/boards/:boardId/tasks` | ✓ member | Create task | | `PATCH` | `/boards/:boardId/tasks/:id` | ✓ member | Update task | | `DELETE` | `/boards/:boardId/tasks/:id` | ✓ member | Delete task | | `POST` | `/boards/:boardId/tasks/:id/attachments` | ✓ member | Upload attachment | ## What You've Learned You've now built a production-grade REST API using virtually every major feature of Minima.js: * **File-based modules** — zero configuration, folder = URL prefix * **`createAuth` + `@minimajs/auth`** — type-safe auth with required/optional modes and guards * **`@minimajs/cookie`** — `httpOnly` refresh token storage * **`@minimajs/schema`** — Zod validation for body, searchParams, with zero boilerplate error handling * **`@minimajs/multipart`** — file uploads with size limits and disk persistence * **`hook.lifespan`** — clean DB connect/disconnect lifecycle * **`hook("request")`** — logging and auth guards scoped to modules * **`hook("error")`** — centralized error handling with proper re-throw * **`abort` helpers** — semantic HTTP errors throughout * **`HttpError.toJSON`** — single place to define API error format * **`export const routes: Routes`** — handlers wired directly in the module, no extra files * **`cors` + `shutdown`** — production-ready global plugins ## 5-Minute Demo Script (For Presenting Minima.js) Use this live flow when introducing Minima.js to other developers: 1. Show `src/module.ts` and explain global composition (`meta.plugins`). 2. Show one feature module (`src/workspaces/module.ts`) and point out `routes` + hooks in one file. 3. Run `POST /auth/login`, then `GET /workspaces` with Bearer token. 4. Trigger a controlled error (`GET /workspaces/999`) to show consistent error JSON. 5. Open `/openapi.json` to prove docs are generated from real route metadata. This sequence demonstrates Minima.js value quickly: minimal boilerplate, strong structure, and predictable runtime behavior. ## Final Verification Checklist * `npm run dev` starts without runtime errors. * `POST /auth/register` and `POST /auth/login` succeed. * Protected routes reject missing/invalid Bearer tokens. * Workspace-scoped routes enforce role checks. * Task attachment upload writes files to `./uploads/attachments`. * Error responses follow the `HttpError.toJSON` shape. ## Next Steps * **[OpenAPI](/packages/openapi)** — Auto-generate API docs from your routes * **[Testing Guide](/guides/testing)** — Test handlers with `app.handle()` and `createRequest()` * **[JWT Authentication Recipe](/cookbook/jwt-authentication)** — Deeper JWT patterns * **[Advanced: Module Discovery](/advanced/module-discovery)** — Customize how modules are found --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/abort/README.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server](../../README.md) / abort # abort Utility functions for working with request aborts and errors ## Functions | Function | Description | | ------ | ------ | | [assert](functions/assert.md) | Ensures an error is an aborted error. If not, re-throws it. | | [is](functions/is.md) | Checks if a given error is an aborted error. | | [notFound](functions/notFound.md) | Aborts the request with a 404 Not Found error. | | [rethrow](functions/rethrow.md) | Ensures an error is not an aborted error. If it is an aborted error, re-throws it. | --- --- url: /api/@minimajs/server/@minimajs/server/error/classes/BaseHttpError.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/error](../README.md) / BaseHttpError # Abstract Class: BaseHttpError Represents the response body of an HTTP error. Can be either a simple string message or a dictionary object with custom error data. ## Extends * `Error` ## Extended by * [`HttpError`](HttpError.md) * [`RedirectError`](RedirectError.md) ## Constructors ### Constructor ```ts new BaseHttpError(message?): BaseHttpError; ``` #### Parameters ##### message? `string` #### Returns `BaseHttpError` #### Inherited from ```ts Error.constructor ``` ### Constructor ```ts new BaseHttpError(message?, options?): BaseHttpError; ``` #### Parameters ##### message? `string` ##### options? `ErrorOptions` #### Returns `BaseHttpError` #### Inherited from ```ts Error.constructor ``` ### Constructor ```ts new BaseHttpError(message?, options?): BaseHttpError; ``` #### Parameters ##### message? `string` ##### options? `ErrorOptions` #### Returns `BaseHttpError` #### Inherited from ```ts Error.constructor ``` ## Properties ### cause? ```ts optional cause: unknown; ``` The cause of the error. #### Inherited from ```ts Error.cause ``` *** ### code? ```ts optional code: string; ``` *** ### message ```ts message: string; ``` #### Inherited from ```ts Error.message ``` *** ### name ```ts name: string; ``` #### Inherited from ```ts Error.name ``` *** ### stack? ```ts optional stack: string; ``` #### Inherited from ```ts Error.stack ``` *** ### status ```ts abstract status: number; ``` *** ### stackTraceLimit ```ts static stackTraceLimit: number; ``` The `Error.stackTraceLimit` property specifies the number of stack frames collected by a stack trace (whether generated by `new Error().stack` or `Error.captureStackTrace(obj)`). The default value is `10` but may be set to any valid JavaScript number. Changes will affect any stack trace captured *after* the value has been changed. If set to a non-number value, or set to a negative number, stack traces will not capture any frames. #### Inherited from ```ts Error.stackTraceLimit ``` ## Methods ### render() ```ts abstract render(ctx): Response | Promise; ``` #### Parameters ##### ctx [`Context`](../../interfaces/Context.md) #### Returns `Response` | `Promise`<`Response`> *** ### captureStackTrace() #### Call Signature ```ts static captureStackTrace(targetObject, constructorOpt?): void; ``` Creates a `.stack` property on `targetObject`, which when accessed returns a string representing the location in the code at which `Error.captureStackTrace()` was called. ```js const myObject = {}; Error.captureStackTrace(myObject); myObject.stack; // Similar to `new Error().stack` ``` The first line of the trace will be prefixed with `${myObject.name}: ${myObject.message}`. The optional `constructorOpt` argument accepts a function. If given, all frames above `constructorOpt`, including `constructorOpt`, will be omitted from the generated stack trace. The `constructorOpt` argument is useful for hiding implementation details of error generation from the user. For instance: ```js function a() { b(); } function b() { c(); } function c() { // Create an error without stack trace to avoid calculating the stack trace twice. const { stackTraceLimit } = Error; Error.stackTraceLimit = 0; const error = new Error(); Error.stackTraceLimit = stackTraceLimit; // Capture the stack trace above function b Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace throw error; } a(); ``` ##### Parameters ###### targetObject `object` ###### constructorOpt? `Function` ##### Returns `void` ##### Inherited from ```ts Error.captureStackTrace ``` #### Call Signature ```ts static captureStackTrace(targetObject, constructorOpt?): void; ``` Create .stack property on a target object ##### Parameters ###### targetObject `object` ###### constructorOpt? `Function` ##### Returns `void` ##### Inherited from ```ts Error.captureStackTrace ``` *** ### is() ```ts static is(value): value is BaseHttpError; ``` #### Parameters ##### value `unknown` #### Returns `value is BaseHttpError` *** ### isError() #### Call Signature ```ts static isError(error): error is Error; ``` Indicates whether the argument provided is a built-in Error instance or not. ##### Parameters ###### error `unknown` ##### Returns `error is Error` ##### Inherited from ```ts Error.isError ``` #### Call Signature ```ts static isError(value): value is Error; ``` Check if a value is an instance of Error ##### Parameters ###### value `unknown` The value to check ##### Returns `value is Error` True if the value is an instance of Error, false otherwise ##### Inherited from ```ts Error.isError ``` *** ### prepareStackTrace() ```ts static prepareStackTrace(err, stackTraces): any; ``` #### Parameters ##### err `Error` ##### stackTraces `CallSite`\[] #### Returns `any` #### See https://v8.dev/docs/stack-trace-api#customizing-stack-traces #### Inherited from ```ts Error.prepareStackTrace ``` --- --- url: /advanced.md --- # Advanced Topics This section covers advanced Minima.js concepts for building custom integrations and understanding the framework's internals. ## Topics ### [Module Discovery Configuration](./module-discovery.md) Customize how Minima.js discovers modules: change filenames, scan roots, or plug in a custom scanner. Topics covered: * `moduleDiscovery` options (`root`, `index`, `scanner`) * Absolute path requirements * Custom discovery patterns * Disabling discovery for manual registration ### [Custom Runtime Adapters](./custom-adapters.md) Learn how to create custom adapters to run Minima.js on different runtimes like Deno, uWebSockets.js, or any other HTTP server implementation. Topics covered: * Understanding the `ServerAdapter` interface * Converting between native and Web standard Request/Response * Implementing runtime-specific features * Examples for Deno, uWebSockets.js, and more ### [Container and Encapsulation](./container-encapsulation.md) Deep dive into Minima.js's container system for managing state, settings, and module isolation. Topics covered: * Understanding the container architecture * How container cloning works (arrays, cloneable objects, references) * Using containers for plugin settings and configuration * Module hierarchy and the modules chain * Best practices for container usage * Advanced patterns for shared state and encapsulation ## Who Should Read This? These guides are for: * **Framework integrators** creating adapters for new runtimes * **Plugin authors** building complex plugins with state management * **Advanced users** who need fine-grained control over encapsulation * **Contributors** understanding Minima.js internals ## Prerequisites Before diving into these topics, you should be familiar with: * [Core Concepts](../core-concepts/architecture.md) * [Hooks System](../guides/hooks.md) * TypeScript and advanced JavaScript concepts ## Related Documentation * [Architecture Overview](../core-concepts/architecture.md) * [Application Lifecycle](../core-concepts/application.md) * [Encapsulation Diagrams](../core-concepts/diagrams/encapsulation.md) * [Plugin System](../core-concepts/plugins.md) ## Getting Help If you're working on a custom adapter or have questions about containers: 1. Check the [source code](https://github.com/minima-js/minimajs) - the implementations are well-documented 2. Review existing adapters in `packages/server/src/node` and `packages/server/src/bun` 3. Open a [discussion](https://github.com/minima-js/minimajs/discussions) on GitHub 4. Join our community for support ## Contributing Found an issue or want to improve these guides? Contributions are welcome! See our [Contributing Guide](https://github.com/minima-js/minimajs/blob/main/CONTRIBUTING.md). --- --- url: /core-concepts/application.md --- # Application The application instance is the heart of every Minima.js project. It's an object that encapsulates your server, routes, middleware, and configuration. You create it using the `createApp` function. ## Creating an Application Minima.js is optimized for both Bun and Node.js. You create an application instance by importing `createApp` from the appropriate runtime-specific path. This ensures you get native performance with zero abstraction overhead. ::: code-group ```typescript [Bun] import { createApp } from "@minimajs/server/bun"; // Creates an app instance using Bun.serve() const app = createApp(); ``` ```typescript [Node.js] import { createApp } from "@minimajs/server/node"; // Creates an app instance using http.createServer() const app = createApp(); ``` ::: If you import directly from `@minimajs/server`, it will default to the Node.js runtime. ## Application Lifecycle The application instance manages the entire server lifecycle, which consists of several key stages: initialization, readiness, listening, and closing. You can tap into these stages using **lifecycle hooks** to manage resources, log events, or perform other setup and teardown actions. For a detailed guide on hooks, see the [Hooks guide](/guides/hooks). ## Core Methods The `app` object provides a small but powerful set of methods for managing your application. ### `app.listen()` The `listen` method starts the web server, making it ready to accept incoming requests on a specified port and host. It returns an object containing the server's address. ```typescript const address = await app.listen({ port: 3000 }); console.log(`Server running at ${address}`); ``` ### `app.register()` The `.register()` method adds functionality to your application. While modules are **auto-discovered** by default, this method is available for: * Manual module registration (when `moduleDiscovery: false`) * Registering global plugins in your entry file * Building reusable plugins and libraries **Note:** When using module discovery (recommended), use `meta.plugins` instead of calling `app.register()` inside modules. ::: code-group ```typescript [Recommended: Using modules with meta.plugins] // src/users/module.ts import { type Meta, type Routes, hook } from "@minimajs/server"; export const meta: Meta = { plugins: [hook("request", () => console.log("Users hook"))], }; export const routes: Routes = { "GET /list": () => "users", }; ``` ```typescript [Alternative: Manual registration] // src/index.ts import { type App, hook } from "@minimajs/server"; async function myModule(app: App) { app.register(hook("request", () => console.log("Module hook!"))); app.get("/hello", () => "Hello from the module!"); } const app = createApp({ moduleDiscovery: false }); app.register(myModule, { prefix: "/api" }); ``` ::: This method is fundamental to Minima.js's principle of **encapsulation**. When you register a module, it creates an isolated scope, meaning any hooks or plugins registered inside it will not affect the rest of your application, ensuring clear boundaries and predictable behavior. ### `app.close()` This method gracefully shuts down the server. It triggers the `close` lifecycle hook, allowing you to perform cleanup tasks like disconnecting from a database. ```typescript // Example of a graceful shutdown process.on("SIGINT", async () => { console.log("Shutting down server..."); await app.close(); console.log("Server closed."); process.exit(0); }); ``` ### `app.handle()` For testing purposes, the `.handle()` method allows you to send mock requests to your application without needing to run a live server. It dispatches the request directly to your handlers and returns a `Response` object. ```typescript import { createRequest } from "@minimajs/server/mock"; test("GET /", async () => { const response = await app.handle(createRequest("/")); expect(response.status).toBe(200); expect(await response.json()).toEqual({ message: "Hello, World!" }); }); ``` For more information on testing your application, see the [Testing guide](/guides/testing). --- --- url: /core-concepts/architecture.md --- # Architecture Minima.js is designed with a **modular, scalable, and runtime-native architecture**. It is built entirely from scratch to enable native integration with modern runtimes like Bun while maintaining full Node.js compatibility, with zero legacy overhead. ## Application & Request Lifecycle Understanding Minima.js’s lifecycle is key to building robust applications. It consists of two interconnected flows: the global application lifecycle and the per-request processing stages. For a comprehensive guide to all available hooks, see the [Hooks Guide](/guides/hooks). ### Application Lifecycle The application passes through four key phases from start to finish. ```mermaid graph TD Start([createApp]) --> Register Register["hook:register · ↓ FIFO
Plugins & modules"] --> Ready Ready["hook:ready · ↓ FIFO
Initialization complete"] --> Listen Listen["hook:listen · ↓ FIFO
Server started"] --> Serving{Server Running} Serving -->|Incoming Requests| RequestCycle[REQUEST LIFECYCLE
see below] RequestCycle --> Serving Serving -->|app.close| Close["hook:close · ↑ LIFO
Cleanup & shutdown"] Close --> End([Application Stopped]) style Register fill:#e1f5ff style Ready fill:#e7f9e7 style Listen fill:#fff4e1 style Serving fill:#f0f0f0 style Close fill:#ffe1e1 style RequestCycle fill:#f5e1ff ``` ### Request Lifecycle Each incoming request flows through multiple stages with three main execution paths. ```mermaid graph TD Start([Incoming HTTP Request]) Start --> CreateCtx["Create Context
params · body · headers"] CreateCtx --> ReqHook{"hook:request
↓ FIFO"} ReqHook -->|Returns Response
short-circuit| SendHook ReqHook -->|Continue| RouteMatch{{"Route Matching"}} RouteMatch --> Handler["Route Handler
Execution"] Handler -->|Returns data| Transform{"hook:transform
↑ LIFO"} Handler -->|Returns Response| SendHook Transform --> Serialize[/"Serialize body
JSON · text · stream"\] Serialize --> SendHook{"hook:send
↑ LIFO"} SendHook --> Defer(["defer()
post-response tasks"]) Defer --> Complete([Request Complete]) %% Error Flow ReqHook -.->|throws| ErrorHook RouteMatch -.->|throws| ErrorHook Handler -.->|throws| ErrorHook Transform -.->|throws| ErrorHook ErrorHook{"hook:error
↑ LIFO"} --> SerializeErr[/"Serialize error"\] --> ErrorSendHook{"hook:send
↑ LIFO"} --> OnError(["onError()
request cleanup"]) --> Defer %% Styling - Hooks (diamonds) style ReqHook fill:#fff4e1,stroke:#ffa726,stroke-width:2px style Transform fill:#ffe7f0,stroke:#e91e63,stroke-width:2px style SendHook fill:#e8f5e9,stroke:#4caf50,stroke-width:2px style ErrorHook fill:#ffebee,stroke:#f44336,stroke-width:2px style ErrorSendHook fill:#e8f5e9,stroke:#4caf50,stroke-width:2px %% Initialization & Context style CreateCtx fill:#e3f2fd,stroke:#2196f3,stroke-width:2px %% Routing & Matching style RouteMatch fill:#f3e5f5,stroke:#9c27b0,stroke-width:2px %% Main Processing style Handler fill:#ede7f6,stroke:#673ab7,stroke-width:3px %% Data Transformation (parallelograms) style Serialize fill:#fff3e0,stroke:#ff9800,stroke-width:2px style SerializeErr fill:#ffebee,stroke:#f44336,stroke-width:2px %% Cleanup & Lifecycle (stadiums) style Defer fill:#f5f5f5,stroke:#9e9e9e,stroke-width:2px style OnError fill:#ffebee,stroke:#f44336,stroke-width:2px %% Start/End style Start fill:#e8f5e9,stroke:#4caf50,stroke-width:2px style Complete fill:#e8f5e9,stroke:#4caf50,stroke-width:2px ``` ## Hook System The hook system gives you fine-grained control over the application and request lifecycle. ### Hook Execution Order Hooks within the same scope execute in **FIFO** (First-In-First-Out) order for request hooks. Register hooks via `meta.plugins`: ::: code-group ```typescript [src/users/module.ts] import { hook } from "@minimajs/server"; export const meta = { plugins: [hook("request", () => console.log("First registered")), hook("request", () => console.log("Second registered"))], }; export const routes: Routes = { // routes here }; ``` ::: **Execution order:** 1. "First registered" → runs first 2. "Second registered" → runs second ### Encapsulation and Scope Isolation Each module creates an **isolated scope**. Hooks and plugins registered via `meta.plugins` only affect that module and its children, not siblings or parents. ```mermaid graph TB Root[Root Scope
hook: Root hook] Root --> Child1[Child Scope 1
hook: Child 1 hook
route: /users] Root --> Child2[Child Scope 2
hook: Child 2 hook
route: /admin] subgraph Execution["Request Execution"] direction TB U1["/users request"] --> UE1[✓ Root hook] --> UE2[✓ Child 1 hook] --> UE3[✓ /users handler] A1["/admin request"] --> AE1[✓ Root hook] --> AE2[✓ Child 2 hook] --> AE3[✓ /admin handler] end Child1 -.->|influences| U1 Child2 -.->|influences| A1 style Root fill:#e1f5ff,stroke:#2196f3,stroke-width:2px style Child1 fill:#e7f9e7,stroke:#4caf50,stroke-width:2px style Child2 fill:#fff4e1,stroke:#ff9800,stroke-width:2px style UE1 fill:#cfe8fc style UE2 fill:#d4f1d4 style AE1 fill:#cfe8fc style AE2 fill:#fff0cc ``` **Example:** ::: code-group ```typescript [src/module.ts] import { hook } from "@minimajs/server"; // Root module - hooks apply to all child modules export const meta = { plugins: [hook("request", () => console.log("Root hook"))], }; export const routes: Routes = { "GET /health": () => "ok", }; ``` ```typescript [src/users/module.ts] import { hook } from "@minimajs/server"; // Child scope 1 export const meta = { plugins: [hook("request", () => console.log("Users hook"))], }; export const routes: Routes = { "GET /list": () => "users", // Request to /users/list executes: Root hook → Users hook }; ``` ```typescript [src/admin/module.ts] import { hook } from "@minimajs/server"; // Child scope 2 (isolated from users module) export const meta = { plugins: [hook("request", () => console.log("Admin hook"))], }; export const routes: Routes = { "GET /dashboard": () => "admin", // Request to /admin/dashboard executes: Root hook → Admin hook }; ``` ::: *** ## Execution Paths & Performance There are four primary execution paths a request can take, each with different performance characteristics. ```mermaid graph TD Start([Incoming Request]) --> Choice{Execution Path} Choice -->|1️⃣ Normal Flow| N1[Route Match] N1 --> N2[Handler returns data] N2 --> N3["TRANSFORM Hook
↑ LIFO"] N3 --> N4[Serialize to JSON] N4 --> N5["SEND Hook
↑ LIFO"] N5 --> N6[defer callbacks] N6 --> N7[Send Response] Choice -->|2️⃣ Direct Response| D1[Route Match] D1 --> D2[Handler returns Response] D2 --> D5["SEND Hook
↑ LIFO"] --> N6 Choice -->|3️⃣ Early Return| E1["REQUEST Hook
↓ FIFO"] E1 --> E2[Returns Response] E2 --> E5["SEND Hook
↑ LIFO"] --> N6 Choice -.->|4️⃣ Error at Any Stage| R1["ERROR Hook
↑ LIFO"] R1 --> R2[Serialize Error] R2 --> R3["SEND Hook
↑ LIFO"] R3 --> R4[onError callbacks] --> N6 style N2 fill:#e7f9e7 style N3 fill:#e7f9e7 style N4 fill:#e7f9e7 style D2 fill:#fff4e1 style E2 fill:#e1f5ff style R1 fill:#ffe1e1 style R2 fill:#ffe1e1 style R4 fill:#ffe1e1 ``` ### 1. Normal Flow (Automatic Serialization) This is the standard path where data returned from a handler goes through the full processing pipeline. ``` REQUEST → Route Match → Handler (returns data) → TRANSFORM → Serialize → SEND → ... ``` ### 2. Direct Response Flow (Bypass Hooks) Returning a `Response` object from a handler bypasses the `transform` and serialization steps for higher performance. ``` REQUEST → Route Match → Handler (returns Response) → SEND → ... ``` ### 3. Early Return Flow (Short-Circuit) Returning a `Response` from an early hook (like `request`) terminates the lifecycle immediately. This is the fastest path and is ideal for things like health checks or handling blocked IPs. ``` REQUEST → hook('request') (returns Response) → SEND → ... ``` ### 4. Error Flow When an error is thrown, the normal flow is interrupted, and the `error` hook pipeline is executed. ``` Any Stage → (error) → ERROR → Serialize Error → ... ``` For more details, see the [Error Handling Guide](/guides/error-handling). ### Performance Considerations **Fastest to Slowest Execution Paths:** 1. **Direct Response in `request` hook** → Bypasses everything. 2. **Direct Response in handler** → Bypasses transform & serialization. 3. **Returning data in handler** → Full pipeline. ::: code-group ```typescript [src/api/module.ts] import { hook, type Routes } from "@minimajs/server"; export const meta = { plugins: [ // Ultra-fast health check (Path 3) hook("request", ({ pathname, responseState }) => { if (pathname === "/health") { // carry global response return new Response("OK", responseState); } }), ], }; export const routes: Routes = { // Fast static response (Path 2) "GET /ping": ({ responseState }) => new Response("pong", responseState), // Full pipeline (Path 1) "GET /data": () => ({ data: "value" }), }; ``` ::: *** ## Core Design Principles Minima.js is built on three pillars that work together to provide a modern and efficient development experience. ### 1. Native Runtime Integration Minima.js provides platform-specific imports that leverage **native APIs**, eliminating abstraction layers and delivering peak runtime performance. ::: code-group ```ts [Bun] import { createApp } from "@minimajs/server/bun"; // Uses Bun's native HTTP server for maximum performance. ``` ```ts [Node.js] import { createApp } from "@minimajs/server/node"; // Uses Node.js's native HTTP server. ``` ::: ### 2. Web API Standards The framework uses **native Web API `Request` and `Response` objects** instead of Node.js-specific abstractions. This makes the API portable, familiar to web developers, and future-proof. ### 3. Modular, Scope-Isolated Design Filesystem-based modules with `meta.plugins` enable **scalable, composable applications** with clear lifecycle guarantees. Each module creates an isolated scope where: * Child modules inherit hooks/plugins from parents * Sibling modules remain completely isolated * No configuration needed - just create directories and module files --- --- url: /packages/auth.md --- # @minimajs/auth Authentication and authorization utilities for Minima.js applications with powerful type-safe middleware and guard support. ```bash npm2yarn npm i @minimajs/auth ``` ## Overview The `@minimajs/auth` package provides a powerful and type-safe way to implement authentication in your Minima.js applications. It uses the concept of middleware plugins and resource accessors to handle authentication logic, making it easy to protect routes and access authenticated user data throughout your application. ### Key Features * **Type-Safe**: Full TypeScript support with automatic type inference * **Flexible**: Support for both optional and required authentication modes * **Context-Aware**: Authentication data is automatically isolated per request * **Error Handling**: Graceful handling of authentication failures with proper HTTP error responses * **Guard Support**: Easy creation of authorization guards for route protection ## Core API: `createAuth` The `createAuth` function is the primary API for setting up authentication in your Minima.js application. It creates a middleware plugin and a resource accessor function. ### Signature ```typescript function createAuth( callback: () => Promise | T, option?: { required?: boolean } ): [Plugin, AuthResource]; ``` ### Parameters * **`callback`**: An async or sync function that performs your authentication logic * Should return the authenticated data (e.g., user object) * Should throw a `BaseHttpError` (like `UnauthorizedError`) if authentication fails * Executed once per request before route handlers run * **`option`**: Optional configuration object * `required: true` - Makes authentication mandatory for all routes using this plugin * If omitted - Authentication is optional, allowing routes to handle missing auth gracefully ### Returns A tuple `[plugin, resource]`: * **`plugin`**: Middleware plugin to register with your app * **`resource`**: Function to access authenticated data with two modes: * `resource()` - Returns the auth data or `undefined` (if optional mode) * `resource.required()` - Always returns the auth data or throws an error ## Basic Usage: Optional Authentication Optional authentication allows routes to handle both authenticated and unauthenticated requests: ```typescript title="src/auth/index.ts" import { headers } from "@minimajs/server"; import { createAuth, UnauthorizedError } from "@minimajs/auth"; export const [authPlugin, getUser] = createAuth(async () => { const token = headers.get("x-user-token"); if (!token) { throw new UnauthorizedError("No token provided"); } const user = await User.findByToken(token); if (!user) { throw new UnauthorizedError("Invalid credentials"); } return user; }); ``` ### Using in Your Application ```typescript title="src/index.ts" import { createApp } from "@minimajs/server"; import { authPlugin, getUser } from "./auth"; const app = createApp(); // Register the auth plugin globally app.register(authPlugin); // Public route - handles both authenticated and unauthenticated users app.get("/", () => { const user = getUser(); // User | undefined if (user) { return { message: `Welcome back, ${user.name}!` }; } return { message: "Welcome, guest!" }; }); // You can also use optional chaining app.get("/profile", () => { const userName = getUser()?.name; return { name: userName ?? "Anonymous" }; }); ``` ## Creating Authorization Guards Guards are functions that enforce authentication requirements for specific routes or route groups. They're useful when you want to protect certain routes while keeping others public. ### Creating a Basic Guard ```typescript title="src/auth/guards.ts" import { getUser } from "./index"; import { ForbiddenError } from "@minimajs/auth"; // Simple guard that requires authentication export function authenticated() { getUser.required(); // Throws UnauthorizedError if not authenticated } // Guard for admin-only routes export function adminOnly() { const user = getUser.required(); if (!user.isAdmin) { throw new ForbiddenError("Admin access required"); } } // Guard with custom permissions export function requirePermission(permission: string) { return () => { const user = getUser.required(); if (!user.permissions.includes(permission)) { throw new ForbiddenError(`Missing permission: ${permission}`); } }; } ``` ### Using Guards with Composition Use the `compose` API to apply guards to specific routes or route modules. First, wrap your guard functions in a plugin. ```typescript title="src/index.ts" import { createApp, compose, plugin, hook, type App } from "@minimajs/server"; import { authPlugin, getUser } from "./auth"; import { authenticated, adminOnly } from "./auth/guards"; const app = createApp(); // Register auth plugin globally app.register(authPlugin); // Public routes (no guard) app.get("/", () => ({ message: "Public endpoint" })); // Protected routes with guards function protectedRoutes(app: App) { app.get("/dashboard", () => { const user = getUser(); // TypeScript knows this is defined because of the guard return { message: `Welcome ${user.name}` }; }); app.get("/settings", () => { return { settings: getUser().preferences }; }); } function adminRoutes(app: App) { app.get("/admin/users", () => { return { users: getAllUsers() }; }); app.delete("/admin/user/:id", () => { // Admin only logic }); } // 1. Convert guard functions into middleware plugins const authenticatedPlugin = plugin((app) => app.register(hook("request", authenticated))); const adminOnlyPlugin = plugin((app) => app.register(hook("request", adminOnly))); // 2. Create composed applicators const withAuth = compose.create(authenticatedPlugin); const withAdminAuth = compose.create(authenticatedPlugin, adminOnlyPlugin); // 3. Apply guards to route groups app.register(withAuth(protectedRoutes)); app.register(withAdminAuth(adminRoutes)); ``` ## Required Authentication Mode When you need to protect all routes by default, use the `required: true` option. This makes authentication mandatory and simplifies your code by removing the need for null checks. ### Setting Up Required Authentication ```typescript title="src/auth/index.ts" import { headers } from "@minimajs/server"; import { createAuth, UnauthorizedError } from "@minimajs/auth"; export const [authPlugin, getUser] = createAuth( async () => { const token = headers.get("x-user-token"); if (!token) { throw new UnauthorizedError("Authentication required"); } const user = await User.findByToken(token); if (!user) { throw new UnauthorizedError("Invalid credentials"); } return user; }, { required: true } // All routes will require authentication ); ``` ### Using Required Authentication With `required: true`, the resource accessor always returns a non-nullable type: ```typescript title="src/index.ts" import { createApp } from "@minimajs/server"; import { authPlugin, getUser } from "./auth"; const app = createApp(); // Register the auth plugin - this protects ALL routes app.register(authPlugin); app.get("/profile", () => { const user = getUser(); // User (not User | undefined) // No need for null checks - TypeScript knows user exists return { id: user.id, name: user.name, email: user.email, }; }); app.get("/settings", () => { // Direct property access without optional chaining return { preferences: getUser().preferences, theme: getUser().settings.theme, }; }); ``` ### Benefits of Required Mode 1. **Type Safety**: TypeScript knows the user is always defined 2. **Cleaner Code**: No need for null checks or optional chaining 3. **Automatic Protection**: All routes are protected by default 4. **Early Errors**: Authentication failures happen before route handlers execute ## TypeScript Support The `createAuth` function provides excellent TypeScript support with automatic type inference: ```typescript interface User { id: number; name: string; email: string; isAdmin: boolean; permissions: string[]; } // Optional mode const [plugin1, getUser1] = createAuth(async () => { // ... auth logic }); const user1 = getUser1(); // Type: User | undefined const name1 = getUser1()?.name; // Type: string | undefined // Required mode const [plugin2, getUser2] = createAuth( async () => { // ... auth logic }, { required: true } ); const user2 = getUser2(); // Type: User (not nullable!) const name2 = getUser2().name; // Type: string (no optional chaining needed) // Using .required() method const user3 = getUser1.required(); // Type: User (throws if not authenticated) ``` ## Advanced Patterns ### Multiple Authentication Strategies You can create multiple authentication strategies for different parts of your application: ```typescript // JWT token authentication export const [jwtPlugin, getJwtUser] = createAuth(async () => { const token = headers.get("authorization")?.replace("Bearer ", ""); return await verifyJwtToken(token); }); // API key authentication export const [apiKeyPlugin, getApiClient] = createAuth(async () => { const apiKey = headers.get("x-api-key"); return await Client.findByApiKey(apiKey); }); // Session-based authentication export const [sessionPlugin, getSessionUser] = createAuth(async () => { const sessionId = cookie.get("session_id"); return await Session.getUser(sessionId); }); // Use different strategies in different routes app.register(jwtPlugin); app.get("/api/users", () => { const user = getJwtUser(); return { users: getUserList(user) }; }); ``` ### Combining with Other Context Data Authentication works seamlessly with other context-based data: ```typescript import { createContext } from "@minimajs/server"; const [getTenant, setTenant] = createContext(); const [authPlugin, getUser] = createAuth(async () => { const tenantId = headers.get("x-tenant-id"); const tenant = await Tenant.findById(tenantId); setTenant(tenant); const token = headers.get("authorization"); return await authenticateUser(token, tenant); }); app.get("/data", () => { const user = getUser(); const tenant = getTenant(); return getData(tenant, user); }); ``` ### Custom Error Messages Customize error responses for different authentication failures: ```typescript import { BaseHttpError } from "@minimajs/server/error"; class TokenExpiredError extends BaseHttpError { constructor() { super("Token has expired", 401); } } class InvalidTokenError extends BaseHttpError { constructor() { super("Invalid token format", 401); } } export const [authPlugin, getUser] = createAuth(async () => { const token = headers.get("authorization")?.replace("Bearer ", ""); if (!token) { throw new UnauthorizedError("No token provided"); } try { const decoded = jwt.verify(token, SECRET); return await User.findById(decoded.userId); } catch (error) { if (error.name === "TokenExpiredError") { throw new TokenExpiredError(); } throw new InvalidTokenError(); } }); ``` ## Error Handling The `createAuth` function handles errors intelligently: * **`BaseHttpError`** (and subclasses like `UnauthorizedError`): * In **optional mode**: Error is stored, `resource()` returns `undefined` * In **required mode**: Error is thrown immediately when accessing the resource * `resource.required()` always throws the error * **Other errors** (e.g., `Error`, network errors): * Always thrown immediately, resulting in 500 Internal Server Error ```typescript const [authPlugin, getUser] = createAuth(async () => { const token = headers.get("authorization"); if (!token) { throw new UnauthorizedError("Missing token"); // BaseHttpError } try { return await fetchUserFromDatabase(token); } catch (error) { // Database errors will throw immediately (500) throw error; } }); ``` ## API Reference ### Error Classes ```typescript import { UnauthorizedError, // 401 ForbiddenError, // 403 BaseHttpError, // Custom status codes } from "@minimajs/auth"; // Usage throw new UnauthorizedError("Invalid credentials"); throw new ForbiddenError("Insufficient permissions"); throw new BaseHttpError("Custom error", 418); ``` ### Type Definitions ```typescript // Auth callback type type AuthCallback = () => Promise | T; // Resource accessor for optional auth interface AuthResourceOptional { (): T | undefined; required(): T; } // Resource accessor for required auth interface AuthResourceWithRequired { (): T; required(): T; } ``` ## Best Practices 1. **Keep Authentication Logic Simple**: The callback should focus solely on authentication 2. **Use Type Parameters**: Always specify the user type for better TypeScript support 3. **Handle Errors Properly**: Throw `BaseHttpError` subclasses for expected failures 4. **Choose the Right Mode**: Use `required: true` for protected APIs, optional for mixed access 5. **Create Reusable Guards**: Extract common authorization logic into guard functions 6. **Separate Concerns**: Keep authentication separate from authorization logic ## Conclusion The `@minimajs/auth` package provides a powerful, type-safe, and flexible authentication system for Minima.js applications. With support for both optional and required authentication modes, combined with guards and composition, you can implement sophisticated authentication and authorization patterns while maintaining clean, readable code. ## License MIT --- --- url: /plugins/body-parser.md --- # Body Parser The Body Parser plugin is responsible for parsing incoming request bodies based on their `Content-Type` header. It enables the use of the `body()` context-aware function to access the parsed body in your route handlers. ## Installation The plugin is included with the `@minimajs/server` package and can be imported from `@minimajs/server/plugins`. ```typescript import { bodyParser } from "@minimajs/server/plugins"; ``` ## Default Behavior **The body parser is automatically enabled by default**. It is configured to parse `application/json` content types, so you can use the `body()` function immediately without any setup. ::: code-group ```typescript [src/users/module.ts] import { body, type Routes } from "@minimajs/server"; function createUser() { const newUser = body<{ name: string; email: string }>(); // ... create user return { created: newUser }; } export const routes: Routes = { // Body parser is already enabled - no registration needed! "POST /": createUser, }; ``` ::: ## Configuration You can override the default configuration or disable the body parser by re-registering it with different options in your module's `meta.plugins`. ### `type` Specifies the content types to parse. Re-registering with a different `type` will override the default JSON-only configuration. * **Type**: `("json" | "text" | "form" | "arrayBuffer" | "blob")[]` * **Default**: `["json"]` ::: code-group ```typescript [src/logs/module.ts] import { bodyParser } from "@minimajs/server/plugins"; import { body, type Meta, type Routes } from "@minimajs/server"; // Override to parse JSON and plain text for this module export const meta: Meta = { plugins: [bodyParser({ type: ["json", "text"] })], }; function logText() { const logMessage = body(); console.log(logMessage); return { status: "logged" }; } export const routes: Routes = { "POST /text": logText, }; ``` ::: ### `clone` Clones the request object before parsing the body. This can be useful if you need to read the raw request body stream more than once. * **Type**: `boolean` * **Default**: `false` ```typescript export const meta: Meta = { plugins: [bodyParser({ type: "json", clone: true })], }; ``` ### `enabled` Disables the body parser when set to `false`. This removes the body parser entirely, and calling `body()` will throw an error. * **Type**: `boolean` * **Default**: `true` (enabled by default) ::: code-group ```typescript [src/raw/module.ts] import { bodyParser } from "@minimajs/server/plugins"; import { type Meta } from "@minimajs/server"; // Disable body parser for this module export const meta: Meta = { plugins: [bodyParser({ enabled: false })], }; ``` ::: ## Examples ### Using Default Configuration Since body parser is enabled by default, you can use it immediately in any module: ::: code-group ```typescript [src/api/module.ts] import { body, type Routes } from "@minimajs/server"; function createUser() { const user = body<{ name: string; email: string }>(); return { created: user }; } export const routes: Routes = { "POST /users": createUser, }; ``` ::: ### Overriding Configuration Re-register the body parser in your root module to change its configuration application-wide: ::: code-group ```typescript [src/module.ts] import { bodyParser } from "@minimajs/server/plugins"; import { body, type Meta, type Routes } from "@minimajs/server"; // Change from JSON-only to support both JSON and text globally export const meta: Meta = { plugins: [bodyParser({ type: ["json", "text"] })], }; function logItem() { const log = body(); // Can now parse text/plain return { logged: log }; } export const routes: Routes = { "POST /logs": logItem, }; ``` ::: ### Disabling Body Parser If you don't need body parsing, you can disable it: ```typescript export const meta: Meta = { plugins: [bodyParser({ enabled: false })], }; ``` --- --- url: /api/@minimajs/server/@minimajs/server/plugins/namespaces/bodyParser/README.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server/plugins](../../README.md) / bodyParser # bodyParser ## Functions | Function | Description | | ------ | ------ | | [skip](functions/skip.md) | - | --- --- url: /plugins.md --- # Built-in Plugins Minima.js comes with a set of pre-built plugins to handle common web development needs. These plugins can be easily integrated into your application: * **In module files** - Use `meta.plugins` (recommended) * **In entry files** - Use `app.register()` ## Quick Example ::: code-group ```typescript [src/module.ts] import { type Meta, type Routes } from "@minimajs/server"; import { cors } from "@minimajs/server/plugins"; // Apply CORS globally to all routes in this scope export const meta: Meta = { plugins: [cors({ origin: "*" })], }; function getData() { return { data: "value" }; } export const routes: Routes = { "GET /api/data": getData, }; ``` ::: ## Available Plugins * **[Body Parser](./body-parser.md)**: For parsing incoming request bodies (e.g., JSON, text). * **[CORS](./cors.md)**: For managing Cross-Origin Resource Sharing headers. * **[Descriptor](./descriptor.md)**: For applying route metadata to entire scopes. * **[Express Middleware](./express.md)**: For integrating Express.js-style middleware (Node.js only). * **[Proxy](./proxy.md)**: For extracting client information from proxy headers (IP, protocol, hostname). * **[Route Logger](./route-logger.md)**: A development utility to log all registered routes. * **[Graceful Shutdown](./shutdown.md)**: For ensuring your server shuts down gracefully. --- --- url: /api/@minimajs/auth/classes/ForbiddenError.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/auth](../README.md) / ForbiddenError # Class: ForbiddenError\ Represents the response body of an HTTP error. Can be either a simple string message or a dictionary object with custom error data. ## Extends * [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md)<`R`> ## Type Parameters ### R `R` ## Constructors ### Constructor ```ts new ForbiddenError(response, options?): ForbiddenError; ``` The initial value of Object.prototype.constructor is the standard built-in Object constructor. #### Parameters ##### response `R` = `...` ##### options? [`HttpErrorOptions`](../../server/@minimajs/server/error/interfaces/HttpErrorOptions.md) #### Returns `ForbiddenError`<`R`> #### Overrides [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`constructor`](../../server/@minimajs/server/error/classes/HttpError.md#constructor) ## Properties ### base? ```ts optional base: unknown; ``` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`base`](../../server/@minimajs/server/error/classes/HttpError.md#base) *** ### cause? ```ts optional cause: unknown; ``` The cause of the error. #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`cause`](../../server/@minimajs/server/error/classes/HttpError.md#cause) *** ### code? ```ts optional code: string; ``` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`code`](../../server/@minimajs/server/error/classes/HttpError.md#code) *** ### constructor ```ts constructor: typeof HttpError; ``` The initial value of Object.prototype.constructor is the standard built-in Object constructor. #### Inherited from ```ts HttpError.constructor ``` *** ### headers? ```ts optional headers: HeadersInit; ``` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`headers`](../../server/@minimajs/server/error/classes/HttpError.md#headers) *** ### message ```ts message: string; ``` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`message`](../../server/@minimajs/server/error/classes/HttpError.md#message) *** ### name ```ts name: string; ``` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`name`](../../server/@minimajs/server/error/classes/HttpError.md#name) *** ### response ```ts response: R; ``` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`response`](../../server/@minimajs/server/error/classes/HttpError.md#response) *** ### stack? ```ts optional stack: string; ``` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`stack`](../../server/@minimajs/server/error/classes/HttpError.md#stack) *** ### status ```ts status: number; ``` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`status`](../../server/@minimajs/server/error/classes/HttpError.md#status) *** ### stackTraceLimit ```ts static stackTraceLimit: number; ``` The `Error.stackTraceLimit` property specifies the number of stack frames collected by a stack trace (whether generated by `new Error().stack` or `Error.captureStackTrace(obj)`). The default value is `10` but may be set to any valid JavaScript number. Changes will affect any stack trace captured *after* the value has been changed. If set to a non-number value, or set to a negative number, stack traces will not capture any frames. #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`stackTraceLimit`](../../server/@minimajs/server/error/classes/HttpError.md#stacktracelimit) *** ### toJSON() ```ts static toJSON: (err) => unknown; ``` #### Type Parameters ##### T `T` *extends* [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md)<`unknown`> = [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md)<`unknown`> #### Parameters ##### err `T` #### Returns `unknown` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`toJSON`](../../server/@minimajs/server/error/classes/HttpError.md#tojson) ## Methods ### render() ```ts render(ctx): Promise; ``` #### Parameters ##### ctx [`Context`](../../server/@minimajs/server/interfaces/Context.md) #### Returns `Promise`<`Response`> #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`render`](../../server/@minimajs/server/error/classes/HttpError.md#render) *** ### toJSON() ```ts toJSON(): unknown; ``` #### Returns `unknown` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`toJSON`](../../server/@minimajs/server/error/classes/HttpError.md#tojson-1) *** ### captureStackTrace() #### Call Signature ```ts static captureStackTrace(targetObject, constructorOpt?): void; ``` Creates a `.stack` property on `targetObject`, which when accessed returns a string representing the location in the code at which `Error.captureStackTrace()` was called. ```js const myObject = {}; Error.captureStackTrace(myObject); myObject.stack; // Similar to `new Error().stack` ``` The first line of the trace will be prefixed with `${myObject.name}: ${myObject.message}`. The optional `constructorOpt` argument accepts a function. If given, all frames above `constructorOpt`, including `constructorOpt`, will be omitted from the generated stack trace. The `constructorOpt` argument is useful for hiding implementation details of error generation from the user. For instance: ```js function a() { b(); } function b() { c(); } function c() { // Create an error without stack trace to avoid calculating the stack trace twice. const { stackTraceLimit } = Error; Error.stackTraceLimit = 0; const error = new Error(); Error.stackTraceLimit = stackTraceLimit; // Capture the stack trace above function b Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace throw error; } a(); ``` ##### Parameters ###### targetObject `object` ###### constructorOpt? `Function` ##### Returns `void` ##### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`captureStackTrace`](../../server/@minimajs/server/error/classes/HttpError.md#capturestacktrace) #### Call Signature ```ts static captureStackTrace(targetObject, constructorOpt?): void; ``` Create .stack property on a target object ##### Parameters ###### targetObject `object` ###### constructorOpt? `Function` ##### Returns `void` ##### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`captureStackTrace`](../../server/@minimajs/server/error/classes/HttpError.md#capturestacktrace) *** ### create() ```ts static create(err, status?): HttpError; ``` #### Parameters ##### err `unknown` ##### status? `number` #### Returns [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md)<`string`> #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`create`](../../server/@minimajs/server/error/classes/HttpError.md#create) *** ### is() ```ts static is(value): value is HttpError; ``` #### Parameters ##### value `unknown` #### Returns `value is HttpError` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`is`](../../server/@minimajs/server/error/classes/HttpError.md#is) *** ### isError() #### Call Signature ```ts static isError(error): error is Error; ``` Indicates whether the argument provided is a built-in Error instance or not. ##### Parameters ###### error `unknown` ##### Returns `error is Error` ##### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`isError`](../../server/@minimajs/server/error/classes/HttpError.md#iserror) #### Call Signature ```ts static isError(value): value is Error; ``` Check if a value is an instance of Error ##### Parameters ###### value `unknown` The value to check ##### Returns `value is Error` True if the value is an instance of Error, false otherwise ##### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`isError`](../../server/@minimajs/server/error/classes/HttpError.md#iserror) *** ### prepareStackTrace() ```ts static prepareStackTrace(err, stackTraces): any; ``` #### Parameters ##### err `Error` ##### stackTraces `CallSite`\[] #### Returns `any` #### See https://v8.dev/docs/stack-trace-api#customizing-stack-traces #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`prepareStackTrace`](../../server/@minimajs/server/error/classes/HttpError.md#preparestacktrace) --- --- url: /api/@minimajs/server/@minimajs/server/error/classes/HttpError.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/error](../README.md) / HttpError # Class: HttpError\ Represents the response body of an HTTP error. Can be either a simple string message or a dictionary object with custom error data. ## Extends * [`BaseHttpError`](BaseHttpError.md) ## Extended by * [`NotFoundError`](NotFoundError.md) * [`ValidationError`](ValidationError.md) * [`ForbiddenError`](../../../../../auth/classes/ForbiddenError.md) * [`UnauthorizedError`](../../../../../auth/classes/UnauthorizedError.md) * [`ValidationError`](../../../../../schema/classes/ValidationError.md) ## Type Parameters ### R `R` = `unknown` ## Constructors ### Constructor ```ts new HttpError( response, status, options?): HttpError; ``` #### Parameters ##### response `R` ##### status [`StatusCode`](../../type-aliases/StatusCode.md) ##### options? [`HttpErrorOptions`](../interfaces/HttpErrorOptions.md) #### Returns `HttpError`<`R`> #### Overrides [`BaseHttpError`](BaseHttpError.md).[`constructor`](BaseHttpError.md#constructor) ## Properties ### base? ```ts optional base: unknown; ``` *** ### cause? ```ts optional cause: unknown; ``` The cause of the error. #### Inherited from [`BaseHttpError`](BaseHttpError.md).[`cause`](BaseHttpError.md#cause) *** ### code? ```ts optional code: string; ``` #### Inherited from [`BaseHttpError`](BaseHttpError.md).[`code`](BaseHttpError.md#code) *** ### constructor ```ts constructor: typeof HttpError; ``` The initial value of Object.prototype.constructor is the standard built-in Object constructor. *** ### headers? ```ts optional headers: HeadersInit; ``` *** ### message ```ts message: string; ``` #### Inherited from [`BaseHttpError`](BaseHttpError.md).[`message`](BaseHttpError.md#message) *** ### name ```ts name: string; ``` #### Inherited from [`BaseHttpError`](BaseHttpError.md).[`name`](BaseHttpError.md#name) *** ### response ```ts response: R; ``` *** ### stack? ```ts optional stack: string; ``` #### Inherited from [`BaseHttpError`](BaseHttpError.md).[`stack`](BaseHttpError.md#stack) *** ### status ```ts status: number; ``` #### Overrides [`BaseHttpError`](BaseHttpError.md).[`status`](BaseHttpError.md#status) *** ### stackTraceLimit ```ts static stackTraceLimit: number; ``` The `Error.stackTraceLimit` property specifies the number of stack frames collected by a stack trace (whether generated by `new Error().stack` or `Error.captureStackTrace(obj)`). The default value is `10` but may be set to any valid JavaScript number. Changes will affect any stack trace captured *after* the value has been changed. If set to a non-number value, or set to a negative number, stack traces will not capture any frames. #### Inherited from [`BaseHttpError`](BaseHttpError.md).[`stackTraceLimit`](BaseHttpError.md#stacktracelimit) *** ### toJSON() ```ts static toJSON: (err) => unknown; ``` #### Type Parameters ##### T `T` *extends* `HttpError`<`unknown`> = `HttpError`<`unknown`> #### Parameters ##### err `T` #### Returns `unknown` ## Methods ### render() ```ts render(ctx): Promise; ``` #### Parameters ##### ctx [`Context`](../../interfaces/Context.md) #### Returns `Promise`<`Response`> #### Overrides [`BaseHttpError`](BaseHttpError.md).[`render`](BaseHttpError.md#render) *** ### toJSON() ```ts toJSON(): unknown; ``` #### Returns `unknown` *** ### captureStackTrace() #### Call Signature ```ts static captureStackTrace(targetObject, constructorOpt?): void; ``` Creates a `.stack` property on `targetObject`, which when accessed returns a string representing the location in the code at which `Error.captureStackTrace()` was called. ```js const myObject = {}; Error.captureStackTrace(myObject); myObject.stack; // Similar to `new Error().stack` ``` The first line of the trace will be prefixed with `${myObject.name}: ${myObject.message}`. The optional `constructorOpt` argument accepts a function. If given, all frames above `constructorOpt`, including `constructorOpt`, will be omitted from the generated stack trace. The `constructorOpt` argument is useful for hiding implementation details of error generation from the user. For instance: ```js function a() { b(); } function b() { c(); } function c() { // Create an error without stack trace to avoid calculating the stack trace twice. const { stackTraceLimit } = Error; Error.stackTraceLimit = 0; const error = new Error(); Error.stackTraceLimit = stackTraceLimit; // Capture the stack trace above function b Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace throw error; } a(); ``` ##### Parameters ###### targetObject `object` ###### constructorOpt? `Function` ##### Returns `void` ##### Inherited from [`BaseHttpError`](BaseHttpError.md).[`captureStackTrace`](BaseHttpError.md#capturestacktrace) #### Call Signature ```ts static captureStackTrace(targetObject, constructorOpt?): void; ``` Create .stack property on a target object ##### Parameters ###### targetObject `object` ###### constructorOpt? `Function` ##### Returns `void` ##### Inherited from [`BaseHttpError`](BaseHttpError.md).[`captureStackTrace`](BaseHttpError.md#capturestacktrace) *** ### create() ```ts static create(err, status): HttpError; ``` #### Parameters ##### err `unknown` ##### status `number` = `500` #### Returns `HttpError`<`string`> *** ### is() ```ts static is(value): value is HttpError; ``` #### Parameters ##### value `unknown` #### Returns `value is HttpError` #### Overrides [`BaseHttpError`](BaseHttpError.md).[`is`](BaseHttpError.md#is) *** ### isError() #### Call Signature ```ts static isError(error): error is Error; ``` Indicates whether the argument provided is a built-in Error instance or not. ##### Parameters ###### error `unknown` ##### Returns `error is Error` ##### Inherited from [`BaseHttpError`](BaseHttpError.md).[`isError`](BaseHttpError.md#iserror) #### Call Signature ```ts static isError(value): value is Error; ``` Check if a value is an instance of Error ##### Parameters ###### value `unknown` The value to check ##### Returns `value is Error` True if the value is an instance of Error, false otherwise ##### Inherited from [`BaseHttpError`](BaseHttpError.md).[`isError`](BaseHttpError.md#iserror) *** ### prepareStackTrace() ```ts static prepareStackTrace(err, stackTraces): any; ``` #### Parameters ##### err `Error` ##### stackTraces `CallSite`\[] #### Returns `any` #### See https://v8.dev/docs/stack-trace-api#customizing-stack-traces #### Inherited from [`BaseHttpError`](BaseHttpError.md).[`prepareStackTrace`](BaseHttpError.md#preparestacktrace) --- --- url: /api/@minimajs/server/@minimajs/server/error/classes/NotFoundError.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/error](../README.md) / NotFoundError # Class: NotFoundError\ Represents the response body of an HTTP error. Can be either a simple string message or a dictionary object with custom error data. ## Extends * [`HttpError`](HttpError.md)<`R`> ## Type Parameters ### R `R` = `unknown` ## Constructors ### Constructor ```ts new NotFoundError(response, options?): NotFoundError; ``` The initial value of Object.prototype.constructor is the standard built-in Object constructor. #### Parameters ##### response `R` = `...` ##### options? [`HttpErrorOptions`](../interfaces/HttpErrorOptions.md) #### Returns `NotFoundError`<`R`> #### Overrides [`HttpError`](HttpError.md).[`constructor`](HttpError.md#constructor) ## Properties ### base? ```ts optional base: unknown; ``` #### Inherited from [`HttpError`](HttpError.md).[`base`](HttpError.md#base) *** ### cause? ```ts optional cause: unknown; ``` The cause of the error. #### Inherited from [`HttpError`](HttpError.md).[`cause`](HttpError.md#cause) *** ### code? ```ts optional code: string; ``` #### Inherited from [`HttpError`](HttpError.md).[`code`](HttpError.md#code) *** ### constructor ```ts constructor: typeof HttpError; ``` The initial value of Object.prototype.constructor is the standard built-in Object constructor. #### Inherited from ```ts HttpError.constructor ``` *** ### headers? ```ts optional headers: HeadersInit; ``` #### Inherited from [`HttpError`](HttpError.md).[`headers`](HttpError.md#headers) *** ### message ```ts message: string; ``` #### Inherited from [`HttpError`](HttpError.md).[`message`](HttpError.md#message) *** ### name ```ts name: string; ``` #### Inherited from [`HttpError`](HttpError.md).[`name`](HttpError.md#name) *** ### response ```ts response: R; ``` #### Inherited from [`HttpError`](HttpError.md).[`response`](HttpError.md#response) *** ### stack? ```ts optional stack: string; ``` #### Inherited from [`HttpError`](HttpError.md).[`stack`](HttpError.md#stack) *** ### status ```ts status: number; ``` #### Inherited from [`HttpError`](HttpError.md).[`status`](HttpError.md#status) *** ### stackTraceLimit ```ts static stackTraceLimit: number; ``` The `Error.stackTraceLimit` property specifies the number of stack frames collected by a stack trace (whether generated by `new Error().stack` or `Error.captureStackTrace(obj)`). The default value is `10` but may be set to any valid JavaScript number. Changes will affect any stack trace captured *after* the value has been changed. If set to a non-number value, or set to a negative number, stack traces will not capture any frames. #### Inherited from [`HttpError`](HttpError.md).[`stackTraceLimit`](HttpError.md#stacktracelimit) *** ### toJSON() ```ts static toJSON: (err) => unknown; ``` #### Type Parameters ##### T `T` *extends* [`HttpError`](HttpError.md)<`unknown`> = [`HttpError`](HttpError.md)<`unknown`> #### Parameters ##### err `T` #### Returns `unknown` #### Inherited from [`HttpError`](HttpError.md).[`toJSON`](HttpError.md#tojson) ## Methods ### render() ```ts render(ctx): Promise; ``` #### Parameters ##### ctx [`Context`](../../interfaces/Context.md) #### Returns `Promise`<`Response`> #### Overrides [`HttpError`](HttpError.md).[`render`](HttpError.md#render) *** ### toJSON() ```ts toJSON(): unknown; ``` #### Returns `unknown` #### Inherited from [`HttpError`](HttpError.md).[`toJSON`](HttpError.md#tojson-1) *** ### captureStackTrace() #### Call Signature ```ts static captureStackTrace(targetObject, constructorOpt?): void; ``` Creates a `.stack` property on `targetObject`, which when accessed returns a string representing the location in the code at which `Error.captureStackTrace()` was called. ```js const myObject = {}; Error.captureStackTrace(myObject); myObject.stack; // Similar to `new Error().stack` ``` The first line of the trace will be prefixed with `${myObject.name}: ${myObject.message}`. The optional `constructorOpt` argument accepts a function. If given, all frames above `constructorOpt`, including `constructorOpt`, will be omitted from the generated stack trace. The `constructorOpt` argument is useful for hiding implementation details of error generation from the user. For instance: ```js function a() { b(); } function b() { c(); } function c() { // Create an error without stack trace to avoid calculating the stack trace twice. const { stackTraceLimit } = Error; Error.stackTraceLimit = 0; const error = new Error(); Error.stackTraceLimit = stackTraceLimit; // Capture the stack trace above function b Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace throw error; } a(); ``` ##### Parameters ###### targetObject `object` ###### constructorOpt? `Function` ##### Returns `void` ##### Inherited from [`HttpError`](HttpError.md).[`captureStackTrace`](HttpError.md#capturestacktrace) #### Call Signature ```ts static captureStackTrace(targetObject, constructorOpt?): void; ``` Create .stack property on a target object ##### Parameters ###### targetObject `object` ###### constructorOpt? `Function` ##### Returns `void` ##### Inherited from [`HttpError`](HttpError.md).[`captureStackTrace`](HttpError.md#capturestacktrace) *** ### create() ```ts static create(err, status): HttpError; ``` #### Parameters ##### err `unknown` ##### status `number` = `500` #### Returns [`HttpError`](HttpError.md)<`string`> #### Inherited from [`HttpError`](HttpError.md).[`create`](HttpError.md#create) *** ### is() ```ts static is(value): value is HttpError; ``` #### Parameters ##### value `unknown` #### Returns `value is HttpError` #### Inherited from [`HttpError`](HttpError.md).[`is`](HttpError.md#is) *** ### isError() #### Call Signature ```ts static isError(error): error is Error; ``` Indicates whether the argument provided is a built-in Error instance or not. ##### Parameters ###### error `unknown` ##### Returns `error is Error` ##### Inherited from [`HttpError`](HttpError.md).[`isError`](HttpError.md#iserror) #### Call Signature ```ts static isError(value): value is Error; ``` Check if a value is an instance of Error ##### Parameters ###### value `unknown` The value to check ##### Returns `value is Error` True if the value is an instance of Error, false otherwise ##### Inherited from [`HttpError`](HttpError.md).[`isError`](HttpError.md#iserror) *** ### prepareStackTrace() ```ts static prepareStackTrace(err, stackTraces): any; ``` #### Parameters ##### err `Error` ##### stackTraces `CallSite`\[] #### Returns `any` #### See https://v8.dev/docs/stack-trace-api#customizing-stack-traces #### Inherited from [`HttpError`](HttpError.md).[`prepareStackTrace`](HttpError.md#preparestacktrace) --- --- url: /api/@minimajs/server/@minimajs/server/error/classes/RedirectError.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/error](../README.md) / RedirectError # Class: RedirectError Represents the response body of an HTTP error. Can be either a simple string message or a dictionary object with custom error data. ## Extends * [`BaseHttpError`](BaseHttpError.md) ## Constructors ### Constructor ```ts new RedirectError( url, isPermanent, options?): RedirectError; ``` #### Parameters ##### url `string` ##### isPermanent `boolean` = `false` ##### options? [`HttpErrorOptions`](../interfaces/HttpErrorOptions.md) #### Returns `RedirectError` #### Overrides [`BaseHttpError`](BaseHttpError.md).[`constructor`](BaseHttpError.md#constructor) ## Properties ### cause? ```ts optional cause: unknown; ``` The cause of the error. #### Inherited from [`BaseHttpError`](BaseHttpError.md).[`cause`](BaseHttpError.md#cause) *** ### code? ```ts optional code: string; ``` #### Inherited from [`BaseHttpError`](BaseHttpError.md).[`code`](BaseHttpError.md#code) *** ### headers? ```ts optional headers: HeadersInit; ``` *** ### message ```ts message: string; ``` #### Inherited from [`BaseHttpError`](BaseHttpError.md).[`message`](BaseHttpError.md#message) *** ### name ```ts name: string; ``` #### Inherited from [`BaseHttpError`](BaseHttpError.md).[`name`](BaseHttpError.md#name) *** ### stack? ```ts optional stack: string; ``` #### Inherited from [`BaseHttpError`](BaseHttpError.md).[`stack`](BaseHttpError.md#stack) *** ### status ```ts status: number; ``` #### Overrides [`BaseHttpError`](BaseHttpError.md).[`status`](BaseHttpError.md#status) *** ### url ```ts readonly url: string; ``` *** ### stackTraceLimit ```ts static stackTraceLimit: number; ``` The `Error.stackTraceLimit` property specifies the number of stack frames collected by a stack trace (whether generated by `new Error().stack` or `Error.captureStackTrace(obj)`). The default value is `10` but may be set to any valid JavaScript number. Changes will affect any stack trace captured *after* the value has been changed. If set to a non-number value, or set to a negative number, stack traces will not capture any frames. #### Inherited from [`BaseHttpError`](BaseHttpError.md).[`stackTraceLimit`](BaseHttpError.md#stacktracelimit) ## Methods ### render() ```ts render(__namedParameters): Response; ``` #### Parameters ##### \_\_namedParameters [`Context`](../../interfaces/Context.md) #### Returns `Response` #### Overrides [`BaseHttpError`](BaseHttpError.md).[`render`](BaseHttpError.md#render) *** ### captureStackTrace() #### Call Signature ```ts static captureStackTrace(targetObject, constructorOpt?): void; ``` Creates a `.stack` property on `targetObject`, which when accessed returns a string representing the location in the code at which `Error.captureStackTrace()` was called. ```js const myObject = {}; Error.captureStackTrace(myObject); myObject.stack; // Similar to `new Error().stack` ``` The first line of the trace will be prefixed with `${myObject.name}: ${myObject.message}`. The optional `constructorOpt` argument accepts a function. If given, all frames above `constructorOpt`, including `constructorOpt`, will be omitted from the generated stack trace. The `constructorOpt` argument is useful for hiding implementation details of error generation from the user. For instance: ```js function a() { b(); } function b() { c(); } function c() { // Create an error without stack trace to avoid calculating the stack trace twice. const { stackTraceLimit } = Error; Error.stackTraceLimit = 0; const error = new Error(); Error.stackTraceLimit = stackTraceLimit; // Capture the stack trace above function b Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace throw error; } a(); ``` ##### Parameters ###### targetObject `object` ###### constructorOpt? `Function` ##### Returns `void` ##### Inherited from [`BaseHttpError`](BaseHttpError.md).[`captureStackTrace`](BaseHttpError.md#capturestacktrace) #### Call Signature ```ts static captureStackTrace(targetObject, constructorOpt?): void; ``` Create .stack property on a target object ##### Parameters ###### targetObject `object` ###### constructorOpt? `Function` ##### Returns `void` ##### Inherited from [`BaseHttpError`](BaseHttpError.md).[`captureStackTrace`](BaseHttpError.md#capturestacktrace) *** ### is() ```ts static is(value): value is BaseHttpError; ``` #### Parameters ##### value `unknown` #### Returns `value is BaseHttpError` #### Inherited from [`BaseHttpError`](BaseHttpError.md).[`is`](BaseHttpError.md#is) *** ### isError() #### Call Signature ```ts static isError(error): error is Error; ``` Indicates whether the argument provided is a built-in Error instance or not. ##### Parameters ###### error `unknown` ##### Returns `error is Error` ##### Inherited from [`BaseHttpError`](BaseHttpError.md).[`isError`](BaseHttpError.md#iserror) #### Call Signature ```ts static isError(value): value is Error; ``` Check if a value is an instance of Error ##### Parameters ###### value `unknown` The value to check ##### Returns `value is Error` True if the value is an instance of Error, false otherwise ##### Inherited from [`BaseHttpError`](BaseHttpError.md).[`isError`](BaseHttpError.md#iserror) *** ### prepareStackTrace() ```ts static prepareStackTrace(err, stackTraces): any; ``` #### Parameters ##### err `Error` ##### stackTraces `CallSite`\[] #### Returns `any` #### See https://v8.dev/docs/stack-trace-api#customizing-stack-traces #### Inherited from [`BaseHttpError`](BaseHttpError.md).[`prepareStackTrace`](BaseHttpError.md#preparestacktrace) --- --- url: /api/@minimajs/schema/classes/SchemaError.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/schema](../README.md) / [](../README.md) / SchemaError # Class: SchemaError ## Extends * `Error` ## Constructors ### Constructor ```ts new SchemaError(message?): SchemaError; ``` #### Parameters ##### message? `string` #### Returns `SchemaError` #### Inherited from ```ts Error.constructor ``` ### Constructor ```ts new SchemaError(message?, options?): SchemaError; ``` #### Parameters ##### message? `string` ##### options? `ErrorOptions` #### Returns `SchemaError` #### Inherited from ```ts Error.constructor ``` ## Properties ### cause? ```ts optional cause: unknown; ``` #### Inherited from ```ts Error.cause ``` *** ### message ```ts message: string; ``` #### Inherited from ```ts Error.message ``` *** ### name ```ts name: string; ``` #### Inherited from ```ts Error.name ``` *** ### stack? ```ts optional stack: string; ``` #### Inherited from ```ts Error.stack ``` *** ### stackTraceLimit ```ts static stackTraceLimit: number; ``` The `Error.stackTraceLimit` property specifies the number of stack frames collected by a stack trace (whether generated by `new Error().stack` or `Error.captureStackTrace(obj)`). The default value is `10` but may be set to any valid JavaScript number. Changes will affect any stack trace captured *after* the value has been changed. If set to a non-number value, or set to a negative number, stack traces will not capture any frames. #### Inherited from ```ts Error.stackTraceLimit ``` ## Methods ### captureStackTrace() ```ts static captureStackTrace(targetObject, constructorOpt?): void; ``` Creates a `.stack` property on `targetObject`, which when accessed returns a string representing the location in the code at which `Error.captureStackTrace()` was called. ```js const myObject = {}; Error.captureStackTrace(myObject); myObject.stack; // Similar to `new Error().stack` ``` The first line of the trace will be prefixed with `${myObject.name}: ${myObject.message}`. The optional `constructorOpt` argument accepts a function. If given, all frames above `constructorOpt`, including `constructorOpt`, will be omitted from the generated stack trace. The `constructorOpt` argument is useful for hiding implementation details of error generation from the user. For instance: ```js function a() { b(); } function b() { c(); } function c() { // Create an error without stack trace to avoid calculating the stack trace twice. const { stackTraceLimit } = Error; Error.stackTraceLimit = 0; const error = new Error(); Error.stackTraceLimit = stackTraceLimit; // Capture the stack trace above function b Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace throw error; } a(); ``` #### Parameters ##### targetObject `object` ##### constructorOpt? `Function` #### Returns `void` #### Inherited from ```ts Error.captureStackTrace ``` *** ### isError() ```ts static isError(error): error is Error; ``` Indicates whether the argument provided is a built-in Error instance or not. #### Parameters ##### error `unknown` #### Returns `error is Error` #### Inherited from ```ts Error.isError ``` *** ### prepareStackTrace() ```ts static prepareStackTrace(err, stackTraces): any; ``` #### Parameters ##### err `Error` ##### stackTraces `CallSite`\[] #### Returns `any` #### See https://v8.dev/docs/stack-trace-api#customizing-stack-traces #### Inherited from ```ts Error.prepareStackTrace ``` --- --- url: /api/@minimajs/server/@minimajs/server/classes/Server.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / Server # Class: Server\ ## Type Parameters ### S `S` ## Implements * [`App`](../interfaces/App.md)<`S`> ## Constructors ### Constructor ```ts new Server(adapter, opts): Server; ``` #### Parameters ##### adapter [`ServerAdapter`](../interfaces/ServerAdapter.md)<`S`> ##### opts [`ServerOptions`](../interfaces/ServerOptions.md) #### Returns `Server`<`S`> ## Properties ### $parent ```ts $parent: App | null = null; ``` #### Implementation of [`App`](../interfaces/App.md).[`$parent`](../interfaces/App.md#parent) *** ### $root ```ts $root: App; ``` #### Implementation of [`App`](../interfaces/App.md).[`$root`](../interfaces/App.md#root) *** ### adapter ```ts readonly adapter: ServerAdapter; ``` *** ### container ```ts readonly container: Container; ``` #### Implementation of [`App`](../interfaces/App.md).[`container`](../interfaces/App.md#container) *** ### log ```ts log: Logger; ``` #### Implementation of [`App`](../interfaces/App.md).[`log`](../interfaces/App.md#log) *** ### prefix ```ts prefix: string; ``` #### Implementation of [`App`](../interfaces/App.md).[`prefix`](../interfaces/App.md#prefix) *** ### router ```ts readonly router: Instance; ``` #### Implementation of [`App`](../interfaces/App.md).[`router`](../interfaces/App.md#router) *** ### serialize ```ts serialize: Serializer; ``` #### Implementation of [`App`](../interfaces/App.md).[`serialize`](../interfaces/App.md#serialize) *** ### server? ```ts optional server: S; ``` #### Implementation of [`App`](../interfaces/App.md).[`server`](../interfaces/App.md#server) ## Methods ### all() #### Call Signature ```ts all(path, handler): this; ``` ##### Parameters ###### path `string` ###### handler [`Handler`](../type-aliases/Handler.md)<`S`> ##### Returns `this` ##### Implementation of [`App`](../interfaces/App.md).[`all`](../interfaces/App.md#all) #### Call Signature ```ts all(path, ...args): this; ``` ##### Parameters ###### path `string` ###### args ...\[`...RouteMetaDescriptor[]`, [`Handler`](../type-aliases/Handler.md)<`S`>] ##### Returns `this` ##### Implementation of [`App`](../interfaces/App.md).[`all`](../interfaces/App.md#all) *** ### close() ```ts close(): Promise; ``` #### Returns `Promise`<`void`> #### Implementation of [`App`](../interfaces/App.md).[`close`](../interfaces/App.md#close) *** ### delete() #### Call Signature ```ts delete(path, handler): this; ``` ##### Parameters ###### path `string` ###### handler [`Handler`](../type-aliases/Handler.md)<`S`> ##### Returns `this` ##### Implementation of [`App`](../interfaces/App.md).[`delete`](../interfaces/App.md#delete) #### Call Signature ```ts delete(path, ...args): this; ``` ##### Parameters ###### path `string` ###### args ...\[`...RouteMetaDescriptor[]`, [`Handler`](../type-aliases/Handler.md)<`S`>] ##### Returns `this` ##### Implementation of [`App`](../interfaces/App.md).[`delete`](../interfaces/App.md#delete) *** ### get() #### Call Signature ```ts get(path, handler): this; ``` ##### Parameters ###### path `string` ###### handler [`Handler`](../type-aliases/Handler.md)<`S`> ##### Returns `this` ##### Implementation of [`App`](../interfaces/App.md).[`get`](../interfaces/App.md#get) #### Call Signature ```ts get(path, ...args): this; ``` ##### Parameters ###### path `string` ###### args ...\[`...descriptors: RouteMetaDescriptor[]`, [`Handler`](../type-aliases/Handler.md)<`S`>] ##### Returns `this` ##### Implementation of [`App`](../interfaces/App.md).[`get`](../interfaces/App.md#get) *** ### handle() ```ts handle(request, ctx): Promise; ``` #### Parameters ##### request `Request` ##### ctx [`RequestHandlerContext`](../type-aliases/RequestHandlerContext.md)<`S`> = `{}` #### Returns `Promise`<`Response`> #### Implementation of [`App`](../interfaces/App.md).[`handle`](../interfaces/App.md#handle) *** ### head() #### Call Signature ```ts head(path, handler): this; ``` ##### Parameters ###### path `string` ###### handler [`Handler`](../type-aliases/Handler.md)<`S`> ##### Returns `this` ##### Implementation of [`App`](../interfaces/App.md).[`head`](../interfaces/App.md#head) #### Call Signature ```ts head(path, ...args): this; ``` ##### Parameters ###### path `string` ###### args ...\[`...RouteMetaDescriptor[]`, [`Handler`](../type-aliases/Handler.md)<`S`>] ##### Returns `this` ##### Implementation of [`App`](../interfaces/App.md).[`head`](../interfaces/App.md#head) *** ### listen() ```ts listen(opts): Promise; ``` #### Parameters ##### opts [`ListenOptions`](../interfaces/ListenOptions.md) #### Returns `Promise`<[`AddressInfo`](../interfaces/AddressInfo.md)> *** ### options() #### Call Signature ```ts options(path, handler): this; ``` ##### Parameters ###### path `string` ###### handler [`Handler`](../type-aliases/Handler.md)<`S`> ##### Returns `this` ##### Implementation of [`App`](../interfaces/App.md).[`options`](../interfaces/App.md#options) #### Call Signature ```ts options(path, ...args): this; ``` ##### Parameters ###### path `string` ###### args ...\[`...RouteMetaDescriptor[]`, [`Handler`](../type-aliases/Handler.md)<`S`>] ##### Returns `this` ##### Implementation of [`App`](../interfaces/App.md).[`options`](../interfaces/App.md#options) *** ### patch() #### Call Signature ```ts patch(path, handler): this; ``` ##### Parameters ###### path `string` ###### handler [`Handler`](../type-aliases/Handler.md)<`S`> ##### Returns `this` ##### Implementation of [`App`](../interfaces/App.md).[`patch`](../interfaces/App.md#patch) #### Call Signature ```ts patch(path, ...args): this; ``` ##### Parameters ###### path `string` ###### args ...\[`...RouteMetaDescriptor[]`, [`Handler`](../type-aliases/Handler.md)<`S`>] ##### Returns `this` ##### Implementation of [`App`](../interfaces/App.md).[`patch`](../interfaces/App.md#patch) *** ### post() #### Call Signature ```ts post(path, handler): this; ``` ##### Parameters ###### path `string` ###### handler [`Handler`](../type-aliases/Handler.md)<`S`> ##### Returns `this` ##### Implementation of [`App`](../interfaces/App.md).[`post`](../interfaces/App.md#post) #### Call Signature ```ts post(path, ...args): this; ``` ##### Parameters ###### path `string` ###### args ...\[`...RouteMetaDescriptor[]`, [`Handler`](../type-aliases/Handler.md)<`S`>] ##### Returns `this` ##### Implementation of [`App`](../interfaces/App.md).[`post`](../interfaces/App.md#post) *** ### put() #### Call Signature ```ts put(path, handler): this; ``` ##### Parameters ###### path `string` ###### handler [`Handler`](../type-aliases/Handler.md)<`S`> ##### Returns `this` ##### Implementation of [`App`](../interfaces/App.md).[`put`](../interfaces/App.md#put) #### Call Signature ```ts put(path, ...args): this; ``` ##### Parameters ###### path `string` ###### args ...\[`...RouteMetaDescriptor[]`, [`Handler`](../type-aliases/Handler.md)<`S`>] ##### Returns `this` ##### Implementation of [`App`](../interfaces/App.md).[`put`](../interfaces/App.md#put) *** ### ready() ```ts ready(): Promise; ``` #### Returns `Promise`<`void`> #### Implementation of [`App`](../interfaces/App.md).[`ready`](../interfaces/App.md#ready) *** ### register() #### Call Signature ```ts register(plugin, opts?): this; ``` ##### Type Parameters ###### T `T` *extends* { `name?`: `string`; } ##### Parameters ###### plugin [`Plugin`](../interfaces/Plugin.md)<`S`, `T`> ###### opts? `T` ##### Returns `this` ##### Implementation of [`App`](../interfaces/App.md).[`register`](../interfaces/App.md#register) #### Call Signature ```ts register(plugin): this; ``` ##### Parameters ###### plugin [`PluginSync`](../interfaces/PluginSync.md)<`S`> ##### Returns `this` ##### Implementation of [`App`](../interfaces/App.md).[`register`](../interfaces/App.md#register) #### Call Signature ```ts register(module, opts?): this; ``` ##### Type Parameters ###### T `T` *extends* { `name?`: `string`; `prefix?`: `string`; } ##### Parameters ###### module [`Module`](../interfaces/Module.md)<`S`, `T`> ###### opts? `T` ##### Returns `this` ##### Implementation of [`App`](../interfaces/App.md).[`register`](../interfaces/App.md#register) #### Call Signature ```ts register(plugin, opts?): this; ``` ##### Parameters ###### plugin [`Registerable`](../type-aliases/Registerable.md)<`any`> ###### opts? `any` ##### Returns `this` ##### Implementation of [`App`](../interfaces/App.md).[`register`](../interfaces/App.md#register) *** ### route() #### Call Signature ```ts route(options, handler): this; ``` ##### Parameters ###### options [`RouteOptions`](../interfaces/RouteOptions.md) ###### handler [`Handler`](../type-aliases/Handler.md)<`S`> ##### Returns `this` ##### Implementation of [`App`](../interfaces/App.md).[`route`](../interfaces/App.md#route) #### Call Signature ```ts route(options, ...args): this; ``` ##### Parameters ###### options [`RouteOptions`](../interfaces/RouteOptions.md) ###### args ...\[`...RouteMetaDescriptor[]`, [`Handler`](../type-aliases/Handler.md)<`S`>] ##### Returns `this` ##### Implementation of [`App`](../interfaces/App.md).[`route`](../interfaces/App.md#route) --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/streaming/classes/StreamFile.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [streaming](../README.md) / StreamFile # Class: StreamFile A File subclass that lazily buffers from a stream on first read. ## Extends * `File` ## Constructors ### Constructor ```ts new StreamFile(filename, __namedParameters): StreamFile; ``` #### Parameters ##### filename `string` ##### \_\_namedParameters [`StreamFileInit`](../interfaces/StreamFileInit.md) #### Returns `StreamFile` #### Overrides ```ts File.constructor ``` ## Properties ### lastModified ```ts readonly lastModified: number; ``` #### Inherited from ```ts File.lastModified ``` *** ### name ```ts readonly name: string; ``` #### Inherited from ```ts File.name ``` *** ### type ```ts readonly type: string; ``` #### Inherited from ```ts File.type ``` *** ### webkitRelativePath ```ts readonly webkitRelativePath: string; ``` #### Inherited from ```ts File.webkitRelativePath ``` ## Accessors ### \[toStringTag] #### Get Signature ```ts get toStringTag: string; ``` ##### Returns `string` *** ### size #### Get Signature ```ts get size(): number; ``` ##### Returns `number` #### Overrides ```ts File.size ``` ## Methods ### arrayBuffer() ```ts arrayBuffer(): Promise; ``` #### Returns `Promise`<`ArrayBuffer`> #### Overrides ```ts File.arrayBuffer ``` *** ### bytes() ```ts bytes(): Promise>; ``` #### Returns `Promise`<`Uint8Array`<`ArrayBuffer`>> #### Overrides ```ts File.bytes ``` *** ### slice() ```ts slice(): Blob; ``` #### Returns `Blob` #### Overrides ```ts File.slice ``` *** ### stream() ```ts stream(): ReadableStream>; ``` #### Returns `ReadableStream`<`Uint8Array`<`ArrayBuffer`>> #### Overrides ```ts File.stream ``` *** ### text() ```ts text(): Promise; ``` #### Returns `Promise`<`string`> #### Overrides ```ts File.text ``` *** ### toFile() ```ts toFile(): Promise; ``` Loads the file into memory and returns a standard File object. #### Returns `Promise`<`File`> *** ### toJSON() ```ts toJSON(): { lastModified: number; name: string; size: number; type: string; }; ``` #### Returns ```ts { lastModified: number; name: string; size: number; type: string; } ``` ##### lastModified ```ts lastModified: number; ``` ##### name ```ts name: string; ``` ##### size ```ts size: number; ``` ##### type ```ts type: string; ``` *** ### toReadable() ```ts toReadable(): Readable | null; ``` Creates a Node.js Readable stream from the buffered content. #### Returns `Readable` | `null` --- --- url: /api/@minimajs/multipart/@minimajs/multipart/schema/classes/TempFile.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/multipart](../../../../README.md) / [@minimajs/multipart/schema](../README.md) / TempFile # Class: TempFile ## Extends * `File` ## Constructors ### Constructor ```ts new TempFile(filename, __namedParameters): TempFile; ``` #### Parameters ##### filename `string` ##### \_\_namedParameters [`TempFileInit`](../interfaces/TempFileInit.md) #### Returns `TempFile` #### Overrides ```ts File.constructor ``` ## Properties ### lastModified ```ts readonly lastModified: number; ``` #### Inherited from ```ts File.lastModified ``` *** ### name ```ts readonly name: string; ``` #### Inherited from ```ts File.name ``` *** ### path ```ts readonly path: string; ``` *** ### signal? ```ts readonly optional signal: AbortSignal; ``` *** ### type ```ts readonly type: string; ``` #### Inherited from ```ts File.type ``` *** ### webkitRelativePath ```ts readonly webkitRelativePath: string; ``` #### Inherited from ```ts File.webkitRelativePath ``` ## Accessors ### \[toStringTag] #### Get Signature ```ts get toStringTag: string; ``` ##### Returns `string` *** ### size #### Get Signature ```ts get size(): number; ``` ##### Returns `number` #### Overrides ```ts File.size ``` ## Methods ### arrayBuffer() ```ts arrayBuffer(): Promise; ``` #### Returns `Promise`<`ArrayBuffer`> #### Overrides ```ts File.arrayBuffer ``` *** ### bytes() ```ts bytes(): Promise>; ``` #### Returns `Promise`<`Uint8Array`<`ArrayBuffer`>> #### Overrides ```ts File.bytes ``` *** ### destroy() ```ts destroy(): Promise; ``` Destroys all active streams and deletes the temporary file from disk. Waits for streams that are actively being consumed to finish before deleting. #### Returns `Promise`<`boolean`> *** ### slice() ```ts slice(): Blob; ``` #### Returns `Blob` #### Overrides ```ts File.slice ``` *** ### stream() ```ts stream(): ReadableStream>; ``` #### Returns `ReadableStream`<`Uint8Array`<`ArrayBuffer`>> #### Overrides ```ts File.stream ``` *** ### text() ```ts text(): Promise; ``` #### Returns `Promise`<`string`> #### Overrides ```ts File.text ``` *** ### toFile() ```ts toFile(): Promise; ``` Loads the file into memory and returns a standard File object. #### Returns `Promise`<`File`> *** ### toJSON() ```ts toJSON(): { lastModified: number; name: string; path: string; size: number; type: string; }; ``` #### Returns ```ts { lastModified: number; name: string; path: string; size: number; type: string; } ``` ##### lastModified ```ts lastModified: number; ``` ##### name ```ts name: string; ``` ##### path ```ts path: string; ``` ##### size ```ts size: number; ``` ##### type ```ts type: string; ``` *** ### toReadable() ```ts toReadable(): Readable; ``` Creates a Node.js Readable stream from the temporary file. Multiple streams can be created; all are tracked for cleanup. #### Returns `Readable` --- --- url: /api/@minimajs/auth/classes/UnauthorizedError.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/auth](../README.md) / UnauthorizedError # Class: UnauthorizedError\ Represents the response body of an HTTP error. Can be either a simple string message or a dictionary object with custom error data. ## Extends * [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md)<`R`> ## Type Parameters ### R `R` ## Constructors ### Constructor ```ts new UnauthorizedError(response): UnauthorizedError; ``` The initial value of Object.prototype.constructor is the standard built-in Object constructor. #### Parameters ##### response `R` = `...` #### Returns `UnauthorizedError`<`R`> #### Overrides [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`constructor`](../../server/@minimajs/server/error/classes/HttpError.md#constructor) ## Properties ### base? ```ts optional base: unknown; ``` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`base`](../../server/@minimajs/server/error/classes/HttpError.md#base) *** ### cause? ```ts optional cause: unknown; ``` The cause of the error. #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`cause`](../../server/@minimajs/server/error/classes/HttpError.md#cause) *** ### code? ```ts optional code: string; ``` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`code`](../../server/@minimajs/server/error/classes/HttpError.md#code) *** ### constructor ```ts constructor: typeof HttpError; ``` The initial value of Object.prototype.constructor is the standard built-in Object constructor. #### Inherited from ```ts HttpError.constructor ``` *** ### headers? ```ts optional headers: HeadersInit; ``` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`headers`](../../server/@minimajs/server/error/classes/HttpError.md#headers) *** ### message ```ts message: string; ``` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`message`](../../server/@minimajs/server/error/classes/HttpError.md#message) *** ### name ```ts name: string; ``` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`name`](../../server/@minimajs/server/error/classes/HttpError.md#name) *** ### response ```ts response: R; ``` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`response`](../../server/@minimajs/server/error/classes/HttpError.md#response) *** ### stack? ```ts optional stack: string; ``` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`stack`](../../server/@minimajs/server/error/classes/HttpError.md#stack) *** ### status ```ts status: number; ``` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`status`](../../server/@minimajs/server/error/classes/HttpError.md#status) *** ### stackTraceLimit ```ts static stackTraceLimit: number; ``` The `Error.stackTraceLimit` property specifies the number of stack frames collected by a stack trace (whether generated by `new Error().stack` or `Error.captureStackTrace(obj)`). The default value is `10` but may be set to any valid JavaScript number. Changes will affect any stack trace captured *after* the value has been changed. If set to a non-number value, or set to a negative number, stack traces will not capture any frames. #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`stackTraceLimit`](../../server/@minimajs/server/error/classes/HttpError.md#stacktracelimit) *** ### toJSON() ```ts static toJSON: (err) => unknown; ``` #### Type Parameters ##### T `T` *extends* [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md)<`unknown`> = [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md)<`unknown`> #### Parameters ##### err `T` #### Returns `unknown` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`toJSON`](../../server/@minimajs/server/error/classes/HttpError.md#tojson) ## Methods ### render() ```ts render(ctx): Promise; ``` #### Parameters ##### ctx [`Context`](../../server/@minimajs/server/interfaces/Context.md) #### Returns `Promise`<`Response`> #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`render`](../../server/@minimajs/server/error/classes/HttpError.md#render) *** ### toJSON() ```ts toJSON(): unknown; ``` #### Returns `unknown` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`toJSON`](../../server/@minimajs/server/error/classes/HttpError.md#tojson-1) *** ### captureStackTrace() #### Call Signature ```ts static captureStackTrace(targetObject, constructorOpt?): void; ``` Creates a `.stack` property on `targetObject`, which when accessed returns a string representing the location in the code at which `Error.captureStackTrace()` was called. ```js const myObject = {}; Error.captureStackTrace(myObject); myObject.stack; // Similar to `new Error().stack` ``` The first line of the trace will be prefixed with `${myObject.name}: ${myObject.message}`. The optional `constructorOpt` argument accepts a function. If given, all frames above `constructorOpt`, including `constructorOpt`, will be omitted from the generated stack trace. The `constructorOpt` argument is useful for hiding implementation details of error generation from the user. For instance: ```js function a() { b(); } function b() { c(); } function c() { // Create an error without stack trace to avoid calculating the stack trace twice. const { stackTraceLimit } = Error; Error.stackTraceLimit = 0; const error = new Error(); Error.stackTraceLimit = stackTraceLimit; // Capture the stack trace above function b Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace throw error; } a(); ``` ##### Parameters ###### targetObject `object` ###### constructorOpt? `Function` ##### Returns `void` ##### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`captureStackTrace`](../../server/@minimajs/server/error/classes/HttpError.md#capturestacktrace) #### Call Signature ```ts static captureStackTrace(targetObject, constructorOpt?): void; ``` Create .stack property on a target object ##### Parameters ###### targetObject `object` ###### constructorOpt? `Function` ##### Returns `void` ##### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`captureStackTrace`](../../server/@minimajs/server/error/classes/HttpError.md#capturestacktrace) *** ### create() ```ts static create(err, status?): HttpError; ``` #### Parameters ##### err `unknown` ##### status? `number` #### Returns [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md)<`string`> #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`create`](../../server/@minimajs/server/error/classes/HttpError.md#create) *** ### is() ```ts static is(value): value is HttpError; ``` #### Parameters ##### value `unknown` #### Returns `value is HttpError` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`is`](../../server/@minimajs/server/error/classes/HttpError.md#is) *** ### isError() #### Call Signature ```ts static isError(error): error is Error; ``` Indicates whether the argument provided is a built-in Error instance or not. ##### Parameters ###### error `unknown` ##### Returns `error is Error` ##### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`isError`](../../server/@minimajs/server/error/classes/HttpError.md#iserror) #### Call Signature ```ts static isError(value): value is Error; ``` Check if a value is an instance of Error ##### Parameters ###### value `unknown` The value to check ##### Returns `value is Error` True if the value is an instance of Error, false otherwise ##### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`isError`](../../server/@minimajs/server/error/classes/HttpError.md#iserror) *** ### prepareStackTrace() ```ts static prepareStackTrace(err, stackTraces): any; ``` #### Parameters ##### err `Error` ##### stackTraces `CallSite`\[] #### Returns `any` #### See https://v8.dev/docs/stack-trace-api#customizing-stack-traces #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`prepareStackTrace`](../../server/@minimajs/server/error/classes/HttpError.md#preparestacktrace) --- --- url: /api/@minimajs/schema/classes/ValidationError.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/schema](../README.md) / [](../README.md) / ValidationError # Class: ValidationError Custom validation error class for schema validation failures. Extends the base HTTP error with validation-specific properties and methods. Provides integration with Zod validation errors and enhanced error reporting. ## Extends * [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md) ## Constructors ### Constructor ```ts new ValidationError(message, extend): ValidationError; ``` Creates a new ValidationError instance. #### Parameters ##### message `string` ##### extend [`ValidatorErrorOptions`](../interfaces/ValidatorErrorOptions.md) = `{}` #### Returns `ValidationError` #### Example ```ts const error = new ValidationError('Validation failed'); ``` #### Overrides [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`constructor`](../../server/@minimajs/server/error/classes/HttpError.md#constructor) ## Properties ### base? ```ts optional base: unknown; ``` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`base`](../../server/@minimajs/server/error/classes/HttpError.md#base) *** ### cause? ```ts optional cause: unknown; ``` The cause of the error. #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`cause`](../../server/@minimajs/server/error/classes/HttpError.md#cause) *** ### code? ```ts optional code: string; ``` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`code`](../../server/@minimajs/server/error/classes/HttpError.md#code) *** ### constructor ```ts constructor: typeof HttpError; ``` The initial value of Object.prototype.constructor is the standard built-in Object constructor. #### Inherited from ```ts BaseError.constructor ``` *** ### headers? ```ts optional headers: HeadersInit; ``` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`headers`](../../server/@minimajs/server/error/classes/HttpError.md#headers) *** ### issues? ```ts optional issues: $ZodIssue[]; ``` Array of zod issues *** ### message ```ts message: string; ``` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`message`](../../server/@minimajs/server/error/classes/HttpError.md#message) *** ### name ```ts name: string = ValidationError.name; ``` The name of this error class #### Overrides [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`name`](../../server/@minimajs/server/error/classes/HttpError.md#name) *** ### response ```ts response: unknown; ``` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`response`](../../server/@minimajs/server/error/classes/HttpError.md#response) *** ### stack? ```ts optional stack: string; ``` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`stack`](../../server/@minimajs/server/error/classes/HttpError.md#stack) *** ### status ```ts status: number; ``` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`status`](../../server/@minimajs/server/error/classes/HttpError.md#status) *** ### stackTraceLimit ```ts static stackTraceLimit: number; ``` The `Error.stackTraceLimit` property specifies the number of stack frames collected by a stack trace (whether generated by `new Error().stack` or `Error.captureStackTrace(obj)`). The default value is `10` but may be set to any valid JavaScript number. Changes will affect any stack trace captured *after* the value has been changed. If set to a non-number value, or set to a negative number, stack traces will not capture any frames. #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`stackTraceLimit`](../../server/@minimajs/server/error/classes/HttpError.md#stacktracelimit) ## Methods ### render() ```ts render(ctx): Promise; ``` #### Parameters ##### ctx [`Context`](../../server/@minimajs/server/interfaces/Context.md) #### Returns `Promise`<`Response`> #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`render`](../../server/@minimajs/server/error/classes/HttpError.md#render) *** ### toJSON() ```ts toJSON(): unknown; ``` #### Returns `unknown` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`toJSON`](../../server/@minimajs/server/error/classes/HttpError.md#tojson-1) *** ### captureStackTrace() ```ts static captureStackTrace(targetObject, constructorOpt?): void; ``` Creates a `.stack` property on `targetObject`, which when accessed returns a string representing the location in the code at which `Error.captureStackTrace()` was called. ```js const myObject = {}; Error.captureStackTrace(myObject); myObject.stack; // Similar to `new Error().stack` ``` The first line of the trace will be prefixed with `${myObject.name}: ${myObject.message}`. The optional `constructorOpt` argument accepts a function. If given, all frames above `constructorOpt`, including `constructorOpt`, will be omitted from the generated stack trace. The `constructorOpt` argument is useful for hiding implementation details of error generation from the user. For instance: ```js function a() { b(); } function b() { c(); } function c() { // Create an error without stack trace to avoid calculating the stack trace twice. const { stackTraceLimit } = Error; Error.stackTraceLimit = 0; const error = new Error(); Error.stackTraceLimit = stackTraceLimit; // Capture the stack trace above function b Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace throw error; } a(); ``` #### Parameters ##### targetObject `object` ##### constructorOpt? `Function` #### Returns `void` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`captureStackTrace`](../../server/@minimajs/server/error/classes/HttpError.md#capturestacktrace) *** ### create() ```ts static create(err, status?): HttpError; ``` #### Parameters ##### err `unknown` ##### status? `number` #### Returns [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md)<`string`> #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`create`](../../server/@minimajs/server/error/classes/HttpError.md#create) *** ### createFromZodError() ```ts static createFromZodError(error): ValidationError; ``` Creates a ValidationError from a ZodError. Recursively converts nested validation errors. #### Parameters ##### error `ZodError` #### Returns `ValidationError` #### Example ```ts try { await schema.parse(data); } catch (err) { if (err instanceof ZodError) { const validationError = ValidationError.createFromZodError(err); throw validationError; } } ``` *** ### is() ```ts static is(value): value is HttpError; ``` #### Parameters ##### value `unknown` #### Returns `value is HttpError` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`is`](../../server/@minimajs/server/error/classes/HttpError.md#is) *** ### isError() ```ts static isError(error): error is Error; ``` Indicates whether the argument provided is a built-in Error instance or not. #### Parameters ##### error `unknown` #### Returns `error is Error` #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`isError`](../../server/@minimajs/server/error/classes/HttpError.md#iserror) *** ### prepareStackTrace() ```ts static prepareStackTrace(err, stackTraces): any; ``` #### Parameters ##### err `Error` ##### stackTraces `CallSite`\[] #### Returns `any` #### See https://v8.dev/docs/stack-trace-api#customizing-stack-traces #### Inherited from [`HttpError`](../../server/@minimajs/server/error/classes/HttpError.md).[`prepareStackTrace`](../../server/@minimajs/server/error/classes/HttpError.md#preparestacktrace) *** ### toJSON() ```ts static toJSON(err): unknown; ``` Serializes a ValidationError to JSON for HTTP responses. #### Parameters ##### err `ValidationError` #### Returns `unknown` #### Throws AssertionError if err is not a ValidationError instance #### Example ```ts const json = ValidationError.toJSON(error); // { // "message": "Validation failed for 'email'", // "issues": [ // { // "code": "invalid_type", // "expected": "string", // "received": "undefined", // "path": ["email"], // "message": "Required" // } // ] // } ``` #### Overrides ```ts BaseError.toJSON ``` --- --- url: /api/@minimajs/server/@minimajs/server/error/classes/ValidationError.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/error](../README.md) / ValidationError # Class: ValidationError\ Represents the response body of an HTTP error. Can be either a simple string message or a dictionary object with custom error data. ## Extends * [`HttpError`](HttpError.md)<`R`> ## Type Parameters ### R `R` = `unknown` ## Constructors ### Constructor ```ts new ValidationError(response, options?): ValidationError; ``` The initial value of Object.prototype.constructor is the standard built-in Object constructor. #### Parameters ##### response `R` = `...` ##### options? [`HttpErrorOptions`](../interfaces/HttpErrorOptions.md) #### Returns `ValidationError`<`R`> #### Overrides [`HttpError`](HttpError.md).[`constructor`](HttpError.md#constructor) ## Properties ### base? ```ts optional base: unknown; ``` #### Inherited from [`HttpError`](HttpError.md).[`base`](HttpError.md#base) *** ### cause? ```ts optional cause: unknown; ``` The cause of the error. #### Inherited from [`HttpError`](HttpError.md).[`cause`](HttpError.md#cause) *** ### code? ```ts optional code: string; ``` #### Inherited from [`HttpError`](HttpError.md).[`code`](HttpError.md#code) *** ### constructor ```ts constructor: typeof HttpError; ``` The initial value of Object.prototype.constructor is the standard built-in Object constructor. #### Inherited from ```ts HttpError.constructor ``` *** ### headers? ```ts optional headers: HeadersInit; ``` #### Inherited from [`HttpError`](HttpError.md).[`headers`](HttpError.md#headers) *** ### message ```ts message: string; ``` #### Inherited from [`HttpError`](HttpError.md).[`message`](HttpError.md#message) *** ### name ```ts name: string; ``` #### Inherited from [`HttpError`](HttpError.md).[`name`](HttpError.md#name) *** ### response ```ts response: R; ``` #### Inherited from [`HttpError`](HttpError.md).[`response`](HttpError.md#response) *** ### stack? ```ts optional stack: string; ``` #### Inherited from [`HttpError`](HttpError.md).[`stack`](HttpError.md#stack) *** ### status ```ts status: number; ``` #### Inherited from [`HttpError`](HttpError.md).[`status`](HttpError.md#status) *** ### getStatusCode() ```ts static getStatusCode: (_error) => number; ``` #### Type Parameters ##### T `T` *extends* `ValidationError`<`unknown`> #### Parameters ##### \_error `T` #### Returns `number` *** ### stackTraceLimit ```ts static stackTraceLimit: number; ``` The `Error.stackTraceLimit` property specifies the number of stack frames collected by a stack trace (whether generated by `new Error().stack` or `Error.captureStackTrace(obj)`). The default value is `10` but may be set to any valid JavaScript number. Changes will affect any stack trace captured *after* the value has been changed. If set to a non-number value, or set to a negative number, stack traces will not capture any frames. #### Inherited from [`HttpError`](HttpError.md).[`stackTraceLimit`](HttpError.md#stacktracelimit) *** ### toJSON() ```ts static toJSON: (err) => unknown; ``` #### Type Parameters ##### T `T` *extends* [`HttpError`](HttpError.md)<`unknown`> = [`HttpError`](HttpError.md)<`unknown`> #### Parameters ##### err `T` #### Returns `unknown` #### Inherited from [`HttpError`](HttpError.md).[`toJSON`](HttpError.md#tojson) ## Methods ### render() ```ts render(ctx): Promise; ``` #### Parameters ##### ctx [`Context`](../../interfaces/Context.md) #### Returns `Promise`<`Response`> #### Inherited from [`HttpError`](HttpError.md).[`render`](HttpError.md#render) *** ### toJSON() ```ts toJSON(): unknown; ``` #### Returns `unknown` #### Inherited from [`HttpError`](HttpError.md).[`toJSON`](HttpError.md#tojson-1) *** ### captureStackTrace() #### Call Signature ```ts static captureStackTrace(targetObject, constructorOpt?): void; ``` Creates a `.stack` property on `targetObject`, which when accessed returns a string representing the location in the code at which `Error.captureStackTrace()` was called. ```js const myObject = {}; Error.captureStackTrace(myObject); myObject.stack; // Similar to `new Error().stack` ``` The first line of the trace will be prefixed with `${myObject.name}: ${myObject.message}`. The optional `constructorOpt` argument accepts a function. If given, all frames above `constructorOpt`, including `constructorOpt`, will be omitted from the generated stack trace. The `constructorOpt` argument is useful for hiding implementation details of error generation from the user. For instance: ```js function a() { b(); } function b() { c(); } function c() { // Create an error without stack trace to avoid calculating the stack trace twice. const { stackTraceLimit } = Error; Error.stackTraceLimit = 0; const error = new Error(); Error.stackTraceLimit = stackTraceLimit; // Capture the stack trace above function b Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace throw error; } a(); ``` ##### Parameters ###### targetObject `object` ###### constructorOpt? `Function` ##### Returns `void` ##### Inherited from [`HttpError`](HttpError.md).[`captureStackTrace`](HttpError.md#capturestacktrace) #### Call Signature ```ts static captureStackTrace(targetObject, constructorOpt?): void; ``` Create .stack property on a target object ##### Parameters ###### targetObject `object` ###### constructorOpt? `Function` ##### Returns `void` ##### Inherited from [`HttpError`](HttpError.md).[`captureStackTrace`](HttpError.md#capturestacktrace) *** ### create() ```ts static create(err, status): HttpError; ``` #### Parameters ##### err `unknown` ##### status `number` = `500` #### Returns [`HttpError`](HttpError.md)<`string`> #### Inherited from [`HttpError`](HttpError.md).[`create`](HttpError.md#create) *** ### is() ```ts static is(value): value is HttpError; ``` #### Parameters ##### value `unknown` #### Returns `value is HttpError` #### Inherited from [`HttpError`](HttpError.md).[`is`](HttpError.md#is) *** ### isError() #### Call Signature ```ts static isError(error): error is Error; ``` Indicates whether the argument provided is a built-in Error instance or not. ##### Parameters ###### error `unknown` ##### Returns `error is Error` ##### Inherited from [`HttpError`](HttpError.md).[`isError`](HttpError.md#iserror) #### Call Signature ```ts static isError(value): value is Error; ``` Check if a value is an instance of Error ##### Parameters ###### value `unknown` The value to check ##### Returns `value is Error` True if the value is an instance of Error, false otherwise ##### Inherited from [`HttpError`](HttpError.md).[`isError`](HttpError.md#iserror) *** ### prepareStackTrace() ```ts static prepareStackTrace(err, stackTraces): any; ``` #### Parameters ##### err `Error` ##### stackTraces `CallSite`\[] #### Returns `any` #### See https://v8.dev/docs/stack-trace-api#customizing-stack-traces #### Inherited from [`HttpError`](HttpError.md).[`prepareStackTrace`](HttpError.md#preparestacktrace) --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/compose/README.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server](../../README.md) / compose # compose ## Functions | Function | Description | | ------ | ------ | | [create](functions/create.md) | Creates a higher-order function that applies multiple plugins to a module. This allows you to pre-configure a set of plugins and apply them to different modules. | --- --- url: /advanced/container-encapsulation.md --- # Container and Encapsulation Minima.js uses a container system to manage application state and plugin settings with automatic encapsulation. The container allows you to store configuration, database connections, and other resources in a way that respects module boundaries. ## What is a Container? The container is a storage object accessible via `app.container` that uses Symbol keys to avoid naming collisions. You can store any data your plugins or application needs: ```typescript const kMyData = Symbol("my-data"); app.register((instance) => { // Store data in container instance.container[kMyData] = { some: "data" }; // Access later const data = instance.container[kMyData]; }); ``` ## Encapsulation When you register a plugin or module, Minima.js creates a **new child context with a cloned container**. This ensures plugin isolation while maintaining inheritance from the parent. ### How Encapsulation Works The container uses three cloning strategies: | Value Type | Behavior | Example | | ---------------------- | -------------------- | ------------------------------- | | Array | Shallow copy | Module chains, arrays of config | | Object with `.clone()` | Deep copy via method | Custom settings classes | | Everything else | Shared reference | Database pools, primitives | This means: * **Arrays** in child modules don't affect parent arrays * **Cloneable objects** get independent copies * **Other values** (objects, connections, primitives) are **shared** across modules ### Example: Basic Encapsulation ```typescript const kConfig = Symbol("config"); // Root level - shared reference app.container[kConfig] = { timeout: 5000 }; app.register((child) => { // Child inherits the same reference console.log(child.container[kConfig]); // { timeout: 5000 } // To isolate: create new object child.container[kConfig] = { timeout: 10000 }; }); ``` ## Common Use Cases ### 1. Shared Database Connection Store database pools that are shared across all modules: ```typescript const kDbPool = Symbol("database-pool"); export function databasePlugin(connectionString: string) { return async (app: App) => { const pool = await createPool(connectionString); // Store in container (shared by reference) app.container[kDbPool] = pool; // Clean up on shutdown app.register( hook("close", async () => { await pool.end(); }) ); }; } // Access in any route app.register(databasePlugin("postgresql://...")); app.get("/users", async (ctx) => { const pool = ctx.app.container[kDbPool]; const result = await pool.query("SELECT * FROM users"); return result.rows; }); ``` ### 2. Module-Specific Settings Override settings for specific modules: ```typescript const kTheme = Symbol("theme"); // Root theme app.container[kTheme] = "light"; app.get("/", (ctx) => { return { theme: ctx.app.container[kTheme] }; // "light" }); // Admin module with different theme app.register((admin) => { admin.container[kTheme] = "dark"; admin.get("/admin", (ctx) => { return { theme: ctx.app.container[kTheme] }; // "dark" }); }); ``` ### 3. Feature Flags Manage feature flags with inheritance: ```typescript const kFeatures = Symbol("features"); interface Features { newUI: boolean; betaAPI: boolean; } // Root features app.container[kFeatures] = { newUI: false, betaAPI: false, }; // Beta module enables beta features app.register("/beta", (beta) => { // Override with new object beta.container[kFeatures] = { ...beta.container[kFeatures], betaAPI: true, }; beta.get("/feature", (ctx) => { const features = ctx.app.container[kFeatures] as Features; if (!features.betaAPI) { throw new Error("Beta API not enabled"); } return { status: "beta" }; }); }); ``` ### 4. Cloneable Configuration Objects For more control over encapsulation, create objects with a `.clone()` method: ```typescript const kSettings = Symbol("settings"); class Settings { constructor( public timeout: number, public retries: number ) {} clone(): Settings { return new Settings(this.timeout, this.retries); } } // Root settings app.container[kSettings] = new Settings(5000, 3); // Child gets automatic clone app.register((child) => { const settings = child.container[kSettings] as Settings; settings.timeout = 10000; // Only affects child console.log(app.container[kSettings].timeout); // 5000 console.log(child.container[kSettings].timeout); // 10000 }); ``` ## Multi-Tenant Applications Containers are perfect for multi-tenant scenarios where each request needs tenant-specific resources: ```typescript const kTenant = Symbol("tenant"); const kDatabase = Symbol("database"); interface Tenant { id: string; name: string; dbName: string; } // Identify tenant from request app.addHook("request", async (ctx) => { const subdomain = ctx.request.headers.get("host")?.split(".")[0]; const tenant = await findTenant(subdomain); ctx.app.container[kTenant] = tenant; // Get tenant-specific database const db = await getDatabase(tenant.dbName); ctx.app.container[kDatabase] = db; }); // Routes automatically have tenant context app.get("/data", async (ctx) => { const tenant = ctx.app.container[kTenant] as Tenant; const db = ctx.app.container[kDatabase]; const data = await db.query("SELECT * FROM data"); return { tenant: tenant.name, data }; }); ``` ## Best Practices ### 1. Always Use Symbol Keys Symbols prevent naming collisions between plugins: ```typescript // Good - unique per plugin export const kMyPlugin = Symbol("my-plugin"); // Bad - can collide (also TypeScript error) app.container["myPlugin"] = data; ``` ### 2. Export Your Symbols Allow users to access your plugin's container data: ```typescript // plugin.ts export const kAuth = Symbol("auth"); export function authPlugin() { return (app: App) => { app.container[kAuth] = createAuthState(); }; } // user.ts import { kAuth } from "./plugin.ts"; app.get("/", (ctx) => { const auth = ctx.app.container[kAuth]; }); ``` ### 3. Clean Up Resources Always clean up in the `close` hook: ```typescript app.register((instance) => { const resource = createResource(); instance.container[kResource] = resource; instance.addHook("close", async () => { await resource.cleanup(); }); }); ``` ### 4. Type Your Container Values Create typed helpers for better DX: ```typescript const kConfig = Symbol("config"); interface Config { apiKey: string; timeout: number; } function getConfig(app: App): Config { if (!(kConfig in app.container)) { throw new Error("Config not initialized"); } return app.container[kConfig] as Config; } function setConfig(app: App, config: Config): void { app.container[kConfig] = config; } // Usage with type safety app.register((instance) => { setConfig(instance, { apiKey: "secret", timeout: 5000, }); }); app.get("/", (ctx) => { const config = getConfig(ctx.app); return { timeout: config.timeout }; }); ``` ### 5. Prefer Immutability Create new objects instead of mutating shared ones: ```typescript // Good - creates new object child.container[kConfig] = { ...parent.container[kConfig], newValue: true, }; // Bad - mutates parent's config (child.container[kConfig] as any).newValue = true; ``` ## Encapsulation in Action ### Example: Isolated Error Handlers Different modules can have different error handling: ```typescript const kErrorFormat = Symbol("error-format"); // Root error format app.container[kErrorFormat] = "json"; app.setErrorHandler((error, ctx) => { const format = ctx.app.container[kErrorFormat]; if (format === "json") { return { error: error.message }; } return error.message; }); // API module uses JSON (inherited) app.register("/api", (api) => { api.get("/data", () => { throw new Error("API error"); // Returns: { error: "API error" } }); }); // Admin module uses plain text app.register("/admin", (admin) => { admin.container[kErrorFormat] = "text"; admin.get("/panel", () => { throw new Error("Admin error"); // Returns: "Admin error" }); }); ``` ### Example: Per-Module Rate Limiting Apply different rate limits to different modules: ```typescript const kRateLimit = Symbol("rate-limit"); interface RateLimit { requests: number; window: number; } // Default rate limit app.container[kRateLimit] = { requests: 100, window: 60000 }; // Public API - strict limits app.register("/api/public", (pub) => { pub.container[kRateLimit] = { requests: 10, window: 60000 }; pub.addHook("request", async (ctx) => { const limit = ctx.app.container[kRateLimit] as RateLimit; await checkRateLimit(ctx.request, limit); }); }); // Internal API - relaxed limits app.register("/api/internal", (internal) => { internal.container[kRateLimit] = { requests: 1000, window: 60000 }; }); ``` ## Understanding Inheritance Container values follow the module hierarchy: ```typescript const kValue = Symbol("value"); app.container[kValue] = "root"; app.register("/level1", (l1) => { console.log(l1.container[kValue]); // "root" - inherited l1.register("/level2", (l2) => { console.log(l2.container[kValue]); // "root" - inherited // Override for this branch l2.container[kValue] = "level2"; l2.register("/level3", (l3) => { console.log(l3.container[kValue]); // "level2" - inherited from parent }); }); }); // Sibling branch still has root value app.register("/other", (other) => { console.log(other.container[kValue]); // "root" }); ``` ## Next Steps * Learn about [Custom Adapters](./custom-adapters.md) * Explore [Plugin Development](../core-concepts/plugins.md) * See [Architecture Overview](../core-concepts/architecture.md) * See [Encapsulation Diagrams](../core-concepts/diagrams/encapsulation.md) --- --- url: /core-concepts/context.md --- # Context: Access Data from Anywhere In many Node.js frameworks, you need to pass `request` and `response` objects down through your application's layers. This "prop drilling" can lead to cluttered code and tight coupling. Minima.js solves this with a powerful **Context** system, powered by Node.js's native `AsyncLocalStorage` API. Each request gets its own context, and you can access request-specific data from **anywhere** in your code without passing `req` or `res`. ## Access the Full Request Context with `context()` Use `context()` when you need the complete request scope in one object. It exposes the request, response state, route info, and per-request locals. ```typescript import { context, type Routes } from "@minimajs/server"; function auditRequest() { const ctx = context(); const method = ctx.request.method; const path = ctx.pathname; const routeName = ctx.route?.path ?? "unknown"; console.log(`[AUDIT] ${method} ${path} (${routeName})`); } export const routes: Routes = { "GET /users/:id": () => { auditRequest(); return { id: "123" }; }, }; ``` **Common fields on `context()`:** * `request` - native Web API `Request` * `responseState` - mutable headers/status * `pathname` - current request path * `route` - matched route (if any) * `locals` - per-request storage > **Note:** `context()` only works inside a request lifecycle. Calling it outside a request will throw. ## Create Your Own Context with `createContext` To create custom request-scoped storage, use the `createContext` function from `@minimajs/server`. ```typescript import { createContext } from "@minimajs/server"; // Create a context to store a request-specific trace ID const [getTraceId, setTraceId] = createContext(""); ``` This returns a tuple with a **getter** (`getTraceId`) and a **setter** (`setTraceId`). Here's how you might use it to apply a `traceId` to every request using a middleware plugin. ```typescript import { createApp, hook } from "@minimajs/server"; import { randomUUID } from "crypto"; // 1. Define a hook plugin that runs on every request. const traceIdPlugin = hook("request", () => { const traceId = randomUUID(); setTraceId(traceId); }); function someDeeplyNestedFunction() { // 3. We can access the trace ID here without any prop drilling! const traceId = getTraceId(); console.log(`Trace ID: ${traceId}`); } async function mainModule(app) { app.get("/", () => { someDeeplyNestedFunction(); return { message: "Hello, World!" }; }); } const app = createApp(); // 2. Apply the middleware plugin to your app. app.register(traceIdPlugin); app.register(mainModule); await app.listen({ port: 3000 }); ``` As you can see, `someDeeplyNestedFunction` can access the `traceId` without having it passed as a parameter. ## Benefits of Using Context * **Cleaner Code:** Eliminates the need to pass `req` and `res` everywhere. * **Decoupling:** Your business logic doesn't need to be aware of the underlying HTTP framework. * **Easier Third-Party Integration:** Integrate libraries that don't have direct access to `req`/`res` objects. * **Improved Testability:** Your functions become easier to test in isolation. --- --- url: /advanced/context-provider.md --- # Context Provider The `contextProvider` plugin controls how Minima.js manages async context using Node.js `AsyncLocalStorage`. Use this to change the default async context behavior. ## How It Works Minima.js uses `AsyncLocalStorage` to maintain request context across async operations. The `contextProvider` plugin lets you configure how this context is established. ```typescript import { contextProvider } from "@minimajs/server/plugins"; import { executionContext } from "@minimajs/server"; app.register(contextProvider((ctx, next) => executionContext.run(ctx, next))); ``` The `contextProvider` callback receives: * `ctx` - The request context * `next` - Function to continue the middleware chain ## Default: `executionContext.run` By default, Minima.js uses `executionContext.run()` which creates an isolated async context for each request: ```typescript import { contextProvider } from "@minimajs/server/plugins"; import { executionContext } from "@minimajs/server"; // This is the default - no need to register manually app.register( contextProvider((ctx, next) => { return executionContext.run(ctx, next); }) ); ``` **Characteristics:** * Each request gets its own isolated context * Context is automatically cleaned up when the request completes * Safe for concurrent requests * Recommended for most use cases ## Alternative: `executionContext.enterWith` For scenarios where you need the context to persist beyond the callback scope, use `enterWith`: ```typescript import { contextProvider } from "@minimajs/server/plugins"; import { executionContext } from "@minimajs/server"; app.register( contextProvider((ctx, next) => { executionContext.enterWith(ctx); return next(); }) ); ``` **Characteristics:** * Sets the context for all subsequent async operations in the current execution * Does not automatically clean up - context persists until overwritten * Useful when integrating with libraries that manage their own async context * Use with caution in concurrent environments ## Important Notes 1. **Only one `contextProvider` is active** - Registering a new one replaces the previous 2. **Always call `next()`** - Failing to call `next()` will hang the request 3. **Preserve async context** - Always use `executionContext.run()` or `enterWith()` to ensure context helpers like `context()`, `params()`, and `body()` work correctly ## When to Use Use `contextProvider` only when you need to change the AsyncLocalStorage behavior. For request wrapping, timing, or tracing, use [middleware](../guides/middleware.md) instead. --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/controller/README.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server](../../README.md) / controller # controller ## Interfaces | Interface | Description | | ------ | ------ | | [RestHttpMapping](interfaces/RestHttpMapping.md) | - | ## Functions | Function | Description | | ------ | ------ | | [rest](functions/rest.md) | - | --- --- url: /guides/controllers.md --- # Controllers Type-safe route registration by mapping HTTP methods and paths to controller functions. ## Basic Usage ```typescript // src/users/controller.ts import { body, params } from "@minimajs/server"; export async function getList() { return { users: [] }; } export async function createUser() { const user = body<{ name: string }>(); return { created: user }; } export async function getUser() { const id = params.get("id"); return { user: { id } }; } ``` ```typescript // src/users/module.ts import type { Meta } from "@minimajs/server"; import { controller } from "@minimajs/server"; export const meta: Meta = { plugins: [ controller(import("./controller"), [ // Format: " " "GET / getList", "POST / createUser", "GET /:id getUser", ]), ], }; ``` ## Route Format ``` ``` * `"GET / getList"` → `GET /` calls `getList` * `"POST / createUser"` → `POST /` calls `createUser` * `"GET /:id getUser"` → `GET /:id` calls `getUser` ## Type Safety TypeScript ensures handler names match exported functions: ```typescript // ✅ Valid controller(import("./controller"), ["GET / getList"]); // ❌ Type error - handler doesn't exist controller(import("./controller"), ["GET / missingHandler"]); ``` ## REST Helper For standard CRUD operations: ```typescript // src/posts/module.ts import { controller } from "@minimajs/server"; export const meta: Meta = { plugins: [controller.rest(import("./controller"), "id")], }; ``` Automatically creates: * `GET /` → `list` * `GET /:id` → `find` * `POST /` → `create` * `PATCH /:id` → `update` * `DELETE /:id` → `remove` Missing handlers are automatically skipped. --- --- url: /api/@minimajs/cookie/namespaces/cookies/README.md --- [**Minima.js API**](../../../../README.md) *** [Minima.js API](../../../../README.md) / [@minimajs/cookie](../../README.md) / cookies # cookies Cookie management utilities ## Functions | Function | Description | | ------ | ------ | | [get](functions/get.md) | Retrieves a single cookie value by name. | | [remove](functions/remove.md) | Removes a cookie by setting its expiration to the past. The cookie is immediately removed from the incoming cookies for the current request. | | [set](functions/set.md) | Sets a cookie to be sent in the response. The cookie value is immediately available for reading within the same request. | --- --- url: /packages/cookie.md --- # @minimajs/cookie Type-safe cookie management for Minima.js applications. [![npm version](https://img.shields.io/npm/v/@minimajs/cookie.svg)](https://www.npmjs.com/package/@minimajs/cookie) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) *** ## Installation ```bash npm install @minimajs/cookie ``` ## Basic Usage The `cookies()` function returns all cookies, and provides namespace methods for getting, setting, and removing individual cookies: ```typescript import { cookies } from "@minimajs/cookie"; import { createApp } from "@minimajs/server"; const app = createApp(); app.get("/example", () => { // Get all cookies const allCookies = cookies(); // { "session-token": "abc123", "theme": "dark", ... } // Get a single cookie const sessionToken = cookies.get("session-token"); // Set a cookie cookies.set("theme", "dark"); // Remove a cookie cookies.remove("old-token"); return { sessionToken }; }); ``` ## API Reference ### `cookies()` Returns all cookies as a record. Accepts an optional type parameter for type-safe access. **Type Parameter:** * `T` (optional): Type definition for the cookies object (defaults to `Record`) **Returns:** `T` - All cookies as a typed record **Examples:** ```typescript // Get all cookies (untyped) const allCookies = cookies(); // Type: Record // Get all cookies with type parameter interface MyCookies { sessionToken?: string; userId?: string; theme?: string; } const typedCookies = cookies(); // Type: MyCookies // Access with autocomplete: typedCookies.sessionToken ``` ### `cookies.get(name)` Retrieves a single cookie by name. **Parameters:** * `name` (string): The cookie name **Returns:** `string | undefined` **Example:** ```typescript // Get a cookie const theme = cookies.get("theme"); // theme is string | undefined ``` ### `cookies.set(name, value, options?)` Sets a cookie with optional configuration. **Parameters:** * `name` (string): The cookie name * `value` (string): The cookie value * `options` (optional): [SerializeOptions](https://github.com/jshttp/cookie#options-1) * `domain` (string): Cookie domain * `path` (string): Cookie path (default: "/") * `maxAge` (number): Max age in seconds * `expires` (Date): Expiration date * `httpOnly` (boolean): HTTP only flag * `secure` (boolean): Secure flag * `sameSite` ("strict" | "lax" | "none"): SameSite policy **Example:** ```typescript // Simple cookie cookies.set("theme", "dark"); // Cookie with options cookies.set("session-token", "abc123", { httpOnly: true, secure: true, maxAge: 3600, // 1 hour sameSite: "strict", }); // Cookie with expiration date cookies.set("temp-token", "xyz789", { expires: new Date(Date.now() + 86400000), // 1 day }); ``` ### `cookies.remove(name, options?)` Removes a cookie by setting its expiration to the past. **Parameters:** * `name` (string): The cookie name * `options` (optional): Same as `set()` options (useful for matching path/domain) **Example:** ```typescript // Remove a cookie cookies.remove("session-token"); // Remove with specific path/domain cookies.remove("session-token", { path: "/admin", domain: "example.com", }); ``` ## Advanced Usage ### Type-Safe Cookies Use TypeScript generics to get type-safe access to your cookies: ```typescript interface UserCookies { sessionId?: string; userId?: string; theme?: "light" | "dark"; locale?: string; } app.get("/profile", () => { const userCookies = cookies(); // TypeScript autocomplete and type checking const theme = userCookies.theme; // Type: "light" | "dark" | undefined const sessionId = userCookies.sessionId; // Type: string | undefined return { theme }; }); ``` ### Session Management Example ```typescript import { cookies } from "@minimajs/cookie"; // Login endpoint app.post("/login", () => { // Authenticate user... const userId = "12345"; // Set session cookie cookies.set("session", userId, { httpOnly: true, secure: true, maxAge: 86400, // 24 hours sameSite: "strict", }); return { success: true }; }); // Protected endpoint app.get("/profile", () => { // Get session const userId = cookies.get("session"); if (!userId) { throw new Error("Not authenticated"); } // Fetch user data... return { userId }; }); // Logout endpoint app.post("/logout", () => { cookies.remove("session"); return { success: true }; }); ``` ## Best Practices 1. **Use `httpOnly` for session cookies** to prevent XSS attacks: ```typescript cookies.set("session", token, { httpOnly: true }); ``` 2. **Use `secure` in production** to ensure cookies are only sent over HTTPS: ```typescript cookies.set("session", token, { secure: process.env.NODE_ENV === "production", }); ``` 3. **Set appropriate `sameSite` policies** to prevent CSRF: ```typescript cookies.set("session", token, { sameSite: "strict" }); ``` 4. **Use short `maxAge` for sensitive data**: ```typescript cookies.set("auth-token", token, { maxAge: 900 }); // 15 minutes ``` ## Links * [Documentation](https://minima-js.github.io/packages/cookie) * [GitHub](https://github.com/minima-js/minimajs) * [npm](https://www.npmjs.com/package/@minimajs/cookie) ## License MIT --- --- url: /plugins/cors.md --- # CORS The CORS plugin manages Cross-Origin Resource Sharing (CORS) headers for your application. This is essential for browser-based clients that access your API from a different domain, origin, or port. ## Installation The plugin is included with the `@minimajs/server` package and can be imported from `@minimajs/server/plugins`. ```typescript import { cors } from "@minimajs/server/plugins"; ``` ## Usage Register the plugin within your module's `meta.plugins`. The default configuration is permissive, allowing requests from all origins. ::: code-group ```typescript [src/module.ts] import { cors } from "@minimajs/server/plugins"; import { type Meta } from "@minimajs/server"; // Allow requests from all origins globally export const meta: Meta = { plugins: [cors()], }; ``` ::: ## Configuration For production environments, you should configure the plugin with more restrictive options to enhance security. ### `origin` Controls the `Access-Control-Allow-Origin` header. * **Type**: `string | string[] | ((origin: string) => boolean | Promise)` * **Default**: `*` ::: code-group ```typescript [src/module.ts] import { cors } from "@minimajs/server/plugins"; import { type Meta } from "@minimajs/server"; export const meta: Meta = { plugins: [ // Allow a single origin cors({ origin: "https://my-app.com" }), // Allow multiple origins cors({ origin: ["https://app-v1.com", "https://app-v2.com"] }), // Dynamic origin validation cors({ origin: (origin) => { // Allow all subdomains of example.com return origin.endsWith(".example.com"); }, }), ], }; ``` ::: ### Other Options * **`methods`**: Configures `Access-Control-Allow-Methods`. Default: `'GET,HEAD,PUT,PATCH,POST,DELETE'`. * **`allowedHeaders`**: Configures `Access-Control-Allow-Headers`. * **`exposedHeaders`**: Configures `Access-Control-Expose-Headers`. * **`credentials`**: Configures `Access-Control-Allow-Credentials`. Default: `false`. * **`maxAge`**: Configures `Access-Control-Max-Age` (in seconds). * **`optionsSuccessStatus`**: Status code to use for successful `OPTIONS` requests. Default: `204`. **Example with multiple options:** ::: code-group ```typescript [src/api/module.ts] import { cors } from "@minimajs/server/plugins"; import { type Meta } from "@minimajs/server"; export const meta: Meta = { plugins: [ cors({ origin: "https://my-app.com", methods: ["GET", "POST"], credentials: true, allowedHeaders: ["Content-Type", "Authorization"], }), ], }; ``` ::: --- --- url: /advanced/custom-adapters.md --- # Custom Runtime Adapters Minima.js uses a flexible adapter pattern to support different runtime environments. Out of the box, it supports Node.js and Bun. This guide shows you how to create custom adapters for new runtimes like Deno, uWebSockets.js, or any other HTTP server implementation. ## Understanding Server Adapters A server adapter is a bridge between Minima.js and the underlying HTTP server implementation. It abstracts runtime-specific details and provides a consistent interface for the framework. ### Adapter Interface ```typescript interface ServerAdapter { /** * Starts the server and begins listening for requests */ listen(server: Server, opts: ListenOptions, requestHandler: RequestHandler): Promise>; /** * Gets the remote address from the context */ remoteAddr(ctx: Context): RemoteAddr | null; /** * Stops the server and closes all connections */ close(server: T): Promise; } ``` Where: * `T` is your native server type (e.g., `Deno.HttpServer`) * `ListenOptions` contains `port` and optional `host` * `RequestHandler` is a function that processes Web standard `Request` → `Response` ## Creating a Deno Adapter Here's how to create an adapter for Deno: ```typescript import type { ServerAdapter, ListenOptions, RequestHandler, ListenResult, AddressInfo } from "@minimajs/server"; import type { Server, Context, RemoteAddr } from "@minimajs/server"; const kReqInfo = Symbol("deno.request-info"); export class DenoServerAdapter implements ServerAdapter { remoteAddr(ctx: Context): RemoteAddr | null { const addr = ctx.locals[kReqInfo] as Deno.NetAddr; return { hostname: addr.hostname, port: addr.port, family: "IPv4", }; } listen( srv: Server, opts: ListenOptions, requestHandler: RequestHandler ): Promise> { const hostname = opts.host || "0.0.0.0"; const port = opts.port; const server = Deno.serve({ hostname, port, handler: (request, info) => { // Pass additional context return requestHandler(srv, request, { locals: { [kReqInfo]: info }, }); }, }); const address: AddressInfo = { hostname, port, family: "IPv4" as const, protocol: "http", href: `http://${hostname}:${port}/`, }; return Promise.resolve({ server, address }); } async close(server: Deno.HttpServer): Promise { await server.shutdown(); } } ``` ### Using the Deno Adapter ```typescript import { createBaseServer } from "@minimajs/server/core"; import { DenoServerAdapter } from "./deno-adapter.ts"; const adapter = new DenoServerAdapter(); const app = createBaseServer(adapter); app.get("/", () => ({ message: "Hello from Deno!" })); await app.listen({ port: 3000 }); ``` ## Key Considerations ### 1. Request/Response Conversion Your adapter must convert between the runtime's native request/response format and Web standards: * **Input**: Convert native request → Web `Request` * **Output**: Convert Web `Response` → native response ### 2. Context Enrichment The `RequestHandler` can include runtime-specific objects: ```ts type RequestHandlerContext = { locals }; ``` ### 3. Address Information Return accurate `AddressInfo` with: * `hostname`: Bind address * `port`: Port number * `family`: "IPv4", "IPv6", or "unix" * `href`: Full URL string ### 4. Graceful Shutdown Implement proper cleanup in the `close()` method: * Stop accepting new connections * Wait for in-flight requests to complete (if possible) * Clean up resources ### 5. Error Handling Handle errors gracefully: ```typescript async listen(/* ... */): Promise> { try { // Start server } catch (error) { throw new Error(`Failed to start server: ${error.message}`); } } ``` ## Using Your Custom Adapter Once you've created your adapter, use it with `createBaseServer`: ```typescript import { createBaseServer } from "@minimajs/server/core"; import { MyCustomAdapter } from "./my-adapter.js"; const adapter = new MyCustomAdapter({ // adapter-specific options }); const app = createBaseServer(adapter, { logger: false, // or use custom pino logger }); app.get("/health", () => ({ status: "ok" })); await app.listen({ port: 3000, host: "localhost" }); ``` ## Best Practices 1. **Type Safety**: Use TypeScript generics to maintain type safety 2. **Performance**: Minimize conversions and allocations in hot paths 3. **Standards**: Prefer Web standards (Request/Response) when available 4. **Testing**: Write comprehensive tests for your adapter 5. **Documentation**: Document runtime-specific behavior and limitations 6. **Error Messages**: Provide clear error messages for common issues ## Next Steps * Learn about [Container and Encapsulation](./container-encapsulation.md) * See [Architecture Overview](../core-concepts/architecture.md) --- --- url: /cookbook/data-validation.md --- # Data Validation with Zod Data validation is a critical part of any web application. It ensures that the data you receive from clients is in the correct format and meets your application's requirements. Minima.js provides a powerful package, `@minimajs/schema`, for data validation. This package is designed to work seamlessly with popular validation libraries like [Zod](https://zod.dev/). This recipe will show you how to use `@minimajs/schema` with Zod to validate incoming request data. ## Prerequisites First, you need to install the required packages: ```bash npm install @minimajs/schema zod ``` ## 1. Creating a Schema The first step is to create a validation schema using Zod. A schema defines the structure and constraints of your data. ```typescript [src/user/schema.ts] import { z } from "zod"; export const createUserSchema = z.object({ name: z.string().min(2), email: z.string().email(), password: z.string().min(8), }); ``` This schema defines a user object with a `name`, `email`, and `password`. It also specifies that the `name` must be at least 2 characters long, the `email` must be a valid email address, and the `password` must be at least 8 characters long. ## 2. Validating the Request Body Now that we have a schema, we can use it to validate the request body. The `@minimajs/schema` package provides a `createBody` function for this purpose. ::: code-group ```typescript [src/users/module.ts] import { createBody } from "@minimajs/schema"; import { type Routes } from "@minimajs/server"; import { createUserSchema } from "./user/schema.js"; const getValidatedBody = createBody(createUserSchema); function createUser() { const { name, email, password } = getValidatedBody(); // At this point, you can be sure that the data is valid. // ... create the user ... return { message: "User created" }; } export const routes: Routes = { "POST /": createUser, }; ``` ```typescript [src/index.ts] import { createApp } from "@minimajs/server/bun"; const app = createApp(); await app.listen({ port: 3000 }); ``` ::: In this example: * We use `createBody(createUserSchema)` to create a `getValidatedBody` function. * When `getValidatedBody()` is called inside the route handler, it will: 1. Parse the request body. 2. Validate it against the `createUserSchema`. 3. If the validation passes, it returns the validated data. 4. If the validation fails, it automatically throws a `ValidationError` and sends a `400 Bad Request` response with the validation errors. ## 3. Validating Headers and Search Params You can also validate request headers and search parameters using the `createHeaders` and `createSearchParams` functions. ::: code-group ```typescript [src/posts/module.ts] import { createSearchParams } from "@minimajs/schema"; import { type Routes } from "@minimajs/server"; import { z } from "zod"; const paginationSchema = z.object({ page: z.number({ coerce: true }).int().positive().default(1), limit: z.number({ coerce: true }).int().positive().default(10), }); const getPagination = createSearchParams(paginationSchema); function listPosts() { const { page, limit } = getPagination(); // ... fetch posts with pagination ... return { page, limit }; } export const routes: Routes = { "GET /": listPosts, }; ``` ::: In this example, we use `createSearchParams` to validate and parse the `page` and `limit` search parameters. ## Handling Validation Errors You don't need to do anything special to handle validation errors. `@minimajs/schema` handles them for you. If a validation fails, it will automatically send a response like this: ```json { "statusCode": 400, "error": "Bad Request", "message": "Validation failed", "issues": [ { "code": "too_small", "minimum": 2, "type": "string", "inclusive": true, "exact": false, "message": "String must contain at least 2 character(s)", "path": ["name"] } ] } ``` This makes it incredibly easy to provide meaningful error messages to your clients without writing any boilerplate code. --- --- url: /cookbook/database-integration.md --- # Database Integration with Prisma A web application is rarely complete without a database. This recipe will show you how to integrate a database with your Minima.js application using [Prisma](https://www.prisma.io/), a popular open-source database toolkit for Node.js and TypeScript. We will use Prisma to connect to a SQLite database, but the same principles apply to other databases supported by Prisma (like PostgreSQL, MySQL, etc.). ## Prerequisites First, you need to install the required packages: ```bash npm install prisma @prisma/client ``` ## 1. Setting up Prisma The first step is to initialize Prisma in your project. ```bash npx prisma init --datasource-provider sqlite ``` This command will create a `prisma` directory with a `schema.prisma` file. This file contains your database schema. Let's define a simple `User` model in `prisma/schema.prisma`: ```prisma [prisma/schema.prisma] model User { id Int @id @default(autoincrement()) email String @unique name String? } ``` Now, you can use the Prisma CLI to create the database and generate the Prisma Client. ```bash npx prisma migrate dev --name init ``` This command will: 1. Create your SQLite database file. 2. Create the `User` table in your database. 3. Generate the Prisma Client library in `node_modules/@prisma/client`. ## 2. Connecting to the Database We need to connect to the database when the application starts and disconnect when it stops. The `hook.lifespan` utility is perfect for this. It is best to register this in your root module. ::: code-group ```typescript [src/database.ts] import { hook, logger } from "@minimajs/server"; import { PrismaClient } from "@prisma/client"; export const prisma = new PrismaClient(); export const dbLifespan = hook.lifespan(async () => { await prisma.$connect(); logger.info("Database connected"); return async () => { await prisma.$disconnect(); logger.info("Database disconnected"); }; }); ``` ```typescript [src/module.ts] import { type Meta } from "@minimajs/server"; import { dbLifespan } from "./database.js"; // Global database connection management export const meta: Meta = { plugins: [dbLifespan], }; ``` ```typescript [src/index.ts] import { createApp } from "@minimajs/server/bun"; const app = createApp(); // Auto-discovers root module with dbLifespan await app.listen({ port: 3000 }); ``` ::: ## 3. Using the Prisma Client in Routes Now that we have connected to the database, we can use the Prisma Client in our route handlers to query the database. ::: code-group ```typescript [src/users/module.ts] import { body, type Routes } from "@minimajs/server"; import { prisma } from "../database.js"; async function listUsers() { const users = await prisma.user.findMany(); return users; } async function createUser() { const { name, email } = body<{ name: string; email: string }>(); const newUser = await prisma.user.create({ data: { name, email, }, }); return newUser; } export const routes: Routes = { "GET /": listUsers, "POST /": createUser, }; ``` ::: ## 4. REST API Example To keep our code organized, we encapsulate the database-related logic in a feature-based module structure. ```text src/ ├── database.ts # Prisma instance & lifespan hook ├── module.ts # Root module (global config) ├── index.ts # Entry point └── users/ └── module.ts # CRUD for /users ``` This approach makes our code more modular and easier to maintain. You now have a solid foundation for building database-driven applications with Minima.js and Prisma! ## See Also * [Building with File-Based Modules](/core-concepts/modules) * [Application Lifespan Hooks](/guides/hooks#hooklifespansetupfn) * [Http Helpers](/guides/http) --- --- url: /plugins/descriptor.md --- # Descriptor The Descriptor plugin applies route metadata to all routes within its scope. Use it to tag entire modules with common metadata like authentication requirements, rate limits, or OpenAPI documentation. ## Usage ::: code-group ```typescript [src/users/module.ts] import { descriptor } from "@minimajs/server/plugins"; import type { Meta, Routes } from "@minimajs/server"; const kAuth = Symbol("auth"); export const meta: Meta = { plugins: [ descriptor([kAuth, "required"]), ], }; function getUsers() { /* ... */ } function createUser() { /* ... */ } export const routes: Routes = { "GET /": getUsers, // Has kAuth metadata "POST /": createUser, // Has kAuth metadata }; ``` ::: ## Multiple Descriptors Pass multiple descriptors at once to your module's `meta.plugins`: ::: code-group ```typescript [src/api/module.ts] import { descriptor } from "@minimajs/server/plugins"; import { describe } from "@minimajs/openapi"; import type { Meta } from "@minimajs/server"; const kAuth = Symbol("auth"); const kRateLimit = Symbol("rateLimit"); export const meta: Meta = { plugins: [ descriptor( [kAuth, "required"], [kRateLimit, { max: 100, window: "1m" }], describe({ tags: ["Users"] }) ), ], }; ``` ::: ## Scoping Like all plugins, `descriptor()` respects module boundaries and prefix inheritance: ::: code-group ```typescript [src/module.ts] import { descriptor } from "@minimajs/server/plugins"; import type { Meta } from "@minimajs/server"; const kPublicApi = Symbol("publicApi"); // Root module export const meta: Meta = { plugins: [descriptor([kPublicApi, true])], }; ``` ```typescript [src/admin/module.ts] import { descriptor } from "@minimajs/server/plugins"; import type { Meta } from "@minimajs/server"; const kAdminOnly = Symbol("adminOnly"); // Child module export const meta: Meta = { plugins: [descriptor([kAdminOnly, true])], }; // Routes here inherit BOTH kPublicApi and kAdminOnly ``` ::: ## Dynamic Descriptors Use a function for metadata based on route properties: ::: code-group ```typescript [src/module.ts] import { descriptor } from "@minimajs/server/plugins"; import type { Meta } from "@minimajs/server"; const kOperationId = Symbol("operationId"); export const meta: Meta = { plugins: [ descriptor((route) => { const method = route.methods[0].toLowerCase(); const path = route.path.replace(/[/:]/g, "_"); route.metadata[kOperationId] = `${method}${path}`; }), ], }; ``` ::: ## See Also * [Route Descriptors Guide](/guides/route-descriptors) - Creating custom descriptors, reading metadata * [OpenAPI](/packages/openapi) - Built-in `describe()` and `internal()` descriptors --- --- url: /guides/error-handling.md --- # Error Handling Proper error handling is crucial for building robust and reliable web applications. Minima.js provides a flexible and powerful error handling mechanism centered around hooks and helpers. By default, uncaught exceptions result in a generic `500 Internal Server Error` response. ## Quick Reference * [`abort`](#the-abort-helper) - Throw HTTP errors with status codes * [`redirect`](#the-redirect-helper) - Redirect users to different URLs * [`error` hook](#error-hook-behavior) - Handle errors at different scopes * [`HttpError.toJSON`](#overriding-tojson-method) - Customize error response format * [`send` hook](#send-hook) - Post-response cleanup (for both success and errors) * [`onError`](#request-scoped-error-handler-onerror) - Request-specific error handling *** ## Throwing Errors ### The `abort` Helper The `abort` helper throws HTTP-specific errors with status codes and custom payloads. ```typescript import { abort, params } from "@minimajs/server"; import type { Routes } from "@minimajs/server"; function getUser() { const user = findUserById(params.get("id")); if (!user) { abort({ error: "User not found" }, 404); } return user; } export const routes: Routes = { "GET /users/:id": getUser, }; ``` **Common shortcuts:** ```typescript abort.notFound("User not found"); // 404 abort.badRequest("Invalid input"); // 400 abort.unauthorized("Login required"); // 401 abort.forbidden("Access denied"); // 403 ``` **Check if error is from abort:** ```typescript if (abort.is(error)) { console.log(error.statusCode); // Access status code } ``` ### The `redirect` Helper Redirect users to different URLs with `redirect`. ```typescript import { redirect } from "@minimajs/server"; import type { Routes } from "@minimajs/server"; function oldPath() { redirect("/new-path"); // 302 temporary redirect } function movedPath() { redirect("/permanent", true); // 301 permanent redirect } export const routes: Routes = { "GET /old-path": oldPath, "GET /moved": movedPath, }; ``` ## Error Handling Flow ```mermaid graph TB Start[Request] --> Handler[Route Handler] Handler -->|Success| Response[Normal Response] Handler -->|Error| ErrorCheck{Error Hooks
Registered?} ErrorCheck -->|Yes| HookChain[Run Error Hooks
LIFO order] ErrorCheck -->|No| FallbackHandler[app.errorHandler] HookChain -->|Handled| CreateResp[Create Error Response] HookChain -->|Unhandled| FallbackHandler FallbackHandler --> CreateResp CreateResp --> SendHook[send Hook] SendHook --> End[Send Response] Response --> SendHook style Start fill:#e3f2fd style Handler fill:#fff3e0 style ErrorCheck fill:#fff9c4 style HookChain fill:#f3e5f5 style FallbackHandler fill:#fce4ec style CreateResp fill:#ffebee style End fill:#c8e6c9 ``` ## Handling Errors with Hooks ### `error` Hook Behavior The `error` hook intercepts errors and can handle them in four ways: ```mermaid graph TB Start[Error Thrown] --> Hook{Error Hook} Hook -->|1. Re-throw/abort| NextHook[Next Error Hook
or app.errorHandler] Hook -->|2. Return data| Success[200 OK Response
✅ Chain stops] Hook -->|3. Return Response| Direct[Send Response
⚠️ Bypasses transform hooks] Hook -->|4. Return undefined| NextHook NextHook --> Final[Final Error Response] style Start fill:#ffcdd2 style Success fill:#c8e6c9 style Direct fill:#ffe0b2 style Final fill:#ffcdd2 ``` **Four possible outcomes:** 1. **Re-throw or abort** (Recommended) - Pass to next error hook or handler 2. **Return data** - Treated as successful `200 OK` response 3. **Return Response** - Sent directly (⚠️ bypasses transform hooks) 4. **Return undefined** - Pass to next error hook ### Global Error Handler Handle errors across your entire application by registering an error hook at the root level: ```typescript import { hook, abort } from "@minimajs/server"; app.register( hook("error", (error) => { console.error("Error occurred:", error); // Re-throw HTTP errors with custom format if (abort.is(error)) { abort({ code: "HTTP_ERROR", message: error.message }, error.statusCode); } // Handle all other errors as 500 abort({ code: "INTERNAL_ERROR", message: "Server error" }, 500); }) ); ``` > **Note:** If no error hook handles the error (all return `undefined` or none are registered), unhandled `HttpError` instances render themselves, while other errors result in a generic `500 Internal Server Error` response. ### Module-Level Error Handler Handle errors for specific modules with scoped error hooks: ```mermaid graph TB Root["Root App
(Global Error Handler)"] Root --> Module1["Admin Module
(Admin Error Handler)"] Root --> Module2["API Module
(API Error Handler)"] Module1 --> Route1["/admin/dashboard"] Module1 --> Route2["/admin/users"] Module2 --> Route3["/api/posts"] Route1 -.->|Error occurs| Exec1["1. Admin Handler
2. Global Handler
3. app.errorHandler"] Route3 -.->|Error occurs| Exec2["1. API Handler
2. Global Handler
3. app.errorHandler"] style Root fill:#e1f5fe style Module1 fill:#b3e5fc style Module2 fill:#b3e5fc style Exec1 fill:#fff3e0 style Exec2 fill:#fff3e0 ``` ::: code-group ```typescript [src/admin/module.ts] import { hook, abort, type Meta, type Routes } from "@minimajs/server"; // Scoped error handling via meta.plugins export const meta: Meta = { plugins: [ hook("error", (error) => { console.error("Admin error:", error); const statusCode = abort.is(error) ? error.statusCode : 500; abort({ adminError: error.message }, statusCode); }), ], }; function getDashboard() { throw new Error("Dashboard failed"); } export const routes: Routes = { "GET /dashboard": getDashboard, }; ``` ```typescript [Manual Registration] async function adminModule(app: App) { app.register( hook("error", (error) => { console.error("Admin error:", error); const statusCode = abort.is(error) ? error.statusCode : 500; abort({ adminError: error.message }, statusCode); }) ); app.get("/dashboard", () => { throw new Error("Dashboard failed"); }); } app.register(adminModule, { prefix: "/admin" }); ``` ::: > **Note:** Error hooks execute in LIFO order, with child scopes running before parent scopes. See the diagram above for the hierarchy. ### Request-Scoped Error Handler (`onError`) Handle errors for a single request with the `onError` helper: ```typescript import { onError } from "@minimajs/server"; app.get("/risky", () => { onError((err) => { console.error("Request failed:", err); }); if (Math.random() > 0.5) { throw new Error("Random failure!"); } return { success: true }; }); ``` ## Customizing Error Responses ### Overriding `toJSON` Method The quickest way to customize error responses is by overriding the static `toJSON` method on error classes. This method controls how errors are serialized when sent to clients. **Global override for all HTTP errors:** ```typescript import { HttpError } from "@minimajs/server/error"; // Override toJSON for all HttpError instances globally HttpError.toJSON = (err: HttpError) => { return { success: false, message: err.response, statusCode: err.status, timestamp: new Date().toISOString(), }; }; // Now all HttpErrors use this format app.get("/users/:id", () => { const user = findUser(params.get("id")); if (!user) { abort("User not found", 404); } return user; }); // Response: { "success": false, "message": "User not found", "statusCode": 404, "timestamp": "2026-01-10T..." } ``` **Create custom error class:** ```typescript import { HttpError } from "@minimajs/server/error"; // Create custom error class with its own toJSON class ApiError extends HttpError { static toJSON(err: ApiError) { return { success: false, error: { code: err.code || "UNKNOWN_ERROR", message: err.response, timestamp: new Date().toISOString(), }, }; } constructor( message: string, statusCode: number, public code?: string ) { super(message, statusCode, { code }); } } // Use in routes app.get("/api/users/:id", () => { const user = findUser(params.get("id")); if (!user) { throw new ApiError("User not found", 404, "USER_NOT_FOUND"); } return user; }); // Response: { "success": false, "error": { "code": "USER_NOT_FOUND", "message": "User not found", "timestamp": "2026-01-10T..." } } ``` **Override ValidationError for custom validation format:** ```typescript import { ValidationError } from "@minimajs/schema/error"; import { z } from "zod"; // Override ValidationError.toJSON globally ValidationError.toJSON = (err: ValidationError) => { return { success: false, error: "Validation failed", validationErrors: err.issues?.map((issue) => ({ field: issue.path.join("."), message: issue.message, code: issue.code, })), }; }; // Now all ValidationErrors use this format app.post("/api/signup", async () => { const schema = z.object({ email: z.string().email(), password: z.string().min(8), }); const data = await body(); const result = schema.safeParse(data); if (!result.success) { throw ValidationError.createFromZodError(result.error); } return { success: true }; }); // Response: { "success": false, "error": "Validation failed", "validationErrors": [...] } ``` ### Per-Instance Customization You can also override `toJSON` per instance for one-off customizations: ```typescript app.get("/special", () => { const error = new HttpError("Special error", 400); error.toJSON = () => ({ custom: "response", timestamp: Date.now() }); throw error; }); ``` > **Tip:** Overriding `toJSON` is preferred over custom error handlers because it: > > * Keeps error formatting logic with the error class > * Works consistently across all error hooks and handlers > * Allows different error types to have different formats > * Maintains type safety and code organization > * Can be set once globally at application startup ## `send` Hook Execute cleanup tasks after a response is sent (for both successful and error responses): ```typescript app.register( hook("send", (response, ctx) => { // Report errors to monitoring service if (response.status >= 400) { reportToSentry(ctx.error, { url: ctx.request.url, method: ctx.request.method, status: response.status, }); } }) ); ``` ## Best Practices * **Use `abort` shortcuts** for common HTTP errors (`abort.notFound()`, `abort.badRequest()`, etc.) * **Override `toJSON`** for custom error response formats instead of custom error handlers * **Re-throw errors in hooks** to allow other handlers to process them * **Log errors** before handling them for debugging and monitoring * **Use scoped error hooks** for module-specific error handling * **Keep error messages generic in production** to avoid leaking sensitive information * **Create custom error classes** for different error types (API errors, validation errors, etc.) --- --- url: /plugins/express.md --- # Express Middleware The Express plugin allows you to integrate Express.js-style middleware into your Minima.js application. This provides compatibility with the vast ecosystem of Express middleware while maintaining Minima.js's lightweight architecture. ## Installation The plugin is included with the `@minimajs/server` package and can be imported from `@minimajs/server/plugins`. ```typescript import { express } from "@minimajs/server/plugins/express"; ``` ## Usage Register Express-style middleware within your module's `meta.plugins`. The middleware function receives the Node.js `req` and `res` objects, along with a `next` callback. ::: code-group ```typescript [src/module.ts] import { express } from "@minimajs/server/plugins/express"; import { type Meta } from "@minimajs/server"; // Use Express middleware globally export const meta: Meta = { plugins: [ express((req, res, next) => { console.log("Request URL:", req.url); next(); }), ], }; ``` ::: ## Important Notes :::warning Node.js Only This plugin **only works with Node.js servers**. It requires access to the underlying `IncomingMessage` and `ServerResponse` objects from Node.js's HTTP module. ::: ## Examples ### Using Third-Party Express Middleware You can use existing Express middleware packages: ::: code-group ```typescript [src/module.ts] import helmet from "helmet"; import compression from "compression"; import { express } from "@minimajs/server/plugins/express"; import { type Meta } from "@minimajs/server"; export const meta: Meta = { plugins: [ express(helmet()), // Security headers express(compression()), // Response compression ], }; ``` ::: ### Custom Middleware Create custom Express-style middleware for specific needs: ::: code-group ```typescript [src/module.ts] import { express } from "@minimajs/server/plugins/express"; import { type Meta } from "@minimajs/server"; export const meta: Meta = { plugins: [ express((req, res, next) => { // Add custom headers res.setHeader("X-Custom-Header", "MyValue"); next(); }), ], }; ``` ::: ### Error Handling Pass errors to the Minima.js error handling system using the `next` callback: ::: code-group ```typescript [src/module.ts] import { express } from "@minimajs/server/plugins/express"; import { type Meta } from "@minimajs/server"; export const meta: Meta = { plugins: [ express((req, res, next) => { try { // Some operation that might fail validateRequest(req); next(); } catch (error) { next(error); } }), ], }; ``` ::: ## Type Definitions ```typescript export type ExpressCallback = (req: unknown, res: unknown, next: (err?: unknown) => void) => void; ``` The callback function signature matches Express.js middleware: * `req`: The Node.js `IncomingMessage` object * `res`: The Node.js `ServerResponse` object * `next`: A callback to continue to the next middleware or pass an error ## Integration with Minima.js Context The Express middleware integrates with Minima.js's context system: * `req` corresponds to `ctx.incomingMessage` * `res` corresponds to `ctx.serverResponse` * Errors passed to `next()` are handled by Minima.js's error handling system --- --- url: /cookbook/file-uploads.md --- # Handling File Uploads File uploads are a common requirement in modern web applications. Minima.js provides a simple and efficient way to handle file uploads using the `@minimajs/multipart` package, which is context-aware and returns native Web API `File` objects. ## Prerequisites ```bash npm install @minimajs/multipart ``` ## Quick Start ::: code-group ```typescript [src/uploads/module.ts] import { abort, type Routes } from "@minimajs/server"; import { multipart, helpers } from "@minimajs/multipart"; async function uploadAvatar() { const file = await multipart.file("avatar"); if (!file) { abort({ error: "No file uploaded" }, 400); } await helpers.save(file, "./uploads"); return { message: "Uploaded", filename: file.name }; } export const routes: Routes = { "POST /upload": uploadAvatar, }; ``` ```typescript [src/index.ts] import { createApp } from "@minimajs/server/bun"; const app = createApp(); await app.listen({ port: 3000 }); ``` ::: ## Single File Upload Use `multipart.file(fieldName)` to get a single file by field name. Returns a native `File` object. ::: code-group ```typescript [src/uploads/module.ts] import { abort, type Routes } from "@minimajs/server"; import { multipart, helpers } from "@minimajs/multipart"; async function uploadAvatar() { const avatar = await multipart.file("avatar"); if (!avatar) { abort({ error: "No avatar uploaded" }, 400); } // Save with auto-generated UUID filename const savedName = await helpers.save(avatar, "./uploads/avatars"); return { message: "Avatar uploaded", originalName: avatar.name, savedAs: savedName, size: avatar.size, type: avatar.type, }; } export const routes: Routes = { "POST /avatar": uploadAvatar, }; ``` ::: Test with curl: ```bash curl -X POST -F "avatar=@photo.jpg" http://localhost:3000/uploads/avatar ``` ## Multiple File Uploads Use `multipart.files()` to iterate over all uploaded files. ::: code-group ```typescript [src/gallery/module.ts] import { type Routes } from "@minimajs/server"; import { multipart, helpers } from "@minimajs/multipart"; async function uploadGallery() { const uploaded = []; for await (const [field, file] of multipart.files()) { const savedName = await helpers.save(file, "./uploads/gallery"); uploaded.push({ field, originalName: file.name, savedAs: savedName, size: file.size, }); } return { message: "Gallery uploaded", files: uploaded }; } export const routes: Routes = { "POST /gallery": uploadGallery, }; ``` ::: Test with curl: ```bash curl -X POST \ -F "photo1=@image1.jpg" \ -F "photo2=@image2.jpg" \ -F "photo3=@image3.jpg" \ http://localhost:3000/gallery ``` ## Mixed Fields and Files Use `multipart.body()` to process both text fields and files together. ::: code-group ```typescript [src/profile/module.ts] import { type Routes } from "@minimajs/server"; import { multipart, helpers } from "@minimajs/multipart"; async function updateProfile() { const data: Record = {}; for await (const [name, value] of multipart.body()) { if (helpers.isFile(value)) { const savedName = await helpers.save(value, "./uploads"); data[name] = { filename: value.name, savedAs: savedName }; } else { data[name] = value; } } return { message: "Profile updated", data }; } export const routes: Routes = { "POST /update": updateProfile, }; ``` ::: Test with curl: ```bash curl -X POST \ -F "username=john" \ -F "email=john@example.com" \ -F "avatar=@photo.jpg" \ http://localhost:3000/profile/update ``` ## Large File Uploads (Streaming) For large files, use the `streaming` module to avoid memory buffering: ::: code-group ```typescript [src/videos/module.ts] import { abort, type Routes } from "@minimajs/server"; import { streaming } from "@minimajs/multipart"; import { pipeline } from "node:stream/promises"; import { createWriteStream } from "node:fs"; async function uploadVideo() { const file = await streaming.file("video"); if (!file) { abort({ error: "No video uploaded" }, 400); } // Stream directly to disk without buffering await pipeline(file.stream(), createWriteStream(`./uploads/${file.name}`)); return { message: "Video uploaded", filename: file.name }; } export const routes: Routes = { "POST /upload": uploadVideo, }; ``` ::: ## Validated Uploads with Zod Use the schema module for type-safe validation: ::: code-group ```typescript [src/posts/module.ts] import { type Routes } from "@minimajs/server"; import { z } from "zod"; import { createMultipart } from "@minimajs/multipart/schema"; import { helpers } from "@minimajs/multipart"; const upload = createMultipart({ title: z.string().min(1).max(100), description: z.string().optional(), image: z .file() .mime(["image/jpeg", "image/png", "image/webp"]) .max(5 * 1024 * 1024), // 5MB }); async function createPost() { const data = await upload(); const savedName = await helpers.save(data.image, "./uploads/posts"); return { title: data.title, description: data.description, imageUrl: `/uploads/posts/${savedName}`, }; } export const routes: Routes = { "POST /create": createPost, }; ``` ::: ## File Size Limits Set limits using the options parameter: ```typescript const file = await multipart.file("document", { limits: { fileSize: 10 * 1024 * 1024, // 10MB max files: 5, // Max 5 files }, }); ``` ## Return File Directly Files can be returned directly from handlers with automatic `Content-Type`: ::: code-group ```typescript [src/preview/module.ts] import { type Routes } from "@minimajs/server"; import { z } from "zod"; import { createMultipart } from "@minimajs/multipart/schema"; const upload = createMultipart({ image: z.file().mime(["image/jpeg", "image/png"]), }); async function previewImage() { const data = await upload(); return data.image; // Returns with correct Content-Type } export const routes: Routes = { "POST /image": previewImage, }; ``` ::: ## Helper Functions ```typescript import { helpers } from "@minimajs/multipart"; // Save file to disk await helpers.save(file, "./uploads"); await helpers.save(file, "./uploads", "custom-name.jpg"); // Type guards helpers.isFile(value); // Check if value is a File helpers.isRawFile(value); // Check if value is raw stream // Generate unique filename helpers.randomName("photo.jpg"); // "uuid-here.jpg" // Create directory if needed await helpers.ensurePath("./uploads", "images"); // Human readable size helpers.humanFileSize(1048576); // "1.0 MiB" ``` ## Next Steps * [Multipart API Reference](/packages/multipart/) - Full API documentation * [Schema Validation](/packages/multipart/schema) - Type-safe uploads with Zod * [Helper Functions](/packages/multipart/helpers) - All utility functions --- --- url: /api/@minimajs/server/@minimajs/server/functions/abort.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / abort # Function: abort() ```ts function abort( response, statusCode, options?): never; ``` Aborts the request with the given response and status code. ## Type Parameters ### R `R` ## Parameters ### response `R` = `...` The error response message ### statusCode [`StatusCode`](../type-aliases/StatusCode.md) = `400` The HTTP status code (default: 400) ### options? [`HttpErrorOptions`](../error/interfaces/HttpErrorOptions.md) Optional error options including custom headers ## Returns `never` ## Throws ## Example ```ts abort('Unauthorized', 401); abort('Bad Request'); abort('Rate limit exceeded', 429, { headers: { 'Retry-After': '60' } }); // Or use abort.notFound() abort.notFound(); ``` ## Since v0.2.0 --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/headers/functions/append.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [headers](../README.md) / append # Function: append() ```ts function append(name, value): void; ``` Appends a response header (useful for headers that can have multiple values like Set-Cookie). ## Parameters ### name `string` The header name to append ### value `string` The header value ## Returns `void` ## Example ```ts headers.append('Set-Cookie', 'sessionId=abc123'); headers.append('Set-Cookie', 'theme=dark'); ``` --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/abort/functions/assert.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [abort](../README.md) / assert # Function: assert() ```ts function assert(error): asserts error is Error; ``` Ensures an error is an aborted error. If not, re-throws it. ## Parameters ### error `unknown` The error to check ## Returns `asserts error is Error` ## Example ```ts try { // some code } catch (err) { abort.assert(err); // handle abort errors only } ``` --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/multipart/functions/body.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [multipart](../README.md) / body # Function: body() ```ts function body(options): AsyncGenerator<[string, string | File]>; ``` Retrieves both text fields and files from a multipart form request as an async iterable. Each iteration yields a tuple of \[fieldName, value] where value can be a string or File. ## Parameters ### options [`MultipartOptions`](../../../type-aliases/MultipartOptions.md) = `{}` ## Returns `AsyncGenerator`<\[`string`, `string` | `File`]> An async iterable that yields tuples of field name and value (string or File) ## Example ```ts for await (const [name, value] of multipart.body()) { if (isFile(value)) { console.log(`File: ${name} = ${value.name}`); helpers.save(value, './dest') } else { console.log(`Field: ${name} = ${value}`); } } ``` --- --- url: /api/@minimajs/multipart/@minimajs/multipart/namespaces/raw/functions/body.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [raw](../README.md) / body # Function: body() ```ts function body(options): AsyncGenerator; ``` Retrieves both text fields and files from a multipart form request as an async iterable. Each iteration yields a MultipartRawResult (either MultipartRawFile or MultipartRawField). ## Type Parameters ### T `T` = [`MultipartRawResult`](../../../type-aliases/MultipartRawResult.md) ## Parameters ### options [`MultipartOptions`](../../../type-aliases/MultipartOptions.md) = `{}` ## Returns `AsyncGenerator`<`T`> An async iterable that yields raw multipart results ## Example ```ts for await (const body of multipart.raw()) { if (isRawFile(body)) { console.log(`File: ${body.fieldname} = ${body.filename}`); await helpers.save(body, './dest'); } else { console.log(`Field: ${body.fieldname} = ${body.value}`); } } ``` --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/streaming/functions/body.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [streaming](../README.md) / body # Function: body() ```ts function body(options): AsyncGenerator<[string, string | StreamFile]>; ``` Iterates over all multipart fields, yielding files as StreamFiles and text fields as strings. ## Parameters ### options [`MultipartOptions`](../../../type-aliases/MultipartOptions.md) = `{}` ## Returns `AsyncGenerator`<\[`string`, `string` | [`StreamFile`](../classes/StreamFile.md)]> --- --- url: /api/@minimajs/server/@minimajs/server/functions/body.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / body # Function: body() ```ts function body(): T; ``` Retrieves the request body. Requires bodyParser plugin to be registered. ## Type Parameters ### T `T` = `unknown` ## Returns `T` ## Example ```ts import { bodyParser } from '@minimajs/server/plugins/body-parser'; app.register(bodyParser()); app.post('/users', () => { const data = body<{ name: string }>(); console.log(data.name); return { received: data }; }); ``` ## Since v0.2.0 --- --- url: /api/@minimajs/server/@minimajs/server/plugins/functions/bodyParser.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / bodyParser # Function: bodyParser() ```ts function bodyParser(opts): PluginSync; ``` ## Parameters ### opts [`BodyParserOptions`](../interfaces/BodyParserOptions.md) = `...` ## Returns [`PluginSync`](../../interfaces/PluginSync.md)<`unknown`> --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/raw/functions/busboy.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [raw](../README.md) / busboy # Function: busboy() ```ts function busboy(opt): readonly [Busboy, () => void]; ``` ## Parameters ### opt [`MultipartOptions`](../../../type-aliases/MultipartOptions.md) ## Returns readonly \[`Busboy`, () => `void`] --- --- url: /api/@minimajs/openapi/functions/cleanJSONSchema.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/openapi](../README.md) / cleanJSONSchema # Function: cleanJSONSchema() ```ts function cleanJSONSchema(schema): SchemaObject; ``` Cleans JSON Schema for OpenAPI compatibility. Removes properties that are valid in JSON Schema but not in OpenAPI. ## Parameters ### schema `unknown` ## Returns [`SchemaObject`](../namespaces/OpenAPI/type-aliases/SchemaObject.md) --- --- url: /api/@minimajs/server/@minimajs/server/functions/compose.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / compose # Function: compose() ```ts function compose(...plugins): Plugin; ``` Composes multiple plugins/modules into a single plugin that registers all of them sequentially. ## Type Parameters ### S `S` ### T `T` *extends* { `name?`: `string`; } = { `name?`: `string`; } ## Parameters ### plugins ...[`Registerable`](../type-aliases/Registerable.md)<`S`>\[] Array of plugins or modules to compose ## Returns [`Plugin`](../interfaces/Plugin.md)<`S`, `T`> A single plugin that registers all provided plugins in order ## Examples ```typescript const dbPlugin = compose( hook("ready", async () => await db.connect()), hook("close", async () => await db.close()) ); app.register(dbPlugin); ``` ```typescript // Compose multiple feature modules const apiModule = compose( authModule, usersModule, postsModule ); app.register(apiModule); ``` --- --- url: /api/@minimajs/server/@minimajs/server/functions/context.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / context # Function: context() ```ts function context(): Context; ``` ## Type Parameters ### S `S` ## Returns [`Context`](../interfaces/Context.md)<`S`> --- --- url: /api/@minimajs/server/@minimajs/server/plugins/functions/contextProvider.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / contextProvider # Function: contextProvider() ```ts function contextProvider(callback): PluginSync; ``` ## Parameters ### callback [`Middleware`](../../type-aliases/Middleware.md) ## Returns [`PluginSync`](../../interfaces/PluginSync.md)<`unknown`> --- --- url: /api/@minimajs/server/@minimajs/server/functions/controller.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / controller # Function: controller() ```ts function controller(methods, controllers): Plugin; ``` ## Type Parameters ### T `T` *extends* `Record`<`string`, [`GenericCallback`](../type-aliases/GenericCallback.md)> ## Parameters ### methods `T` | `Promise`<`T`> ### controllers ( | `` `ACL ${string} ${Extract}` `` | `` `BIND ${string} ${Extract}` `` | `` `CHECKOUT ${string} ${Extract}` `` | `` `CONNECT ${string} ${Extract}` `` | `` `COPY ${string} ${Extract}` `` | `` `DELETE ${string} ${Extract}` `` | `` `GET ${string} ${Extract}` `` | `` `HEAD ${string} ${Extract}` `` | `` `LINK ${string} ${Extract}` `` | `` `LOCK ${string} ${Extract}` `` | `` `M-SEARCH ${string} ${Extract}` `` | `` `MERGE ${string} ${Extract}` `` | `` `MKACTIVITY ${string} ${Extract}` `` | `` `MKCALENDAR ${string} ${Extract}` `` | `` `MKCOL ${string} ${Extract}` `` | `` `MOVE ${string} ${Extract}` `` | `` `NOTIFY ${string} ${Extract}` `` | `` `OPTIONS ${string} ${Extract}` `` | `` `PATCH ${string} ${Extract}` `` | `` `POST ${string} ${Extract}` `` | `` `PROPFIND ${string} ${Extract}` `` | `` `PROPPATCH ${string} ${Extract}` `` | `` `PURGE ${string} ${Extract}` `` | `` `PUT ${string} ${Extract}` `` | `` `REBIND ${string} ${Extract}` `` | `` `REPORT ${string} ${Extract}` `` | `` `SEARCH ${string} ${Extract}` `` | `` `SOURCE ${string} ${Extract}` `` | `` `SUBSCRIBE ${string} ${Extract}` `` | `` `TRACE ${string} ${Extract}` `` | `` `UNBIND ${string} ${Extract}` `` | `` `UNLINK ${string} ${Extract}` `` | `` `UNLOCK ${string} ${Extract}` `` | `` `UNSUBSCRIBE ${string} ${Extract}` ``)\[] ## Returns [`Plugin`](../interfaces/Plugin.md)<`unknown`, { `name?`: `string`; }> --- --- url: /api/@minimajs/cookie/functions/cookies.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/cookie](../README.md) / cookies # Function: cookies() ```ts function cookies(): T; ``` Retrieves all cookies from the current request as a typed record. ## Type Parameters ### T `T` = `Record`<`string`, `string`> Type definition for the cookie object (defaults to `Record`) ## Returns `T` All cookies as a typed record ## Example ```typescript // Get all cookies (untyped) const allCookies = cookies(); // Type: Record // Get all cookies with type safety interface UserCookies { sessionId?: string; theme?: "light" | "dark"; } const userCookies = cookies(); // Type: UserCookies ``` ## Since 1.0.0 --- --- url: /api/@minimajs/server/@minimajs/server/plugins/functions/cors.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / cors # Function: cors() ```ts function cors(options): PluginSync; ``` Creates a CORS plugin that handles Cross-Origin Resource Sharing. Uses the send hook to set CORS headers on responses. ## Parameters ### options [`CorsOptions`](../interfaces/CorsOptions.md) = `{}` Configuration options for CORS ## Returns [`PluginSync`](../../interfaces/PluginSync.md)<`unknown`> A plugin that adds CORS support to the app ## Example ```typescript import { cors } from '@minimajs/server/plugins'; // Allow all origins app.register(cors()); // Custom configuration app.register(cors({ origin: 'https://example.com', credentials: true, methods: ['GET', 'POST'], })); // Dynamic origin validation app.register(cors({ origin: (origin) => { return origin.endsWith('.example.com'); } })); ``` --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/compose/functions/create.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [compose](../README.md) / create # Function: create() ```ts function create(...plugins): (mod) => Registerable; ``` Creates a higher-order function that applies multiple plugins to a module. This allows you to pre-configure a set of plugins and apply them to different modules. ## Type Parameters ### S `S` ## Parameters ### plugins ...[`Registerable`](../../../type-aliases/Registerable.md)<`S`>\[] Array of plugins to be applied ## Returns A function that takes a module and returns a new module with all plugins applied ```ts (mod): Registerable; ``` ### Parameters #### mod [`Registerable`](../../../type-aliases/Registerable.md)<`S`> ### Returns [`Registerable`](../../../type-aliases/Registerable.md)<`S`> ## Example ```typescript // Create a composer with common plugins const withAuth = compose.create( authPlugin, loggingPlugin ); // Apply to different modules const usersModule = (app: App) => { app.get("/users", () => ({ users: [] })); }); app.register(withAuth(usersModule)); ``` --- --- url: /api/@minimajs/server/@minimajs/server/bun/functions/createApp.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/bun](../README.md) / createApp # Function: createApp() ```ts function createApp(options): Server>; ``` Creates a new Minima.js application using the Bun runtime adapter. This is the primary factory function for initializing Minima.js applications on Bun. It sets up the server with Bun-specific optimizations and returns a configured application instance. ## Type Parameters ### T `T` = `unknown` Type for additional server context data ## Parameters ### options [`BunAppOptions`](../interfaces/BunAppOptions.md)<`T`> = `{}` Configuration options for the application ## Returns [`Server`](../../classes/Server.md)<`Server`<`T`>> A configured Minima.js server instance ## Example ```typescript const app = createApp({ server: { development: process.env.NODE_ENV !== 'production' } }); ``` --- --- url: /api/@minimajs/server/@minimajs/server/node/functions/createApp.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/node](../README.md) / createApp # Function: createApp() ```ts function createApp(options): Server>; ``` Creates a new Minima.js application for Node.js runtime. ## Parameters ### options [`NodeAppOptions`](../interfaces/NodeAppOptions.md) = `{}` Configuration options for the application ## Returns [`Server`](../../classes/Server.md)<`Server`<*typeof* `IncomingMessage`, *typeof* `ServerResponse`>> A configured Minima.js application instance ## Example ```typescript import { createApp } from '@minimajs/server/node'; const app = createApp(); app.get('/api/users', () => [{ id: 1, name: 'John' }]); app.listen({ port: 3000 }); ``` --- --- url: /api/@minimajs/auth/functions/createAuth.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/auth](../README.md) / createAuth # Function: createAuth() ## Call Signature ```ts function createAuth(callback, option): [PluginSync, AuthResourceWithRequired]; ``` Creates an authentication middleware plugin and resource accessor for Minima.js applications. This function sets up authentication by creating a middleware plugin that executes your authentication logic and a resource accessor function to retrieve the authenticated data throughout your application. ### Type Parameters #### T `T` The type of the authentication data (e.g., User object) #### S `S` ### Parameters #### callback [`AuthCallback`](../type-aliases/AuthCallback.md)<`T`> An async or sync function that performs authentication logic. Should return the authenticated data (e.g., user object) or throw a BaseHttpError (like UnauthorizedError) if authentication fails. #### option Configuration options for authentication behavior: \- `required: true` - Makes authentication mandatory. The resource accessor will always return T (non-nullable). If authentication fails, all routes protected by this plugin will automatically throw the authentication error. \- If omitted, authentication is optional. The resource accessor returns T | undefined, allowing routes to handle missing authentication gracefully. ##### required `true` ### Returns \[[`PluginSync`](../../server/@minimajs/server/interfaces/PluginSync.md)<`S`>, [`AuthResourceWithRequired`](../interfaces/AuthResourceWithRequired.md)<`T`>] A tuple containing: 1. `plugin` - A middleware plugin to register with your app using `app.register(plugin)` 2. `resource` - A function to access the authenticated data: * When `required: true`: Returns T (non-nullable) * When optional: Returns T | undefined * Has a `.required()` method that always returns T or throws if auth failed ### Examples ```typescript // Optional authentication import { headers } from "@minimajs/server"; import { createAuth, UnauthorizedError } from "@minimajs/auth"; export const [plugin, getUser] = createAuth(async () => { const token = headers.get("x-user-token"); const user = await User.findByToken(token); if (!user) { throw new UnauthorizedError("Invalid credentials"); } return user; }); // In your app app.register(plugin); app.get("/", () => { const user = getUser(); // User | undefined if (user) console.log(`Logged in as ${user.name}`); }); // Create a guard for protected routes function guard() { getUser.required(); // Throws if auth failed } app.register(interceptor([guard], protectedRoutes)); ``` ```typescript // Required authentication (all routes protected by default) export const [plugin, getUser] = createAuth( async () => { const token = headers.get("x-user-token"); const user = await User.findByToken(token); if (!user) { throw new UnauthorizedError("Invalid credentials"); } return user; }, { required: true } ); // In your app app.register(plugin); // All routes now require authentication app.get("/profile", () => { const user = getUser(); // User (non-nullable) return { name: user.name }; // TypeScript knows user exists }); ``` ## Call Signature ```ts function createAuth(callback): [PluginSync, AuthResourceOptional]; ``` Creates an authentication middleware plugin and resource accessor for Minima.js applications. This function sets up authentication by creating a middleware plugin that executes your authentication logic and a resource accessor function to retrieve the authenticated data throughout your application. ### Type Parameters #### T `T` The type of the authentication data (e.g., User object) #### S `S` ### Parameters #### callback [`AuthCallback`](../type-aliases/AuthCallback.md)<`T`> An async or sync function that performs authentication logic. Should return the authenticated data (e.g., user object) or throw a BaseHttpError (like UnauthorizedError) if authentication fails. ### Returns \[[`PluginSync`](../../server/@minimajs/server/interfaces/PluginSync.md)<`S`>, [`AuthResourceOptional`](../interfaces/AuthResourceOptional.md)<`T`>] A tuple containing: 1. `plugin` - A middleware plugin to register with your app using `app.register(plugin)` 2. `resource` - A function to access the authenticated data: * When `required: true`: Returns T (non-nullable) * When optional: Returns T | undefined * Has a `.required()` method that always returns T or throws if auth failed ### Examples ```typescript // Optional authentication import { headers } from "@minimajs/server"; import { createAuth, UnauthorizedError } from "@minimajs/auth"; export const [plugin, getUser] = createAuth(async () => { const token = headers.get("x-user-token"); const user = await User.findByToken(token); if (!user) { throw new UnauthorizedError("Invalid credentials"); } return user; }); // In your app app.register(plugin); app.get("/", () => { const user = getUser(); // User | undefined if (user) console.log(`Logged in as ${user.name}`); }); // Create a guard for protected routes function guard() { getUser.required(); // Throws if auth failed } app.register(interceptor([guard], protectedRoutes)); ``` ```typescript // Required authentication (all routes protected by default) export const [plugin, getUser] = createAuth( async () => { const token = headers.get("x-user-token"); const user = await User.findByToken(token); if (!user) { throw new UnauthorizedError("Invalid credentials"); } return user; }, { required: true } ); // In your app app.register(plugin); // All routes now require authentication app.get("/profile", () => { const user = getUser(); // User (non-nullable) return { name: user.name }; // TypeScript knows user exists }); ``` --- --- url: /api/@minimajs/server/@minimajs/server/core/functions/createBaseServer.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/core](../README.md) / createBaseServer # Function: createBaseServer() ```ts function createBaseServer(server, options): Server; ``` Creates a Minima.js application instance using a custom runtime adapter. This is the low-level factory used internally by `createApp` from both the Bun and Node.js runtime packages. Use it directly when targeting a custom runtime (e.g. Deno, uWebSockets.js) by providing your own `ServerAdapter`. Registers the following built-in plugins automatically: * `contextProvider` — sets up per-request `AsyncLocalStorage` context * `deferrer` — enables post-response `defer()` callbacks * `bodyParser` — parses `application/json` request bodies by default * `routeLogger` — logs registered routes during startup * `moduleDiscovery` — auto-discovers `module.ts` files (unless disabled) ## Type Parameters ### T `T` ## Parameters ### server [`ServerAdapter`](../../interfaces/ServerAdapter.md)<`T`> ### options [`CreateBaseSeverOptions`](../interfaces/CreateBaseSeverOptions.md) ## Returns [`Server`](../../classes/Server.md)<`T`> ## Example ```typescript import { createBaseServer } from "@minimajs/server/core"; import { MyCustomAdapter } from "./my-adapter.js"; const app = createBaseServer(new MyCustomAdapter(), { prefix: "/api", logger: false, }); app.get("/health", () => ({ status: "ok" })); await app.listen({ port: 3000 }); ``` --- --- url: /api/@minimajs/schema/functions/createBody.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/schema](../README.md) / [](../README.md) / createBody # Function: createBody() ```ts function createBody(schema, option): SchemaValidator>; ``` ## Type Parameters ### T `T` *extends* `ZodType`<`unknown`, `unknown`, `$ZodTypeInternals`<`unknown`, `unknown`>> ## Parameters ### schema `T` ### option [`ValidationOptions`](../validation/interfaces/ValidationOptions.md) = `{}` ## Returns [`SchemaValidator`](../type-aliases/SchemaValidator.md)<`output`<`T`>> --- --- url: /api/@minimajs/schema/functions/createBodyAsync.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/schema](../README.md) / [](../README.md) / createBodyAsync # Function: createBodyAsync() ```ts function createBodyAsync(schema, option): SchemaValidator>>; ``` ## Type Parameters ### T `T` *extends* `ZodType`<`unknown`, `unknown`, `$ZodTypeInternals`<`unknown`, `unknown`>> ## Parameters ### schema `T` ### option [`ValidationOptions`](../validation/interfaces/ValidationOptions.md) = `{}` ## Returns [`SchemaValidator`](../type-aliases/SchemaValidator.md)<`Promise`<`output`<`T`>>> --- --- url: /api/@minimajs/server/@minimajs/server/functions/createContext.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / createContext # Function: createContext() ```ts function createContext(value?): readonly [() => T, (val) => void]; ``` Creates a context for sharing data within a request's scope. It enables sharing data within the request scope without the need to explicitly pass it around. ## Type Parameters ### T `T` ## Parameters ### value? The default value for the context. `T` | () => `T` ## Returns readonly \[() => `T`, (`val`) => `void`] A tuple containing a getter and a setter for the context value. ## Example ```ts import { createContext } from "@minimajs/server"; export interface User { name: string; } // default name is empty string export const [getUser, setUser] = createContext({ name: "" }); ``` ## Since v0.1.0 --- --- url: /api/@minimajs/schema/functions/createHeaders.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/schema](../README.md) / [](../README.md) / createHeaders # Function: createHeaders() ```ts function createHeaders(obj, option): SchemaValidator<$InferObjectOutput<{ -readonly [P in string | number | symbol]: T[P] }, { }>>; ``` ## Type Parameters ### T `T` *extends* `Readonly`<{ \[`k`: `string`]: `$ZodType`<`unknown`, `unknown`, `$ZodTypeInternals`<`unknown`, `unknown`>>; }> ## Parameters ### obj `T` ### option [`ValidationOptions`](../validation/interfaces/ValidationOptions.md) = `{}` ## Returns [`SchemaValidator`](../type-aliases/SchemaValidator.md)<`$InferObjectOutput`<{ -readonly \[P in string | number | symbol]: T\[P] }, { }>> --- --- url: /api/@minimajs/schema/functions/createHeadersAsync.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/schema](../README.md) / [](../README.md) / createHeadersAsync # Function: createHeadersAsync() ```ts function createHeadersAsync(obj, option): SchemaValidator>>; ``` ## Type Parameters ### T `T` *extends* `Readonly`<{ \[`k`: `string`]: `$ZodType`<`unknown`, `unknown`, `$ZodTypeInternals`<`unknown`, `unknown`>>; }> ## Parameters ### obj `T` ### option [`ValidationOptions`](../validation/interfaces/ValidationOptions.md) = `{}` ## Returns [`SchemaValidator`](../type-aliases/SchemaValidator.md)<`Promise`<`$InferObjectOutput`<{ -readonly \[P in string | number | symbol]: T\[P] }, { }>>> --- --- url: /api/@minimajs/server/@minimajs/server/functions/createHooksStore.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / createHooksStore # Function: createHooksStore() ```ts function createHooksStore(parent?): HookStore; ``` Creates a new HookStore with proper cloning support for module isolation ## Parameters ### parent? [`HookStore`](../type-aliases/HookStore.md) ## Returns [`HookStore`](../type-aliases/HookStore.md) --- --- url: /api/@minimajs/server/@minimajs/server/logger/functions/createLogger.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/logger](../README.md) / createLogger # Function: createLogger() ```ts function createLogger(option): Logger; ``` Creates a Pino logger instance with merged default options and mixin support. Combines default logger options with user-provided options and adds module name context. ## Parameters ### option `LoggerOptions` = `{}` ## Returns `Logger`<`never`, `boolean`> --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/schema/functions/createMultipart.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/multipart](../../../../README.md) / [@minimajs/multipart/schema](../README.md) / createMultipart # Function: createMultipart() ```ts function createMultipart(obj, option): () => Promise<$InferObjectOutput>; ``` Creates a type-safe multipart form data parser with Zod schema validation. Returns a function that parses and validates incoming multipart requests, providing TempFile instances for uploaded files (disk-backed, memory-efficient). ## Type Parameters ### T `T` *extends* `Readonly`<{ \[`k`: `string`]: `$ZodType`<`unknown`, `unknown`, `$ZodTypeInternals`<`unknown`, `unknown`>>; }> Zod schema shape defining expected fields and files ## Parameters ### obj `T` Zod schema object defining the structure of multipart data ### option [`UploadOption`](../interfaces/UploadOption.md) = `{}` Optional upload configuration (limits, temp directory, etc.) ## Returns Async function that parses and validates multipart data ```ts (): Promise<$InferObjectOutput>; ``` ### Returns `Promise`<`$InferObjectOutput`<`T`, { }>> ## Throws When validation fails (wrapped ZodError) ## Example ```ts import { z } from 'zod'; import { createMultipart } from "@minimajs/multipart/schema"; import { helpers } from "@minimajs/multipart"; const upload = createMultipart({ name: z.string().min(3).max(30), avatar: z.file().max(2 * 1024 * 1024), // 2MB max }); const data = await upload(); console.log(data.name); // Type-safe access await helpers.save(data.avatar, "./uploads/avatars"); ``` --- --- url: /api/@minimajs/schema/functions/createParams.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/schema](../README.md) / [](../README.md) / createParams # Function: createParams() ```ts function createParams(obj, option): SchemaValidator<$InferObjectOutput<{ -readonly [P in string | number | symbol]: T[P] }, { }>>; ``` ## Type Parameters ### T `T` *extends* `Readonly`<{ \[`k`: `string`]: `$ZodType`<`unknown`, `unknown`, `$ZodTypeInternals`<`unknown`, `unknown`>>; }> ## Parameters ### obj `T` ### option [`ValidationOptions`](../validation/interfaces/ValidationOptions.md) = `{}` ## Returns [`SchemaValidator`](../type-aliases/SchemaValidator.md)<`$InferObjectOutput`<{ -readonly \[P in string | number | symbol]: T\[P] }, { }>> --- --- url: /api/@minimajs/schema/functions/createParamsAsync.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/schema](../README.md) / [](../README.md) / createParamsAsync # Function: createParamsAsync() ```ts function createParamsAsync(obj, option): SchemaValidator>>; ``` ## Type Parameters ### T `T` *extends* `Readonly`<{ \[`k`: `string`]: `$ZodType`<`unknown`, `unknown`, `$ZodTypeInternals`<`unknown`, `unknown`>>; }> ## Parameters ### obj `T` ### option [`ValidationOptions`](../validation/interfaces/ValidationOptions.md) = `{}` ## Returns [`SchemaValidator`](../type-aliases/SchemaValidator.md)<`Promise`<`$InferObjectOutput`<{ -readonly \[P in string | number | symbol]: T\[P] }, { }>>> --- --- url: /api/@minimajs/server/@minimajs/server/mock/functions/createRequest.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/mock](../README.md) / createRequest # Function: createRequest() ```ts function createRequest(url, options): Request; ``` ## Parameters ### url `string` ### options [`MockRequestOptions`](../interfaces/MockRequestOptions.md) = `{}` ## Returns `Request` --- --- url: /api/@minimajs/schema/functions/createResponse.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/schema](../README.md) / [](../README.md) / createResponse # Function: createResponse() ## Call Signature ```ts function createResponse(schema, options?): SchemaType; ``` Creates a response body schema descriptor for OpenAPI documentation. Unlike request validators, this doesn't perform runtime validation - it only attaches the schema to route metadata for documentation generation. ### Type Parameters #### T `T` *extends* `ZodType`<`unknown`, `unknown`, `$ZodTypeInternals`<`unknown`, `unknown`>> ### Parameters #### schema `T` #### options? ##### name? `string` ### Returns [`SchemaType`](../type-aliases/SchemaType.md) ### Example ```typescript import { schema, createBody, createResponse } from "@minimajs/schema"; import { z } from "zod"; const bodySchema = createBody(z.object({ name: z.string() })); // Default status code (200) const responseSchema = createResponse(z.object({ id: z.string(), name: z.string() })); // Explicit status code const createdSchema = createResponse(201, z.object({ id: z.string() })); const errorSchema = createResponse(400, z.object({ error: z.string() })); app.post('/users', schema(bodySchema, responseSchema, errorSchema), () => { const { name } = bodySchema(); return { id: crypto.randomUUID(), name }; } ); ``` ## Call Signature ```ts function createResponse( statusCode, schema, options?): SchemaType; ``` Creates a response body schema descriptor for OpenAPI documentation. Unlike request validators, this doesn't perform runtime validation - it only attaches the schema to route metadata for documentation generation. ### Type Parameters #### T `T` *extends* `ZodType`<`unknown`, `unknown`, `$ZodTypeInternals`<`unknown`, `unknown`>> ### Parameters #### statusCode `number` #### schema `T` #### options? ##### name? `string` ### Returns [`SchemaType`](../type-aliases/SchemaType.md) ### Example ```typescript import { schema, createBody, createResponse } from "@minimajs/schema"; import { z } from "zod"; const bodySchema = createBody(z.object({ name: z.string() })); // Default status code (200) const responseSchema = createResponse(z.object({ id: z.string(), name: z.string() })); // Explicit status code const createdSchema = createResponse(201, z.object({ id: z.string() })); const errorSchema = createResponse(400, z.object({ error: z.string() })); app.post('/users', schema(bodySchema, responseSchema, errorSchema), () => { const { name } = bodySchema(); return { id: crypto.randomUUID(), name }; } ); ``` --- --- url: /api/@minimajs/schema/functions/createResponseHeaders.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/schema](../README.md) / [](../README.md) / createResponseHeaders # Function: createResponseHeaders() ## Call Signature ```ts function createResponseHeaders(obj, options?): SchemaType; ``` Creates a response headers schema descriptor for OpenAPI documentation. Unlike request validators, this doesn't perform runtime validation - it only attaches the schema to route metadata for documentation generation. This allows you to document response headers independently from the response body, enabling different status codes for headers and body schemas. ### Type Parameters #### T `T` *extends* `Readonly`<{ \[`k`: `string`]: `$ZodType`<`unknown`, `unknown`, `$ZodTypeInternals`<`unknown`, `unknown`>>; }> ### Parameters #### obj `T` #### options? ##### name? `string` ### Returns [`SchemaType`](../type-aliases/SchemaType.md) ### Example ```typescript import { schema, createBody, createResponse, createResponseHeaders } from "@minimajs/schema"; import { z } from "zod"; const bodySchema = createBody(z.object({ name: z.string() })); const responseBodySchema = createResponse(z.object({ id: z.string(), name: z.string() })); const responseHeadersSchema = createResponseHeaders({ 'x-custom': z.string() }); // Different status codes for body and headers const createdBodySchema = createResponse(201, z.object({ id: z.string() })); const unauthorizedHeadersSchema = createResponseHeaders(401, { 'www-authenticate': z.string() }); app.post('/users', schema(bodySchema, createdBodySchema, responseHeadersSchema, unauthorizedHeadersSchema), () => { const { name } = bodySchema(); return { id: crypto.randomUUID(), name }; } ); ``` ## Call Signature ```ts function createResponseHeaders( statusCode, obj, options?): SchemaType; ``` Creates a response headers schema descriptor for OpenAPI documentation. Unlike request validators, this doesn't perform runtime validation - it only attaches the schema to route metadata for documentation generation. This allows you to document response headers independently from the response body, enabling different status codes for headers and body schemas. ### Type Parameters #### T `T` *extends* `Readonly`<{ \[`k`: `string`]: `$ZodType`<`unknown`, `unknown`, `$ZodTypeInternals`<`unknown`, `unknown`>>; }> ### Parameters #### statusCode `number` #### obj `T` #### options? ##### name? `string` ### Returns [`SchemaType`](../type-aliases/SchemaType.md) ### Example ```typescript import { schema, createBody, createResponse, createResponseHeaders } from "@minimajs/schema"; import { z } from "zod"; const bodySchema = createBody(z.object({ name: z.string() })); const responseBodySchema = createResponse(z.object({ id: z.string(), name: z.string() })); const responseHeadersSchema = createResponseHeaders({ 'x-custom': z.string() }); // Different status codes for body and headers const createdBodySchema = createResponse(201, z.object({ id: z.string() })); const unauthorizedHeadersSchema = createResponseHeaders(401, { 'www-authenticate': z.string() }); app.post('/users', schema(bodySchema, createdBodySchema, responseHeadersSchema, unauthorizedHeadersSchema), () => { const { name } = bodySchema(); return { id: crypto.randomUUID(), name }; } ); ``` --- --- url: /api/@minimajs/schema/functions/createSearchParams.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/schema](../README.md) / [](../README.md) / createSearchParams # Function: createSearchParams() ```ts function createSearchParams(obj, option): SchemaValidator<$InferObjectOutput<{ -readonly [P in string | number | symbol]: T[P] }, { }>>; ``` ## Type Parameters ### T `T` *extends* `Readonly`<{ \[`k`: `string`]: `$ZodType`<`unknown`, `unknown`, `$ZodTypeInternals`<`unknown`, `unknown`>>; }> ## Parameters ### obj `T` ### option [`ValidationOptions`](../validation/interfaces/ValidationOptions.md) = `{}` ## Returns [`SchemaValidator`](../type-aliases/SchemaValidator.md)<`$InferObjectOutput`<{ -readonly \[P in string | number | symbol]: T\[P] }, { }>> --- --- url: /api/@minimajs/schema/functions/createSearchParamsAsync.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/schema](../README.md) / [](../README.md) / createSearchParamsAsync # Function: createSearchParamsAsync() ```ts function createSearchParamsAsync(obj, option): SchemaValidator>>; ``` ## Type Parameters ### T `T` *extends* `Readonly`<{ \[`k`: `string`]: `$ZodType`<`unknown`, `unknown`, `$ZodTypeInternals`<`unknown`, `unknown`>>; }> ## Parameters ### obj `T` ### option [`ValidationOptions`](../validation/interfaces/ValidationOptions.md) = `{}` ## Returns [`SchemaValidator`](../type-aliases/SchemaValidator.md)<`Promise`<`$InferObjectOutput`<{ -readonly \[P in string | number | symbol]: T\[P] }, { }>>> --- --- url: /api/@minimajs/server/@minimajs/server/plugins/functions/defer.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / defer # Function: defer() ```ts function defer(cb): void; ``` Registers a callback to execute after the response. Useful for cleanup tasks, logging, or post-response processing. ## Parameters ### cb [`DeferCallback`](../type-aliases/DeferCallback.md) The callback function to execute after response ## Returns `void` ## Example ```typescript import { defer } from '@minimajs/server'; app.get('/user/:id', async (req) => { const user = await getUser(params.get('id')); defer(() => { console.log('Response send, logging metrics...'); logMetrics('user-fetched', { userId: user.id }); }); return user; }); ``` --- --- url: /api/@minimajs/server/@minimajs/server/plugins/functions/deferrer.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / deferrer # Function: deferrer() ```ts function deferrer(): PluginSync; ``` Creates a plugin that enables defer and onError functionality. This plugin registers hooks to run deferred callbacks after response is sent and error callbacks when an error occurs. ## Returns [`PluginSync`](../../interfaces/PluginSync.md)<`unknown`> A plugin that adds defer and onError functionality to the app ## Example ```typescript import { minimaPlugin } from '@minimajs/server/plugins'; const app = createApp(); app.register(minimaPlugin()); ``` --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/hook/functions/define.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [hook](../README.md) / define # Function: define() ```ts function define(hooks): PluginSync; ``` Creates a plugin that registers multiple hooks at once ## Type Parameters ### S `S` ## Parameters ### hooks `Partial`<{ `close`: [`OnCloseHook`](../../../type-aliases/OnCloseHook.md); `error`: [`OnErrorHook`](../../../type-aliases/OnErrorHook.md); `listen`: [`OnListenHook`](../../../type-aliases/OnListenHook.md); `ready`: [`OnReadyHook`](../../../type-aliases/OnReadyHook.md); `register`: [`OnRegisterHook`](../../../type-aliases/OnRegisterHook.md); `request`: [`OnRequestHook`](../../../type-aliases/OnRequestHook.md); `send`: [`OnSendHook`](../../../type-aliases/OnSendHook.md); `timeout`: [`OnTimeoutHook`](../../../type-aliases/OnTimeoutHook.md); `transform`: [`OnTransformHook`](../../../type-aliases/OnTransformHook.md); }> ## Returns [`PluginSync`](../../../interfaces/PluginSync.md)<`S`> --- --- url: /api/@minimajs/openapi/functions/describe.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/openapi](../README.md) / describe # Function: describe() ```ts function describe(options): RouteMetaDescriptor; ``` Adds OpenAPI operation metadata to a route. ## Type Parameters ### S `S` = `any` ## Parameters ### options [`OperationObject`](../namespaces/OpenAPI/type-aliases/OperationObject.md) ## Returns [`RouteMetaDescriptor`](../../server/@minimajs/server/type-aliases/RouteMetaDescriptor.md)<`S`> ## Example ```typescript import { describe } from "@minimajs/openapi"; app.get("/users", describe({ summary: "List all users", tags: ["Users"] }), () => { return getUsers(); }); app.post("/users", describe({ summary: "Create a user", description: "Creates a new user account with the provided details.", tags: ["Users"], operationId: "createUser" }), () => { return createUser(); }); app.get("/legacy", describe({ deprecated: true }), () => { return legacyEndpoint(); }); ``` --- --- url: /api/@minimajs/server/@minimajs/server/plugins/functions/descriptor.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / descriptor # Function: descriptor() ```ts function descriptor(...meta): PluginSync; ``` Creates a plugin that adds metadata to all routes registered within its scope. Route descriptors can be either: * A tuple `[key, value]` to set a specific metadata entry * A function that receives the route config and can modify metadata dynamically ## Type Parameters ### T `T` ## Parameters ### meta ...[`RouteMetaDescriptor`](../../type-aliases/RouteMetaDescriptor.md)<`T`>\[] One or more route metadata descriptors to apply to all routes in the module ## Returns [`PluginSync`](../../interfaces/PluginSync.md)<`T`> A plugin that registers the descriptors for route metadata ## Example ```typescript // Single descriptor app.register(descriptor([authTag, "required"])); // Multiple descriptors app.register(descriptor( [authTag, "required"], [rateLimitTag, { max: 100 }], describe({ tags: ["Users"] }) )); // Function descriptor for dynamic metadata app.register(descriptor((route) => { route.metadata[kPath] = route.path; })); // In module meta.plugins export const meta = { plugins: [ descriptor([adminTag, true], describe({ tags: ["Admin"] })), ], }; ``` --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/helpers/functions/drain.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [helpers](../README.md) / drain # Function: drain() ```ts function drain(file): Promise; ``` Consumes and discards a raw multipart file stream. ## Parameters ### file [`MultipartRawFile`](../../../interfaces/MultipartRawFile.md) ## Returns `Promise`<`void`> --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/helpers/functions/ensurePath.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [helpers](../README.md) / ensurePath # Function: ensurePath() ```ts function ensurePath(...paths): Promise; ``` Ensures a directory path exists, creating it recursively if needed. ## Parameters ### paths ...`string`\[] ## Returns `Promise`<`string`> ## Example ```ts const dir = await ensurePath('/uploads', 'images'); // Creates /uploads/images if it doesn't exist ``` --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/runHooks/functions/error.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [runHooks](../README.md) / error # Function: error() ```ts function error( app, error, ctx): Promise; ``` ## Type Parameters ### S `S` ## Parameters ### app [`App`](../../../interfaces/App.md)<`S`> ### error `unknown` ### ctx [`Context`](../../../interfaces/Context.md)<`S`> ## Returns `Promise`<`unknown`> --- --- url: /api/@minimajs/server/@minimajs/server/plugins/functions/express.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / express # Function: express() ```ts function express(callback): PluginSync< | Server | Server>; ``` Integrates an Express-style middleware into the request lifecycle. This function creates a plugin that registers a middleware compatible with Express.js. The middleware function receives the incoming request and response objects, along with a `next` callback to signal completion or pass errors. ## Parameters ### callback [`ExpressCallback`](../type-aliases/ExpressCallback.md) The Express-style middleware function ## Returns [`PluginSync`](../../interfaces/PluginSync.md)< | `Server`<*typeof* `IncomingMessage`, *typeof* `ServerResponse`> | `Server`<*typeof* `IncomingMessage`, *typeof* `ServerResponse`>> A plugin that adds the middleware to the request hook ## Example ```typescript import { express } from '@minimajs/server/plugins/express'; const app = createApp(); // Use Express middleware (Only works with Node.js server) app.register( express((req, res, next) => { console.log('Request URL:', req.url); next(); }) ); ``` --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/hook/functions/factory.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [hook](../README.md) / factory # Function: factory() ```ts function factory(callback): PluginSync; ``` ## Type Parameters ### S `S` ## Parameters ### callback [`HookFactoryCallback`](../../../type-aliases/HookFactoryCallback.md)<`S`> ## Returns [`PluginSync`](../../../interfaces/PluginSync.md)<`S`> --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/multipart/functions/fields.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [multipart](../README.md) / fields # Function: fields() ```ts function fields(): Promise; ``` Retrieves all text fields from a multipart form request. Files are ignored - only text field data is processed. ## Type Parameters ### T `T` *extends* `Record`<`string`, `string` | `string`\[]> The expected shape of the fields object ## Returns `Promise`<`T`> A promise that resolves to an object containing field names and their values ## Example ```ts const fields = await multipart.fields<{ name: string; email: string }>(); console.log(fields.name, fields.email); ``` --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/multipart/functions/file.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [multipart](../README.md) / file # Function: file() ```ts function file(name, options): Promise; ``` Retrieves a single file from a multipart form request. ## Parameters ### name `string` field name to match. Only files from this field are returned. ### options [`MultipartOptions`](../../../type-aliases/MultipartOptions.md) = `{}` ## Returns `Promise`<`File` | `null`> A promise that resolves to the uploaded File ## Example ```ts // Get file from specific field const avatar = await multipart.file('avatar'); if (avatar) { await helpers.save(avatar, './uploads'); } ``` --- --- url: /api/@minimajs/multipart/@minimajs/multipart/namespaces/raw/functions/file.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [raw](../README.md) / file # Function: file() ```ts function file(name, options): Promise; ``` Retrieves a raw file stream from a multipart form request without buffering into memory. Useful for streaming large files directly to disk or other destinations. ## Parameters ### name `string` field name to match ### options [`MultipartOptions`](../../../type-aliases/MultipartOptions.md) = `{}` ## Returns `Promise`<[`MultipartRawFile`](../../../interfaces/MultipartRawFile.md) | `null`> A promise that resolves to the raw file with stream, or null if not found ## Example ```ts const raw = await multipart.rawFile('video'); if (raw) { await pipeline(raw.stream, createWriteStream(`/uploads/${raw.filename}`)); } ``` --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/streaming/functions/file.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [streaming](../README.md) / file # Function: file() ```ts function file(name, options): Promise; ``` Retrieves a specific file field by name as a StreamFile (lazy streaming, not buffered). ## Parameters ### name `string` ### options [`MultipartOptions`](../../../type-aliases/MultipartOptions.md) = `{}` ## Returns `Promise`<[`StreamFile`](../classes/StreamFile.md) | `null`> --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/multipart/functions/files.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [multipart](../README.md) / files # Function: files() ```ts function files(options): AsyncGenerator; ``` Retrieves all files from a multipart form request as an async iterable. Field data is ignored - only files are processed. ## Parameters ### options [`MultipartOptions`](../../../type-aliases/MultipartOptions.md) = `{}` ## Returns `AsyncGenerator`\ An async iterable that yields File instances ## Example ```ts for await (const file of multipart.files()) { console.log(file.name); await helpers.save(file, '/uploads'); } ``` --- --- url: /api/@minimajs/multipart/@minimajs/multipart/namespaces/raw/functions/files.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [raw](../README.md) / files # Function: files() ```ts function files(options): AsyncGenerator; ``` ## Parameters ### options [`MultipartOptions`](../../../type-aliases/MultipartOptions.md) = `{}` ## Returns `AsyncGenerator`<[`MultipartRawFile`](../../../interfaces/MultipartRawFile.md)> --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/multipart/functions/firstFile.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [multipart](../README.md) / firstFile # Function: firstFile() ```ts function firstFile(options): Promise<[string, File] | null>; ``` Retrieves the first file from a multipart form request. ## Parameters ### options [`MultipartOptions`](../../../type-aliases/MultipartOptions.md) = `{}` ## Returns `Promise`<\[`string`, `File`] | `null`> A promise that resolves to a tuple of \[fieldName, File] or null if no file is found ## Example ```ts const result = await multipart.firstFile(); if (result) { const [fieldName, file] = result; console.log(`Received ${file.name} from field ${fieldName}`); } ``` --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/raw/functions/firstFile.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [raw](../README.md) / firstFile # Function: firstFile() ```ts function firstFile(options): Promise; ``` Retrieves the first raw file stream from a multipart form request without buffering. ## Parameters ### options [`MultipartOptions`](../../../type-aliases/MultipartOptions.md) = `{}` ## Returns `Promise`<[`MultipartRawFile`](../../../interfaces/MultipartRawFile.md) | `null`> A promise that resolves to the first raw file with stream, or null if no file is found ## Example ```ts const raw = await multipart.firstRawFile(); if (raw) { return response(Readable.toWeb(raw.stream), { headers: { 'Content-Type': raw.mimeType } }); } ``` --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/streaming/functions/firstFile.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [streaming](../README.md) / firstFile # Function: firstFile() ```ts function firstFile(options): Promise<[string, StreamFile] | null>; ``` Retrieves the first file field as a StreamFile with its field name. ## Parameters ### options [`MultipartOptions`](../../../type-aliases/MultipartOptions.md) = `{}` ## Returns `Promise`<\[`string`, [`StreamFile`](../classes/StreamFile.md)] | `null`> --- --- url: /api/@minimajs/openapi/functions/generateOpenAPIDocument.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/openapi](../README.md) / generateOpenAPIDocument # Function: generateOpenAPIDocument() ```ts function generateOpenAPIDocument(app, document): Document; ``` ## Parameters ### app [`App`](../../server/@minimajs/server/interfaces/App.md) ### document [`Document`](../namespaces/OpenAPI/type-aliases/Document.md) ## Returns [`Document`](../namespaces/OpenAPI/type-aliases/Document.md) --- --- url: /api/@minimajs/cookie/namespaces/cookies/functions/get.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/cookie](../../../README.md) / [cookies](../README.md) / get # Function: get() ```ts function get(name): string | undefined; ``` Retrieves a single cookie value by name. ## Parameters ### name `string` The cookie name ## Returns `string` | `undefined` The cookie value, or `undefined` if not found ## Example ```typescript const theme = cookies.get("theme"); // theme is string | undefined const userId = cookies.get("user-id"); if (!userId) { throw new Error("Not authenticated"); } ``` ## Since 1.0.0 --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/headers/functions/get.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [headers](../README.md) / get # Function: get() ## Call Signature ```ts function get(name): string | undefined; ``` Retrieves a single header value by name with optional transformation. Throws ValidationError if the header is not found. ### Parameters #### name [`HttpHeaderIncoming`](../../../type-aliases/HttpHeaderIncoming.md) The header name to retrieve ### Returns `string` | `undefined` ### Example ```ts const auth = headers.get('authorization'); // string const token = headers.get('authorization', (val) => val.split(' ')[1]); // string ``` ## Call Signature ```ts function get(name, transform): R | undefined; ``` Retrieves a single header value by name with optional transformation. Throws ValidationError if the header is not found. ### Type Parameters #### R `R` ### Parameters #### name [`HttpHeaderIncoming`](../../../type-aliases/HttpHeaderIncoming.md) The header name to retrieve #### transform (`value`) => `R` ### Returns `R` | `undefined` ### Example ```ts const auth = headers.get('authorization'); // string const token = headers.get('authorization', (val) => val.split(' ')[1]); // string ``` --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/params/functions/get.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [params](../README.md) / get # Function: get() ## Call Signature ```ts function get(name): string; ``` Retrieves a single param by name with optional transformation. Throws NotFoundError if the param is not found. ### Parameters #### name `string` ### Returns `string` ### Example ```ts const id = params.get('id'); // string const page = params.get('page', (val) => parseInt(val)); // number const age = params.get('age', (val) => { const num = parseInt(val); if (num < 0) throw new Error('must be positive'); return num; }); // number ``` ## Call Signature ```ts function get(name, transform): R; ``` Retrieves a single param by name with optional transformation. Throws NotFoundError if the param is not found. ### Type Parameters #### R `R` ### Parameters #### name `string` #### transform (`value`) => `R` ### Returns `R` ### Example ```ts const id = params.get('id'); // string const page = params.get('page', (val) => parseInt(val)); // number const age = params.get('age', (val) => { const num = parseInt(val); if (num < 0) throw new Error('must be positive'); return num; }); // number ``` --- --- url: >- /api/@minimajs/server/@minimajs/server/namespaces/searchParams/functions/get.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [searchParams](../README.md) / get # Function: get() ## Call Signature ```ts function get(name): string | undefined; ``` Retrieves a single search param by name with optional transformation. Throws ValidationError if the param is not found. ### Parameters #### name `string` The query parameter name to retrieve ### Returns `string` | `undefined` ### Example ```ts const page = searchParams.get('page'); // string const pageNum = searchParams.get('page', (val) => parseInt(val)); // number ``` ## Call Signature ```ts function get(name, transform): R; ``` Retrieves a single search param by name with optional transformation. Throws ValidationError if the param is not found. ### Type Parameters #### R `R` ### Parameters #### name `string` The query parameter name to retrieve #### transform (`value`) => `R` ### Returns `R` ### Example ```ts const page = searchParams.get('page'); // string const pageNum = searchParams.get('page', (val) => parseInt(val)); // number ``` --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/headers/functions/getAll.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [headers](../README.md) / getAll # Function: getAll() ## Call Signature ```ts function getAll(name): string[]; ``` Retrieves all values for a header name with optional transformation. Returns an empty array if the header is not found. ### Parameters #### name [`HttpHeaderIncoming`](../../../type-aliases/HttpHeaderIncoming.md) The header name to retrieve ### Returns `string`\[] ### Example ```ts const cookies = headers.getAll('cookie'); // string[] const parsed = headers.getAll('cookie', (val) => val.split('=')); // string[][] ``` ## Call Signature ```ts function getAll(name, transform): R[]; ``` Retrieves all values for a header name with optional transformation. Returns an empty array if the header is not found. ### Type Parameters #### R `R` ### Parameters #### name [`HttpHeaderIncoming`](../../../type-aliases/HttpHeaderIncoming.md) The header name to retrieve #### transform (`value`) => `R` ### Returns `R`\[] ### Example ```ts const cookies = headers.getAll('cookie'); // string[] const parsed = headers.getAll('cookie', (val) => val.split('=')); // string[][] ``` --- --- url: >- /api/@minimajs/server/@minimajs/server/namespaces/searchParams/functions/getAll.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [searchParams](../README.md) / getAll # Function: getAll() ## Call Signature ```ts function getAll(name): string[]; ``` Retrieves all values for a search param by name with optional transformation. Returns an empty array if the param is not found. ### Parameters #### name `string` The query parameter name to retrieve ### Returns `string`\[] ### Example ```ts const tags = searchParams.getAll('tag'); // string[] const tagIds = searchParams.getAll('tag', (val) => parseInt(val)); // number[] ``` ## Call Signature ```ts function getAll(name, transform): R[]; ``` Retrieves all values for a search param by name with optional transformation. Returns an empty array if the param is not found. ### Type Parameters #### R `R` ### Parameters #### name `string` The query parameter name to retrieve #### transform (`value`) => `R` ### Returns `R`\[] ### Example ```ts const tags = searchParams.getAll('tag'); // string[] const tagIds = searchParams.getAll('tag', (val) => parseInt(val)); // number[] ``` --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/plugin/functions/getName.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [plugin](../README.md) / getName # Function: getName() ```ts function getName(fn, opts?): string; ``` ## Parameters ### fn [`Registerable`](../../../type-aliases/Registerable.md) ### opts? #### name? `string` ## Returns `string` --- --- url: /api/@minimajs/server/@minimajs/server/functions/handler.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / handler # Function: handler() ## Call Signature ```ts function handler(callback): Handler; ``` ### Type Parameters #### S `S` = `any` ### Parameters #### callback [`Handler`](../type-aliases/Handler.md)<`S`> ### Returns [`Handler`](../type-aliases/Handler.md)<`S`> ## Call Signature ```ts function handler(...args): Handler; ``` ### Type Parameters #### S `S` = `any` ### Parameters #### args ...\[`...descriptors: RouteMetaDescriptor[]`, [`Handler`](../type-aliases/Handler.md)<`S`>] ### Returns [`Handler`](../type-aliases/Handler.md)<`S`> --- --- url: /api/@minimajs/server/@minimajs/server/functions/headers.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / headers # Function: headers() ```ts function headers(): { [k: string]: string; }; ``` Retrieves the request headers. ## Returns ```ts { [k: string]: string; } ``` ## Example ```ts const h = headers(); console.log(h['content-type']); // Or use headers.get const auth = headers.get('authorization'); // Or use headers.getAll for all values const cookies = headers.getAll('cookie'); // Set a header headers.set('x-custom', 'value'); ``` ## Since v0.2.0 --- --- url: /api/@minimajs/server/@minimajs/server/functions/hook.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / hook # Function: hook() ## Call Signature ```ts function hook(name, callback): PluginSync; ``` Creates a plugin that registers a lifecycle hook ### Type Parameters #### S `S` ### Parameters #### name `"request"` #### callback [`OnRequestHook`](../type-aliases/OnRequestHook.md)<`S`> ### Returns [`PluginSync`](../interfaces/PluginSync.md)<`S`> ## Call Signature ```ts function hook(name, callback): PluginSync; ``` Creates a plugin that registers a lifecycle hook ### Type Parameters #### S `S` ### Parameters #### name `"transform"` #### callback [`OnTransformHook`](../type-aliases/OnTransformHook.md)<`S`> ### Returns [`PluginSync`](../interfaces/PluginSync.md)<`S`> ## Call Signature ```ts function hook(name, callback): PluginSync; ``` Creates a plugin that registers a lifecycle hook ### Type Parameters #### S `S` ### Parameters #### name `"send"` #### callback [`OnSendHook`](../type-aliases/OnSendHook.md)<`S`> ### Returns [`PluginSync`](../interfaces/PluginSync.md)<`S`> ## Call Signature ```ts function hook(name, callback): PluginSync; ``` Creates a plugin that registers a lifecycle hook ### Type Parameters #### S `S` ### Parameters #### name `"error"` #### callback [`OnErrorHook`](../type-aliases/OnErrorHook.md)<`S`> ### Returns [`PluginSync`](../interfaces/PluginSync.md)<`S`> ## Call Signature ```ts function hook(name, callback): PluginSync; ``` Creates a plugin that registers a lifecycle hook ### Type Parameters #### S `S` ### Parameters #### name `"timeout"` #### callback [`OnTimeoutHook`](../type-aliases/OnTimeoutHook.md)<`S`> ### Returns [`PluginSync`](../interfaces/PluginSync.md)<`S`> ## Call Signature ```ts function hook(name, callback): PluginSync; ``` Creates a plugin that registers a lifecycle hook ### Type Parameters #### S `S` ### Parameters #### name `"close"` #### callback [`OnCloseHook`](../type-aliases/OnCloseHook.md) ### Returns [`PluginSync`](../interfaces/PluginSync.md)<`S`> ## Call Signature ```ts function hook(name, callback): PluginSync; ``` Creates a plugin that registers a lifecycle hook ### Type Parameters #### S `S` ### Parameters #### name `"listen"` #### callback [`OnListenHook`](../type-aliases/OnListenHook.md) ### Returns [`PluginSync`](../interfaces/PluginSync.md)<`S`> ## Call Signature ```ts function hook(name, callback): PluginSync; ``` Creates a plugin that registers a lifecycle hook ### Type Parameters #### S `S` ### Parameters #### name `"ready"` #### callback [`OnReadyHook`](../type-aliases/OnReadyHook.md)<`S`> ### Returns [`PluginSync`](../interfaces/PluginSync.md)<`S`> ## Call Signature ```ts function hook(name, callback): PluginSync; ``` Creates a plugin that registers a lifecycle hook ### Type Parameters #### S `S` ### Parameters #### name `"register"` #### callback [`OnRegisterHook`](../type-aliases/OnRegisterHook.md) ### Returns [`PluginSync`](../interfaces/PluginSync.md)<`S`> --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/helpers/functions/humanFileSize.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [helpers](../README.md) / humanFileSize # Function: humanFileSize() ```ts function humanFileSize(bytes, dp): string; ``` Converts a byte count into a human-readable file size string with binary units. ## Parameters ### bytes `number` ### dp `number` = `1` ## Returns `string` ## Example ```ts humanFileSize(1024); // "1.0 KiB" humanFileSize(1536, 2); // "1.50 KiB" humanFileSize(5242880); // "5.0 MiB" ``` --- --- url: /api/@minimajs/openapi/functions/internal.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/openapi](../README.md) / internal # Function: internal() ```ts function internal(isInternal): RouteMetaDescriptor; ``` Marks a route as internal, excluding it from the OpenAPI spec. ## Parameters ### isInternal `boolean` = `true` ## Returns [`RouteMetaDescriptor`](../../server/@minimajs/server/type-aliases/RouteMetaDescriptor.md) ## Example ```typescript import { internal } from "@minimajs/openapi"; // Health check - not part of public API app.get("/health", internal(), () => "ok"); // Internal admin endpoint app.get("/admin/metrics", internal(), () => getMetrics()); ``` --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/request/functions/ip.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [request](../README.md) / ip # Function: ip() ```ts function ip(): string | null; ``` Retrieves the client IP address from the request. Requires IP address configuration via request.ip.configure(). ## Returns `string` | `null` The client IP address as a string ## Throws Error if IP address plugin is not configured ## Example ```ts import { request } from '@minimajs/server'; // Then use it in handlers app.get('/api/info', () => { const clientIp = request.ip(); return { ip: clientIp }; }); ``` --- --- url: >- /api/@minimajs/server/@minimajs/server/plugins/namespaces/proxy/functions/ip.md --- [**Minima.js API**](../../../../../../../../README.md) *** [Minima.js API](../../../../../../../../README.md) / [@minimajs/server](../../../../../../README.md) / [@minimajs/server/plugins](../../../README.md) / [proxy](../README.md) / ip # Function: ip() ```ts function ip(options): PluginSync; ``` ## Type Parameters ### S `S` ## Parameters ### options [`ProxyIpPluginOptions`](../../../interfaces/ProxyIpPluginOptions.md)<`S`> = `{}` ## Returns [`PluginSync`](../../../../interfaces/PluginSync.md)<`S`> --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/abort/functions/is.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [abort](../README.md) / is # Function: is() ```ts function is(error): error is BaseHttpError; ``` Checks if a given error is an aborted error. ## Parameters ### error `unknown` The error to check ## Returns `error is BaseHttpError` True if the error is a BaseHttpError ## Example ```ts if (abort.is(error)) { console.log('Request was aborted'); } ``` --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/plugin/functions/is.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [plugin](../README.md) / is # Function: is() ```ts function is(fn): fn is Plugin; ``` ## Type Parameters ### S `S` ## Parameters ### fn [`Registerable`](../../../type-aliases/Registerable.md) ## Returns `fn is Plugin` --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/helpers/functions/isFile.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [helpers](../README.md) / isFile # Function: isFile() ```ts function isFile(f): f is File; ``` Checks if a value is a Web API File instance. ## Parameters ### f `unknown` ## Returns `f is File` --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/helpers/functions/isRawField.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [helpers](../README.md) / isRawField # Function: isRawField() ```ts function isRawField(f): f is MultipartRawField; ``` Checks if a value is a raw multipart file from the parser. ## Parameters ### f `any` ## Returns `f is MultipartRawField` --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/helpers/functions/isRawFile.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [helpers](../README.md) / isRawFile # Function: isRawFile() ```ts function isRawFile(f): f is MultipartRawFile; ``` Checks if a value is a raw multipart file from the parser. ## Parameters ### f `any` ## Returns `f is MultipartRawFile` --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/plugin/functions/isSync.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [plugin](../README.md) / isSync # Function: isSync() ```ts function isSync(fn): fn is PluginSync; ``` ## Type Parameters ### S `S` ## Parameters ### fn [`Registerable`](../../../type-aliases/Registerable.md)<`S`> ## Returns `fn is PluginSync` --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/schema/functions/isUploadedFile.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/multipart](../../../../README.md) / [@minimajs/multipart/schema](../README.md) / isUploadedFile # Function: isUploadedFile() ```ts function isUploadedFile(f): f is TempFile; ``` ## Parameters ### f `unknown` ## Returns `f is TempFile` --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/hook/functions/lifespan.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [hook](../README.md) / lifespan # Function: lifespan() ```ts function lifespan(setup): PluginSync; ``` Creates a plugin that sets up resources on ready and tears them down on close ## Type Parameters ### S `S` ## Parameters ### setup (`app`) => | `void` | [`LifeSpanCleanupCallback`](../../../type-aliases/LifeSpanCleanupCallback.md)<`S`> | `Promise`< | `void` | [`LifeSpanCleanupCallback`](../../../type-aliases/LifeSpanCleanupCallback.md)<`S`>> ## Returns [`PluginSync`](../../../interfaces/PluginSync.md)<`S`> --- --- url: /api/@minimajs/server/@minimajs/server/functions/maybeContext.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / maybeContext # Function: maybeContext() ```ts function maybeContext(): Context; ``` ## Type Parameters ### S `S` ## Returns [`Context`](../interfaces/Context.md)<`S`> --- --- url: /api/@minimajs/server/@minimajs/server/functions/middleware.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / middleware # Function: middleware() ```ts function middleware(...middlewares): PluginSync; ``` ## Type Parameters ### S `S` = `any` ## Parameters ### middlewares ...[`Middleware`](../type-aliases/Middleware.md)<`S`>\[] ## Returns [`PluginSync`](../interfaces/PluginSync.md)<`S`> --- --- url: /api/@minimajs/server/@minimajs/server/logger/functions/mixin.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/logger](../README.md) / mixin # Function: mixin() ```ts function mixin(data): Dict; ``` Mixin function for Pino logger that enriches log data with module name context. Automatically adds the current module name to log entries if not already present. ## Parameters ### data `Dict`<`unknown`> ## Returns `Dict`<`unknown`> --- --- url: /api/@minimajs/server/@minimajs/server/mock/functions/mockContext.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/mock](../README.md) / mockContext # Function: mockContext() ```ts function mockContext(callback, options): T; ``` Creates a mock context for testing context-based functions. This allows you to test route handlers and context functions in isolation. ## Type Parameters ### S `S` ### T `T` = `void` ## Parameters ### callback [`MockContextCallback`](../type-aliases/MockContextCallback.md)<`T`, `S`> ### options [`MockContextOptions`](../interfaces/MockContextOptions.md)<`S`> = `{}` ## Returns `T` ## Example ```ts import { mockContext } from '@minimajs/server/mock'; import { body, params } from '@minimajs/server'; mockContext(() => { const user = body(); expect(user.name).toBe("John"); }, { body: { name: "John" } }); mockContext(() => { const id = params().id; expect(id).toBe("123"); }, { url: '/users/123', params: { id: '123' } }); ``` ## Since v0.2.0 --- --- url: /api/@minimajs/server/@minimajs/server/plugins/functions/moduleDiscovery.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / moduleDiscovery # Function: moduleDiscovery() ```ts function moduleDiscovery(options): Plugin; ``` Module discovery plugin Uses Node.js's built-in import caching for performance ## Parameters ### options [`ModuleDiscoveryOptions`](../../interfaces/ModuleDiscoveryOptions.md) ## Returns [`Plugin`](../../interfaces/Plugin.md)<`unknown`, { `name?`: `string`; }> --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/abort/functions/notFound.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [abort](../README.md) / notFound # Function: notFound() ```ts function notFound(message?, options?): never; ``` Aborts the request with a 404 Not Found error. ## Parameters ### message? `string` Optional error message ### options? [`HttpErrorOptions`](../../../error/interfaces/HttpErrorOptions.md) Optional error options including custom headers ## Returns `never` ## Throws ## Example ```ts abort.notFound(); abort.notFound('User not found'); abort.notFound('Resource not found', { headers: { 'X-Resource-Type': 'product' } }); ``` --- --- url: /api/@minimajs/server/@minimajs/server/plugins/functions/onError.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / onError # Function: onError() ```ts function onError(cb): void; ``` Registers an error handling callback for the current request context. Called when an error occurs during request processing. ## Parameters ### cb [`ErrorCallback`](../type-aliases/ErrorCallback.md) The callback function to execute when an error occurs ## Returns `void` ## Example ```typescript import { onError } from '@minimajs/server'; app.get('/data', async (req) => { onError((err) => { console.error('Request failed:', err); // Cleanup resources, log to monitoring, etc. }); const data = await fetchData(); return data; }); ``` --- --- url: /api/@minimajs/openapi/functions/openapi.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/openapi](../README.md) / openapi # Function: openapi() ```ts function openapi(__namedParameters): PluginSync; ``` ## Parameters ### \_\_namedParameters [`OpenAPIPluginOptions`](../interfaces/OpenAPIPluginOptions.md) = `{}` ## Returns [`PluginSync`](../../server/@minimajs/server/interfaces/PluginSync.md)<`any`> --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/params/functions/optional.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [params](../README.md) / optional # Function: optional() ## Call Signature ```ts function optional(name): string | undefined; ``` Retrieves a single param by name with optional transformation. Returns undefined if the param is not found. ### Parameters #### name `string` ### Returns `string` | `undefined` ### Example ```ts const id = params.option('id'); // string | undefined const page = params.option('page', (val) => parseInt(val)); // number | undefined ``` ## Call Signature ```ts function optional(name, transform): R | undefined; ``` Retrieves a single param by name with optional transformation. Returns undefined if the param is not found. ### Type Parameters #### R `R` ### Parameters #### name `string` #### transform (`value`) => `R` ### Returns `R` | `undefined` ### Example ```ts const id = params.option('id'); // string | undefined const page = params.option('page', (val) => parseInt(val)); // number | undefined ``` --- --- url: /api/@minimajs/server/@minimajs/server/functions/params.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / params # Function: params() ```ts function params(): T; ``` Retrieves the request params. ## Type Parameters ### T `T` = [`Dict`](../type-aliases/Dict.md)<`string`> ## Returns `T` ## Example ```ts const p = params<{ id: string }>(); console.log(p.id); // Or use params.get const id = params.get('id'); ``` ## Since v0.2.0 --- --- url: /api/@minimajs/server/@minimajs/server/functions/plugin.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / plugin # Function: plugin() ```ts function plugin(fn, name?): Plugin; ``` Wraps a plain function into a Plugin with automatic kPluginSkipOverride This prevents the plugin from being encapsulated and allows direct registration ## Type Parameters ### S `S` ### T `T` *extends* { `name?`: `string`; } = { `name?`: `string`; } ## Parameters ### fn [`PluginCallback`](../type-aliases/PluginCallback.md)<`S`, `T`> ### name? `string` ## Returns [`Plugin`](../interfaces/Plugin.md)<`S`, `T`> --- --- url: /api/@minimajs/server/@minimajs/server/plugins/functions/proxy.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / proxy # Function: proxy() ```ts function proxy(options): PluginSync; ``` Proxy plugin that extracts client information from proxy headers. Useful when your application is behind a reverse proxy or load balancer. By default, the plugin collects IP, host, and proto metadata even when not behind a trusted proxy. Disable individual features by setting them to false. ## Type Parameters ### S `S` ## Parameters ### options [`ProxyOptions`](../interfaces/ProxyOptions.md)<`S`> = `{}` Configuration for extracting IP, protocol, and hostname ## Returns [`PluginSync`](../../interfaces/PluginSync.md)<`S`> A request hook that processes proxy headers ## Example ```ts // Basic usage - auto-enables IP, host, and proto extraction app.register(proxy({ trustProxies: true })); // Disable specific features app.register(proxy({ trustProxies: true, ip: {}, // Custom settings host: false, // Disable host extraction proto: false // Disable proto extraction })); // Trust specific proxy IPs app.register(proxy({ trustProxies: ['127.0.0.1', '10.0.0.1'], ip: { proxyDepth: 2 }, host: { stripPort: true } })); // Multiple header fallback for different cloud providers app.register(proxy({ trustProxies: true, proto: { header: ['x-forwarded-proto', 'cloudfront-forwarded-proto', 'x-arr-ssl'] }, host: { header: ['x-forwarded-host', 'x-original-host'], stripPort: true } })); // Custom trust validator app.register(proxy({ trustProxies: (ctx) => { const ip = ctx.incomingMessage?.socket?.remoteAddress; return ip?.startsWith('10.') || ip === '127.0.0.1'; }, ip: { proxyDepth: 2 } })); // Custom callbacks for complex scenarios app.register(proxy({ trustProxies: true, ip: (ctx) => ctx.request.headers.get('x-real-ip') || null, proto: (ctx) => ctx.request.headers.get('x-forwarded-proto') || 'https', host: (ctx) => ctx.request.headers.get('host') || 'example.com' })); ``` --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/helpers/functions/randomName.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [helpers](../README.md) / randomName # Function: randomName() ```ts function randomName(filename): string; ``` Generates a random UUID-based filename while preserving the original extension. Useful for storing files with unique names to prevent collisions. ## Parameters ### filename `string` ## Returns `string` A UUID filename with the original file extension --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/helpers/functions/raw2file.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [helpers](../README.md) / raw2file # Function: raw2file() ```ts function raw2file(raw, options): Promise; ``` Converts a raw multipart file stream into a Web API File by buffering the entire stream. ## Parameters ### raw [`MultipartRawFile`](../../../interfaces/MultipartRawFile.md) ### options [`Stream2BytesOptions`](../interfaces/Stream2BytesOptions.md) ## Returns `Promise`<`File`> --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/helpers/functions/raw2streamFile.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [helpers](../README.md) / raw2streamFile # Function: raw2streamFile() ```ts function raw2streamFile(raw): StreamFile; ``` Wraps a raw multipart file stream into a StreamFile without buffering. ## Parameters ### raw [`MultipartRawFile`](../../../interfaces/MultipartRawFile.md) ## Returns [`StreamFile`](../../streaming/classes/StreamFile.md) --- --- url: /api/@minimajs/server/@minimajs/server/functions/redirect.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / redirect # Function: redirect() ```ts function redirect( path, isPermanent?, options?): never; ``` Redirects to the specified path. ## Parameters ### path `string` The URL path to redirect to ### isPermanent? `boolean` Whether the redirect is permanent (301) or temporary (302) ### options? [`HttpErrorOptions`](../error/interfaces/HttpErrorOptions.md) Optional error options including custom headers ## Returns `never` ## Throws ## Example ```ts redirect('/login'); redirect('/new-url', true); // permanent redirect redirect('/login', false, { headers: { 'X-Reason': 'session-expired' } }); ``` ## Since v0.2.0 --- --- url: >- /api/@minimajs/server/@minimajs/server/namespaces/request/functions/remoteAddr.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [request](../README.md) / remoteAddr # Function: remoteAddr() ```ts function remoteAddr(): RemoteAddr | null; ``` ## Returns [`RemoteAddr`](../../../interfaces/RemoteAddr.md) | `null` --- --- url: /api/@minimajs/cookie/namespaces/cookies/functions/remove.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/cookie](../../../README.md) / [cookies](../README.md) / remove # Function: remove() ```ts function remove(name, options?): void; ``` Removes a cookie by setting its expiration to the past. The cookie is immediately removed from the incoming cookies for the current request. ## Parameters ### name `string` The cookie name to remove ### options? `SerializeOptions` Cookie options (must match the path/domain of the original cookie) ## Returns `void` ## Example ```typescript // Remove a cookie cookies.remove("sessionId"); // Remove a cookie with specific path/domain cookies.remove("adminToken", { path: "/admin", domain: "example.com", }); ``` ## Remarks To successfully remove a cookie, the `path` and `domain` options must match those used when the cookie was originally set. Browsers will only delete cookies that match all attributes. ## Since 1.0.0 --- --- url: /api/@minimajs/server/@minimajs/server/functions/request.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / request # Function: request() ```ts function request(): Request; ``` Retrieves the HTTP request object. ## Returns `Request` ## Example ```ts const req = request(); console.log(req.url); ``` ## Since v0.2.0 --- --- url: >- /api/@minimajs/server/@minimajs/server/namespaces/runHooks/functions/request.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [runHooks](../README.md) / request # Function: request() ```ts function request(app, ctx): Promise; ``` ## Type Parameters ### S `S` ## Parameters ### app [`App`](../../../interfaces/App.md)<`S`> ### ctx [`Context`](../../../interfaces/Context.md)<`S`> ## Returns `Promise`<`void` | `Response`> --- --- url: /api/@minimajs/server/@minimajs/server/functions/response.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / response # Function: response() ```ts function response(body, options): Response; ``` Creates an HTTP response with serialized body, optional status code, and headers. ## Parameters ### body [`ResponseBody`](../type-aliases/ResponseBody.md) ### options [`ResponseOptions`](../interfaces/ResponseOptions.md) = `{}` ## Returns `Response` ## Example ```ts return response('Hello World'); return response(new Blob(['data'])); return response(stream, { status: 'CREATED', headers: { 'X-Custom': 'value' } }); ``` ## Since v0.2.0 --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/controller/functions/rest.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [controller](../README.md) / rest # Function: rest() ```ts function rest(modules, name): Plugin; ``` ## Parameters ### modules `any` ### name `string` ## Returns [`Plugin`](../../../interfaces/Plugin.md)<`any`, { `name?`: `string`; }> --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/abort/functions/rethrow.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [abort](../README.md) / rethrow # Function: rethrow() ```ts function rethrow(error): asserts error is Error; ``` Ensures an error is not an aborted error. If it is an aborted error, re-throws it. ## Parameters ### error `unknown` The error to check ## Returns `asserts error is Error` ## Example ```ts try { // some code } catch (err) { abort.rethrow(err); // handle non-abort errors } ``` --- --- url: /api/@minimajs/server/@minimajs/server/plugins/functions/routeLogger.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / routeLogger # Function: routeLogger() ```ts function routeLogger(options): PluginSync; ``` Displays a formatted tree of all routes with their HTTP methods and paths. Useful for debugging and understanding the application's route structure during development. ## Parameters ### options [`RouteLoggerOptions`](../interfaces/RouteLoggerOptions.md) = `{}` Configuration options for route logging ## Returns [`PluginSync`](../../interfaces/PluginSync.md)<`unknown`> ## Example ```typescript import { createApp } from "@minimajs/server"; import { routeLogger } from "@minimajs/server/plugins"; const app = createApp(); // With default settings app.register(routeLogger()); // With custom logger app.register(routeLogger({ logger: (routes) => console.log("Routes:\n", routes) })); // With common prefix removed app.register(routeLogger({ commonPrefix: false })); ``` --- --- url: /api/@minimajs/server/@minimajs/server/functions/runHooks.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / runHooks # Function: runHooks() ```ts function runHooks( app, name, ... args): Promise; ``` Runs all hooks for a given lifecycle event with automatic order detection * Parent → Child hooks run in FIFO order (normal) * Child → Parent hooks run in LIFO order (reversed) ## Type Parameters ### S `S` ## Parameters ### app [`App`](../interfaces/App.md)<`S`> ### name [`LifecycleHook`](../type-aliases/LifecycleHook.md) ### args ...`any`\[] ## Returns `Promise`<`void`> --- --- url: /api/@minimajs/server/@minimajs/server/functions/safe.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / safe # Function: safe() ```ts function safe(cb): (...args) => T; ``` ## Type Parameters ### T `T` ### U `U` *extends* `unknown`\[] ## Parameters ### cb (...`args`) => `T` ## Returns ```ts (...args): T; ``` ### Parameters #### args ...`U` ### Returns `T` --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/runHooks/functions/safe.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [runHooks](../README.md) / safe # Function: safe() ```ts function safe( app, name, ... args): Promise; ``` ## Type Parameters ### S `S` ## Parameters ### app [`App`](../../../interfaces/App.md)<`S`> ### name [`LifecycleHook`](../../../type-aliases/LifecycleHook.md) ### args ...`any`\[] ## Returns `Promise`<`void`> --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/helpers/functions/save.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [helpers](../README.md) / save # Function: save() ```ts function save( file, dest, filename?): Promise; ``` Saves a file or raw multipart stream to disk. ## Parameters ### file [`MultipartRawFile`](../../../interfaces/MultipartRawFile.md) | `File` ### dest `string` = `...` ### filename? `string` ## Returns `Promise`<`string`> --- --- url: /api/@minimajs/schema/functions/schema.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/schema](../README.md) / [](../README.md) / schema # Function: schema() ```ts function schema(...schemas): RouteMetaDescriptor; ``` Creates a route metadata descriptor that attaches JSON schemas to routes. Converts Zod schemas to JSON Schema format and separates them into request (body, headers, searchParams, params) and response schemas for OpenAPI documentation. ## Parameters ### schemas ...[`SchemaType`](../type-aliases/SchemaType.md)\[] ## Returns [`RouteMetaDescriptor`](../../server/@minimajs/server/type-aliases/RouteMetaDescriptor.md) ## Example ```typescript import { schema, createBody, createResponse } from "@minimajs/schema"; import { z } from "zod"; const bodySchema = createBody(z.object({ name: z.string() })); const responseSchema = createResponse(z.object({ id: z.string(), name: z.string() })); const errorSchema = createResponse(400, z.object({ error: z.string() })); app.post('/users', schema(bodySchema, responseSchema, errorSchema), () => { const { name } = bodySchema(); return { id: crypto.randomUUID(), name }; } ); ``` --- --- url: /api/@minimajs/server/@minimajs/server/functions/searchParams.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / searchParams # Function: searchParams() ```ts function searchParams(): T; ``` Retrieves the search params (query string). ## Type Parameters ### T `T` *extends* `Record`<`string`, `string`> ## Returns `T` ## Example ```ts const query = searchParams<{ page: string }>(); console.log(query.page); // Or use searchParams.get const page = searchParams.get('page'); ``` ## Since v0.2.0 --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/runHooks/functions/send.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [runHooks](../README.md) / send # Function: send() ```ts function send( app, response, ctx): Promise; ``` ## Type Parameters ### S `S` ## Parameters ### app [`App`](../../../interfaces/App.md)<`S`> ### response `Response` ### ctx [`Context`](../../../interfaces/Context.md)<`S`> ## Returns `Promise`<`void` | `Response`> --- --- url: /api/@minimajs/cookie/namespaces/cookies/functions/set.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/cookie](../../../README.md) / [cookies](../README.md) / set # Function: set() ```ts function set( name, value, options?): void; ``` Sets a cookie to be sent in the response. The cookie value is immediately available for reading within the same request. ## Parameters ### name `string` The cookie name ### value `string` The cookie value ### options? `SerializeOptions` Cookie serialization options (path, domain, maxAge, etc.) ## Returns `void` ## Example ```typescript // Simple cookie cookies.set("theme", "dark"); // Secure session cookie cookies.set("sessionId", "abc123", { httpOnly: true, secure: true, maxAge: 3600, // 1 hour in seconds sameSite: "strict", }); // Cookie with custom path cookies.set("adminToken", "xyz789", { path: "/admin", httpOnly: true, }); ``` ## See [serialize options](https://github.com/jshttp/cookie#options-1|Cookie) ## Since 1.0.0 --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/headers/functions/set.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [headers](../README.md) / set # Function: set() ## Call Signature ```ts function set(name, value): void; ``` Sets a single response header. ### Parameters #### name `string` The header name to set #### value `string` The header value ### Returns `void` ### Example ```ts headers.set('x-custom-header', 'value'); ``` ## Call Signature ```ts function set(headers): void; ``` Sets multiple response headers from a HeadersInit object. ### Parameters #### headers [`HeadersInit`](../../../type-aliases/HeadersInit.md) Headers to set (object, array of tuples, or Headers instance) ### Returns `void` ### Example ```ts // Object headers.set({ 'x-custom': 'value', 'x-another': 'value2' }); // Array of tuples headers.set([['x-custom', 'value'], ['x-another', 'value2']]); // Headers instance headers.set(new Headers({ 'x-custom': 'value' })); ``` ## Call Signature ```ts function set(headers, value): void; ``` Sets a single response header. ### Parameters #### headers `string` #### value `string` The header value ### Returns `void` ### Example ```ts headers.set('x-custom-header', 'value'); ``` --- --- url: /api/@minimajs/server/@minimajs/server/plugins/functions/shutdown.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / shutdown # Function: shutdown() ```ts function shutdown(options): PluginSync; ``` Creates a plugin for graceful server shutdown. Handles specified process signals by gracefully shutting down the server. Calls app.close() which stops the server and runs close hooks. Includes timeout protection to prevent hung shutdowns. ## Parameters ### options [`ShutdownOptions`](../interfaces/ShutdownOptions.md) = `{}` Configuration options for graceful shutdown ## Returns [`PluginSync`](../../interfaces/PluginSync.md)<`unknown`> A plugin that sets up graceful shutdown handlers ## Example ```typescript import { gracefulShutdown } from '@minimajs/server/plugins'; app.register(gracefulShutdown()); ``` --- --- url: >- /api/@minimajs/server/@minimajs/server/plugins/namespaces/bodyParser/functions/skip.md --- [**Minima.js API**](../../../../../../../../README.md) *** [Minima.js API](../../../../../../../../README.md) / [@minimajs/server](../../../../../../README.md) / [@minimajs/server/plugins](../../../README.md) / [bodyParser](../README.md) / skip # Function: skip() ```ts function skip(): RouteMetaDescriptor; ``` ## Returns [`RouteMetaDescriptor`](../../../../type-aliases/RouteMetaDescriptor.md) --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/response/functions/status.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [response](../README.md) / status # Function: status() ```ts function status(statusCode): void; ``` Creates an empty response with the specified status code. ## Parameters ### statusCode [`StatusCode`](../../../type-aliases/StatusCode.md) The HTTP status code (number or StatusCodes key) ## Returns `void` ## Example ```ts return response.status(204); // No Content return response.status('NO_CONTENT'); ``` ## Since v0.2.0 --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/helpers/functions/stream2buffer.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [helpers](../README.md) / stream2buffer # Function: stream2buffer() ```ts function stream2buffer(stream): Promise>; ``` Reads a stream into a Buffer. ## Parameters ### stream `Readable` ## Returns `Promise`<`Buffer`<`ArrayBufferLike`>> --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/helpers/functions/stream2bytes.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [helpers](../README.md) / stream2bytes # Function: stream2bytes() ```ts function stream2bytes(stream, __namedParameters): Promise>; ``` Reads a stream into a Uint8Array with optional size limit. ## Parameters ### stream `Readable` ### \_\_namedParameters [`Stream2BytesOptions`](../interfaces/Stream2BytesOptions.md) = `{}` ## Returns `Promise`<`Uint8Array`<`ArrayBuffer`>> --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/helpers/functions/stream2void.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [helpers](../README.md) / stream2void # Function: stream2void() ```ts function stream2void(): Writable; ``` Creates a writable stream that discards all data. ## Returns `Writable` --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/plugin/functions/sync.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [plugin](../README.md) / sync # Function: sync() ```ts function sync(synced): PluginSync; ``` ## Type Parameters ### S `S` ## Parameters ### synced (`app`) => `void` ## Returns [`PluginSync`](../../../interfaces/PluginSync.md)<`S`> --- --- url: >- /api/@minimajs/server/@minimajs/server/namespaces/runHooks/functions/transform.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [runHooks](../README.md) / transform # Function: transform() ```ts function transform( app, data, ctx): Promise; ``` ## Type Parameters ### S `S` ## Parameters ### app [`App`](../../../interfaces/App.md)<`S`> ### data `unknown` ### ctx [`Context`](../../../interfaces/Context.md)<`S`> ## Returns `Promise`<`unknown`> --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/request/functions/url.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [request](../README.md) / url # Function: url() ```ts function url(): URL; ``` Retrieves the full request URL. ## Returns `URL` ## Example ```ts const url = request.url(); console.log(url.pathname); ``` ## Since v0.2.0 --- --- url: /api/@minimajs/schema/validation/functions/validator.md --- [**Minima.js API**](../../../../README.md) *** [Minima.js API](../../../../README.md) / [@minimajs/schema](../../README.md) / [validation](../README.md) / validator # Function: validator() ```ts function validator( schema, data, type, option): SchemaValidator>; ``` ## Type Parameters ### T `T` *extends* `ZodType`<`unknown`, `unknown`, `$ZodTypeInternals`<`unknown`, `unknown`>> ## Parameters ### schema `T` ### data `DataCallback` ### type [`SchemaDataTypes`](../../type-aliases/SchemaDataTypes.md) ### option [`ValidationOptions`](../interfaces/ValidationOptions.md) ## Returns [`SchemaValidator`](../../type-aliases/SchemaValidator.md)<`output`<`T`>> --- --- url: /api/@minimajs/schema/validation/functions/validatorAsync.md --- [**Minima.js API**](../../../../README.md) *** [Minima.js API](../../../../README.md) / [@minimajs/schema](../../README.md) / [validation](../README.md) / validatorAsync # Function: validatorAsync() ```ts function validatorAsync( schema, data, type, option): SchemaValidator>>; ``` ## Type Parameters ### T `T` *extends* `ZodType`<`unknown`, `unknown`, `$ZodTypeInternals`<`unknown`, `unknown`>> ## Parameters ### schema `T` ### data `DataCallback` ### type [`SchemaDataTypes`](../../type-aliases/SchemaDataTypes.md) ### option [`ValidationOptions`](../interfaces/ValidationOptions.md) ## Returns [`SchemaValidator`](../../type-aliases/SchemaValidator.md)<`Promise`<`output`<`T`>>> --- --- url: /getting-started.md --- # Getting Started with Minima.js This guide introduces the core concepts of Minima.js to get you up and running quickly. We'll start with a minimal application and then explore the key features that make the framework powerful and elegant. > **New to Minima.js?** Check out the [Introduction](/intro) for a conceptual overview before diving into this tutorial. ## Setup First, choose your runtime and create a new project directory. **Option 1: Bun** ```bash mkdir minimajs-app cd minimajs-app bun init -y bun add @minimajs/server ``` Then start your server: ```bash bun --watch src/index.ts # development with auto-reload bun src/index.ts # production ``` **Option 2: Node.js** ```bash mkdir minimajs-app cd minimajs-app npm init -y npm install @minimajs/server npm install -D typescript tsx @types/node ``` Update your `package.json` to enable ES modules and add start scripts: ```json { "type": "module", "scripts": { "start": "tsx src/index.ts", "dev": "tsx watch src/index.ts" } } ``` Create a `tsconfig.json` for TypeScript support: ```json { "compilerOptions": { "target": "ESNext", "module": "ESNext", "moduleResolution": "bundler", "strict": true } } ``` Then start your server: ```bash npm run dev # development with auto-reload npm run start # production ``` ## Choose Your Runtime Minima.js is optimized for both runtimes. You select your target by changing the import path: * `@minimajs/server/bun`: Uses Bun's native, high-performance `Bun.serve()`. * `@minimajs/server/node`: Uses Node.js's standard `http.createServer()`. * `@minimajs/server`: Defaults to the Node.js runtime. This provides native performance with zero abstraction overhead. ## A Minimal Application Create a `src/index.ts` file. Here is a very basic Minima.js application: ::: code-group ```typescript [Bun] import { createApp } from "@minimajs/server/bun"; import { params } from "@minimajs/server"; const app = createApp(); // Simple functional route app.get("/", () => ({ message: "Hello, World!" })); // Demonstrates context-aware access to route parameters app.get("/hello/:name", () => { const name = params.get("name"); return { message: `Hello, ${name}!` }; }); const address = await app.listen({ port: 3000 }); console.log(`Server listening on ${address}`); ``` ```typescript [Node.js] import { createApp } from "@minimajs/server/node"; import { params } from "@minimajs/server"; const app = createApp(); // Simple functional route app.get("/", () => ({ message: "Hello, World!" })); // Demonstrates context-aware access to route parameters app.get("/hello/:name", () => { const name = params.get("name"); return { message: `Hello, ${name}!` }; }); const address = await app.listen({ port: 3000 }); console.log(`Server listening on ${address}`); ``` ::: This short example already showcases several core concepts. Let's build on this foundation. ## Access Request Data Anywhere Notice we imported `params` and used it directly in the route handler without it being passed as an argument: ```typescript import { params } from "@minimajs/server"; app.get("/hello/:name", () => { const name = params.get("name"); // ✅ No req.params.name return { message: `Hello, ${name}!` }; }); ``` **Available context functions:** `request`, `response`, `params`, `body`, `headers`, `searchParams` For more details, see the [Http Helpers Guide](/guides/http). ## Organize with File-Based Modules As your application grows, organize routes by creating `module.ts` files. They're auto-discovered based on folder structure: ``` src/ ├── index.ts # Entry point ├── users/ │ └── module.ts # → /users/* └── posts/ └── module.ts # → /posts/* ``` ::: code-group ```typescript [src/index.ts] import { createApp } from "@minimajs/server"; const app = createApp(); // Auto-discovers modules! await app.listen({ port: 3000 }); ``` ```typescript [src/users/module.ts] import { params } from "@minimajs/server"; import type { Routes } from "@minimajs/server"; function listUsers() { return [{ id: 1, name: "John" }]; } function getUser() { const id = params.get("id"); return { id, name: "John" }; } export const routes: Routes = { "GET /list": listUsers, "GET /:id": getUser, }; ``` ::: **Your API is ready:** * `GET /users/list` * `GET /users/:id` * `GET /posts/list` **Want to add plugins to a module?** Use `meta.plugins`: ```typescript import { type Meta, type Routes, hook } from "@minimajs/server"; export const meta: Meta = { plugins: [hook("request", () => console.log("User route accessed"))], }; function listUsers() { return [ /* users */ ]; } export const routes: Routes = { "GET /list": listUsers, }; ``` Learn more: [Module Tutorial](/core-concepts/modules) ## Add Lifecycle Hooks Use hooks to tap into request/app lifecycle events. Perfect for logging, auth, error handling: ```ts import { createApp } from "@minimajs/server"; import { hook } from "@minimajs/server"; const app = createApp(); // Log every request app.register( hook("request", ({ request, pathname }) => { console.log(`[REQ] ${request.method} ${pathname}`); }) ); ``` **Common hooks:** `request`, `transform`, `send`, `error`, `hook.lifespan` Learn more: [Hooks Guide](/guides/hooks) ## Handle Errors Centrally Use an `error` hook to catch all errors in one place: ```ts import { createApp } from "@minimajs/server"; import { hook, abort } from "@minimajs/server"; const app = createApp(); app.register( hook("error", (error) => { console.error("Error:", error.message); abort("Something went wrong!", { status: 500 }); }) ); ``` Learn more: [Error Handling Guide](/guides/error-handling) ## Next Steps You now have a working Minima.js application! Here's what to explore next: * **[Task Board Tutorial](/tutorials/task-board-api/)** - Build a complete REST API from scratch * **[Module Tutorial](/core-concepts/modules)** - Step-by-step guide to structuring your app * **[JWT Authentication Recipe](/cookbook/jwt-authentication)** - Add auth in 5 minutes * **[Hooks Guide](/guides/hooks)** - Master the lifecycle system * **[Routing Guide](/guides/routing)** - Advanced routing patterns --- --- url: /plugins/shutdown.md --- # Graceful Shutdown The Graceful Shutdown plugin ensures that your server shuts down cleanly and predictably. It listens for process termination signals (`SIGINT` and `SIGTERM`) and, upon receiving one, instructs the Minima.js application to run its shutdown procedure via `app.close()`. This allows your application to finish processing active requests, close database connections, and run any other cleanup logic defined in `close` hooks before the process exits. ## Installation The plugin is included with the `@minimajs/server` package and can be imported from `@minimajs/server/plugins`. ```typescript import { shutdown } from "@minimajs/server/plugins"; ``` ## Usage Register the plugin within your root module's `meta.plugins`. It requires no default configuration. ::: code-group ```typescript [src/module.ts] import { shutdown } from "@minimajs/server/plugins"; import { type Meta } from "@minimajs/server"; // Enable graceful shutdown globally export const meta: Meta = { plugins: [shutdown()], }; ``` ::: With the plugin registered, pressing `Ctrl+C` in your terminal will now trigger the graceful shutdown process instead of immediately terminating the application. ## Configuration You can customize the shutdown behavior in your root module: ### `signals` An array of process signals to listen for. * **Type**: `Signals[]` (e.g., `'SIGINT'`, `'SIGTERM'`) * **Default**: `['SIGINT', 'SIGTERM']` ### `timeout` The maximum time in milliseconds to wait for the graceful shutdown to complete before forcefully terminating the process. This prevents your application from hanging indefinitely during shutdown. * **Type**: `number` * **Default**: `30000` (30 seconds) **Example with custom options:** ::: code-group ```typescript [src/module.ts] import { shutdown } from "@minimajs/server/plugins"; import { type Meta } from "@minimajs/server"; export const meta: Meta = { plugins: [ shutdown({ signals: ["SIGINT"], // Only listen for SIGINT timeout: 10000, // Wait a maximum of 10 seconds }), ], }; ``` ::: --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/headers/README.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server](../../README.md) / headers # headers Utility functions for working with HTTP headers ## Functions | Function | Description | | ------ | ------ | | [append](functions/append.md) | Appends a response header (useful for headers that can have multiple values like Set-Cookie). | | [get](functions/get.md) | Retrieves a single header value by name with optional transformation. Throws ValidationError if the header is not found. | | [getAll](functions/getAll.md) | Retrieves all values for a header name with optional transformation. Returns an empty array if the header is not found. | | [set](functions/set.md) | Sets a single response header. | --- --- url: /api/@minimajs/multipart/@minimajs/multipart/namespaces/helpers/README.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/multipart](../../../../README.md) / [@minimajs/multipart](../../README.md) / helpers # helpers ## Interfaces | Interface | Description | | ------ | ------ | | [Stream2BytesOptions](interfaces/Stream2BytesOptions.md) | Options for stream to Uint8Array conversion. | ## Type Aliases | Type Alias | Description | | ------ | ------ | | [Dict](type-aliases/Dict.md) | Generic dictionary type alias for objects with optional properties. | | [Unit](type-aliases/Unit.md) | File size unit type representing binary prefixes (base 1024). Available units: KiB, MiB, GiB, TiB, PiB, EiB, ZiB, YiB | ## Functions | Function | Description | | ------ | ------ | | [drain](functions/drain.md) | Consumes and discards a raw multipart file stream. | | [ensurePath](functions/ensurePath.md) | Ensures a directory path exists, creating it recursively if needed. | | [humanFileSize](functions/humanFileSize.md) | Converts a byte count into a human-readable file size string with binary units. | | [isFile](functions/isFile.md) | Checks if a value is a Web API File instance. | | [isRawField](functions/isRawField.md) | Checks if a value is a raw multipart file from the parser. | | [isRawFile](functions/isRawFile.md) | Checks if a value is a raw multipart file from the parser. | | [randomName](functions/randomName.md) | Generates a random UUID-based filename while preserving the original extension. Useful for storing files with unique names to prevent collisions. | | [raw2file](functions/raw2file.md) | Converts a raw multipart file stream into a Web API File by buffering the entire stream. | | [raw2streamFile](functions/raw2streamFile.md) | Wraps a raw multipart file stream into a StreamFile without buffering. | | [save](functions/save.md) | Saves a file or raw multipart stream to disk. | | [stream2buffer](functions/stream2buffer.md) | Reads a stream into a Buffer. | | [stream2bytes](functions/stream2bytes.md) | Reads a stream into a Uint8Array with optional size limit. | | [stream2void](functions/stream2void.md) | Creates a writable stream that discards all data. | --- --- url: /packages/multipart/helpers.md --- # Helper Functions The `helpers` module provides utility functions for file handling, type guards, and stream operations. ```typescript import { helpers } from "@minimajs/multipart"; ``` ## File Operations ### `save(file, dest?, filename?)` Saves a file to disk. Works with `File`, `StreamFile`, `TempFile`, or `MultipartRawFile`. **Parameters:** * `file` - The file to save (File, StreamFile, TempFile, or MultipartRawFile) * `dest` - Destination directory (defaults to `process.cwd()`) * `filename` - Custom filename (auto-generates UUID-based name if omitted) **Returns:** `Promise` - The saved filename ```typescript import { multipart, helpers } from "@minimajs/multipart"; const avatar = await multipart.file("avatar"); // Auto-generated UUID filename const savedName = await helpers.save(avatar, "./uploads"); console.log(savedName); // "550e8400-e29b-41d4-a716-446655440000.jpg" // Custom filename await helpers.save(avatar, "./uploads", "profile.jpg"); ``` Works with raw streams too: ```typescript import { raw, helpers } from "@minimajs/multipart"; for await (const file of raw.files()) { await helpers.save(file, "./uploads"); } ``` ### `randomName(filename)` Generates a random UUID-based filename while preserving the original extension. **Parameters:** * `filename` - Original filename to extract extension from **Returns:** `string` - UUID filename with original extension ```typescript helpers.randomName("photo.jpg"); // "550e8400-e29b-41d4-a716-446655440000.jpg" helpers.randomName("document.pdf"); // "a1b2c3d4-e5f6-7890-abcd-ef1234567890.pdf" helpers.randomName("archive.tar.gz"); // "f47ac10b-58cc-4372-a567-0e02b2c3d479.gz" ``` ### `ensurePath(...paths)` Ensures a directory path exists, creating it recursively if needed. **Parameters:** * `...paths` - Path segments to join and create **Returns:** `Promise` - The resolved absolute path ```typescript // Create single directory await helpers.ensurePath("./uploads"); // Create nested directories await helpers.ensurePath("./uploads", "images", "avatars"); // Creates: ./uploads/images/avatars // Use with save const dir = await helpers.ensurePath("./uploads", "documents"); await helpers.save(file, dir); ``` ### `drain(rawFile)` Consumes and discards a raw multipart file stream. Use this to skip unwanted files without memory buildup. **Parameters:** * `rawFile` - The raw file to drain **Returns:** `Promise` ```typescript import { raw, helpers } from "@minimajs/multipart"; for await (const file of raw.files()) { if (file.type.startsWith("image/")) { await helpers.save(file, "./uploads"); } else { // Skip non-image files await helpers.drain(file); } } ``` ## Type Guards ### `isFile(value)` Checks if a value is a Web API `File` instance. Also returns true for `StreamFile` and `TempFile` since they extend `File`. **Parameters:** * `value` - Value to check **Returns:** `value is File` ```typescript import { multipart, helpers } from "@minimajs/multipart"; for await (const [name, value] of multipart.body()) { if (helpers.isFile(value)) { // value is File console.log(value.name, value.size, value.type); await helpers.save(value, "./uploads"); } else { // value is string console.log(name, value); } } ``` ### `isRawFile(value)` Checks if a value is a raw multipart file from the parser (has unbuffered stream). **Parameters:** * `value` - Value to check **Returns:** `value is MultipartRawFile` ```typescript import { raw, helpers } from "@minimajs/multipart"; for await (const item of raw.body()) { if (helpers.isRawFile(item)) { // item is MultipartRawFile console.log(item.fieldname, item.filename, item.mimeType); await helpers.save(item, "./uploads"); } else { // item is MultipartRawField console.log(item.fieldname, item.value); } } ``` ### `isRawField(value)` Checks if a value is a raw multipart text field from the parser. **Parameters:** * `value` - Value to check **Returns:** `value is MultipartRawField` ```typescript import { raw, helpers } from "@minimajs/multipart"; for await (const item of raw.body()) { if (helpers.isRawField(item)) { // item is MultipartRawField console.log(item.fieldname, item.value); } } ``` ## Stream Utilities ### `stream2bytes(stream, options?)` Reads a Node.js Readable stream into a `Uint8Array` with optional size limit. **Parameters:** * `stream` - Node.js Readable stream * `options.fileSize` - Maximum allowed size in bytes (default: Infinity) **Returns:** `Promise` **Throws:** `Error` if stream exceeds `fileSize` limit ```typescript import { Readable } from "node:stream"; import { helpers } from "@minimajs/multipart"; const stream = Readable.from(["Hello", " ", "World"]); const bytes = await helpers.stream2bytes(stream); console.log(new TextDecoder().decode(bytes)); // "Hello World" // With size limit const limited = await helpers.stream2bytes(stream, { fileSize: 1024 * 1024, // 1MB max }); ``` ### `stream2buffer(stream)` Reads a Node.js Readable stream into a Buffer. **Parameters:** * `stream` - Node.js Readable stream **Returns:** `Promise` ```typescript import { Readable } from "node:stream"; import { helpers } from "@minimajs/multipart"; const stream = Readable.from([Buffer.from("Hello")]); const buffer = await helpers.stream2buffer(stream); console.log(buffer.toString()); // "Hello" ``` ### `stream2void()` Creates a Writable stream that discards all data. Useful for consuming streams you don't need. **Returns:** `Writable` ```typescript import { pipeline } from "node:stream/promises"; import { helpers } from "@minimajs/multipart"; // Discard stream contents await pipeline(someStream, helpers.stream2void()); ``` ## Conversion Utilities ### `raw2file(raw, options)` Converts a raw multipart file stream into a Web API `File` by buffering the entire stream into memory. **Parameters:** * `raw` - Raw multipart file * `options.fileSize` - Maximum file size in bytes **Returns:** `Promise` ```typescript import { raw, helpers } from "@minimajs/multipart"; const rawFile = await raw.file("avatar"); const file = await helpers.raw2file(rawFile, { fileSize: 5 * 1024 * 1024 }); console.log(file.name, file.size, file.type); ``` ### `raw2streamFile(raw)` Wraps a raw multipart file stream into a `StreamFile` without buffering. The stream is consumed lazily on first read. **Parameters:** * `raw` - Raw multipart file **Returns:** `StreamFile` ```typescript import { raw, helpers } from "@minimajs/multipart"; const rawFile = await raw.file("video"); const streamFile = helpers.raw2streamFile(rawFile); // Not buffered yet console.log(streamFile.name, streamFile.type); // Buffers on first read const content = await streamFile.text(); ``` --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/hook/README.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server](../../README.md) / hook # hook ## Functions | Function | Description | | ------ | ------ | | [define](functions/define.md) | Creates a plugin that registers multiple hooks at once | | [factory](functions/factory.md) | - | | [lifespan](functions/lifespan.md) | Creates a plugin that sets up resources on ready and tears them down on close | --- --- url: /guides/hooks.md --- # Hooks Hooks in Minima.js allow you to **tap into the application and request lifecycle**, enabling custom behavior at precise points. **In Minima.js, everything is a plugin** - even hooks are plugins. You apply hooks via: * **`meta.plugins`** in module files (recommended) * **`app.register(hook(...))`** for manual registration ::: code-group ```typescript [src/users/module.ts] import { hook } from "@minimajs/server"; export const meta = { plugins: [ hook("request", ({ request }) => { console.log(`${request.method} ${request.url}`); }), hook("error", (error) => { console.error("Error in users module:", error); }), ], }; ``` ::: > **Important:** The `meta.plugins` property **only works in module files** (files named `module.{ts,js}` by default, or whatever you configure with `moduleDiscovery.index`). It will **not** work in random files - only in files that are auto-discovered as modules. For other files or manual registration, use `app.register(hook(...))` instead. ## Quick Reference ### Request Lifecycle Hooks * [`request`](#request) - Intercept requests before route matching (auth, rate limiting) * [`transform`](#transform) - Modify response data before serialization * [`send`](#send) - Post-response logging and cleanup (called just before returning) * [`error`](/guides/error-handling#error-hook-behavior) - Handle and format errors * [`timeout`](#timeout) - Handle request timeouts ### Application Lifecycle Hooks * [`hook.lifespan`](#hooklifespansetupfn) - Manage resources with setup/teardown * [`ready`](#ready) - Execute when app is ready * [`listen`](#listen) - Execute when server starts listening * [`close`](#close) - Execute when app shuts down * [`register`](#register) - Execute when plugins are registered ### Request-Scoped Helpers * [`defer`](#defercallback) - Execute after response is sent * [`onError`](/guides/error-handling#request-scoped-error-handler-onerror) - Request-specific error handling ### Other Topics * [Hook Execution Order](#hook-execution-order) - FIFO and LIFO patterns with scope inheritance * [Best Practices](#best-practices) - Recommendations for using hooks *** ## Application Lifecycle Hooks Application lifecycle hooks are tied to the application's lifespan, ideal for managing resources, initializing services, or performing cleanup tasks. ### `hook.lifespan(setupFn)` `hook.lifespan` provides a clean pattern to manage resources for the entire application. The `setupFn` runs on app startup and returns a cleanup function that executes on app shutdown. This is perfect for managing database connections, message queues, or any resource that needs graceful setup and teardown. **Recommended: Use in root module's `meta.plugins`** ::: code-group ```typescript [src/module.ts] import { hook } from "@minimajs/server"; const db = { async connect() { console.log("DB connected"); }, async disconnect() { console.log("DB disconnected"); }, }; export const meta = { plugins: [ hook.lifespan(async () => { await db.connect(); // Return a cleanup function to run on app close return async () => { await db.disconnect(); }; }), ], }; ``` ```typescript [src/index.ts] import { createApp } from "@minimajs/server/bun"; const app = createApp(); // Auto-discovers module with db lifecycle await app.listen({ port: 3000 }); ``` ::: ::: ### Other Application Lifecycle Hooks #### `ready` The `ready` hook executes when the application has completed initialization and all plugins have been registered. Use it for tasks that need to run before the server starts listening. ::: code-group ```typescript [src/module.ts] import { hook } from "@minimajs/server"; export const meta = { plugins: [ hook("ready", async (app) => { console.log("Application is ready!"); // Pre-warm caches, verify connections, etc. }), ], }; ``` ::: #### `listen` The `listen` hook executes after the server starts listening for connections. It receives the server instance as a parameter. ::: code-group ```typescript [src/module.ts] import { hook } from "@minimajs/server"; export const meta = { plugins: [ hook("listen", (server) => { console.log(`Server listening on ${server.hostname}:${server.port}`); }), ], }; ``` ::: #### `close` The `close` hook executes when the application is shutting down. Use it for cleanup tasks like closing database connections or flushing logs. ::: code-group ```typescript [src/module.ts] import { hook } from "@minimajs/server"; export const meta = { plugins: [ hook("close", async () => { console.log("Server shutting down..."); await db.close(); await cache.flush(); }), ], }; ``` ::: > **Tip:** Use `hook.lifespan` instead of separate `ready` and `close` hooks when you need paired setup/teardown logic for a single resource. #### `register` The `register` hook executes whenever a plugin is registered. It receives the plugin and its options as parameters. This is primarily used for debugging or plugin inspection. ::: code-group ```typescript [src/module.ts] import { hook } from "@minimajs/server"; export const meta = { plugins: [ hook("register", (plugin, opts) => { console.log(`Plugin registered: ${plugin.name || "anonymous"}`, opts); }), ], }; ``` ::: ## Request Lifecycle Hooks Request hooks execute for each incoming request, allowing you to intercept, modify, and extend the request-response cycle. Before calling the handler → forward (Parent → Child). After the handler → backward (Child → Parent). ### Defining Hooks There are two primary ways to define request hooks: * **`hook(name, handler)`**: Registers a single hook handler. * **`hook.define({ ... })`**: Registers multiple hooks in a single, organized object. Here’s how to define multiple hooks at once: ::: code-group ```typescript [src/api/module.ts] import { hook, abort } from "@minimajs/server"; export const meta = { plugins: [ hook.define({ request({ request, pathname }) { console.log("Incoming request:", request.url()); if (pathname === "/maintenance") { // need to maintain headers in responseState return abort("Under maintenance", 503); } }, send(response, { request }) { console.log("Response sent for:", request.url()); }, }), ], }; ``` ::: ### The Request Lifecycle Minima.js provides several built-in hooks that fire at different stages of the request lifecycle. Some hooks can even return a `Response` to short-circuit the cycle. | Hook | When | Use Case | Can Return Response | | ----------- | -------------------------- | -------------------------------------- | ------------------- | | `request` | Before route matching | Authentication, logging, rate limiting | ✅ Yes | | `transform` | After handler returns data | Transform or enrich response payload | ❌ No | | `send` | After response sent | Logging, cleanup, metrics | ❌ No | | `error` | On error | Format/log errors | ✅ Yes | | `timeout` | Request timeout | Handle slow requests | ✅ Yes | > **Error Handling:** For detailed information on `error` hook, see the [Error Handling Guide](/guides/error-handling). For global error handling behavior, use [`app.errorHandler`](/guides/error-handling#custom-error-handler-apperrorhandler). ### Lifecycle Hook Examples #### `request` The `request` hook intercepts a request **before it reaches the route handler**. It's ideal for authentication, logging, rate limiting, or returning an early response to short-circuit the request lifecycle. ::: code-group ```typescript [src/api/module.ts] import { hook, abort } from "@minimajs/server"; export const meta = { plugins: [ // Authentication check hook("request", ({ request }) => { if (!request.headers.get("authorization")) { // Early termination - bypasses route handler abort("Unauthorized", 401); } }), // Request logging hook("request", ({ request, pathname }) => { console.log(`[${request.method}] ${pathname}`, { userAgent: request.headers.get("user-agent"), timestamp: new Date().toISOString(), }); }), // Rate limiting hook("request", ({ request }) => { const ip = request.headers.get("x-forwarded-for") || "unknown"; if (isRateLimited(ip)) { abort("Too Many Requests", 429); } }), ], }; ``` ::: **Flow:** ```mermaid graph LR A[Incoming Request] --> B[Request Hook 1] B -->|Response| Exit1[Early Exit] B -->|void| C[Request Hook 2] C -->|Response| Exit2[Early Exit] C -->|void| D[Request Hook 3] D -->|Response| Exit3[Early Exit] D -->|void| E[Route Match] E --> F[Handler] F --> G[Transform & Send] Exit1 & Exit2 & Exit3 --> H[Send to Client] G --> H style Exit1 fill:#ff6b6b style Exit2 fill:#ff6b6b style Exit3 fill:#ff6b6b style E fill:#51cf66 ``` > **Important:** `request` hooks execute in **Parent → Child (FIFO) order**. Returning a `Response` terminates the chain immediately and skips the route handler. #### `transform` The `transform` hook modifies response data returned by a handler before it is serialized. Transform hooks execute in **Child → Parent (LIFO) order**, meaning the last registered transform runs first. ::: code-group ```typescript [src/users/module.ts] import { hook } from "@minimajs/server"; import type { Routes } from "@minimajs/server"; export const meta = { plugins: [ hook("transform", (data) => { if (Array.isArray(data.users)) { data.users = data.users.map((u) => u.toUpperCase()); } return data; }), ], }; function listUsers() { return { users: ["Alice", "Bob"] }; } export const routes: Routes = { "GET /list": listUsers, // Response: { "users": ["ALICE", "BOB"] } }; ``` ::: > `transform` hooks **cannot** return a `Response` object. They only modify data. > > **Important:** `transform` hooks execute in **Child → Parent (LIFO) order**. This allows child modules to transform data first, with parent transforms applying afterward. > > **Alternative:** For global serialization behavior (e.g., custom JSON formatting, MessagePack), use [`app.serialize`](/guides/http#custom-serializer-appserialize) instead. #### `send` The `send` hook executes **just before returning the final response**, after the response has been sent to the client. It receives the response object and context, making it ideal for logging, metrics, and cleanup tasks. ::: code-group ```typescript [src/api/module.ts] import { hook } from "@minimajs/server"; export const meta = { plugins: [ // Logging response hook("send", (response, { request, pathname }) => { console.log(`[${request.method}] ${pathname}`, { status: response.status, timestamp: new Date().toISOString(), }); }), // Metrics collection hook("send", (response, ctx) => { metrics.recordResponse({ status: response.status, duration: Date.now() - ctx.startTime, }); }), ], }; ``` ::: > **Note:** The `send` hook cannot return a `Response` object or modify the response. It's strictly for post-response tasks like logging and cleanup. **Flow:** ```mermaid graph LR A[Handler] --> B[Transform] --> C[Serialize] C --> D[Send Hook 3] D -->|Response| Exit1[Early Exit] D -->|void| E[Send Hook 2] E -->|Response| Exit2[Early Exit] E -->|void| F[Send Hook 1] F -->|Response| Exit3[Early Exit] F -->|void| G[Create Response] Exit1 & Exit2 & Exit3 & G --> H[Send to Client] style Exit1 fill:#ff6b6b style Exit2 fill:#ff6b6b style Exit3 fill:#ff6b6b style G fill:#51cf66 ``` > **Important:** `send` hooks execute in **Child → Parent (LIFO) order**. ## Request-Scoped Helpers Minima.js also offers helpers for running logic within the scope of a single request. #### `defer(callback)` The `defer` helper registers a callback to be executed **after the response has been sent**, ideal for non-blocking tasks like analytics or logging. ::: code-group ```typescript [src/api/module.ts] import { defer } from "@minimajs/server"; import type { Routes } from "@minimajs/server"; function getHome() { defer(() => { console.log("Response sent, running deferred task..."); }); return { message: "Hello World!" }; } export const routes: Routes = { "GET /": getHome, }; ``` ::: > `defer` callbacks execute after the `send` hook has completed. > **Note:** For request-specific error handling, see [`onError`](/guides/error-handling#request-scoped-error-handler-onerror) in the Error Handling Guide. ## Hook Execution Order Minima.js uses two execution patterns for hooks based on their purpose: **Parent → Child (FIFO)** for setup/preparation hooks and **Child → Parent (LIFO)** for cleanup/response hooks. ### Execution Patterns #### Parent → Child (FIFO - First In, First Out) These hooks execute in **registration order**: parent hooks run first, then child hooks. This pattern is used for: * **Setup hooks**: `register`, `listen`, `ready` * **Incoming request hooks**: `request` ::: code-group ```typescript [src/module.ts] import { hook } from "@minimajs/server"; export const meta = { plugins: [hook("request", () => console.log("Parent: Auth"))], }; ``` ```typescript [src/users/module.ts] import { hook } from "@minimajs/server"; import type { Routes } from "@minimajs/server"; export const meta = { plugins: [hook("request", () => console.log("Child: Logging"))], }; function listUsers() { return "users"; } export const routes: Routes = { "GET /list": listUsers, }; ``` ::: **Execution when calling `/users/list`:** 1. "Parent: Auth" (parent runs first) 2. "Child: Logging" (child runs second) **Why?** Parent middleware like authentication or logging should run **before** module-specific logic. #### Child → Parent (LIFO - Last In, First Out) These hooks execute in **reverse order**: child hooks run first, then parent hooks. This pattern is used for: * **Response hooks**: `transform`, `send` * **Error hooks**: `error` * **Cleanup hooks**: `close`, `timeout` ::: code-group ```typescript [src/module.ts] import { hook } from "@minimajs/server"; export const meta = { plugins: [hook("error", () => ({ error: "Generic error" }))], }; ``` ```typescript [src/users/module.ts] import { hook } from "@minimajs/server"; import type { Routes } from "@minimajs/server"; export const meta = { plugins: [hook("error", () => ({ error: "Module-specific error" }))], }; function listUsers() { throw new Error("Failed"); } export const routes: Routes = { "GET /list": listUsers, }; ``` ::: **Execution on error in `/users/list`:** 1. Child error handler (module-specific) 2. Parent error handler (only if child doesn't handle) **Why?** The most specific handler (child) should try first, with parent as fallback. ### Hook Order Reference Table | Hook | Direction | Order | Scope | Use Case | | ----------- | ------------------ | ----- | --------- | -------------------------------------- | | `register` | Parent → Child | FIFO | Global | Track plugin registration | | `listen` | Parent → Child | FIFO | Global | Server startup notifications | | `ready` | Parent → Child | FIFO | Global | Initialize resources in order | | `close` | **Child → Parent** | LIFO | Global | Cleanup in reverse order | | `request` | Parent → Child | FIFO | Per-scope | Incoming request middleware | | `transform` | **Child → Parent** | LIFO | Per-scope | Transform response data (last first) | | `send` | **Child → Parent** | LIFO | Per-scope | Post-response logging/cleanup | | `error` | **Child → Parent** | LIFO | Per-scope | Error handling (specific → general) | | `timeout` | **Child → Parent** | LIFO | Per-scope | Timeout handling (specific → fallback) | > **Global Scope**: SERVER\_HOOKS (`close`, `listen`, `ready`, `register`) are shared across all modules - there's only one server instance. > > **Per-scope**: LIFECYCLE\_HOOKS are cloned for each child scope to maintain encapsulation. ### Practical Examples #### Setup Flow (Parent → Child) ::: code-group ```typescript [src/module.ts] import { hook } from "@minimajs/server"; // Parent: Initialize database export const meta = { plugins: [ hook("ready", async () => { await db.connect(); console.log("1. Database connected"); }), ], }; ``` ```typescript [src/cache/module.ts] import { hook } from "@minimajs/server"; // Child: Initialize cache (depends on db) export const meta = { plugins: [ hook("ready", async () => { await cache.warmup(); console.log("2. Cache warmed up"); }), ], }; ``` ::: **Output:** 1 → 2 (dependencies initialize in order) #### Cleanup Flow (Child → Parent) ::: code-group ```typescript [src/module.ts] import { hook } from "@minimajs/server"; // Parent: Close database export const meta = { plugins: [ hook("close", async () => { await db.disconnect(); console.log("2. Database closed"); }), ], }; ``` ```typescript [src/cache/module.ts] import { hook } from "@minimajs/server"; // Child: Flush cache first export const meta = { plugins: [ hook("close", async () => { await cache.flush(); console.log("1. Cache flushed"); }), ], }; ``` ::: **Output:** 1 → 2 (cleanup in reverse order of setup) #### Error Handling (Child → Parent) ::: code-group ```typescript [src/module.ts] import { hook, abort } from "@minimajs/server"; // Parent: Generic error handler export const meta = { plugins: [ hook("error", (err) => { if (!abort.is(err)) { console.log("Fallback: Generic error response", err); return abort({ message: "Something went wrong" }, 500); } }), ], }; ``` ```typescript [src/users/module.ts] import { hook } from "@minimajs/server"; // Child: Specific validation error handler export const meta = { plugins: [ hook("error", (err) => { if (err.name === "ValidationError") { console.log("Handled: Validation error"); return { error: "Validation failed", details: err.details }; } // Return undefined to let parent handle it }), ], }; export default async function (app) { app.post("/create", () => { /* ... */ }); } ``` ::: **Behavior:** * ValidationError: Child handles it * Other errors: Falls through to parent ### Scope Inheritance Child modules inherit hooks from their parents, but sibling modules remain isolated. ::: code-group ```typescript [src/module.ts] import { hook } from "@minimajs/server"; // Parent hook - inherited by all children export const meta = { plugins: [hook("request", () => console.log("Parent"))], }; export default async function (app) { app.get("/health", () => "ok"); } ``` ```typescript [src/users/module.ts] import { hook } from "@minimajs/server"; // Child scope 1 export const meta = { plugins: [hook("request", () => console.log("Child 1"))], }; export default async function (app) { app.get("/list", () => "users"); } ``` ```typescript [src/admin/module.ts] import { hook } from "@minimajs/server"; // Child scope 2 export const meta = { plugins: [hook("request", () => console.log("Child 2"))], }; export default async function (app) { app.get("/dashboard", () => "admin"); } ``` ::: **Execution when calling `/users/list`:** ``` Child 1 (child hook - runs first) Parent (inherited from parent - runs second) ``` **Execution when calling `/admin/dashboard`:** ``` Child 2 (child hook - runs first) Parent (inherited from parent - runs second) ``` ```mermaid graph TB Root["Root App
(Parent Hook)"] Root --> Child1["Child Scope 1
(Child 1 Hook)"] Root --> Child2["Child Scope 2
(Child 2 Hook)"] Child1 --> Route1["/users"] Child2 --> Route2["/admin"] Route1 -.->|Executes
request hook| Exec1["1. Parent Hook
2. Child 1 Hook"] Route2 -.->|Executes
request hook| Exec2["1. Parent Hook
2. Child 2 Hook"] style Root fill:#e7f5ff style Child1 fill:#d0ebff style Child2 fill:#d0ebff style Exec1 fill:#fff3bf style Exec2 fill:#fff3bf ``` > A request to `/users/list` will only trigger hooks from **users module**, not from its sibling admin module. *** ## Manual Registration (Alternative) If you're not using module discovery (`moduleDiscovery: false`) or need to register hooks manually in your entry file, you can use `app.register(hook(...))`: ```typescript import { createApp, hook } from "@minimajs/server/bun"; const app = createApp({ moduleDiscovery: false }); // Register hooks manually app.register( hook("request", ({ request }) => { console.log(`${request.method} ${request.url}`); }) ); app.register( hook.lifespan(async () => { await db.connect(); return async () => await db.disconnect(); }) ); // Register a module manually app.register( async (app) => { app.register(hook("error", () => ({ error: "Module error" }))); app.get("/users", () => "users"); }, { prefix: "/api" } ); await app.listen({ port: 3000 }); ``` **When to use manual registration:** * Apps without module discovery * Registering global plugins in entry files * Building reusable plugin libraries * Quick prototypes or single-file apps **Recommended:** Use `meta.plugins` in module files for better organization and automatic discovery. *** ## Best Practices * **Use `meta.plugins`** in module files instead of `app.register()` for better organization * **Use `hook.lifespan`** for managing resources with paired setup and teardown logic (databases, connections, etc.) * **Use `defer`** for non-blocking, post-response tasks like logging or analytics * **Use `onError`** for request-specific error handling that shouldn't be global * **Avoid returning `Response` objects** from hooks unless necessary for short-circuiting (authentication, rate-limiting) * **Use `response()` helper** to create responses that preserve context headers set by plugins * **Register hooks in the appropriate scope** to ensure proper FIFO/LIFO ordering based on hook type * **Use `hook.define`** to organize multiple related hooks together --- --- url: /guides/http.md --- # HTTP Helpers The request and response objects are globally accessible anywhere from request contexts. This guide covers helper functions for interacting with HTTP requests and responses. ## Quick Reference ### Request Helpers * [`request()`](#request) - Get native Request object * [`request.url()`](#requesturl) - Get URL object * [`request.ip()`](#requestip) - Get client IP address * [`headers()`](#headers) - Get request headers * [`searchParams()`](#searchparams) - Get query string parameters * [`params()`](#params) - Get route parameters * [`body()`](#body) - Get request body ### Response Helpers * [`response()`](#response-1) - Get native Response object * [`response.status()`](#responsestatus) - Set status code * [`headers.set()`](#headersset) - Set response headers ### Customization * [`app.serialize`](#custom-serializer-appserialize) - Global serialization * [`transform` hook](#modifying-response-data-transform-hook) - Modify data before serialization * [`send` hook](#modifying-the-final-response-send-hook) - Modify response before sending *** ## Request ### `request()` Retrieves the native Web API `Request` object. ```ts import { request } from "@minimajs/server"; import type { Routes } from "@minimajs/server"; function getURL() { const req = request(); return req.url; } export const routes: Routes = { "GET /": getURL, }; ``` You can use `request()` in nested function calls: ```ts import { request } from "@minimajs/server"; import type { Routes } from "@minimajs/server"; function fetchURL() { return request().url; } function getURL() { return fetchURL(); } export const routes: Routes = { "GET /": getURL, }; ``` ### `request.url()` Returns the parsed URL object from the request. ```ts import { request } from "@minimajs/server"; import type { Routes } from "@minimajs/server"; function getUsers() { const url = request.url(); console.log(url.pathname); // "/users" console.log(url.searchParams.get("page")); // query param return { path: url.pathname }; } export const routes: Routes = { "GET /users": getUsers, }; ``` ### `request.ip()` Returns the client's IP address. Requires the **Proxy** plugin to be registered and configured. **Configuration:** Before using `request.ip()`, register the IP plugin (often via `proxy`): ```ts import { request } from "@minimajs/server"; import { proxy } from "@minimajs/server/plugins"; // Use custom header (e.g., Cloudflare) app.register(proxy({ trustProxies: true, ip: { header: "CF-Connecting-IP" } })); ``` **Example:** ```ts import type { Routes } from "@minimajs/server"; function getIP() { const ip = request.ip(); return { clientIp: ip }; } export const routes: Routes = { "GET /": getIP, }; ``` ## Headers ### `headers()` Returns the request headers. Supports direct access and transformation utilities. ```ts import { headers } from "@minimajs/server"; import type { Routes } from "@minimajs/server"; function getHeaders() { const reqHeaders = headers(); const auth = reqHeaders.get("authorization"); return { auth }; } export const routes: Routes = { "GET /": getHeaders, }; ``` ### `headers.get()` Gets a single header value with optional transformation. ```ts import { headers } from "@minimajs/server"; // Get as string const contentType = headers.get("content-type"); // Transform to number const contentLength = headers.get("content-length", Number); ``` ### `headers.getAll()` Gets all values for a header with optional transformation. ```ts import { headers } from "@minimajs/server"; // Get all values const cookies = headers.getAll("cookie"); // Transform each value const lengths = headers.getAll("x-custom", Number); ``` ## Search Params ### `searchParams()` Returns the URL search parameters (query string). ```ts import { searchParams } from "@minimajs/server"; import type { Routes } from "@minimajs/server"; function search() { const params = searchParams(); const query = params.get("q"); return { query }; } export const routes: Routes = { "GET /search": search, }; ``` ### `searchParams.get()` Gets a single query parameter with optional transformation. ```ts import { searchParams } from "@minimajs/server"; // Get as string const query = searchParams.get("q"); // Transform to number const page = searchParams.get("page", Number); ``` ### `searchParams.getAll()` Gets all values for a query parameter with optional transformation. ```ts import { searchParams } from "@minimajs/server"; // Get all values const tags = searchParams.getAll("tag"); // Transform each value const ids = searchParams.getAll("id", Number); ``` ## Route Params ### `params()` Returns the route parameters. ```ts import { params } from "@minimajs/server"; import type { Routes } from "@minimajs/server"; function getUser() { const routeParams = params(); const userId = routeParams.get("id"); return { userId }; } export const routes: Routes = { "GET /users/:id": getUser, }; ``` ### `params.get()` Gets a route parameter with optional transformation. ```ts import { params } from "@minimajs/server"; import type { Routes } from "@minimajs/server"; function getUser() { // Get as string const userId = params.get("id"); // Transform to number const numericId = params.get("id", Number); return { userId, numericId }; } export const routes: Routes = { "GET /users/:id": getUser, }; ``` ## Request Body ### `body()` Returns the parsed request body. The body parser is **enabled by default** and configured to parse JSON, so you can use `body()` immediately without any setup. ```ts import { body } from "@minimajs/server"; import type { Routes } from "@minimajs/server"; function createUser() { const data = body(); return { created: data }; } // Body parser is already enabled - no registration needed! export const routes: Routes = { "POST /users": createUser, }; ``` To change the configuration or disable the body parser, see the [Body Parser plugin documentation](/plugins/body-parser). *** ## Response ### `response()` Returns the native `Response` object for the current request context. ```ts import { response } from "@minimajs/server"; import type { Routes } from "@minimajs/server"; function getResponse() { const res = response(); console.log(res.status); // 200 return "Hello"; } export const routes: Routes = { "GET /": getResponse, }; ``` ### `response.status()` Sets the HTTP status code for the response. ```ts [module.ts] import { response } from "@minimajs/server"; import type { Routes } from "@minimajs/server"; function throwError() { response.status(500); return { error: "Internal Server Error" }; } function createItem() { response.status(201); return { id: 123 }; } export const routes: Routes = { "GET /error": throwError, "POST /created": createItem, }; ``` ### `headers.set()` Sets response headers. ```ts [module.ts] import { headers } from "@minimajs/server"; import type { Routes } from "@minimajs/server"; function getHome() { headers.set("X-Custom-Header", "value"); headers.set("Content-Type", "application/json"); return { message: "Hello" }; } export const routes: Routes = { "GET /": getHome, }; ``` *** ## Modifying Response ### Custom Serializer: `app.serialize` Define global serialization logic for all responses. ```ts import { createApp } from "@minimajs/server"; const app = createApp(); app.serialize = function serialize(data) { return JSON.stringify({ success: true, data }); }; app.get("/users", () => { return [{ id: 1, name: "Alice" }]; // Response: {"success":true,"data":[{"id":1,"name":"Alice"}]} }); ``` **Use cases:** * Add global response wrappers * Custom encoding formats * Consistent API response structure ### Modifying Response Data: `transform` Hook Use the `transform` hook to modify response data before serialization. ```ts import { hook } from "@minimajs/server"; // Add timestamp to all responses hook("transform", (data) => { return { ...data, timestamp: Date.now() }; }); app.get("/users", () => { return { users: [] }; // Response: {"users":[],"timestamp":1234567890} }); ``` See [Transform Hook](/guides/hooks#transform) for more details. ### Post-Response Tasks: `send` Hook Use the `send` hook to execute tasks after the response is sent, such as logging or cleanup. ```ts import { hook } from "@minimajs/server"; // Log all responses after they're sent hook("send", (response, ctx) => { console.log(`Response sent: ${response.status} for ${ctx.pathname}`); }); app.get("/", () => "Hello"); // Logs: Response sent: 200 for / ``` See [Send Hook](/guides/hooks#send) for more details. *** ## Related Guides * [Hooks](/guides/hooks) - Request lifecycle and hook system * [Error Handling](/guides/error-handling) - Error handling patterns * [Context](/core-concepts/context) - Request context management --- --- url: /api/@minimajs/server/@minimajs/server/interfaces/AddressInfo.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / AddressInfo # Interface: AddressInfo Information about the server's network address and binding. ## Properties ### family ```ts family: "IPv4" | "IPv6" | "unix"; ``` The IP address family *** ### hostname ```ts hostname: string; ``` The hostname the server is bound to *** ### href ```ts href: string; ``` The full address string *** ### port ```ts port: number; ``` The port number the server is listening on *** ### protocol ```ts protocol: "http" | "https"; ``` The protocol being used ## Methods ### toString() ```ts toString(): string; ``` #### Returns `string` --- --- url: /api/@minimajs/server/@minimajs/server/interfaces/App.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / App # Interface: App\ ## Type Parameters ### S `S` = `any` ## Properties ### $parent ```ts readonly $parent: App | null; ``` *** ### $root ```ts readonly $root: App; ``` *** ### container ```ts readonly container: Container; ``` *** ### log ```ts log: Logger; ``` *** ### prefix ```ts readonly prefix: string; ``` *** ### router ```ts readonly router: Instance; ``` *** ### serialize ```ts serialize: Serializer; ``` *** ### server? ```ts optional server: S; ``` ## Methods ### all() #### Call Signature ```ts all(path, handler): this; ``` ##### Parameters ###### path `string` ###### handler [`Handler`](../type-aliases/Handler.md)<`S`> ##### Returns `this` #### Call Signature ```ts all(path, ...args): this; ``` ##### Parameters ###### path `string` ###### args ...\[`...RouteMetaDescriptor[]`, [`Handler`](../type-aliases/Handler.md)<`S`>] ##### Returns `this` *** ### close() ```ts close(): Promise; ``` #### Returns `Promise`<`void`> *** ### delete() #### Call Signature ```ts delete(path, handler): this; ``` ##### Parameters ###### path `string` ###### handler [`Handler`](../type-aliases/Handler.md)<`S`> ##### Returns `this` #### Call Signature ```ts delete(path, ...args): this; ``` ##### Parameters ###### path `string` ###### args ...\[`...RouteMetaDescriptor[]`, [`Handler`](../type-aliases/Handler.md)<`S`>] ##### Returns `this` *** ### get() #### Call Signature ```ts get(path, handler): this; ``` ##### Parameters ###### path `string` ###### handler [`Handler`](../type-aliases/Handler.md)<`S`> ##### Returns `this` #### Call Signature ```ts get(path, ...args): this; ``` ##### Parameters ###### path `string` ###### args ...\[`...RouteMetaDescriptor[]`, [`Handler`](../type-aliases/Handler.md)<`S`>] ##### Returns `this` *** ### handle() ```ts handle(request): Promise; ``` #### Parameters ##### request `Request` #### Returns `Promise`<`Response`> *** ### head() #### Call Signature ```ts head(path, handler): this; ``` ##### Parameters ###### path `string` ###### handler [`Handler`](../type-aliases/Handler.md)<`S`> ##### Returns `this` #### Call Signature ```ts head(path, ...args): this; ``` ##### Parameters ###### path `string` ###### args ...\[`...RouteMetaDescriptor[]`, [`Handler`](../type-aliases/Handler.md)<`S`>] ##### Returns `this` *** ### options() #### Call Signature ```ts options(path, handler): this; ``` ##### Parameters ###### path `string` ###### handler [`Handler`](../type-aliases/Handler.md)<`S`> ##### Returns `this` #### Call Signature ```ts options(path, ...args): this; ``` ##### Parameters ###### path `string` ###### args ...\[`...RouteMetaDescriptor[]`, [`Handler`](../type-aliases/Handler.md)<`S`>] ##### Returns `this` *** ### patch() #### Call Signature ```ts patch(path, handler): this; ``` ##### Parameters ###### path `string` ###### handler [`Handler`](../type-aliases/Handler.md)<`S`> ##### Returns `this` #### Call Signature ```ts patch(path, ...args): this; ``` ##### Parameters ###### path `string` ###### args ...\[`...RouteMetaDescriptor[]`, [`Handler`](../type-aliases/Handler.md)<`S`>] ##### Returns `this` *** ### post() #### Call Signature ```ts post(path, handler): this; ``` ##### Parameters ###### path `string` ###### handler [`Handler`](../type-aliases/Handler.md)<`S`> ##### Returns `this` #### Call Signature ```ts post(path, ...args): this; ``` ##### Parameters ###### path `string` ###### args ...\[`...RouteMetaDescriptor[]`, [`Handler`](../type-aliases/Handler.md)<`S`>] ##### Returns `this` *** ### put() #### Call Signature ```ts put(path, handler): this; ``` ##### Parameters ###### path `string` ###### handler [`Handler`](../type-aliases/Handler.md)<`S`> ##### Returns `this` #### Call Signature ```ts put(path, ...args): this; ``` ##### Parameters ###### path `string` ###### args ...\[`...RouteMetaDescriptor[]`, [`Handler`](../type-aliases/Handler.md)<`S`>] ##### Returns `this` *** ### ready() ```ts ready(): Promise; ``` #### Returns `Promise`<`void`> *** ### register() #### Call Signature ```ts register(plugin, opts?): this; ``` ##### Type Parameters ###### T `T` *extends* { `name?`: `string`; } ##### Parameters ###### plugin [`Plugin`](Plugin.md)<`S`, `T`> ###### opts? `T` ##### Returns `this` #### Call Signature ```ts register(sync): this; ``` ##### Parameters ###### sync [`PluginSync`](PluginSync.md)<`S`> ##### Returns `this` #### Call Signature ```ts register(module, opts?): this; ``` ##### Type Parameters ###### T `T` *extends* { `name?`: `string`; `prefix?`: `string`; } ##### Parameters ###### module [`Module`](Module.md)<`S`, `T`> ###### opts? `T` ##### Returns `this` #### Call Signature ```ts register(plugin, opts?): this; ``` ##### Parameters ###### plugin [`Registerable`](../type-aliases/Registerable.md)<`any`> ###### opts? `any` ##### Returns `this` *** ### route() #### Call Signature ```ts route(options, handler): this; ``` ##### Parameters ###### options [`RouteOptions`](RouteOptions.md) ###### handler [`Handler`](../type-aliases/Handler.md)<`S`> ##### Returns `this` #### Call Signature ```ts route(options, ...args): this; ``` ##### Parameters ###### options [`RouteOptions`](RouteOptions.md) ###### args ...\[`...RouteMetaDescriptor[]`, [`Handler`](../type-aliases/Handler.md)<`S`>] ##### Returns `this` --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/interfaces/ArraySchemaObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / ArraySchemaObject # Interface: ArraySchemaObject ## Extends * [`BaseSchemaObject`](../type-aliases/BaseSchemaObject.md) ## Properties ### $schema? ```ts optional $schema: string; ``` #### Inherited from ```ts BaseSchemaObject.$schema ``` *** ### additionalProperties? ```ts optional additionalProperties: | boolean | ReferenceObject | SchemaObject; ``` #### Inherited from ```ts BaseSchemaObject.additionalProperties ``` *** ### allOf? ```ts optional allOf: ( | ReferenceObject | SchemaObject)[]; ``` #### Inherited from ```ts BaseSchemaObject.allOf ``` *** ### anyOf? ```ts optional anyOf: ( | ReferenceObject | SchemaObject)[]; ``` #### Inherited from ```ts BaseSchemaObject.anyOf ``` *** ### const? ```ts optional const: any; ``` #### Inherited from ```ts BaseSchemaObject.const ``` *** ### contentMediaType? ```ts optional contentMediaType: string; ``` #### Inherited from ```ts BaseSchemaObject.contentMediaType ``` *** ### default? ```ts optional default: any; ``` #### Inherited from ```ts BaseSchemaObject.default ``` *** ### deprecated? ```ts optional deprecated: boolean; ``` #### Inherited from ```ts BaseSchemaObject.deprecated ``` *** ### description? ```ts optional description: string; ``` #### Inherited from ```ts BaseSchemaObject.description ``` *** ### discriminator? ```ts optional discriminator: DiscriminatorObject; ``` #### Inherited from ```ts BaseSchemaObject.discriminator ``` *** ### enum? ```ts optional enum: any[]; ``` #### Inherited from ```ts BaseSchemaObject.enum ``` *** ### example? ```ts optional example: any; ``` #### Inherited from ```ts BaseSchemaObject.example ``` *** ### examples? ```ts optional examples: any[]; ``` #### Inherited from ```ts BaseSchemaObject.examples ``` *** ### exclusiveMaximum? ```ts optional exclusiveMaximum: number | boolean; ``` #### Inherited from ```ts BaseSchemaObject.exclusiveMaximum ``` *** ### exclusiveMinimum? ```ts optional exclusiveMinimum: number | boolean; ``` #### Inherited from ```ts BaseSchemaObject.exclusiveMinimum ``` *** ### externalDocs? ```ts optional externalDocs: ExternalDocumentationObject; ``` #### Inherited from ```ts BaseSchemaObject.externalDocs ``` *** ### format? ```ts optional format: string; ``` #### Inherited from ```ts BaseSchemaObject.format ``` *** ### items ```ts items: | ReferenceObject | SchemaObject; ``` *** ### maximum? ```ts optional maximum: number; ``` #### Inherited from ```ts BaseSchemaObject.maximum ``` *** ### maxItems? ```ts optional maxItems: number; ``` #### Inherited from ```ts BaseSchemaObject.maxItems ``` *** ### maxLength? ```ts optional maxLength: number; ``` #### Inherited from ```ts BaseSchemaObject.maxLength ``` *** ### maxProperties? ```ts optional maxProperties: number; ``` #### Inherited from ```ts BaseSchemaObject.maxProperties ``` *** ### minimum? ```ts optional minimum: number; ``` #### Inherited from ```ts BaseSchemaObject.minimum ``` *** ### minItems? ```ts optional minItems: number; ``` #### Inherited from ```ts BaseSchemaObject.minItems ``` *** ### minLength? ```ts optional minLength: number; ``` #### Inherited from ```ts BaseSchemaObject.minLength ``` *** ### minProperties? ```ts optional minProperties: number; ``` #### Inherited from ```ts BaseSchemaObject.minProperties ``` *** ### multipleOf? ```ts optional multipleOf: number; ``` #### Inherited from ```ts BaseSchemaObject.multipleOf ``` *** ### not? ```ts optional not: | ReferenceObject | SchemaObject; ``` #### Inherited from ```ts BaseSchemaObject.not ``` *** ### oneOf? ```ts optional oneOf: ( | ReferenceObject | SchemaObject)[]; ``` #### Inherited from ```ts BaseSchemaObject.oneOf ``` *** ### pattern? ```ts optional pattern: string; ``` #### Inherited from ```ts BaseSchemaObject.pattern ``` *** ### properties? ```ts optional properties: { [name: string]: | ReferenceObject | SchemaObject; }; ``` #### Index Signature ```ts [name: string]: | ReferenceObject | SchemaObject ``` #### Inherited from ```ts BaseSchemaObject.properties ``` *** ### readOnly? ```ts optional readOnly: boolean; ``` #### Inherited from ```ts BaseSchemaObject.readOnly ``` *** ### required? ```ts optional required: string[]; ``` #### Inherited from ```ts BaseSchemaObject.required ``` *** ### title? ```ts optional title: string; ``` #### Inherited from ```ts BaseSchemaObject.title ``` *** ### type ```ts type: "array"; ``` *** ### uniqueItems? ```ts optional uniqueItems: boolean; ``` #### Inherited from ```ts BaseSchemaObject.uniqueItems ``` *** ### writeOnly? ```ts optional writeOnly: boolean; ``` #### Inherited from ```ts BaseSchemaObject.writeOnly ``` *** ### xml? ```ts optional xml: XMLObject; ``` #### Inherited from ```ts BaseSchemaObject.xml ``` --- --- url: /api/@minimajs/auth/interfaces/AuthOption.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/auth](../README.md) / AuthOption # Interface: AuthOption ## Properties ### required? ```ts optional required: boolean; ``` --- --- url: /api/@minimajs/auth/interfaces/AuthResourceOptional.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/auth](../README.md) / AuthResourceOptional # Interface: AuthResourceOptional()\ ## Type Parameters ### T `T` ```ts AuthResourceOptional(): T | undefined; ``` ## Returns `T` | `undefined` ## Methods ### required() ```ts required(): T; ``` #### Returns `T` --- --- url: /api/@minimajs/auth/interfaces/AuthResourceWithRequired.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/auth](../README.md) / AuthResourceWithRequired # Interface: AuthResourceWithRequired()\ ## Type Parameters ### T `T` ```ts AuthResourceWithRequired(): T; ``` ## Returns `T` ## Methods ### required() ```ts required(): T; ``` #### Returns `T` --- --- url: /api/@minimajs/server/@minimajs/server/plugins/interfaces/BodyParserOptions.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / BodyParserOptions # Interface: BodyParserOptions Options for body parser plugin ## Properties ### clone? ```ts optional clone: boolean; ``` Clone the request before parsing (useful if you need to read the body multiple times) #### Default ```ts false ``` *** ### enabled? ```ts optional enabled: boolean; ``` *** ### type? ```ts optional type: | BodyParserType | BodyParserType[]; ``` Content types to parse (array for multiple types, or single type) * "json": Parse as JSON (application/json) * "text": Parse as text (text/\*) * "form": Parse as form data (application/x-www-form-urlencoded, multipart/form-data) - **DEPRECATED**: Use @minimajs/multipart instead * "arrayBuffer": Parse as ArrayBuffer * "blob": Parse as Blob #### Default ```ts ["json"] ``` --- --- url: /api/@minimajs/server/@minimajs/server/bun/interfaces/BunAppOptions.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/bun](../README.md) / BunAppOptions # Interface: BunAppOptions\ Configuration options for creating a Bun-based Minima.js application. ## Extends * [`CreateBaseSeverOptions`](../../core/interfaces/CreateBaseSeverOptions.md) ## Type Parameters ### T `T` Type for additional server context data ## Properties ### logger? ```ts optional logger: false | Logger; ``` Pino logger instance, or false to disable logging #### Inherited from [`CreateBaseSeverOptions`](../../core/interfaces/CreateBaseSeverOptions.md).[`logger`](../../core/interfaces/CreateBaseSeverOptions.md#logger) *** ### moduleDiscovery? ```ts optional moduleDiscovery: | false | ModuleDiscoveryOptions; ``` #### Inherited from [`CreateBaseSeverOptions`](../../core/interfaces/CreateBaseSeverOptions.md).[`moduleDiscovery`](../../core/interfaces/CreateBaseSeverOptions.md#modulediscovery) *** ### prefix? ```ts optional prefix: string; ``` URL prefix for all routes #### Inherited from [`CreateBaseSeverOptions`](../../core/interfaces/CreateBaseSeverOptions.md).[`prefix`](../../core/interfaces/CreateBaseSeverOptions.md#prefix) *** ### router? ```ts optional router: Config; ``` Router configuration from find-my-way #### Inherited from [`CreateBaseSeverOptions`](../../core/interfaces/CreateBaseSeverOptions.md).[`router`](../../core/interfaces/CreateBaseSeverOptions.md#router) *** ### server? ```ts optional server: BunServeOptions; ``` Bun-specific server configuration options. These options are passed directly to Bun.serve(). --- --- url: /api/@minimajs/server/@minimajs/server/interfaces/Context.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / Context # Interface: Context\ ## Type Parameters ### S `S` = `unknown` ## Properties ### $metadata ```ts readonly $metadata: ContextMetadata; ``` *** ### app ```ts readonly app: App; ``` *** ### container ```ts readonly container: Container; ``` *** ### incomingMessage ```ts readonly incomingMessage: S extends | Server | Server ? IncomingMessage : undefined; ``` *** ### locals ```ts readonly locals: ContextLocals; ``` *** ### pathname ```ts readonly pathname: string; ``` *** ### request ```ts readonly request: Request; ``` *** ### responseState ```ts readonly responseState: ResponseState; ``` *** ### route ```ts readonly route: Route | null; ``` *** ### server ```ts readonly server: S; ``` *** ### serverAdapter ```ts readonly serverAdapter: ServerAdapter; ``` *** ### serverResponse ```ts readonly serverResponse: S extends | Server | Server ? ServerResponse : undefined; ``` --- --- url: /api/@minimajs/server/@minimajs/server/interfaces/ContextLocals.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / ContextLocals # Interface: ContextLocals ## Indexable ```ts [key: symbol]: unknown ``` ## Properties ### \[kIpAddr]? ```ts optional [kIpAddr]: string | null; ``` --- --- url: /api/@minimajs/server/@minimajs/server/interfaces/ContextMetadata.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / ContextMetadata # Interface: ContextMetadata ## Properties ### host? ```ts optional host: string; ``` *** ### pathEnd ```ts pathEnd: number; ``` *** ### pathStart ```ts pathStart: number; ``` *** ### proto? ```ts optional proto: string; ``` *** ### url? ```ts optional url: URL; ``` --- --- url: /api/@minimajs/server/@minimajs/server/plugins/interfaces/CorsOptions.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / CorsOptions # Interface: CorsOptions ## Properties ### allowedHeaders? ```ts optional allowedHeaders: string | string[]; ``` Configures the Access-Control-Allow-Headers header *** ### credentials? ```ts optional credentials: boolean; ``` Configures the Access-Control-Allow-Credentials header *** ### exposedHeaders? ```ts optional exposedHeaders: string | string[]; ``` Configures the Access-Control-Expose-Headers header *** ### maxAge? ```ts optional maxAge: number; ``` Configures the Access-Control-Max-Age header (in seconds) *** ### methods? ```ts optional methods: string | string[]; ``` Configures the Access-Control-Allow-Methods header. Default: 'GET,HEAD,PUT,PATCH,POST,DELETE' *** ### optionsSuccessStatus? ```ts optional optionsSuccessStatus: number; ``` Provides a status code to use for successful OPTIONS requests. Default: 204 *** ### origin? ```ts optional origin: string | string[] | (origin) => boolean | Promise; ``` Configures the Access-Control-Allow-Origin header. Default: '\*' *** ### preflightContinue? ```ts optional preflightContinue: boolean; ``` Pass the CORS preflight response to the next handler. Default: false --- --- url: >- /api/@minimajs/server/@minimajs/server/core/interfaces/CreateBaseSeverOptions.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/core](../README.md) / CreateBaseSeverOptions # Interface: CreateBaseSeverOptions Configuration options for creating a base server instance. ## Extended by * [`BunAppOptions`](../../bun/interfaces/BunAppOptions.md) * [`NodeAppOptions`](../../node/interfaces/NodeAppOptions.md) ## Properties ### logger? ```ts optional logger: false | Logger; ``` Pino logger instance, or false to disable logging *** ### moduleDiscovery? ```ts optional moduleDiscovery: | false | ModuleDiscoveryOptions; ``` *** ### prefix? ```ts optional prefix: string; ``` URL prefix for all routes *** ### router? ```ts optional router: Config; ``` Router configuration from find-my-way --- --- url: /api/@minimajs/server/@minimajs/server/plugins/interfaces/HostSettings.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / HostSettings # Interface: HostSettings ## Properties ### header? ```ts optional header: string | string[]; ``` --- --- url: /api/@minimajs/server/@minimajs/server/error/interfaces/HttpErrorOptions.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/error](../README.md) / HttpErrorOptions # Interface: HttpErrorOptions ## Extends * `ErrorOptions` ## Properties ### base? ```ts optional base: unknown; ``` *** ### cause? ```ts optional cause: unknown; ``` The cause of the error. #### Inherited from ```ts ErrorOptions.cause ``` *** ### code? ```ts optional code: string; ``` *** ### headers? ```ts optional headers: HeadersInit; ``` *** ### message? ```ts optional message: string; ``` *** ### name? ```ts optional name: string; ``` --- --- url: /api/@minimajs/server/@minimajs/server/interfaces/ImportedModule.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / ImportedModule # Interface: ImportedModule ## Properties ### default? ```ts optional default: Module; ``` *** ### dir ```ts dir: string; ``` *** ### meta ```ts meta: Meta; ``` *** ### routes? ```ts optional routes: Routes; ``` --- --- url: /api/@minimajs/server/@minimajs/server/plugins/interfaces/IpSettings.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / IpSettings # Interface: IpSettings ## Properties ### depth? ```ts optional depth: number; ``` *** ### header? ```ts optional header: string | string[]; ``` *** ### strategy? ```ts optional strategy: IpStrategy; ``` --- --- url: /api/@minimajs/server/@minimajs/server/interfaces/ListenOptions.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / ListenOptions # Interface: ListenOptions Options for starting a server listener. ## Properties ### host? ```ts optional host: string; ``` Hostname to bind to (default: "0.0.0.0") *** ### port ```ts port: number; ``` Port number to bind to --- --- url: /api/@minimajs/server/@minimajs/server/interfaces/ListenResult.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / ListenResult # Interface: ListenResult\ Result returned when a server starts listening. Contains the native server instance and address information. ## Type Parameters ### T `T` ## Properties ### address ```ts address: AddressInfo; ``` Network address and binding information *** ### server ```ts server: T; ``` The native server instance (e.g., Bun server, Node server) --- --- url: /api/@minimajs/server/@minimajs/server/interfaces/Meta.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / Meta # Interface: Meta\ ## Type Parameters ### S `S` = `any` ## Properties ### name? ```ts optional name: string; ``` *** ### plugins? ```ts optional plugins: ( | Plugin | PluginSync)[]; ``` *** ### prefix? ```ts optional prefix: string; ``` --- --- url: /api/@minimajs/server/@minimajs/server/mock/interfaces/MockContextOptions.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/mock](../README.md) / MockContextOptions # Interface: MockContextOptions\ Creates a mock Request object for testing. ## Example ```ts // Simple GET request const req = createRequest('/users'); // POST request with JSON body const req = createRequest('/users', { method: 'POST', body: { name: 'John' } }); // With query parameters const req = createRequest('/users', { query: { page: '1', limit: '10' } }); // With custom headers const req = createRequest('/users', { headers: { 'authorization': 'Bearer token' } }); ``` ## Since v0.2.0 ## Extends * [`MockRequestOptions`](MockRequestOptions.md) ## Type Parameters ### S `S` ## Properties ### body? ```ts optional body: unknown; ``` #### Inherited from [`MockRequestOptions`](MockRequestOptions.md).[`body`](MockRequestOptions.md#body) *** ### context? ```ts optional context: Partial, "$metadata">> & { $metadata?: Partial; }; ``` #### Type Declaration ##### $metadata? ```ts optional $metadata: Partial; ``` *** ### headers? ```ts optional headers: Record; ``` #### Inherited from [`MockRequestOptions`](MockRequestOptions.md).[`headers`](MockRequestOptions.md#headers) *** ### method? ```ts optional method: string; ``` #### Inherited from [`MockRequestOptions`](MockRequestOptions.md).[`method`](MockRequestOptions.md#method) *** ### params? ```ts optional params: Record; ``` *** ### query? ```ts optional query: Record; ``` #### Inherited from [`MockRequestOptions`](MockRequestOptions.md).[`query`](MockRequestOptions.md#query) *** ### url? ```ts optional url: string; ``` --- --- url: /api/@minimajs/server/@minimajs/server/mock/interfaces/MockRequestOptions.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/mock](../README.md) / MockRequestOptions # Interface: MockRequestOptions Creates a mock Request object for testing. ## Example ```ts // Simple GET request const req = createRequest('/users'); // POST request with JSON body const req = createRequest('/users', { method: 'POST', body: { name: 'John' } }); // With query parameters const req = createRequest('/users', { query: { page: '1', limit: '10' } }); // With custom headers const req = createRequest('/users', { headers: { 'authorization': 'Bearer token' } }); ``` ## Since v0.2.0 ## Extended by * [`MockContextOptions`](MockContextOptions.md) ## Properties ### body? ```ts optional body: unknown; ``` *** ### headers? ```ts optional headers: Record; ``` *** ### method? ```ts optional method: string; ``` *** ### query? ```ts optional query: Record; ``` --- --- url: /api/@minimajs/server/@minimajs/server/interfaces/Module.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / Module # Interface: Module()\ ## Type Parameters ### S `S` = `unknown` ### T `T` *extends* [`RegisterOptions`](../type-aliases/RegisterOptions.md) = [`RegisterOptions`](../type-aliases/RegisterOptions.md) ```ts Module(app, opts): void | Promise; ``` ## Parameters ### app [`App`](App.md)<`S`> ### opts `T` ## Returns `void` | `Promise`<`void`> ## Properties ### \[kModuleName]? ```ts optional [kModuleName]: string; ``` --- --- url: /api/@minimajs/server/@minimajs/server/interfaces/ModuleDiscoveryOptions.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / ModuleDiscoveryOptions # Interface: ModuleDiscoveryOptions ## Properties ### index? ```ts optional index: string; ``` *** ### root? ```ts optional root: string; ``` *** ### scanner? ```ts optional scanner: ModuleScanner; ``` --- --- url: /api/@minimajs/multipart/@minimajs/multipart/interfaces/MultipartRawField.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [@minimajs/multipart](../README.md) / MultipartRawField # Interface: MultipartRawField ## Properties ### \[RAW\_FIELD] ```ts [RAW_FIELD]: true; ``` *** ### fieldname ```ts fieldname: string; ``` *** ### fieldnameTruncated ```ts fieldnameTruncated: boolean; ``` *** ### mimeType ```ts mimeType: string; ``` *** ### transferEncoding ```ts transferEncoding: string; ``` *** ### value ```ts value: string; ``` *** ### valueTruncated ```ts valueTruncated: boolean; ``` --- --- url: /api/@minimajs/multipart/@minimajs/multipart/interfaces/MultipartRawFile.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [@minimajs/multipart](../README.md) / MultipartRawFile # Interface: MultipartRawFile ## Properties ### \[RAW\_FILE] ```ts [RAW_FILE]: true; ``` *** ### fieldname ```ts fieldname: string; ``` *** ### filename ```ts filename: string; ``` *** ### mimeType ```ts mimeType: string; ``` *** ### stream ```ts stream: BusboyFileStream; ``` *** ### transferEncoding ```ts transferEncoding: string; ``` --- --- url: /api/@minimajs/server/@minimajs/server/node/interfaces/NodeAppOptions.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/node](../README.md) / NodeAppOptions # Interface: NodeAppOptions Configuration options for creating a Node.js-based Minima.js application. Extends the base server options with Node.js-specific server configuration. ## Extends * [`CreateBaseSeverOptions`](../../core/interfaces/CreateBaseSeverOptions.md) ## Properties ### logger? ```ts optional logger: false | Logger; ``` Pino logger instance, or false to disable logging #### Inherited from [`CreateBaseSeverOptions`](../../core/interfaces/CreateBaseSeverOptions.md).[`logger`](../../core/interfaces/CreateBaseSeverOptions.md#logger) *** ### moduleDiscovery? ```ts optional moduleDiscovery: | false | ModuleDiscoveryOptions; ``` #### Inherited from [`CreateBaseSeverOptions`](../../core/interfaces/CreateBaseSeverOptions.md).[`moduleDiscovery`](../../core/interfaces/CreateBaseSeverOptions.md#modulediscovery) *** ### prefix? ```ts optional prefix: string; ``` URL prefix for all routes #### Inherited from [`CreateBaseSeverOptions`](../../core/interfaces/CreateBaseSeverOptions.md).[`prefix`](../../core/interfaces/CreateBaseSeverOptions.md#prefix) *** ### router? ```ts optional router: Config; ``` Router configuration from find-my-way #### Inherited from [`CreateBaseSeverOptions`](../../core/interfaces/CreateBaseSeverOptions.md).[`router`](../../core/interfaces/CreateBaseSeverOptions.md#router) *** ### server? ```ts optional server: NodeServerOptions; ``` Node.js-specific server options including HTTP/HTTPS configuration --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/interfaces/NonArraySchemaObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / NonArraySchemaObject # Interface: NonArraySchemaObject ## Extends * [`BaseSchemaObject`](../type-aliases/BaseSchemaObject.md) ## Properties ### $schema? ```ts optional $schema: string; ``` #### Inherited from ```ts BaseSchemaObject.$schema ``` *** ### additionalProperties? ```ts optional additionalProperties: | boolean | ReferenceObject | SchemaObject; ``` #### Inherited from ```ts BaseSchemaObject.additionalProperties ``` *** ### allOf? ```ts optional allOf: ( | ReferenceObject | SchemaObject)[]; ``` #### Inherited from ```ts BaseSchemaObject.allOf ``` *** ### anyOf? ```ts optional anyOf: ( | ReferenceObject | SchemaObject)[]; ``` #### Inherited from ```ts BaseSchemaObject.anyOf ``` *** ### const? ```ts optional const: any; ``` #### Inherited from ```ts BaseSchemaObject.const ``` *** ### contentMediaType? ```ts optional contentMediaType: string; ``` #### Inherited from ```ts BaseSchemaObject.contentMediaType ``` *** ### default? ```ts optional default: any; ``` #### Inherited from ```ts BaseSchemaObject.default ``` *** ### deprecated? ```ts optional deprecated: boolean; ``` #### Inherited from ```ts BaseSchemaObject.deprecated ``` *** ### description? ```ts optional description: string; ``` #### Inherited from ```ts BaseSchemaObject.description ``` *** ### discriminator? ```ts optional discriminator: DiscriminatorObject; ``` #### Inherited from ```ts BaseSchemaObject.discriminator ``` *** ### enum? ```ts optional enum: any[]; ``` #### Inherited from ```ts BaseSchemaObject.enum ``` *** ### example? ```ts optional example: any; ``` #### Inherited from ```ts BaseSchemaObject.example ``` *** ### examples? ```ts optional examples: any[]; ``` #### Inherited from ```ts BaseSchemaObject.examples ``` *** ### exclusiveMaximum? ```ts optional exclusiveMaximum: number | boolean; ``` #### Inherited from ```ts BaseSchemaObject.exclusiveMaximum ``` *** ### exclusiveMinimum? ```ts optional exclusiveMinimum: number | boolean; ``` #### Inherited from ```ts BaseSchemaObject.exclusiveMinimum ``` *** ### externalDocs? ```ts optional externalDocs: ExternalDocumentationObject; ``` #### Inherited from ```ts BaseSchemaObject.externalDocs ``` *** ### format? ```ts optional format: string; ``` #### Inherited from ```ts BaseSchemaObject.format ``` *** ### maximum? ```ts optional maximum: number; ``` #### Inherited from ```ts BaseSchemaObject.maximum ``` *** ### maxItems? ```ts optional maxItems: number; ``` #### Inherited from ```ts BaseSchemaObject.maxItems ``` *** ### maxLength? ```ts optional maxLength: number; ``` #### Inherited from ```ts BaseSchemaObject.maxLength ``` *** ### maxProperties? ```ts optional maxProperties: number; ``` #### Inherited from ```ts BaseSchemaObject.maxProperties ``` *** ### minimum? ```ts optional minimum: number; ``` #### Inherited from ```ts BaseSchemaObject.minimum ``` *** ### minItems? ```ts optional minItems: number; ``` #### Inherited from ```ts BaseSchemaObject.minItems ``` *** ### minLength? ```ts optional minLength: number; ``` #### Inherited from ```ts BaseSchemaObject.minLength ``` *** ### minProperties? ```ts optional minProperties: number; ``` #### Inherited from ```ts BaseSchemaObject.minProperties ``` *** ### multipleOf? ```ts optional multipleOf: number; ``` #### Inherited from ```ts BaseSchemaObject.multipleOf ``` *** ### not? ```ts optional not: | ReferenceObject | SchemaObject; ``` #### Inherited from ```ts BaseSchemaObject.not ``` *** ### oneOf? ```ts optional oneOf: ( | ReferenceObject | SchemaObject)[]; ``` #### Inherited from ```ts BaseSchemaObject.oneOf ``` *** ### pattern? ```ts optional pattern: string; ``` #### Inherited from ```ts BaseSchemaObject.pattern ``` *** ### properties? ```ts optional properties: { [name: string]: | ReferenceObject | SchemaObject; }; ``` #### Index Signature ```ts [name: string]: | ReferenceObject | SchemaObject ``` #### Inherited from ```ts BaseSchemaObject.properties ``` *** ### readOnly? ```ts optional readOnly: boolean; ``` #### Inherited from ```ts BaseSchemaObject.readOnly ``` *** ### required? ```ts optional required: string[]; ``` #### Inherited from ```ts BaseSchemaObject.required ``` *** ### title? ```ts optional title: string; ``` #### Inherited from ```ts BaseSchemaObject.title ``` *** ### type? ```ts optional type: NonArraySchemaObjectType; ``` *** ### uniqueItems? ```ts optional uniqueItems: boolean; ``` #### Inherited from ```ts BaseSchemaObject.uniqueItems ``` *** ### writeOnly? ```ts optional writeOnly: boolean; ``` #### Inherited from ```ts BaseSchemaObject.writeOnly ``` *** ### xml? ```ts optional xml: XMLObject; ``` #### Inherited from ```ts BaseSchemaObject.xml ``` --- --- url: /api/@minimajs/openapi/interfaces/OpenAPIPluginOptions.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/openapi](../README.md) / OpenAPIPluginOptions # Interface: OpenAPIPluginOptions ## Extends * `Omit`<[`Document`](../namespaces/OpenAPI/type-aliases/Document.md), `"info"` | `"openapi"`> ## Properties ### components? ```ts optional components: ComponentsObject; ``` #### Inherited from ```ts Omit.components ``` *** ### externalDocs? ```ts optional externalDocs: ExternalDocumentationObject; ``` #### Inherited from ```ts Omit.externalDocs ``` *** ### info? ```ts optional info: InfoObject; ``` *** ### jsonSchemaDialect? ```ts optional jsonSchemaDialect: string; ``` #### Inherited from ```ts Omit.jsonSchemaDialect ``` *** ### path? ```ts optional path: string; ``` *** ### paths? ```ts optional paths: PathsObject<{ }, { }>; ``` #### Inherited from ```ts Omit.paths ``` *** ### security? ```ts optional security: SecurityRequirementObject[]; ``` #### Inherited from ```ts Omit.security ``` *** ### servers? ```ts optional servers: ServerObject[]; ``` #### Inherited from ```ts Omit.servers ``` *** ### tags? ```ts optional tags: TagObject[]; ``` #### Inherited from ```ts Omit.tags ``` *** ### webhooks? ```ts optional webhooks: Record>; ``` #### Inherited from ```ts Omit.webhooks ``` *** ### x-express-openapi-additional-middleware? ```ts optional x-express-openapi-additional-middleware: ( | (request, response, next) => Promise | (request, response, next) => void)[]; ``` #### Inherited from ```ts Omit.x-express-openapi-additional-middleware ``` *** ### x-express-openapi-validation-strict? ```ts optional x-express-openapi-validation-strict: boolean; ``` #### Inherited from ```ts Omit.x-express-openapi-validation-strict ``` --- --- url: /api/@minimajs/server/@minimajs/server/interfaces/Plugin.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / Plugin # Interface: Plugin()\ ## Type Parameters ### S `S` = `unknown` ### T `T` *extends* [`PluginOptions`](../type-aliases/PluginOptions.md) = [`PluginOptions`](../type-aliases/PluginOptions.md) ```ts Plugin(app, opts): void | Promise; ``` ## Parameters ### app [`App`](App.md)<`S`> ### opts `T` ## Returns `void` | `Promise`<`void`> ## Properties ### \[kModuleName]? ```ts optional [kModuleName]: string; ``` *** ### \[kPlugin] ```ts [kPlugin]: true; ``` --- --- url: /api/@minimajs/server/@minimajs/server/interfaces/PluginSync.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / PluginSync # Interface: PluginSync()\ ## Type Parameters ### S `S` = `unknown` ```ts PluginSync(app): void; ``` ## Parameters ### app [`App`](App.md)<`S`> ## Returns `void` ## Properties ### \[kPluginSync] ```ts [kPluginSync]: true; ``` --- --- url: /api/@minimajs/server/@minimajs/server/plugins/interfaces/ProtoSettings.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / ProtoSettings # Interface: ProtoSettings ## Properties ### header? ```ts optional header: string | string[]; ``` --- --- url: >- /api/@minimajs/server/@minimajs/server/plugins/interfaces/ProxyIpPluginOptions.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / ProxyIpPluginOptions # Interface: ProxyIpPluginOptions\ ## Type Parameters ### S `S` ## Properties ### ip? ```ts optional ip: | false | IpSettings | IpExtractor; ``` *** ### trustProxies? ```ts optional trustProxies: | string[] | TrustProxyConfig | (ctx) => boolean; ``` --- --- url: /api/@minimajs/server/@minimajs/server/plugins/interfaces/ProxyOptions.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / ProxyOptions # Interface: ProxyOptions\ ## Type Parameters ### S `S` ## Properties ### host? ```ts optional host: | false | HostSettings | HostExtractor; ``` *** ### ip? ```ts optional ip: | false | IpSettings | IpExtractor; ``` *** ### proto? ```ts optional proto: | false | ProtoSettings | ProtoExtractor; ``` *** ### trustProxies? ```ts optional trustProxies: | string[] | TrustProxyConfig | (ctx) => boolean; ``` --- --- url: /api/@minimajs/server/@minimajs/server/interfaces/RemoteAddr.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / RemoteAddr # Interface: RemoteAddr ## Properties ### family ```ts family: "IPv4" | "IPv6"; ``` *** ### hostname ```ts hostname: string; ``` *** ### port ```ts port: number; ``` --- --- url: /api/@minimajs/server/@minimajs/server/interfaces/ResponseOptions.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / ResponseOptions # Interface: ResponseOptions ## Properties ### headers? ```ts optional headers: HeadersInit; ``` *** ### status? ```ts optional status: | number | "CONTINUE" | "SWITCHING_PROTOCOLS" | "PROCESSING" | "EARLY_HINTS" | "OK" | "CREATED" | "ACCEPTED" | "NON_AUTHORITATIVE_INFORMATION" | "NO_CONTENT" | "RESET_CONTENT" | "PARTIAL_CONTENT" | "MULTI_STATUS" | "MULTIPLE_CHOICES" | "MOVED_PERMANENTLY" | "MOVED_TEMPORARILY" | "SEE_OTHER" | "NOT_MODIFIED" | "USE_PROXY" | "TEMPORARY_REDIRECT" | "PERMANENT_REDIRECT" | "BAD_REQUEST" | "UNAUTHORIZED" | "PAYMENT_REQUIRED" | "FORBIDDEN" | "NOT_FOUND" | "METHOD_NOT_ALLOWED" | "NOT_ACCEPTABLE" | "PROXY_AUTHENTICATION_REQUIRED" | "REQUEST_TIMEOUT" | "CONFLICT" | "GONE" | "LENGTH_REQUIRED" | "PRECONDITION_FAILED" | "REQUEST_TOO_LONG" | "REQUEST_URI_TOO_LONG" | "UNSUPPORTED_MEDIA_TYPE" | "REQUESTED_RANGE_NOT_SATISFIABLE" | "EXPECTATION_FAILED" | "IM_A_TEAPOT" | "INSUFFICIENT_SPACE_ON_RESOURCE" | "METHOD_FAILURE" | "MISDIRECTED_REQUEST" | "UNPROCESSABLE_ENTITY" | "LOCKED" | "FAILED_DEPENDENCY" | "UPGRADE_REQUIRED" | "PRECONDITION_REQUIRED" | "TOO_MANY_REQUESTS" | "REQUEST_HEADER_FIELDS_TOO_LARGE" | "UNAVAILABLE_FOR_LEGAL_REASONS" | "INTERNAL_SERVER_ERROR" | "NOT_IMPLEMENTED" | "BAD_GATEWAY" | "SERVICE_UNAVAILABLE" | "GATEWAY_TIMEOUT" | "HTTP_VERSION_NOT_SUPPORTED" | "INSUFFICIENT_STORAGE" | "NETWORK_AUTHENTICATION_REQUIRED"; ``` *** ### statusText? ```ts optional statusText: string; ``` --- --- url: /api/@minimajs/server/@minimajs/server/interfaces/ResponseState.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / ResponseState # Interface: ResponseState ## Properties ### headers ```ts headers: Headers; ``` *** ### status? ```ts optional status: number; ``` *** ### statusText? ```ts optional statusText: string; ``` --- --- url: >- /api/@minimajs/server/@minimajs/server/namespaces/controller/interfaces/RestHttpMapping.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server](../../../README.md) / [controller](../README.md) / RestHttpMapping # Interface: RestHttpMapping ## Properties ### method ```ts method: HTTPMethod; ``` *** ### name ```ts name: string; ``` *** ### path ```ts path: string; ``` --- --- url: /api/@minimajs/server/@minimajs/server/interfaces/Route.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / Route # Interface: Route\ ## Type Parameters ### S `S` ## Properties ### handler ```ts handler: Handler; ``` *** ### metadata ```ts metadata: RouteMetadata; ``` *** ### methods ```ts methods: HTTPMethod[]; ``` *** ### params ```ts params: | { [key: string]: string | undefined; } | undefined; ``` *** ### path ```ts path: string; ``` --- --- url: /api/@minimajs/server/@minimajs/server/interfaces/RouteConfig.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / RouteConfig # Interface: RouteConfig\ ## Extends * `Omit`<[`Route`](Route.md)<`S`>, `"params"`> ## Type Parameters ### S `S` ## Properties ### app ```ts app: App; ``` *** ### handler ```ts handler: Handler; ``` #### Inherited from ```ts Omit.handler ``` *** ### metadata ```ts metadata: RouteMetadata; ``` #### Inherited from ```ts Omit.metadata ``` *** ### methods ```ts methods: HTTPMethod[]; ``` #### Inherited from ```ts Omit.methods ``` *** ### path ```ts path: string; ``` #### Inherited from ```ts Omit.path ``` --- --- url: /api/@minimajs/server/@minimajs/server/interfaces/RouteFindResult.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / RouteFindResult # Interface: RouteFindResult\ ## Extends * `FindResult`<`any`> ## Type Parameters ### T `T` ## Properties ### handler ```ts handler: Handler; ``` #### Inherited from ```ts FindResult.handler ``` *** ### params ```ts params: { [k: string]: string | undefined; }; ``` #### Index Signature ```ts [k: string]: string | undefined ``` #### Inherited from ```ts FindResult.params ``` *** ### searchParams ```ts searchParams: { [k: string]: string; }; ``` #### Index Signature ```ts [k: string]: string ``` #### Inherited from ```ts FindResult.searchParams ``` *** ### store ```ts store: RouteConfig; ``` #### Overrides ```ts FindResult.store ``` --- --- url: >- /api/@minimajs/server/@minimajs/server/plugins/interfaces/RouteLoggerOptions.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / RouteLoggerOptions # Interface: RouteLoggerOptions ## Properties ### commonPrefix? ```ts optional commonPrefix: boolean; ``` Whether to print routes with common prefix removed for cleaner output. Defaults to false *** ### delay? ```ts optional delay: number; ``` *** ### enabled? ```ts optional enabled: boolean; ``` *** ### logger()? ```ts optional logger: (message) => void; ``` Custom logger function to output routes. Defaults to console.log with magenta color #### Parameters ##### message `string` #### Returns `void` --- --- url: /api/@minimajs/server/@minimajs/server/interfaces/RouteOptions.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / RouteOptions # Interface: RouteOptions ## Properties ### method ```ts method: HTTPMethod | HTTPMethod[]; ``` *** ### path ```ts path: string; ``` --- --- url: /api/@minimajs/server/@minimajs/server/interfaces/ServerAdapter.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / ServerAdapter # Interface: ServerAdapter\ Adapter interface for different server implementations. Abstracts the underlying server runtime (Bun, Node, Deno, etc). ## Example ```typescript // Bun server adapter const bunAdapter: ServerAdapter = { async listen(opts, handler) { const server = Bun.serve({ port: opts.port, hostname: opts.host, fetch: handler }); return { server, address: {...} }; }, async close(server) { server.stop(); } }; ``` ## Type Parameters ### T `T` The native server type (e.g., BunServer, http.Server) ## Methods ### close() ```ts close(server): Promise; ``` Stops the server and closes all connections. #### Parameters ##### server `T` The native server instance to close #### Returns `Promise`<`void`> Promise that resolves when server is closed *** ### listen() ```ts listen( server, opts, requestHandler): Promise>; ``` Starts the server and begins listening for requests. #### Parameters ##### server [`Server`](../classes/Server.md)<`T`> ##### opts [`ListenOptions`](ListenOptions.md) Listening options (port, host) ##### requestHandler [`RequestHandler`](../type-aliases/RequestHandler.md)<`T`> Function to handle incoming requests #### Returns `Promise`<[`ListenResult`](ListenResult.md)<`T`>> Promise resolving to server instance and address info *** ### remoteAddr() ```ts remoteAddr(ctx): RemoteAddr | null; ``` #### Parameters ##### ctx [`Context`](Context.md)<`T`> #### Returns [`RemoteAddr`](RemoteAddr.md) | `null` --- --- url: /api/@minimajs/server/@minimajs/server/interfaces/ServerOptions.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / ServerOptions # Interface: ServerOptions ## Properties ### logger ```ts logger: Logger; ``` *** ### prefix ```ts prefix: string; ``` *** ### router ```ts router: Instance; ``` --- --- url: /api/@minimajs/server/@minimajs/server/plugins/interfaces/ShutdownOptions.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / ShutdownOptions # Interface: ShutdownOptions ## Properties ### signals? ```ts optional signals: Signals[]; ``` Array of signals to listen for (e.g., \['SIGINT', 'SIGTERM']) *** ### timeout? ```ts optional timeout: number; ``` Timeout in milliseconds before forcing process exit. Defaults to 30000ms (30 seconds) --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/helpers/interfaces/Stream2BytesOptions.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [helpers](../README.md) / Stream2BytesOptions # Interface: Stream2BytesOptions Options for stream to Uint8Array conversion. ## Properties ### fileSize? ```ts optional fileSize: number; ``` Maximum allowed file size in bytes. --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/streaming/interfaces/StreamFileInit.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [streaming](../README.md) / StreamFileInit # Interface: StreamFileInit ## Extends * `FilePropertyBag` ## Properties ### endings? ```ts optional endings: "native" | "transparent"; ``` #### Inherited from ```ts FilePropertyBag.endings ``` *** ### lastModified? ```ts optional lastModified: number; ``` #### Overrides ```ts FilePropertyBag.lastModified ``` *** ### stream ```ts stream: Readable; ``` *** ### type ```ts type: string; ``` #### Overrides ```ts FilePropertyBag.type ``` --- --- url: /api/@minimajs/multipart/@minimajs/multipart/schema/interfaces/TempFileInit.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/multipart](../../../../README.md) / [@minimajs/multipart/schema](../README.md) / TempFileInit # Interface: TempFileInit ## Extends * `FilePropertyBag` ## Properties ### endings? ```ts optional endings: "native" | "transparent"; ``` #### Inherited from ```ts FilePropertyBag.endings ``` *** ### lastModified? ```ts optional lastModified: number; ``` #### Overrides ```ts FilePropertyBag.lastModified ``` *** ### path ```ts path: string; ``` *** ### signal? ```ts optional signal: AbortSignal; ``` *** ### size ```ts size: number; ``` *** ### type? ```ts optional type: string; ``` #### Overrides ```ts FilePropertyBag.type ``` --- --- url: /api/@minimajs/server/@minimajs/server/plugins/interfaces/TrustProxyConfig.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / TrustProxyConfig # Interface: TrustProxyConfig\ ## Type Parameters ### S `S` ## Properties ### proxies? ```ts optional proxies: string[]; ``` *** ### validator()? ```ts optional validator: (ctx, ip) => boolean; ``` #### Parameters ##### ctx [`Context`](../../interfaces/Context.md)<`S`> ##### ip `string` | `null` #### Returns `boolean` --- --- url: /api/@minimajs/multipart/@minimajs/multipart/schema/interfaces/UploadOption.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/multipart](../../../../README.md) / [@minimajs/multipart/schema](../README.md) / UploadOption # Interface: UploadOption Configuration options for multipart upload handling. ## Extends * [`MultipartOptions`](../../type-aliases/MultipartOptions.md) ## Properties ### defCharset? ```ts optional defCharset: string; ``` Default character set to use when one isn't defined. #### Default ```ts 'utf8' ``` #### Inherited from ```ts MultipartOptions.defCharset ``` *** ### fileHwm? ```ts optional fileHwm: number; ``` highWaterMark to use for file streams. #### Default ```ts ReadableStream default. ``` #### Inherited from ```ts MultipartOptions.fileHwm ``` *** ### highWaterMark? ```ts optional highWaterMark: number; ``` `highWaterMark` to use for this Busboy instance. #### Default ```ts WritableStream default. ``` #### Inherited from ```ts MultipartOptions.highWaterMark ``` *** ### isPartAFile()? ```ts optional isPartAFile: (fieldName, contentType, fileName) => boolean; ``` Detect if a Part is a file. By default a file is detected if contentType is application/octet-stream or fileName is not undefined. Modify this to handle e.g. Blobs. #### Parameters ##### fieldName `string` | `undefined` ##### contentType `string` | `undefined` ##### fileName `string` | `undefined` #### Returns `boolean` #### Inherited from ```ts MultipartOptions.isPartAFile ``` *** ### limits? ```ts optional limits: { fieldNameSize?: number; fields?: number; fieldSize?: number; files?: number; fileSize?: number; headerPairs?: number; headerSize?: number; parts?: number; }; ``` Various limits on incoming data. #### fieldNameSize? ```ts optional fieldNameSize: number; ``` Max field name size (in bytes) ##### Default ```ts 100 bytes ``` #### fields? ```ts optional fields: number; ``` Max number of non-file fields ##### Default ```ts Infinity ``` #### fieldSize? ```ts optional fieldSize: number; ``` Max field value size (in bytes) ##### Default ```ts 1MB ``` #### files? ```ts optional files: number; ``` For multipart forms, the max number of file fields ##### Default ```ts Infinity ``` #### fileSize? ```ts optional fileSize: number; ``` For multipart forms, the max file size (in bytes) ##### Default ```ts Infinity ``` #### headerPairs? ```ts optional headerPairs: number; ``` For multipart forms, the max number of header key=>value pairs to parse ##### Default ```ts 2000 ``` #### headerSize? ```ts optional headerSize: number; ``` For multipart forms, the max size of a header part ##### Default ```ts 81920 ``` #### parts? ```ts optional parts: number; ``` For multipart forms, the max number of parts (fields + files) ##### Default ```ts Infinity ``` #### Inherited from ```ts MultipartOptions.limits ``` *** ### preservePath? ```ts optional preservePath: boolean; ``` If paths in the multipart 'filename' field shall be preserved. #### Default ```ts false ``` #### Inherited from ```ts MultipartOptions.preservePath ``` *** ### tmpDir? ```ts optional tmpDir: string; ``` Directory for storing temporary files. Defaults to system temp directory. --- --- url: /api/@minimajs/schema/validation/interfaces/ValidationOptions.md --- [**Minima.js API**](../../../../README.md) *** [Minima.js API](../../../../README.md) / [@minimajs/schema](../../README.md) / [validation](../README.md) / ValidationOptions # Interface: ValidationOptions ## Properties ### name? ```ts optional name: string; ``` *** ### stripUnknown? ```ts optional stripUnknown: boolean; ``` --- --- url: /api/@minimajs/schema/interfaces/ValidatorErrorOptions.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/schema](../README.md) / [](../README.md) / ValidatorErrorOptions # Interface: ValidatorErrorOptions Options for creating a validation error. Extends HTTP error options with validation-specific properties. ## Extends * `Omit`<[`HttpErrorOptions`](../../server/@minimajs/server/error/interfaces/HttpErrorOptions.md), `"base"`> ## Properties ### base? ```ts optional base: unknown; ``` The base error *** ### cause? ```ts optional cause: unknown; ``` #### Inherited from ```ts Omit.cause ``` *** ### code? ```ts optional code: string; ``` #### Inherited from ```ts Omit.code ``` *** ### headers? ```ts optional headers: HeadersInit; ``` #### Inherited from ```ts Omit.headers ``` *** ### issues? ```ts optional issues: $ZodIssue[]; ``` Array of zod issues *** ### message? ```ts optional message: string; ``` #### Inherited from ```ts Omit.message ``` *** ### name? ```ts optional name: string; ``` #### Inherited from ```ts Omit.name ``` --- --- url: /intro.md --- # Introduction to Minima.js Minima.js is a **TypeScript-first, high-performance web framework** built from scratch for modern JavaScript runtimes like **Node.js** and **Bun**. Built on battle-tested libraries like find-my-way and avvio, it combines production-ready reliability with a **clean, modern API** that embraces **file-based modules, context-aware design, and Web standards** — giving you performance and clarity without hidden behavior. ## Core Concepts Minima.js is built around five key ideas: 1. **Runtime-Native Support** - Built from scratch for Bun and Node.js with zero abstractions 2. **Web Standard First** - Uses native `Request`, `Response`, `File`, `Blob`, and `Uint8Array` throughout — no Node.js-specific buffers or proprietary abstractions 3. **File-Based Modules** - Your folder structure defines your API structure 4. **Context Functions** - Access request data anywhere without prop drilling 5. **Everything is a Plugin** - Hooks, middleware, auth—all follow the same pattern Let's explore each one. *** ## Runtime-Native Support Minima.js is designed for native integration with modern JavaScript runtimes like Bun and Node.js. You can switch between runtimes by changing a single import, ensuring optimal performance without abstraction overhead. ::: code-group ```typescript [Bun (Native)] import { createApp } from "@minimajs/server/bun"; // [!code highlight] import { params, headers } from "@minimajs/server"; const app = createApp(); app.get("/api/:resource", () => { const resource = params.get("resource"); const apiKey = headers.get("x-api-key"); return { resource, apiKey }; }); await app.listen({ port: 3000 }); ``` ```typescript [Node.js] import { createApp } from "@minimajs/server/node"; // [!code highlight] import { params, headers } from "@minimajs/server"; const app = createApp(); app.get("/api/:resource", () => { const resource = params.get("resource"); const apiKey = headers.get("x-api-key"); return { resource, apiKey }; }); await app.listen({ port: 3000 }); ``` ::: **Key Advantages:** * **One import to switch** - Change `/bun` to `/node` (or vice versa) and you're done * **Zero abstraction overhead** - Direct access to `Bun.serve()` or native Node.js HTTP * **No compatibility layers** - Not a legacy framework ported to modern runtimes * **Runtime-optimized** - Each import is tailored for its runtime's strengths **Why this matters:** * Your code runs at native speed with no framework overhead * Easy to test across runtimes in CI/CD * Future-proof as new runtimes emerge * Full control over runtime-specific features when needed *** ## File-Based Modules Instead of manually importing and registering routes, Minima.js **automatically discovers modules** from your file structure. Create a file, get a route. ### Auto-Discovery ::: code-group ```typescript [src/index.ts] import { createApp } from "@minimajs/server/bun"; const app = createApp(); // Discovers all modules automatically await app.listen({ port: 3000 }); ``` ```typescript [src/users/module.ts] import type { Routes } from "@minimajs/server"; function getUsers() { return [ { id: 1, name: "Alice" }, { id: 2, name: "Bob" }, ]; } export const routes: Routes = { "GET /list": getUsers, }; // ✅ Auto-loaded as /users/* ``` ```typescript [src/posts/module.ts] import type { Routes } from "@minimajs/server"; function getLatestPosts() { return { posts: [] }; } export const routes: Routes = { "GET /latest": getLatestPosts, }; // ✅ Auto-loaded as /posts/* ``` ::: **File structure = API structure:** * `src/users/module.ts` → `/users/*` * `src/posts/module.ts` → `/posts/*` * `src/api/v1/users/module.ts` → `/api/v1/users/*` No imports. No registration. Just create files. ### Module Plugins with `meta.plugins` Each module can declare its own plugins—hooks, middleware, auth—all in one place: ::: code-group ```typescript [src/users/module.ts] import type { Meta, Routes } from "@minimajs/server"; import { hook } from "@minimajs/server"; import { cors } from "@minimajs/server/plugins"; export const meta: Meta = { plugins: [cors({ origin: "https://example.com" }), hook("request", () => console.log("User route accessed"))], }; function getUsers() { return [ /* users */ ]; } export const routes: Routes = { "GET /list": getUsers, }; ``` ::: **Benefits:** * **Declarative** - See what affects each module at the top * **Scoped** - Plugins only affect this module and its children * **Isolated** - Siblings don't interfere with each other * **Testable** - Easy to mock plugins for testing ### Root Module for Global Config Create `src/module.ts` to configure ALL modules: ::: code-group ```typescript [src/module.ts] import { handler, type Meta, type Routes } from "@minimajs/server"; import { internal } from "@minimajs/openapi"; import { cors } from "@minimajs/server/plugins"; import { authPlugin } from "./plugins/auth.js"; // Root module - plugins apply to EVERY route export const meta: Meta = { prefix: "/api", plugins: [ authPlugin, // Global authentication cors({ origin: "*" }), // Global CORS ], }; // to attach route meta descriptors, use handler function // handler(...descriptors, handle) const health = handler(internal(), () => { return { status: "ok" }; }); export const routes: Routes = { "GET /health": health, }; ``` ```typescript [src/users/module.ts] import type { Routes } from "@minimajs/server"; function getUsers() { return [ /* users */ ]; } // Automatically inherits authPlugin and CORS from root export const routes: Routes = { "GET /list": getUsers, }; // ✅ /api/users/list (has auth + CORS from root) ``` ::: **Perfect for:** * Global authentication * Body parsing * CORS configuration * Rate limiting * Request logging > **Learn more:** [Full module tutorial →](/core-concepts/modules) *** ## Context Functions Access request data anywhere without passing context—powered by `AsyncLocalStorage`. This allows your functions to be pure and easily testable, pulling request-specific information only when needed. ```typescript [src/api/module.ts] import { params, searchParams, request, abort } from "@minimajs/server"; import type { Routes } from "@minimajs/server"; function getUserById() { const userId = params.get("id"); return { userId }; } function search() { const query = searchParams.get("q"); const page = searchParams.get("page", Number) ?? 1; // page type will be inferred as number return { query, page }; } async function uploadFile() { const req = request(); const formData = await req.formData(); return { uploaded: true }; } export const routes: Routes = { // Route params - accessible from anywhere within the request context "GET /users/:id": getUserById, // Query params with type coercion "GET /search": search, // Native Web API Request object - for full control "POST /upload": uploadFile, }; ``` **Extract logic to pure functions:** ```typescript [src/api/module.ts] import { params, headers, abort } from "@minimajs/server"; import type { Routes } from "@minimajs/server"; // Pure functions that leverage Minima.js's context function getUser() { // Assuming User.findById exists and uses context return User.findById(params.get("id", Number)); } function isAuthenticated() { return headers.get("authorization")?.startsWith("Bearer "); } async function getUserPosts() { if (!isAuthenticated()) { abort(401, "Unauthorized"); // Use abort for early exit with an error response } const user = await getUser(); return { user, posts: [] }; } export const routes: Routes = { // Compose them anywhere for clean, readable logic "GET /users/:id/posts": getUserPosts, }; ``` ## Hooks & Plugins **In Minima.js, everything is a plugin** - even hooks are plugins. Apply them via `meta.plugins` in your modules. ### Registering Hooks ::: code-group ```typescript [src/api/module.ts] import type { Meta, Routes } from "@minimajs/server"; import { hook } from "@minimajs/server"; export const meta: Meta = { plugins: [ // Request hook for logging hook("request", ({ request, pathname }) => { console.log(`${request.method} ${pathname}`); }), // Transform hook to modify response data hook("transform", (data) => { if (typeof data === "object") { return { ...data, timestamp: Date.now() }; } return data; }), ], }; function getData() { return { value: "test" }; } export const routes: Routes = { "GET /data": getData, // Response: { "value": "test", "timestamp": 1234567890 } }; ``` ::: **Available hooks:** * **`request`** - Before route matching (auth, rate limiting) * **`transform`** - Modify response data before serialization * **`send`** - After response sent (logging, cleanup) * **`error`** - Handle errors * **`timeout`** - Handle request timeouts **Application lifecycle hooks:** * **`hook.lifespan`** - Setup/teardown (database connections) * **`ready`** - When app is ready * **`listen`** - When server starts * **`close`** - When app shuts down > **Learn more:** [Hooks Guide](/guides/hooks) | [Error Handling](/guides/error-handling) *** ## Summary **Minima.js** gives you four superpowers: 1. **Runtime-native** - Built for Bun and Node.js with zero overhead 2. **File-based modules** - Structure your app naturally, no wiring needed 3. **Context everywhere** - Access request data from any function 4. **Plugin-based everything** - Compose behavior with `meta.plugins` Together, these create a framework where your architecture stays intentional, not accidental—and your code stays clean, not cluttered. **Ready to start building?** → [Getting Started Guide](/getting-started) --- --- url: /cookbook/jwt-authentication.md --- # JWT Authentication This recipe shows you how to implement JWT-based authentication using Minima.js's file-based module system. We'll use the `@minimajs/auth` package and `jsonwebtoken`, organizing everything into auto-discovered modules with `meta.plugins`. ## Prerequisites First, you need to install the required packages: ```bash npm install @minimajs/auth jsonwebtoken npm install -D @types/jsonwebtoken ``` ## Project Structure Here's our complete file structure using file-based module discovery: ``` src/ ├── index.ts # Entry point (auto-discovers modules) ├── auth/ │ ├── tools.ts # Auth plugin & getUser helper │ ├── guard.ts # Guard plugin for protected routes │ └── module.ts # Public routes: POST /auth/login └── profile/ └── module.ts # Protected routes: GET /profile/me, /profile/settings ``` **Key points:** * `module.ts` files are auto-discovered and loaded * Each module declares its plugins via `export const meta: Meta` * No manual registration needed - just create files! ## 1. Creating the Auth Tools Use the `createAuth` function from `@minimajs/auth` to create a reusable authentication plugin and a `getUser` helper to access the authenticated user. ::: code-group ```typescript [src/auth/tools.ts] import { createAuth } from "@minimajs/auth"; import { headers } from "@minimajs/server"; import * as jwt from "jsonwebtoken"; const JWT_SECRET = "your-super-secret-key"; // A simple user type for demonstration export interface User { id: number; username: string; } // createAuth returns a plugin and a getter function. // We are using optional authentication mode here. export const [authPlugin, getUser] = createAuth(async (): Promise => { const authHeader = headers.get("authorization"); if (!authHeader || !authHeader.startsWith("Bearer ")) { return null; // No token, so no user } const token = authHeader.split(" ")[1]; try { const decoded = jwt.verify(token, JWT_SECRET) as { userId: number; username: string }; return { id: decoded.userId, username: decoded.username }; } catch (error) { // For optional auth, you can return null for invalid tokens // or throw an error if you want to handle it specifically. return null; } }); ``` ::: ## 2. Creating a Guard Plugin A "guard" is a plugin that ensures a user is authenticated before allowing access to a route. Create it as a reusable plugin that can be added to `meta.plugins`. ::: code-group ```typescript [src/auth/guard.ts] import { plugin, hook } from "@minimajs/server"; import { getUser } from "./tools.js"; // This is our guard plugin - can be used in meta.plugins export const guardPlugin = plugin((app) => { app.register( hook("request", () => { // .required() throws an UnauthorizedError if the user is not authenticated getUser.required(); }) ); }); ``` ::: ## 3. Public Auth Routes (Login) Create the auth module with public routes (login). Register the `authPlugin` in `meta.plugins` to make `getUser()` available in this module's routes. ::: code-group ```typescript [src/auth/module.ts] import { body, type Meta } from "@minimajs/server"; import * as jwt from "jsonwebtoken"; import { UnauthorizedError } from "@minimajs/auth"; import { authPlugin } from "./tools.js"; const JWT_SECRET = "your-super-secret-key"; // A mock user database const users = [{ id: 1, username: "john.doe", password: "password123" }]; // Register authPlugin to make getUser() available export const meta: Meta = { plugins: [authPlugin], }; function login() { const { username, password } = body<{ username?: string; password?: string }>(); const user = users.find((u) => u.username === username && u.password === password); if (!user) { throw new UnauthorizedError("Invalid credentials"); } const token = jwt.sign({ userId: user.id, username: user.username }, JWT_SECRET, { expiresIn: "1h", }); return { token }; } export const routes: Routes = { "POST /login": login, }; // ✅ Auto-loaded as /auth/login ``` ::: ## 4. Protected Routes Module Create a protected module by adding both `authPlugin` and `guardPlugin` to `meta.plugins`. The guard ensures the user is authenticated before accessing routes. ::: code-group ```typescript [src/profile/module.ts] import type { Meta, Routes } from "@minimajs/server"; import { authPlugin, getUser } from "../auth/tools.js"; import { guardPlugin } from "../auth/guard.js"; // Apply both auth and guard plugins export const meta: Meta = { plugins: [ authPlugin, // Makes getUser() available guardPlugin, // Ensures user is authenticated ], }; function getMe() { // Because guard is applied, getUser() will always return a user here const user = getUser(); return { user }; } function getSettings() { const user = getUser(); return { user, message: "User settings", }; } export const routes: Routes = { "GET /me": getMe, "GET /settings": getSettings, }; // ✅ Auto-loaded as /profile/* // ✅ All routes are protected by guardPlugin ``` ::: ## 5. Entry Point The entry point is minimal - just create the app and let module discovery do the rest! ::: code-group ```typescript [src/index.ts] import { createApp } from "@minimajs/server/bun"; const app = createApp(); // Auto-discovers all modules await app.listen({ port: 3000 }); ``` ::: ### Alternative: Global Auth via Root Module If you want `getUser()` available in **all modules** without repeating `authPlugin`, create a root module: ::: code-group ```typescript [src/module.ts] import type { Meta, Routes } from "@minimajs/server"; import { authPlugin } from "./auth/tools.js"; // Root module - all child modules inherit these plugins export const meta: Meta = { plugins: [ authPlugin, // Now available in ALL modules ], }; function getHealth() { return "ok"; } export const routes: Routes = { "GET /health": getHealth, }; ``` ```typescript [src/auth/module.ts] import { body, type Routes } from "@minimajs/server"; import { getUser } from "./tools.js"; // ✅ authPlugin inherited from root function login() { // ... login logic } export const routes: Routes = { "POST /login": login, }; ``` ```typescript [src/profile/module.ts] import type { Meta, Routes } from "@minimajs/server"; import { getUser } from "../auth/tools.js"; // ✅ authPlugin inherited from root import { guardPlugin } from "../auth/guard.js"; // Only need guard here - authPlugin comes from root export const meta: Meta = { plugins: [guardPlugin], }; function getMe() { const user = getUser(); return { user }; } export const routes: Routes = { "GET /me": getMe, }; ``` ::: This approach is cleaner when most of your modules need authentication. ## How It Works With file-based module discovery: 1. **`/auth/login`** (public) - No guard, anyone can login 2. **`/profile/me`** (protected) - Guard in `meta.plugins` ensures authentication 3. **`/profile/settings`** (protected) - Same guard applies to all routes in module **API Routes:** * `POST /auth/login` - Public (login with credentials, get JWT) * `GET /profile/me` - Protected (returns authenticated user) * `GET /profile/settings` - Protected (returns user settings) **Testing:** ```bash # 1. Login to get token curl -X POST http://localhost:3000/auth/login \ -H "Content-Type: application/json" \ -d '{"username": "john.doe", "password": "password123"}' # Response: { "token": "eyJhbG..." } # 2. Access protected route with token curl http://localhost:3000/profile/me \ -H "Authorization: Bearer eyJhbG..." # Response: { "user": { "id": 1, "username": "john.doe" } } # 3. Without token -> 401 Unauthorized curl http://localhost:3000/profile/me ``` This approach provides a clean, file-based way to handle authentication and authorization in your Minima.js application. Each module declares its own requirements via `meta.plugins`, making it easy to see what protection applies to each feature. --- --- url: /guides/logger.md --- # Minima.js: Integrated Logging with Pino Minima.js streamlines development by offering a built-in logger powered by Pino. This logger simplifies debugging and monitoring by providing informative messages about your application's execution. ## Quick Reference * [`logger.info()`](#leveraging-the-built-in-logger) - Log informational messages * [`logger.error()`](#logging-errors) - Log errors * [`logger.debug()`](#debug-logging) - Log debug information * [`logger.warn()`](#warning-logs) - Log warnings * [`app.log`](#accessing-logger) - Access logger from app instance *** **Leveraging the Built-in Logger:** Here's how to integrate it into your code: **Example:** ```typescript title="src/services/index.ts" import { logger, type App, searchParams } from "@minimajs/server"; async function serviceHandler() { // Log request details with search parameters logger.info("received service request with %o", searchParams()); return "service request"; } export async function serviceModule(app: App) { app.get("/", serviceHandler); } ``` In this example: 1. We import `logger` and other necessary functions. 2. Inside `serviceHandler`, we leverage `logger.info` to log a message with the received search parameters using a placeholder (`%o`) for the object. **Console Output:** When you run your application and make a request like `curl http://localhost:1234/services?name=John`, the console might display an output similar to: ``` INFO (serviceModule:serviceHandler): received service request with {"name":"John"} ``` **Breakdown of the Output:** * `INFO`: The log level (in this case, informational) * `(serviceModule:serviceHandler)`: Indicates the source of the log message (\:\) * `received service request with {"name":"John"}`: The actual log message with the interpolated search parameters object. **Embrace Streamlined Development with Minima.js's Built-in Logging** By incorporating the built-in Pino logger, Minima.js empowers you to construct well-instrumented Node.js applications, fostering efficient development and a clear understanding of your application's execution flow. --- --- url: /guides/middleware.md --- # Middleware Middleware in Minima.js provides a way to **wrap the entire request-response cycle** using an onion-like execution pattern. Unlike hooks which react to specific lifecycle events, middleware gives you full control over the request flow with `next()` semantics. ::: warning Prefer Hooks Over Middleware Minima.js is optimized for a single middleware (the internal `contextProvider`). Adding additional middlewares introduces overhead in the request chain. For most use cases, **use hooks instead**: * **Error handling** → `hook("error", ...)` * **Authentication** → `hook("request", ...)` * **Logging** → `hook("request", ...)` or `hook("send", ...)` * **Validation** → `hook("request", ...)` Only use middleware when you **must wrap the request** with before/after logic that requires async context preservation (e.g., APM transactions, OpenTelemetry spans). ::: **In Minima.js, everything is a plugin** - middleware is registered as a plugin via: * **`meta.plugins`** in module files (recommended) * **`app.register(middleware(...))`** for manual registration ::: code-group ```typescript [src/module.ts] import { middleware } from "@minimajs/server"; import type { Routes } from "@minimajs/server"; export const meta = { plugins: [ middleware(async (ctx, next) => { const start = Date.now(); const response = await next(); console.log(`Request took ${Date.now() - start}ms`); return response; }), ], }; export const routes: Routes = { // Your routes here }; ``` ::: > **Important:** The `meta.plugins` property **only works in module files** (files named `module.{ts,js}` by default). For other files or manual registration, use `app.register(middleware(...))` instead. ## Quick Reference * [`middleware()`](#basic-usage) - Register middleware that wraps the request/response cycle * [Execution Order](#execution-order) - Understand the onion model (FIFO in, LIFO out) * [Middleware vs Hooks](#middleware-vs-hooks) - When to use each * [Async Context](#async-context-and-apm) - APM, tracing, and AsyncLocalStorage compatibility *** ## Basic Usage Middleware functions receive the request context and a `next` function. Call `next()` to continue to the next middleware or route handler: ```typescript import { middleware } from "@minimajs/server"; // Simple logging middleware app.register( middleware(async (ctx, next) => { console.log(`${ctx.request.method} ${ctx.pathname}`); return next(); }) ); ``` ### Wrapping the Response (Onion Model) Middleware can execute code **before** and **after** the handler: ```typescript app.register( middleware(async (ctx, next) => { // BEFORE: runs before handler console.log("Request started"); const response = await next(); // Call handler // AFTER: runs after handler returns console.log("Request completed"); return response; }) ); ``` *** ## Execution Order Middleware follows the **onion model**: execution flows inward through `next()` calls, then unwinds outward as each middleware returns. ### Multiple Middlewares ```typescript app.register( middleware( async (ctx, next) => { console.log("1. First middleware - before"); const response = await next(); console.log("6. First middleware - after"); return response; }, async (ctx, next) => { console.log("2. Second middleware - before"); const response = await next(); console.log("5. Second middleware - after"); return response; }, async (ctx, next) => { console.log("3. Third middleware - before"); const response = await next(); console.log("4. Third middleware - after"); return response; } ) ); app.get("/test", () => { console.log("Handler executed"); return { success: true }; }); ``` **Output:** ``` 1. First middleware - before 2. Second middleware - before 3. Third middleware - before Handler executed 4. Third middleware - after 5. Second middleware - after 6. First middleware - after ``` ### Visual Representation ``` Request ──►┌─────────────────────────────────────────────┐ │ Middleware 1 (before) │ │ ┌─────────────────────────────────────────┐│ │ │ Middleware 2 (before) ││ │ │ ┌─────────────────────────────────────┐││ │ │ │ Middleware 3 (before) │││ │ │ │ ┌─────────────────────────────────┐│││ │ │ │ │ Handler ││││ │ │ │ └─────────────────────────────────┘│││ │ │ │ Middleware 3 (after) │││ │ │ └─────────────────────────────────────┘││ │ │ Middleware 2 (after) ││ │ └─────────────────────────────────────────┘│ │ Middleware 1 (after) │ └─────────────────────────────────────────────┘◄── Response ``` *** ## Middleware vs Hooks Both middleware and hooks allow you to intercept requests, but they serve different purposes: | Feature | Middleware | Hooks | | ------------------- | ------------------------------- | ----------------------------------- | | **Execution Model** | Onion (wrap with `next()`) | Sequential (FIFO/LIFO) | | **Scope** | ⚠️ Always global | ✅ Module-scoped | | **Performance** | ⚠️ Adds overhead per middleware | ✅ Optimized | | **Async Context** | ✅ Preserved through chain | ⚠️ May break in loop iterations | | **Use Case** | APM, tracing | Logging, error handling, validation | > **Important:** Middleware is **always registered globally**, regardless of where you define it. Even if you register middleware inside a module, it will apply to all requests across the entire application. Use hooks for module-scoped behavior. ::: tip Register Middleware on Root App Only To keep your code future-proof, always register middleware on the root app explicitly. If you need to register middleware from within a module, use `app.$root`: ```typescript import { middleware, plugin } from "@minimajs/server"; export const meta = { plugins: [ plugin.sync((app) => { app.$root.register( middleware(async (ctx, next) => { // Your middleware logic return next(); }) ); }), ], }; ``` This ensures your middleware is explicitly global and won't break if module-scoped middleware is added in the future. ::: ### When to Use Middleware Only use middleware when you need to **wrap** the request with before/after logic: * **APM/Tracing** - Elastic APM, OpenTelemetry spans that must wrap the entire request * **Timing with async context** - When you need timing data to propagate through async operations ### When to Use Hooks * **Error Handling** - Use `error` hook for scoped error handling * **Authentication** - Use `request` hook to validate and reject requests * **Logging** - Log requests/responses as side effects * **Validation** - Quick request validation * **Cleanup** - Post-response cleanup tasks via `send` hook *** ## Async Context and APM Middleware is the recommended way to integrate APM tools (Elastic APM, OpenTelemetry, etc.) because it **preserves async context** through the entire request chain. ### Why Middleware for APM? Minima.js uses `AsyncLocalStorage` internally via `executionContext`. Middleware runs as a **direct call chain** within this context, ensuring APM transactions are properly tracked: ```typescript import { middleware } from "@minimajs/server"; import apm from "elastic-apm-node"; app.register( middleware(async (ctx, next) => { const transaction = apm.startTransaction(ctx.pathname, "request"); try { const response = await next(); transaction?.setOutcome("success"); return response; } catch (error) { transaction?.setOutcome("failure"); throw error; } finally { transaction?.end(); } }) ); ``` ### Why Not Hooks for APM? Hooks use a `for...await` loop internally, which can break async context propagation: ```typescript // ⚠️ This may lose APM context app.register( hook("request", async (ctx) => { const transaction = apm.startTransaction(); // May be lost }) ); ``` The middleware approach keeps everything in a single promise chain, preserving the async context. *** ## Common Patterns ### Request Timing with APM ```typescript import { middleware } from "@minimajs/server"; import apm from "elastic-apm-node"; app.register( middleware(async (ctx, next) => { const transaction = apm.startTransaction(ctx.pathname, "request"); const start = Date.now(); try { const response = await next(); transaction?.setOutcome("success"); console.log(`${ctx.pathname} took ${Date.now() - start}ms`); return response; } catch (error) { transaction?.setOutcome("failure"); apm.captureError(error); throw error; // Re-throw to let error hooks handle it } finally { transaction?.end(); } }) ); ``` > **Note:** For error handling, authentication, rate limiting, and other request validation, use hooks instead. Hooks provide module-scoped behavior and integrate with the error handling system. *** ## Registration Patterns ### Single Middleware ```typescript app.register( middleware(async (ctx, next) => { console.log("Single middleware"); return next(); }) ); ``` ### Multiple Middlewares (Same Registration) ```typescript app.register( middleware( async (ctx, next) => { console.log("First"); return next(); }, async (ctx, next) => { console.log("Second"); return next(); } ) ); ``` ### Multiple Registrations ```typescript app.register( middleware(async (ctx, next) => { console.log("First"); return next(); }) ); app.register( middleware(async (ctx, next) => { console.log("Second"); return next(); }) ); ``` All patterns maintain FIFO order for the "before" phase and LIFO for the "after" phase. *** ## Best Practices * **Use middleware for APM/tracing** - Async context is preserved through the chain * **Always return `next()`** - Don't skip calling next unless intentional * **Don't call `next()` multiple times** - This will throw an error * **Keep middleware focused** - Each middleware should do one thing well * **Order matters** - Register middleware in the order you want them to execute * **Prefer hooks** - Use hooks for error handling, authentication, validation, and side effects > **Advanced:** To customize `AsyncLocalStorage` behavior, see [Context Provider](../advanced/context-provider.md). --- --- url: /api/README.md --- **Minima.js API** *** # Minima.js API ## Packages | Package | Description | | ------ | ------ | | [@minimajs/auth](@minimajs/auth/README.md) | Authentication and authorization utilities with session management and guard support | | [@minimajs/cookie](@minimajs/cookie/README.md) | Type-safe cookie management for Minima.js | | [@minimajs/multipart](@minimajs/multipart/README.md) | Multipart/form-data handling with file upload support, validation, and schema integration | | [@minimajs/openapi](@minimajs/openapi/README.md) | OpenAPI 3.1 specification generator for MinimaJS with Zod schema integration | | [@minimajs/schema](@minimajs/schema/README.md) | Schema validation powered by Zod for request/response validation with type safety | | [@minimajs/server](@minimajs/server/README.md) | High-performance HTTP framework built for node/bun with context-aware request handling and zero boilerplate | --- --- url: /minimajs-vs-crowd.md --- # Minima.js vs. Other Frameworks Most framework comparisons are either hype or feature checklists. This page answers one practical question: **When is Minima.js the better choice for your team, and when is it not?** ## TL;DR Choose **Minima.js** if you want: * modern server runtime support (Node.js + Bun) * Web API-first backend primitives (`Request`, `Response`, `File`) * low-boilerplate modular architecture * hook-driven composition instead of heavy framework ceremony Do **not** choose Minima.js if you need: * Edge-first deployment model (Cloudflare-style first) * class/decorator-heavy enterprise patterns by default * a very large legacy plugin ecosystem like Express ## What Minima.js Optimizes For Minima.js is designed around server-side developer productivity with strong architecture defaults: 1. **Web-standard primitives** instead of framework-specific request/response wrappers. 2. **File-based module discovery** with explicit route maps. 3. **Context availability via AsyncLocalStorage** without prop-drilling request objects. 4. **Composable hooks/plugins** for lifecycle and cross-cutting concerns. ## Why Minima.js Feels Different In Practice These are not marketing points; they directly change how codebases scale. ### 1. Pure ESM + Web-native APIs by default Minima.js is aligned with modern runtime direction end-to-end: * native ESM imports/exports * first-class TypeScript + ESM workflows * standard Web primitives (`Request`, `Response`, `Headers`, `File`) instead of custom wrappers * no CommonJS compatibility tax in core architecture decisions Practical impact: * less ambiguity in build/runtime behavior (Node.js + Bun) * easier onboarding for developers who know `fetch` * less lock-in to framework-specific object APIs * cleaner portability of helper logic ### 2. Encapsulated module tree (strong isolation boundaries) Minima.js module composition is encapsulated by design. Parent/child boundaries help prevent accidental cross-module leakage of behavior. Practical impact: * hooks/plugins can be scoped intentionally * route/module growth remains predictable * fewer “global side-effects” surprises as teams add features This is a major difference from typical ad-hoc middleware layering in Express apps, where global behavior often grows implicitly over time. ### 3. Auto module discovery with explicit route maps Minima.js combines: * filesystem-driven module discovery * explicit `routes: Routes` declarations inside each module That gives you both velocity and clarity: less registration boilerplate, but still obvious route ownership. ### 4. Hook system built for real application lifecycle Minima.js hooks cover the full lifecycle (request flow, errors, startup/shutdown, response stages), with module-aware scoping. Practical impact: * cross-cutting behavior stays centralized and testable * you can enforce policy by scope (global/module/route) * operational concerns (resource connect/disconnect, graceful shutdown) are first-class ## Quick Comparison Matrix | Dimension | Minima.js | Express | Fastify | NestJS | Hono | |---|---|---|---|---|---| | Runtime focus | Node.js + Bun servers | Node.js servers | Node.js servers | Node.js servers | Edge + multi-runtime | | HTTP primitives | Web API (`Request`/`Response`) | Node req/res wrappers | Fastify req/reply wrappers | Framework abstractions | Web API style context | | Module isolation | Encapsulated module tree | Mostly convention-based | Plugin encapsulation | Module + DI boundaries | App/router composition | | Module discovery | Auto-discovery + explicit routes | Manual wiring | Manual wiring | CLI/decorator driven structure | Manual wiring | | Lifecycle model | Multi-stage hooks + lifespan | Middleware-first | Hooks + lifecycle | Interceptors/guards/pipes | Middleware + handlers | | Architecture style | Functional modules + hooks | Middleware chains | Plugin + schema-centric | DI + decorators + classes | Functional handlers | | Boilerplate | Low | Low | Medium | High | Low | | Best fit | Server APIs with clean modular growth | Legacy simplicity/ecosystem | High-throughput tuned APIs | Large enterprise org patterns | Edge-first apps | ## Minima.js vs Express Express is proven and still widely used. But for modern TypeScript backends, teams often outgrow its patterns. ### Where Minima.js is stronger * Pure ESM + TypeScript-first modern workflow. * Built around async-first modern code paths. * Uses standard Web APIs instead of legacy Node request/response ergonomics. * Cleaner request-scoped access patterns without manually threading `req` everywhere. ### Where Express is stronger * Largest ecosystem and historical community footprint. * Easy fit for older codebases already centered on Express middleware. **Pick Minima.js over Express when:** You want a modern server foundation without carrying legacy ergonomics forward. ## Minima.js vs Fastify Fastify is excellent for highly tuned Node APIs and has a strong performance culture. ### Where Minima.js is stronger * Auto-discovery + module route ownership model improves structure at scale. * Smaller conceptual surface for teams that value flow and readability. * Web API-first developer model. * File-based module structure that scales cleanly without extra registration overhead. ### Where Fastify is stronger * Mature ecosystem for schema-driven optimization patterns. * Better fit if your team is already deeply invested in Fastify plugins and conventions. **Pick Minima.js over Fastify when:** You care more about architecture clarity and low-ceremony development than maximizing framework-specific tuning knobs. ## Minima.js vs NestJS NestJS is a full framework platform with strong opinions around classes, DI, and decorators. ### Where Minima.js is stronger * Hook + module encapsulation model keeps cross-cutting concerns clean without deep class hierarchy. * Lower abstraction tax: fewer framework-specific concepts to onboard. * Function-first code style that stays close to plain TypeScript. * Less ceremony for straightforward API modules. ### Where NestJS is stronger * Fits organizations that explicitly prefer Angular-like architecture. * Strong ecosystem around decorators, pipes, guards, and enterprise conventions. **Pick Minima.js over NestJS when:** You want scalable architecture without adopting a class/decorator-heavy programming model. ## Minima.js vs Hono Hono is a strong choice for Edge-centric workloads. ### Where Minima.js is stronger * Better default fit for long-running application servers on Node.js/Bun. * Rich server-side patterns (module discovery, deep plugin lifecycle, file-heavy APIs). * Pure ESM + Web API orientation without forcing Edge-first constraints. ### Where Hono is stronger * Edge runtime footprint and deployment model. * Great option when your primary target is Workers-style environments. **Pick Minima.js over Hono when:** Your core product runs as a server backend, not primarily at the Edge. ## Example: Request Access in Deep Helpers ::: code-group ```typescript [Minima.js] import { request } from "@minimajs/server"; export function auditAction(action: string) { const req = request(); const ip = req.headers.get("x-forwarded-for"); console.log({ action, ip }); } ``` ```typescript [Traditional req threading] export function auditAction(req: RequestLike, action: string) { const ip = req.headers["x-forwarded-for"]; console.log({ action, ip }); } // Every caller must pass req manually handler((req) => auditAction(req, "create_task")); ``` ::: ## Decision Checklist Choose **Minima.js** if most answers are “yes”: * Do you want a pure ESM, Web-native API foundation on Node.js/Bun? * Do you want less framework ceremony and clearer modules? * Do you want strong module isolation boundaries as your codebase grows? * Do you want auto module discovery without losing explicit route ownership? * Do you want hooks/plugins for cross-cutting logic without class-heavy patterns? * Do you want to scale codebase structure through modules instead of conventions spread across many file types? If most answers are “no,” another framework may fit better for your constraints. --- --- url: /advanced/module-discovery.md --- # Module Discovery Configuration This guide covers advanced configuration for Minima.js module discovery. Use it when you need custom file names, a non-standard directory structure, or a custom scanner. ## Default Behavior By default, Minima.js: * Scans the directory of your entry file * Looks for `module.{ts,js}` files * Treats a `module.ts` in the root as the **root module** ```typescript // src/index.ts import { createApp } from "@minimajs/server/bun"; const app = createApp(); // defaults: root = entry dir, index = "module.{ts,js}" await app.listen({ port: 3000 }); ``` ## Configuration Options Configure discovery via `createApp({ moduleDiscovery: { ... } })`. ### `index` (glob pattern) Use a different glob pattern instead of the default `module.{ts,js}`. ```typescript // src/index.ts import { createApp } from "@minimajs/server/bun"; const app = createApp({ moduleDiscovery: { index: "route.{ts,js}", // or "route.ts" if using bun/tsx }, }); ``` **Resulting pattern:** `**/route.{ts,js}` ```text src/ ├── index.ts ├── users/ │ └── route.ts └── posts/ └── route.ts ``` #### Glob Patterns The `index` option supports glob patterns, allowing you to discover modules based on naming conventions. ```typescript // src/index.ts const app = createApp({ moduleDiscovery: { index: "*.module.{ts,js}", // or "*.module.ts" if using bun/tsx }, }); ``` **Resulting pattern:** `**/*.module.{ts,js}` ```text src/ ├── index.ts ├── users/ │ └── users.module.ts └── posts/ └── posts.module.ts ``` ### `root` (directory) Scan a specific directory instead of the entry file folder. ```typescript // src/index.ts import { createApp } from "@minimajs/server/bun"; import path from "node:path"; const app = createApp({ moduleDiscovery: { root: path.resolve(import.meta.dir, "features"), }, }); ``` **Resulting pattern:** `features/**/module.{ts,js}` ```text src/ ├── index.ts └── features/ ├── users/ │ └── module.ts └── posts/ └── module.ts ``` > **Important:** `moduleDiscovery.root` must be an **absolute path**. Use `path.resolve()`. ### Combine `root` + `index` ```typescript // src/index.ts import { createApp } from "@minimajs/server/bun"; import path from "node:path"; const app = createApp({ moduleDiscovery: { root: path.resolve(import.meta.dir, "app"), index: "route.{ts,js}", }, }); ``` **Resulting pattern:** `app/**/route.{ts,js}` ## Custom Scanner You can provide a custom scanner to control how modules are discovered. ```typescript // src/index.ts import { createApp, type ModuleScanner } from "@minimajs/server"; import { readdir } from "node:fs/promises"; import path from "node:path"; const scanner: ModuleScanner = async function* scan(dir, index) { // Example: only scan one level deep const entries = await readdir(dir, { withFileTypes: true }); for (const entry of entries) { if (!entry.isDirectory()) continue; const file = path.join(dir, entry.name, `${index}.ts`); yield file; } }; const app = createApp({ moduleDiscovery: { scanner, }, }); ``` Use a custom scanner if you need: * Non-standard folder layouts * Filters based on naming conventions * External module sources ## Disabling Module Discovery If you want to register everything manually: ```typescript const app = createApp({ moduleDiscovery: false, }); ``` ## Troubleshooting **Modules not discovered? Check:** 1. ✅ Is the filename correct? (`module.{ts,js}` by default) 2. ✅ Is `moduleDiscovery` enabled? (it is by default) 3. ✅ Is the root path absolute? 4. ✅ Is the file inside the discovery root? ## Related Docs * [Modules Tutorial](/core-concepts/modules) * [Plugins](/core-concepts/plugins) --- --- url: /core-concepts/modules.md --- # Building with File-Based Modules Learn how to structure your Minima.js application using filesystem-based modules. By the end of this tutorial, you'll understand how to organize features into modules, scope plugins, and build scalable APIs using nothing but your file structure. ## What You'll Learn * Creating your first auto-discovered module * Adding plugins to modules with `meta.plugins` * Building nested module hierarchies * Setting up global configuration with a root module * Customizing module discovery behavior ## Prerequisites This tutorial assumes you have a basic Minima.js app with an entry point (`src/index.ts`). If not, see [Getting Started](/getting-started) first. *** ## Step 1: Create Your First Module Let's start by creating a simple users module. Minima.js will automatically discover any file named `module.ts` in subdirectories. **1. Create the directory structure:** ``` src/ ├── index.ts └── users/ └── module.ts # This will be auto-discovered ``` **2. Write your first module:** ::: code-group ```typescript [src/users/module.ts] import type { Routes } from "@minimajs/server"; import { params } from "@minimajs/server"; const users = [ { id: 1, name: "Alice" }, { id: 2, name: "Bob" }, ]; function listUsers() { return users; } function getUser() { const id = params.get("id"); return users.find((u) => u.id === Number(id)); } export const routes: Routes = { "GET /list": listUsers, "GET /:id": getUser, }; ``` ```typescript [src/index.ts] import { createApp } from "@minimajs/server/bun"; const app = createApp(); // Auto-discovers users/module.ts await app.listen({ port: 3000 }); ``` ::: **3. Test it:** ```bash curl http://localhost:3000/users/list # → [{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}] curl http://localhost:3000/users/1 # → {"id":1,"name":"Alice"} ``` 🎉 **What just happened?** * Minima.js found `users/module.ts` automatically * The directory name (`users`) became the route prefix (`/users`) * Your routes (`/list` and `/:id`) were mounted under `/users` *** ## Step 2: Add Plugins to Your Module Now let's add some plugins to our users module - like request logging and CORS. **1. Add the `meta` export with plugins:** ::: code-group ```typescript [src/users/module.ts] import type { Meta, Routes } from "@minimajs/server"; import { hook, params } from "@minimajs/server"; import { cors } from "@minimajs/server/plugins"; const users = [ { id: 1, name: "Alice" }, { id: 2, name: "Bob" }, ]; // Register plugins in meta.plugins export const meta: Meta = { plugins: [ cors(), // Enable cors for this module hook("request", ({ request }) => { console.log(`[Users] ${request.method} ${request.url}`); }), ], }; function listUsers() { return users; } function getUser() { const id = params.get("id"); return users.find((u) => u.id === Number(id)); } export const routes: Routes = { "GET /list": listUsers, "GET /:id": getUser, }; ``` ::: **2. Test the routes:** ```bash curl http://localhost:3000/users/list # → [{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}] # Check your server logs - you'll see the logging hook output ``` ✨ **Key Concept:** Plugins in `meta.plugins` are **scoped to the module**. They only affect routes in this module, not others. *** ## Step 3: Create a Nested Module Let's add a nested module for user profiles. This demonstrates how modules can be organized hierarchically. **1. Create the nested structure:** ``` src/ ├── index.ts └── users/ ├── module.ts └── profile/ └── module.ts # Nested module ``` **2. Create the nested module:** ::: code-group ```typescript [src/users/profile/module.ts] import type { Routes } from "@minimajs/server"; import { params } from "@minimajs/server"; function getProfile() { const userId = params.get("userId"); return { userId, bio: "User profile for " + userId, settings: { theme: "dark" }, }; } export const routes: Routes = { "GET /:userId": getProfile, }; ``` ::: **3. Test the nested route:** ```bash curl http://localhost:3000/users/profile/1 # → {"userId":"1","bio":"User profile for 1",...} ``` 📁 **Route Structure:** * `src/users/module.ts` → `/users/*` * `src/users/profile/module.ts` → `/users/profile/*` The prefixes stack automatically! *** ## Step 4: Share Config with a Parent Module What if you want multiple child modules to share plugins? Use a parent module. **1. Restructure to use a parent:** ``` src/ ├── index.ts └── api/ ├── module.ts # Parent module ├── users/ │ └── module.ts # Child 1 └── posts/ └── module.ts # Child 2 ``` **2. Create the parent module with shared plugins:** ::: code-group ```typescript [src/api/module.ts] import type { Meta, Routes } from "@minimajs/server"; import { cors } from "@minimajs/server/plugins"; // These plugins apply to ALL child modules export const meta: Meta = { prefix: "/api/v1", plugins: [cors({ origin: "*" })], }; function getHealth() { return { status: "ok" }; } export const routes: Routes = { "GET /health": getHealth, }; ``` ```typescript [src/api/users/module.ts] import type { Routes } from "@minimajs/server"; function listUsers() { return { users: [] }; } // No need to register cors - inherited from parent! export const routes: Routes = { "GET /list": listUsers, }; ``` ```typescript [src/api/posts/module.ts] import type { Routes } from "@minimajs/server"; function listPosts() { return { posts: [] }; } // Also inherits CORS from parent export const routes: Routes = { "GET /list": listPosts, }; ``` ::: **3. Check the resulting routes:** * `GET /api/v1/health` (parent) * `GET /api/v1/users/list` (child, with inherited plugins) * `GET /api/v1/posts/list` (child, with inherited plugins) 🎯 **Inheritance:** Child modules automatically get their parent's prefix and plugins! *** ## Step 5: Set Up a Root Module (Global Config) For truly global configuration that applies to **every module**, create a root module in your discovery root. **1. Create a root module:** ``` src/ ├── index.ts ├── module.ts # ROOT module - applies to everything ├── users/ │ └── module.ts └── posts/ └── module.ts ``` **2. Add global plugins in the root module:** ::: code-group ```typescript [src/module.ts] import type { Meta, Routes } from "@minimajs/server"; import { cors } from "@minimajs/server/plugins"; import { hook } from "@minimajs/server"; // 🌍 Global configuration - inherited by ALL modules export const meta: Meta = { prefix: "/api", plugins: [ cors({ origin: "*" }), // All routes get CORS hook("request", ({ request }) => { console.log(`[Global] ${request.method} ${request.url}`); }), ], }; function getHealth() { return { status: "ok" }; } export const routes: Routes = { "GET /health": getHealth, }; ``` ::: **3. Now every module gets these plugins automatically:** ::: code-group ```typescript [src/users/module.ts] import type { Routes } from "@minimajs/server"; function listUsers() { return { users: [] }; } // No CORS here - inherited from root! export const routes: Routes = { "GET /list": listUsers, }; ``` ::: **Resulting structure:** * `GET /api/health` (root) * `GET /api/users/list` (inherits `/api` prefix + all plugins) * `GET /api/posts/list` (inherits `/api` prefix + all plugins) 💡 **Best Practice:** Put authentication, CORS, rate limiting, and global logging in the root module. ## Common Patterns ### Pattern 1: API Versioning ``` src/ ├── module.ts # Root with global auth ├── v1/ │ ├── module.ts # Prefix: /api/v1 │ ├── users/ │ │ └── module.ts │ └── posts/ │ └── module.ts └── v2/ ├── module.ts # Prefix: /api/v2 └── users/ └── module.ts ``` ### Pattern 2: Public vs Protected Routes ::: code-group ```typescript [src/module.ts] import { authPlugin } from "./plugins/auth.js"; // Root module - makes auth available everywhere export const meta: Meta = { plugins: [authPlugin], }; ``` ```typescript [src/public/module.ts] import type { Routes } from "@minimajs/server"; function login() { /* ... */ } // No guard - anyone can access export const routes: Routes = { "POST /login": login, }; ``` ```typescript [src/protected/module.ts] import type { Meta, Routes } from "@minimajs/server"; import { guardPlugin } from "../plugins/guard.js"; // Add guard to require authentication export const meta: Meta = { plugins: [guardPlugin], }; function getProfile() { /* ... */ } export const routes: Routes = { "GET /profile": getProfile, }; ``` ::: ### Pattern 3: Feature-Based Organization ``` src/ ├── auth/ │ ├── module.ts # Login, logout, etc. │ └── middleware/ │ └── guard.ts ├── users/ │ ├── module.ts # User CRUD │ └── profile/ │ └── module.ts # User profiles └── posts/ ├── module.ts # Post CRUD └── comments/ └── module.ts # Post comments ``` *** ## Troubleshooting ### My module isn't being discovered **Check:** 1. ✅ Is the file named `module.{ts,js}`? 2. ✅ Is it in a subdirectory of your entry point? 3. ✅ Is `moduleDiscovery` enabled? (It's on by default) **Debug by logging discovered modules:** ```typescript const app = createApp(); console.log("Checking module discovery..."); await app.ready(); ``` ### Plugins not working **Remember:** * `meta.plugins` only works in `module.ts` files (or your configured index filename) * Plugins are scoped to the module and its children * Parent modules' plugins are inherited by children ### Routes returning 404 **Check your prefix stacking:** ``` src/api/users/module.ts └─> /api (from parent) + /users (from directory) = /api/users/* ``` Use absolute prefixes in `meta.prefix` to override: ```typescript export const meta: Meta = { prefix: "/custom", // Overrides directory-based prefix }; ``` *** ## Next Steps Now that you understand modules, explore: * **[Plugins](/core-concepts/plugins)** - Create reusable plugins for your modules * **[Hooks](/guides/hooks)** - Learn all available lifecycle hooks * **[JWT Authentication](/cookbook/jwt-authentication)** - Build a real auth system with modules *** ## Quick Reference ### File Naming * Default: `module.{ts,js}` * Advanced configuration: [Module Discovery](/advanced/module-discovery) ### Module Structure ```typescript import type { Meta, Routes } from "@minimajs/server"; export const meta: Meta = { prefix: "/custom", // Optional: override directory name plugins: [ /* ... */ ], // Optional: module-scoped plugins }; export const routes: Routes = { // Your routes here }; ``` ### Module Types * **Regular Module:** Any `module.ts` in a subdirectory * **Root Module:** `module.ts` in the discovery root (global config) * **Nested Module:** `module.ts` inside another module's directory ### Plugin Scope * Root module plugins → Inherited by ALL modules * Parent module plugins → Inherited by children * Module plugins → Only that module * Sibling modules → Isolated from each other --- --- url: /api/@minimajs/multipart/@minimajs/multipart/namespaces/multipart/README.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/multipart](../../../../README.md) / [@minimajs/multipart](../../README.md) / multipart # multipart ## Functions | Function | Description | | ------ | ------ | | [body](functions/body.md) | Retrieves both text fields and files from a multipart form request as an async iterable. Each iteration yields a tuple of \[fieldName, value] where value can be a string or File. | | [fields](functions/fields.md) | Retrieves all text fields from a multipart form request. Files are ignored - only text field data is processed. | | [file](functions/file.md) | Retrieves a single file from a multipart form request. | | [files](functions/files.md) | Retrieves all files from a multipart form request as an async iterable. Field data is ignored - only files are processed. | | [firstFile](functions/firstFile.md) | Retrieves the first file from a multipart form request. | --- --- url: /packages/multipart.md --- # Multipart File Uploads The `@minimajs/multipart` package provides multiple APIs for handling multipart form data with different memory strategies. ## Installation ```bash npm install @minimajs/multipart ``` ## Overview The package provides four modules for different use cases: | Module | Memory | Use Case | | ----------- | ----------- | --------------------------------- | | `multipart` | Buffered | Simple uploads, small files | | `streaming` | Lazy buffer | Large files with File API | | `raw` | Unbuffered | Advanced use cases, custom piping | | `schema` | Disk-backed | Validated uploads with Zod | ## Quick Start ### Simple File Upload ```typescript import { multipart, helpers } from "@minimajs/multipart"; export async function uploadAvatar() { const avatar = await multipart.file("avatar"); if (!avatar) { return { error: "No file uploaded" }; } await helpers.save(avatar, "./uploads/avatars"); return { success: true, filename: avatar.name }; } ``` ### Streaming Large Files For large files, use the `raw` module to stream directly without memory buffering: ```typescript import { raw, helpers } from "@minimajs/multipart"; export async function uploadVideo() { const video = await raw.file("video"); if (!video) { return { error: "No video uploaded" }; } await helpers.save(video, "./uploads/videos"); return { filename: video.filename }; } ``` ### Validated Uploads with Zod For type-safe validation, use the schema module: ```typescript import { z } from "zod"; import { createMultipart } from "@minimajs/multipart/schema"; import { helpers } from "@minimajs/multipart"; const upload = createMultipart({ name: z.string().min(1), avatar: z .file() .mime(["image/jpeg", "image/png"]) .max(5 * 1024 * 1024), }); export async function handleUpload() { const data = await upload(); await helpers.save(data.avatar, "./uploads"); return { name: data.name }; } ``` ## multipart Module (Buffered) Standard approach that loads files into memory as Web API `File` objects. Best for small files. ### `multipart.file(name, options?)` Retrieves a single file by field name. ```typescript import { multipart } from "@minimajs/multipart"; const avatar = await multipart.file("avatar"); if (avatar) { console.log(avatar.name); // filename console.log(avatar.type); // MIME type console.log(avatar.size); // bytes } ``` **Returns:** `Promise` ### `multipart.firstFile(options?)` Retrieves the first file from the request. ```typescript const result = await multipart.firstFile(); if (result) { const [fieldName, file] = result; console.log(`${file.name} from field ${fieldName}`); } ``` **Returns:** `Promise<[field: string, file: File] | null>` ### `multipart.files(options?)` Iterates over all files in the request. ```typescript for await (const [field, file] of multipart.files()) { console.log(`${field}: ${file.name}`); await helpers.save(file, "./uploads"); } ``` **Returns:** `AsyncGenerator<[field: string, file: File]>` ### `multipart.fields()` Retrieves all text fields (files are ignored). ```typescript const fields = await multipart.fields<{ name: string; email: string }>(); console.log(fields.name, fields.email); ``` **Returns:** `Promise` ### `multipart.body(options?)` Iterates over both fields and files. ```typescript import { helpers } from "@minimajs/multipart"; for await (const [name, value] of multipart.body()) { if (helpers.isFile(value)) { await helpers.save(value, "./uploads"); } else { console.log(`${name}: ${value}`); } } ``` **Returns:** `AsyncGenerator<[field: string, value: string | File]>` ## streaming Module (Lazy Buffer) **Recommended for large files.** Returns `StreamFile` instances that don't load into memory until accessed. Stream directly to disk without buffering. ### `streaming.file(name, options?)` ```typescript import { streaming } from "@minimajs/multipart"; const file = await streaming.file("video"); // Not buffered - access metadata immediately console.log(file.name, file.type); // Stream directly to disk (no memory buffering) import { pipeline } from "node:stream/promises"; import { createWriteStream } from "node:fs"; await pipeline(file.stream(), createWriteStream("./uploads/video.mp4")); ``` **Returns:** `Promise` ### `streaming.firstFile(options?)` ```typescript const result = await streaming.firstFile(); if (result) { const [field, file] = result; const buffer = await file.arrayBuffer(); } ``` **Returns:** `Promise<[field: string, file: StreamFile] | null>` ### `streaming.body(options?)` ```typescript for await (const [name, value] of streaming.body()) { if (typeof value !== "string") { // StreamFile - buffers on read const content = await value.text(); } } ``` **Returns:** `AsyncGenerator<[field: string, value: string | StreamFile]>` ### StreamFile API ```typescript class StreamFile extends File { stream(): ReadableStream; // Web stream (one-time use) bytes(): Promise; // Buffer and return text(): Promise; // Decode as UTF-8 arrayBuffer(): Promise; toReadable(): Readable | null; // Node.js stream toFile(): Promise; // Convert to standard File } ``` ## raw Module (Advanced) Low-level access to busboy streams for advanced use cases. For most large file handling, prefer `streaming` module instead. ### `raw.file(name, options?)` ```typescript import { raw, helpers } from "@minimajs/multipart"; import { pipeline } from "node:stream/promises"; import { createWriteStream } from "node:fs"; const video = await raw.file("video"); if (video) { await pipeline(video.stream, createWriteStream(`./uploads/${video.filename}`)); } ``` **Returns:** `Promise` ### `raw.firstFile(options?)` ```typescript const file = await raw.firstFile(); if (file) { await helpers.save(file, "./uploads"); } ``` **Returns:** `Promise` ### `raw.files(options?)` ```typescript for await (const file of raw.files()) { await helpers.save(file, "./uploads"); } ``` **Returns:** `AsyncGenerator` ### `raw.body(options?)` ```typescript import { helpers } from "@minimajs/multipart"; for await (const item of raw.body()) { if (helpers.isRawFile(item)) { await helpers.save(item, "./uploads"); } else { console.log(`${item.fieldname}: ${item.value}`); } } ``` **Returns:** `AsyncGenerator` ### Raw Types ```typescript interface MultipartRawFile { fieldname: string; filename: string; mimeType: string; transferEncoding: string; stream: BusboyFileStream; [RAW_FILE]: true; } interface MultipartRawField { fieldname: string; value: string; [RAW_FIELD]: true; } type MultipartRawResult = MultipartRawFile | MultipartRawField; ``` ## helpers Module Utility functions for file handling. ### `helpers.save(file, dest, filename?)` Saves a file to disk. Works with `File`, `StreamFile`, `TempFile`, or `MultipartRawFile`. ```typescript import { helpers } from "@minimajs/multipart"; // Auto-generated UUID filename const name = await helpers.save(file, "./uploads"); // Returns: "550e8400-e29b-41d4-a716-446655440000.jpg" // Custom filename await helpers.save(file, "./uploads", "avatar.jpg"); ``` ### `helpers.isFile(value)` Type guard for Web API `File`. ```typescript if (helpers.isFile(value)) { console.log(value.name, value.size); } ``` ### `helpers.isRawFile(value)` Type guard for raw multipart files. ```typescript if (helpers.isRawFile(value)) { await pipeline(value.stream, destination); } ``` ### `helpers.isRawField(value)` Type guard for raw multipart fields. ```typescript if (helpers.isRawField(value)) { console.log(value.fieldname, value.value); } ``` ### `helpers.drain(rawFile)` Consumes and discards a raw file stream. ```typescript // Skip unwanted files await helpers.drain(rawFile); ``` ### `helpers.randomName(filename)` Generates UUID filename preserving extension. ```typescript helpers.randomName("photo.jpg"); // "550e8400-e29b-41d4-a716-446655440000.jpg" ``` ### `helpers.ensurePath(...paths)` Creates directory if it doesn't exist. ```typescript await helpers.ensurePath("./uploads", "avatars"); ``` ### `helpers.humanFileSize(bytes, decimals?)` Converts bytes to human-readable format. ```typescript helpers.humanFileSize(1048576); // "1.0 MiB" helpers.humanFileSize(1536, 2); // "1.50 KiB" ``` ## Configuration Options All modules accept `MultipartOptions`: ```typescript interface MultipartOptions { limits?: { fieldNameSize?: number; // Max field name size (100 bytes) fieldSize?: number; // Max field value size (1MB) fields?: number; // Max text fields (Infinity) fileSize?: number; // Max file size (Infinity) files?: number; // Max files (Infinity) parts?: number; // Max parts (Infinity) headerPairs?: number; // Max headers (2000) }; } ``` **Example:** ```typescript const avatar = await multipart.file("avatar", { limits: { fileSize: 5 * 1024 * 1024, // 5MB files: 1, }, }); ``` ## Complete Example ```typescript import { multipart, helpers } from "@minimajs/multipart"; export async function handleUpload() { const result: Record = {}; for await (const [name, value] of multipart.body()) { if (helpers.isFile(value)) { const savedName = await helpers.save(value, "./uploads"); result[name] = { filename: value.name, savedAs: savedName, size: helpers.humanFileSize(value.size), type: value.type, }; } else { result[name] = value; } } return { success: true, data: result }; } ``` ## Next Steps * [Schema Validation](./schema) - Type-safe uploads with Zod validation --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/README.md --- [**Minima.js API**](../../../../README.md) *** [Minima.js API](../../../../README.md) / [@minimajs/openapi](../../README.md) / OpenAPI # OpenAPI ## Interfaces | Interface | Description | | ------ | ------ | | [ArraySchemaObject](interfaces/ArraySchemaObject.md) | - | | [NonArraySchemaObject](interfaces/NonArraySchemaObject.md) | - | ## Type Aliases | Type Alias | Description | | ------ | ------ | | [ApiKeySecurityScheme](type-aliases/ApiKeySecurityScheme.md) | - | | [ArraySchemaObjectType](type-aliases/ArraySchemaObjectType.md) | - | | [BaseSchemaObject](type-aliases/BaseSchemaObject.md) | - | | [CallbackObject](type-aliases/CallbackObject.md) | - | | [ComponentsObject](type-aliases/ComponentsObject.md) | - | | [ContactObject](type-aliases/ContactObject.md) | - | | [DiscriminatorObject](type-aliases/DiscriminatorObject.md) | - | | [Document](type-aliases/Document.md) | - | | [EncodingObject](type-aliases/EncodingObject.md) | - | | [ExampleObject](type-aliases/ExampleObject.md) | - | | [ExternalDocumentationObject](type-aliases/ExternalDocumentationObject.md) | - | | [HeaderObject](type-aliases/HeaderObject.md) | - | | [HttpMethods](type-aliases/HttpMethods.md) | - | | [HttpSecurityScheme](type-aliases/HttpSecurityScheme.md) | - | | [InfoObject](type-aliases/InfoObject.md) | - | | [LicenseObject](type-aliases/LicenseObject.md) | - | | [LinkObject](type-aliases/LinkObject.md) | - | | [MediaTypeObject](type-aliases/MediaTypeObject.md) | - | | [NonArraySchemaObjectType](type-aliases/NonArraySchemaObjectType.md) | - | | [OAuth2SecurityScheme](type-aliases/OAuth2SecurityScheme.md) | - | | [OpenIdSecurityScheme](type-aliases/OpenIdSecurityScheme.md) | - | | [OperationObject](type-aliases/OperationObject.md) | - | | [ParameterBaseObject](type-aliases/ParameterBaseObject.md) | - | | [ParameterObject](type-aliases/ParameterObject.md) | - | | [PathItemObject](type-aliases/PathItemObject.md) | - | | [PathsObject](type-aliases/PathsObject.md) | - | | [ReferenceObject](type-aliases/ReferenceObject.md) | - | | [RequestBodyObject](type-aliases/RequestBodyObject.md) | - | | [ResponseObject](type-aliases/ResponseObject.md) | - | | [ResponsesObject](type-aliases/ResponsesObject.md) | - | | [SchemaObject](type-aliases/SchemaObject.md) | There is no way to tell typescript to require items when type is either 'array' or array containing 'array' type 'items' will be always visible as optional Casting schema object to ArraySchemaObject or NonArraySchemaObject will work fine | | [SecurityRequirementObject](type-aliases/SecurityRequirementObject.md) | - | | [SecuritySchemeObject](type-aliases/SecuritySchemeObject.md) | - | | [ServerObject](type-aliases/ServerObject.md) | - | | [ServerVariableObject](type-aliases/ServerVariableObject.md) | - | | [TagObject](type-aliases/TagObject.md) | - | | [XMLObject](type-aliases/XMLObject.md) | - | --- --- url: /packages/openapi.md --- # @minimajs/openapi OpenAPI 3.1 specification generator for MinimaJS with automatic schema extraction and route documentation. ## Installation ```bash bun add @minimajs/openapi ``` For schema integration (recommended): ```bash bun add @minimajs/openapi @minimajs/schema zod ``` ## Features * OpenAPI 3.1 specification generation * Automatic schema extraction from `@minimajs/schema` * Route descriptors for operation metadata * Path parameter detection from routes * Support for query parameters, headers, request/response bodies * Multiple response status codes * Security scheme definitions * Tag organization ## Quick Start ```typescript import { createApp } from "@minimajs/server/bun"; import { openapi } from "@minimajs/openapi"; const app = createApp(); app.register( openapi({ info: { title: "My API", version: "1.0.0", }, }) ); // OpenAPI spec available at GET /openapi.json await app.listen({ port: 3000 }); ``` ## Route Descriptors ### `describe()` - Operation Metadata Add OpenAPI operation metadata to routes: ```typescript import { describe } from "@minimajs/openapi"; app.get( "/users", describe({ summary: "List all users", description: "Returns a paginated list of users.", tags: ["Users"], operationId: "listUsers", }), () => { return getUsers(); } ); app.post( "/users", describe({ summary: "Create a user", tags: ["Users"], operationId: "createUser", }), () => { return createUser(); } ); ``` #### Available Options | Option | Type | Description | | -------------- | ---------- | ----------------------------------------- | | `summary` | `string` | Short operation summary | | `description` | `string` | Detailed description (Markdown supported) | | `tags` | `string[]` | Tags for grouping operations | | `operationId` | `string` | Unique operation identifier | | `deprecated` | `boolean` | Mark as deprecated | | `security` | `array` | Operation-level security requirements | | `externalDocs` | `object` | Link to external documentation | | `servers` | `array` | Operation-specific servers | | `parameters` | `array` | Additional parameters | | `requestBody` | `object` | Request body (if not using schema) | | `responses` | `object` | Responses (if not using schema) | ### `internal()` - Exclude from OpenAPI Mark routes as internal to exclude them from the specification: ```typescript import { internal } from "@minimajs/openapi"; // These won't appear in OpenAPI docs app.get("/health", internal(), () => "ok"); app.get("/metrics", internal(), () => getMetrics()); app.get("/openapi.json", internal(), () => spec); // Auto-excluded ``` ### Module-Level Descriptors Apply descriptors to all routes in a module: ```typescript import { type Routes } from "@minimajs/server"; import { descriptor } from "@minimajs/server/plugins"; import { describe } from "@minimajs/openapi"; // src/users/module.ts export const meta = { plugins: [descriptor(describe({ tags: ["Users"] }))], }; export const routes: Routes = { "GET /": () => getUsers(), // Tagged: Users "POST /": () => createUser(), // Tagged: Users "GET /:id": () => getUser(), // Tagged: Users }; ``` Combine multiple descriptors: ```typescript export const meta = { plugins: [descriptor(describe({ tags: ["Admin"], security: [{ bearerAuth: [] }] }), [kAdminOnly, true])], }; ``` ## Schema Integration Use `@minimajs/schema` to automatically document request/response shapes. ### Request Body ```typescript import { schema, createBody, createResponse } from "@minimajs/schema"; import { describe } from "@minimajs/openapi"; import { z } from "zod"; const CreateUser = createBody( z.object({ name: z.string().min(1).describe("User's full name"), email: z.string().email().describe("User's email address"), role: z.enum(["admin", "user"]).default("user"), }) ); const UserResponse = createResponse( 201, z.object({ id: z.string().uuid(), name: z.string(), email: z.string(), role: z.string(), createdAt: z.string().datetime(), }) ); app.post("/users", describe({ summary: "Create user", tags: ["Users"] }), schema(CreateUser, UserResponse), () => { const body = CreateUser(); return UserResponse({ id: crypto.randomUUID(), ...body, createdAt: new Date().toISOString(), }); }); ``` ### Query Parameters ```typescript import { createSearchParams, schema } from "@minimajs/schema"; const ListParams = createSearchParams({ page: z.coerce.number().int().min(1).default(1), limit: z.coerce.number().int().min(1).max(100).default(20), search: z.string().optional(), sort: z.enum(["name", "createdAt", "-name", "-createdAt"]).optional(), }); app.get("/users", describe({ summary: "List users", tags: ["Users"] }), schema(ListParams), () => { const { page, limit, search, sort } = ListParams(); return getUsers({ page, limit, search, sort }); }); ``` ### Path Parameters ```typescript import { createParams, schema } from "@minimajs/schema"; const UserParams = createParams({ id: z.string().uuid().describe("User ID"), }); app.get("/users/:id", describe({ summary: "Get user by ID", tags: ["Users"] }), schema(UserParams), () => { const { id } = UserParams(); return getUser(id); }); ``` ### Headers ```typescript import { createHeaders, schema } from "@minimajs/schema"; const AuthHeaders = createHeaders({ authorization: z.string().describe("Bearer token"), "x-request-id": z.string().uuid().optional(), }); app.get("/protected", describe({ summary: "Protected endpoint" }), schema(AuthHeaders), () => { const { authorization } = AuthHeaders(); return { authenticated: true }; }); ``` ### Multiple Response Status Codes ```typescript const SuccessResponse = createResponse(200, z.object({ data: z.any() })); const NotFoundResponse = createResponse( 404, z.object({ error: z.string(), code: z.literal("NOT_FOUND"), }) ); const ValidationError = createResponse( 400, z.object({ error: z.string(), code: z.literal("VALIDATION_ERROR"), details: z.array( z.object({ field: z.string(), message: z.string(), }) ), }) ); app.get("/users/:id", schema(SuccessResponse, NotFoundResponse, ValidationError), () => { // Handler logic }); ``` ### Response Headers ```typescript import { createResponseHeaders, createResponse, schema } from "@minimajs/schema"; const DownloadResponse = createResponse(200, z.instanceof(Blob)); const DownloadHeaders = createResponseHeaders({ "content-type": z.string(), "content-disposition": z.string(), "content-length": z.string(), }); app.get("/files/:id/download", schema(DownloadResponse, DownloadHeaders), () => { // Return file blob }); ``` ## Plugin Configuration ### Basic Configuration ```typescript app.register( openapi({ info: { title: "My API", version: "1.0.0", description: "API description with **Markdown** support", }, }) ); ``` ### Custom Endpoint Path ```typescript app.register( openapi({ path: "/api/v1/openapi.json", info: { title: "My API", version: "1.0.0" }, }) ); ``` ### Tags Define tags for organizing operations: ```typescript app.register( openapi({ info: { title: "My API", version: "1.0.0" }, tags: [ { name: "Users", description: "User management" }, { name: "Products", description: "Product catalog" }, { name: "Orders", description: "Order processing" }, ], }) ); ``` ### Security Schemes ```typescript app.register( openapi({ info: { title: "My API", version: "1.0.0" }, components: { securitySchemes: { bearerAuth: { type: "http", scheme: "bearer", bearerFormat: "JWT", description: "JWT authentication", }, apiKey: { type: "apiKey", in: "header", name: "X-API-Key", description: "API key authentication", }, oauth2: { type: "oauth2", flows: { authorizationCode: { authorizationUrl: "https://auth.example.com/authorize", tokenUrl: "https://auth.example.com/token", scopes: { "read:users": "Read user data", "write:users": "Modify user data", }, }, }, }, }, }, // Apply globally security: [{ bearerAuth: [] }], }) ); ``` ### Servers ```typescript app.register( openapi({ info: { title: "My API", version: "1.0.0" }, servers: [ { url: "https://api.example.com", description: "Production" }, { url: "https://staging-api.example.com", description: "Staging" }, { url: "http://localhost:3000", description: "Development" }, ], }) ); ``` ### Full Configuration Example ```typescript app.register( openapi({ path: "/openapi.json", info: { title: "E-Commerce API", version: "2.1.0", description: ` # E-Commerce API Complete API for managing products, orders, and users. ## Authentication All endpoints require Bearer token authentication unless marked as public. `, termsOfService: "https://example.com/terms", contact: { name: "API Support", url: "https://example.com/support", email: "api@example.com", }, license: { name: "MIT", url: "https://opensource.org/licenses/MIT", }, }, servers: [ { url: "https://api.example.com/v2", description: "Production" }, { url: "https://sandbox.example.com/v2", description: "Sandbox" }, ], tags: [ { name: "Products", description: "Product catalog management" }, { name: "Orders", description: "Order processing and fulfillment" }, { name: "Users", description: "User account management" }, ], components: { securitySchemes: { bearerAuth: { type: "http", scheme: "bearer", bearerFormat: "JWT", }, }, }, security: [{ bearerAuth: [] }], externalDocs: { description: "Full Developer Documentation", url: "https://docs.example.com", }, }) ); ``` ## Programmatic Generation Generate the OpenAPI document without registering an endpoint: ```typescript import { generateOpenAPIDocument } from "@minimajs/openapi"; const spec = generateOpenAPIDocument(app, { info: { title: "My API", version: "1.0.0" }, }); // Write to file await Bun.write("openapi.json", JSON.stringify(spec, null, 2)); // Or use in tests expect(spec.paths["/users"].get.summary).toBe("List users"); ``` ## API Reference ### `openapi(options)` Creates an OpenAPI plugin that serves the specification. | Option | Type | Default | Description | | -------------- | ----------------------------- | --------------- | -------------------------- | | `path` | `string` | `/openapi.json` | Endpoint path for the spec | | `info` | `InfoObject` | **required** | API metadata | | `servers` | `ServerObject[]` | `[]` | Server configurations | | `tags` | `TagObject[]` | `[]` | Tag definitions | | `security` | `SecurityRequirementObject[]` | - | Global security | | `components` | `ComponentsObject` | - | Reusable components | | `externalDocs` | `ExternalDocumentationObject` | - | External docs link | ### `generateOpenAPIDocument(app, options)` Generates the OpenAPI document programmatically. **Parameters:** * `app` - MinimaJS application instance * `options` - Same as `openapi()` options except `path` **Returns:** `OpenAPI.Document` ### `describe(options)` Creates a route descriptor for OpenAPI operation metadata. **Parameters:** `Partial` **Returns:** `RouteMetaDescriptor` ### `internal()` Creates a route descriptor that excludes the route from OpenAPI. **Returns:** `RouteMetaDescriptor` ## Swagger UI Integration Serve Swagger UI alongside your OpenAPI spec: ```typescript import { openapi } from "@minimajs/openapi"; app.register( openapi({ info: { title: "My API", version: "1.0.0" }, }) ); // Serve Swagger UI app.get("/docs", () => { const html = /* html */ ` API Docs
`; return new Response(html, { headers: { "content-type": "text/html" }, }); }); ``` ## See Also * [Schema Package](/packages/schema) - Request/response validation * [Route Descriptors](/guides/route-descriptors) - Custom metadata * [Descriptor Plugin](/plugins/descriptor) - Module-level metadata --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/params/README.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server](../../README.md) / params # params Utility functions for working with route parameters ## Functions | Function | Description | | ------ | ------ | | [get](functions/get.md) | Retrieves a single param by name with optional transformation. Throws NotFoundError if the param is not found. | | [optional](functions/optional.md) | Retrieves a single param by name with optional transformation. Returns undefined if the param is not found. | --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/plugin/README.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server](../../README.md) / plugin # plugin Plugin utilities namespace providing helper functions for creating and composing plugins. ## Functions | Function | Description | | ------ | ------ | | [getName](functions/getName.md) | - | | [is](functions/is.md) | - | | [isSync](functions/isSync.md) | - | | [sync](functions/sync.md) | - | --- --- url: /core-concepts/plugins.md --- # Plugins & Composition Plugins are the fundamental building blocks of Minima.js applications. They allow you to encapsulate and reuse logic, extend functionality, add lifecycle hooks, and compose complex features from smaller, manageable pieces. **In Minima.js, everything is a plugin** - even hooks are plugins. Apply them via: * **`meta.plugins`** in module files (recommended) * **`app.register()`** for manual registration This guide covers how to create plugins and how to use them in your modules. ## What is a Plugin? A plugin is a reusable component that extends the functionality of your application. Plugins can add hooks, middleware, authentication, logging, or any cross-cutting concern. **Key characteristics:** * Created with `plugin()` or `plugin.sync()` * Registered via `meta.plugins` in modules (recommended) * Can be registered via `app.register()` (manual) * Execute in the order they're defined ## Creating Plugins Minima.js provides two functions for creating plugins: `plugin` for asynchronous logic and `plugin.sync` for synchronous logic. ### `plugin()` Creates an asynchronous plugin. This is useful for plugins that need to perform async operations during setup. ```typescript plugin(fn: PluginCallback): Plugin ``` **Example (with options factory):** ::: code-group ```typescript [plugins/api-key.ts] import { plugin, hook } from "@minimajs/server"; interface ApiPluginOptions { apiKey: string; timeout?: number; } export const apiPlugin = (options: ApiPluginOptions) => plugin(async function api(app) { const { apiKey, timeout = 5000 } = options; app.register( hook("request", async () => { // Example: check api key on all requests in this scope }) ); }); ``` ```typescript [src/api/module.ts] import type { Routes } from "@minimajs/server"; import { apiPlugin } from "../../plugins/api-key.js"; // Register plugin with options in meta export const meta = { plugins: [ apiPlugin({ apiKey: process.env.API_KEY!, timeout: 10000, }), ], }; function getData() { return "protected data"; } export const routes: Routes = { "GET /data": getData, }; ``` ::: ### `plugin.sync()` Creates a synchronous plugin. For simple plugins that don't perform async operations, this is a convenient option. ```typescript plugin.sync(fn: PluginCallbackSync): Plugin ``` **Example:** ::: code-group ```typescript [plugins/cors.ts] import { plugin, hook } from "@minimajs/server"; export const corsPlugin = plugin.sync(function cors(app) { app.register( hook("request", (ctx) => { ctx.responseState.headers.set("Access-Control-Allow-Origin", "*"); }) ); }); ``` ```typescript [src/api/module.ts] import type { Routes } from "@minimajs/server"; import { corsPlugin } from "../../plugins/cors.js"; export const meta = { plugins: [corsPlugin], }; function getData() { return { data: "value" }; } export const routes: Routes = { "GET /data": getData, }; ``` ::: ## Composing Plugins The `compose()` function combines multiple plugins into a single plugin, executing them sequentially. **Common use cases:** * Group related hooks (lifecycle, logging) * Create reusable plugin stacks (security, auth + logging) * Organize complex plugin configurations ### Basic Usage ::: code-group ```typescript [src/api/module.ts] import { compose, type Routes } from "@minimajs/server"; import { cors } from "@minimajs/server/plugins"; import { helmetPlugin } from "../../plugins/helmet.js"; import { rateLimitPlugin } from "../../plugins/rate-limit.js"; // Compose security plugins const securityPlugins = compose(cors({ origin: "https://example.com" }), helmetPlugin(), rateLimitPlugin({ max: 100 })); export const meta = { plugins: [securityPlugins], }; function getSecureData() { return "protected"; } export const routes: Routes = { "GET /secure": getSecureData, }; ``` ```typescript [src/module.ts] import { compose, hook, type Routes } from "@minimajs/server"; // Group lifecycle hooks const appLifecycle = compose( hook("ready", async () => { await db.connect(); await cache.warmup(); }), hook("close", async () => { await cache.flush(); await db.disconnect(); }) ); export const meta = { plugins: [appLifecycle], }; function getHealth() { return "ok"; } export const routes: Routes = { "GET /health": getHealth, }; ``` ::: ### `compose.create()` for Modules with `app.register()` `compose.create()` creates a wrapper that applies plugins to modules when using `app.register()`. **This is only useful for manual module registration, not for `meta.plugins`.** ::: code-group ```typescript [src/index.ts] import { createApp, compose } from "@minimajs/server"; import { authPlugin } from "./plugins/auth.js"; import { loggingPlugin } from "./plugins/logging.js"; const app = createApp({ moduleDiscovery: false }); // Create a wrapper with common plugins const withAuthAndLogging = compose.create(authPlugin, loggingPlugin); // Manually register modules wrapped with plugins app.register( withAuthAndLogging(async (app) => { app.get("/users", () => "users"); }), { prefix: "/api" } ); await app.listen({ port: 3000 }); ``` ::: ## Best Practices 1. **Keep Plugins Focused**: Each plugin should have a single, clear responsibility 2. **Use Composition for Reusability**: Group related hooks and setup logic with `compose()` 3. **Order Matters in Composition**: Plugins execute in the order they're defined in the array ## Practical Examples ### Authentication Plugin ::: code-group ```typescript [plugins/auth.ts] import { plugin, hook, abort } from "@minimajs/server"; interface AuthOptions { secretKey: string; excludePaths?: string[]; } export const authPlugin = (options: AuthOptions) => plugin(async function auth(app) { const { secretKey, excludePaths = [] } = options; app.register( hook("request", async (ctx) => { if (excludePaths.includes(ctx.pathname)) return; const token = ctx.request.headers.get("authorization")?.split(" ")[1]; if (!token) { abort({ error: "Unauthorized" }, 401); } try { const user = await verifyToken(token, secretKey); // You would typically use `createContext` to make the user available. // e.g., `setUser(user)` } catch (err) { abort({ error: "Invalid token" }, 401); } }) ); }); ``` ```typescript [src/api/module.ts] import type { Routes } from "@minimajs/server"; import { authPlugin } from "../../plugins/auth.js"; export const meta = { plugins: [ authPlugin({ secretKey: process.env.JWT_SECRET!, excludePaths: ["/login", "/register"], }), ], }; function getProtectedData() { return { data: "secret" }; } export const routes: Routes = { "GET /protected": getProtectedData, }; ``` ::: ### Logging Plugin ::: code-group ```typescript [plugins/logger.ts] import { plugin, hook } from "@minimajs/server"; export const requestLogger = plugin(async function logger(app) { app.register( hook("request", (ctx) => { console.log(`[${new Date().toISOString()}] ${ctx.request.method} ${ctx.request.url}`); }) ); app.register( hook("send", (response, ctx) => { console.log(`[${new Date().toISOString()}] ${ctx.request.method} ${ctx.request.url} - ${response.status}`); }) ); }); ``` ```typescript [src/module.ts] import type { Routes } from "@minimajs/server"; import { requestLogger } from "../plugins/logger.js"; // Register logger in root module - applies to all child modules export const meta = { plugins: [requestLogger], }; function getHealth() { return "ok"; } export const routes: Routes = { "GET /health": getHealth, }; ``` ::: ### Database Connection ::: code-group ```typescript [database/connection.ts] import { plugin, hook } from "@minimajs/server"; interface DbOptions { connectionString: string; poolSize?: number; } export const connectDatabase = (options: DbOptions) => plugin(async function database(app) { const { connectionString, poolSize = 10 } = options; app.register( hook("ready", async () => { await db.connect(connectionString, { poolSize }); console.log("Database connected"); }) ); app.register( hook("close", async () => { await db.disconnect(); console.log("Database disconnected"); }) ); // Add health check route app.get("/health/db", async () => { const isHealthy = await db.ping(); return { status: isHealthy ? "healthy" : "unhealthy" }; }); }); ``` ```typescript [src/module.ts] import type { Routes } from "@minimajs/server"; import { connectDatabase } from "../database/connection.js"; // Register database plugin in root module export const meta = { plugins: [ connectDatabase({ connectionString: process.env.DATABASE_URL!, }), ], }; function getHealth() { return "ok"; } export const routes: Routes = { "GET /health": getHealth, }; ``` ::: *** ## Manual Registration (Alternative) If you're not using module discovery or need to register plugins in your entry file, use `app.register()`. ```typescript import { createApp } from "@minimajs/server/bun"; import { authPlugin } from "./plugins/auth.js"; const app = createApp({ moduleDiscovery: false }); app.register(authPlugin({ secretKey: process.env.JWT_SECRET! })); await app.listen({ port: 3000 }); ``` **When to use:** * Apps without module discovery * Registering global plugins in entry files * Quick prototypes or single-file apps **Recommended:** Use `meta.plugins` in module files for better organization. *** ## Plugin vs. Module When using `app.register()`, understanding the scoping difference between plugins and modules is crucial. ### The Key Difference: Scoping **Plugin** wraps logic with `plugin()` - extends the current scope: ```typescript import { createApp, plugin, hook } from "@minimajs/server/bun"; const loggerPlugin = plugin(async function logger(app) { app.register(hook("request", () => console.log("Logged"))); }); const app = createApp({ moduleDiscovery: false }); // Register plugin - it extends the root scope app.register(loggerPlugin); // This route gets the logger hook app.get("/users", () => "users"); // This module also inherits the logger hook app.register( async (app) => { app.get("/list", () => "posts"); // ✅ Logger runs here too }, { prefix: "/posts" } ); ``` **Module** is a plain function - creates an isolated scope: ```typescript import { createApp, hook } from "@minimajs/server/bun"; const app = createApp({ moduleDiscovery: false }); // Register a module - creates isolated scope app.register( async (app) => { // Hook registered here stays isolated app.register(hook("request", () => console.log("Users only"))); app.get("/list", () => "users"); // ✅ Hook runs here }, { prefix: "/users" } ); // This sibling module doesn't get the hook app.register( async (app) => { app.get("/list", () => "posts"); // ❌ Hook does NOT run here }, { prefix: "/posts" } ); ``` ### When to Use Each | Feature | Plugin (`plugin()`) | Module (`async function`) | | --------------- | ------------------------------ | -------------------------------- | | **Scope** | Extends **current** scope | Creates **new isolated** scope | | **Use Case** | Global hooks, middleware, auth | Feature routes, isolated logic | | **Inheritance** | Children inherit it | Children inherit, siblings don't | **Use plugin when:** You want hooks/middleware to apply to everything registered after it (global auth, logging, CORS) **Use module when:** You want to isolate a feature's routes and logic from other parts of the app > For a deeper dive into modules and auto-discovery, see the [Modules guide](/core-concepts/modules). ## See Also * [Hooks](/guides/hooks) * [Modules](/core-concepts/modules) --- --- url: /api/@minimajs/server/@minimajs/server/plugins/namespaces/proxy/README.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/server](../../../../../README.md) / [@minimajs/server/plugins](../../README.md) / proxy # proxy ## Functions | Function | Description | | ------ | ------ | | [ip](functions/ip.md) | - | --- --- url: /plugins/proxy.md --- # Proxy The Proxy plugin extracts client information from proxy headers when your application is behind a reverse proxy, load balancer, or CDN. It handles IP address extraction, protocol detection, and hostname reconstruction from common proxy headers like `X-Forwarded-For`, `X-Forwarded-Proto`, and `X-Forwarded-Host`. ## Installation The plugin is included with the `@minimajs/server` package and can be imported from `@minimajs/server/plugins`. ```typescript import { proxy } from "@minimajs/server/plugins"; ``` ## Usage ### Basic Usage By default, calling `proxy()` with no arguments **trusts all proxies** and extracts IP, host, and protocol information from proxy headers. It is recommended to register it in your root module. ::: code-group ```typescript [src/module.ts] import { proxy } from "@minimajs/server/plugins"; import { request, type Routes, type Meta } from "@minimajs/server"; // Trust all proxies - extracts IP, host, and proto export const meta: Meta = { plugins: [proxy()], }; function getClientInfo() { const clientIp = request.ip(); const info = request.url(); return { ip: clientIp, host: info.host, proto: info.protocol }; } export const routes: Routes = { "GET /client-info": getClientInfo, }; ``` ::: ### Disabling Features Set any feature to `false` to disable it within your module configuration: ::: code-group ```typescript [src/module.ts] import { proxy } from "@minimajs/server/plugins"; import { type Meta } from "@minimajs/server"; export const meta: Meta = { plugins: [ proxy({ host: false, // Only extract IP, disable host and proto proto: false, }), ], }; ``` ::: ## Configuration ### `trustProxies` Determines whether to trust proxy headers from the incoming request. When omitted or `undefined`, **all proxies are trusted by default**. * **Type**: `boolean | string[] | ((ctx: Context) => boolean) | undefined` * **Default**: `undefined` (trusts all proxies) ::: code-group ```typescript [src/module.ts] import { proxy } from "@minimajs/server/plugins"; import { request, type Meta } from "@minimajs/server"; export const meta: Meta = { plugins: [ // Don't trust any proxies - extraction is disabled proxy({ trustProxies: [] }), // Trust specific proxy IP addresses (Node.js runtime only) proxy({ trustProxies: ["127.0.0.1", "10.0.0.0/8"], }), // Custom trust validator proxy({ trustProxies: (ctx) => { const ip = request.remoteAddr(); return ip?.startsWith("10.") || ip === "127.0.0.1"; }, }), ], }; ``` ::: ### `ip` Configures IP address extraction from proxy headers. **Enabled by default**. Set to `false` to disable. * **Type**: `IpSettings | ((ctx: Context) => string | null) | false` * **Default**: Enabled with default settings #### IpSettings Interface ```typescript interface IpSettings { header?: string | string[]; // Custom header(s) to check depth?: number; // 1-based index from the right (server-side) of the X-Forwarded-For header. strategy?: "first" | "last"; // Selection strategy for x-forwarded-for } ``` #### Disabling IP Extraction ```typescript export const meta: Meta = { plugins: [ proxy({ ip: false }) ] }; ``` #### Using Depth (Recommended for Multi-Proxy) When you specify `depth`, the plugin automatically uses it to extract the IP at that position in the `X-Forwarded-For` chain. `depth` is a 1-based index from the right (server-side). For an `X-Forwarded-For` header of `"client, proxy1, proxy2"`: * `depth: 1` extracts `proxy2` * `depth: 2` extracts `proxy1` * `depth: 3` extracts `client` ```typescript // Extract the client IP, assuming 2 trusted proxies // x-forwarded-for: "client, proxy1, proxy2" export const meta: Meta = { plugins: [ proxy({ ip: { depth: 3 }, }), ], }; ``` ### `host` Configures hostname extraction from proxy headers. **Enabled by default**. Set to `false` to disable. * **Type**: `HostSettings | ((ctx: Context) => string | null) | false` * **Default**: Enabled with default settings #### HostSettings Interface ```typescript interface HostSettings { header?: string | string[]; // Header(s) to check (default: "x-forwarded-host") } ``` #### Disabling Host Extraction ```typescript export const meta: Meta = { plugins: [ proxy({ host: false }) ] }; ``` #### Using Settings Object ```typescript // Multiple header fallback export const meta: Meta = { plugins: [ proxy({ host: { header: ["x-forwarded-host", "x-original-host"], }, }), ], }; ``` ### `proto` Configures protocol extraction from proxy headers. Enabled by default, set to `false` to disable. * **Type**: `ProtoSettings | ProtoCallback | false` * **Default**: Enabled (uses default settings) > **Note**: `proto` and `host` are always extracted together. To disable both, you must set both `proto: false` and `host: false`. #### Disabling Proto Extraction ```typescript export const meta: Meta = { plugins: [ proxy({ trustProxies: true, proto: false, // Must also set host: false to disable both host: false, }), ], }; ``` ## Complete Examples ### Default (Development) ::: code-group ```typescript [src/module.ts] import { proxy } from "@minimajs/server/plugins"; import { type Meta } from "@minimajs/server"; // Trust all proxies, extract all information export const meta: Meta = { plugins: [proxy()], }; ``` ::: ### Behind NGINX ::: code-group ```typescript [src/module.ts] import { proxy } from "@minimajs/server/plugins"; import { type Meta } from "@minimajs/server"; export const meta: Meta = { plugins: [ proxy({ trustProxies: ["127.0.0.1"], // Trust localhost NGINX ip: { depth: 2 }, // If NGINX is the only proxy, client IP is at depth 2 }), ], }; ``` ::: ### Behind Multiple Proxies ::: code-group ```typescript [src/module.ts] import { proxy } from "@minimajs/server/plugins"; import { type Meta } from "@minimajs/server"; export const meta: Meta = { plugins: [ proxy({ trustProxies: ["10.0.0.1", "10.0.0.2"], // Trust specific proxies ip: { depth: 3 }, // If there are 2 proxies, client IP is at depth 3 host: { header: ["x-forwarded-host", "x-original-host"], }, }), ], }; ``` ::: ### Custom Logic for All Options ::: code-group ```typescript [src/module.ts] import { proxy } from "@minimajs/server/plugins"; import { type Meta } from "@minimajs/server"; export const meta: Meta = { plugins: [ proxy({ trustProxies: (ctx) => { const ip = ctx.incomingMessage?.socket?.remoteAddress; return ip === "127.0.0.1" || ip?.startsWith("10."); }, ip: (ctx) => { // Prefer Cloudflare header, fallback to X-Forwarded-For return ( ctx.request.headers.get("cf-connecting-ip") || ctx.request.headers.get("x-forwarded-for")?.split(",")[0]?.trim() || null ); }, host: (ctx) => { const host = ctx.request.headers.get("x-forwarded-host") || ctx.request.url.hostname; return host.split(":")[0]; // Strip port }, proto: (ctx) => { const proto = ctx.request.headers.get("x-forwarded-proto"); const ssl = ctx.request.headers.get("x-arr-ssl"); return proto === "https" || ssl === "on" ? "https" : "http"; }, }), ], }; ``` ::: ## Accessing Extracted Values ### IP Address ::: code-group ```typescript [src/users/module.ts] import { request, type Routes } from "@minimajs/server"; function getClientIp() { const clientIp = request.ip(); return { ip: clientIp }; } export const routes: Routes = { "GET /client-ip": getClientIp, }; ``` ::: ### Host and Protocol The extracted host and protocol are used to reconstruct the `request.url()` object: ::: code-group ```typescript [src/system/module.ts] import { request, type Routes } from "@minimajs/server"; function getRequestInfo() { const info = request.url(); // type URL return { host: info.host, proto: info.protocol, url: info.href, }; } export const routes: Routes = { "GET /request-info": getRequestInfo, }; ``` ::: ## Security Considerations ### Trust Only Known Proxies in Production By default, `proxy()` trusts all proxies. In production, always specify which proxies to trust via `meta.plugins` in your root module. ::: code-group ```typescript [src/module.ts] import { proxy } from "@minimajs/server/plugins"; import { type Meta } from "@minimajs/server"; export const meta: Meta = { plugins: [ // ✅ Production - trust specific proxies proxy({ trustProxies: ["10.0.1.1", "10.0.1.2", "10.0.0.0/16"], }), ], }; ``` ::: ### Header Spoofing Without proper trust validation, clients can spoof headers. Always ensure `trustProxies` is correctly configured to only validate headers from your actual infrastructure. ## Common Proxy Headers | Header | Purpose | Example Values | | ------------------- | ----------------------- | --------------------------- | | `X-Forwarded-For` | Client IP address chain | `203.0.113.195, 70.41.3.18` | | `X-Forwarded-Proto` | Original protocol | `https`, `http` | | `X-Forwarded-Host` | Original hostname | `example.com` | | `X-Real-IP` | Client IP (NGINX) | `203.0.113.195` | | `CF-Connecting-IP` | Client IP (Cloudflare) | `203.0.113.195` | | `X-Arr-SSL` | SSL indicator (Azure) | `on` | ## TypeScript Types ```typescript import type { ProxyOptions, IpSettings, HostSettings, ProtoSettings } from "@minimajs/server/plugins"; const options: ProxyOptions = { trustProxies: true, ip: { depth: 1 }, host: { header: "x-forwarded-host" }, proto: {}, }; ``` --- --- url: /api/@minimajs/multipart/@minimajs/multipart/namespaces/raw/README.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/multipart](../../../../README.md) / [@minimajs/multipart](../../README.md) / raw # raw ## Variables | Variable | Description | | ------ | ------ | | [RAW\_FIELD](variables/RAW_FIELD.md) | - | | [RAW\_FILE](variables/RAW_FILE.md) | - | ## Functions | Function | Description | | ------ | ------ | | [body](functions/body.md) | Retrieves both text fields and files from a multipart form request as an async iterable. Each iteration yields a MultipartRawResult (either MultipartRawFile or MultipartRawField). | | [busboy](functions/busboy.md) | - | | [file](functions/file.md) | Retrieves a raw file stream from a multipart form request without buffering into memory. Useful for streaming large files directly to disk or other destinations. | | [files](functions/files.md) | - | | [firstFile](functions/firstFile.md) | Retrieves the first raw file stream from a multipart form request without buffering. | --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/request/README.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server](../../README.md) / request # request Request utilities for accessing request data ## Functions | Function | Description | | ------ | ------ | | [ip](functions/ip.md) | Retrieves the client IP address from the request. Requires IP address configuration via request.ip.configure(). | | [remoteAddr](functions/remoteAddr.md) | - | | [url](functions/url.md) | Retrieves the full request URL. | --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/response/README.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server](../../README.md) / response # response Response utilities for managing HTTP responses ## Functions | Function | Description | | ------ | ------ | | [status](functions/status.md) | Creates an empty response with the specified status code. | --- --- url: /guides/route-descriptors.md --- # Route Descriptors Route descriptors allow you to attach metadata to routes. This metadata can be used by plugins like OpenAPI for documentation generation, authentication requirements, rate limiting, or any custom route-level configuration. ## What is a Route Descriptor? A route descriptor is either: 1. **A tuple** `[symbol, value]` - sets a specific metadata entry 2. **A function** `(route) => void` - receives the route config for dynamic modifications ```typescript import type { RouteMetaDescriptor } from "@minimajs/server"; // Tuple form - simple key-value pair const myDescriptor: RouteMetaDescriptor = [mySymbol, "value"]; // Function form - access to full route config const dynamicDescriptor: RouteMetaDescriptor = (route) => { route.metadata[mySymbol] = route.path; }; ``` ## The `RouteMetaDescriptor` Type The type definition: ```typescript type RouteMetaDescriptor = | [symbol: symbol, value: unknown] | ((config: RouteConfig) => void); ``` The `RouteConfig` provides access to: ```typescript interface RouteConfig { methods: HTTPMethod[]; // HTTP methods (GET, POST, etc.) path: string; // Route path pattern handler: Handler; // Route handler function metadata: RouteMetadata; // Metadata object to modify app: App; // Application instance } ``` ## Using Descriptors on Routes ### With `export const routes` (Recommended) When using the file-based module system, use the `handler()` helper to attach descriptors to your route handlers. ```typescript import { handler, type Routes } from "@minimajs/server"; function getUsers() { /* ... */ } function createUser() { /* ... */ } export const routes: Routes = { // Single descriptor "GET /users": handler(myDescriptor, getUsers), // Multiple descriptors - applied in order "POST /users": handler(descriptor1, descriptor2, descriptor3, createUser), }; ``` ### Programmatic Usage Descriptors are passed between the path and handler in programmatic route definitions: ```typescript import { createApp } from "@minimajs/server/bun"; const app = createApp(); // Single descriptor app.get("/users", myDescriptor, () => { return getUsers(); }); // Multiple descriptors app.post("/users", descriptor1, descriptor2, descriptor3, () => { return createUser(); }); ``` ## Creating Custom Descriptors ### Simple Tuple Descriptors For static metadata, use helper functions that return tuples: ```typescript // descriptors/auth.ts import type { RouteMetaDescriptor } from "@minimajs/server"; export const kAuthRequired = Symbol("auth.required"); export const kAuthRoles = Symbol("auth.roles"); export const kRateLimit = Symbol("rateLimit"); // Simple boolean flag export function requireAuth(): RouteMetaDescriptor { return [kAuthRequired, true]; } // With parameters export function requireRoles(...roles: string[]): RouteMetaDescriptor { return [kAuthRoles, roles]; } // With configuration object export function rateLimit(config: { max: number; window: string }): RouteMetaDescriptor { return [kRateLimit, config]; } ``` Usage in a module: ```typescript import { handler, type Routes } from "@minimajs/server"; import { requireAuth, requireRoles, rateLimit } from "./descriptors/auth.js"; function getProfile() { /* ... */ } function deleteUser() { /* ... */ } export const routes: Routes = { // Single descriptor "GET /profile": handler(requireAuth(), getProfile), // Multiple descriptors "DELETE /users/:id": handler( requireAuth(), requireRoles("admin"), rateLimit({ max: 10, window: "1m" }), deleteUser ), }; ``` ### Dynamic Function Descriptors For metadata that depends on route properties: ```typescript import type { RouteMetaDescriptor } from "@minimajs/server"; const kOperationId = Symbol("operationId"); const kAuditLog = Symbol("auditLog"); // Generate operationId from route info export function autoOperationId(): RouteMetaDescriptor { return (route) => { const method = route.methods[0].toLowerCase(); const path = route.path.replace(/[/:]/g, "_").replace(/^_/, ""); route.metadata[kOperationId] = `${method}_${path}`; }; } // Conditional metadata based on HTTP method export function auditMutations(): RouteMetaDescriptor { return (route) => { const mutationMethods = ["POST", "PUT", "PATCH", "DELETE"]; if (route.methods.some(m => mutationMethods.includes(m))) { route.metadata[kAuditLog] = true; } }; } ``` ### Composing Descriptors Create higher-level descriptors from multiple lower-level ones: ```typescript import type { RouteMetaDescriptor } from "@minimajs/server"; import { requireAuth, requireRoles, rateLimit } from "./auth.js"; import { describe } from "@minimajs/openapi"; // Combine multiple descriptors for admin routes export function adminRoute(summary: string): RouteMetaDescriptor[] { return [ requireAuth(), requireRoles("admin"), rateLimit({ max: 100, window: "1m" }), describe({ summary, tags: ["Admin"] }), ]; } // Usage with spread app.get("/admin/users", ...adminRoute("List admin users"), () => { return getAdminUsers(); }); ``` ## Reading Route Metadata Access route metadata in hooks to implement cross-cutting concerns: ### In Request Hooks ```typescript import { hook, abort } from "@minimajs/server"; import { kAuthRequired, kAuthRoles } from "./descriptors/auth.js"; app.register( hook("request", async (ctx) => { const metadata = ctx.route?.store.metadata; if (!metadata) return; // Check authentication requirement if (metadata[kAuthRequired]) { const token = ctx.request.headers.get("authorization"); if (!token) { abort({ error: "Unauthorized" }, 401); } // Verify token... } // Check role requirements const requiredRoles = metadata[kAuthRoles] as string[] | undefined; if (requiredRoles?.length) { const userRoles = getUserRoles(); // From verified token const hasRole = requiredRoles.some(r => userRoles.includes(r)); if (!hasRole) { abort({ error: "Forbidden" }, 403); } } }) ); ``` ### In Send Hooks ```typescript import { hook } from "@minimajs/server"; const kCacheControl = Symbol("cacheControl"); app.register( hook("send", (response, ctx) => { const cacheControl = ctx.route?.store.metadata[kCacheControl] as string | undefined; if (cacheControl) { response.headers.set("Cache-Control", cacheControl); } return response; }) ); ``` ### Building Plugins from Metadata Create reusable plugins that act on metadata: ```typescript import { plugin, hook, abort } from "@minimajs/server"; import { kRateLimit } from "./symbols.js"; interface RateLimitConfig { max: number; window: string; } const rateLimitStore = new Map(); export const rateLimitPlugin = plugin(async (app) => { app.register( hook("request", (ctx) => { const config = ctx.route?.store.metadata[kRateLimit] as RateLimitConfig | undefined; if (!config) return; const key = `${ctx.request.ip}:${ctx.pathname}`; const now = Date.now(); const entry = rateLimitStore.get(key); if (entry && entry.resetAt > now) { if (entry.count >= config.max) { abort({ error: "Rate limit exceeded" }, 429); } entry.count++; } else { rateLimitStore.set(key, { count: 1, resetAt: now + parseWindow(config.window) }); } }) ); }); ``` ## Module-Level Descriptors Use the `descriptor()` plugin to apply metadata to all routes in a module: ```typescript import { descriptor } from "@minimajs/server/plugins"; import type { Meta, Routes } from "@minimajs/server"; export const meta: Meta = { plugins: [ descriptor( requireAuth(), rateLimit({ max: 100, window: "1m" }) ), ], }; function getData() { /* ... */ } function createData() { /* ... */ } export const routes: Routes = { // All routes inherit the descriptors "GET /data": getData, "POST /data": createData, }; ``` > For detailed documentation on the `descriptor()` plugin, see [Plugins - Descriptor](/core-concepts/plugins#route-metadata-with-descriptor). ## OpenAPI Integration The `@minimajs/openapi` package provides built-in descriptors: ### `describe()` - Operation Metadata ```typescript import { describe } from "@minimajs/openapi"; import { handler, type Routes } from "@minimajs/server"; function getUsers() { /* ... */ } export const routes: Routes = { "GET /users": handler(describe({ summary: "List all users", description: "Returns a paginated list of all users.", tags: ["Users"], operationId: "listUsers", deprecated: false, security: [{ bearerAuth: [] }], }), getUsers), }; ``` ### `internal()` - Exclude from OpenAPI ```typescript import { internal } from "@minimajs/openapi"; import { handler, type Routes } from "@minimajs/server"; function getHealth() { return "ok"; } function getMetrics() { /* ... */ } export const routes: Routes = { // Won't appear in OpenAPI documentation "GET /health": handler(internal(), getHealth), "GET /metrics": handler(internal(), getMetrics), }; ``` ### Combining with Schema ```typescript import { schema, createBody, createResponse } from "@minimajs/schema"; import { describe } from "@minimajs/openapi"; import { handler, type Routes } from "@minimajs/server"; import { z } from "zod"; const CreateUser = createBody( z.object({ name: z.string(), email: z.string().email(), }) ); const UserResponse = createResponse(201, z.object({ id: z.string(), name: z.string(), email: z.string(), })); function createUser() { const body = CreateUser(); return UserResponse({ id: "123", ...body }); } export const routes: Routes = { "POST /users": handler( describe({ summary: "Create user", tags: ["Users"] }), schema(CreateUser, UserResponse), createUser ), }; ``` ## Best Practices 1. **Use symbols for keys** - Prevents naming collisions between packages ```typescript // Good - unique symbol export const kAuth = Symbol("myapp.auth"); // Avoid - string keys can collide metadata["auth"] = true; ``` 2. **Create helper functions** - More readable than raw tuples ```typescript // Good export const routes: Routes = { "GET /admin": handler(requireAuth(), requireRoles("admin"), getAdmin), }; ``` 3. **Export symbols for consumers** - Allow other code to read your metadata ```typescript // auth.ts export const kAuthRequired = Symbol("auth.required"); export function requireAuth(): RouteMetaDescriptor { return [kAuthRequired, true]; } ``` 4. **Keep descriptors focused** - Single responsibility per descriptor ```typescript // Good - separate concerns app.get("/data", requireAuth(), rateLimit(100), cacheFor("1h"), handler); // Avoid - mixing concerns app.get("/data", authAndRateLimitAndCache(), handler); ``` 5. **Use module-level for common metadata** - Route-level for exceptions ```typescript const kPublic = Symbol("public"); export const meta: Meta = { plugins: [descriptor(requireAuth())], // Default: auth required }; export const routes: Routes = { "GET /public": handler([kPublic, true], getPublic), // Exception: public "GET /private": getPrivate, // Uses module default }; ``` ## See Also * [Plugins - Descriptor](/core-concepts/plugins#route-metadata-with-descriptor) * [Hooks](/guides/hooks) * [OpenAPI Generation](/packages/openapi) * [Schema Validation](/packages/schema) --- --- url: /plugins/route-logger.md --- # Route Logger The Route Logger is a development utility that provides a clear overview of all registered routes in your application. When the server starts, it prints a formatted, color-coded tree of all endpoints to the console. This is incredibly useful for debugging and for quickly understanding the overall structure of your API. ## Usage The route logger is **automatically enabled by default**. No configuration is required to see your route tree on startup. When you start your application, you will see output similar to this in your console: ``` ┌─ / │ ├─ / (GET) │ └─ /hello/:name (GET) └─ /api └─ /users (GET) ``` ## Configuration You can customize or disable the route logger by re-registering it in your root module's `meta.plugins`. ### `enabled` Disables the route logger completely when set to `false`. * **Type**: `boolean` * **Default**: `true` ::: code-group ```typescript [src/module.ts] import { routeLogger } from "@minimajs/server/plugins"; import { type Meta } from "@minimajs/server"; export const meta: Meta = { plugins: [ routeLogger({ enabled: false }), ], }; ``` ::: ### `logger` Allows you to provide a custom logging function to display the route tree. * **Type**: `(message: string) => void` * **Default**: A function that logs to the console using `app.log.info`. ::: code-group ```typescript [src/module.ts] import { routeLogger } from "@minimajs/server/plugins"; import { type Meta } from "@minimajs/server"; export const meta: Meta = { plugins: [ routeLogger({ logger: (routes) => { console.log("--- Registered Application Routes ---"); console.log(routes); console.log("------------------------------------"); }, }), ], }; ``` ::: ### `commonPrefix` Determines whether to display routes with their full path or with the common prefix removed for a more compact view. * **Type**: `boolean` * **Default**: `false` ::: code-group ```typescript [src/module.ts] import { routeLogger } from "@minimajs/server/plugins"; import { type Meta } from "@minimajs/server"; export const meta: Meta = { plugins: [ routeLogger({ commonPrefix: true }), ], }; ``` ::: --- --- url: /guides/routing.md --- # Routing Routing is the process of defining how your application responds to a client request to a particular endpoint, which is a URI (or path) and a specific HTTP request method (GET, POST, and so on). In Minima.js, you can define routes using the `routes` export in a module file, or programmatically using the application instance. Each route has a handler function that is executed when the route is matched. ## Quick Reference * [`export const routes`](#basic-routing) - Define routes declaratively using the `Routes` type * [`app.get/post/put/delete()`](#programmatic-routing) - Define routes programmatically * [`app.route()`](#programmatic-routing) - Define routes with advanced options * [`params()`](#route-parameters) - Get route parameters * [`searchParams()`](#query-parameters) - Get query string parameters * [Route metadata](#route-metadata) - Attach metadata to routes *** ## Basic Routing The recommended way to define routes is by exporting a `routes` object from a module file. The `Routes` type is a record that maps `" /path"` keys to handler functions. ```typescript import type { Routes } from "@minimajs/server"; function getHome() { return "Hello, World!"; } function createUser() { return { message: "User created" }; } export const routes: Routes = { // GET / "GET /": getHome, // POST /users "POST /users": createUser, }; ``` The key format is `"METHOD /path"`, where `METHOD` is an uppercase HTTP method and `/path` is the route path. ### Programmatic Routing You can also define routes programmatically using the `app.get()`, `app.post()`, `app.put()`, `app.delete()` methods on the application instance. This is useful for standalone app scripts or when you need dynamic route registration. ```typescript import { createApp } from "@minimajs/server"; const app = createApp(); // GET / app.get("/", () => "Hello, World!"); // POST /users app.post("/users", () => ({ message: "User created" })); ``` You can also use the `app.route()` method to define routes with more advanced options: ```typescript app.route({ method: "GET", url: "/", handler: () => "Hello, World!", }); ``` ### Available Methods Minima.js supports all the standard HTTP methods. **Routes key format:** * `"GET /path"` - GET requests * `"POST /path"` - POST requests * `"PUT /path"` - PUT requests * `"PATCH /path"` - PATCH requests * `"DELETE /path"` - DELETE requests * `"HEAD /path"` - HEAD requests * `"OPTIONS /path"` - OPTIONS requests * `"ALL /path"` - matches all methods **Programmatic app methods:** * `app.get(path, handler)` * `app.post(path, handler)` * `app.put(path, handler)` * `app.patch(path, handler)` * `app.delete(path, handler)` * `app.head(path, handler)` * `app.options(path, handler)` * `app.all(path, handler)` (matches all methods) ## Route Parameters Route parameters are named URL segments that are used to capture the values specified at their position in the URL. The captured values are populated in the `params` object, which can be accessed from the `@minimajs/server` package. ```typescript import type { Routes } from "@minimajs/server"; import { params } from "@minimajs/server"; function getUser() { const { id } = params<{ id: string }>(); return { id }; } export const routes: Routes = { // GET /users/123 "GET /users/:id": getUser, }; ``` You can define multiple parameters in a single route: ```typescript import type { Routes } from "@minimajs/server"; import { params } from "@minimajs/server"; function getPost() { const { userId, postId } = params<{ userId: string; postId: string }>(); return { userId, postId }; } export const routes: Routes = { // GET /users/123/posts/456 "GET /users/:userId/posts/:postId": getPost, }; ``` ### Optional Parameters You can make a route parameter optional by adding a question mark (`?`) to the end of its name. ```typescript import type { Routes } from "@minimajs/server"; import { params } from "@minimajs/server"; function getUser() { const { id } = params<{ id?: string }>(); return { id: id || "No ID provided" }; } export const routes: Routes = { // GET /users/123 or /users "GET /users/:id?": getUser, }; ``` ## Wildcards Wildcards (`*`) can be used to match any character in a URL segment. ```typescript import type { Routes } from "@minimajs/server"; import { params } from "@minimajs/server"; function getWildcard() { const wildcard = params.get("*"); return { wildcard }; } export const routes: Routes = { // Matches /posts/foo, /posts/bar, etc. "GET /posts/*": getWildcard, }; ``` ## Regular Expressions You can also use regular expressions to define routes. This is useful for more advanced matching scenarios. ```typescript import type { Routes } from "@minimajs/server"; import { params } from "@minimajs/server"; function getFile() { const { file } = params<{ file: string }>(); return { file }; // { file: '123' } } export const routes: Routes = { // Matches /files/123.png "GET /files/:file(^\\d+).png": getFile, }; ``` ## Route Metadata Minima.js allows you to attach custom metadata to your routes. This is a powerful feature for adding route-specific configuration, flags, or contextual information that can be accessed by handlers, hooks, or plugins. Metadata is passed as `[key, value]` tuples directly in the route definition, before the final handler function. It's recommended to use `Symbol`s as keys for your metadata to avoid potential name collisions. **Defining Metadata with the `routes` export:** When using the `routes` object, you can attach metadata using the `handler()` function. This function takes any number of descriptors (metadata tuples or functions) and a final handler callback. ```typescript import { handler, type Routes } from "@minimajs/server"; // Define custom symbols for metadata keys const kAuthRequired = Symbol("AuthRequired"); const kPermissions = Symbol("Permissions"); function getAdmin() { return { message: "Welcome, admin!" }; } function createData() { return { message: "Data created" }; } // Wrap handlers with descriptors using the handler() helper const adminHandler = handler([kAuthRequired, true], [kPermissions, ["admin", "moderator"]], getAdmin); const dataHandler = handler([kAuthRequired, false], createData); export const routes: Routes = { "GET /admin": adminHandler, "POST /api/data": dataHandler, }; ``` **Defining Metadata programmatically:** Programmatic methods like `app.get()` and `app.post()` support variadic descriptors passed directly before the handler callback. ```typescript import { createApp } from "@minimajs/server"; const app = createApp(); const kAuthRequired = Symbol("AuthRequired"); const kPermissions = Symbol("Permissions"); // Descriptors are passed between path and handler app.get("/admin", [kAuthRequired, true], [kPermissions, ["admin", "moderator"]], () => { return { message: "Welcome, admin!" }; }); app.post("/api/data", [kAuthRequired, false], () => { return { message: "Data created" }; }); ``` **Accessing Metadata in a Handler:** You can access the metadata for the current route using the `context().route.metadata` object within any handler or any function called within the handler's scope. ```typescript import { context } from "@minimajs/server"; // Assuming kAuthRequired and kPermissions are imported or defined const kAuthRequired = Symbol("AuthRequired"); const kPermissions = Symbol("Permissions"); app.get("/admin-dashboard", [kAuthRequired, true], [kPermissions, ["admin"]], () => { const routeMetadata = context().route.metadata; const authRequired = routeMetadata.get(kAuthRequired); // true const requiredPermissions = routeMetadata.get(kPermissions); // ["admin"] console.log(`Auth Required: ${authRequired}`); console.log(`Required Permissions: ${requiredPermissions}`); return { authRequired, requiredPermissions }; }); ``` **Accessing Metadata in a Hook:** Metadata is especially useful in hooks for implementing cross-cutting concerns dynamically. For instance, an authentication hook can check if a route requires authentication based on its metadata. ```typescript import { app } from "./your-app-instance"; // Your app instance import { hook, context, abort } from "@minimajs/server"; const kAuthRequired = Symbol("AuthRequired"); // Must be the same Symbol instance app.register( hook("request", () => { const routeMetadata = context().route.metadata; const authRequired = routeMetadata[kAuthRequired]; if (authRequired) { // Perform actual authentication check const isAuthenticated = false; // Replace with your auth logic if (!isAuthenticated) { abort("Unauthorized", 401); } } }) ); app.get( "/protected", [kAuthRequired, true], // This route will be checked by the hook () => { return { message: "You accessed a protected route!" }; } ); app.get( "/public", [kAuthRequired, false], // This route will skip the auth check () => { return { message: "This route is public." }; } ); ``` By leveraging route metadata, you can create highly configurable and modular applications, where route-specific behavior can be easily defined and managed without cluttering your main handler logic. ## Structuring Routes with Modules As your application grows, it's a good practice to organize your routes into modules. Each module file can export a `routes` object typed as `Routes`, and the framework will automatically discover and register them. ```typescript // modules/users/index.ts import type { Routes } from "@minimajs/server"; import { params } from "@minimajs/server"; function listUsers() { return "List users"; } function getUser() { const { id } = params<{ id: string }>(); return { id }; } function createUser() { return { message: "User created" }; } export const routes: Routes = { "GET /": listUsers, "GET /:id": getUser, "POST /": createUser, }; ``` To learn more about how to structure your application with modules, please refer to the [Modules](/core-concepts/modules) guide. --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/runHooks/README.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server](../../README.md) / runHooks # runHooks ## Functions | Function | Description | | ------ | ------ | | [error](functions/error.md) | - | | [request](functions/request.md) | - | | [safe](functions/safe.md) | - | | [send](functions/send.md) | - | | [transform](functions/transform.md) | - | --- --- url: /packages/schema.md --- # @minimajs/schema Type-safe request validation for Minima.js powered by [Zod](https://zod.dev/). Validate request bodies, headers, search params, and route params with full TypeScript inference. ## Features * 🔒 **Type-Safe** - Full TypeScript inference from Zod schemas * ⚡ **Runtime Validation** - Catch invalid data before it reaches your handlers * 🎯 **Context-Aware** - Validates and caches data in request context * 🔄 **Async Support** - Built-in async validation for database checks * 📦 **Two APIs** - Simple validators and resource-based validation ## Installation ```bash # Using Bun bun add @minimajs/schema zod # Using npm npm install @minimajs/schema zod ``` ## Two Validation Approaches ### 1. Simple Validators (Recommended for Basic Use) Direct validation functions that parse data immediately: ```ts import { createBody, createHeaders, createSearchParams } from "@minimajs/schema"; import { z } from "zod"; const getUserData = createBody( z.object({ name: z.string(), email: z.string().email(), }) ); app.post("/users", () => { const data = getUserData(); return { created: data }; }); ``` ### 2. Resource API (Advanced - With Route Metadata) Validation integrated with route metadata, validated in `request` hook: ```ts import { createBody, schema, configureSchema } from "@minimajs/schema/resource"; import { z } from "zod"; // Register the schema plugin app.register(configureSchema()); // Create validator const getUserData = createBody( z.object({ name: z.string(), email: z.string().email(), }) ); // Use with schema() descriptor app.post("/users", schema(getUserData), () => { const data = getUserData(); // Already validated in request hook return { created: data }; }); ``` ## API Reference ### Simple Validators #### `createBody(schema)` Validates request body against a Zod schema. ```ts import { createBody } from "@minimajs/schema"; import { z } from "zod"; const getUserData = createBody( z.object({ name: z.string().min(2), email: z.string().email(), age: z.number().int().positive().optional(), }) ); app.post("/users", () => { const data = getUserData(); // data: { name: string; email: string; age?: number } return { created: data }; }); ``` ```ts // Preserve unknown fields const getUserData = createBody(userSchema); ``` #### `createBodyAsync(schema)` Async version for schemas with async refinements: ```ts import { createBodyAsync } from "@minimajs/schema"; import { z } from "zod"; const getUserData = createBodyAsync( z.object({ email: z .string() .email() .refine( async (email) => { const exists = await db.users.exists({ email }); return !exists; }, { message: "Email already taken" } ), name: z.string(), }) ); app.post("/users", async () => { const data = await getUserData(); return { created: data }; }); ``` #### `createHeaders(schema, options?)` Validates request headers: ```ts import { createHeaders } from "@minimajs/schema"; import { z } from "zod"; const getHeaders = createHeaders({ authorization: z.string().startsWith("Bearer "), "content-type": z.literal("application/json"), }); app.post("/protected", () => { const headers = getHeaders(); return { authenticated: true }; }); ``` #### `createHeadersAsync(schema, options?)` Async version for header validation. #### `createSearchParams(schema, options?)` Validates URL search/query parameters: ```ts import { createSearchParams } from "@minimajs/schema"; import { z } from "zod"; const getQuery = createSearchParams({ page: z.string().transform(Number).pipe(z.number().positive()), limit: z.string().transform(Number).pipe(z.number().max(100)), search: z.string().optional(), }); app.get("/users", () => { const query = getQuery(); return { page: query.page, limit: query.limit, users: [], }; }); ``` #### `createSearchParamsAsync(schema, options?)` Async version for search params validation. ### Resource API (Advanced) #### `createBody(schema, options?)` Creates a validator function with metadata for use with `schema()` descriptor: ```ts import { createBody, schema, configureSchema } from "@minimajs/schema/resource"; import { z } from "zod"; app.register(configureSchema()); const getUserData = createBody( z.object({ name: z.string(), email: z.string().email(), }) ); app.post("/users", schema(getUserData), () => { const data = getUserData(); // Already validated return { created: data }; }); ``` #### `createHeaders(schema, options?)` Header validator for resource API. #### `createSearchParams(schema, options?)` Search params validator for resource API. #### `createParams(schema, options?)` Route params validator (resource API only): ```ts import { createParams, schema, configureSchema } from "@minimajs/schema/resource"; import { z } from "zod"; app.register(configureSchema()); const getParams = createParams({ id: z.string().uuid(), }); app.get("/users/:id", schema(getParams), () => { const params = getParams(); return { userId: params.id }; }); ``` #### `schema(...validators)` Route metadata descriptor that attaches validators to a route: ```ts import { schema, createBody, createParams } from "@minimajs/schema/resource"; const getUserData = createBody(userSchema); const getParams = createParams({ id: z.string().uuid() }); app.post("/users/:id", schema(getUserData, getParams), () => { const data = getUserData(); const params = getParams(); return { updated: data }; }); ``` #### `configureSchema()` Plugin that validates all schemas in the `request` hook: ```ts import { configureSchema } from "@minimajs/schema/resource"; app.register(configureSchema()); ``` ## Error Handling ### ValidationError Validation failures throw `ValidationError` (422 status): ```ts import { ValidationError } from "@minimajs/schema"; try { const data = createBody(userSchema); } catch (err) { if (err instanceof ValidationError) { console.log(err.message); // "Validation failed for 'email'" console.log(err.issues); // Zod issues array } } ``` ### Error Response Format ```json { "message": "Validation failed for 'email', 'name'", "issues": [ { "code": "invalid_type", "expected": "string", "received": "undefined", "path": ["email"], "message": "Required" } ] } ``` ### Custom Error Handling ```ts import { hook } from "@minimajs/server"; import { ValidationError } from "@minimajs/schema"; app.register( hook("error", (error) => { if (error instanceof ValidationError) { return { success: false, errors: error.issues?.map((issue) => ({ field: issue.path.join("."), message: issue.message, })), }; } }) ); ``` ## Advanced Examples ### Nested Object Validation ```ts const addressSchema = z.object({ street: z.string(), city: z.string(), zipCode: z.string().regex(/^\d{5}$/), }); const getUserData = createBody( z.object({ name: z.string(), email: z.string().email(), address: addressSchema, alternateAddresses: z.array(addressSchema).optional(), }) ); app.post("/users", () => { const data = getUserData(); return { created: data }; }); ``` ### Cross-Field Validation ```ts const getUserData = createBody( z .object({ password: z.string().min(8), confirmPassword: z.string(), }) .refine((data) => data.password === data.confirmPassword, { message: "Passwords must match", path: ["confirmPassword"], }) ); app.post("/register", () => { const data = getUserData(); return { success: true }; }); ``` ### Database Uniqueness Check ```ts const getUserData = createBodyAsync( z.object({ email: z .string() .email() .refine( async (email) => { const user = await db.users.findOne({ email }); return !user; }, { message: "Email already exists" } ), name: z.string(), }) ); app.post("/users", async () => { const data = await getUserData(); return { created: data }; }); ``` ### Transformations ```ts const getQuery = createSearchParams({ // Transform string to number page: z.string().transform(Number).pipe(z.number().positive()), // Trim whitespace search: z.string().trim().optional(), // Parse date startDate: z .string() .transform((str) => new Date(str)) .pipe(z.date()), // Parse JSON filter: z .string() .transform((str) => JSON.parse(str)) .pipe(z.object({ category: z.string() })), }); app.get("/users", () => { const query = getQuery(); return { page: query.page, // number search: query.search, // string | undefined startDate: query.startDate, // Date filter: query.filter, // { category: string } }; }); ``` ### Discriminated Unions ```ts const getEventData = createBody( z.discriminatedUnion("type", [ z.object({ type: z.literal("user.created"), userId: z.string(), email: z.string().email(), }), z.object({ type: z.literal("user.deleted"), userId: z.string(), }), ]) ); app.post("/webhooks", () => { const event = getEventData(); switch (event.type) { case "user.created": return handleUserCreated(event); case "user.deleted": return handleUserDeleted(event); } }); ``` ### Partial Updates ```ts const userSchema = z.object({ name: z.string(), email: z.string().email(), age: z.number(), }); // Make all fields optional const getUpdates = createBody(userSchema.partial()); app.patch("/users/:id", () => { const updates = getUpdates(); return { updated: updates }; }); ``` ## When to Use Each API ### Simple Validators (`@minimajs/schema`) **Best for:** * Quick validation without route metadata * Simple applications * One-off validators * Direct control over validation timing ```ts import { createBody } from "@minimajs/schema"; ``` ### Resource API (`@minimajs/schema/resource`) **Best for:** * Complex applications with many routes * Consistent validation across routes * OpenAPI/documentation generation * Validation in request hooks (before handler) ```ts import { createBody, schema, configureSchema } from "@minimajs/schema/resource"; ``` ## TypeScript Tips ### Infer Types from Schemas ```ts import { z } from "zod"; const userSchema = z.object({ name: z.string(), email: z.string().email(), }); type User = z.infer; // { name: string; email: string } ``` ### Reusable Schemas ```ts // schemas/user.ts export const userIdSchema = z.string().uuid(); export const createUserSchema = z.object({ name: z.string().min(2), email: z.string().email(), }); export const updateUserSchema = createUserSchema.partial(); export type CreateUser = z.infer; export type UpdateUser = z.infer; ``` ## Related * [Zod Documentation](https://zod.dev/) - Schema validation library * [Minima.js Server](https://minima-js.github.io/) - Web framework * [Validation Guide](https://minima-js.github.io/guides/validation) - Comprehensive validation guide ## License MIT --- --- url: /packages/multipart/schema.md --- # Multipart Schema Validation Type-safe multipart form data parsing with Zod schema validation. Files are automatically saved to disk as `TempFile` instances (memory-efficient), while text fields are validated according to your schema. ## Installation ```bash npm install @minimajs/multipart zod ``` ## Why Use Schema Validation? * ✅ **Full TypeScript inference** - Types flow automatically from your schema * ✅ **Automatic validation** - File size, MIME type, and field validation * ✅ **Memory efficient** - Files saved to disk, not held in memory * ✅ **Native File API** - Compatible with Web `File` interface * ✅ **Direct response** - Return files directly with correct content-type * ✅ **Better errors** - Clear validation error messages ### Return Files Directly `TempFile` extends the native `File` API, so you can return it directly from handlers: ```typescript const upload = createMultipart({ avatar: z.file().mime(["image/jpeg", "image/png"]), }); export async function getAvatar() { const data = await upload(); return data.avatar; // Returns file with correct Content-Type header } ``` ## Quick Start ### Basic File Upload with Validation ```typescript import { z } from "zod"; import { createMultipart } from "@minimajs/multipart/schema"; import { helpers } from "@minimajs/multipart"; const upload = createMultipart({ name: z.string().min(3).max(30), email: z.string().email(), avatar: z.file().max(2 * 1024 * 1024), // 2MB max }); export async function handleUpload() { const data = await upload(); // TypeScript knows the exact types! console.log(data.name); // string console.log(data.email); // string console.log(data.avatar); // TempFile // Move file to destination await helpers.save(data.avatar, "./uploads/avatars"); return { success: true, user: data.name }; } ``` ## API Reference ### `createMultipart(schema, options?)` Creates a type-safe multipart parser with Zod validation. **Parameters:** * `schema` - Zod schema object (`z.ZodRawShape`) * `options` - Optional upload configuration **Returns:** Async function that parses and validates multipart data **Throws:** `ValidationError` when validation fails ## File Validation ### File Size Validation Use `.max()` and `.min()` to validate file sizes. ```typescript import { z } from "zod"; import { createMultipart } from "@minimajs/multipart/schema"; const upload = createMultipart({ avatar: z .file() .min(1024) // Min 1KB .max(5 * 1024 * 1024), // Max 5MB }); ``` ### MIME Type Validation Use `.mime()` to validate file types. ```typescript const upload = createMultipart({ avatar: z .file() .max(2 * 1024 * 1024) .mime(["image/jpeg", "image/png", "image/webp"]), }); ``` All [Zod file validations](https://zod.dev/api?id=files) are supported. ## Multiple Files ### Array of Files Use `z.array()` to handle multiple files. ```typescript import { z } from "zod"; import { createMultipart } from "@minimajs/multipart/schema"; import { helpers } from "@minimajs/multipart"; const upload = createMultipart({ email: z.string().email(), photos: z .array(z.file().max(5 * 1024 * 1024)) .min(1) // At least 1 photo .max(10), // Max 10 photos }); export async function handleGallery() { const data = await upload(); // Process each photo for (const photo of data.photos) { await helpers.save(photo, "./uploads/gallery"); } return { count: data.photos.length }; } ``` ### TempFile Methods ```typescript // Read as buffer const buffer = await file.arrayBuffer(); // Read as text const text = await file.text(); // Read as bytes const bytes = await file.bytes(); // Get readable stream (Web Streams API) const stream = file.stream(); // Get Node.js readable stream const nodeStream = file.toReadable(); // Load into memory as standard File const memoryFile = await file.toFile(); // Cleanup (delete temp file) await file.destroy(); ``` ### Moving Files Use `helpers.save()` to save files to their final destination. ```typescript import { helpers } from "@minimajs/multipart"; const data = await upload(); // Auto-generated filename with UUID const savedName = await helpers.save(data.avatar, "./uploads"); console.log(savedName); // e.g., "a1b2c3d4-e5f6.jpg" // Custom filename await helpers.save(data.avatar, "./uploads", "profile.jpg"); ``` ## Advanced Examples ### Complete User Profile Upload ```typescript import { z } from "zod"; import { createMultipart } from "@minimajs/multipart/schema"; import { helpers } from "@minimajs/multipart"; const profileUpload = createMultipart({ // Text fields username: z.string().min(3).max(20), email: z.string().email(), bio: z.string().max(500).optional(), // File fields avatar: z .file() .max(2 * 1024 * 1024) .mime(["image/jpeg", "image/png"]), coverPhoto: z .file() .max(5 * 1024 * 1024) .mime(["image/jpeg", "image/png"]) .optional(), }); export async function updateProfile() { const data = await profileUpload(); // Save avatar const avatarPath = await helpers.save(data.avatar, "./uploads/avatars"); // Save cover photo if provided let coverPath; if (data.coverPhoto) { coverPath = await helpers.save(data.coverPhoto, "./uploads/covers"); } return { username: data.username, email: data.email, bio: data.bio, avatarUrl: `/uploads/avatars/${avatarPath}`, coverUrl: coverPath ? `/uploads/covers/${coverPath}` : null, }; } ``` ## Upload Configuration ### Custom Options Pass configuration options as the second parameter. ```typescript import type { UploadOption } from "@minimajs/multipart/schema"; const options: UploadOption = { limits: { fileSize: 10 * 1024 * 1024, // 10MB max per file files: 5, // Max 5 files total fields: 10, // Max 10 text fields }, }; const upload = createMultipart(schema, options); ``` ## Error Handling The schema validation throws `ValidationError` when validation fails. ```typescript import { ValidationError } from "@minimajs/multipart/schema"; export async function handleUpload() { try { const data = await upload(); return { success: true, data }; } catch (error) { if (error instanceof ValidationError) { // Handle validation errors return { success: false, errors: error.errors, // Array of validation errors }; } throw error; } } ``` ## Type Safety TypeScript automatically infers types from your schema. ```typescript const upload = createMultipart({ name: z.string(), age: z.number(), avatar: z.file(), photos: z.array(z.file()).optional(), }); const data = await upload(); // TypeScript knows: // data.name is string // data.age is number // data.avatar is TempFile // data.photos is TempFile[] | undefined ``` ## Cleanup `TempFile` instances are stored on disk. They are **automatically cleaned up** after the request completes via Minima's `defer()` mechanism. ## Next Steps * [Basic Multipart API](./index) - Lower-level multipart handling --- --- url: /api/@minimajs/server/@minimajs/server/namespaces/searchParams/README.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server](../../README.md) / searchParams # searchParams Utility functions for working with URL search parameters (query string) ## Functions | Function | Description | | ------ | ------ | | [get](functions/get.md) | Retrieves a single search param by name with optional transformation. Throws ValidationError if the param is not found. | | [getAll](functions/getAll.md) | Retrieves all values for a search param by name with optional transformation. Returns an empty array if the param is not found. | --- --- url: /api/@minimajs/multipart/@minimajs/multipart/namespaces/streaming/README.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/multipart](../../../../README.md) / [@minimajs/multipart](../../README.md) / streaming # streaming ## Classes | Class | Description | | ------ | ------ | | [StreamFile](classes/StreamFile.md) | A File subclass that lazily buffers from a stream on first read. | ## Interfaces | Interface | Description | | ------ | ------ | | [StreamFileInit](interfaces/StreamFileInit.md) | - | ## Functions | Function | Description | | ------ | ------ | | [body](functions/body.md) | Iterates over all multipart fields, yielding files as StreamFiles and text fields as strings. | | [file](functions/file.md) | Retrieves a specific file field by name as a StreamFile (lazy streaming, not buffered). | | [firstFile](functions/firstFile.md) | Retrieves the first file field as a StreamFile with its field name. | --- --- url: /guides/testing.md --- title: Testing sidebar\_position: 8 tags: * testing * unit-tests * integration-tests # Testing Minima.js is built with testability in mind. This guide covers testing strategies for your Minima.js applications using popular testing frameworks. ## Quick Reference * [Setup](#setup) - Configure your testing environment * [Unit Testing](#unit-testing) - Test individual handlers and functions * [Integration Testing](#integration-testing) - Test full request/response cycles * [Testing Hooks](#testing-hooks) - Test lifecycle hooks * [Testing Plugins](#testing-plugins) - Test custom plugins * [Mocking](#mocking) - Mock dependencies and context * [Best Practices](#best-practices) - Testing recommendations ## Setup ### With Bun Bun includes a built-in test runner: ```bash bun test ``` **Example test file** (`app.test.ts`): ```ts import { describe, test, expect } from "bun:test"; import { createApp } from "@minimajs/server/bun"; describe("App", () => { test("GET /health returns 200", async () => { const app = createApp(); app.get("/health", () => ({ status: "ok" })); const response = await app.handle(new Request("http://localhost/health")); expect(response.status).toBe(200); const data = await response.json(); expect(data).toEqual({ status: "ok" }); }); }); ``` > **Tip:** Use `createRequest()` from `@minimajs/server/mock` for cleaner test code, or use native `new Request()` for more control. ### With Jest/Vitest **Install dependencies:** ```bash npm install --save-dev vitest # or npm install --save-dev jest @types/jest ``` **Configure** (`vitest.config.ts`): ```ts import { defineConfig } from "vitest/config"; export default defineConfig({ test: { globals: true, environment: "node", }, }); ``` ## Unit Testing Test individual handlers in isolation. ### Testing Route Handlers ::: code-group ```ts [Bun] import { describe, test, expect } from "bun:test"; import { createApp } from "@minimajs/server/bun"; import { createRequest } from "@minimajs/server/mock"; import { params, body } from "@minimajs/server"; describe("User Routes", () => { test("GET /users/:id returns user", async () => { const app = createApp(); app.get("/users/:id", () => { const id = params.get("id"); return { id, name: "Alice" }; }); const response = await app.handle(createRequest("/users/123")); expect(response.status).toBe(200); const data = await response.json(); expect(data).toEqual({ id: "123", name: "Alice" }); }); test("POST /users creates user", async () => { const app = createApp(); app.post("/users", () => { const userData = body(); return { id: "456", ...userData }; }); const response = await app.handle( createRequest("/users", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name: "Bob" }), }) ); expect(response.status).toBe(200); const data = await response.json(); expect(data).toEqual({ id: "456", name: "Bob" }); }); }); ``` ```ts [Jest/Vitest] import { describe, test, expect } from "vitest"; // or @jest/globals import { createApp } from "@minimajs/server/node"; import { createRequest } from "@minimajs/server/mock"; import { params, body } from "@minimajs/server"; describe("User Routes", () => { test("GET /users/:id returns user", async () => { const app = createApp(); app.get("/users/:id", () => { const id = params.get("id"); return { id, name: "Alice" }; }); const response = await app.handle(createRequest("/users/123")); expect(response.status).toBe(200); const data = await response.json(); expect(data).toEqual({ id: "123", name: "Alice" }); }); // ... other tests }); ``` ::: > **Alternative:** You can also use native `new Request("http://localhost/path", options)` if you need more control over the request object. ### Testing with Query Parameters ```ts import { createApp } from "@minimajs/server/bun"; import { createRequest } from "@minimajs/server/mock"; import { searchParams } from "@minimajs/server"; test("GET /search with query params", async () => { const app = createApp(); app.get("/search", () => { const params = searchParams(); const query = params.get("q"); return { results: [], query }; }); const response = await app.handle(createRequest("/search?q=test")); const data = await response.json(); expect(data.query).toBe("test"); }); ``` ### Testing Headers ```ts import { createApp } from "@minimajs/server/bun"; import { createRequest } from "@minimajs/server/mock"; import { headers, response } from "@minimajs/server"; test("requires authorization header", async () => { const app = createApp(); app.get("/protected", () => { const auth = headers().get("authorization"); if (!auth) { response.status(401); return { error: "Unauthorized" }; } return { data: "secret" }; }); // Without auth const res1 = await app.handle(createRequest("/protected")); expect(res1.status).toBe(401); // With auth const res2 = await app.handle( createRequest("/protected", { headers: { Authorization: "Bearer token" }, }) ); expect(res2.status).toBe(200); }); ``` ## Integration Testing Test the full application with plugins and middleware. ### Testing with Plugins ```ts import { createRequest } from "@minimajs/server/mock"; import { bodyParser } from "@minimajs/server/plugins"; test("full app with plugins", async () => { const app = createApp(); app.register(bodyParser()); app.post("/data", () => { const data = body(); return { received: data }; }); const response = await app.handle( createRequest("/data", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ value: 42 }), }) ); const result = await response.json(); expect(result.received).toEqual({ value: 42 }); }); ``` ### Testing Module Encapsulation ```ts import { createRequest } from "@minimajs/server/mock"; test("module routes are isolated", async () => { const app = createApp(); app.register( async (adminApp) => { adminApp.get("/users", () => ({ users: [] })); }, { prefix: "/admin" } ); app.register( async (apiApp) => { apiApp.get("/users", () => ({ data: [] })); }, { prefix: "/api" } ); // Test admin module const res1 = await app.handle(createRequest("/admin/users")); const data1 = await res1.json(); expect(data1).toHaveProperty("users"); // Test api module const res2 = await app.handle(createRequest("/api/users")); const data2 = await res2.json(); expect(data2).toHaveProperty("data"); }); ``` ## Testing Hooks ### Testing Request Hooks ```ts import { createRequest } from "@minimajs/server/mock"; import { hook, createContext } from "@minimajs/server"; test("request hook modifies context", async () => { const app = createApp(); const [getRequestId, setRequestId] = createContext(); app.register( hook("request", () => { setRequestId("test-123"); }) ); app.get("/", () => { const requestId = getRequestId(); return { requestId }; }); const response = await app.handle(createRequest("/")); const data = await response.json(); expect(data.requestId).toBe("test-123"); }); ``` ### Testing Transform Hooks ```ts import { createRequest } from "@minimajs/server/mock"; test("transform hook wraps response", async () => { const app = createApp(); app.register( hook("transform", (data) => { return { success: true, data }; }) ); app.get("/users", () => [{ id: 1 }]); const response = await app.handle(createRequest("/users")); const data = await response.json(); expect(data).toEqual({ success: true, data: [{ id: 1 }], }); }); ``` ### Testing Send Hooks ```ts import { createRequest } from "@minimajs/server/mock"; test("send hook adds custom header", async () => { const app = createApp(); app.register( hook("send", (ctx) => { return response("hello world", { headers: { "X-Custom": "value" }, }); }) ); app.get("/", () => "ok"); const response = await app.handle(createRequest("/")); expect(response.headers.get("X-Custom")).toBe("value"); }); ``` ## Testing Plugins ### Testing Custom Plugins ```ts import { createRequest } from "@minimajs/server/mock"; import { plugin } from "@minimajs/server"; const myPlugin = (options) => { return app.register( hook("request", () => { context.set("pluginData", options.value); }) ); }; test("custom plugin sets context", async () => { const app = createApp(); app.register(myPlugin({ value: "test" })); app.get("/", () => { return { data: context.get("pluginData") }; }); const response = await app.handle(createRequest("/")); const data = await response.json(); expect(data.data).toBe("test"); }); ``` ## Mocking ### Mocking External Services ```ts import { createRequest } from "@minimajs/server/mock"; import { mock } from "bun:test"; test("mocked database query", async () => { const mockDb = { query: mock(() => Promise.resolve([{ id: 1, name: "Alice" }])), }; const app = createApp(); app.get("/users", async () => { const users = await mockDb.query(); return users; }); const response = await app.handle(createRequest("/users")); const data = await response.json(); expect(mockDb.query).toHaveBeenCalled(); expect(data).toHaveLength(1); }); ``` ### Mocking Context Values ```ts import { createRequest } from "@minimajs/server/mock"; import { createContext } from "@minimajs/server"; test("mock context for testing", async () => { const app = createApp(); const [getUserId, setUserId] = createContext(); // Set up context in request hook app.register( hook("request", () => { setUserId("mock-user-123"); }) ); app.get("/profile", () => { const userId = setUserId(); return { userId }; }); const response = await app.handle(createRequest("/profile")); const data = await response.json(); expect(data.userId).toBe("mock-user-123"); }); ``` ## Best Practices ### 1. Test in Isolation Create a fresh app instance for each test: ```ts import { beforeEach } from "bun:test"; describe("User API", () => { let app; beforeEach(() => { app = createApp(); // Setup routes app.get("/users", () => []); }); test("test 1", async () => { // app is fresh }); test("test 2", async () => { // app is fresh again }); }); ``` ### 2. Use Helper Functions ```ts // test-helpers.ts import { createRequest } from "@minimajs/server/mock"; export async function makeRequest(app: App, path: string, options?: RequestInit) { const response = await app.handle(createRequest(path, options)); const data = await response.json(); return { response, data }; } // In tests test("using helper", async () => { const app = createApp(); app.get("/", () => ({ ok: true })); const { response, data } = await makeRequest(app, "/"); expect(data.ok).toBe(true); }); ``` ### 3. Test Error Cases ```ts import { createRequest } from "@minimajs/server/mock"; test("handles errors gracefully", async () => { const app = createApp(); app.get("/error", () => { throw new Error("Something went wrong"); }); const response = await app.handle(createRequest("/error")); expect(response.status).toBe(500); }); ``` ### 4. Test Edge Cases ```ts import { createRequest } from "@minimajs/server/mock"; describe("Edge cases", () => { test("handles missing parameters", async () => { const app = createApp(); app.get("/users/:id", () => { const id = params.get("id"); if (!id) { response.status(400); return { error: "ID required" }; } return { id }; }); const response = await app.handle(createRequest("/users/")); expect(response.status).toBe(404); // Route doesn't match }); test("handles malformed JSON", async () => { const app = createApp(); app.register(bodyParser()); app.post("/data", () => { try { const data = body(); return data; } catch (error) { response.status(400); return { error: "Invalid JSON" }; } }); const response = await app.handle( createRequest("/data", { method: "POST", headers: { "Content-Type": "application/json" }, body: "{ invalid json }", }) ); expect(response.status).toBe(400); }); }); ``` ### 5. Coverage Goals Aim for good coverage of: * ✅ Happy paths (expected inputs) * ✅ Error paths (invalid inputs, exceptions) * ✅ Edge cases (boundaries, empty values) * ✅ Integration points (plugins, hooks) ## Related Guides * [Error Handling](/guides/error-handling) - Testing error scenarios * [Hooks](/guides/hooks) - Understanding lifecycle hooks * [Plugins](/core-concepts/plugins) - Creating testable plugins --- --- url: /tutorials/task-board-api/presentation-playbook.md --- # Tutorial Presentation Playbook Use this when you need to present Minima.js to developers quickly and clearly. ## 30-Second Pitch Minima.js is a backend framework focused on fast iteration with strong structure: * modular architecture by default (`module.ts` discovery) * low boilerplate route wiring (`routes: Routes`) * first-class runtime hooks for request, error, and lifespan behavior * composable plugins for auth, CORS, OpenAPI, and operations ## 5-Minute Live Demo Flow 1. Show `src/module.ts` Explain: global plugins + one place for app-wide behavior. 2. Show `src/workspaces/module.ts` Explain: handlers + routes + guards in one module. 3. Run auth flow `POST /auth/register` then `POST /auth/login`. 4. Run protected route `GET /workspaces` with and without `Authorization` header. 5. Trigger controlled error `GET /workspaces/999` and show consistent error JSON. 6. Open generated spec `GET /openapi.json` to show docs are code-driven. ## What Developers Usually Ask ### “How much boilerplate do I need?” Very little. Most features can be built by adding a module folder with `module.ts`, `meta`, and `routes`. ### “Can I enforce organization-wide behavior?” Yes. Put it in root `meta.plugins` (`hook("request")`, `hook("error")`, CORS, shutdown, etc.). ### “How do nested resources work?” Use `meta.prefix` for dynamic/nested paths like `/workspaces/:workspaceId/boards`. ### “How do I keep auth and permissions clean?” Use composable guards (`authenticated`, `workspaceMember`, `workspaceAdmin`, `boardMember`) and run them at module or handler scope. ## Talking Points That Land Well * “Folder structure is API structure unless you override with `meta.prefix`.” * “No controller ceremony required; route map is explicit and type-safe.” * “Hooks let you keep cross-cutting concerns out of business logic.” * “Error shape can be standardized in one place (`HttpError.toJSON`).” ## Recommended Demo Commands ::: code-group ```bash [Terminal] # login curl -X POST http://localhost:3000/auth/login \ -H "Content-Type: application/json" \ -d '{"email":"alice@example.com","password":"secret123"}' # protected route curl http://localhost:3000/workspaces \ -H "Authorization: Bearer " # docs curl http://localhost:3000/openapi.json | head ``` ::: ## Mistakes to Avoid While Presenting * Leading with abstractions before showing one real module. * Showing too many files before the first successful request. * Skipping failure cases; error behavior is one of the strongest trust signals. --- --- url: /tutorials/task-board-api.md --- # Tutorial: Build a Task Board API Build a production-style Task Board API (Trello/Linear-style backend) from zero to deployment-ready structure using Minima.js. By the end, you will have: * JWT auth (access + refresh) * Multi-workspace access control * Nested boards/tasks routes * File uploads for task attachments * Consistent API error format * OpenAPI docs and graceful shutdown ## Why This Tutorial Is Structured This Way This tutorial follows a strict **copy → run → verify** loop: 1. Add code for one capability. 2. Run a smoke check. 3. Move to the next capability. Each step has a clear outcome so you always know what “done” means before continuing. ## What You’ll Learn (Framework Coverage) | Feature | Where it appears | |---|---| | File-based module discovery | All modules | | `meta.prefix` for nested resources | Boards + Tasks | | `@minimajs/auth` | Auth plugin and guards | | `@minimajs/cookie` | Refresh token cookie | | `@minimajs/schema` + Zod | Body + query validation | | `@minimajs/multipart` | Attachment uploads | | Prisma integration | All data access | | `hook.lifespan` | DB connect/disconnect | | `hook("request")` | Logging + route guards | | `hook("error")` | Centralized error behavior | | `abort.*` helpers | Typed HTTP failures | | `cors` + `shutdown` | Production runtime basics | | `routes: Routes` map | Handler wiring per module | ## Final Project Structure ::: code-group ```text [Project Tree] task-board/ ├── src/ │ ├── index.ts # Entry + error serializers │ ├── module.ts # Global plugins │ ├── database.ts # Prisma + lifespan hook │ ├── auth/ │ │ ├── index.ts # createAuth + token helpers │ │ ├── guards.ts # authenticated/workspaceMember/boardMember/workspaceAdmin │ │ └── module.ts # /auth routes │ ├── workspaces/ │ │ └── module.ts │ ├── boards/ │ │ └── module.ts │ ├── tasks/ │ │ └── module.ts │ └── members/ │ └── module.ts ├── prisma/ │ └── schema.prisma └── package.json ``` ::: ## Prerequisites * TypeScript basics * REST API basics * Node.js 20+ No prior Minima.js experience required. ## Steps 1. **[Project Setup](./01-setup.md)**: bootstrap app + Prisma schema 2. **[Database & Root Module](./02-database.md)**: lifespan hook + global plugins 3. **[Authentication](./03-auth.md)**: access/refresh flow + guards 4. **[Workspaces](./04-workspaces.md)**: first protected resource CRUD 5. **[Boards & Tasks](./05-boards-tasks.md)**: nested routes + uploads + pagination 6. **[Members & Roles](./06-members.md)**: role-based authorization 7. **[Error Handling & Polish](./07-errors-polish.md)**: uniform error shape + operational polish ## Working Method (Recommended) * Keep one terminal running `npm run dev`. * Keep one terminal for `curl` checks. * After each step, run the step’s smoke test before continuing. ## Need To Present Minima.js? Use the companion guide: [Tutorial Presentation Playbook](./presentation-playbook.md) Start here: [Project Setup](./01-setup.md) --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/ApiKeySecurityScheme.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / ApiKeySecurityScheme # Type Alias: ApiKeySecurityScheme ```ts type ApiKeySecurityScheme = OpenAPIV3.ApiKeySecurityScheme; ``` --- --- url: >- /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/ArraySchemaObjectType.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / ArraySchemaObjectType # Type Alias: ArraySchemaObjectType ```ts type ArraySchemaObjectType = OpenAPIV3.ArraySchemaObjectType; ``` --- --- url: /api/@minimajs/auth/type-aliases/AuthCallback.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/auth](../README.md) / AuthCallback # Type Alias: AuthCallback()\ ```ts type AuthCallback = () => Promise | T; ``` ## Type Parameters ### T `T` ## Returns `Promise`<`T`> | `T` --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/BaseSchemaObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / BaseSchemaObject # Type Alias: BaseSchemaObject ```ts type BaseSchemaObject = Modify, { $schema?: string; additionalProperties?: | boolean | ReferenceObject | SchemaObject; allOf?: ( | ReferenceObject | SchemaObject)[]; anyOf?: ( | ReferenceObject | SchemaObject)[]; const?: any; contentMediaType?: string; discriminator?: DiscriminatorObject; examples?: OpenAPIV3.BaseSchemaObject["example"][]; exclusiveMaximum?: boolean | number; exclusiveMinimum?: boolean | number; externalDocs?: ExternalDocumentationObject; not?: | ReferenceObject | SchemaObject; oneOf?: ( | ReferenceObject | SchemaObject)[]; properties?: { [name: string]: | ReferenceObject | SchemaObject; }; xml?: XMLObject; }>; ``` --- --- url: /api/@minimajs/server/@minimajs/server/plugins/type-aliases/BodyParserType.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / BodyParserType # Type Alias: BodyParserType ```ts type BodyParserType = "json" | "text" | "form" | "arrayBuffer" | "blob"; ``` --- --- url: /api/@minimajs/server/@minimajs/server/bun/type-aliases/BunServeOptions.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/bun](../README.md) / BunServeOptions # Type Alias: BunServeOptions\ ```ts type BunServeOptions = Omit, "fetch" | "port" | "hostname">; ``` ## Type Parameters ### T `T` = `unknown` --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/CallbackObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / CallbackObject # Type Alias: CallbackObject ```ts type CallbackObject = Record; ``` --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/ComponentsObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / ComponentsObject # Type Alias: ComponentsObject ```ts type ComponentsObject = Modify; examples?: Record; headers?: Record; links?: Record; parameters?: Record; pathItems?: Record; requestBodies?: Record; responses?: Record; schemas?: Record; securitySchemes?: Record; }>; ``` --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/ContactObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / ContactObject # Type Alias: ContactObject ```ts type ContactObject = OpenAPIV3.ContactObject; ``` --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/Container.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / Container # Type Alias: Container\ ```ts type Container = { [key: symbol]: unknown; [kAppDescriptor]: RouteMetaDescriptor[]; [kHooks]: HookStore; [kMiddlewares]: Set>; [kModulesChain]: App[]; $rootMiddleware: Middleware; }; ``` ## Type Parameters ### S `S` = `unknown` ## Indexable ```ts [key: symbol]: unknown ``` ## Properties ### \[kAppDescriptor] ```ts [kAppDescriptor]: RouteMetaDescriptor[]; ``` *** ### \[kHooks] ```ts [kHooks]: HookStore; ``` *** ### \[kMiddlewares] ```ts [kMiddlewares]: Set>; ``` *** ### \[kModulesChain] ```ts [kModulesChain]: App[]; ``` *** ### $rootMiddleware ```ts $rootMiddleware: Middleware; ``` --- --- url: /api/@minimajs/server/@minimajs/server/plugins/type-aliases/DeferCallback.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / DeferCallback # Type Alias: DeferCallback() ```ts type DeferCallback = (response) => void | Promise; ``` ## Parameters ### response `Response` ## Returns `void` | `Promise`<`void`> --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/helpers/type-aliases/Dict.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [helpers](../README.md) / Dict # Type Alias: Dict\ ```ts type Dict = NodeJS.Dict; ``` Generic dictionary type alias for objects with optional properties. ## Type Parameters ### T `T` = `any` The type of values in the dictionary --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/Dict.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / Dict # Type Alias: Dict\ ```ts type Dict = NodeJS.Dict; ``` ## Type Parameters ### T `T` = `unknown` --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/DiscriminatorObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / DiscriminatorObject # Type Alias: DiscriminatorObject ```ts type DiscriminatorObject = OpenAPIV3.DiscriminatorObject; ``` --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/Document.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / Document # Type Alias: Document\ ```ts type Document = Modify, "paths" | "components">, { info: InfoObject; jsonSchemaDialect?: string; servers?: ServerObject[]; } & | Pick, "paths"> & Omit>, "paths"> | Pick, "webhooks"> & Omit>, "webhooks"> | Pick, "components"> & Omit>, "components">>; ``` ## Type Parameters ### T `T` *extends* { } = { } --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/EncodingObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / EncodingObject # Type Alias: EncodingObject ```ts type EncodingObject = OpenAPIV3.EncodingObject; ``` --- --- url: /api/@minimajs/server/@minimajs/server/plugins/type-aliases/ErrorCallback.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / ErrorCallback # Type Alias: ErrorCallback() ```ts type ErrorCallback = (response) => void | Promise; ``` ## Parameters ### response `Response` ## Returns `void` | `Promise`<`void`> --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/ErrorHandler.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / ErrorHandler # Type Alias: ErrorHandler()\ ```ts type ErrorHandler = (error, ctx) => Response | Promise; ``` ## Type Parameters ### S `S` = `unknown` ## Parameters ### error `unknown` ### ctx [`Context`](../interfaces/Context.md)<`S`> ## Returns `Response` | `Promise`<`Response`> --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/ExampleObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / ExampleObject # Type Alias: ExampleObject ```ts type ExampleObject = OpenAPIV3.ExampleObject; ``` --- --- url: /api/@minimajs/server/@minimajs/server/plugins/type-aliases/ExpressCallback.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / ExpressCallback # Type Alias: ExpressCallback() ```ts type ExpressCallback = (req, res, next) => void; ``` ## Parameters ### req `IncomingMessage` ### res `ServerResponse` ### next (`err?`) => `void` ## Returns `void` --- --- url: >- /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/ExternalDocumentationObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / ExternalDocumentationObject # Type Alias: ExternalDocumentationObject ```ts type ExternalDocumentationObject = OpenAPIV3.ExternalDocumentationObject; ``` --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/GenericCallback.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / GenericCallback # Type Alias: GenericCallback() ```ts type GenericCallback = (...args) => any; ``` ## Parameters ### args ...`any`\[] ## Returns `any` --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/GenericHookCallback.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / GenericHookCallback # Type Alias: GenericHookCallback() ```ts type GenericHookCallback = (...args) => any | Promise; ``` ## Parameters ### args ...`any`\[] ## Returns `any` | `Promise`<`any`> --- --- url: /api/@minimajs/auth/type-aliases/GuardCallback.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/auth](../README.md) / GuardCallback # Type Alias: GuardCallback()\ ```ts type GuardCallback = (data?, error?) => Promise | boolean; ``` ## Type Parameters ### T `T` ## Parameters ### data? `T` ### error? [`BaseHttpError`](../../server/@minimajs/server/error/classes/BaseHttpError.md) ## Returns `Promise`<`boolean`> | `boolean` --- --- url: /api/@minimajs/auth/type-aliases/GuardMessageCallback.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/auth](../README.md) / GuardMessageCallback # Type Alias: GuardMessageCallback() ```ts type GuardMessageCallback = (error?) => string; ``` ## Parameters ### error? [`BaseHttpError`](../../server/@minimajs/server/error/classes/BaseHttpError.md) ## Returns `string` --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/Handler.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / Handler # Type Alias: Handler\ ```ts type Handler = (ctx) => unknown & { [kHandlerDescriptor]?: RouteMetaDescriptor[]; }; ``` ## Type Declaration ### \[kHandlerDescriptor]? ```ts optional [kHandlerDescriptor]: RouteMetaDescriptor[]; ``` ## Type Parameters ### S `S` = `unknown` --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/HeaderObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / HeaderObject # Type Alias: HeaderObject ```ts type HeaderObject = OpenAPIV3.HeaderObject; ``` --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/HeadersInit.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / HeadersInit # Type Alias: HeadersInit ```ts type HeadersInit = Record | Headers | [string, string][]; ``` --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/HookFactoryCallback.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / HookFactoryCallback # Type Alias: HookFactoryCallback()\ ```ts type HookFactoryCallback = (hooks, app) => void; ``` ## Type Parameters ### S `S` ## Parameters ### hooks [`HookStore`](HookStore.md) ### app [`App`](../interfaces/App.md)<`S`> ## Returns `void` --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/HookStore.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / HookStore # Type Alias: HookStore ```ts type HookStore = { [K in LifecycleHook]: Set } & { clone: HookStore; }; ``` ## Type Declaration ### clone() ```ts clone(): HookStore; ``` #### Returns `HookStore` --- --- url: /api/@minimajs/server/@minimajs/server/plugins/type-aliases/HostExtractor.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / HostExtractor # Type Alias: HostExtractor()\ ```ts type HostExtractor = (ctx) => string | null; ``` ## Type Parameters ### S `S` ## Parameters ### ctx [`Context`](../../interfaces/Context.md)<`S`> ## Returns `string` | `null` --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/HttpCodes.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / HttpCodes # Type Alias: HttpCodes ```ts type HttpCodes = number; ``` --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/HttpHeader.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / HttpHeader # Type Alias: HttpHeader ```ts type HttpHeader = string; ``` --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/HttpHeaderIncoming.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / HttpHeaderIncoming # Type Alias: HttpHeaderIncoming ```ts type HttpHeaderIncoming = | keyof OmitIndexSignature | string & Record; ``` --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/HttpMethods.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / HttpMethods # Type Alias: HttpMethods ```ts type HttpMethods = OpenAPIV3.HttpMethods; ``` --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/HttpSecurityScheme.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / HttpSecurityScheme # Type Alias: HttpSecurityScheme ```ts type HttpSecurityScheme = OpenAPIV3.HttpSecurityScheme; ``` --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/InfoObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / InfoObject # Type Alias: InfoObject ```ts type InfoObject = Modify; ``` --- --- url: /api/@minimajs/server/@minimajs/server/plugins/type-aliases/IpExtractor.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / IpExtractor # Type Alias: IpExtractor()\ ```ts type IpExtractor = (ctx) => string | null; ``` ## Type Parameters ### S `S` ## Parameters ### ctx [`Context`](../../interfaces/Context.md)<`S`> ## Returns `string` | `null` --- --- url: /api/@minimajs/server/@minimajs/server/plugins/type-aliases/IpStrategy.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / IpStrategy # Type Alias: IpStrategy ```ts type IpStrategy = "first" | "last"; ``` --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/LicenseObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / LicenseObject # Type Alias: LicenseObject ```ts type LicenseObject = Modify; ``` --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/LifecycleHook.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / LifecycleHook # Type Alias: LifecycleHook ```ts type LifecycleHook = | typeof SERVER_HOOKS[number] | typeof LIFECYCLE_HOOKS[number]; ``` --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/LifeSpanCleanupCallback.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / LifeSpanCleanupCallback # Type Alias: LifeSpanCleanupCallback()\ ```ts type LifeSpanCleanupCallback = (app) => void | Promise; ``` ## Type Parameters ### S `S` ## Parameters ### app [`App`](../interfaces/App.md)<`S`> ## Returns `void` | `Promise`<`void`> --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/LinkObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / LinkObject # Type Alias: LinkObject ```ts type LinkObject = Modify; ``` --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/MediaTypeObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / MediaTypeObject # Type Alias: MediaTypeObject ```ts type MediaTypeObject = Modify; schema?: | SchemaObject | ReferenceObject; }>; ``` --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/Middleware.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / Middleware # Type Alias: Middleware()\ ```ts type Middleware = (ctx, next) => Promise; ``` ## Type Parameters ### S `S` = `unknown` ## Parameters ### ctx [`Context`](../interfaces/Context.md)<`S`> ### next [`MiddlewareNext`](MiddlewareNext.md) ## Returns `Promise`<`Response`> --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/MiddlewareNext.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / MiddlewareNext # Type Alias: MiddlewareNext() ```ts type MiddlewareNext = () => Promise; ``` ## Returns `Promise`<`Response`> --- --- url: >- /api/@minimajs/server/@minimajs/server/mock/type-aliases/MockContextCallback.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/mock](../README.md) / MockContextCallback # Type Alias: MockContextCallback()\ ```ts type MockContextCallback = (ctx) => T; ``` ## Type Parameters ### T `T` ### S `S` ## Parameters ### ctx [`Context`](../../interfaces/Context.md)<`S`> ## Returns `T` --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/ModuleScanner.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / ModuleScanner # Type Alias: ModuleScanner() ```ts type ModuleScanner = (pattern) => AsyncGenerator; ``` ## Parameters ### pattern `string` ## Returns `AsyncGenerator`<`string`> --- --- url: /api/@minimajs/multipart/@minimajs/multipart/type-aliases/MultipartOptions.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [@minimajs/multipart](../README.md) / MultipartOptions # Type Alias: MultipartOptions ```ts type MultipartOptions = Omit; ``` --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/type-aliases/MultipartRawResult.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [@minimajs/multipart](../README.md) / MultipartRawResult # Type Alias: MultipartRawResult ```ts type MultipartRawResult = | MultipartRawFile | MultipartRawField; ``` --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/Next.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / Next # Type Alias: Next() ```ts type Next = (error?, response?) => void; ``` ## Parameters ### error? `unknown` ### response? `unknown` ## Returns `void` --- --- url: /api/@minimajs/server/@minimajs/server/node/type-aliases/NodeServerOptions.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/node](../README.md) / NodeServerOptions # Type Alias: NodeServerOptions ```ts type NodeServerOptions = ServerOptions; ``` --- --- url: >- /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/NonArraySchemaObjectType.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / NonArraySchemaObjectType # Type Alias: NonArraySchemaObjectType ```ts type NonArraySchemaObjectType = OpenAPIV3.NonArraySchemaObjectType | "null"; ``` --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/OAuth2SecurityScheme.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / OAuth2SecurityScheme # Type Alias: OAuth2SecurityScheme ```ts type OAuth2SecurityScheme = OpenAPIV3.OAuth2SecurityScheme; ``` --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/OnceCallback.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / OnceCallback # Type Alias: OnceCallback()\ ```ts type OnceCallback = () => T; ``` ## Type Parameters ### T `T` ## Returns `T` --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/OnCloseHook.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / OnCloseHook # Type Alias: OnCloseHook()\ ```ts type OnCloseHook = (app) => void | Promise; ``` ## Type Parameters ### S `S` = `unknown` ## Parameters ### app [`App`](../interfaces/App.md)<`S`> ## Returns `void` | `Promise`<`void`> --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/OnErrorHook.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / OnErrorHook # Type Alias: OnErrorHook()\ ```ts type OnErrorHook = (err, ctx) => unknown | Promise; ``` ## Type Parameters ### S `S` = `unknown` ## Parameters ### err `unknown` ### ctx [`Context`](../interfaces/Context.md)<`S`> ## Returns `unknown` | `Promise`<`unknown`> --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/OnListenHook.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / OnListenHook # Type Alias: OnListenHook()\ ```ts type OnListenHook = (address, app) => void | Promise; ``` ## Type Parameters ### S `S` = `unknown` ## Parameters ### address [`AddressInfo`](../interfaces/AddressInfo.md) ### app [`App`](../interfaces/App.md)<`S`> ## Returns `void` | `Promise`<`void`> --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/OnReadyHook.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / OnReadyHook # Type Alias: OnReadyHook()\ ```ts type OnReadyHook = (app) => void | Promise; ``` ## Type Parameters ### S `S` = `unknown` ## Parameters ### app [`App`](../interfaces/App.md)<`S`> ## Returns `void` | `Promise`<`void`> --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/OnRegisterHook.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / OnRegisterHook # Type Alias: OnRegisterHook()\ ```ts type OnRegisterHook = (plugin, opts) => void | Promise; ``` ## Type Parameters ### S `S` = `unknown` ## Parameters ### plugin [`Plugin`](../interfaces/Plugin.md)<`S`> ### opts [`RegisterOptions`](RegisterOptions.md) ## Returns `void` | `Promise`<`void`> --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/OnRequestHook.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / OnRequestHook # Type Alias: OnRequestHook()\ ```ts type OnRequestHook = (ctx) => void | Response | Promise; ``` ## Type Parameters ### S `S` = `unknown` ## Parameters ### ctx [`Context`](../interfaces/Context.md)<`S`> ## Returns `void` | `Response` | `Promise`<`void` | `Response`> --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/OnSendHook.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / OnSendHook # Type Alias: OnSendHook()\ ```ts type OnSendHook = (response, ctx) => void | Promise; ``` ## Type Parameters ### S `S` = `unknown` ## Parameters ### response `Response` ### ctx [`Context`](../interfaces/Context.md)<`S`> ## Returns `void` | `Promise`<`void`> --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/OnTimeoutHook.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / OnTimeoutHook # Type Alias: OnTimeoutHook()\ ```ts type OnTimeoutHook = (ctx) => void | Promise; ``` ## Type Parameters ### S `S` = `unknown` ## Parameters ### ctx [`Context`](../interfaces/Context.md)<`S`> ## Returns `void` | `Promise`<`void`> --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/OnTransformHook.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / OnTransformHook # Type Alias: OnTransformHook()\ ```ts type OnTransformHook = (data, ctx) => unknown | Promise; ``` ## Type Parameters ### S `S` = `unknown` ## Parameters ### data `unknown` ### ctx [`Context`](../interfaces/Context.md)<`S`> ## Returns `unknown` | `Promise`<`unknown`> --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/OpenIdSecurityScheme.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / OpenIdSecurityScheme # Type Alias: OpenIdSecurityScheme ```ts type OpenIdSecurityScheme = OpenAPIV3.OpenIdSecurityScheme; ``` --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/OperationObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / OperationObject # Type Alias: OperationObject\ ```ts type OperationObject = Modify, { callbacks?: Record; parameters?: ( | ReferenceObject | ParameterObject)[]; requestBody?: | ReferenceObject | RequestBodyObject; responses?: ResponsesObject; servers?: ServerObject[]; }> & T; ``` ## Type Parameters ### T `T` *extends* { } = { } --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/ParameterBaseObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / ParameterBaseObject # Type Alias: ParameterBaseObject ```ts type ParameterBaseObject = OpenAPIV3.ParameterBaseObject; ``` --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/ParameterObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / ParameterObject # Type Alias: ParameterObject ```ts type ParameterObject = OpenAPIV3.ParameterObject; ``` --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/PathItemObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / PathItemObject # Type Alias: PathItemObject\ ```ts type PathItemObject = Modify, { parameters?: ( | ReferenceObject | ParameterObject)[]; servers?: ServerObject[]; }> & { [method in HttpMethods]?: OperationObject }; ``` ## Type Parameters ### T `T` *extends* { } = { } --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/PathsObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / PathsObject # Type Alias: PathsObject\ ```ts type PathsObject = Record & P | undefined>; ``` ## Type Parameters ### T `T` *extends* { } = { } ### P `P` *extends* { } = { } --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/PluginCallback.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / PluginCallback # Type Alias: PluginCallback()\ ```ts type PluginCallback = (app, opts) => void | Promise; ``` ## Type Parameters ### S `S` ### T `T` *extends* [`PluginOptions`](PluginOptions.md) ## Parameters ### app [`App`](../interfaces/App.md)<`S`> ### opts `T` ## Returns `void` | `Promise`<`void`> --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/PluginOptions.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / PluginOptions # Type Alias: PluginOptions\ ```ts type PluginOptions = T & { name?: string; }; ``` ## Type Declaration ### name? ```ts optional name: string; ``` ## Type Parameters ### T `T` = { } --- --- url: /api/@minimajs/server/@minimajs/server/plugins/type-aliases/ProtoExtractor.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / ProtoExtractor # Type Alias: ProtoExtractor()\ ```ts type ProtoExtractor = (ctx) => string; ``` ## Type Parameters ### S `S` ## Parameters ### ctx [`Context`](../../interfaces/Context.md)<`S`> ## Returns `string` --- --- url: /api/@minimajs/server/@minimajs/server/plugins/type-aliases/QuitHandler.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/plugins](../README.md) / QuitHandler # Type Alias: QuitHandler() ```ts type QuitHandler = () => Promise; ``` ## Returns `Promise`<`void`> --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/ReferenceObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / ReferenceObject # Type Alias: ReferenceObject ```ts type ReferenceObject = Modify; ``` --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/Registerable.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / Registerable # Type Alias: Registerable()\ ```ts type Registerable = (app, opts?) => void | Promise; ``` ## Type Parameters ### S `S` = `any` ## Parameters ### app [`App`](../interfaces/App.md)<`S`> ### opts? `any` ## Returns `void` | `Promise`<`void`> --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/RegisterOptions.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / RegisterOptions # Type Alias: RegisterOptions\ ```ts type RegisterOptions = T & { name?: string; prefix?: string; }; ``` ## Type Declaration ### name? ```ts optional name: string; ``` ### prefix? ```ts optional prefix: string; ``` ## Type Parameters ### T `T` = { } --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/RequestBodyObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / RequestBodyObject # Type Alias: RequestBodyObject ```ts type RequestBodyObject = Modify; ``` --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/RequestHandler.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / RequestHandler # Type Alias: RequestHandler()\ ```ts type RequestHandler = (server, request, partial) => Promise; ``` Handler function that processes HTTP requests. Takes a Web standard Request and returns a Web standard Response. ## Type Parameters ### S `S` ## Parameters ### server [`Server`](../classes/Server.md)<`S`> ### request `Request` ### partial [`RequestHandlerContext`](RequestHandlerContext.md)<`S`> ## Returns `Promise`<`Response`> --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/RequestHandlerContext.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / RequestHandlerContext # Type Alias: RequestHandlerContext\ ```ts type RequestHandlerContext = Partial, "locals" | "incomingMessage" | "serverResponse">>; ``` ## Type Parameters ### S `S` = `unknown` --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/ResponseBody.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / ResponseBody # Type Alias: ResponseBody ```ts type ResponseBody = | string | ReadableStream | ArrayBuffer | Blob | FormData | URLSearchParams | null; ``` --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/ResponseObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / ResponseObject # Type Alias: ResponseObject ```ts type ResponseObject = Modify; ``` --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/ResponsesObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / ResponsesObject # Type Alias: ResponsesObject ```ts type ResponsesObject = Record; ``` --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/RouteMetadata.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / RouteMetadata # Type Alias: RouteMetadata ```ts type RouteMetadata = { [key: symbol]: unknown; }; ``` ## Index Signature ```ts [key: symbol]: unknown ``` --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/RouteMetaDescriptor.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / RouteMetaDescriptor # Type Alias: RouteMetaDescriptor\ ```ts type RouteMetaDescriptor = [symbol, unknown] | (config) => void; ``` ## Type Parameters ### S `S` = `any` --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/Routes.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / Routes # Type Alias: Routes\ ```ts type Routes = Record<`${HTTPMethod} ${string}`, Handler>; ``` ## Type Parameters ### S `S` = `any` --- --- url: /api/@minimajs/schema/type-aliases/SchemaDataTypes.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/schema](../README.md) / [](../README.md) / SchemaDataTypes # Type Alias: SchemaDataTypes ```ts type SchemaDataTypes = | "body" | "headers" | "searchParams" | "params" | "responseBody" | "responseHeaders"; ``` --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/SchemaObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / SchemaObject # Type Alias: SchemaObject ```ts type SchemaObject = | ArraySchemaObject | NonArraySchemaObject | MixedSchemaObject; ``` There is no way to tell typescript to require items when type is either 'array' or array containing 'array' type 'items' will be always visible as optional Casting schema object to ArraySchemaObject or NonArraySchemaObject will work fine --- --- url: /api/@minimajs/schema/type-aliases/SchemaType.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/schema](../README.md) / [](../README.md) / SchemaType # Type Alias: SchemaType ```ts type SchemaType = { [kDataType]: SchemaDataTypes; [kSchema]: z.ZodType; [kSchemaName]?: string; [kStatusCode]?: number; }; ``` ## Properties ### \[kDataType] ```ts [kDataType]: SchemaDataTypes; ``` *** ### \[kSchema] ```ts [kSchema]: z.ZodType; ``` *** ### \[kSchemaName]? ```ts optional [kSchemaName]: string; ``` *** ### \[kStatusCode]? ```ts optional [kStatusCode]: number; ``` --- --- url: /api/@minimajs/schema/type-aliases/SchemaValidator.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/schema](../README.md) / [](../README.md) / SchemaValidator # Type Alias: SchemaValidator\ ```ts type SchemaValidator = () => T & SchemaType; ``` ## Type Parameters ### T `T` --- --- url: >- /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/SecurityRequirementObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / SecurityRequirementObject # Type Alias: SecurityRequirementObject ```ts type SecurityRequirementObject = OpenAPIV3.SecurityRequirementObject; ``` --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/SecuritySchemeObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / SecuritySchemeObject # Type Alias: SecuritySchemeObject ```ts type SecuritySchemeObject = OpenAPIV3.SecuritySchemeObject; ``` --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/Serializer.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / Serializer # Type Alias: Serializer()\ ```ts type Serializer = (body, ctx) => | ResponseBody | Promise; ``` ## Type Parameters ### S `S` = `unknown` ## Parameters ### body `unknown` ### ctx [`Context`](../interfaces/Context.md)<`S`> ## Returns | [`ResponseBody`](ResponseBody.md) | `Promise`<[`ResponseBody`](ResponseBody.md)> --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/ServerObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / ServerObject # Type Alias: ServerObject ```ts type ServerObject = Modify; }>; ``` --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/ServerVariableObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / ServerVariableObject # Type Alias: ServerVariableObject ```ts type ServerVariableObject = Modify; ``` --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/Signals.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / Signals # Type Alias: Signals ```ts type Signals = NodeJS.Signals; ``` --- --- url: /api/@minimajs/server/@minimajs/server/type-aliases/StatusCode.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / StatusCode # Type Alias: StatusCode ```ts type StatusCode = keyof typeof StatusCodes | number; ``` --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/TagObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / TagObject # Type Alias: TagObject ```ts type TagObject = OpenAPIV3.TagObject; ``` --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/helpers/type-aliases/Unit.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [helpers](../README.md) / Unit # Type Alias: Unit ```ts type Unit = typeof units[number]; ``` File size unit type representing binary prefixes (base 1024). Available units: KiB, MiB, GiB, TiB, PiB, EiB, ZiB, YiB --- --- url: /api/@minimajs/openapi/namespaces/OpenAPI/type-aliases/XMLObject.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/openapi](../../../README.md) / [OpenAPI](../README.md) / XMLObject # Type Alias: XMLObject ```ts type XMLObject = OpenAPIV3.XMLObject; ``` --- --- url: /comparison/nestjs.md --- ## Minima.js vs NestJS ### 1. Philosophy #### NestJS > “Let’s bring Angular + Spring Boot + annotations into Node.js because… reasons.” * Built for people who miss Java * Abstracts JavaScript until it barely looks like JavaScript * Assumes: * DI container * Reflection * Metadata / Classes everywhere #### Minima.js > “JavaScript already works. Let’s not fight it.” * Embraces: * Functions * Composition * Explicit execution * Runtime context (ALS) * No fake "enterprise" layers #### Verdict: NestJS fights the language. Minima respects it. *** ### Request Context Access **NestJS** Accessing the request object requires framework-specific APIs and request-scoped providers: ```ts @Injectable({ scope: Scope.REQUEST }) export class RequestContextService { constructor(@Inject(REQUEST) private readonly req: Request) {} getRequest() { return this.req; } } ``` This relies on: * Decorators * Reflection * Request-scoped dependency injection * Framework lifecycle management *** **Minima.js** Request and response are available anywhere using AsyncLocalStorage: ```ts const { req, res } = context(); ``` * No decorators * No container * Works across async boundaries *** ### Dependency Injection **NestJS** Dependencies are resolved through a container: ```ts @Injectable() export class AuthService { constructor(private readonly userService: UserService) {} authenticate() { // ... } } ``` This requires: * Class-based design * Provider registration * Container bootstrapping for tests *** **Minima.js** Dependencies are explicit and local: ```typescript // services/auth.ts export function login(user: User) { // do set authentication } ``` *** ### Authorization **NestJS** ```ts @Injectable() export class AuthGuard implements CanActivate { canActivate(ctx: ExecutionContext) { const req = ctx.switchToHttp().getRequest(); return !!req.user; } } ``` Guards are tightly coupled to the NestJS runtime. *** **Minima.js** Authorization logic is a simple, composable function. ```ts // auth/services.ts import { headers, abort } from "@minimajs/server"; const isAuthenticated = () => { if (!headers.get("Authorization")) { abort({ message: "Not Authenticated" }, 401); } }; ``` These functions can be applied as middleware using the composition API. ```ts import { plugin, hook, compose } from "@minimajs/server"; // Wrap the auth logic in a plugin const authPlugin = plugin((app) => { app.register(hook("request", isAuthenticated)); }); function adminModule(app: App) { app.get("/profile", () => ({ user: "admin" })); } // Apply the plugin to the module const protectedAdminModule = compose.create(authPlugin)(adminModule); app.register(protectedAdminModule); ``` *** ### Summary NestJS emphasizes **framework-managed abstraction**. Minima.js emphasizes **explicit control and simplicity**. The result is less magic, fewer concepts, and clearer execution flow. --- --- url: /core-concepts/diagrams/application-lifecycle.md --- ```mermaid graph TD Start([createApp]) --> Register Register["hook:register · ↓ FIFO
Plugins & modules"] --> Ready Ready["hook:ready · ↓ FIFO
Initialization complete"] --> Listen Listen["hook:listen · ↓ FIFO
Server started"] --> Serving{Server Running} Serving -->|Incoming Requests| RequestCycle[REQUEST LIFECYCLE
see below] RequestCycle --> Serving Serving -->|app.close| Close["hook:close · ↑ LIFO
Cleanup & shutdown"] Close --> End([Application Stopped]) style Register fill:#e1f5ff style Ready fill:#e7f9e7 style Listen fill:#fff4e1 style Serving fill:#f0f0f0 style Close fill:#ffe1e1 style RequestCycle fill:#f5e1ff ``` --- --- url: /core-concepts/diagrams/encapsulation.md --- ```mermaid graph TB Root[Root Scope
hook: Root hook] Root --> Child1[Child Scope 1
hook: Child 1 hook
route: /users] Root --> Child2[Child Scope 2
hook: Child 2 hook
route: /admin] subgraph Execution["Request Execution"] direction TB U1["/users request"] --> UE1[✓ Root hook] --> UE2[✓ Child 1 hook] --> UE3[✓ /users handler] A1["/admin request"] --> AE1[✓ Root hook] --> AE2[✓ Child 2 hook] --> AE3[✓ /admin handler] end Child1 -.->|influences| U1 Child2 -.->|influences| A1 style Root fill:#e1f5ff,stroke:#2196f3,stroke-width:2px style Child1 fill:#e7f9e7,stroke:#4caf50,stroke-width:2px style Child2 fill:#fff4e1,stroke:#ff9800,stroke-width:2px style UE1 fill:#cfe8fc style UE2 fill:#d4f1d4 style AE1 fill:#cfe8fc style AE2 fill:#fff0cc ``` --- --- url: /core-concepts/diagrams/flow-execution-paths.md --- ```mermaid graph TD Start([Incoming Request]) --> Choice{Execution Path} Choice -->|1️⃣ Normal Flow| N1[Route Match] N1 --> N2[Handler returns data] N2 --> N3["TRANSFORM Hook
↑ LIFO"] N3 --> N4[Serialize to JSON] N4 --> N5["SEND Hook
↑ LIFO"] N5 --> N6[defer callbacks] N6 --> N7[Send Response] Choice -->|2️⃣ Direct Response| D1[Route Match] D1 --> D2[Handler returns Response] D2 --> D5["SEND Hook
↑ LIFO"] --> N6 Choice -->|3️⃣ Early Return| E1["REQUEST Hook
↓ FIFO"] E1 --> E2[Returns Response] E2 --> E5["SEND Hook
↑ LIFO"] --> N6 Choice -.->|4️⃣ Error at Any Stage| R1["ERROR Hook
↑ LIFO"] R1 --> R2[Serialize Error] R2 --> R3["SEND Hook
↑ LIFO"] R3 --> R4[onError callbacks] --> N6 style N2 fill:#e7f9e7 style N3 fill:#e7f9e7 style N4 fill:#e7f9e7 style D2 fill:#fff4e1 style E2 fill:#e1f5ff style R1 fill:#ffe1e1 style R2 fill:#ffe1e1 style R4 fill:#ffe1e1 ``` --- --- url: /core-concepts/diagrams/request-lifecycle.md --- ```mermaid graph TD Start([Incoming HTTP Request]) Start --> CreateCtx["Create Context
params · body · headers"] CreateCtx --> ReqHook{"hook:request
↓ FIFO"} ReqHook -->|Returns Response
short-circuit| SendHook ReqHook -->|Continue| RouteMatch{{"Route Matching"}} RouteMatch --> Handler["Route Handler
Execution"] Handler -->|Returns data| Transform{"hook:transform
↑ LIFO"} Handler -->|Returns Response| SendHook Transform --> Serialize[/"Serialize body
JSON · text · stream"\] Serialize --> SendHook{"hook:send
↑ LIFO"} SendHook --> Defer(["defer()
post-response tasks"]) Defer --> Complete([Request Complete]) %% Error Flow ReqHook -.->|throws| ErrorHook RouteMatch -.->|throws| ErrorHook Handler -.->|throws| ErrorHook Transform -.->|throws| ErrorHook ErrorHook{"hook:error
↑ LIFO"} --> SerializeErr[/"Serialize error"\] --> ErrorSendHook{"hook:send
↑ LIFO"} --> OnError(["onError()
request cleanup"]) --> Defer %% Styling - Hooks (diamonds) style ReqHook fill:#fff4e1,stroke:#ffa726,stroke-width:2px style Transform fill:#ffe7f0,stroke:#e91e63,stroke-width:2px style SendHook fill:#e8f5e9,stroke:#4caf50,stroke-width:2px style ErrorHook fill:#ffebee,stroke:#f44336,stroke-width:2px style ErrorSendHook fill:#e8f5e9,stroke:#4caf50,stroke-width:2px %% Initialization & Context style CreateCtx fill:#e3f2fd,stroke:#2196f3,stroke-width:2px %% Routing & Matching style RouteMatch fill:#f3e5f5,stroke:#9c27b0,stroke-width:2px %% Main Processing style Handler fill:#ede7f6,stroke:#673ab7,stroke-width:3px %% Data Transformation (parallelograms) style Serialize fill:#fff3e0,stroke:#ff9800,stroke-width:2px style SerializeErr fill:#ffebee,stroke:#f44336,stroke-width:2px %% Cleanup & Lifecycle (stadiums) style Defer fill:#f5f5f5,stroke:#9e9e9e,stroke-width:2px style OnError fill:#ffebee,stroke:#f44336,stroke-width:2px %% Start/End style Start fill:#e8f5e9,stroke:#4caf50,stroke-width:2px style Complete fill:#e8f5e9,stroke:#4caf50,stroke-width:2px ``` --- --- url: /guides/diagrams/error-handler-flow.md --- ```mermaid graph TB Start[Request] --> Handler[Route Handler] Handler -->|Success| Response[Normal Response] Handler -->|Error| ErrorCheck{Error Hooks
Registered?} ErrorCheck -->|Yes| HookChain[Run Error Hooks
LIFO order] ErrorCheck -->|No| FallbackHandler[app.errorHandler] HookChain -->|Handled| CreateResp[Create Error Response] HookChain -->|Unhandled| FallbackHandler FallbackHandler --> CreateResp CreateResp --> SendHook[send Hook] SendHook --> End[Send Response] Response --> SendHook style Start fill:#e3f2fd style Handler fill:#fff3e0 style ErrorCheck fill:#fff9c4 style HookChain fill:#f3e5f5 style FallbackHandler fill:#fce4ec style CreateResp fill:#ffebee style End fill:#c8e6c9 ``` --- --- url: /guides/diagrams/error-scope-hierarchy.md --- ```mermaid graph TB Root["Root App
(Global Error Handler)"] Root --> Module1["Admin Module
(Admin Error Handler)"] Root --> Module2["API Module
(API Error Handler)"] Module1 --> Route1["/admin/dashboard"] Module1 --> Route2["/admin/users"] Module2 --> Route3["/api/posts"] Route1 -.->|Error occurs| Exec1["1. Admin Handler
2. Global Handler
3. app.errorHandler"] Route3 -.->|Error occurs| Exec2["1. API Handler
2. Global Handler
3. app.errorHandler"] style Root fill:#e1f5fe style Module1 fill:#b3e5fc style Module2 fill:#b3e5fc style Exec1 fill:#fff3e0 style Exec2 fill:#fff3e0 ``` --- --- url: /guides/diagrams/error-hook-outcomes.md --- ```mermaid graph TB Start[Error Thrown] --> Hook{Error Hook} Hook -->|1. Re-throw/abort| NextHook[Next Error Hook
or app.errorHandler] Hook -->|2. Return data| Success[200 OK Response
✅ Chain stops] Hook -->|3. Return Response| Direct[Send Response
⚠️ Bypasses transform hooks] Hook -->|4. Return undefined| NextHook NextHook --> Final[Final Error Response] style Start fill:#ffcdd2 style Success fill:#c8e6c9 style Direct fill:#ffe0b2 style Final fill:#ffcdd2 ``` --- --- url: /guides/diagrams/hook-scope-inheritance.md --- ```mermaid graph TB Root["Root App
(Parent Hook)"] Root --> Child1["Child Scope 1
(Child 1 Hook)"] Root --> Child2["Child Scope 2
(Child 2 Hook)"] Child1 --> Route1["/users"] Child2 --> Route2["/admin"] Route1 -.->|Executes
request hook| Exec1["1. Parent Hook
2. Child 1 Hook"] Route2 -.->|Executes
request hook| Exec2["1. Parent Hook
2. Child 2 Hook"] style Root fill:#e7f5ff style Child1 fill:#d0ebff style Child2 fill:#d0ebff style Exec1 fill:#fff3bf style Exec2 fill:#fff3bf ``` --- --- url: /guides/diagrams/hook-lifo-execution.md --- ```mermaid graph LR Start[Request Arrives] --> Hook3["Send Hook 3 (registered last)
▶ Runs FIRST"] Hook3 --> Hook2["Send Hook 2 (registered second)
▶ Runs SECOND"] Hook2 --> Hook1["Send Hook 1 (registered first)
▶ Runs LAST"] Hook1 --> Handler[Send Response] style Hook3 fill:#51cf66 style Hook2 fill:#74c0fc style Hook1 fill:#ffd43b ``` **Note**: LIFO order applies to Child → Parent hooks: `transform`, `send`, `error`, `close`, `timeout`. Parent → Child hooks like `request` use FIFO order. --- --- url: /guides/diagrams/request-hook-flow.md --- ```mermaid graph LR A[Incoming Request] --> B[Request Hook 1] B -->|Response| Exit1[Early Exit] B -->|void| C[Request Hook 2] C -->|Response| Exit2[Early Exit] C -->|void| D[Request Hook 3] D -->|Response| Exit3[Early Exit] D -->|void| E[Route Match] E --> F[Handler] F --> G[Transform & Send] Exit1 & Exit2 & Exit3 --> H[Send to Client] G --> H style Exit1 fill:#ff6b6b style Exit2 fill:#ff6b6b style Exit3 fill:#ff6b6b style E fill:#51cf66 ``` --- --- url: /guides/diagrams/send-hook-flow.md --- ```mermaid graph LR A[Handler] --> B[Transform] --> C[Serialize] C --> D[Send Hook 3] D -->|Response| Exit1[Early Exit] D -->|void| E[Send Hook 2] E -->|Response| Exit2[Early Exit] E -->|void| F[Send Hook 1] F -->|Response| Exit3[Early Exit] F -->|void| G[Create Response] Exit1 & Exit2 & Exit3 & G --> H[Send to Client] style Exit1 fill:#ff6b6b style Exit2 fill:#ff6b6b style Exit3 fill:#ff6b6b style G fill:#51cf66 ``` --- --- url: /api/@minimajs/schema/validation/README.md --- [**Minima.js API**](../../../README.md) *** [Minima.js API](../../../README.md) / [@minimajs/schema](../README.md) / validation # validation ## Interfaces | Interface | Description | | ------ | ------ | | [ValidationOptions](interfaces/ValidationOptions.md) | - | ## Functions | Function | Description | | ------ | ------ | | [validator](functions/validator.md) | - | | [validatorAsync](functions/validatorAsync.md) | - | --- --- url: /api/@minimajs/server/@minimajs/server/variables/executionContext.md --- [**Minima.js API**](../../../../../README.md) *** [Minima.js API](../../../../../README.md) / [@minimajs/server](../../../README.md) / [@minimajs/server](../README.md) / executionContext # Variable: executionContext ```ts const executionContext: AsyncLocalStorage>; ``` --- --- url: /api/@minimajs/server/@minimajs/server/symbols/variables/kBody.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/symbols](../README.md) / kBody # Variable: kBody ```ts const kBody: typeof kBody; ``` Symbol for request body storage in context. Used by body parser plugin to store parsed body. --- --- url: /api/@minimajs/server/@minimajs/server/symbols/variables/kBodySkip.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/symbols](../README.md) / kBodySkip # Variable: kBodySkip ```ts const kBodySkip: typeof kBodySkip; ``` Symbol to mark requests that should skip body parsing. Used to opt-out of automatic body parsing for specific routes. --- --- url: /api/@minimajs/server/@minimajs/server/symbols/variables/kHandlerDescriptor.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/symbols](../README.md) / kHandlerDescriptor # Variable: kHandlerDescriptor ```ts const kHandlerDescriptor: typeof kHandlerDescriptor; ``` --- --- url: /api/@minimajs/server/@minimajs/server/symbols/variables/kHooks.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/symbols](../README.md) / kHooks # Variable: kHooks ```ts const kHooks: typeof kHooks; ``` Symbol for accessing registered hooks. --- --- url: /api/@minimajs/server/@minimajs/server/symbols/variables/kIpAddr.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/symbols](../README.md) / kIpAddr # Variable: kIpAddr ```ts const kIpAddr: typeof kIpAddr; ``` --- --- url: /api/@minimajs/server/@minimajs/server/symbols/variables/kMiddlewares.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/symbols](../README.md) / kMiddlewares # Variable: kMiddlewares ```ts const kMiddlewares: typeof kMiddlewares; ``` --- --- url: /api/@minimajs/server/@minimajs/server/symbols/variables/kModuleName.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/symbols](../README.md) / kModuleName # Variable: kModuleName ```ts const kModuleName: typeof kModuleName; ``` Symbol for plugin name metadata. Used to identify plugins for debugging and error messages. --- --- url: /api/@minimajs/server/@minimajs/server/symbols/variables/kModulesChain.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/symbols](../README.md) / kModulesChain # Variable: kModulesChain ```ts const kModulesChain: typeof kModulesChain; ``` Symbol for maintaining module chain (root -> ... -> child) in container. --- --- url: /api/@minimajs/server/@minimajs/server/symbols/variables/kPlugin.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/symbols](../README.md) / kPlugin # Variable: kPlugin ```ts const kPlugin: typeof kPlugin; ``` Symbol to mark plugins that should skip context override. Used for plugins that need to maintain parent context. --- --- url: /api/@minimajs/server/@minimajs/server/symbols/variables/kPluginSync.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/symbols](../README.md) / kPluginSync # Variable: kPluginSync ```ts const kPluginSync: typeof kPluginSync; ``` Symbol to mark synchronous plugins. Used for plugins that don't require async initialization. --- --- url: /api/@minimajs/server/@minimajs/server/symbols/variables/kRequestSchema.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/symbols](../README.md) / kRequestSchema # Variable: kRequestSchema ```ts const kRequestSchema: typeof kRequestSchema; ``` --- --- url: /api/@minimajs/server/@minimajs/server/symbols/variables/kResponseSchema.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/symbols](../README.md) / kResponseSchema # Variable: kResponseSchema ```ts const kResponseSchema: typeof kResponseSchema; ``` --- --- url: /api/@minimajs/server/@minimajs/server/logger/variables/logger.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/logger](../README.md) / logger # Variable: logger ```ts const logger: Logger; ``` --- --- url: /api/@minimajs/server/@minimajs/server/logger/variables/loggerOptions.md --- [**Minima.js API**](../../../../../../README.md) *** [Minima.js API](../../../../../../README.md) / [@minimajs/server](../../../../README.md) / [@minimajs/server/logger](../README.md) / loggerOptions # Variable: loggerOptions ```ts const loggerOptions: LoggerOptions; ``` --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/raw/variables/RAW_FIELD.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [raw](../README.md) / RAW\_FIELD # Variable: RAW\_FIELD ```ts const RAW_FIELD: typeof RAW_FIELD; ``` --- --- url: >- /api/@minimajs/multipart/@minimajs/multipart/namespaces/raw/variables/RAW_FILE.md --- [**Minima.js API**](../../../../../../../README.md) *** [Minima.js API](../../../../../../../README.md) / [@minimajs/multipart](../../../../../README.md) / [@minimajs/multipart](../../../README.md) / [raw](../README.md) / RAW\_FILE # Variable: RAW\_FILE ```ts const RAW_FILE: typeof RAW_FILE; ```