UNPKG

burdy

Version:

Open Source Headless Platform

207 lines (206 loc) 10.3 kB
"use strict"; 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;