Skip to content

Global Adaptor Context

This document describes the global adaptor object available throughout the adaptor:ex framework. This object provides utility functions, error classes, and system-wide services that plugins, functions and other modules can access.

Overview

The adaptor object is a global namespace that contains:

  • Utility functions - Helper functions for common operations
  • Error classes - Custom error types for the framework
  • System services - Authentication, logging, plugin management, etc.
  • Configuration - Runtime configuration and metadata
  • Built-in plugins - Core plugin implementations

The adaptor object is initialized in adaptor.js and extended with additional properties during runtime in index.js.


Properties

Core Information

info

  • Type: Object
  • Description: NPM package information from package.json
  • Properties:
  • name - Package name
  • version - Current version
  • description - Package description
  • Plus other package.json fields
  • Read-only: Yes

Example:

console.log(`Running adaptor:ex version ${adaptor.info.version}`)


locale

  • Type: string
  • Description: System locale from Intl.DateTimeFormat().resolvedOptions().locale
  • Read-only: Yes
  • Example: 'en-US', 'de-DE'

python

  • Type: string
  • Description: Python command to use for executing Python scripts
  • Default:
    • 'python' on Windows
    • 'python3' on Unix/Linux/Mac
  • Read-only: No (can be overridden in config)

Example:

const { execSync } = require('child_process');
execSync(`${adaptor.python} script.py`);


Configuration Properties

These properties come from the config file and are assigned to adaptor during initialization:

data

  • Type: string
  • Description: Absolute path to the data directory where games and plugins are stored
  • Default: './adaptorex'
  • Read-only: Yes
  • Example: '/var/lib/adaptor'

host

  • Type: string
  • Description: Host URL/IP for the server
  • Read-only: Yes
  • Example: 'http://localhost'

port

  • Type: number
  • Description: Port number the server is running on
  • Read-only: Yes
  • Example: 3000

url

  • Type: string | undefined
  • Description: Optional remote URL for the server (for public access)
  • Read-only: Yes
  • Example: 'https://myserver.com'

authentication

  • Type: string
  • Description: Authentication method being used
  • Values: 'basic', 'disabled', or undefined
  • Read-only: Yes

headless

  • Type: boolean
  • Description: Whether the server is running in headless mode (not itself hosting the web interface)
  • Read-only: Yes

whitelist

  • Type: Array<string> | undefined
  • Description: CORS whitelist of allowed origins
  • Read-only: Yes

System Services

auth

  • Type: BasicAuth | NoAuth
  • Description: Authentication service instance
  • Methods:

    • authenticate(req, res, next) - Express middleware for authentication
    • authenticateSocket(socket, next) - Socket.io middleware for authentication
    • getUser(config, username) - Get user information
  • Read-only: Yes

Example:

// In Express route
app.get('/protected', adaptor.auth.authenticate, (req, res) => {
  res.json({ user: req.user });
});

// In Socket.io namespace
const namespace = adaptor.io.of('/custom')
namespace.use(adaptor.auth.authenticateSocket.bind(adaptor.auth))

io

  • Type: socket.io.Server
  • Description: Socket.io server instance for real-time communication
  • Read-only: Yes

Example:

// Create a custom namespace
const myNamespace = adaptor.io.of(`/${game.name}/my-plugin/my-namespace`)

myNamespace.on('connection', (socket) => {
  console.log('Client connected:', socket.id)

  socket.on('custom-event', (data) => {
    // Handle event
  })
})

openapi

  • Type: Object
  • Description: Dereferenced OpenAPI specification document for the REST API
  • Read-only: Yes

asyncapi

  • Type: Object
  • Description: Dereferenced AsyncAPI specification document for Socket.IO Socket API
  • Read-only: Yes

webhooks

  • Type: Array<Object>
  • Description: List of available webhook endpoints
  • Structure: Each webhook object contains:
    • name (string) - Identifier (e.g., 'local', 'remote')
    • title (string) - Display name
    • url (string) - Full URL
  • Read-only: No (can add webhooks)
  • Note: Use game.getWebhookURLs() to get custom webhook URLs for your plugin

