@devx-commerce/strapi
Version:
Medusa plugin for Strapi as CMS
333 lines • 26.8 kB
JavaScript
;
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) {
let errorDetails = `HTTP ${response.status} ${response.statusText}`;
try {
const errorResponse = await response.json();
if (errorResponse.error) {
errorDetails += ` - ${JSON.stringify(errorResponse.error)}`;
this.logger.error(`Strapi API request failed for ${url}:`, errorResponse);
}
}
catch (parseError) {
this.logger.error("Failed to parse error response from Strapi", parseError);
}
throw new Error(errorDetails);
}
const responseData = await response.json();
const { data, error } = responseData;
if (error) {
this.logger.error(`Strapi API returned error for ${url}:`, error);
this.logger.error("Full response:", responseData);
throw new Error(error.message || JSON.stringify(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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