ExisJS

exisjs/plugin

The exisjs/plugin module provides tools and interfaces for authoring, typing, and distributing reusable ExisJS plugins, middleware packages, and third-party integrations.


Module Exports

import { definePlugin } from 'exisjs/plugin'import type {  ExisPlugin,  ExisPluginInstance,  HookReady,  HookClose,  HookRequest,  HookResponse,  HookError,  HookRoute,} from 'exisjs/plugin'

1. definePlugin(plugin)

The definePlugin helper wraps a plugin definition object and returns a hybrid callable object. This allows developers to register the plugin directly without options (app.register(myPlugin)) or invoke it as a factory function to pass configuration parameters (app.register(myPlugin({ apiKey: '...' }))).

function definePlugin<TOptions = Record<string, unknown>>(  plugin: ExisPlugin<TOptions>): ExisPlugin<TOptions> & ((options?: TOptions) => ExisPluginInstance)

Parameters

ParameterTypeDescription
pluginExisPlugin<TOptions>Object conforming to the ExisPlugin specification.

2. ExisPlugin<TOptions> Interface

The core specification contract for all plugins:

PropertyTypeDefaultDescription
namestring(Required)Unique identifier for the plugin. Used to detect duplicate registrations.
register(app: App, options?: TOptions) => void | Promise<void>(Required)Lifecycle method executed during app.register().
versionstringundefinedSemantic version string of the plugin package.
dependenciesstring[][]List of required plugin names that must be registered before this plugin boots.
encapsulatebooleanfalseWhen true, creates an isolated sub-router and dependency scope.

3. Authoring Plugins

Basic Plugin

src/plugins/request-logger.plugin.ts
import { definePlugin } from 'exisjs/plugin'
export const requestLoggerPlugin = definePlugin({  name: 'custom-request-logger',  version: '1.0.0',
  async register(app) {    app.use((req, res, next) => {      app.log.info({ method: req.method, url: req.url }, 'Incoming request')      next()    })  },})

Configurable Generic Plugin with Lifecycle Teardown

src/plugins/database.plugin.ts
import { definePlugin } from 'exisjs/plugin'import { Pool } from 'pg'
export interface DatabasePluginOptions {  connectionString: string  maxConnections?: number}
export const databasePlugin = definePlugin<DatabasePluginOptions>({  name: 'postgres-database-plugin',  version: '1.2.0',
  async register(app, options) {    if (!options?.connectionString) {      throw new Error('[databasePlugin] "connectionString" is required')    }
    const pool = new Pool({      connectionString: options.connectionString,      max: options.maxConnections ?? 10,    })
    await pool.connect()
    // Provide database pool to the DI container    app.provide('DB_POOL', { useValue: pool })
    // Register graceful shutdown hook    app.onClose(async () => {      await pool.end()    })  },})

Plugin with Dependencies

src/plugins/auth.plugin.ts
import { definePlugin } from 'exisjs/plugin'
export const authPlugin = definePlugin({  name: 'auth-plugin',  dependencies: ['postgres-database-plugin'], // Guarantees DB is registered first
  async register(app) {    const db = app.resolve('DB_POOL')    app.provide('AuthService', {      useFactory: () => new AuthService(db),    })  },})

4. Registering Plugins in Applications

Plugins can be registered in src/http/server.ts using app.register() or statically declared in exis.config.ts:

In src/http/server.ts

src/http/server.ts
import { exis } from 'exisjs'import { databasePlugin } from '../plugins/database.plugin'import { authPlugin } from '../plugins/auth.plugin'
export default exis({  async onStart(app) {    await app.register(      databasePlugin({        connectionString: process.env.DATABASE_URL!,        maxConnections: 20,      })    )    await app.register(authPlugin)  },})

In exis.config.ts

exis.config.ts
import { defineConfig } from 'exisjs/config'import { databasePlugin } from './src/plugins/database.plugin'import { authPlugin } from './src/plugins/auth.plugin'
export default defineConfig({  plugins: [    databasePlugin({      connectionString: process.env.DATABASE_URL!,    }),    authPlugin,  ],})