burdy
Version:
Open Source Headless Platform
207 lines (206 loc) • 10.3 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildPath = exports.compilePost = exports.compilePostContainer = exports.retrievePostAndCompile = exports.publishedQuery = void 0;
const typeorm_1 = require("typeorm");
const post_model_1 = __importDefault(require("../models/post.model"));
const asset_model_1 = __importDefault(require("../models/asset.model"));
const bad_request_error_1 = __importDefault(require("../errors/bad-request-error"));
const post_parser_1 = require("./post.parser");
const mappers_1 = require("./mappers");
const lodash_1 = __importDefault(require("lodash"));
const hooks_1 = __importDefault(require("../../shared/features/hooks"));
const path_to_regexp_1 = require("path-to-regexp");
const deepcopy_1 = __importDefault(require("deepcopy"));
const MAX_RELATIONS_DEPTH = 3;
const publishedQuery = (qb, draft) => {
if (!draft) {
qb.andWhere('post.publishedAt is NOT NULL');
qb.andWhere(new typeorm_1.Brackets((subQb) => {
subQb
.where('post.publishedFrom is NULL')
.orWhere('post.publishedFrom <= CURRENT_TIMESTAMP');
}));
qb.andWhere(new typeorm_1.Brackets((subQb) => {
subQb
.where('post.publishedUntil is NULL')
.orWhere('post.publishedUntil >= CURRENT_TIMESTAMP');
}));
}
};
exports.publishedQuery = publishedQuery;
const retrievePostAndCompile = ({ id, slugPath, versionId }, options) => __awaiter(void 0, void 0, void 0, function* () {
const postRepository = (0, typeorm_1.getRepository)(post_model_1.default);
const where = {};
if (slugPath) {
where.slugPath = slugPath;
}
else if (id) {
where.id = id;
}
const qb = yield postRepository.createQueryBuilder('post')
.leftJoinAndSelect('post.meta', 'meta')
.leftJoinAndSelect('post.author', 'author')
.leftJoinAndSelect('post.contentType', 'contentType')
.leftJoinAndSelect('post.tags', 'tags');
if (slugPath) {
qb.where('post.slugPath = :slugPath', { slugPath });
}
else if (id) {
qb.where('post.id = :id', { id });
}
(0, exports.publishedQuery)(qb, options === null || options === void 0 ? void 0 : options.draft);
let post = yield qb.getOne();
if (!((options === null || options === void 0 ? void 0 : options.depth) > 0) && !(options === null || options === void 0 ? void 0 : options.draft)) {
yield hooks_1.default.doAction('public/getPost', post);
}
if (versionId) {
const postVersion = yield postRepository.findOne({
relations: ['meta', 'contentType', 'author', 'tags'],
where: {
id: versionId,
parentId: post === null || post === void 0 ? void 0 : post.id
}
});
if (!postVersion)
throw new bad_request_error_1.default('invalid_post_version');
post = postVersion;
}
const getReturn = () => {
if (options === null || options === void 0 ? void 0 : options.nullable)
return null;
throw new bad_request_error_1.default('invalid_post');
};
if (!post)
return getReturn();
return post.type === 'hierarchical_post' ? (0, exports.compilePostContainer)(post, options) : (0, exports.compilePost)(post, options);
});
exports.retrievePostAndCompile = retrievePostAndCompile;
const compilePostContainer = (post, options) => __awaiter(void 0, void 0, void 0, function* () {
var _a, _b, _c, _d, _e;
const postRepository = (0, typeorm_1.getRepository)(post_model_1.default);
const { draft } = options;
const includeChildren = Boolean((_a = options === null || options === void 0 ? void 0 : options.query) === null || _a === void 0 ? void 0 : _a.includeChildren);
if (!includeChildren) {
return (0, exports.compilePost)(post, options);
}
const page = (_c = (_b = options === null || options === void 0 ? void 0 : options.query) === null || _b === void 0 ? void 0 : _b.page) !== null && _c !== void 0 ? _c : 1;
const perPage = (_e = (_d = options === null || options === void 0 ? void 0 : options.query) === null || _d === void 0 ? void 0 : _d.perPage) !== null && _e !== void 0 ? _e : 10;
const childPostQuery = postRepository.createQueryBuilder('post')
.leftJoinAndSelect('post.meta', 'meta')
.leftJoinAndSelect('post.author', 'author')
.leftJoinAndSelect('post.contentType', 'contentType')
.leftJoinAndSelect('post.tags', 'tags');
childPostQuery
.where('post.type = :type', { type: 'post' })
.andWhere('post.parentId = :parent', { parent: post.id });
childPostQuery.skip(perPage * (page - 1));
childPostQuery.take(perPage);
(0, exports.publishedQuery)(childPostQuery, draft);
const childCountQuery = postRepository.createQueryBuilder('post');
childCountQuery
.where('post.type = :type', { type: 'post' })
.andWhere('post.parentId = :parent', { parent: post.id });
(0, exports.publishedQuery)(childCountQuery, draft);
const [childPosts, count] = yield Promise.all([
childPostQuery.getMany(),
childCountQuery.getCount()
]);
const [postContainer, ...posts] = yield Promise.all([
(0, exports.compilePost)(post),
...childPosts.map(post => (0, exports.compilePost)(post, options)),
]);
return Object.assign(Object.assign({}, postContainer), { posts, paginate: {
pageSize: perPage,
current: page,
total: count,
} });
});
exports.compilePostContainer = compilePostContainer;
const compilePost = (post, options) => __awaiter(void 0, void 0, void 0, function* () {
const assetRepository = (0, typeorm_1.getRepository)(asset_model_1.default);
const relationsDepth = lodash_1.default.isNil(options === null || options === void 0 ? void 0 : options.relationsDepth) ? MAX_RELATIONS_DEPTH : options === null || options === void 0 ? void 0 : options.relationsDepth;
const depth = (options === null || options === void 0 ? void 0 : options.depth) || 0;
const { content, assets: assetsRefs, references } = (0, post_parser_1.parseContent)(post);
const mappedPost = (0, mappers_1.mapPublicPostWithMeta)(post);
// Inject references
const referencesIds = lodash_1.default.uniq(Object.values(references || {})).filter(slugPath => Boolean(slugPath));
if ((referencesIds === null || referencesIds === void 0 ? void 0 : referencesIds.length) > 0 && depth < relationsDepth) {
// @ts-ignore
const posts = yield Promise.all(referencesIds.map((slugPath) => {
return (0, exports.retrievePostAndCompile)({ slugPath }, Object.assign(Object.assign({}, (options || {})), { nullable: true, depth: depth + 1, relationsDepth }));
}));
const postsObj = {};
posts.filter(post => post).forEach((post) => {
postsObj[post.slugPath] = post;
});
Object.keys(references).forEach(key => {
if (postsObj[references[key]]) {
lodash_1.default.set(content, key, postsObj[references[key]]);
}
else {
lodash_1.default.unset(content, key);
}
});
}
// Inject assets
const assetsNpaths = lodash_1.default.uniq(Object.values(assetsRefs || {})).filter(npath => !!npath);
if ((assetsNpaths === null || assetsNpaths === void 0 ? void 0 : assetsNpaths.length) > 0) {
const assets = yield assetRepository.find({
relations: ['meta', 'tags'],
where: {
npath: (0, typeorm_1.In)(assetsNpaths)
}
});
const assetsObj = {};
assets.forEach(asset => {
assetsObj[asset.npath] = (0, mappers_1.mapPublicAsset)(asset);
});
Object.keys(assetsRefs).forEach(key => {
lodash_1.default.set(content, key, Object.assign(Object.assign({}, lodash_1.default.get(content, key, {})), ((assetsObj === null || assetsObj === void 0 ? void 0 : assetsObj[assetsRefs === null || assetsRefs === void 0 ? void 0 : assetsRefs[key]]) || {})));
});
}
return Object.assign(Object.assign({}, mappedPost), { meta: Object.assign(Object.assign({}, mappedPost.meta), { content }) });
});
exports.compilePost = compilePost;
const escapeRegExp = (str) => {
return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1');
};
const buildPath = (path, rules) => {
let resultArray;
let keys = [];
rules = (0, deepcopy_1.default)(rules);
const rule = rules.find((rule) => {
keys = [];
const regexp = (0, path_to_regexp_1.pathToRegexp)(rule.source, keys);
resultArray = regexp.exec(path);
return !!resultArray;
});
if (!rule) {
return undefined;
}
const params = {};
keys.forEach((key, index) => {
params[key.name] = resultArray === null || resultArray === void 0 ? void 0 : resultArray[index + 1];
});
const rewrite = (string, params = {}) => {
let tmpString = string;
Object.keys(params).forEach((key) => {
tmpString = tmpString.replace(new RegExp(escapeRegExp(`{${key}}`), 'g'), params[key] || '');
});
return tmpString;
};
return rewrite(((rule === null || rule === void 0 ? void 0 : rule.destination) || (rule === null || rule === void 0 ? void 0 : rule.rewrite)), params);
};
exports.buildPath = buildPath;