feat: sales channel module (#5923)
This commit is contained in:
1 parent
dfd9e7c772
commit
3db2f95e65
54 files changed
+1364
-61
No files matched your search
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/core-flows": patch
|
||||||
|
"@medusajs/link-modules": patch
|
||||||
|
"@medusajs/medusa": patch
|
||||||
|
"@medusajs/modules-sdk": patch
|
||||||
|
"@medusajs/types": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
feat: Sales Channel module
|
||||||
@@ -71,5 +71,10 @@ module.exports = {
|
|||||||
resources: "shared",
|
resources: "shared",
|
||||||
resolve: "@medusajs/promotion",
|
resolve: "@medusajs/promotion",
|
||||||
},
|
},
|
||||||
|
[Modules.SALES_CHANNEL]: {
|
||||||
|
scope: "internal",
|
||||||
|
resources: "shared",
|
||||||
|
resolve: "@medusajs/sales-channel",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { MedusaV2Flag } from "@medusajs/utils"
|
import { MedusaV2Flag } from "@medusajs/utils"
|
||||||
import { WorkflowArguments } from "@medusajs/workflows-sdk"
|
import { WorkflowArguments } from "@medusajs/workflows-sdk"
|
||||||
|
import { Modules } from "@medusajs/modules-sdk"
|
||||||
|
|
||||||
type HandlerInputData = {
|
type HandlerInputData = {
|
||||||
cart: {
|
cart: {
|
||||||
@@ -30,10 +31,10 @@ export async function attachCartToSalesChannel({
|
|||||||
const salesChannel = data[Aliases.SalesChannel]
|
const salesChannel = data[Aliases.SalesChannel]
|
||||||
|
|
||||||
await remoteLink.create({
|
await remoteLink.create({
|
||||||
cartService: {
|
[Modules.CART]: {
|
||||||
cart_id: cart.id,
|
cart_id: cart.id,
|
||||||
},
|
},
|
||||||
salesChannelService: {
|
[Modules.SALES_CHANNEL]: {
|
||||||
sales_channel_id: salesChannel.sales_channel_id,
|
sales_channel_id: salesChannel.sales_channel_id,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { MedusaV2Flag } from "@medusajs/utils"
|
import { MedusaV2Flag } from "@medusajs/utils"
|
||||||
import { WorkflowArguments } from "@medusajs/workflows-sdk"
|
import { WorkflowArguments } from "@medusajs/workflows-sdk"
|
||||||
|
import { Modules } from "@medusajs/modules-sdk"
|
||||||
|
|
||||||
type HandlerInputData = {
|
type HandlerInputData = {
|
||||||
cart: {
|
cart: {
|
||||||
@@ -30,10 +31,10 @@ export async function detachCartFromSalesChannel({
|
|||||||
const salesChannel = data[Aliases.SalesChannel]
|
const salesChannel = data[Aliases.SalesChannel]
|
||||||
|
|
||||||
await remoteLink.dismiss({
|
await remoteLink.dismiss({
|
||||||
cartService: {
|
[Modules.CART]: {
|
||||||
cart_id: cart.id,
|
cart_id: cart.id,
|
||||||
},
|
},
|
||||||
salesChannelService: {
|
[Modules.SALES_CHANNEL]: {
|
||||||
sales_channel_id: salesChannel.sales_channel_id,
|
sales_channel_id: salesChannel.sales_channel_id,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ export async function attachSalesChannelToProducts({
|
|||||||
[Modules.PRODUCT]: {
|
[Modules.PRODUCT]: {
|
||||||
product_id: id,
|
product_id: id,
|
||||||
},
|
},
|
||||||
salesChannelService: {
|
[Modules.SALES_CHANNEL]: {
|
||||||
sales_channel_id: salesChannelId,
|
sales_channel_id: salesChannelId,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ export async function detachSalesChannelFromProducts({
|
|||||||
[Modules.PRODUCT]: {
|
[Modules.PRODUCT]: {
|
||||||
product_id: id,
|
product_id: id,
|
||||||
},
|
},
|
||||||
salesChannelService: {
|
[Modules.SALES_CHANNEL]: {
|
||||||
sales_channel_id: salesChannelId,
|
sales_channel_id: salesChannelId,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { ModuleJoinerConfig } from "@medusajs/types"
|
import { ModuleJoinerConfig } from "@medusajs/types"
|
||||||
import { LINKS } from "../links"
|
import { LINKS } from "../links"
|
||||||
|
import { Modules } from "@medusajs/modules-sdk"
|
||||||
|
|
||||||
export const CartSalesChannel: ModuleJoinerConfig = {
|
export const CartSalesChannel: ModuleJoinerConfig = {
|
||||||
serviceName: LINKS.CartSalesChannel,
|
serviceName: LINKS.CartSalesChannel,
|
||||||
@@ -19,14 +20,14 @@ export const CartSalesChannel: ModuleJoinerConfig = {
|
|||||||
primaryKeys: ["id", "cart_id", "sales_channel_id"],
|
primaryKeys: ["id", "cart_id", "sales_channel_id"],
|
||||||
relationships: [
|
relationships: [
|
||||||
{
|
{
|
||||||
serviceName: "cartService",
|
serviceName: Modules.CART,
|
||||||
isInternalService: true,
|
isInternalService: true,
|
||||||
primaryKey: "id",
|
primaryKey: "id",
|
||||||
foreignKey: "cart_id",
|
foreignKey: "cart_id",
|
||||||
alias: "cart",
|
alias: "cart",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
serviceName: "salesChannelService",
|
serviceName: Modules.SALES_CHANNEL,
|
||||||
isInternalService: true,
|
isInternalService: true,
|
||||||
primaryKey: "id",
|
primaryKey: "id",
|
||||||
foreignKey: "sales_channel_id",
|
foreignKey: "sales_channel_id",
|
||||||
@@ -35,7 +36,7 @@ export const CartSalesChannel: ModuleJoinerConfig = {
|
|||||||
],
|
],
|
||||||
extends: [
|
extends: [
|
||||||
{
|
{
|
||||||
serviceName: "cartService",
|
serviceName: Modules.CART,
|
||||||
fieldAlias: {
|
fieldAlias: {
|
||||||
sales_channel: "sales_channel_link.sales_channel",
|
sales_channel: "sales_channel_link.sales_channel",
|
||||||
},
|
},
|
||||||
@@ -48,7 +49,7 @@ export const CartSalesChannel: ModuleJoinerConfig = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
serviceName: "salesChannelService",
|
serviceName: Modules.SALES_CHANNEL,
|
||||||
fieldAlias: {
|
fieldAlias: {
|
||||||
carts: "cart_link.cart",
|
carts: "cart_link.cart",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export const ProductSalesChannel: ModuleJoinerConfig = {
|
|||||||
alias: "product",
|
alias: "product",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
serviceName: "salesChannelService",
|
serviceName: Modules.SALES_CHANNEL,
|
||||||
isInternalService: true,
|
isInternalService: true,
|
||||||
primaryKey: "id",
|
primaryKey: "id",
|
||||||
foreignKey: "sales_channel_id",
|
foreignKey: "sales_channel_id",
|
||||||
@@ -48,7 +48,7 @@ export const ProductSalesChannel: ModuleJoinerConfig = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
serviceName: "salesChannelService",
|
serviceName: Modules.SALES_CHANNEL,
|
||||||
relationship: {
|
relationship: {
|
||||||
serviceName: LINKS.ProductSalesChannel,
|
serviceName: LINKS.ProductSalesChannel,
|
||||||
isInternalService: true,
|
isInternalService: true,
|
||||||
|
|||||||
@@ -25,25 +25,25 @@ export const LINKS = {
|
|||||||
ProductSalesChannel: composeLinkName(
|
ProductSalesChannel: composeLinkName(
|
||||||
Modules.PRODUCT,
|
Modules.PRODUCT,
|
||||||
"product_id",
|
"product_id",
|
||||||
"salesChannelService",
|
Modules.SALES_CHANNEL,
|
||||||
"sales_channel_id"
|
"sales_channel_id"
|
||||||
),
|
),
|
||||||
CartSalesChannel: composeLinkName(
|
CartSalesChannel: composeLinkName(
|
||||||
"cartService",
|
Modules.CART,
|
||||||
"cart_id",
|
"cart_id",
|
||||||
"salesChannelService",
|
Modules.SALES_CHANNEL,
|
||||||
"sales_channel_id"
|
"sales_channel_id"
|
||||||
),
|
),
|
||||||
OrderSalesChannel: composeLinkName(
|
OrderSalesChannel: composeLinkName(
|
||||||
"orderService",
|
"orderService",
|
||||||
"order_id",
|
"order_id",
|
||||||
"salesChannelService",
|
Modules.SALES_CHANNEL,
|
||||||
"sales_channel_id"
|
"sales_channel_id"
|
||||||
),
|
),
|
||||||
PublishableApiKeySalesChannel: composeLinkName(
|
PublishableApiKeySalesChannel: composeLinkName(
|
||||||
"publishableApiKeyService",
|
"publishableApiKeyService",
|
||||||
"publishable_key_id",
|
"publishable_key_id",
|
||||||
"salesChannelService",
|
Modules.SALES_CHANNEL,
|
||||||
"sales_channel_id"
|
"sales_channel_id"
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,7 @@ import { ModuleJoinerConfig } from "@medusajs/types"
|
|||||||
import { Cart } from "../models"
|
import { Cart } from "../models"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
serviceName: "cartService",
|
serviceName: Modules.CART,
|
||||||
primaryKeys: ["id"],
|
primaryKeys: ["id"],
|
||||||
linkableKeys: { cart_id: "Cart" },
|
linkableKeys: { cart_id: "Cart" },
|
||||||
alias: {
|
alias: {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
export * as cart from "./cart-service"
|
export * as cart from "./cart-service"
|
||||||
export * as customer from "./customer-service"
|
export * as customer from "./customer-service"
|
||||||
export * as region from "./region-service"
|
export * as region from "./region-service"
|
||||||
export * as salesChannel from "./sales-channel-service"
|
|
||||||
export * as shippingProfile from "./shipping-profile-service"
|
export * as shippingProfile from "./shipping-profile-service"
|
||||||
export * as publishableApiKey from "./publishable-api-key-service"
|
export * as publishableApiKey from "./publishable-api-key-service"
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
import { ModuleJoinerConfig } from "@medusajs/types"
|
|
||||||
|
|
||||||
export default {
|
|
||||||
serviceName: "salesChannelService",
|
|
||||||
primaryKeys: ["id"],
|
|
||||||
linkableKeys: { sales_channel_id: "SalesChannel" },
|
|
||||||
schema: `
|
|
||||||
scalar Date
|
|
||||||
scalar JSON
|
|
||||||
|
|
||||||
type SalesChannel {
|
|
||||||
id: ID!
|
|
||||||
name: String!
|
|
||||||
description: String!
|
|
||||||
is_disabled: Boolean
|
|
||||||
created_at: Date!
|
|
||||||
updated_at: Date!
|
|
||||||
deleted_at: Date
|
|
||||||
metadata: JSON
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
alias: [
|
|
||||||
{
|
|
||||||
name: "sales_channel",
|
|
||||||
args: { entity: "SalesChannel" },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "sales_channels",
|
|
||||||
args: { entity: "SalesChannel" },
|
|
||||||
},
|
|
||||||
],
|
|
||||||
} as ModuleJoinerConfig
|
|
||||||
@@ -69,7 +69,7 @@ import { ShippingMethodRepository } from "../repositories/shipping-method"
|
|||||||
import { PaymentSessionInput } from "../types/payment"
|
import { PaymentSessionInput } from "../types/payment"
|
||||||
import { validateEmail } from "../utils/is-email"
|
import { validateEmail } from "../utils/is-email"
|
||||||
import { RemoteQueryFunction } from "@medusajs/types"
|
import { RemoteQueryFunction } from "@medusajs/types"
|
||||||
import { RemoteLink } from "@medusajs/modules-sdk"
|
import { Modules, RemoteLink } from "@medusajs/modules-sdk"
|
||||||
|
|
||||||
type InjectedDependencies = {
|
type InjectedDependencies = {
|
||||||
manager: EntityManager
|
manager: EntityManager
|
||||||
@@ -501,10 +501,10 @@ class CartService extends TransactionBaseService {
|
|||||||
)
|
)
|
||||||
|
|
||||||
await this.remoteLink_.create({
|
await this.remoteLink_.create({
|
||||||
cartService: {
|
[Modules.CART]: {
|
||||||
cart_id: cart.id,
|
cart_id: cart.id,
|
||||||
},
|
},
|
||||||
salesChannelService: {
|
[Modules.SALES_CHANNEL]: {
|
||||||
sales_channel_id: salesChannel.id,
|
sales_channel_id: salesChannel.id,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -1294,20 +1294,20 @@ class CartService extends TransactionBaseService {
|
|||||||
if (this.featureFlagRouter_.isFeatureEnabled(MedusaV2Flag.key)) {
|
if (this.featureFlagRouter_.isFeatureEnabled(MedusaV2Flag.key)) {
|
||||||
if (cart.sales_channel_id) {
|
if (cart.sales_channel_id) {
|
||||||
await this.remoteLink_.dismiss({
|
await this.remoteLink_.dismiss({
|
||||||
cartService: {
|
[Modules.CART]: {
|
||||||
cart_id: cart.id,
|
cart_id: cart.id,
|
||||||
},
|
},
|
||||||
salesChannelService: {
|
[Modules.SALES_CHANNEL]: {
|
||||||
sales_channel_id: cart.sales_channel_id,
|
sales_channel_id: cart.sales_channel_id,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.remoteLink_.create({
|
await this.remoteLink_.create({
|
||||||
cartService: {
|
[Modules.CART]: {
|
||||||
cart_id: cart.id,
|
cart_id: cart.id,
|
||||||
},
|
},
|
||||||
salesChannelService: {
|
[Modules.SALES_CHANNEL]: {
|
||||||
sales_channel_id: salesChannel.id,
|
sales_channel_id: salesChannel.id,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ export enum Modules {
|
|||||||
PROMOTION = "promotion",
|
PROMOTION = "promotion",
|
||||||
AUTHENTICATION = "authentication",
|
AUTHENTICATION = "authentication",
|
||||||
WORKFLOW_ENGINE = "workflows",
|
WORKFLOW_ENGINE = "workflows",
|
||||||
|
SALES_CHANNEL = "salesChannel",
|
||||||
CART = "cart",
|
CART = "cart",
|
||||||
CUSTOMER = "customer",
|
CUSTOMER = "customer",
|
||||||
PAYMENT = "payment",
|
PAYMENT = "payment",
|
||||||
@@ -32,6 +33,7 @@ export enum ModuleRegistrationName {
|
|||||||
PROMOTION = "promotionModuleService",
|
PROMOTION = "promotionModuleService",
|
||||||
AUTHENTICATION = "authenticationModuleService",
|
AUTHENTICATION = "authenticationModuleService",
|
||||||
WORKFLOW_ENGINE = "workflowsModuleService",
|
WORKFLOW_ENGINE = "workflowsModuleService",
|
||||||
|
SALES_CHANNEL = "salesChannelModuleService",
|
||||||
CART = "cartModuleService",
|
CART = "cartModuleService",
|
||||||
CUSTOMER = "customerModuleService",
|
CUSTOMER = "customerModuleService",
|
||||||
PAYMENT = "paymentModuleService",
|
PAYMENT = "paymentModuleService",
|
||||||
@@ -48,6 +50,7 @@ export const MODULE_PACKAGE_NAMES = {
|
|||||||
[Modules.PROMOTION]: "@medusajs/promotion",
|
[Modules.PROMOTION]: "@medusajs/promotion",
|
||||||
[Modules.AUTHENTICATION]: "@medusajs/authentication",
|
[Modules.AUTHENTICATION]: "@medusajs/authentication",
|
||||||
[Modules.WORKFLOW_ENGINE]: "@medusajs/workflow-engine-inmemory",
|
[Modules.WORKFLOW_ENGINE]: "@medusajs/workflow-engine-inmemory",
|
||||||
|
[Modules.SALES_CHANNEL]: "@medusajs/sales-channel",
|
||||||
[Modules.CART]: "@medusajs/cart",
|
[Modules.CART]: "@medusajs/cart",
|
||||||
[Modules.CUSTOMER]: "@medusajs/customer",
|
[Modules.CUSTOMER]: "@medusajs/customer",
|
||||||
[Modules.PAYMENT]: "@medusajs/payment",
|
[Modules.PAYMENT]: "@medusajs/payment",
|
||||||
@@ -182,6 +185,20 @@ export const ModulesDefinition: { [key: string | Modules]: ModuleDefinition } =
|
|||||||
resources: MODULE_RESOURCE_TYPE.SHARED,
|
resources: MODULE_RESOURCE_TYPE.SHARED,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
[Modules.SALES_CHANNEL]: {
|
||||||
|
key: Modules.SALES_CHANNEL,
|
||||||
|
registrationName: ModuleRegistrationName.SALES_CHANNEL,
|
||||||
|
defaultPackage: false,
|
||||||
|
label: upperCaseFirst(ModuleRegistrationName.SALES_CHANNEL),
|
||||||
|
isRequired: false,
|
||||||
|
canOverride: true,
|
||||||
|
isQueryable: true,
|
||||||
|
dependencies: ["logger"],
|
||||||
|
defaultModuleDeclaration: {
|
||||||
|
scope: MODULE_SCOPE.INTERNAL,
|
||||||
|
resources: MODULE_RESOURCE_TYPE.SHARED,
|
||||||
|
},
|
||||||
|
},
|
||||||
[Modules.CART]: {
|
[Modules.CART]: {
|
||||||
key: Modules.CART,
|
key: Modules.CART,
|
||||||
registrationName: ModuleRegistrationName.CART,
|
registrationName: ModuleRegistrationName.CART,
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
/dist
|
||||||
|
node_modules
|
||||||
|
.DS_store
|
||||||
|
.env*
|
||||||
|
.env
|
||||||
|
*.sql
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# Sales Channel Module
|
||||||
|
|
||||||
|
Sales Channel module enables management of sales channels that are used for grouping Products/Carts/Orders etc.
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
||||||
|
import { SalesChannel } from "@models"
|
||||||
|
|
||||||
|
const salesChannelData = [
|
||||||
|
{
|
||||||
|
id: "channel-1",
|
||||||
|
name: "Channel 1",
|
||||||
|
description: "Channel description 1",
|
||||||
|
is_disabled: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "channel-2",
|
||||||
|
name: "Channel 2",
|
||||||
|
description: "Channel description 2",
|
||||||
|
is_disabled: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "channel-3",
|
||||||
|
name: "Channel 3",
|
||||||
|
description: "Channel description 3",
|
||||||
|
is_disabled: true,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
export async function createSalesChannels(
|
||||||
|
manager: SqlEntityManager,
|
||||||
|
channelData: any[] = salesChannelData
|
||||||
|
): Promise<SalesChannel[]> {
|
||||||
|
const channels: SalesChannel[] = []
|
||||||
|
|
||||||
|
for (let data of channelData) {
|
||||||
|
const sc = manager.create(SalesChannel, data)
|
||||||
|
|
||||||
|
channels.push(sc)
|
||||||
|
}
|
||||||
|
|
||||||
|
await manager.persistAndFlush(channels)
|
||||||
|
|
||||||
|
return channels
|
||||||
|
}
|
||||||
+248
@@ -0,0 +1,248 @@
|
|||||||
|
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
||||||
|
|
||||||
|
import { ISalesChannelModuleService } from "@medusajs/types"
|
||||||
|
|
||||||
|
import { initialize } from "../../../src"
|
||||||
|
|
||||||
|
import { DB_URL, MikroOrmWrapper } from "../../utils"
|
||||||
|
import { createSalesChannels } from "../../__fixtures__"
|
||||||
|
|
||||||
|
jest.setTimeout(30000)
|
||||||
|
|
||||||
|
describe("Sales Channel Service", () => {
|
||||||
|
let service: ISalesChannelModuleService
|
||||||
|
let testManager: SqlEntityManager
|
||||||
|
let repositoryManager: SqlEntityManager
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await MikroOrmWrapper.setupDatabase()
|
||||||
|
repositoryManager = await MikroOrmWrapper.forkManager()
|
||||||
|
|
||||||
|
service = await initialize({
|
||||||
|
database: {
|
||||||
|
clientUrl: DB_URL,
|
||||||
|
schema: process.env.MEDUSA_SALES_CHANNEL_DB_SCHEMA,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
testManager = await MikroOrmWrapper.forkManager()
|
||||||
|
|
||||||
|
await createSalesChannels(testManager)
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await MikroOrmWrapper.clearDatabase()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("create", () => {
|
||||||
|
it("should create a SalesChannel successfully", async () => {
|
||||||
|
const [created] = await service.create([
|
||||||
|
{
|
||||||
|
name: "test",
|
||||||
|
description: "test",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const [channel] = await service.list({
|
||||||
|
name: [created.name],
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(channel.name).toEqual("test")
|
||||||
|
expect(channel.description).toEqual("test")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("retrieve", () => {
|
||||||
|
const id = "channel-1"
|
||||||
|
|
||||||
|
it("should return SalesChannel for the given id", async () => {
|
||||||
|
const result = await service.retrieve(id)
|
||||||
|
|
||||||
|
expect(result).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should throw an error when SalesChannelId with id does not exist", async () => {
|
||||||
|
let error
|
||||||
|
|
||||||
|
try {
|
||||||
|
await service.retrieve("does-not-exist")
|
||||||
|
} catch (e) {
|
||||||
|
error = e
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error.message).toEqual(
|
||||||
|
"SalesChannel with id: does-not-exist was not found"
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("update", () => {
|
||||||
|
const id = "channel-2"
|
||||||
|
|
||||||
|
it("should update the name of the SalesChannel successfully", async () => {
|
||||||
|
await service.update([
|
||||||
|
{
|
||||||
|
id,
|
||||||
|
name: "Update name 2",
|
||||||
|
is_disabled: true,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const channel = await service.retrieve(id)
|
||||||
|
|
||||||
|
expect(channel.name).toEqual("Update name 2")
|
||||||
|
expect(channel.is_disabled).toEqual(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should throw an error when a id does not exist", async () => {
|
||||||
|
let error
|
||||||
|
|
||||||
|
try {
|
||||||
|
await service.update([
|
||||||
|
{
|
||||||
|
id: "does-not-exist",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
} catch (e) {
|
||||||
|
error = e
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error.message).toEqual(
|
||||||
|
'SalesChannel with id "does-not-exist" not found'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("list", () => {
|
||||||
|
it("should return a list of SalesChannels", async () => {
|
||||||
|
const result = await service.list()
|
||||||
|
|
||||||
|
expect(result).toEqual([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: "channel-1",
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
id: "channel-2",
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
id: "channel-3",
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should list SalesChannels by name", async () => {
|
||||||
|
const result = await service.list({
|
||||||
|
name: ["Channel 2", "Channel 3"],
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(result).toEqual([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: "channel-2",
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
id: "channel-3",
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("listAndCount", () => {
|
||||||
|
it("should return sales channels and count", async () => {
|
||||||
|
const [result, count] = await service.listAndCount()
|
||||||
|
|
||||||
|
expect(count).toEqual(3)
|
||||||
|
expect(result).toEqual([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: "channel-1",
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
id: "channel-2",
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
id: "channel-3",
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should return sales channels and count when filtered", async () => {
|
||||||
|
const [result, count] = await service.listAndCount({
|
||||||
|
id: ["channel-2"],
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(count).toEqual(1)
|
||||||
|
expect(result).toEqual([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: "channel-2",
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should return sales channels and count when using skip and take", async () => {
|
||||||
|
const [results, count] = await service.listAndCount(
|
||||||
|
{},
|
||||||
|
{ skip: 1, take: 1 }
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(count).toEqual(3)
|
||||||
|
expect(results).toEqual([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: "channel-2",
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should return requested fields", async () => {
|
||||||
|
const [result, count] = await service.listAndCount(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
take: 1,
|
||||||
|
select: ["id", "name"],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const serialized = JSON.parse(JSON.stringify(result))
|
||||||
|
|
||||||
|
expect(count).toEqual(3)
|
||||||
|
expect(serialized).toEqual([
|
||||||
|
{
|
||||||
|
id: "channel-1",
|
||||||
|
name: "Channel 1",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should filter disabled channels", async () => {
|
||||||
|
const [result, count] = await service.listAndCount(
|
||||||
|
{ is_disabled: true },
|
||||||
|
{ select: ["id"] }
|
||||||
|
)
|
||||||
|
|
||||||
|
const serialized = JSON.parse(JSON.stringify(result))
|
||||||
|
|
||||||
|
expect(count).toEqual(1)
|
||||||
|
expect(serialized).toEqual([
|
||||||
|
{
|
||||||
|
id: "channel-3",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("delete", () => {
|
||||||
|
const id = "channel-2"
|
||||||
|
|
||||||
|
it("should delete the SalesChannel given an id successfully", async () => {
|
||||||
|
await service.delete([id])
|
||||||
|
|
||||||
|
const result = await service.list({
|
||||||
|
id: [id],
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(result).toHaveLength(0)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
if (typeof process.env.DB_TEMP_NAME === "undefined") {
|
||||||
|
const tempName = parseInt(process.env.JEST_WORKER_ID || "1")
|
||||||
|
process.env.DB_TEMP_NAME = `medusa-sales-channel-integration-${tempName}`
|
||||||
|
}
|
||||||
|
|
||||||
|
process.env.MEDUSA_SALES_CHANNEL_DB_SCHEMA = "public"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import { JestUtils } from "medusa-test-utils"
|
||||||
|
|
||||||
|
JestUtils.afterAllHookDropDatabase()
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { ModuleServiceInitializeOptions } from "@medusajs/types"
|
||||||
|
|
||||||
|
export const databaseOptions: ModuleServiceInitializeOptions["database"] = {
|
||||||
|
schema: "public",
|
||||||
|
clientUrl: "medusa-sales-channel-test",
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { TestDatabaseUtils } from "medusa-test-utils"
|
||||||
|
|
||||||
|
import * as SalesChannelModels from "@models"
|
||||||
|
|
||||||
|
const pathToMigrations = "../../src/migrations"
|
||||||
|
const mikroOrmEntities = SalesChannelModels as unknown as any[]
|
||||||
|
|
||||||
|
export const MikroOrmWrapper = TestDatabaseUtils.getMikroOrmWrapper(
|
||||||
|
mikroOrmEntities,
|
||||||
|
pathToMigrations
|
||||||
|
)
|
||||||
|
|
||||||
|
export const MikroOrmConfig = TestDatabaseUtils.getMikroOrmConfig(
|
||||||
|
mikroOrmEntities,
|
||||||
|
pathToMigrations
|
||||||
|
)
|
||||||
|
|
||||||
|
export const DB_URL = TestDatabaseUtils.getDatabaseURL()
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from "./database"
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
module.exports = {
|
||||||
|
moduleNameMapper: {
|
||||||
|
"^@models": "<rootDir>/src/models",
|
||||||
|
"^@services": "<rootDir>/src/services",
|
||||||
|
"^@repositories": "<rootDir>/src/repositories",
|
||||||
|
"^@types": "<rootDir>/src/types",
|
||||||
|
},
|
||||||
|
transform: {
|
||||||
|
"^.+\\.[jt]s?$": [
|
||||||
|
"ts-jest",
|
||||||
|
{
|
||||||
|
tsConfig: "tsconfig.spec.json",
|
||||||
|
isolatedModules: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
testEnvironment: `node`,
|
||||||
|
moduleFileExtensions: [`js`, `ts`],
|
||||||
|
modulePathIgnorePatterns: ["dist/"],
|
||||||
|
setupFiles: ["<rootDir>/integration-tests/setup-env.js"],
|
||||||
|
setupFilesAfterEnv: ["<rootDir>/integration-tests/setup.js"],
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import * as entities from "./src/models"
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
entities: Object.values(entities),
|
||||||
|
schema: "public",
|
||||||
|
clientUrl: "postgres://postgres@localhost/medusa-sales-channel",
|
||||||
|
type: "postgresql",
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"name": "@medusajs/sales-channel",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "Medusa Sales Channel module",
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"types": "dist/index.d.ts",
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"medusa-sales-channel-seed": "dist/scripts/bin/run-seed.js"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/medusajs/medusa",
|
||||||
|
"directory": "packages/sales-channel"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"author": "Medusa",
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"watch": "tsc --build --watch",
|
||||||
|
"watch:test": "tsc --build tsconfig.spec.json --watch",
|
||||||
|
"prepublishOnly": "cross-env NODE_ENV=production tsc --build && tsc-alias -p tsconfig.json",
|
||||||
|
"build": "rimraf dist && tsc --build && tsc-alias -p tsconfig.json",
|
||||||
|
"test": "jest --runInBand --bail --forceExit -- src/**/__tests__/**/*.ts",
|
||||||
|
"test:integration": "jest --runInBand --forceExit -- integration-tests/**/__tests__/**/*.ts",
|
||||||
|
"migration:generate": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:generate",
|
||||||
|
"migration:initial": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:create --initial",
|
||||||
|
"migration:create": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:create",
|
||||||
|
"migration:up": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:up",
|
||||||
|
"orm:cache:clear": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm cache:clear"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@mikro-orm/cli": "5.9.7",
|
||||||
|
"cross-env": "^5.2.1",
|
||||||
|
"jest": "^29.6.3",
|
||||||
|
"medusa-test-utils": "^1.1.40",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"ts-jest": "^29.1.1",
|
||||||
|
"ts-node": "^10.9.1",
|
||||||
|
"tsc-alias": "^1.8.6",
|
||||||
|
"typescript": "^5.1.6"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@medusajs/modules-sdk": "^1.12.4",
|
||||||
|
"@medusajs/types": "^1.11.8",
|
||||||
|
"@medusajs/utils": "^1.11.1",
|
||||||
|
"@mikro-orm/core": "5.9.7",
|
||||||
|
"@mikro-orm/migrations": "5.9.7",
|
||||||
|
"@mikro-orm/postgresql": "5.9.7",
|
||||||
|
"awilix": "^8.0.0",
|
||||||
|
"dotenv": "^16.1.4",
|
||||||
|
"knex": "2.4.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { Modules } from "@medusajs/modules-sdk"
|
||||||
|
import { ModulesSdkUtils } from "@medusajs/utils"
|
||||||
|
|
||||||
|
import * as SalesChannelModels from "@models"
|
||||||
|
|
||||||
|
import { moduleDefinition } from "./module-definition"
|
||||||
|
|
||||||
|
export default moduleDefinition
|
||||||
|
|
||||||
|
const migrationScriptOptions = {
|
||||||
|
moduleName: Modules.SALES_CHANNEL,
|
||||||
|
models: SalesChannelModels,
|
||||||
|
pathToMigrations: __dirname + "/migrations",
|
||||||
|
}
|
||||||
|
|
||||||
|
export const runMigrations = ModulesSdkUtils.buildMigrationScript(
|
||||||
|
migrationScriptOptions
|
||||||
|
)
|
||||||
|
export const revertMigration = ModulesSdkUtils.buildRevertMigrationScript(
|
||||||
|
migrationScriptOptions
|
||||||
|
)
|
||||||
|
|
||||||
|
export * from "./initialize"
|
||||||
|
export * from "./types"
|
||||||
|
export * from "./loaders"
|
||||||
|
export * from "./models"
|
||||||
|
export * from "./services"
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import {
|
||||||
|
ExternalModuleDeclaration,
|
||||||
|
InternalModuleDeclaration,
|
||||||
|
MedusaModule,
|
||||||
|
MODULE_PACKAGE_NAMES,
|
||||||
|
Modules,
|
||||||
|
} from "@medusajs/modules-sdk"
|
||||||
|
import { ModulesSdkTypes, ISalesChannelModuleService } from "@medusajs/types"
|
||||||
|
import { InitializeModuleInjectableDependencies } from "@types"
|
||||||
|
|
||||||
|
import { moduleDefinition } from "../module-definition"
|
||||||
|
|
||||||
|
export const initialize = async (
|
||||||
|
options?:
|
||||||
|
| ModulesSdkTypes.ModuleServiceInitializeOptions
|
||||||
|
| ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions
|
||||||
|
| ExternalModuleDeclaration
|
||||||
|
| InternalModuleDeclaration,
|
||||||
|
injectedDependencies?: InitializeModuleInjectableDependencies
|
||||||
|
): Promise<ISalesChannelModuleService> => {
|
||||||
|
const serviceKey = Modules.SALES_CHANNEL
|
||||||
|
|
||||||
|
const loaded = await MedusaModule.bootstrap<ISalesChannelModuleService>({
|
||||||
|
moduleKey: serviceKey,
|
||||||
|
defaultPath: MODULE_PACKAGE_NAMES[Modules.SALES_CHANNEL],
|
||||||
|
declaration: options as
|
||||||
|
| InternalModuleDeclaration
|
||||||
|
| ExternalModuleDeclaration,
|
||||||
|
injectedDependencies,
|
||||||
|
moduleExports: moduleDefinition,
|
||||||
|
})
|
||||||
|
|
||||||
|
return loaded[serviceKey]
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { Modules } from "@medusajs/modules-sdk"
|
||||||
|
import { ModuleJoinerConfig } from "@medusajs/types"
|
||||||
|
import { MapToConfig } from "@medusajs/utils"
|
||||||
|
import { SalesChannel } from "@models"
|
||||||
|
|
||||||
|
export const LinkableKeys = {
|
||||||
|
sales_channel_id: SalesChannel.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.SALES_CHANNEL,
|
||||||
|
primaryKeys: ["id"],
|
||||||
|
linkableKeys: LinkableKeys,
|
||||||
|
alias: [
|
||||||
|
{
|
||||||
|
name: ["sales_channel", "sales_channels"],
|
||||||
|
args: { entity: "SalesChannel" },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
} as ModuleJoinerConfig
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
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 SalesChannelModels from "@models"
|
||||||
|
|
||||||
|
export default async (
|
||||||
|
{
|
||||||
|
options,
|
||||||
|
container,
|
||||||
|
logger,
|
||||||
|
}: LoaderOptions<
|
||||||
|
| ModulesSdkTypes.ModuleServiceInitializeOptions
|
||||||
|
| ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions
|
||||||
|
>,
|
||||||
|
moduleDeclaration?: InternalModuleDeclaration
|
||||||
|
): Promise<void> => {
|
||||||
|
const entities = Object.values(
|
||||||
|
SalesChannelModels
|
||||||
|
) as unknown as EntitySchema[]
|
||||||
|
const pathToMigrations = __dirname + "/../migrations"
|
||||||
|
|
||||||
|
await ModulesSdkUtils.mikroOrmConnectionLoader({
|
||||||
|
moduleName: Modules.SALES_CHANNEL,
|
||||||
|
entities,
|
||||||
|
container,
|
||||||
|
options,
|
||||||
|
moduleDeclaration,
|
||||||
|
logger,
|
||||||
|
pathToMigrations,
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { ModulesSdkUtils } from "@medusajs/utils"
|
||||||
|
import * as ModuleModels from "@models"
|
||||||
|
import * as ModuleRepositories from "@repositories"
|
||||||
|
import * as ModuleServices from "@services"
|
||||||
|
|
||||||
|
export default ModulesSdkUtils.moduleContainerLoaderFactory({
|
||||||
|
moduleModels: ModuleModels,
|
||||||
|
moduleRepositories: ModuleRepositories,
|
||||||
|
moduleServices: ModuleServices,
|
||||||
|
})
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
export * from "./connection"
|
||||||
|
export * from "./container"
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
{
|
||||||
|
"namespaces": [
|
||||||
|
"public"
|
||||||
|
],
|
||||||
|
"name": "public",
|
||||||
|
"tables": [
|
||||||
|
{
|
||||||
|
"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": false,
|
||||||
|
"mappedType": "text"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"name": "description",
|
||||||
|
"type": "text",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": true,
|
||||||
|
"mappedType": "text"
|
||||||
|
},
|
||||||
|
"is_disabled": {
|
||||||
|
"name": "is_disabled",
|
||||||
|
"type": "boolean",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": false,
|
||||||
|
"default": "false",
|
||||||
|
"mappedType": "boolean"
|
||||||
|
},
|
||||||
|
"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": "sales_channel",
|
||||||
|
"schema": "public",
|
||||||
|
"indexes": [
|
||||||
|
{
|
||||||
|
"columnNames": [
|
||||||
|
"deleted_at"
|
||||||
|
],
|
||||||
|
"composite": false,
|
||||||
|
"keyName": "IDX_sales_channel_deleted_at",
|
||||||
|
"primary": false,
|
||||||
|
"unique": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"keyName": "sales_channel_pkey",
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"composite": false,
|
||||||
|
"primary": true,
|
||||||
|
"unique": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"checks": [],
|
||||||
|
"foreignKeys": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { Migration } from "@mikro-orm/migrations"
|
||||||
|
|
||||||
|
export class Migration20240115152146 extends Migration {
|
||||||
|
async up(): Promise<void> {
|
||||||
|
this.addSql(
|
||||||
|
'create table if not exists "sales_channel" ("id" text not null, "name" text not null, "description" text null, "is_disabled" boolean not null default false, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "sales_channel_pkey" primary key ("id"));'
|
||||||
|
)
|
||||||
|
this.addSql(
|
||||||
|
'create index "IDX_sales_channel_deleted_at" on "sales_channel" ("deleted_at");'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { default as SalesChannel } from "./sales-channel"
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
import { DALUtils, generateEntityId } from "@medusajs/utils"
|
||||||
|
|
||||||
|
import {
|
||||||
|
BeforeCreate,
|
||||||
|
Entity,
|
||||||
|
Filter,
|
||||||
|
Index,
|
||||||
|
OptionalProps,
|
||||||
|
PrimaryKey,
|
||||||
|
Property,
|
||||||
|
} from "@mikro-orm/core"
|
||||||
|
import { DAL } from "@medusajs/types"
|
||||||
|
|
||||||
|
type SalesChannelOptionalProps = "is_disabled" | DAL.EntityDateColumns
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||||
|
export default class SalesChannel {
|
||||||
|
[OptionalProps]?: SalesChannelOptionalProps
|
||||||
|
|
||||||
|
@PrimaryKey({ columnType: "text" })
|
||||||
|
id!: string
|
||||||
|
|
||||||
|
@Property({ columnType: "text" })
|
||||||
|
name!: string
|
||||||
|
|
||||||
|
@Property({ columnType: "text", nullable: true })
|
||||||
|
description: string | null = null
|
||||||
|
|
||||||
|
@Property({ columnType: "boolean", default: false })
|
||||||
|
is_disabled = false
|
||||||
|
|
||||||
|
@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
|
||||||
|
|
||||||
|
@Index({ name: "IDX_sales_channel_deleted_at" })
|
||||||
|
@Property({ columnType: "timestamptz", nullable: true })
|
||||||
|
deleted_at: Date | null = null
|
||||||
|
|
||||||
|
@BeforeCreate()
|
||||||
|
onCreate() {
|
||||||
|
this.id = generateEntityId(this.id, "sc")
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeCreate()
|
||||||
|
onInit() {
|
||||||
|
this.id = generateEntityId(this.id, "sc")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { ModuleExports } from "@medusajs/types"
|
||||||
|
import { SalesChannelModuleService } from "@services"
|
||||||
|
|
||||||
|
import loadConnection from "./loaders/connection"
|
||||||
|
import loadContainer from "./loaders/container"
|
||||||
|
|
||||||
|
const service = SalesChannelModuleService
|
||||||
|
const loaders = [loadContainer, loadConnection] as any
|
||||||
|
|
||||||
|
export const moduleDefinition: ModuleExports = {
|
||||||
|
service,
|
||||||
|
loaders,
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { MikroOrmBaseRepository as BaseRepository } from "@medusajs/utils"
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
import { ModulesSdkUtils } from "@medusajs/utils"
|
||||||
|
import { Modules } from "@medusajs/modules-sdk"
|
||||||
|
import * as ProductModels from "@models"
|
||||||
|
import { createSalesChannels } from "../seed-utils"
|
||||||
|
import { EOL } from "os"
|
||||||
|
|
||||||
|
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-product-seed <filePath>`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const run = ModulesSdkUtils.buildSeedScript({
|
||||||
|
moduleName: Modules.PRODUCT,
|
||||||
|
models: ProductModels,
|
||||||
|
pathToMigrations: __dirname + "/../../migrations",
|
||||||
|
seedHandler: async ({ manager, data }) => {
|
||||||
|
const { salesChannelData } = data
|
||||||
|
await createSalesChannels(manager, salesChannelData)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
await run({ path })
|
||||||
|
})()
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { SalesChannel } from "@models"
|
||||||
|
import { RequiredEntityData } from "@mikro-orm/core"
|
||||||
|
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
||||||
|
|
||||||
|
export async function createSalesChannels(
|
||||||
|
manager: SqlEntityManager,
|
||||||
|
data: RequiredEntityData<SalesChannel>[]
|
||||||
|
) {
|
||||||
|
const channels = data.map((channel) => {
|
||||||
|
return manager.create(SalesChannel, channel)
|
||||||
|
})
|
||||||
|
|
||||||
|
await manager.persistAndFlush(channels)
|
||||||
|
|
||||||
|
return channels
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { SalesChannelService, SalesChannelModuleService } from "@services"
|
||||||
|
import { asClass, asValue, createContainer } from "awilix"
|
||||||
|
|
||||||
|
export const mockContainer = createContainer()
|
||||||
|
|
||||||
|
mockContainer.register({
|
||||||
|
transaction: asValue(async (task) => await task()),
|
||||||
|
salesChannelRepository: asValue({
|
||||||
|
find: jest.fn().mockImplementation(async ({ where: { code } }) => {
|
||||||
|
return [{}]
|
||||||
|
}),
|
||||||
|
findAndCount: jest.fn().mockResolvedValue([[], 0]),
|
||||||
|
getFreshManager: jest.fn().mockResolvedValue({}),
|
||||||
|
}),
|
||||||
|
salesChannelService: asClass(SalesChannelService),
|
||||||
|
salesChannelModuleService: asClass(SalesChannelModuleService),
|
||||||
|
})
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import { mockContainer } from "../__fixtures__/sales-channel"
|
||||||
|
|
||||||
|
describe("Sales channel service", function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should list sales channels with filters and relations", async function () {
|
||||||
|
const salesChannelRepository = mockContainer.resolve(
|
||||||
|
"salesChannelRepository"
|
||||||
|
)
|
||||||
|
const salesChannelService = mockContainer.resolve("salesChannelService")
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
select: ["id", "name"],
|
||||||
|
}
|
||||||
|
|
||||||
|
await salesChannelService.list({}, config)
|
||||||
|
|
||||||
|
expect(salesChannelRepository.find).toHaveBeenCalledWith(
|
||||||
|
{
|
||||||
|
where: {},
|
||||||
|
options: {
|
||||||
|
fields: ["id", "name"],
|
||||||
|
limit: 15,
|
||||||
|
offset: 0,
|
||||||
|
withDeleted: undefined,
|
||||||
|
populate: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expect.any(Object)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
export { default as SalesChannelService } from "./sales-channel"
|
||||||
|
export { default as SalesChannelModuleService } from "./sales-channel-module"
|
||||||
@@ -0,0 +1,247 @@
|
|||||||
|
import {
|
||||||
|
Context,
|
||||||
|
DAL,
|
||||||
|
FilterableSalesChannelProps,
|
||||||
|
FindConfig,
|
||||||
|
InternalModuleDeclaration,
|
||||||
|
ISalesChannelModuleService,
|
||||||
|
ModuleJoinerConfig,
|
||||||
|
RestoreReturn,
|
||||||
|
SalesChannelDTO,
|
||||||
|
SoftDeleteReturn,
|
||||||
|
} from "@medusajs/types"
|
||||||
|
import {
|
||||||
|
InjectManager,
|
||||||
|
InjectTransactionManager,
|
||||||
|
mapObjectTo,
|
||||||
|
MedusaContext,
|
||||||
|
} from "@medusajs/utils"
|
||||||
|
import { CreateSalesChannelDTO, UpdateSalesChannelDTO } from "@medusajs/types"
|
||||||
|
|
||||||
|
import { SalesChannel } from "@models"
|
||||||
|
|
||||||
|
import SalesChannelService from "./sales-channel"
|
||||||
|
import {
|
||||||
|
joinerConfig,
|
||||||
|
entityNameToLinkableKeysMap,
|
||||||
|
LinkableKeys,
|
||||||
|
} from "../joiner-config"
|
||||||
|
|
||||||
|
type InjectedDependencies = {
|
||||||
|
baseRepository: DAL.RepositoryService
|
||||||
|
salesChannelService: SalesChannelService<any>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class SalesChannelModuleService<
|
||||||
|
TEntity extends SalesChannel = SalesChannel
|
||||||
|
> implements ISalesChannelModuleService
|
||||||
|
{
|
||||||
|
protected baseRepository_: DAL.RepositoryService
|
||||||
|
protected readonly salesChannelService_: SalesChannelService<TEntity>
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
{ baseRepository, salesChannelService }: InjectedDependencies,
|
||||||
|
protected readonly moduleDeclaration: InternalModuleDeclaration
|
||||||
|
) {
|
||||||
|
this.baseRepository_ = baseRepository
|
||||||
|
this.salesChannelService_ = salesChannelService
|
||||||
|
}
|
||||||
|
|
||||||
|
__joinerConfig(): ModuleJoinerConfig {
|
||||||
|
return joinerConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
async create(
|
||||||
|
data: CreateSalesChannelDTO[],
|
||||||
|
sharedContext?: Context
|
||||||
|
): Promise<SalesChannelDTO[]>
|
||||||
|
|
||||||
|
async create(
|
||||||
|
data: CreateSalesChannelDTO,
|
||||||
|
sharedContext?: Context
|
||||||
|
): Promise<SalesChannelDTO>
|
||||||
|
|
||||||
|
@InjectTransactionManager("baseRepository_")
|
||||||
|
async create(
|
||||||
|
data: CreateSalesChannelDTO | CreateSalesChannelDTO[],
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<SalesChannelDTO | SalesChannelDTO[]> {
|
||||||
|
const input = Array.isArray(data) ? data : [data]
|
||||||
|
|
||||||
|
const result = await this.salesChannelService_.create(input, sharedContext)
|
||||||
|
|
||||||
|
return await this.baseRepository_.serialize<SalesChannelDTO[]>(
|
||||||
|
Array.isArray(data) ? result : result[0],
|
||||||
|
{
|
||||||
|
populate: true,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async delete(ids: string[], sharedContext?: Context): Promise<void>
|
||||||
|
|
||||||
|
async delete(id: string, sharedContext?: Context): Promise<void>
|
||||||
|
|
||||||
|
@InjectTransactionManager("baseRepository_")
|
||||||
|
async delete(
|
||||||
|
ids: string | string[],
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<void> {
|
||||||
|
const salesChannelIds = Array.isArray(ids) ? ids : [ids]
|
||||||
|
await this.salesChannelService_.delete(salesChannelIds, sharedContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager("baseRepository_")
|
||||||
|
protected async softDelete_(
|
||||||
|
salesChannelIds: string[],
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<[TEntity[], Record<string, unknown[]>]> {
|
||||||
|
return await this.salesChannelService_.softDelete(
|
||||||
|
salesChannelIds,
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectManager("baseRepository_")
|
||||||
|
async softDelete<
|
||||||
|
TReturnableLinkableKeys extends string = Lowercase<
|
||||||
|
keyof typeof LinkableKeys
|
||||||
|
>
|
||||||
|
>(
|
||||||
|
salesChannelIds: string[],
|
||||||
|
{ returnLinkableKeys }: SoftDeleteReturn<TReturnableLinkableKeys> = {},
|
||||||
|
sharedContext: Context = {}
|
||||||
|
): Promise<Record<Lowercase<keyof typeof LinkableKeys>, string[]> | void> {
|
||||||
|
const [_, cascadedEntitiesMap] = await this.softDelete_(
|
||||||
|
salesChannelIds,
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
|
||||||
|
let mappedCascadedEntitiesMap
|
||||||
|
if (returnLinkableKeys) {
|
||||||
|
mappedCascadedEntitiesMap = mapObjectTo<
|
||||||
|
Record<Lowercase<keyof typeof LinkableKeys>, string[]>
|
||||||
|
>(cascadedEntitiesMap, entityNameToLinkableKeysMap, {
|
||||||
|
pick: returnLinkableKeys,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return mappedCascadedEntitiesMap ? mappedCascadedEntitiesMap : void 0
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager("baseRepository_")
|
||||||
|
async restore_(
|
||||||
|
salesChannelIds: string[],
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<[TEntity[], Record<string, unknown[]>]> {
|
||||||
|
return await this.salesChannelService_.restore(
|
||||||
|
salesChannelIds,
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectManager("baseRepository_")
|
||||||
|
async restore<
|
||||||
|
TReturnableLinkableKeys extends string = Lowercase<
|
||||||
|
keyof typeof LinkableKeys
|
||||||
|
>
|
||||||
|
>(
|
||||||
|
salesChannelIds: string[],
|
||||||
|
{ returnLinkableKeys }: RestoreReturn<TReturnableLinkableKeys> = {},
|
||||||
|
sharedContext: Context = {}
|
||||||
|
): Promise<Record<Lowercase<keyof typeof LinkableKeys>, string[]> | void> {
|
||||||
|
const [_, cascadedEntitiesMap] = await this.restore_(
|
||||||
|
salesChannelIds,
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
|
||||||
|
let mappedCascadedEntitiesMap
|
||||||
|
if (returnLinkableKeys) {
|
||||||
|
mappedCascadedEntitiesMap = mapObjectTo<
|
||||||
|
Record<Lowercase<keyof typeof LinkableKeys>, string[]>
|
||||||
|
>(cascadedEntitiesMap, entityNameToLinkableKeysMap, {
|
||||||
|
pick: returnLinkableKeys,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return mappedCascadedEntitiesMap ? mappedCascadedEntitiesMap : void 0
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(
|
||||||
|
data: UpdateSalesChannelDTO[],
|
||||||
|
sharedContext?: Context
|
||||||
|
): Promise<SalesChannelDTO[]>
|
||||||
|
|
||||||
|
async update(
|
||||||
|
data: UpdateSalesChannelDTO,
|
||||||
|
sharedContext?: Context
|
||||||
|
): Promise<SalesChannelDTO>
|
||||||
|
|
||||||
|
@InjectTransactionManager("baseRepository_")
|
||||||
|
async update(
|
||||||
|
data: UpdateSalesChannelDTO | UpdateSalesChannelDTO[],
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<SalesChannelDTO | SalesChannelDTO[]> {
|
||||||
|
const input = Array.isArray(data) ? data : [data]
|
||||||
|
|
||||||
|
const result = await this.salesChannelService_.update(input, sharedContext)
|
||||||
|
|
||||||
|
return await this.baseRepository_.serialize<SalesChannelDTO[]>(
|
||||||
|
Array.isArray(data) ? result : result[0],
|
||||||
|
{
|
||||||
|
populate: true,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectManager("baseRepository_")
|
||||||
|
async retrieve(
|
||||||
|
salesChannelId: string,
|
||||||
|
config: FindConfig<SalesChannelDTO> = {},
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<SalesChannelDTO> {
|
||||||
|
const salesChannel = await this.salesChannelService_.retrieve(
|
||||||
|
salesChannelId,
|
||||||
|
config
|
||||||
|
)
|
||||||
|
|
||||||
|
return await this.baseRepository_.serialize<SalesChannelDTO>(salesChannel, {
|
||||||
|
populate: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectManager("baseRepository_")
|
||||||
|
async list(
|
||||||
|
filters: {} = {},
|
||||||
|
config: FindConfig<SalesChannelDTO> = {},
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<SalesChannelDTO[]> {
|
||||||
|
const salesChannels = await this.salesChannelService_.list(filters, config)
|
||||||
|
|
||||||
|
return await this.baseRepository_.serialize<SalesChannelDTO[]>(
|
||||||
|
salesChannels,
|
||||||
|
{
|
||||||
|
populate: true,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectManager("baseRepository_")
|
||||||
|
async listAndCount(
|
||||||
|
filters: FilterableSalesChannelProps = {},
|
||||||
|
config: FindConfig<SalesChannelDTO> = {},
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<[SalesChannelDTO[], number]> {
|
||||||
|
const [salesChannels, count] = await this.salesChannelService_.listAndCount(
|
||||||
|
filters,
|
||||||
|
config
|
||||||
|
)
|
||||||
|
|
||||||
|
return [
|
||||||
|
await this.baseRepository_.serialize<SalesChannelDTO[]>(salesChannels, {
|
||||||
|
populate: true,
|
||||||
|
}),
|
||||||
|
count,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import { DAL } from "@medusajs/types"
|
||||||
|
import { ModulesSdkUtils } from "@medusajs/utils"
|
||||||
|
import { CreateSalesChannelDTO, UpdateSalesChannelDTO } from "@medusajs/types"
|
||||||
|
|
||||||
|
import { SalesChannel } from "@models"
|
||||||
|
|
||||||
|
type InjectedDependencies = {
|
||||||
|
salesChannelRepository: DAL.RepositoryService
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class SalesChannelService<
|
||||||
|
TEntity extends SalesChannel = SalesChannel
|
||||||
|
> extends ModulesSdkUtils.abstractServiceFactory<
|
||||||
|
InjectedDependencies,
|
||||||
|
{
|
||||||
|
create: CreateSalesChannelDTO
|
||||||
|
update: UpdateSalesChannelDTO
|
||||||
|
}
|
||||||
|
>(SalesChannel)<TEntity> {
|
||||||
|
constructor(container: InjectedDependencies) {
|
||||||
|
// @ts-ignore
|
||||||
|
super(...arguments)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { Logger } from "@medusajs/types"
|
||||||
|
|
||||||
|
export type InitializeModuleInjectableDependencies = {
|
||||||
|
logger?: Logger
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { DAL } from "@medusajs/types"
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||||
|
import { SalesChannel } from "@models"
|
||||||
|
import { CreateSalesChannelDTO, UpdateSalesChannelDTO } from "@medusajs/types"
|
||||||
|
|
||||||
|
export interface ISalesChannelRepository<
|
||||||
|
TEntity extends SalesChannel = SalesChannel
|
||||||
|
> extends DAL.RepositoryService<
|
||||||
|
TEntity,
|
||||||
|
{
|
||||||
|
create: CreateSalesChannelDTO
|
||||||
|
update: UpdateSalesChannelDTO
|
||||||
|
}
|
||||||
|
> {}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"lib": ["es2020"],
|
||||||
|
"target": "es2020",
|
||||||
|
"outDir": "./dist",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"declaration": true,
|
||||||
|
"module": "commonjs",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"sourceMap": false,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"strictNullChecks": true,
|
||||||
|
"strictFunctionTypes": true,
|
||||||
|
"noImplicitThis": true,
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"downlevelIteration": true, // to use ES5 specific tooling
|
||||||
|
"baseUrl": ".",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"paths": {
|
||||||
|
"@models": ["./src/models"],
|
||||||
|
"@services": ["./src/services"],
|
||||||
|
"@repositories": ["./src/repositories"],
|
||||||
|
"@types": ["./src/types"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["src"],
|
||||||
|
"exclude": [
|
||||||
|
"dist",
|
||||||
|
"./src/**/__tests__",
|
||||||
|
"./src/**/__mocks__",
|
||||||
|
"./src/**/__fixtures__",
|
||||||
|
"node_modules"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"include": ["src", "integration-tests"],
|
||||||
|
"exclude": ["node_modules", "dist"],
|
||||||
|
"compilerOptions": {
|
||||||
|
"sourceMap": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { BaseFilterable } from "../dal"
|
||||||
|
|
||||||
export interface SalesChannelLocationDTO {
|
export interface SalesChannelLocationDTO {
|
||||||
sales_channel_id: string
|
sales_channel_id: string
|
||||||
location_id: string
|
location_id: string
|
||||||
@@ -6,8 +8,16 @@ export interface SalesChannelLocationDTO {
|
|||||||
|
|
||||||
export interface SalesChannelDTO {
|
export interface SalesChannelDTO {
|
||||||
id: string
|
id: string
|
||||||
|
name: string
|
||||||
description: string | null
|
description: string | null
|
||||||
is_disabled: boolean
|
is_disabled: boolean
|
||||||
metadata: Record<string, unknown> | null
|
metadata: Record<string, unknown> | null
|
||||||
locations?: SalesChannelLocationDTO[]
|
locations?: SalesChannelLocationDTO[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface FilterableSalesChannelProps
|
||||||
|
extends BaseFilterable<FilterableSalesChannelProps> {
|
||||||
|
id?: string[]
|
||||||
|
name?: string[]
|
||||||
|
is_disabled?: boolean
|
||||||
|
}
|
||||||
@@ -1 +1,3 @@
|
|||||||
export * from "./common"
|
export * from "./common"
|
||||||
|
export * from "./mutations"
|
||||||
|
export * from "./service"
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
export interface CreateSalesChannelDTO {
|
||||||
|
name: string
|
||||||
|
description?: string
|
||||||
|
is_disabled?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateSalesChannelDTO {
|
||||||
|
id: string
|
||||||
|
name?: string
|
||||||
|
description?: string
|
||||||
|
is_disabled?: boolean
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
import { IModuleService } from "../modules-sdk"
|
||||||
|
import { FilterableSalesChannelProps, SalesChannelDTO } from "./common"
|
||||||
|
import { FindConfig } from "../common"
|
||||||
|
import { Context } from "../shared-context"
|
||||||
|
import { RestoreReturn, SoftDeleteReturn } from "../dal"
|
||||||
|
import { CreateSalesChannelDTO, UpdateSalesChannelDTO } from "./mutations"
|
||||||
|
|
||||||
|
export interface ISalesChannelModuleService extends IModuleService {
|
||||||
|
create(
|
||||||
|
data: CreateSalesChannelDTO[],
|
||||||
|
sharedContext?: Context
|
||||||
|
): Promise<SalesChannelDTO[]>
|
||||||
|
create(
|
||||||
|
data: CreateSalesChannelDTO,
|
||||||
|
sharedContext?: Context
|
||||||
|
): Promise<SalesChannelDTO>
|
||||||
|
|
||||||
|
update(
|
||||||
|
data: UpdateSalesChannelDTO[],
|
||||||
|
sharedContext?: Context
|
||||||
|
): Promise<SalesChannelDTO[]>
|
||||||
|
update(
|
||||||
|
data: UpdateSalesChannelDTO,
|
||||||
|
sharedContext?: Context
|
||||||
|
): Promise<SalesChannelDTO>
|
||||||
|
|
||||||
|
delete(ids: string[], sharedContext?: Context): Promise<void>
|
||||||
|
delete(id: string, sharedContext?: Context): Promise<void>
|
||||||
|
|
||||||
|
retrieve(
|
||||||
|
id: string,
|
||||||
|
config?: FindConfig<SalesChannelDTO>,
|
||||||
|
sharedContext?: Context
|
||||||
|
): Promise<SalesChannelDTO>
|
||||||
|
|
||||||
|
list(
|
||||||
|
filters?: FilterableSalesChannelProps,
|
||||||
|
config?: FindConfig<SalesChannelDTO>,
|
||||||
|
sharedContext?: Context
|
||||||
|
): Promise<SalesChannelDTO[]>
|
||||||
|
|
||||||
|
listAndCount(
|
||||||
|
filters?: FilterableSalesChannelProps,
|
||||||
|
config?: FindConfig<SalesChannelDTO>,
|
||||||
|
sharedContext?: Context
|
||||||
|
): Promise<[SalesChannelDTO[], number]>
|
||||||
|
|
||||||
|
softDelete<TReturnableLinkableKeys extends string = string>(
|
||||||
|
salesChannelIds: string[],
|
||||||
|
config?: SoftDeleteReturn<TReturnableLinkableKeys>,
|
||||||
|
sharedContext?: Context
|
||||||
|
): Promise<Record<string, string[]> | void>
|
||||||
|
|
||||||
|
restore<TReturnableLinkableKeys extends string = string>(
|
||||||
|
salesChannelIds: string[],
|
||||||
|
config?: RestoreReturn<TReturnableLinkableKeys>,
|
||||||
|
sharedContext?: Context
|
||||||
|
): Promise<Record<string, string[]> | void>
|
||||||
|
}
|
||||||
@@ -8370,7 +8370,7 @@ __metadata:
|
|||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
"@medusajs/modules-sdk@^1.12.2, @medusajs/modules-sdk@^1.12.3, @medusajs/modules-sdk@^1.12.5, @medusajs/modules-sdk@^1.12.6, @medusajs/modules-sdk@^1.12.7, @medusajs/modules-sdk@^1.8.8, @medusajs/modules-sdk@workspace:^, @medusajs/modules-sdk@workspace:packages/modules-sdk":
|
"@medusajs/modules-sdk@^1.12.2, @medusajs/modules-sdk@^1.12.3, @medusajs/modules-sdk@^1.12.4, @medusajs/modules-sdk@^1.12.5, @medusajs/modules-sdk@^1.12.6, @medusajs/modules-sdk@^1.12.7, @medusajs/modules-sdk@^1.8.8, @medusajs/modules-sdk@workspace:^, @medusajs/modules-sdk@workspace:packages/modules-sdk":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@medusajs/modules-sdk@workspace:packages/modules-sdk"
|
resolution: "@medusajs/modules-sdk@workspace:packages/modules-sdk"
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -8565,6 +8565,33 @@ __metadata:
|
|||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
|
"@medusajs/sales-channel@workspace:packages/sales-channel":
|
||||||
|
version: 0.0.0-use.local
|
||||||
|
resolution: "@medusajs/sales-channel@workspace:packages/sales-channel"
|
||||||
|
dependencies:
|
||||||
|
"@medusajs/modules-sdk": ^1.12.4
|
||||||
|
"@medusajs/types": ^1.11.8
|
||||||
|
"@medusajs/utils": ^1.11.1
|
||||||
|
"@mikro-orm/cli": 5.9.7
|
||||||
|
"@mikro-orm/core": 5.9.7
|
||||||
|
"@mikro-orm/migrations": 5.9.7
|
||||||
|
"@mikro-orm/postgresql": 5.9.7
|
||||||
|
awilix: ^8.0.0
|
||||||
|
cross-env: ^5.2.1
|
||||||
|
dotenv: ^16.1.4
|
||||||
|
jest: ^29.6.3
|
||||||
|
knex: 2.4.2
|
||||||
|
medusa-test-utils: ^1.1.40
|
||||||
|
rimraf: ^3.0.2
|
||||||
|
ts-jest: ^29.1.1
|
||||||
|
ts-node: ^10.9.1
|
||||||
|
tsc-alias: ^1.8.6
|
||||||
|
typescript: ^5.1.6
|
||||||
|
bin:
|
||||||
|
medusa-sales-channel-seed: dist/scripts/bin/run-seed.js
|
||||||
|
languageName: unknown
|
||||||
|
linkType: soft
|
||||||
|
|
||||||
"@medusajs/stock-location@workspace:packages/stock-location":
|
"@medusajs/stock-location@workspace:packages/stock-location":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@medusajs/stock-location@workspace:packages/stock-location"
|
resolution: "@medusajs/stock-location@workspace:packages/stock-location"
|
||||||
@@ -8608,7 +8635,7 @@ __metadata:
|
|||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
"@medusajs/types@^1.10.0, @medusajs/types@^1.11.10, @medusajs/types@^1.11.11, @medusajs/types@^1.11.5, @medusajs/types@^1.11.6, @medusajs/types@^1.11.9, @medusajs/types@^1.8.10, @medusajs/types@workspace:^, @medusajs/types@workspace:packages/types":
|
"@medusajs/types@^1.10.0, @medusajs/types@^1.11.10, @medusajs/types@^1.11.11, @medusajs/types@^1.11.5, @medusajs/types@^1.11.6, @medusajs/types@^1.11.8, @medusajs/types@^1.11.9, @medusajs/types@^1.8.10, @medusajs/types@workspace:^, @medusajs/types@workspace:packages/types":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@medusajs/types@workspace:packages/types"
|
resolution: "@medusajs/types@workspace:packages/types"
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -8711,7 +8738,7 @@ __metadata:
|
|||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
"@medusajs/utils@^1.1.41, @medusajs/utils@^1.10.5, @medusajs/utils@^1.11.2, @medusajs/utils@^1.11.3, @medusajs/utils@^1.11.4, @medusajs/utils@^1.9.2, @medusajs/utils@^1.9.4, @medusajs/utils@workspace:^, @medusajs/utils@workspace:packages/utils":
|
"@medusajs/utils@^1.1.41, @medusajs/utils@^1.10.5, @medusajs/utils@^1.11.1, @medusajs/utils@^1.11.2, @medusajs/utils@^1.11.3, @medusajs/utils@^1.11.4, @medusajs/utils@^1.9.2, @medusajs/utils@^1.9.4, @medusajs/utils@workspace:^, @medusajs/utils@workspace:packages/utils":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@medusajs/utils@workspace:packages/utils"
|
resolution: "@medusajs/utils@workspace:packages/utils"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
Reference in new issue
Block a user