@cisstech/nge
Version:
NG Essentials is a collection of libraries for Angular developers.
486 lines (476 loc) • 16 kB
JavaScript
function deepCopy(obj) {
if (obj === null || typeof obj !== 'object') {
return obj;
}
const copy = obj instanceof Array ? [] : {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
;
copy[key] = deepCopy(obj[key]);
}
}
return copy;
}
class Serializer {
static serialize(instance) {
const record = {};
const prototype = instance.constructor.prototype;
const properties = prototype.__properties_infos__;
Object.keys(properties).forEach((propertyName) => {
if (!(propertyName in instance)) {
return;
}
const property = properties[propertyName];
const exportName = (property.aliases ?? []).pop() ?? propertyName;
const value = instance[propertyName];
if (value == null) {
return;
}
switch (typeof value) {
case 'string':
case 'number':
case 'boolean':
if (value != null) {
record[exportName] = value;
}
break;
case 'object':
if (property.type) {
if (Array.isArray(value)) {
record[exportName] = value
.map((e) => {
return Serializer.serialize(e);
})
.filter((e) => e != null);
}
else if (property.indexed) {
record[exportName] = Object.keys(value).reduce((obj, key) => {
if (value[key] === undefined) {
return obj;
}
obj[key] = Serializer.serialize(value[key]);
return obj;
}, {});
}
else {
record[exportName] = Serializer.serialize(value);
}
}
else {
if (Array.isArray(value)) {
record[exportName] = value.filter((obj) => obj != null);
}
else {
record[exportName] = deepCopy(value);
}
}
break;
}
});
return record;
}
static deserialize(target, props) {
const record = {
...props,
};
const prototype = target.prototype;
const info = prototype.__class_info__;
if (info.resolver) {
target = info.resolver(props);
}
const properties = prototype.__properties_infos__;
Object.keys(properties).forEach((propertyName) => {
const property = properties[propertyName];
const aliases = property.aliases ?? [];
const value = props[propertyName] ??
Object.keys(props).find((k) => {
return !!aliases.find((alias) => alias === k);
});
if (value == null) {
return;
}
switch (typeof value) {
case 'object':
if (property.type) {
if (Array.isArray(value)) {
record[propertyName] = value.map((e) => {
return Serializer.deserialize(property.type, e);
});
}
else if (property.indexed) {
Object.keys(value).forEach((k) => {
value[k] = Serializer.deserialize(property.type, value[k]);
});
record[propertyName] = value;
}
else {
record[propertyName] = Serializer.deserialize(property.type, value);
}
}
else {
record[propertyName] = value;
}
break;
default:
record[propertyName] = value;
break;
}
});
return new target(record);
}
}
class Builder {
/**
* Creates new instance of `T` class.
* @param props properties to pass to the constructor of the instance.
* @returns new instance of `T`
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
static create(props) {
throw new Error('This is an abstract method. It needs to be overridden.');
}
save() {
throw new Error('This is an abstract method. It needs to be overridden.');
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
with(props) {
throw new Error('This is an abstract method. It needs to be overridden.');
}
}
function Entity(info) {
return function (target) {
const prototype = target.prototype;
info = info ?? {};
prototype.__class_info__ = prototype.__class_info__ ?? info;
prototype.__class_info__ = {
...prototype.__class_info__,
...info,
};
prototype.save = function () {
return Serializer.serialize(this);
};
prototype.with = function (props) {
return new target({
...this,
...props,
});
};
target.create = function (props) {
return Serializer.deserialize(target, props);
};
return target;
};
}
function Property(info) {
return (instance, name) => {
info = info ?? {
aliases: [],
};
const prototype = instance.constructor.prototype;
prototype.__properties_infos__ = prototype.__properties_infos__ ?? {};
prototype.__properties_infos__[name] = info;
};
}
function rgbFromHex(color) {
color = color.replace('#', '');
const n = color.length;
if (n == 3) {
// convert rgb to rrggbb
const r = color[0];
const g = color[1];
const b = color[2];
color = `${r}${r}${g}${g}${b}${b}`;
}
const rgb = parseInt(color, 16); // convert rrggbb to decimal
return {
r: (rgb >> 16) & 0xff, // extract red
g: (rgb >> 8) & 0xff, // extract green
b: (rgb >> 0) & 0xff, // extract blue
};
}
function rgbToHex(r, g, b) {
r = Math.round(r);
g = Math.round(g);
b = Math.round(b);
const componentToHex = (c) => {
const hex = c.toString(16);
return hex.length == 1 ? '0' + hex : hex;
};
return '#' + componentToHex(r) + componentToHex(g) + componentToHex(b);
}
function colorContrast(color) {
const { r, g, b } = rgbFromHex(color);
const contrast = (Math.round(r * 299) + Math.round(g * 587) + Math.round(b * 114)) / 1000;
return contrast >= 128 ? 'black' : 'white';
}
// https://maketintsandshades.com/about
function colorTint(color, factor = 0.1 /* 10% */) {
let { r, g, b } = rgbFromHex(color);
r += (255 - r) * factor;
g += (255 - g) * factor;
b += (255 - b) * factor;
return rgbToHex(r, g, b);
}
function colorShade(color, factor = 0.88 /* 12% */) {
let { r, g, b } = rgbFromHex(color);
r *= factor;
g *= factor;
b *= factor;
return rgbToHex(r, g, b);
}
function deepEqual(a, b) {
if (a === b)
return true;
if (a && b && typeof a == 'object' && typeof b == 'object') {
if (a.constructor !== b.constructor)
return false;
var length, i, keys;
if (Array.isArray(a)) {
length = a.length;
if (length != b.length)
return false;
for (i = length; i-- !== 0;)
if (!deepEqual(a[i], b[i]))
return false;
return true;
}
if (a.constructor === RegExp)
return a.source === b.source && a.flags === b.flags;
if (a.valueOf !== Object.prototype.valueOf)
return a.valueOf() === b.valueOf();
if (a.toString !== Object.prototype.toString)
return a.toString() === b.toString();
keys = Object.keys(a);
length = keys.length;
if (length !== Object.keys(b).length)
return false;
for (i = length; i-- !== 0;)
if (!Object.prototype.hasOwnProperty.call(b, keys[i]))
return false;
for (i = length; i-- !== 0;) {
var key = keys[i];
if (!deepEqual(a[key], b[key]))
return false;
}
return true;
}
// true if both NaN, false otherwise
return a !== a && b !== b;
}
function ensuresNonNull(value, message) {
if (value == null) {
throw new ReferenceError(message);
}
return true;
}
function ensuresNonNullArray(value, message) {
if (value == null) {
throw new ReferenceError(message);
}
value.forEach((v) => {
if (v == null) {
throw ReferenceError(message);
}
});
return true;
}
function ensuresNonNullString(value, message) {
if (value == null || value.trim().length === 0) {
message = message || `'require non null|empty string`;
throw new ReferenceError(message);
}
return true;
}
function ensures(condition, message) {
if (!condition) {
throw new Error(message);
}
}
function epoch() {
return new Date('01/01/1970');
}
function addDays(date, days) {
date = new Date(date.valueOf());
date.setDate(date.getDate() + days);
return date;
}
/** Gets current value of unix timestamp */
function timestamp() {
return new Date().getTime() / 1000;
}
/**
* Gets unix timestamp value of `date`
* @param date the date.
*/
function toTimestamp(date) {
return date.getTime() / 1000;
}
/**
* Converts an unix timestamp to a Date object
* @param time an unix timestamp
*/
function dateFromTimestamp(time) {
return new Date(time * 1000);
}
/**
* Converts an unix timestamp to a date in the format 'day month hours mins'
* @param time an unix timestamp.
* @param locale target language locale tag.
* @returns string representation of the date.
*/
function fullDate(time, locale) {
const format = {
month: 'short',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
};
return convertDate(time, format, locale);
}
/**
* Converts an unix timestamp to a date in the format 'day month'
* @param time an unix timestamp.
* @param locale target language locale tag.
* @returns string representation of the date.
*/
function shortDate(time, locale) {
return convertDate(time, { month: 'short', day: 'numeric' }, locale);
}
/**
* Converts an unix timestamp to a date in the format 'hours mins'
* @param time an unix timestamp.
* @returns string representation of the date.
*/
function hours(time) {
const date = dateFromTimestamp(time);
const minutes = date.getMinutes();
const minutesFormat = minutes >= 10 ? minutes : `0${minutes}`;
return `${date.getHours()}:${minutesFormat}`;
}
/**
* Gets a value indicating whether the timestamp is today.
* @param time an unix timestamp.
*/
function isToday(time) {
return new Date().toLocaleDateString() === dateFromTimestamp(time).toLocaleDateString();
}
/**
* Gets a value indicating whether the given dates representes the same year, month and day.
* @param d1 the first date.
* @param d2 the second date.
*/
function compareDays(d1, d2) {
return d1.getFullYear() === d2.getFullYear() && d1.getMonth() === d2.getMonth() && d1.getDate() === d2.getDate();
}
function convertDate(time, format, locale) {
const date = dateFromTimestamp(time);
return date.toLocaleDateString(locale, format);
}
function weeksDiff(d1, d2) {
let diff = (d2.getTime() - d1.getTime()) / 1000;
diff /= 60 * 60 * 24 * 7;
return Math.abs(Math.round(diff));
}
function dateRangeOverlaps(a_start, a_end, b_start, b_end) {
if (a_start < b_start && b_start < a_end)
return true; // b starts in a
if (a_start < b_end && b_end < a_end)
return true; // b ends in a
if (b_start < a_start && a_end < b_end)
return true; // a in b
return false;
}
function isImage(extension) {
extension = extension.toLowerCase();
if (!extension.startsWith('.')) {
extension = '.' + extension;
}
return ['.ai', '.png', '.jpg', '.pjg', '.gif', '.svg', '.jpeg'].includes(extension);
}
function isPdf(extension) {
extension = extension.toLowerCase();
if (!extension.startsWith('.')) {
extension = '.' + extension;
}
return extension === '.pdf';
}
function isWordDoc(extension) {
extension = extension.toLowerCase();
if (!extension.startsWith('.')) {
extension = '.' + extension;
}
return ['.odt', '.doc', '.docx'].includes(extension);
}
function isText(extension) {
extension = extension.toLowerCase();
return extension === 'txt' || extension === '.txt';
}
function isExcelDoc(extension) {
extension = extension.toLowerCase();
if (!extension.startsWith('.')) {
extension = '.' + extension;
}
return ['.xlsx', '.xlsm', '.xsl', '.xst'].includes(extension);
}
function isPowerPointDoc(extension) {
extension = extension.toLowerCase();
if (!extension.startsWith('.')) {
extension = '.' + extension;
}
return ['.ppt', '.pptm', '.pptx'].includes(extension);
}
/**
* Gets the extension of the file (without the dot '.').
* Throws an exception if the file is undefined.
* @param file the file
* @returns the extension of the file.
*/
function extensionOf(file) {
if (file instanceof File) {
const tmp1 = Math.max(0, file.name.lastIndexOf('.'));
return file.name.slice((tmp1 || Infinity) + 1).toLowerCase();
}
const tmp2 = Math.max(0, file.type.lastIndexOf('/'));
return file.type.slice((tmp2 || Infinity) + 1).toLowerCase();
}
function isNullOrEmpty(text) {
return text == null || text.trim() === '';
}
function anyNullOrEmpty(...args) {
if (args == null) {
return true;
}
for (const e of args) {
if (isNullOrEmpty(e)) {
return true;
}
}
return false;
}
const urlPattern = '^(https?:\\/\\/)?' + // protocol
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name
'((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address
'(\\:\\d+)?(\\/[@-a-z\\d%_.~+]*)*' + // port and path
'(\\?[;@&a-z\\d%_.~+=-]*)?' + // query string
'(\\#[@-a-z\\d_]*)?$';
function isURL(str) {
// https://stackoverflow.com/questions/5717093/check-if-a-javascript-string-is-a-url
const pattern = new RegExp(urlPattern, 'i'); // fragment locator
return !!pattern.test(str);
}
function hashCode(str) {
let hash = 0;
if (str.length === 0)
return hash;
for (let i = 0; i < str.length; i++) {
const char = str.charCodeAt(i);
hash = (hash << 5) - hash + char;
hash = hash & hash; // Convert to 32bit integer
}
return hash;
}
/**
* Generated bundle index. Do not edit.
*/
export { Builder, Entity, Property, addDays, anyNullOrEmpty, colorContrast, colorShade, colorTint, compareDays, convertDate, dateFromTimestamp, dateRangeOverlaps, deepCopy, deepEqual, ensures, ensuresNonNull, ensuresNonNullArray, ensuresNonNullString, epoch, extensionOf, fullDate, hashCode, hours, isExcelDoc, isImage, isNullOrEmpty, isPdf, isPowerPointDoc, isText, isToday, isURL, isWordDoc, rgbFromHex, rgbToHex, shortDate, timestamp, toTimestamp, urlPattern, weeksDiff };
//# sourceMappingURL=cisstech-nge-utils.mjs.map