@medusajs/utils
Version:
Medusa utilities functions shared by Medusa core and Modules
341 lines • 17.7 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MedusaInternalService = MedusaInternalService;
const common_1 = require("../common");
const dal_1 = require("../dal");
const dml_1 = require("../dml");
const build_query_1 = require("./build-query");
const decorators_1 = require("./decorators");
function MedusaInternalService(rawModel) {
const model = dml_1.DmlEntity.isDmlEntity(rawModel)
? (0, dml_1.toMikroORMEntity)(rawModel)
: rawModel;
const injectedRepositoryName = `${(0, common_1.lowerCaseFirst)(model.name)}Repository`;
const propertyRepositoryName = `__${injectedRepositoryName}__`;
class AbstractService_ {
constructor(container) {
this.__container__ = container;
this[propertyRepositoryName] = container[injectedRepositoryName];
}
static applyFreeTextSearchFilter(filters, config) {
if ((0, common_1.isDefined)(filters?.q)) {
config.filters ??= {};
config.filters[dal_1.FreeTextSearchFilterKeyPrefix + model.name] = {
value: filters.q,
fromEntity: model.name,
};
delete filters.q;
}
}
static retrievePrimaryKeys(entity) {
return (entity.meta?.primaryKeys ??
entity.prototype.__meta?.primaryKeys ?? ["id"]);
}
static buildUniqueCompositeKeyValue(keys, data) {
return keys.map((k) => data[k]).join(":");
}
/**
* Only apply top level default ordering as the relation
* default ordering is already applied through the foreign key
* @param config
*/
static applyDefaultOrdering(config) {
if ((0, common_1.isPresent)(config.order)) {
return;
}
config.order = {};
const primaryKeys = AbstractService_.retrievePrimaryKeys(model);
primaryKeys.forEach((primaryKey) => {
config.order[primaryKey] = "ASC";
});
}
async retrieve(idOrObject, config = {}, sharedContext = {}) {
const primaryKeys = AbstractService_.retrievePrimaryKeys(model);
if (!(0, common_1.isDefined)(idOrObject) ||
((0, common_1.isString)(idOrObject) && primaryKeys.length > 1) ||
((!(0, common_1.isString)(idOrObject) ||
((0, common_1.isObject)(idOrObject) && !idOrObject[primaryKeys[0]])) &&
primaryKeys.length === 1)) {
throw new common_1.MedusaError(common_1.MedusaError.Types.NOT_FOUND, `${primaryKeys.length === 1
? `${(0, common_1.lowerCaseFirst)(model.name) + " - " + primaryKeys[0]}`
: `${(0, common_1.lowerCaseFirst)(model.name)} - ${primaryKeys.join(", ")}`} must be defined`);
}
let primaryKeysCriteria = {};
if (primaryKeys.length === 1) {
primaryKeysCriteria[primaryKeys[0]] = idOrObject;
}
else {
const idOrObject_ = Array.isArray(idOrObject)
? idOrObject
: [idOrObject];
primaryKeysCriteria = {
$or: idOrObject_.map((primaryKeyValue) => ({
$and: primaryKeys.map((key) => ({ [key]: primaryKeyValue[key] })),
})),
};
}
const queryOptions = (0, build_query_1.buildQuery)(primaryKeysCriteria, config);
const entities = await this[propertyRepositoryName].find(queryOptions, sharedContext);
if (!entities?.length) {
throw new common_1.MedusaError(common_1.MedusaError.Types.NOT_FOUND, `${model.name} with ${primaryKeys.join(", ")}: ${Array.isArray(idOrObject)
? idOrObject.map((v) => [(0, common_1.isString)(v) ? v : Object.values(v)].join(", "))
: (0, common_1.isObject)(idOrObject)
? Object.values(idOrObject).join(", ")
: idOrObject} was not found`);
}
return entities[0];
}
async list(filters = {}, config = {}, sharedContext = {}) {
AbstractService_.applyDefaultOrdering(config);
AbstractService_.applyFreeTextSearchFilter(filters, config);
const queryOptions = (0, build_query_1.buildQuery)(filters, config);
return await this[propertyRepositoryName].find(queryOptions, sharedContext);
}
async listAndCount(filters = {}, config = {}, sharedContext = {}) {
AbstractService_.applyDefaultOrdering(config);
AbstractService_.applyFreeTextSearchFilter(filters, config);
const queryOptions = (0, build_query_1.buildQuery)(filters, config);
return await this[propertyRepositoryName].findAndCount(queryOptions, sharedContext);
}
async create(data, sharedContext = {}) {
if (!(0, common_1.isDefined)(data) || (Array.isArray(data) && data.length === 0)) {
return (Array.isArray(data) ? [] : void 0);
}
const data_ = Array.isArray(data) ? data : [data];
const entities = await this[propertyRepositoryName].create(data_, sharedContext);
return Array.isArray(data) ? entities : entities[0];
}
async update(input, sharedContext = {}) {
if (!(0, common_1.isDefined)(input) || (Array.isArray(input) && input.length === 0)) {
return (Array.isArray(input) ? [] : void 0);
}
let shouldReturnArray = false;
if (Array.isArray(input)) {
shouldReturnArray = true;
}
else if ((0, common_1.isObject)(input) && "selector" in input) {
shouldReturnArray = true;
}
const primaryKeys = AbstractService_.retrievePrimaryKeys(model);
const inputArray = Array.isArray(input) ? input : [input];
const toUpdateData = [];
// Only used when we receive data and no selector
const keySelectorForDataOnly = {
$or: [],
};
const keySelectorDataMap = new Map();
for (const input_ of inputArray) {
if (input_.selector) {
const entitiesToUpdate = await this.list(input_.selector, {}, sharedContext);
// Create a pair of entity and data to update
entitiesToUpdate.forEach((entity) => {
toUpdateData.push({
entity,
update: input_.data,
});
});
}
else {
// in case we are manipulating the data, then extract the primary keys as a selector and the rest as the data to update
const selector = {};
primaryKeys.forEach((key) => {
selector[key] = input_[key];
});
const uniqueCompositeKey = AbstractService_.buildUniqueCompositeKeyValue(primaryKeys, input_);
keySelectorDataMap.set(uniqueCompositeKey, input_);
keySelectorForDataOnly.$or.push(selector);
}
}
if (keySelectorForDataOnly.$or.length) {
const entitiesToUpdate = await this.list(keySelectorForDataOnly, {}, sharedContext);
// Create a pair of entity and data to update
entitiesToUpdate.forEach((entity) => {
const uniqueCompositeKey = AbstractService_.buildUniqueCompositeKeyValue(primaryKeys, entity);
toUpdateData.push({
entity,
update: keySelectorDataMap.get(uniqueCompositeKey),
});
});
// Only throw for missing entities when we dont have selectors involved as selector by design can return 0 entities
if (entitiesToUpdate.length !== keySelectorDataMap.size) {
const entityName = model.name ?? model;
const compositeKeysValuesForFoundEntities = new Set(entitiesToUpdate.map((entity) => {
return AbstractService_.buildUniqueCompositeKeyValue(primaryKeys, entity);
}));
const missingEntityValues = [];
[...keySelectorDataMap.keys()].filter((key) => {
if (!compositeKeysValuesForFoundEntities.has(key)) {
const value = key.replace(/:/gi, " - ");
missingEntityValues.push(value);
}
});
throw new common_1.MedusaError(common_1.MedusaError.Types.NOT_FOUND, `${entityName} with ${primaryKeys.join(", ")} "${missingEntityValues.join(", ")}" not found`);
}
}
if (!toUpdateData.length) {
return (shouldReturnArray ? [] : void 0);
}
// Manage metadata if needed
toUpdateData.forEach(({ entity, update }) => {
const update_ = update;
const entity_ = entity;
if ((0, common_1.isPresent)(update_.metadata)) {
entity_.metadata = update_.metadata = (0, common_1.mergeMetadata)(entity_.metadata ?? {}, update_.metadata);
}
});
const entities = await this[propertyRepositoryName].update(toUpdateData, sharedContext);
return shouldReturnArray ? entities : entities[0];
}
async delete(idOrSelector, sharedContext = {}) {
if (!(0, common_1.isDefined)(idOrSelector) ||
(Array.isArray(idOrSelector) && !idOrSelector.length)) {
return [];
}
const primaryKeys = AbstractService_.retrievePrimaryKeys(model);
if ((Array.isArray(idOrSelector) && idOrSelector.length === 0) ||
(((0, common_1.isString)(idOrSelector) ||
(Array.isArray(idOrSelector) && (0, common_1.isString)(idOrSelector[0]))) &&
primaryKeys.length > 1)) {
throw new common_1.MedusaError(common_1.MedusaError.Types.NOT_FOUND, `${primaryKeys.length === 1
? `"${(0, common_1.lowerCaseFirst)(model.name) + " - " + primaryKeys[0]}"`
: `${(0, common_1.lowerCaseFirst)(model.name)} - ${primaryKeys.join(", ")}`} must be defined`);
}
const deleteCriteria = {
$or: [],
};
if ((0, common_1.isObject)(idOrSelector) && "selector" in idOrSelector) {
deleteCriteria.$or.push(idOrSelector.selector);
}
else {
const primaryKeysValues = Array.isArray(idOrSelector)
? idOrSelector
: [idOrSelector];
deleteCriteria.$or = primaryKeysValues.map((primaryKeyValue) => {
const criteria = {};
if ((0, common_1.isObject)(primaryKeyValue)) {
Object.entries(primaryKeyValue).forEach(([key, value]) => {
criteria[key] = value;
});
}
else {
criteria[primaryKeys[0]] = primaryKeyValue;
}
return criteria;
});
}
if (!deleteCriteria.$or.length) {
return [];
}
return await this[propertyRepositoryName].delete(deleteCriteria, sharedContext);
}
async softDelete(idsOrFilter, sharedContext = {}) {
if ((Array.isArray(idsOrFilter) && !idsOrFilter.length) ||
(!Array.isArray(idsOrFilter) && !idsOrFilter)) {
return [[], {}];
}
return await this[propertyRepositoryName].softDelete(idsOrFilter, sharedContext);
}
async restore(idsOrFilter, sharedContext = {}) {
return await this[propertyRepositoryName].restore(idsOrFilter, sharedContext);
}
async upsert(data, sharedContext = {}) {
const data_ = Array.isArray(data) ? data : [data];
const entities = await this[propertyRepositoryName].upsert(data_, sharedContext);
return Array.isArray(data) ? entities : entities[0];
}
async upsertWithReplace(data, config = {
relations: [],
}, sharedContext = {}) {
const data_ = Array.isArray(data) ? data : [data];
const { entities, performedActions } = await this[propertyRepositoryName].upsertWithReplace(data_, config, sharedContext);
return {
entities: Array.isArray(data) ? entities : entities[0],
performedActions,
};
}
}
__decorate([
(0, decorators_1.InjectManager)(propertyRepositoryName),
__param(2, (0, decorators_1.MedusaContext)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object, Object]),
__metadata("design:returntype", Promise)
], AbstractService_.prototype, "retrieve", null);
__decorate([
(0, decorators_1.InjectManager)(propertyRepositoryName),
__param(2, (0, decorators_1.MedusaContext)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object, Object]),
__metadata("design:returntype", Promise)
], AbstractService_.prototype, "list", null);
__decorate([
(0, decorators_1.InjectManager)(propertyRepositoryName),
__param(2, (0, decorators_1.MedusaContext)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object, Object]),
__metadata("design:returntype", Promise)
], AbstractService_.prototype, "listAndCount", null);
__decorate([
(0, decorators_1.InjectTransactionManager)(propertyRepositoryName),
__param(1, (0, decorators_1.MedusaContext)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object]),
__metadata("design:returntype", Promise)
], AbstractService_.prototype, "create", null);
__decorate([
(0, decorators_1.InjectTransactionManager)(propertyRepositoryName),
__param(1, (0, decorators_1.MedusaContext)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object]),
__metadata("design:returntype", Promise)
], AbstractService_.prototype, "update", null);
__decorate([
(0, decorators_1.InjectTransactionManager)(propertyRepositoryName),
__param(1, (0, decorators_1.MedusaContext)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object]),
__metadata("design:returntype", Promise)
], AbstractService_.prototype, "delete", null);
__decorate([
(0, decorators_1.InjectTransactionManager)(propertyRepositoryName),
__param(1, (0, decorators_1.MedusaContext)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object]),
__metadata("design:returntype", Promise)
], AbstractService_.prototype, "softDelete", null);
__decorate([
(0, decorators_1.InjectTransactionManager)(propertyRepositoryName),
__param(1, (0, decorators_1.MedusaContext)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object]),
__metadata("design:returntype", Promise)
], AbstractService_.prototype, "restore", null);
__decorate([
(0, decorators_1.InjectTransactionManager)(propertyRepositoryName),
__param(1, (0, decorators_1.MedusaContext)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object]),
__metadata("design:returntype", Promise)
], AbstractService_.prototype, "upsert", null);
__decorate([
(0, decorators_1.InjectTransactionManager)(propertyRepositoryName),
__param(2, (0, decorators_1.MedusaContext)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object, Object]),
__metadata("design:returntype", Promise)
], AbstractService_.prototype, "upsertWithReplace", null);
return AbstractService_;
}
//# sourceMappingURL=medusa-internal-service.js.map
;