Skip to content
6 changes: 6 additions & 0 deletions .changeset/eighty-sheep-burn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@medusajs/workflow-engine-redis": patch
"@medusajs/core-flows": patch
---

fix(workflow-engine-redis,core-flows): support top-level redis options and allow adding addresses to orders without existing country code
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { MedusaError } from "@medusajs/framework/utils"
import { throwIfCountryCodeChanged } from "../order-validation"

describe("throwIfCountryCodeChanged", () => {
it("should not throw when existing address is undefined or has no country_code", () => {
expect(() =>
throwIfCountryCodeChanged({
existingAddress: undefined,
inputAddress: { country_code: "us" },
})
).not.toThrow()

expect(() =>
throwIfCountryCodeChanged({
existingAddress: { country_code: undefined },
inputAddress: { country_code: "us" },
})
).not.toThrow()
})

it("should not throw when input address has no country_code", () => {
expect(() =>
throwIfCountryCodeChanged({
existingAddress: { country_code: "us" },
inputAddress: undefined,
})
).not.toThrow()

expect(() =>
throwIfCountryCodeChanged({
existingAddress: { country_code: "us" },
inputAddress: { country_code: undefined },
})
).not.toThrow()
})

it("should not throw when existing and input country_codes match", () => {
expect(() =>
throwIfCountryCodeChanged({
existingAddress: { country_code: "us" },
inputAddress: { country_code: "us" },
})
).not.toThrow()
})

it("should throw MedusaError INVALID_DATA when changing existing country_code to a different value", () => {
expect(() =>
throwIfCountryCodeChanged({
existingAddress: { country_code: "us" },
inputAddress: { country_code: "ca" },
})
).toThrow(
new MedusaError(MedusaError.Types.INVALID_DATA, "Country code cannot be changed")
)
})
})
19 changes: 19 additions & 0 deletions packages/core/core-flows/src/order/utils/order-validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,22 @@ export function throwIfItemsDoesNotExistsInReturn({
)
}
}

export function throwIfCountryCodeChanged({
existingAddress,
inputAddress,
}: {
existingAddress?: { country_code?: string | null } | null
inputAddress?: { country_code?: string | null } | null
}) {
if (
inputAddress?.country_code &&
existingAddress?.country_code &&
existingAddress.country_code !== inputAddress.country_code
) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
"Country code cannot be changed"
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { MedusaError } from "@medusajs/framework/utils"
import { createWorkflow, WorkflowResponse } from "@medusajs/framework/workflows-sdk"
import { updateOrderValidationStep } from "../update-order"

const runValidationStep = async (order: any, input: any) => {
const workflow = createWorkflow(
`update-order-validation-test-${Math.random().toString(36).slice(2)}`,
(wfInput: any) => {
updateOrderValidationStep(wfInput)
return new WorkflowResponse({})
}
)

return workflow().run({ input: { order, input } })
}

describe("updateOrderValidationStep", () => {
it("should not throw when adding shipping address to order with no existing shipping address", async () => {
const order: any = {
id: "order_1",
shipping_address: undefined,
billing_address: undefined,
}

const input: any = {
id: "order_1",
shipping_address: {
address_1: "Main St 123",
city: "Warsaw",
postal_code: "00-001",
country_code: "pl",
},
}

await expect(
runValidationStep(order, input)
).resolves.not.toThrow()
})

it("should throw when trying to change an existing country_code to a different country_code", async () => {
const order: any = {
id: "order_1",
shipping_address: {
country_code: "us",
},
}

const input: any = {
id: "order_1",
shipping_address: {
country_code: "ca",
},
}

await expect(
runValidationStep(order, input)
).rejects.toEqual(
expect.objectContaining({
type: MedusaError.Types.INVALID_DATA,
message: "Country code cannot be changed",
})
)
})

it("should not throw when updating address without changing country_code", async () => {
const order: any = {
id: "order_1",
shipping_address: {
country_code: "us",
city: "Old City",
},
}

const input: any = {
id: "order_1",
shipping_address: {
country_code: "us",
city: "New City",
},
}

await expect(
runValidationStep(order, input)
).resolves.not.toThrow()
})
})
34 changes: 12 additions & 22 deletions packages/core/core-flows/src/order/workflows/update-order.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
UpdateOrderDTO,
} from "@medusajs/framework/types"
import {
MedusaError,
OrderWorkflowEvents,
validateEmail,
} from "@medusajs/framework/utils"
Expand All @@ -27,7 +26,10 @@ import {
updateOrderShippingMethodsTranslationsStep,
updateOrdersStep,
} from "../steps"
import { throwIfOrderIsCancelled } from "../utils/order-validation"
import {
throwIfCountryCodeChanged,
throwIfOrderIsCancelled,
} from "../utils/order-validation"
import { findOrCreateCustomerStep } from "../../cart"
import { updateOrderTaxLinesTranslationsStep } from "../steps/update-order-tax-lines-translations"

Expand Down Expand Up @@ -73,27 +75,15 @@ export const updateOrderValidationStep = createStep(
async function ({ order, input }: UpdateOrderValidationStepInput) {
throwIfOrderIsCancelled({ order })

if (
input.shipping_address?.country_code &&
order.shipping_address?.country_code !==
input.shipping_address?.country_code
) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
"Country code cannot be changed"
)
}
throwIfCountryCodeChanged({
existingAddress: order.shipping_address,
inputAddress: input.shipping_address,
})

if (
input.billing_address?.country_code &&
order.billing_address?.country_code !==
input.billing_address?.country_code
) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
"Country code cannot be changed"
)
}
throwIfCountryCodeChanged({
existingAddress: order.billing_address,
inputAddress: input.billing_address,
})

if (input.email) {
validateEmail(input.email)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,25 @@ describe("Redis Loader", () => {
})
})

describe("Top-level options support", () => {
it("should accept top-level redisUrl without nested redis key", async () => {
await redisLoader(
{
container: containerMock as any,
logger: loggerMock,
options: {
redisUrl: "redis://localhost:6379",
queueName: "top-level-queue",
},
} as any,
{} as any
)

const registerCall = containerMock.register.mock.calls[0][0]
expect(registerCall.redisQueueName.resolve()).toEqual("top-level-queue")
})
})

describe("Error handling", () => {
it("should throw error when redisUrl is not provided", async () => {
await expect(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export default async (
{ container, logger, options, dataLoaderOnly }: LoaderOptions,
moduleDeclaration: InternalModuleDeclaration
): Promise<void> => {
const redisModuleOptions = ((options?.redis ?? options) || {}) as RedisWorkflowsOptions
const {
url,
redisUrl,
Expand All @@ -28,7 +29,7 @@ export default async (
cleanerQueueOptions,
cleanerWorkerOptions,
pubsub,
} = options?.redis as RedisWorkflowsOptions
} = redisModuleOptions

// Handle backward compatibility for deprecated options
const resolvedUrl = redisUrl ?? url
Expand Down
Loading