4e8af72305
refs https://github.com/TryGhost/Team/issues/2534 As we're using soft deletes for mentions we need to store the `deleted` column as well as enforce a `'deleted:false'` filter on the bookshelf model. We've also implemented the handling for deleting mentions. Where we remove a mention anytime we receive and update from or to a page which no longer exists. Co-authored-by: Steve Larson <9larsons@gmail.com>
119 lines
3.4 KiB
JavaScript
119 lines
3.4 KiB
JavaScript
const nql = require('@tryghost/nql');
|
|
const Mention = require('./Mention');
|
|
|
|
/**
|
|
* @typedef {import('./Mention')} Mention
|
|
* @typedef {import('./MentionsAPI').GetPageOptions} GetPageOptions
|
|
* @typedef {import('./MentionsAPI').IMentionRepository} IMentionRepository
|
|
*/
|
|
|
|
/**
|
|
* @template Model
|
|
* @typedef {import('./MentionsAPI').Page<Model>} Page<Model>
|
|
*/
|
|
|
|
/**
|
|
* @implements {IMentionRepository}
|
|
*/
|
|
module.exports = class InMemoryMentionRepository {
|
|
/** @type {Mention[]} */
|
|
#store = [];
|
|
/** @type {Object.<string, true>} */
|
|
#ids = {};
|
|
|
|
/**
|
|
* @param {Mention} mention
|
|
* @returns {any}
|
|
*/
|
|
toPrimitive(mention) {
|
|
return {
|
|
...mention.toJSON(),
|
|
id: mention.id.toHexString(),
|
|
resource_id: mention.resourceId ? mention.resourceId.toHexString() : null
|
|
};
|
|
}
|
|
|
|
/**
|
|
* @param {Mention} mention
|
|
* @returns {Promise<void>}
|
|
*/
|
|
async save(mention) {
|
|
if (this.#ids[mention.id.toHexString()]) {
|
|
const existing = this.#store.findIndex((item) => {
|
|
return item.id.equals(mention.id);
|
|
});
|
|
this.#store.splice(existing, 1, mention);
|
|
} else {
|
|
this.#store.push(mention);
|
|
this.#ids[mention.id.toHexString()] = true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {URL} source
|
|
* @param {URL} target
|
|
* @returns {Promise<Mention>}
|
|
*/
|
|
async getBySourceAndTarget(source, target) {
|
|
return this.#store.find((item) => {
|
|
return item.source.href === source.href && item.target.href === target.href && !Mention.isDeleted(item);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* @param {object} options
|
|
* @param {string} [options.filter]
|
|
* @param {string} [options.order]
|
|
* @param {number | null} options.page
|
|
* @param {number | 'all'} options.limit
|
|
* @returns {Promise<Page<Mention>>}
|
|
*/
|
|
async getPage(options) {
|
|
const filter = nql(options.filter || '', {});
|
|
const data = this.#store.slice();
|
|
|
|
const results = data.slice().filter((item) => {
|
|
return filter.queryJSON(this.toPrimitive(item)) && !Mention.isDeleted(item);
|
|
});
|
|
|
|
if (options.order === 'created_at desc') {
|
|
results.sort((a, b) => {
|
|
return Number(b.timestamp) - Number(a.timestamp);
|
|
});
|
|
}
|
|
|
|
if (options.limit === 'all') {
|
|
return {
|
|
data: results,
|
|
meta: {
|
|
pagination: {
|
|
page: 1,
|
|
pages: 1,
|
|
limit: 'all',
|
|
total: results.length,
|
|
prev: null,
|
|
next: null
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
const start = (options.page - 1) * options.limit;
|
|
const end = start + options.limit;
|
|
const pages = Math.ceil(results.length / options.limit);
|
|
return {
|
|
data: results.slice(start, end),
|
|
meta: {
|
|
pagination: {
|
|
page: options.page,
|
|
pages: pages,
|
|
limit: options.limit,
|
|
total: results.length,
|
|
prev: options.page === 1 ? null : options.page - 1,
|
|
next: options.page === pages ? null : options.page + 1
|
|
}
|
|
}
|
|
};
|
|
}
|
|
};
|