@formo/analytics 1.16.10 → 1.16.12

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 (190) hide show
  1. package/dist/cjs/src/FormoAnalytics.d.ts +0 -1
  2. package/dist/cjs/src/FormoAnalytics.d.ts.map +1 -1
  3. package/dist/cjs/src/FormoAnalytics.js +25 -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.js +1 -1
  56. package/dist/cjs/src/utils/address.d.ts.map +1 -1
  57. package/dist/cjs/src/utils/base.d.ts.map +1 -1
  58. package/dist/cjs/src/utils/converter.d.ts.map +1 -1
  59. package/dist/cjs/src/utils/timestamp.d.ts.map +1 -1
  60. package/dist/cjs/src/validators/address.d.ts.map +1 -1
  61. package/dist/cjs/src/validators/checks.d.ts.map +1 -1
  62. package/dist/cjs/src/validators/object.d.ts.map +1 -1
  63. package/dist/cjs/src/validators/string.d.ts.map +1 -1
  64. package/dist/cjs/test/lib/events.spec.d.ts +2 -0
  65. package/dist/cjs/test/lib/events.spec.d.ts.map +1 -0
  66. package/dist/cjs/test/lib/events.spec.js +14 -0
  67. package/dist/cjs/test/lib/events.spec.js.map +1 -0
  68. package/dist/cjs/tsconfig.tsbuildinfo +1 -1
  69. package/dist/esm/src/FormoAnalytics.d.ts +0 -1
  70. package/dist/esm/src/FormoAnalytics.d.ts.map +1 -1
  71. package/dist/esm/src/FormoAnalytics.js +26 -19
  72. package/dist/esm/src/FormoAnalytics.js.map +1 -1
  73. package/dist/esm/src/FormoAnalyticsProvider.d.ts.map +1 -1
  74. package/dist/esm/src/FormoAnalyticsProvider.js +2 -1
  75. package/dist/esm/src/FormoAnalyticsProvider.js.map +1 -1
  76. package/dist/esm/src/constants/config.d.ts.map +1 -1
  77. package/dist/esm/src/lib/event/EventFactory.d.ts +0 -3
  78. package/dist/esm/src/lib/event/EventFactory.d.ts.map +1 -1
  79. package/dist/esm/src/lib/event/EventFactory.js +6 -7
  80. package/dist/esm/src/lib/event/EventFactory.js.map +1 -1
  81. package/dist/esm/src/lib/event/EventManager.d.ts +1 -2
  82. package/dist/esm/src/lib/event/EventManager.d.ts.map +1 -1
  83. package/dist/esm/src/lib/event/EventManager.js +2 -2
  84. package/dist/esm/src/lib/event/EventManager.js.map +1 -1
  85. package/dist/esm/src/lib/event/utils.d.ts +2 -1
  86. package/dist/esm/src/lib/event/utils.d.ts.map +1 -1
  87. package/dist/esm/src/lib/event/utils.js +21 -4
  88. package/dist/esm/src/lib/event/utils.js.map +1 -1
  89. package/dist/esm/src/lib/ramda/internal/_curry1.d.ts.map +1 -1
  90. package/dist/esm/src/lib/ramda/internal/_curry2.d.ts.map +1 -1
  91. package/dist/esm/src/lib/ramda/internal/_curry3.d.ts.map +1 -1
  92. package/dist/esm/src/lib/storage/StorageManager.d.ts +9 -0
  93. package/dist/esm/src/lib/storage/StorageManager.d.ts.map +1 -0
  94. package/dist/esm/src/lib/storage/StorageManager.js +47 -0
  95. package/dist/esm/src/lib/storage/StorageManager.js.map +1 -0
  96. package/dist/esm/src/lib/storage/built-in/blueprint.d.ts +12 -0
  97. package/dist/esm/src/lib/storage/built-in/blueprint.d.ts.map +1 -0
  98. package/dist/esm/src/lib/storage/built-in/blueprint.js +12 -0
  99. package/dist/esm/src/lib/storage/built-in/blueprint.js.map +1 -0
  100. package/dist/esm/src/lib/storage/built-in/cookie.d.ts +10 -0
  101. package/dist/esm/src/lib/storage/built-in/cookie.d.ts.map +1 -0
  102. package/dist/esm/src/lib/storage/built-in/cookie.js +71 -0
  103. package/dist/esm/src/lib/storage/built-in/cookie.js.map +1 -0
  104. package/dist/esm/src/lib/storage/built-in/memory.d.ts +10 -0
  105. package/dist/esm/src/lib/storage/built-in/memory.d.ts.map +1 -0
  106. package/dist/esm/src/lib/storage/built-in/memory.js +39 -0
  107. package/dist/esm/src/lib/storage/built-in/memory.js.map +1 -0
  108. package/dist/esm/src/lib/storage/built-in/web.d.ts +11 -0
  109. package/dist/esm/src/lib/storage/built-in/web.d.ts.map +1 -0
  110. package/dist/esm/src/lib/storage/built-in/web.js +70 -0
  111. package/dist/esm/src/lib/storage/built-in/web.js.map +1 -0
  112. package/dist/esm/src/lib/storage/constant.d.ts +3 -0
  113. package/dist/esm/src/lib/storage/constant.d.ts.map +1 -0
  114. package/dist/esm/src/lib/storage/constant.js +3 -0
  115. package/dist/esm/src/lib/storage/constant.js.map +1 -0
  116. package/dist/esm/src/lib/storage/index.d.ts +6 -3
  117. package/dist/esm/src/lib/storage/index.d.ts.map +1 -1
  118. package/dist/esm/src/lib/storage/index.js +17 -3
  119. package/dist/esm/src/lib/storage/index.js.map +1 -1
  120. package/dist/esm/src/lib/storage/type.d.ts +14 -2
  121. package/dist/esm/src/lib/storage/type.d.ts.map +1 -1
  122. package/dist/esm/src/lib/version.d.ts +1 -1
  123. package/dist/esm/src/lib/version.js +1 -1
  124. package/dist/esm/src/utils/address.d.ts.map +1 -1
  125. package/dist/esm/src/utils/base.d.ts.map +1 -1
  126. package/dist/esm/src/utils/converter.d.ts.map +1 -1
  127. package/dist/esm/src/utils/timestamp.d.ts.map +1 -1
  128. package/dist/esm/src/validators/address.d.ts.map +1 -1
  129. package/dist/esm/src/validators/checks.d.ts.map +1 -1
  130. package/dist/esm/src/validators/object.d.ts.map +1 -1
  131. package/dist/esm/src/validators/string.d.ts.map +1 -1
  132. package/dist/esm/test/lib/events.spec.d.ts +2 -0
  133. package/dist/esm/test/lib/events.spec.d.ts.map +1 -0
  134. package/dist/esm/test/lib/events.spec.js +12 -0
  135. package/dist/esm/test/lib/events.spec.js.map +1 -0
  136. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  137. package/dist/index.umd.min.js +1 -1
  138. package/dist/index.umd.min.js.map +1 -1
  139. package/package.json +2 -2
  140. package/src/FormoAnalytics.ts +41 -57
  141. package/src/FormoAnalyticsProvider.tsx +2 -1
  142. package/src/lib/event/EventFactory.ts +5 -15
  143. package/src/lib/event/EventManager.ts +2 -3
  144. package/src/lib/event/utils.ts +23 -4
  145. package/src/lib/storage/StorageManager.ts +51 -0
  146. package/src/lib/storage/built-in/blueprint.ts +17 -0
  147. package/src/lib/storage/built-in/cookie.ts +66 -0
  148. package/src/lib/storage/built-in/memory.ts +23 -0
  149. package/src/lib/storage/built-in/web.ts +57 -0
  150. package/src/lib/storage/constant.ts +2 -0
  151. package/src/lib/storage/index.ts +24 -3
  152. package/src/lib/storage/type.ts +20 -2
  153. package/src/lib/version.ts +1 -1
  154. package/test/lib/events.spec.ts +12 -0
  155. package/dist/cjs/src/lib/storage/key.d.ts +0 -9
  156. package/dist/cjs/src/lib/storage/key.d.ts.map +0 -1
  157. package/dist/cjs/src/lib/storage/key.js +0 -15
  158. package/dist/cjs/src/lib/storage/key.js.map +0 -1
  159. package/dist/cjs/src/lib/storage/local.d.ts +0 -4
  160. package/dist/cjs/src/lib/storage/local.d.ts.map +0 -1
  161. package/dist/cjs/src/lib/storage/local.js +0 -8
  162. package/dist/cjs/src/lib/storage/local.js.map +0 -1
  163. package/dist/cjs/src/lib/storage/native.d.ts +0 -16
  164. package/dist/cjs/src/lib/storage/native.d.ts.map +0 -1
  165. package/dist/cjs/src/lib/storage/native.js +0 -86
  166. package/dist/cjs/src/lib/storage/native.js.map +0 -1
  167. package/dist/cjs/src/lib/storage/session.d.ts +0 -4
  168. package/dist/cjs/src/lib/storage/session.d.ts.map +0 -1
  169. package/dist/cjs/src/lib/storage/session.js +0 -8
  170. package/dist/cjs/src/lib/storage/session.js.map +0 -1
  171. package/dist/esm/src/lib/storage/key.d.ts +0 -9
  172. package/dist/esm/src/lib/storage/key.d.ts.map +0 -1
  173. package/dist/esm/src/lib/storage/key.js +0 -12
  174. package/dist/esm/src/lib/storage/key.js.map +0 -1
  175. package/dist/esm/src/lib/storage/local.d.ts +0 -4
  176. package/dist/esm/src/lib/storage/local.d.ts.map +0 -1
  177. package/dist/esm/src/lib/storage/local.js +0 -3
  178. package/dist/esm/src/lib/storage/local.js.map +0 -1
  179. package/dist/esm/src/lib/storage/native.d.ts +0 -16
  180. package/dist/esm/src/lib/storage/native.d.ts.map +0 -1
  181. package/dist/esm/src/lib/storage/native.js +0 -83
  182. package/dist/esm/src/lib/storage/native.js.map +0 -1
  183. package/dist/esm/src/lib/storage/session.d.ts +0 -4
  184. package/dist/esm/src/lib/storage/session.d.ts.map +0 -1
  185. package/dist/esm/src/lib/storage/session.js +0 -3
  186. package/dist/esm/src/lib/storage/session.js.map +0 -1
  187. package/src/lib/storage/key.ts +0 -16
  188. package/src/lib/storage/local.ts +0 -3
  189. package/src/lib/storage/native.ts +0 -97
  190. 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.10",
