Skip to content

Introduction

Controller module. Loads controller files from electron/controller/ and converts exported classes into callable method mapping objects. Each frontend IPC request is routed to a corresponding controller method via the {controller}/{name}/{method} channel format.

The module provides both synchronous loading (loadController, for CJS projects) and asynchronous loading (loadControllerAsync, for ESM projects). A thread-safety flag prevents concurrent sync/async loading — calling a synchronous method during async loading throws an error.

Two loading modes are supported internally:

  • Bundle mode (registry): reads pre-registered controller modules from globalThis.__EE_CONTROLLER_REGISTRY__, populated by the esbuild plugin during build.
  • Dev mode (filesystem): scans the filesystem recursively using scanDirSync / scanDirAsync.

Class controllers are processed by wrapClass(), which traverses the prototype chain and converts each method to a middleware function via methodToMiddleware(). Each middleware invocation creates a new controller instance, ensuring concurrency safety when multiple requests arrive simultaneously.

Export structure example:

controller/
  user.js          -> { controller: { user: { add: fn, delete: fn } } }
  admin/login.js   -> { controller: { admin: { login: { auth: fn } } } }

Import

Both CJS and ESM:

javascript
// ESM
import { loadController, loadControllerAsync, getControllers, getController } from 'ee-core/controller';
// CJS
const { loadController, loadControllerAsync, getControllers, getController } = require('ee-core/controller');

API

loadController()

Description: Load controllers synchronously. Uses require() to load all controller files, suitable for CJS projects. Internally creates a ControllerLoader instance and calls its load() method, which checks for globalThis.__EE_CONTROLLER_REGISTRY__ (bundle mode) first, then falls back to filesystem scanning (dev mode) with caseStyle: 'lower'. Parameters: None Returns: Record<string, unknown> — Controller method mapping object, structured as { controller: { module: { method: fn } } }Example:

javascript
import { loadController } from 'ee-core/controller';

const controllers = loadController();
// Result: { controller: { user: { add: fn, delete: fn } } }

See also: ControllerLoader class in ee-core/controller/controller_loader

loadControllerAsync()

Description: Load controllers asynchronously. Uses dynamic import() to load all controller files, suitable for ESM projects. Sets an internal loading flag during the async operation to prevent concurrent synchronous loading. The flag is cleared in a finally block, ensuring it resets even if loading fails. Parameters: None Returns: Promise<Record<string, unknown>> — Controller method mapping object, structured as { controller: { module: { method: fn } } }Example:

javascript
import { loadControllerAsync } from 'ee-core/controller';

const controllers = await loadControllerAsync();

getControllers()

Description: Get all loaded controllers. If controllers have not been loaded yet, synchronous loading (loadController()) is automatically triggered. Throws an error if async loading is currently in progress — in that case, you must await loadControllerAsync() before accessing controllers. Parameters: None Returns: Record<string, unknown> — Controller method mapping object Example:

javascript
import { getControllers } from 'ee-core/controller';

const controllers = getControllers();

getController()

Description: Alias for getControllers(). Returns the same controller method mapping object. Parameters: None Returns: Record<string, unknown> — Controller method mapping object Example:

javascript
import { getController } from 'ee-core/controller';

const controllers = getController();

See also: getControllers


ControllerLoader class

Internal loader class that handles the actual controller file scanning and method wrapping. Exported from ee-core/controller/controller_loader for advanced use.

javascript
// ESM
import { ControllerLoader } from 'ee-core/controller/controller_loader';
// CJS
const { ControllerLoader } = require('ee-core/controller/controller_loader');

ControllerLoader.constructor()

Description: Creates a new ControllerLoader instance with an internal Timing object for performance tracking. Parameters: None Returns: ControllerLoader instance

ControllerLoader.load()

Description: Synchronous controller loading. Checks for globalThis.__EE_CONTROLLER_REGISTRY__ first (bundle mode); if absent, falls back to filesystem scanning (dev mode). Uses FileLoader with caseStyle: 'lower' and a custom initializer that wraps class controllers via wrapClass(). Records timing via Timing.start() / Timing.end(). Parameters: None Returns: Record<string, unknown> — Controller method mapping object, structured as { controller: { module: { method: fn } } }

ControllerLoader.loadAsync()

Description: Asynchronous controller loading (ESM support). Same flow as load(), but uses FileLoader.loadAsync() which uses import() instead of require() for file loading. Records timing via Timing.start() / Timing.end(). Parameters: None Returns: Promise<Record<string, unknown>> — Controller method mapping object