diff --git a/ghost/core/core/server/services/tiers/TierRepository.js b/ghost/core/core/server/services/tiers/TierRepository.js index a83549987a..9006ddd976 100644 --- a/ghost/core/core/server/services/tiers/TierRepository.js +++ b/ghost/core/core/server/services/tiers/TierRepository.js @@ -1,4 +1,5 @@ const {Tier} = require('@tryghost/tiers'); +const nql = require('@tryghost/nql'); /** * @typedef {import('@tryghost/tiers/lib/TiersAPI').ITierRepository} ITierRepository @@ -8,6 +9,11 @@ const {Tier} = require('@tryghost/tiers'); * @implements {ITierRepository} */ module.exports = class TierRepository { + /** @type {import('@tryghost/tiers/lib/Tier')[]} */ + #store = []; + /** @type {Object.} */ + #ids = {}; + /** @type {Object} */ #ProductModel; @@ -24,6 +30,32 @@ module.exports = class TierRepository { 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('@tryghost/tiers/lib/Tier')} tier + * @returns {any} + */ + toPrimitive(tier) { + return { + ...tier, + active: (tier.status === 'active'), + type: tier.type, + id: tier.id.toHexString() + }; + } + /** * @private */ @@ -54,16 +86,12 @@ module.exports = class TierRepository { * @returns {Promise} */ async getAll(options = {}) { - const collection = await this.#ProductModel.findAll({...options, withRelated: ['benefits']}); - - const result = []; - - for (const model of collection.models) { - const tier = await Tier.create(this.mapToTier(model)); - result.push(tier); - } - - return result; + const filter = nql(options.filter, {}); + return Promise.all(this.#store.slice().filter((item) => { + return filter.queryJSON(this.toPrimitive(item)); + }).map((tier) => { + return Tier.create(tier); + })); } /** @@ -71,9 +99,15 @@ module.exports = class TierRepository { * @returns {Promise} */ async getById(id) { - const model = await this.#ProductModel.findOne({id: id.toHexString()}, {withRelated: ['benefits']}); + const found = this.#store.find((item) => { + return item.id.equals(id); + }); - return await Tier.create(this.mapToTier(model)); + if (!found) { + return null; + } + + return Tier.create(found); } /** @@ -99,14 +133,20 @@ module.exports = class TierRepository { benefits: tier.benefits.map(name => ({name})) }; - const existing = await this.#ProductModel.findOne({id: data.id}, {require: false}); + const toSave = await Tier.create(tier); - if (!existing) { - await this.#ProductModel.add(data); - } else { + 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) { diff --git a/ghost/core/core/server/services/tiers/service.js b/ghost/core/core/server/services/tiers/service.js index f74556ffd0..e7deb4d7bd 100644 --- a/ghost/core/core/server/services/tiers/service.js +++ b/ghost/core/core/server/services/tiers/service.js @@ -22,6 +22,10 @@ class TiersServiceWrapper { } }; + await repository.init(); + + this.repository = repository; + this.api = new TiersAPI({ repository, slugService diff --git a/ghost/core/test/utils/fixture-utils.js b/ghost/core/test/utils/fixture-utils.js index e2737d3993..fb87e11fa5 100644 --- a/ghost/core/test/utils/fixture-utils.js +++ b/ghost/core/test/utils/fixture-utils.js @@ -891,6 +891,10 @@ const getFixtureOps = (toDos) => { } }); + fixtureOps.push(() => { + return require('../../core/server/services/tiers').repository?.init(); + }); + return fixtureOps; }; diff --git a/ghost/core/test/utils/fixtures/data-generator.js b/ghost/core/test/utils/fixtures/data-generator.js index 703e62e622..55f46e18f4 100644 --- a/ghost/core/test/utils/fixtures/data-generator.js +++ b/ghost/core/test/utils/fixtures/data-generator.js @@ -1237,6 +1237,9 @@ DataGenerator.forKnex = (function () { slug: 'gold', active: true, type: 'paid', + currency: 'usd', + monthly_price: 500, + yearly_price: 5000, visibility: 'public', benefits: [], created_by: DataGenerator.Content.users[0].id, diff --git a/ghost/core/test/utils/stripe-mocker.js b/ghost/core/test/utils/stripe-mocker.js index 7f0acc4ee2..10e3df0f61 100644 --- a/ghost/core/test/utils/stripe-mocker.js +++ b/ghost/core/test/utils/stripe-mocker.js @@ -92,12 +92,15 @@ class StripeMocker { * @returns */ async createTier({name, currency, monthly_price, yearly_price}) { - return await models.Product.add({ + const result = await tiers.api.add({ name: name ?? ('Tier ' + this.#generateRandomId()), type: 'paid', currency: currency.toUpperCase(), - monthly_price, - yearly_price + monthlyPrice: monthly_price, + yearlyPrice: yearly_price + }); + return await models.Product.findOne({ + id: result.id.toHexString() }); }