UNPKG

@devx-commerce/strapi

Version:

Medusa plugin for Strapi as CMS

319 lines 25.2 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const utils_1 = require("@medusajs/framework/utils"); const qs_1 = __importDefault(require("qs")); var StrapiEntity; (function (StrapiEntity) { StrapiEntity["PRODUCT"] = "products"; StrapiEntity["VARIANT"] = "product-variants"; StrapiEntity["CATEGORY"] = "categories"; StrapiEntity["COLLECTION"] = "collections"; })(StrapiEntity || (StrapiEntity = {})); class StrapiModuleService { constructor({ logger }, options) { this.logger = logger; this.options = { ...options, default_locale: options.default_locale || "en", system_id_key: options.system_id_key || "systemId", }; this.systemIdKey = (this.options.system_id_key ?? "systemId").trim(); } static validateOptions(options) { if (!options.base_url || !options.api_key) { throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Strapi base URL and API key are required"); } } /** * Makes an API request to Strapi. */ async makeRequest(endpoint, options = {}) { const url = `${this.options.base_url}/${endpoint}`; try { const response = await fetch(url, { headers: { Authorization: `Bearer ${this.options.api_key}`, "Content-Type": "application/json", }, ...options, }); if (!response.ok) { throw new Error(`HTTP ${response.status} ${response.statusText}`); } const { data, error } = await response.json(); if (error) { throw new Error(error.message || "Unknown error"); } return data; } catch (error) { this.logger.error(`API request failed: ${url}`, error); throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `API request failed: ${error.message || error}`); } } /** * Fetches an entity by its system ID. */ async getEntityBySystemId(entity, systemId, options) { this.logger.debug(`Fetching entity ${entity} with systemId: ${systemId}`); try { const params = qs_1.default.stringify({ filters: { [this.systemIdKey]: { $eq: systemId } }, fields: ["documentId"], status: "draft", ...options, }); const result = await this.makeRequest(`${entity}?${params}`); return result?.[0]; } catch (error) { this.logger.error(`Failed to fetch ${entity} with systemId: ${systemId}`, error); throw error; } } /** * Creates a new entry in the specified Strapi entity. */ async createEntry(entity, payload) { this.logger.debug(`Creating ${entity} in Strapi`); try { const params = qs_1.default.stringify({ status: "draft" }); return await this.makeRequest(`${entity}?${params}`, { method: "POST", body: JSON.stringify({ data: { ...payload, // locale: this.options.default_locale }, }), }); } catch (error) { this.logger.error(`Failed to create ${entity} in Strapi`, error); throw error; } } /** * Updates an existing entry in the specified Strapi entity. */ async updateEntry(entity, documentId, payload) { this.logger.debug(`Updating ${entity} with documentId: ${documentId}`); try { return await this.makeRequest(`${entity}/${documentId}`, { method: "PUT", body: JSON.stringify({ data: payload }), }); } catch (error) { this.logger.error(`Failed to update ${entity} in Strapi`, error); throw error; } } /** * Deletes an entry in the specified Strapi entity. */ async deleteEntry(entity, documentId) { try { return await this.makeRequest(`${entity}/${documentId}`, { method: "DELETE", }); } catch (error) { this.logger.error(`Failed to delete ${entity} in Strapi`, error); throw error; } } /** * Generic method to upsert an entity */ async upsertEntity(entity, systemId, createPayload, updatePayload) { const entry = await this.getEntityBySystemId(entity, systemId); if (!entry) { this.logger.debug(`No ${entity} found with ID: ${systemId}, creating it`); return await this.createEntry(entity, createPayload); } this.logger.debug(`Updating ${entity} with ID: ${systemId}`); return await this.updateEntry(entity, entry.documentId, updatePayload); } /** * Lists entities based on the provided filter. */ async list(filter) { let entity = StrapiEntity.PRODUCT; let systemKey = "productId"; let systemId = filter.productId; if (filter.collectionId) { entity = StrapiEntity.COLLECTION; systemKey = "collectionId"; systemId = filter.collectionId; } if (filter.categoryId) { entity = StrapiEntity.CATEGORY; systemKey = "categoryId"; systemId = filter.categoryId; } if (filter.variantId) { entity = StrapiEntity.VARIANT; systemKey = "variantId"; systemId = filter.variantId; } const systemIdFilter = Array.isArray(systemId) ? systemId : [systemId]; this.logger.debug(`Fetching entity ${entity} with ID: ${systemIdFilter}`); if (!systemIdFilter.length) { this.logger.debug(`No system IDs provided for ${entity}, returning empty array`); return []; } const params = qs_1.default.stringify({ filters: { [this.systemIdKey]: { $in: systemIdFilter } }, // locale: filter.context?.locale || this.options.default_locale, }); const entries = await this.makeRequest(`${entity}?${params}`); return entries.map(({ [this.systemIdKey]: systemId, ...rest }) => ({ ...rest, [systemKey]: systemId, })); } /** * Upserts a product in Strapi. */ async upsertProduct(product) { const createPayload = { [this.systemIdKey]: product.id, title: product.title || "", handle: product.handle || "", productType: product.type?.value || "", }; const updatePayload = { handle: product.handle || "", productType: product.type?.value || "", }; const entry = await this.upsertEntity(StrapiEntity.PRODUCT, product.id, createPayload, updatePayload); // Create variants if they exist if (product.variants?.length) { await this.upsertProductVariants(product.variants, entry); } return entry; } /** * Deletes a product in Strapi. */ async deleteProduct(productId) { const productEntry = await this.getEntityBySystemId(StrapiEntity.PRODUCT, productId, { populate: "variants", fields: ["*"] }); if (!productEntry) { this.logger.log(`No product found in Strapi ${productId}`); return null; } await this.deleteEntry(StrapiEntity.PRODUCT, productEntry.documentId); if (Array.isArray(productEntry.variants)) { // Delete variants in parallel await Promise.all(productEntry.variants.map((v) => this.deleteEntry(StrapiEntity.VARIANT, v.documentId))); } return productId; } /** * Upserts product variants for a given product entry. */ async upsertProductVariants(variants, productEntry) { // Process variants in parallel await Promise.all(variants.map(async (variant) => { const createPayload = { [this.systemIdKey]: variant.id, title: variant.title || "", product: productEntry.documentId, sku: variant.sku || "", }; const updatePayload = { product: productEntry.documentId, sku: variant.sku || "", }; await this.upsertEntity(StrapiEntity.VARIANT, variant.id, createPayload, updatePayload); })); } /** * Upserts a product variant in Strapi. */ async upsertProductVariant(variant) { const entry = await this.getEntityBySystemId(StrapiEntity.VARIANT, variant.id); if (!entry) { const productEntry = await this.getEntityBySystemId(StrapiEntity.PRODUCT, variant.product_id); if (!productEntry) { this.logger.log(`No product found in Strapi (ID: ${variant.product_id}) — skipping creation of variant ${variant.id}`); return null; } return await this.createEntry(StrapiEntity.VARIANT, { [this.systemIdKey]: variant.id, title: variant.title || "", product: productEntry.documentId, sku: variant.sku || "", }); } return await this.updateEntry(StrapiEntity.VARIANT, entry.documentId, { sku: variant.sku || "", }); } /** * Deletes a product variant in Strapi. */ async deleteProductVariant(variantId) { const entry = await this.getEntityBySystemId(StrapiEntity.VARIANT, variantId); if (!entry) { this.logger.log(`No product variant found in Strapi ${variantId}`); return null; } await this.deleteEntry(StrapiEntity.VARIANT, entry.documentId); return variantId; } /** * Upserts a collection in Strapi. */ async upsertCollection(collection) { return await this.upsertEntity(StrapiEntity.COLLECTION, collection.id, { [this.systemIdKey]: collection.id, title: collection.title || "", handle: collection.handle || "", }, { handle: collection.handle || "", }); } /** * Deletes a collection in Strapi. */ async deleteCollection(collectionId) { const entry = await this.getEntityBySystemId(StrapiEntity.COLLECTION, collectionId); if (!entry) { this.logger.log(`No collection found in Strapi ${collectionId}`); return null; } await this.deleteEntry(StrapiEntity.COLLECTION, entry.documentId); return collectionId; } /** * Upserts a product category in Strapi. */ async upsertCategory(category) { return await this.upsertEntity(StrapiEntity.CATEGORY, category.id, { [this.systemIdKey]: category.id, title: category.name || "", handle: category.handle || "", }, { handle: category.handle || "", }); } /** * Deletes a product category in Strapi. */ async deleteCategory(categoryId) { const entry = await this.getEntityBySystemId(StrapiEntity.CATEGORY, categoryId); if (!entry) { this.logger.log(`No category found in Strapi ${categoryId}`); return null; } await this.deleteEntry(StrapiEntity.CATEGORY, entry.documentId); return categoryId; } } exports.default = StrapiModuleService; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL3N0cmFwaS9zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBT0EscURBQXdEO0FBQ3hELDRDQUFvQjtBQVlwQixJQUFLLFlBS0o7QUFMRCxXQUFLLFlBQVk7SUFDZixvQ0FBb0IsQ0FBQTtJQUNwQiw0Q0FBNEIsQ0FBQTtJQUM1Qix1Q0FBdUIsQ0FBQTtJQUN2QiwwQ0FBMEIsQ0FBQTtBQUM1QixDQUFDLEVBTEksWUFBWSxLQUFaLFlBQVksUUFLaEI7QUFFRCxNQUFxQixtQkFBbUI7SUFLdEMsWUFBWSxFQUFFLE1BQU0sRUFBd0IsRUFBRSxPQUFzQjtRQUNsRSxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUNyQixJQUFJLENBQUMsT0FBTyxHQUFHO1lBQ2IsR0FBRyxPQUFPO1lBQ1YsY0FBYyxFQUFFLE9BQU8sQ0FBQyxjQUFjLElBQUksSUFBSTtZQUM5QyxhQUFhLEVBQUUsT0FBTyxDQUFDLGFBQWEsSUFBSSxVQUFVO1NBQ25ELENBQUM7UUFFRixJQUFJLENBQUMsV0FBVyxHQUFHLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLElBQUksVUFBVSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDdkUsQ0FBQztJQUVELE1BQU0sQ0FBQyxlQUFlLENBQUMsT0FBc0I7UUFDM0MsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDMUMsTUFBTSxJQUFJLG1CQUFXLENBQ25CLG1CQUFXLENBQUMsS0FBSyxDQUFDLFlBQVksRUFDOUIsMENBQTBDLENBQzNDLENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0ssS0FBSyxDQUFDLFdBQVcsQ0FDdkIsUUFBZ0IsRUFDaEIsVUFBd0MsRUFBRTtRQUUxQyxNQUFNLEdBQUcsR0FB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