Skip to content

Commit

Permalink
feat(link-modules,modules-sdk, utils, types, products) - Remote Link …
Browse files Browse the repository at this point in the history
…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 <[email protected]>
  • Loading branch information
carlos-r-l-rodrigues and riqwan authored Aug 30, 2023
1 parent bc4c9e0 commit 4d16acf
Show file tree
Hide file tree
Showing 97 changed files with 3,535 additions and 419 deletions.
7 changes: 7 additions & 0 deletions .changeset/poor-ants-deliver.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@medusajs/link-modules": patch
"@medusajs/modules-sdk": patch
"@medusajs/types": patch
---

Add extra fields to link modules
9 changes: 9 additions & 0 deletions .changeset/selfish-needles-beg.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@medusajs/orchestration": minor
"@medusajs/link-modules": minor
"@medusajs/modules-sdk": minor
"@medusajs/types": minor
"@medusajs/utils": minor
---

Medusa App Loader
13 changes: 13 additions & 0 deletions .changeset/warm-bikes-enjoy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
"@medusajs/stock-location": minor
"@medusajs/orchestration": minor
"@medusajs/link-modules": minor
"@medusajs/modules-sdk": minor
"@medusajs/inventory": minor
"@medusajs/product": minor
"@medusajs/medusa": minor
"@medusajs/types": minor
"@medusajs/utils": minor
---

introduce @medusajs/link-modules
188 changes: 188 additions & 0 deletions integration-tests/plugins/__tests__/link-modules/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
import { initialize, runMigrations } from "@medusajs/link-modules"
import { MedusaModule, ModuleJoinerConfig } from "@medusajs/modules-sdk"

jest.setTimeout(5000000)

const DB_HOST = process.env.DB_HOST
const DB_USERNAME = process.env.DB_USERNAME
const DB_PASSWORD = process.env.DB_PASSWORD
const DB_NAME = process.env.DB_TEMP_NAME
const DB_URL = `postgres://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}/${DB_NAME}`

