UNPKG

@devx-commerce/strapi-x-custom-jw-mayave

Version:

Medusa plugin for Strapi as CMS - JW Mayave Custom Release

388 lines 32.2 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.StrapiEntity = void 0; 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 || (exports.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 = {}) { this.logger.info("inside make request"); 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 { this.logger.info("inside get entity by system id......."); const params = qs_1.default.stringify({ filters: { [this.systemIdKey]: { $eq: systemId } }, fields: ["documentId"], // status: "draft", // Temporarily ...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 { this.logger.info("inside create entry"); // const params = qs.stringify({ status: "draft" }); const params = qs_1.default.stringify({ status: "published" }); // Temporarily 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 { this.logger.info("inside update entry"); 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 { this.logger.info("inside delete entry"); 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) { this.logger.info("inside upsert entity"); 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) { this.logger.info("inside list"); 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 ? [systemId] : []).filter((id) => typeof id === "string" && id.length > 0); 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 idChunks = StrapiModuleService.chunkArray(systemIdFilter, 100); const aggregatedEntries = []; for (const chunk of idChunks) { const params = qs_1.default.stringify({ filters: { [this.systemIdKey]: { $in: chunk } }, populate: "images", // locale: filter.context?.locale || this.options.default_locale, }); try { const entries = await this.makeRequest(`${entity}?${params}`); aggregatedEntries.push(...entries); } catch (error) { this.logger.error(`Failed to fetch ${entity} for chunk of size ${chunk.length}`, error); } } return aggregatedEntries.map(({ [this.systemIdKey]: systemId, ...rest }) => ({ ...rest, [systemKey]: systemId, })); } /** * Upserts a product in Strapi. */ async upsertProduct(product) { this.logger.info("inside upsert 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) { this.logger.info("inside delete product"); 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) { this.logger.info("inside upsert product variants"); // Apply per-variant lock to avoid duplicate creates under concurrency await Promise.all(variants.map(async (variant) => { const key = variant.id; const run = async () => { 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); }; await this.withVariantLock(key, run); })); } /** * Upserts a product variant in Strapi. */ async upsertProductVariant(variant) { this.logger.info("inside upsert product variant"); const key = variant.id; return await this.withVariantLock(key, async () => { 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 || "", }); }); } async withVariantLock(key, fn) { const previous = StrapiModuleService.variantLocks.get(key) || Promise.resolve(); let resolveCurrent; const current = new Promise((resolve) => (resolveCurrent = resolve)); // Chain to previous to serialize per key const task = previous .catch(() => { }) .then(async () => { try { return await fn(); } finally { resolveCurrent(undefined); // Clean up so the map does not grow unbounded // Only delete if the same promise is still stored const stored = StrapiModuleService.variantLocks.get(key); if (stored === current) { StrapiModuleService.variantLocks.delete(key); } } }); StrapiModuleService.variantLocks.set(key, current); // Await the task result return (await task); } /** * Deletes a product variant in Strapi. */ async deleteProductVariant(variantId) { this.logger.info("inside delete product variant"); 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) { this.logger.info("inside upsert 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) { this.logger.info("inside delete collection"); 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) { this.logger.info("inside upsert 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) { this.logger.info("inside delete category"); 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; } } StrapiModuleService.variantLocks = new Map(); StrapiModuleService.chunkArray = (array, chunkSize = 101) => { const chunks = []; for (let i = 0; i < array.length; i += chunkSize) { chunks.push(array.slice(i, i + chunkSize)); } return chunks; }; exports.default = StrapiModuleService; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL3N0cmFwaS9zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQU9BLHFEQUF3RDtBQUN4RCw0Q0FBb0I7QUFZcEIsSUFBWSxZQUtYO0FBTEQsV0FBWSxZQUFZO0lBQ3RCLG9DQUFvQixDQUFBO0lBQ3BCLDRDQUE0QixDQUFBO0lBQzVCLHVDQUF1QixDQUFBO0lBQ3ZCLDBDQUEwQixDQUFBO0FBQzVCLENBQUMsRUFMVyxZQUFZLDRCQUFaLFlBQVksUUFLdkI7QUFFRCxNQUFxQixtQkFBbUI7SUFNdEMsWUFBWSxFQUFFLE1BQU0sRUFBd0IsRUFBRSxPQUFzQjtRQUNsRSxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUNyQixJQUFJLENBQUMsT0FBTyxHQUFHO1lBQ2IsR0FBRyxPQUFPO1lBQ1YsY0FBYyxFQUFFLE9BQU8sQ0FBQyxjQUFjLElBQUksSUFBSTtZQUM5QyxhQUFhLEVBQUUsT0FBTyxDQUFDLGFBQWEsSUFBSSxVQUFVO1NBQ25ELENBQUM7UUFFRixJQUFJLENBQUMsV0FBVyxHQUFHLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLElBQUksVUFBVSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDdkUsQ0FBQztJQUVELE1BQU0sQ0FBQyxlQUFlLENBQUMsT0FBc0I7UUFDM0MsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDMUMsTUFBTSxJQUFJLG1CQUFXLENBQ25CLG1CQUFXLENBQUMsS0FBSyxDQUFDLFlBQVksRUFDOUIsMENBQTBDLENBQzNDLENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQztJQVVEOztPQUVHO0lBQ0ssS0FBSyxDQUFDLFdBQVcsQ0FDdkIsUUFBZ0IsRUFDaEIsVUFBd0MsRUFBRTtRQUUxQyxJQUFJLENBQUMs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