@kwiz/common
Version:
KWIZ common utilities and helpers for M365 platform
267 lines (226 loc) • 9.7 kB
text/typescript
var _objectTypes = {
"Function": typeof (() => {/*empty*/ }),
"Undefined": typeof (undefined),
"String": typeof (""),
"Number": typeof (1),
"Object": typeof ({}),
"Boolean": typeof (true)
};
/** check if a global object in that full name exists and return its type or "undefined" */
export function typeofFullName(fullName: string, windowOrParent?: Window | any) {
//todo: possible to merge with getFromFullName, but we need to distinguish between null and undefined
if (!fullName) {
return _objectTypes.Undefined;
}
try {
let names = fullName.split(".");
let len = names.length;
let obj = windowOrParent || window;
for (var i = 0; i < len; i++) {
obj = obj[names[i]];
if (typeof obj === _objectTypes.Undefined)
return _objectTypes.Undefined;
if (obj === null && i < len)//one of the chained objects (not the leaf) is null - so return undefined
return _objectTypes.Undefined;
}
return typeof obj;
} catch (ex) {
return _objectTypes.Undefined;
}
}
/** get the value by full name of property */
export function getFromFullName<T>(fullName: string, windowOrParent?: Window | any) {
try {
if (isNullOrEmptyString(fullName)) {
return null;
}
try {
var names = fullName.split(".");
var len = names.length;
var obj = windowOrParent || window;
for (var i = 0; i < len; i++) {
obj = obj[names[i]];
if (typeof obj === _objectTypes.Undefined || obj === null) {
return null;
}
}
return <T>obj;
} catch (ex) {
}
} catch (e) { }
return null;
}
export function isTypeofFullNameObject(fullName: string, windowOrParent?: Window | any): boolean {
return typeofFullName(fullName, windowOrParent) === _objectTypes.Object;
}
export function isTypeofFullNameString(fullName: string, windowOrParent?: Window | any): boolean {
return typeofFullName(fullName, windowOrParent) === _objectTypes.String;
}
export function isTypeofFullNameNumber(fullName: string, windowOrParent?: Window | any): boolean {
return typeofFullName(fullName, windowOrParent) === _objectTypes.Number;
}
export function isTypeofFullNameNullOrUndefined(fullName: string, windowOrParent?: Window | any): boolean {
if (typeofFullName(fullName, windowOrParent) === _objectTypes.Undefined) {
return true;
}
try {
var names = fullName.split(".");
var len = names.length;
var obj = windowOrParent || window;
for (var i = 0; i < len && obj !== null; i++) {
obj = obj[names[i]];
}
return obj === null || obj === undefined;
} catch (ex) {
return true;
}
}
export function isTypeofFullNameUndefined(fullName: string, windowOrParent?: Window | any): boolean {
return typeofFullName(fullName, windowOrParent) === _objectTypes.Undefined;
}
export function isTypeofFullNameFunction(fullName: string, windowOrParent?: Window | any): boolean {
return typeofFullName(fullName, windowOrParent) === _objectTypes.Function;
}
export function isTypeofFullNameBoolean(fullName: string, windowOrParent?: Window | any): boolean {
return typeofFullName(fullName, windowOrParent) === _objectTypes.Boolean;
}
export function isType(obj: any, str: string) {
return typeof (obj) === str;
}
// eslint-disable-next-line @typescript-eslint/ban-types
export function isObject(obj: any): obj is object {
return isType(obj, _objectTypes.Object);
}
/** Checks if obj is empty - as primitive, array or object
* If an object, pass an optional array of keys to ignore
*/
export function isEmptyObject(obj: any, options?: { ignoreKeys?: string[] }) {
let ignoreKeys = options && options.ignoreKeys || [];
return isNullOrUndefined(obj) || (Array.isArray(obj) && obj.length === 0) ||
(isObject(obj) && Object.keys(obj)
//if options.ignoreKeys is not empty - only include keys that are NOT in this array
.filter(key => SafeIfElse(() => ignoreKeys.indexOf(key) < 0, true))
.length === 0);
}
export function isNullOrUndefined(obj: any) {
return isUndefined(obj) || obj === null;
}
/** return true if o is undefined, null or not a number */
export function isNullOrNaN(o: any): boolean {
return isNullOrEmptyString(o) || isNaN(o);
}
/** return true if o is undefined, null or empty string */
export function isNullOrEmptyString(o: any): o is null | undefined | "" {
return isNullOrUndefined(o) || o === '';
}
/** o is an array that is not empty (length > 0) */
export function isNotEmptyArray(o: any): o is any[] {
return Array.isArray(o) && o.length > 0;
}
/** o is undefined, null or an empty array */
export function isNullOrEmptyArray(o: any): boolean {
return isNullOrUndefined(o) || (Array.isArray(o) && o.length < 1);
}
export function isString(obj: any): obj is string {
return isType(obj, _objectTypes.String);
}
export function isNotEmptyString(obj: any): obj is string {
return isString(obj) && obj.length > 0;
}
/** true if object is a Date object */
export function isDate(obj: any): obj is Date {
return !isNullOrUndefined(obj) && isFunction(obj.getTime) && !isNullOrNaN((obj as Date).getTime());
}
/** true if obj is a number or a numeric string */
export function isNumeric(obj: any): obj is number | string {
return !isNullOrEmptyString(obj) && !Array.isArray(obj) &&//[14] will return true, since [14].toString() is "14"
!isNaN(parseFloat(obj as string)) && isFinite(obj as number) && isType(Number(obj), _objectTypes.Number);
}
/** true if obj is a number */
export function isNumber(obj?: any): obj is number {
return !isNullOrNaN(obj) && isType(obj, _objectTypes.Number);
}
export function isNumberArray(obj: any[]): obj is number[] {
return !isNullOrUndefined(obj) && Array.isArray(obj) && obj.every((entry) => {
return isNumber(entry);
});
}
export function isUndefined(obj: any): obj is undefined {
return isType(obj, _objectTypes.Undefined);
}
//eslint-disable-next-line @typescript-eslint/ban-types
export function isFunction(obj: any): obj is Function {
return isType(obj, _objectTypes.Function);
}
export function isBoolean(obj: any): obj is boolean {
return isType(obj, _objectTypes.Boolean);
}
export function isPromise<t>(obj: any): obj is Promise<t> {
return obj && isFunction(obj["then"]);
}
export type primitiveTypes = string | number | Date | boolean | null;
/**returns true if object is string, number, date, boolean value or null*/
export function isPrimitiveValue(obj: any): obj is primitiveTypes {
return isNullOrUndefined(obj) || isString(obj) || isNumber(obj) || isDate(obj) || isBoolean(obj);
}
export function isValidGuid(str: string) {
var a = new RegExp("^[{|\\(]?[0-9a-fA-F]{8}[-]?([0-9a-fA-F]{4}[-]?){3}[0-9a-fA-F]{12}[\\)|}]?$");
return !!a.exec(str);
}
export var BoolTrueStrings = ["true", "1", "on", "yes"];
export var BoolFalseStrings = ["false", "0", "off", "no"];
export function isTrueString(str: string, options?: { allowPositiveNumbers?: boolean; }) {
if (isNullOrEmptyString(str)) return false;
else if (BoolTrueStrings.includes(str.toLowerCase()))
return true;
else if (options && options.allowPositiveNumbers && isNumeric(str))
return Number(str) > 0;//any number greater than 0 is considered true.
else return false;
}
export function newGuid() {
var S4 = () => {
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
};
// then to call it, plus stitch in '4' in the third group
return (S4() + S4() + "-" + S4() + "-4" + S4().substr(0, 3) + "-" + S4() + "-" + S4() + S4() + S4()).toLowerCase();
}
/** check if object has all members (they are not undefined) */
export function hasMembers(o: any, ...members: string[]) {
if (!isNullOrUndefined(o)) {
for (let i = 0; i < members.length; i++)
if (isUndefined(o[members[i]]))
return false;
return true;//not null and all members exist
}
return false;
}
/** compares 2 versions. if v1 is bigger return 1, if v2 is bigger returns -1, if equals return 0 */
export function CompareVersion(v1: string, v2: string) {
let v1Split = v1 && v1.split('.').map(s => parseInt(s, 10)) || [];
let v2Split = v2 && v2.split('.').map(s => parseInt(s, 10)) || [];
for (let i = 0; i < Math.max(v1.length, v2.length); i++) {
let p1 = v1Split[i];
let p2 = v2Split[i];
if (isNaN(p1)) p1 = -1;
if (isNaN(p2)) p2 = -1;
if (p1 > p2) return 1;
else if (p1 < p2) return -1;
}
//finished while equal? return 0
return 0;
}
/** pass along a list of unsafe tests to get a value, the first one that doesn't throw an exception and doesnt return null will get returned */
export function SafeIfElse<T>(...list: ((() => T) | T)[]) {
for (let i = 0; i < list.length; i++) {
let v: T = null;
let getter = list[i];
if (isFunction(getter)) {
try {
v = getter();
} catch (e) { v = null; }
}
else v = getter;
if (!isNullOrUndefined(v)) return v;
}
return null;
}