"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Collection = void 0; const errors_1 = require("@tryghost/errors"); const tpl_1 = __importDefault(require("@tryghost/tpl")); const nql_1 = __importDefault(require("@tryghost/nql")); const nql_filter_expansions_1 = require("@tryghost/nql-filter-expansions"); const CollectionPostAdded_1 = require("./events/CollectionPostAdded"); const CollectionPostRemoved_1 = require("./events/CollectionPostRemoved"); const bson_objectid_1 = __importDefault(require("bson-objectid")); const messages = { invalidIDProvided: 'Invalid ID provided for Collection', invalidDateProvided: 'Invalid date provided for {fieldName}', invalidFilterProvided: { message: 'Invalid filter provided for automatic Collection', context: 'Automatic type of collection should always have a filter value' }, noTitleProvided: 'Title must be provided', slugMustBeUnique: 'Slug must be unique' }; function validateFilter(filter, type, isAllowedEmpty = false) { const allowedProperties = ['featured', 'published_at', 'tag', 'tags']; if (type === 'manual') { if (filter !== null) { throw new errors_1.ValidationError({ message: (0, tpl_1.default)(messages.invalidFilterProvided.message), context: (0, tpl_1.default)(messages.invalidFilterProvided.context) }); } return; } // type === 'automatic' now if (filter === null) { throw new errors_1.ValidationError({ message: (0, tpl_1.default)(messages.invalidFilterProvided.message), context: (0, tpl_1.default)(messages.invalidFilterProvided.context) }); } if (filter.trim() === '' && !isAllowedEmpty) { throw new errors_1.ValidationError({ message: (0, tpl_1.default)(messages.invalidFilterProvided.message), context: (0, tpl_1.default)(messages.invalidFilterProvided.context) }); } try { const parsedFilter = (0, nql_1.default)(filter); const keysUsed = []; nql_1.default.utils.mapQuery(parsedFilter.toJSON(), function (value, key) { keysUsed.push(key); }); if (keysUsed.some(key => !allowedProperties.includes(key))) { throw new errors_1.ValidationError({ message: (0, tpl_1.default)(messages.invalidFilterProvided.message) }); } } catch (err) { throw new errors_1.ValidationError({ message: (0, tpl_1.default)(messages.invalidFilterProvided.message) }); } } class Collection { events; id; title; _slug; get slug() { return this._slug; } async setSlug(slug, uniqueChecker) { if (slug === this.slug) { return; } if (await uniqueChecker.isUniqueSlug(slug)) { this._slug = slug; } else { throw new errors_1.ValidationError({ message: (0, tpl_1.default)(messages.slugMustBeUnique) }); } } description; type; _filter; get filter() { return this._filter; } set filter(value) { if (this.slug === 'latest' || this.slug === 'featured') { return; } validateFilter(value, this.type); this._filter = value; } featureImage; createdAt; updatedAt; get deletable() { return this.slug !== 'latest' && this.slug !== 'featured'; } _deleted = false; _posts; get posts() { return this._posts; } get deleted() { return this._deleted; } set deleted(value) { if (this.deletable) { this._deleted = value; } } postMatchesFilter(post) { const filterNql = (0, nql_1.default)(this.filter, { expansions: nql_filter_expansions_1.posts }); return filterNql.queryJSON(post); } /** * @param post {{id: string}} - The post to add to the collection * @param index {number} - The index to insert the post at, use negative numbers to count from the end. */ addPost(post, index = -0) { if (this.slug === 'latest') { return false; } if (this.type === 'automatic') { const matchesFilter = this.postMatchesFilter(post); if (!matchesFilter) { return false; } } if (this.posts.includes(post.id)) { this._posts = this.posts.filter(id => id !== post.id); } else { this.events.push(CollectionPostAdded_1.CollectionPostAdded.create({ post_id: post.id, collection_id: this.id })); } if (index < 0 || Object.is(index, -0)) { index = this.posts.length + index; } this.posts.splice(index, 0, post.id); return true; } removePost(id) { if (this.posts.includes(id)) { this._posts = this.posts.filter(postId => postId !== id); this.events.push(CollectionPostRemoved_1.CollectionPostRemoved.create({ post_id: id, collection_id: this.id })); } } includesPost(id) { return this.posts.includes(id); } removeAllPosts() { for (const id of this._posts) { this.events.push(CollectionPostRemoved_1.CollectionPostRemoved.create({ post_id: id, collection_id: this.id })); } this._posts = []; } // eslint-disable-next-line @typescript-eslint/no-explicit-any constructor(data) { this.id = data.id; this.title = data.title; this._slug = data.slug; this.description = data.description; this.type = data.type; this._filter = data.filter; this.featureImage = data.featureImage; this.createdAt = data.createdAt; this.updatedAt = data.updatedAt; this.deleted = data.deleted; this._posts = data.posts; this.events = []; } toJSON() { return { id: this.id, title: this.title, slug: this.slug, description: this.description, type: this.type, filter: this.filter, featureImage: this.featureImage, createdAt: this.createdAt, updatedAt: this.updatedAt, posts: this.posts }; } // eslint-disable-next-line @typescript-eslint/no-explicit-any static validateDateField(date, fieldName) { if (!date) { return new Date(); } if (date instanceof Date) { return date; } throw new errors_1.ValidationError({ message: (0, tpl_1.default)(messages.invalidDateProvided, { fieldName }) }); } // eslint-disable-next-line @typescript-eslint/no-explicit-any static async create(data) { let id; if (!data.id) { id = new bson_objectid_1.default(); } else if (typeof data.id === 'string') { id = bson_objectid_1.default.createFromHexString(data.id); } else if (data.id instanceof bson_objectid_1.default) { id = data.id; } else { throw new errors_1.ValidationError({ message: (0, tpl_1.default)(messages.invalidIDProvided) }); } const type = data.type === 'automatic' ? 'automatic' : 'manual'; const filter = typeof data.filter === 'string' ? data.filter : null; validateFilter(filter, type, data.slug === 'latest'); if (!data.title) { throw new errors_1.ValidationError({ message: (0, tpl_1.default)(messages.noTitleProvided) }); } return new Collection({ id: id.toHexString(), title: data.title, slug: data.slug, description: data.description || null, type: type, filter: filter, featureImage: data.feature_image || null, createdAt: Collection.validateDateField(data.created_at, 'created_at'), updatedAt: Collection.validateDateField(data.updated_at, 'updated_at'), deleted: data.deleted || false, posts: data.slug !== 'latest' ? (data.posts || []) : [] }); } } exports.Collection = Collection; //# sourceMappingURL=Collection.js.map