@lowentry/utils 1.7.1 → 1.9.1
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/LeUtils.js +251 -1
- package/index.js +2 -4
- package/package.json +2 -1
package/LeUtils.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import FastDeepEqual from 'fast-deep-equal';
|
|
2
|
-
import
|
|
2
|
+
import CloneDeep from 'clone-deep';
|
|
3
|
+
import {ISSET, IS_OBJECT, IS_ARRAY, STRING, INT_LAX, FLOAT_LAX, INT_LAX_ANY, FLOAT_LAX_ANY} from './LeTypes.js';
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -2765,4 +2766,253 @@ export const LeUtils = {
|
|
|
2765
2766
|
}
|
|
2766
2767
|
return transactionalValue.changes[transactionalValue.changes.length - 1].value;
|
|
2767
2768
|
},
|
|
2769
|
+
|
|
2770
|
+
/**
|
|
2771
|
+
* Creates a worker thread. Workers have to be stored at /workers/{workerName}.worker.js for this to work.
|
|
2772
|
+
*
|
|
2773
|
+
* Example of a worker file:
|
|
2774
|
+
*
|
|
2775
|
+
* ```js
|
|
2776
|
+
* onmessage = (message) =>
|
|
2777
|
+
* {
|
|
2778
|
+
* postMessage({
|
|
2779
|
+
* ...message.data,
|
|
2780
|
+
* results: ['...some expensive calculation involving message.data...'],
|
|
2781
|
+
* });
|
|
2782
|
+
* };
|
|
2783
|
+
* ```
|
|
2784
|
+
*
|
|
2785
|
+
* Usage:
|
|
2786
|
+
*
|
|
2787
|
+
* ```js
|
|
2788
|
+
* const {results} = await (async () =>
|
|
2789
|
+
* {
|
|
2790
|
+
* try
|
|
2791
|
+
* {
|
|
2792
|
+
* return await LeUtils.sendWorkerMessage('my-worker', {someData:[1, 2, 3, 4, 5]});
|
|
2793
|
+
* }
|
|
2794
|
+
* catch(error)
|
|
2795
|
+
* {
|
|
2796
|
+
* console.error('MyWorker: ', error);
|
|
2797
|
+
* return {results:[]};
|
|
2798
|
+
* }
|
|
2799
|
+
* })();
|
|
2800
|
+
* ```
|
|
2801
|
+
*
|
|
2802
|
+
* or, if you want more control over the number of threads you have (the above example will only create 1 thread per worker):
|
|
2803
|
+
*
|
|
2804
|
+
* ```js
|
|
2805
|
+
* const myWorker1 = LeUtils.createWorkerThread('my-worker'); // creates a thread, you can create multiple worker threads of the same worker, to run multiple instances in parallel
|
|
2806
|
+
* const myWorker2 = LeUtils.createWorkerThread('my-worker'); // same worker, another thread
|
|
2807
|
+
* const {results} = await (async () =>
|
|
2808
|
+
* {
|
|
2809
|
+
* try
|
|
2810
|
+
* {
|
|
2811
|
+
* return await myWorker1.sendMessage({someData:[1, 2, 3, 4, 5]});
|
|
2812
|
+
* }
|
|
2813
|
+
* catch(error)
|
|
2814
|
+
* {
|
|
2815
|
+
* console.error('MyWorker: ', error);
|
|
2816
|
+
* return {results:[]};
|
|
2817
|
+
* }
|
|
2818
|
+
* })();
|
|
2819
|
+
* ```
|
|
2820
|
+
*
|
|
2821
|
+
* @param {string} name
|
|
2822
|
+
* @returns {{worker: Worker, sendMessage: function(Object, {timeout: number|undefined}|undefined): Promise<Object>}}
|
|
2823
|
+
*/
|
|
2824
|
+
createWorkerThread:
|
|
2825
|
+
(name) =>
|
|
2826
|
+
{
|
|
2827
|
+
const worker = new Worker('/workers/' + name + '.worker.js');
|
|
2828
|
+
let listeners = {};
|
|
2829
|
+
|
|
2830
|
+
const addListener = (id, callback) =>
|
|
2831
|
+
{
|
|
2832
|
+
listeners[id] = callback;
|
|
2833
|
+
};
|
|
2834
|
+
|
|
2835
|
+
const removeListener = (id) =>
|
|
2836
|
+
{
|
|
2837
|
+
delete listeners[id];
|
|
2838
|
+
};
|
|
2839
|
+
|
|
2840
|
+
const sendMessage = (data, options) =>
|
|
2841
|
+
{
|
|
2842
|
+
return new Promise((resolve, reject) =>
|
|
2843
|
+
{
|
|
2844
|
+
const id = LeUtils.uniqueId();
|
|
2845
|
+
addListener(id, resolve);
|
|
2846
|
+
setTimeout(() =>
|
|
2847
|
+
{
|
|
2848
|
+
removeListener(id);
|
|
2849
|
+
reject('timeout');
|
|
2850
|
+
}, options?.timeout ?? 10000);
|
|
2851
|
+
|
|
2852
|
+
worker.postMessage({
|
|
2853
|
+
id,
|
|
2854
|
+
...data,
|
|
2855
|
+
});
|
|
2856
|
+
});
|
|
2857
|
+
};
|
|
2858
|
+
|
|
2859
|
+
worker.onerror = (error) =>
|
|
2860
|
+
{
|
|
2861
|
+
console.error('Worker ' + name + ':', error);
|
|
2862
|
+
};
|
|
2863
|
+
worker.onmessage = (message) =>
|
|
2864
|
+
{
|
|
2865
|
+
const data = message.data;
|
|
2866
|
+
if(data?.id)
|
|
2867
|
+
{
|
|
2868
|
+
const callback = listeners[data.id];
|
|
2869
|
+
if(callback)
|
|
2870
|
+
{
|
|
2871
|
+
removeListener(data.id);
|
|
2872
|
+
callback(data);
|
|
2873
|
+
}
|
|
2874
|
+
}
|
|
2875
|
+
};
|
|
2876
|
+
|
|
2877
|
+
return {worker, sendMessage};
|
|
2878
|
+
},
|
|
2879
|
+
|
|
2880
|
+
/**
|
|
2881
|
+
* Sends a message to the given worker. Creates a worker thread for this worker if it doesn't exist yet.
|
|
2882
|
+
*
|
|
2883
|
+
* See {@link LeUtils#createWorkerThread} for more info on how to use workers.
|
|
2884
|
+
*
|
|
2885
|
+
* @param {string} workerName
|
|
2886
|
+
* @param {Object} data
|
|
2887
|
+
* @param {{timeout: number|undefined}} [options]
|
|
2888
|
+
* @returns {Promise<Object>}
|
|
2889
|
+
*/
|
|
2890
|
+
sendWorkerMessage:
|
|
2891
|
+
(() =>
|
|
2892
|
+
{
|
|
2893
|
+
const workers = {};
|
|
2894
|
+
return (workerName, data, options) =>
|
|
2895
|
+
{
|
|
2896
|
+
if(!workers[workerName])
|
|
2897
|
+
{
|
|
2898
|
+
workers[workerName] = LeUtils.createWorkerThread(workerName);
|
|
2899
|
+
}
|
|
2900
|
+
return workers[workerName].sendMessage(data, options);
|
|
2901
|
+
};
|
|
2902
|
+
})(),
|
|
2903
|
+
|
|
2904
|
+
/**
|
|
2905
|
+
* Returns a deep copy of the given value.
|
|
2906
|
+
*
|
|
2907
|
+
* @param {*} value
|
|
2908
|
+
* @returns {*}
|
|
2909
|
+
*/
|
|
2910
|
+
clone:
|
|
2911
|
+
(value) => CloneDeep(value, true),
|
|
2912
|
+
|
|
2913
|
+
/**
|
|
2914
|
+
* Purges the given email address, returning an empty string if it's invalid.
|
|
2915
|
+
*
|
|
2916
|
+
* @param {string} email
|
|
2917
|
+
* @returns {string}
|
|
2918
|
+
*/
|
|
2919
|
+
purgeEmail:
|
|
2920
|
+
(email) =>
|
|
2921
|
+
{
|
|
2922
|
+
email = STRING(email).trim().toLowerCase().replace(/\s/g, '');
|
|
2923
|
+
if(!email.includes('@') || !email.includes('.'))
|
|
2924
|
+
{
|
|
2925
|
+
return '';
|
|
2926
|
+
}
|
|
2927
|
+
return email;
|
|
2928
|
+
},
|
|
2929
|
+
|
|
2930
|
+
/**
|
|
2931
|
+
* Returns true if the focus is effectively clear, meaning that the user is not typing in an input field.
|
|
2932
|
+
*
|
|
2933
|
+
* @returns {boolean}
|
|
2934
|
+
*/
|
|
2935
|
+
isFocusClear:(() =>
|
|
2936
|
+
{
|
|
2937
|
+
const inputTypes = ['text', 'search', 'email', 'number', 'password', 'tel', 'time', 'url', 'week', 'month', 'date', 'datetime-local'];
|
|
2938
|
+
return () => !((document?.activeElement?.tagName?.toLowerCase() === 'input') && inputTypes.includes(document?.activeElement?.type?.toLowerCase()));
|
|
2939
|
+
})(),
|
|
2940
|
+
|
|
2941
|
+
/**
|
|
2942
|
+
* Returns the user's locale. Returns 'en-US' if it can't be determined.
|
|
2943
|
+
*
|
|
2944
|
+
* @returns {string}
|
|
2945
|
+
*/
|
|
2946
|
+
getUserLocale:(() =>
|
|
2947
|
+
{
|
|
2948
|
+
let userLocale = null;
|
|
2949
|
+
return () =>
|
|
2950
|
+
{
|
|
2951
|
+
if(userLocale === null)
|
|
2952
|
+
{
|
|
2953
|
+
userLocale = (() =>
|
|
2954
|
+
{
|
|
2955
|
+
if(typeof window === 'undefined')
|
|
2956
|
+
{
|
|
2957
|
+
return 'en-US';
|
|
2958
|
+
}
|
|
2959
|
+
let locales = window.navigator.languages;
|
|
2960
|
+
if(!IS_ARRAY(locales) || (locales.length <= 0))
|
|
2961
|
+
{
|
|
2962
|
+
return 'en-US';
|
|
2963
|
+
}
|
|
2964
|
+
locales = locales.filter(locale => ((typeof locale === 'string') && locale.includes('-') && (locale.toLowerCase() !== 'en-us')));
|
|
2965
|
+
if(locales.length <= 0)
|
|
2966
|
+
{
|
|
2967
|
+
return 'en-US';
|
|
2968
|
+
}
|
|
2969
|
+
const localesNoEnglish = locales.filter(locale => !locale.toLowerCase().startsWith('en-'));
|
|
2970
|
+
if(localesNoEnglish.length <= 0)
|
|
2971
|
+
{
|
|
2972
|
+
return locales[0];
|
|
2973
|
+
}
|
|
2974
|
+
return localesNoEnglish[0];
|
|
2975
|
+
})();
|
|
2976
|
+
}
|
|
2977
|
+
return userLocale;
|
|
2978
|
+
};
|
|
2979
|
+
})(),
|
|
2980
|
+
|
|
2981
|
+
/**
|
|
2982
|
+
* Returns the user's locale date format. Always returns YYYY MM DD, with the character in between depending on the user's locale. Returns 'YYYY/MM/DD' if the user's locale can't be determined.
|
|
2983
|
+
*
|
|
2984
|
+
* @returns {string}
|
|
2985
|
+
*/
|
|
2986
|
+
getUserLocaleDateFormat:(() =>
|
|
2987
|
+
{
|
|
2988
|
+
let userLocaleDateFormat = null;
|
|
2989
|
+
return () =>
|
|
2990
|
+
{
|
|
2991
|
+
if(userLocaleDateFormat === null)
|
|
2992
|
+
{
|
|
2993
|
+
userLocaleDateFormat = (() =>
|
|
2994
|
+
{
|
|
2995
|
+
let char = '/';
|
|
2996
|
+
if((typeof window !== 'undefined') && (typeof Intl !== 'undefined') && (typeof Intl.DateTimeFormat !== 'undefined'))
|
|
2997
|
+
{
|
|
2998
|
+
const formattedDate = new Intl.DateTimeFormat(LeUtils.getUserLocale()).format();
|
|
2999
|
+
if(formattedDate.includes('-'))
|
|
3000
|
+
{
|
|
3001
|
+
char = '-';
|
|
3002
|
+
}
|
|
3003
|
+
else if(formattedDate.includes('. '))
|
|
3004
|
+
{
|
|
3005
|
+
char = '.';
|
|
3006
|
+
}
|
|
3007
|
+
else if(formattedDate.includes('.'))
|
|
3008
|
+
{
|
|
3009
|
+
char = '.';
|
|
3010
|
+
}
|
|
3011
|
+
}
|
|
3012
|
+
return 'YYYY' + char + 'MM' + char + 'DD';
|
|
3013
|
+
})();
|
|
3014
|
+
}
|
|
3015
|
+
return userLocaleDateFormat;
|
|
3016
|
+
};
|
|
3017
|
+
})(),
|
|
2768
3018
|
};
|
package/index.js
CHANGED
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export {LeUtils, ISSET, IS_ARRAY, ARRAY, IS_OBJECT, OBJECT, STRING, STRING_ANY, INT, INT_ANY, FLOAT, FLOAT_ANY, INT_LAX, INT_LAX_ANY, FLOAT_LAX, FLOAT_LAX_ANY};
|
|
1
|
+
export {LeUtils} from './LeUtils.js';
|
|
2
|
+
export {ISSET, IS_ARRAY, ARRAY, IS_OBJECT, OBJECT, STRING, STRING_ANY, INT, INT_ANY, FLOAT, FLOAT_ANY, INT_LAX, INT_LAX_ANY, FLOAT_LAX, FLOAT_LAX_ANY} from './LeTypes.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lowentry/utils",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Provides utilities for general JavaScript development.",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"test": "node --check index.js"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
+
"clone-deep": "^4",
|
|
23
24
|
"fast-deep-equal": "^3"
|
|
24
25
|
}
|
|
25
26
|
}
|