See More

export class Utils { public static addRange(target: T[], ...values: T[]) { if (!target) { target = []; } if (!values || values.length === 0) { return target; } for (const value of values) { if (value && target.indexOf(value) < 0) { target.push(value); } } return target; } public static getHashCode(source: string): number { if (!source || source.length === 0) { return 0; } let hash: number = 0; for (let index = 0; index < source.length; index++) { const character = source.charCodeAt(index); hash = ((hash << 5) - hash) + character; hash |= 0; } return hash; } public static getCookies(cookies: string, exclusions?: string[]): object { const result: object = {}; const parts: string[] = (cookies || '').split('; '); for (const part of parts) { const cookie: string[] = part.split('='); if (!Utils.isMatch(cookie[0], exclusions)) { result[cookie[0]] = cookie[1]; } } return !Utils.isEmpty(result) ? result : null; } public static guid(): string { function s4() { return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1); } return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4(); } // tslint:disable-next-line:ban-types public static merge(defaultValues: Object, values: Object) { const result: object = {}; for (const key in defaultValues || {}) { if (defaultValues[key] !== undefined && defaultValues[key] !== null) { result[key] = defaultValues[key]; } } for (const key in values || {}) { if (values[key] !== undefined && values[key] !== null) { result[key] = values[key]; } } return result; } public static parseVersion(source: string): string { if (!source) { return null; } const versionRegex = /(v?((\d+)\.(\d+)(\.(\d+))?)(?:-([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?(?:\+([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?)/; const matches = versionRegex.exec(source); if (matches && matches.length > 0) { return matches[0]; } return null; } public static parseQueryString(query: string, exclusions?: string[]) { if (!query || query.length === 0) { return null; } const pairs: string[] = query.split('&'); if (pairs.length === 0) { return null; } const result: object = {}; for (const pair of pairs) { const parts = pair.split('='); if (!Utils.isMatch(parts[0], exclusions)) { result[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]); } } return !Utils.isEmpty(result) ? result : null; } public static randomNumber(): number { return Math.floor(Math.random() * 9007199254740992); } /** * Checks to see if a value matches a pattern. * @param input the value to check against the @pattern. * @param pattern The pattern to check, supports wild cards (*). */ public static isMatch(input: string, patterns: string[], ignoreCase: boolean = true): boolean { if (!input || typeof input !== 'string') { return false; } const trim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; input = (ignoreCase ? input.toLowerCase() : input).replace(trim, ''); return (patterns || []).some((pattern) => { if (typeof pattern !== 'string') { return false; } pattern = (ignoreCase ? pattern.toLowerCase() : pattern).replace(trim, ''); if (pattern.length <= 0) { return false; } const startsWithWildcard: boolean = pattern[0] === '*'; if (startsWithWildcard) { pattern = pattern.slice(1); } const endsWithWildcard: boolean = pattern[pattern.length - 1] === '*'; if (endsWithWildcard) { pattern = pattern.substring(0, pattern.length - 1); } if (startsWithWildcard && endsWithWildcard) { return pattern.length <= input.length && input.indexOf(pattern, 0) !== -1; } if (startsWithWildcard) { return Utils.endsWith(input, pattern); } if (endsWithWildcard) { return Utils.startsWith(input, pattern); } return input === pattern; }); } public static isEmpty(input: object) { return input === null || (typeof (input) === 'object' && Object.keys(input).length === 0); } public static startsWith(input: string, prefix: string): boolean { return input.substring(0, prefix.length) === prefix; } public static endsWith(input: string, suffix: string): boolean { return input.indexOf(suffix, input.length - suffix.length) !== -1; } /** * Stringifys an object with optional exclusions and max depth. * @param data The data object to add. * @param exclusions Any property names that should be excluded. * @param maxDepth The max depth of the object to include. */ public static stringify(data: any, exclusions?: string[], maxDepth?: number): string { function stringifyImpl(obj: any, excludedKeys: string[]): string { const cache: string[] = []; return JSON.stringify(obj, (key: string, value: any) => { if (Utils.isMatch(key, excludedKeys)) { return; } if (typeof value === 'object' && !!value) { if (cache.indexOf(value) !== -1) { // Circular reference found, discard key return; } cache.push(value); } return value; }); } if (({}).toString.call(data) === '[object Object]') { const flattened = {}; /* tslint:disable:forin */ for (const prop in data) { const value = data[prop]; if (value === data) { continue; } flattened[prop] = data[prop]; } /* tslint:enable:forin */ return stringifyImpl(flattened, exclusions); } if (({}).toString.call(data) === '[object Array]') { const result = []; for (let index = 0; index < data.length; index++) { result[index] = JSON.parse(stringifyImpl(data[index], exclusions)); } return JSON.stringify(result); } return stringifyImpl(data, exclusions); } public static toBoolean(input, defaultValue: boolean = false): boolean { if (typeof input === 'boolean') { return input; } if (input === null || typeof input !== 'number' && typeof input !== 'string') { return defaultValue; } switch ((input + '').toLowerCase().trim()) { case 'true': case 'yes': case '1': return true; case 'false': case 'no': case '0': case null: return false; } return defaultValue; } }