feat(medusa, link-modules): sales channel <> pubkey link (#5820)

This commit is contained in:
Frane Polić
2024-01-05 14:51:57 +01:00
committed by GitHub
parent bf63c4e6a3
commit 6fc6a9de6a
12 changed files with 195 additions and 38 deletions

View File

@@ -0,0 +1,7 @@
---
"@medusajs/link-modules": patch
"@medusajs/medusa": patch
---
feat: PubKey <> SC joiner config

View File

@@ -338,14 +338,14 @@ describe("Publishable API keys", () => {
expect(response.status).toBe(200)
expect(mappings).toEqual([
{
expect.objectContaining({
sales_channel_id: salesChannel1.id,
publishable_key_id: pubKeyId,
},
{
}),
expect.objectContaining({
sales_channel_id: salesChannel2.id,
publishable_key_id: pubKeyId,
},
}),
])
expect(response.data.publishable_api_key).toMatchObject({
@@ -386,10 +386,10 @@ describe("Publishable API keys", () => {
await dbConnection.manager.query(
`INSERT INTO publishable_api_key_sales_channel
(publishable_key_id, sales_channel_id)
VALUES ('${pubKeyId}', '${salesChannel1.id}'),
('${pubKeyId}', '${salesChannel2.id}'),
('${pubKeyId}', '${salesChannel3.id}');`
(id, publishable_key_id, sales_channel_id)
VALUES ('pksc-1','${pubKeyId}', '${salesChannel1.id}'),
('pksc-2','${pubKeyId}', '${salesChannel2.id}'),
('pksc-3','${pubKeyId}', '${salesChannel3.id}');`
)
})
@@ -417,16 +417,16 @@ describe("Publishable API keys", () => {
const mappings = await dbConnection.manager.query(
`SELECT *
FROM publishable_api_key_sales_channel
WHERE publishable_key_id = '${pubKeyId}'`
WHERE publishable_key_id = '${pubKeyId}';`
)
expect(response.status).toBe(200)
expect(mappings).toEqual([
{
expect.objectContaining({
sales_channel_id: salesChannel3.id,
publishable_key_id: pubKeyId,
},
}),
])
expect(response.data.publishable_api_key).toMatchObject({
@@ -467,9 +467,9 @@ describe("Publishable API keys", () => {
await dbConnection.manager.query(
`INSERT INTO publishable_api_key_sales_channel
(publishable_key_id, sales_channel_id)
VALUES ('${pubKeyId}', '${salesChannel1.id}'),
('${pubKeyId}', '${salesChannel2.id}');`
(id, publishable_key_id, sales_channel_id)
VALUES ('pksc-1', '${pubKeyId}', '${salesChannel1.id}'),
('pksc-2', '${pubKeyId}', '${salesChannel2.id}');`
)
})

View File

@@ -5,3 +5,4 @@ export * from "./product-shipping-profile"
export * from "./product-sales-channel"
export * from "./cart-sales-channel"
export * from "./order-sales-channel"
export * from "./publishable-api-key-sales-channel"

View File

@@ -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,
},
},
],
}

View File

@@ -40,4 +40,10 @@ export const LINKS = {
"salesChannelService",
"sales_channel_id"
),
PublishableApiKeySalesChannel: composeLinkName(
"publishableApiKeyService",
"publishable_key_id",
"salesChannelService",
"sales_channel_id"
),
}

View File

@@ -3,3 +3,4 @@ export * as customer from "./customer-service"
export * as region from "./region-service"
export * as salesChannel from "./sales-channel-service"
export * as shippingProfile from "./shipping-profile-service"
export * as publishableApiKey from "./publishable-api-key-service"

View File

@@ -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

View File

@@ -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";
`)
}
}

View File

@@ -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()
export class PublishableApiKeySalesChannel {
@PrimaryColumn()
@Entity("publishable_api_key_sales_channel")
export class PublishableApiKeySalesChannel extends BaseEntity {
@Column({ type: "text" })
id: string
@PrimaryColumn({ type: "text" })
sales_channel_id: string
@PrimaryColumn()
@PrimaryColumn({ type: "text" })
publishable_key_id: string
/**
* @apiIgnore
*/
@BeforeInsert()
private beforeInsert(): void {
this.id = generateEntityId(this.id, "pksc")
}
}
/**

View File

@@ -11,6 +11,7 @@ import { SalesChannelLocation } from "./sales-channel-location"
import { Product } from "./product"
import { Cart } from "./cart"
import { Order } from "./order"
import { PublishableApiKey } from "./publishable-api-key"
@FeatureFlagEntity("sales_channels")
export class SalesChannel extends SoftDeletableEntity {
@@ -74,6 +75,20 @@ export class SalesChannel extends SoftDeletableEntity {
)
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(
() => SalesChannelLocation,
(scLocation) => scLocation.sales_channel,

View File

@@ -3,6 +3,7 @@ import { Brackets, In } from "typeorm"
import { PublishableApiKeySalesChannel, SalesChannel } from "../models"
import { dataSource } from "../loaders/database"
import SalesChannelRepository from "./sales-channel"
import { generateEntityId } from "../utils"
const publishableApiKeySalesChannelAlias = "PublishableKeySalesChannel"
@@ -64,15 +65,16 @@ export const PublishableApiKeySalesChannelRepository = dataSource
publishableApiKeyId: string,
salesChannelIds: string[]
): Promise<void> {
const valuesToInsert = salesChannelIds.map((id) => ({
id: generateEntityId(undefined, "pksc"),
sales_channel_id: id,
publishable_key_id: publishableApiKeyId,
}))
await this.createQueryBuilder()
.insert()
.into(PublishableApiKeySalesChannel)
.values(
salesChannelIds.map((id) => ({
sales_channel_id: id,
publishable_key_id: publishableApiKeyId,
}))
)
.values(valuesToInsert)
.orIgnore()
.execute()
},

View File

@@ -41,19 +41,13 @@ describe("PublishableApiKeyService", () => {
await publishableApiKeyService.retrieve(
IdMap.getId("order-edit-with-changes")
)
expect(
publishableApiKeyRepository.findOne
).toHaveBeenCalledTimes(1)
expect(
publishableApiKeyRepository.findOne
).toHaveBeenCalledWith(
{
relationLoadStrategy: "query",
where: {
id: IdMap.getId("order-edit-with-changes")
}
}
)
expect(publishableApiKeyRepository.findOne).toHaveBeenCalledTimes(1)
expect(publishableApiKeyRepository.findOne).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 () => {