Example:

// Available webhooks
for (const webhook of adaptor.webhooks) {
  console.log(`${webhook.title}: ${webhook.url}`);
}
// Output:
// Local: http://localhost:3000
// eth0: http://192.168.1.100:3000
// Remote: https://myserver.com

Built-in Plugins

messenger

  • Type: Object
  • Description: Built-in messenger plugin module
  • Read-only: Yes

logic

  • Type: Object
  • Description: Built-in logic plugin module
  • Read-only: Yes

socketio

  • Type: Object
  • Description: Built-in socket.io plugin module
  • Read-only: Yes

Plugin

  • Type: Class
  • Description: Base Plugin class for creating plugins
  • Read-only: Yes

PluginItem

  • Type: Class
  • Description: Base PluginItem class for plugin data items
  • Read-only: Yes

Utility Functions

parseJSON(str)

Parses JSON strings.

Parameters: - str (string) - JSON string to parse

Returns: Object | null - Parsed object or undifined if parsing fails

Description: Makes the static function Variables.parseJSON globally available.


parseQuery(query)

Parses and resolves variable references in MongoDB-style queries.

Parameters:

  • query (Object | string) - Query object or string to parse

Returns: Object - Parsed query object

Description: Makes the static function Variables.parseQuery globally available.


now()

Returns the current date and time.

Parameters: None

Returns: Date - Current date/time as Date object

Description: Centralized function for getting current time. Useful for consistency across the framework.

Example:

const timestamp = adaptor.now()
console.log('Current time:', timestamp)

userInfo()

Returns information about the current OS user.

Parameters: None

Returns: Object - User information from os.userInfo()

  • username - Username
  • uid - User ID (Unix)
  • gid - Group ID (Unix)
  • shell - User's shell
  • homedir - Home directory

Example:

const user = adaptor.userInfo();
console.log('Running as:', user.username);

getPlugin(name)

Retrieves plugin module and (if not yet installed) installs the plugin by name.

Parameters:

  • name (string) - Plugin name

Returns: Object | undefined - Plugin module or undefined if not installed

Description: Access installed plugin modules from the plugin manager. You probably don't want this. Instead use game.getPlugin(name) to get the plugin instance instead.


getAvailablePlugins()

Lists all available plugins (installed and not installed).

Parameters: None

Returns: Array<Object> - Array of plugin information objects

Description: Returns information about all plugins available in the plugin directory, whether installed or not.

Example:

const plugins = adaptor.getAvailablePlugins();
plugins.forEach(plugin => {
  console.log(`${plugin.name} v${plugin.version}`);
});

createId()

Generates a short unique identifier.

Parameters: None

Returns: string - 8-character unique ID

Description: Uses nanoid to generate short, URL-safe unique identifiers.

Example:

const sessionId = adaptor.createId();
// Returns: "x3K9mP2n" (8 characters)

isInt(value)

Checks if a value is an integer or can be parsed as one.

Parameters:

  • value (string | number) - Value to check

Returns: boolean - true if value is an integer or parseable to integer

Example:

adaptor.isInt(42);        // true
adaptor.isInt("42");      // true
adaptor.isInt(42.5);      // false
adaptor.isInt("42.5");    // false
adaptor.isInt("abc");     // false


isEmpty(obj)

Checks if an object has any own properties.

Parameters:

  • obj (Object) - Object to check

Returns: boolean - true if object has no own properties

Example:

adaptor.isEmpty({});              // true
adaptor.isEmpty({ key: 'value' }); // false

hasOwnProperties(obj, properties)

Checks if an object has all specified properties.

Parameters:

  • obj (Object) - Object to check
  • properties (Array<string>) - Array of property names

Returns: boolean - true if all properties exist on the object

Example:

const obj = { name: 'Alice', age: 30 };

