Files
medusa-store/packages/link-modules/src/initialize/index.ts
Philip Korsholm 148f537b47 feat(medusa): integrate pricing module to core (#5304)
* 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>
2023-10-30 14:42:17 +01:00

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 })
}
}