@formo/analytics 1.16.9 → 1.16.11

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.
Files changed (194) hide show
  1. package/dist/cjs/src/FormoAnalytics.d.ts +1 -3
  2. package/dist/cjs/src/FormoAnalytics.d.ts.map +1 -1
  3. package/dist/cjs/src/FormoAnalytics.js +21 -18
  4. package/dist/cjs/src/FormoAnalytics.js.map +1 -1
  5. package/dist/cjs/src/FormoAnalyticsProvider.d.ts.map +1 -1
  6. package/dist/cjs/src/FormoAnalyticsProvider.js +1 -0
  7. package/dist/cjs/src/FormoAnalyticsProvider.js.map +1 -1
  8. package/dist/cjs/src/constants/config.d.ts.map +1 -1
  9. package/dist/cjs/src/lib/event/EventFactory.d.ts +0 -3
  10. package/dist/cjs/src/lib/event/EventFactory.d.ts.map +1 -1
  11. package/dist/cjs/src/lib/event/EventFactory.js +5 -6
  12. package/dist/cjs/src/lib/event/EventFactory.js.map +1 -1
  13. package/dist/cjs/src/lib/event/EventManager.d.ts +1 -2
  14. package/dist/cjs/src/lib/event/EventManager.d.ts.map +1 -1
  15. package/dist/cjs/src/lib/event/EventManager.js +2 -2
  16. package/dist/cjs/src/lib/event/EventManager.js.map +1 -1
  17. package/dist/cjs/src/lib/event/utils.d.ts +2 -1
  18. package/dist/cjs/src/lib/event/utils.d.ts.map +1 -1
  19. package/dist/cjs/src/lib/event/utils.js +20 -2
  20. package/dist/cjs/src/lib/event/utils.js.map +1 -1
  21. package/dist/cjs/src/lib/ramda/internal/_curry1.d.ts.map +1 -1
  22. package/dist/cjs/src/lib/ramda/internal/_curry2.d.ts.map +1 -1
  23. package/dist/cjs/src/lib/ramda/internal/_curry3.d.ts.map +1 -1
  24. package/dist/cjs/src/lib/storage/StorageManager.d.ts +9 -0
  25. package/dist/cjs/src/lib/storage/StorageManager.d.ts.map +1 -0
  26. package/dist/cjs/src/lib/storage/StorageManager.js +53 -0
  27. package/dist/cjs/src/lib/storage/StorageManager.js.map +1 -0
  28. package/dist/cjs/src/lib/storage/built-in/blueprint.d.ts +12 -0
  29. package/dist/cjs/src/lib/storage/built-in/blueprint.d.ts.map +1 -0
  30. package/dist/cjs/src/lib/storage/built-in/blueprint.js +14 -0
  31. package/dist/cjs/src/lib/storage/built-in/blueprint.js.map +1 -0
  32. package/dist/cjs/src/lib/storage/built-in/cookie.d.ts +10 -0
  33. package/dist/cjs/src/lib/storage/built-in/cookie.d.ts.map +1 -0
  34. package/dist/cjs/src/lib/storage/built-in/cookie.js +76 -0
  35. package/dist/cjs/src/lib/storage/built-in/cookie.js.map +1 -0
  36. package/dist/cjs/src/lib/storage/built-in/memory.d.ts +10 -0
  37. package/dist/cjs/src/lib/storage/built-in/memory.d.ts.map +1 -0
  38. package/dist/cjs/src/lib/storage/built-in/memory.js +44 -0
  39. package/dist/cjs/src/lib/storage/built-in/memory.js.map +1 -0
  40. package/dist/cjs/src/lib/storage/built-in/web.d.ts +11 -0
  41. package/dist/cjs/src/lib/storage/built-in/web.d.ts.map +1 -0
  42. package/dist/cjs/src/lib/storage/built-in/web.js +75 -0
  43. package/dist/cjs/src/lib/storage/built-in/web.js.map +1 -0
  44. package/dist/cjs/src/lib/storage/constant.d.ts +3 -0
  45. package/dist/cjs/src/lib/storage/constant.d.ts.map +1 -0
  46. package/dist/cjs/src/lib/storage/constant.js +6 -0
  47. package/dist/cjs/src/lib/storage/constant.js.map +1 -0
  48. package/dist/cjs/src/lib/storage/index.d.ts +6 -3
  49. package/dist/cjs/src/lib/storage/index.d.ts.map +1 -1
  50. package/dist/cjs/src/lib/storage/index.js +23 -10
  51. package/dist/cjs/src/lib/storage/index.js.map +1 -1
  52. package/dist/cjs/src/lib/storage/type.d.ts +14 -2
  53. package/dist/cjs/src/lib/storage/type.d.ts.map +1 -1
  54. package/dist/cjs/src/lib/version.d.ts +1 -1
  55. package/dist/cjs/src/lib/version.d.ts.map +1 -1
  56. package/dist/cjs/src/lib/version.js +1 -1
  57. package/dist/cjs/src/lib/version.js.map +1 -1
  58. package/dist/cjs/src/utils/address.d.ts.map +1 -1
  59. package/dist/cjs/src/utils/base.d.ts.map +1 -1
  60. package/dist/cjs/src/utils/converter.d.ts.map +1 -1
  61. package/dist/cjs/src/utils/timestamp.d.ts.map +1 -1
  62. package/dist/cjs/src/validators/address.d.ts.map +1 -1
  63. package/dist/cjs/src/validators/checks.d.ts.map +1 -1
  64. package/dist/cjs/src/validators/object.d.ts.map +1 -1
  65. package/dist/cjs/src/validators/string.d.ts.map +1 -1
  66. package/dist/cjs/test/lib/events.spec.d.ts +2 -0
  67. package/dist/cjs/test/lib/events.spec.d.ts.map +1 -0
  68. package/dist/cjs/test/lib/events.spec.js +14 -0
  69. package/dist/cjs/test/lib/events.spec.js.map +1 -0
  70. package/dist/cjs/tsconfig.tsbuildinfo +1 -1
  71. package/dist/esm/src/FormoAnalytics.d.ts +1 -3
  72. package/dist/esm/src/FormoAnalytics.d.ts.map +1 -1
  73. package/dist/esm/src/FormoAnalytics.js +22 -19
  74. package/dist/esm/src/FormoAnalytics.js.map +1 -1
  75. package/dist/esm/src/FormoAnalyticsProvider.d.ts.map +1 -1
  76. package/dist/esm/src/FormoAnalyticsProvider.js +2 -1
  77. package/dist/esm/src/FormoAnalyticsProvider.js.map +1 -1
  78. package/dist/esm/src/constants/config.d.ts.map +1 -1
  79. package/dist/esm/src/lib/event/EventFactory.d.ts +0 -3
  80. package/dist/esm/src/lib/event/EventFactory.d.ts.map +1 -1
  81. package/dist/esm/src/lib/event/EventFactory.js +6 -7
  82. package/dist/esm/src/lib/event/EventFactory.js.map +1 -1
  83. package/dist/esm/src/lib/event/EventManager.d.ts +1 -2
  84. package/dist/esm/src/lib/event/EventManager.d.ts.map +1 -1
  85. package/dist/esm/src/lib/event/EventManager.js +2 -2
  86. package/dist/esm/src/lib/event/EventManager.js.map +1 -1
  87. package/dist/esm/src/lib/event/utils.d.ts +2 -1
  88. package/dist/esm/src/lib/event/utils.d.ts.map +1 -1
  89. package/dist/esm/src/lib/event/utils.js +21 -4
  90. package/dist/esm/src/lib/event/utils.js.map +1 -1
  91. package/dist/esm/src/lib/ramda/internal/_curry1.d.ts.map +1 -1
  92. package/dist/esm/src/lib/ramda/internal/_curry2.d.ts.map +1 -1
  93. package/dist/esm/src/lib/ramda/internal/_curry3.d.ts.map +1 -1
  94. package/dist/esm/src/lib/storage/StorageManager.d.ts +9 -0
  95. package/dist/esm/src/lib/storage/StorageManager.d.ts.map +1 -0
  96. package/dist/esm/src/lib/storage/StorageManager.js +47 -0
  97. package/dist/esm/src/lib/storage/StorageManager.js.map +1 -0
  98. package/dist/esm/src/lib/storage/built-in/blueprint.d.ts +12 -0
  99. package/dist/esm/src/lib/storage/built-in/blueprint.d.ts.map +1 -0
  100. package/dist/esm/src/lib/storage/built-in/blueprint.js +12 -0
  101. package/dist/esm/src/lib/storage/built-in/blueprint.js.map +1 -0
  102. package/dist/esm/src/lib/storage/built-in/cookie.d.ts +10 -0
  103. package/dist/esm/src/lib/storage/built-in/cookie.d.ts.map +1 -0
  104. package/dist/esm/src/lib/storage/built-in/cookie.js +71 -0
  105. package/dist/esm/src/lib/storage/built-in/cookie.js.map +1 -0
  106. package/dist/esm/src/lib/storage/built-in/memory.d.ts +10 -0
  107. package/dist/esm/src/lib/storage/built-in/memory.d.ts.map +1 -0
  108. package/dist/esm/src/lib/storage/built-in/memory.js +39 -0
  109. package/dist/esm/src/lib/storage/built-in/memory.js.map +1 -0
  110. package/dist/esm/src/lib/storage/built-in/web.d.ts +11 -0
  111. package/dist/esm/src/lib/storage/built-in/web.d.ts.map +1 -0
  112. package/dist/esm/src/lib/storage/built-in/web.js +70 -0
  113. package/dist/esm/src/lib/storage/built-in/web.js.map +1 -0
  114. package/dist/esm/src/lib/storage/constant.d.ts +3 -0
  115. package/dist/esm/src/lib/storage/constant.d.ts.map +1 -0
  116. package/dist/esm/src/lib/storage/constant.js +3 -0
  117. package/dist/esm/src/lib/storage/constant.js.map +1 -0
  118. package/dist/esm/src/lib/storage/index.d.ts +6 -3
  119. package/dist/esm/src/lib/storage/index.d.ts.map +1 -1
  120. package/dist/esm/src/lib/storage/index.js +17 -3
  121. package/dist/esm/src/lib/storage/index.js.map +1 -1
  122. package/dist/esm/src/lib/storage/type.d.ts +14 -2
  123. package/dist/esm/src/lib/storage/type.d.ts.map +1 -1
  124. package/dist/esm/src/lib/version.d.ts +1 -1
  125. package/dist/esm/src/lib/version.d.ts.map +1 -1
  126. package/dist/esm/src/lib/version.js +1 -1
  127. package/dist/esm/src/lib/version.js.map +1 -1
  128. package/dist/esm/src/utils/address.d.ts.map +1 -1
  129. package/dist/esm/src/utils/base.d.ts.map +1 -1
  130. package/dist/esm/src/utils/converter.d.ts.map +1 -1
  131. package/dist/esm/src/utils/timestamp.d.ts.map +1 -1
  132. package/dist/esm/src/validators/address.d.ts.map +1 -1
  133. package/dist/esm/src/validators/checks.d.ts.map +1 -1
  134. package/dist/esm/src/validators/object.d.ts.map +1 -1
  135. package/dist/esm/src/validators/string.d.ts.map +1 -1
  136. package/dist/esm/test/lib/events.spec.d.ts +2 -0
  137. package/dist/esm/test/lib/events.spec.d.ts.map +1 -0
  138. package/dist/esm/test/lib/events.spec.js +12 -0
  139. package/dist/esm/test/lib/events.spec.js.map +1 -0
  140. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  141. package/dist/index.umd.min.js +1 -1
  142. package/dist/index.umd.min.js.map +1 -1
  143. package/package.json +2 -2
  144. package/src/FormoAnalytics.ts +39 -58
  145. package/src/FormoAnalyticsProvider.tsx +2 -1
  146. package/src/lib/event/EventFactory.ts +5 -15
  147. package/src/lib/event/EventManager.ts +2 -3
  148. package/src/lib/event/utils.ts +23 -4
  149. package/src/lib/storage/StorageManager.ts +51 -0
  150. package/src/lib/storage/built-in/blueprint.ts +17 -0
  151. package/src/lib/storage/built-in/cookie.ts +66 -0
  152. package/src/lib/storage/built-in/memory.ts +23 -0
  153. package/src/lib/storage/built-in/web.ts +57 -0
  154. package/src/lib/storage/constant.ts +2 -0
  155. package/src/lib/storage/index.ts +24 -3
  156. package/src/lib/storage/type.ts +20 -2
  157. package/src/lib/version.ts +1 -1
  158. package/test/lib/events.spec.ts +12 -0
  159. package/dist/cjs/src/lib/storage/key.d.ts +0 -9
  160. package/dist/cjs/src/lib/storage/key.d.ts.map +0 -1
  161. package/dist/cjs/src/lib/storage/key.js +0 -15
  162. package/dist/cjs/src/lib/storage/key.js.map +0 -1
  163. package/dist/cjs/src/lib/storage/local.d.ts +0 -4
  164. package/dist/cjs/src/lib/storage/local.d.ts.map +0 -1
  165. package/dist/cjs/src/lib/storage/local.js +0 -8
  166. package/dist/cjs/src/lib/storage/local.js.map +0 -1
  167. package/dist/cjs/src/lib/storage/native.d.ts +0 -16
  168. package/dist/cjs/src/lib/storage/native.d.ts.map +0 -1
  169. package/dist/cjs/src/lib/storage/native.js +0 -86
  170. package/dist/cjs/src/lib/storage/native.js.map +0 -1
  171. package/dist/cjs/src/lib/storage/session.d.ts +0 -4
  172. package/dist/cjs/src/lib/storage/session.d.ts.map +0 -1
  173. package/dist/cjs/src/lib/storage/session.js +0 -8
  174. package/dist/cjs/src/lib/storage/session.js.map +0 -1
  175. package/dist/esm/src/lib/storage/key.d.ts +0 -9
  176. package/dist/esm/src/lib/storage/key.d.ts.map +0 -1
  177. package/dist/esm/src/lib/storage/key.js +0 -12
  178. package/dist/esm/src/lib/storage/key.js.map +0 -1
  179. package/dist/esm/src/lib/storage/local.d.ts +0 -4
  180. package/dist/esm/src/lib/storage/local.d.ts.map +0 -1
  181. package/dist/esm/src/lib/storage/local.js +0 -3
  182. package/dist/esm/src/lib/storage/local.js.map +0 -1
  183. package/dist/esm/src/lib/storage/native.d.ts +0 -16
  184. package/dist/esm/src/lib/storage/native.d.ts.map +0 -1
  185. package/dist/esm/src/lib/storage/native.js +0 -83
  186. package/dist/esm/src/lib/storage/native.js.map +0 -1
  187. package/dist/esm/src/lib/storage/session.d.ts +0 -4
  188. package/dist/esm/src/lib/storage/session.d.ts.map +0 -1
  189. package/dist/esm/src/lib/storage/session.js +0 -3
  190. package/dist/esm/src/lib/storage/session.js.map +0 -1
  191. package/src/lib/storage/key.ts +0 -16
  192. package/src/lib/storage/local.ts +0 -3
  193. package/src/lib/storage/native.ts +0 -97
  194. package/src/lib/storage/session.ts +0 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@formo/analytics",
