Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added custom storage option #452

Merged
merged 3 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## X.X.X
- You can now provide custom storage methods to the SDK

## 23.6.3
- You can now add segmentation while presenting a widget with 'present_feedback_widget'

Expand Down
15 changes: 14 additions & 1 deletion examples/worker.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
importScripts("../lib/countly.js");

const STORE={}; // in-memory storage for worker

Countly.init({
app_key: "YOUR_APP_KEY",
url: "https://try.count.ly",
debug: true
debug: true,
storage: {
getItem: function (key) {
return STORE[key];
},
setItem: function (key, value) {
STORE[key] = value;
},
removeItem: function (key) {
delete STORE[key];
}
}
});

onmessage = function (e) {
Expand Down
52 changes: 37 additions & 15 deletions lib/countly.js
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@
this.ignore_visitor = getConfig("ignore_visitor", ob, false);
this.require_consent = getConfig("require_consent", ob, false);
this.track_domains = !isBrowser ? undefined : getConfig("track_domains", ob, true);
this.storage = !isBrowser ? "none" : getConfig("storage", ob, "default");
this.storage = getConfig("storage", ob, "default");
this.enableOrientationTracking = !isBrowser ? undefined : getConfig("enable_orientation_tracking", ob, true);
this.maxKeyLength = getConfig("max_key_length", ob, configurationDefaultValues.MAX_KEY_LENGTH);
this.maxValueSize = getConfig("max_value_size", ob, configurationDefaultValues.MAX_VALUE_SIZE);
Expand Down Expand Up @@ -3915,7 +3915,7 @@
log(logLevelEnums.DEBUG, "Processing request", params);
setValueInStorage("cly_queue", requestQueue, true);
if (!self.test_mode) {
sendXmlHttpRequest("send_request_queue", self.url + apiPath, params, function(err, parameters) {

Check warning on line 3918 in lib/countly.js

View workflow job for this annotation

GitHub Actions / build-and-test (12.x)

'parameters' is defined but never used

Check warning on line 3918 in lib/countly.js

View workflow job for this annotation

GitHub Actions / build-and-test (14.x)

'parameters' is defined but never used

Check warning on line 3918 in lib/countly.js

View workflow job for this annotation

GitHub Actions / build-and-test (16.x)

'parameters' is defined but never used
log(logLevelEnums.DEBUG, "Request Finished", parameters, err);
if (err) {
failTimeout = getTimestamp() + failTimeoutAmount;
Expand Down Expand Up @@ -4419,9 +4419,9 @@
* @returns {Varies} values stored for key
*/
function getValueFromStorage(key, useLocalStorage, useRawKey) {
// check if we should use storage at all
if (self.storage === "none") {
log(logLevelEnums.WARNING, "Storage is disabled. Value with key: " + key + " won't be retrieved");
// check if we should use storage at all. If in worker context but no storage is available, return early
if (self.storage === "none" || (typeof self.storage !== "object" && !isBrowser)) {
log(logLevelEnums.DEBUG, "Storage is disabled. Value with key: [" + key + "] won't be retrieved");
return;
}

Expand All @@ -4433,11 +4433,17 @@
}
}

var data;
// use dev provided storage if available
if (typeof self.storage === "object" && typeof self.storage.getItem === "function") {
data = self.storage.getItem(key);
return key.endsWith("cly_id") ? data : self.deserialize(data);
}

// developer set values takes priority
if (useLocalStorage === undefined) {
useLocalStorage = lsSupport;
}
var data;

// Get value
if (useLocalStorage) { // Native support
Expand Down Expand Up @@ -4465,8 +4471,8 @@
*/
function setValueInStorage(key, value, useLocalStorage, useRawKey) {
// check if we should use storage options at all
if (self.storage === "none") {
log(logLevelEnums.WARNING, "Storage is disabled. Value with key: " + key + " won't be stored");
if (self.storage === "none" || (typeof self.storage !== "object" && !isBrowser)) {
log(logLevelEnums.DEBUG, "Storage is disabled. Value with key: " + key + " won't be stored");
return;
}

Expand All @@ -4478,12 +4484,18 @@
}
}

// developer set values takes priority
if (useLocalStorage === undefined) {
useLocalStorage = lsSupport;
}

if (typeof value !== "undefined" && value !== null) {
// use dev provided storage if available
if (typeof self.storage === "object" && typeof self.storage.setItem === "function") {
self.storage.setItem(key, value);
return;
}

// developer set values takes priority
if (useLocalStorage === undefined) {
useLocalStorage = lsSupport;
}

value = self.serialize(value);
// Set the store
if (useLocalStorage) { // Native support
Expand All @@ -4504,8 +4516,8 @@
*/
function removeValueFromStorage(key, useLocalStorage, useRawKey) {
// check if we should use storage options at all
if (self.storage === "none") {
log(logLevelEnums.WARNING, "Storage is disabled. Value with key: " + key + " won't be removed");
if (self.storage === "none" || (typeof self.storage !== "object" && !isBrowser)) {
log(logLevelEnums.DEBUG, "Storage is disabled. Value with key: " + key + " won't be removed");
return;
}

Expand All @@ -4517,6 +4529,12 @@
}
}

// use dev provided storage if available
if (typeof self.storage === "object" && typeof self.storage.removeItem === "function") {
self.storage.removeItem(key);
return;
}

// developer set values takes priority
if (useLocalStorage === undefined) {
useLocalStorage = lsSupport;
Expand Down Expand Up @@ -4837,7 +4855,11 @@
* @param {string} conf.metrics._browser_version - browser version
* @param {string} conf.metrics._ua - user agent string
* @param {Object=} [conf.headers={}] - Object to override or add headers to all SDK requests
* @param {string=} [conf.storage=default] - What type of storage to use, by default uses local storage and would fallback to cookies, but you can set values "localstorage" or "cookies" to force only specific storage, or use "none" to not use any storage and keep everything in memory
* @param {string | Object} [conf.storage=default] - What type of storage to use, by default uses local storage and would fallback to cookies, but you can set values "localstorage" or "cookies" to force only specific storage, or use "none" to not use any storage and keep everything in memory
* If developer wants to provide their own storage methods they can provide an object with methods getItem(key:string), setItem(key:string, value:string), removeItem(key:string)
* SDK would hand the key and value params to use these methods to store and retrieve data.
* Here key is the key of the data to be stored and value is the value of the data to be stored.
* This can be used in scenarios where a clear storage method is not available, like in web workers
* @returns {Object} countly tracker instance
* @example
* Countly.init({
Expand Down
Loading