Files
medusa-store/www/docs/content/development/entities/repositories.md
Shahed Nasser 914d773d3a api-ref: custom API reference (#4770)
* initialized next.js project

* finished markdown sections

* added operation schema component

* change page metadata

* eslint fixes

* fixes related to deployment

* added response schema

* resolve max stack issue

* support for different property types

* added support for property types

* added loading for components

* added more loading

* type fixes

* added oneOf type

* removed console

* fix replace with push

* refactored everything

* use static content for description

* fixes and improvements

* added code examples section

* fix path name

* optimizations

* fixed tag navigation

* add support for admin and store references

* general enhancements

* optimizations and fixes

* fixes and enhancements

* added search bar

* loading enhancements

* added loading

* added code blocks

* added margin top

* add empty response text

* fixed oneOf parameters

* added path and query parameters

* general fixes

* added base path env variable

* small fix for arrays

* enhancements

* design enhancements

* general enhancements

* fix isRequired

* added enum values

* enhancements

* general fixes

* general fixes

* changed oas generation script

* additions to the introduction section

* added copy button for code + other enhancements

* fix response code block

* fix metadata

* formatted store introduction

* move sidebar logic to Tags component

* added test env variables

* fix code block bug

* added loading animation

* added expand param + loading

* enhance operation loading

* made responsive + improvements

* added loading provider

* fixed loading

* adjustments for small devices

* added sidebar label for endpoints

* added feedback component

* fixed analytics

* general fixes

* listen to scroll for other headings

* added sample env file

* update api ref files + support new fields

* fix for external docs link

* added new sections

* fix last item in sidebar not showing

* move docs content to www/docs

* change redirect url

* revert change

* resolve build errors

* configure rewrites

* changed to environment variable url

* revert changing environment variable name

* add environment variable for API path

* fix links

* fix tailwind settings

* remove vercel file

* reconfigured api route

* move api page under api

* fix page metadata

* fix external link in navigation bar

* update api spec

* updated api specs

* fixed google lint error

* add max-height on request samples

* add padding before loading

* fix for one of name

* fix undefined types

* general fixes

* remove response schema example

* redesigned navigation bar

* redesigned sidebar

* fixed up paddings

* added feedback component + report issue

* fixed up typography, padding, and general styling

* redesigned code blocks

* optimization

* added error timeout

* fixes

* added indexing with algolia + fixes

* fix errors with algolia script

* redesign operation sections

* fix heading scroll

* design fixes

* fix padding

* fix padding + scroll issues

* fix scroll issues

* improve scroll performance

* fixes for safari

* optimization and fixes

* fixes to docs + details animation

* padding fixes for code block

* added tab animation

* fixed incorrect link

* added selection styling

* fix lint errors

* redesigned details component

* added detailed feedback form

* api reference fixes

* fix tabs

* upgrade + fixes

* updated documentation links

* optimizations to sidebar items

* fix spacing in sidebar item

* optimizations and fixes

* fix endpoint path styling

* remove margin

* final fixes

* change margin on small devices

* generated OAS

* fixes for mobile

* added feedback modal

* optimize dark mode button

* fixed color mode useeffect

* minimize dom size

* use new style system

* radius and spacing design system

* design fixes

* fix eslint errors

* added meta files

* change cron schedule

* fix docusaurus configurations

* added operating system to feedback data

* change content directory name

* fixes to contribution guidelines

* revert renaming content

* added api-reference to documentation workflow

* fixes for search

* added dark mode + fixes

* oas fixes

* handle bugs

* added code examples for clients

* changed tooltip text

* change authentication to card

* change page title based on selected section

* redesigned mobile navbar

* fix icon colors

* fix key colors

* fix medusa-js installation command

* change external regex in algolia

* change changeset

* fix padding on mobile

* fix hydration error

* update depedencies
2023-08-15 18:07:54 +03:00

8.4 KiB
Raw Blame History

description
description
In this document, you'll learn what repositories are, how to use them within your Medusa backend, and what are some of their common methods.

Repositories

In this document, you'll learn what repositories are, how to use them within your Medusa backend, and what are some of their common methods.

Overview

Repositories provide generic helper methods for entities. For example, a find method to retrieve all entities with pagination, or findOne to retrieve a single entity record.

Repostories are Typeorm repositories, so you can refer to Typeorm's documentation on all available methods.

This guide provides some basic methods you'll need during your custom development with Medusa.


Basic Implementation

Each entity you create needs a repository. A repository is created under the src/repositories directory of your Medusa backend project. The file name is the name of the repository without Repository.

For example, to create a repository for a Post entity, create the file src/repositories/post.ts with the following content:

import { Post } from "../models/post"
import { 
  dataSource,
} from "@medusajs/medusa/dist/loaders/database"

export const PostRepository = dataSource
  .getRepository(Post)

export default PostRepository

The repository is created using the getRepository method of the data source exported from the core package in Medusa. This method accepts the entity as a parameter.

:::tip

A data source is Typeorms connection settings that allows you to connect to your database. You can learn more about it in Typeorms documentation.

:::


Customizing a Repository

If you want to add methods to the repository or override Typeorm's Repository methods, you can do that using the extend method:

import { Post } from "../models/post"
import { 
  dataSource,
} from "@medusajs/medusa/dist/loaders/database"

export const PostRepository = dataSource
  .getRepository(Post)
  .extend({
    customFunction(): void {
      // TODO add custom implementation
      return
    },
  })

export default PostRepository

You can learn about available Repository methods in Typeorm's documentation.


Using Repositories in Other Resources

When you want to perform an action or use on an entity in one of your custom resources, such as an endpoint or a service, you need to use its repository.

Endpoints

To access a repository within an endpoint, use the req.scope.resolve method. For example:

import { PostRepository } from "../repositories/post"
import { EntityManager } from "typeorm"

// ...

export default () => {
  // ...

  storeRouter.get("/posts", async (req, res) => {
    const postRepository: typeof PostRepository = 
      req.scope.resolve("postRepository")
    const manager: EntityManager = req.scope.resolve("manager")
    const postRepo = manager.withRepository(postRepository)

    return res.json({
      posts: await postRepo.find(),
    })
  })

  // ...
}

You can learn more about endpoints here.

Services and Subscribers

As repositories are registered in the dependency container, they can be accessed through dependency injection in the constructor of a service or a subscriber.

For example:

import { PostRepository } from "../repositories/post"

class PostService extends TransactionBaseService {
  // ...
  protected postRepository_: typeof PostRepository

  constructor(container) {
    super(container)
    // ...
    this.postRepository_ = container.postRepository
  }

  async list(): Promise<Post[]> {
    const postRepo = this.activeManager_.withRepository(
      this.postRepository_
    )
    return await postRepo.find()
  }

  // ...
}

You can learn more about services here.

Other Resources

Resources that have access to the dependency container can access repositories just like any other resources. You can learn more about the dependency container and dependency injection in this documentation.


Common Methods

This section covers some common methods and use cases you'll use with repositories. You can refer to Typeorm's documentation for full details on available methods.

Retrieving a List of Records

To retrieve a list of records of an entity, use the find method:

const posts = await postRepository.find()

You can also filter the retrieved items by passing an object of type FindOption as a first parameter:

const posts = await postRepository.find({
  where: {
    id: "1",
  },
})

In addition, you can pass skip and take properties to the object for pagination purposes. skip's value is a number that indicates how many items to skip before retrieving the results, and take indicates how many items to return:

const posts = await postRepository.find({
  skip: 0,
  take: 20,
})

To expand relations and retrieve them as part of each item in the result, you can pass the relations property to the parameter object:

const posts = await postRepository.find({
  relations: ["authors"],
})

Medusa provides a utility method buildQuery that allows you to easily format the object to pass to the find method. buildQuery accepts two parameters:

  1. The first parameter is an object whose keys are the attributes of the entity, and their values are the value to filter by.
  2. The second parameter includes the options related to pagination (such as skip and take), the relations to expand, and fields to select in each returned item.

For example:

import { buildQuery } from "@medusajs/medusa"

// ...
const selector = {
  id: "1",
}

const config = {
  skip: 0,
  take: 20,
  relations: ["authors"],
  select: ["title"],
}

const query = buildQuery(selector, config)

const posts = await postRepository.find(query)

Retrieving a List of Records with Count

You can retrieve a list of records along with their count using the findAndCount method:

const [posts, count] = await postRepository.findAndCount()

This method also accepts the same options object as a parameter similar to the find method.

Retrieving a Single Record

You can retrieve one record of an entity using the findOne method:

const post = await postRepository.findOne({
  where: {
    id: "1",
  },
})

If the record does not exist, null will be returned instead.

You can also pass the method an options object similar to the find method to expand relations or specify what fields to select.

Create Record

To create a new record of an entity, use the create and save methods of the repository:

const post = postRepository.create()
post.title = data.title
post.author_id = data.author_id
const result = await postRepository.save(post)

The save method is what actually persists the created record in the database.

Update Record

To update a record of an entity, use the save method of the repository:

// const data = {
//   title: ''
// }

// const post = await postRepository.findOne({
//   where: {
//     id: '1'
//   }
// })

Object.assign(post, data)

const updatedPost = await postRepository.save(post)

Delete a Record

To delete a record of an entity, use the remove method of the repository:

const post = await postRepository.findOne({
  where: {
    id: "1",
  },
})

await postRepository.remove([post])

This method accepts an array of records to delete.

Soft Delete a Record

If an entity extends the SoftDeletableEntity class, it can be soft deleted. This means that the entity won't be fully deleted from the database, but it can't be retrieved as a non-deleted entity would.

To soft-delete a record of an entity, use the softRemove method:

const post = await postRepository.findOne({
  where: {
    id: "1",
  },
})

await postRepository.softRemove([post])

You can later retrieve that entity by passing the withDeleted option to methods like find, findAndCount, or findOne:

const posts = await postRepository.find({
  withDeleted: true,
})