UNPKG

@noxfly/noxus

Version:

Simulate lightweight HTTP-like requests between renderer and main process in Electron applications with MessagePort, with structured and modular design.

403 lines (388 loc) 19.3 kB
import { M as MaybeAsync, T as Type } from './app-injector-B3MvgV3k.mjs'; export { A as AppInjector, F as ForwardRefFn, a as ForwardReference, I as IBinding, L as Lifetime, R as RootInjector, f as forwardRef, i as inject } from './app-injector-B3MvgV3k.mjs'; import { R as Request, a as IResponse, h as IGuard } from './request-Dx_5Prte.mjs'; export { A as AtomicHttpMethod, j as Authorize, D as Delete, G as Get, H as HttpMethod, c as IBatchRequestItem, e as IBatchRequestPayload, d as IBatchResponsePayload, I as IRendererEventMessage, b as IRequest, m as IRouteMetadata, p as Patch, P as Post, o as Put, f as RENDERER_EVENT_TYPE, q as ROUTE_METADATA_KEY, g as createRendererEventMessage, k as getGuardForController, l as getGuardForControllerAction, n as getRouteMetadata, i as isRendererEventMessage } from './request-Dx_5Prte.mjs'; import { BrowserWindow } from 'electron/main'; export { BadGatewayException, BadRequestException, ConflictException, ForbiddenException, GatewayTimeoutException, HttpVersionNotSupportedException, INJECTABLE_METADATA_KEY, INJECT_METADATA_KEY, Inject, Injectable, InsufficientStorageException, InternalServerException, LogLevel, Logger, LoopDetectedException, MethodNotAllowedException, NetworkAuthenticationRequiredException, NetworkConnectTimeoutException, NotAcceptableException, NotExtendedException, NotFoundException, NotImplementedException, PaymentRequiredException, RequestTimeoutException, ResponseException, ServiceUnavailableException, TooManyRequestsException, UnauthorizedException, UpgradeRequiredException, VariantAlsoNegotiatesException, getInjectableMetadata, hasInjectableMetadata } from './child.mjs'; /** * @copyright 2025 NoxFly * @license MIT * @author NoxFly */ /** * NextFunction is a function that is called to continue the middleware chain. * It returns an Promise that emits when the next middleware is done. */ type NextFunction = () => Promise<void>; /** * IMiddleware interface defines a middleware that can be used in the application. * It has an `invoke` method that takes a request, a response, and a next function. * The `invoke` method can return a MaybeAsync, which means it can return either a value or a Promise. * * Use it on a class that should be registered as a middleware in the application. */ interface IMiddleware { invoke(request: Request, response: IResponse, next: NextFunction): MaybeAsync<void>; } /** * UseMiddlewares decorator can be used to register middlewares for a controller or a controller action. * * @param mdlw - The middlewares list to register for the controller or the controller action. */ declare function UseMiddlewares(mdlw: Type<IMiddleware>[]): ClassDecorator & MethodDecorator; /** * Gets the middlewares for a controller or a controller action. * This function retrieves the middlewares registered with the UseMiddlewares decorator. * It returns an array of middleware classes that can be used to process requests for the specified controller. * @param controllerName The name of the controller to get the middlewares for. * @returns An array of middlewares for the controller. */ declare function getMiddlewaresForController(controllerName: string): Type<IMiddleware>[]; /** * Gets the middlewares for a controller action. * This function retrieves the middlewares registered with the UseMiddlewares decorator for a specific action in a controller. * It returns an array of middleware classes that can be used to process requests for the specified controller action. * @param controllerName The name of the controller to get the middlewares for. * @param actionName The name of the action to get the middlewares for. * @returns An array of middlewares for the controller action. */ declare function getMiddlewaresForControllerAction(controllerName: string, actionName: string): Type<IMiddleware>[]; /** * A lazy route entry maps a path prefix to a dynamic import function. * The module is loaded on the first request matching the prefix. */ interface ILazyRoute { /** Path prefix (e.g. "auth", "printing"). Matched against the first segment(s) of the request path. */ path: string; /** Dynamic import function returning the module file. */ loadModule: () => Promise<unknown>; } /** * IRouteDefinition interface defines the structure of a route in the application. * It includes the HTTP method, path, controller class, handler method name, * guards, and middlewares associated with the route. */ interface IRouteDefinition { method: string; path: string; controller: Type<any>; handler: string; guards: Type<IGuard>[]; middlewares: Type<IMiddleware>[]; } /** * This type defines a function that represents an action in a controller. * It takes a Request and an IResponse as parameters and returns a value or a Promise. */ type ControllerAction = (request: Request, response: IResponse) => any; /** * Router class is responsible for managing the application's routing. * It registers controllers, handles requests, and manages middlewares and guards. */ declare class Router { private readonly routes; private readonly rootMiddlewares; private readonly lazyRoutes; /** * Registers a controller class with the router. * This method extracts the route metadata from the controller class and registers it in the routing tree. * It also handles the guards and middlewares associated with the controller. * @param controllerClass - The controller class to register. */ registerController(controllerClass: Type<unknown>): Router; /** * Registers a lazy route. The module behind this route prefix will only * be imported (and its controllers/services registered in DI) the first * time a request targets this prefix. * * @param pathPrefix - Route prefix (e.g. "auth"). Matched against the first segment of the request path. * @param loadModule - A function that returns a dynamic import promise. */ registerLazyRoute(pathPrefix: string, loadModule: () => Promise<unknown>): Router; /** * Defines a middleware for the root of the application. * This method allows you to register a middleware that will be applied to all requests * to the application, regardless of the controller or action. * @param middleware - The middleware class to register. */ defineRootMiddleware(middleware: Type<IMiddleware>): Router; /** * Shuts down the message channel for a specific sender ID. * This method closes the IPC channel for the specified sender ID and * removes it from the messagePorts map. * @param channelSenderId - The ID of the sender channel to shut down. */ handle(request: Request): Promise<IResponse>; private handleAtomic; private handleBatch; private normalizeBatchPayload; private normalizeBatchItem; /** * Finds the route definition for a given request. * This method searches the routing tree for a matching route based on the request's path and method. * If no matching route is found, it throws a NotFoundException. * @param request - The Request object containing the method and path to search for. * @returns The IRouteDefinition for the matched route. */ /** * Attempts to find a route definition for the given request. * Returns undefined instead of throwing when the route is not found, * so the caller can try lazy-loading first. */ private tryFindRoute; /** * Finds the route definition for a given request. * If no eagerly-registered route matches, attempts to load a lazy module * whose prefix matches the request path, then retries. */ private findRoute; /** * Given a request path, checks whether a lazy route prefix matches * and triggers the dynamic import if it hasn't been loaded yet. */ private tryLoadLazyRoute; /** * Dynamically imports a lazy module and registers its decorated classes * (controllers, services) in the DI container using the two-phase strategy. */ private loadLazyModule; /** * Resolves the controller for a given route definition. * This method creates an instance of the controller class and prepares the request parameters. * It also runs the request pipeline, which includes executing middlewares and guards. * @param request - The Request object containing the request data. * @param response - The IResponse object to populate with the response data. * @param routeDef - The IRouteDefinition for the matched route. * @return A Promise that resolves when the controller action has been executed. * @throws UnauthorizedException if the request is not authorized by the guards. */ private resolveController; /** * Runs the request pipeline for a given request. * This method executes the middlewares and guards associated with the route, * and finally calls the controller action. * @param request - The Request object containing the request data. * @param response - The IResponse object to populate with the response data. * @param routeDef - The IRouteDefinition for the matched route. * @param controllerInstance - The instance of the controller class. * @return A Promise that resolves when the request pipeline has been executed. * @throws ResponseException if the response status is not successful. */ private runRequestPipeline; /** * Runs a middleware function in the request pipeline. * This method creates an instance of the middleware and invokes its `invoke` method, * passing the request, response, and next function. * @param request - The Request object containing the request data. * @param response - The IResponse object to populate with the response data. * @param next - The NextFunction to call to continue the middleware chain. * @param middlewareType - The type of the middleware to run. * @return A Promise that resolves when the middleware has been executed. */ private runMiddleware; /** * Runs a guard to check if the request is authorized. * This method creates an instance of the guard and calls its `canActivate` method. * If the guard returns false, it throws an UnauthorizedException. * @param request - The Request object containing the request data. * @param guardType - The type of the guard to run. * @return A Promise that resolves if the guard allows the request, or throws an UnauthorizedException if not. * @throws UnauthorizedException if the guard denies access to the request. */ private runGuard; /** * Extracts parameters from the actual request path based on the template path. * This method splits the actual path and the template path into segments, * then maps the segments to parameters based on the template. * @param actual - The actual request path. * @param template - The template path to extract parameters from. * @returns An object containing the extracted parameters. */ private extractParams; } interface RendererChannels { request: Electron.MessageChannelMain; socket: Electron.MessageChannelMain; } declare class NoxSocket { private readonly channels; register(senderId: number, requestChannel: Electron.MessageChannelMain, socketChannel: Electron.MessageChannelMain): void; get(senderId: number): RendererChannels | undefined; unregister(senderId: number): void; getSenderIds(): number[]; emit<TPayload = unknown>(eventName: string, payload?: TPayload, targetSenderIds?: number[]): number; emitToRenderer<TPayload = unknown>(senderId: number, eventName: string, payload?: TPayload): boolean; } /** * The application service should implement this interface, as * the NoxApp class instance will use it to notify the given service * about application lifecycle events. */ interface IApp { dispose(): Promise<void>; onReady(mainWindow?: BrowserWindow): Promise<void>; onActivated(): Promise<void>; } /** * NoxApp is the main application class that manages the application lifecycle, * handles IPC communication, and integrates with the Router. */ declare class NoxApp { private readonly router; private readonly socket; private app; private mainWindow; /** * */ private readonly onRendererMessage; constructor(router: Router, socket: NoxSocket); /** * Initializes the NoxApp instance. * This method sets up the IPC communication, registers event listeners, * and prepares the application for use. */ init(): Promise<NoxApp>; /** * Handles the request from the renderer process. * This method creates a Request object from the IPC event data, * processes it through the Router, and sends the response back * to the renderer process using the MessageChannel. */ private giveTheRendererAPort; /** * MacOS specific behavior. */ private onAppActivated; /** * Shuts down the message channel for a specific sender ID. * This method closes the IPC channel for the specified sender ID and * removes it from the messagePorts map. * @param channelSenderId - The ID of the sender channel to shut down. * @param remove - Whether to remove the channel from the messagePorts map. */ private shutdownChannel; /** * Handles the application shutdown process. * This method is called when all windows are closed, and it cleans up the message channels */ private onAllWindowsClosed; /** * Sets the main BrowserWindow that was created early by bootstrapApplication. * This window will be passed to IApp.onReady when start() is called. * @param window - The BrowserWindow created during bootstrap. */ setMainWindow(window: BrowserWindow): void; /** * Registers a lazy-loaded route. The module behind this path prefix * will only be dynamically imported when the first IPC request * targets this prefix — like Angular's loadChildren. * * @example * ```ts * noxApp.lazy("auth", () => import("./modules/auth/auth.module.js")); * noxApp.lazy("printing", () => import("./modules/printing/printing.module.js")); * ``` * * @param pathPrefix - The route prefix (e.g. "auth", "cash-register"). * @param loadModule - A function returning a dynamic import promise. * @returns NoxApp instance for method chaining. */ lazy(pathPrefix: string, loadModule: () => Promise<unknown>): NoxApp; /** * Eagerly loads one or more modules with a two-phase DI guarantee. * Use this when a service needed at startup lives inside a module * (e.g. the Application service depends on LoaderService). * * All dynamic imports run in parallel; bindings are registered first, * then singletons are resolved — safe regardless of import ordering. * * @param importFns - Functions returning dynamic import promises. */ loadModules(importFns: Array<() => Promise<unknown>>): Promise<void>; /** * Configures the NoxApp instance with the provided application class. * This method allows you to set the application class that will handle lifecycle events. * @param app - The application class to configure. * @returns NoxApp instance for method chaining. */ configure(app: Type<IApp>): NoxApp; /** * Registers a middleware for the root of the application. * This method allows you to define a middleware that will be applied to all requests * @param middleware - The middleware class to register. * @returns NoxApp instance for method chaining. */ use(middleware: Type<IMiddleware>): NoxApp; /** * Should be called after the bootstrapApplication function is called. * Passes the early-created BrowserWindow (if any) to the configured IApp service. * @returns NoxApp instance for method chaining. */ start(): NoxApp; } /** * Options for bootstrapping the Noxus application. */ interface BootstrapOptions { /** * If provided, Noxus creates a BrowserWindow immediately after Electron is ready, * before any DI processing occurs. This window is passed to the configured * IApp service via onReady(). It allows the user to see a window as fast as possible, * even before the application is fully initialized. */ window?: Electron.BrowserWindowConstructorOptions; } /** * Bootstraps the Noxus application. * This function initializes the application by creating an instance of NoxApp, * registering the root module, and starting the application. * * When {@link BootstrapOptions.window} is provided, a BrowserWindow is created * immediately after Electron readiness — before DI resolution — so the user * sees a window as quickly as possible. * * @param rootModule - The root module of the application, decorated with @Module. * @param options - Optional bootstrap configuration. * @return A promise that resolves to the NoxApp instance. * @throws Error if the root module is not decorated with @Module, or if the electron process could not start. */ declare function bootstrapApplication(rootModule?: Type<any> | null, options?: BootstrapOptions): Promise<NoxApp>; /** * The configuration that waits a controller's decorator. */ interface IControllerMetadata { path: string; guards: Type<IGuard>[]; } /** * Controller decorator is used to define a controller in the application. * It is a kind of node in the routing tree, that can contains routes and middlewares. * * @param path - The path for the controller. */ declare function Controller(path: string): ClassDecorator; /** * Gets the controller metadata for a given target class. * This metadata includes the path and guards defined by the @Controller decorator. * @param target - The target class to get the controller metadata from. * @returns The controller metadata if it exists, otherwise undefined. */ declare function getControllerMetadata(target: Type<unknown>): IControllerMetadata | undefined; declare const CONTROLLER_METADATA_KEY: unique symbol; interface IModuleMetadata { imports?: Type<unknown>[]; exports?: Type<unknown>[]; providers?: Type<unknown>[]; controllers?: Type<unknown>[]; } /** * Module decorator is used to define a module in the application. * It is a kind of node in the routing tree, that can contains controllers, services, and other modules. * * @param metadata - The metadata for the module. */ declare function Module(metadata: IModuleMetadata): ClassDecorator; declare function getModuleMetadata(target: Function): IModuleMetadata | undefined; declare const MODULE_METADATA_KEY: unique symbol; export { type BootstrapOptions, CONTROLLER_METADATA_KEY, Controller, type ControllerAction, type IApp, type IControllerMetadata, IGuard, type ILazyRoute, type IMiddleware, type IModuleMetadata, IResponse, type IRouteDefinition, MODULE_METADATA_KEY, MaybeAsync, Module, type NextFunction, NoxApp, NoxSocket, Request, Router, Type, UseMiddlewares, bootstrapApplication, getControllerMetadata, getMiddlewaresForController, getMiddlewaresForControllerAction, getModuleMetadata };