chore: Hide repository creation if they are not custom + add upsert support by default (#6127)
This commit is contained in:
committed by
GitHub
parent
8a8a7183b8
commit
5e655dd59b
@@ -64,6 +64,10 @@ export interface AbstractService<
|
||||
idsOrFilter: string[] | InternalFilterQuery,
|
||||
sharedContext?: Context
|
||||
): Promise<[TEntity[], Record<string, unknown[]>]>
|
||||
upsert(
|
||||
data: (TDTOs["create"] | TDTOs["update"])[],
|
||||
sharedContext?: Context
|
||||
): Promise<TEntity[]>
|
||||
}
|
||||
|
||||
export function abstractServiceFactory<
|
||||
@@ -75,7 +79,7 @@ export function abstractServiceFactory<
|
||||
>(
|
||||
model: new (...args: any[]) => any
|
||||
): {
|
||||
new <TEntity extends {}>(container: TContainer): AbstractService<
|
||||
new <TEntity extends object = any>(container: TContainer): AbstractService<
|
||||
TEntity,
|
||||
TContainer,
|
||||
TDTOs,
|
||||
@@ -237,6 +241,14 @@ export function abstractServiceFactory<
|
||||
sharedContext
|
||||
)
|
||||
}
|
||||
|
||||
@InjectTransactionManager(propertyRepositoryName)
|
||||
async upsert(
|
||||
data: (TDTOs["create"] | TDTOs["update"])[],
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TEntity[]> {
|
||||
return await this[propertyRepositoryName].upsert(data, sharedContext)
|
||||
}
|
||||
}
|
||||
|
||||
return AbstractService_ as unknown as new <TEntity extends {}>(
|
||||
|
||||
@@ -2,6 +2,7 @@ export * from "./load-module-database-config"
|
||||
export * from "./decorators"
|
||||
export * from "./build-query"
|
||||
export * from "./loaders/mikro-orm-connection-loader"
|
||||
export * from "./loaders/container-loader-factory"
|
||||
export * from "./create-pg-connection"
|
||||
export * from "./migration-scripts"
|
||||
export * from "./abstract-service-factory"
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
import {
|
||||
Constructor,
|
||||
LoaderOptions,
|
||||
MedusaContainer,
|
||||
ModuleServiceInitializeCustomDataLayerOptions,
|
||||
ModuleServiceInitializeOptions,
|
||||
RepositoryService,
|
||||
} from "@medusajs/types"
|
||||
import { lowerCaseFirst } from "../../common"
|
||||
import { asClass } from "awilix"
|
||||
import { abstractServiceFactory } from "../abstract-service-factory"
|
||||
import { mikroOrmBaseRepositoryFactory } from "../../dal"
|
||||
|
||||
type RepositoryLoaderOptions = {
|
||||
moduleModels: Record<string, any>
|
||||
moduleRepositories?: Record<string, any>
|
||||
customRepositories: Record<string, any>
|
||||
container: MedusaContainer
|
||||
}
|
||||
|
||||
type ServiceLoaderOptions = {
|
||||
moduleModels: Record<string, any>
|
||||
moduleServices: Record<string, any>
|
||||
container: MedusaContainer
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory for creating a container loader for a module.
|
||||
*
|
||||
* @param moduleModels
|
||||
* @param moduleServices
|
||||
* @param moduleRepositories
|
||||
* @param customRepositoryLoader The default repository loader is based on mikro orm. If you want to use a custom repository loader, you can pass it here.
|
||||
*/
|
||||
export function moduleContainerLoaderFactory({
|
||||
moduleModels,
|
||||
moduleServices,
|
||||
moduleRepositories = {},
|
||||
customRepositoryLoader = loadModuleRepositories,
|
||||
}: {
|
||||
moduleModels: Record<string, any>
|
||||
moduleServices: Record<string, any>
|
||||
moduleRepositories?: Record<string, any>
|
||||
customRepositoryLoader?: (options: RepositoryLoaderOptions) => void
|
||||
}): ({ container, options }: LoaderOptions) => Promise<void> {
|
||||
return async ({
|
||||
container,
|
||||
options,
|
||||
}: LoaderOptions<
|
||||
| ModuleServiceInitializeOptions
|
||||
| ModuleServiceInitializeCustomDataLayerOptions
|
||||
>) => {
|
||||
const customRepositories = (
|
||||
options as ModuleServiceInitializeCustomDataLayerOptions
|
||||
)?.repositories
|
||||
|
||||
loadModuleServices({
|
||||
moduleModels,
|
||||
moduleServices,
|
||||
container,
|
||||
})
|
||||
|
||||
const repositoryLoader = customRepositoryLoader ?? loadModuleRepositories
|
||||
repositoryLoader({
|
||||
moduleModels,
|
||||
moduleRepositories,
|
||||
customRepositories: customRepositories ?? {},
|
||||
container,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the services from the module services object. If a service is not
|
||||
* present a default service will be created for the model.
|
||||
*
|
||||
* @param moduleModels
|
||||
* @param moduleServices
|
||||
* @param container
|
||||
*/
|
||||
export function loadModuleServices({
|
||||
moduleModels,
|
||||
moduleServices,
|
||||
container,
|
||||
}: ServiceLoaderOptions) {
|
||||
const moduleServicesMap = new Map(
|
||||
Object.entries(moduleServices).map(([key, repository]) => [
|
||||
lowerCaseFirst(key),
|
||||
repository,
|
||||
])
|
||||
)
|
||||
|
||||
// Build default services for all models that are not present in the module services
|
||||
Object.values(moduleModels).forEach((Model) => {
|
||||
const mappedServiceName = lowerCaseFirst(Model.name) + "Service"
|
||||
const finalService = moduleServicesMap.get(mappedServiceName)
|
||||
|
||||
if (!finalService) {
|
||||
moduleServicesMap.set(mappedServiceName, abstractServiceFactory(Model))
|
||||
}
|
||||
})
|
||||
|
||||
const allServices = [...moduleServicesMap]
|
||||
|
||||
allServices.forEach(([key, service]) => {
|
||||
container.register({
|
||||
[lowerCaseFirst(key)]: asClass(service as Constructor<any>).singleton(),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the repositories from the custom repositories object. If a repository is not
|
||||
* present in the custom repositories object, the default repository will be used from the module repository.
|
||||
* If none are present, a default repository will be created for the model.
|
||||
*
|
||||
* @param moduleModels
|
||||
* @param moduleRepositories
|
||||
* @param customRepositories
|
||||
* @param container
|
||||
*/
|
||||
export function loadModuleRepositories({
|
||||
moduleModels,
|
||||
moduleRepositories = {},
|
||||
customRepositories,
|
||||
container,
|
||||
}: RepositoryLoaderOptions) {
|
||||
const customRepositoriesMap = new Map(
|
||||
Object.entries(customRepositories).map(([key, repository]) => [
|
||||
lowerCaseFirst(key),
|
||||
repository,
|
||||
])
|
||||
)
|
||||
const moduleRepositoriesMap = new Map(
|
||||
Object.entries(moduleRepositories).map(([key, repository]) => [
|
||||
lowerCaseFirst(key),
|
||||
repository,
|
||||
])
|
||||
)
|
||||
|
||||
// Build default repositories for all models that are not present in the custom repositories or module repositories
|
||||
Object.values(moduleModels).forEach((Model) => {
|
||||
const mappedRepositoryName = lowerCaseFirst(Model.name) + "Repository"
|
||||
let finalRepository = customRepositoriesMap.get(mappedRepositoryName)
|
||||
finalRepository ??= moduleRepositoriesMap.get(mappedRepositoryName)
|
||||
|
||||
if (!finalRepository) {
|
||||
moduleRepositoriesMap.set(
|
||||
mappedRepositoryName,
|
||||
mikroOrmBaseRepositoryFactory(Model)
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
const allRepositories = [...customRepositoriesMap, ...moduleRepositoriesMap]
|
||||
|
||||
allRepositories.forEach(([key, repository]) => {
|
||||
let finalRepository = customRepositoriesMap.get(key)
|
||||
|
||||
if (!finalRepository) {
|
||||
finalRepository = repository
|
||||
}
|
||||
|
||||
container.register({
|
||||
[lowerCaseFirst(key)]: asClass(
|
||||
finalRepository as Constructor<RepositoryService>
|
||||
).singleton(),
|
||||
})
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user