@datocms/cma-client
Version:
JS client for DatoCMS REST Content Management API
330 lines (329 loc) • 14.8 kB
TypeScript
import type * as ApiTypes from '../generated/ApiTypes';
import type * as RawApiTypes from '../generated/RawApiTypes';
interface GenericClient {
itemTypes: {
rawList(): Promise<{
data: RawApiTypes.ItemType[];
}>;
};
fields: {
rawList(itemTypeId: string): Promise<{
data: RawApiTypes.Field[];
}>;
rawReferencing(itemTypeId: string): Promise<{
data: RawApiTypes.Field[];
}>;
};
fieldsets: {
rawList(itemTypeId: string): Promise<{
data: RawApiTypes.Fieldset[];
}>;
};
plugins: {
rawList(): Promise<{
data: RawApiTypes.Plugin[];
}>;
};
site: {
rawFind(params: {
include: string;
}): Promise<{
data: any;
included?: Array<RawApiTypes.ItemType | RawApiTypes.Field | any>;
}>;
};
}
/**
* Repository for DatoCMS schema entities including item types, fields, and plugins.
* Provides caching and efficient lookup functionality for schema-related operations.
*
* ## Purpose
*
* SchemaRepository is designed to solve the performance problem of repeatedly fetching
* the same schema information during complex operations that traverse nested blocks,
* structured text, or modular content. It acts as an in-memory cache/memoization layer
* for schema entities to avoid redundant API calls.
*
* ## What it's for:
*
* - **Caching schema entities**: Automatically caches item types, fields, fieldsets,
* and plugins after the first API request, returning cached results on subsequent calls
* - **Complex traversal operations**: Essential when using utilities like
* `mapBlocksInNonLocalizedFieldValue()` that need to repeatedly lookup block models and fields
* while traversing nested content structures
* - **Bulk operations**: Ideal for scripts that process multiple records of different
* types and need efficient access to schema information
* - **Read-heavy workflows**: Perfect for scenarios where you need to repeatedly access
* the same schema information without making redundant API calls
*
* ## What it's NOT for:
*
* - **Schema modification**: Do NOT use SchemaRepository if your script modifies models,
* fields, fieldsets, or plugins, as the cache will become stale
* - **Record/content operations**: This is only for schema entities, not for records,
* uploads, or other content
* - **Long-running applications**: The cache has no expiration or invalidation mechanism,
* so it's not suitable for applications that need fresh schema data over time
* - **Concurrent schema changes**: No protection against cache inconsistency if other
* processes modify the schema while your script runs
*
* ## Usage Pattern
*
* ```typescript
* const schemaRepository = new SchemaRepository(client);
*
* // These calls will hit the API and cache the results
* const models = await schemaRepository.getAllModels();
* const blogPost = await schemaRepository.getItemTypeByApiKey('blog_post');
*
* // These subsequent calls will return cached results (no API calls)
* const sameModels = await schemaRepository.getAllModels();
* const sameBlogPost = await schemaRepository.getItemTypeByApiKey('blog_post');
*
* // Pass the repository to utilities that need schema information
* await mapBlocksInNonLocalizedFieldValue(schemaRepository, record, (block) => {
* // The utility will use the cached schema data internally
* });
* ```
*
* ## Performance Benefits
*
* Without SchemaRepository, a script processing structured text with nested blocks
* might make the same `client.itemTypes.list()` or `client.fields.list()` calls
* dozens of times. SchemaRepository ensures each unique schema request is made only once.
*
* ## Best Practices
*
* - Use SchemaRepository consistently throughout your script — if you need it for one
* utility call, use it for all schema operations to maximize cache efficiency
* - Create one instance per script execution, not per operation
* - Only use when you have read-only access to schema entities
* - Consider using optimistic locking for any record updates to handle potential
* version conflicts when working with cached schema information
*/
export declare class SchemaRepository {
private client;
private itemTypesPromise;
private itemTypesByApiKey;
private itemTypesById;
private fieldsByItemType;
private fieldsetsByItemType;
private pluginsPromise;
private pluginsById;
private pluginsByPackageName;
private prefetchPromise;
/**
* Creates a new SchemaRepository instance.
* @param client - The DatoCMS client instance
*/
constructor(client: GenericClient);
/**
* Loads and caches all item types from the DatoCMS API.
* This method is called lazily and caches the result for subsequent calls.
* @returns Promise that resolves to an array of item types
*/
private loadItemTypes;
/**
* Gets all item types from the DatoCMS project.
* @returns Promise that resolves to an array of all item types
*/
getAllItemTypes(): Promise<ApiTypes.ItemType[]>;
/**
* Gets all item types from the DatoCMS project.
* @returns Promise that resolves to an array of all item types
*/
getAllRawItemTypes(): Promise<RawApiTypes.ItemType[]>;
/**
* Gets all item types that are models (not modular blocks).
* @returns Promise that resolves to an array of model item types
*/
getAllModels(): Promise<ApiTypes.ItemType[]>;
/**
* Gets all item types that are models (not modular blocks).
* @returns Promise that resolves to an array of model item types
*/
getAllRawModels(): Promise<RawApiTypes.ItemType[]>;
/**
* Gets all item types that are modular blocks.
* @returns Promise that resolves to an array of block model item types
*/
getAllBlockModels(): Promise<ApiTypes.ItemType[]>;
/**
* Gets all item types that are modular blocks.
* @returns Promise that resolves to an array of block model item types
*/
getAllRawBlockModels(): Promise<RawApiTypes.ItemType[]>;
/**
* Gets an item type by its API key.
* @param apiKey - The API key of the item type to retrieve
* @returns Promise that resolves to the item type
* @throws Error if the item type is not found
*/
getItemTypeByApiKey(apiKey: string): Promise<ApiTypes.ItemType>;
/**
* Gets an item type by its API key.
* @param apiKey - The API key of the item type to retrieve
* @returns Promise that resolves to the item type
* @throws Error if the item type is not found
*/
getRawItemTypeByApiKey(apiKey: string): Promise<RawApiTypes.ItemType>;
/**
* Gets an item type by its ID.
* @param id - The ID of the item type to retrieve
* @returns Promise that resolves to the item type
* @throws Error if the item type is not found
*/
getItemTypeById(id: string): Promise<ApiTypes.ItemType>;
/**
* Gets an item type by its ID.
* @param id - The ID of the item type to retrieve
* @returns Promise that resolves to the item type
* @throws Error if the item type is not found
*/
getRawItemTypeById(id: string): Promise<RawApiTypes.ItemType>;
/**
* Gets all fields for a given item type.
* Fields are cached after the first request for performance.
* @param itemType - The item type to get fields for
* @returns Promise that resolves to an array of fields
*/
getItemTypeFields(itemType: ApiTypes.ItemType | RawApiTypes.ItemType): Promise<ApiTypes.Field[]>;
/**
* Gets all fields for a given item type.
* Fields are cached after the first request for performance.
* @param itemType - The item type to get fields for
* @returns Promise that resolves to an array of fields
*/
getRawItemTypeFields(itemType: ApiTypes.ItemType | RawApiTypes.ItemType): Promise<RawApiTypes.Field[]>;
/**
* Gets all fieldsets for a given item type.
* Fieldsets are cached after the first request for performance.
* @param itemType - The item type to get fieldsets for
* @returns Promise that resolves to an array of fieldsets
*/
getItemTypeFieldsets(itemType: ApiTypes.ItemType | RawApiTypes.ItemType): Promise<ApiTypes.Fieldset[]>;
/**
* Gets all fieldsets for a given item type.
* Fieldsets are cached after the first request for performance.
* @param itemType - The item type to get fieldsets for
* @returns Promise that resolves to an array of fieldsets
*/
getRawItemTypeFieldsets(itemType: ApiTypes.ItemType | RawApiTypes.ItemType): Promise<RawApiTypes.Fieldset[]>;
/**
* Loads and caches all plugins from the DatoCMS API.
* This method is called lazily and caches the result for subsequent calls.
* @returns Promise that resolves to an array of plugins
*/
private loadPlugins;
/**
* Gets all plugins from the DatoCMS project.
* @returns Promise that resolves to an array of all plugins
*/
getAllPlugins(): Promise<ApiTypes.Plugin[]>;
/**
* Gets all plugins from the DatoCMS project.
* @returns Promise that resolves to an array of all plugins
*/
getAllRawPlugins(): Promise<RawApiTypes.Plugin[]>;
/**
* Gets a plugin by its ID.
* @param id - The ID of the plugin to retrieve
* @returns Promise that resolves to the plugin
* @throws Error if the plugin is not found
*/
getPluginById(id: string): Promise<ApiTypes.Plugin>;
/**
* Gets a plugin by its ID.
* @param id - The ID of the plugin to retrieve
* @returns Promise that resolves to the plugin
* @throws Error if the plugin is not found
*/
getRawPluginById(id: string): Promise<RawApiTypes.Plugin>;
/**
* Gets a plugin by its package name.
* @param packageName - The package name of the plugin to retrieve
* @returns Promise that resolves to the plugin
* @throws Error if the plugin is not found
*/
getPluginByPackageName(packageName: string): Promise<ApiTypes.Plugin>;
/**
* Gets a plugin by its package name.
* @param packageName - The package name of the plugin to retrieve
* @returns Promise that resolves to the plugin
* @throws Error if the plugin is not found
*/
getRawPluginByPackageName(packageName: string): Promise<RawApiTypes.Plugin>;
/**
* Prefetches all models and their fields in a single optimized API call.
* This method populates the internal caches for both item types and fields,
* making subsequent lookups very fast without additional API calls.
*
* This is more efficient than lazy loading when you know you'll need access
* to multiple models and fields, as it reduces the number of API requests
* from potentially dozens down to just one.
*
* @returns Promise that resolves when all data has been fetched and cached
*/
prefetchAllModelsAndFields(): Promise<void>;
/**
* Gets all models that directly or indirectly embed the given block models.
* This method recursively traverses the schema to find all models that reference
* the provided blocks, either directly through block fields or indirectly through
* other block models that reference them.
*
* @param blocks - Array of block models to find references to
* @returns Promise that resolves to array of models that embed these blocks
*/
getRawModelsEmbeddingBlocks(blocks: Array<ApiTypes.ItemType | RawApiTypes.ItemType>): Promise<Array<RawApiTypes.ItemType>>;
/**
* Gets all models that directly or indirectly embed the given block models.
* This method recursively traverses the schema to find all models that reference
* the provided blocks, either directly through block fields or indirectly through
* other block models that reference them.
*
* @param blocks - Array of block models to find references to
* @returns Promise that resolves to array of models that embed these blocks
*/
getModelsEmbeddingBlocks(blocks: Array<ApiTypes.ItemType | RawApiTypes.ItemType>): Promise<Array<ApiTypes.ItemType>>;
/**
* Gets all block models that are directly or indirectly nested within the given item types.
* This method recursively traverses the schema to find all blocks that are nested
* within the provided item types, either directly through block fields or indirectly through
* other nested block models.
*
* @param itemTypes - Array of item types to find nested blocks for
* @returns Promise that resolves to array of all block models nested in these item types
*/
getRawNestedBlocks(itemTypes: Array<ApiTypes.ItemType | RawApiTypes.ItemType>): Promise<Array<RawApiTypes.ItemType>>;
/**
* Gets all block models that are directly or indirectly nested within the given item types.
* This method recursively traverses the schema to find all blocks that are nested
* within the provided item types, either directly through block fields or indirectly through
* other nested block models.
*
* @param itemTypes - Array of item types to find nested blocks for
* @returns Promise that resolves to array of all block models nested in these item types
*/
getNestedBlocks(itemTypes: Array<ApiTypes.ItemType | RawApiTypes.ItemType>): Promise<Array<ApiTypes.ItemType>>;
/**
* Gets all models that are directly or indirectly nested/referenced within the given item types.
* This method recursively traverses the schema to find all models that are referenced
* by the provided item types through link fields, either directly or indirectly through
* other referenced blocks.
*
* @param itemTypes - Array of item types to find nested models for
* @returns Promise that resolves to array of all models nested in these item types
*/
getRawNestedModels(itemTypes: Array<ApiTypes.ItemType | RawApiTypes.ItemType>): Promise<Array<RawApiTypes.ItemType>>;
/**
* Gets all models that are directly or indirectly nested/referenced within the given item types.
* This method recursively traverses the schema to find all models that are referenced
* by the provided item types through link fields, either directly or indirectly through
* other referenced blocks.
*
* @param itemTypes - Array of item types to find nested models for
* @returns Promise that resolves to array of all models nested in these item types
*/
getNestedModels(itemTypes: Array<ApiTypes.ItemType | RawApiTypes.ItemType>): Promise<Array<ApiTypes.ItemType>>;
}
export {};