4d16acf5f0
What:
- Definition of all Modules links
- `link-modules` package to manage the creation of all pre-defined link or custom ones
```typescript
import { initialize as iniInventory } from "@medusajs/inventory";
import { initialize as iniProduct } from "@medusajs/product";
import {
initialize as iniLinks,
runMigrations as migrateLinks
} from "@medusajs/link-modules";
await Promise.all([iniInventory(), iniProduct()]);
await migrateLinks(); // create tables based on previous loaded modules
await iniLinks(); // load link based on previous loaded modules
await iniLinks(undefined, [
{
serviceName: "product_custom_translation_service_link",
isLink: true,
databaseConfig: {
tableName: "product_transalations",
},
alias: [
{
name: "translations",
},
],
primaryKeys: ["id", "product_id", "translation_id"],
relationships: [
{
serviceName: Modules.PRODUCT,
primaryKey: "id",
foreignKey: "product_id",
alias: "product",
},
{
serviceName: "custom_translation_service",
primaryKey: "id",
foreignKey: "translation_id",
alias: "transalation",
deleteCascade: true,
},
],
extends: [
{
serviceName: Modules.PRODUCT,
relationship: {
serviceName: "product_custom_translation_service_link",
primaryKey: "product_id",
foreignKey: "id",
alias: "translations",
isList: true,
},
},
{
serviceName: "custom_translation_service",
relationship: {
serviceName: "product_custom_translation_service_link",
primaryKey: "product_id",
foreignKey: "id",
alias: "product_link",
},
},
],
},
]); // custom links
```
Remote Link
```typescript
import { RemoteLink, Modules } from "@medusajs/modules-sdk";
// [...] initialize modules and links
const remoteLink = new RemoteLink();
// upsert the relationship
await remoteLink.create({ // one (object) or many (array)
[Modules.PRODUCT]: {
variant_id: "var_abc",
},
[Modules.INVENTORY]: {
inventory_item_id: "iitem_abc",
},
data: { // optional additional fields
required_quantity: 5
}
});
// dismiss (doesn't cascade)
await remoteLink.dismiss({ // one (object) or many (array)
[Modules.PRODUCT]: {
variant_id: "var_abc",
},
[Modules.INVENTORY]: {
inventory_item_id: "iitem_abc",
},
});
// delete
await remoteLink.delete({
// every key is a module
[Modules.PRODUCT]: {
// every key is a linkable field
variant_id: "var_abc", // single or multiple values
},
});
// restore
await remoteLink.restore({
// every key is a module
[Modules.PRODUCT]: {
// every key is a linkable field
variant_id: "var_abc", // single or multiple values
},
});
```
Co-authored-by: Riqwan Thamir <5105988+riqwan@users.noreply.github.com>
111 lines
2.6 KiB
TypeScript
111 lines
2.6 KiB
TypeScript
import { JoinerRelationship, ModuleJoinerConfig } from "@medusajs/types"
|
|
import {
|
|
SoftDeletableFilterKey,
|
|
mikroOrmSoftDeletableFilterOptions,
|
|
simpleHash,
|
|
} from "@medusajs/utils"
|
|
|
|
import { EntitySchema } from "@mikro-orm/core"
|
|
import { composeTableName } from "./compose-link-name"
|
|
|
|
function getClass(...properties) {
|
|
return class LinkModel {
|
|
constructor(...values) {
|
|
properties.forEach((name, idx) => {
|
|
this[name] = values[idx]
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
export function generateEntity(
|
|
joinerConfig: ModuleJoinerConfig,
|
|
primary: JoinerRelationship,
|
|
foreign: JoinerRelationship
|
|
) {
|
|
const fieldNames = primary.foreignKey.split(",").concat(foreign.foreignKey)
|
|
|
|
const tableName =
|
|
joinerConfig.databaseConfig?.tableName ??
|
|
composeTableName(
|
|
primary.serviceName,
|
|
primary.foreignKey,
|
|
foreign.serviceName,
|
|
foreign.foreignKey
|
|
)
|
|
|
|
const fields = fieldNames.reduce((acc, curr) => {
|
|
acc[curr] = {
|
|
type: "string",
|
|
nullable: false,
|
|
primary: true,
|
|
}
|
|
return acc
|
|
}, {})
|
|
|
|
const extraFields = joinerConfig.databaseConfig?.extraFields ?? {}
|
|
|
|
for (const column in extraFields) {
|
|
fieldNames.push(column)
|
|
|
|
fields[column] = {
|
|
type: extraFields[column].type,
|
|
nullable: !!extraFields[column].nullable,
|
|
defaultRaw: extraFields[column].defaultValue,
|
|
...(extraFields[column].options ?? {}),
|
|
}
|
|
}
|
|
|
|
const hashTableName = simpleHash(tableName)
|
|
|
|
return new EntitySchema({
|
|
class: getClass(
|
|
...fieldNames.concat("created_at", "updated_at", "deleted_at")
|
|
) as any,
|
|
tableName,
|
|
properties: {
|
|
id: {
|
|
type: "string",
|
|
nullable: false,
|
|
},
|
|
...fields,
|
|
created_at: {
|
|
type: "Date",
|
|
nullable: false,
|
|
defaultRaw: "CURRENT_TIMESTAMP",
|
|
},
|
|
updated_at: {
|
|
type: "Date",
|
|
nullable: false,
|
|
defaultRaw: "CURRENT_TIMESTAMP",
|
|
},
|
|
deleted_at: { type: "Date", nullable: true },
|
|
},
|
|
filters: {
|
|
[SoftDeletableFilterKey]: mikroOrmSoftDeletableFilterOptions,
|
|
},
|
|
indexes: [
|
|
{
|
|
properties: ["id"],
|
|
name: "IDX_id_" + hashTableName,
|
|
},
|
|
{
|
|
properties: primary.foreignKey.split(","),
|
|
name:
|
|
"IDX_" +
|
|
primary.foreignKey.split(",").join("_") +
|
|
"_" +
|
|
hashTableName,
|
|
},
|
|
{
|
|
properties: foreign.foreignKey,
|
|
name: "IDX_" + foreign.foreignKey + "_" + hashTableName,
|
|
},
|
|
{
|
|
properties: ["deleted_at"],
|
|
name: "IDX_deleted_at_" + hashTableName,
|
|
},
|
|
],
|
|
})
|
|
}
|