Ghost/ghost/member-attribution/lib/history.js
Fabien "egg" O'Carroll f523e1eb6b Refactored UrlHistory to use static factory method
This keeps the constructor clean, relying on types for validation,
whilst preserving the validation when creating the instance. The
constructor is now private so that the factory which handles
validation is always used.

The tests have also been updated to test the public factory interface
rather than the internal validation methods. Validation has been
rolled into a single method and slightly improved in the way of
readability.
2022-08-25 16:09:34 -04:00

67 lines
1.3 KiB
JavaScript

/**
* @typedef {Object} UrlHistoryItem
* @prop {string} path
* @prop {number} time
*/
/**
* @typedef {UrlHistoryItem[]} UrlHistoryArray
*/
/**
* Represents a validated history
*/
class UrlHistory {
/**
* @private
* @param {UrlHistoryArray} urlHistory
*/
constructor(urlHistory) {
/** @private */
this.history = urlHistory;
}
get length() {
return this.history.length;
}
/**
* Iterate from latest item to newest item (reversed!)
*/
*[Symbol.iterator]() {
yield* this.history.slice().reverse();
}
/**
* @private
* @param {any[]} history
* @returns {boolean}
*/
static isValidHistory(history) {
for (const item of history) {
if (typeof item?.path !== 'string' || !Number.isSafeInteger(item?.time)) {
return false;
}
}
return true;
}
/**
* @param {unknown} urlHistory
* @returns {UrlHistory}
*/
static create(urlHistory) {
if (!Array.isArray(urlHistory)) {
return new UrlHistory([]);
}
if (!this.isValidHistory(urlHistory)) {
return new UrlHistory([]);
}
return new UrlHistory(urlHistory);
}
}
module.exports = UrlHistory;