3
- "version": "1.16.9",
3
+ "version": "1.16.11",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/getformo/sdk.git"
@@ -87,7 +87,7 @@
87
87
  "size-limit": [
88
88
  {
89
89
  "path": "dist/index.umd.min.js",
90
- "limit": "26 KB"
90
+ "limit": "27 KB"
91
91
  }
92
92
  ],
93
93
  "peerDependencies": {
@@ -9,15 +9,12 @@ import {
9
9
  TEventType,
10
10
  } from "./constants";
11
11
  import {
12
+ cookie,
12
13
  EventManager,
13
14
  EventQueue,
14
15
  IEventManager,
15
- IStorageKeyManager,
16
- local,
17
16
  logger,
18
17
  Logger,
19
- session,
20
- StorageKey,
21
18
  } from "./lib";
22
19
  import {
23
20
  Address,
@@ -40,7 +37,6 @@ export class FormoAnalytics implements IFormoAnalytics {
40
37
  private _providerListeners: Record<string, (...args: unknown[]) => void> = {};
41
38
  private session: FormoAnalyticsSession;
42
39
  private eventManager: IEventManager;
43
- private storageKeyManager: IStorageKeyManager;
44
40
  private _providers: readonly EIP6963ProviderDetail[] = [];
45
41
 
46
42
  config: Config;
@@ -57,13 +53,9 @@ export class FormoAnalytics implements IFormoAnalytics {
57
53
  trackLocalhost: options.trackLocalhost || false,
58
54
  };
59
55
 
60
- this.storageKeyManager = new StorageKey(this.config.writeKey);
61
-
62
- this.session = new FormoAnalyticsSession(this.storageKeyManager);
56
+ this.session = new FormoAnalyticsSession();
63
57
  this.currentUserId =
64
- (session.get(
65
- this.storageKeyManager.getKey(SESSION_USER_ID_KEY)
66
- ) as string) || undefined;
58
+ (cookie().get(SESSION_USER_ID_KEY) as string) || undefined;
67
59
 
68
60
  this.identify = this.identify.bind(this);
69
61
  this.connect = this.connect.bind(this);
@@ -87,8 +79,7 @@ export class FormoAnalytics implements IFormoAnalytics {
87
79
  retryCount: options.retryCount,
88
80
  maxQueueSize: options.maxQueueSize,
89
81
  flushInterval: options.flushInterval,
90
- }),
91
- this.storageKeyManager
82
+ })
92
83
  );
