feat(link-modules,modules-sdk, utils, types, products) - Remote Link and Link modules (#4695)
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>
This commit is contained in:
committed by
GitHub
parent
bc4c9e0d32
commit
4d16acf5f0
9
packages/link-modules/src/utils/compose-link-name.ts
Normal file
9
packages/link-modules/src/utils/compose-link-name.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { lowerCaseFirst, toPascalCase } from "@medusajs/utils"
|
||||
|
||||
export const composeLinkName = (...args) => {
|
||||
return lowerCaseFirst(toPascalCase(composeTableName(...args.concat("link"))))
|
||||
}
|
||||
|
||||
export const composeTableName = (...args) => {
|
||||
return args.map((name) => name.replace(/(_id|Service)$/gi, "")).join("_")
|
||||
}
|
||||
110
packages/link-modules/src/utils/generate-entity.ts
Normal file
110
packages/link-modules/src/utils/generate-entity.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
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,
|
||||
},
|
||||
],
|
||||
})
|
||||
}
|
||||
12
packages/link-modules/src/utils/index.ts
Normal file
12
packages/link-modules/src/utils/index.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { MODULE_RESOURCE_TYPE } from "@medusajs/types"
|
||||
|
||||
export * from "./compose-link-name"
|
||||
export * from "./generate-entity"
|
||||
|
||||
export function shouldForceTransaction(target: any): boolean {
|
||||
return target.moduleDeclaration?.resources === MODULE_RESOURCE_TYPE.ISOLATED
|
||||
}
|
||||
|
||||
export function doNotForceTransaction(): boolean {
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user