Appearance
ImagesModule
The NestJS ImagesModule is a module that provides an API for managing images and their renditions, allowing for the storage and retrieval of images and their associated metadata.
Each image in the Images API has multiple renditions representing different sizes, such as 1x, 2x, and small thumbnail sizes.
The Images API in conjunction with the ImageUploader from HopeUiKit provides a seamless integration for uploading images using @uppy/core and Companion. This combination streamlines the process of handling image uploads, ensuring a smooth user experience and simplifying the management of image resources within your application.
Entity Inheritance
NestKit provide base classes that can be inherited and customized with your needs. For entities we use TypeORM TableInheritance
.
Key Components
The module provides a set of reusable components, including resolvers, services, and data access layers, that can be easily integrated into a NestJS project.
Image Entity
The Image is a data model in the Images API that represents an image and contains its unique identifier, associated metadata, and an array of related ImageRendition objects that represent specific sizes or formats of the image. It is used to manage the storage and retrieval of images in the database.
Image Renition Entity
The ImageRendition is an entity in the Images API that represents a rendition of an image and contains its unique ID, along with metadata such as the image URL, file size, and MIME type. It is associated with a parent Image
entity and represents a specific size or format of the image.
NestJS Images Service
A ImagesService provides programmatic access to the Images API. It typically includes methods for creating, retrieving, updating, and deleting image entities.
NestJS Image Renditions Service
The ImageRenditionsService is a service in the Images API that provides methods for managing the image renditions associated with an Image
entity. It allows for the creation, deletion, and retrieval of image renditions and their associated metadata, such as the image URL, file size, and MIME type.
GraphQL Images Resolver
The GraphQL ImagesResolver
in NestKit provides a convenient way to retrieve and manipulate images data in a GraphQL API.
GraphQL Image Renditions Resolver
The GraphQL ImageRenditionsResolver
in NestKit provides a convenient way to retrieve and manipulate image renditions data in a GraphQL API.
How to install ImagesModule to my app
To create a ImagesModule
in NestJS, you can follow these steps:
Install the required dependencies for
BrandsModule
:Create an
images
folder in your project'ssrc/modules
directory.Create an
image-renditions
folder insrc/modules/images
directory.Inside the
image-renditions
folder, create aimage-rendition.entity.ts
file and extendsBaseImageRendition
from NestKit with the following code:ts// src/modules/images/image-renditions/image-rendition.entity.ts import { BaseImageRendition } from '@deeepvision/nest-kit/dist/modules/images'; import { ObjectType } from '@nestjs/graphql'; import { ChildEntity } from 'typeorm'; @ObjectType() @ChildEntity() export class ImageRendition extends BaseImageRendition {}
Inside the
image-renditions
folder, create aimage-renditions.service.ts
file and extendsBaseImageRenditionsService
from NestKit with the following code:ts// src/modules/images/image-renditions/image-renditions.service.ts import { BaseImageRenditionsService } from '@deeepvision/nest-kit/dist/modules/images'; import { ImageRendition } from './image-rendition.entity'; export class ImageRenditionsService extends BaseImageRenditionsService<ImageRendition> {}
Inside the
image-renditions
folder, create aimage-renditions.resolver.ts
file and extendsBaseImageRenditionsResolver
from NestKit with the following code:ts// src/modules/images/image-renditions/image-renditions.resolver.ts import { Resolver } from '@nestjs/graphql'; import { ImageRendition } from './image-rendition.entity'; import { BaseImageRenditionsResolver } from '@deeepvision/nest-kit/dist/modules/images'; @Resolver(() => ImageRendition) export class ImageRenditionsResolver extends BaseImageRenditionsResolver(ImageRendition) {}
Inside the
images
folder, create aimage.entity.ts
file and extendsBaseImage
from NestKit with the following code:ts// src/modules/images/image.entity.ts import { BaseImage } from '@deeepvision/nest-kit/dist/modules/images'; import { ObjectType } from '@nestjs/graphql'; import { ChildEntity } from 'typeorm'; import { ImageRendition } from './image-renditions/image-rendition.entity'; @ObjectType() @ChildEntity() export class Image extends BaseImage { renditions!: Promise<ImageRendition[]>; }
Inside the
images
folder, create aimages.service.ts
file and extendsBaseImagesService
from NestKit with the following code:ts// src/modules/images/images.service.ts import { BaseImagesService } from '@deeepvision/nest-kit/dist/modules/images'; import { Image } from './image.entity'; export class ImagesService extends BaseImagesService<Image> {}
Inside the
images
folder, create aimages.resolver.ts
file and extendsBaseImageRenditionsResolver
from NestKit with the following code:ts// src/modules/images/images.resolver.ts import { Resolver } from '@nestjs/graphql'; import { BaseImagesResolver } from '@deeepvision/nest-kit/dist/modules/images'; import { Image } from './image.entity'; import { ImagesService } from './images.service'; import { ImageRenditionsService } from './image-renditions/image-renditions.service'; @Resolver(() => Image) export class ImagesResolver extends BaseImagesResolver(Image) { constructor( protected readonly imagesService: ImagesService, protected readonly imageRenditionsService: ImageRenditionsService, ) { super(imagesService, imageRenditionsService); } }
Inside the
images
folder, create aimages.module.ts
file with the following code:ts// src/modules/images/images.module.ts import { Module } from '@nestjs/common'; import { ImagesService } from './images.service'; import { TypeOrmModule } from '@nestjs/typeorm'; import { ImagesResolver } from './images.resolver'; import { Image } from './image.entity'; import { ImageRendition } from './image-renditions/image-rendition.entity'; import { ImageRenditionsService } from './image-renditions/image-renditions.service'; import { ImageRenditionsResolver } from './image-renditions/image-renditions.resolver'; import { IMAGES_SERVICE_TOKEN, IMAGE_RENDITIONS_SERVICE_TOKEN } from '@deeepvision/nest-kit/dist/modules/images'; @Module({ imports: [ TypeOrmModule.forFeature([Image, ImageRendition]), ], providers: [ ImagesService, { provide: IMAGES_SERVICE_TOKEN, useExisting: ImagesService, }, ImagesResolver, ImageRenditionsService, { provide: IMAGE_RENDITIONS_SERVICE_TOKEN, useExisting: ImageRenditionsService, }, ImageRenditionsResolver, ], exports: [ ImagesService, { provide: IMAGES_SERVICE_TOKEN, useExisting: ImagesService, }, ImageRenditionsService, { provide: IMAGE_RENDITIONS_SERVICE_TOKEN, useExisting: ImageRenditionsService, }, ], }) export class ImagesModule {}
Finally, import the
ImagesModule
into your mainAppModule
or another module:ts// src/modules/app.module.ts import { Module } from '@nestjs/common'; import { ImagesModule } from './modules/images/images.module.ts'; @Module({ imports: [ImagesModule], }) export class AppModule {}
In this code, we are importing the
ImagesModule
and adding it to theimports
array of ourAppModule
.
How to create new image
Call the create
of ImagesService
and pass in an object of CreateImageOptions
:
ts
const image = await this.imagesService.create({
renditions: [
{
type: ImageRenditionType.MAIN_2X,
meta: {
filesize: 2048,
mimeType: 'image/webp',
width: 1600,
height: 1200,
},
url: 'https://cdn.holistic-cms.com/image_2x.webp',
},
{
type: ImageRenditionType.MAIN,
meta: {
filesize: 1024,
mimeType: 'image/webp',
width: 800,
height: 600,
},
url: 'https://cdn.holistic-cms.com/image.webp',
},
{
type: ImageRenditionType.MAIN_LEGACY,
meta: {
filesize: 1024,
mimeType: 'image/jpeg',
width: 800,
height: 600,
},
url: 'https://cdn.holistic-cms.com/image.jpg',
},
{
type: ImageRenditionType.SMALL,
meta: {
filesize: 256,
mimeType: 'image/webp',
width: 200,
height: 150,
},
url: 'https://cdn.holistic-cms.com/image_thumb.webp',
},
],
});
The create method returns a Promise
that resolves to the newly created image object.
Create new image with GraphQL
Here's an example GraphQL mutation to create a new image.
How to attach image to my entity
Firstly, you need to create an one-to-one relation between your and Image entities using TypeORM:
First, define your entity (Post for example) with the
@OneToOne()
decorator to specify the relation to theImage
entity:ts@Entity() export class Post { // ... @OneToOne(() => Image, { eager: true, // optional, will load the related image entity along with the post cascade: true, // optional, will automatically persist the related image entity when the post is saved onDelete: 'RESTRICT', // optional, throw an error if the related image will be attempted to delete }) @JoinColumn() // use post.image_id column image: Image; }
Define your
Image
entity with the@OneToOne()
decorator to specify the reverse relation to thePost
entity:ts@ObjectType() @ChildEntity() export class Image extends BaseImage { renditions!: Promise<ImageRendition[]>; @OneToOne(() => Post, post => post.image) post: Post; }
Ensure that the imageId field is defined as a foreign key in your
Post
entity:ts@Entity() export class Post { // ... @OneToOne(() => Image, { eager: true, cascade: true, onDelete: 'SET NULL', }) @JoinColumn() image: Image; @Column() imageId: string; }
Use the
save()
method on your Post entity to persist it along with the relatedImage
entity:ts// src/modules/posts/posts.service.ts interface CreatePostOptions { title: string; imageId: string; // image has already been created on frontend and only image Id passed } class PostsService { ... async create(opts: CreatePostOptions, ctx: ServiceMethodContext) { const post = this.postRepository.create(opts); try { return await this.postRepository.save(opts); ... } }
This will create a new
Post
entity and attachImage
entity with aone-to-one
relation.Now, you can fetch an image for a post using relation:
ts
const post = await this.getOneOrFail(postId, ctx);
// post.image => Image
How to get image by ID
Use the getOne()
method from your ImagesService
to get a image by id in other parts of your application.
ts
const image = await this.imagesService.getOne('hcimg:xxxxxxxxxxx');
Use the getOneOrFail()
method to retrieve a image by id or throw an error if the image is not found.
ts
const image = await this.imagesService.getOneOrFail('hcimg:xxxxxxxxxxx', ctx);
Fetch image by id with GraphQL
Here's an example GraphQL query to fetch image by id.
How to delete image
Call the delete
method of the ImagesService
and pass in the id
of the image you want to delete:
ts
await this.imagesService.delete('hcimg:xxxxxxxxxxx');