@medusajs/region
Version:
Medusa Region module
212 lines • 10.3 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 });
const utils_1 = require("@medusajs/framework/utils");
const _models_1 = require("../models");
class RegionModuleService extends (0, utils_1.MedusaService)({ Region: _models_1.Region, Country: _models_1.Country }) {
constructor({ baseRepository, regionService, countryService }, moduleDeclaration) {
// @ts-ignore
super(...arguments);
this.moduleDeclaration = moduleDeclaration;
this.baseRepository_ = baseRepository;
this.regionService_ = regionService;
this.countryService_ = countryService;
}
// @ts-expect-error
async createRegions(data, sharedContext = {}) {
const input = Array.isArray(data) ? data : [data];
const result = await this.createRegions_(input, sharedContext);
return await this.baseRepository_.serialize(Array.isArray(data) ? result : result[0]);
}
async createRegions_(data, sharedContext = {}) {
let normalizedInput = RegionModuleService.normalizeInput(data);
let normalizedDbRegions = normalizedInput.map((region) => (0, utils_1.removeUndefined)({
...region,
countries: undefined,
}));
const result = await this.regionService_.create(normalizedDbRegions, sharedContext);
if (data.some((input) => input.countries?.length)) {
await this.validateCountries(normalizedInput.map((r) => r.countries ?? []).flat(), sharedContext);
await this.countryService_.update(normalizedInput.map((region, i) => ({
selector: { iso_2: region.countries },
data: {
region_id: result[i].id,
},
})), sharedContext);
}
return result;
}
// @ts-expect-error
async softDeleteRegions(ids, config, sharedContext = {}) {
const result = await super.softDeleteRegions(ids, config, sharedContext);
// Note: You cannot revert the state of a region by simply restoring it. The association with countries is lost.
await super.updateCountries({
selector: { region_id: ids },
data: { region_id: null },
}, sharedContext);
return result;
}
async upsertRegions(data, sharedContext = {}) {
const input = Array.isArray(data) ? data : [data];
const forUpdate = input.filter((region) => !!region.id);
const forCreate = input.filter((region) => !region.id);
const operations = [];
if (forCreate.length) {
operations.push(this.createRegions_(forCreate, sharedContext));
}
if (forUpdate.length) {
operations.push(this.updateRegions_(forUpdate, sharedContext));
}
const result = (await (0, utils_1.promiseAll)(operations)).flat();
return await this.baseRepository_.serialize(Array.isArray(data) ? result : result[0]);
}
// @ts-expect-error
async updateRegions(idOrSelector, data, sharedContext = {}) {
let normalizedInput = [];
if ((0, utils_1.isString)(idOrSelector)) {
normalizedInput = [{ id: idOrSelector, ...data }];
}
else {
const regions = await this.regionService_.list(idOrSelector, {}, sharedContext);
normalizedInput = regions.map((region) => ({
id: region.id,
...data,
}));
}
const updateResult = await this.updateRegions_(normalizedInput, sharedContext);
const regions = await this.baseRepository_.serialize(updateResult);
return (0, utils_1.isString)(idOrSelector) ? regions[0] : regions;
}
async updateRegions_(data, sharedContext = {}) {
const normalizedInput = RegionModuleService.normalizeInput(data);
// If countries are being updated for a region, first make previously set countries' region to null to get to a clean slate.
// Somewhat less efficient, but region operations will be very rare, so it is better to go with a simple solution
const regionsWithCountryUpdate = normalizedInput
.filter((region) => !!region.countries)
.map((region) => region.id)
.flat();
let normalizedDbRegions = normalizedInput.map((region) => (0, utils_1.removeUndefined)({
...region,
countries: undefined, // -> delete countries if passed because we want to do update "manually"
}));
if (regionsWithCountryUpdate.length) {
await this.countryService_.update({
selector: {
region_id: regionsWithCountryUpdate,
},
data: { region_id: null },
}, sharedContext);
await this.validateCountries(normalizedInput.map((d) => d.countries ?? []).flat(), sharedContext);
await this.countryService_.update(normalizedInput.map((region) => ({
selector: { iso_2: region.countries },
data: {
region_id: region.id,
},
})), sharedContext);
}
return await this.regionService_.update(normalizedDbRegions, sharedContext);
}
static normalizeInput(regions) {
return regions.map((region) => (0, utils_1.removeUndefined)({
...region,
currency_code: region.currency_code?.toLowerCase(),
name: region.name?.trim(),
countries: region.countries?.map((country) => country.toLowerCase()),
}));
}
/**
* Validate that countries can be assigned to a region.
*
* NOTE: this method relies on countries of the regions that we are assigning to need to be unassigned first.
* @param countries
* @param sharedContext
* @private
*/
async validateCountries(countries, sharedContext) {
if (!countries?.length) {
return [];
}
// The new regions being created have a country conflict
const uniqueCountries = Array.from(new Set(countries));
if (uniqueCountries.length !== countries.length) {
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Countries with codes: "${(0, utils_1.getDuplicates)(countries).join(", ")}" are already assigned to a region`);
}
const countriesInDb = await this.countryService_.list({ iso_2: uniqueCountries }, { select: ["iso_2", "region_id"] }, sharedContext);
const countryCodesInDb = countriesInDb.map((c) => c.iso_2.toLowerCase());
// Countries missing in the database
if (countriesInDb.length !== uniqueCountries.length) {
const missingCountries = (0, utils_1.arrayDifference)(uniqueCountries, countryCodesInDb);
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Countries with codes: "${missingCountries.join(", ")}" do not exist`);
}
// Countries that already have a region already assigned to them
// @ts-ignore
const countriesWithRegion = countriesInDb.filter((c) => !!c.region_id);
if (countriesWithRegion.length) {
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Countries with codes: "${countriesWithRegion
.map((c) => c.iso_2)
.join(", ")}" are already assigned to a region`);
}
return countriesInDb;
}
}
exports.default = RegionModuleService;
__decorate([
(0, utils_1.InjectManager)()
// @ts-expect-error
,
__param(1, (0, utils_1.MedusaContext)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object]),
__metadata("design:returntype", Promise)
], RegionModuleService.prototype, "createRegions", null);
__decorate([
(0, utils_1.InjectTransactionManager)(),
__param(1, (0, utils_1.MedusaContext)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Array, Object]),
__metadata("design:returntype", Promise)
], RegionModuleService.prototype, "createRegions_", null);
__decorate([
(0, utils_1.InjectManager)()
// @ts-expect-error
,
__param(2, (0, utils_1.MedusaContext)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object, Object]),
__metadata("design:returntype", Promise)
], RegionModuleService.prototype, "softDeleteRegions", null);
__decorate([
(0, utils_1.InjectTransactionManager)(),
__param(1, (0, utils_1.MedusaContext)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object]),
__metadata("design:returntype", Promise)
], RegionModuleService.prototype, "upsertRegions", null);
__decorate([
(0, utils_1.InjectManager)()
// @ts-expect-error
,
__param(2, (0, utils_1.MedusaContext)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object, Object]),
__metadata("design:returntype", Promise)
], RegionModuleService.prototype, "updateRegions", null);
__decorate([
(0, utils_1.InjectTransactionManager)(),
__param(1, (0, utils_1.MedusaContext)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Array, Object]),
__metadata("design:returntype", Promise)
], RegionModuleService.prototype, "updateRegions_", null);
//# sourceMappingURL=region-module.js.map
;