How to Create a File Provider Module

In this document, you’ll learn how to create a file provider module and the methods you must implement in its main service.


1. Create Module Directory#

Start by creating a new directory for your module. For example, src/modules/my-file.


2. Create the File Provider Service#

Create the file src/modules/my-file/service.ts that holds the implementation of the module's main service. It must extend the AbstractFileProviderService class imported from @medusajs/framework/utils:

src/modules/my-file/service.ts
1import { AbstractFileProviderService } from "@medusajs/framework/utils"2
3class MyFileProviderService extends AbstractFileProviderService {4  // TODO implement methods5}6
7export default MyFileProviderService

constructor#

The constructor allows you to access resources from the module's container using the first parameter, and the module's options using the second parameter.

If you're creating a client or establishing a connection with a third-party service, do it in the constructor.

Example

Code
1import { Logger } from "@medusajs/framework/types"2import { AbstractFileProviderService } from "@medusajs/framework/utils"3
4type InjectedDependencies = {5  logger: Logger6}7
8type Options = {9  apiKey: string10}11
12class MyFileProviderService extends AbstractFileProviderService {13  protected logger_: Logger14  protected options_: Options15  static identifier = "my-file"16  // assuming you're initializing a client17  protected client18
19  constructor (20    { logger }: InjectedDependencies,21    options: Options22  ) {23    super()24
25    this.logger_ = logger26    this.options_ = options27
28    // assuming you're initializing a client29    this.client = new Client(options)30  }31}32
33export default MyFileProviderService

identifier#

Each file provider has a unique ID used to identify it. The provider's ID will be stored as fs_{identifier}_{id}, where {id} is the provider's id property in the medusa-config.ts.

Example

Code
1class MyFileProviderService extends AbstractFileProviderService {2  static identifier = "my-file"3  // ...4}

validateOptions#

This method validates the options of the provider set in medusa-config.ts. Implementing this method is optional. It's useful if your provider requires custom validation.

If the options aren't valid, throw an error.

Example

Code
1class MyFileProviderService extends AbstractFileProviderService {2  static validateOptions(options: Record<any, any>) {3    if (!options.apiKey) {4      throw new MedusaError(5        MedusaError.Types.INVALID_DATA,6        "API key is required in the provider's options."7      )8    }9  }10}

Parameters

optionsRecord<any, any>
The provider's options.

Returns

voidvoid
This method validates the options of the provider set in medusa-config.ts. Implementing this method is optional. It's useful if your provider requires custom validation. If the options aren't valid, throw an error.

upload#

This method uploads a file using your provider's custom logic.

Example

Code
1class MyFileProviderService extends AbstractFileProviderService {2  // ...3  async upload(4    file: ProviderUploadFileDTO5  ): Promise<ProviderFileResultDTO> {6    // TODO upload file to third-party provider7    // or using custom logic8
9    return {10      url: "some-url.com",11      key: "file-name"12    }13  }14}

Parameters

The file to upload

Returns

PromisePromise<ProviderFileResultDTO>
The uploaded file's details.

delete#

This method deletes the file from storage.

Example

Code
1class MyFileProviderService extends AbstractFileProviderService {2  // ...3  async delete(file: ProviderDeleteFileDTO): Promise<void> {4    // TODO logic to remove the file from storage5    // Use the `file.fileKey` to delete the file6    // for example:7    this.client.delete(file.fileKey)8  }9}

Parameters

The details of the file to delete.

Returns

PromisePromise<void>
Resolves when the file is deleted.

getPresignedDownloadUrl#

This method is used to retrieve a download URL of the file. For some providers, such as S3, a presigned URL indicates a temporary URL to get access to a file.

If your provider doesn’t perform or offer a similar functionality, you can return the URL to download the file.

Example

Code
1class MyFileProviderService extends AbstractFileProviderService {2  // ...3  async getPresignedDownloadUrl(4    fileData: ProviderGetFileDTO5  ): Promise<string> {6    // TODO logic to get the presigned URL7    // Use the `file.fileKey` to delete the file8    // for example:9    return this.client.getPresignedUrl(fileData.fileKey)10  }11}

Parameters

The details of the file to get its presigned URL.

Returns

PromisePromise<string>
The file's presigned URL.

3. Create Module Definition File#

Create the file src/modules/my-file/index.ts with the following content:

src/modules/my-file/index.ts
1import MyFileProviderService from "./service"2import { 3  ModuleProvider, 4  Modules5} from "@medusajs/framework/utils"6
7export default ModuleProvider(Modules.FILE, {8  services: [MyFileProviderService],9})

This exports the module's definition, indicating that the MyFileProviderService is the module's service.


4. Use Module#

To use your File Module Provider, add it to the providers array of the File Module in medusa-config.ts:

NoteThe File Module accepts one provider only.
medusa-config.ts
1module.exports = defineConfig({2  // ...3  modules: [4    {5      resolve: "@medusajs/medusa/file",6      options: {7        providers: [8          // default provider9          {10            resolve: "@medusajs/medusa/file-local",11            id: "local",12          },13          {14            resolve: "./src/modules/my-file",15            id: "my-file",16            options: {17              // provider options...18            },19          },20        ],21      },22    },23  ]24})

5. Test it Out#

To test out your file provider, use the Medusa Admin or the Upload API route to upload a file.

Was this page helpful?