-
Marin Karamihalev authoredMarin Karamihalev authored
util.ts 5.36 KiB
import { CommandType } from "../types";
// import set from "lodash.set";
const digitDotRe = /^\d+\..*$/;
const digitRe = /^\d+$/;
export const isDigit = (v: any) => digitRe.test(v);
const firstIsIndex = (s: string) => digitDotRe.test(s);
// based on https://stackoverflow.com/questions/54733539/javascript-implementation-of-lodash-set-method
const set = (obj, path, value) => {
if (Object(obj) !== obj) return obj;
if (!Array.isArray(path)) path = path.toString().match(/[^.[\]]+/g) || [];
path
.slice(0, -1)
.reduce(
(a, c, i) =>
Object(a[c]) === a[c]
? a[c]
: (a[c] = Math.abs(path[i + 1]) >> 0 === +path[i + 1] ? [] : {}),
obj
)[path[path.length - 1]] = value;
return obj;
};
// Based on: https://www.30secondsofcode.org/js/s/unflatten-object
export const unflatten = (obj: any) =>
Object.keys(obj).reduce(
(res, k) => {
k.split(".")
.map((v) => (isDigit(v) ? parseInt(v) - 1 : v))
.reduce(
(acc: any, e, i, keys) =>
acc[e] ||
(acc[e] = isNaN(Number(keys[i + 1]))
? keys.length - 1 === i
? obj[k]
: {}
: []),
res
);
return res;
},
firstIsIndex(Object.keys(obj)[0]) ? [] : {}
);
export const search = (obj: any, key: string): any => {
if (typeof obj !== "object") return null;
if (obj[key]) return obj[key];
for (const val of Object.values(obj)) {
const s = search(val, key);
if (s) return s;
}
};
export const searchParent = (
obj: any,
key: string
): Record<string, any> | undefined => {
if (typeof obj !== "object") return;
if (obj[key]) return obj;
for (const val of Object.values(obj)) {
const s = searchParent(val, key);
if (s) return s;
}
};
const fixPath = (s: string): string =>
s
.split(".")
.filter((it) => it !== "")
.map((it) => (isDigit(it) ? `[${parseInt(it) - 1}]` : it))
.join(".")
.split(".[")
.join("[");
export const convertToNestedObject = (arr) => {
const res = {};
arr
.map((it) =>
Object.entries(it.resultParams).map(([key, value]) => ({
path: fixPath(it.resolvedPath + key),
value,
}))
)
.flat(1)
.sort((a, b) => a.path.localeCompare(b.path))
.forEach(({ path, value }) => {
set(res, path, value);
});
return res;
};
export const hasMultipleIndexes = (
arr: string[],
pathSplit: string[]
): boolean =>
arr.some((it) => {
const spl = it.split(".");
return spl.length > pathSplit.length && isDigit(spl[pathSplit.length - 1]);
});
const _searchAll = (obj: any, key: string): any[] =>
typeof obj !== "object"
? []
: Object.entries(obj).reduce(
(acc, [k, v]) => [...acc, k === key ? v : _searchAll(v, key)],
[] as any[]
);
export const searchAll = (obj: any, key: string) =>
_searchAll(obj, key).flat(Infinity);
export const extractCommand = (msg: {
[key: string]: any;
}): CommandType | undefined => {
const msgType: string | undefined = search(msg, "msgType");
if (!msgType) {
const id: string | undefined = search(msg, "msgId");
const [frst] = id ? id.split("@") : [""];
return frst.toUpperCase().replace("_RESP", "") as CommandType;
}
return msgType.replace("_RESP", "") as CommandType;
};
/** Unwraps object with single key */
export const unwrapObject = (data: any): any =>
!Array.isArray(data) &&
typeof data === "object" &&
Object.keys(data).length === 1
? Object.values(data)[0]
: data;
/** Unwraps array with single item */
export const unwrapArray = (arr: any) =>
Array.isArray(arr) && arr.length === 1 ? arr[0] : arr;
const isObject = (val: any): boolean =>
typeof val === "object" && val !== null && !Array.isArray(val);
export const isEmpty = (obj: any): boolean =>
obj !== null &&
obj !== undefined &&
obj &&
typeof obj === "object" &&
Object.keys(obj).length === 0;
export const fullyUnwrapObject = (obj: any, shouldBeArray: boolean) => {
if (isObject(obj) && Object.keys(obj).length === 1)
return fullyUnwrapObject(Object.values(obj)[0], shouldBeArray);
const isArray = Array.isArray(obj);
if (shouldBeArray)
if (isArray) return obj.filter((v) => !isEmpty(v));
else return isEmpty(obj) ? [] : [obj];
else if (isArray)
return fullyUnwrapObject(
obj.find((v) => !isEmpty(v)),
shouldBeArray
);
else return obj;
};
export function makeBuffer(
rootRecord: any,
payload: any,
options: Record<string, string>
) {
const NoSessionContextRecord = rootRecord.lookupType(
"usp_record.NoSessionContextRecord"
);
const noSessionContextRecordMsg = NoSessionContextRecord.create({
payload,
});
const record: any = rootRecord.lookupType("usp_record.Record");
const recordMsg = record.create({
version: "1.0",
PayloadSecurity: record.PayloadSecurity.PLAINTEXT,
noSessionContext: noSessionContextRecordMsg,
...options,
});
const buffer = record.encode(recordMsg).finish();
return buffer;
}
export const uniq = (initial?: string): string =>
(initial || "") +
(
Date.now().toString(36) + Math.random().toString(36).substr(2, 5)
).toUpperCase();
export const parseID = (msg: any) => {
const foundId = search(msg, "msgId");
// if id is formatted by me (command@) then use, otherwise check for sub id
const id = foundId.includes("@")
? foundId
: search(msg, "subscriptionId") || null;
return id;
};