chore: Abstract module service (#6188)

**What**
- Remove services that do not have any custom business and replace them with a simple interfaces
- Abstract module service provide the following base implementation
  - retrieve
  - list
  - listAndCount
  - delete
  - softDelete
  - restore

The above methods are created for the main model and also for each other models for which a config is provided

all method such as list, listAndCount, delete, softDelete and restore are pluralized with the model it refers to

**Migration**
- [x] product
- [x] pricing
- [x] promotion
- [x] cart
- [x] auth
- [x] customer
- [x] payment
- [x] Sales channel
- [x] Workflow-*


**Usage**

**Module**

The module service can now extend the ` ModulesSdkUtils.abstractModuleServiceFactory` which returns a class with the default implementation for each method and each model following the standard naming convention mentioned above.
This factory have 3 template arguments being the container, the main model DTO and an object representing the other model with a config object that contains at list the DTO and optionally a singular and plural property in case it needs to be set manually. It looks like the following:

```ts
export default class PricingModuleService</* ... */>
  extends ModulesSdkUtils.abstractModuleServiceFactory<
    InjectedDependencies,
    PricingTypes.PriceSetDTO,
    {
      Currency: { dto: PricingTypes.CurrencyDTO }
      MoneyAmount: { dto: PricingTypes.MoneyAmountDTO }
      PriceSetMoneyAmount: { dto: PricingTypes.PriceSetMoneyAmountDTO }
      PriceSetMoneyAmountRules: {
        dto: PricingTypes.PriceSetMoneyAmountRulesDTO
      }
      PriceRule: { dto: PricingTypes.PriceRuleDTO }
      RuleType: { dto: PricingTypes.RuleTypeDTO }
      PriceList: { dto: PricingTypes.PriceListDTO }
      PriceListRule: { dto: PricingTypes.PriceListRuleDTO }
    }
  >(PriceSet, generateMethodForModels, entityNameToLinkableKeysMap)
  implements PricingTypes.IPricingModuleService
{
// ...
}
```

In the above, the singular and plural can be inferred as there is no tricky naming. Also, the default implementation does not remove the fact that you need to provides all the overloads etc in your module service interface. The above will provide a default implementation following the interface `AbstractModuleService` which is also auto generated, hence you will have the following methods available:

**for the main model**
- list
- retrieve
- listAndCount 
- delete
- softDelete
- restore


**for the other models**
- list**MyModels**
- retrieve**MyModel**
- listAndCount**MyModels**
- delete**MyModels**
- softDelete**MyModels**
- restore**MyModels**

**Internal module service**

The internal module service can now extend `ModulesSdkUtils.internalModuleServiceFactory` which takes only one template argument which is the container type. 
All internal services provides a default implementation for all retrieve, list, listAndCount, create, update, delete, softDelete, restore methods which follow the following interface `ModulesSdkTypes.InternalModuleService`:

```ts
export interface InternalModuleService<
  TEntity extends {},
  TContainer extends object = object
> {
  get __container__(): TContainer

  retrieve(
    idOrObject: string,
    config?: FindConfig<any>,
    sharedContext?: Context
  ): Promise<TEntity>
  retrieve(
    idOrObject: object,
    config?: FindConfig<any>,
    sharedContext?: Context
  ): Promise<TEntity>

  list(
    filters?: FilterQuery<any> | BaseFilterable<FilterQuery<any>>,
    config?: FindConfig<any>,
    sharedContext?: Context
  ): Promise<TEntity[]>

  listAndCount(
    filters?: FilterQuery<any> | BaseFilterable<FilterQuery<any>>,
    config?: FindConfig<any>,
    sharedContext?: Context
  ): Promise<[TEntity[], number]>

  create(data: any[], sharedContext?: Context): Promise<TEntity[]>
  create(data: any, sharedContext?: Context): Promise<TEntity>

  update(data: any[], sharedContext?: Context): Promise<TEntity[]>
  update(data: any, sharedContext?: Context): Promise<TEntity>
  update(
    selectorAndData: {
      selector: FilterQuery<any> | BaseFilterable<FilterQuery<any>>
      data: any
    },
    sharedContext?: Context
  ): Promise<TEntity[]>
  update(
    selectorAndData: {
      selector: FilterQuery<any> | BaseFilterable<FilterQuery<any>>
      data: any
    }[],
    sharedContext?: Context
  ): Promise<TEntity[]>

  delete(idOrSelector: string, sharedContext?: Context): Promise<void>
  delete(idOrSelector: string[], sharedContext?: Context): Promise<void>
  delete(idOrSelector: object, sharedContext?: Context): Promise<void>
  delete(idOrSelector: object[], sharedContext?: Context): Promise<void>
  delete(
    idOrSelector: {
      selector: FilterQuery<any> | BaseFilterable<FilterQuery<any>>
    },
    sharedContext?: Context
  ): Promise<void>

  softDelete(
    idsOrFilter: string[] | InternalFilterQuery,
    sharedContext?: Context
  ): Promise<[TEntity[], Record<string, unknown[]>]>

  restore(
    idsOrFilter: string[] | InternalFilterQuery,
    sharedContext?: Context
  ): Promise<[TEntity[], Record<string, unknown[]>]>

  upsert(data: any[], sharedContext?: Context): Promise<TEntity[]>
  upsert(data: any, sharedContext?: Context): Promise<TEntity>
}
```

When a service is auto generated you can use that interface to type your class property representing the expected internal service.

**Repositories**

The repositories can now extend `DALUtils.mikroOrmBaseRepositoryFactory` which takes one template argument being the entity or the template entity and provides all the default implementation. If the repository is auto generated you can type it using the `RepositoryService` interface. Here is the new interface typings.

```ts
export interface RepositoryService<T = any> extends BaseRepositoryService<T> {
  find(options?: FindOptions<T>, context?: Context): Promise<T[]>

  findAndCount(
    options?: FindOptions<T>,
    context?: Context
  ): Promise<[T[], number]>

  create(data: any[], context?: Context): Promise<T[]>

  // Becareful here, if you have a custom internal service, the update data should never be the entity otherwise
 // both entity and update will point to the same ref and create issues with mikro orm
  update(data: { entity; update }[], context?: Context): Promise<T[]>

  delete(
    idsOrPKs: FilterQuery<T> & BaseFilterable<FilterQuery<T>>,
    context?: Context
  ): Promise<void>

  /**
   * Soft delete entities and cascade to related entities if configured.
   *
   * @param idsOrFilter
   * @param context
   *
   * @returns [T[], Record<string, string[]>] the second value being the map of the entity names and ids that were soft deleted
   */
  softDelete(
    idsOrFilter: string[] | InternalFilterQuery,
    context?: Context
  ): Promise<[T[], Record<string, unknown[]>]>

  restore(
    idsOrFilter: string[] | InternalFilterQuery,
    context?: Context
  ): Promise<[T[], Record<string, unknown[]>]>

  upsert(data: any[], context?: Context): Promise<T[]>
}
```
This commit is contained in:
Adrien de Peretti
2024-02-02 15:20:32 +01:00
committed by GitHub
parent abc30517cb
commit a7be5d7b6d
163 changed files with 2867 additions and 5080 deletions
@@ -9,6 +9,8 @@ import { createAuthenticatedCustomer } from "../../../helpers/create-authenticat
const env = { MEDUSA_FF_MEDUSA_V2: true }
jest.setTimeout(100000)
describe("GET /store/customers/me/addresses", () => {
let dbConnection
let appContainer
@@ -16,13 +18,17 @@ describe("GET /store/customers/me/addresses", () => {
let customerModuleService: ICustomerModuleService
beforeAll(async () => {
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
dbConnection = await initDb({ cwd, env } as any)
shutdownServer = await startBootstrapApp({ cwd, env })
appContainer = getContainer()
customerModuleService = appContainer.resolve(
ModuleRegistrationName.CUSTOMER
)
try {
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
dbConnection = await initDb({ cwd, env } as any)
shutdownServer = await startBootstrapApp({ cwd, env })
appContainer = getContainer()
customerModuleService = appContainer.resolve(
ModuleRegistrationName.CUSTOMER
)
} catch (error) {
console.error(error)
}
})
afterAll(async () => {
@@ -5,14 +5,13 @@ import {
simpleProductFactory,
simpleRegionFactory,
} from "../../../../factories"
import { PricingModuleService } from "@medusajs/pricing"
import { ProductModuleService } from "@medusajs/product"
import { AxiosInstance } from "axios"
import path from "path"
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
import adminSeeder from "../../../../helpers/admin-seeder"
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
import { ProductModuleService } from "@medusajs/product"
import { PricingModuleService } from "@medusajs/pricing"
jest.setTimeout(50000)
@@ -11,7 +11,7 @@ import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app
import { getContainer } from "../../../../environment-helpers/use-container"
import { initDb, useDb } from "../../../../environment-helpers/use-db"
jest.setTimeout(30000)
jest.setTimeout(50000)
describe("CreateProduct workflow", function () {
let medusaContainer
@@ -129,7 +129,7 @@ describe("CreateProduct workflow", function () {
expect(product).toEqual(
expect.objectContaining({
deleted_at: expect.any(String),
deleted_at: expect.any(Date),
})
)
})
@@ -1,16 +1,16 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { AuthProviderService } from "@services"
import { MikroOrmWrapper } from "../../../utils"
import { createAuthProviders } from "../../../__fixtures__/auth-provider"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
import ContainerLoader from "../../../../src/loaders/container"
import { ModulesSdkTypes } from "@medusajs/types"
jest.setTimeout(30000)
describe("AuthProvider Service", () => {
let service: AuthProviderService
let service: ModulesSdkTypes.InternalModuleService<any>
let testManager: SqlEntityManager
let repositoryManager: SqlEntityManager
@@ -180,7 +180,7 @@ describe("AuthProvider Service", () => {
error = e
}
expect(error.message).toEqual('"authProviderProvider" must be defined')
expect(error.message).toEqual("authProvider - provider must be defined")
})
it("should return authProvider based on config select param", async () => {
@@ -166,7 +166,7 @@ describe("AuthUser Service", () => {
error = e
}
expect(error.message).toEqual('"authUserId" must be defined')
expect(error.message).toEqual("authUser - id must be defined")
})
})
@@ -229,7 +229,7 @@ describe("AuthUser Service", () => {
id: "test",
provider_id: "manual",
entity_id: "test",
scope: "store"
scope: "store",
},
])
@@ -43,9 +43,8 @@ describe("AuthModuleService - AuthProvider", () => {
describe("listAuthProviders", () => {
it("should list AuthProviders", async () => {
const authProviders = await service.listAuthProviders()
const serialized = JSON.parse(JSON.stringify(authProviders))
expect(serialized).toEqual(
expect(authProviders).toEqual(
expect.arrayContaining([
expect.objectContaining({
provider: "manual",
@@ -80,9 +79,7 @@ describe("AuthModuleService - AuthProvider", () => {
is_active: true,
})
const serialized = JSON.parse(JSON.stringify(authProviders))
expect(serialized).toEqual([
expect(authProviders).toEqual([
expect.objectContaining({
provider: "manual",
}),
@@ -99,10 +96,9 @@ describe("AuthModuleService - AuthProvider", () => {
describe("listAndCountAuthProviders", () => {
it("should list and count AuthProviders", async () => {
const [authProviders, count] = await service.listAndCountAuthProviders()
const serialized = JSON.parse(JSON.stringify(authProviders))
expect(count).toEqual(4)
expect(serialized).toEqual([
expect(authProviders).toEqual([
expect.objectContaining({
provider: "manual",
}),
@@ -136,10 +132,8 @@ describe("AuthModuleService - AuthProvider", () => {
is_active: true,
})
const serialized = JSON.parse(JSON.stringify(authProviders))
expect(count).toEqual(3)
expect(serialized).toEqual([
expect(authProviders).toEqual([
expect.objectContaining({
provider: "manual",
}),
@@ -171,9 +165,7 @@ describe("AuthModuleService - AuthProvider", () => {
select: ["provider"],
})
const serialized = JSON.parse(JSON.stringify(authProvider))
expect(serialized).toEqual({
expect(authProvider).toEqual({
provider,
})
})
@@ -201,7 +193,7 @@ describe("AuthModuleService - AuthProvider", () => {
error = e
}
expect(error.message).toEqual('"authProviderProvider" must be defined')
expect(error.message).toEqual("authProvider - provider must be defined")
})
})
@@ -209,7 +201,7 @@ describe("AuthModuleService - AuthProvider", () => {
const provider = "manual"
it("should delete the authProviders given a provider successfully", async () => {
await service.deleteAuthProvider([provider])
await service.deleteAuthProviders([provider])
const authProviders = await service.listAuthProviders({
provider: [provider],
@@ -43,17 +43,16 @@ describe("AuthModuleService - AuthUser", () => {
describe("listAuthUsers", () => {
it("should list authUsers", async () => {
const authUsers = await service.listAuthUsers()
const serialized = JSON.parse(JSON.stringify(authUsers))
expect(serialized).toEqual([
expect(authUsers).toEqual([
expect.objectContaining({
provider: "manual",
provider: { provider: "manual" },
}),
expect.objectContaining({
provider: "manual",
provider: { provider: "manual" },
}),
expect.objectContaining({
provider: "store",
provider: { provider: "store" },
}),
])
})
@@ -75,9 +74,7 @@ describe("AuthModuleService - AuthUser", () => {
provider_id: "manual",
})
const serialized = JSON.parse(JSON.stringify(authUsers))
expect(serialized).toEqual([
expect(authUsers).toEqual([
expect.objectContaining({
id: "test-id",
}),
@@ -91,18 +88,17 @@ describe("AuthModuleService - AuthUser", () => {
describe("listAndCountAuthUsers", () => {
it("should list and count authUsers", async () => {
const [authUsers, count] = await service.listAndCountAuthUsers()
const serialized = JSON.parse(JSON.stringify(authUsers))
expect(count).toEqual(3)
expect(serialized).toEqual([
expect(authUsers).toEqual([
expect.objectContaining({
provider: "manual",
provider: { provider: "manual" },
}),
expect.objectContaining({
provider: "manual",
provider: { provider: "manual" },
}),
expect.objectContaining({
provider: "store",
provider: { provider: "store" },
}),
])
})
@@ -171,7 +167,7 @@ describe("AuthModuleService - AuthUser", () => {
error = e
}
expect(error.message).toEqual('"authUserId" must be defined')
expect(error.message).toEqual("authUser - id must be defined")
})
it("should return authUser based on config select param", async () => {
@@ -179,9 +175,7 @@ describe("AuthModuleService - AuthUser", () => {
select: ["id"],
})
const serialized = JSON.parse(JSON.stringify(authUser))
expect(serialized).toEqual({
expect(authUser).toEqual({
id,
})
})
@@ -191,7 +185,7 @@ describe("AuthModuleService - AuthUser", () => {
const id = "test-id"
it("should delete the authUsers given an id successfully", async () => {
await service.deleteAuthUser([id])
await service.deleteAuthUsers([id])
const authUsers = await service.listAuthUsers({
id: [id],
@@ -45,9 +45,8 @@ describe("AuthModuleService - AuthProvider", () => {
describe("listAuthProviders", () => {
it("should list default AuthProviders registered by loaders", async () => {
const authProviders = await service.listAuthProviders()
const serialized = JSON.parse(JSON.stringify(authProviders))
expect(serialized).toEqual(
expect(authProviders).toEqual(
expect.arrayContaining([
expect.objectContaining({
provider: "emailpass",
+9 -8
View File
@@ -1,10 +1,11 @@
import { AbstractAuthModuleProvider, MedusaError } from "@medusajs/utils"
import {
AuthProviderScope,
AuthenticationInput,
AuthenticationResponse,
AuthProviderScope,
ModulesSdkTypes,
} from "@medusajs/types"
import { AuthProviderService, AuthUserService } from "@services"
import { AuthUserService } from "@services"
import jwt, { JwtPayload } from "jsonwebtoken"
import { AuthorizationCode } from "simple-oauth2"
@@ -12,7 +13,7 @@ import url from "url"
type InjectedDependencies = {
authUserService: AuthUserService
authProviderService: AuthProviderService
authProviderService: ModulesSdkTypes.InternalModuleService<any>
}
type ProviderConfig = {
@@ -25,13 +26,13 @@ class GoogleProvider extends AbstractAuthModuleProvider {
public static PROVIDER = "google"
public static DISPLAY_NAME = "Google Authentication"
protected readonly authUserSerivce_: AuthUserService
protected readonly authProviderService_: AuthProviderService
protected readonly authUserService_: AuthUserService
protected readonly authProviderService_: ModulesSdkTypes.InternalModuleService<any>
constructor({ authUserService, authProviderService }: InjectedDependencies) {
super(arguments[0])
this.authUserSerivce_ = authUserService
this.authUserService_ = authUserService
this.authProviderService_ = authProviderService
}
@@ -89,13 +90,13 @@ class GoogleProvider extends AbstractAuthModuleProvider {
let authUser
try {
authUser = await this.authUserSerivce_.retrieveByProviderAndEntityId(
authUser = await this.authUserService_.retrieveByProviderAndEntityId(
entity_id,
GoogleProvider.PROVIDER
)
} catch (error) {
if (error.type === MedusaError.Types.NOT_FOUND) {
const [createdAuthUser] = await this.authUserSerivce_.create([
const [createdAuthUser] = await this.authUserService_.create([
{
entity_id,
provider: GoogleProvider.PROVIDER,
+53 -170
View File
@@ -1,35 +1,35 @@
import jwt from "jsonwebtoken"
import {
AuthenticationInput,
AuthenticationResponse,
AuthProviderDTO,
AuthTypes,
AuthUserDTO,
AuthenticationInput,
AuthenticationResponse,
Context,
CreateAuthProviderDTO,
CreateAuthUserDTO,
DAL,
FilterableAuthProviderProps,
FilterableAuthUserProps,
FindConfig,
InternalModuleDeclaration,
JWTGenerationOptions,
MedusaContainer,
ModuleJoinerConfig,
ModulesSdkTypes,
UpdateAuthUserDTO,
} from "@medusajs/types"
import { AuthProvider, AuthUser } from "@models"
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
import {
AbstractAuthModuleProvider,
InjectManager,
InjectTransactionManager,
MedusaContext,
MedusaError,
ModulesSdkUtils,
} from "@medusajs/utils"
import { AuthProvider, AuthUser } from "@models"
import { AuthProviderService, AuthUserService } from "@services"
import { ServiceTypes } from "@types"
import { joinerConfig } from "../joiner-config"
type AuthModuleOptions = {
jwt_secret: string
@@ -42,28 +42,32 @@ type AuthJWTPayload = {
type InjectedDependencies = {
baseRepository: DAL.RepositoryService
authUserService: AuthUserService<any>
authProviderService: AuthProviderService<any>
authUserService: ModulesSdkTypes.InternalModuleService<any>
authProviderService: ModulesSdkTypes.InternalModuleService<any>
}
export default class AuthModuleService<
TAuthUser extends AuthUser = AuthUser,
TAuthProvider extends AuthProvider = AuthProvider
> implements AuthTypes.IAuthModuleService
{
__joinerConfig(): ModuleJoinerConfig {
return joinerConfig
}
const generateMethodForModels = [AuthProvider, AuthUser]
export default class AuthModuleService<
TAuthUser extends AuthUser = AuthUser,
TAuthProvider extends AuthProvider = AuthProvider
>
extends ModulesSdkUtils.abstractModuleServiceFactory<
InjectedDependencies,
AuthTypes.AuthProviderDTO,
{
AuthUser: { dto: AuthUserDTO }
AuthProvider: { dto: AuthProviderDTO }
}
>(AuthProvider, generateMethodForModels, entityNameToLinkableKeysMap)
implements AuthTypes.IAuthModuleService
{
__hooks = {
onApplicationStart: async () => await this.createProvidersOnLoad(),
}
protected __container__: MedusaContainer
protected baseRepository_: DAL.RepositoryService
protected authUserService_: AuthUserService<TAuthUser>
protected authProviderService_: AuthProviderService<TAuthProvider>
protected authUserService_: ModulesSdkTypes.InternalModuleService<TAuthUser>
protected authProviderService_: ModulesSdkTypes.InternalModuleService<TAuthProvider>
protected options_: AuthModuleOptions
constructor(
@@ -75,66 +79,17 @@ export default class AuthModuleService<
options: AuthModuleOptions,
protected readonly moduleDeclaration: InternalModuleDeclaration
) {
this.__container__ = arguments[0]
// @ts-ignore
super(...arguments)
this.baseRepository_ = baseRepository
this.authUserService_ = authUserService
this.authProviderService_ = authProviderService
this.options_ = options
}
async retrieveAuthProvider(
provider: string,
config: FindConfig<AuthProviderDTO> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<AuthProviderDTO> {
const authProvider = await this.authProviderService_.retrieve(
provider,
config,
sharedContext
)
return await this.baseRepository_.serialize<AuthTypes.AuthProviderDTO>(
authProvider,
{ populate: true }
)
}
async listAuthProviders(
filters: FilterableAuthProviderProps = {},
config: FindConfig<AuthProviderDTO> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<AuthProviderDTO[]> {
const authProviders = await this.authProviderService_.list(
filters,
config,
sharedContext
)
return await this.baseRepository_.serialize<AuthTypes.AuthProviderDTO[]>(
authProviders,
{ populate: true }
)
}
@InjectManager("baseRepository_")
async listAndCountAuthProviders(
filters: FilterableAuthProviderProps = {},
config: FindConfig<AuthProviderDTO>,
@MedusaContext() sharedContext: Context = {}
): Promise<[AuthTypes.AuthProviderDTO[], number]> {
const [authProviders, count] = await this.authProviderService_.listAndCount(
filters,
config,
sharedContext
)
return [
await this.baseRepository_.serialize<AuthTypes.AuthProviderDTO[]>(
authProviders,
{ populate: true }
),
count,
]
__joinerConfig(): ModuleJoinerConfig {
return joinerConfig
}
async generateJwtToken(
@@ -205,18 +160,11 @@ export default class AuthModuleService<
return Array.isArray(data) ? serializedProviders : serializedProviders[0]
}
@InjectTransactionManager("baseRepository_")
protected async createAuthProviders_(
data: any[],
@MedusaContext() sharedContext: Context
): Promise<TAuthProvider[]> {
return await this.authProviderService_.create(data, sharedContext)
}
updateAuthProvider(
data: AuthTypes.UpdateAuthProviderDTO[],
sharedContext?: Context
): Promise<AuthProviderDTO[]>
updateAuthProvider(
data: AuthTypes.UpdateAuthProviderDTO,
sharedContext?: Context
@@ -247,78 +195,11 @@ export default class AuthModuleService<
return await this.authProviderService_.update(data, sharedContext)
}
@InjectTransactionManager("baseRepository_")
async deleteAuthProvider(
ids: string[],
@MedusaContext() sharedContext: Context = {}
): Promise<void> {
await this.authProviderService_.delete(ids, sharedContext)
}
@InjectManager("baseRepository_")
async retrieveAuthUser(
id: string,
config: FindConfig<AuthUserDTO> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<AuthUserDTO> {
const authUser = await this.authUserService_.retrieve(
id,
config,
sharedContext
)
return await this.baseRepository_.serialize<AuthTypes.AuthUserDTO>(
authUser,
{
exclude: ["password_hash"],
}
)
}
@InjectManager("baseRepository_")
async listAuthUsers(
filters: FilterableAuthUserProps = {},
config: FindConfig<AuthUserDTO> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<AuthUserDTO[]> {
const authUsers = await this.authUserService_.list(
filters,
config,
sharedContext
)
return await this.baseRepository_.serialize<AuthTypes.AuthUserDTO[]>(
authUsers,
{
populate: true,
}
)
}
@InjectManager("baseRepository_")
async listAndCountAuthUsers(
filters: FilterableAuthUserProps = {},
config: FindConfig<AuthUserDTO> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<[AuthUserDTO[], number]> {
const [authUsers, count] = await this.authUserService_.listAndCount(
filters,
config,
sharedContext
)
return [
await this.baseRepository_.serialize<AuthTypes.AuthUserDTO[]>(authUsers, {
populate: true,
}),
count,
]
}
createAuthUser(
data: CreateAuthUserDTO[],
sharedContext?: Context
): Promise<AuthUserDTO[]>
createAuthUser(
data: CreateAuthUserDTO,
sharedContext?: Context
@@ -342,23 +223,17 @@ export default class AuthModuleService<
return Array.isArray(data) ? serializedUsers : serializedUsers[0]
}
@InjectTransactionManager("baseRepository_")
protected async createAuthUsers_(
data: CreateAuthUserDTO[],
@MedusaContext() sharedContext: Context
): Promise<TAuthUser[]> {
return await this.authUserService_.create(data, sharedContext)
}
updateAuthUser(
data: UpdateAuthUserDTO[],
sharedContext?: Context
): Promise<AuthUserDTO[]>
updateAuthUser(
data: UpdateAuthUserDTO,
sharedContext?: Context
): Promise<AuthUserDTO>
// TODO: should be pluralized, see convention about the methods naming or the abstract module service interface definition @engineering
@InjectManager("baseRepository_")
async updateAuthUser(
data: UpdateAuthUserDTO | UpdateAuthUserDTO[],
@@ -385,14 +260,6 @@ export default class AuthModuleService<
return await this.authUserService_.update(data, sharedContext)
}
@InjectTransactionManager("baseRepository_")
async deleteAuthUser(
ids: string[],
@MedusaContext() sharedContext: Context = {}
): Promise<void> {
await this.authUserService_.delete(ids, sharedContext)
}
protected getRegisteredAuthenticationProvider(
provider: string,
{ authScope }: AuthenticationInput
@@ -448,6 +315,22 @@ export default class AuthModuleService<
}
}
@InjectTransactionManager("baseRepository_")
protected async createAuthProviders_(
data: any[],
@MedusaContext() sharedContext: Context
): Promise<TAuthProvider[]> {
return await this.authProviderService_.create(data, sharedContext)
}
@InjectTransactionManager("baseRepository_")
protected async createAuthUsers_(
data: CreateAuthUserDTO[],
@MedusaContext() sharedContext: Context
): Promise<TAuthUser[]> {
return await this.authUserService_.create(data, sharedContext)
}
private async createProvidersOnLoad() {
const providersToLoad = this.__container__["auth_providers"]
@@ -1,24 +0,0 @@
import { DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { AuthProvider } from "@models"
import { ServiceTypes } from "@types"
type InjectedDependencies = {
authProviderRepository: DAL.RepositoryService
}
export default class AuthProviderService<
TEntity extends AuthProvider = AuthProvider
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: ServiceTypes.CreateAuthProviderDTO
update: ServiceTypes.UpdateAuthProviderDTO
}
>(AuthProvider)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
}
+13 -12
View File
@@ -1,4 +1,10 @@
import { AuthTypes, Context, DAL, FindConfig } from "@medusajs/types"
import {
AuthTypes,
Context,
DAL,
FindConfig,
RepositoryService,
} from "@medusajs/types"
import {
InjectManager,
MedusaContext,
@@ -6,7 +12,6 @@ import {
ModulesSdkUtils,
} from "@medusajs/utils"
import { AuthUser } from "@models"
import { ServiceTypes, RepositoryTypes } from "@types"
type InjectedDependencies = {
authUserRepository: DAL.RepositoryService
@@ -14,13 +19,11 @@ type InjectedDependencies = {
export default class AuthUserService<
TEntity extends AuthUser = AuthUser
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: ServiceTypes.CreateAuthUserDTO
}
>(AuthUser)<TEntity> {
protected readonly authUserRepository_: RepositoryTypes.IAuthUserRepository<TEntity>
> extends ModulesSdkUtils.internalModuleServiceFactory<InjectedDependencies>(
AuthUser
)<TEntity> {
protected readonly authUserRepository_: RepositoryService<TEntity>
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
@@ -28,9 +31,7 @@ export default class AuthUserService<
}
@InjectManager("authUserRepository_")
async retrieveByProviderAndEntityId<
TEntityMethod = AuthTypes.AuthUserDTO
>(
async retrieveByProviderAndEntityId<TEntityMethod = AuthTypes.AuthUserDTO>(
entityId: string,
provider: string,
config: FindConfig<TEntityMethod> = {},
-1
View File
@@ -1,3 +1,2 @@
export { default as AuthModuleService } from "./auth-module"
export { default as AuthProviderService } from "./auth-provider"
export { default as AuthUserService } from "./auth-user"
@@ -1,28 +1,2 @@
import { AuthProvider, AuthUser } from "@models"
import { CreateAuthProviderDTO, UpdateAuthProviderDTO } from "./auth-provider"
import { DAL } from "@medusajs/types"
import { CreateAuthUserDTO, UpdateAuthUserDTO } from "./auth-user"
export * from "./auth-user"
export * from "./auth-provider"
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IAuthProviderRepository<
TEntity extends AuthProvider = AuthProvider
> extends DAL.RepositoryService<
TEntity,
{
create: CreateAuthProviderDTO
update: UpdateAuthProviderDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IAuthUserRepository<TEntity extends AuthUser = AuthUser>
extends DAL.RepositoryService<
TEntity,
{
create: CreateAuthUserDTO
update: UpdateAuthUserDTO
}
> {}
-23
View File
@@ -1,23 +0,0 @@
import { DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { Address } from "@models"
import { CreateAddressDTO, UpdateAddressDTO } from "@types"
type InjectedDependencies = {
addressRepository: DAL.RepositoryService
}
export default class AddressService<
TEntity extends Address = Address
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: CreateAddressDTO
update: UpdateAddressDTO
}
>(Address)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
}
+85 -261
View File
@@ -3,20 +3,22 @@ import {
Context,
DAL,
FilterableLineItemTaxLineProps,
FindConfig,
ICartModuleService,
InternalModuleDeclaration,
ModuleJoinerConfig,
ModulesSdkTypes,
} from "@medusajs/types"
import {
InjectManager,
InjectTransactionManager,
MedusaContext,
MedusaError,
isObject,
isString,
MedusaContext,
MedusaError,
ModulesSdkUtils,
} from "@medusajs/utils"
import {
Address,
Cart,
LineItem,
LineItemAdjustment,
@@ -25,32 +27,73 @@ import {
ShippingMethodAdjustment,
ShippingMethodTaxLine,
} from "@models"
import { CreateLineItemDTO, UpdateLineItemDTO } from "@types"
import { joinerConfig } from "../joiner-config"
import * as services from "../services"
import {
CreateLineItemDTO,
CreateLineItemTaxLineDTO,
CreateShippingMethodDTO,
CreateShippingMethodTaxLineDTO,
UpdateLineItemDTO,
UpdateLineItemTaxLineDTO,
UpdateShippingMethodTaxLineDTO,
} from "@types"
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
type InjectedDependencies = {
baseRepository: DAL.RepositoryService
cartService: services.CartService
addressService: services.AddressService
lineItemService: services.LineItemService
shippingMethodAdjustmentService: services.ShippingMethodAdjustmentService
shippingMethodService: services.ShippingMethodService
lineItemAdjustmentService: services.LineItemAdjustmentService
lineItemTaxLineService: services.LineItemTaxLineService
shippingMethodTaxLineService: services.ShippingMethodTaxLineService
cartService: ModulesSdkTypes.InternalModuleService<any>
addressService: ModulesSdkTypes.InternalModuleService<any>
lineItemService: ModulesSdkTypes.InternalModuleService<any>
shippingMethodAdjustmentService: ModulesSdkTypes.InternalModuleService<any>
shippingMethodService: ModulesSdkTypes.InternalModuleService<any>
lineItemAdjustmentService: ModulesSdkTypes.InternalModuleService<any>
lineItemTaxLineService: ModulesSdkTypes.InternalModuleService<any>
shippingMethodTaxLineService: ModulesSdkTypes.InternalModuleService<any>
}
export default class CartModuleService implements ICartModuleService {
const generateMethodForModels = [
Address,
LineItem,
LineItemAdjustment,
LineItemTaxLine,
ShippingMethod,
ShippingMethodAdjustment,
ShippingMethodTaxLine,
]
export default class CartModuleService<
TCart extends Cart = Cart,
TAddress extends Address = Address,
TLineItem extends LineItem = LineItem,
TLineItemAdjustment extends LineItemAdjustment = LineItemAdjustment,
TLineItemTaxLine extends LineItemTaxLine = LineItemTaxLine,
TShippingMethodAdjustment extends ShippingMethodAdjustment = ShippingMethodAdjustment,
TShippingMethodTaxLine extends ShippingMethodTaxLine = ShippingMethodTaxLine,
TShippingMethod extends ShippingMethod = ShippingMethod
>
extends ModulesSdkUtils.abstractModuleServiceFactory<
InjectedDependencies,
CartTypes.CartDTO,
{
Address: { dto: CartTypes.CartAddressDTO }
LineItem: { dto: CartTypes.CartLineItemDTO }
LineItemAdjustment: { dto: CartTypes.LineItemAdjustmentDTO }
LineItemTaxLine: { dto: CartTypes.LineItemTaxLineDTO }
ShippingMethod: { dto: CartTypes.CartShippingMethodDTO }
ShippingMethodAdjustment: { dto: CartTypes.ShippingMethodAdjustmentDTO }
ShippingMethodTaxLine: { dto: CartTypes.ShippingMethodTaxLineDTO }
}
>(Cart, generateMethodForModels, entityNameToLinkableKeysMap)
implements ICartModuleService
{
protected baseRepository_: DAL.RepositoryService
protected cartService_: services.CartService
protected addressService_: services.AddressService
protected lineItemService_: services.LineItemService
protected shippingMethodAdjustmentService_: services.ShippingMethodAdjustmentService
protected shippingMethodService_: services.ShippingMethodService
protected lineItemAdjustmentService_: services.LineItemAdjustmentService
protected lineItemTaxLineService_: services.LineItemTaxLineService
protected shippingMethodTaxLineService_: services.ShippingMethodTaxLineService
protected cartService_: ModulesSdkTypes.InternalModuleService<TCart>
protected addressService_: ModulesSdkTypes.InternalModuleService<TAddress>
protected lineItemService_: ModulesSdkTypes.InternalModuleService<TLineItem>
protected shippingMethodAdjustmentService_: ModulesSdkTypes.InternalModuleService<TShippingMethodAdjustment>
protected shippingMethodService_: ModulesSdkTypes.InternalModuleService<TShippingMethod>
protected lineItemAdjustmentService_: ModulesSdkTypes.InternalModuleService<TLineItemAdjustment>
protected lineItemTaxLineService_: ModulesSdkTypes.InternalModuleService<TLineItemTaxLine>
protected shippingMethodTaxLineService_: ModulesSdkTypes.InternalModuleService<TShippingMethodTaxLine>
constructor(
{
@@ -66,6 +109,9 @@ export default class CartModuleService implements ICartModuleService {
}: InjectedDependencies,
protected readonly moduleDeclaration: InternalModuleDeclaration
) {
// @ts-ignore
super(...arguments)
this.baseRepository_ = baseRepository
this.cartService_ = cartService
this.addressService_ = addressService
@@ -81,52 +127,6 @@ export default class CartModuleService implements ICartModuleService {
return joinerConfig
}
@InjectManager("baseRepository_")
async retrieve(
id: string,
config: FindConfig<CartTypes.CartDTO> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<CartTypes.CartDTO> {
const cart = await this.cartService_.retrieve(id, config, sharedContext)
return await this.baseRepository_.serialize<CartTypes.CartDTO>(cart, {
populate: true,
})
}
@InjectManager("baseRepository_")
async list(
filters: CartTypes.FilterableCartProps = {},
config: FindConfig<CartTypes.CartDTO> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<CartTypes.CartDTO[]> {
const carts = await this.cartService_.list(filters, config, sharedContext)
return this.baseRepository_.serialize<CartTypes.CartDTO[]>(carts, {
populate: true,
})
}
@InjectManager("baseRepository_")
async listAndCount(
filters: CartTypes.FilterableCartProps = {},
config: FindConfig<CartTypes.CartDTO> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<[CartTypes.CartDTO[], number]> {
const [carts, count] = await this.cartService_.listAndCount(
filters,
config,
sharedContext
)
return [
await this.baseRepository_.serialize<CartTypes.CartDTO[]>(carts, {
populate: true,
}),
count,
]
}
async create(
data: CartTypes.CreateCartDTO[],
sharedContext?: Context
@@ -229,98 +229,6 @@ export default class CartModuleService implements ICartModuleService {
return await this.cartService_.update(data, sharedContext)
}
async delete(ids: string[], sharedContext?: Context): Promise<void>
async delete(ids: string, sharedContext?: Context): Promise<void>
@InjectTransactionManager("baseRepository_")
async delete(
ids: string[] | string,
@MedusaContext() sharedContext: Context = {}
): Promise<void> {
const cartIds = Array.isArray(ids) ? ids : [ids]
await this.cartService_.delete(cartIds, sharedContext)
}
@InjectManager("baseRepository_")
async listAddresses(
filters: CartTypes.FilterableAddressProps = {},
config: FindConfig<CartTypes.CartAddressDTO> = {},
@MedusaContext() sharedContext: Context = {}
) {
const addresses = await this.addressService_.list(
filters,
config,
sharedContext
)
return await this.baseRepository_.serialize<CartTypes.CartAddressDTO[]>(
addresses,
{
populate: true,
}
)
}
@InjectManager("baseRepository_")
async retrieveLineItem(
itemId: string,
config: FindConfig<CartTypes.CartLineItemDTO> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<CartTypes.CartLineItemDTO> {
const item = await this.lineItemService_.retrieve(
itemId,
config,
sharedContext
)
return await this.baseRepository_.serialize<CartTypes.CartLineItemDTO>(
item,
{
populate: true,
}
)
}
@InjectManager("baseRepository_")
async listLineItems(
filters: CartTypes.FilterableLineItemProps = {},
config: FindConfig<CartTypes.CartLineItemDTO> = {},
@MedusaContext() sharedContext: Context = {}
) {
const items = await this.lineItemService_.list(
filters,
config,
sharedContext
)
return await this.baseRepository_.serialize<CartTypes.CartLineItemDTO[]>(
items,
{
populate: true,
}
)
}
@InjectManager("baseRepository_")
async listShippingMethods(
filters: CartTypes.FilterableShippingMethodProps = {},
config: FindConfig<CartTypes.CartShippingMethodDTO> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<CartTypes.CartShippingMethodDTO[]> {
const methods = await this.shippingMethodService_.list(
filters,
config,
sharedContext
)
return await this.baseRepository_.serialize<
CartTypes.CartShippingMethodDTO[]
>(methods, {
populate: true,
})
}
addLineItems(
data: CartTypes.CreateLineItemForCartDTO
): Promise<CartTypes.CartLineItemDTO[]>
@@ -585,18 +493,6 @@ export default class CartModuleService implements ICartModuleService {
return await this.addressService_.update(data, sharedContext)
}
async deleteAddresses(ids: string[], sharedContext?: Context): Promise<void>
async deleteAddresses(ids: string, sharedContext?: Context): Promise<void>
@InjectTransactionManager("baseRepository_")
async deleteAddresses(
ids: string[] | string,
@MedusaContext() sharedContext: Context = {}
): Promise<void> {
const addressIds = Array.isArray(ids) ? ids : [ids]
await this.addressService_.delete(addressIds, sharedContext)
}
async addShippingMethods(
data: CartTypes.CreateShippingMethodDTO
): Promise<CartTypes.CartShippingMethodDTO>
@@ -665,7 +561,10 @@ export default class CartModuleService implements ICartModuleService {
data: CartTypes.CreateShippingMethodDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<ShippingMethod[]> {
return await this.shippingMethodService_.create(data, sharedContext)
return await this.shippingMethodService_.create(
data as unknown as CreateShippingMethodDTO[],
sharedContext
)
}
async removeShippingMethods(
@@ -708,25 +607,6 @@ export default class CartModuleService implements ICartModuleService {
await this.shippingMethodService_.delete(toDelete, sharedContext)
}
@InjectManager("baseRepository_")
async listLineItemAdjustments(
filters: CartTypes.FilterableLineItemAdjustmentProps = {},
config: FindConfig<CartTypes.LineItemAdjustmentDTO> = {},
@MedusaContext() sharedContext: Context = {}
) {
const adjustments = await this.lineItemAdjustmentService_.list(
filters,
config,
sharedContext
)
return await this.baseRepository_.serialize<
CartTypes.LineItemAdjustmentDTO[]
>(adjustments, {
populate: true,
})
}
async addLineItemAdjustments(
adjustments: CartTypes.CreateLineItemAdjustmentDTO[]
): Promise<CartTypes.LineItemAdjustmentDTO[]>
@@ -882,25 +762,6 @@ export default class CartModuleService implements ICartModuleService {
await this.lineItemAdjustmentService_.delete(ids, sharedContext)
}
@InjectManager("baseRepository_")
async listShippingMethodAdjustments(
filters: CartTypes.FilterableShippingMethodAdjustmentProps = {},
config: FindConfig<CartTypes.ShippingMethodAdjustmentDTO> = {},
@MedusaContext() sharedContext: Context = {}
) {
const adjustments = await this.shippingMethodAdjustmentService_.list(
filters,
config,
sharedContext
)
return await this.baseRepository_.serialize<
CartTypes.ShippingMethodAdjustmentDTO[]
>(adjustments, {
populate: true,
})
}
@InjectTransactionManager("baseRepository_")
async setShippingMethodAdjustments(
cartId: string,
@@ -1070,26 +931,6 @@ export default class CartModuleService implements ICartModuleService {
await this.shippingMethodAdjustmentService_.delete(ids, sharedContext)
}
@InjectManager("baseRepository_")
async listLineItemTaxLines(
filters: CartTypes.FilterableLineItemTaxLineProps = {},
config: FindConfig<CartTypes.LineItemTaxLineDTO> = {},
@MedusaContext() sharedContext: Context = {}
) {
const taxLines = await this.lineItemTaxLineService_.list(
filters,
config,
sharedContext
)
return await this.baseRepository_.serialize<CartTypes.LineItemTaxLineDTO[]>(
taxLines,
{
populate: true,
}
)
}
addLineItemTaxLines(
taxLines: CartTypes.CreateLineItemTaxLineDTO[]
): Promise<CartTypes.LineItemTaxLineDTO[]>
@@ -1123,14 +964,14 @@ export default class CartModuleService implements ICartModuleService {
const lines = Array.isArray(taxLines) ? taxLines : [taxLines]
addedTaxLines = await this.lineItemTaxLineService_.create(
lines as CartTypes.CreateLineItemTaxLineDTO[],
lines as CreateLineItemTaxLineDTO[],
sharedContext
)
} else {
const data = Array.isArray(cartIdOrData) ? cartIdOrData : [cartIdOrData]
addedTaxLines = await this.lineItemTaxLineService_.create(
data as CartTypes.CreateLineItemTaxLineDTO[],
data as CreateLineItemTaxLineDTO[],
sharedContext
)
}
@@ -1184,13 +1025,15 @@ export default class CartModuleService implements ICartModuleService {
}
})
await this.lineItemTaxLineService_.delete(
toDelete.map((taxLine) => taxLine!.id),
sharedContext
)
if (toDelete.length) {
await this.lineItemTaxLineService_.delete(
toDelete.map((taxLine) => taxLine!.id),
sharedContext
)
}
const result = await this.lineItemTaxLineService_.upsert(
taxLines,
taxLines as UpdateLineItemTaxLineDTO[],
sharedContext
)
@@ -1242,25 +1085,6 @@ export default class CartModuleService implements ICartModuleService {
await this.lineItemTaxLineService_.delete(ids, sharedContext)
}
@InjectManager("baseRepository_")
async listShippingMethodTaxLines(
filters: CartTypes.FilterableShippingMethodTaxLineProps = {},
config: FindConfig<CartTypes.ShippingMethodTaxLineDTO> = {},
@MedusaContext() sharedContext: Context = {}
) {
const taxLines = await this.shippingMethodTaxLineService_.list(
filters,
config,
sharedContext
)
return await this.baseRepository_.serialize<
CartTypes.ShippingMethodTaxLineDTO[]
>(taxLines, {
populate: true,
})
}
addShippingMethodTaxLines(
taxLines: CartTypes.CreateShippingMethodTaxLineDTO[]
): Promise<CartTypes.ShippingMethodTaxLineDTO[]>
@@ -1296,12 +1120,12 @@ export default class CartModuleService implements ICartModuleService {
const lines = Array.isArray(taxLines) ? taxLines : [taxLines]
addedTaxLines = await this.shippingMethodTaxLineService_.create(
lines as CartTypes.CreateShippingMethodTaxLineDTO[],
lines as CreateShippingMethodTaxLineDTO[],
sharedContext
)
} else {
addedTaxLines = await this.shippingMethodTaxLineService_.create(
taxLines as CartTypes.CreateShippingMethodTaxLineDTO[],
taxLines as CreateShippingMethodTaxLineDTO[],
sharedContext
)
}
@@ -1367,7 +1191,7 @@ export default class CartModuleService implements ICartModuleService {
}
const result = await this.shippingMethodTaxLineService_.upsert(
taxLines,
taxLines as UpdateShippingMethodTaxLineDTO[],
sharedContext
)
-23
View File
@@ -1,23 +0,0 @@
import { DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { Cart } from "@models"
import { CreateCartDTO, UpdateCartDTO } from "@types"
type InjectedDependencies = {
cartRepository: DAL.RepositoryService
}
export default class CartService<
TEntity extends Cart = Cart
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: CreateCartDTO
update: UpdateCartDTO
}
>(Cart)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
}
-9
View File
@@ -1,10 +1 @@
export { default as AddressService } from "./address"
export { default as CartService } from "./cart"
export { default as CartModuleService } from "./cart-module"
export { default as LineItemService } from "./line-item"
export { default as LineItemAdjustmentService } from "./line-item-adjustment"
export { default as LineItemTaxLineService } from "./line-item-tax-line"
export { default as ShippingMethodService } from "./shipping-method"
export { default as ShippingMethodAdjustmentService } from "./shipping-method-adjustment"
export { default as ShippingMethodTaxLineService } from "./shipping-method-tax-line"
@@ -1,26 +0,0 @@
import { DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { LineItemAdjustment } from "@models"
import {
CreateLineItemAdjustmentDTO,
UpdateLineItemAdjustmentDTO,
} from "@types"
type InjectedDependencies = {
lineItemAdjustmentRepository: DAL.RepositoryService
}
export default class LineItemAdjustmentService<
TEntity extends LineItemAdjustment = LineItemAdjustment
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: CreateLineItemAdjustmentDTO
update: UpdateLineItemAdjustmentDTO
}
>(LineItemAdjustment)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
}
@@ -1,26 +0,0 @@
import {
CreateLineItemTaxLineDTO,
DAL,
UpdateLineItemTaxLineDTO,
} from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { LineItemTaxLine } from "@models"
type InjectedDependencies = {
lineItemTaxLineRepository: DAL.RepositoryService
}
export default class LineItemTaxLineService<
TEntity extends LineItemTaxLine = LineItemTaxLine
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: CreateLineItemTaxLineDTO
update: UpdateLineItemTaxLineDTO
}
>(LineItemTaxLine)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
}
-23
View File
@@ -1,23 +0,0 @@
import { DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { LineItem } from "@models"
import { CreateLineItemDTO, UpdateLineItemDTO } from "@types"
type InjectedDependencies = {
lineItemRepository: DAL.RepositoryService
}
export default class LineItemService<
TEntity extends LineItem = LineItem
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: CreateLineItemDTO
update: UpdateLineItemDTO
}
>(LineItem)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
}
@@ -1,26 +0,0 @@
import { DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { ShippingMethodAdjustment } from "@models"
import {
CreateShippingMethodAdjustmentDTO,
UpdateShippingMethodAdjustmentDTO,
} from "@types"
type InjectedDependencies = {
shippingMethodAdjustmentRepository: DAL.RepositoryService
}
export default class ShippingMethodAdjustmentService<
TEntity extends ShippingMethodAdjustment = ShippingMethodAdjustment
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: CreateShippingMethodAdjustmentDTO
update: UpdateShippingMethodAdjustmentDTO
}
>(ShippingMethodAdjustment)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
}
@@ -1,22 +0,0 @@
import { CreateShippingMethodTaxLineDTO, DAL, UpdateShippingMethodTaxLineDTO } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { ShippingMethodTaxLine } from "@models"
type InjectedDependencies = {
shippingMethodTaxLineRepository: DAL.RepositoryService
}
export default class ShippingMethodTaxLineService<
TEntity extends ShippingMethodTaxLine = ShippingMethodTaxLine
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: CreateShippingMethodTaxLineDTO
update: UpdateShippingMethodTaxLineDTO
}
>(ShippingMethodTaxLine)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
}
@@ -1,23 +0,0 @@
import { DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { ShippingMethod } from "@models"
import { CreateShippingMethodDTO, UpdateShippingMethodDTO } from "../types"
type InjectedDependencies = {
shippingMethodRepository: DAL.RepositoryService
}
export default class ShippingMethodService<
TEntity extends ShippingMethod = ShippingMethod
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: CreateShippingMethodDTO
update: UpdateShippingMethodDTO
}
>(ShippingMethod)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
}
-1
View File
@@ -5,7 +5,6 @@ export * from "./cart"
export * from "./line-item"
export * from "./line-item-adjustment"
export * from "./line-item-tax-line"
export * from "./repositories"
export * from "./shipping-method"
export * from "./shipping-method-adjustment"
export * from "./shipping-method-tax-line"
-114
View File
@@ -1,114 +0,0 @@
import { DAL } from "@medusajs/types"
import {
Cart,
LineItem,
LineItemAdjustment,
LineItemTaxLine,
ShippingMethod,
ShippingMethodAdjustment,
ShippingMethodTaxLine,
} from "@models"
import { CreateAddressDTO, UpdateAddressDTO } from "./address"
import { CreateCartDTO, UpdateCartDTO } from "./cart"
import { CreateLineItemDTO, UpdateLineItemDTO } from "./line-item"
import {
CreateLineItemAdjustmentDTO,
UpdateLineItemAdjustmentDTO,
} from "./line-item-adjustment"
import {
CreateLineItemTaxLineDTO,
UpdateLineItemTaxLineDTO,
} from "./line-item-tax-line"
import {
CreateShippingMethodDTO,
UpdateShippingMethodDTO,
} from "./shipping-method"
import {
CreateShippingMethodAdjustmentDTO,
UpdateShippingMethodAdjustmentDTO,
} from "./shipping-method-adjustment"
import {
CreateShippingMethodTaxLineDTO,
UpdateShippingMethodTaxLineDTO,
} from "./shipping-method-tax-line"
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IAddressRepository<TEntity extends Cart = Cart>
extends DAL.RepositoryService<
TEntity,
{
create: CreateAddressDTO
update: UpdateAddressDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface ICartRepository<TEntity extends Cart = Cart>
extends DAL.RepositoryService<
TEntity,
{
create: CreateCartDTO
update: UpdateCartDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface ILineItemRepository<TEntity extends LineItem = LineItem>
extends DAL.RepositoryService<
TEntity,
{
create: CreateLineItemDTO
update: UpdateLineItemDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IShippingMethodRepository<
TEntity extends ShippingMethod = ShippingMethod
> extends DAL.RepositoryService<
TEntity,
{
create: CreateShippingMethodDTO
update: UpdateShippingMethodDTO
}
> {}
export interface ILineItemAdjustmentRepository<
TEntity extends LineItemAdjustment = LineItemAdjustment
> extends DAL.RepositoryService<
TEntity,
{
create: CreateLineItemAdjustmentDTO
update: UpdateLineItemAdjustmentDTO
}
> {}
export interface IShippingMethodAdjustmentRepository<
TEntity extends ShippingMethodAdjustment = ShippingMethodAdjustment
> extends DAL.RepositoryService<
TEntity,
{
create: CreateShippingMethodAdjustmentDTO
update: UpdateShippingMethodAdjustmentDTO
}
> {}
export interface IShippingMethodTaxLineRepository<
TEntity extends ShippingMethodTaxLine = ShippingMethodTaxLine
> extends DAL.RepositoryService<
TEntity,
{
create: CreateShippingMethodTaxLineDTO
update: UpdateShippingMethodTaxLineDTO
}
> {}
export interface ILineItemTaxLineRepository<
TEntity extends LineItemTaxLine = LineItemTaxLine
> extends DAL.RepositoryService<
TEntity,
{
create: CreateLineItemTaxLineDTO
update: UpdateLineItemTaxLineDTO
}
> {}
+1 -1
View File
@@ -1,6 +1,6 @@
export interface CreateShippingMethodDTO {
name: string
cart_id: string
shippingMethod_id: string
amount: number
data?: Record<string, unknown>
}
@@ -12,7 +12,7 @@ export const deleteCustomerGroupStep = createStep(
ModuleRegistrationName.CUSTOMER
)
await service.softDeleteCustomerGroup(ids)
await service.softDeleteCustomerGroups(ids)
return new StepResponse(void 0, ids)
},
@@ -25,6 +25,6 @@ export const deleteCustomerGroupStep = createStep(
ModuleRegistrationName.CUSTOMER
)
await service.restoreCustomerGroup(prevCustomerGroups)
await service.restoreCustomerGroups(prevCustomerGroups)
}
)
@@ -1,8 +1,8 @@
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import {
CustomerGroupUpdatableFields,
FilterableCustomerGroupProps,
ICustomerModuleService,
CustomerGroupUpdatableFields,
} from "@medusajs/types"
import {
getSelectsAndRelationsFromObjectArray,
@@ -31,7 +31,7 @@ export const updateCustomerGroupsStep = createStep(
relations,
})
const customers = await service.updateCustomerGroup(
const customers = await service.updateCustomerGroups(
data.selector,
data.update
)
@@ -49,7 +49,7 @@ export const updateCustomerGroupsStep = createStep(
await promiseAll(
prevCustomerGroups.map((c) =>
service.updateCustomerGroup(c.id, {
service.updateCustomerGroups(c.id, {
name: c.name,
})
)
@@ -1,8 +1,8 @@
import {
ICustomerModuleService,
CreateCustomerAddressDTO,
ICustomerModuleService,
} from "@medusajs/types"
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
import { createStep, StepResponse } from "@medusajs/workflows-sdk"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
export const createCustomerAddressesStepId = "create-customer-addresses"
@@ -29,6 +29,6 @@ export const createCustomerAddressesStep = createStep(
ModuleRegistrationName.CUSTOMER
)
await service.deleteAddress(ids)
await service.deleteAddresses(ids)
}
)
@@ -14,7 +14,7 @@ export const deleteCustomerAddressesStep = createStep(
const existing = await service.listAddresses({
id: ids,
})
await service.deleteAddress(ids)
await service.deleteAddresses(ids)
return new StepResponse(void 0, existing)
},
@@ -1,12 +1,12 @@
import {
ICustomerModuleService,
CreateCustomerAddressDTO,
FilterableCustomerAddressProps,
CustomerAddressDTO,
FilterableCustomerAddressProps,
ICustomerModuleService,
} from "@medusajs/types"
import { createStep } from "@medusajs/workflows-sdk"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { unsetForUpdate, unsetForCreate } from "./utils"
import { unsetForCreate, unsetForUpdate } from "./utils"
import { isDefined } from "@medusajs/utils"
type StepInput = {
@@ -53,7 +53,7 @@ export const maybeUnsetDefaultBillingAddressesStep = createStep(
ModuleRegistrationName.CUSTOMER
)
await customerModuleService.updateAddress(
await customerModuleService.updateAddresses(
{ id: addressesToSet },
{ is_default_billing: true }
)
@@ -1,12 +1,12 @@
import {
ICustomerModuleService,
CreateCustomerAddressDTO,
FilterableCustomerAddressProps,
CustomerAddressDTO,
FilterableCustomerAddressProps,
ICustomerModuleService,
} from "@medusajs/types"
import { createStep } from "@medusajs/workflows-sdk"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { unsetForUpdate, unsetForCreate } from "./utils"
import { unsetForCreate, unsetForUpdate } from "./utils"
import { isDefined } from "@medusajs/utils"
type StepInput = {
@@ -52,7 +52,7 @@ export const maybeUnsetDefaultShippingAddressesStep = createStep(
ModuleRegistrationName.CUSTOMER
)
await customerModuleService.updateAddress(
await customerModuleService.updateAddresses(
{ id: addressesToSet },
{ is_default_shipping: true }
)
@@ -31,7 +31,7 @@ export const updateCustomerAddressesStep = createStep(
relations,
})
const customerAddresses = await service.updateAddress(
const customerAddresses = await service.updateAddresses(
data.selector,
data.update
)
@@ -48,7 +48,7 @@ export const updateCustomerAddressesStep = createStep(
)
await promiseAll(
prevCustomerAddresses.map((c) => service.updateAddress(c.id, { ...c }))
prevCustomerAddresses.map((c) => service.updateAddresses(c.id, { ...c }))
)
}
)
@@ -21,7 +21,7 @@ export const unsetForCreate = async (
[field]: true,
})
await customerService.updateAddress(
await customerService.updateAddresses(
{ customer_id: customerIds, [field]: true },
{ [field]: false }
)
@@ -28,7 +28,7 @@ export const unsetForUpdate = async (
[field]: true,
})
await customerService.updateAddress(
await customerService.updateAddresses(
{ customer_id: customerIds, [field]: true },
{ [field]: false }
)
@@ -535,7 +535,7 @@ describe("Customer Module Service", () => {
await service.delete(customer.id)
const res = await service.listCustomerGroupRelations({
const res = await service.listCustomerGroupCustomers({
customer_id: customer.id,
customer_group_id: group.id,
})
@@ -546,7 +546,7 @@ describe("Customer Module Service", () => {
describe("deleteCustomerGroup", () => {
it("should delete a single customer group", async () => {
const [group] = await service.createCustomerGroup([{ name: "VIP" }])
await service.deleteCustomerGroup(group.id)
await service.deleteCustomerGroups(group.id)
await expect(
service.retrieveCustomerGroup(group.id)
@@ -560,7 +560,7 @@ describe("Customer Module Service", () => {
])
const groupIds = groups.map((group) => group.id)
await service.deleteCustomerGroup(groupIds)
await service.deleteCustomerGroups(groupIds)
for (const group of groups) {
await expect(
@@ -575,7 +575,7 @@ describe("Customer Module Service", () => {
await service.createCustomerGroup([{ name: "VIP" }, { name: "Regular" }])
const selector = { name: "VIP" }
await service.deleteCustomerGroup(selector)
await service.deleteCustomerGroups(selector)
const remainingGroups = await service.listCustomerGroups({ name: "VIP" })
expect(remainingGroups.length).toBe(0)
@@ -595,9 +595,9 @@ describe("Customer Module Service", () => {
customer_group_id: group.id,
})
await service.deleteCustomerGroup(group.id)
await service.deleteCustomerGroups(group.id)
const res = await service.listCustomerGroupRelations({
const res = await service.listCustomerGroupCustomers({
customer_id: customer.id,
customer_group_id: group.id,
})
@@ -743,7 +743,7 @@ describe("Customer Module Service", () => {
address_1: "123 Main St",
})
await service.updateAddress(address.id, {
await service.updateAddresses(address.id, {
address_name: "Work",
address_1: "456 Main St",
})
@@ -778,7 +778,7 @@ describe("Customer Module Service", () => {
address_1: "456 Main St",
})
await service.updateAddress(
await service.updateAddresses(
{ customer_id: customer.id },
{
address_name: "Under Construction",
@@ -822,7 +822,7 @@ describe("Customer Module Service", () => {
},
])
await service.updateAddress([address1.id, address2.id], {
await service.updateAddresses([address1.id, address2.id], {
address_name: "Under Construction",
})
@@ -864,7 +864,7 @@ describe("Customer Module Service", () => {
})
await expect(
service.updateAddress(address.id, { is_default_shipping: true })
service.updateAddresses(address.id, { is_default_shipping: true })
).rejects.toThrow("A default shipping address already exists")
})
})
@@ -1087,7 +1087,7 @@ describe("Customer Module Service", () => {
describe("softDeleteCustomerGroup", () => {
it("should soft delete a single customer group", async () => {
const [group] = await service.createCustomerGroup([{ name: "VIP" }])
await service.softDeleteCustomerGroup([group.id])
await service.softDeleteCustomerGroups([group.id])
const res = await service.listCustomerGroups({ id: group.id })
expect(res.length).toBe(0)
@@ -1105,7 +1105,7 @@ describe("Customer Module Service", () => {
{ name: "Regular" },
])
const groupIds = groups.map((group) => group.id)
await service.softDeleteCustomerGroup(groupIds)
await service.softDeleteCustomerGroups(groupIds)
const res = await service.listCustomerGroups({ id: groupIds })
expect(res.length).toBe(0)
@@ -1121,12 +1121,12 @@ describe("Customer Module Service", () => {
describe("restoreCustomerGroup", () => {
it("should restore a single customer group", async () => {
const [group] = await service.createCustomerGroup([{ name: "VIP" }])
await service.softDeleteCustomerGroup([group.id])
await service.softDeleteCustomerGroups([group.id])
const res = await service.listCustomerGroups({ id: group.id })
expect(res.length).toBe(0)
await service.restoreCustomerGroup([group.id])
await service.restoreCustomerGroups([group.id])
const restoredGroup = await service.retrieveCustomerGroup(group.id, {
withDeleted: true,
@@ -1140,12 +1140,12 @@ describe("Customer Module Service", () => {
{ name: "Regular" },
])
const groupIds = groups.map((group) => group.id)
await service.softDeleteCustomerGroup(groupIds)
await service.softDeleteCustomerGroups(groupIds)
const res = await service.listCustomerGroups({ id: groupIds })
expect(res.length).toBe(0)
await service.restoreCustomerGroup(groupIds)
await service.restoreCustomerGroups(groupIds)
const restoredGroups = await service.listCustomerGroups(
{ id: groupIds },
+10 -5
View File
@@ -2,27 +2,32 @@ import { DAL } from "@medusajs/types"
import { generateEntityId } from "@medusajs/utils"
import {
BeforeCreate,
Cascade,
Entity,
Index,
ManyToOne,
OnInit,
OptionalProps,
PrimaryKey,
Property,
ManyToOne,
Cascade,
Index,
} from "@mikro-orm/core"
import Customer from "./customer"
type OptionalAddressProps = DAL.EntityDateColumns // TODO: To be revisited when more clear
export const UNIQUE_CUSTOMER_SHIPPING_ADDRESS =
"IDX_customer_address_unique_customer_shipping"
export const UNIQUE_CUSTOMER_BILLING_ADDRESS =
"IDX_customer_address_unique_customer_billing"
@Entity({ tableName: "customer_address" })
@Index({
name: "IDX_customer_address_unique_customer_shipping",
name: UNIQUE_CUSTOMER_SHIPPING_ADDRESS,
expression:
'create unique index "IDX_customer_address_unique_customer_shipping" on "customer_address" ("customer_id") where "is_default_shipping" = true',
})
@Index({
name: "IDX_customer_address_unique_customer_billing",
name: UNIQUE_CUSTOMER_BILLING_ADDRESS,
expression:
'create unique index "IDX_customer_address_unique_customer_billing" on "customer_address" ("customer_id") where "is_default_billing" = true',
})
-23
View File
@@ -1,23 +0,0 @@
import { DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { Address } from "@models"
import { CreateAddressDTO, UpdateAddressDTO } from "@types"
type InjectedDependencies = {
addressRepository: DAL.RepositoryService
}
export default class AddressService<
TEntity extends Address = Address
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: CreateAddressDTO
update: UpdateAddressDTO
}
>(Address)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
}
@@ -1,25 +0,0 @@
import { DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { CustomerGroupCustomer } from "@models"
type CreateCustomerGroupCustomerDTO = {
customer_id: string
customer_group_id: string
created_by?: string
}
type InjectedDependencies = {
customerGroupRepository: DAL.RepositoryService
}
export default class CustomerGroupCustomerService<
TEntity extends CustomerGroupCustomer = CustomerGroupCustomer
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{ create: CreateCustomerGroupCustomerDTO }
>(CustomerGroupCustomer)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
}
@@ -1,23 +0,0 @@
import { DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { CustomerGroup } from "@models"
import { CreateCustomerGroupDTO, UpdateCustomerGroupDTO } from "@medusajs/types"
type InjectedDependencies = {
customerGroupRepository: DAL.RepositoryService
}
export default class CustomerGroupService<
TEntity extends CustomerGroup = CustomerGroup
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: CreateCustomerGroupDTO
update: UpdateCustomerGroupDTO
}
>(CustomerGroup)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
}
+154 -464
View File
@@ -1,48 +1,69 @@
import {
Context,
CustomerDTO,
CustomerTypes,
DAL,
FindConfig,
ICustomerModuleService,
InternalModuleDeclaration,
ModuleJoinerConfig,
CustomerTypes,
SoftDeleteReturn,
RestoreReturn,
ModulesSdkTypes,
} from "@medusajs/types"
import {
InjectManager,
InjectTransactionManager,
MedusaContext,
mapObjectTo,
isString,
isObject,
isDuplicateError,
isString,
MedusaContext,
MedusaError,
ModulesSdkUtils,
} from "@medusajs/utils"
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
import * as services from "../services"
import { MedusaError } from "@medusajs/utils"
import {
Address,
Customer,
CustomerGroup,
CustomerGroupCustomer,
} from "@models"
import { EntityManager } from "@mikro-orm/core"
const UNIQUE_CUSTOMER_SHIPPING_ADDRESS =
"IDX_customer_address_unique_customer_shipping"
const UNIQUE_CUSTOMER_BILLING_ADDRESS =
"IDX_customer_address_unique_customer_billing"
import {
UNIQUE_CUSTOMER_BILLING_ADDRESS,
UNIQUE_CUSTOMER_SHIPPING_ADDRESS,
} from "../models/address"
type InjectedDependencies = {
baseRepository: DAL.RepositoryService
customerService: services.CustomerService
addressService: services.AddressService
customerGroupService: services.CustomerGroupService
customerGroupCustomerService: services.CustomerGroupCustomerService
customerService: ModulesSdkTypes.InternalModuleService<any>
addressService: ModulesSdkTypes.InternalModuleService<any>
customerGroupService: ModulesSdkTypes.InternalModuleService<any>
customerGroupCustomerService: ModulesSdkTypes.InternalModuleService<any>
}
export default class CustomerModuleService implements ICustomerModuleService {
const generateMethodForModels = [Address, CustomerGroup, CustomerGroupCustomer]
export default class CustomerModuleService<
TAddress extends Address = Address,
TCustomer extends Customer = Customer,
TCustomerGroup extends CustomerGroup = CustomerGroup,
TCustomerGroupCustomer extends CustomerGroupCustomer = CustomerGroupCustomer
>
// TODO seb I let you manage that when you are moving forward
extends ModulesSdkUtils.abstractModuleServiceFactory<
InjectedDependencies,
CustomerDTO,
{
Address: { dto: any }
CustomerGroup: { dto: any }
CustomerGroupCustomer: { dto: any }
}
>(Customer, generateMethodForModels, entityNameToLinkableKeysMap)
implements ICustomerModuleService
{
protected baseRepository_: DAL.RepositoryService
protected customerService_: services.CustomerService
protected addressService_: services.AddressService
protected customerGroupService_: services.CustomerGroupService
protected customerGroupCustomerService_: services.CustomerGroupCustomerService
protected customerService_: ModulesSdkTypes.InternalModuleService<TCustomer>
protected addressService_: ModulesSdkTypes.InternalModuleService<TAddress>
protected customerGroupService_: ModulesSdkTypes.InternalModuleService<TCustomerGroup>
protected customerGroupCustomerService_: ModulesSdkTypes.InternalModuleService<TCustomerGroupCustomer>
constructor(
{
@@ -54,6 +75,9 @@ export default class CustomerModuleService implements ICustomerModuleService {
}: InjectedDependencies,
protected readonly moduleDeclaration: InternalModuleDeclaration
) {
// @ts-ignore
super(...arguments)
this.baseRepository_ = baseRepository
this.customerService_ = customerService
this.addressService_ = addressService
@@ -65,26 +89,6 @@ export default class CustomerModuleService implements ICustomerModuleService {
return joinerConfig
}
@InjectManager("baseRepository_")
async retrieve(
id: string,
config: FindConfig<CustomerTypes.CustomerDTO> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<CustomerTypes.CustomerDTO> {
const customer = await this.customerService_.retrieve(
id,
config,
sharedContext
)
return await this.baseRepository_.serialize<CustomerTypes.CustomerDTO>(
customer,
{
populate: true,
}
)
}
async create(
data: CustomerTypes.CreateCustomerDTO,
sharedContext?: Context
@@ -95,13 +99,33 @@ export default class CustomerModuleService implements ICustomerModuleService {
sharedContext?: Context
): Promise<CustomerTypes.CustomerDTO[]>
@InjectTransactionManager("baseRepository_")
@InjectManager("baseRepository_")
async create(
dataOrArray:
| CustomerTypes.CreateCustomerDTO
| CustomerTypes.CreateCustomerDTO[],
@MedusaContext() sharedContext: Context = {}
) {
): Promise<CustomerTypes.CustomerDTO | CustomerTypes.CustomerDTO[]> {
const customers = await this.create_(dataOrArray, sharedContext).catch(
this.handleDbErrors
)
const serialized = await this.baseRepository_.serialize<
CustomerTypes.CustomerDTO[]
>(customers, {
populate: true,
})
return Array.isArray(dataOrArray) ? serialized : serialized[0]
}
@InjectTransactionManager("baseRepository_")
async create_(
dataOrArray:
| CustomerTypes.CreateCustomerDTO
| CustomerTypes.CreateCustomerDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<CustomerTypes.CustomerDTO[]> {
const data = Array.isArray(dataOrArray) ? dataOrArray : [dataOrArray]
const customers = await this.customerService_.create(data, sharedContext)
@@ -121,12 +145,7 @@ export default class CustomerModuleService implements ICustomerModuleService {
await this.addAddresses(addressDataWithCustomerIds, sharedContext)
const serialized = await this.baseRepository_.serialize<
CustomerTypes.CustomerDTO[]
>(customers, {
populate: true,
})
return Array.isArray(dataOrArray) ? serialized : serialized[0]
return customers as unknown as CustomerTypes.CustomerDTO[]
}
update(
@@ -151,37 +170,38 @@ export default class CustomerModuleService implements ICustomerModuleService {
data: CustomerTypes.CustomerUpdatableFields,
@MedusaContext() sharedContext: Context = {}
) {
let updateData: CustomerTypes.UpdateCustomerDTO[] = []
let updateData:
| CustomerTypes.UpdateCustomerDTO
| CustomerTypes.UpdateCustomerDTO[]
| {
selector: CustomerTypes.FilterableCustomerProps
data: CustomerTypes.CustomerUpdatableFields
} = []
if (isString(idsOrSelector)) {
updateData = [
{
id: idsOrSelector,
...data,
},
]
updateData = {
id: idsOrSelector,
...data,
}
} else if (Array.isArray(idsOrSelector)) {
updateData = idsOrSelector.map((id) => ({
id,
...data,
}))
} else {
const ids = await this.customerService_.list(
idsOrSelector,
{ select: ["id"] },
sharedContext
)
updateData = ids.map(({ id }) => ({
id,
...data,
}))
updateData = {
selector: idsOrSelector,
data: data,
}
}
const customers = await this.customerService_.update(
updateData,
sharedContext
)
const serialized = await this.baseRepository_.serialize<
CustomerTypes.CustomerDTO[]
CustomerTypes.CustomerDTO | CustomerTypes.CustomerDTO[]
>(customers, {
populate: true,
})
@@ -189,78 +209,6 @@ export default class CustomerModuleService implements ICustomerModuleService {
return isString(idsOrSelector) ? serialized[0] : serialized
}
delete(customerId: string, sharedContext?: Context): Promise<void>
delete(customerIds: string[], sharedContext?: Context): Promise<void>
delete(
selector: CustomerTypes.FilterableCustomerProps,
sharedContext?: Context
): Promise<void>
@InjectTransactionManager("baseRepository_")
async delete(
idsOrSelector: string | string[] | CustomerTypes.FilterableCustomerProps,
@MedusaContext() sharedContext: Context = {}
) {
let toDelete = Array.isArray(idsOrSelector)
? idsOrSelector
: [idsOrSelector as string]
if (isObject(idsOrSelector)) {
const ids = await this.customerService_.list(
idsOrSelector,
{
select: ["id"],
},
sharedContext
)
toDelete = ids.map(({ id }) => id)
}
return await this.customerService_.delete(toDelete, sharedContext)
}
@InjectManager("baseRepository_")
async list(
filters: CustomerTypes.FilterableCustomerProps = {},
config: FindConfig<CustomerTypes.CustomerDTO> = {},
@MedusaContext() sharedContext: Context = {}
) {
const customers = await this.customerService_.list(
filters,
config,
sharedContext
)
return await this.baseRepository_.serialize<CustomerTypes.CustomerDTO[]>(
customers,
{
populate: true,
}
)
}
@InjectManager("baseRepository_")
async listAndCount(
filters: CustomerTypes.FilterableCustomerProps = {},
config: FindConfig<CustomerTypes.CustomerDTO> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<[CustomerTypes.CustomerDTO[], number]> {
const [customers, count] = await this.customerService_.listAndCount(
filters,
config,
sharedContext
)
return [
await this.baseRepository_.serialize<CustomerTypes.CustomerDTO[]>(
customers,
{
populate: true,
}
),
count,
]
}
async createCustomerGroup(
dataOrArrayOfData: CustomerTypes.CreateCustomerGroupDTO,
sharedContext?: Context
@@ -278,55 +226,36 @@ export default class CustomerModuleService implements ICustomerModuleService {
| CustomerTypes.CreateCustomerGroupDTO[],
@MedusaContext() sharedContext: Context = {}
) {
const data = Array.isArray(dataOrArrayOfData)
? dataOrArrayOfData
: [dataOrArrayOfData]
const groups = await this.customerGroupService_.create(
dataOrArrayOfData,
sharedContext
)
const groups = await this.customerGroupService_.create(data, sharedContext)
const serialized = await this.baseRepository_.serialize<
CustomerTypes.CustomerGroupDTO[]
return await this.baseRepository_.serialize<
CustomerTypes.CustomerGroupDTO | CustomerTypes.CustomerGroupDTO[]
>(groups, {
populate: true,
})
return Array.isArray(dataOrArrayOfData) ? serialized : serialized[0]
}
@InjectManager("baseRepository_")
async retrieveCustomerGroup(
groupId: string,
config: FindConfig<CustomerTypes.CustomerGroupDTO> = {},
@MedusaContext() sharedContext: Context = {}
) {
const group = await this.customerGroupService_.retrieve(
groupId,
config,
sharedContext
)
return await this.baseRepository_.serialize<CustomerTypes.CustomerGroupDTO>(
group,
{ populate: true }
)
}
async updateCustomerGroup(
async updateCustomerGroups(
groupId: string,
data: CustomerTypes.CustomerGroupUpdatableFields,
sharedContext?: Context
): Promise<CustomerTypes.CustomerGroupDTO>
async updateCustomerGroup(
async updateCustomerGroups(
groupIds: string[],
data: CustomerTypes.CustomerGroupUpdatableFields,
sharedContext?: Context
): Promise<CustomerTypes.CustomerGroupDTO[]>
async updateCustomerGroup(
async updateCustomerGroups(
selector: CustomerTypes.FilterableCustomerGroupProps,
data: CustomerTypes.CustomerGroupUpdatableFields,
sharedContext?: Context
): Promise<CustomerTypes.CustomerGroupDTO[]>
@InjectTransactionManager("baseRepository_")
async updateCustomerGroup(
async updateCustomerGroups(
groupIdOrSelector:
| string
| string[]
@@ -334,29 +263,27 @@ export default class CustomerModuleService implements ICustomerModuleService {
data: CustomerTypes.CustomerGroupUpdatableFields,
@MedusaContext() sharedContext: Context = {}
) {
let updateData: CustomerTypes.UpdateCustomerGroupDTO[] = []
if (isString(groupIdOrSelector)) {
updateData = [
{
id: groupIdOrSelector,
...data,
},
]
} else if (Array.isArray(groupIdOrSelector)) {
updateData = groupIdOrSelector.map((id) => ({
let updateData:
| CustomerTypes.UpdateCustomerGroupDTO
| CustomerTypes.UpdateCustomerGroupDTO[]
| {
selector: CustomerTypes.FilterableCustomerGroupProps
data: CustomerTypes.CustomerGroupUpdatableFields
} = []
if (isString(groupIdOrSelector) || Array.isArray(groupIdOrSelector)) {
const groupIdOrSelectorArray = Array.isArray(groupIdOrSelector)
? groupIdOrSelector
: [groupIdOrSelector]
updateData = groupIdOrSelectorArray.map((id) => ({
id,
...data,
}))
} else {
const ids = await this.customerGroupService_.list(
groupIdOrSelector,
{ select: ["id"] },
sharedContext
)
updateData = ids.map(({ id }) => ({
id,
...data,
}))
updateData = {
selector: groupIdOrSelector,
data: data,
}
}
const groups = await this.customerGroupService_.update(
@@ -376,39 +303,6 @@ export default class CustomerModuleService implements ICustomerModuleService {
>(groups, { populate: true })
}
deleteCustomerGroup(groupId: string, sharedContext?: Context): Promise<void>
deleteCustomerGroup(
groupIds: string[],
sharedContext?: Context
): Promise<void>
deleteCustomerGroup(
selector: CustomerTypes.FilterableCustomerGroupProps,
sharedContext?: Context
): Promise<void>
@InjectTransactionManager("baseRepository_")
async deleteCustomerGroup(
groupIdOrSelector:
| string
| string[]
| CustomerTypes.FilterableCustomerGroupProps,
@MedusaContext() sharedContext: Context = {}
) {
let toDelete = Array.isArray(groupIdOrSelector)
? groupIdOrSelector
: [groupIdOrSelector as string]
if (isObject(groupIdOrSelector)) {
const ids = await this.customerGroupService_.list(
groupIdOrSelector,
{ select: ["id"] },
sharedContext
)
toDelete = ids.map(({ id }) => id)
}
return await this.customerGroupService_.delete(toDelete, sharedContext)
}
async addCustomerToGroup(
groupCustomerPair: CustomerTypes.GroupCustomerPair,
sharedContext?: Context
@@ -425,17 +319,20 @@ export default class CustomerModuleService implements ICustomerModuleService {
@MedusaContext() sharedContext: Context = {}
): Promise<{ id: string } | { id: string }[]> {
const groupCustomers = await this.customerGroupCustomerService_.create(
Array.isArray(data) ? data : [data],
data,
sharedContext
)
if (Array.isArray(data)) {
return groupCustomers.map((gc) => ({ id: gc.id }))
return (groupCustomers as unknown as TCustomerGroupCustomer[]).map(
(gc) => ({ id: gc.id })
)
}
return { id: groupCustomers[0].id }
return { id: groupCustomers.id }
}
// TODO: should be createAddresses to conform to the convention
async addAddresses(
addresses: CustomerTypes.CreateCustomerAddressDTO[],
sharedContext?: Context
@@ -445,7 +342,7 @@ export default class CustomerModuleService implements ICustomerModuleService {
sharedContext?: Context
): Promise<CustomerTypes.CustomerAddressDTO>
@InjectTransactionManager("baseRepository_")
@InjectManager("baseRepository_")
async addAddresses(
data:
| CustomerTypes.CreateCustomerAddressDTO
@@ -454,13 +351,10 @@ export default class CustomerModuleService implements ICustomerModuleService {
): Promise<
CustomerTypes.CustomerAddressDTO | CustomerTypes.CustomerAddressDTO[]
> {
const addresses = await this.addressService_.create(
Array.isArray(data) ? data : [data],
sharedContext
const addresses = await this.addAddresses_(data, sharedContext).catch(
this.handleDbErrors
)
await this.flush(sharedContext).catch(this.handleDbErrors)
const serialized = await this.baseRepository_.serialize<
CustomerTypes.CustomerAddressDTO[]
>(addresses, { populate: true })
@@ -472,24 +366,39 @@ export default class CustomerModuleService implements ICustomerModuleService {
return serialized[0]
}
async updateAddress(
@InjectTransactionManager("baseRepository_")
private async addAddresses_(
data:
| CustomerTypes.CreateCustomerAddressDTO
| CustomerTypes.CreateCustomerAddressDTO[],
@MedusaContext() sharedContext: Context = {}
) {
const addresses = await this.addressService_.create(
Array.isArray(data) ? data : [data],
sharedContext
)
return addresses
}
async updateAddresses(
addressId: string,
data: CustomerTypes.UpdateCustomerAddressDTO,
sharedContext?: Context
): Promise<CustomerTypes.CustomerAddressDTO>
async updateAddress(
async updateAddresses(
addressIds: string[],
data: CustomerTypes.UpdateCustomerAddressDTO,
sharedContext?: Context
): Promise<CustomerTypes.CustomerAddressDTO[]>
async updateAddress(
async updateAddresses(
selector: CustomerTypes.FilterableCustomerAddressProps,
data: CustomerTypes.UpdateCustomerAddressDTO,
sharedContext?: Context
): Promise<CustomerTypes.CustomerAddressDTO[]>
@InjectTransactionManager("baseRepository_")
async updateAddress(
async updateAddresses(
addressIdOrSelector:
| string
| string[]
@@ -497,7 +406,12 @@ export default class CustomerModuleService implements ICustomerModuleService {
data: CustomerTypes.UpdateCustomerAddressDTO,
@MedusaContext() sharedContext: Context = {}
) {
let updateData: CustomerTypes.UpdateCustomerAddressDTO[] = []
let updateData:
| CustomerTypes.UpdateCustomerAddressDTO[]
| {
selector: CustomerTypes.FilterableCustomerAddressProps
data: CustomerTypes.UpdateCustomerAddressDTO
} = []
if (isString(addressIdOrSelector)) {
updateData = [
{
@@ -511,15 +425,10 @@ export default class CustomerModuleService implements ICustomerModuleService {
...data,
}))
} else {
const ids = await this.addressService_.list(
addressIdOrSelector,
{ select: ["id"] },
sharedContext
)
updateData = ids.map(({ id }) => ({
id,
...data,
}))
updateData = {
selector: addressIdOrSelector,
data,
}
}
const addresses = await this.addressService_.update(
@@ -540,78 +449,6 @@ export default class CustomerModuleService implements ICustomerModuleService {
return serialized
}
async deleteAddress(addressId: string, sharedContext?: Context): Promise<void>
async deleteAddress(
addressIds: string[],
sharedContext?: Context
): Promise<void>
async deleteAddress(
selector: CustomerTypes.FilterableCustomerAddressProps,
sharedContext?: Context
): Promise<void>
@InjectTransactionManager("baseRepository_")
async deleteAddress(
addressIdOrSelector:
| string
| string[]
| CustomerTypes.FilterableCustomerAddressProps,
@MedusaContext() sharedContext: Context = {}
) {
let toDelete = Array.isArray(addressIdOrSelector)
? addressIdOrSelector
: [addressIdOrSelector as string]
if (isObject(addressIdOrSelector)) {
const ids = await this.addressService_.list(
addressIdOrSelector,
{ select: ["id"] },
sharedContext
)
toDelete = ids.map(({ id }) => id)
}
await this.addressService_.delete(toDelete, sharedContext)
}
@InjectManager("baseRepository_")
async listAddresses(
filters?: CustomerTypes.FilterableCustomerAddressProps,
config?: FindConfig<CustomerTypes.CustomerAddressDTO>,
@MedusaContext() sharedContext: Context = {}
): Promise<CustomerTypes.CustomerAddressDTO[]> {
const addresses = await this.addressService_.list(
filters,
config,
sharedContext
)
return await this.baseRepository_.serialize<
CustomerTypes.CustomerAddressDTO[]
>(addresses, { populate: true })
}
@InjectManager("baseRepository_")
async listAndCountAddresses(
filters?: CustomerTypes.FilterableCustomerAddressProps,
config?: FindConfig<CustomerTypes.CustomerAddressDTO>,
@MedusaContext() sharedContext: Context = {}
): Promise<[CustomerTypes.CustomerAddressDTO[], number]> {
const [addresses, count] = await this.addressService_.listAndCount(
filters,
config,
sharedContext
)
return [
await this.baseRepository_.serialize<CustomerTypes.CustomerAddressDTO[]>(
addresses,
{ populate: true }
),
count,
]
}
async removeCustomerFromGroup(
groupCustomerPair: CustomerTypes.GroupCustomerPair,
sharedContext?: Context
@@ -636,153 +473,6 @@ export default class CustomerModuleService implements ICustomerModuleService {
)
}
@InjectManager("baseRepository_")
async listCustomerGroupRelations(
filters?: CustomerTypes.FilterableCustomerGroupCustomerProps,
config?: FindConfig<CustomerTypes.CustomerGroupCustomerDTO>,
@MedusaContext() sharedContext: Context = {}
) {
const groupCustomers = await this.customerGroupCustomerService_.list(
filters,
config,
sharedContext
)
return await this.baseRepository_.serialize<
CustomerTypes.CustomerGroupCustomerDTO[]
>(groupCustomers, {
populate: true,
})
}
@InjectManager("baseRepository_")
async listCustomerGroups(
filters: CustomerTypes.FilterableCustomerGroupProps = {},
config: FindConfig<CustomerTypes.CustomerGroupDTO> = {},
@MedusaContext() sharedContext: Context = {}
) {
const groups = await this.customerGroupService_.list(
filters,
config,
sharedContext
)
return await this.baseRepository_.serialize<
CustomerTypes.CustomerGroupDTO[]
>(groups, {
populate: true,
})
}
@InjectManager("baseRepository_")
async listAndCountCustomerGroups(
filters: CustomerTypes.FilterableCustomerGroupProps = {},
config: FindConfig<CustomerTypes.CustomerGroupDTO> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<[CustomerTypes.CustomerGroupDTO[], number]> {
const [groups, count] = await this.customerGroupService_.listAndCount(
filters,
config,
sharedContext
)
return [
await this.baseRepository_.serialize<CustomerTypes.CustomerGroupDTO[]>(
groups,
{
populate: true,
}
),
count,
]
}
@InjectTransactionManager("baseRepository_")
async softDeleteCustomerGroup<
TReturnableLinkableKeys extends string = string
>(
groupIds: string[],
config: SoftDeleteReturn<TReturnableLinkableKeys> = {},
@MedusaContext() sharedContext: Context = {}
) {
const [_, cascadedEntitiesMap] =
await this.customerGroupService_.softDelete(groupIds, sharedContext)
return config.returnLinkableKeys
? mapObjectTo<Record<TReturnableLinkableKeys, string[]>>(
cascadedEntitiesMap,
entityNameToLinkableKeysMap,
{
pick: config.returnLinkableKeys,
}
)
: void 0
}
@InjectTransactionManager("baseRepository_")
async restoreCustomerGroup<TReturnableLinkableKeys extends string = string>(
groupIds: string[],
config: RestoreReturn<TReturnableLinkableKeys> = {},
@MedusaContext() sharedContext: Context = {}
) {
const [_, cascadedEntitiesMap] = await this.customerGroupService_.restore(
groupIds,
sharedContext
)
return config.returnLinkableKeys
? mapObjectTo<Record<TReturnableLinkableKeys, string[]>>(
cascadedEntitiesMap,
entityNameToLinkableKeysMap,
{
pick: config.returnLinkableKeys,
}
)
: void 0
}
@InjectTransactionManager("baseRepository_")
async softDelete<TReturnableLinkableKeys extends string = string>(
customerIds: string[],
config: SoftDeleteReturn<TReturnableLinkableKeys> = {},
@MedusaContext() sharedContext: Context = {}
) {
const [_, cascadedEntitiesMap] = await this.customerService_.softDelete(
customerIds,
sharedContext
)
return config.returnLinkableKeys
? mapObjectTo<Record<TReturnableLinkableKeys, string[]>>(
cascadedEntitiesMap,
entityNameToLinkableKeysMap,
{
pick: config.returnLinkableKeys,
}
)
: void 0
}
@InjectTransactionManager("baseRepository_")
async restore<TReturnableLinkableKeys extends string = string>(
customerIds: string[],
config: RestoreReturn<TReturnableLinkableKeys> = {},
@MedusaContext() sharedContext: Context = {}
) {
const [_, cascadedEntitiesMap] = await this.customerService_.restore(
customerIds,
sharedContext
)
return config.returnLinkableKeys
? mapObjectTo<Record<TReturnableLinkableKeys, string[]>>(
cascadedEntitiesMap,
entityNameToLinkableKeysMap,
{
pick: config.returnLinkableKeys,
}
)
: void 0
}
private async flush(context: Context) {
const em = (context.manager ?? context.transactionManager) as EntityManager
await em.flush()
@@ -1,22 +0,0 @@
import { CustomerTypes, DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { Customer } from "@models"
type InjectedDependencies = {
customerRepository: DAL.RepositoryService
}
export default class CustomerService<
TEntity extends Customer = Customer
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: CustomerTypes.CreateCustomerDTO
update: CustomerTypes.UpdateCustomerDTO
}
>(Customer)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
}
-4
View File
@@ -1,5 +1 @@
export { default as AddressService } from "./address"
export { default as CustomerGroupService } from "./customer-group"
export { default as CustomerService } from "./customer"
export { default as CustomerModuleService } from "./customer-module"
export { default as CustomerGroupCustomerService } from "./customer-group-customer"
+4 -1
View File
@@ -1,5 +1,8 @@
import { Logger } from "@medusajs/types"
export * from "./address"
export * as ServiceTypes from "./services"
export * from "./services"
export type InitializeModuleInjectableDependencies = {
logger?: Logger
}
@@ -0,0 +1,5 @@
export interface CreateCustomerGroupCustomerDTO {
customer_id: string
customer_group_id: string
created_by?: string
}
@@ -0,0 +1,2 @@
export * from "./address"
export * from "./customer-group-customer"
@@ -116,7 +116,7 @@ describe("Payment Module Service", () => {
expect(collection.length).toEqual(1)
await service.deletePaymentCollection(["pay-col-id-1"])
await service.deletePaymentCollections(["pay-col-id-1"])
collection = await service.listPaymentCollections({
id: ["pay-col-id-1"],
-1
View File
@@ -1,2 +1 @@
export { default as PaymentModuleService } from "./payment-module"
export { default as PaymentCollectionService } from "./payment-collection"
@@ -1,26 +0,0 @@
import { PaymentCollection } from "@models"
import {
CreatePaymentCollectionDTO,
DAL,
UpdatePaymentCollectionDTO,
} from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
type InjectedDependencies = {
paymentCollectionRepository: DAL.RepositoryService
}
export default class PaymentCollectionService<
TEntity extends PaymentCollection = PaymentCollection
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: CreatePaymentCollectionDTO
update: UpdatePaymentCollectionDTO
}
>(PaymentCollection)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
}
+44 -88
View File
@@ -4,11 +4,10 @@ import {
CreatePaymentDTO,
CreatePaymentSessionDTO,
DAL,
FilterablePaymentCollectionProps,
FindConfig,
InternalModuleDeclaration,
IPaymentModuleService,
ModuleJoinerConfig,
ModulesSdkTypes,
PaymentCollectionDTO,
PaymentDTO,
SetPaymentSessionsDTO,
@@ -16,28 +15,64 @@ import {
UpdatePaymentDTO,
} from "@medusajs/types"
import {
InjectManager,
InjectTransactionManager,
MedusaContext,
ModulesSdkUtils,
} from "@medusajs/utils"
import * as services from "@services"
import { joinerConfig } from "../joiner-config"
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
import {
Capture,
Payment,
PaymentCollection,
PaymentMethodToken,
PaymentProvider,
PaymentSession,
Refund,
} from "@models"
type InjectedDependencies = {
baseRepository: DAL.RepositoryService
paymentCollectionService: services.PaymentCollectionService
paymentCollectionService: ModulesSdkTypes.InternalModuleService<any>
}
export default class PaymentModuleService implements IPaymentModuleService {
const generateMethodForModels = [
Capture,
PaymentCollection,
PaymentMethodToken,
PaymentProvider,
PaymentSession,
Refund,
]
export default class PaymentModuleService<
TPaymentCollection extends PaymentCollection = PaymentCollection
>
extends ModulesSdkUtils.abstractModuleServiceFactory<
// TODO revisit when moving forward frane
InjectedDependencies,
PaymentDTO,
{
Capture: { dto: any }
PaymentCollection: { dto: any }
PaymentMethodToken: { dto: any }
PaymentProvider: { dto: any }
PaymentSession: { dto: any }
Refund: { dto: any }
}
>(Payment, generateMethodForModels, entityNameToLinkableKeysMap)
implements IPaymentModuleService
{
protected baseRepository_: DAL.RepositoryService
protected paymentCollectionService_: services.PaymentCollectionService
protected paymentCollectionService_: ModulesSdkTypes.InternalModuleService<TPaymentCollection>
constructor(
{ baseRepository, paymentCollectionService }: InjectedDependencies,
protected readonly moduleDeclaration: InternalModuleDeclaration
) {
// @ts-ignore
super(...arguments)
this.baseRepository_ = baseRepository
this.paymentCollectionService_ = paymentCollectionService
@@ -105,85 +140,6 @@ export default class PaymentModuleService implements IPaymentModuleService {
)
}
deletePaymentCollection(
paymentCollectionId: string[],
sharedContext?: Context
): Promise<void>
deletePaymentCollection(
paymentCollectionId: string,
sharedContext?: Context
): Promise<void>
@InjectTransactionManager("baseRepository_")
async deletePaymentCollection(
ids: string | string[],
@MedusaContext() sharedContext?: Context
): Promise<void> {
const paymentCollectionIds = Array.isArray(ids) ? ids : [ids]
await this.paymentCollectionService_.delete(
paymentCollectionIds,
sharedContext
)
}
@InjectManager("baseRepository_")
async retrievePaymentCollection(
paymentCollectionId: string,
config: FindConfig<PaymentCollectionDTO> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<PaymentCollectionDTO> {
const paymentCollection = await this.paymentCollectionService_.retrieve(
paymentCollectionId,
config,
sharedContext
)
return await this.baseRepository_.serialize<PaymentCollectionDTO>(
paymentCollection,
{ populate: true }
)
}
@InjectManager("baseRepository_")
async listPaymentCollections(
filters: FilterablePaymentCollectionProps = {},
config: FindConfig<PaymentCollectionDTO> = {},
@MedusaContext() sharedContext?: Context
): Promise<PaymentCollectionDTO[]> {
const paymentCollections = await this.paymentCollectionService_.list(
filters,
config,
sharedContext
)
return await this.baseRepository_.serialize<PaymentCollectionDTO[]>(
paymentCollections,
{ populate: true }
)
}
@InjectManager("baseRepository_")
async listAndCountPaymentCollections(
filters: FilterablePaymentCollectionProps = {},
config: FindConfig<PaymentCollectionDTO> = {},
@MedusaContext() sharedContext?: Context
): Promise<[PaymentCollectionDTO[], number]> {
const [paymentCollections, count] =
await this.paymentCollectionService_.listAndCount(
filters,
config,
sharedContext
)
return [
await this.baseRepository_.serialize<PaymentCollectionDTO[]>(
paymentCollections,
{ populate: true }
),
count,
]
}
/**
* TODO
*/
@@ -1,18 +0,0 @@
import {
DAL,
CreatePaymentCollectionDTO,
UpdatePaymentCollectionDTO,
} from "@medusajs/types"
import { PaymentCollection } from "@models"
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IPaymentCollectionRepository<
TEntity extends PaymentCollection = PaymentCollection
> extends DAL.RepositoryService<
TEntity,
{
create: CreatePaymentCollectionDTO
update: UpdatePaymentCollectionDTO
}
> {}
@@ -183,7 +183,7 @@ describe("Currency Service", () => {
error = e
}
expect(error.message).toEqual('"currencyCode" must be defined')
expect(error.message).toEqual("currency - code must be defined")
})
it("should return currency based on config select param", async () => {
@@ -258,7 +258,7 @@ describe("MoneyAmount Service", () => {
error = e
}
expect(error.message).toEqual('"moneyAmountId" must be defined')
expect(error.message).toEqual("moneyAmount - id must be defined")
})
it("should return moneyAmount based on config select param", async () => {
@@ -162,7 +162,7 @@ describe("PriceListRule Service", () => {
error = e
}
expect(error.message).toEqual('"priceListRuleId" must be defined')
expect(error.message).toEqual("priceListRule - id must be defined")
})
})
@@ -157,7 +157,7 @@ describe("PriceList Service", () => {
error = e
}
expect(error.message).toEqual('"priceListId" must be defined')
expect(error.message).toEqual("priceList - id must be defined")
})
})
@@ -219,7 +219,7 @@ describe("PriceRule Service", () => {
error = e
}
expect(error.message).toEqual('"priceRuleId" must be defined')
expect(error.message).toEqual("priceRule - id must be defined")
})
it("should return priceRule based on config select param", async () => {
@@ -168,7 +168,7 @@ describe("PriceSetMoneyAmountRules Service", () => {
}
expect(error.message).toEqual(
'"priceSetMoneyAmountRulesId" must be defined'
"priceSetMoneyAmountRules - id must be defined"
)
})
@@ -305,7 +305,7 @@ describe("PriceSet Service", () => {
error = e
}
expect(error.message).toEqual('"priceSetId" must be defined')
expect(error.message).toEqual("priceSet - id must be defined")
})
it("should return priceSet based on config select param", async () => {
@@ -180,7 +180,7 @@ describe("PricingModule Service - Currency", () => {
error = e
}
expect(error.message).toEqual('"currencyCode" must be defined')
expect(error.message).toEqual("currency - code must be defined")
})
it("should return currency based on config select param", async () => {
@@ -245,7 +245,7 @@ describe("PricingModule Service - MoneyAmount", () => {
error = e
}
expect(error.message).toEqual('"moneyAmountId" must be defined')
expect(error.message).toEqual("moneyAmount - id must be defined")
})
it("should return moneyAmount based on config select param", async () => {
@@ -320,7 +320,7 @@ describe("PricingModule Service - MoneyAmount", () => {
})
})
describe("restoreDeletedMoneyAmounts", () => {
describe("restoreMoneyAmounts", () => {
const id = "money-amount-USD"
it("should restore softDeleted priceSetMoneyAmount and PriceRule when restoring soft-deleting money amount", async () => {
@@ -330,7 +330,7 @@ describe("PricingModule Service - MoneyAmount", () => {
await createPriceRules(testManager)
await createPriceSetMoneyAmountRules(testManager)
await service.softDeleteMoneyAmounts([id])
await service.restoreDeletedMoneyAmounts([id])
await service.restoreMoneyAmounts([id])
const [moneyAmount] = await service.listMoneyAmounts(
{
@@ -171,7 +171,7 @@ describe("PriceListRule Service", () => {
error = e
}
expect(error.message).toEqual('"priceListRuleId" must be defined')
expect(error.message).toEqual("priceListRule - id must be defined")
})
})
@@ -283,7 +283,7 @@ describe("PriceListRule Service", () => {
expect(priceList.price_list_rules).toEqual(
expect.arrayContaining([
expect.objectContaining({
rule_type: "rule-type-3",
rule_type: { id: "rule-type-3" },
price_list_rule_values: [
expect.objectContaining({ value: "sc-1" }),
],
@@ -323,7 +323,7 @@ describe("PriceListRule Service", () => {
expect(priceList.price_list_rules).toEqual(
expect.arrayContaining([
expect.objectContaining({
rule_type: "rule-type-3",
rule_type: { id: "rule-type-3" },
price_list_rule_values: expect.arrayContaining([
expect.objectContaining({ value: "sc-1" }),
expect.objectContaining({ value: "sc-2" }),
@@ -351,7 +351,7 @@ describe("PriceListRule Service", () => {
)
expect(priceList.price_list_rules).toEqual([
expect.objectContaining({ rule_type: "rule-type-2" }),
expect.objectContaining({ rule_type: { id: "rule-type-2" } }),
])
})
})
@@ -179,7 +179,7 @@ describe("PriceList Service", () => {
error = e
}
expect(error.message).toEqual('"priceListId" must be defined')
expect(error.message).toEqual("priceList - id must be defined")
})
})
@@ -224,7 +224,7 @@ describe("PricingModule Service - PriceRule", () => {
error = e
}
expect(error.message).toEqual('"priceRuleId" must be defined')
expect(error.message).toEqual("priceRule - id must be defined")
})
it("should return PriceRule based on config select param", async () => {
@@ -192,7 +192,7 @@ describe("PricingModule Service - PriceSetMoneyAmountRules", () => {
}
expect(error.message).toEqual(
'"priceSetMoneyAmountRulesId" must be defined'
"priceSetMoneyAmountRules - id must be defined"
)
})
@@ -248,7 +248,7 @@ describe("PricingModule Service - PriceSet", () => {
error = e
}
expect(error.message).toEqual('"priceSetId" must be defined')
expect(error.message).toEqual("priceSet - id must be defined")
})
it("should return priceSet based on config select param", async () => {
@@ -170,7 +170,7 @@ describe("PricingModuleService ruleType", () => {
error = e
}
expect(error.message).toEqual('"ruleTypeId" must be defined')
expect(error.message).toEqual("ruleType - id must be defined")
})
it("should return ruleType based on config select param", async () => {
@@ -164,7 +164,7 @@ describe("RuleType Service", () => {
error = e
}
expect(error.message).toEqual('"ruleTypeId" must be defined')
expect(error.message).toEqual("ruleType - id must be defined")
})
it("should return ruleType based on config select param", async () => {
@@ -1,6 +1,5 @@
import { Currency } from "@models"
import { CurrencyService } from "@services"
import { asClass, asValue, createContainer } from "awilix"
import { asValue } from "awilix"
;(Currency as any).meta = {
/**
@@ -10,10 +9,7 @@ import { asClass, asValue, createContainer } from "awilix"
}
export const nonExistingCurrencyCode = "non-existing-code"
export const mockContainer = createContainer()
mockContainer.register({
transaction: asValue(async (task) => await task()),
export const currencyRepositoryMock = {
currencyRepository: asValue({
find: jest.fn().mockImplementation(async ({ where: { code } }) => {
if (code === nonExistingCurrencyCode) {
@@ -25,5 +21,4 @@ mockContainer.register({
findAndCount: jest.fn().mockResolvedValue([[], 0]),
getFreshManager: jest.fn().mockResolvedValue({}),
}),
currencyService: asClass(CurrencyService),
})
}
@@ -1,18 +1,31 @@
import {
mockContainer,
currencyRepositoryMock,
nonExistingCurrencyCode,
} from "../__fixtures__/currency"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
import ContainerLoader from "../../loaders/container"
import { MedusaContainer } from "@medusajs/types"
const code = "existing-currency"
describe("Currency service", function () {
beforeEach(function () {
let container: MedusaContainer
beforeEach(async function () {
jest.clearAllMocks()
container = createMedusaContainer()
container.register("manager", asValue({}))
await ContainerLoader({ container })
container.register(currencyRepositoryMock)
})
it("should retrieve a currency", async function () {
const currencyService = mockContainer.resolve("currencyService")
const currencyRepository = mockContainer.resolve("currencyRepository")
const currencyService = container.resolve("currencyService")
const currencyRepository = container.resolve("currencyRepository")
await currencyService.retrieve(code)
@@ -33,8 +46,8 @@ describe("Currency service", function () {
})
it("should fail to retrieve a currency", async function () {
const currencyService = mockContainer.resolve("currencyService")
const currencyRepository = mockContainer.resolve("currencyRepository")
const currencyService = container.resolve("currencyService")
const currencyRepository = container.resolve("currencyRepository")
const err = await currencyService
.retrieve(nonExistingCurrencyCode)
@@ -62,8 +75,8 @@ describe("Currency service", function () {
})
it("should list currencys", async function () {
const currencyService = mockContainer.resolve("currencyService")
const currencyRepository = mockContainer.resolve("currencyRepository")
const currencyService = container.resolve("currencyService")
const currencyRepository = container.resolve("currencyRepository")
const filters = {}
const config = {
@@ -88,8 +101,8 @@ describe("Currency service", function () {
})
it("should list currencys with filters", async function () {
const currencyService = mockContainer.resolve("currencyService")
const currencyRepository = mockContainer.resolve("currencyRepository")
const currencyService = container.resolve("currencyService")
const currencyRepository = container.resolve("currencyRepository")
const filters = {
tags: {
@@ -126,8 +139,8 @@ describe("Currency service", function () {
})
it("should list currencys with filters and relations", async function () {
const currencyService = mockContainer.resolve("currencyService")
const currencyRepository = mockContainer.resolve("currencyRepository")
const currencyService = container.resolve("currencyService")
const currencyRepository = container.resolve("currencyRepository")
const filters = {
tags: {
@@ -163,9 +176,9 @@ describe("Currency service", function () {
)
})
it("should list and count the currencys with filters and relations", async function () {
const currencyService = mockContainer.resolve("currencyService")
const currencyRepository = mockContainer.resolve("currencyRepository")
it("should list and count the currencies with filters and relations", async function () {
const currencyService = container.resolve("currencyService")
const currencyRepository = container.resolve("currencyRepository")
const filters = {
tags: {
-23
View File
@@ -1,23 +0,0 @@
import { DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { Currency } from "@models"
import { ServiceTypes } from "@types"
type InjectedDependencies = {
currencyRepository: DAL.RepositoryService
}
export default class CurrencyService<
TEntity extends Currency = Currency
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: ServiceTypes.CreateCurrencyDTO
update: ServiceTypes.UpdateCurrencyDTO
}
>(Currency)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
}
-6
View File
@@ -1,12 +1,6 @@
export { default as CurrencyService } from "./currency"
export { default as MoneyAmountService } from "./money-amount"
export { default as PriceListService } from "./price-list"
export { default as PriceListRuleService } from "./price-list-rule"
export { default as PriceListRuleValueService } from "./price-list-rule-value"
export { default as PriceRuleService } from "./price-rule"
export { default as PriceSetService } from "./price-set"
export { default as PriceSetMoneyAmountService } from "./price-set-money-amount"
export { default as PriceSetMoneyAmountRulesService } from "./price-set-money-amount-rules"
export { default as PriceSetRuleTypeService } from "./price-set-rule-type"
export { default as PricingModuleService } from "./pricing-module"
export { default as RuleTypeService } from "./rule-type"
@@ -1,27 +0,0 @@
import { DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { MoneyAmount } from "@models"
import { ServiceTypes } from "@types"
type InjectedDependencies = {
moneyAmountRepository: DAL.RepositoryService
}
export default class MoneyAmountService<
TEntity extends MoneyAmount = MoneyAmount
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: ServiceTypes.CreateMoneyAmountDTO
update: ServiceTypes.UpdateMoneyAmountDTO
},
{
list: ServiceTypes.FilterableMoneyAmountProps
listAndCount: ServiceTypes.FilterableMoneyAmountProps
}
>(MoneyAmount)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
}
@@ -9,26 +9,32 @@ type InjectedDependencies = {
export default class PriceListRuleValueService<
TEntity extends PriceListRuleValue = PriceListRuleValue
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
update: ServiceTypes.UpdatePriceListRuleValueDTO
},
{
list: ServiceTypes.FilterablePriceListRuleValueProps
listAndCount: ServiceTypes.FilterablePriceListRuleValueProps
}
>(PriceListRuleValue)<TEntity> {
> extends ModulesSdkUtils.internalModuleServiceFactory<InjectedDependencies>(
PriceListRuleValue
)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
async create(
create(
data: ServiceTypes.CreatePriceListRuleValueDTO[],
context: Context
): Promise<TEntity[]>
create(
data: ServiceTypes.CreatePriceListRuleValueDTO,
context: Context
): Promise<TEntity>
async create(
data:
| ServiceTypes.CreatePriceListRuleValueDTO
| ServiceTypes.CreatePriceListRuleValueDTO[],
context: Context = {}
): Promise<TEntity[]> {
const priceListRuleValues = data.map((priceRuleValueData) => {
): Promise<TEntity | TEntity[]> {
const data_ = Array.isArray(data) ? data : [data]
const priceListRuleValues = data_.map((priceRuleValueData) => {
const { price_list_rule_id: priceListRuleId, ...priceRuleValue } =
priceRuleValueData
@@ -9,27 +9,31 @@ type InjectedDependencies = {
export default class PriceListRuleService<
TEntity extends PriceListRule = PriceListRule
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: ServiceTypes.CreatePriceListRuleDTO
update: ServiceTypes.UpdatePriceListRuleDTO
},
{
list: ServiceTypes.FilterablePriceListRuleProps
listAndCount: ServiceTypes.FilterablePriceListRuleProps
}
>(PriceListRule)<TEntity> {
> extends ModulesSdkUtils.internalModuleServiceFactory<InjectedDependencies>(
PriceListRule
)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
async create(
create(
data: ServiceTypes.CreatePriceListRuleDTO[],
sharedContext?: Context
): Promise<TEntity[]>
create(
data: ServiceTypes.CreatePriceListRuleDTO,
sharedContext?: Context
): Promise<TEntity>
async create(
data:
| ServiceTypes.CreatePriceListRuleDTO
| ServiceTypes.CreatePriceListRuleDTO[],
context: Context = {}
): Promise<TEntity[]> {
const priceListRule = data.map((priceListRule) => {
): Promise<TEntity | TEntity[]> {
const data_ = Array.isArray(data) ? data : [data]
const priceListRule = data_.map((priceListRule) => {
const {
price_list_id: priceListId,
rule_type_id: ruleTypeId,
@@ -50,11 +54,28 @@ export default class PriceListRuleService<
return await super.create(priceListRule, context)
}
async update(
// @ts-ignore
update(
data: ServiceTypes.UpdatePriceListRuleDTO[],
context: Context
): Promise<TEntity[]>
// @ts-ignore
update(
data: ServiceTypes.UpdatePriceListRuleDTO,
context: Context
): Promise<TEntity>
// TODO add support for selector? and then rm ts ignore
// @ts-ignore
async update(
data:
| ServiceTypes.UpdatePriceListRuleDTO
| ServiceTypes.UpdatePriceListRuleDTO[],
context: Context = {}
): Promise<TEntity[]> {
const priceListRules = data.map((priceListRule) => {
): Promise<TEntity | TEntity[]> {
const data_ = Array.isArray(data) ? data : [data]
const priceListRules = data_.map((priceListRule) => {
const { price_list_id, rule_type_id, ...priceListRuleData } =
priceListRule
+27 -14
View File
@@ -9,32 +9,45 @@ type InjectedDependencies = {
export default class PriceListService<
TEntity extends PriceList = PriceList
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{},
{
list: ServiceTypes.FilterablePriceListProps
listAndCount: ServiceTypes.FilterablePriceListProps
}
>(PriceList)<TEntity> {
> extends ModulesSdkUtils.internalModuleServiceFactory<InjectedDependencies>(
PriceList
)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
async create(
create(
data: ServiceTypes.CreatePriceListDTO[],
sharedContext?: Context
): Promise<TEntity[]> {
const priceLists = this.normalizePriceListDate(data)
): Promise<TEntity[]>
create(
data: ServiceTypes.CreatePriceListDTO,
sharedContext?: Context
): Promise<TEntity>
async create(
data: ServiceTypes.CreatePriceListDTO | ServiceTypes.CreatePriceListDTO[],
sharedContext?: Context
): Promise<TEntity | TEntity[]> {
const data_ = Array.isArray(data) ? data : [data]
const priceLists = this.normalizePriceListDate(data_)
return await super.create(priceLists, sharedContext)
}
// @ts-ignore
update(data: any[], sharedContext?: Context): Promise<TEntity[]>
// @ts-ignore
update(data: any, sharedContext?: Context): Promise<TEntity>
// TODO: Add support for selector? and then rm ts ignore
// @ts-ignore
async update(
data: ServiceTypes.UpdatePriceListDTO[],
data: ServiceTypes.UpdatePriceListDTO | ServiceTypes.UpdatePriceListDTO[],
sharedContext?: Context
): Promise<TEntity[]> {
const priceLists = this.normalizePriceListDate(data)
): Promise<TEntity | TEntity[]> {
const data_ = Array.isArray(data) ? data : [data]
const priceLists = this.normalizePriceListDate(data_)
return await super.update(priceLists, sharedContext)
}
+16 -13
View File
@@ -10,26 +10,29 @@ type InjectedDependencies = {
export default class PriceRuleService<
TEntity extends PriceRule = PriceRule
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
update: ServiceTypes.UpdatePriceRuleDTO
},
{
list: ServiceTypes.FilterablePriceRuleProps
listAndCount: ServiceTypes.FilterablePriceRuleProps
}
>(PriceRule)<TEntity> {
> extends ModulesSdkUtils.internalModuleServiceFactory<InjectedDependencies>(
PriceRule
)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
async create(
create(
data: ServiceTypes.CreatePriceRuleDTO[],
sharedContext?: Context
): Promise<TEntity[]> {
const toCreate = data.map((ruleData) => {
): Promise<TEntity[]>
create(
data: ServiceTypes.CreatePriceRuleDTO,
sharedContext?: Context
): Promise<TEntity>
async create(
data: ServiceTypes.CreatePriceRuleDTO | ServiceTypes.CreatePriceRuleDTO[],
sharedContext: Context = {}
): Promise<TEntity | TEntity[]> {
const data_ = Array.isArray(data) ? data : [data]
const toCreate = data_.map((ruleData) => {
const ruleDataClone = { ...ruleData } as any
ruleDataClone.rule_type ??= ruleData.rule_type_id
@@ -1,27 +0,0 @@
import { DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { PriceSetMoneyAmountRules } from "@models"
import { ServiceTypes } from "@types"
type InjectedDependencies = {
priceSetMoneyAmountRulesRepository: DAL.RepositoryService
}
export default class PriceSetMoneyAmountRulesService<
TEntity extends PriceSetMoneyAmountRules = PriceSetMoneyAmountRules
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: ServiceTypes.CreatePriceSetMoneyAmountRulesDTO
update: ServiceTypes.UpdatePriceSetMoneyAmountRulesDTO
},
{
list: ServiceTypes.FilterablePriceSetMoneyAmountRulesProps
listAndCount: ServiceTypes.FilterablePriceSetMoneyAmountRulesProps
}
>(PriceSetMoneyAmountRules)<TEntity> {
constructor({ priceSetMoneyAmountRulesRepository }: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
}
@@ -1,27 +0,0 @@
import { DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { PriceSetMoneyAmount } from "@models"
import { ServiceTypes } from "@types"
type InjectedDependencies = {
priceSetMoneyAmountRepository: DAL.RepositoryService
}
export default class PriceSetMoneyAmountService<
TEntity extends PriceSetMoneyAmount = PriceSetMoneyAmount
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: ServiceTypes.CreatePriceSetMoneyAmountDTO
update: ServiceTypes.UpdatePriceSetMoneyAmountDTO
},
{
list: ServiceTypes.FilterablePriceSetMoneyAmountProps
listAndCount: ServiceTypes.FilterablePriceSetMoneyAmountProps
}
>(PriceSetMoneyAmount)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
}
@@ -1,27 +0,0 @@
import { DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { PriceSetRuleType } from "@models"
import { ServiceTypes } from "@types"
type InjectedDependencies = {
priceSetRuleTypeRepository: DAL.RepositoryService
}
export default class PriceSetRuleTypeService<
TEntity extends PriceSetRuleType = PriceSetRuleType
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: ServiceTypes.CreatePriceSetRuleTypeDTO
update: ServiceTypes.UpdatePriceSetRuleTypeDTO
},
{
list: ServiceTypes.FilterablePriceSetRuleTypeProps
listAndCount: ServiceTypes.FilterablePriceSetRuleTypeProps
}
>(PriceSetRuleType)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
}
@@ -1,28 +0,0 @@
import { DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { PriceSet } from "@models"
import { ServiceTypes } from "@types"
type InjectedDependencies = {
priceSetRepository: DAL.RepositoryService
}
export default class PriceSetService<
TEntity extends PriceSet = PriceSet
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: Omit<ServiceTypes.CreatePriceSetDTO, "rules">
update: Omit<ServiceTypes.UpdatePriceSetDTO, "rules">
},
{
list: ServiceTypes.FilterablePriceSetProps
listAndCount: ServiceTypes.FilterablePriceSetProps
}
>(PriceSet)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
}
File diff suppressed because it is too large Load Diff
+39 -23
View File
@@ -14,17 +14,9 @@ type InjectedDependencies = {
export default class RuleTypeService<
TEntity extends RuleType = RuleType
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: ServiceTypes.CreateRuleTypeDTO
update: ServiceTypes.UpdateRuleTypeDTO
},
{
list: ServiceTypes.FilterableRuleTypeProps
listAndCount: ServiceTypes.FilterableRuleTypeProps
}
>(RuleType)<TEntity> {
> extends ModulesSdkUtils.internalModuleServiceFactory<InjectedDependencies>(
RuleType
)<TEntity> {
protected readonly ruleTypeRepository_: DAL.RepositoryService<TEntity>
constructor({ ruleTypeRepository }: InjectedDependencies) {
@@ -33,21 +25,45 @@ export default class RuleTypeService<
this.ruleTypeRepository_ = ruleTypeRepository
}
@InjectTransactionManager("ruleTypeRepository_")
async create(
create(
data: ServiceTypes.CreateRuleTypeDTO,
sharedContext: Context
): Promise<TEntity>
create(
data: ServiceTypes.CreateRuleTypeDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity[]> {
validateRuleAttributes(data.map((d) => d.rule_attribute))
return await this.ruleTypeRepository_.create(data, sharedContext)
}
sharedContext: Context
): Promise<TEntity[]>
@InjectTransactionManager("ruleTypeRepository_")
async update(
data: ServiceTypes.UpdateRuleTypeDTO[],
async create(
data: ServiceTypes.CreateRuleTypeDTO | ServiceTypes.CreateRuleTypeDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity[]> {
validateRuleAttributes(data.map((d) => d.rule_attribute))
return await this.ruleTypeRepository_.update(data, sharedContext)
): Promise<TEntity | TEntity[]> {
const data_ = Array.isArray(data) ? data : [data]
validateRuleAttributes(data_.map((d) => d.rule_attribute))
return await super.create(data, sharedContext)
}
// @ts-ignore
update(
data: ServiceTypes.UpdateRuleTypeDTO[],
sharedContext: Context
): Promise<TEntity[]>
// @ts-ignore
update(
data: ServiceTypes.UpdateRuleTypeDTO,
sharedContext: Context
): Promise<TEntity>
@InjectTransactionManager("ruleTypeRepository_")
// TODO: add support for selector? and then rm ts ignore
// @ts-ignore
async update(
data: ServiceTypes.UpdateRuleTypeDTO | ServiceTypes.UpdateRuleTypeDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity | TEntity[]> {
const data_ = Array.isArray(data) ? data : [data]
validateRuleAttributes(data_.map((d) => d.rule_attribute))
return await super.update(data, sharedContext)
}
}
@@ -1,44 +1,3 @@
import {
Currency,
MoneyAmount,
PriceList,
PriceListRule,
PriceListRuleValue,
PriceRule,
PriceSet,
PriceSetMoneyAmount,
PriceSetMoneyAmountRules,
PriceSetRuleType,
RuleType,
} from "@models"
import { DAL } from "@medusajs/types"
import { CreateCurrencyDTO, UpdateCurrencyDTO } from "./currency"
import { CreateMoneyAmountDTO, UpdateMoneyAmountDTO } from "./money-amount"
import {
CreatePriceListRuleValueDTO,
UpdatePriceListRuleValueDTO,
} from "./price-list-rule-value"
import {
CreatePriceListRuleDTO,
UpdatePriceListRuleDTO,
} from "./price-list-rule"
import { CreatePriceListDTO, UpdatePriceListDTO } from "./price-list"
import { CreatePriceRuleDTO, UpdatePriceRuleDTO } from "./price-rule"
import {
CreatePriceSetMoneyAmountRulesDTO,
UpdatePriceSetMoneyAmountRulesDTO,
} from "./price-set-money-amount-rules"
import {
CreatePriceSetMoneyAmountDTO,
UpdatePriceSetMoneyAmountDTO,
} from "./price-set-money-amount"
import {
CreatePriceSetRuleTypeDTO,
UpdatePriceSetRuleTypeDTO,
} from "./price-set-rule-type"
import { CreatePriceSetDTO, UpdatePriceSetDTO } from "./price-set"
import { CreateRuleTypeDTO, UpdateRuleTypeDTO } from "./rule-type"
export * from "./currency"
export * from "./money-amount"
export * from "./price-list-rule-value"
@@ -50,119 +9,3 @@ export * from "./price-set-money-amount"
export * from "./price-set-rule-type"
export * from "./price-set"
export * from "./rule-type"
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface ICurrencyRepository<TEntity extends Currency = Currency>
extends DAL.RepositoryService<
TEntity,
{
create: CreateCurrencyDTO
update: UpdateCurrencyDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IMoneyAmountRepository<
TEntity extends MoneyAmount = MoneyAmount
> extends DAL.RepositoryService<
TEntity,
{
create: CreateMoneyAmountDTO
update: UpdateMoneyAmountDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IPriceListRuleValueRepository<
TEntity extends PriceListRuleValue = PriceListRuleValue
> extends DAL.RepositoryService<
TEntity,
{
create: CreatePriceListRuleValueDTO
update: UpdatePriceListRuleValueDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IPriceListRuleRepository<
TEntity extends PriceListRule = PriceListRule
> extends DAL.RepositoryService<
TEntity,
{
create: CreatePriceListRuleDTO
update: UpdatePriceListRuleDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IPriceListRepository<TEntity extends PriceList = PriceList>
extends DAL.RepositoryService<
TEntity,
{
create: CreatePriceListDTO
update: UpdatePriceListDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IPriceRuleRepository<TEntity extends PriceRule = PriceRule>
extends DAL.RepositoryService<
TEntity,
{
create: CreatePriceRuleDTO
update: UpdatePriceRuleDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IPriceSetMoneyAmountRulesRepository<
TEntity extends PriceSetMoneyAmountRules = PriceSetMoneyAmountRules
> extends DAL.RepositoryService<
TEntity,
{
create: CreatePriceSetMoneyAmountRulesDTO
update: UpdatePriceSetMoneyAmountRulesDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IPriceSetMoneyAmountRepository<
TEntity extends PriceSetMoneyAmount = PriceSetMoneyAmount
> extends DAL.RepositoryService<
TEntity,
{
create: CreatePriceSetMoneyAmountDTO
update: UpdatePriceSetMoneyAmountDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IPriceSetRuleTypeRepository<
TEntity extends PriceSetRuleType = PriceSetRuleType
> extends DAL.RepositoryService<
TEntity,
{
create: CreatePriceSetRuleTypeDTO
update: UpdatePriceSetRuleTypeDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IPriceSetRepository<TEntity extends PriceSet = PriceSet>
extends DAL.RepositoryService<
TEntity,
{
create: CreatePriceSetDTO
update: UpdatePriceSetDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IRuleTypeRepository<TEntity extends RuleType = RuleType>
extends DAL.RepositoryService<
TEntity,
{
create: CreateRuleTypeDTO
update: UpdateRuleTypeDTO
}
> {}
@@ -240,7 +240,7 @@ describe("Product collection Service", () => {
error = e
}
expect(error.message).toEqual('"productCollectionId" must be defined')
expect(error.message).toEqual("productCollection - id must be defined")
})
it("should return collection based on config select param", async () => {
@@ -796,7 +796,23 @@ describe("ProductModuleService products", function () {
const products = await module.create([data])
let retrievedProducts = await module.list({ id: products[0].id })
expect(retrievedProducts).toHaveLength(1)
expect(retrievedProducts[0].deleted_at).toBeNull()
await module.softDelete([products[0].id])
retrievedProducts = await module.list(
{ id: products[0].id },
{
withDeleted: true,
}
)
expect(retrievedProducts).toHaveLength(1)
expect(retrievedProducts[0].deleted_at).not.toBeNull()
await module.restore([products[0].id])
const deletedProducts = await module.list(
@@ -205,7 +205,7 @@ describe("ProductOption Service", () => {
error = e
}
expect(error.message).toEqual('"productOptionId" must be defined')
expect(error.message).toEqual("productOption - id must be defined")
})
it("should return option based on config select param", async () => {
@@ -237,7 +237,7 @@ describe("ProductTag Service", () => {
error = e
}
expect(error.message).toEqual('"productTagId" must be defined')
expect(error.message).toEqual("productTag - id must be defined")
})
it("should return tag based on config select param", async () => {
@@ -199,7 +199,7 @@ describe("ProductType Service", () => {
error = e
}
expect(error.message).toEqual('"productTypeId" must be defined')
expect(error.message).toEqual("productType - id must be defined")
})
it("should return type based on config select param", async () => {
@@ -320,7 +320,7 @@ describe("ProductVariant Service", () => {
error = e
}
expect(error.message).toEqual('"productVariantId" must be defined')
expect(error.message).toEqual("productVariant - id must be defined")
})
})
})
@@ -78,7 +78,7 @@ describe("Product Service", () => {
error = e
}
expect(error.message).toEqual('"productId" must be defined')
expect(error.message).toEqual("product - id must be defined")
})
it("should throw an error when product with id does not exist", async () => {
@@ -217,7 +217,7 @@ describe("Product Service", () => {
error = e
}
expect(error.message).toEqual(`Product with id "undefined" not found`)
expect(error.message).toEqual(`Product with id "" not found`)
let result = await service.retrieve(productOne.id)
+1 -1
View File
@@ -144,7 +144,7 @@ class Product {
@ManyToMany(() => ProductCategory, "products", {
owner: true,
pivotTable: "product_category_product",
cascade: ["soft-remove"] as any,
// TODO: rm cascade: ["soft-remove"] as any,
})
categories = new Collection<ProductCategory>(this)
@@ -14,6 +14,6 @@ export class ProductImageRepository extends DALUtils.mikroOrmBaseRepositoryFacto
async upsert(urls: string[], context: Context = {}): Promise<Image[]> {
const data = urls.map((url) => ({ url }))
return await super.upsert(data, context)
return (await super.upsert(data, context)) as Image[]
}
}
+8 -15
View File
@@ -17,8 +17,8 @@ import {
DALUtils,
isDefined,
MedusaError,
promiseAll,
ProductUtils,
promiseAll,
} from "@medusajs/utils"
import { ProductServiceTypes } from "../types/services"
@@ -118,7 +118,10 @@ export class ProductRepository extends DALUtils.mikroOrmBaseRepositoryFactory<Pr
}
async update(
data: WithRequiredProperty<ProductServiceTypes.UpdateProductDTO, "id">[],
data: {
entity: Product
update: WithRequiredProperty<ProductServiceTypes.UpdateProductDTO, "id">
}[],
context: Context = {}
): Promise<Product[]> {
let categoryIds: string[] = []
@@ -128,7 +131,7 @@ export class ProductRepository extends DALUtils.mikroOrmBaseRepositoryFactory<Pr
// TODO: use the getter method (getActiveManager)
const manager = this.getActiveManager<SqlEntityManager>(context)
data.forEach((productData) => {
data.forEach(({ update: productData }) => {
categoryIds = categoryIds.concat(
productData?.categories?.map((c) => c.id) || []
)
@@ -144,16 +147,6 @@ export class ProductRepository extends DALUtils.mikroOrmBaseRepositoryFactory<Pr
}
})
const productsToUpdate = await manager.find(
Product,
{
id: data.map((updateData) => updateData.id),
},
{
populate: ["tags", "categories"],
}
)
const collectionsToAssign = collectionIds.length
? await manager.find(ProductCollection, {
id: collectionIds,
@@ -195,11 +188,11 @@ export class ProductRepository extends DALUtils.mikroOrmBaseRepositoryFactory<Pr
)
const productsToUpdateMap = new Map<string, Product>(
productsToUpdate.map((product) => [product.id, product])
data.map(({ entity }) => [entity.id, entity])
)
const products = await promiseAll(
data.map(async (updateData) => {
data.map(async ({ update: updateData }) => {
const product = productsToUpdateMap.get(updateData.id)
if (!product) {
@@ -1,11 +1,8 @@
import { asClass, asValue, createContainer } from "awilix"
import { ProductService } from "@services"
import { asValue } from "awilix"
export const nonExistingProductId = "non-existing-id"
export const mockContainer = createContainer()
mockContainer.register({
transaction: asValue(async (task) => await task()),
export const productRepositoryMock = {
productRepository: asValue({
find: jest.fn().mockImplementation(async ({ where: { id } }) => {
if (id === nonExistingProductId) {
@@ -17,5 +14,4 @@ mockContainer.register({
findAndCount: jest.fn().mockResolvedValue([[], 0]),
getFreshManager: jest.fn().mockResolvedValue({}),
}),
productService: asClass(ProductService),
})
}
@@ -1,13 +1,28 @@
import { mockContainer, nonExistingProductId } from "../__fixtures__/product"
import {
nonExistingProductId,
productRepositoryMock,
} from "../__fixtures__/product"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
import ContainerLoader from "../../loaders/container"
describe("Product service", function () {
beforeEach(function () {
let container
beforeEach(async function () {
jest.clearAllMocks()
container = createMedusaContainer()
container.register("manager", asValue({}))
await ContainerLoader({ container })
container.register(productRepositoryMock)
})
it("should retrieve a product", async function () {
const productService = mockContainer.resolve("productService")
const productRepository = mockContainer.resolve("productRepository")
const productService = container.resolve("productService")
const productRepository = container.resolve("productRepository")
const productId = "existing-product"
await productService.retrieve(productId)
@@ -30,8 +45,8 @@ describe("Product service", function () {
})
it("should fail to retrieve a product", async function () {
const productService = mockContainer.resolve("productService")
const productRepository = mockContainer.resolve("productRepository")
const productService = container.resolve("productService")
const productRepository = container.resolve("productRepository")
const err = await productService
.retrieve(nonExistingProductId)
@@ -59,8 +74,8 @@ describe("Product service", function () {
})
it("should list products", async function () {
const productService = mockContainer.resolve("productService")
const productRepository = mockContainer.resolve("productRepository")
const productService = container.resolve("productService")
const productRepository = container.resolve("productRepository")
const filters = {}
const config = {
@@ -85,8 +100,8 @@ describe("Product service", function () {
})
it("should list products with filters", async function () {
const productService = mockContainer.resolve("productService")
const productRepository = mockContainer.resolve("productRepository")
const productService = container.resolve("productService")
const productRepository = container.resolve("productRepository")
const filters = {
tags: {
@@ -123,8 +138,8 @@ describe("Product service", function () {
})
it("should list products with filters and relations", async function () {
const productService = mockContainer.resolve("productService")
const productRepository = mockContainer.resolve("productRepository")
const productService = container.resolve("productService")
const productRepository = container.resolve("productRepository")
const filters = {
tags: {
@@ -161,8 +176,8 @@ describe("Product service", function () {
})
it("should list and count the products with filters and relations", async function () {
const productService = mockContainer.resolve("productService")
const productRepository = mockContainer.resolve("productRepository")
const productService = container.resolve("productService")
const productRepository = container.resolve("productRepository")
const filters = {
tags: {
-2
View File
@@ -6,5 +6,3 @@ export { default as ProductTagService } from "./product-tag"
export { default as ProductVariantService } from "./product-variant"
export { default as ProductTypeService } from "./product-type"
export { default as ProductOptionService } from "./product-option"
export { default as ProductImageService } from "./product-image"
export { default as ProductOptionValueService } from "./product-option-value"
@@ -7,14 +7,7 @@ import {
} from "@medusajs/utils"
import { ProductCollection } from "@models"
import {
IProductCollectionRepository,
ProductCollectionServiceTypes,
} from "@types"
import {
CreateProductCollection,
UpdateProductCollection,
} from "../types/services/product-collection"
import { ProductCollectionServiceTypes } from "@types"
type InjectedDependencies = {
productCollectionRepository: DAL.RepositoryService
@@ -22,15 +15,11 @@ type InjectedDependencies = {
export default class ProductCollectionService<
TEntity extends ProductCollection = ProductCollection
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: CreateProductCollection
update: UpdateProductCollection
}
>(ProductCollection)<TEntity> {
> extends ModulesSdkUtils.internalModuleServiceFactory<InjectedDependencies>(
ProductCollection
)<TEntity> {
// eslint-disable-next-line max-len
protected readonly productCollectionRepository_: IProductCollectionRepository<TEntity>
protected readonly productCollectionRepository_: DAL.RepositoryService<TEntity>
constructor(container: InjectedDependencies) {
super(container)
@@ -38,9 +27,9 @@ export default class ProductCollectionService<
}
@InjectManager("productCollectionRepository_")
async list<TEntityMethod = ProductTypes.ProductCollectionDTO>(
async list(
filters: ProductTypes.FilterableProductCollectionProps = {},
config: FindConfig<TEntityMethod> = {},
config: FindConfig<TEntity> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity[]> {
return await this.productCollectionRepository_.find(
@@ -50,9 +39,9 @@ export default class ProductCollectionService<
}
@InjectManager("productCollectionRepository_")
async listAndCount<TEntityMethod = ProductTypes.ProductCollectionDTO>(
async listAndCount(
filters: ProductTypes.FilterableProductCollectionProps = {},
config: FindConfig<TEntityMethod> = {},
config: FindConfig<TEntity> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<[TEntity[], number]> {
return await this.productCollectionRepository_.findAndCount(
@@ -61,11 +50,9 @@ export default class ProductCollectionService<
)
}
protected buildListQueryOptions<
TEntityMethod = ProductTypes.ProductCollectionDTO
>(
protected buildListQueryOptions(
filters: ProductTypes.FilterableProductCollectionProps = {},
config: FindConfig<TEntityMethod> = {}
config: FindConfig<TEntity> = {}
): DAL.FindOptions<TEntity> {
const queryOptions = ModulesSdkUtils.buildQuery<TEntity>(filters, config)
@@ -80,12 +67,24 @@ export default class ProductCollectionService<
return queryOptions
}
create(
data: ProductCollectionServiceTypes.CreateProductCollection,
context?: Context
): Promise<TEntity>
create(
data: ProductCollectionServiceTypes.CreateProductCollection[],
context?: Context
): Promise<TEntity[]>
@InjectTransactionManager("productCollectionRepository_")
async create(
data: ProductCollectionServiceTypes.CreateProductCollection[],
data:
| ProductCollectionServiceTypes.CreateProductCollection
| ProductCollectionServiceTypes.CreateProductCollection[],
context: Context = {}
): Promise<TEntity[]> {
const productCollections = data.map((collectionData) => {
): Promise<TEntity | TEntity[]> {
const data_ = Array.isArray(data) ? data : [data]
const productCollections = data_.map((collectionData) => {
if (collectionData.product_ids) {
collectionData.products = collectionData.product_ids
@@ -98,12 +97,27 @@ export default class ProductCollectionService<
return super.create(productCollections, context)
}
@InjectTransactionManager("productCollectionRepository_")
async update(
// @ts-ignore
update(
data: ProductCollectionServiceTypes.UpdateProductCollection,
context?: Context
): Promise<TEntity>
// @ts-ignore
update(
data: ProductCollectionServiceTypes.UpdateProductCollection[],
context?: Context
): Promise<TEntity[]>
@InjectTransactionManager("productCollectionRepository_")
// @ts-ignore Do not implement all the expected overloads, see if we must do it
async update(
data:
| ProductCollectionServiceTypes.UpdateProductCollection
| ProductCollectionServiceTypes.UpdateProductCollection[],
context: Context = {}
): Promise<TEntity[]> {
const productCollections = data.map((collectionData) => {
): Promise<TEntity | TEntity[]> {
const data_ = Array.isArray(data) ? data : [data]
const productCollections = data_.map((collectionData) => {
if (collectionData.product_ids) {
collectionData.products = collectionData.product_ids
@@ -1,18 +0,0 @@
import { Image } from "@models"
import { DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
type InjectedDependencies = {
productImageRepository: DAL.RepositoryService
}
export default class ProductImageService<
TEntity extends Image = Image
> extends ModulesSdkUtils.abstractServiceFactory<InjectedDependencies>(
Image
)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
}

Some files were not shown because too many files have changed in this diff Show More