* add pricing integraiton feature flag * init * first endpoint * cleanup * remove console.logs * refactor to util and implement across endpoints * add changeset * rename variables * remove mistype * feat(medusa): move price module integration to pricing service (#5322) * initial changes * chore: make product service always internal for pricing module * add notes --------- Co-authored-by: Riqwan Thamir <rmthamir@gmail.com> * nit * cleanup * update to object querying * update cart integration test * remove uppercase currency_code * nit * Feat/admin product pricing module reads (#5354) * initial changes to list prices for admin * working price module implementation of list prices * nit * variant pricing * redo integration test changes * cleanup * cleanup * fix unit tests * [wip] Core <> Pricing - price updates (#5364) * chore: update medusa-app * wip * get links and modules working with migration * wip * chore: make test pass * Feat/rule type utils (#5371) * initial rule type utils * update migration script * chore: cleanup * ensure prices are always decorated * chore: use seed instead * chore: fix oas conflict * region id add to admin price read! --------- Co-authored-by: Philip Korsholm <88927411+pKorsholm@users.noreply.github.com> Co-authored-by: Philip Korsholm <philip.korsholm@hotmail.com> * pr feedback * create remoteQueryFunction type * fix merge * fix loaders issue * Feat(medusa, types, pricing): pricing module migration script (#5409) * add migration script for money amounts in pricing module * add changeset * rename file * cleanup imports * update changeset * add check for pricing module and ff * feat(medusa,workflows,types): update prices on product and variant update (#5412) * wip * chore: update product prices through workflow * chore: cleanup * chore: update product handler updates prices for variants * chore: handle reverts * chore: address pr comments * chore: scope workflow handlers to flag handlers * chore: update return * chore: update db url * chore: remove migration * chore: increase jest timeout * Feat(medusa): update migration and initDb to run link-migrations (#5437) * initial * loader update * more progress on loaders * update integration tests and remote-query loader * remove helper * migrate isolated modules * fix test * fix integration test * update with pr feedback * unregister medusa-app * re-register medusaApp * fix featureflag * set timeout * set timeout * conditionally run link-module migrations * pr feedback 1 * add driver options for db * throw if link is not defined in migration script * pass config module directly * include container in migrate command * chore: increase timeout * rm redis from api integration tests to test * chore: temporarily skip tests * chore: undo skips + add timeout for workflow tests * chore: increase timeout for order edits * re-add redis * include final resolution * add sharedcontainer to medusaapp loader * chore: move migration under run command * try removing redis_url from api tests * chore: cleanup server on process exit * chore: clear container on exit * chore: adjustments * chore: remove consoles * chore: close express app on finish * chore: destroy pg connection on shutdown * chore: skip * chore: unskip test * chore: cleanup container pg connection * chore: skip --------- Co-authored-by: Riqwan Thamir <rmthamir@gmail.com>
191 lines
5.3 KiB
TypeScript
191 lines
5.3 KiB
TypeScript
import { InternalModuleDeclaration, MedusaModule } from "@medusajs/modules-sdk"
|
|
import {
|
|
ExternalModuleDeclaration,
|
|
ILinkModule,
|
|
LinkModuleDefinition,
|
|
LoaderOptions,
|
|
MODULE_RESOURCE_TYPE,
|
|
MODULE_SCOPE,
|
|
ModuleExports,
|
|
ModuleJoinerConfig,
|
|
ModuleServiceInitializeCustomDataLayerOptions,
|
|
ModuleServiceInitializeOptions,
|
|
} from "@medusajs/types"
|
|
import {
|
|
ContainerRegistrationKeys,
|
|
lowerCaseFirst,
|
|
simpleHash,
|
|
} from "@medusajs/utils"
|
|
import * as linkDefinitions from "../definitions"
|
|
import { getMigration } from "../migration"
|
|
import { InitializeModuleInjectableDependencies } from "../types"
|
|
import { composeLinkName, generateGraphQLSchema } from "../utils"
|
|
import { getLinkModuleDefinition } from "./module-definition"
|
|
|
|
export const initialize = async (
|
|
options?:
|
|
| ModuleServiceInitializeOptions
|
|
| ModuleServiceInitializeCustomDataLayerOptions
|
|
| ExternalModuleDeclaration
|
|
| InternalModuleDeclaration,
|
|
modulesDefinition?: ModuleJoinerConfig[],
|
|
injectedDependencies?: InitializeModuleInjectableDependencies
|
|
): Promise<{ [link: string]: ILinkModule }> => {
|
|
const allLinks = {}
|
|
const modulesLoadedKeys = MedusaModule.getLoadedModules().map(
|
|
(mod) => Object.keys(mod)[0]
|
|
)
|
|
|
|
const allLinksToLoad = Object.values(linkDefinitions).concat(
|
|
modulesDefinition ?? []
|
|
)
|
|
|
|
for (const linkDefinition of allLinksToLoad) {
|
|
const definition = JSON.parse(JSON.stringify(linkDefinition))
|
|
|
|
const [primary, foreign] = definition.relationships ?? []
|
|
|
|
if (definition.relationships?.length !== 2 && !definition.isReadOnlyLink) {
|
|
throw new Error(
|
|
`Link module ${definition.serviceName} can only link 2 modules.`
|
|
)
|
|
} else if (
|
|
foreign?.foreignKey?.split(",").length > 1 &&
|
|
!definition.isReadOnlyLink
|
|
) {
|
|
throw new Error(`Foreign key cannot be a composed key.`)
|
|
}
|
|
|
|
const serviceKey = !definition.isReadOnlyLink
|
|
? lowerCaseFirst(
|
|
definition.serviceName ??
|
|
composeLinkName(
|
|
primary.serviceName,
|
|
primary.foreignKey,
|
|
foreign.serviceName,
|
|
foreign.foreignKey
|
|
)
|
|
)
|
|
: simpleHash(JSON.stringify(definition.extends))
|
|
|
|
if (modulesLoadedKeys.includes(serviceKey)) {
|
|
continue
|
|
} else if (serviceKey in allLinks) {
|
|
throw new Error(`Link module ${serviceKey} already defined.`)
|
|
}
|
|
|
|
if (definition.isReadOnlyLink) {
|
|
const extended: any[] = []
|
|
for (const extension of definition.extends ?? []) {
|
|
if (
|
|
modulesLoadedKeys.includes(extension.serviceName) &&
|
|
modulesLoadedKeys.includes(extension.relationship.serviceName)
|
|
) {
|
|
extended.push(extension)
|
|
}
|
|
}
|
|
|
|
definition.extends = extended
|
|
if (extended.length === 0) {
|
|
continue
|
|
}
|
|
} else if (
|
|
(!primary.isInternalService &&
|
|
!modulesLoadedKeys.includes(primary.serviceName)) ||
|
|
(!foreign.isInternalService &&
|
|
!modulesLoadedKeys.includes(foreign.serviceName))
|
|
) {
|
|
continue
|
|
}
|
|
|
|
definition.schema = generateGraphQLSchema(definition, primary, foreign)
|
|
|
|
const moduleDefinition = getLinkModuleDefinition(
|
|
definition,
|
|
primary,
|
|
foreign
|
|
) as ModuleExports
|
|
|
|
const linkModuleDefinition: LinkModuleDefinition = {
|
|
key: serviceKey,
|
|
registrationName: serviceKey,
|
|
label: serviceKey,
|
|
defaultModuleDeclaration: {
|
|
scope: MODULE_SCOPE.INTERNAL,
|
|
resources: injectedDependencies?.[
|
|
ContainerRegistrationKeys.PG_CONNECTION
|
|
]
|
|
? MODULE_RESOURCE_TYPE.SHARED
|
|
: MODULE_RESOURCE_TYPE.ISOLATED,
|
|
},
|
|
}
|
|
|
|
const loaded = await MedusaModule.bootstrapLink({
|
|
definition: linkModuleDefinition,
|
|
declaration: options as InternalModuleDeclaration,
|
|
moduleExports: moduleDefinition,
|
|
injectedDependencies,
|
|
})
|
|
|
|
allLinks[serviceKey as string] = Object.values(loaded)[0]
|
|
}
|
|
|
|
return allLinks
|
|
}
|
|
|
|
export async function runMigrations(
|
|
{
|
|
options,
|
|
logger,
|
|
}: Omit<LoaderOptions<ModuleServiceInitializeOptions>, "container">,
|
|
modulesDefinition?: ModuleJoinerConfig[]
|
|
) {
|
|
const modulesLoadedKeys = MedusaModule.getLoadedModules().map(
|
|
(mod) => Object.keys(mod)[0]
|
|
)
|
|
|
|
const allLinksToLoad = Object.values(linkDefinitions).concat(
|
|
modulesDefinition ?? []
|
|
)
|
|
|
|
const allLinks = new Set<string>()
|
|
for (const definition of allLinksToLoad) {
|
|
if (definition.isReadOnlyLink) {
|
|
continue
|
|
}
|
|
|
|
if (definition.relationships?.length !== 2) {
|
|
throw new Error(
|
|
`Link module ${definition.serviceName} must have 2 relationships.`
|
|
)
|
|
}
|
|
|
|
const [primary, foreign] = definition.relationships ?? []
|
|
const serviceKey = lowerCaseFirst(
|
|
definition.serviceName ??
|
|
composeLinkName(
|
|
primary.serviceName,
|
|
primary.foreignKey,
|
|
foreign.serviceName,
|
|
foreign.foreignKey
|
|
)
|
|
)
|
|
|
|
if (allLinks.has(serviceKey)) {
|
|
throw new Error(`Link module ${serviceKey} already exists.`)
|
|
}
|
|
|
|
allLinks.add(serviceKey)
|
|
|
|
if (
|
|
!modulesLoadedKeys.includes(primary.serviceName) ||
|
|
!modulesLoadedKeys.includes(foreign.serviceName)
|
|
) {
|
|
continue
|
|
}
|
|
|
|
const migrate = getMigration(definition, serviceKey, primary, foreign)
|
|
await migrate({ options, logger })
|
|
}
|
|
}
|