UNPKG

@webiny/api-headless-cms-ddb-es

Version:

DynamoDB and Elasticsearch storage operations plugin for Headless CMS API.

188 lines (187 loc) 7.71 kB
import { createTable, registerExtension as registerDynamoDbExtension } from "@webiny/db-dynamodb"; import { StorageOperationsFactory as StorageOperationsFactoryAbstraction } from "@webiny/api-headless-cms/exports/api/cms/storage.js"; import { ENTITIES } from "./types.js"; import { createRegisterExtensionPlugin } from "@webiny/handler"; import { createFeature } from "@webiny/feature/api/index.js"; import { CmsEntryOpenSearchValueSearchFeature, CmsEntryOpenSearchValueSearchRegistry } from "./features/CmsEntryOpenSearchValueSearch/index.js"; import { CmsEntryOpenSearchIndex, CmsEntryOpenSearchIndexFeature } from "./features/CmsEntryOpenSearchIndex/index.js"; import { createModelsStorageOperations } from "./operations/model/index.js"; import { createEntriesStorageOperations } from "./operations/entry/index.js"; import { createGroupEntity } from "./definitions/group.js"; import { createModelEntity } from "./definitions/model.js"; import { createEntryEntity } from "./definitions/entry.js"; import { createElasticsearchIndex } from "./elasticsearch/createElasticsearchIndex.js"; import { createGroupsStorageOperations } from "./operations/group/index.js"; import { createOpenSearchEntity, createOpenSearchTable } from "@webiny/api-opensearch"; import { deleteElasticsearchIndex } from "./elasticsearch/deleteElasticsearchIndex.js"; import { createCreateIndexTask } from "./tasks/createIndexTaskPlugin.js"; import { ModelAfterCreateEventHandler } from "@webiny/api-headless-cms/features/contentModel/CreateModel/index.js"; import { ModelAfterCreateFromEventHandler } from "@webiny/api-headless-cms/features/contentModel/CreateModelFrom/events.js"; import { ModelAfterDeleteEventHandler } from "@webiny/api-headless-cms/features/contentModel/DeleteModel/events.js"; import { CmsModelFieldToGraphQLRegistry } from "@webiny/api-headless-cms/exports/api/cms/graphql.js"; import { CompressionHandler } from "@webiny/utils/exports/api.js"; import { CmsEntryOpenSearchBodyModifier } from "./features/CmsEntryOpenSearchBodyModifier/index.js"; import { CmsEntryOpenSearchSortModifier } from "./features/CmsEntryOpenSearchSortModifier/index.js"; import { CmsEntryOpenSearchQueryModifier } from "./features/CmsEntryOpenSearchQueryModifier/index.js"; import { CmsEntryOpenSearchFullTextSearch } from "./features/CmsEntryOpenSearchFullTextSearch/index.js"; import { CmsEntryOpenSearchValuesModifier } from "./features/CmsEntryOpenSearchValuesModifier/index.js"; import { CmsEntryOpenSearchFieldIndexFeature, CmsEntryOpenSearchFieldIndexRegistry } from "./features/CmsEntryOpenSearchFieldIndex/index.js"; import { CmsEntryOpenSearchFilterFeature, CmsEntryOpenSearchFilterRegistry } from "./features/CmsEntryOpenSearchFilter/index.js"; const createOpenSearchStorageOperations = params => { const { table, esTable, documentClient, elasticsearch, plugins, container } = params; const tableInstance = createTable({ name: table || process.env.DB_TABLE, documentClient }); const tableElasticsearchInstance = createOpenSearchTable({ name: esTable, documentClient }); const entities = { groups: createGroupEntity({ entityName: ENTITIES.GROUPS, table: tableInstance }), models: createModelEntity({ entityName: ENTITIES.MODELS, table: tableInstance }), entries: createEntryEntity({ entityName: ENTITIES.ENTRIES, table: tableInstance }), entriesEs: createOpenSearchEntity({ entityName: ENTITIES.ENTRIES_ES, table: tableElasticsearchInstance }) }; const fieldRegistry = container.resolve(CmsModelFieldToGraphQLRegistry); const fieldIndexRegistry = container.resolve(CmsEntryOpenSearchFieldIndexRegistry); const compressionHandler = container.resolve(CompressionHandler); const bodyModifiers = container.resolveAll(CmsEntryOpenSearchBodyModifier); const sortModifiers = container.resolveAll(CmsEntryOpenSearchSortModifier); const queryModifiers = container.resolveAll(CmsEntryOpenSearchQueryModifier); const valueSearchRegistry = container.resolve(CmsEntryOpenSearchValueSearchRegistry); const fullTextSearches = container.resolveAll(CmsEntryOpenSearchFullTextSearch); const valuesModifiers = container.resolveAll(CmsEntryOpenSearchValuesModifier); const filterRegistry = container.resolve(CmsEntryOpenSearchFilterRegistry); container.registerFactory(ModelAfterCreateEventHandler, () => ({ async handle(event) { const { model } = event.payload; await createElasticsearchIndex({ client: elasticsearch, model, indexConfigs: container.resolveAll(CmsEntryOpenSearchIndex) }); } })); container.registerFactory(ModelAfterCreateFromEventHandler, () => ({ async handle(event) { const { model } = event.payload; await createElasticsearchIndex({ client: elasticsearch, model, indexConfigs: container.resolveAll(CmsEntryOpenSearchIndex) }); } })); container.registerFactory(ModelAfterDeleteEventHandler, () => ({ async handle(event) { const { model } = event.payload; await deleteElasticsearchIndex({ client: elasticsearch, model }); } })); const entries = createEntriesStorageOperations({ entity: entities.entries, esEntity: entities.entriesEs, plugins, elasticsearch, fieldRegistry, fieldIndexRegistry, compressionHandler, bodyModifiers, sortModifiers, queryModifiers, valueSearchRegistry, fullTextSearches, valuesModifiers, filterRegistry }); return { name: "dynamodb:opensearch", beforeInit: async context => { context.db.registry.register({ item: entities.entries, app: "cms", tags: ["regular", entities.entries.name] }); context.db.registry.register({ item: entities.entriesEs, app: "cms", tags: ["es", entities.entriesEs.name] }); // TODO we know that context is ok, but types are missing elasticsearch/opensearch // @ts-expect-error createCreateIndexTask(context); entries.dataLoaders.clearAll(); }, getEntities: () => entities, getTable: () => tableInstance, getEsTable: () => tableElasticsearchInstance, groups: createGroupsStorageOperations({ entity: entities.groups, container }), models: createModelsStorageOperations({ entity: entities.models, elasticsearch }), entries }; }; class OpenSearchStorageOperationsFactoryImpl { async create(context) { return createOpenSearchStorageOperations({ documentClient: context.db.driver.getClient(), elasticsearch: context.opensearch, plugins: context.plugins, container: context.container }); } } const OpenSearchStorageOperationsFactory = StorageOperationsFactoryAbstraction.createImplementation({ implementation: OpenSearchStorageOperationsFactoryImpl, dependencies: [] }); const storageOperationsFeature = createFeature({ name: "cms.storageOperations.openSearch", register: container => { CmsEntryOpenSearchFieldIndexFeature.register(container); CmsEntryOpenSearchFilterFeature.register(container); CmsEntryOpenSearchIndexFeature.register(container); CmsEntryOpenSearchValueSearchFeature.register(container); container.register(OpenSearchStorageOperationsFactory).inSingletonScope(); } }); export const registerCmsOpenSearchStorageOperations = () => { return [registerDynamoDbExtension(), createRegisterExtensionPlugin(context => { return storageOperationsFeature.register(context.container); })]; }; //# sourceMappingURL=feature.js.map