@rytass/cms-base-nestjs-module
Version:
Rytass Content Management System NestJS Base Module
111 lines (108 loc) • 4.79 kB
JavaScript
import { Injectable, Inject } from '@nestjs/common';
import { RESOLVED_ARTICLE_REPO, RESOLVED_ARTICLE_VERSION_REPO } from '../typings/cms-base-providers.js';
import { Brackets, Repository } from 'typeorm';
import DataLoader from 'dataloader';
import { LRUCache } from 'lru-cache';
import { ArticleStage } from '../typings/article-stage.enum.js';
import { SignatureService } from '../services/signature.service.js';
import { ArticleSignatureResult } from '../typings/article-signature-result.enum.js';
function _ts_decorate(decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
}
function _ts_metadata(k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
}
function _ts_param(paramIndex, decorator) {
return function(target, key) {
decorator(target, key, paramIndex);
};
}
class ArticleDataLoader {
articleRepo;
articleVersionRepo;
signatureService;
constructor(articleRepo, articleVersionRepo, signatureService){
this.articleRepo = articleRepo;
this.articleVersionRepo = articleVersionRepo;
this.signatureService = signatureService;
}
stageCache = new LRUCache({
ttl: 1000 * 5,
ttlAutopurge: true,
max: 1000
});
stageLoader = new DataLoader(async (queryArgs)=>{
const qb = this.articleVersionRepo.createQueryBuilder('versions');
qb.withDeleted();
qb.leftJoinAndSelect('versions.signatures', 'signatures');
qb.andWhere(new Brackets((subQb)=>{
queryArgs.forEach((args, index)=>{
subQb.orWhere(`versions.articleId = :id_${index} AND versions.version = :version_${index}`, {
[`id_${index}`]: args.id,
[`version_${index}`]: args.version
});
});
return subQb;
}));
const versions = await qb.getMany();
const versionMap = new Map(versions.map((version)=>[
`${version.articleId}:${version.version}`,
(()=>{
if (version.deletedAt) return ArticleStage.DELETED;
if (version.releasedAt) {
if (version.releasedAt.getTime() > Date.now()) {
return ArticleStage.SCHEDULED;
}
return ArticleStage.RELEASED;
}
if (version.signatures.some((sig)=>sig.result === ArticleSignatureResult.APPROVED && sig.deletedAt === null && sig.signatureLevelId === this.signatureService.finalSignatureLevel?.id)) {
return ArticleStage.VERIFIED;
}
if (version.submittedAt) {
return ArticleStage.REVIEWING;
}
return ArticleStage.DRAFT;
})()
]));
return queryArgs.map((args)=>versionMap.get(`${args.id}:${args.version}`) ?? ArticleStage.UNKNOWN);
}, {
cache: true,
cacheMap: this.stageCache,
cacheKeyFn: (queryArgs)=>`${queryArgs.id}:${queryArgs.version}`
});
categoriesLoader = new DataLoader(async (ids)=>{
const qb = this.articleRepo.createQueryBuilder('articles');
qb.leftJoinAndSelect('articles.categories', 'categories');
qb.andWhere('articles.id IN (:...ids)', {
ids
});
const articles = await qb.getMany();
const categoryMap = new Map(articles.map((article)=>[
article.id,
article.categories
]));
return ids.map((id)=>categoryMap.get(id) ?? []);
}, {
cache: true,
cacheMap: new LRUCache({
ttl: 1000 * 60,
ttlAutopurge: true,
max: 1000
})
});
}
ArticleDataLoader = _ts_decorate([
Injectable(),
_ts_param(0, Inject(RESOLVED_ARTICLE_REPO)),
_ts_param(1, Inject(RESOLVED_ARTICLE_VERSION_REPO)),
_ts_metadata("design:type", Function),
_ts_metadata("design:paramtypes", [
typeof Repository === "undefined" ? Object : Repository,
typeof Repository === "undefined" ? Object : Repository,
typeof SignatureService === "undefined" ? Object : SignatureService
])
], ArticleDataLoader);
export { ArticleDataLoader };