ctx.dataSourceManager

The Data Source Manager (DataSourceManager instance) is used to manage and access multiple data sources (e.g., the main database main, logging database logging, etc.). It is used when multiple data sources exist or when cross-data source metadata access is required.

Use Cases

ScenarioDescription
Multi-data sourceEnumerate all data sources, or get a specific data source by key.
Cross-data source accessAccess metadata using the "data source key + collection name" format when the data source of the current context is unknown.
Get fields by full pathUse the dataSourceKey.collectionName.fieldPath format to retrieve field definitions across different data sources.

Note: If you are only operating on the current data source, prioritize using ctx.dataSource. Use ctx.dataSourceManager only when you need to enumerate or switch between data sources.

Type Definition

dataSourceManager: DataSourceManager;

class DataSourceManager {
  constructor();

  // Data source management
  addDataSource(ds: DataSource | DataSourceOptions): void;
  upsertDataSource(ds: DataSource | DataSourceOptions): void;
  removeDataSource(key: string): void;
  clearDataSources(): void;

  // Read data sources
  getDataSources(): DataSource[];                     // Get all data sources
  getDataSource(key: string): DataSource | undefined;  // Get data source by key

  // Access metadata directly by data source + collection
  getCollection(dataSourceKey: string, collectionName: string): Collection | undefined;
  getCollectionField(fieldPathWithDataSource: string): CollectionField | undefined;
}

Relationship with ctx.dataSource

RequirementRecommended Usage
Single data source bound to the current contextctx.dataSource (e.g., the data source of the current page/block)
Entry point for all data sourcesctx.dataSourceManager
List or switch data sourcesctx.dataSourceManager.getDataSources() / getDataSource(key)
Get collection within the current data sourcectx.dataSource.getCollection(name)
Get collection across data sourcesctx.dataSourceManager.getCollection(dataSourceKey, collectionName)
Get field within the current data sourcectx.dataSource.getCollectionField('users.profile.avatar')
Get field across data sourcesctx.dataSourceManager.getCollectionField('main.users.profile.avatar')

Examples

Get a Specific Data Source

// Get the data source named 'main'
const mainDS = ctx.dataSourceManager.getDataSource('main');

// Get all collections under this data source
const collections = mainDS?.getCollections();

Access Collection Metadata Across Data Sources

// Get collection by dataSourceKey + collectionName
const users = ctx.dataSourceManager.getCollection('main', 'users');
const orders = ctx.dataSourceManager.getCollection('main', 'orders');

// Get the primary key of the collection
const primaryKey = users?.filterTargetKey ?? 'id';

Get Field Definition by Full Path

// Format: dataSourceKey.collectionName.fieldPath
// Get field definition by "data source key.collection name.field path"
const field = ctx.dataSourceManager.getCollectionField('main.users.profile.avatar');

// Supports association field paths
const userNameField = ctx.dataSourceManager.getCollectionField('main.orders.createdBy.name');

Iterate Through All Data Sources

const dataSources = ctx.dataSourceManager.getDataSources();
for (const ds of dataSources) {
  ctx.logger.info(`Data Source: ${ds.key}, Display Name: ${ds.displayName}`);
  const collections = ds.getCollections();
  for (const col of collections) {
    ctx.logger.info(`  - Collection: ${col.name}`);
  }
}

Dynamically Select Data Source Based on Variables

const dsKey = ctx.getVar('dataSourceKey') ?? 'main';
const collectionName = ctx.getVar('collectionName') ?? 'users';
const col = ctx.dataSourceManager.getCollection(dsKey, collectionName);
if (col) {
  const fields = col.getFields();
  // ...
}

Notes

  • The path format for getCollectionField is dataSourceKey.collectionName.fieldPath, where the first segment is the data source key, followed by the collection name and the field path.
  • getDataSource(key) returns undefined if the data source does not exist; it is recommended to perform a null check before use.
  • addDataSource will throw an exception if the key already exists; upsertDataSource will either overwrite the existing one or add a new one.