feat: Update signature of region module to match latest spec (#6487)
This commit is contained in:
1 parent
c86e27bd0d
commit
5b85c3103e
8 files changed
+174
-87
No files matched your search
@@ -2,14 +2,14 @@ import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
|||||||
import {
|
import {
|
||||||
FilterableRegionProps,
|
FilterableRegionProps,
|
||||||
IRegionModuleService,
|
IRegionModuleService,
|
||||||
UpdatableRegionFields,
|
UpdateRegionDTO,
|
||||||
} from "@medusajs/types"
|
} from "@medusajs/types"
|
||||||
import { getSelectsAndRelationsFromObjectArray } from "@medusajs/utils"
|
import { getSelectsAndRelationsFromObjectArray } from "@medusajs/utils"
|
||||||
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||||
|
|
||||||
type UpdateRegionsStepInput = {
|
type UpdateRegionsStepInput = {
|
||||||
selector: FilterableRegionProps
|
selector: FilterableRegionProps
|
||||||
update: UpdatableRegionFields
|
update: UpdateRegionDTO
|
||||||
}
|
}
|
||||||
|
|
||||||
export const updateRegionsStepId = "update-region"
|
export const updateRegionsStepId = "update-region"
|
||||||
@@ -42,7 +42,7 @@ export const updateRegionsStep = createStep(
|
|||||||
ModuleRegistrationName.REGION
|
ModuleRegistrationName.REGION
|
||||||
)
|
)
|
||||||
|
|
||||||
await service.update(
|
await service.upsert(
|
||||||
prevData.map((r) => ({
|
prevData.map((r) => ({
|
||||||
id: r.id,
|
id: r.id,
|
||||||
name: r.name,
|
name: r.name,
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import {
|
import {
|
||||||
FilterableRegionProps,
|
FilterableRegionProps,
|
||||||
RegionDTO,
|
RegionDTO,
|
||||||
UpdatableRegionFields,
|
UpdateRegionDTO,
|
||||||
} from "@medusajs/types"
|
} from "@medusajs/types"
|
||||||
import { WorkflowData, createWorkflow } from "@medusajs/workflows-sdk"
|
import { WorkflowData, createWorkflow } from "@medusajs/workflows-sdk"
|
||||||
import { updateRegionsStep } from "../steps"
|
import { updateRegionsStep } from "../steps"
|
||||||
|
|
||||||
type UpdateRegionsStepInput = {
|
type UpdateRegionsStepInput = {
|
||||||
selector: FilterableRegionProps
|
selector: FilterableRegionProps
|
||||||
update: UpdatableRegionFields
|
update: UpdateRegionDTO
|
||||||
}
|
}
|
||||||
|
|
||||||
type WorkflowInput = UpdateRegionsStepInput
|
type WorkflowInput = UpdateRegionsStepInput
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import {
|
|||||||
deleteRegionsWorkflow,
|
deleteRegionsWorkflow,
|
||||||
updateRegionsWorkflow,
|
updateRegionsWorkflow,
|
||||||
} from "@medusajs/core-flows"
|
} from "@medusajs/core-flows"
|
||||||
import { UpdatableRegionFields } from "@medusajs/types"
|
import { UpdateRegionDTO } from "@medusajs/types"
|
||||||
import { remoteQueryObjectFromString } from "@medusajs/utils"
|
import { remoteQueryObjectFromString } from "@medusajs/utils"
|
||||||
import { MedusaRequest, MedusaResponse } from "../../../../types/routing"
|
import { MedusaRequest, MedusaResponse } from "../../../../types/routing"
|
||||||
import { defaultAdminRegionFields } from "../query-config"
|
import { defaultAdminRegionFields } from "../query-config"
|
||||||
@@ -27,7 +27,7 @@ export const POST = async (req: MedusaRequest, res: MedusaResponse) => {
|
|||||||
const { result, errors } = await updateRegionsWorkflow(req.scope).run({
|
const { result, errors } = await updateRegionsWorkflow(req.scope).run({
|
||||||
input: {
|
input: {
|
||||||
selector: { id: req.params.id },
|
selector: { id: req.params.id },
|
||||||
update: req.validatedBody as UpdatableRegionFields,
|
update: req.validatedBody as UpdateRegionDTO,
|
||||||
},
|
},
|
||||||
throwOnError: false,
|
throwOnError: false,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -167,6 +167,68 @@ describe("Region Module Service", () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should upsert the region successfully", async () => {
|
||||||
|
const createdRegion = await service.upsert({
|
||||||
|
name: "North America",
|
||||||
|
currency_code: "USD",
|
||||||
|
countries: ["us", "ca"],
|
||||||
|
})
|
||||||
|
|
||||||
|
await service.upsert({
|
||||||
|
id: createdRegion.id,
|
||||||
|
name: "Americas",
|
||||||
|
currency_code: "MXN",
|
||||||
|
countries: ["us", "mx"],
|
||||||
|
})
|
||||||
|
|
||||||
|
const latestRegion = await service.retrieve(createdRegion.id, {
|
||||||
|
relations: ["currency", "countries"],
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(latestRegion).toMatchObject({
|
||||||
|
id: createdRegion.id,
|
||||||
|
name: "Americas",
|
||||||
|
currency_code: "mxn",
|
||||||
|
})
|
||||||
|
expect(latestRegion.countries.map((c) => c.iso_2)).toEqual(["mx", "us"])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should allow mixing create and update operations in upsert", async () => {
|
||||||
|
const createdRegion = await service.upsert({
|
||||||
|
name: "North America",
|
||||||
|
currency_code: "USD",
|
||||||
|
countries: ["us", "ca"],
|
||||||
|
})
|
||||||
|
|
||||||
|
const upserted = await service.upsert([
|
||||||
|
{
|
||||||
|
id: createdRegion.id,
|
||||||
|
name: "Americas",
|
||||||
|
currency_code: "USD",
|
||||||
|
countries: ["us", "ca"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Central America",
|
||||||
|
currency_code: "MXN",
|
||||||
|
countries: ["mx"],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
expect(upserted).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: createdRegion.id,
|
||||||
|
name: "Americas",
|
||||||
|
currency_code: "usd",
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
name: "Central America",
|
||||||
|
currency_code: "mxn",
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
it("should update the region successfully", async () => {
|
it("should update the region successfully", async () => {
|
||||||
const createdRegion = await service.create({
|
const createdRegion = await service.create({
|
||||||
name: "North America",
|
name: "North America",
|
||||||
|
|||||||
@@ -10,14 +10,13 @@ import {
|
|||||||
RegionCountryDTO,
|
RegionCountryDTO,
|
||||||
RegionCurrencyDTO,
|
RegionCurrencyDTO,
|
||||||
RegionDTO,
|
RegionDTO,
|
||||||
UpdatableRegionFields,
|
|
||||||
UpdateRegionDTO,
|
UpdateRegionDTO,
|
||||||
|
UpsertRegionDTO,
|
||||||
} from "@medusajs/types"
|
} from "@medusajs/types"
|
||||||
import {
|
import {
|
||||||
arrayDifference,
|
arrayDifference,
|
||||||
InjectManager,
|
InjectManager,
|
||||||
InjectTransactionManager,
|
InjectTransactionManager,
|
||||||
isObject,
|
|
||||||
isString,
|
isString,
|
||||||
MedusaContext,
|
MedusaContext,
|
||||||
MedusaError,
|
MedusaError,
|
||||||
@@ -30,7 +29,7 @@ import {
|
|||||||
|
|
||||||
import { Country, Currency, Region } from "@models"
|
import { Country, Currency, Region } from "@models"
|
||||||
|
|
||||||
import { CreateCountryDTO, CreateCurrencyDTO } from "@types"
|
import { CreateCountryDTO, CreateCurrencyDTO, UpdateRegionInput } from "@types"
|
||||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||||
|
|
||||||
const COUNTRIES_LIMIT = 1000
|
const COUNTRIES_LIMIT = 1000
|
||||||
@@ -143,54 +142,64 @@ export default class RegionModuleService<
|
|||||||
return await this.regionService_.create(normalizedDbRegions, sharedContext)
|
return await this.regionService_.create(normalizedDbRegions, sharedContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
async update(
|
async upsert(
|
||||||
selector: FilterableRegionProps,
|
data: UpsertRegionDTO[],
|
||||||
data: UpdatableRegionFields,
|
|
||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<RegionDTO[]>
|
): Promise<RegionDTO[]>
|
||||||
async update(
|
async upsert(
|
||||||
regionId: string,
|
data: UpsertRegionDTO,
|
||||||
data: UpdatableRegionFields,
|
|
||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<RegionDTO>
|
): Promise<RegionDTO>
|
||||||
async update(data: UpdateRegionDTO[]): Promise<RegionDTO[]>
|
@InjectTransactionManager("baseRepository_")
|
||||||
@InjectManager("baseRepository_")
|
async upsert(
|
||||||
async update(
|
data: UpsertRegionDTO | UpsertRegionDTO[],
|
||||||
idOrSelectorOrData: string | FilterableRegionProps | UpdateRegionDTO[],
|
|
||||||
data?: UpdatableRegionFields,
|
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
): Promise<RegionDTO | RegionDTO[]> {
|
): Promise<RegionDTO | RegionDTO[]> {
|
||||||
const updateResult = await this.update_(
|
const input = Array.isArray(data) ? data : [data]
|
||||||
idOrSelectorOrData,
|
const forUpdate = input.filter(
|
||||||
data,
|
(region): region is UpdateRegionInput => !!region.id
|
||||||
sharedContext
|
)
|
||||||
|
const forCreate = input.filter(
|
||||||
|
(region): region is CreateRegionDTO => !region.id
|
||||||
)
|
)
|
||||||
|
|
||||||
const regions = await this.baseRepository_.serialize<
|
const operations: Promise<Region[]>[] = []
|
||||||
RegionDTO[] | RegionDTO
|
|
||||||
>(updateResult)
|
|
||||||
|
|
||||||
return isString(idOrSelectorOrData) ? regions[0] : regions
|
if (forCreate.length) {
|
||||||
|
operations.push(this.create_(forCreate, sharedContext))
|
||||||
|
}
|
||||||
|
if (forUpdate.length) {
|
||||||
|
operations.push(this.update_(forUpdate, sharedContext))
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager("baseRepository_")
|
const result = (await promiseAll(operations)).flat()
|
||||||
protected async update_(
|
return await this.baseRepository_.serialize<RegionDTO[] | RegionDTO>(
|
||||||
idOrSelectorOrData: string | FilterableRegionProps | UpdateRegionDTO[],
|
Array.isArray(data) ? result : result[0]
|
||||||
data?: UpdatableRegionFields,
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(
|
||||||
|
id: string,
|
||||||
|
data: UpdateRegionDTO,
|
||||||
|
sharedContext?: Context
|
||||||
|
): Promise<RegionDTO>
|
||||||
|
async update(
|
||||||
|
selector: FilterableRegionProps,
|
||||||
|
data: UpdateRegionDTO,
|
||||||
|
sharedContext?: Context
|
||||||
|
): Promise<RegionDTO[]>
|
||||||
|
@InjectManager("baseRepository_")
|
||||||
|
async update(
|
||||||
|
idOrSelector: string | FilterableRegionProps,
|
||||||
|
data: UpdateRegionDTO,
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
): Promise<Region[]> {
|
): Promise<RegionDTO | RegionDTO[]> {
|
||||||
let normalizedInput: UpdateRegionDTO[] = []
|
let normalizedInput: UpdateRegionInput[] = []
|
||||||
if (isString(idOrSelectorOrData)) {
|
if (isString(idOrSelector)) {
|
||||||
normalizedInput = [{ id: idOrSelectorOrData, ...data }]
|
normalizedInput = [{ id: idOrSelector, ...data }]
|
||||||
}
|
} else {
|
||||||
|
|
||||||
if (Array.isArray(idOrSelectorOrData)) {
|
|
||||||
normalizedInput = idOrSelectorOrData
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isObject(idOrSelectorOrData)) {
|
|
||||||
const regions = await this.regionService_.list(
|
const regions = await this.regionService_.list(
|
||||||
idOrSelectorOrData,
|
idOrSelector,
|
||||||
{},
|
{},
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
@@ -200,7 +209,22 @@ export default class RegionModuleService<
|
|||||||
...data,
|
...data,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
normalizedInput = RegionModuleService.normalizeInput(normalizedInput)
|
|
||||||
|
const updateResult = await this.update_(normalizedInput, sharedContext)
|
||||||
|
|
||||||
|
const regions = await this.baseRepository_.serialize<
|
||||||
|
RegionDTO[] | RegionDTO
|
||||||
|
>(updateResult)
|
||||||
|
|
||||||
|
return isString(idOrSelector) ? regions[0] : regions
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager("baseRepository_")
|
||||||
|
protected async update_(
|
||||||
|
data: UpdateRegionInput[],
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<Region[]> {
|
||||||
|
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.
|
// 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
|
// Somewhat less efficient, but region operations will be very rare, so it is better to go with a simple solution
|
||||||
@@ -245,9 +269,7 @@ export default class RegionModuleService<
|
|||||||
return await this.regionService_.update(normalizedDbRegions, sharedContext)
|
return await this.regionService_.update(normalizedDbRegions, sharedContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
private static normalizeInput<T extends UpdatableRegionFields>(
|
private static normalizeInput<T extends UpdateRegionDTO>(regions: T[]): T[] {
|
||||||
regions: T[]
|
|
||||||
): T[] {
|
|
||||||
return regions.map((region) =>
|
return regions.map((region) =>
|
||||||
removeUndefined({
|
removeUndefined({
|
||||||
...region,
|
...region,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Logger } from "@medusajs/types"
|
import { Logger, UpdateRegionDTO } from "@medusajs/types"
|
||||||
import { Country } from "@models"
|
import { Country } from "@models"
|
||||||
|
|
||||||
export type InitializeModuleInjectableDependencies = {
|
export type InitializeModuleInjectableDependencies = {
|
||||||
@@ -24,3 +24,5 @@ export type CreateCountryDTO = {
|
|||||||
name: string
|
name: string
|
||||||
display_name: string
|
display_name: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type UpdateRegionInput = UpdateRegionDTO & { id: string }
|
||||||
@@ -22,16 +22,13 @@ export interface CreateRegionDTO {
|
|||||||
metadata?: Record<string, unknown>
|
metadata?: Record<string, unknown>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface UpsertRegionDTO {
|
||||||
/**
|
/**
|
||||||
* The attributes to update in the region.
|
* The id of the region in the case of an update
|
||||||
*/
|
*/
|
||||||
export interface UpdateRegionDTO {
|
id?: string
|
||||||
/**
|
/**
|
||||||
* The ID of the region.
|
* The target name of the region
|
||||||
*/
|
|
||||||
id: string
|
|
||||||
/**
|
|
||||||
* The name of the region.
|
|
||||||
*/
|
*/
|
||||||
name?: string
|
name?: string
|
||||||
/**
|
/**
|
||||||
@@ -48,12 +45,9 @@ export interface UpdateRegionDTO {
|
|||||||
metadata?: Record<string, unknown>
|
metadata?: Record<string, unknown>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface UpdateRegionDTO {
|
||||||
/**
|
/**
|
||||||
* The updatable fields of a region.
|
* The target name of the region
|
||||||
*/
|
|
||||||
export interface UpdatableRegionFields {
|
|
||||||
/**
|
|
||||||
* The name of the region.
|
|
||||||
*/
|
*/
|
||||||
name?: string
|
name?: string
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -10,11 +10,7 @@ import {
|
|||||||
RegionCurrencyDTO,
|
RegionCurrencyDTO,
|
||||||
RegionDTO,
|
RegionDTO,
|
||||||
} from "./common"
|
} from "./common"
|
||||||
import {
|
import { CreateRegionDTO, UpsertRegionDTO, UpdateRegionDTO } from "./mutations"
|
||||||
CreateRegionDTO,
|
|
||||||
UpdatableRegionFields,
|
|
||||||
UpdateRegionDTO,
|
|
||||||
} from "./mutations"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main service interface for the region module.
|
* The main service interface for the region module.
|
||||||
@@ -45,21 +41,46 @@ export interface IRegionModuleService extends IModuleService {
|
|||||||
create(data: CreateRegionDTO, sharedContext?: Context): Promise<RegionDTO>
|
create(data: CreateRegionDTO, sharedContext?: Context): Promise<RegionDTO>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method updates existing regions.
|
* This method updates existing regions, or creates new ones if they don't exist.
|
||||||
*
|
*
|
||||||
* @param {UpdateRegionDTO[]} data - The attributes to update in each region.
|
* @param {UpsertRegionDTO[]} data - The attributes to update or create in each region.
|
||||||
* @returns {Promise<RegionDTO[]>} The updated regions.
|
* @returns {Promise<RegionDTO[]>} The updated and created regions.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* {example-code}
|
* {example-code}
|
||||||
*/
|
*/
|
||||||
update(data: UpdateRegionDTO[]): Promise<RegionDTO[]>
|
upsert(data: UpsertRegionDTO[], sharedContext?: Context): Promise<RegionDTO[]>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method updates an existing region, or creates a new one if it doesn't exist.
|
||||||
|
*
|
||||||
|
* @param {UpsertRegionDTO} data - The attributes to update or create for the region.
|
||||||
|
* @returns {Promise<RegionDTO>} The updated or created region.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* {example-code}
|
||||||
|
*/
|
||||||
|
upsert(data: UpsertRegionDTO, sharedContext?: Context): Promise<RegionDTO>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method updates an existing region.
|
||||||
|
*
|
||||||
|
* @param {string} id - The region's ID.
|
||||||
|
* @param {UpdatableRegionFields} data - The details to update in the region.
|
||||||
|
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
|
||||||
|
* @returns {Promise<RegionDTO>} The updated region.
|
||||||
|
*/
|
||||||
|
update(
|
||||||
|
id: string,
|
||||||
|
data: UpdateRegionDTO,
|
||||||
|
sharedContext?: Context
|
||||||
|
): Promise<RegionDTO>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method updates existing regions.
|
* This method updates existing regions.
|
||||||
*
|
*
|
||||||
* @param {FilterableRegionProps} selector - The filters to specify which regions should be updated.
|
* @param {FilterableRegionProps} selector - The filters to specify which regions should be updated.
|
||||||
* @param {UpdatableRegionFields} data - The details to update in the regions.
|
* @param {UpdateRegionDTO} data - The details to update in the regions.
|
||||||
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
|
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
|
||||||
* @returns {Promise<RegionDTO[]>} The updated regions.
|
* @returns {Promise<RegionDTO[]>} The updated regions.
|
||||||
*
|
*
|
||||||
@@ -68,24 +89,10 @@ export interface IRegionModuleService extends IModuleService {
|
|||||||
*/
|
*/
|
||||||
update(
|
update(
|
||||||
selector: FilterableRegionProps,
|
selector: FilterableRegionProps,
|
||||||
data: UpdatableRegionFields,
|
data: UpdateRegionDTO,
|
||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<RegionDTO[]>
|
): Promise<RegionDTO[]>
|
||||||
|
|
||||||
/**
|
|
||||||
* This method updates an existing region.
|
|
||||||
*
|
|
||||||
* @param {string} regionId - The region's ID.
|
|
||||||
* @param {UpdatableRegionFields} data - The details to update in the regions.
|
|
||||||
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
|
|
||||||
* @returns {Promise<RegionDTO>} The updated region.
|
|
||||||
*/
|
|
||||||
update(
|
|
||||||
regionId: string,
|
|
||||||
data: UpdatableRegionFields,
|
|
||||||
sharedContext?: Context
|
|
||||||
): Promise<RegionDTO>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method deletes regions by their IDs.
|
* This method deletes regions by their IDs.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in new issue
Block a user