feat(cart): Add cart module package (#5982)

* feat: Add CartModule foundation

* remove migration

* fix ts issue

* Create hot-dingos-pay.md
This commit is contained in:
Oli Juhl authored and GitHub committed 2024-01-02 15:59:23 +01:00
1 parent 487067fb48
commit 925feea04a
44 files changed
+679 -3

No files matched your search

+7
View File
@@ -0,0 +1,7 @@
import { moduleDefinition } from "./module-definition"
export default moduleDefinition
export * from "./initialize"
export * from "./loaders"
export * from "./scripts"
+27
View File
@@ -0,0 +1,27 @@
import {
ExternalModuleDeclaration,
InternalModuleDeclaration,
MedusaModule,
MODULE_PACKAGE_NAMES,
Modules,
} from "@medusajs/modules-sdk"
import { ICartModuleService, ModulesSdkTypes } from "@medusajs/types"
import { moduleDefinition } from "../module-definition"
import { InitializeModuleInjectableDependencies } from "../types"
export const initialize = async (
options?: ModulesSdkTypes.ModuleBootstrapDeclaration,
injectedDependencies?: InitializeModuleInjectableDependencies
): Promise<ICartModuleService> => {
const loaded = await MedusaModule.bootstrap<ICartModuleService>({
moduleKey: Modules.CART,
defaultPath: MODULE_PACKAGE_NAMES[Modules.CART],
declaration: options as
| InternalModuleDeclaration
| ExternalModuleDeclaration,
injectedDependencies,
moduleExports: moduleDefinition,
})
return loaded[Modules.CART]
}
+31
View File
@@ -0,0 +1,31 @@
import { Modules } from "@medusajs/modules-sdk"
import { ModuleJoinerConfig } from "@medusajs/types"
import { MapToConfig } from "@medusajs/utils"
import { Cart } from "@models"
export const LinkableKeys = {
cart_id: Cart.name,
}
const entityLinkableKeysMap: MapToConfig = {}
Object.entries(LinkableKeys).forEach(([key, value]) => {
entityLinkableKeysMap[value] ??= []
entityLinkableKeysMap[value].push({
mapTo: key,
valueFrom: key.split("_").pop()!,
})
})
export const entityNameToLinkableKeysMap: MapToConfig = entityLinkableKeysMap
export const joinerConfig: ModuleJoinerConfig = {
serviceName: Modules.CART,
primaryKeys: ["id"],
linkableKeys: LinkableKeys,
alias: {
name: ["cart", "carts"],
args: {
entity: Cart.name,
},
},
}
+36
View File
@@ -0,0 +1,36 @@
import {
InternalModuleDeclaration,
LoaderOptions,
Modules,
} from "@medusajs/modules-sdk"
import { ModulesSdkTypes } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { EntitySchema } from "@mikro-orm/core"
import * as CartModels from "../models"
export default async (
{
options,
container,
logger,
}: LoaderOptions<
| ModulesSdkTypes.ModuleServiceInitializeOptions
| ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions
>,
moduleDeclaration?: InternalModuleDeclaration
): Promise<void> => {
const entities = Object.values(
CartModels
) as unknown as EntitySchema[]
const pathToMigrations = __dirname + "/../migrations"
await ModulesSdkUtils.mikroOrmConnectionLoader({
moduleName: Modules.CART,
entities,
container,
options,
moduleDeclaration,
logger,
pathToMigrations,
})
}
+38
View File
@@ -0,0 +1,38 @@
import * as defaultRepositories from "@repositories"
import { LoaderOptions } from "@medusajs/modules-sdk"
import { ModulesSdkTypes } from "@medusajs/types"
import { loadCustomRepositories } from "@medusajs/utils"
import { asClass } from "awilix"
export default async ({
container,
options,
}: LoaderOptions<
| ModulesSdkTypes.ModuleServiceInitializeOptions
| ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions
>): Promise<void> => {
const customRepositories = (
options as ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions
)?.repositories
container.register({
// cartService: asClass(defaultServices.CartService).singleton(),
})
if (customRepositories) {
loadCustomRepositories({
defaultRepositories,
customRepositories,
container,
})
} else {
loadDefaultRepositories({ container })
}
}
function loadDefaultRepositories({ container }) {
container.register({
baseRepository: asClass(defaultRepositories.BaseRepository).singleton(),
})
}
+2
View File
@@ -0,0 +1,2 @@
export * from "./connection"
export * from "./container"
+18
View File
@@ -0,0 +1,18 @@
import { generateEntityId } from "@medusajs/utils"
import { BeforeCreate, Entity, OnInit, PrimaryKey } from "@mikro-orm/core"
@Entity()
export default class Cart {
@PrimaryKey({ columnType: "text" })
id!: string
@BeforeCreate()
onCreate() {
this.id = generateEntityId(this.id, "cart")
}
@OnInit()
onInit() {
this.id = generateEntityId(this.id, "cart")
}
}
+2
View File
@@ -0,0 +1,2 @@
export { default as Cart } from "./cart";
+12
View File
@@ -0,0 +1,12 @@
import { ModuleExports } from "@medusajs/types"
import { CartModuleService } from "@services"
import loadConnection from "./loaders/connection"
import loadContainer from "./loaders/container"
const service = CartModuleService
const loaders = [loadContainer, loadConnection] as any
export const moduleDefinition: ModuleExports = {
service,
loaders,
}
+1
View File
@@ -0,0 +1 @@
export { MikroOrmBaseRepository as BaseRepository } from "@medusajs/utils"
@@ -0,0 +1,8 @@
#!/usr/bin/env node
export default (async () => {
const { revertMigration } = await import("../migration-down")
const { config } = await import("dotenv")
config()
await revertMigration()
})()
@@ -0,0 +1,8 @@
#!/usr/bin/env node
export default (async () => {
const { runMigrations } = await import("../migration-up")
const { config } = await import("dotenv")
config()
await runMigrations()
})()
+19
View File
@@ -0,0 +1,19 @@
#!/usr/bin/env node
import { EOL } from "os"
import { run } from "../seed"
const args = process.argv
const path = args.pop() as string
export default (async () => {
const { config } = await import("dotenv")
config()
if (!path) {
throw new Error(
`filePath is required.${EOL}Example: medusa-cart-seed <filePath>`
)
}
await run({ path })
})()
+2
View File
@@ -0,0 +1,2 @@
export * from "./migration-up"
export * from "./migration-down"
@@ -0,0 +1,50 @@
import { Modules } from "@medusajs/modules-sdk";
import { LoaderOptions, Logger, ModulesSdkTypes } from "@medusajs/types";
import { DALUtils, ModulesSdkUtils } from "@medusajs/utils";
import { EntitySchema } from "@mikro-orm/core";
import * as CartModels from "@models";
/**
* This script is only valid for mikro orm managers. If a user provide a custom manager
* he is in charge of reverting the migrations.
* @param options
* @param logger
* @param moduleDeclaration
*/
export async function revertMigration({
options,
logger,
}: Pick<
LoaderOptions<ModulesSdkTypes.ModuleServiceInitializeOptions>,
"options" | "logger"
> = {}) {
logger ??= console as unknown as Logger
const dbData = ModulesSdkUtils.loadDatabaseConfig(
Modules.CART,
options
)!
const entities = Object.values(
CartModels
) as unknown as EntitySchema[]
const pathToMigrations = __dirname + "/../migrations"
const orm = await DALUtils.mikroOrmCreateConnection(
dbData,
entities,
pathToMigrations
)
try {
const migrator = orm.getMigrator()
await migrator.down()
logger?.info("Cart module migration executed")
} catch (error) {
logger?.error(
`Cart module migration failed to run - Error: ${error}`
)
}
await orm.close()
}
+62
View File
@@ -0,0 +1,62 @@
import { Modules } from "@medusajs/modules-sdk";
import { LoaderOptions, Logger, ModulesSdkTypes } from "@medusajs/types";
import { DALUtils, ModulesSdkUtils } from "@medusajs/utils";
import { EntitySchema } from "@mikro-orm/core";
import * as CartModels from "@models";
/**
* This script is only valid for mikro orm managers. If a user provide a custom manager
* he is in charge of running the migrations.
* @param options
* @param logger
* @param moduleDeclaration
*/
export async function runMigrations({
options,
logger,
}: Pick<
LoaderOptions<ModulesSdkTypes.ModuleServiceInitializeOptions>,
"options" | "logger"
> = {}) {
logger ??= console as unknown as Logger
const dbData = ModulesSdkUtils.loadDatabaseConfig(
Modules.CART,
options
)!
const entities = Object.values(
CartModels
) as unknown as EntitySchema[]
const pathToMigrations = __dirname + "/../migrations"
const orm = await DALUtils.mikroOrmCreateConnection(
dbData,
entities,
pathToMigrations
)
try {
const migrator = orm.getMigrator()
const pendingMigrations = await migrator.getPendingMigrations()
logger.info(
`Running pending migrations: ${JSON.stringify(
pendingMigrations,
null,
2
)}`
)
await migrator.up({
migrations: pendingMigrations.map((m) => m.name),
})
logger.info("Cart module migration executed")
} catch (error) {
logger.error(
`Cart module migration failed to run - Error: ${error}`
)
}
await orm.close()
}
+63
View File
@@ -0,0 +1,63 @@
import { Modules } from "@medusajs/modules-sdk"
import { LoaderOptions, Logger, ModulesSdkTypes } from "@medusajs/types"
import { DALUtils, ModulesSdkUtils } from "@medusajs/utils"
import { EntitySchema } from "@mikro-orm/core"
import * as CartModels from "@models"
import { EOL } from "os"
import { resolve } from "path"
export async function run({
options,
logger,
path,
}: Partial<
Pick<
LoaderOptions<ModulesSdkTypes.ModuleServiceInitializeOptions>,
"options" | "logger"
>
> & {
path: string
}) {
logger ??= console as unknown as Logger
logger.info(`Loading seed data from ${path}...`)
const { cartData } = await import(
resolve(process.cwd(), path)
).catch((e) => {
logger?.error(
`Failed to load seed data from ${path}. Please, provide a relative path and check that you export the following: cartData.${EOL}${e}`
)
throw e
})
const dbData = ModulesSdkUtils.loadDatabaseConfig(
Modules.CART,
options
)!
const entities = Object.values(
CartModels
) as unknown as EntitySchema[]
const pathToMigrations = __dirname + "/../migrations"
const orm = await DALUtils.mikroOrmCreateConnection(
dbData,
entities,
pathToMigrations
)
const manager = orm.em.fork()
try {
logger.info("Seeding cart data..")
// TODO: implement cart seed data
// await createCarts(manager, cartsData)
} catch (e) {
logger.error(
`Failed to insert the seed data in the PostgreSQL database ${dbData.clientUrl}.${EOL}${e}`
)
}
await orm.close(true)
}
@@ -0,0 +1,5 @@
describe("Noop test", () => {
it("noop check", async () => {
expect(true).toBe(true)
})
})
+32
View File
@@ -0,0 +1,32 @@
import {
CartTypes,
DAL,
InternalModuleDeclaration,
ModuleJoinerConfig,
} from "@medusajs/types"
import { Cart } from "@models"
import { joinerConfig } from "../joiner-config"
type InjectedDependencies = {
baseRepository: DAL.RepositoryService
}
export default class CartModuleService<
TCart extends Cart = Cart
> implements CartTypes.ICartModuleService
{
protected baseRepository_: DAL.RepositoryService
constructor(
{ baseRepository }: InjectedDependencies,
protected readonly moduleDeclaration: InternalModuleDeclaration
) {
this.baseRepository_ = baseRepository
}
__joinerConfig(): ModuleJoinerConfig {
return joinerConfig
}
}
+2
View File
@@ -0,0 +1,2 @@
export { default as CartModuleService } from "./cart-module";
+5
View File
@@ -0,0 +1,5 @@
import { Logger } from "@medusajs/types"
export type InitializeModuleInjectableDependencies = {
logger?: Logger
}