import Key from './Key'; export type BlacklistItemJSON = string | { url: string, keys: string[], }; export type BlacklistJSON = BlacklistItemJSON[]; const regexFromWildcard = (pattern: string): RegExp => { const regexStr = '^' + pattern.replace(/\*/g, '.*') + '$'; return new RegExp(regexStr); }; export class BlacklistItem { public readonly pattern: string; private regex: RegExp; public readonly partial: boolean; public readonly keys: string[]; private readonly keyEntities: Key[]; constructor( pattern: string, partial: boolean, keys: string[] ) { this.pattern = pattern; this.regex = regexFromWildcard(pattern); this.partial = partial; this.keys = keys; this.keyEntities = this.keys.map(Key.fromMapKey); } static fromJSON(json: BlacklistItemJSON): BlacklistItem { return typeof json === 'string' ? new BlacklistItem(json, false, []) : new BlacklistItem(json.url, true, json.keys); } toJSON(): BlacklistItemJSON { if (!this.partial) { return this.pattern; } return { url: this.pattern, keys: this.keys }; } matches(url: URL): boolean { return this.pattern.includes('/') ? this.regex.test(url.host + url.pathname) : this.regex.test(url.host); } includeKey(url: URL, key: Key): boolean { if (!this.matches(url) || !this.partial) { return false; } return this.keyEntities.some(k => k.equals(key)); } } export default class Blacklist { constructor( public readonly items: BlacklistItem[], ) { } static fromJSON(json: BlacklistJSON): Blacklist { const items = json.map(o => BlacklistItem.fromJSON(o)); return new Blacklist(items); } toJSON(): BlacklistJSON { return this.items.map(item => item.toJSON()); } includesEntireBlacklist(url: URL): boolean { return this.items.some(item => !item.partial && item.matches(url)); } includeKey(url: URL, key: Key) { return this.items.some(item => item.includeKey(url, key)); } }