@wandzai/utils 1.0.58-audience-page-discrepency-6 → 1.0.58-interactions-close-btn-2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/cache.ts +1 -0
- package/src/common.ts +104 -0
- package/src/date.ts +37 -0
- package/src/encrypt-decrypt.ts +14 -0
- package/src/gzip.ts +30 -0
- package/src/hash.ts +12 -0
- package/src/http.ts +64 -0
- package/src/{index.d.ts → index.ts} +1 -0
- package/src/interactions.ts +79 -0
- package/src/mysql.ts +14 -0
- package/src/numeric.ts +9 -0
- package/src/schedule.ts +35 -0
- package/src/snowflake.ts +23 -0
- package/src/wandz.ts +132 -0
- package/tsconfig.lib.json +9 -0
- package/src/cache.d.ts +0 -1
- package/src/cache.js +0 -6
- package/src/cache.js.map +0 -1
- package/src/common.d.ts +0 -16
- package/src/common.js +0 -93
- package/src/common.js.map +0 -1
- package/src/date.d.ts +0 -10
- package/src/date.js +0 -65
- package/src/date.js.map +0 -1
- package/src/encrypt-decrypt.d.ts +0 -2
- package/src/encrypt-decrypt.js +0 -17
- package/src/encrypt-decrypt.js.map +0 -1
- package/src/gzip.d.ts +0 -1
- package/src/gzip.js +0 -22
- package/src/gzip.js.map +0 -1
- package/src/hash.d.ts +0 -1
- package/src/hash.js +0 -17
- package/src/hash.js.map +0 -1
- package/src/http.d.ts +0 -5
- package/src/http.js +0 -47
- package/src/http.js.map +0 -1
- package/src/index.js +0 -29
- package/src/index.js.map +0 -1
- package/src/mysql.d.ts +0 -1
- package/src/mysql.js +0 -19
- package/src/mysql.js.map +0 -1
- package/src/numeric.d.ts +0 -2
- package/src/numeric.js +0 -14
- package/src/numeric.js.map +0 -1
- package/src/schedule.d.ts +0 -8
- package/src/schedule.js +0 -31
- package/src/schedule.js.map +0 -1
- package/src/snowflake.d.ts +0 -3
- package/src/snowflake.js +0 -31
- package/src/snowflake.js.map +0 -1
- package/src/wandz.d.ts +0 -17
- package/src/wandz.js +0 -118
- package/src/wandz.js.map +0 -1
package/package.json
CHANGED
package/src/cache.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const cacheKeyBuilder = (cacheKey: string, identifiers: any): string => `${cacheKey}${JSON.stringify(identifiers)}`;
|
package/src/common.ts
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
export const fakeDelay = (milliSec: number) =>
|
|
2
|
+
new Promise((resolve) => {
|
|
3
|
+
setTimeout(resolve, milliSec);
|
|
4
|
+
});
|
|
5
|
+
|
|
6
|
+
export const convertCamelCaseToUnderscore = (term: string):
|
|
7
|
+
string =>
|
|
8
|
+
term
|
|
9
|
+
.split(/\.?(?=[A-Z])/)
|
|
10
|
+
.join('_')
|
|
11
|
+
.toLowerCase();
|
|
12
|
+
export const convertUnderscoreToCamelCase = (underscoreString: string): string => {
|
|
13
|
+
return underscoreString.replace(/_([a-z])/g, (_match: string, group) => {
|
|
14
|
+
return group.toUpperCase();
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const convertUnderscoreToCamelCaseObj = (obj: Record<string, any>): Record<string, any> => {
|
|
19
|
+
return Object.keys(obj).reduce((acc, key) => {
|
|
20
|
+
acc[convertUnderscoreToCamelCase(key)] = obj[key];
|
|
21
|
+
return acc;
|
|
22
|
+
}, {});
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
export const convertCamelCaseToUnderscoreObj = (obj: Record<string, any>): Record<string, any> => {
|
|
27
|
+
return Object.keys(obj).reduce((acc, key) => {
|
|
28
|
+
acc[convertCamelCaseToUnderscore(key)] = obj[key];
|
|
29
|
+
return acc;
|
|
30
|
+
}, {});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
export const kebabToDisplayName = (kebabCase: string) => kebabCase
|
|
35
|
+
.split('-')
|
|
36
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
37
|
+
.join(' ');
|
|
38
|
+
|
|
39
|
+
export const stringifyWithSingleQuotes = (arr: any[]) => {
|
|
40
|
+
return JSON.stringify(arr, (key, value) => {
|
|
41
|
+
if (typeof value === 'string') {
|
|
42
|
+
return `'${value}'`; /** Wrap string values with single quotes */
|
|
43
|
+
}
|
|
44
|
+
return value;
|
|
45
|
+
})
|
|
46
|
+
.replace(/"([^"]+)":/g, "'$1':") /** Wrap keys with single quotes */
|
|
47
|
+
.replace(/"/g, ''); /** Remove any remaining double quotes */
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export const upperCaseFirstChar = (word: string) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
|
|
51
|
+
|
|
52
|
+
export const upperCaseFirstCharOfEachWord = (str: string) => {
|
|
53
|
+
return (str || '').replace(/\b\w/g, function (match) {
|
|
54
|
+
return match.toUpperCase();
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export const upperCaseFirstCharOfEachWordSplitBySpace = (str: string) => {
|
|
59
|
+
return (str || '').split(' ').map(upperCaseFirstChar).join(' ');
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export const jsonToConsistentString = (jsonObj) => {
|
|
63
|
+
// Helper function to sort an object recursively
|
|
64
|
+
function sortObject(obj) {
|
|
65
|
+
if (obj === null || typeof obj !== 'object') {
|
|
66
|
+
return obj;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (Array.isArray(obj)) {
|
|
70
|
+
return obj.map(sortObject);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const sortedKeys = Object.keys(obj).sort();
|
|
74
|
+
const sortedObj = {};
|
|
75
|
+
|
|
76
|
+
for (const key of sortedKeys) {
|
|
77
|
+
sortedObj[key] = sortObject(obj[key]);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return sortedObj;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Sort the JSON object */
|
|
84
|
+
const sortedJsonObj = sortObject(jsonObj);
|
|
85
|
+
|
|
86
|
+
/** Convert the sorted JSON object to a string */
|
|
87
|
+
return JSON.stringify(sortedJsonObj);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export const booleanStringToBoolean = (value: string) => value === 'true';
|
|
91
|
+
export const booleanStringToNumber = (value: string) =>
|
|
92
|
+
booleanStringToBoolean(value) ? 1 : 0;
|
|
93
|
+
|
|
94
|
+
/**Convert snowflake response keys CAPITAL_CHAR into capitalChar **/
|
|
95
|
+
export const normalizeSfResponseObjKeys = (obj: Record<string, any>) => {
|
|
96
|
+
return Object.fromEntries(
|
|
97
|
+
Object.entries(obj).map(([key, value]) => [
|
|
98
|
+
key
|
|
99
|
+
.toLowerCase()
|
|
100
|
+
.replace(/_([a-z])/g, (_, char) => char.toUpperCase()), // Convert _X to X
|
|
101
|
+
value
|
|
102
|
+
])
|
|
103
|
+
);
|
|
104
|
+
}
|
package/src/date.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {TimeUnits} from '@wandzai/wandz-interfaces';
|
|
2
|
+
|
|
3
|
+
export const formatDateYearMonthDay = (date: string | Date) =>
|
|
4
|
+
new Date(date).toLocaleDateString('en-CA', { year: 'numeric', month: '2-digit', day: '2-digit' });
|
|
5
|
+
|
|
6
|
+
export const calcDatesRange = (range: number) => {
|
|
7
|
+
const today = new Date();
|
|
8
|
+
const startDate = new Date(today);
|
|
9
|
+
startDate.setDate(today.getDate() - range);
|
|
10
|
+
|
|
11
|
+
return {
|
|
12
|
+
startDate: formatDateYearMonthDay(startDate),
|
|
13
|
+
endDate: formatDateYearMonthDay(today),
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const getTimeDifference = (date: Date, timeUnit: TimeUnits): number => {
|
|
18
|
+
/** Get the current date and time */
|
|
19
|
+
const now = new Date();
|
|
20
|
+
|
|
21
|
+
/** Calculate the time difference in milliseconds */
|
|
22
|
+
const timeDifference = now.getTime() - date.getTime();
|
|
23
|
+
|
|
24
|
+
/** Convert the time difference to the specified time unit */
|
|
25
|
+
switch (timeUnit) {
|
|
26
|
+
case TimeUnits.Hours:
|
|
27
|
+
return timeDifference / (1000 * 60 * 60);
|
|
28
|
+
case TimeUnits.Minutes:
|
|
29
|
+
return timeDifference / (1000 * 60);
|
|
30
|
+
case TimeUnits.Seconds:
|
|
31
|
+
return timeDifference / 1000;
|
|
32
|
+
case TimeUnits.Days:
|
|
33
|
+
return timeDifference / (1000 * 60 * 60 * 24);
|
|
34
|
+
default:
|
|
35
|
+
return timeDifference; /** Return milliseconds by default */
|
|
36
|
+
}
|
|
37
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const CryptoJS = require('crypto-js');
|
|
2
|
+
const key = '66807eb6-f5c0-4245-8e4c-0c5d3f80f203';
|
|
3
|
+
|
|
4
|
+
export const encryptData = (data: any): string => {
|
|
5
|
+
const encryptedData = CryptoJS.RC4.encrypt(JSON.stringify(data), key).toString();
|
|
6
|
+
|
|
7
|
+
return encodeURIComponent(encryptedData);
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const decryptData = (data: string): any => {
|
|
11
|
+
const decodedEncrypted = decodeURIComponent(data);
|
|
12
|
+
const bytes = CryptoJS.RC4.decrypt(decodedEncrypted, key);
|
|
13
|
+
return JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
|
|
14
|
+
};
|
package/src/gzip.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gzip single file or every file in given folder
|
|
3
|
+
* @file gzip.js
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {createGzip} from 'zlib';
|
|
7
|
+
import {createReadStream, createWriteStream} from 'fs';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @method gzipFile
|
|
11
|
+
* @param {String} fileIn
|
|
12
|
+
* @param {String} fileOut
|
|
13
|
+
*/
|
|
14
|
+
export function gzipFile(fileIn: string, fileOut: string) {
|
|
15
|
+
return new Promise<void>((resolve, reject) => {
|
|
16
|
+
const inp = createReadStream(fileIn);
|
|
17
|
+
const out = createWriteStream(fileOut);
|
|
18
|
+
const gzip = createGzip();
|
|
19
|
+
|
|
20
|
+
inp
|
|
21
|
+
.pipe(gzip)
|
|
22
|
+
.pipe(out)
|
|
23
|
+
.on('finish', function () {
|
|
24
|
+
resolve();
|
|
25
|
+
})
|
|
26
|
+
.on('error', function (err) {
|
|
27
|
+
reject(err);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
}
|
package/src/hash.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const hmacSHA512 = require('crypto-js/hmac-sha512');
|
|
2
|
+
const Base64 = require('crypto-js/enc-base64');
|
|
3
|
+
|
|
4
|
+
export const hashData = (strToHash: string, specificSalt: string): string => {
|
|
5
|
+
try {
|
|
6
|
+
const saltPrefix: string = 'YvSmHe0x5FC90fmk';
|
|
7
|
+
const salt: string = `${saltPrefix}-${specificSalt.toLowerCase()}`;
|
|
8
|
+
return Base64.stringify(hmacSHA512(strToHash, salt)).replaceAll('+', '');
|
|
9
|
+
} catch (error) {
|
|
10
|
+
console.error('Error:', error.message);
|
|
11
|
+
}
|
|
12
|
+
};
|
package/src/http.ts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import {Request} from 'express';
|
|
2
|
+
import * as querystring from 'querystring';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Extracts ip address from http request
|
|
6
|
+
* @param {Request} req - http request
|
|
7
|
+
*/
|
|
8
|
+
export function getIpFromHttpRequest(req: Request): string {
|
|
9
|
+
return req.headers['x-forwarded-for']
|
|
10
|
+
? String(req.headers['x-forwarded-for']).split(',')[0].trim()
|
|
11
|
+
: req.socket.remoteAddress;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function buildUriBodyString(queryParams: Record<string, any>): string {
|
|
15
|
+
return Object.keys(queryParams)
|
|
16
|
+
.map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(queryParams[key]))}`)
|
|
17
|
+
.join('&');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* On platform side we're stringifies all entries (also strings) as you can see buildUriBodyString above
|
|
22
|
+
* On the other hand, while using <getEncodedQueryParams> to verify network calls on Automation,
|
|
23
|
+
* the string values are not sent wrapped with double quotes,
|
|
24
|
+
* therefore we'll add a safety mechanism
|
|
25
|
+
* */
|
|
26
|
+
export function getEncodedQueryParams(fullUrl: string): object {
|
|
27
|
+
const queryStringStartIndex = fullUrl.indexOf('?');
|
|
28
|
+
if (queryStringStartIndex === -1) {
|
|
29
|
+
return {}; // No query string found
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const queryString = fullUrl.substring(queryStringStartIndex + 1);
|
|
33
|
+
const data = querystring.parse(queryString);
|
|
34
|
+
|
|
35
|
+
return Object.keys(data).reduce((acc, key) => {
|
|
36
|
+
try {
|
|
37
|
+
/** safety mechanism */
|
|
38
|
+
acc[key] = JSON.parse(data[key] as string);
|
|
39
|
+
} catch (e) {
|
|
40
|
+
acc[key] = data[key]; /** for non-object values*/
|
|
41
|
+
}
|
|
42
|
+
return acc;
|
|
43
|
+
}, {});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Builds a query string from an object of parameters.
|
|
48
|
+
*
|
|
49
|
+
* @param {Record<string, any>} params - The parameters to be converted into a query string.
|
|
50
|
+
* @returns {string} The constructed query string.
|
|
51
|
+
*/
|
|
52
|
+
export function buildQueryString(params: Record<string, any>): string {
|
|
53
|
+
const queryParams = new URLSearchParams();
|
|
54
|
+
|
|
55
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
56
|
+
if (typeof value === 'object') {
|
|
57
|
+
queryParams.append(key, JSON.stringify(value));
|
|
58
|
+
} else {
|
|
59
|
+
queryParams.append(key, String(value));
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
return queryParams.toString();
|
|
64
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import {Devices, IInteraction, IInteractionCloseButtonConfig} from "@wandzai/wandz-interfaces";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
const btnSvg = '<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M9.87097 0.366057C10.3591 -0.121966 11.1504 -0.122072 11.6385 0.366057C12.1261 0.854212 12.1264 1.64566 11.6385 2.13363L7.76941 6.0018L11.6385 9.87094L11.7245 9.96567C12.1243 10.4566 12.0959 11.1811 11.6385 11.6385C11.1811 12.096 10.4567 12.1243 9.96569 11.7245L9.87097 11.6385L6.00085 7.76938L2.13366 11.6375C1.64563 12.1255 0.85426 12.1253 0.366085 11.6375C-0.121993 11.1494 -0.122063 10.3581 0.366085 9.86996L4.23327 6.0018L0.366085 2.13461C-0.12203 1.64652 -0.121894 0.855216 0.366085 0.367033C0.854135 -0.121035 1.64547 -0.121806 2.13366 0.366057L6.00183 4.23422L9.87097 0.366057Z" fill="#2F2F2F"/></svg>'
|
|
5
|
+
const DEFAULTS = {
|
|
6
|
+
OFFSET: 8,
|
|
7
|
+
SIZE: 12,
|
|
8
|
+
COLOR: '#000000',
|
|
9
|
+
PADDING: 10,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const getCloseButton = (
|
|
13
|
+
interaction: IInteraction,
|
|
14
|
+
deviceType: Devices.PC | Devices.MOB,
|
|
15
|
+
btnClassName: string = 'exit-btn',
|
|
16
|
+
btnId: string = 'wandz-interaction-close-btn',
|
|
17
|
+
tagType: string = 'span',
|
|
18
|
+
) => {
|
|
19
|
+
let config = interaction.closeButtonConfig?.[deviceType] || interaction.closeButtonConfig?.[Devices.PC];
|
|
20
|
+
if (!config) {
|
|
21
|
+
config = {
|
|
22
|
+
color: interaction.closeButtonColor || DEFAULTS.COLOR,
|
|
23
|
+
size: DEFAULTS.SIZE,
|
|
24
|
+
offsetX: DEFAULTS.OFFSET,
|
|
25
|
+
offsetY: DEFAULTS.OFFSET,
|
|
26
|
+
} as IInteractionCloseButtonConfig;
|
|
27
|
+
}
|
|
28
|
+
let extraStyles = '';
|
|
29
|
+
const backgroundConfig = config.background;
|
|
30
|
+
if (backgroundConfig) {
|
|
31
|
+
extraStyles = `
|
|
32
|
+
#${btnId} {
|
|
33
|
+
width: ${config.size + DEFAULTS.PADDING * 2}px;
|
|
34
|
+
height: ${config.size + DEFAULTS.PADDING * 2}px;
|
|
35
|
+
background-color: ${backgroundConfig.color};
|
|
36
|
+
border-radius: ${backgroundConfig.radius}px;
|
|
37
|
+
box-shadow: inset 0 0 0 1.5px ${backgroundConfig.borderColor};
|
|
38
|
+
}`
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
html: `<${tagType} id="${btnId}" class="${btnClassName}">${btnSvg}</${tagType}>`,
|
|
42
|
+
styles: `
|
|
43
|
+
#${btnId} {
|
|
44
|
+
position: absolute;
|
|
45
|
+
top: ${config.offsetY}px;
|
|
46
|
+
right: ${config.offsetX}px;
|
|
47
|
+
line-height: ${config.size}px;
|
|
48
|
+
cursor: pointer;
|
|
49
|
+
display: flex;
|
|
50
|
+
align-items: center;
|
|
51
|
+
justify-content: center;
|
|
52
|
+
overflow: hidden;
|
|
53
|
+
}
|
|
54
|
+
#${btnId} svg {
|
|
55
|
+
height: ${config.size}px;
|
|
56
|
+
width: ${config.size}px;
|
|
57
|
+
}
|
|
58
|
+
#${btnId} svg path {
|
|
59
|
+
fill: ${config.color};
|
|
60
|
+
}
|
|
61
|
+
#${btnId}::after {
|
|
62
|
+
content: '';
|
|
63
|
+
position: absolute;
|
|
64
|
+
top: 0;
|
|
65
|
+
left: 0;
|
|
66
|
+
width: 100%;
|
|
67
|
+
height: 100%;
|
|
68
|
+
background-color: #ffffff;
|
|
69
|
+
opacity: 0;
|
|
70
|
+
transition: opacity 0.3s ease;
|
|
71
|
+
pointer-events: none;
|
|
72
|
+
}
|
|
73
|
+
#${btnId}:hover::after {
|
|
74
|
+
opacity: 0.3;
|
|
75
|
+
}
|
|
76
|
+
${extraStyles}
|
|
77
|
+
`,
|
|
78
|
+
};
|
|
79
|
+
};
|
package/src/mysql.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const formatParamValue = (value: any): string => {
|
|
2
|
+
if (typeof value === 'object') {
|
|
3
|
+
/** Currently used for arrays (typeof [] is 'object') */
|
|
4
|
+
return `'${JSON.stringify(value)}'`;
|
|
5
|
+
} else if (typeof value === 'string') {
|
|
6
|
+
return `'${value}'`;
|
|
7
|
+
} else {
|
|
8
|
+
return value;
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const buildMysqlProcedureString = (procedure: string, params: any[]): string => {
|
|
13
|
+
return `CALL ${procedure}(${params.map((v) => formatParamValue(v)).join(',')});`;
|
|
14
|
+
};
|
package/src/numeric.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const getRandomIntInclusive = (minVal: number, maxVal: number) => {
|
|
2
|
+
const min = Math.ceil(minVal);
|
|
3
|
+
const max = Math.floor(maxVal);
|
|
4
|
+
return Math.floor(Math.random() * (max - min + 1)) + min; //The maximum is inclusive and the minimum is inclusive
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export const getRandomFloatInclusive = (minVal: number, maxVal: number) => {
|
|
8
|
+
return Number((Math.random() * (minVal - maxVal + 1) + minVal).toFixed(2));
|
|
9
|
+
};
|
package/src/schedule.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as dayjs from 'dayjs';
|
|
2
|
+
import * as utc from 'dayjs/plugin/utc';
|
|
3
|
+
import * as timezone from 'dayjs/plugin/timezone';
|
|
4
|
+
|
|
5
|
+
dayjs.extend(utc);
|
|
6
|
+
dayjs.extend(timezone);
|
|
7
|
+
export { dayjs };
|
|
8
|
+
|
|
9
|
+
export const nowInUTC = (asDate: boolean = true): Date | dayjs.Dayjs =>
|
|
10
|
+
asDate ? dayjs().utc().toDate() : dayjs().utc();
|
|
11
|
+
|
|
12
|
+
export const isInPast = (date: Date | string): boolean => dayjs.utc(date).isBefore(nowInUTC());
|
|
13
|
+
|
|
14
|
+
export const isSameDate = (date1: Date | string, date2: Date | string): boolean =>
|
|
15
|
+
dayjs(date1).isSame(dayjs(date2), 'day');
|
|
16
|
+
|
|
17
|
+
export const getHourOfUTCDate = (date: Date | string): number => dayjs.utc(date).hour();
|
|
18
|
+
|
|
19
|
+
export const formatUTCDateWithTimezone = (date: Date | string, timezone: string, format: string): string => {
|
|
20
|
+
return dayjs
|
|
21
|
+
.utc(date) // Explicitly treat the input as UTC
|
|
22
|
+
.tz(timezone) // Convert to user's timezone
|
|
23
|
+
.format(format);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const getTimezoneOffsetInHours = (region: string): number => {
|
|
27
|
+
// Get the current time in the given timezone
|
|
28
|
+
const nowInTimezone = dayjs().tz(region);
|
|
29
|
+
|
|
30
|
+
// Get the offset in minutes and convert to hours
|
|
31
|
+
const offsetInHours = nowInTimezone.utcOffset() / 60;
|
|
32
|
+
|
|
33
|
+
// Return the offset in hours
|
|
34
|
+
return parseFloat(offsetInHours.toFixed(1));
|
|
35
|
+
};
|
package/src/snowflake.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const formatParamValue = (value: any): string => {
|
|
2
|
+
if (Array.isArray(value)) {
|
|
3
|
+
return `[${value.map(formatParamValue).join(',')}]`;
|
|
4
|
+
} else if (typeof value === 'boolean') {
|
|
5
|
+
return value ? 'TRUE' : 'FALSE';
|
|
6
|
+
} else if (typeof value === 'number') {
|
|
7
|
+
return value.toString();
|
|
8
|
+
} else if (value === null) {
|
|
9
|
+
return 'NULL';
|
|
10
|
+
} else if (typeof value === 'object') {
|
|
11
|
+
const content = Object.entries(value).map(([key, value]) => {
|
|
12
|
+
return `'${key}', ${formatParamValue(value)}`;
|
|
13
|
+
}).join(',');
|
|
14
|
+
return `object_construct(${content})`;
|
|
15
|
+
} else {
|
|
16
|
+
return `'${value}'`;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const buildComplexTypedProcedure = (procedure: string, params: { [paramName: string]: any }): string =>
|
|
21
|
+
`CALL ${procedure}(${Object.entries(params)
|
|
22
|
+
.map(([paramName, paramValue]) => `${paramName} => ${formatParamValue(paramValue)}`)
|
|
23
|
+
.join(', ')})`;
|
package/src/wandz.ts
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AdaptiveSearchReplaceLabels,
|
|
3
|
+
AffinityTypes,
|
|
4
|
+
AiFeatureDistributionType,
|
|
5
|
+
IAdaptiveSearch,
|
|
6
|
+
IAffinityBasedCustomAiFeatureConfig,
|
|
7
|
+
IAiFeaturesBasicConfig,
|
|
8
|
+
IAudience,
|
|
9
|
+
ICustomAiFeature,
|
|
10
|
+
ICustomAudience,
|
|
11
|
+
IEntity,
|
|
12
|
+
IEventBasedCustomAiFeatureConfig,
|
|
13
|
+
IPredictionModel,
|
|
14
|
+
IStorageBasedCustomAiFeatureConfig, IWandzAiFeaturesConfig,
|
|
15
|
+
WandzEntities,
|
|
16
|
+
} from '@wandzai/wandz-interfaces';
|
|
17
|
+
|
|
18
|
+
/** ai-features */
|
|
19
|
+
export const entityTechNameBuilder = (entityName: string) => {
|
|
20
|
+
/** Convert display name to slug:
|
|
21
|
+
transform to lowercase, replace spaces with underscores
|
|
22
|
+
remove anything not alphanumeric, or underscore, or dot
|
|
23
|
+
*/
|
|
24
|
+
return entityName
|
|
25
|
+
.toLowerCase()
|
|
26
|
+
.replace(/ /g, '_')
|
|
27
|
+
.replace(/[^\w_.]+/g, '');
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export function isAffinityBasedCustomAiFeature(
|
|
31
|
+
feature: ICustomAiFeature,
|
|
32
|
+
): feature is IAffinityBasedCustomAiFeatureConfig {
|
|
33
|
+
return (feature as IAffinityBasedCustomAiFeatureConfig).affinityType != null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function isStorageBasedCustomAiFeature(
|
|
37
|
+
feature: ICustomAiFeature,
|
|
38
|
+
): feature is IStorageBasedCustomAiFeatureConfig {
|
|
39
|
+
return (feature as IStorageBasedCustomAiFeatureConfig).storageLogic != null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function isEventBasedCustomAiFeature(feature: ICustomAiFeature): feature is IEventBasedCustomAiFeatureConfig {
|
|
43
|
+
return (feature as IEventBasedCustomAiFeatureConfig).eventLogic != null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const getCustomAiFeatureType = (feature: ICustomAiFeature): AiFeatureDistributionType => {
|
|
47
|
+
if (isEventBasedCustomAiFeature(feature)) {
|
|
48
|
+
return 'event';
|
|
49
|
+
} else if (isAffinityBasedCustomAiFeature(feature)) {
|
|
50
|
+
return feature.affinityType;
|
|
51
|
+
}
|
|
52
|
+
return 'storage';
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const isAiFeature = (entity: IEntity): entity is IAiFeaturesBasicConfig => {
|
|
56
|
+
return (entity as IAiFeaturesBasicConfig).aiFeature != null;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const isAudience = (entity: IEntity): entity is IAudience => {
|
|
60
|
+
return (entity as IAudience).operator != null && (entity as IAudience).rules != null;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export const isCustomEntity = (entity: IEntity) => {
|
|
64
|
+
return (
|
|
65
|
+
/** checking if entity matches <ICreationMeta> interfaces */
|
|
66
|
+
entity.hasOwnProperty('createdBy')
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const isCustomAudience = (audience: IAudience): audience is ICustomAudience => {
|
|
71
|
+
return isCustomEntity(audience);
|
|
72
|
+
};
|
|
73
|
+
export const isCustomAiFeature = (feature: IAiFeaturesBasicConfig): feature is ICustomAiFeature => {
|
|
74
|
+
return isCustomEntity(feature);
|
|
75
|
+
};
|
|
76
|
+
export const isInHouseAiFeature = (entity: IEntity): entity is IWandzAiFeaturesConfig => {
|
|
77
|
+
return isAiFeature(entity) && !isCustomEntity(entity);
|
|
78
|
+
};
|
|
79
|
+
export const isModel = (entity: IEntity): entity is IPredictionModel => {
|
|
80
|
+
return (entity as IPredictionModel).targetRules != null;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export const getEntityID = (entity: IEntity): string => {
|
|
84
|
+
if (isAiFeature(entity)) {
|
|
85
|
+
return entity.id?.toString();
|
|
86
|
+
} else if (isAudience(entity)) {
|
|
87
|
+
return entity.guid;
|
|
88
|
+
} else if (isModel(entity)) {
|
|
89
|
+
return entity.guid;
|
|
90
|
+
}
|
|
91
|
+
return '';
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export const getEntityType = (entity: IEntity): WandzEntities => {
|
|
95
|
+
if (isAiFeature(entity)) {
|
|
96
|
+
return WandzEntities.AI_FEATURE;
|
|
97
|
+
} else if (isAudience(entity)) {
|
|
98
|
+
return WandzEntities.AUDIENCE;
|
|
99
|
+
} else if (isModel(entity)) {
|
|
100
|
+
return WandzEntities.MODEL;
|
|
101
|
+
}
|
|
102
|
+
return WandzEntities.AI_FEATURE;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export const getEntityDisplayName = (entity: IEntity): string => {
|
|
106
|
+
if (isAiFeature(entity)) {
|
|
107
|
+
return entity.displayName;
|
|
108
|
+
} else if (isAudience(entity)) {
|
|
109
|
+
return entity.displayName;
|
|
110
|
+
} else if (isModel(entity)) {
|
|
111
|
+
return entity.name;
|
|
112
|
+
}
|
|
113
|
+
return '';
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
/** Adaptive search */
|
|
117
|
+
export const getAdaptiveSearchDataByField = (search: IAdaptiveSearch, label: AdaptiveSearchReplaceLabels): any => {
|
|
118
|
+
switch (label) {
|
|
119
|
+
case AdaptiveSearchReplaceLabels.CONTENTS:
|
|
120
|
+
return search.whatToShow.contents;
|
|
121
|
+
case AdaptiveSearchReplaceLabels.PRIORITIZE_BY:
|
|
122
|
+
return search.whatToShow.priority;
|
|
123
|
+
case AdaptiveSearchReplaceLabels.SUGGESTIONS_MAX_QUANTITY:
|
|
124
|
+
return search.whatToShow.suggestionsAmount;
|
|
125
|
+
case AdaptiveSearchReplaceLabels.TEST_GROUP_SIZE:
|
|
126
|
+
return search.testGroupSize;
|
|
127
|
+
case AdaptiveSearchReplaceLabels.NUM_CHARACTERS_STOP_SHOWING:
|
|
128
|
+
return search.typedCharactersToStopShowing;
|
|
129
|
+
case AdaptiveSearchReplaceLabels.ADD_ADAPTIVE_URL_PARAM:
|
|
130
|
+
return search.addUrlParam;
|
|
131
|
+
}
|
|
132
|
+
};
|
package/src/cache.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const cacheKeyBuilder: (cacheKey: string, identifiers: any) => string;
|
package/src/cache.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.cacheKeyBuilder = void 0;
|
|
4
|
-
const cacheKeyBuilder = (cacheKey, identifiers) => `${cacheKey}${JSON.stringify(identifiers)}`;
|
|
5
|
-
exports.cacheKeyBuilder = cacheKeyBuilder;
|
|
6
|
-
//# sourceMappingURL=cache.js.map
|
package/src/cache.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../../libs/utils/src/cache.ts"],"names":[],"mappings":";;;AAAO,MAAM,eAAe,GAAG,CAAC,QAAgB,EAAE,WAAgB,EAAU,EAAE,CAAC,GAAG,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,CAAC;AAA9G,QAAA,eAAe,mBAA+F"}
|
package/src/common.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export declare const fakeDelay: (milliSec: number) => Promise<unknown>;
|
|
2
|
-
export declare const convertCamelCaseToUnderscore: (term: string) => string;
|
|
3
|
-
export declare const convertUnderscoreToCamelCase: (underscoreString: string) => string;
|
|
4
|
-
export declare const convertUnderscoreToCamelCaseObj: (obj: Record<string, any>) => Record<string, any>;
|
|
5
|
-
export declare const convertCamelCaseToUnderscoreObj: (obj: Record<string, any>) => Record<string, any>;
|
|
6
|
-
export declare const kebabToDisplayName: (kebabCase: string) => string;
|
|
7
|
-
export declare const stringifyWithSingleQuotes: (arr: any[]) => string;
|
|
8
|
-
export declare const upperCaseFirstChar: (word: string) => string;
|
|
9
|
-
export declare const upperCaseFirstCharOfEachWord: (str: string) => string;
|
|
10
|
-
export declare const upperCaseFirstCharOfEachWordSplitBySpace: (str: string) => string;
|
|
11
|
-
export declare const jsonToConsistentString: (jsonObj: any) => string;
|
|
12
|
-
export declare const booleanStringToBoolean: (value: string) => value is "true";
|
|
13
|
-
export declare const booleanStringToNumber: (value: string) => 1 | 0;
|
|
14
|
-
export declare const normalizeSfResponseObjKeys: (obj: Record<string, any>) => {
|
|
15
|
-
[k: string]: any;
|
|
16
|
-
};
|