Whats Medusa an introduction part 3 Modules
Tags: webdev, javascript, beginners, medusa
Published: 2023-05-29 17:32:47

In this blogpost I will introduce you to Modules and how you can use them.

Modules are self-contained reusable pieces of code which add functionality to your ecommerce application.
Modules increase Medusas extensibilty and can be seen as small units of independent code. Modules can run independently of Medusas core package.

Modules are created and loaded similarly to plugins. They can be loaded from a local project or can be installed from an NPM package. 

### Create a module

Create a directory with the following structure in it:

```
custom-module
|
|--index.ts
|
|--services // directory
```

The directory can be an NPM project but that's optional. index.ts is the entry point to our module. The services directory holds extra services. The following TypeScript configuration file tsconfig.json should be added in the root of the project.

```js
{
  "compilerOptions": {
    "lib": [
      "es2020"
    ],
    "target": "2020",
    "outDir": "./dist",
    "esModuleInterop": true,
    "declaration": true,
    "module": "commonjs",
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "sourceMap": true,
    "noImplicitReturns": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "noImplicitThis": true,
    "allowJs": true,
    "skipLibCheck": true,
  },
  "include": ["src"],
  "exclude": [
    "dist",
    "./src/**/__tests__",
    "./src/**/__mocks__",
    "./src/**/__fixtures__",
    "node_modules"
  ]
}
```

###Implementing the module

When developing the module you'll later reference the module using a file path to a index.js or index.ts file.
This file acts as an entry point to our module.

###Export the module

To use the module withe the medusa backend we need to export it. This is done in the file index.ts the file must export an object with the following properties:

```js
type ModuleExports = {
  service: Constructor<any>
  loaders?: ModuleLoaderFunction[]
  migrations?: any[]
  models?: Constructor<any>[]
  runMigrations?(
    options: LoaderOptions,
    moduleDeclaration: InternalModuleDeclaration
  ): Promise<void>
  revertMigration?(
    options: LoaderOptions,
    moduleDeclaration: InternalModuleDeclaration
  ): Promise<void>
}
```
### Reference module

To use the module in the Medusa backend add your module to medusa-config.js:

```js
module.exports = {
  // ...
  modules: { 
    // ...
    moduleType: {
      resolve: "module-name-or-path", 
      options: {
        // options if necessary
      },
      // optional
      resources: "shared",
    },
  },
}
```
###Module reference

If a module is installed as NPM package the value of the resolve property should be the name of the package:
```js
module.exports = {
  // ...
  modules: { 
    // ...
    moduleType: {
      resolve: "custom-module", 
      // ...
    },
  },
}
```

Whe using a local module you must reference the module from using an relative file path to ot from the Medusa backend.
```
|
|---custom module
|   |
|   |---index.ts
|   |
|   |---services
|   |    |
|   |    |---custom-service.ts
|
|
|
---medusa-backend
```
You can reference your module in two ways:

1. Referencing the directory 
the index.ts file is in the root of the directory

medusa-config.js:
```js
module.exports = {
  // ...
  modules: { 
    // ...
    moduleType: {
      resolve: "../custom-module", 
      // ...
    },
  },
}
```

2. Referencing the index file
medusa-config.js
```js
module.exports = {
  // ...
  modules: { 
    // ...
    moduleType: {
      resolve: "../custom-module/index.ts", 
      // ...
    },
  },
}
```

###Test your module

Test your module running the following command:
```
npx @medusajs/medusa-cli develop
```

###Howto publish a module

You'll need an NPM account to publish a module.

Create an NPM project

Run the folllowing commands to create a directory and init an NPM project in it:
```
mkdir my-module
yarn init
```
A package.json file will be created inside the directory.

###Changes to package.json

In your package.json file add the following fields:
```js
{
  // other fields
  "main": "dist/index.js",
  "publishConfig": {
    "access": "public"
  },
  "files": [
    "dist"
  ],
  "devDependencies": {
    "@medusajs/types": "^0.0.2",
    "cross-env": "^5.2.1",
    "typescript": "^4.4.4"
  },
  "scripts": {
    "watch": "tsc --build --watch",
    "prepare": "cross-env NODE_ENV=production npm run build",
    "build": "tsc --build",
  },
  "dependencies": {
    "@medusajs/modules-sdk": "^0.1.0",
  }
}
```

###Configure tsconfig.json

Create a tsconfig.json file in the root of your NPM project:

tsconfig.json
```
{
  "compilerOptions": {
    "lib": [
      "es2020"
    ],
    "target": "2020",
    "outDir": "./dist",
    "esModuleInterop": true,
    "declaration": true,
    "module": "commonjs",
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "sourceMap": true,
    "noImplicitReturns": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "noImplicitThis": true,
    "allowJs": true,
    "skipLibCheck": true,
  },
  "include": ["src"],
  "exclude": [
    "dist",
    "./src/**/__tests__",
    "./src/**/__mocks__",
    "./src/**/__fixtures__",
    "node_modules"
  ]
}
```

##Publish and use module
Run prepare command
```
yarn prepare
```
Login into your npm account:
```
npm login
```
Publish module package
```
npm publish
```

Thats all for now on modules in Medusa.js I hope you enjoyed this blogpost.