adaptor.hasOwnProperties(obj, ['name', 'age']); // true
adaptor.hasOwnProperties(obj, ['name', 'email']); // false

getPath(obj, path)

Accesses nested object properties using dot notation.

Parameters:

  • obj (Object) - Object to traverse
  • path (string) - Dot-separated path (e.g., 'user.profile.name')

Returns: * | undefined - Value at path, or undefined if path doesn't exist

Description: Safely access nested properties. Also supports array index notation.

Example:

const data = {
  user: {
    profile: {
      name: 'Alice',
      scores: [10, 20, 30]
    }
  }
};

adaptor.getPath(data, 'user.profile.name');      // 'Alice'
adaptor.getPath(data, 'user.profile.scores[1]'); // 20
adaptor.getPath(data, 'user.invalid.path');      // undefined

assignPath(obj, path, value)

Sets a nested object property using dot notation.

Parameters:

  • obj (Object) - Object to modify
  • path (string or Array<string>) - Dot-separated path
  • value (*) - Value to assign

Returns: void

Description: Creates intermediate objects as needed to set the value at the specified path.

Example:

const obj = {};
adaptor.assignPath(obj, 'user.profile.name', 'Alice');
// Result: { user: { profile: { name: 'Alice' } } }

adaptor.assignPath(obj, 'user.profile.age', 30);
// Result: { user: { profile: { name: 'Alice', age: 30 } } }

equalValues(objA, objB)

Checks if two objects have equal values (shallow comparison via JSON).

Parameters:

  • objA (Object) - First object
  • objB (Object) - Second object

Returns: boolean - true if objects are equal

Warning: Uses JSON.stringify, so property order matters and complex objects (functions, dates, etc.) may not compare correctly. Adaptor:ex now always installs with lodash, so please use _.isEqual() instead.


changes(original, changed)

Compares two objects and returns what changed.

Parameters:

  • original (Object) - Original object
  • changed (Object) - Modified object

Returns: Object - Change summary

  • updated (Object) - Properties that changed or are new
  • removed (Array<string>) - Properties that were removed

Example:

const original = { a: 1, b: 2, c: 3 }
const changed = { a: 1, b: 3, d: 4 }

const diff = adaptor.changes(original, changed)
// Returns: {
//   updated: { b: 3, d: 4 },
//   removed: ['c']
// }

deepClone(obj)

Creates a deep clone of an object with no references.

Parameters:

  • obj (Object) - Object to clone

Returns: Object - Deep clone of the object

Warning: Uses JSON serialization, so functions, Dates, RegExp, and other complex types won't be cloned correctly. Adaptor:ex now always installs with lodash, so please use _.cloneDeep() instead.


dereference(schemaOrPath)

Resolves $ref references in JSON schemas.

Parameters:

  • schemaOrPath (Object | string) - Schema object or file path to dereference

Returns: Promise<Object> - Dereferenced schema

Description: Uses @apidevtools/json-schema-ref-parser to resolve all $ref references in a JSON schema.

Example:

const schema = {
  type: 'object',
  properties: {
    user: { $ref: '#/definitions/User' }
  },
  definitions: {
    User: { type: 'object', properties: { name: { type: 'string' } } }
  }
}

const resolved = await adaptor.dereference(schema)
// $ref replaced with actual definition

isObject(value)

Checks if a value is a plain object (not array, not null).

Parameters:

  • value (*) - Value to check

Returns: boolean - true if value is a plain object

Example:

adaptor.isObject({});           // true
adaptor.isObject({ a: 1 });     // true
adaptor.isObject([]);           // false
adaptor.isObject(null);         // false
adaptor.isObject('string');     // false

getIPs()

Gets all IPv4 addresses of the system.

Parameters: None

Returns: Object - Dictionary of interface names to IP addresses

  • Keys: Network interface names
  • Values: Arrays of IP addresses

Example:

const ips = adaptor.getIPs()
// Returns: {
//   'eth0': ['192.168.1.100'],
//   'wlan0': ['192.168.1.101']
// }

