feat: map container types for core services to interface (#11295)
This commit is contained in:
6
.changeset/witty-lies-burn.md
Normal file
6
.changeset/witty-lies-burn.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@medusajs/types": patch
|
||||
"@medusajs/utils": patch
|
||||
---
|
||||
|
||||
feat: map container types for core services to interface
|
||||
@@ -66,7 +66,7 @@ export interface FindConfig<Entity> {
|
||||
/**
|
||||
* An array of strings, each being attribute names of the entity to retrieve in the result.
|
||||
*/
|
||||
select?: (keyof Entity | string)[]
|
||||
select?: (keyof Entity | (string & {}))[]
|
||||
|
||||
/**
|
||||
* A number indicating the number of records to skip before retrieving the results.
|
||||
|
||||
@@ -14,10 +14,10 @@ describe("generateContainerTypes", function () {
|
||||
{
|
||||
cache: {
|
||||
__definition: {
|
||||
key: "cache",
|
||||
key: "foo-cache",
|
||||
label: "Cache",
|
||||
defaultPackage: "@medusajs/foo",
|
||||
resolvePath: "@medusajs/foo",
|
||||
defaultPackage: "@medusajs/foo-cache",
|
||||
resolvePath: "@medusajs/foo-cache",
|
||||
defaultModuleDeclaration: {
|
||||
scope: "internal",
|
||||
},
|
||||
@@ -34,11 +34,46 @@ describe("generateContainerTypes", function () {
|
||||
expect(await fileSystem.exists("modules-bindings.d.ts")).toBeTruthy()
|
||||
expect(await fileSystem.contents("modules-bindings.d.ts"))
|
||||
.toMatchInlineSnapshot(`
|
||||
"import type Cache from '@medusajs/foo'
|
||||
"import type FooCache from '@medusajs/foo-cache'
|
||||
|
||||
declare module '@medusajs/framework/types' {
|
||||
interface ModulesImplementations {
|
||||
cache: InstanceType<(typeof Cache)['service']>
|
||||
'foo-cache': InstanceType<(typeof FooCache)['service']>
|
||||
}
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
it("point inbuilt packages to their interfaces", async function () {
|
||||
await generateContainerTypes(
|
||||
{
|
||||
cache: {
|
||||
__definition: {
|
||||
key: "cache",
|
||||
label: "Cache",
|
||||
defaultPackage: "@medusajs/foo-cache",
|
||||
resolvePath: "@medusajs/foo-cache",
|
||||
defaultModuleDeclaration: {
|
||||
scope: "internal",
|
||||
},
|
||||
},
|
||||
__joinerConfig: {},
|
||||
},
|
||||
},
|
||||
{
|
||||
outputDir: fileSystem.basePath,
|
||||
interfaceName: "ModulesImplementations",
|
||||
}
|
||||
)
|
||||
|
||||
expect(await fileSystem.exists("modules-bindings.d.ts")).toBeTruthy()
|
||||
expect(await fileSystem.contents("modules-bindings.d.ts"))
|
||||
.toMatchInlineSnapshot(`
|
||||
"import type { ICacheService } from '@medusajs/framework/types'
|
||||
|
||||
declare module '@medusajs/framework/types' {
|
||||
interface ModulesImplementations {
|
||||
'cache': ICacheService
|
||||
}
|
||||
}"
|
||||
`)
|
||||
@@ -47,10 +82,10 @@ describe("generateContainerTypes", function () {
|
||||
it("should normalize module path pointing to a relative file", async function () {
|
||||
await generateContainerTypes(
|
||||
{
|
||||
cache: {
|
||||
bar: {
|
||||
__definition: {
|
||||
key: "cache",
|
||||
label: "Cache",
|
||||
key: "bar",
|
||||
label: "Bar",
|
||||
defaultPackage: "./foo/bar",
|
||||
resolvePath: "./foo/bar",
|
||||
defaultModuleDeclaration: {
|
||||
@@ -69,11 +104,11 @@ describe("generateContainerTypes", function () {
|
||||
expect(await fileSystem.exists("modules-bindings.d.ts")).toBeTruthy()
|
||||
expect(await fileSystem.contents("modules-bindings.d.ts"))
|
||||
.toMatchInlineSnapshot(`
|
||||
"import type Cache from '../../foo/bar'
|
||||
"import type Bar from '../../foo/bar'
|
||||
|
||||
declare module '@medusajs/framework/types' {
|
||||
interface ModulesImplementations {
|
||||
cache: InstanceType<(typeof Cache)['service']>
|
||||
'bar': InstanceType<(typeof Bar)['service']>
|
||||
}
|
||||
}"
|
||||
`)
|
||||
|
||||
@@ -1,9 +1,43 @@
|
||||
import { join } from "path"
|
||||
import { Modules } from "./definition"
|
||||
import type { LoadedModule } from "@medusajs/types"
|
||||
import { FileSystem } from "../common/file-system"
|
||||
import { toCamelCase } from "../common/to-camel-case"
|
||||
import { upperCaseFirst } from "../common/upper-case-first"
|
||||
|
||||
/**
|
||||
* For known services that has interfaces, we will set the container
|
||||
* type to the interface than the actual service implementation.
|
||||
*
|
||||
* The idea is to provide more precise types.
|
||||
*/
|
||||
const SERVICES_INTERFACES = {
|
||||
[Modules.AUTH]: "IAuthModuleService",
|
||||
[Modules.CACHE]: "ICacheService",
|
||||
[Modules.CART]: "ICartModuleService",
|
||||
[Modules.CUSTOMER]: "ICustomerModuleService",
|
||||
[Modules.EVENT_BUS]: "IEventBusModuleService",
|
||||
[Modules.INVENTORY]: "IInventoryService",
|
||||
[Modules.PAYMENT]: "IPaymentModuleService",
|
||||
[Modules.PRICING]: "IPricingModuleService",
|
||||
[Modules.PRODUCT]: "IProductModuleService",
|
||||
[Modules.PROMOTION]: "IPromotionModuleService",
|
||||
[Modules.SALES_CHANNEL]: "ISalesChannelModuleService",
|
||||
[Modules.TAX]: "ITaxModuleService",
|
||||
[Modules.FULFILLMENT]: "IFulfillmentModuleService",
|
||||
[Modules.STOCK_LOCATION]: "IStockLocationService",
|
||||
[Modules.USER]: "IUserModuleService",
|
||||
[Modules.WORKFLOW_ENGINE]: "IWorkflowEngineService",
|
||||
[Modules.REGION]: "IRegionModuleService",
|
||||
[Modules.ORDER]: "IOrderModuleService",
|
||||
[Modules.API_KEY]: "IApiKeyModuleService",
|
||||
[Modules.STORE]: "IStoreModuleService",
|
||||
[Modules.CURRENCY]: "ICurrencyModuleService",
|
||||
[Modules.FILE]: "IFileModuleService",
|
||||
[Modules.NOTIFICATION]: "INotificationModuleService",
|
||||
[Modules.LOCKING]: "ILockingModule",
|
||||
}
|
||||
|
||||
/**
|
||||
* Modules registered inside the config file points to one
|
||||
* of the following paths.
|
||||
@@ -55,6 +89,15 @@ export async function generateContainerTypes(
|
||||
* Key registered within the container
|
||||
*/
|
||||
const key = service.__definition.key
|
||||
const interfaceKey = `'${key}'`
|
||||
|
||||
if (SERVICES_INTERFACES[key]) {
|
||||
result.imports.push(
|
||||
`import type { ${SERVICES_INTERFACES[key]} } from '@medusajs/framework/types'`
|
||||
)
|
||||
result.mappings.push(`${interfaceKey}: ${SERVICES_INTERFACES[key]}`)
|
||||
return
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo. The property should exist on "LoadedModule"
|
||||
@@ -71,7 +114,7 @@ export async function generateContainerTypes(
|
||||
|
||||
result.imports.push(`import type ${serviceName} from '${servicePath}'`)
|
||||
result.mappings.push(
|
||||
`${key}: InstanceType<(typeof ${serviceName})['service']>`
|
||||
`${interfaceKey}: InstanceType<(typeof ${serviceName})['service']>`
|
||||
)
|
||||
})
|
||||
return result
|
||||
|
||||
@@ -120,7 +120,7 @@ export type AbstractModuleService<
|
||||
TModelName
|
||||
>}`]: (
|
||||
id: string,
|
||||
config?: FindConfig<any>,
|
||||
config?: FindConfig<TModelsDtoConfig[TModelName]["dto"]>,
|
||||
sharedContext?: Context
|
||||
) => Promise<TModelsDtoConfig[TModelName]["dto"]>
|
||||
} & {
|
||||
@@ -129,7 +129,7 @@ export type AbstractModuleService<
|
||||
TModelName
|
||||
>}`]: (
|
||||
filters?: any,
|
||||
config?: FindConfig<any>,
|
||||
config?: FindConfig<TModelsDtoConfig[TModelName]["dto"]>,
|
||||
sharedContext?: Context
|
||||
) => Promise<TModelsDtoConfig[TModelName]["dto"][]>
|
||||
} & {
|
||||
@@ -137,9 +137,11 @@ export type AbstractModuleService<
|
||||
TModelsDtoConfig,
|
||||
TModelName
|
||||
>}`]: {
|
||||
(filters?: any, config?: FindConfig<any>, sharedContext?: Context): Promise<
|
||||
[TModelsDtoConfig[TModelName]["dto"][], number]
|
||||
>
|
||||
(
|
||||
filters?: any,
|
||||
config?: FindConfig<TModelsDtoConfig[TModelName]["dto"]>,
|
||||
sharedContext?: Context
|
||||
): Promise<[TModelsDtoConfig[TModelName]["dto"][], number]>
|
||||
}
|
||||
} & {
|
||||
[TModelName in keyof TModelsDtoConfig as `delete${ExtractPluralName<
|
||||
|
||||
Reference in New Issue
Block a user