UNPKG

@mojojs/core

Version:

Real-time web framework

368 lines (367 loc) 12 kB
import type { Route } from './router/route.js'; import type { AnyArguments, AppOptions, BackendInfo, UserAgentOptions, MojoAction, MojoContext, MojoModels, NestedHelpers, RouteArguments, ServerOptions, TestUserAgentOptions } from './types.js'; import { CLI } from './cli.js'; import { Hooks } from './hooks.js'; import { Logger } from './logger.js'; import { Mime } from './mime.js'; import { Renderer } from './renderer.js'; import { Router } from './router.js'; import { ServerRequest } from './server/request.js'; import { ServerResponse } from './server/response.js'; import { Session } from './session.js'; import { Static } from './static.js'; import { MockUserAgent } from './user-agent/mock.js'; import { TestUserAgent } from './user-agent/test.js'; import { UserAgent } from './user-agent.js'; import { Validator } from './validator.js'; import Path from '@mojojs/path'; type AppHook = (app: App, ...args: any[]) => any; type ContextHook = (app: MojoContext, ...args: any[]) => any; type Decoration = ((...args: any[]) => any) | { get?: () => any; set?: (value: any) => any; configurable?: boolean; }; /** * Application class. */ export declare class App { /** * Command line interface. * @example * // Add another path to load commands from * app.cli.commandPaths.push(app.home.child('cli').toString()); */ cli: CLI; /** * Application config. * @example * // Remove value * delete app.config.foo; * * // Assign multiple values at once * Object.assign(app.config, {foo: 'test', bar: 23}); */ config: Record<string, any>; /** * Default stash values. * @example * // Remove value * delete app.defaults.foo; * * // Assign multiple values at once * Object.assign(app.defaults, {foo: 'test', bar: 23}); */ defaults: Record<string, any>; /** * Detect if the application has been imported and disable the command line interface if it has. */ detectImport: boolean; /** * Format for HTTP exceptions ("html", "json", or "txt"). * @example * // Change default exception format for whole application * app.exceptionFormat = 'json'; */ exceptionFormat: string; /** * Application hooks. * @example * // Run a custom hook * await app.hooks.runHook('my:hook', foo, bar); */ hooks: Hooks; /** * Application home directory. * @example * // Portably generate path relative to home directory * const path = app.home.child('data', 'important.txt'); */ home: Path; /** * Application logger. * @example * // Log debug message * app.log.debug('It works'); */ log: Logger; /** * MIME types. * @example * // Get MIME type for extension * const type = app.mime.extType('txt'); */ mime: Mime; /** * Operating mode for application. Defaults to the value of the `NODE_ENV` environment variable or `development`. */ mode: string; /** * Storage for user defined models. * @example * // Store database connection * app.models.pg = new Pg('postgres://127.0.0.1:5432/db'); */ models: MojoModels; /** * Application renderer. * @example * // Disable compression * app.renderer.autoCompress = false; * * // Add another "views" directory * app.renderer.viewPaths.push(app.home.child('views').toString()); */ renderer: Renderer; /** * Application router. * @example * // Add routes * const r = app.router; * r.get('/foo/bar').to('test#foo', {title: 'Hello Mojo!'}); * r.post('/baz').to('test#baz'); * * // Add another path to load controllers from * app.router.controllerPaths.push(app.home.child('more-controllers').toString()); */ router: Router; /** * Rotating secret passphrases used for signed cookies and the like. * @example * // Rotate passphrases * app.secrets = ['new_passw0rd', 'old_passw0rd', 'very_old_passw0rd']; */ secrets: string[]; /** * Encrypted cookie based session manager. * @example * // Change name of cookie used for all sessions * app.sessions.cookieName = 'mysession'; * * // Disable SameSite feature * app.sessions.sameSite = 'none'; */ session: Session; /** * Static file server. * @example * // Add another "public" directory * app.static.publicPaths.push('/home/sri/public'); * * // Add another "public" directory with higher precedence * app.static.publicPaths.unshift('/home/sri/themes/blue/public'); */ static: Static; /** * HTTP/WebSocket user-agent. * @example * # Perform HTTP request * const res = await app.ua.get('http://example.com'); */ ua: UserAgent; /** * JSON schema validator. * @example * // Add a named schema for later use * app.validator.addSchema({type: 'object', properties: {test: {type: 'number'}}}, 'testForm'); */ validator: Validator; _contextClass: any; _nestedHelpers: Record<string, NestedHelpers>; constructor(options?: AppOptions); /** * Add an application hook to extend the framework. * @example * // Run code whenever a server has been started * app.addAppHook('server:start', async app => { * ... * }); */ addAppHook(name: string, fn: AppHook): this; /** * Add a context hook to extend the framework. * @example * // Run code after a new request has been received * app.addContextHook('dispatch:before', async ctx => { * ... * }); */ addContextHook(name: string, fn: ContextHook): this; /** * Add a helper. * @example * // Render response with header * app.addHelper('renderWithHeader', async (ctx, ...args) => { * ctx.res.set('X-Mojo', 'I <3 mojo.js!'); * await ctx.render(...args); * }); * * // Render response with header using nested helper * app.addHelper('renderWith.header', async (ctx, ...args) => { * ctx.res.set('X-Mojo', 'I <3 mojo.js!'); * await ctx.render(...args); * }); */ addHelper(name: string, fn: MojoAction): this; /** * Generate route matching any of the listed HTTP request methods or all. * @example * // Route with pattern and destination * app.any('/user').to('User#whatever'); * * // Route with HTTP methods, pattern, restrictive placeholders and destination * app.any(['DELETE', 'PUT'], '/:foo', {foo: /\w+/}).to('Foo#bar'); * * // Route with pattern, name and destination * app.any('/:foo').name('foo_route').to('Foo#bar'); * * // Route with pattern, condition and destination * app.any('/').requires({agent: /Firefox/}).to('Foo#bar'); * * // Route with pattern and a closure as destination * app.any('/:foo', async ctx => ctx.render({text: 'Hello World!'})); */ any(...args: AnyArguments): Route; /** * Decorate context class with a method or getter/setter. * @example * // Decorate context with getter * app.decorateContext('helloWorld', {get: () => 'Hello World!'}); */ decorateContext(name: string, fn: Decoration): this; /** * Generate route matching only `DELETE` requests. * @example * // Route with destination * app.delete('/user').to('User#remove'); */ delete(...args: RouteArguments): Route; /** * Generate route matching only `GET` requests. * @example * // Route with destination * app.get('/user').to('User#show'); */ get(...args: RouteArguments): Route; /** * Handle a new incoming request, used by servers. */ handleRequest(ctx: MojoContext): Promise<void>; /** * Create a context for application. */ newContext(req: ServerRequest, res: ServerResponse, backend: BackendInfo): MojoContext; /** * Create a mock context for application. Very useful for testing helpers. * @example * // Use a mock context to call a helper * const ctx = app.newMockContext(); * const html = ctx.assetTag('/app.js'); */ newMockContext(options?: { headers?: string[]; method?: string; url?: string; }): MojoContext; /** * Create a new mock user-agent for application. */ newMockUserAgent(options?: UserAgentOptions, serverOptions?: ServerOptions): Promise<MockUserAgent>; /** * Create a new test user-agent for application. * @example * // Test plain text endpoint * const ua = await app.newTestUserAgent(); * (await ua.getOk('/')).statusIs(200).bodyIs('Hello World!'); */ newTestUserAgent(options?: TestUserAgentOptions, serverOptions?: ServerOptions): Promise<TestUserAgent>; /** * Your main hook into the application, it is a shortcut for the `app:start` hook and runs during application * startup. You can use it to perform tasks like preparing database connections. * @example * // Perform async operations on application startup * app.onStart(async app => { * if (app.models.db === undefined) app.models.db = new SomeDatabase(); * await app.models.db.connect(); * }); */ onStart(fn: AppHook): this; /** * The opposite of `onStart`, it is a shortcut for the `app:stop` hook and runs during application shutdown. You can * use it to perform tasks like closing database connections gracefully. * @example * app.onStop(async app => { * await app.models.db.disconnect(); * }); */ onStop(fn: AppHook): this; /** * Generate route matching only `OPTIONS` requests. * @example * // Route with destination * app.options('/user').to('User#overview'); */ options(...args: RouteArguments): Route; /** * Generate route matching only `PATCH` requests. * @example * // Route with destination * app.patch('/user').to('User#update'); */ patch(...args: RouteArguments): Route; /** * Register plugin. * @example * // Mount application under "/prefix" * app.plugin(mountPlugin, {app: myOtherApp, path: '/prefix'}); * * // Load configuration from file * app.plugin(jsonConfigPlugin, {file: 'myapp.conf'}); */ plugin<T>(plugin: (app: App, options: Record<string, any>) => T, options?: Record<string, any>): T; /** * Generate route matching only `POST` requests. * @example * // Route with destination * app.post('/user').to('User#create'); */ post(...args: RouteArguments): Route; /** * Generate route matching only `PUT` requests. * @example * // Route with destination * app.put('/user').to('User#replace'); */ put(...args: RouteArguments): Route; /** * Start the command line interface. * @example * // Get arguments from "process.argv" * app.start(); * * // Always start server (rarely used) * app.start('server', '-l', 'http://*:8080'); */ start(command?: string, ...args: string[]): Promise<void>; /** * Generate route for a nested route with its own intermediate destination. * @example * // Intermediate destination and prefix shared between two routes * const auth = app.under('/user').to('User#auth'); * auth.get('/show').to('User#show'); * auth.post('/create').to('User#create'); */ under(...args: AnyArguments): Route; /** * Warmup the cache, usually called automatically. */ warmup(): Promise<void>; /** * Generate route matching only WebSocket handshake requests. * @example * // Route with destination * app.websocket('/echo').to('Example#echo'); */ websocket(...args: RouteArguments): Route; } export {};