Error Classes

All error classes extend the base AdaptorError and are available as properties on adaptor. The adaptor editor will also show error "causes". So if you are rethrowing an error with additional information, append the original error in the cause property:

catch (originalError) {
  throw new adaptor.AdaptorError('Something went wrong at my-plugin', { cause: originalError })
}

AdaptorError

Base error class for all adaptor:ex errors.

Properties:

  • name (string) - Error name
  • message (string) - Error message

Constructor:

new adaptor.AdaptorError(message)

Example:

throw new adaptor.AdaptorError('Something went wrong')

NotFoundError

Error for resources that cannot be found (404).

Constructor:

new adaptor.NotFoundError(message)

Example:

const session = game.findSession('name', sessionName)
if (!session) {
  throw new adaptor.NotFoundError(`Session ${sessionName} not found`)
}

InvalidError

Error for invalid input or validation failures (400).

Constructor:

new adaptor.InvalidError(message)

Example:

if (!payload.required_field) {
  throw new adaptor.InvalidError('required_field is missing')
}

DuplicateError

Error for duplicate resource creation.

Constructor:

new adaptor.DuplicateError(message)

Example:

if (existingUser) {
  throw new adaptor.DuplicateError(`User ${username} already exists`)
}

ForbiddenError

Error for forbidden operations.

Constructor:

new adaptor.ForbiddenError(message)

Example:

if (reservedNames.includes(name)) {
  throw new adaptor.ForbiddenError(`Name '${name}' is reserved`)
}

OutdatedError

Error for outdated resources.

Constructor:

new adaptor.OutdatedError(message)

Example:

if (operation.updatedAt < Date.now() - 24 * 60 * 60 * 1000) {
  throw new adaptor.OutdatedError('Operation is outdated')
}

ConnectionError

Error for connection failures.

Constructor:

new adaptor.ConnectionError(message)

Example:

try {
  await fetch('https://example.com')
} catch (error) {
  throw new adaptor.ConnectionError('Failed to connect to example.com', { cause: error })
}

LimitReachedError

Error for resource limit reached.

Constructor:

new adaptor.LimitReachedError(message)

Example:

if (users.length >= 100) {
  throw new adaptor.LimitReachedError('User limit reached')
}

Utility Classes

Log

Logging system with levels, file output, and real-time streaming.

Access: log (global) or adaptor.log

Log Levels:

  • trace - Most verbose
  • debug - Debug information
  • info - General information
  • warn - Warnings
  • error - Errors
  • silent - No logging

Methods:

  • trace(prefix, message, ...args) - Log trace message
  • debug(prefix, message, ...args) - Log debug message
  • info(prefix, message, ...args) - Log info message
  • warn(prefix, message, ...args) - Log warning message
  • error(prefix, message, ...args) - Log error message
  • setLevel(level) - Change log level
  • getContextLog(context) - Get logger with prepended context

Example:

log.info('my-plugin', 'Plugin initialized')
log.debug('my-plugin', 'Processing data:', data)
log.error('my-plugin', 'Something failed')

// Context logger
const contextLog = log.getContextLog('my-game my-plugin my-subsystem')
contextLog('Starting...') // Uses debug level
contextLog.info('Ready')
contextLog.error('Failed')

Queue

FIFO queue with callback execution.

Constructor:

new adaptor.Queue(callback)

Parameters:

  • callback (Function) - Function to call for each queued item

Methods:

  • put(item, returnCallback) - Add item to queue
  • join() - Wait for queue to finish
  • cancel() - Cancel queue after current item

Example:

const queue = new adaptor.Queue(async (item) => {
  // Process item
  await processItem(item)
  return { success: true }
})

// Add items
queue.put(item1, (result) => {
  console.log('Item 1 processed:', result)
})

queue.put(item2, (result) => {
  console.log('Item 2 processed:', result)
})

// Wait for completion
await queue.join()