Database

Database is a core component of database-type data sources (DataSource). Each database-type data source has a corresponding Database instance, accessible via dataSource.db. The main data source's database instance also has a convenient alias app.db. Familiarizing yourself with db's common methods is fundamental to writing server-side plugins.

Database Components

A typical Database consists of the following parts:

  • Collection: Defines data table structure.
  • Model: Corresponds to ORM models (usually managed by Sequelize).
  • Repository: Repository layer that encapsulates data access logic, providing higher-level operation methods.
  • FieldType: Field types.
  • FilterOperator: Operators used for filtering.
  • Event: Lifecycle events and database events.

Usage Timing in Plugins

Things Suitable for the beforeLoad Stage

At this stage, database operations cannot be performed yet. It is suitable for static class registration or event listening.

  • db.registerFieldTypes() - Register custom field types
  • db.registerModels() - Register custom model classes
  • db.registerRepositories() - Register custom repository classes
  • db.registerOperators() - Register custom filter operators
  • db.on() - Listen to database-related events

Things Suitable for the load Stage

At this stage, all preceding class definitions and events have been loaded, so loading data tables won't have missing or omitted dependencies.

  • db.defineCollection() - Define new data tables
  • db.extendCollection() - Extend existing data table configurations

However, for defining plugin built-in tables, it's more recommended to place them in the ./src/server/collections directory. See Collections.

Data Operations

Database provides two main ways to access and operate data:

Operations via Repository

const repo = db.getRepository('users');
const user = await repo.findOne({ filter: { id: 1 } });

The Repository layer is typically used to encapsulate business logic, such as pagination, filtering, permission checks, etc.

Operations via Model

const UserModel = db.getModel('users');
const user = await UserModel.findByPk(1);

The Model layer directly corresponds to ORM entities, suitable for lower-level database operations.

Which Stages Allow Database Operations?

Plugin Lifecycle

StageDatabase Operations Allowed
staticImportNo
afterAddNo
beforeLoadNo
loadNo
installYes
beforeEnableYes
afterEnableYes
beforeDisableYes
afterDisableYes
removeYes
handleSyncMessageYes

App Events

StageDatabase Operations Allowed
beforeLoadNo
afterLoadNo
beforeStartYes
afterStartYes
beforeInstallNo
afterInstallYes
beforeStopYes
afterStopNo
beforeDestroyYes
afterDestroyNo
beforeLoadPluginNo
afterLoadPluginNo
beforeEnablePluginYes
afterEnablePluginYes
beforeDisablePluginYes
afterDisablePluginYes
afterUpgradeYes

Database Events/Hooks

StageDatabase Operations Allowed
beforeSyncNo
afterSyncYes
beforeValidateYes
afterValidateYes
beforeCreateYes
afterCreateYes
beforeUpdateYes
afterUpdateYes
beforeSaveYes
afterSaveYes
beforeDestroyYes
afterDestroyYes
afterCreateWithAssociationsYes
afterUpdateWithAssociationsYes
afterSaveWithAssociationsYes
beforeDefineCollectionNo
afterDefineCollectionNo
beforeRemoveCollectionNo
afterRemoveCollectionNo
  • Collections - Define or extend data table structures with code
  • DataSourceManager - Manage multiple data sources and their database instances
  • Context - Access the db instance in requests
  • Plugin - Plugin class lifecycle, member methods, and the app object
  • Event - Application-level and database-level event listening and handling