diff --git a/.changeset/cool-walls-smoke.md b/.changeset/cool-walls-smoke.md new file mode 100644 index 0000000000..6e0377b3a4 --- /dev/null +++ b/.changeset/cool-walls-smoke.md @@ -0,0 +1,7 @@ +--- +"@medusajs/orchestration": patch +"@medusajs/core-flows": patch +"@medusajs/framework": patch +--- + +chore(orchestration): validate missing PK filters when throwIfKeyNotFound diff --git a/integration-tests/modules/__tests__/modules/remote-query.spec.ts b/integration-tests/modules/__tests__/modules/remote-query.spec.ts index 7256ff4ee1..cf77a808cc 100644 --- a/integration-tests/modules/__tests__/modules/remote-query.spec.ts +++ b/integration-tests/modules/__tests__/modules/remote-query.spec.ts @@ -1,6 +1,6 @@ +import { medusaIntegrationTestRunner } from "@medusajs/test-utils" import { IRegionModuleService, RemoteQueryFunction } from "@medusajs/types" import { ContainerRegistrationKeys, Modules } from "@medusajs/utils" -import { medusaIntegrationTestRunner } from "@medusajs/test-utils" import { createAdminUser } from "../../..//helpers/create-admin-user" import { adminHeaders } from "../../../helpers/create-admin-user" @@ -70,6 +70,77 @@ medusaIntegrationTestRunner({ ) }) + it("should fail to retrieve not passing primary key in filters", async () => { + const noPk = remoteQuery( + { + region: { + fields: ["id", "currency_code"], + }, + }, + { throwIfKeyNotFound: true } + ) + await expect(noPk).rejects.toThrow( + "Region: Primary key(s) [id, iso_2] not found in filters" + ) + + const noPk2 = remoteQuery( + { + country: { + fields: ["*"], + }, + }, + { throwIfKeyNotFound: true } + ) + await expect(noPk2).rejects.toThrow( + "Country: Primary key(s) [id, iso_2] not found in filters" + ) + + const noPk3 = remoteQuery( + { + country: { + fields: ["*"], + __args: { + iso_2: undefined, + }, + }, + }, + { throwIfKeyNotFound: true } + ) + await expect(noPk3).rejects.toThrow( + "Country: Value for primary key iso_2 not found in filters" + ) + + const noPk4 = remoteQuery( + { + region: { + fields: ["id", "currency_code"], + __args: { + id: null, + }, + }, + }, + { throwIfKeyNotFound: true } + ) + await expect(noPk4).rejects.toThrow( + "Region: Value for primary key id not found in filters" + ) + + const noPk5 = remoteQuery( + { + region: { + fields: ["id", "currency_code"], + __args: { + currency_code: "EUR", + }, + }, + }, + { throwIfKeyNotFound: true } + ) + await expect(noPk5).rejects.toThrow( + "Region: Primary key(s) [id, iso_2] not found in filters" + ) + }) + it("should fail if a expected relation is not found", async () => { const region = await regionModule.createRegions({ name: "Test Region", diff --git a/packages/core/core-flows/src/order/workflows/claim/confirm-claim-request.ts b/packages/core/core-flows/src/order/workflows/claim/confirm-claim-request.ts index a127e8492e..599b4f9a71 100644 --- a/packages/core/core-flows/src/order/workflows/claim/confirm-claim-request.ts +++ b/packages/core/core-flows/src/order/workflows/claim/confirm-claim-request.ts @@ -75,14 +75,14 @@ export type ConfirmClaimRequestValidationStepInput = { /** * This step validates that a requested claim can be confirmed. If the order or claim is canceled, * or the order change is not active, the step will throw an error. - * + * * :::note - * + * * You can retrieve an order, order claim, and order change details using [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query), * or [useQueryGraphStep](https://docs.medusajs.com/resources/references/medusa-workflows/steps/useQueryGraphStep). - * + * * ::: - * + * * @example * const data = confirmClaimRequestValidationStep({ * order: { @@ -270,12 +270,12 @@ export type ConfirmClaimRequestWorkflowInput = { export const confirmClaimRequestWorkflowId = "confirm-claim-request" /** - * This workflow confirms a requested claim. It's used by the + * This workflow confirms a requested claim. It's used by the * [Confirm Claim Request API Route](https://docs.medusajs.com/api/admin#claims_postclaimsidrequest). - * + * * You can use this workflow within your customizations or your own custom workflows, allowing you to confirm a claim * for an order in your custom flows. - * + * * @example * const { result } = await confirmClaimRequestWorkflow(container) * .run({ @@ -283,9 +283,9 @@ export const confirmClaimRequestWorkflowId = "confirm-claim-request" * claim_id: "claim_123", * } * }) - * + * * @summary - * + * * Confirm a requested claim. */ export const confirmClaimRequestWorkflow = createWorkflow( @@ -387,13 +387,6 @@ export const confirmClaimRequestWorkflow = createWorkflow( updateReturnsStep(updateReturnDate) }) - const claimId = transform( - { createdClaimItems }, - ({ createdClaimItems }) => { - return createdClaimItems?.[0]?.claim_id - } - ) - const { returnShippingMethod, claimShippingMethod } = transform( { orderPreview, orderClaim, returnId }, extractShippingOption @@ -421,7 +414,7 @@ export const confirmClaimRequestWorkflow = createWorkflow( "additional_items.item.variant.inventory_items.inventory.location_levels.stock_locations.sales_channels.id", "additional_items.item.variant.inventory_items.inventory.location_levels.stock_locations.sales_channels.name", ], - variables: { id: claimId }, + variables: { id: input.claim_id }, list: false, throw_if_key_not_found: true, }).config({ name: "claim-query" }) @@ -477,7 +470,6 @@ export const confirmClaimRequestWorkflow = createWorkflow( id: returnShippingMethod.shipping_option_id, }, list: false, - throw_if_key_not_found: true, }).config({ name: "claim-return-shipping-option" }) const fulfillmentData = transform( diff --git a/packages/core/core-flows/src/order/workflows/create-fulfillment.ts b/packages/core/core-flows/src/order/workflows/create-fulfillment.ts index 8f4304eacb..05393a0e41 100644 --- a/packages/core/core-flows/src/order/workflows/create-fulfillment.ts +++ b/packages/core/core-flows/src/order/workflows/create-fulfillment.ts @@ -384,7 +384,6 @@ export const createOrderFulfillmentWorkflow = createWorkflow( id: shippingOptionId, }, list: false, - throw_if_key_not_found: true, }).config({ name: "get-shipping-option" }) const lineItemIds = transform( diff --git a/packages/core/core-flows/src/order/workflows/exchange/confirm-exchange-request.ts b/packages/core/core-flows/src/order/workflows/exchange/confirm-exchange-request.ts index a4acf07065..6599211ef8 100644 --- a/packages/core/core-flows/src/order/workflows/exchange/confirm-exchange-request.ts +++ b/packages/core/core-flows/src/order/workflows/exchange/confirm-exchange-request.ts @@ -63,14 +63,14 @@ export type ConfirmExchangeRequestValidationStepInput = { /** * This step validates that a requested exchange can be confirmed. * If the order or exchange is canceled, or the order change is not active, the step will throw an error. - * + * * :::note - * + * * You can retrieve an order, order exchange, and order change details using [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query), * or [useQueryGraphStep](https://docs.medusajs.com/resources/references/medusa-workflows/steps/useQueryGraphStep). - * + * * ::: - * + * * @example * const data = confirmExchangeRequestValidationStep({ * order: { @@ -266,10 +266,10 @@ export const confirmExchangeRequestWorkflowId = "confirm-exchange-request" /** * This workflow confirms an exchange request. It's used by the * [Confirm Exchange Admin API Route](https://docs.medusajs.com/api/admin#exchanges_postexchangesidrequest). - * + * * You can use this workflow within your customizations or your own custom workflows, allowing you to confirm an exchange * for an order in your custom flow. - * + * * @example * const { result } = await confirmExchangeRequestWorkflow(container) * .run({ @@ -277,9 +277,9 @@ export const confirmExchangeRequestWorkflowId = "confirm-exchange-request" * exchange_id: "exchange_123", * } * }) - * + * * @summary - * + * * Confirm an exchange request. */ export const confirmExchangeRequestWorkflow = createWorkflow( @@ -373,13 +373,6 @@ export const confirmExchangeRequestWorkflow = createWorkflow( updateReturnsStep(updateReturnData) }) - const exchangeId = transform( - { createdExchangeItems }, - ({ createdExchangeItems }) => { - return createdExchangeItems?.[0]?.exchange_id - } - ) - const { returnShippingMethod, exchangeShippingMethod } = transform( { orderPreview, orderExchange, returnId }, extractShippingOption @@ -407,7 +400,7 @@ export const confirmExchangeRequestWorkflow = createWorkflow( "additional_items.item.variant.inventory_items.inventory.location_levels.stock_locations.sales_channels.id", "additional_items.item.variant.inventory_items.inventory.location_levels.stock_locations.sales_channels.name", ], - variables: { id: exchangeId }, + variables: { id: input.exchange_id }, list: false, throw_if_key_not_found: true, }).config({ name: "exchange-query" }) @@ -463,7 +456,6 @@ export const confirmExchangeRequestWorkflow = createWorkflow( id: returnShippingMethod.shipping_option_id, }, list: false, - throw_if_key_not_found: true, }).config({ name: "exchange-return-shipping-option" }) const fulfillmentData = transform( diff --git a/packages/core/core-flows/src/order/workflows/payments/create-order-refund-credit-lines.ts b/packages/core/core-flows/src/order/workflows/payments/create-order-refund-credit-lines.ts index 903301c485..ee276352d2 100644 --- a/packages/core/core-flows/src/order/workflows/payments/create-order-refund-credit-lines.ts +++ b/packages/core/core-flows/src/order/workflows/payments/create-order-refund-credit-lines.ts @@ -97,7 +97,6 @@ export const createOrderRefundCreditLinesWorkflow = createWorkflow( order_id: input.order_id, status: [OrderChangeStatus.PENDING], }, - options: { throwIfKeyNotFound: true }, }).config({ name: "order-change-query" }) const orderChange = transform( diff --git a/packages/core/core-flows/src/order/workflows/return/confirm-return-request.ts b/packages/core/core-flows/src/order/workflows/return/confirm-return-request.ts index b500e0dd1a..ac3c8ce212 100644 --- a/packages/core/core-flows/src/order/workflows/return/confirm-return-request.ts +++ b/packages/core/core-flows/src/order/workflows/return/confirm-return-request.ts @@ -58,14 +58,14 @@ export type ConfirmReturnRequestValidationStepInput = { /** * This step validates that a return request can be confirmed. * If the order or return is canceled or the order change is not active, the step will throw an error. - * + * * :::note - * + * * You can retrieve an order, order change, and return details using [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query), * or [useQueryGraphStep](https://docs.medusajs.com/resources/references/medusa-workflows/steps/useQueryGraphStep). - * + * * ::: - * + * * @example * const data = confirmReturnRequestValidationStep({ * order: { @@ -219,12 +219,12 @@ export type ConfirmReturnRequestWorkflowInput = { export const confirmReturnRequestWorkflowId = "confirm-return-request" /** - * This workflow confirms a return request. It's used by the + * This workflow confirms a return request. It's used by the * [Confirm Return Request Admin API Route](https://docs.medusajs.com/api/admin#returns_postreturnsidrequest). - * + * * You can use this workflow within your customizations or your own custom workflows, allowing you to confirm a return request * in your custom flow. - * + * * @example * const { result } = await confirmReturnRequestWorkflow(container) * .run({ @@ -232,9 +232,9 @@ export const confirmReturnRequestWorkflowId = "confirm-return-request" * return_id: "return_123", * } * }) - * + * * @summary - * + * * Confirm a return request. */ export const confirmReturnRequestWorkflow = createWorkflow( @@ -326,7 +326,6 @@ export const confirmReturnRequestWorkflow = createWorkflow( id: returnShippingOptionId, }, list: false, - throw_if_key_not_found: true, }).config({ name: "return-shipping-option" }) const fulfillmentData = transform( diff --git a/packages/core/core-flows/src/order/workflows/return/create-complete-return.ts b/packages/core/core-flows/src/order/workflows/return/create-complete-return.ts index dcc1a29163..5278df3bdf 100644 --- a/packages/core/core-flows/src/order/workflows/return/create-complete-return.ts +++ b/packages/core/core-flows/src/order/workflows/return/create-complete-return.ts @@ -225,17 +225,17 @@ export type CreateCompleteReturnValidationStepInput = { /** * This step validates that a return can be created and completed for an order. - * If the order is canceled, the items do not exist in the order, - * the return reasons are invalid, or the refund amount is greater than the order total, + * If the order is canceled, the items do not exist in the order, + * the return reasons are invalid, or the refund amount is greater than the order total, * the step will throw an error. - * + * * :::note - * + * * You can retrieve an order details using [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query), * or [useQueryGraphStep](https://docs.medusajs.com/resources/references/medusa-workflows/steps/useQueryGraphStep). - * + * * ::: - * + * * @example * const data = createCompleteReturnValidationStep({ * order: { @@ -256,10 +256,7 @@ export type CreateCompleteReturnValidationStepInput = { export const createCompleteReturnValidationStep = createStep( "create-return-order-validation", async function ( - { - order, - input, - }: CreateCompleteReturnValidationStepInput, + { order, input }: CreateCompleteReturnValidationStepInput, context ) { if (!input.items) { @@ -282,13 +279,13 @@ export const createCompleteReturnValidationStep = createStep( export const createAndCompleteReturnOrderWorkflowId = "create-complete-return-order" /** - * This workflow creates and completes a return from the storefront. The admin would receive the return and - * process it from the dashboard. This workflow is used by the + * This workflow creates and completes a return from the storefront. The admin would receive the return and + * process it from the dashboard. This workflow is used by the * [Create Return Store API Route](https://docs.medusajs.com/api/store#return_postreturn). - * + * * You can use this workflow within your customizations or your own custom workflows, allowing you to create a return * for an order in your custom flow. - * + * * @example * const { result } = await createAndCompleteReturnOrderWorkflow(container) * .run({ @@ -302,9 +299,9 @@ export const createAndCompleteReturnOrderWorkflowId = * ] * } * }) - * + * * @summary - * + * * Create and complete a return for an order. */ export const createAndCompleteReturnOrderWorkflow = createWorkflow( @@ -348,7 +345,6 @@ export const createAndCompleteReturnOrderWorkflow = createWorkflow( ], variables: returnShippingOptionsVariables, list: false, - throw_if_key_not_found: true, }).config({ name: "return-shipping-option" }) const shippingMethodData = transform( diff --git a/packages/core/core-flows/src/order/workflows/transfer/accept-order-transfer.ts b/packages/core/core-flows/src/order/workflows/transfer/accept-order-transfer.ts index b3ba57d108..9ead905357 100644 --- a/packages/core/core-flows/src/order/workflows/transfer/accept-order-transfer.ts +++ b/packages/core/core-flows/src/order/workflows/transfer/accept-order-transfer.ts @@ -18,9 +18,9 @@ import { } from "@medusajs/utils" import { useQueryGraphStep } from "../../../common" -import { throwIfOrderIsCancelled } from "../../utils/order-validation" import { previewOrderChangeStep } from "../../steps" import { confirmOrderChanges } from "../../steps/confirm-order-changes" +import { throwIfOrderIsCancelled } from "../../utils/order-validation" /** * The details of the order transfer acceptance to validate. @@ -43,14 +43,14 @@ export type AcceptOrderTransferValidationStepInput = { /** * This step validates that an order transfer can be accepted. If the * order doesn't have an existing transfer request, the step throws an error. - * + * * :::note - * + * * You can retrieve an order and order change details using [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query), * or [useQueryGraphStep](https://docs.medusajs.com/resources/references/medusa-workflows/steps/useQueryGraphStep). - * + * * ::: - * + * * @example * const data = acceptOrderTransferValidationStep({ * token: "sk_123456", @@ -95,12 +95,12 @@ export const acceptOrderTransferValidationStep = createStep( export const acceptOrderTransferWorkflowId = "accept-order-transfer-workflow" /** - * This workflow accepts an order transfer, requested previously by the {@link requestOrderTransferWorkflow}. This workflow is used by the + * This workflow accepts an order transfer, requested previously by the {@link requestOrderTransferWorkflow}. This workflow is used by the * [Accept Order Transfer Store API Route](https://docs.medusajs.com/api/store#orders_postordersidtransferaccept). - * + * * You can use this workflow within your customizations or your own custom workflows, allowing you to build a custom flow * around accepting an order transfer. - * + * * @example * const { result } = await acceptOrderTransferWorkflow(container) * .run({ @@ -109,9 +109,9 @@ export const acceptOrderTransferWorkflowId = "accept-order-transfer-workflow" * order_id: "order_123", * } * }) - * + * * @summary - * + * * Accept an order transfer request. */ export const acceptOrderTransferWorkflow = createWorkflow( @@ -149,7 +149,6 @@ export const acceptOrderTransferWorkflow = createWorkflow( order_id: input.order_id, status: [OrderChangeStatus.REQUESTED], }, - options: { throwIfKeyNotFound: true }, }).config({ name: "order-change-query" }) const orderChange = transform( diff --git a/packages/core/core-flows/src/order/workflows/transfer/cancel-order-transfer.ts b/packages/core/core-flows/src/order/workflows/transfer/cancel-order-transfer.ts index 76a20f1c5a..7581e2bf4a 100644 --- a/packages/core/core-flows/src/order/workflows/transfer/cancel-order-transfer.ts +++ b/packages/core/core-flows/src/order/workflows/transfer/cancel-order-transfer.ts @@ -43,14 +43,14 @@ export type CancelTransferOrderRequestValidationStep = { * This step validates that a requested order transfer can be canceled. * If the customer canceling the order transfer isn't the one that requested the transfer, * the step throws an error. Admin users can cancel any order transfer. - * + * * :::note - * + * * You can retrieve an order and order change details using [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query), * or [useQueryGraphStep](https://docs.medusajs.com/resources/references/medusa-workflows/steps/useQueryGraphStep). - * + * * ::: - * + * * @example * const data = cancelTransferOrderRequestValidationStep({ * order: { @@ -101,10 +101,10 @@ export const cancelTransferOrderRequestWorkflowId = * This workflow cancels a requested order transfer. This operation is allowed only by admin users and the customer that requested the transfer. * This workflow is used by the [Cancel Order Transfer Store API Route](https://docs.medusajs.com/api/store#orders_postordersidtransfercancel), * and the [Cancel Transfer Request Admin API Route](https://docs.medusajs.com/api/admin#orders_postordersidtransfercancel). - * + * * You can use this workflow within your customizations or your own custom workflows, allowing you to build a custom flow * around canceling an order transfer. - * + * * @example * const { result } = await cancelOrderTransferRequestWorkflow(container) * .run({ @@ -114,9 +114,9 @@ export const cancelTransferOrderRequestWorkflowId = * actor_type: "customer" * } * }) - * + * * @summary - * + * * Cancel an order transfer request. */ export const cancelOrderTransferRequestWorkflow = createWorkflow( @@ -143,7 +143,6 @@ export const cancelOrderTransferRequestWorkflow = createWorkflow( order_id: input.order_id, status: [OrderChangeStatus.PENDING, OrderChangeStatus.REQUESTED], }, - options: { throwIfKeyNotFound: true }, }).config({ name: "order-change-query" }) const orderChange = transform( diff --git a/packages/core/core-flows/src/order/workflows/transfer/decline-order-transfer.ts b/packages/core/core-flows/src/order/workflows/transfer/decline-order-transfer.ts index a342b7d941..d49d2b700b 100644 --- a/packages/core/core-flows/src/order/workflows/transfer/decline-order-transfer.ts +++ b/packages/core/core-flows/src/order/workflows/transfer/decline-order-transfer.ts @@ -42,16 +42,16 @@ export type DeclineTransferOrderRequestValidationStepInput = { /** * This step validates that a requested order transfer can be declineed. - * If the provided token doesn't match the token of the transfer request, + * If the provided token doesn't match the token of the transfer request, * the step throws an error. - * + * * :::note - * + * * You can retrieve an order and order change details using [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query), * or [useQueryGraphStep](https://docs.medusajs.com/resources/references/medusa-workflows/steps/useQueryGraphStep). - * + * * ::: - * + * * @example * const data = declineTransferOrderRequestValidationStep({ * order: { @@ -93,9 +93,9 @@ export const declineTransferOrderRequestWorkflowId = /** * This workflow declines a requested order transfer by its token. It's used by the * [Decline Order Transfer Store API Route](https://docs.medusajs.com/api/store#orders_postordersidtransferdecline). - * + * * You can use this workflow within your customizations or your own custom workflows, allowing you to wrap custom logic around declining an order transfer request. - * + * * @example * const { result } = await declineOrderTransferRequestWorkflow(container) * .run({ @@ -104,9 +104,9 @@ export const declineTransferOrderRequestWorkflowId = * order_id: "order_123", * } * }) - * + * * @summary - * + * * Decline a requested order transfer. */ export const declineOrderTransferRequestWorkflow = createWorkflow( @@ -133,7 +133,6 @@ export const declineOrderTransferRequestWorkflow = createWorkflow( order_id: input.order_id, status: [OrderChangeStatus.PENDING, OrderChangeStatus.REQUESTED], }, - options: { throwIfKeyNotFound: true }, }).config({ name: "order-change-query" }) const orderChange = transform( diff --git a/packages/core/framework/src/http/middlewares/ensure-publishable-api-key.ts b/packages/core/framework/src/http/middlewares/ensure-publishable-api-key.ts index e6693477fa..9447ce3176 100644 --- a/packages/core/framework/src/http/middlewares/ensure-publishable-api-key.ts +++ b/packages/core/framework/src/http/middlewares/ensure-publishable-api-key.ts @@ -33,21 +33,18 @@ export async function ensurePublishableApiKeyMiddleware( const query = req.scope.resolve(ContainerRegistrationKeys.QUERY) try { - const { data } = await query.graph( - { - entity: "api_key", - fields: ["id", "token", "sales_channels_link.sales_channel_id"], - filters: { - token: publishableApiKey, - type: ApiKeyType.PUBLISHABLE, - $or: [ - { revoked_at: { $eq: null } }, - { revoked_at: { $gt: new Date() } }, - ], - }, + const { data } = await query.graph({ + entity: "api_key", + fields: ["id", "token", "sales_channels_link.sales_channel_id"], + filters: { + token: publishableApiKey, + type: ApiKeyType.PUBLISHABLE, + $or: [ + { revoked_at: { $eq: null } }, + { revoked_at: { $gt: new Date() } }, + ], }, - { throwIfKeyNotFound: true } - ) + }) apiKey = data[0] } catch (e) { diff --git a/packages/core/orchestration/src/__tests__/joiner/remote-joiner-data.ts b/packages/core/orchestration/src/__tests__/joiner/remote-joiner-data.ts index 453b4ed02c..30b6584c74 100644 --- a/packages/core/orchestration/src/__tests__/joiner/remote-joiner-data.ts +++ b/packages/core/orchestration/src/__tests__/joiner/remote-joiner-data.ts @@ -832,5 +832,21 @@ describe("RemoteJoiner", () => { await expect(dataNotFound).rejects.toThrowError( "order id not found: ord_1234556" ) + + const queryNotFoundNoParam = RemoteJoiner.parseQuery(` + query { + order { + id + number + } + } + `) + const dataNotFoundNoPK = joiner.query(queryNotFoundNoParam, { + throwIfKeyNotFound: true, + }) + + await expect(dataNotFoundNoPK).rejects.toThrowError( + "order: Primary key(s) [id] not found in filters" + ) }) }) diff --git a/packages/core/orchestration/src/joiner/remote-joiner.ts b/packages/core/orchestration/src/joiner/remote-joiner.ts index cbf3099722..35992aada5 100644 --- a/packages/core/orchestration/src/joiner/remote-joiner.ts +++ b/packages/core/orchestration/src/joiner/remote-joiner.ts @@ -37,6 +37,15 @@ type InternalImplodeMapping = { isList?: boolean } +type InternalParseExpandsParams = { + initialService: RemoteExpandProperty + query: RemoteJoinerQuery + serviceConfig: InternalJoinerServiceConfig + expands: RemoteJoinerQuery["expands"] + implodeMapping: InternalImplodeMapping[] + options?: RemoteJoinerOptions +} + export class RemoteJoiner { private serviceConfigCache: Map = new Map() @@ -831,14 +840,9 @@ export class RemoteJoiner { }) } - private parseExpands(params: { - initialService: RemoteExpandProperty - query: RemoteJoinerQuery - serviceConfig: InternalJoinerServiceConfig - expands: RemoteJoinerQuery["expands"] - implodeMapping: InternalImplodeMapping[] - options?: RemoteJoinerOptions - }): Map { + private parseExpands( + params: InternalParseExpandsParams + ): Map { const { initialService, query, serviceConfig, expands, implodeMapping } = params @@ -1203,8 +1207,30 @@ export class RemoteJoiner { queryObj, }) + if (options?.throwIfKeyNotFound) { + if (primaryKeyArg?.value == undefined) { + if (!primaryKeyArg) { + throw new MedusaError( + MedusaError.Types.NOT_FOUND, + `${ + serviceConfig.entity ?? serviceConfig.serviceName + }: Primary key(s) [${serviceConfig.primaryKeys.join( + ", " + )}] not found in filters` + ) + } + + throw new MedusaError( + MedusaError.Types.NOT_FOUND, + `${ + serviceConfig.entity ?? serviceConfig.serviceName + }: Value for primary key ${primaryKeyArg.name} not found in filters` + ) + } + } + const implodeMapping: InternalImplodeMapping[] = [] - const parseExpandsConfig: Parameters[0] = { + const parseExpandsConfig: InternalParseExpandsParams = { initialService: { property: "", parent: "",