chore: Update modules providers configuration with 'identifier' and 'PROVIDER' (#9636)

* chore: Update modules providers configuration with 'identifier' and 'PROVIDER'

* update check

* fix tests

* type

* normalize auth provider

* emailpass

* providers

---------

Co-authored-by: Carlos R. L. Rodrigues <rodrigolr@gmail.com>
Co-authored-by: Carlos R. L. Rodrigues <37986729+carlos-r-l-rodrigues@users.noreply.github.com>
This commit is contained in:
authored and GitHub committed 2024-10-18 09:24:15 +02:00
1 parent 902ac12f73
commit 876d8072e7
22 files changed
+131 -67

No files matched your search

@@ -1 +1,3 @@
export class ModuleProvider2Service {} export class ModuleProvider2Service {
static identifier = "provider-2"
}
@@ -1,5 +1,9 @@
import { IModuleService, ModuleResolution } from "@medusajs/types" import { IModuleService, ModuleResolution } from "@medusajs/types"
import { createMedusaContainer, upperCaseFirst } from "@medusajs/utils" import {
createMedusaContainer,
getProviderRegistrationKey,
upperCaseFirst,
} from "@medusajs/utils"
import { join } from "path" import { join } from "path"
import { import {
ModuleWithDmlMixedWithoutJoinerConfigFixtures, ModuleWithDmlMixedWithoutJoinerConfigFixtures,
@@ -10,11 +14,7 @@ import {
import { ModuleService as ModuleServiceWithProvider } from "../__fixtures__/module-with-providers" import { ModuleService as ModuleServiceWithProvider } from "../__fixtures__/module-with-providers"
import { ModuleProviderService as ModuleServiceWithProviderProvider1 } from "../__fixtures__/module-with-providers/provider-1" import { ModuleProviderService as ModuleServiceWithProviderProvider1 } from "../__fixtures__/module-with-providers/provider-1"
import { ModuleProvider2Service as ModuleServiceWithProviderProvider2 } from "../__fixtures__/module-with-providers/provider-2" import { ModuleProvider2Service as ModuleServiceWithProviderProvider2 } from "../__fixtures__/module-with-providers/provider-2"
import { import { loadInternalModule, loadResources } from "../load-internal"
getProviderRegistrationKey,
loadInternalModule,
loadResources,
} from "../load-internal"
describe("load internal", () => { describe("load internal", () => {
describe("loadResources", () => { describe("loadResources", () => {
@@ -376,9 +376,10 @@ describe("load internal", () => {
const moduleService = container.resolve(moduleResolution.definition.key) const moduleService = container.resolve(moduleResolution.definition.key)
const provider = (moduleService as any).container[ const provider = (moduleService as any).container[
getProviderRegistrationKey( getProviderRegistrationKey({
ModuleServiceWithProviderProvider1.identifier providerId: moduleResolution.options!.providers![0].id,
) providerIdentifier: ModuleServiceWithProviderProvider1.identifier,
})
] ]
expect(moduleService).toBeInstanceOf(ModuleServiceWithProvider) expect(moduleService).toBeInstanceOf(ModuleServiceWithProvider)
@@ -427,7 +428,10 @@ describe("load internal", () => {
const moduleService = container.resolve(moduleResolution.definition.key) const moduleService = container.resolve(moduleResolution.definition.key)
const provider = (moduleService as any).container[ const provider = (moduleService as any).container[
getProviderRegistrationKey(moduleResolution.options!.providers![0].id) getProviderRegistrationKey({
providerId: moduleResolution.options!.providers![0].id,
providerIdentifier: ModuleServiceWithProviderProvider2.identifier,
})
] ]
expect(moduleService).toBeInstanceOf(ModuleServiceWithProvider) expect(moduleService).toBeInstanceOf(ModuleServiceWithProvider)
@@ -18,6 +18,7 @@ import {
defineJoinerConfig, defineJoinerConfig,
DmlEntity, DmlEntity,
dynamicImport, dynamicImport,
getProviderRegistrationKey,
isString, isString,
MedusaModuleProviderType, MedusaModuleProviderType,
MedusaModuleType, MedusaModuleType,
@@ -51,17 +52,6 @@ type ResolvedModuleProvider = ModuleProviderExports & {
discoveryPath: string discoveryPath: string
} }
export const moduleProviderRegistrationKeyPrefix = "__providers__"
/**
* Return the key used to register a module provider in the container
* @param {string} moduleKey
* @return {string}
*/
export function getProviderRegistrationKey(moduleKey: string): string {
return moduleProviderRegistrationKeyPrefix + moduleKey
}
export async function resolveModuleExports({ export async function resolveModuleExports({
resolution, resolution,
}: { }: {
@@ -140,7 +130,7 @@ async function loadInternalProvider(
moduleExports: !isString(providerRes) ? providerRes : undefined, moduleExports: !isString(providerRes) ? providerRes : undefined,
definition: { definition: {
...resolution.definition, ...resolution.definition,
key: provider.id, key: provider.id!,
}, },
resolutionPath: isString(provider.resolve) resolutionPath: isString(provider.resolve)
? require.resolve(provider.resolve, { ? require.resolve(provider.resolve, {
@@ -321,13 +311,39 @@ export async function loadInternalModule(args: {
for (const moduleProviderService of moduleProviderServices) { for (const moduleProviderService of moduleProviderServices) {
const modProvider_ = moduleProviderService as any const modProvider_ = moduleProviderService as any
modProvider_.identifier ??= keyName const originalIdentifier = modProvider_.identifier as string
modProvider_.__type = MedusaModuleProviderType const providerId = keyName
const registrationKey = getProviderRegistrationKey(
modProvider_.identifier if (!originalIdentifier) {
const providerResolutionName =
modProvider_.DISPLAY_NAME ?? resolution.resolutionPath
throw new Error(
`Module provider ${providerResolutionName} does not have a static "identifier" property on its service class.`
) )
}
const alreadyRegisteredProvider = container.hasRegistration(
getProviderRegistrationKey({
providerId,
providerIdentifier: originalIdentifier,
})
)
if (alreadyRegisteredProvider) {
throw new Error(
`Module provider ${originalIdentifier} has already been registered. Please provide a different "id" in the provider options.`
)
}
modProvider_.__type = MedusaModuleProviderType
const registrationKey = getProviderRegistrationKey({
providerId,
providerIdentifier: originalIdentifier,
})
container.register({ container.register({
[registrationKey]: asFunction((cradle) => { [registrationKey]: asFunction(() => {
;(moduleProviderService as any).__type = MedusaModuleType ;(moduleProviderService as any).__type = MedusaModuleType
return new moduleProviderService( return new moduleProviderService(
localContainer.cradle, localContainer.cradle,
@@ -42,7 +42,7 @@ export type ModuleProviderLoaderFunction = (
export type ModuleProvider = { export type ModuleProvider = {
resolve: string | ModuleProviderExports<any> resolve: string | ModuleProviderExports<any>
id: string id?: string
options?: Record<string, unknown> options?: Record<string, unknown>
is_default?: boolean is_default?: boolean
} }
@@ -69,22 +69,32 @@ export abstract class AbstractAuthModuleProvider implements IAuthProvider {
/** /**
* @ignore * @ignore
*/ */
private static PROVIDER: string static identifier: string
/** /**
* @ignore * @ignore
*/ */
private static DISPLAY_NAME: string static DISPLAY_NAME: string
/** /**
* @ignore * @ignore
*/ */
protected readonly container_: any protected readonly container_: any
/** /**
* @deprecated Use `identifier` instead.
* @ignore * @ignore
*/ */
public get provider() { public get provider() {
return (this.constructor as typeof AbstractAuthModuleProvider).PROVIDER return (this.constructor as typeof AbstractAuthModuleProvider).identifier
} }
/**
* @ignore
*/
public get identifier() {
return (this.constructor as typeof AbstractAuthModuleProvider).identifier
}
/** /**
* @ignore * @ignore
*/ */
@@ -98,21 +108,6 @@ export abstract class AbstractAuthModuleProvider implements IAuthProvider {
*/ */
static validateOptions(options: Record<any, any>): void | never {} static validateOptions(options: Record<any, any>): void | never {}
/**
* @ignore
*
* @privateRemarks
* Documenting the constructor in the class's TSDocs as it's difficult to relay
* the necessary information with this constructor's signature.
*/
protected constructor({}, config: { provider: string; displayName: string }) {
this.container_ = arguments[0]
;(this.constructor as typeof AbstractAuthModuleProvider).PROVIDER ??=
config.provider
;(this.constructor as typeof AbstractAuthModuleProvider).DISPLAY_NAME ??=
config.displayName
}
/** /**
* This method authenticates the user. * This method authenticates the user.
* *
@@ -19,3 +19,4 @@ export * from "./module-provider"
export * from "./query-context" export * from "./query-context"
export * from "./types/links-config" export * from "./types/links-config"
export * from "./types/medusa-service" export * from "./types/medusa-service"
export * from "./module-provider-registration-key"
@@ -0,0 +1,19 @@
export const moduleProviderRegistrationKeyPrefix = "__providers__"
/**
* Return the key used to register a module provider in the container
* @param {string} moduleKey
* @return {string}
*/
export function getProviderRegistrationKey({
providerId,
providerIdentifier,
}: {
providerId?: string
providerIdentifier?: string
}): string {
const registrationIdentifier = `${
providerIdentifier ? providerIdentifier : ""
}${providerId ? `${providerIdentifier ? "_" : ""}${providerId}` : ""}`
return moduleProviderRegistrationKeyPrefix + registrationIdentifier
}
@@ -10,6 +10,8 @@ import {
} from "@medusajs/framework/utils" } from "@medusajs/framework/utils"
export class AuthServiceFixtures extends AbstractAuthModuleProvider { export class AuthServiceFixtures extends AbstractAuthModuleProvider {
static identifier = "plaintextpass"
constructor() { constructor() {
super( super(
{}, {},
@@ -4,7 +4,10 @@ import {
ModuleProvider, ModuleProvider,
ModulesSdkTypes, ModulesSdkTypes,
} from "@medusajs/framework/types" } from "@medusajs/framework/types"
import { ContainerRegistrationKeys } from "@medusajs/framework/utils" import {
ContainerRegistrationKeys,
getProviderRegistrationKey,
} from "@medusajs/framework/utils"
import { LockingProviderService } from "@services" import { LockingProviderService } from "@services"
import { import {
LockingDefaultProvider, LockingDefaultProvider,
@@ -14,10 +17,20 @@ import {
import { Lifetime, aliasTo, asFunction, asValue } from "awilix" import { Lifetime, aliasTo, asFunction, asValue } from "awilix"
import { InMemoryLockingProvider } from "../providers/in-memory" import { InMemoryLockingProvider } from "../providers/in-memory"
const registrationFn = async (klass, container) => { const registrationFn = async (klass, container, { id }) => {
const key = LockingProviderService.getRegistrationIdentifier(klass) const key = LockingProviderService.getRegistrationIdentifier(klass)
if (!id) {
throw new Error(`No "id" provided for provider ${key}`)
}
const regKey = getProviderRegistrationKey({
providerId: id,
providerIdentifier: key,
})
container.register({ container.register({
[LockingProviderRegistrationPrefix + key]: aliasTo("__providers__" + key), [LockingProviderRegistrationPrefix + key]: aliasTo(regKey),
}) })
container.registerAdd(LockingIdentifiersRegistrationName, asValue(key)) container.registerAdd(LockingIdentifiersRegistrationName, asValue(key))
@@ -5,7 +5,7 @@ import {
ModuleProvider, ModuleProvider,
ModulesSdkTypes, ModulesSdkTypes,
} from "@medusajs/framework/types" } from "@medusajs/framework/types"
import { Lifetime, asFunction, asValue } from "awilix" import { asFunction, asValue, Lifetime } from "awilix"
import { MedusaError } from "@medusajs/framework/utils" import { MedusaError } from "@medusajs/framework/utils"
import { PaymentProviderService } from "@services" import { PaymentProviderService } from "@services"
@@ -14,14 +14,16 @@ import * as providers from "../providers"
const PROVIDER_REGISTRATION_KEY = "payment_providers" const PROVIDER_REGISTRATION_KEY = "payment_providers"
const registrationFn = async (klass, container, pluginOptions) => { const registrationFn = async (klass, container, pluginOptions) => {
if (!klass?.PROVIDER) { if (!klass?.identifier) {
throw new MedusaError( throw new MedusaError(
MedusaError.Types.INVALID_ARGUMENT, MedusaError.Types.INVALID_ARGUMENT,
`Trying to register a payment provider without a provider identifier.` `Trying to register a payment provider without a provider identifier.`
) )
} }
const key = `pp_${klass.PROVIDER}_${pluginOptions.id}` const key = `pp_${klass.identifier}${
pluginOptions.id ? `_${pluginOptions.id}` : ""
}`
container.register({ container.register({
[key]: asFunction((cradle) => new klass(cradle, pluginOptions.options), { [key]: asFunction((cradle) => new klass(cradle, pluginOptions.options), {
@@ -13,7 +13,6 @@ import {
export class SystemProviderService extends AbstractPaymentProvider { export class SystemProviderService extends AbstractPaymentProvider {
static identifier = "system" static identifier = "system"
static PROVIDER = "system"
async getStatus(_): Promise<string> { async getStatus(_): Promise<string> {
return "authorized" return "authorized"
@@ -20,6 +20,9 @@ type InjectedDependencies = {
interface LocalServiceConfig extends EmailPassAuthProviderOptions {} interface LocalServiceConfig extends EmailPassAuthProviderOptions {}
export class EmailPassAuthService extends AbstractAuthModuleProvider { export class EmailPassAuthService extends AbstractAuthModuleProvider {
static identifier = "emailpass"
static DISPLAY_NAME = "Email/Password Authentication"
protected config_: LocalServiceConfig protected config_: LocalServiceConfig
protected logger_: Logger protected logger_: Logger
@@ -27,10 +30,8 @@ export class EmailPassAuthService extends AbstractAuthModuleProvider {
{ logger }: InjectedDependencies, { logger }: InjectedDependencies,
options: EmailPassAuthProviderOptions options: EmailPassAuthProviderOptions
) { ) {
super( // @ts-ignore
{}, super(...arguments)
{ provider: "emailpass", displayName: "Email/Password Authentication" }
)
this.config_ = options this.config_ = options
this.logger_ = logger this.logger_ = logger
} }
@@ -18,6 +18,9 @@ interface LocalServiceConfig extends GithubAuthProviderOptions {}
// TODO: Add state param that is stored in Redis, to prevent CSRF attacks // TODO: Add state param that is stored in Redis, to prevent CSRF attacks
export class GithubAuthService extends AbstractAuthModuleProvider { export class GithubAuthService extends AbstractAuthModuleProvider {
static identifier = "github"
static DISPLAY_NAME = "Github Authentication"
protected config_: LocalServiceConfig protected config_: LocalServiceConfig
protected logger_: Logger protected logger_: Logger
@@ -39,7 +42,8 @@ export class GithubAuthService extends AbstractAuthModuleProvider {
{ logger }: InjectedDependencies, { logger }: InjectedDependencies,
options: GithubAuthProviderOptions options: GithubAuthProviderOptions
) { ) {
super({}, { provider: "github", displayName: "Github Authentication" }) // @ts-ignore
super(...arguments)
this.config_ = options this.config_ = options
this.logger_ = logger this.logger_ = logger
} }
@@ -19,6 +19,9 @@ interface LocalServiceConfig extends GoogleAuthProviderOptions {}
// TODO: Add state param that is stored in Redis, to prevent CSRF attacks // TODO: Add state param that is stored in Redis, to prevent CSRF attacks
export class GoogleAuthService extends AbstractAuthModuleProvider { export class GoogleAuthService extends AbstractAuthModuleProvider {
static identifier = "google"
static DISPLAY_NAME = "Google Authentication"
protected config_: LocalServiceConfig protected config_: LocalServiceConfig
protected logger_: Logger protected logger_: Logger
@@ -40,7 +43,8 @@ export class GoogleAuthService extends AbstractAuthModuleProvider {
{ logger }: InjectedDependencies, { logger }: InjectedDependencies,
options: GoogleAuthProviderOptions options: GoogleAuthProviderOptions
) { ) {
super({}, { provider: "google", displayName: "Google Authentication" }) // @ts-ignore
super(...arguments)
this.config_ = options this.config_ = options
this.logger_ = logger this.logger_ = logger
} }
@@ -1,7 +1,7 @@
import { import {
LocalNotificationServiceOptions,
Logger, Logger,
NotificationTypes, NotificationTypes,
LocalNotificationServiceOptions,
} from "@medusajs/framework/types" } from "@medusajs/framework/types"
import { import {
AbstractNotificationProviderService, AbstractNotificationProviderService,
@@ -15,6 +15,7 @@ type InjectedDependencies = {
interface LocalServiceConfig {} interface LocalServiceConfig {}
export class LocalNotificationService extends AbstractNotificationProviderService { export class LocalNotificationService extends AbstractNotificationProviderService {
static identifier = "notification-local"
protected config_: LocalServiceConfig protected config_: LocalServiceConfig
protected logger_: Logger protected logger_: Logger
@@ -19,6 +19,7 @@ interface SendgridServiceConfig {
} }
export class SendgridNotificationService extends AbstractNotificationProviderService { export class SendgridNotificationService extends AbstractNotificationProviderService {
static identifier = "notification-sendgrid"
protected config_: SendgridServiceConfig protected config_: SendgridServiceConfig
protected logger_: Logger protected logger_: Logger
@@ -2,7 +2,7 @@ import StripeBase from "../core/stripe-base"
import { PaymentIntentOptions, PaymentProviderKeys } from "../types" import { PaymentIntentOptions, PaymentProviderKeys } from "../types"
class BancontactProviderService extends StripeBase { class BancontactProviderService extends StripeBase {
static PROVIDER = PaymentProviderKeys.BAN_CONTACT static identifier = PaymentProviderKeys.BAN_CONTACT
constructor(_, options) { constructor(_, options) {
super(_, options) super(_, options)
@@ -2,7 +2,7 @@ import StripeBase from "../core/stripe-base"
import { PaymentIntentOptions, PaymentProviderKeys } from "../types" import { PaymentIntentOptions, PaymentProviderKeys } from "../types"
class BlikProviderService extends StripeBase { class BlikProviderService extends StripeBase {
static PROVIDER = PaymentProviderKeys.BLIK static identifier = PaymentProviderKeys.BLIK
constructor(_, options) { constructor(_, options) {
super(_, options) super(_, options)
@@ -2,7 +2,7 @@ import StripeBase from "../core/stripe-base"
import { PaymentIntentOptions, PaymentProviderKeys } from "../types" import { PaymentIntentOptions, PaymentProviderKeys } from "../types"
class GiropayProviderService extends StripeBase { class GiropayProviderService extends StripeBase {
static PROVIDER = PaymentProviderKeys.GIROPAY static identifier = PaymentProviderKeys.GIROPAY
constructor(_, options) { constructor(_, options) {
super(_, options) super(_, options)
@@ -2,7 +2,7 @@ import StripeBase from "../core/stripe-base"
import { PaymentIntentOptions, PaymentProviderKeys } from "../types" import { PaymentIntentOptions, PaymentProviderKeys } from "../types"
class IdealProviderService extends StripeBase { class IdealProviderService extends StripeBase {
static PROVIDER = PaymentProviderKeys.IDEAL static identifier = PaymentProviderKeys.IDEAL
constructor(_, options) { constructor(_, options) {
super(_, options) super(_, options)
@@ -2,7 +2,7 @@ import StripeBase from "../core/stripe-base"
import { PaymentIntentOptions, PaymentProviderKeys } from "../types" import { PaymentIntentOptions, PaymentProviderKeys } from "../types"
class StripeProviderService extends StripeBase { class StripeProviderService extends StripeBase {
static PROVIDER = PaymentProviderKeys.STRIPE static identifier = PaymentProviderKeys.STRIPE
constructor(_, options) { constructor(_, options) {
super(_, options) super(_, options)
@@ -2,7 +2,7 @@ import StripeBase from "../core/stripe-base"
import { PaymentIntentOptions, PaymentProviderKeys } from "../types" import { PaymentIntentOptions, PaymentProviderKeys } from "../types"
class Przelewy24ProviderService extends StripeBase { class Przelewy24ProviderService extends StripeBase {
static PROVIDER = PaymentProviderKeys.PRZELEWY_24 static identifier = PaymentProviderKeys.PRZELEWY_24
constructor(_, options) { constructor(_, options) {
super(_, options) super(_, options)