add image derivative db

This commit is contained in:
rubikscraft
2022-04-21 17:08:37 +02:00
parent 47210fabce
commit f1188483ad
9 changed files with 120 additions and 18 deletions

View File

@@ -1,12 +1,19 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm'; import { TypeOrmModule } from '@nestjs/typeorm';
import { EImageDerivativeBackend } from '../../models/entities/image-derivative.entity';
import { EImageFileBackend } from '../../models/entities/image-file.entity'; import { EImageFileBackend } from '../../models/entities/image-file.entity';
import { EImageBackend } from '../../models/entities/image.entity'; import { EImageBackend } from '../../models/entities/image.entity';
import { ImageDBService } from './image-db.service'; import { ImageDBService } from './image-db.service';
import { ImageFileDBService } from './image-file-db.service'; import { ImageFileDBService } from './image-file-db.service';
@Module({ @Module({
imports: [TypeOrmModule.forFeature([EImageBackend, EImageFileBackend])], imports: [
TypeOrmModule.forFeature([
EImageBackend,
EImageFileBackend,
EImageDerivativeBackend,
]),
],
providers: [ImageDBService, ImageFileDBService], providers: [ImageDBService, ImageFileDBService],
exports: [ImageDBService, ImageFileDBService], exports: [ImageDBService, ImageFileDBService],
}) })

View File

