feat(medusa, link-modules): sales channel <> pubkey link (#5820)
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/link-modules": patch
|
||||||
|
"@medusajs/medusa": patch
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
feat: PubKey <> SC joiner config
|
||||||
@@ -338,14 +338,14 @@ describe("Publishable API keys", () => {
|
|||||||
expect(response.status).toBe(200)
|
expect(response.status).toBe(200)
|
||||||
|
|
||||||
expect(mappings).toEqual([
|
expect(mappings).toEqual([
|
||||||
{
|
expect.objectContaining({
|
||||||
sales_channel_id: salesChannel1.id,
|
sales_channel_id: salesChannel1.id,
|
||||||
publishable_key_id: pubKeyId,
|
publishable_key_id: pubKeyId,
|
||||||
},
|
}),
|
||||||
{
|
expect.objectContaining({
|
||||||
sales_channel_id: salesChannel2.id,
|
sales_channel_id: salesChannel2.id,
|
||||||
publishable_key_id: pubKeyId,
|
publishable_key_id: pubKeyId,
|
||||||
},
|
}),
|
||||||
])
|
])
|
||||||
|
|
||||||
expect(response.data.publishable_api_key).toMatchObject({
|
expect(response.data.publishable_api_key).toMatchObject({
|
||||||
@@ -386,10 +386,10 @@ describe("Publishable API keys", () => {
|
|||||||
|
|
||||||
await dbConnection.manager.query(
|
await dbConnection.manager.query(
|
||||||
`INSERT INTO publishable_api_key_sales_channel
|
`INSERT INTO publishable_api_key_sales_channel
|
||||||
(publishable_key_id, sales_channel_id)
|
(id, publishable_key_id, sales_channel_id)
|
||||||
VALUES ('${pubKeyId}', '${salesChannel1.id}'),
|
VALUES ('pksc-1','${pubKeyId}', '${salesChannel1.id}'),
|
||||||
('${pubKeyId}', '${salesChannel2.id}'),
|
('pksc-2','${pubKeyId}', '${salesChannel2.id}'),
|
||||||
('${pubKeyId}', '${salesChannel3.id}');`
|
('pksc-3','${pubKeyId}', '${salesChannel3.id}');`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -417,16 +417,16 @@ describe("Publishable API keys", () => {
|
|||||||
const mappings = await dbConnection.manager.query(
|
const mappings = await dbConnection.manager.query(
|
||||||
`SELECT *
|
`SELECT *
|
||||||
FROM publishable_api_key_sales_channel
|
FROM publishable_api_key_sales_channel
|
||||||
WHERE publishable_key_id = '${pubKeyId}'`
|
WHERE publishable_key_id = '${pubKeyId}';`
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(response.status).toBe(200)
|
expect(response.status).toBe(200)
|
||||||
|
|
||||||
expect(mappings).toEqual([
|
expect(mappings).toEqual([
|
||||||
{
|
expect.objectContaining({
|
||||||
sales_channel_id: salesChannel3.id,
|
sales_channel_id: salesChannel3.id,
|
||||||
publishable_key_id: pubKeyId,
|
publishable_key_id: pubKeyId,
|
||||||
},
|
}),
|
||||||
])
|
])
|
||||||
|
|
||||||
expect(response.data.publishable_api_key).toMatchObject({
|
expect(response.data.publishable_api_key).toMatchObject({
|
||||||
@@ -467,9 +467,9 @@ describe("Publishable API keys", () => {
|
|||||||
|
|
||||||
await dbConnection.manager.query(
|
await dbConnection.manager.query(
|
||||||
`INSERT INTO publishable_api_key_sales_channel
|
`INSERT INTO publishable_api_key_sales_channel
|
||||||
(publishable_key_id, sales_channel_id)
|
(id, publishable_key_id, sales_channel_id)
|
||||||
VALUES ('${pubKeyId}', '${salesChannel1.id}'),
|
VALUES ('pksc-1', '${pubKeyId}', '${salesChannel1.id}'),
|
||||||
('${pubKeyId}', '${salesChannel2.id}');`
|
('pksc-2', '${pubKeyId}', '${salesChannel2.id}');`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -5,3 +5,4 @@ export * from "./product-shipping-profile"
|
|||||||
export * from "./product-sales-channel"
|
export * from "./product-sales-channel"
|
||||||
export * from "./cart-sales-channel"
|
export * from "./cart-sales-channel"
|
||||||
export * from "./order-sales-channel"
|
export * from "./order-sales-channel"
|
||||||
|
export * from "./publishable-api-key-sales-channel"
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
import { ModuleJoinerConfig } from "@medusajs/types"
|
||||||
|
import { LINKS } from "../links"
|
||||||
|
|
||||||
|
export const PublishableApiKeySalesChannel: ModuleJoinerConfig = {
|
||||||
|
serviceName: LINKS.PublishableApiKeySalesChannel,
|
||||||
|
isLink: true,
|
||||||
|
databaseConfig: {
|
||||||
|
tableName: "publishable_api_key_sales_channel",
|
||||||
|
idPrefix: "pksc",
|
||||||
|
},
|
||||||
|
alias: [
|
||||||
|
{
|
||||||
|
name: "publishable_api_key_sales_channel",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "publishable_api_key_sales_channels",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
primaryKeys: ["id", "publishable_key_id", "sales_channel_id"],
|
||||||
|
relationships: [
|
||||||
|
{
|
||||||
|
serviceName: "publishableApiKeyService",
|
||||||
|
isInternalService: true,
|
||||||
|
primaryKey: "id",
|
||||||
|
foreignKey: "publishable_key_id",
|
||||||
|
alias: "publishable_key",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
serviceName: "salesChannelService",
|
||||||
|
isInternalService: true,
|
||||||
|
primaryKey: "id",
|
||||||
|
foreignKey: "sales_channel_id",
|
||||||
|
alias: "sales_channel",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
extends: [
|
||||||
|
{
|
||||||
|
serviceName: "publishableApiKeyService",
|
||||||
|
fieldAlias: {
|
||||||
|
sales_channels: "sales_channels_link.sales_channel",
|
||||||
|
},
|
||||||
|
relationship: {
|
||||||
|
serviceName: LINKS.PublishableApiKeySalesChannel,
|
||||||
|
isInternalService: true,
|
||||||
|
primaryKey: "publishable_key_id",
|
||||||
|
foreignKey: "id",
|
||||||
|
alias: "sales_channels_link",
|
||||||
|
isList: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
serviceName: "salesChannelService",
|
||||||
|
relationship: {
|
||||||
|
serviceName: LINKS.PublishableApiKeySalesChannel,
|
||||||
|
isInternalService: true,
|
||||||
|
primaryKey: "sales_channel_id",
|
||||||
|
foreignKey: "id",
|
||||||
|
alias: "publishable_keys_link",
|
||||||
|
isList: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
@@ -40,4 +40,10 @@ export const LINKS = {
|
|||||||
"salesChannelService",
|
"salesChannelService",
|
||||||
"sales_channel_id"
|
"sales_channel_id"
|
||||||
),
|
),
|
||||||
|
PublishableApiKeySalesChannel: composeLinkName(
|
||||||
|
"publishableApiKeyService",
|
||||||
|
"publishable_key_id",
|
||||||
|
"salesChannelService",
|
||||||
|
"sales_channel_id"
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,3 +3,4 @@ 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 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"
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import { ModuleJoinerConfig } from "@medusajs/types"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
serviceName: "publishableApiKeyService",
|
||||||
|
primaryKeys: ["id"],
|
||||||
|
linkableKeys: { publishable_key_id: "PublishableApiKey" },
|
||||||
|
schema: `
|
||||||
|
scalar Date
|
||||||
|
scalar JSON
|
||||||
|
|
||||||
|
type PublishableApiKey {
|
||||||
|
id: ID!
|
||||||
|
sales_channel_id: String!
|
||||||
|
publishable_key_id: String!
|
||||||
|
created_at: Date!
|
||||||
|
updated_at: Date!
|
||||||
|
deleted_at: Date
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
alias: [
|
||||||
|
{
|
||||||
|
name: ["publishable_api_key", "publishable_api_keys"],
|
||||||
|
args: { entity: "PublishableApiKey" },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
} as ModuleJoinerConfig
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from "typeorm"
|
||||||
|
|
||||||
|
export class PublishableKeySalesChannelLink1701894188811
|
||||||
|
implements MigrationInterface
|
||||||
|
{
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`
|
||||||
|
ALTER TABLE "publishable_api_key_sales_channel" ADD COLUMN IF NOT EXISTS "id" text;
|
||||||
|
UPDATE "publishable_api_key_sales_channel" SET "id" = 'pksc_' || substr(md5(random()::text), 0, 27) WHERE id is NULL;
|
||||||
|
ALTER TABLE "publishable_api_key_sales_channel" ALTER COLUMN "id" SET NOT NULL;
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS "IDX_id_publishable_api_key_sales_channel" ON "publishable_api_key_sales_channel" ("id");
|
||||||
|
|
||||||
|
ALTER TABLE "publishable_api_key_sales_channel" ADD COLUMN IF NOT EXISTS "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now();
|
||||||
|
ALTER TABLE "publishable_api_key_sales_channel" ADD COLUMN IF NOT EXISTS "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now();
|
||||||
|
ALTER TABLE "publishable_api_key_sales_channel" ADD COLUMN IF NOT EXISTS "deleted_at" TIMESTAMP WITH TIME ZONE;
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`
|
||||||
|
DROP INDEX IF EXISTS "IDX_id_publishable_api_key_sales_channel";
|
||||||
|
ALTER TABLE "publishable_api_key_sales_channel" DROP COLUMN IF EXISTS "id";
|
||||||
|
ALTER TABLE "publishable_api_key_sales_channel" DROP COLUMN IF EXISTS "created_at";
|
||||||
|
ALTER TABLE "publishable_api_key_sales_channel" DROP COLUMN IF EXISTS "updated_at";
|
||||||
|
ALTER TABLE "publishable_api_key_sales_channel" DROP COLUMN IF EXISTS "deleted_at";
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +1,25 @@
|
|||||||
import { Entity, PrimaryColumn } from "typeorm"
|
import { BeforeInsert, Column, Entity, PrimaryColumn } from "typeorm"
|
||||||
|
import { BaseEntity } from "../interfaces"
|
||||||
|
import { generateEntityId } from "../utils"
|
||||||
|
|
||||||
@Entity()
|
@Entity("publishable_api_key_sales_channel")
|
||||||
export class PublishableApiKeySalesChannel {
|
export class PublishableApiKeySalesChannel extends BaseEntity {
|
||||||
@PrimaryColumn()
|
@Column({ type: "text" })
|
||||||
|
id: string
|
||||||
|
|
||||||
|
@PrimaryColumn({ type: "text" })
|
||||||
sales_channel_id: string
|
sales_channel_id: string
|
||||||
|
|
||||||
@PrimaryColumn()
|
@PrimaryColumn({ type: "text" })
|
||||||
publishable_key_id: string
|
publishable_key_id: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @apiIgnore
|
||||||
|
*/
|
||||||
|
@BeforeInsert()
|
||||||
|
private beforeInsert(): void {
|
||||||
|
this.id = generateEntityId(this.id, "pksc")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { SalesChannelLocation } from "./sales-channel-location"
|
|||||||
import { Product } from "./product"
|
import { Product } from "./product"
|
||||||
import { Cart } from "./cart"
|
import { Cart } from "./cart"
|
||||||
import { Order } from "./order"
|
import { Order } from "./order"
|
||||||
|
import { PublishableApiKey } from "./publishable-api-key"
|
||||||
|
|
||||||
@FeatureFlagEntity("sales_channels")
|
@FeatureFlagEntity("sales_channels")
|
||||||
export class SalesChannel extends SoftDeletableEntity {
|
export class SalesChannel extends SoftDeletableEntity {
|
||||||
@@ -74,6 +75,20 @@ export class SalesChannel extends SoftDeletableEntity {
|
|||||||
)
|
)
|
||||||
orders: Order[]
|
orders: Order[]
|
||||||
|
|
||||||
|
@ManyToMany(() => PublishableApiKey)
|
||||||
|
@JoinTable({
|
||||||
|
name: "publishable_api_key_sales_channel",
|
||||||
|
inverseJoinColumn: {
|
||||||
|
name: "publishable_key_id",
|
||||||
|
referencedColumnName: "id",
|
||||||
|
},
|
||||||
|
joinColumn: {
|
||||||
|
name: "sales_channel_id",
|
||||||
|
referencedColumnName: "id",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
publishableKeys: PublishableApiKey[]
|
||||||
|
|
||||||
@OneToMany(
|
@OneToMany(
|
||||||
() => SalesChannelLocation,
|
() => SalesChannelLocation,
|
||||||
(scLocation) => scLocation.sales_channel,
|
(scLocation) => scLocation.sales_channel,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Brackets, In } from "typeorm"
|
|||||||
import { PublishableApiKeySalesChannel, SalesChannel } from "../models"
|
import { PublishableApiKeySalesChannel, SalesChannel } from "../models"
|
||||||
import { dataSource } from "../loaders/database"
|
import { dataSource } from "../loaders/database"
|
||||||
import SalesChannelRepository from "./sales-channel"
|
import SalesChannelRepository from "./sales-channel"
|
||||||
|
import { generateEntityId } from "../utils"
|
||||||
|
|
||||||
const publishableApiKeySalesChannelAlias = "PublishableKeySalesChannel"
|
const publishableApiKeySalesChannelAlias = "PublishableKeySalesChannel"
|
||||||
|
|
||||||
@@ -64,15 +65,16 @@ export const PublishableApiKeySalesChannelRepository = dataSource
|
|||||||
publishableApiKeyId: string,
|
publishableApiKeyId: string,
|
||||||
salesChannelIds: string[]
|
salesChannelIds: string[]
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
const valuesToInsert = salesChannelIds.map((id) => ({
|
||||||
|
id: generateEntityId(undefined, "pksc"),
|
||||||
|
sales_channel_id: id,
|
||||||
|
publishable_key_id: publishableApiKeyId,
|
||||||
|
}))
|
||||||
|
|
||||||
await this.createQueryBuilder()
|
await this.createQueryBuilder()
|
||||||
.insert()
|
.insert()
|
||||||
.into(PublishableApiKeySalesChannel)
|
.into(PublishableApiKeySalesChannel)
|
||||||
.values(
|
.values(valuesToInsert)
|
||||||
salesChannelIds.map((id) => ({
|
|
||||||
sales_channel_id: id,
|
|
||||||
publishable_key_id: publishableApiKeyId,
|
|
||||||
}))
|
|
||||||
)
|
|
||||||
.orIgnore()
|
.orIgnore()
|
||||||
.execute()
|
.execute()
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -41,19 +41,13 @@ describe("PublishableApiKeyService", () => {
|
|||||||
await publishableApiKeyService.retrieve(
|
await publishableApiKeyService.retrieve(
|
||||||
IdMap.getId("order-edit-with-changes")
|
IdMap.getId("order-edit-with-changes")
|
||||||
)
|
)
|
||||||
expect(
|
expect(publishableApiKeyRepository.findOne).toHaveBeenCalledTimes(1)
|
||||||
publishableApiKeyRepository.findOne
|
expect(publishableApiKeyRepository.findOne).toHaveBeenCalledWith({
|
||||||
).toHaveBeenCalledTimes(1)
|
relationLoadStrategy: "query",
|
||||||
expect(
|
where: {
|
||||||
publishableApiKeyRepository.findOne
|
id: IdMap.getId("order-edit-with-changes"),
|
||||||
).toHaveBeenCalledWith(
|
},
|
||||||
{
|
})
|
||||||
relationLoadStrategy: "query",
|
|
||||||
where: {
|
|
||||||
id: IdMap.getId("order-edit-with-changes")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should create a publishable api key and call the repository with the right arguments as well as the event bus service", async () => {
|
it("should create a publishable api key and call the repository with the right arguments as well as the event bus service", async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user