1babf6126a
refs https://github.com/TryGhost/Team/issues/2416 This extends the mock API to use a more formal pattern of moving our entity code into a separate package, and use the service/repository patterns we've been work toward. The repository is currently in memory, this allows us to start using the API without having to make commitments to the database structure. We've also injected a single fake webmention for testing. I'd expect the Mention object to change a lot from this initial definition as we gain more information about the type of data we expect to see.
109 lines
3.0 KiB
JavaScript
109 lines
3.0 KiB
JavaScript
const nql = require('@tryghost/nql');
|
|
|
|
/**
|
|
* @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;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* @param {object} options
|
|
* @param {string} [options.filter]
|
|
* @param {number | null} options.page
|
|
* @param {number | 'all'} options.limit
|
|
* @returns {Promise<Page<Mention>>}
|
|
*/
|
|
async getPage(options) {
|
|
const filter = nql(options.filter || '', {});
|
|
const results = this.#store.slice().filter((item) => {
|
|
return filter.queryJSON(this.toPrimitive(item));
|
|
});
|
|
|
|
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
|
|
}
|
|
}
|
|
};
|
|
}
|
|
};
|