UNPKG

@rokmohar/medusa-plugin-meilisearch

Version:
207 lines 19 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MeiliSearchService = void 0; const meilisearch_1 = require("meilisearch"); const utils_1 = require("@medusajs/utils"); const types_1 = require("../types"); const embedder_1 = require("../utils/embedder"); const transformer_1 = require("../utils/transformer"); class MeiliSearchService extends utils_1.SearchUtils.AbstractSearchService { static identifier = 'index-meilisearch'; isDefault = false; config_; client_; embedder_; // First arg is the awilix cradle for this module's local container, not a MedusaContainer. // Calls like `.resolve()` on it fail. Callers must supply the real container via AddDocumentsOptions. constructor(cradle, options) { super(cradle, options); this.config_ = options; if (!options.config.apiKey) { throw Error('Meilisearch API key is missing in plugin config. See https://github.com/rokmohar/medusa-plugin-meilisearch'); } if (!options.config.host) { throw Error('Meilisearch host is missing in plugin config. See https://github.com/rokmohar/medusa-plugin-meilisearch'); } this.client_ = new meilisearch_1.Meilisearch(options.config); this.embedder_ = new embedder_1.MeiliSearchEmbedder(options, this.client_); } getLanguageIndexName(baseKey, language) { const { i18n } = this.config_; if (i18n?.strategy !== 'separate-index' || !language) { return baseKey; } return `${baseKey}_${language}`; } getFieldsForType(type) { const fields = new Set(); Object.values(this.config_.settings ?? {}) .filter((config) => { return config.type === type && config.enabled !== false; }) .forEach((config) => { if (Array.isArray(config.fields)) { config.fields.forEach((field) => { return fields.add(field); }); } }); if (!fields.size) { fields.add('*'); } return Array.from(fields); } getIndexesByType(type) { const { i18n } = this.config_; const baseIndexes = Object.entries(this.config_.settings ?? {}) .filter(([, config]) => { return config.type === type && config.enabled !== false; }) .map(([key]) => { return key; }); if (i18n?.strategy === 'separate-index') { const { languages } = i18n; return baseIndexes.flatMap((baseIndex) => { return languages.map((lang) => { return this.getLanguageIndexName(baseIndex, lang); }); }); } return baseIndexes; } async createIndex(indexName, options = { primaryKey: 'id' }) { return this.client_.createIndex(indexName, options); } getIndex(indexName) { return this.client_.index(indexName); } async addDocuments(indexName, documents, _type, options) { const { language, container } = options ?? {}; const { i18n } = this.config_; const i18nOptions = { i18n, language, container, }; const records = documents.filter((d) => { return typeof d === 'object' && d !== null && !Array.isArray(d); }); if (i18n?.strategy === 'separate-index') { const langIndexName = this.getLanguageIndexName(indexName, language ?? i18n.defaultLanguage); const transformedDocuments = await this.getTransformedDocuments(indexName, records, i18nOptions); return this.client_.index(langIndexName).addDocuments(transformedDocuments, { primaryKey: 'id' }); } else { const transformedDocuments = await this.getTransformedDocuments(indexName, records, i18nOptions); return this.client_.index(indexName).addDocuments(transformedDocuments, { primaryKey: 'id' }); } } async replaceDocuments(indexName, documents, type, options) { return this.addDocuments(indexName, documents, type, options); } async deleteDocument(indexName, documentId, language) { const actualIndexName = this.getLanguageIndexName(indexName, language); return this.client_.index(actualIndexName).deleteDocument(documentId); } async deleteDocuments(indexName, documents, language) { const actualIndexName = this.getLanguageIndexName(indexName, language); return this.client_.index(actualIndexName).deleteDocuments(documents); } async deleteAllDocuments(indexName, language) { const actualIndexName = this.getLanguageIndexName(indexName, language); return this.client_.index(actualIndexName).deleteAllDocuments(); } async search(indexName, query, options) { const { language, paginationOptions, filter, additionalOptions, semanticSearch = false, semanticRatio = 0.5, attributesToRetrieve, } = options; const actualIndexName = this.getLanguageIndexName(indexName, language); // Build base search options let searchOptions = { filter, attributesToRetrieve, ...paginationOptions, ...additionalOptions, }; // Enhance with vector search if needed searchOptions = this.embedder_.enhanceSearchOptions(searchOptions, semanticSearch, semanticRatio); // Perform search return this.client_.index(actualIndexName).search(query, searchOptions); } async updateSettings(indexName, settings) { const indexConfig = this.config_.settings?.[indexName]; if (indexConfig?.enabled === false) { return; } const { i18n } = this.config_; if (i18n?.strategy === 'separate-index') { const { languages } = i18n; return Promise.all(languages.map(async (lang) => { const langIndexName = this.getLanguageIndexName(indexName, lang); await this.upsertIndex(langIndexName, settings); await this.updateIndexSettings(langIndexName, settings.indexSettings); // Configure embedders for vector search if (this.embedder_.isVectorSearchEnabled()) { await this.embedder_.configureEmbedders(langIndexName); } })); } else { await this.upsertIndex(indexName, settings); await this.updateIndexSettings(indexName, settings.indexSettings); // Configure embedders for vector search if (this.embedder_.isVectorSearchEnabled()) { await this.embedder_.configureEmbedders(indexName); } return; } } async updateIndexSettings(indexName, indexSettings) { return this.client_.index(indexName).updateSettings(indexSettings); } async upsertIndex(indexName, settings) { const indexConfig = this.config_.settings?.[indexName]; if (indexConfig?.enabled === false) { return; } try { await this.client_.getIndex(indexName); } catch (error) { if (typeof error === 'object' && error !== null && 'code' in error && error.code === types_1.meilisearchErrorCodes.INDEX_NOT_FOUND) { await this.createIndex(indexName, { primaryKey: settings.primaryKey ?? 'id', }); } } } async getTransformedDocuments(indexName, documents, options) { if (!documents.length) { return []; } const indexConfig = this.config_.settings?.[indexName]; switch (indexConfig?.type) { case utils_1.SearchUtils.indexTypes.PRODUCTS: return Promise.all(documents.map(async (doc) => { return indexConfig.transformer?.(doc, transformer_1.transformProduct, { ...options }) ?? (0, transformer_1.transformProduct)(doc, options); })); case 'categories': return Promise.all(documents.map(async (doc) => { return indexConfig.transformer?.(doc, transformer_1.transformCategory, { ...options }) ?? (0, transformer_1.transformCategory)(doc, options); })); default: return documents; } } /** * Get embedder configuration status for admin panel * Delegates to the embedder service */ getVectorSearchStatus() { return this.embedder_.getVectorSearchStatus(); } } exports.MeiliSearchService = MeiliSearchService; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVpbGlzZWFyY2guanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy9tZWlsaXNlYXJjaC9zZXJ2aWNlcy9tZWlsaXNlYXJjaC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw2Q0FBeUY7QUFFekYsMkNBQTZDO0FBQzdDLG9DQUErRjtBQUMvRixnREFBdUQ7QUFDdkQsc0RBQTRGO0FBRTVGLE1BQWEsa0JBQW1CLFNBQVEsbUJBQVcsQ0FBQyxxQkFBcUI7SUFDaEUsTUFBTSxDQUFDLFVBQVUsR0FBRyxtQkFBbUIsQ0FBQTtJQUV2QyxTQUFTLEdBQUcsS0FBSyxDQUFBO0lBRUwsT0FBTyxDQUEwQjtJQUNqQyxPQUFPLENBQWE7SUFDcEIsU0FBUyxDQUFxQjtJQUVqRCwyRkFBMkY7SUFDM0Ysc0dBQXNHO0lBQ3RHLFlBQVksTUFBZSxFQUFFLE9BQWlDO1FBQzVELEtBQUssQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUE7UUFFdEIsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUE7UUFFdEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDM0IsTUFBTSxLQUFLLENBQ1QsNEdBQTRHLENBQzdHLENBQUE7UUFDSCxDQUFDO1FBRUQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDekIsTUFBTSxLQUFLLENBQ1QseUdBQXlHLENBQzFHLENBQUE7UUFDSCxDQUFDO1FBRUQsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLHlCQUFXLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFBO1FBQzlDLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSw4QkFBbUIsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFBO0lBQ2pFLENBQUM7SUFFUyxvQkFBb0IsQ0FBQyxPQUFlLEVBQUUsUUFBaUI7UUFDL0Qs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