UNPKG

ghost

Version:

The professional publishing platform

158 lines (141 loc) 4.36 kB
const Tier = require('./Tier'); const nql = require('@tryghost/nql'); /** * @typedef {import('./TiersAPI').ITierRepository} ITierRepository */ /** * @implements {ITierRepository} */ module.exports = class TierRepository { /** @type {import('./Tier')[]} */ #store = []; /** @type {Object.<string, true>} */ #ids = {}; /** @type {Object} */ #ProductModel; /** @type {import('@tryghost/domain-events')} */ #DomainEvents; /** * @param {object} deps * @param {object} deps.ProductModel Bookshelf Model * @param {import('@tryghost/domain-events')} deps.DomainEvents */ constructor(deps) { this.#ProductModel = deps.ProductModel; this.#DomainEvents = deps.DomainEvents; } async init() { this.#store = []; this.#ids = {}; const models = await this.#ProductModel.findAll({ withRelated: ['benefits'] }); for (const model of models) { const tier = await Tier.create(this.mapToTier(model)); this.#store.push(tier); this.#ids[tier.id.toHexString()] = true; } } /** * @param {import('./Tier')} tier * @returns {any} */ toPrimitive(tier) { return { ...tier.toJSON(), active: (tier.status === 'active'), type: tier.type, id: tier.id.toHexString() }; } /** * @private */ mapToTier(model) { const json = model.toJSON(); return { id: json.id, name: json.name, slug: json.slug, status: json.active ? 'active' : 'archived', welcomePageURL: json.welcome_page_url, visibility: json.visibility, trialDays: json.trial_days, description: json.description, type: json.type, currency: json.currency, monthlyPrice: json.monthly_price, yearlyPrice: json.yearly_price, createdAt: json.created_at, updatedAt: json.updated_at, benefits: json.benefits.map(item => item.name) }; } /** * @param {object} [options] * @param {string} [options.filter] * @returns {Promise<import('./Tier')[]>} */ async getAll(options = {}) { const filter = nql(); filter.filter = options.filter || {}; return Promise.all(this.#store.slice().filter((item) => { return filter.queryJSON(this.toPrimitive(item)); }).map((tier) => { return Tier.create(tier); })); } /** * @param {import('bson-objectid').default} id * @returns {Promise<import('./Tier')>} */ async getById(id) { const found = this.#store.find((item) => { return item.id.equals(id); }); if (!found) { return null; } return Tier.create(found); } /** * @param {import('./Tier')} tier * @returns {Promise<void>} */ async save(tier) { const data = { id: tier.id.toHexString(), name: tier.name, slug: tier.slug, active: tier.status === 'active', welcome_page_url: tier.welcomePageURL, visibility: tier.visibility, trial_days: tier.trialDays, description: tier.description, type: tier.type, currency: tier.currency, monthly_price: tier.monthlyPrice, yearly_price: tier.yearlyPrice, created_at: tier.createdAt, updated_at: tier.updatedAt, benefits: tier.benefits.map(name => ({name})) }; const toSave = await Tier.create(tier); if (this.#ids[tier.id.toHexString()]) { const existing = this.#store.findIndex((item) => { return item.id.equals(tier.id); }); await this.#ProductModel.edit(data, { id: data.id }); this.#store.splice(existing, 1, toSave); } else { await this.#ProductModel.add(data); this.#store.push(toSave); this.#ids[tier.id.toHexString()] = true; } for (const event of tier.events) { this.#DomainEvents.dispatch(event); } } };