93
84
 
94
85
  // TODO: replace with eip6963
@@ -141,8 +132,8 @@ export class FormoAnalytics implements IFormoAnalytics {
141
132
  */
142
133
  public reset(): void {
143
134
  this.currentUserId = undefined;
144
- local.remove(this.storageKeyManager.getKey(LOCAL_ANONYMOUS_ID_KEY));
145
- session.remove(this.storageKeyManager.getKey(SESSION_USER_ID_KEY));
135
+ cookie().remove(LOCAL_ANONYMOUS_ID_KEY);
136
+ cookie().remove(SESSION_USER_ID_KEY);
146
137
  }
147
138
 
148
139
  /**
@@ -391,7 +382,8 @@ export class FormoAnalytics implements IFormoAnalytics {
391
382
  callback?: (...args: unknown[]) => void
392
383
  ): Promise<void> {
393
384
  try {
394
- if (!params) { // If no params provided, auto-identify
385
+ if (!params) {
386
+ // If no params provided, auto-identify
395
387
  for (const providerDetail of this._providers) {
396
388
  const provider = providerDetail.provider;
397
389
  if (!provider) continue;
@@ -400,14 +392,22 @@ export class FormoAnalytics implements IFormoAnalytics {
400
392
  const address = await this.getAddress(provider);
401
393
  if (address) {
402
394
  // NOTE: do not set this.currentAddress without explicit connect or identify
403
- await this.identify({
404
- address,
405
- providerName: providerDetail.info.name,
406
- rdns: providerDetail.info.rdns,
407
- }, properties, context, callback);
395
+ await this.identify(
396
+ {
397
+ address,
398
+ providerName: providerDetail.info.name,
399
+ rdns: providerDetail.info.rdns,
400
+ },
401
+ properties,
402
+ context,
403
+ callback
404
+ );
408
405
  }
409
406
  } catch (err) {
410
- logger.error(`Failed to identify provider ${providerDetail.info.name}:`, err);
407
+ logger.error(
408
+ `Failed to identify provider ${providerDetail.info.name}:`,
409
+ err
410
+ );
411
411
  }
412
412
  }
413
413
  return;
@@ -418,7 +418,7 @@ export class FormoAnalytics implements IFormoAnalytics {
418
418
  if (address) this.currentAddress = address;
419
419
  if (userId) {
420
420
  this.currentUserId = userId;
421
- session.set(this.storageKeyManager.getKey(SESSION_USER_ID_KEY), userId);
421
+ cookie().set(SESSION_USER_ID_KEY, userId);
422
422
  }
423
423
 
424
424
  await this.trackEvent(
@@ -486,7 +486,7 @@ export class FormoAnalytics implements IFormoAnalytics {
486
486
  * @returns {Promise<void>}
487
487
  */
488
488
  async track(
489
- event: EventType,
489
+ event: string,
490
490
  properties?: IFormoEventProperties,
491
491
  context?: IFormoEventContext,
492
492
  callback?: (...args: unknown[]) => void
@@ -701,7 +701,7 @@ export class FormoAnalytics implements IFormoAnalytics {
701
701
  };
702
702
  this.currentChainId = undefined;
703
703
  this.currentAddress = undefined;
704
- session.remove(this.storageKeyManager.getKey(SESSION_USER_ID_KEY));
704
+ cookie().remove(SESSION_USER_ID_KEY);
705
705
 
706
706
  await this.trackEvent(
707
707
  EventType.DISCONNECT,
@@ -750,14 +750,8 @@ export class FormoAnalytics implements IFormoAnalytics {
750
750
  }
751
751
 
752
752
  private async trackFirstPageHit(): Promise<void> {
753
- if (
754
- session.get(this.storageKeyManager.getKey(SESSION_CURRENT_URL_KEY)) ===
755
- null
756
- ) {
757
- session.set(
758
- this.storageKeyManager.getKey(SESSION_CURRENT_URL_KEY),
759
- window.location.href
760
- );
753
+ if (cookie().get(SESSION_CURRENT_URL_KEY) === null) {
754
+ cookie().set(SESSION_CURRENT_URL_KEY, window.location.href);
761
755
  }
762
756
 
763
757
  return this.trackPageHit();
@@ -783,15 +777,10 @@ export class FormoAnalytics implements IFormoAnalytics {
783
777
  }
784
778
 
785
779
  private async onLocationChange(): Promise<void> {
786
- const currentUrl = session.get(
787
- this.storageKeyManager.getKey(SESSION_CURRENT_URL_KEY)
788
- );
780
+ const currentUrl = cookie().get(SESSION_CURRENT_URL_KEY);
789
781
 
790
782
  if (currentUrl !== window.location.href) {
791
- session.set(
792
- this.storageKeyManager.getKey(SESSION_CURRENT_URL_KEY),
793
- window.location.href
794
- );
783
+ cookie().set(SESSION_CURRENT_URL_KEY, window.location.href);
795
784
  this.trackPageHit();
796
785
  }
797
786
  }
@@ -891,7 +880,9 @@ export class FormoAnalytics implements IFormoAnalytics {
891
880
  return this._provider;
892
881
  }
893
882
 
894
- private async getAddress(provider?: EIP1193Provider): Promise<Address | null> {
883
+ private async getAddress(
884
+ provider?: EIP1193Provider
885
+ ): Promise<Address | null> {
895
886
  if (this.currentAddress) return this.currentAddress;
896
887
  const p = provider || this.provider;
897
888
  if (!p) {
@@ -1010,28 +1001,18 @@ interface IFormoAnalyticsSession {
1010
1001
  }
1011
1002
 
1012
1003
  class FormoAnalyticsSession implements IFormoAnalyticsSession {
1013
- private storageKeyManager: IStorageKeyManager;
1014
- constructor(storageKeyManager: IStorageKeyManager) {
1015
- this.storageKeyManager = storageKeyManager;
1016
- }
1017
-
1018
1004
  public isWalletDetected(rdns: string): boolean {
1019
- const rdnses =
1020
- (session.get(
1021
- this.storageKeyManager.getKey(SESSION_WALLET_DETECTED_KEY)
1022
- ) as string[]) || [];
1005
+ const rdnses = cookie().get(SESSION_WALLET_DETECTED_KEY)?.split(",") || [];
1023
1006
  return rdnses.includes(rdns);
1024
1007
  }
1025
1008
 
1026
1009
  public markWalletDetected(rdns: string): void {
1027
- const rdnses =
1028
- (session.get(
1029
- this.storageKeyManager.getKey(SESSION_WALLET_DETECTED_KEY)
1030
- ) as string[]) || [];
1010
+ const rdnses = cookie().get(SESSION_WALLET_DETECTED_KEY)?.split(",") || [];
1031
1011
  rdnses.push(rdns);
1032
- session.set(
1033
- this.storageKeyManager.getKey(SESSION_WALLET_DETECTED_KEY),
1034
- rdnses
1035
- );
1012
+ cookie().set(SESSION_WALLET_DETECTED_KEY, rdnses.join(","), {
1013
+ // by the end of the day
1014
+ expires: new Date(Date.now() + 86400 * 1000).toUTCString(),
1015
+ path: "/",
1016
+ });
1036
1017
  }
1037
1018
  }
@@ -1,6 +1,6 @@
1
1
  import { createContext, useContext, useEffect, useRef, useState } from "react";
2
2
  import { FormoAnalytics } from "./FormoAnalytics";
3
- import { logger } from "./lib";
3
+ import { initStorageManager, logger } from "./lib";
4
4
  import { FormoAnalyticsProviderProps, IFormoAnalytics } from "./types";
5
5
 
6
6
  const defaultContext: IFormoAnalytics = {
@@ -43,6 +43,7 @@ const InitializedAnalytics = ({
43
43
  }: FormoAnalyticsProviderProps) => {
44
44
  const [sdk, setSdk] = useState<IFormoAnalytics>(defaultContext);
45
45
  const initializedStartedRef = useRef(false);
46
+ initStorageManager(writeKey);
46
47
 
47
48
  const initializeFormoAnalytics = async (writeKey: string, options: any) => {
48
49
  try {
@@ -25,18 +25,13 @@ import { getCurrentTimeFormatted } from "../../utils/timestamp";
25
25
  import { isUndefined } from "../../validators";
26
26
  import { logger } from "../logger";
27
27
  import mergeDeepRight from "../ramda/mergeDeepRight";
28
- import { IStorageKeyManager, local, session } from "../storage";
28
+ import { cookie, session } from "../storage";
29
29
  import { version } from "../version";
30
30
  import { CHANNEL, VERSION } from "./constants";
31
31
  import { IEventFactory } from "./type";
32
32
  import { generateAnonymousId } from "./utils";
33
33
 
34
34
  class EventFactory implements IEventFactory {
35
- private storageKeyManager: IStorageKeyManager;
36
- constructor(storageKeyManager: IStorageKeyManager) {
37
- this.storageKeyManager = storageKeyManager;
38
- }
39
-
40
35
  private getTimezone(): string {
41
36
  try {
42
37
  return Intl.DateTimeFormat().resolvedOptions().timeZone;
@@ -103,9 +98,7 @@ class EventFactory implements IEventFactory {
103
98
  referrer: document.referrer,
104
99
  };
105
100
  const storedTrafficSources =
106
- (session.get(
107
- this.storageKeyManager.getKey(SESSION_TRAFFIC_SOURCE_KEY)
108
- ) as ITrafficSource) || {};
101
+ (session().get(SESSION_TRAFFIC_SOURCE_KEY) as ITrafficSource) || {};
109
102
 
110
103
  const finalTrafficSources: ITrafficSource = {
111
104
  ref: contextTrafficSources.ref || storedTrafficSources?.ref || "",
@@ -144,10 +137,7 @@ class EventFactory implements IEventFactory {
144
137
  );
145
138
 
146
139
  if (Object.keys(sessionStoredTrafficSources).length)
147
- session.set(
148
- this.storageKeyManager.getKey(SESSION_TRAFFIC_SOURCE_KEY),
149
- sessionStoredTrafficSources
150
- );
140
+ session().set(SESSION_TRAFFIC_SOURCE_KEY, sessionStoredTrafficSources);
151
141
 
152
142
  return finalTrafficSources;
153
143
  };
@@ -220,11 +210,11 @@ class EventFactory implements IEventFactory {
220
210
  version: VERSION,
221
211
  } as Partial<IFormoEvent>;
222
212
 
223
- if (!local.isAvailable()) {
213
+ if (!cookie().isAvailable()) {
224
214
  commonEventData.anonymous_id = generateNativeUUID();
225
215
  } else {
226
216
  commonEventData.anonymous_id = generateAnonymousId(
227
- this.storageKeyManager.getKey(LOCAL_ANONYMOUS_ID_KEY)
217
+ LOCAL_ANONYMOUS_ID_KEY
228
218
  );
229
219
  }
230
220
 
@@ -1,7 +1,6 @@
1
1
  import { Address, APIEvent } from "../../types";
2
2
  import { logger } from "../logger";
3
3
  import { IEventQueue } from "../queue";
4
- import { IStorageKeyManager } from "../storage";
5
4
  import { EventFactory } from "./EventFactory";
6
5
  import { IEventFactory, IEventManager } from "./type";
7
6
 
@@ -16,9 +15,9 @@ class EventManager implements IEventManager {
16
15
  *
17
16
  * @param eventQueue Event queue instance
18
17
  */
19
- constructor(eventQueue: IEventQueue, storageKeyManager: IStorageKeyManager) {
18
+ constructor(eventQueue: IEventQueue) {
20
19
  this.eventQueue = eventQueue;
21
- this.eventFactory = new EventFactory(storageKeyManager);
20
+ this.eventFactory = new EventFactory();
22
21
  }
23
22
 
24
23
  /**
@@ -1,14 +1,33 @@
1
1
  import { AnonymousID } from "../../types";
2
2
  import { generateNativeUUID } from "../../utils";
3
- import { local } from "../storage";
3
+ import { cookie } from "../storage";
4
4
 
5
5
  const generateAnonymousId = (key: string): AnonymousID => {
6
- const storedAnonymousId = local.get(key);
6
+ const storedAnonymousId = cookie().get(key);
7
7
  if (storedAnonymousId && typeof storedAnonymousId === "string")
8
8
  return storedAnonymousId as AnonymousID;
9
9
  const newAnonymousId = generateNativeUUID();
10
- local.set(key, newAnonymousId);
10
+ cookie().set(key, newAnonymousId, {
11
+ maxAge: Date.now() + 1000 * 60 * 60 * 24 * 365, // 1 year
12
+ domain: getCookieDomain(),
13
+ path: "/",
14
+ });
11
15
  return newAnonymousId;
12
16
  };
13
17
 
14
- export { generateAnonymousId };
18
+ function getCookieDomain(hostname: string = window.location.hostname): string {
19
+ // Special cases
20
+ if (hostname === "localhost" || /^\d{1,3}(\.\d{1,3}){3}$/.test(hostname)) {
21
+ // Localhost or IP address
22
+ return "";
23
+ }
24
+
25
+ const parts = hostname.split(".");
26
+ if (parts.length >= 2) {
27
+ return `.${parts.slice(-2).join(".")}`; // e.g. example.com
28
+ }
29
+
30
+ return "";
31
+ }
32
+
33
+ export { generateAnonymousId, getCookieDomain };
@@ -0,0 +1,51 @@
1
+ import { logger } from "../logger";
2
+ import CookieStorage from "./built-in/cookie";
3
+ import MemoryStorage from "./built-in/memory";
4
+ import WebStorage from "./built-in/web";
5
+ import { IStorage, StorageType } from "./type";
6
+
7
+ // Fallback as follows: cookieStorage, localStorage, sessionStorage, memoryStorage
8
+ const TYPES: StorageType[] = [
9
+ "cookieStorage",
10
+ "localStorage",
11
+ "sessionStorage",
12
+ "memoryStorage",
13
+ ];
14
+
15
+ export class StorageManager {
16
+ private storages: Map<StorageType, IStorage> = new Map();
17
+
18
+ constructor(private readonly writeKey: string) {}
19
+
20
+ getStorage(type: StorageType): IStorage {
21
+ if (!this.storages.has(type)) {
22
+ let storage = this.createStorage(type);
23
+ // If storage is not available, try next
24
+ while (!storage.isAvailable()) {
25
+ const index = TYPES.indexOf(type);
26
+ logger.warn(
27
+ `Storage ${type} is not available, trying ${TYPES[index + 1]}`
28
+ );
29
+ storage = this.createStorage(TYPES[index + 1]);
30
+ }
31
+
32
+ // Add to cache
33
+ this.storages.set(type, this.createStorage(type));
34
+ }
35
+ return this.storages.get(type)!;
36
+ }
37
+
38
+ private createStorage(type: StorageType): IStorage {
39
+ switch (type) {
40
+ case "cookieStorage":
41
+ return new CookieStorage(this.writeKey);
42
+ case "localStorage":
43
+ return new WebStorage(this.writeKey, localStorage);
44
+ case "sessionStorage":
45
+ return new WebStorage(this.writeKey, sessionStorage);
46
+ case "memoryStorage":
47
+ default:
48
+ return new MemoryStorage(this.writeKey);
49
+ }
50
+ }
51
+ }
@@ -0,0 +1,17 @@
1
+ import { KEY_PREFIX } from "../constant";
2
+ import { CookieOptions } from "../type";
3
+
4
+ abstract class StorageBlueprint {
5
+ constructor(private readonly writeKey: string) {}
6
+
7
+ abstract isAvailable(): boolean;
8
+ abstract set(key: string, value: string, options?: CookieOptions): void;
9
+ abstract get(key: string): any;
10
+ abstract remove(key: string): void;
11
+
12
+ protected getKey(key: string): string {
13
+ return `${KEY_PREFIX}_${this.writeKey}.${key}`;
14
+ }
15
+ }
16
+
17
+ export default StorageBlueprint;
@@ -0,0 +1,66 @@
1
+ import StorageBlueprint from "./blueprint";
2
+ import { CookieOptions } from "../type";
3
+
4
+ class CookieStorage extends StorageBlueprint {
5
+ public override isAvailable(): boolean {
6
+ try {
7
+ document.cookie = "cookie_test=1";
8
+ const available = document.cookie.includes("cookie_test=");
9
+ this.remove("cookie_test");
10
+ return available;
11
+ } catch {
12
+ return false;
13
+ }
14
+ }
15
+
16
+ public override set(
17
+ key: string,
18
+ value: string,
19
+ options?: CookieOptions
20
+ ): void {
21
+ const expires = options?.expires;
22
+ const maxAge = options?.maxAge;
23
+ const path = options?.path || "/";
24
+ const domain = options?.domain;
25
+ const sameSite = options?.sameSite;
26
+ const secure = options?.secure || false;
27
+
28
+ let cookie = `${encodeURIComponent(this.getKey(key))}=${encodeURIComponent(
29
+ value
30
+ )}`;
31
+ if (maxAge) {
32
+ cookie += "; max-age=" + maxAge;
33
+ }
34
+ if (expires) {
35
+ cookie += "; expires=" + expires;
36
+ }
37
+ if (path) {
38
+ cookie += "; path=" + path;
39
+ }
40
+ if (domain) {
41
+ cookie += "; domain=" + domain;
42
+ }
43
+ if (sameSite) {
44
+ cookie += "; samesite=" + sameSite;
45
+ }
46
+ if (secure) {
47
+ cookie += "; secure";
48
+ }
49
+ document.cookie = cookie;
50
+ }
51
+
52
+ public override get(key: string): string | null {
53
+ const match = document.cookie.match(
54
+ new RegExp(`(?:^|; )${encodeURIComponent(this.getKey(key))}=([^;]*)`)
55
+ );
56
+ return match ? decodeURIComponent(match[1]) : null;
57
+ }
58
+
59
+ public override remove(key: string): void {
60
+ document.cookie = `${encodeURIComponent(
61
+ this.getKey(key)
62
+ )}=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
63
+ }
64
+ }
65
+
66
+ export default CookieStorage;
@@ -0,0 +1,23 @@
1
+ import StorageBlueprint from "./blueprint";
2
+
3
+ class MemoryStorage extends StorageBlueprint {
4
+ private memoryStorage: Record<string, string> = {};
5
+
6
+ public override isAvailable(): boolean {
7
+ return true;
8
+ }
9
+
10
+ public override set(key: string, value: string): void {
11
+ this.memoryStorage[this.getKey(key)] = value;
12
+ }
13
+
14
+ public override get(key: string): string | null {
15
+ return this.memoryStorage[this.getKey(key)] || null;
16
+ }
17
+
18
+ public override remove(key: string): void {
19
+ delete this.memoryStorage[this.getKey(key)];
20
+ }
21
+ }
22
+
23
+ export default MemoryStorage;
@@ -0,0 +1,57 @@
1
+ import { logger } from "../../logger";
2
+ import { JSON_PREFIX } from "../constant";
3
+ import StorageBlueprint from "./blueprint";
4
+
5
+ class WebStorage extends StorageBlueprint {
6
+ constructor(writeKey: string, private readonly backend: Storage) {
7
+ super(writeKey);
8
+ }
9
+
10
+ public override isAvailable(): boolean {
11
+ try {
12
+ const testKey = "__storage_test__";
13
+ this.backend.setItem(testKey, "1");
14
+ this.backend.removeItem(testKey);
15
+ return true;
16
+ } catch {
17
+ return false;
18
+ }
19
+ }
20
+
21
+ public override set(key: string, value: any): void {
22
+ if (typeof value === "boolean") value = value === true ? "true" : "false";
23
+ if (typeof value === "object") value = JSON_PREFIX + JSON.stringify(value);
24
+ this.backend.setItem(key, value);
25
+ }
26
+
27
+ public override get(key: string): string | boolean | Record<any, any> | null {
28
+ const value = this.backend.getItem(key);
29
+
30
+ if (!value || typeof value !== "string") return null;
31
+ if (["null", "undefined"].some((item) => item == value)) return null;
32
+
33
+ if (value.startsWith(JSON_PREFIX)) {
34
+ try {
35
+ return JSON.parse(value.slice(JSON_PREFIX.length));
36
+ } catch (error) {
37
+ logger.error(
38
+ `[FORMO_ERROR] ${this.backend.constructor.name} failed to parse JSON`,
39
+ error
40
+ );
41
+ return null;
42
+ }
43
+ }
44
+
45
+ if (["true", "false"].some((item) => item == value)) {
46
+ return JSON.parse(value);
47
+ }
48
+
49
+ return value;
50
+ }
51
+
52
+ public override remove(key: string): void {
53
+ this.backend.removeItem(key);
54
+ }
55
+ }
56
+
57
+ export default WebStorage;
@@ -0,0 +1,2 @@
1
+ export const JSON_PREFIX = "__json=";
2
+ export const KEY_PREFIX = "formo";
@@ -1,4 +1,25 @@
1
- export { StorageKey } from "./key";
2
- export { default as local } from "./local";
3
- export { default as session } from "./session";
1
+ import { IStorage, StorageType } from "./type";
2
+ import { StorageManager } from "./StorageManager";
4
3
  export * from "./type";
4
+
5
+ let globalManager: StorageManager | null = null;
6
+
7
+ export function initStorageManager(writeKey: string): void {
8
+ if (!globalManager) {
9
+ globalManager = new StorageManager(writeKey);
10
+ }
11
+ }
12
+
13
+ function getStorageInstance(type: StorageType): IStorage {
14
+ if (!globalManager) {
15
+ throw new Error(
16
+ "StorageManager not initialized. Call initStorageManager(writeKey) first."
17
+ );
18
+ }
19
+ return globalManager.getStorage(type);
20
+ }
21
+
22
+ export const cookie = () => getStorageInstance("cookieStorage");
23
+ export const local = () => getStorageInstance("localStorage");
24
+ export const session = () => getStorageInstance("sessionStorage");
25
+ export const memory = () => getStorageInstance("memoryStorage");
@@ -1,3 +1,21 @@
1
- export interface IStorageKeyManager {
2
- getKey(name: string): string;
1
+ export type StorageType =
2
+ | "cookieStorage"
3
+ | "localStorage"
4
+ | "sessionStorage"
5
+ | "memoryStorage";
6
+
7
+ export type CookieOptions = {
8
+ maxAge?: number;
9
+ expires?: string;
10
+ path?: string;
11
+ domain?: string;
12
+ secure?: boolean;
13
+ sameSite?: "lax" | "strict" | "none";
14
+ };
15
+
16
+ export interface IStorage {
17
+ isAvailable(): boolean;
18
+ set(key: string, value: string, options?: CookieOptions): void;
19
+ get(key: string): any;
20
+ remove(key: string): void;
3
21
  }
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- export const version = '1.16.9';
2
+ export const version = '1.16.11';
@@ -0,0 +1,12 @@
1
+ import { describe, it } from "mocha";
2
+ import { expect } from "chai";
3
+ import { getCookieDomain } from "../../src/lib/event/utils";
4
+
5
+ describe("getCookieDomain", () => {
6
+ it("should return the cookie domain format", () => {
7
+ expect(getCookieDomain("192.168.0.1")).to.equal("");
8
+ expect(getCookieDomain("localhost:3000")).to.equal("");
9
+ expect(getCookieDomain("example.com")).to.equal(".example.com");
10
+ expect(getCookieDomain("www.example.com")).to.equal(".example.com");
11
+ });
12
+ });
@@ -1,9 +0,0 @@
1
- import { IStorageKeyManager } from "./type";
2
- declare class StorageKey implements IStorageKeyManager {
3
- private readonly prefix;
4
- private readonly writeKey;
5
- constructor(writeKey: string);
6
- getKey(name: string): string;
7
- }
8
- export { StorageKey };
9
- //# sourceMappingURL=key.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"key.d.ts","sourceRoot":"","sources":["../../../../../src/lib/storage/key.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAE5C,cAAM,UAAW,YAAW,kBAAkB;IAC5C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAW;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAEtB,QAAQ,EAAE,MAAM;IAI5B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;CAG7B;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"}
@@ -1,15 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.StorageKey = void 0;
4
- var StorageKey = /** @class */ (function () {
5
- function StorageKey(writeKey) {
6
- this.prefix = "formo";
7
- this.writeKey = writeKey;
8
- }
9
- StorageKey.prototype.getKey = function (name) {
10
- return this.prefix + "_" + this.writeKey + "." + name;
11
- };
12
- return StorageKey;
13
- }());
14
- exports.StorageKey = StorageKey;
15
- //# sourceMappingURL=key.js.map