describe("Link Modules", () => {
let links
const linkDefinition: ModuleJoinerConfig[] = [
{
serviceName: "linkServiceName",
isLink: true,
databaseConfig: {
tableName: "linkTableName",
idPrefix: "prefix",
extraFields: {
extra_field: {
type: "integer",
defaultValue: "-1",
},
another_field: {
type: "string",
nullable: true,
},
},
},
relationships: [
{
serviceName: "moduleA",
primaryKey: "id",
foreignKey: "product_id",
alias: "product",
},
{
serviceName: "moduleB",
primaryKey: "id",
foreignKey: "inventory_item_id",
alias: "inventory",
},
],
},
]
const dbConfig = {
database: {
clientUrl: DB_URL,
},
}

beforeAll(async () => {
jest.spyOn(MedusaModule, "getLoadedModules").mockImplementation((() => {
return [{ moduleA: [{}] }, { moduleB: [{}] }]
}) as any)

await runMigrations({ options: dbConfig }, linkDefinition)
links = await initialize(dbConfig, linkDefinition)
})

afterAll(async () => {
jest.clearAllMocks()
})

it("Should insert values in a declared link", async function () {
// simple
await links.linkServiceName.create("modA_id", "modB_id")

// extra fields
await links.linkServiceName.create("123", "abc", {
extra_field: 333,
another_field: "value**",
})

// bulk
await links.linkServiceName.create([
["111", "aaa", { another_field: "test" }],
["222", "bbb"],
["333", "ccc", { extra_field: 2 }],
["444", "bbb"],
])

const values = await links.linkServiceName.list()

expect(values).toEqual([
{
product_id: "modA_id",
inventory_item_id: "modB_id",
id: expect.stringMatching("prefix_.+"),
extra_field: -1,
another_field: null,
created_at: expect.any(Date),
updated_at: expect.any(Date),
deleted_at: null,
},
expect.objectContaining({
product_id: "123",
inventory_item_id: "abc",
id: expect.stringMatching("prefix_.+"),
extra_field: 333,
another_field: "value**",
}),
expect.objectContaining({
product_id: "111",
inventory_item_id: "aaa",
extra_field: -1,
another_field: "test",
}),
expect.objectContaining({
product_id: "222",
inventory_item_id: "bbb",
extra_field: -1,
another_field: null,
}),
expect.objectContaining({
product_id: "333",
inventory_item_id: "ccc",
id: expect.stringMatching("prefix_.+"),
extra_field: 2,
}),
expect.objectContaining({
product_id: "444",
inventory_item_id: "bbb",
}),
])
})

it("Should dismiss the link of a given pair of keys", async function () {
// simple
const dismissSingle = await links.linkServiceName.dismiss(
"modA_id",
"modB_id"
)

// bulk
const dismissMulti = await links.linkServiceName.dismiss([
["111", "aaa"],
["333", "ccc"],
])

expect(dismissSingle).toEqual([
expect.objectContaining({
product_id: "modA_id",
inventory_item_id: "modB_id",
deleted_at: expect.any(Date),
}),
])

expect(dismissMulti).toEqual([
expect.objectContaining({
product_id: "111",
inventory_item_id: "aaa",
deleted_at: expect.any(Date),
}),
expect.objectContaining({
product_id: "333",
inventory_item_id: "ccc",
deleted_at: expect.any(Date),
}),
])
})

it("Should delete all the links related to a given key", async function () {
await links.linkServiceName.softDelete({
inventory_item_id: "bbb",
})

const values = await links.linkServiceName.list(
{ inventory_item_id: "bbb" },
{ withDeleted: true }
)

expect(values).toEqual([
expect.objectContaining({
product_id: "222",
inventory_item_id: "bbb",
deleted_at: expect.any(Date),
}),
expect.objectContaining({
product_id: "444",
inventory_item_id: "bbb",
deleted_at: expect.any(Date),
}),
])
})
})
14 changes: 7 additions & 7 deletions packages/cache-inmemory/jest.config.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
module.exports = {
globals: {
"ts-jest": {
tsConfig: "tsconfig.spec.json",
isolatedModules: false,
},
},
transform: {
"^.+\\.[jt]s?$": "ts-jest",
"^.+\\.[jt]s?$": [
"ts-jest",
{
tsConfig: "tsconfig.json",
isolatedModules: true,
},
],
},
testEnvironment: `node`,
moduleFileExtensions: [`js`, `ts`],
Expand Down
6 changes: 3 additions & 3 deletions packages/cache-inmemory/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
"devDependencies": {
"@medusajs/types": "^1.8.8",
"cross-env": "^5.2.1",
"jest": "^25.5.4",
"jest": "^29.6.3",
"rimraf": "^5.0.1",
"ts-jest": "^25.5.1",
"typescript": "^4.4.4"
"ts-jest": "^29.1.1",
"typescript": "^5.1.6"
},
"scripts": {
"watch": "tsc --build --watch",
Expand Down
14 changes: 7 additions & 7 deletions packages/cache-redis/jest.config.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
module.exports = {
globals: {
"ts-jest": {
tsConfig: "tsconfig.spec.json",
isolatedModules: false,
},
},
transform: {
"^.+\\.[jt]s?$": "ts-jest",
"^.+\\.[jt]s?$": [
"ts-jest",
{
tsConfig: "tsconfig.json",
isolatedModules: true,
},
],
},
testEnvironment: `node`,
moduleFileExtensions: [`js`, `ts`],
Expand Down
6 changes: 3 additions & 3 deletions packages/cache-redis/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
"devDependencies": {
"@medusajs/types": "^1.8.8",
"cross-env": "^5.2.1",
"jest": "^25.5.4",
"jest": "^29.6.3",
"rimraf": "^5.0.1",
"ts-jest": "^25.5.1",
"typescript": "^4.4.4"
"ts-jest": "^29.1.1",
"typescript": "^5.1.6"
},
"scripts": {
"watch": "tsc --build --watch",
Expand Down
16 changes: 8 additions & 8 deletions packages/event-bus-local/jest.config.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
module.exports = {
globals: {
"ts-jest": {
tsConfig: "tsconfig.spec.json",
isolatedModules: false,
},
},
transform: {
"^.+\\.[jt]s?$": "ts-jest",
"^.+\\.[jt]s?$": [
"ts-jest",
{
tsConfig: "tsconfig.json",
isolatedModules: true,
},
],
},
testEnvironment: `node`,
moduleFileExtensions: [`js`, `jsx`, `ts`, `tsx`, `json`],
moduleFileExtensions: [`js`, `ts`],
}
6 changes: 3 additions & 3 deletions packages/event-bus-local/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
"devDependencies": {
"@medusajs/types": "^1.8.10",
"cross-env": "^5.2.1",
"jest": "^25.5.2",
"jest": "^29.6.3",
"rimraf": "^5.0.1",
"ts-jest": "^25.5.1",
"typescript": "^4.4.4"
"ts-jest": "^29.1.1",
"typescript": "^5.1.6"
},
"scripts": {
"watch": "tsc --build --watch",
Expand Down
16 changes: 8 additions & 8 deletions packages/event-bus-redis/jest.config.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
module.exports = {
globals: {
"ts-jest": {
tsConfig: "tsconfig.spec.json",
isolatedModules: false,
},
},
transform: {
"^.+\\.[jt]s?$": "ts-jest",
"^.+\\.[jt]s?$": [
"ts-jest",
{
tsConfig: "tsconfig.json",
isolatedModules: true,
},
],
},
testEnvironment: `node`,
moduleFileExtensions: [`js`, `jsx`, `ts`, `tsx`, `json`],
moduleFileExtensions: [`js`, `ts`],
}
6 changes: 3 additions & 3 deletions packages/event-bus-redis/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@
"devDependencies": {
"@medusajs/types": "^1.8.10",
"cross-env": "^5.2.1",
"jest": "^25.5.2",
"jest": "^29.6.3",
"medusa-test-utils": "^1.1.40",
"rimraf": "^5.0.1",
"ts-jest": "^25.5.1",
"typescript": "^4.4.4"
"ts-jest": "^29.1.1",
"typescript": "^5.1.6"
},
"scripts": {
"watch": "tsc --build --watch",
Expand Down
14 changes: 7 additions & 7 deletions packages/inventory/jest.config.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
module.exports = {
globals: {
"ts-jest": {
tsConfig: "tsconfig.spec.json",
isolatedModules: false,
},
},
transform: {
"^.+\\.[jt]s?$": "ts-jest",
"^.+\\.[jt]s?$": [
"ts-jest",
{
tsConfig: "tsconfig.json",
isolatedModules: true,
},
],
},
testEnvironment: `node`,
moduleFileExtensions: [`js`, `ts`],
Expand Down
6 changes: 3 additions & 3 deletions packages/inventory/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
"devDependencies": {
"@medusajs/types": "^1.8.11",
"cross-env": "^5.2.1",
"jest": "^25.5.4",
"jest": "^29.6.3",
"rimraf": "^5.0.1",
"ts-jest": "^25.5.1",
"typescript": "^4.4.4"
"ts-jest": "^29.1.1",
"typescript": "^5.1.6"
},
"dependencies": {
"@medusajs/modules-sdk": "^1.8.8",
Expand Down
Loading

0 comments on commit 4d16acf

Please sign in to comment.