mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-29 22:01:49 +03:00
104f84f252
As discussed with the product team we want to enforce kebab-case file names for all files, with the exception of files which export a single class, in which case they should be PascalCase and reflect the class which they export. This will help find classes faster, and should push better naming for them too. Some files and packages have been excluded from this linting, specifically when a library or framework depends on the naming of a file for the functionality e.g. Ember, knex-migrator, adapter-manager
92 lines
2.0 KiB
JavaScript
92 lines
2.0 KiB
JavaScript
/**
|
|
* @typedef {Object} UrlHistoryItem
|
|
* @prop {string} [path]
|
|
* @prop {string} [id]
|
|
* @prop {string} [type]
|
|
* @prop {string} [referrerSource]
|
|
* @prop {string} [referrerMedium]
|
|
* @prop {string} [referrerUrl]
|
|
* @prop {number} time
|
|
*/
|
|
|
|
/**
|
|
* @typedef {UrlHistoryItem[]} UrlHistoryArray
|
|
*/
|
|
|
|
/**
|
|
* Types allowed to add in the URLHistory manually
|
|
*/
|
|
const ALLOWED_TYPES = ['post'];
|
|
|
|
/**
|
|
* 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) {
|
|
const isValidIdEntry = typeof item?.id === 'string' && typeof item?.type === 'string' && ALLOWED_TYPES.includes(item.type);
|
|
const isValidPathEntry = typeof item?.path === 'string';
|
|
|
|
const isValidEntry = isValidPathEntry || isValidIdEntry;
|
|
|
|
if (!isValidEntry || !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([]);
|
|
}
|
|
|
|
const now = Date.now();
|
|
const filteredHistory = urlHistory.filter((item) => {
|
|
return now - item.time < this.MAX_AGE;
|
|
});
|
|
|
|
return new UrlHistory(filteredHistory);
|
|
}
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
static MAX_AGE = 1000 * 60 * 60 * 24;
|
|
}
|
|
|
|
module.exports = UrlHistory;
|