@@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { AsyncFailable, Fail } from 'picsur-shared/dist/types'; import { AsyncFailable, Fail } from 'picsur-shared/dist/types';
import { Repository } from 'typeorm'; import { Repository } from 'typeorm';
import { EImageDerivativeBackend } from '../../models/entities/image-derivative.entity';
import { EImageFileBackend } from '../../models/entities/image-file.entity'; import { EImageFileBackend } from '../../models/entities/image-file.entity';
import { EImageBackend } from '../../models/entities/image.entity'; import { EImageBackend } from '../../models/entities/image.entity';
@@ -13,6 +14,9 @@ export class ImageDBService {
@InjectRepository(EImageFileBackend) @InjectRepository(EImageFileBackend)
private imageFileRepo: Repository<EImageFileBackend>, private imageFileRepo: Repository<EImageFileBackend>,
@InjectRepository(EImageDerivativeBackend)
private imageDerivativeRepo: Repository<EImageDerivativeBackend>,
) {} ) {}
public async create(): AsyncFailable<EImageBackend> { public async create(): AsyncFailable<EImageBackend> {
@@ -62,12 +66,19 @@ export class ImageDBService {
public async delete(id: string): AsyncFailable<true> { public async delete(id: string): AsyncFailable<true> {
try { try {
const derivativesResult = await this.imageDerivativeRepo.delete({
imageId: id,
});
const filesResult = await this.imageFileRepo.delete({ const filesResult = await this.imageFileRepo.delete({
imageId: id, imageId: id,
}); });
const result = await this.imageRepo.delete({ id }); const result = await this.imageRepo.delete({ id });
if (result.affected === 0 && filesResult.affected === 0) if (
result.affected === 0 &&
filesResult.affected === 0 &&
derivativesResult.affected === 0
)
return Fail('Image not found'); return Fail('Image not found');
} catch (e) { } catch (e) {
return Fail(e); return Fail(e);
@@ -80,6 +91,7 @@ export class ImageDBService {
return Fail('You must confirm that you want to delete all images'); return Fail('You must confirm that you want to delete all images');
try { try {
await this.imageDerivativeRepo.delete({});
await this.imageFileRepo.delete({}); await this.imageFileRepo.delete({});
await this.imageRepo.delete({}); await this.imageRepo.delete({});
} catch (e) { } catch (e) {

View File

@@ -3,6 +3,7 @@ import { InjectRepository } from '@nestjs/typeorm';
import { AsyncFailable, Fail } from 'picsur-shared/dist/types'; import { AsyncFailable, Fail } from 'picsur-shared/dist/types';
import { Repository } from 'typeorm'; import { Repository } from 'typeorm';
import { ImageFileType } from '../../models/constants/image-file-types.const'; import { ImageFileType } from '../../models/constants/image-file-types.const';
import { EImageDerivativeBackend } from '../../models/entities/image-derivative.entity';
import { EImageFileBackend } from '../../models/entities/image-file.entity'; import { EImageFileBackend } from '../../models/entities/image-file.entity';
@Injectable() @Injectable()
@@ -10,9 +11,12 @@ export class ImageFileDBService {
constructor( constructor(
@InjectRepository(EImageFileBackend) @InjectRepository(EImageFileBackend)
private imageFileRepo: Repository<EImageFileBackend>, private imageFileRepo: Repository<EImageFileBackend>,
@InjectRepository(EImageDerivativeBackend)
private imageDerivativeRepo: Repository<EImageDerivativeBackend>,
) {} ) {}
public async setSingle( public async setFile(
imageId: string, imageId: string,
type: ImageFileType, type: ImageFileType,
file: Buffer, file: Buffer,
@@ -25,7 +29,9 @@ export class ImageFileDBService {
imageFile.data = file; imageFile.data = file;
try { try {
await this.imageFileRepo.save(imageFile); await this.imageFileRepo.upsert(imageFile, {
conflictPaths: ['imageId', 'type'],
});
} catch (e) { } catch (e) {
return Fail(e); return Fail(e);
} }
@@ -33,7 +39,7 @@ export class ImageFileDBService {
return true; return true;
} }
public async getSingle( public async getFile(
imageId: string, imageId: string,
type: ImageFileType, type: ImageFileType,
): AsyncFailable<EImageFileBackend> { ): AsyncFailable<EImageFileBackend> {
@@ -49,7 +55,7 @@ export class ImageFileDBService {
} }
} }
public async getSingleMime( public async getFileMime(
imageId: string, imageId: string,
type: ImageFileType, type: ImageFileType,
): AsyncFailable<string> { ): AsyncFailable<string> {
@@ -65,4 +71,58 @@ export class ImageFileDBService {
return Fail(e); return Fail(e);
} }
} }
public async addDerivative(
imageId: string,
key: string,
mime: string,
file: Buffer,
): AsyncFailable<true> {
const imageDerivative = new EImageDerivativeBackend();
imageDerivative.imageId = imageId;
imageDerivative.key = key;
imageDerivative.mime = mime;
imageDerivative.data = file;
try {
await this.imageDerivativeRepo.save(imageDerivative);
} catch (e) {
return Fail(e);
}
return true;
}
public async getDerivative(
imageId: string,
key: string,
): AsyncFailable<EImageDerivativeBackend> {
try {
const found = await this.imageDerivativeRepo.findOne({
where: { imageId, key },
});
if (!found) return Fail('Image not found');
return found;
} catch (e) {
return Fail(e);
}
}
public async getDerivativeMime(
imageId: string,
key: string,
): AsyncFailable<string> {
try {
const found = await this.imageDerivativeRepo.findOne({
where: { imageId, key },
select: ['mime'],
});
if (!found) return Fail('Image not found');
return found.mime;
} catch (e) {
return Fail(e);
}
}
} }

View File

@@ -66,8 +66,6 @@ export class RolesService {
[] as Permissions, [] as Permissions,
); );
console.log(permissions);
return makeUnique(permissions); return makeUnique(permissions);
} }

View File

@@ -50,7 +50,7 @@ export class ImageManagerService {
const imageEntity = await this.imagesService.create(); const imageEntity = await this.imagesService.create();
if (HasFailed(imageEntity)) return imageEntity; if (HasFailed(imageEntity)) return imageEntity;
const imageFileEntity = await this.imageFilesService.setSingle( const imageFileEntity = await this.imageFilesService.setFile(
imageEntity.id, imageEntity.id,
ImageFileType.MASTER, ImageFileType.MASTER,
processResult.image, processResult.image,
@@ -74,11 +74,11 @@ export class ImageManagerService {
// File getters ============================================================== // File getters ==============================================================
public async getMaster(imageId: string): AsyncFailable<EImageFileBackend> { public async getMaster(imageId: string): AsyncFailable<EImageFileBackend> {
return this.imageFilesService.getSingle(imageId, ImageFileType.MASTER); return this.imageFilesService.getFile(imageId, ImageFileType.MASTER);
} }
public async getMasterMime(imageId: string): AsyncFailable<FullMime> { public async getMasterMime(imageId: string): AsyncFailable<FullMime> {
const mime = await this.imageFilesService.getSingleMime( const mime = await this.imageFilesService.getFileMime(
imageId, imageId,
ImageFileType.MASTER, ImageFileType.MASTER,
); );
@@ -88,11 +88,11 @@ export class ImageManagerService {
} }
public async getOriginal(imageId: string): AsyncFailable<EImageFileBackend> { public async getOriginal(imageId: string): AsyncFailable<EImageFileBackend> {
return this.imageFilesService.getSingle(imageId, ImageFileType.ORIGINAL); return this.imageFilesService.getFile(imageId, ImageFileType.ORIGINAL);
} }
public async getOriginalMime(imageId: string): AsyncFailable<FullMime> { public async getOriginalMime(imageId: string): AsyncFailable<FullMime> {
const mime = await this.imageFilesService.getSingleMime( const mime = await this.imageFilesService.getFileMime(
imageId, imageId,
ImageFileType.ORIGINAL, ImageFileType.ORIGINAL,
); );

View File

@@ -1,5 +1,4 @@
export enum ImageFileType { export enum ImageFileType {
ORIGINAL = 'original', ORIGINAL = 'original',
MASTER = 'master', MASTER = 'master',
DERIVED = 'derived',
} }

View File

@@ -0,0 +1,23 @@
import { Column, Entity, Index, PrimaryGeneratedColumn, Unique } from 'typeorm';
@Entity()
@Unique(['imageId', 'key'])
export class EImageDerivativeBackend {
@PrimaryGeneratedColumn('uuid')
private _id?: string;
@Index()
@Column({ nullable: false })
imageId: string;
@Index()
@Column({ nullable: false })
key: string;
@Column({ nullable: false })
mime: string;
// Binary data
@Column({ type: 'bytea', nullable: false })
data: Buffer;
}

View File

@@ -1,17 +1,18 @@
import { Column, Entity, Index, PrimaryGeneratedColumn } from 'typeorm'; import { Column, Entity, Index, PrimaryGeneratedColumn, Unique } from 'typeorm';
import { ImageFileType } from '../constants/image-file-types.const'; import { ImageFileType } from '../constants/image-file-types.const';
@Entity() @Entity()
@Unique(['imageId', 'type'])
export class EImageFileBackend { export class EImageFileBackend {
@PrimaryGeneratedColumn('uuid') @PrimaryGeneratedColumn('uuid')
private _id?: string; private _id?: string;
@Column({ nullable: false })
@Index() @Index()
@Column({ nullable: false })
imageId: string; imageId: string;
@Column({ nullable: false, enum: ImageFileType })
@Index() @Index()
@Column({ nullable: false, enum: ImageFileType })
type: ImageFileType; type: ImageFileType;
@Column({ nullable: false }) @Column({ nullable: false })

View File

@@ -1,3 +1,4 @@
import { EImageDerivativeBackend } from './image-derivative.entity';
import { EImageFileBackend } from './image-file.entity'; import { EImageFileBackend } from './image-file.entity';
import { EImageBackend } from './image.entity'; import { EImageBackend } from './image.entity';
import { ERoleBackend } from './role.entity'; import { ERoleBackend } from './role.entity';
@@ -8,6 +9,7 @@ import { EUsrPreferenceBackend } from './usr-preference.entity';
export const EntityList = [ export const EntityList = [
EImageBackend, EImageBackend,
EImageFileBackend, EImageFileBackend,
EImageDerivativeBackend,
EUserBackend, EUserBackend,
ERoleBackend, ERoleBackend,
ESysPreferenceBackend, ESysPreferenceBackend,