0.2.0 • Published 4 months ago

@vicodes/strapi-orm v0.2.0

Weekly downloads
-
License
MIT
Repository
github
Last release
4 months ago

Motivation

Strapi is a great headless CMS, and a good entry point for start-ups. Sometimes it might become a core part of the project, but it can't substitute a strong backend application. This is where StrapiORM comes in. It allows the backend applications to treat Strapi as a database, and abstracts the filtering, population and sorting of the entities.

Install

npm i @vicodes/strapi-orm

Example

First create a Manager instance

const manager = new Manager({
  baseUrl: 'http://localhost:1337/api',
  accessToken: 'super-secret-token',
  flatten: true,
})

Then create the entities that represent Strapi Content Types. Use the StrapiEntity decorator to specify the URI path of the Strapi Content Type, either as a string or as a StrapiEntityOptions object with the following properties:

interface StrapiEntityOptions {
  path: string
}
import { StrapiEntity } from './strapi-entity.decorator'

@StrapiEntity('scopes')
export class Scope {
  id: number
  name: string
}

@StrapiEntity({ path: 'roles' })
export class Role {
  id: number
  name: string
  scope: Scope
}

@StrapiEntity('users')
export class User {
  id: number
  firstName: string
  lastName: string
  role: Role
}

Using Repository

import { Manager } from '@vicodes/strapi-orm'
import { User } from './user.entity'
import { StrapiRepository } from './strapi.repository'

// It's important to type the repository with the entity type to get maximum of type safety
const roleRepository: StrapiRepository<Role> = manager.getRepository(Role)
const scopeRepository: StrapiRepository<Scope> = manager.getRepository(Scope)

const scope = await scopeRepository.findById(1)

const adminRole: Role = {
  name: 'admin',
  scope: scope,
}

await roleRepository.create(adminRole)

Using QueryBuilder

You can use the QueryBuilder to create complex queries. This will create the query params to select, populate filter and sort without the hustle of creating the query string or object.

import { Manager } from '@vicodes/strapi-orm'
import { User } from './user.entity'
import { StrapiRepository } from './strapi.repository'

const manager = new Manager({
  baseUrl: 'http://localhost:1337/api',
  accessToken: 'super-secret-token',
  flatten: true,
})

const respository: StrapiRepository<User> = manager.getRepository(User)

const users = await respository
  .createQueryBuilder()
  .select(['firstName', 'lastName'])
  .populate('role')
  .populate('role.scope', '*', { name: { $in: ['read-only', 'read-write'] } })
  .where('role.scope.name', 'read-only')
  .getMany()

Overriding the default request service

StrapiORM uses a default request service that uses fetch to make the requests to the Strapi API. It can be overridden by passing a custom request service to the Manager constructor.

import { Manager, RequestService } from '@vicodes/strapi-orm'

class CustomRequestService extends RequestService {
  constructor(config: ConnectionConfig) {
    super(config)
  }

  getAuthHeaders(): Record<string, string> {
    return {
      Authorization: 'Basic user:password',
    }
  }

  handleResponse<Entity>(jsonResponse: unknown): Promise<Entity> {
    // Do something with the response, like modifying the data
    // By default here is where the response is flattened
  }

  request<Entity>(path: string, requestOptions: RequestOptions): Promise<Entity> {
    // Use your custom request library, like axios
  }
}

API

Manager

new Manager(options: ConnectionConfig, requestService?: RequestService)

Creates a new Manager instance.

ConnectionConfig is an object with the following properties:

PropertyTypeDescriptionRequiredDefault
baseUrlstringBase url of the Strapi APItrue
accessTokenstringAccess token of the Strapi APItrue
flattenbooleanFlatten the response from the Strapi API, removing the attributes and data propertiesfalsefalse

manager.getRepository(target: Entity): Repository<Entity>:

Returns a new Repository instance for the given entity.

Repository

repository.find(): Promise<Entity[]>

repository.findBy(where: FindOptionsWhere<Entity>): Promise<Entity[]>

repository.findOneById(id: number | string): Promise<Entity>

repository.findOneBy(where: FindOptionsWhere<Entity>): Promise<Entity[]>

repository.create(entity: Entity): Promise<Entity>

repository.update(id: number | string, entity: Entity): Promise<Entity>

repository.delete(id: number | string): Promise<Entity>

repository.createQueryBuilder(): StrapiQueryBuilder<Entity>

QueryBuilder

queryBuilder.select(fields: string | string[]): SelectQueryBuilder<Entity>

queryBuilder.populate(relation: string, fields?: string | string[], filter?: StrapiFilter, sort?: StrapiSort): SelectQueryBuilder<Entity>

queryBuilder.where(field: string, filters: StrapiFilter): SelectQueryBuilder<Entity>

queryBuilder.getMany(): Promise<Entity[]>

queryBuilder.getOne(): Promise<Entity>

0.2.0-alpha.2e6f01

4 months ago

0.2.0-alpha.c647f7

5 months ago

0.2.0-alpha.37dd7f

5 months ago

0.1.0-alpha.ff2c35

5 months ago

0.2.0

5 months ago

0.1.0-alpha.ba0a4b

5 months ago

0.1.0-alpha.2c321a

5 months ago

0.1.0

5 months ago

0.0.3

5 months ago

0.0.3-alpha.6774c0

5 months ago

0.0.2

5 months ago

0.0.1

5 months ago