feat: region payment providers management workflows/api (#6864)

This commit is contained in:
Adrien de Peretti
2024-04-04 20:41:34 +02:00
committed by GitHub
parent 12fcb655cd
commit e944a627f0
48 changed files with 1033 additions and 89 deletions
@@ -0,0 +1,216 @@
import { ModuleRegistrationName, RemoteLink } from "@medusajs/modules-sdk"
import { IPaymentModuleService, RemoteQueryFunction } from "@medusajs/types"
import { createStep, StepResponse } from "@medusajs/workflows-sdk"
import {
arrayDifference,
ContainerRegistrationKeys,
LINKS,
MedusaError,
Modules,
promiseAll,
remoteQueryObjectFromString,
} from "@medusajs/utils"
export interface SetRegionsPaymentProvidersStepInput {
input: {
id: string
payment_providers?: string[]
}[]
}
interface FilteredSetRegionsPaymentProvidersStepInput {
id: string
payment_providers: string[]
}
type LinkItems = {
[Modules.REGION]: { region_id: string }
[Modules.PAYMENT]: { payment_provider_id: string }
}[]
async function validatePaymentProvidersExists(
paymentService: IPaymentModuleService,
paymentProviderIds: string[]
) {
const paymentProviders = await paymentService.listPaymentProviders({
id: { $in: paymentProviderIds },
is_enabled: true,
})
const retrievedPaymentProviderIds = paymentProviders.map((p) => p.id)
const missingProviders = arrayDifference(
paymentProviderIds,
retrievedPaymentProviderIds
)
if (missingProviders.length) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Payment providers with ids ${missingProviders.join(
", "
)} not found or not enabled`
)
}
}
async function getCurrentRegionPaymentProvidersLinks(
regionIds: string[],
{ remoteQuery }: { remoteQuery: RemoteQueryFunction }
): Promise<
{
[Modules.REGION]: { region_id: string }
[Modules.PAYMENT]: { payment_provider_id: string }
}[]
> {
const query = remoteQueryObjectFromString({
service: LINKS.RegionPaymentProvider,
variables: {
filters: { region_id: regionIds },
take: null,
},
fields: ["region_id", "payment_provider_id"],
})
const regionProviderLinks = (await remoteQuery(query)) as {
region_id: string
payment_provider_id: string
}[]
return regionProviderLinks.map((region) => {
return {
[Modules.REGION]: {
region_id: region.region_id,
},
[Modules.PAYMENT]: {
payment_provider_id: region.payment_provider_id,
},
}
})
}
export const setRegionsPaymentProvidersStepId =
"add-region-payment-providers-step"
export const setRegionsPaymentProvidersStep = createStep(
setRegionsPaymentProvidersStepId,
async (data: SetRegionsPaymentProvidersStepInput, { container }) => {
const dataInputToProcess = data.input.filter((inputData) => {
return inputData.payment_providers?.length
}) as FilteredSetRegionsPaymentProvidersStepInput[]
if (!dataInputToProcess.length) {
return new StepResponse(void 0)
}
const paymentService = container.resolve<IPaymentModuleService>(
ModuleRegistrationName.PAYMENT
)
const remoteLink = container.resolve<RemoteLink>(
ContainerRegistrationKeys.REMOTE_LINK
)
const remoteQuery = container.resolve<RemoteQueryFunction>(
ContainerRegistrationKeys.REMOTE_QUERY
)
const allPaymentProviderIds = dataInputToProcess
.map((inputData) => {
return inputData.payment_providers!
})
.flat()
const uniquePaymentProviderIds = Array.from(
new Set<string>(allPaymentProviderIds)
)
await validatePaymentProvidersExists(
paymentService,
uniquePaymentProviderIds
)
const regionIds = dataInputToProcess.map((inputData) => inputData.id)
const currentExistingLinks = await getCurrentRegionPaymentProvidersLinks(
regionIds,
{ remoteQuery }
)
const linksToRemove: LinkItems = currentExistingLinks
.filter((existingLink) => {
return !dataInputToProcess.some((input) => {
return (
input.id === existingLink[Modules.REGION].region_id &&
input.payment_providers.includes(
existingLink[Modules.PAYMENT].payment_provider_id
)
)
})
})
.map((link) => {
return {
[Modules.REGION]: { region_id: link[Modules.REGION].region_id },
[Modules.PAYMENT]: {
payment_provider_id: link[Modules.PAYMENT].payment_provider_id,
},
}
})
const linksToCreate = dataInputToProcess
.map((inputData) => {
return inputData.payment_providers.map((provider) => {
const alreadyExists = currentExistingLinks.some((link) => {
return (
link[Modules.REGION].region_id === inputData.id &&
link[Modules.PAYMENT].payment_provider_id === provider
)
})
if (alreadyExists) {
return
}
return {
[Modules.REGION]: { region_id: inputData.id },
[Modules.PAYMENT]: { payment_provider_id: provider },
}
})
})
.flat()
.filter((d): d is LinkItems[0] => !!d)
const promises: Promise<unknown[]>[] = []
if (linksToRemove.length) {
promises.push(remoteLink.dismiss(linksToRemove))
}
if (linksToCreate.length) {
promises.push(remoteLink.create(linksToCreate))
}
await promiseAll(promises)
return new StepResponse(void 0, {
linksToCreate: linksToRemove,
linksToRemove: linksToCreate,
})
},
async (rollbackData, { container }) => {
if (!rollbackData) {
return
}
const remoteLink = container.resolve<RemoteLink>(
ContainerRegistrationKeys.REMOTE_LINK
)
const promises: Promise<unknown[]>[] = []
if (rollbackData.linksToRemove.length) {
promises.push(remoteLink.dismiss(rollbackData.linksToRemove))
}
if (rollbackData.linksToCreate.length) {
promises.push(remoteLink.create(rollbackData.linksToCreate))
}
await promiseAll(promises)
}
)
@@ -29,6 +29,10 @@ export const updateRegionsStep = createStep(
relations,
})
if (Object.keys(data.update).length === 0) {
return new StepResponse(prevData, [])
}
const regions = await service.update(data.selector, data.update)
return new StepResponse(regions, prevData)
@@ -48,7 +52,7 @@ export const updateRegionsStep = createStep(
name: r.name,
currency_code: r.currency_code,
metadata: r.metadata,
countries: r.countries.map((c) => c.iso_2),
countries: r.countries?.map((c) => c.iso_2),
}))
)
}
@@ -1,13 +1,57 @@
import { CreateRegionDTO, RegionDTO } from "@medusajs/types"
import { WorkflowData, createWorkflow } from "@medusajs/workflows-sdk"
import { WorkflowTypes } from "@medusajs/types"
import {
createWorkflow,
transform,
WorkflowData,
} from "@medusajs/workflows-sdk"
import { createRegionsStep } from "../steps"
type WorkflowInput = { regionsData: CreateRegionDTO[] }
import { setRegionsPaymentProvidersStep } from "../steps/set-regions-payment-providers"
export const createRegionsWorkflowId = "create-regions"
export const createRegionsWorkflow = createWorkflow(
createRegionsWorkflowId,
(input: WorkflowData<WorkflowInput>): WorkflowData<RegionDTO[]> => {
return createRegionsStep(input.regionsData)
(
input: WorkflowData<WorkflowTypes.RegionWorkflow.CreateRegionsWorkflowInput>
): WorkflowData<WorkflowTypes.RegionWorkflow.CreateRegionsWorkflowOutput> => {
const data = transform(input, (data) => {
const regionIndexToPaymentProviders = data.regions.map(
(region, index) => {
return {
region_index: index,
payment_providers: region.payment_providers,
}
}
)
return {
regions: data.regions,
regionIndexToPaymentProviders,
}
})
const regions = createRegionsStep(data.regions)
const normalizedRegionProviderData = transform(
{
regionIndexToPaymentProviders: data.regionIndexToPaymentProviders,
regions,
},
(data) => {
return data.regionIndexToPaymentProviders.map(
({ region_index, payment_providers }) => {
return {
id: data.regions[region_index].id,
payment_providers,
}
}
)
}
)
setRegionsPaymentProvidersStep({
input: normalizedRegionProviderData,
})
return regions
}
)
@@ -1,22 +1,46 @@
import { WorkflowTypes } from "@medusajs/types"
import {
FilterableRegionProps,
RegionDTO,
UpdateRegionDTO,
} from "@medusajs/types"
import { WorkflowData, createWorkflow } from "@medusajs/workflows-sdk"
createWorkflow,
transform,
WorkflowData,
} from "@medusajs/workflows-sdk"
import { updateRegionsStep } from "../steps"
type UpdateRegionsStepInput = {
selector: FilterableRegionProps
update: UpdateRegionDTO
}
type WorkflowInput = UpdateRegionsStepInput
import { setRegionsPaymentProvidersStep } from "../steps/set-regions-payment-providers"
export const updateRegionsWorkflowId = "update-regions"
export const updateRegionsWorkflow = createWorkflow(
updateRegionsWorkflowId,
(input: WorkflowData<WorkflowInput>): WorkflowData<RegionDTO[]> => {
return updateRegionsStep(input)
(
input: WorkflowData<WorkflowTypes.RegionWorkflow.UpdateRegionsWorkflowInput>
): WorkflowData<WorkflowTypes.RegionWorkflow.UpdateRegionsWorkflowOutput> => {
const data = transform(input, (data) => {
const { selector, update } = data
const { payment_providers = [], ...rest } = update
return {
selector,
update: rest,
payment_providers,
}
})
const regions = updateRegionsStep(data)
const upsertProvidersNormalizedInput = transform(
{ data, regions },
(data) => {
return data.regions.map((region) => {
return {
id: region.id,
payment_providers: data.data.payment_providers,
}
})
}
)
setRegionsPaymentProvidersStep({
input: upsertProvidersNormalizedInput,
})
return regions
}
)
@@ -1,6 +1,6 @@
import { Modules } from "@medusajs/modules-sdk"
import { ModuleJoinerConfig } from "@medusajs/types"
import { LINKS } from "../links"
import { LINKS } from "@medusajs/utils"
export const CartPaymentCollection: ModuleJoinerConfig = {
serviceName: LINKS.CartPaymentCollection,
@@ -1,6 +1,6 @@
import { Modules } from "@medusajs/modules-sdk"
import { ModuleJoinerConfig } from "@medusajs/types"
import { LINKS } from "../links"
import { LINKS } from "@medusajs/utils"
export const CartPromotion: ModuleJoinerConfig = {
serviceName: LINKS.CartPromotion,
@@ -1,6 +1,6 @@
import { Modules } from "@medusajs/modules-sdk"
import { ModuleJoinerConfig } from "@medusajs/types"
import { LINKS } from "../links"
import { LINKS } from "@medusajs/utils"
export const FulfillmentSetLocation: ModuleJoinerConfig = {
serviceName: LINKS.FulfillmentSetLocation,
@@ -1,6 +1,5 @@
import { ModuleJoinerConfig } from "@medusajs/types"
import { LINKS } from "../links"
import { LINKS } from "@medusajs/utils"
export const OrderSalesChannel: ModuleJoinerConfig = {
serviceName: LINKS.OrderSalesChannel,
@@ -1,6 +1,6 @@
import { Modules } from "@medusajs/modules-sdk"
import { ModuleJoinerConfig } from "@medusajs/types"
import { LINKS } from "../links"
import { LINKS } from "@medusajs/utils"
export const ProductSalesChannel: ModuleJoinerConfig = {
serviceName: LINKS.ProductSalesChannel,
@@ -1,6 +1,6 @@
import { Modules } from "@medusajs/modules-sdk"
import { ModuleJoinerConfig } from "@medusajs/types"
import { LINKS } from "../links"
import { LINKS } from "@medusajs/utils"
export const ProductShippingProfile: ModuleJoinerConfig = {
serviceName: LINKS.ProductShippingProfile,
@@ -1,6 +1,6 @@
import { Modules } from "@medusajs/modules-sdk"
import { ModuleJoinerConfig } from "@medusajs/types"
import { LINKS } from "../links"
import { LINKS } from "@medusajs/utils"
export const ProductVariantInventoryItem: ModuleJoinerConfig = {
serviceName: LINKS.ProductVariantInventoryItem,
@@ -1,6 +1,6 @@
import { Modules } from "@medusajs/modules-sdk"
import { ModuleJoinerConfig } from "@medusajs/types"
import { LINKS } from "../links"
import { LINKS } from "@medusajs/utils"
export const ProductVariantPriceSet: ModuleJoinerConfig = {
serviceName: LINKS.ProductVariantPriceSet,
@@ -1,6 +1,6 @@
import { Modules } from "@medusajs/modules-sdk"
import { ModuleJoinerConfig } from "@medusajs/types"
import { LINKS } from "../links"
import { LINKS } from "@medusajs/utils"
export const PublishableApiKeySalesChannel: ModuleJoinerConfig = {
serviceName: LINKS.PublishableApiKeySalesChannel,
@@ -1,6 +1,6 @@
import { Modules } from "@medusajs/modules-sdk"
import { ModuleJoinerConfig } from "@medusajs/types"
import { LINKS } from "../links"
import { LINKS } from "@medusajs/utils"
export const RegionPaymentProvider: ModuleJoinerConfig = {
serviceName: LINKS.RegionPaymentProvider,
@@ -1,6 +1,6 @@
import { Modules } from "@medusajs/modules-sdk"
import { ModuleJoinerConfig } from "@medusajs/types"
import { LINKS } from "../links"
import { LINKS } from "@medusajs/utils"
export const SalesChannelLocation: ModuleJoinerConfig = {
serviceName: LINKS.SalesChannelLocation,
@@ -1,6 +1,6 @@
import { Modules } from "@medusajs/modules-sdk"
import { ModuleJoinerConfig } from "@medusajs/types"
import { LINKS } from "../links"
import { LINKS } from "@medusajs/utils"
export const ShippingOptionPriceSet: ModuleJoinerConfig = {
serviceName: LINKS.ShippingOptionPriceSet,
@@ -2,7 +2,7 @@ import { getDatabaseURL } from "./database"
import { initDb } from "./medusa-test-runner-utils/use-db"
import { startBootstrapApp } from "./medusa-test-runner-utils/bootstrap-app"
import { createDatabase, dropDatabase } from "pg-god"
import { ContainerLike } from "@medusajs/types"
import {ContainerLike, MedusaContainer} from "@medusajs/types"
import { createMedusaContainer } from "@medusajs/utils"
const axios = require("axios").default
@@ -70,7 +70,7 @@ const dbTestUtilFactory = (): any => ({
export interface MedusaSuiteOptions<TService = unknown> {
dbUtils: any
dbConnection: any // Legacy typeorm connection
getContainer: () => ContainerLike
getContainer: () => MedusaContainer
api: any
dbConfig: {
dbName: string
@@ -89,7 +89,7 @@ export function medusaIntegrationTestRunner({
testSuite,
}: {
moduleName?: string
env?: Record<string, string>
env?: Record<string, string | any>
dbName?: string
schema?: string
debug?: boolean
@@ -34,7 +34,7 @@ export function moduleIntegrationTestRunner({
injectedDependencies?: Record<string, any>
resolve?: string
debug?: boolean
testSuite: <TService = unknown>(options: SuiteOptions<TService>) => () => void
testSuite: <TService = unknown>(options: SuiteOptions<TService>) => void
}) {
const moduleSdkImports = require("@medusajs/modules-sdk")
@@ -8,8 +8,10 @@ import {
} from "@medusajs/core-flows"
import { UpdateRegionDTO } from "@medusajs/types"
import { defaultAdminRegionFields } from "../query-config"
import { remoteQueryObjectFromString } from "@medusajs/utils"
import {
ContainerRegistrationKeys,
remoteQueryObjectFromString
} from "@medusajs/utils"
export const GET = async (
req: AuthenticatedMedusaRequest,
@@ -22,7 +24,7 @@ export const GET = async (
const queryObject = remoteQueryObjectFromString({
entryPoint: "region",
variables,
fields: defaultAdminRegionFields,
fields: req.remoteQueryConfig.fields,
})
const [region] = await remoteQuery(queryObject)
@@ -46,7 +48,19 @@ export const POST = async (
throw errors[0].error
}
res.status(200).json({ region: result[0] })
const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
const queryObject = remoteQueryObjectFromString({
entryPoint: "region",
variables: {
filters: { id: req.params.id },
},
fields: req.remoteQueryConfig.fields,
})
const regions = await remoteQuery(queryObject)
res.status(200).json({ region: regions[0] })
}
export const DELETE = async (
@@ -40,11 +40,23 @@ export const adminRegionRoutesMiddlewares: MiddlewareRoute[] = [
{
method: ["POST"],
matcher: "/admin/regions",
middlewares: [transformBody(AdminPostRegionsReq)],
middlewares: [
transformQuery(
AdminGetRegionsRegionParams,
QueryConfig.retrieveTransformQueryConfig
),
transformBody(AdminPostRegionsReq),
],
},
{
method: ["POST"],
matcher: "/admin/regions/:id",
middlewares: [transformBody(AdminPostRegionsRegionReq)],
middlewares: [
transformQuery(
AdminGetRegionsRegionParams,
QueryConfig.retrieveTransformQueryConfig
),
transformBody(AdminPostRegionsRegionReq),
],
},
]
@@ -1,5 +1,3 @@
export const defaultAdminRegionRelations = ["countries"]
export const allowedAdminRegionRelations = ["countries"]
export const defaultAdminRegionFields = [
"id",
"name",
@@ -16,13 +14,12 @@ export const defaultAdminRegionFields = [
]
export const retrieveTransformQueryConfig = {
defaultFields: defaultAdminRegionFields,
defaultRelations: defaultAdminRegionRelations,
allowedRelations: allowedAdminRegionRelations,
defaults: defaultAdminRegionFields,
isList: false,
}
export const listTransformQueryConfig = {
defaults: defaultAdminRegionFields,
defaultLimit: 20,
isList: true,
}
@@ -5,24 +5,24 @@ import {
import { CreateRegionDTO } from "@medusajs/types"
import { createRegionsWorkflow } from "@medusajs/core-flows"
import { defaultAdminRegionFields } from "./query-config"
import { remoteQueryObjectFromString } from "@medusajs/utils"
import {
ContainerRegistrationKeys,
remoteQueryObjectFromString,
} from "@medusajs/utils"
export const GET = async (
req: AuthenticatedMedusaRequest,
res: MedusaResponse
) => {
const remoteQuery = req.scope.resolve("remoteQuery")
const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
const queryObject = remoteQueryObjectFromString({
entryPoint: "region",
variables: {
filters: req.filterableFields,
order: req.listConfig.order,
skip: req.listConfig.skip,
take: req.listConfig.take,
...req.remoteQueryConfig.pagination,
},
fields: defaultAdminRegionFields,
fields: req.remoteQueryConfig.fields,
})
const { rows: regions, metadata } = await remoteQuery(queryObject)
@@ -46,7 +46,7 @@ export const POST = async (
]
const { result, errors } = await createRegionsWorkflow(req.scope).run({
input: { regionsData: input },
input: { regions: input },
throwOnError: false,
})
@@ -54,5 +54,17 @@ export const POST = async (
throw errors[0].error
}
res.status(200).json({ region: result[0] })
const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
const queryObject = remoteQueryObjectFromString({
entryPoint: "region",
variables: {
filters: { id: result[0].id },
},
fields: req.remoteQueryConfig.fields,
})
const regions = await remoteQuery(queryObject)
res.status(200).json({ region: regions[0] })
}
@@ -7,7 +7,7 @@ import {
IsString,
ValidateNested,
} from "class-validator"
import { FindParams, extendedFindParamsMixin } from "../../../types/common"
import { extendedFindParamsMixin, FindParams } from "../../../types/common"
import { OperatorMapValidator } from "../../../types/validators/operator-map"
export class AdminGetRegionsRegionParams extends FindParams {}
@@ -90,6 +90,11 @@ export class AdminPostRegionsReq {
@IsObject()
@IsOptional()
metadata?: Record<string, unknown>
@IsOptional()
@IsArray()
@IsString({ each: true })
payment_providers?: string[]
}
export class AdminPostRegionsRegionReq {
@@ -108,4 +113,9 @@ export class AdminPostRegionsRegionReq {
@IsObject()
@IsOptional()
metadata?: Record<string, unknown>
@IsOptional()
@IsArray()
@IsString({ each: true })
payment_providers?: string[]
}
+1
View File
@@ -11,6 +11,7 @@ export enum LinkModuleUtils {
REMOTE_LINK = "remoteLink",
}
// TODO: Remove this enum and use the one from @medusajs/utils
export enum Modules {
AUTH = "auth",
CACHE = "cacheService",
+5 -1
View File
@@ -70,7 +70,11 @@ export function toRemoteJoinerQuery(
}
if (isEntryPoint) {
remoteJoinerQuery.alias = key
if (value.isServiceAccess) {
remoteJoinerQuery.service = key
} else {
remoteJoinerQuery.alias = key
}
} else {
remoteJoinerQuery.expands!.push(expandObj)
}
+1
View File
@@ -8,3 +8,4 @@ export default moduleDefinition
export { revertMigration, runMigrations }
export * from "./initialize"
export * from "./types"
+23 -1
View File
@@ -1,5 +1,27 @@
import { Logger } from "@medusajs/types"
import {
Logger,
ModuleProviderExports,
ModuleServiceInitializeOptions,
} from "@medusajs/types"
export type InitializeModuleInjectableDependencies = {
logger?: Logger
}
export type PaymentModuleOptions = Partial<ModuleServiceInitializeOptions> & {
/**
* Providers to be registered
*/
providers?: {
/**
* The module provider to be registered
*/
resolve: string | ModuleProviderExports
options: {
/**
* key value pair of the provider name and the configuration to be passed to the provider constructor
*/
config: Record<string, unknown>
}
}[]
}
+1 -1
View File
@@ -465,7 +465,7 @@ export interface FilterablePaymentProviderProps
/**
* The IDs to filter the payment collection by.
*/
id?: string | string[]
id?: string | string[] | OperatorMap<string | string[]>
/**
* Filter by enabled status
+1 -1
View File
@@ -76,7 +76,7 @@ export interface FilterableRegionProps
/**
* The IDs to filter the regions by.
*/
id?: string[] | string
id?: string[] | string | OperatorMap<string | string[]>
/**
* Filter regions by their name.
*/
+1
View File
@@ -4,4 +4,5 @@ export * as ProductWorkflow from "./product"
export * as InventoryWorkflow from "./inventory"
export * as PriceListWorkflow from "./price-list"
export * as UserWorkflow from "./user"
export * as RegionWorkflow from "./region"
export * as InviteWorkflow from "./invite"
@@ -0,0 +1,9 @@
import { CreateRegionDTO, RegionDTO } from "../../region"
export interface CreateRegionsWorkflowInput {
regions: (CreateRegionDTO & {
payment_providers?: string[]
})[]
}
export type CreateRegionsWorkflowOutput = RegionDTO[]
@@ -0,0 +1,2 @@
export * from "./update-regions"
export * from "./create-regions"
@@ -0,0 +1,10 @@
import { FilterableRegionProps, RegionDTO, UpdateRegionDTO } from "../../region"
export interface UpdateRegionsWorkflowInput {
selector: FilterableRegionProps
update: UpdateRegionDTO & {
payment_providers?: string[]
}
}
export type UpdateRegionsWorkflowOutput = RegionDTO[]
+1
View File
@@ -13,4 +13,5 @@ export * as SearchUtils from "./search"
export * as ShippingProfileUtils from "./shipping"
export * as UserUtils from "./user"
export * as InventoryUtils from "./inventory"
export * as LinkUtils from "./link"
export * as ApiKeyUtils from "./api-key"
@@ -48,6 +48,57 @@ describe("remoteQueryObjectFromString", function () {
"url",
"metadata",
],
isServiceAccess: false,
tags: {
fields: ["id", "created_at", "updated_at", "deleted_at", "value"],
},
options: {
fields: [
"id",
"created_at",
"updated_at",
"deleted_at",
"title",
"product_id",
"metadata",
],
values: {
fields: [
"id",
"created_at",
"updated_at",
"deleted_at",
"value",
"option_id",
"variant_id",
"metadata",
],
},
},
},
})
})
it("should return a remote query object using service entry point", function () {
const output = remoteQueryObjectFromString({
service: "product",
variables: {},
fields,
})
expect(output).toEqual({
product: {
__args: {},
fields: [
"id",
"created_at",
"updated_at",
"deleted_at",
"url",
"metadata",
],
isServiceAccess: true,
tags: {
fields: ["id", "created_at", "updated_at", "deleted_at", "value"],
},
@@ -1,8 +1,6 @@
/**
* Convert a string fields array to a remote query object
* @param entryPoint
* @param variables
* @param fields
* @param config - The configuration object
*
* @example
* const fields = [
@@ -83,28 +81,41 @@
* // },
* // }
*/
export function remoteQueryObjectFromString({
entryPoint,
variables,
fields,
}: {
entryPoint: string
variables?: any
fields: string[]
}): object {
export function remoteQueryObjectFromString(
config:
| {
entryPoint: string
variables?: any
fields: string[]
}
| {
service: string
variables?: any
fields: string[]
}
): object {
const { entryPoint, service, variables, fields } = {
...config,
entryPoint: "entryPoint" in config ? config.entryPoint : undefined,
service: "service" in config ? config.service : undefined,
}
const entryKey = (entryPoint ?? service) as string
const remoteJoinerConfig: object = {
[entryPoint]: {
[entryKey]: {
fields: [],
isServiceAccess: !!service, // specifies if the entry point is a service
},
}
if (variables) {
remoteJoinerConfig[entryPoint]["__args"] = variables
remoteJoinerConfig[entryKey]["__args"] = variables
}
for (const field of fields) {
if (!field.includes(".")) {
remoteJoinerConfig[entryPoint]["fields"].push(field)
remoteJoinerConfig[entryKey]["fields"].push(field)
continue
}
@@ -114,7 +125,7 @@ export function remoteQueryObjectFromString({
const deepConfigRef = fieldSegments.reduce((acc, curr) => {
acc[curr] ??= {}
return acc[curr]
}, remoteJoinerConfig[entryPoint])
}, remoteJoinerConfig[entryKey])
deepConfigRef["fields"] ??= []
deepConfigRef["fields"].push(fieldProperty)
+1
View File
@@ -22,5 +22,6 @@ export * from "./totals"
export * from "./totals/big-number"
export * from "./user"
export * from "./api-key"
export * from "./link"
export const MedusaModuleType = Symbol.for("MedusaModule")
@@ -0,0 +1,9 @@
import { lowerCaseFirst, toPascalCase } from "../common"
export const composeLinkName = (...args) => {
return lowerCaseFirst(toPascalCase(composeTableName(...args.concat("link"))))
}
export const composeTableName = (...args) => {
return args.map((name) => name.replace(/(_id|Service)$/gi, "")).join("_")
}
+2
View File
@@ -0,0 +1,2 @@
export * from "./links"
export * from "./compose-link-name"
@@ -1,5 +1,5 @@
import { Modules } from "@medusajs/modules-sdk"
import { composeLinkName } from "./utils"
import { Modules } from "../modules-sdk"
import { composeLinkName } from "./compose-link-name"
export const LINKS = {
ProductVariantInventoryItem: composeLinkName(
@@ -0,0 +1,24 @@
export enum Modules {
AUTH = "auth",
CACHE = "cacheService",
CART = "cart",
CUSTOMER = "customer",
EVENT_BUS = "eventBus",
INVENTORY = "inventoryService",
LINK = "linkModules",
PAYMENT = "payment",
PRICING = "pricingService",
PRODUCT = "productService",
PROMOTION = "promotion",
SALES_CHANNEL = "salesChannel",
TAX = "tax",
FULFILLMENT = "fulfillment",
STOCK_LOCATION = "stockLocationService",
USER = "user",
WORKFLOW_ENGINE = "workflows",
REGION = "region",
ORDER = "order",
API_KEY = "apiKey",
STORE = "store",
CURRENCY = "currency",
}
+1
View File
@@ -8,3 +8,4 @@ export * from "./create-pg-connection"
export * from "./migration-scripts"
export * from "./internal-module-service-factory"
export * from "./abstract-module-service-factory"
export * from "./definition"