feat: Remove sales channels from pub keys (#6876)
**What** - Add workflow + step for detaching sales channels from pub API keys - Tweak linking error message to be more helpful - Add `removeRemoteLink` step to delete API key workflow
This commit is contained in:
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/medusa": patch
|
||||||
|
"@medusajs/core-flows": patch
|
||||||
|
"@medusajs/link-modules": patch
|
||||||
|
"@medusajs/modules-sdk": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
feat: Remove sales channels from pub keys
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ApiKeyType } from "@medusajs/utils"
|
import { ApiKeyType, ContainerRegistrationKeys } from "@medusajs/utils"
|
||||||
import { medusaIntegrationTestRunner } from "medusa-test-utils"
|
import { medusaIntegrationTestRunner } from "medusa-test-utils"
|
||||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||||
|
|
||||||
@@ -268,6 +268,127 @@ medusaIntegrationTestRunner({
|
|||||||
"Sales channels with IDs phony do not exist"
|
"Sales channels with IDs phony do not exist"
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should detach sales channels from a publishable API key", async () => {
|
||||||
|
const salesChannelRes = await api.post(
|
||||||
|
`/admin/sales-channels`,
|
||||||
|
{
|
||||||
|
name: "Test Sales Channel",
|
||||||
|
},
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
const { sales_channel } = salesChannelRes.data
|
||||||
|
|
||||||
|
const apiKeyRes = await api.post(
|
||||||
|
`/admin/api-keys`,
|
||||||
|
{
|
||||||
|
title: "Test publishable KEY",
|
||||||
|
type: ApiKeyType.PUBLISHABLE,
|
||||||
|
},
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
const { api_key } = apiKeyRes.data
|
||||||
|
|
||||||
|
const keyWithChannelsRes = await api.post(
|
||||||
|
`/admin/api-keys/${api_key.id}/sales-channels/batch/add`,
|
||||||
|
{
|
||||||
|
sales_channel_ids: [sales_channel.id],
|
||||||
|
},
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
const { api_key: keyWithChannels } = keyWithChannelsRes.data
|
||||||
|
|
||||||
|
expect(keyWithChannelsRes.status).toEqual(200)
|
||||||
|
expect(keyWithChannels.title).toEqual("Test publishable KEY")
|
||||||
|
expect(keyWithChannels.sales_channels).toEqual([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: sales_channel.id,
|
||||||
|
name: "Test Sales Channel",
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
|
||||||
|
const keyWithoutChannelsRes = await api.post(
|
||||||
|
`/admin/api-keys/${api_key.id}/sales-channels/batch/remove`,
|
||||||
|
{
|
||||||
|
sales_channel_ids: [sales_channel.id],
|
||||||
|
},
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
const { api_key: keyWithoutChannels } = keyWithoutChannelsRes.data
|
||||||
|
|
||||||
|
expect(keyWithoutChannelsRes.status).toEqual(200)
|
||||||
|
expect(keyWithoutChannels.title).toEqual("Test publishable KEY")
|
||||||
|
expect(keyWithoutChannels.sales_channels).toEqual([])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should detach sales channels from a publishable API key on delete", async () => {
|
||||||
|
const salesChannelRes = await api.post(
|
||||||
|
`/admin/sales-channels`,
|
||||||
|
{
|
||||||
|
name: "Test Sales Channel",
|
||||||
|
},
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
const { sales_channel } = salesChannelRes.data
|
||||||
|
|
||||||
|
const apiKeyRes = await api.post(
|
||||||
|
`/admin/api-keys`,
|
||||||
|
{
|
||||||
|
title: "Test publishable KEY",
|
||||||
|
type: ApiKeyType.PUBLISHABLE,
|
||||||
|
},
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
const { api_key } = apiKeyRes.data
|
||||||
|
|
||||||
|
const keyWithChannelsRes = await api.post(
|
||||||
|
`/admin/api-keys/${api_key.id}/sales-channels/batch/add`,
|
||||||
|
{
|
||||||
|
sales_channel_ids: [sales_channel.id],
|
||||||
|
},
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
const { api_key: keyWithChannels } = keyWithChannelsRes.data
|
||||||
|
|
||||||
|
expect(keyWithChannelsRes.status).toEqual(200)
|
||||||
|
expect(keyWithChannels.title).toEqual("Test publishable KEY")
|
||||||
|
expect(keyWithChannels.sales_channels).toEqual([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: sales_channel.id,
|
||||||
|
name: "Test Sales Channel",
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
|
||||||
|
await api.delete(`/admin/api-keys/${api_key.id}`, adminHeaders)
|
||||||
|
|
||||||
|
const deletedApiKeys = await api.get(
|
||||||
|
`/admin/api-keys?id=${api_key.id}`,
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(deletedApiKeys.data.api_keys).toHaveLength(0)
|
||||||
|
|
||||||
|
const remoteQuery = container.resolve(
|
||||||
|
ContainerRegistrationKeys.REMOTE_QUERY
|
||||||
|
)
|
||||||
|
|
||||||
|
// Not the prettiest, but an easy way to check if the link was removed
|
||||||
|
const channels = await remoteQuery({
|
||||||
|
publishable_api_key_sales_channels: {
|
||||||
|
__args: { sales_channel_id: [sales_channel.id] },
|
||||||
|
fields: ["id", "sales_channel_id", "publishable_key_id"],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(channels).toHaveLength(0)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
+4
@@ -16,6 +16,10 @@ export const associateApiKeysWithSalesChannelsStep = createStep(
|
|||||||
async (input: StepInput, { container }) => {
|
async (input: StepInput, { container }) => {
|
||||||
const remoteLink = container.resolve(ContainerRegistrationKeys.REMOTE_LINK)
|
const remoteLink = container.resolve(ContainerRegistrationKeys.REMOTE_LINK)
|
||||||
|
|
||||||
|
if (!input.links) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const links = input.links
|
const links = input.links
|
||||||
.map((link) => {
|
.map((link) => {
|
||||||
return link.sales_channel_ids.map((id) => {
|
return link.sales_channel_ids.map((id) => {
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import { Modules } from "@medusajs/modules-sdk"
|
||||||
|
import { ContainerRegistrationKeys } from "@medusajs/utils"
|
||||||
|
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||||
|
|
||||||
|
interface StepInput {
|
||||||
|
links: {
|
||||||
|
api_key_id: string
|
||||||
|
sales_channel_ids: string[]
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const detachApiKeysWithSalesChannelsStepId =
|
||||||
|
"detach-sales-channels-with-api-keys"
|
||||||
|
export const detachApiKeysWithSalesChannelsStep = createStep(
|
||||||
|
detachApiKeysWithSalesChannelsStepId,
|
||||||
|
async (input: StepInput, { container }) => {
|
||||||
|
const remoteLink = container.resolve(ContainerRegistrationKeys.REMOTE_LINK)
|
||||||
|
|
||||||
|
const links = input.links
|
||||||
|
.map((link) => {
|
||||||
|
return link.sales_channel_ids.map((id) => {
|
||||||
|
return {
|
||||||
|
[Modules.API_KEY]: {
|
||||||
|
publishable_key_id: link.api_key_id,
|
||||||
|
},
|
||||||
|
[Modules.SALES_CHANNEL]: {
|
||||||
|
sales_channel_id: id,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.flat()
|
||||||
|
|
||||||
|
await remoteLink.dismiss(links)
|
||||||
|
|
||||||
|
return new StepResponse(void 0, links)
|
||||||
|
},
|
||||||
|
async (links, { container }) => {
|
||||||
|
if (!links?.length) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const remoteLink = container.resolve(ContainerRegistrationKeys.REMOTE_LINK)
|
||||||
|
|
||||||
|
await remoteLink.create(links)
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
export * from "./associate-sales-channels-with-publishable-keys"
|
export * from "./associate-sales-channels-with-publishable-keys"
|
||||||
export * from "./create-api-keys"
|
export * from "./create-api-keys"
|
||||||
export * from "./delete-api-keys"
|
export * from "./delete-api-keys"
|
||||||
|
export * from "./detach-sales-channels-from-publishable-keys"
|
||||||
export * from "./revoke-api-keys"
|
export * from "./revoke-api-keys"
|
||||||
export * from "./update-api-keys"
|
export * from "./update-api-keys"
|
||||||
export * from "./validate-sales-channel-exists"
|
export * from "./validate-sales-channel-exists"
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
import { Modules } from "@medusajs/modules-sdk"
|
||||||
import { WorkflowData, createWorkflow } from "@medusajs/workflows-sdk"
|
import { WorkflowData, createWorkflow } from "@medusajs/workflows-sdk"
|
||||||
|
import { removeRemoteLinkStep } from "../../common/steps/remove-remote-links"
|
||||||
import { deleteApiKeysStep } from "../steps"
|
import { deleteApiKeysStep } from "../steps"
|
||||||
|
|
||||||
type WorkflowInput = { ids: string[] }
|
type WorkflowInput = { ids: string[] }
|
||||||
@@ -7,6 +9,11 @@ export const deleteApiKeysWorkflowId = "delete-api-keys"
|
|||||||
export const deleteApiKeysWorkflow = createWorkflow(
|
export const deleteApiKeysWorkflow = createWorkflow(
|
||||||
deleteApiKeysWorkflowId,
|
deleteApiKeysWorkflowId,
|
||||||
(input: WorkflowData<WorkflowInput>): WorkflowData<void> => {
|
(input: WorkflowData<WorkflowInput>): WorkflowData<void> => {
|
||||||
return deleteApiKeysStep(input.ids)
|
deleteApiKeysStep(input.ids)
|
||||||
|
|
||||||
|
// Please note, the ids here should be publishable key IDs
|
||||||
|
removeRemoteLinkStep({
|
||||||
|
[Modules.API_KEY]: { publishable_key_id: input.ids },
|
||||||
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -3,3 +3,4 @@ export * from "./delete-api-keys"
|
|||||||
export * from "./update-api-keys"
|
export * from "./update-api-keys"
|
||||||
export * from "./revoke-api-keys"
|
export * from "./revoke-api-keys"
|
||||||
export * from "./add-sales-channels-to-publishable-key"
|
export * from "./add-sales-channels-to-publishable-key"
|
||||||
|
export * from "./remove-sales-channels-from-publishable-key"
|
||||||
|
|||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
import { WorkflowData, createWorkflow } from "@medusajs/workflows-sdk"
|
||||||
|
import { detachApiKeysWithSalesChannelsStep } from "../steps/detach-sales-channels-from-publishable-keys"
|
||||||
|
|
||||||
|
type WorkflowInput = {
|
||||||
|
data: {
|
||||||
|
api_key_id: string
|
||||||
|
sales_channel_ids: string[]
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const removeSalesChannelsFromApiKeyWorkflowId =
|
||||||
|
"remove-sales-channels-from-api-key"
|
||||||
|
export const removeSalesChannelsFromApiKeyWorkflow = createWorkflow(
|
||||||
|
removeSalesChannelsFromApiKeyWorkflowId,
|
||||||
|
(input: WorkflowData<WorkflowInput>) => {
|
||||||
|
detachApiKeysWithSalesChannelsStep({ links: input.data })
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -11,10 +11,10 @@ export const PublishableApiKeySalesChannel: ModuleJoinerConfig = {
|
|||||||
},
|
},
|
||||||
alias: [
|
alias: [
|
||||||
{
|
{
|
||||||
name: "publishable_api_key_sales_channel",
|
name: [
|
||||||
},
|
"publishable_api_key_sales_channel",
|
||||||
{
|
"publishable_api_key_sales_channels",
|
||||||
name: "publishable_api_key_sales_channels",
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
primaryKeys: ["id", "publishable_key_id", "sales_channel_id"],
|
primaryKeys: ["id", "publishable_key_id", "sales_channel_id"],
|
||||||
@@ -49,7 +49,7 @@ export const PublishableApiKeySalesChannel: ModuleJoinerConfig = {
|
|||||||
{
|
{
|
||||||
serviceName: Modules.SALES_CHANNEL,
|
serviceName: Modules.SALES_CHANNEL,
|
||||||
fieldAlias: {
|
fieldAlias: {
|
||||||
api_keys: "api_keys_link.api_key",
|
publishable_api_keys: "api_keys_link.api_key",
|
||||||
},
|
},
|
||||||
relationship: {
|
relationship: {
|
||||||
serviceName: LINKS.PublishableApiKeySalesChannel,
|
serviceName: LINKS.PublishableApiKeySalesChannel,
|
||||||
|
|||||||
@@ -50,6 +50,18 @@ export const LINKS = {
|
|||||||
Modules.STOCK_LOCATION,
|
Modules.STOCK_LOCATION,
|
||||||
"location_id"
|
"location_id"
|
||||||
),
|
),
|
||||||
|
PublishableApiKeySalesChannel: composeLinkName(
|
||||||
|
Modules.API_KEY,
|
||||||
|
"api_key_id",
|
||||||
|
Modules.SALES_CHANNEL,
|
||||||
|
"sales_channel_id"
|
||||||
|
),
|
||||||
|
ProductSalesChannel: composeLinkName(
|
||||||
|
Modules.PRODUCT,
|
||||||
|
"product_id",
|
||||||
|
Modules.SALES_CHANNEL,
|
||||||
|
"sales_channel_id"
|
||||||
|
),
|
||||||
|
|
||||||
// Internal services
|
// Internal services
|
||||||
ProductShippingProfile: composeLinkName(
|
ProductShippingProfile: composeLinkName(
|
||||||
@@ -58,22 +70,10 @@ export const LINKS = {
|
|||||||
"shippingProfileService",
|
"shippingProfileService",
|
||||||
"profile_id"
|
"profile_id"
|
||||||
),
|
),
|
||||||
ProductSalesChannel: composeLinkName(
|
|
||||||
Modules.PRODUCT,
|
|
||||||
"product_id",
|
|
||||||
Modules.SALES_CHANNEL,
|
|
||||||
"sales_channel_id"
|
|
||||||
),
|
|
||||||
OrderSalesChannel: composeLinkName(
|
OrderSalesChannel: composeLinkName(
|
||||||
"orderService",
|
"orderService",
|
||||||
"order_id",
|
"order_id",
|
||||||
Modules.SALES_CHANNEL,
|
Modules.SALES_CHANNEL,
|
||||||
"sales_channel_id"
|
"sales_channel_id"
|
||||||
),
|
),
|
||||||
PublishableApiKeySalesChannel: composeLinkName(
|
|
||||||
Modules.API_KEY,
|
|
||||||
"api_key_id",
|
|
||||||
Modules.SALES_CHANNEL,
|
|
||||||
"sales_channel_id"
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,13 +9,14 @@ import {
|
|||||||
AuthenticatedMedusaRequest,
|
AuthenticatedMedusaRequest,
|
||||||
MedusaResponse,
|
MedusaResponse,
|
||||||
} from "../../../../../../../types/routing"
|
} from "../../../../../../../types/routing"
|
||||||
import { AdminPostApiKeysApiKeySalesChannelsBatchReq } from "../../../../validators"
|
import { AdminPostApiKeysApiKeySalesChannelsBatchAddReq } from "../../../../validators"
|
||||||
|
|
||||||
export const POST = async (
|
export const POST = async (
|
||||||
req: AuthenticatedMedusaRequest,
|
req: AuthenticatedMedusaRequest,
|
||||||
res: MedusaResponse
|
res: MedusaResponse
|
||||||
) => {
|
) => {
|
||||||
const body = req.validatedBody as AdminPostApiKeysApiKeySalesChannelsBatchReq
|
const body =
|
||||||
|
req.validatedBody as AdminPostApiKeysApiKeySalesChannelsBatchAddReq
|
||||||
|
|
||||||
const apiKeyModule = req.scope.resolve(ModuleRegistrationName.API_KEY)
|
const apiKeyModule = req.scope.resolve(ModuleRegistrationName.API_KEY)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
import { removeSalesChannelsFromApiKeyWorkflow } from "@medusajs/core-flows"
|
||||||
|
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||||
|
import {
|
||||||
|
ContainerRegistrationKeys,
|
||||||
|
MedusaError,
|
||||||
|
remoteQueryObjectFromString,
|
||||||
|
} from "@medusajs/utils"
|
||||||
|
import {
|
||||||
|
AuthenticatedMedusaRequest,
|
||||||
|
MedusaResponse,
|
||||||
|
} from "../../../../../../../types/routing"
|
||||||
|
import { AdminPostApiKeysApiKeySalesChannelsBatchRemoveReq } from "../../../../validators"
|
||||||
|
|
||||||
|
export const POST = async (
|
||||||
|
req: AuthenticatedMedusaRequest,
|
||||||
|
res: MedusaResponse
|
||||||
|
) => {
|
||||||
|
const body =
|
||||||
|
req.validatedBody as AdminPostApiKeysApiKeySalesChannelsBatchRemoveReq
|
||||||
|
|
||||||
|
const apiKeyModule = req.scope.resolve(ModuleRegistrationName.API_KEY)
|
||||||
|
|
||||||
|
const apiKey = await apiKeyModule.retrieve(req.params.id)
|
||||||
|
|
||||||
|
if (apiKey.type !== "publishable") {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.INVALID_DATA,
|
||||||
|
"Sales channels can only be associated with publishable API keys"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const workflowInput = {
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
api_key_id: req.params.id,
|
||||||
|
sales_channel_ids: body.sales_channel_ids,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
const { errors } = await removeSalesChannelsFromApiKeyWorkflow(req.scope).run(
|
||||||
|
{
|
||||||
|
input: workflowInput,
|
||||||
|
throwOnError: false,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (Array.isArray(errors) && errors[0]) {
|
||||||
|
throw errors[0].error
|
||||||
|
}
|
||||||
|
|
||||||
|
const query = remoteQueryObjectFromString({
|
||||||
|
entryPoint: "api_key",
|
||||||
|
fields: req.remoteQueryConfig.fields,
|
||||||
|
variables: {
|
||||||
|
id: req.params.id,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
|
||||||
|
|
||||||
|
const [result] = await remoteQuery(query)
|
||||||
|
|
||||||
|
res.status(200).json({ api_key: result })
|
||||||
|
}
|
||||||
@@ -5,7 +5,8 @@ import {
|
|||||||
AdminGetApiKeysApiKeyParams,
|
AdminGetApiKeysApiKeyParams,
|
||||||
AdminGetApiKeysParams,
|
AdminGetApiKeysParams,
|
||||||
AdminPostApiKeysApiKeyReq,
|
AdminPostApiKeysApiKeyReq,
|
||||||
AdminPostApiKeysApiKeySalesChannelsBatchReq,
|
AdminPostApiKeysApiKeySalesChannelsBatchAddReq,
|
||||||
|
AdminPostApiKeysApiKeySalesChannelsBatchRemoveReq,
|
||||||
AdminPostApiKeysReq,
|
AdminPostApiKeysReq,
|
||||||
AdminRevokeApiKeysApiKeyReq,
|
AdminRevokeApiKeysApiKeyReq,
|
||||||
} from "./validators"
|
} from "./validators"
|
||||||
@@ -84,7 +85,18 @@ export const adminApiKeyRoutesMiddlewares: MiddlewareRoute[] = [
|
|||||||
AdminGetApiKeysApiKeyParams,
|
AdminGetApiKeysApiKeyParams,
|
||||||
QueryConfig.retrieveTransformQueryConfig
|
QueryConfig.retrieveTransformQueryConfig
|
||||||
),
|
),
|
||||||
transformBody(AdminPostApiKeysApiKeySalesChannelsBatchReq),
|
transformBody(AdminPostApiKeysApiKeySalesChannelsBatchAddReq),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: ["POST"],
|
||||||
|
matcher: "/admin/api-keys/:id/sales-channels/batch/remove",
|
||||||
|
middlewares: [
|
||||||
|
transformQuery(
|
||||||
|
AdminGetApiKeysApiKeyParams,
|
||||||
|
QueryConfig.retrieveTransformQueryConfig
|
||||||
|
),
|
||||||
|
transformBody(AdminPostApiKeysApiKeySalesChannelsBatchRemoveReq),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -79,7 +79,10 @@ export class AdminRevokeApiKeysApiKeyReq {
|
|||||||
|
|
||||||
export class AdminDeleteApiKeysApiKeyReq {}
|
export class AdminDeleteApiKeysApiKeyReq {}
|
||||||
|
|
||||||
export class AdminPostApiKeysApiKeySalesChannelsBatchReq {
|
export class AdminPostApiKeysApiKeySalesChannelsBatchAddReq {
|
||||||
@IsArray()
|
@IsArray()
|
||||||
sales_channel_ids: string[]
|
sales_channel_ids: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
|
export class AdminPostApiKeysApiKeySalesChannelsBatchRemoveReq extends AdminPostApiKeysApiKeySalesChannelsBatchAddReq {}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
|
|
||||||
import { isObject, promiseAll, toPascalCase } from "@medusajs/utils"
|
import { isObject, promiseAll, toPascalCase } from "@medusajs/utils"
|
||||||
import { MedusaModule } from "./medusa-module"
|
import { MedusaModule } from "./medusa-module"
|
||||||
|
import { linkingErrorMessage } from "./utils/linking-error"
|
||||||
|
|
||||||
export type DeleteEntityInput = {
|
export type DeleteEntityInput = {
|
||||||
[moduleName: string]: { [linkableKey: string]: string | string[] }
|
[moduleName: string]: { [linkableKey: string]: string | string[] }
|
||||||
@@ -353,7 +354,13 @@ export class RemoteLink {
|
|||||||
|
|
||||||
if (!service) {
|
if (!service) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Module to link ${moduleA}[${moduleAKey}] and ${moduleB}[${moduleBKey}] was not found.`
|
linkingErrorMessage({
|
||||||
|
moduleA,
|
||||||
|
moduleAKey,
|
||||||
|
moduleB,
|
||||||
|
moduleBKey,
|
||||||
|
type: "link",
|
||||||
|
})
|
||||||
)
|
)
|
||||||
} else if (!serviceLinks.has(service.__definition.key)) {
|
} else if (!serviceLinks.has(service.__definition.key)) {
|
||||||
serviceLinks.set(service.__definition.key, [])
|
serviceLinks.set(service.__definition.key, [])
|
||||||
@@ -404,7 +411,13 @@ export class RemoteLink {
|
|||||||
|
|
||||||
if (!service) {
|
if (!service) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Module to dismiss link ${moduleA}[${moduleAKey}] and ${moduleB}[${moduleBKey}] was not found.`
|
linkingErrorMessage({
|
||||||
|
moduleA,
|
||||||
|
moduleAKey,
|
||||||
|
moduleB,
|
||||||
|
moduleBKey,
|
||||||
|
type: "dismiss",
|
||||||
|
})
|
||||||
)
|
)
|
||||||
} else if (!serviceLinks.has(service.__definition.key)) {
|
} else if (!serviceLinks.has(service.__definition.key)) {
|
||||||
serviceLinks.set(service.__definition.key, [])
|
serviceLinks.set(service.__definition.key, [])
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
const typeToMethod = new Map([
|
||||||
|
[`dismiss`, `dismiss`],
|
||||||
|
[`link`, `create`],
|
||||||
|
])
|
||||||
|
|
||||||
|
type LinkingErrorMessageInput = {
|
||||||
|
moduleA: string
|
||||||
|
moduleAKey: string
|
||||||
|
moduleB: string
|
||||||
|
moduleBKey: string
|
||||||
|
type: "dismiss" | "link"
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Example: Module to dismiss salesChannel and apiKey by keys sales_channel_id and api_key_id was not found. Ensure the link exists, keys are correct, and the link is passed in the correct order to method 'remoteLink.dismiss'
|
||||||
|
*/
|
||||||
|
export const linkingErrorMessage = (input: LinkingErrorMessageInput) => {
|
||||||
|
const { moduleA, moduleB, moduleAKey, moduleBKey, type } = input
|
||||||
|
return `Module to type ${moduleA} and ${moduleB} by keys ${moduleAKey} and ${moduleBKey} was not found. Ensure the link exists, keys are correct, and link is passed in the correct order to method 'remoteLink.${typeToMethod.get(
|
||||||
|
type
|
||||||
|
)}'.
|
||||||
|
`
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user