chore(): Reorganize modules (#7210)
**What** Move all modules to the modules directory
This commit is contained in:
committed by
GitHub
parent
7a351eef09
commit
4eae25e1ef
10
packages/modules/customer/src/index.ts
Normal file
10
packages/modules/customer/src/index.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import {
|
||||
moduleDefinition,
|
||||
revertMigration,
|
||||
runMigrations,
|
||||
} from "./module-definition"
|
||||
|
||||
export default moduleDefinition
|
||||
export { revertMigration, runMigrations }
|
||||
|
||||
export * from "./initialize"
|
||||
31
packages/modules/customer/src/initialize/index.ts
Normal file
31
packages/modules/customer/src/initialize/index.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import {
|
||||
ExternalModuleDeclaration,
|
||||
InternalModuleDeclaration,
|
||||
MedusaModule,
|
||||
MODULE_PACKAGE_NAMES,
|
||||
Modules,
|
||||
} from "@medusajs/modules-sdk"
|
||||
import { ICustomerModuleService, ModulesSdkTypes } from "@medusajs/types"
|
||||
import { moduleDefinition } from "../module-definition"
|
||||
import { InitializeModuleInjectableDependencies } from "@types"
|
||||
|
||||
export const initialize = async (
|
||||
options?:
|
||||
| ModulesSdkTypes.ModuleServiceInitializeOptions
|
||||
| ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions
|
||||
| ExternalModuleDeclaration
|
||||
| InternalModuleDeclaration,
|
||||
injectedDependencies?: InitializeModuleInjectableDependencies
|
||||
): Promise<ICustomerModuleService> => {
|
||||
const loaded = await MedusaModule.bootstrap<ICustomerModuleService>({
|
||||
moduleKey: Modules.CUSTOMER,
|
||||
defaultPath: MODULE_PACKAGE_NAMES[Modules.CUSTOMER],
|
||||
declaration: options as
|
||||
| InternalModuleDeclaration
|
||||
| ExternalModuleDeclaration,
|
||||
injectedDependencies,
|
||||
moduleExports: moduleDefinition,
|
||||
})
|
||||
|
||||
return loaded[Modules.CUSTOMER]
|
||||
}
|
||||
49
packages/modules/customer/src/joiner-config.ts
Normal file
49
packages/modules/customer/src/joiner-config.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { Modules } from "@medusajs/modules-sdk"
|
||||
import { ModuleJoinerConfig } from "@medusajs/types"
|
||||
import { MapToConfig } from "@medusajs/utils"
|
||||
import { Address, Customer, CustomerGroup } from "@models"
|
||||
|
||||
export const LinkableKeys = {
|
||||
customer_id: Customer.name,
|
||||
customer_group_id: CustomerGroup.name,
|
||||
customer_address_id: Address.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.CUSTOMER,
|
||||
primaryKeys: ["id"],
|
||||
linkableKeys: LinkableKeys,
|
||||
alias: [
|
||||
{
|
||||
name: ["customer", "customers"],
|
||||
args: {
|
||||
entity: Customer.name,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["customer_group", "customer_groups"],
|
||||
args: {
|
||||
entity: CustomerGroup.name,
|
||||
methodSuffix: "CustomerGroups",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["customer_address", "customer_addresses"],
|
||||
args: {
|
||||
entity: Address.name,
|
||||
methodSuffix: "Addresses",
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
34
packages/modules/customer/src/loaders/connection.ts
Normal file
34
packages/modules/customer/src/loaders/connection.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
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 CustomerModels from "../models"
|
||||
|
||||
export default async (
|
||||
{
|
||||
options,
|
||||
container,
|
||||
logger,
|
||||
}: LoaderOptions<
|
||||
| ModulesSdkTypes.ModuleServiceInitializeOptions
|
||||
| ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions
|
||||
>,
|
||||
moduleDeclaration?: InternalModuleDeclaration
|
||||
): Promise<void> => {
|
||||
const entities = Object.values(CustomerModels) as unknown as EntitySchema[]
|
||||
const pathToMigrations = __dirname + "/../migrations"
|
||||
|
||||
await ModulesSdkUtils.mikroOrmConnectionLoader({
|
||||
moduleName: Modules.CUSTOMER,
|
||||
entities,
|
||||
container,
|
||||
options,
|
||||
moduleDeclaration,
|
||||
logger,
|
||||
pathToMigrations,
|
||||
})
|
||||
}
|
||||
11
packages/modules/customer/src/loaders/container.ts
Normal file
11
packages/modules/customer/src/loaders/container.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import * as ModuleModels from "@models"
|
||||
import * as CustomerRepositories from "@repositories"
|
||||
import * as ModuleServices from "@services"
|
||||
|
||||
import { ModulesSdkUtils } from "@medusajs/utils"
|
||||
|
||||
export default ModulesSdkUtils.moduleContainerLoaderFactory({
|
||||
moduleModels: ModuleModels,
|
||||
moduleServices: ModuleServices,
|
||||
moduleRepositories: CustomerRepositories,
|
||||
})
|
||||
2
packages/modules/customer/src/loaders/index.ts
Normal file
2
packages/modules/customer/src/loaders/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from "./connection"
|
||||
export * from "./container"
|
||||
@@ -0,0 +1,583 @@
|
||||
{
|
||||
"namespaces": [
|
||||
"public"
|
||||
],
|
||||
"name": "public",
|
||||
"tables": [
|
||||
{
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": false,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"company_name": {
|
||||
"name": "company_name",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"first_name": {
|
||||
"name": "first_name",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"last_name": {
|
||||
"name": "last_name",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"email": {
|
||||
"name": "email",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"phone": {
|
||||
"name": "phone",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"has_account": {
|
||||
"name": "has_account",
|
||||
"type": "boolean",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": false,
|
||||
"default": "false",
|
||||
"mappedType": "boolean"
|
||||
},
|
||||
"metadata": {
|
||||
"name": "metadata",
|
||||
"type": "jsonb",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "json"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamptz",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": false,
|
||||
"length": 6,
|
||||
"default": "now()",
|
||||
"mappedType": "datetime"
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "timestamptz",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": false,
|
||||
"length": 6,
|
||||
"default": "now()",
|
||||
"mappedType": "datetime"
|
||||
},
|
||||
"deleted_at": {
|
||||
"name": "deleted_at",
|
||||
"type": "timestamptz",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"length": 6,
|
||||
"mappedType": "datetime"
|
||||
},
|
||||
"created_by": {
|
||||
"name": "created_by",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "text"
|
||||
}
|
||||
},
|
||||
"name": "customer",
|
||||
"schema": "public",
|
||||
"indexes": [
|
||||
{
|
||||
"keyName": "customer_pkey",
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"composite": false,
|
||||
"primary": true,
|
||||
"unique": true
|
||||
}
|
||||
],
|
||||
"checks": [],
|
||||
"foreignKeys": {}
|
||||
},
|
||||
{
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": false,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"address_name": {
|
||||
"name": "address_name",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"is_default_shipping": {
|
||||
"name": "is_default_shipping",
|
||||
"type": "boolean",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": false,
|
||||
"default": "false",
|
||||
"mappedType": "boolean"
|
||||
},
|
||||
"is_default_billing": {
|
||||
"name": "is_default_billing",
|
||||
"type": "boolean",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": false,
|
||||
"default": "false",
|
||||
"mappedType": "boolean"
|
||||
},
|
||||
"customer_id": {
|
||||
"name": "customer_id",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": false,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"company": {
|
||||
"name": "company",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"first_name": {
|
||||
"name": "first_name",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"last_name": {
|
||||
"name": "last_name",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"address_1": {
|
||||
"name": "address_1",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"address_2": {
|
||||
"name": "address_2",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"city": {
|
||||
"name": "city",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"country_code": {
|
||||
"name": "country_code",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"province": {
|
||||
"name": "province",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"postal_code": {
|
||||
"name": "postal_code",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"phone": {
|
||||
"name": "phone",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"metadata": {
|
||||
"name": "metadata",
|
||||
"type": "jsonb",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "json"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamptz",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": false,
|
||||
"length": 6,
|
||||
"default": "now()",
|
||||
"mappedType": "datetime"
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "timestamptz",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": false,
|
||||
"length": 6,
|
||||
"default": "now()",
|
||||
"mappedType": "datetime"
|
||||
}
|
||||
},
|
||||
"name": "customer_address",
|
||||
"schema": "public",
|
||||
"indexes": [
|
||||
{
|
||||
"columnNames": [
|
||||
"customer_id"
|
||||
],
|
||||
"composite": false,
|
||||
"keyName": "IDX_customer_address_customer_id",
|
||||
"primary": false,
|
||||
"unique": false
|
||||
},
|
||||
{
|
||||
"keyName": "IDX_customer_address_unqiue_customer_billing",
|
||||
"columnNames": [],
|
||||
"composite": false,
|
||||
"primary": false,
|
||||
"unique": false,
|
||||
"expression": "create unique index \"IDX_customer_address_unqiue_customer_billing\" on \"customer_address\" (\"customer_id\") where \"is_default_billing\" = true"
|
||||
},
|
||||
{
|
||||
"keyName": "IDX_customer_address_unqiue_customer_shipping",
|
||||
"columnNames": [],
|
||||
"composite": false,
|
||||
"primary": false,
|
||||
"unique": false,
|
||||
"expression": "create unique index \"IDX_customer_address_unique_customer_shipping\" on \"customer_address\" (\"customer_id\") where \"is_default_shipping\" = true"
|
||||
},
|
||||
{
|
||||
"keyName": "customer_address_pkey",
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"composite": false,
|
||||
"primary": true,
|
||||
"unique": true
|
||||
}
|
||||
],
|
||||
"checks": [],
|
||||
"foreignKeys": {
|
||||
"customer_address_customer_id_foreign": {
|
||||
"constraintName": "customer_address_customer_id_foreign",
|
||||
"columnNames": [
|
||||
"customer_id"
|
||||
],
|
||||
"localTableName": "public.customer_address",
|
||||
"referencedColumnNames": [
|
||||
"id"
|
||||
],
|
||||
"referencedTableName": "public.customer",
|
||||
"deleteRule": "cascade",
|
||||
"updateRule": "cascade"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": false,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"metadata": {
|
||||
"name": "metadata",
|
||||
"type": "jsonb",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "json"
|
||||
},
|
||||
"created_by": {
|
||||
"name": "created_by",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamptz",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": false,
|
||||
"length": 6,
|
||||
"default": "now()",
|
||||
"mappedType": "datetime"
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "timestamptz",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": false,
|
||||
"length": 6,
|
||||
"default": "now()",
|
||||
"mappedType": "datetime"
|
||||
},
|
||||
"deleted_at": {
|
||||
"name": "deleted_at",
|
||||
"type": "timestamptz",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"length": 6,
|
||||
"mappedType": "datetime"
|
||||
}
|
||||
},
|
||||
"name": "customer_group",
|
||||
"schema": "public",
|
||||
"indexes": [
|
||||
{
|
||||
"keyName": "customer_group_pkey",
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"composite": false,
|
||||
"primary": true,
|
||||
"unique": true
|
||||
}
|
||||
],
|
||||
"checks": [],
|
||||
"foreignKeys": {}
|
||||
},
|
||||
{
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": false,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"customer_id": {
|
||||
"name": "customer_id",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": false,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"customer_group_id": {
|
||||
"name": "customer_group_id",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": false,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"metadata": {
|
||||
"name": "metadata",
|
||||
"type": "jsonb",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "json"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamptz",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": false,
|
||||
"length": 6,
|
||||
"default": "now()",
|
||||
"mappedType": "datetime"
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "timestamptz",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": false,
|
||||
"length": 6,
|
||||
"default": "now()",
|
||||
"mappedType": "datetime"
|
||||
},
|
||||
"created_by": {
|
||||
"name": "created_by",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "text"
|
||||
}
|
||||
},
|
||||
"name": "customer_group_customer",
|
||||
"schema": "public",
|
||||
"indexes": [
|
||||
{
|
||||
"columnNames": [
|
||||
"customer_group_id"
|
||||
],
|
||||
"composite": false,
|
||||
"keyName": "IDX_customer_group_customer_group_id",
|
||||
"primary": false,
|
||||
"unique": false
|
||||
},
|
||||
{
|
||||
"columnNames": [
|
||||
"customer_id"
|
||||
],
|
||||
"composite": false,
|
||||
"keyName": "IDX_customer_group_customer_customer_id",
|
||||
"primary": false,
|
||||
"unique": false
|
||||
},
|
||||
{
|
||||
"keyName": "customer_group_customer_pkey",
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"composite": false,
|
||||
"primary": true,
|
||||
"unique": true
|
||||
}
|
||||
],
|
||||
"checks": [],
|
||||
"foreignKeys": {
|
||||
"customer_group_customer_customer_group_id_foreign": {
|
||||
"constraintName": "customer_group_customer_customer_group_id_foreign",
|
||||
"columnNames": [
|
||||
"customer_group_id"
|
||||
],
|
||||
"localTableName": "public.customer_group_customer",
|
||||
"referencedColumnNames": [
|
||||
"id"
|
||||
],
|
||||
"referencedTableName": "public.customer_group",
|
||||
"deleteRule": "cascade"
|
||||
},
|
||||
"customer_group_customer_customer_id_foreign": {
|
||||
"constraintName": "customer_group_customer_customer_id_foreign",
|
||||
"columnNames": [
|
||||
"customer_id"
|
||||
],
|
||||
"localTableName": "public.customer_group_customer",
|
||||
"referencedColumnNames": [
|
||||
"id"
|
||||
],
|
||||
"referencedTableName": "public.customer",
|
||||
"deleteRule": "cascade"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import { Migration } from "@mikro-orm/migrations"
|
||||
|
||||
export class Migration20240124154000 extends Migration {
|
||||
async up(): Promise<void> {
|
||||
// Customer table modifications
|
||||
this.addSql(
|
||||
'create table if not exists "customer" ("id" text not null, "company_name" text null, "first_name" text null, "last_name" text null, "email" text null, "phone" text null, "has_account" boolean not null default false, "metadata" jsonb null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, "created_by" text null, constraint "customer_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql('alter table "customer" alter column "email" drop not null;')
|
||||
this.addSql(
|
||||
'alter table "customer" add column if not exists "company_name" text null;'
|
||||
)
|
||||
this.addSql(
|
||||
'alter table "customer" add column if not exists "created_by" text null;'
|
||||
)
|
||||
this.addSql('drop index if exists "IDX_8abe81b9aac151ae60bf507ad1";')
|
||||
|
||||
// Customer Address table
|
||||
this.addSql(
|
||||
'create table if not exists "customer_address" ("id" text not null, "customer_id" text not null, "address_name" text null, "is_default_shipping" boolean not null default false, "is_default_billing" boolean not null default false, "company" text null, "first_name" text null, "last_name" text null, "address_1" text null, "address_2" text null, "city" text null, "country_code" text null, "province" text null, "postal_code" text null, "phone" text null, "metadata" jsonb null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), constraint "customer_address_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql(
|
||||
'create index if not exists "IDX_customer_address_customer_id" on "customer_address" ("customer_id");'
|
||||
)
|
||||
this.addSql(
|
||||
'create unique index "IDX_customer_address_unique_customer_billing" on "customer_address" ("customer_id") where "is_default_billing" = true;'
|
||||
)
|
||||
this.addSql(
|
||||
'create unique index "IDX_customer_address_unique_customer_shipping" on "customer_address" ("customer_id") where "is_default_shipping" = true;'
|
||||
)
|
||||
|
||||
// Customer Group table modifications
|
||||
this.addSql(
|
||||
'create table if not exists "customer_group" ("id" text not null, "name" text null, "metadata" jsonb null, "created_by" text null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "customer_group_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql(
|
||||
'alter table "customer_group" add column if not exists "created_by" text null;'
|
||||
)
|
||||
this.addSql('drop index if exists "IDX_c4c3a5225a7a1f0af782c40abc";')
|
||||
this.addSql(
|
||||
'create unique index if not exists "IDX_customer_group_name" on "customer_group" ("name") where "deleted_at" is null;'
|
||||
)
|
||||
|
||||
// Customer Group Customer table
|
||||
this.addSql(
|
||||
'create table if not exists "customer_group_customer" ("id" text not null, "customer_id" text not null, "customer_group_id" text not null, "metadata" jsonb null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "created_by" text null, constraint "customer_group_customer_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql(
|
||||
'create index if not exists "IDX_customer_group_customer_group_id" on "customer_group_customer" ("customer_group_id");'
|
||||
)
|
||||
this.addSql(
|
||||
'create index if not exists "IDX_customer_group_customer_customer_id" on "customer_group_customer" ("customer_id");'
|
||||
)
|
||||
|
||||
// Foreign key constraints
|
||||
this.addSql(
|
||||
'alter table "customer" drop constraint if exists "FK_8abe81b9aac151ae60bf507ad15";'
|
||||
)
|
||||
this.addSql(
|
||||
'alter table "customer_address" add constraint "customer_address_customer_id_foreign" foreign key ("customer_id") references "customer" ("id") on update cascade on delete cascade;'
|
||||
)
|
||||
this.addSql(
|
||||
'alter table "customer_group_customer" add constraint "customer_group_customer_customer_group_id_foreign" foreign key ("customer_group_id") references "customer_group" ("id") on delete cascade;'
|
||||
)
|
||||
this.addSql(
|
||||
'alter table "customer_group_customer" add constraint "customer_group_customer_customer_id_foreign" foreign key ("customer_id") references "customer" ("id") on delete cascade;'
|
||||
)
|
||||
}
|
||||
}
|
||||
125
packages/modules/customer/src/models/address.ts
Normal file
125
packages/modules/customer/src/models/address.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
import { DAL } from "@medusajs/types"
|
||||
import { Searchable, generateEntityId } from "@medusajs/utils"
|
||||
import {
|
||||
BeforeCreate,
|
||||
Cascade,
|
||||
Entity,
|
||||
Index,
|
||||
ManyToOne,
|
||||
OnInit,
|
||||
OptionalProps,
|
||||
PrimaryKey,
|
||||
Property,
|
||||
} 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: 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: UNIQUE_CUSTOMER_BILLING_ADDRESS,
|
||||
expression:
|
||||
'create unique index "IDX_customer_address_unique_customer_billing" on "customer_address" ("customer_id") where "is_default_billing" = true',
|
||||
})
|
||||
export default class Address {
|
||||
[OptionalProps]: OptionalAddressProps
|
||||
|
||||
@PrimaryKey({ columnType: "text" })
|
||||
id!: string
|
||||
|
||||
@Searchable()
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
address_name: string | null = null
|
||||
|
||||
@Property({ columnType: "boolean", default: false })
|
||||
is_default_shipping: boolean = false
|
||||
|
||||
@Property({ columnType: "boolean", default: false })
|
||||
is_default_billing: boolean = false
|
||||
|
||||
@Property({ columnType: "text" })
|
||||
customer_id: string
|
||||
|
||||
@ManyToOne(() => Customer, {
|
||||
fieldName: "customer_id",
|
||||
index: "IDX_customer_address_customer_id",
|
||||
cascade: [Cascade.REMOVE, Cascade.PERSIST],
|
||||
})
|
||||
customer: Customer
|
||||
|
||||
@Searchable()
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
company: string | null = null
|
||||
|
||||
@Searchable()
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
first_name: string | null = null
|
||||
|
||||
@Searchable()
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
last_name: string | null = null
|
||||
|
||||
@Searchable()
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
address_1: string | null = null
|
||||
|
||||
@Searchable()
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
address_2: string | null = null
|
||||
|
||||
@Searchable()
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
city: string | null = null
|
||||
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
country_code: string | null = null
|
||||
|
||||
@Searchable()
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
province: string | null = null
|
||||
|
||||
@Searchable()
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
postal_code: string | null = null
|
||||
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
phone: string | null = null
|
||||
|
||||
@Property({ columnType: "jsonb", nullable: true })
|
||||
metadata: Record<string, unknown> | null = null
|
||||
|
||||
@Property({
|
||||
onCreate: () => new Date(),
|
||||
columnType: "timestamptz",
|
||||
defaultRaw: "now()",
|
||||
})
|
||||
created_at: Date
|
||||
|
||||
@Property({
|
||||
onCreate: () => new Date(),
|
||||
onUpdate: () => new Date(),
|
||||
columnType: "timestamptz",
|
||||
defaultRaw: "now()",
|
||||
})
|
||||
updated_at: Date
|
||||
|
||||
@BeforeCreate()
|
||||
onCreate() {
|
||||
this.id = generateEntityId(this.id, "cuaddr")
|
||||
}
|
||||
|
||||
@OnInit()
|
||||
onInit() {
|
||||
this.id = generateEntityId(this.id, "cuaddr")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import { DAL } from "@medusajs/types"
|
||||
import { generateEntityId } from "@medusajs/utils"
|
||||
import {
|
||||
Cascade,
|
||||
BeforeCreate,
|
||||
ManyToOne,
|
||||
Entity,
|
||||
OnInit,
|
||||
OptionalProps,
|
||||
PrimaryKey,
|
||||
Property,
|
||||
} from "@mikro-orm/core"
|
||||
import Customer from "./customer"
|
||||
import CustomerGroup from "./customer-group"
|
||||
|
||||
type OptionalGroupProps = "customer_group" | "customer" | DAL.EntityDateColumns // TODO: To be revisited when more clear
|
||||
|
||||
@Entity({ tableName: "customer_group_customer" })
|
||||
export default class CustomerGroupCustomer {
|
||||
[OptionalProps]: OptionalGroupProps
|
||||
|
||||
@PrimaryKey({ columnType: "text" })
|
||||
id!: string
|
||||
|
||||
@Property({ columnType: "text" })
|
||||
customer_id: string
|
||||
|
||||
@Property({ columnType: "text" })
|
||||
customer_group_id: string
|
||||
|
||||
@ManyToOne({
|
||||
entity: () => Customer,
|
||||
fieldName: "customer_id",
|
||||
index: "IDX_customer_group_customer_customer_id",
|
||||
cascade: [Cascade.REMOVE],
|
||||
})
|
||||
customer: Customer
|
||||
|
||||
@ManyToOne({
|
||||
entity: () => CustomerGroup,
|
||||
fieldName: "customer_group_id",
|
||||
index: "IDX_customer_group_customer_group_id",
|
||||
cascade: [Cascade.REMOVE],
|
||||
})
|
||||
customer_group: CustomerGroup
|
||||
|
||||
@Property({ columnType: "jsonb", nullable: true })
|
||||
metadata: Record<string, unknown> | null = null
|
||||
|
||||
@Property({
|
||||
onCreate: () => new Date(),
|
||||
columnType: "timestamptz",
|
||||
defaultRaw: "now()",
|
||||
})
|
||||
created_at: Date
|
||||
|
||||
@Property({
|
||||
onCreate: () => new Date(),
|
||||
onUpdate: () => new Date(),
|
||||
columnType: "timestamptz",
|
||||
defaultRaw: "now()",
|
||||
})
|
||||
updated_at: Date
|
||||
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
created_by: string | null = null
|
||||
|
||||
@BeforeCreate()
|
||||
onCreate() {
|
||||
this.id = generateEntityId(this.id, "cusgc")
|
||||
}
|
||||
|
||||
@OnInit()
|
||||
onInit() {
|
||||
this.id = generateEntityId(this.id, "cusgc")
|
||||
}
|
||||
}
|
||||
70
packages/modules/customer/src/models/customer-group.ts
Normal file
70
packages/modules/customer/src/models/customer-group.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { DAL } from "@medusajs/types"
|
||||
import { DALUtils, Searchable, generateEntityId } from "@medusajs/utils"
|
||||
import {
|
||||
BeforeCreate,
|
||||
Entity,
|
||||
OnInit,
|
||||
OptionalProps,
|
||||
PrimaryKey,
|
||||
Property,
|
||||
ManyToMany,
|
||||
Collection,
|
||||
Filter,
|
||||
} from "@mikro-orm/core"
|
||||
import Customer from "./customer"
|
||||
import CustomerGroupCustomer from "./customer-group-customer"
|
||||
|
||||
type OptionalGroupProps = DAL.SoftDeletableEntityDateColumns // TODO: To be revisited when more clear
|
||||
|
||||
@Entity({ tableName: "customer_group" })
|
||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||
export default class CustomerGroup {
|
||||
[OptionalProps]: OptionalGroupProps
|
||||
|
||||
@PrimaryKey({ columnType: "text" })
|
||||
id!: string
|
||||
|
||||
@Searchable()
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
name: string | null = null
|
||||
|
||||
@ManyToMany({
|
||||
entity: () => Customer,
|
||||
pivotEntity: () => CustomerGroupCustomer,
|
||||
})
|
||||
customers = new Collection<Customer>(this)
|
||||
|
||||
@Property({ columnType: "jsonb", nullable: true })
|
||||
metadata: Record<string, unknown> | null = null
|
||||
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
created_by: string | null = null
|
||||
|
||||
@Property({
|
||||
onCreate: () => new Date(),
|
||||
columnType: "timestamptz",
|
||||
defaultRaw: "now()",
|
||||
})
|
||||
created_at: Date
|
||||
|
||||
@Property({
|
||||
onCreate: () => new Date(),
|
||||
onUpdate: () => new Date(),
|
||||
columnType: "timestamptz",
|
||||
defaultRaw: "now()",
|
||||
})
|
||||
updated_at: Date
|
||||
|
||||
@Property({ columnType: "timestamptz", nullable: true })
|
||||
deleted_at: Date | null = null
|
||||
|
||||
@BeforeCreate()
|
||||
onCreate() {
|
||||
this.id = generateEntityId(this.id, "cusgroup")
|
||||
}
|
||||
|
||||
@OnInit()
|
||||
onInit() {
|
||||
this.id = generateEntityId(this.id, "cusgroup")
|
||||
}
|
||||
}
|
||||
101
packages/modules/customer/src/models/customer.ts
Normal file
101
packages/modules/customer/src/models/customer.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
import { DAL } from "@medusajs/types"
|
||||
import { DALUtils, Searchable, generateEntityId } from "@medusajs/utils"
|
||||
import {
|
||||
BeforeCreate,
|
||||
Cascade,
|
||||
Collection,
|
||||
Entity,
|
||||
Filter,
|
||||
ManyToMany,
|
||||
OnInit,
|
||||
OneToMany,
|
||||
OptionalProps,
|
||||
PrimaryKey,
|
||||
Property,
|
||||
} from "@mikro-orm/core"
|
||||
import Address from "./address"
|
||||
import CustomerGroup from "./customer-group"
|
||||
import CustomerGroupCustomer from "./customer-group-customer"
|
||||
|
||||
type OptionalCustomerProps =
|
||||
| "groups"
|
||||
| "addresses"
|
||||
| DAL.SoftDeletableEntityDateColumns
|
||||
|
||||
@Entity({ tableName: "customer" })
|
||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||
export default class Customer {
|
||||
[OptionalProps]?: OptionalCustomerProps
|
||||
|
||||
@PrimaryKey({ columnType: "text" })
|
||||
id: string
|
||||
|
||||
@Searchable()
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
company_name: string | null = null
|
||||
|
||||
@Searchable()
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
first_name: string | null = null
|
||||
|
||||
@Searchable()
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
last_name: string | null = null
|
||||
|
||||
@Searchable()
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
email: string | null = null
|
||||
|
||||
@Searchable()
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
phone: string | null = null
|
||||
|
||||
@Property({ columnType: "boolean", default: false })
|
||||
has_account: boolean = false
|
||||
|
||||
@Property({ columnType: "jsonb", nullable: true })
|
||||
metadata: Record<string, unknown> | null = null
|
||||
|
||||
@ManyToMany({
|
||||
mappedBy: "customers",
|
||||
entity: () => CustomerGroup,
|
||||
pivotEntity: () => CustomerGroupCustomer,
|
||||
})
|
||||
groups = new Collection<CustomerGroup>(this)
|
||||
|
||||
@OneToMany(() => Address, (address) => address.customer, {
|
||||
cascade: [Cascade.REMOVE],
|
||||
})
|
||||
addresses = new Collection<Address>(this)
|
||||
|
||||
@Property({
|
||||
onCreate: () => new Date(),
|
||||
columnType: "timestamptz",
|
||||
defaultRaw: "now()",
|
||||
})
|
||||
created_at: Date
|
||||
|
||||
@Property({
|
||||
onCreate: () => new Date(),
|
||||
onUpdate: () => new Date(),
|
||||
columnType: "timestamptz",
|
||||
defaultRaw: "now()",
|
||||
})
|
||||
updated_at: Date
|
||||
|
||||
@Property({ columnType: "timestamptz", nullable: true })
|
||||
deleted_at: Date | null = null
|
||||
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
created_by: string | null = null
|
||||
|
||||
@BeforeCreate()
|
||||
onCreate() {
|
||||
this.id = generateEntityId(this.id, "cus")
|
||||
}
|
||||
|
||||
@OnInit()
|
||||
onInit() {
|
||||
this.id = generateEntityId(this.id, "cus")
|
||||
}
|
||||
}
|
||||
4
packages/modules/customer/src/models/index.ts
Normal file
4
packages/modules/customer/src/models/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export { default as Address } from "./address"
|
||||
export { default as Customer } from "./customer"
|
||||
export { default as CustomerGroup } from "./customer-group"
|
||||
export { default as CustomerGroupCustomer } from "./customer-group-customer"
|
||||
31
packages/modules/customer/src/module-definition.ts
Normal file
31
packages/modules/customer/src/module-definition.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { Modules } from "@medusajs/modules-sdk"
|
||||
import { ModuleExports } from "@medusajs/types"
|
||||
import { ModulesSdkUtils } from "@medusajs/utils"
|
||||
import * as Models from "@models"
|
||||
import { CustomerModuleService } from "@services"
|
||||
import loadConnection from "./loaders/connection"
|
||||
import loadContainer from "./loaders/container"
|
||||
|
||||
const migrationScriptOptions = {
|
||||
moduleName: Modules.CUSTOMER,
|
||||
models: Models,
|
||||
pathToMigrations: __dirname + "/migrations",
|
||||
}
|
||||
|
||||
export const revertMigration = ModulesSdkUtils.buildRevertMigrationScript(
|
||||
migrationScriptOptions
|
||||
)
|
||||
|
||||
export const runMigrations = ModulesSdkUtils.buildMigrationScript(
|
||||
migrationScriptOptions
|
||||
)
|
||||
|
||||
const service = CustomerModuleService
|
||||
const loaders = [loadContainer, loadConnection] as any
|
||||
|
||||
export const moduleDefinition: ModuleExports = {
|
||||
service,
|
||||
loaders,
|
||||
runMigrations,
|
||||
revertMigration,
|
||||
}
|
||||
1
packages/modules/customer/src/repositories/index.ts
Normal file
1
packages/modules/customer/src/repositories/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { MikroOrmBaseRepository as BaseRepository } from "@medusajs/utils"
|
||||
19
packages/modules/customer/src/scripts/bin/run-seed.ts
Normal file
19
packages/modules/customer/src/scripts/bin/run-seed.ts
Normal 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 })
|
||||
})()
|
||||
58
packages/modules/customer/src/scripts/seed.ts
Normal file
58
packages/modules/customer/src/scripts/seed.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
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 CustomerModels 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 { customerData } = 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: customerData.${EOL}${e}`
|
||||
)
|
||||
throw e
|
||||
}
|
||||
)
|
||||
|
||||
const dbData = ModulesSdkUtils.loadDatabaseConfig(Modules.CUSTOMER, options)!
|
||||
const entities = Object.values(CustomerModels) 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 customer data..")
|
||||
|
||||
// TODO: implement customer seed data
|
||||
// await createCustomers(manager, customersData)
|
||||
} catch (e) {
|
||||
logger.error(
|
||||
`Failed to insert the seed data in the PostgreSQL database ${dbData.clientUrl}.${EOL}${e}`
|
||||
)
|
||||
}
|
||||
|
||||
await orm.close(true)
|
||||
}
|
||||
471
packages/modules/customer/src/services/customer-module.ts
Normal file
471
packages/modules/customer/src/services/customer-module.ts
Normal file
@@ -0,0 +1,471 @@
|
||||
import {
|
||||
Context,
|
||||
CustomerDTO,
|
||||
CustomerTypes,
|
||||
DAL,
|
||||
ICustomerModuleService,
|
||||
InternalModuleDeclaration,
|
||||
ModuleJoinerConfig,
|
||||
ModulesSdkTypes,
|
||||
} from "@medusajs/types"
|
||||
|
||||
import {
|
||||
InjectManager,
|
||||
InjectTransactionManager,
|
||||
isString,
|
||||
MedusaContext,
|
||||
ModulesSdkUtils,
|
||||
} from "@medusajs/utils"
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||
import {
|
||||
Address,
|
||||
Customer,
|
||||
CustomerGroup,
|
||||
CustomerGroupCustomer,
|
||||
} from "@models"
|
||||
import { EntityManager } from "@mikro-orm/core"
|
||||
|
||||
type InjectedDependencies = {
|
||||
baseRepository: DAL.RepositoryService
|
||||
customerService: ModulesSdkTypes.InternalModuleService<any>
|
||||
addressService: ModulesSdkTypes.InternalModuleService<any>
|
||||
customerGroupService: ModulesSdkTypes.InternalModuleService<any>
|
||||
customerGroupCustomerService: ModulesSdkTypes.InternalModuleService<any>
|
||||
}
|
||||
|
||||
const generateMethodForModels = [
|
||||
{ model: Address, singular: "Address", plural: "Addresses" },
|
||||
CustomerGroup,
|
||||
CustomerGroupCustomer,
|
||||
]
|
||||
|
||||
export default class CustomerModuleService<
|
||||
TAddress extends Address = Address,
|
||||
TCustomer extends Customer = Customer,
|
||||
TCustomerGroup extends CustomerGroup = CustomerGroup,
|
||||
TCustomerGroupCustomer extends CustomerGroupCustomer = CustomerGroupCustomer
|
||||
>
|
||||
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_: ModulesSdkTypes.InternalModuleService<TCustomer>
|
||||
protected addressService_: ModulesSdkTypes.InternalModuleService<TAddress>
|
||||
protected customerGroupService_: ModulesSdkTypes.InternalModuleService<TCustomerGroup>
|
||||
protected customerGroupCustomerService_: ModulesSdkTypes.InternalModuleService<TCustomerGroupCustomer>
|
||||
|
||||
constructor(
|
||||
{
|
||||
baseRepository,
|
||||
customerService,
|
||||
addressService,
|
||||
customerGroupService,
|
||||
customerGroupCustomerService,
|
||||
}: InjectedDependencies,
|
||||
protected readonly moduleDeclaration: InternalModuleDeclaration
|
||||
) {
|
||||
// @ts-ignore
|
||||
super(...arguments)
|
||||
|
||||
this.baseRepository_ = baseRepository
|
||||
this.customerService_ = customerService
|
||||
this.addressService_ = addressService
|
||||
this.customerGroupService_ = customerGroupService
|
||||
this.customerGroupCustomerService_ = customerGroupCustomerService
|
||||
}
|
||||
|
||||
__joinerConfig(): ModuleJoinerConfig {
|
||||
return joinerConfig
|
||||
}
|
||||
|
||||
async create(
|
||||
data: CustomerTypes.CreateCustomerDTO,
|
||||
sharedContext?: Context
|
||||
): Promise<CustomerTypes.CustomerDTO>
|
||||
|
||||
async create(
|
||||
data: CustomerTypes.CreateCustomerDTO[],
|
||||
sharedContext?: Context
|
||||
): Promise<CustomerTypes.CustomerDTO[]>
|
||||
|
||||
@InjectManager("baseRepository_")
|
||||
async create(
|
||||
dataOrArray:
|
||||
| CustomerTypes.CreateCustomerDTO
|
||||
| CustomerTypes.CreateCustomerDTO[],
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<CustomerTypes.CustomerDTO | CustomerTypes.CustomerDTO[]> {
|
||||
const customers = await this.create_(dataOrArray, sharedContext)
|
||||
|
||||
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)
|
||||
|
||||
const addressDataWithCustomerIds = data
|
||||
.map(({ addresses }, i) => {
|
||||
if (!addresses) {
|
||||
return []
|
||||
}
|
||||
|
||||
return addresses.map((address) => ({
|
||||
...address,
|
||||
customer_id: customers[i].id,
|
||||
}))
|
||||
})
|
||||
.flat()
|
||||
|
||||
await this.addAddresses(addressDataWithCustomerIds, sharedContext)
|
||||
|
||||
return customers as unknown as CustomerTypes.CustomerDTO[]
|
||||
}
|
||||
|
||||
update(
|
||||
customerId: string,
|
||||
data: CustomerTypes.CustomerUpdatableFields,
|
||||
sharedContext?: Context
|
||||
): Promise<CustomerTypes.CustomerDTO>
|
||||
update(
|
||||
customerIds: string[],
|
||||
data: CustomerTypes.CustomerUpdatableFields,
|
||||
sharedContext?: Context
|
||||
): Promise<CustomerTypes.CustomerDTO[]>
|
||||
update(
|
||||
selector: CustomerTypes.FilterableCustomerProps,
|
||||
data: CustomerTypes.CustomerUpdatableFields,
|
||||
sharedContext?: Context
|
||||
): Promise<CustomerTypes.CustomerDTO[]>
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
async update(
|
||||
idsOrSelector: string | string[] | CustomerTypes.FilterableCustomerProps,
|
||||
data: CustomerTypes.CustomerUpdatableFields,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
) {
|
||||
let updateData:
|
||||
| CustomerTypes.UpdateCustomerDTO
|
||||
| CustomerTypes.UpdateCustomerDTO[]
|
||||
| {
|
||||
selector: CustomerTypes.FilterableCustomerProps
|
||||
data: CustomerTypes.CustomerUpdatableFields
|
||||
}
|
||||
|
||||
if (isString(idsOrSelector)) {
|
||||
updateData = {
|
||||
id: idsOrSelector,
|
||||
...data,
|
||||
}
|
||||
} else if (Array.isArray(idsOrSelector)) {
|
||||
updateData = idsOrSelector.map((id) => ({
|
||||
id,
|
||||
...data,
|
||||
}))
|
||||
} else {
|
||||
updateData = {
|
||||
selector: idsOrSelector,
|
||||
data: data,
|
||||
}
|
||||
}
|
||||
|
||||
const customers = await this.customerService_.update(
|
||||
updateData,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
const serialized = await this.baseRepository_.serialize<
|
||||
CustomerTypes.CustomerDTO | CustomerTypes.CustomerDTO[]
|
||||
>(customers, {
|
||||
populate: true,
|
||||
})
|
||||
|
||||
return isString(idsOrSelector) ? serialized[0] : serialized
|
||||
}
|
||||
|
||||
async createCustomerGroup(
|
||||
dataOrArrayOfData: CustomerTypes.CreateCustomerGroupDTO,
|
||||
sharedContext?: Context
|
||||
): Promise<CustomerTypes.CustomerGroupDTO>
|
||||
|
||||
async createCustomerGroup(
|
||||
dataOrArrayOfData: CustomerTypes.CreateCustomerGroupDTO[],
|
||||
sharedContext?: Context
|
||||
): Promise<CustomerTypes.CustomerGroupDTO[]>
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
async createCustomerGroup(
|
||||
dataOrArrayOfData:
|
||||
| CustomerTypes.CreateCustomerGroupDTO
|
||||
| CustomerTypes.CreateCustomerGroupDTO[],
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
) {
|
||||
const groups = await this.customerGroupService_.create(
|
||||
dataOrArrayOfData,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
return await this.baseRepository_.serialize<
|
||||
CustomerTypes.CustomerGroupDTO | CustomerTypes.CustomerGroupDTO[]
|
||||
>(groups, {
|
||||
populate: true,
|
||||
})
|
||||
}
|
||||
|
||||
async updateCustomerGroups(
|
||||
groupId: string,
|
||||
data: CustomerTypes.CustomerGroupUpdatableFields,
|
||||
sharedContext?: Context
|
||||
): Promise<CustomerTypes.CustomerGroupDTO>
|
||||
async updateCustomerGroups(
|
||||
groupIds: string[],
|
||||
data: CustomerTypes.CustomerGroupUpdatableFields,
|
||||
sharedContext?: Context
|
||||
): Promise<CustomerTypes.CustomerGroupDTO[]>
|
||||
async updateCustomerGroups(
|
||||
selector: CustomerTypes.FilterableCustomerGroupProps,
|
||||
data: CustomerTypes.CustomerGroupUpdatableFields,
|
||||
sharedContext?: Context
|
||||
): Promise<CustomerTypes.CustomerGroupDTO[]>
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
async updateCustomerGroups(
|
||||
groupIdOrSelector:
|
||||
| string
|
||||
| string[]
|
||||
| CustomerTypes.FilterableCustomerGroupProps,
|
||||
data: CustomerTypes.CustomerGroupUpdatableFields,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
) {
|
||||
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 {
|
||||
updateData = {
|
||||
selector: groupIdOrSelector,
|
||||
data: data,
|
||||
}
|
||||
}
|
||||
|
||||
const groups = await this.customerGroupService_.update(
|
||||
updateData,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
if (isString(groupIdOrSelector)) {
|
||||
return await this.baseRepository_.serialize<CustomerTypes.CustomerGroupDTO>(
|
||||
groups[0],
|
||||
{ populate: true }
|
||||
)
|
||||
}
|
||||
|
||||
return await this.baseRepository_.serialize<
|
||||
CustomerTypes.CustomerGroupDTO[]
|
||||
>(groups, { populate: true })
|
||||
}
|
||||
|
||||
async addCustomerToGroup(
|
||||
groupCustomerPair: CustomerTypes.GroupCustomerPair,
|
||||
sharedContext?: Context
|
||||
): Promise<{ id: string }>
|
||||
|
||||
async addCustomerToGroup(
|
||||
groupCustomerPairs: CustomerTypes.GroupCustomerPair[],
|
||||
sharedContext?: Context
|
||||
): Promise<{ id: string }[]>
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
async addCustomerToGroup(
|
||||
data: CustomerTypes.GroupCustomerPair | CustomerTypes.GroupCustomerPair[],
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<{ id: string } | { id: string }[]> {
|
||||
const groupCustomers = await this.customerGroupCustomerService_.create(
|
||||
data,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
if (Array.isArray(data)) {
|
||||
return (groupCustomers as unknown as TCustomerGroupCustomer[]).map(
|
||||
(gc) => ({ id: gc.id })
|
||||
)
|
||||
}
|
||||
|
||||
return { id: groupCustomers.id }
|
||||
}
|
||||
|
||||
// TODO: should be createAddresses to conform to the convention
|
||||
async addAddresses(
|
||||
addresses: CustomerTypes.CreateCustomerAddressDTO[],
|
||||
sharedContext?: Context
|
||||
): Promise<CustomerTypes.CustomerAddressDTO[]>
|
||||
async addAddresses(
|
||||
address: CustomerTypes.CreateCustomerAddressDTO,
|
||||
sharedContext?: Context
|
||||
): Promise<CustomerTypes.CustomerAddressDTO>
|
||||
|
||||
@InjectManager("baseRepository_")
|
||||
async addAddresses(
|
||||
data:
|
||||
| CustomerTypes.CreateCustomerAddressDTO
|
||||
| CustomerTypes.CreateCustomerAddressDTO[],
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<
|
||||
CustomerTypes.CustomerAddressDTO | CustomerTypes.CustomerAddressDTO[]
|
||||
> {
|
||||
const addresses = await this.addAddresses_(data, sharedContext)
|
||||
|
||||
const serialized = await this.baseRepository_.serialize<
|
||||
CustomerTypes.CustomerAddressDTO[]
|
||||
>(addresses, { populate: true })
|
||||
|
||||
if (Array.isArray(data)) {
|
||||
return serialized
|
||||
}
|
||||
|
||||
return serialized[0]
|
||||
}
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
private async addAddresses_(
|
||||
data:
|
||||
| CustomerTypes.CreateCustomerAddressDTO
|
||||
| CustomerTypes.CreateCustomerAddressDTO[],
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
) {
|
||||
return await this.addressService_.create(
|
||||
Array.isArray(data) ? data : [data],
|
||||
sharedContext
|
||||
)
|
||||
}
|
||||
|
||||
async updateAddresses(
|
||||
addressId: string,
|
||||
data: CustomerTypes.UpdateCustomerAddressDTO,
|
||||
sharedContext?: Context
|
||||
): Promise<CustomerTypes.CustomerAddressDTO>
|
||||
async updateAddresses(
|
||||
addressIds: string[],
|
||||
data: CustomerTypes.UpdateCustomerAddressDTO,
|
||||
sharedContext?: Context
|
||||
): Promise<CustomerTypes.CustomerAddressDTO[]>
|
||||
async updateAddresses(
|
||||
selector: CustomerTypes.FilterableCustomerAddressProps,
|
||||
data: CustomerTypes.UpdateCustomerAddressDTO,
|
||||
sharedContext?: Context
|
||||
): Promise<CustomerTypes.CustomerAddressDTO[]>
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
async updateAddresses(
|
||||
addressIdOrSelector:
|
||||
| string
|
||||
| string[]
|
||||
| CustomerTypes.FilterableCustomerAddressProps,
|
||||
data: CustomerTypes.UpdateCustomerAddressDTO,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
) {
|
||||
let updateData:
|
||||
| CustomerTypes.UpdateCustomerAddressDTO[]
|
||||
| {
|
||||
selector: CustomerTypes.FilterableCustomerAddressProps
|
||||
data: CustomerTypes.UpdateCustomerAddressDTO
|
||||
}
|
||||
if (isString(addressIdOrSelector)) {
|
||||
updateData = [
|
||||
{
|
||||
id: addressIdOrSelector,
|
||||
...data,
|
||||
},
|
||||
]
|
||||
} else if (Array.isArray(addressIdOrSelector)) {
|
||||
updateData = addressIdOrSelector.map((id) => ({
|
||||
id,
|
||||
...data,
|
||||
}))
|
||||
} else {
|
||||
updateData = {
|
||||
selector: addressIdOrSelector,
|
||||
data,
|
||||
}
|
||||
}
|
||||
|
||||
const addresses = await this.addressService_.update(
|
||||
updateData,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
await this.flush(sharedContext)
|
||||
|
||||
const serialized = await this.baseRepository_.serialize<
|
||||
CustomerTypes.CustomerAddressDTO[]
|
||||
>(addresses, { populate: true })
|
||||
|
||||
if (isString(addressIdOrSelector)) {
|
||||
return serialized[0]
|
||||
}
|
||||
|
||||
return serialized
|
||||
}
|
||||
|
||||
async removeCustomerFromGroup(
|
||||
groupCustomerPair: CustomerTypes.GroupCustomerPair,
|
||||
sharedContext?: Context
|
||||
): Promise<void>
|
||||
async removeCustomerFromGroup(
|
||||
groupCustomerPairs: CustomerTypes.GroupCustomerPair[],
|
||||
sharedContext?: Context
|
||||
): Promise<void>
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
async removeCustomerFromGroup(
|
||||
data: CustomerTypes.GroupCustomerPair | CustomerTypes.GroupCustomerPair[],
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<void> {
|
||||
const pairs = Array.isArray(data) ? data : [data]
|
||||
const groupCustomers = await this.customerGroupCustomerService_.list({
|
||||
$or: pairs,
|
||||
})
|
||||
await this.customerGroupCustomerService_.delete(
|
||||
groupCustomers.map((gc) => gc.id),
|
||||
sharedContext
|
||||
)
|
||||
}
|
||||
|
||||
private async flush(context: Context) {
|
||||
const em = (context.manager ?? context.transactionManager) as EntityManager
|
||||
await em.flush()
|
||||
}
|
||||
}
|
||||
1
packages/modules/customer/src/services/index.ts
Normal file
1
packages/modules/customer/src/services/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { default as CustomerModuleService } from "./customer-module"
|
||||
8
packages/modules/customer/src/types/index.ts
Normal file
8
packages/modules/customer/src/types/index.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Logger } from "@medusajs/types"
|
||||
|
||||
export * as ServiceTypes from "./services"
|
||||
export * from "./services"
|
||||
|
||||
export type InitializeModuleInjectableDependencies = {
|
||||
logger?: Logger
|
||||
}
|
||||
28
packages/modules/customer/src/types/services/address.ts
Normal file
28
packages/modules/customer/src/types/services/address.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
export type CreateAddressDTO = {
|
||||
customer_id: string
|
||||
company?: string | null
|
||||
first_name?: string | null
|
||||
last_name?: string | null
|
||||
address_1?: string | null
|
||||
address_2?: string | null
|
||||
city?: string | null
|
||||
country_code?: string | null
|
||||
province?: string | null
|
||||
postal_code?: string | null
|
||||
phone?: string | null
|
||||
metadata?: Record<string, unknown> | null
|
||||
}
|
||||
|
||||
export type UpdateAddressDTO = {
|
||||
company?: string | null
|
||||
first_name?: string | null
|
||||
last_name?: string | null
|
||||
address_1?: string | null
|
||||
address_2?: string | null
|
||||
city?: string | null
|
||||
country_code?: string | null
|
||||
province?: string | null
|
||||
postal_code?: string | null
|
||||
phone?: string | null
|
||||
metadata?: Record<string, unknown> | null
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export interface CreateCustomerGroupCustomerDTO {
|
||||
customer_id: string
|
||||
customer_group_id: string
|
||||
created_by?: string
|
||||
}
|
||||
2
packages/modules/customer/src/types/services/index.ts
Normal file
2
packages/modules/customer/src/types/services/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from "./address"
|
||||
export * from "./customer-group-customer"
|
||||
Reference in New Issue
Block a user