noibu-react-native 0.0.1 → 0.0.3
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/README.md +9 -7
- package/dist/api/clientConfig.js +50 -48
- package/dist/api/helpCode.js +3 -3
- package/dist/api/inputManager.js +5 -5
- package/dist/api/metroplexSocket.js +31 -43
- package/dist/api/storedMetrics.js +18 -22
- package/dist/api/storedPageVisit.js +27 -29
- package/dist/constants.d.ts +2 -2
- package/dist/constants.js +7 -48
- package/dist/entry/index.d.ts +8 -1
- package/dist/entry/index.js +8 -2
- package/dist/entry/init.js +6 -5
- package/dist/monitors/clickMonitor.js +1 -2
- package/dist/monitors/elementMonitor.js +4 -1
- package/dist/monitors/errorMonitor.d.ts +25 -0
- package/dist/monitors/errorMonitor.js +109 -262
- package/dist/monitors/httpDataBundler.js +11 -12
- package/dist/monitors/inputMonitor.js +4 -1
- package/dist/monitors/locationChangeMonitor.js +4 -16
- package/dist/monitors/pageMonitor.js +4 -1
- package/dist/monitors/requestMonitor.js +5 -19
- package/dist/pageVisit/pageVisit.js +3 -1
- package/dist/pageVisit/pageVisitEventError/blacklistedDomains.js +9 -0
- package/dist/pageVisit/pageVisitEventError/pageVisitEventError.js +9 -14
- package/dist/pageVisit/pageVisitEventHTTP/pageVisitEventHTTP.js +3 -14
- package/dist/storage/rnStorageProvider.d.ts +23 -0
- package/dist/storage/rnStorageProvider.js +23 -52
- package/dist/storage/storage.d.ts +38 -0
- package/dist/storage/storage.js +69 -104
- package/dist/storage/storageProvider.d.ts +25 -0
- package/dist/storage/storageProvider.js +38 -71
- package/dist/utils/function.js +80 -53
- package/dist/utils/performance.js +0 -7
- package/dist/utils/stacktrace-parser.d.ts +9 -0
- package/dist/utils/stacktrace-parser.js +156 -0
- package/package.json +4 -4
- package/dist/storage/localStorageProvider.js +0 -23
- package/dist/storage/sessionStorageProvider.js +0 -23
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { isValidURL, getOnURL, getJSStack, stringifyJSON, getMaxSubstringAllowed } from '../../utils/function.js';
|
|
1
|
+
import { isValidURL, getOnURL, getProperGlobalUrl, getJSStack, stringifyJSON, getMaxSubstringAllowed } from '../../utils/function.js';
|
|
2
2
|
import { EVENT_ERROR_TYPE, URL_ATT_NAME, ERROR_EVENT_TYPE, ERROR_EVENT_ERROR_TYPE, CUSTOM_ERROR_EVENT_TYPE, ERROR_EVENT_UNHANDLED_REJECTION_TYPE, ERROR_LOG_EVENT_ERROR_TYPE, FETCH_EXCEPTION_ERROR_TYPE, WRAPPED_EXCEPTION_ERROR_TYPE, GQL_ERROR_TYPE, RESPONSE_ERROR_TYPE, XML_HTTP_REQUEST_ERROR_TYPE, ERROR_SOURCE_ATT_NAME, TYPE_ATT_NAME, JS_EVENT_TYPE, JS_ERROR_ATT_NAME, JS_STACK_FRAMES_ATT_NAME, JS_STACK_FILE_ATT_NAME, JS_STACK_METHOD_ATT_NAME, SEVERITY_ERROR, JS_STACK_MESSAGE_ATT_NAME, HTTP_EVENT_TYPE, NOIBU_INPUT_URLS, HTTP_CODE_ATT_NAME, PV_SEQ_ATT_NAME, GQL_EVENT_TYPE, GQL_ERROR_ATT_NAME } from '../../constants.js';
|
|
3
|
+
import blacklisedDomains from './blacklistedDomains.js';
|
|
3
4
|
import ClientConfig from '../../api/clientConfig.js';
|
|
4
5
|
import { InputMonitor } from '../../monitors/inputMonitor.js';
|
|
5
6
|
import StoredMetrics from '../../api/storedMetrics.js';
|
|
@@ -68,7 +69,7 @@ function getPVErrorFromXMLHttpRequest(errPayload, httpDataSeqNum) {
|
|
|
68
69
|
*/
|
|
69
70
|
function getPVErrorFromErrorEvent(errPayload) {
|
|
70
71
|
return {
|
|
71
|
-
[URL_ATT_NAME]: getOnURL(errPayload.filename ||
|
|
72
|
+
[URL_ATT_NAME]: getOnURL(errPayload.filename || getProperGlobalUrl()), // todo implement navigation
|
|
72
73
|
[TYPE_ATT_NAME]: JS_EVENT_TYPE,
|
|
73
74
|
[JS_ERROR_ATT_NAME]: getJSStack(errPayload.error),
|
|
74
75
|
};
|
|
@@ -80,9 +81,7 @@ function getPVErrorFromErrorEvent(errPayload) {
|
|
|
80
81
|
function getPVErrorFromErrorLog(errPayload) {
|
|
81
82
|
return {
|
|
82
83
|
// default to window url
|
|
83
|
-
[URL_ATT_NAME]: getOnURL(
|
|
84
|
-
(window.location && window.location.href) || 'http://localhost',
|
|
85
|
-
),
|
|
84
|
+
[URL_ATT_NAME]: getOnURL(getProperGlobalUrl()), // todo should be current navigation
|
|
86
85
|
[TYPE_ATT_NAME]: JS_EVENT_TYPE,
|
|
87
86
|
[JS_ERROR_ATT_NAME]: getJSStack(errPayload),
|
|
88
87
|
};
|
|
@@ -270,7 +269,7 @@ function isCollectError(pvError) {
|
|
|
270
269
|
/** Saves the error to the ErrorQueue
|
|
271
270
|
* @param {} type
|
|
272
271
|
* @param {} payload
|
|
273
|
-
* @param {} httpDataSeqNum
|
|
272
|
+
* @param {} [httpDataSeqNum]
|
|
274
273
|
*/
|
|
275
274
|
function saveErrorToPagevisit(type, payload, httpDataSeqNum) {
|
|
276
275
|
// We do not want to process errors events as errors (yet)
|
|
@@ -288,16 +287,12 @@ function saveErrorToPagevisit(type, payload, httpDataSeqNum) {
|
|
|
288
287
|
|
|
289
288
|
// We need valid URLs in order to check their blacklist status
|
|
290
289
|
if (isValidURL(currErrURL)) {
|
|
291
|
-
new URL(currErrURL);
|
|
290
|
+
const urlOb = new URL(currErrURL);
|
|
292
291
|
|
|
293
|
-
// if the domain is blacklisted
|
|
294
|
-
|
|
295
|
-
/* if ( // todo we don't support hostname on react native yet
|
|
296
|
-
urlOb.hostname in blacklisedDomains ||
|
|
297
|
-
!urlOb.protocol.startsWith('http')
|
|
298
|
-
) {
|
|
292
|
+
// if the domain is blacklisted we drop the error
|
|
293
|
+
if (urlOb.hostname in blacklisedDomains) {
|
|
299
294
|
return;
|
|
300
|
-
}
|
|
295
|
+
}
|
|
301
296
|
}
|
|
302
297
|
|
|
303
298
|
if (isCollectError(pvError)) {
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { getMaxSubstringAllowed, asString
|
|
1
|
+
import { getMaxSubstringAllowed, asString } from '../../utils/function.js';
|
|
2
2
|
import { timestampWrapper } from '../../utils/date.js';
|
|
3
3
|
import { InputMonitor } from '../../monitors/inputMonitor.js';
|
|
4
|
-
import { HTTP_METHOD_ATT_NAME, MAX_HTTP_DATA_EVENT_COUNT, PV_SEQ_ATT_NAME, HTTP_DATA_METROPLEX_TYPE,
|
|
4
|
+
import { HTTP_METHOD_ATT_NAME, MAX_HTTP_DATA_EVENT_COUNT, PV_SEQ_ATT_NAME, HTTP_DATA_METROPLEX_TYPE, HTTP_EVENT_TYPE, PAGE_VISIT_HTTP_DATA_ATT_NAME } from '../../constants.js';
|
|
5
5
|
import { PageVisit } from '../pageVisit.js';
|
|
6
6
|
import StoredMetrics from '../../api/storedMetrics.js';
|
|
7
7
|
import MetroplexSocket from '../../api/metroplexSocket.js';
|
|
8
|
-
import ClientConfig from '../../api/clientConfig.js';
|
|
9
8
|
|
|
10
9
|
/** @module PageVisitEventHTTP */
|
|
11
10
|
|
|
@@ -79,16 +78,6 @@ class PageVisitEventHTTP {
|
|
|
79
78
|
HTTP_DATA_METROPLEX_TYPE,
|
|
80
79
|
metroplexMsg,
|
|
81
80
|
);
|
|
82
|
-
|
|
83
|
-
if (getProperGlobalUrl().includes('checkout.mec.ca')) {
|
|
84
|
-
ClientConfig.getInstance().postNoibuErrorAndOptionallyDisableClient(
|
|
85
|
-
`Sending PVH to Metro: ${JSON.stringify(this.httpData)}
|
|
86
|
-
|
|
87
|
-
Whitelisted URLs: ${NOIBUJS_CONFIG()[HTTP_DATA_PAYLOAD_URL_REGEXES_FLAG_NAME]}`,
|
|
88
|
-
false,
|
|
89
|
-
SEVERITY_ERROR,
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
81
|
} else {
|
|
93
82
|
// have collected more than the max number of http requests for this
|
|
94
83
|
// page visit, so increment the over request limit count
|
|
@@ -96,7 +85,7 @@ Whitelisted URLs: ${NOIBUJS_CONFIG()[HTTP_DATA_PAYLOAD_URL_REGEXES_FLAG_NAME]}`,
|
|
|
96
85
|
}
|
|
97
86
|
}
|
|
98
87
|
// if this was an error, send immediately so we don't lose it
|
|
99
|
-
if (isHttpCodeFailure(this.
|
|
88
|
+
if (isHttpCodeFailure(this.httpEvent.code)) {
|
|
100
89
|
PageVisit.getInstance().addPageVisitEvent(
|
|
101
90
|
{
|
|
102
91
|
event: this.httpEvent,
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import StorageProvider from './storageProvider';
|
|
2
|
+
/**
|
|
3
|
+
* React native storage provider implementation
|
|
4
|
+
*/
|
|
5
|
+
export default class RNStorageProvider extends StorageProvider {
|
|
6
|
+
/**
|
|
7
|
+
* Creates new instance
|
|
8
|
+
*/
|
|
9
|
+
constructor();
|
|
10
|
+
/**
|
|
11
|
+
* Checks if storage is available
|
|
12
|
+
* @returns {Object}
|
|
13
|
+
*/
|
|
14
|
+
static isAvailable(): Promise<{
|
|
15
|
+
result: boolean;
|
|
16
|
+
error: unknown;
|
|
17
|
+
}>;
|
|
18
|
+
/**
|
|
19
|
+
* Calculates used scape
|
|
20
|
+
* @returns {Number}
|
|
21
|
+
*/
|
|
22
|
+
calculateUsedSize(): Promise<number>;
|
|
23
|
+
}
|
|
@@ -1,62 +1,33 @@
|
|
|
1
|
+
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
1
2
|
import StorageProvider from './storageProvider.js';
|
|
2
3
|
|
|
3
4
|
// eslint-disable-next-line max-classes-per-file
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* React native storage implementation: temporary
|
|
7
|
-
*/
|
|
8
|
-
class RNStorageTmp {
|
|
9
|
-
/** */
|
|
10
|
-
constructor() {
|
|
11
|
-
this._map = new Map();
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* @param key
|
|
16
|
-
* @returns {string}
|
|
17
|
-
*/
|
|
18
|
-
getItem(key) {
|
|
19
|
-
return this._map.get(key);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* @param key
|
|
24
|
-
* @param value
|
|
25
|
-
* @returns {Map<string, string>}
|
|
26
|
-
*/
|
|
27
|
-
setItem(key, value) {
|
|
28
|
-
return this._map.set(key, value);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* @param key
|
|
33
|
-
* @returns {boolean}
|
|
34
|
-
*/
|
|
35
|
-
removeItem(key) {
|
|
36
|
-
return this._map.delete(key);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
5
|
/**
|
|
41
6
|
* React native storage provider implementation
|
|
42
7
|
*/
|
|
43
8
|
class RNStorageProvider extends StorageProvider {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Creates new instance
|
|
11
|
+
*/
|
|
12
|
+
constructor() {
|
|
13
|
+
super(AsyncStorage);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Checks if storage is available
|
|
17
|
+
* @returns {Object}
|
|
18
|
+
*/
|
|
19
|
+
static isAvailable() {
|
|
20
|
+
return StorageProvider.isAvailable(() => AsyncStorage);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Calculates used scape
|
|
24
|
+
* @returns {Number}
|
|
25
|
+
*/
|
|
26
|
+
async calculateUsedSize() {
|
|
27
|
+
const keys = await AsyncStorage.getAllKeys();
|
|
28
|
+
const items = await AsyncStorage.multiGet(keys);
|
|
29
|
+
return items.reduce((sum, [key, item]) => sum + key.length + (item || '').length, 0);
|
|
30
|
+
}
|
|
60
31
|
}
|
|
61
32
|
|
|
62
33
|
export { RNStorageProvider as default };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Encapsulates storage api
|
|
3
|
+
*/
|
|
4
|
+
export default class Storage implements Noibu.Storage {
|
|
5
|
+
private readonly _isRNStorageAvailable;
|
|
6
|
+
private readonly _rnStorageError;
|
|
7
|
+
private static _instance;
|
|
8
|
+
private readonly _provider;
|
|
9
|
+
private readonly _type;
|
|
10
|
+
/**
|
|
11
|
+
* Creates new instance assessing available options
|
|
12
|
+
*/
|
|
13
|
+
constructor();
|
|
14
|
+
/**
|
|
15
|
+
* Singleton
|
|
16
|
+
* @returns {Storage}
|
|
17
|
+
*/
|
|
18
|
+
static getInstance(): Storage;
|
|
19
|
+
/** Checks if storage is available */
|
|
20
|
+
isAvailable(): Promise<boolean>;
|
|
21
|
+
/** Loads value from storage */
|
|
22
|
+
load<R = unknown>(key: string): Promise<R | null>;
|
|
23
|
+
/** Saves value to storage */
|
|
24
|
+
save(key: string, value: Noibu.StorageValue): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Removes value from storage
|
|
27
|
+
* @param {String} key
|
|
28
|
+
*/
|
|
29
|
+
remove(key: string): Promise<void>;
|
|
30
|
+
/** Calculates used scape */
|
|
31
|
+
calculateUsedSize(): Promise<number>;
|
|
32
|
+
/**
|
|
33
|
+
* Returns string indicating current provider type
|
|
34
|
+
* and availability for other storage types
|
|
35
|
+
* @returns {String}
|
|
36
|
+
*/
|
|
37
|
+
getDiagnoseInfo(): Promise<string>;
|
|
38
|
+
}
|
package/dist/storage/storage.js
CHANGED
|
@@ -1,119 +1,84 @@
|
|
|
1
|
-
import LocalStorageProvider from './localStorageProvider.js';
|
|
2
|
-
import SessionStorageProvider from './sessionStorageProvider.js';
|
|
3
1
|
import RNStorageProvider from './rnStorageProvider.js';
|
|
4
2
|
|
|
5
3
|
/**
|
|
6
4
|
* Encapsulates storage api
|
|
7
5
|
*/
|
|
8
6
|
class Storage {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if (this._isLocalStorageAvailable) {
|
|
26
|
-
this._provider = new LocalStorageProvider();
|
|
27
|
-
this._type = 'LocalStorage';
|
|
28
|
-
} else if (this._isSessionStorageAvailable) {
|
|
29
|
-
this._provider = new SessionStorageProvider();
|
|
30
|
-
this._type = 'SessionStorage';
|
|
31
|
-
} else if (this._isRNStorageAvailable) {
|
|
32
|
-
console.log('_isRNStorageAvailable');
|
|
33
|
-
this._provider = new RNStorageProvider();
|
|
34
|
-
this._type = 'RNStorage';
|
|
7
|
+
_isRNStorageAvailable;
|
|
8
|
+
_rnStorageError;
|
|
9
|
+
static _instance;
|
|
10
|
+
_provider;
|
|
11
|
+
_type;
|
|
12
|
+
/**
|
|
13
|
+
* Creates new instance assessing available options
|
|
14
|
+
*/
|
|
15
|
+
constructor() {
|
|
16
|
+
// todo replace with promise all if more storage available
|
|
17
|
+
const rnStorageAvailability = RNStorageProvider.isAvailable();
|
|
18
|
+
this._provider = rnStorageAvailability.then(({ result }) => result ? new RNStorageProvider() : null);
|
|
19
|
+
this._type = rnStorageAvailability.then(({ result }) => result ? 'RNStorage' : 'unavailable');
|
|
20
|
+
this._isRNStorageAvailable = rnStorageAvailability.then(({ result }) => result);
|
|
21
|
+
this._rnStorageError = rnStorageAvailability.then(({ error }) => error);
|
|
35
22
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Singleton
|
|
25
|
+
* @returns {Storage}
|
|
26
|
+
*/
|
|
27
|
+
static getInstance() {
|
|
28
|
+
if (!this._instance) {
|
|
29
|
+
this._instance = new Storage();
|
|
30
|
+
}
|
|
31
|
+
return this._instance;
|
|
45
32
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Checks if storage is available
|
|
51
|
-
* @returns {Boolean}
|
|
52
|
-
*/
|
|
53
|
-
isAvailable() {
|
|
54
|
-
return this._provider != null;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Loads value from storage
|
|
59
|
-
* @param {String} key
|
|
60
|
-
* @returns {String}
|
|
61
|
-
*/
|
|
62
|
-
load(key) {
|
|
63
|
-
if (this.isAvailable()) {
|
|
64
|
-
return this._provider.load(key);
|
|
33
|
+
/** Checks if storage is available */
|
|
34
|
+
async isAvailable() {
|
|
35
|
+
return (await this._provider) !== null;
|
|
65
36
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
*/
|
|
74
|
-
save(key, value) {
|
|
75
|
-
if (this.isAvailable()) {
|
|
76
|
-
this._provider.save(key, value);
|
|
37
|
+
/** Loads value from storage */
|
|
38
|
+
async load(key) {
|
|
39
|
+
const provider = await this._provider;
|
|
40
|
+
if (provider !== null) {
|
|
41
|
+
return provider.load(key);
|
|
42
|
+
}
|
|
43
|
+
return null;
|
|
77
44
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if (this.isAvailable()) {
|
|
86
|
-
this._provider.remove(key);
|
|
45
|
+
/** Saves value to storage */
|
|
46
|
+
async save(key, value) {
|
|
47
|
+
const provider = await this._provider;
|
|
48
|
+
if (provider !== null) {
|
|
49
|
+
return provider.save(key, value);
|
|
50
|
+
}
|
|
51
|
+
return undefined;
|
|
87
52
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Removes value from storage
|
|
55
|
+
* @param {String} key
|
|
56
|
+
*/
|
|
57
|
+
async remove(key) {
|
|
58
|
+
const provider = await this._provider;
|
|
59
|
+
if (provider !== null) {
|
|
60
|
+
return provider.remove(key);
|
|
61
|
+
}
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
/** Calculates used scape */
|
|
65
|
+
async calculateUsedSize() {
|
|
66
|
+
const provider = await this._provider;
|
|
67
|
+
if (provider !== null) {
|
|
68
|
+
return provider.calculateUsedSize();
|
|
69
|
+
}
|
|
70
|
+
return 0;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Returns string indicating current provider type
|
|
74
|
+
* and availability for other storage types
|
|
75
|
+
* @returns {String}
|
|
76
|
+
*/
|
|
77
|
+
async getDiagnoseInfo() {
|
|
78
|
+
return `storage provider: ${await this
|
|
79
|
+
._type} (rnStorage available: ${await this
|
|
80
|
+
._isRNStorageAvailable}, error: ${await this._rnStorageError})`;
|
|
97
81
|
}
|
|
98
|
-
return 0;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Returns string indicating current provider type
|
|
103
|
-
* and availability for other storage types
|
|
104
|
-
* @returns {String}
|
|
105
|
-
*/
|
|
106
|
-
getDiagnoseInfo() {
|
|
107
|
-
return (
|
|
108
|
-
`storage provider: ${this._type} ` +
|
|
109
|
-
`(localStorage available: ${this._isLocalStorageAvailable}, ` +
|
|
110
|
-
`error: ${this._localStorageError}) ` +
|
|
111
|
-
`(sessionStorage available: ${this._isSessionStorageAvailable}, ` +
|
|
112
|
-
`error: ${this._sessionStorageError})` +
|
|
113
|
-
`(rnStorage available: ${this._isRNStorageAvailable}, ` +
|
|
114
|
-
`error: ${this._rnStorageError})`
|
|
115
|
-
);
|
|
116
|
-
}
|
|
117
82
|
}
|
|
118
83
|
|
|
119
84
|
export { Storage as default };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base implementation for LocalStorage and SessionStorage
|
|
3
|
+
*/
|
|
4
|
+
export default abstract class StorageProvider {
|
|
5
|
+
_provider: Noibu.Provider;
|
|
6
|
+
/** Creates new instance based on provided provider type */
|
|
7
|
+
constructor(provider: Noibu.Provider);
|
|
8
|
+
/** Checks if provider is available */
|
|
9
|
+
static isAvailable(resolver: () => Noibu.Provider): Promise<{
|
|
10
|
+
result: boolean;
|
|
11
|
+
error: unknown;
|
|
12
|
+
}>;
|
|
13
|
+
/**
|
|
14
|
+
* Loads value from storage
|
|
15
|
+
*/
|
|
16
|
+
load<R = Noibu.StorageValue>(key: string): Promise<R | null>;
|
|
17
|
+
/** Saves value to storage */
|
|
18
|
+
save(key: string, value: Noibu.StorageValue): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Removes value from storage
|
|
21
|
+
* @param {String} key
|
|
22
|
+
*/
|
|
23
|
+
remove(key: string): Promise<void>;
|
|
24
|
+
abstract calculateUsedSize(): Promise<number>;
|
|
25
|
+
}
|
|
@@ -4,80 +4,47 @@ import { NOIBU_LOCAL_STORAGE_TEST_KEY } from '../constants.js';
|
|
|
4
4
|
* Base implementation for LocalStorage and SessionStorage
|
|
5
5
|
*/
|
|
6
6
|
class StorageProvider {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
constructor(provider) {
|
|
12
|
-
this._provider = provider;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Checks if provider is available
|
|
17
|
-
* @param {Function} function that returns storage instance
|
|
18
|
-
* @return {Object} { result: true|false, error: null|Error }
|
|
19
|
-
*/
|
|
20
|
-
static isAvailable(resolver) {
|
|
21
|
-
let result = true;
|
|
22
|
-
let error = null;
|
|
23
|
-
try {
|
|
24
|
-
// access to localStorage/sessionStorage may throw an error
|
|
25
|
-
// so use function to resolve it wrapped with try/catch
|
|
26
|
-
const provider = resolver();
|
|
27
|
-
console.log({ provider, providerset: provider.setItem });
|
|
28
|
-
provider.setItem(NOIBU_LOCAL_STORAGE_TEST_KEY, 0);
|
|
29
|
-
provider.removeItem(NOIBU_LOCAL_STORAGE_TEST_KEY);
|
|
30
|
-
} catch (e) {
|
|
31
|
-
result = false;
|
|
32
|
-
error = e;
|
|
7
|
+
_provider;
|
|
8
|
+
/** Creates new instance based on provided provider type */
|
|
9
|
+
constructor(provider) {
|
|
10
|
+
this._provider = provider;
|
|
33
11
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
load(key) {
|
|
43
|
-
return this._provider.getItem(key);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Saves value to storage
|
|
48
|
-
* @param {String} key
|
|
49
|
-
* @param {String} value
|
|
50
|
-
*/
|
|
51
|
-
save(key, value) {
|
|
52
|
-
this._provider.setItem(key, value);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Removes value from storage
|
|
57
|
-
* @param {String} key
|
|
58
|
-
*/
|
|
59
|
-
remove(key) {
|
|
60
|
-
this._provider.removeItem(key);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Calculates used scape
|
|
65
|
-
* @returns {Number}
|
|
66
|
-
*/
|
|
67
|
-
calculateUsedSize() {
|
|
68
|
-
let size = 0;
|
|
69
|
-
for (let i = 0; i < this._provider.length; i++) {
|
|
70
|
-
const key = this._provider.key(i);
|
|
71
|
-
if (key) {
|
|
72
|
-
size += key.length;
|
|
73
|
-
const value = this._provider.getItem(key);
|
|
74
|
-
if (value) {
|
|
75
|
-
size += value.length;
|
|
12
|
+
/** Checks if provider is available */
|
|
13
|
+
static async isAvailable(resolver) {
|
|
14
|
+
let result = true;
|
|
15
|
+
let error = null;
|
|
16
|
+
try {
|
|
17
|
+
const provider = resolver();
|
|
18
|
+
await provider.setItem(NOIBU_LOCAL_STORAGE_TEST_KEY, '0');
|
|
19
|
+
await provider.removeItem(NOIBU_LOCAL_STORAGE_TEST_KEY);
|
|
76
20
|
}
|
|
77
|
-
|
|
21
|
+
catch (e) {
|
|
22
|
+
result = false;
|
|
23
|
+
error = e;
|
|
24
|
+
}
|
|
25
|
+
return { result, error };
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Loads value from storage
|
|
29
|
+
*/
|
|
30
|
+
async load(key) {
|
|
31
|
+
const value = await this._provider.getItem(key);
|
|
32
|
+
if (value !== null) {
|
|
33
|
+
return value;
|
|
34
|
+
}
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
/** Saves value to storage */
|
|
38
|
+
save(key, value) {
|
|
39
|
+
return this._provider.setItem(key, `${value}`);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Removes value from storage
|
|
43
|
+
* @param {String} key
|
|
44
|
+
*/
|
|
45
|
+
remove(key) {
|
|
46
|
+
return this._provider.removeItem(key);
|
|
78
47
|
}
|
|
79
|
-
return size;
|
|
80
|
-
}
|
|
81
48
|
}
|
|
82
49
|
|
|
83
50
|
export { StorageProvider as default };
|