3
+ "version": "1.16.12",
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,9 @@ 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
387
+ logger.info("Auto-identifying with providers:", this._providers.map(p => p.info.name));
395
388
  for (const providerDetail of this._providers) {
396
389
  const provider = providerDetail.provider;
397
390
  if (!provider) continue;
@@ -399,15 +392,24 @@ export class FormoAnalytics implements IFormoAnalytics {
399
392
  try {
400
393
  const address = await this.getAddress(provider);
401
394
  if (address) {
395
+ logger.info("Auto-identifying", address, providerDetail.info.name, providerDetail.info.rdns);
402
396
  // 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);
397
+ await this.identify(
398
+ {
399
+ address,
400
+ providerName: providerDetail.info.name,
401
+ rdns: providerDetail.info.rdns,
402
+ },
403
+ properties,
404
+ context,
405
+ callback
406
+ );
408
407
  }
409
408
  } catch (err) {
410
- logger.error(`Failed to identify provider ${providerDetail.info.name}:`, err);
409
+ logger.error(
410
+ `Failed to identify provider ${providerDetail.info.name}:`,
411
+ err
412
+ );
411
413
  }
412
414
  }
413
415
  return;
@@ -415,10 +417,11 @@ export class FormoAnalytics implements IFormoAnalytics {
415
417
 
416
418
  // Explicit identify
417
419
  const { userId, address, providerName, rdns } = params;
420
+ logger.info("Identify", address, userId, providerName, rdns);
418
421
  if (address) this.currentAddress = address;
419
422
  if (userId) {
420
423
  this.currentUserId = userId;
421
- session.set(this.storageKeyManager.getKey(SESSION_USER_ID_KEY), userId);
424
+ cookie().set(SESSION_USER_ID_KEY, userId);
422
425
  }
423
426
 
424
427
  await this.trackEvent(
@@ -701,7 +704,7 @@ export class FormoAnalytics implements IFormoAnalytics {
701
704
  };
702
705
  this.currentChainId = undefined;
703
706
  this.currentAddress = undefined;
704
- session.remove(this.storageKeyManager.getKey(SESSION_USER_ID_KEY));
707
+ cookie().remove(SESSION_USER_ID_KEY);
705
708
 
706
709
  await this.trackEvent(
707
710
  EventType.DISCONNECT,
@@ -750,14 +753,8 @@ export class FormoAnalytics implements IFormoAnalytics {
750
753
  }
751
754
 
752
755
  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
- );
756
+ if (cookie().get(SESSION_CURRENT_URL_KEY) === null) {
757
+ cookie().set(SESSION_CURRENT_URL_KEY, window.location.href);
761
758
  }
762
759
 
763
760
  return this.trackPageHit();
@@ -783,15 +780,10 @@ export class FormoAnalytics implements IFormoAnalytics {
783
780
  }
784
781
 
785
782
  private async onLocationChange(): Promise<void> {
786
- const currentUrl = session.get(
787
- this.storageKeyManager.getKey(SESSION_CURRENT_URL_KEY)
788
- );
783
+ const currentUrl = cookie().get(SESSION_CURRENT_URL_KEY);
789
784
 
790
785
  if (currentUrl !== window.location.href) {
791
- session.set(
792
- this.storageKeyManager.getKey(SESSION_CURRENT_URL_KEY),
793
- window.location.href
794
- );
786
+ cookie().set(SESSION_CURRENT_URL_KEY, window.location.href);
795
787
  this.trackPageHit();
796
788
  }
797
789
  }
@@ -891,7 +883,9 @@ export class FormoAnalytics implements IFormoAnalytics {
891
883
  return this._provider;
892
884
  }
893
885
 
894
- private async getAddress(provider?: EIP1193Provider): Promise<Address | null> {
886
+ private async getAddress(
887
+ provider?: EIP1193Provider
888
+ ): Promise<Address | null> {
895
889
  if (this.currentAddress) return this.currentAddress;
896
890
  const p = provider || this.provider;
897
891
  if (!p) {
@@ -1010,28 +1004,18 @@ interface IFormoAnalyticsSession {
1010
1004
  }
1011
1005
 
1012
1006
  class FormoAnalyticsSession implements IFormoAnalyticsSession {
1013
- private storageKeyManager: IStorageKeyManager;
1014
- constructor(storageKeyManager: IStorageKeyManager) {
1015
- this.storageKeyManager = storageKeyManager;
1016
- }
1017
-
1018
1007
  public isWalletDetected(rdns: string): boolean {
1019
- const rdnses =
1020
- (session.get(
1021
- this.storageKeyManager.getKey(SESSION_WALLET_DETECTED_KEY)
1022
- ) as string[]) || [];
1008
+ const rdnses = cookie().get(SESSION_WALLET_DETECTED_KEY)?.split(",") || [];
1023
1009
  return rdnses.includes(rdns);
1024
1010
  }
1025
1011
 
1026
1012
  public markWalletDetected(rdns: string): void {
1027
- const rdnses =
1028
- (session.get(
1029
- this.storageKeyManager.getKey(SESSION_WALLET_DETECTED_KEY)
1030
- ) as string[]) || [];
1013
+ const rdnses = cookie().get(SESSION_WALLET_DETECTED_KEY)?.split(",") || [];
1031
1014
  rdnses.push(rdns);
1032
- session.set(
1033
- this.storageKeyManager.getKey(SESSION_WALLET_DETECTED_KEY),
1034
- rdnses
1035
- );
1015
+ cookie().set(SESSION_WALLET_DETECTED_KEY, rdnses.join(","), {
1016
+ // by the end of the day
1017
+ expires: new Date(Date.now() + 86400 * 1000).toUTCString(),
1018
+ path: "/",
1019
+ });
1036
1020
  }
1037
1021
  }
@@ -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(this.getKey(key), value);
25
+ }
26
+
27
+ public override get(key: string): string | boolean | Record<any, any> | null {
28
+ const value = this.backend.getItem(this.getKey(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(this.getKey(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.10';
2
+ export const version = '1.16.12';
@@ -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