@newrelic/browser-agent 0.1.231 → 1.232.0

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 (210) hide show
  1. package/README.md +2 -2
  2. package/dist/cjs/common/config/state/configurable.js +27 -21
  3. package/dist/cjs/common/config/state/init.js +8 -0
  4. package/dist/cjs/common/config/state/runtime.js +24 -26
  5. package/dist/cjs/common/constants/env.cdn.js +1 -1
  6. package/dist/cjs/common/constants/env.npm.js +1 -1
  7. package/dist/cjs/common/context/shared-context.js +2 -1
  8. package/dist/cjs/common/event-emitter/contextual-ee.test.js +2 -2
  9. package/dist/cjs/common/event-emitter/register-handler.test.js +1 -1
  10. package/dist/cjs/common/event-listener/event-listener-opts.js +4 -2
  11. package/dist/cjs/common/harvest/harvest-scheduler.js +14 -11
  12. package/dist/cjs/common/harvest/harvest.js +3 -1
  13. package/dist/cjs/common/session/constants.js +12 -0
  14. package/dist/cjs/common/session/session-entity.js +278 -0
  15. package/dist/cjs/common/session/session-entity.test.js +436 -0
  16. package/dist/cjs/common/storage/first-party-cookies.js +35 -0
  17. package/dist/cjs/common/storage/local-memory.js +35 -0
  18. package/dist/cjs/common/storage/local-memory.test.js +20 -0
  19. package/dist/cjs/common/storage/local-storage.js +33 -0
  20. package/dist/cjs/common/storage/local-storage.test.js +14 -0
  21. package/dist/cjs/common/timer/interaction-timer.js +78 -0
  22. package/dist/cjs/common/timer/interaction-timer.test.js +216 -0
  23. package/dist/cjs/common/timer/timer.js +32 -0
  24. package/dist/cjs/common/timer/timer.test.js +105 -0
  25. package/dist/cjs/common/unload/eol.js +2 -2
  26. package/dist/cjs/common/util/data-size.js +6 -0
  27. package/dist/cjs/common/util/data-size.test.js +47 -0
  28. package/dist/cjs/common/util/invoke.js +73 -0
  29. package/dist/cjs/common/util/invoke.test.js +49 -0
  30. package/dist/cjs/common/util/obfuscate.js +0 -4
  31. package/dist/cjs/common/window/page-visibility.js +3 -1
  32. package/dist/cjs/common/wrap/wrap-timer.js +1 -1
  33. package/dist/cjs/features/ajax/aggregate/index.js +2 -2
  34. package/dist/cjs/features/jserrors/aggregate/index.js +3 -3
  35. package/dist/cjs/features/metrics/aggregate/index.js +13 -2
  36. package/dist/cjs/features/page_action/aggregate/index.js +2 -2
  37. package/dist/cjs/features/page_view_event/aggregate/index.js +6 -3
  38. package/dist/cjs/features/page_view_timing/aggregate/index.js +6 -6
  39. package/dist/cjs/features/session_trace/aggregate/index.js +2 -2
  40. package/dist/cjs/features/spa/aggregate/index.js +6 -5
  41. package/dist/cjs/features/utils/agent-session.js +73 -0
  42. package/dist/cjs/features/utils/feature-base.js +1 -1
  43. package/dist/cjs/features/utils/instrument-base.js +7 -2
  44. package/dist/cjs/features/utils/lazy-loader.js +1 -1
  45. package/dist/cjs/loaders/agent.js +1 -1
  46. package/dist/cjs/loaders/api/api.js +1 -4
  47. package/dist/cjs/loaders/api/apiAsync.js +3 -2
  48. package/dist/cjs/loaders/configure/configure.js +0 -6
  49. package/dist/esm/common/config/state/configurable.js +26 -20
  50. package/dist/esm/common/config/state/init.js +8 -0
  51. package/dist/esm/common/config/state/runtime.js +24 -26
  52. package/dist/esm/common/constants/env.cdn.js +1 -1
  53. package/dist/esm/common/constants/env.npm.js +1 -1
  54. package/dist/esm/common/context/shared-context.js +2 -1
  55. package/dist/esm/common/event-emitter/contextual-ee.test.js +2 -2
  56. package/dist/esm/common/event-emitter/register-handler.test.js +1 -1
  57. package/dist/esm/common/event-listener/event-listener-opts.js +4 -2
  58. package/dist/esm/common/harvest/harvest-scheduler.js +14 -11
  59. package/dist/esm/common/harvest/harvest.js +3 -1
  60. package/dist/esm/common/session/constants.js +3 -0
  61. package/dist/esm/common/session/session-entity.js +271 -0
  62. package/dist/esm/common/session/session-entity.test.js +434 -0
  63. package/dist/esm/common/storage/first-party-cookies.js +28 -0
  64. package/dist/esm/common/storage/local-memory.js +28 -0
  65. package/dist/esm/common/storage/local-memory.test.js +18 -0
  66. package/dist/esm/common/storage/local-storage.js +26 -0
  67. package/dist/esm/common/storage/local-storage.test.js +12 -0
  68. package/dist/esm/common/timer/interaction-timer.js +71 -0
  69. package/dist/esm/common/timer/interaction-timer.test.js +214 -0
  70. package/dist/esm/common/timer/timer.js +25 -0
  71. package/dist/esm/common/timer/timer.test.js +103 -0
  72. package/dist/esm/common/unload/eol.js +1 -1
  73. package/dist/esm/common/util/data-size.js +7 -0
  74. package/dist/esm/common/util/data-size.test.js +45 -0
  75. package/dist/esm/common/util/invoke.js +66 -0
  76. package/dist/esm/common/util/invoke.test.js +47 -0
  77. package/dist/esm/common/util/obfuscate.js +0 -4
  78. package/dist/esm/common/window/page-visibility.js +3 -1
  79. package/dist/esm/common/wrap/wrap-timer.js +1 -1
  80. package/dist/esm/features/ajax/aggregate/index.js +2 -2
  81. package/dist/esm/features/jserrors/aggregate/index.js +3 -3
  82. package/dist/esm/features/metrics/aggregate/index.js +14 -3
  83. package/dist/esm/features/page_action/aggregate/index.js +2 -2
  84. package/dist/esm/features/page_view_event/aggregate/index.js +6 -3
  85. package/dist/esm/features/page_view_timing/aggregate/index.js +6 -6
  86. package/dist/esm/features/session_trace/aggregate/index.js +2 -2
  87. package/dist/esm/features/spa/aggregate/index.js +6 -5
  88. package/dist/esm/features/utils/agent-session.js +67 -0
  89. package/dist/esm/features/utils/feature-base.js +1 -1
  90. package/dist/esm/features/utils/instrument-base.js +7 -2
  91. package/dist/esm/features/utils/lazy-loader.js +1 -1
  92. package/dist/esm/loaders/agent.js +1 -1
  93. package/dist/esm/loaders/api/api.js +2 -5
  94. package/dist/esm/loaders/api/apiAsync.js +2 -1
  95. package/dist/esm/loaders/configure/configure.js +2 -8
  96. package/dist/types/common/config/state/configurable.d.ts.map +1 -1
  97. package/dist/types/common/config/state/init.d.ts.map +1 -1
  98. package/dist/types/common/config/state/runtime.d.ts.map +1 -1
  99. package/dist/types/common/context/shared-context.d.ts.map +1 -1
  100. package/dist/types/common/event-listener/event-listener-opts.d.ts +2 -2
  101. package/dist/types/common/event-listener/event-listener-opts.d.ts.map +1 -1
  102. package/dist/types/common/harvest/harvest-scheduler.d.ts +1 -0
  103. package/dist/types/common/harvest/harvest-scheduler.d.ts.map +1 -1
  104. package/dist/types/common/harvest/harvest.d.ts.map +1 -1
  105. package/dist/types/common/session/constants.d.ts +4 -0
  106. package/dist/types/common/session/constants.d.ts.map +1 -0
  107. package/dist/types/common/session/session-entity.d.ts +72 -0
  108. package/dist/types/common/session/session-entity.d.ts.map +1 -0
  109. package/dist/types/common/storage/first-party-cookies.d.ts +8 -0
  110. package/dist/types/common/storage/first-party-cookies.d.ts.map +1 -0
  111. package/dist/types/common/storage/local-memory.d.ts +8 -0
  112. package/dist/types/common/storage/local-memory.d.ts.map +1 -0
  113. package/dist/types/common/storage/local-storage.d.ts +6 -0
  114. package/dist/types/common/storage/local-storage.d.ts.map +1 -0
  115. package/dist/types/common/timer/interaction-timer.d.ts +11 -0
  116. package/dist/types/common/timer/interaction-timer.d.ts.map +1 -0
  117. package/dist/types/common/timer/timer.d.ts +12 -0
  118. package/dist/types/common/timer/timer.d.ts.map +1 -0
  119. package/dist/types/common/util/data-size.d.ts +7 -1
  120. package/dist/types/common/util/data-size.d.ts.map +1 -1
  121. package/dist/types/common/util/invoke.d.ts +35 -0
  122. package/dist/types/common/util/invoke.d.ts.map +1 -0
  123. package/dist/types/common/util/obfuscate.d.ts.map +1 -1
  124. package/dist/types/common/window/page-visibility.d.ts +1 -1
  125. package/dist/types/common/window/page-visibility.d.ts.map +1 -1
  126. package/dist/types/features/ajax/aggregate/index.d.ts +2 -2
  127. package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
  128. package/dist/types/features/jserrors/aggregate/index.d.ts +2 -2
  129. package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
  130. package/dist/types/features/metrics/aggregate/index.d.ts +2 -2
  131. package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
  132. package/dist/types/features/page_action/aggregate/index.d.ts +2 -2
  133. package/dist/types/features/page_action/aggregate/index.d.ts.map +1 -1
  134. package/dist/types/features/page_view_event/aggregate/index.d.ts +2 -2
  135. package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
  136. package/dist/types/features/page_view_timing/aggregate/index.d.ts +2 -2
  137. package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
  138. package/dist/types/features/session_trace/aggregate/index.d.ts +2 -2
  139. package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
  140. package/dist/types/features/spa/aggregate/index.d.ts +2 -2
  141. package/dist/types/features/spa/aggregate/index.d.ts.map +1 -1
  142. package/dist/types/features/utils/agent-session.d.ts +2 -0
  143. package/dist/types/features/utils/agent-session.d.ts.map +1 -0
  144. package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
  145. package/dist/types/features/utils/lazy-loader.d.ts +2 -2
  146. package/dist/types/features/utils/lazy-loader.d.ts.map +1 -1
  147. package/dist/types/loaders/api/api.d.ts.map +1 -1
  148. package/dist/types/loaders/api/apiAsync.d.ts.map +1 -1
  149. package/dist/types/loaders/configure/configure.d.ts.map +1 -1
  150. package/package.json +6 -5
  151. package/src/common/config/state/configurable.js +26 -19
  152. package/src/common/config/state/init.js +7 -0
  153. package/src/common/config/state/runtime.js +22 -27
  154. package/src/common/context/shared-context.js +2 -1
  155. package/src/common/event-emitter/contextual-ee.test.js +2 -2
  156. package/src/common/event-emitter/register-handler.test.js +1 -1
  157. package/src/common/event-listener/event-listener-opts.js +4 -4
  158. package/src/common/harvest/harvest-scheduler.js +12 -8
  159. package/src/common/harvest/harvest.js +3 -1
  160. package/src/common/session/constants.js +3 -0
  161. package/src/common/session/session-entity.js +271 -0
  162. package/src/common/session/session-entity.test.js +317 -0
  163. package/src/common/storage/first-party-cookies.js +31 -0
  164. package/src/common/storage/local-memory.js +30 -0
  165. package/src/common/storage/local-memory.test.js +19 -0
  166. package/src/common/storage/local-storage.js +28 -0
  167. package/src/common/storage/local-storage.test.js +17 -0
  168. package/src/common/timer/interaction-timer.js +75 -0
  169. package/src/common/timer/interaction-timer.test.js +167 -0
  170. package/src/common/timer/timer.js +31 -0
  171. package/src/common/timer/timer.test.js +100 -0
  172. package/src/common/unload/eol.js +1 -1
  173. package/src/common/util/data-size.js +6 -0
  174. package/src/common/util/data-size.test.js +50 -0
  175. package/src/common/util/invoke.js +55 -0
  176. package/src/common/util/invoke.test.js +65 -0
  177. package/src/common/util/obfuscate.js +0 -4
  178. package/src/common/window/page-visibility.js +2 -2
  179. package/src/common/wrap/wrap-timer.js +1 -1
  180. package/src/features/ajax/aggregate/index.js +2 -2
  181. package/src/features/jserrors/aggregate/index.js +3 -3
  182. package/src/features/metrics/aggregate/index.js +18 -3
  183. package/src/features/page_action/aggregate/index.js +2 -2
  184. package/src/features/page_view_event/aggregate/index.js +6 -3
  185. package/src/features/page_view_timing/aggregate/index.js +6 -6
  186. package/src/features/session_trace/aggregate/index.js +2 -2
  187. package/src/features/spa/aggregate/index.js +5 -5
  188. package/src/features/utils/agent-session.js +68 -0
  189. package/src/features/utils/feature-base.js +1 -1
  190. package/src/features/utils/instrument-base.js +5 -2
  191. package/src/features/utils/lazy-loader.js +1 -1
  192. package/src/loaders/agent.js +1 -1
  193. package/src/loaders/api/api.js +2 -5
  194. package/src/loaders/api/apiAsync.js +2 -1
  195. package/src/loaders/configure/configure.js +2 -7
  196. package/dist/cjs/common/util/single.js +0 -23
  197. package/dist/cjs/common/window/session-storage.js +0 -87
  198. package/dist/cjs/features/utils/aggregate-base.js +0 -13
  199. package/dist/esm/common/util/single.js +0 -16
  200. package/dist/esm/common/window/session-storage.js +0 -77
  201. package/dist/esm/features/utils/aggregate-base.js +0 -6
  202. package/dist/types/common/util/single.d.ts +0 -2
  203. package/dist/types/common/util/single.d.ts.map +0 -1
  204. package/dist/types/common/window/session-storage.d.ts +0 -18
  205. package/dist/types/common/window/session-storage.d.ts.map +0 -1
  206. package/dist/types/features/utils/aggregate-base.d.ts +0 -4
  207. package/dist/types/features/utils/aggregate-base.d.ts.map +0 -1
  208. package/src/common/util/single.js +0 -18
  209. package/src/common/window/session-storage.js +0 -75
  210. package/src/features/utils/aggregate-base.js +0 -7
@@ -0,0 +1,436 @@
1
+ "use strict";
2
+
3
+ var _localMemory = require("../storage/local-memory");
4
+ var _localStorage = require("../storage/local-storage");
5
+ var _constants = require("./constants");
6
+ var _sessionEntity = require("./session-entity");
7
+ const agentIdentifier = 'test_agent_identifier';
8
+ const key = 'test_key';
9
+ const value = 'test_value';
10
+ jest.mock('../timer/timer');
11
+ jest.mock('../timer/interaction-timer');
12
+ jest.useFakeTimers();
13
+ const mockBrowserScope = jest.fn().mockImplementation(() => true);
14
+ jest.mock('../util/global-scope', () => ({
15
+ __esModule: true,
16
+ get isBrowserScope() {
17
+ return mockBrowserScope();
18
+ },
19
+ get globalScope() {
20
+ return global.window;
21
+ }
22
+ }));
23
+ beforeEach(() => {
24
+ jest.restoreAllMocks();
25
+ mockBrowserScope.mockReturnValue(true);
26
+ });
27
+ describe('constructor', () => {
28
+ test('must use required fields', () => {
29
+ try {
30
+ expect(new _sessionEntity.SessionEntity({})).toThrow(new Error('Missing Required Fields'));
31
+ } catch (err) {}
32
+ });
33
+ test('top-level properties are set and exposed', () => {
34
+ const session = new _sessionEntity.SessionEntity({
35
+ agentIdentifier,
36
+ key
37
+ });
38
+ expect(session).toMatchObject({
39
+ agentIdentifier: expect.any(String),
40
+ key: expect.any(String),
41
+ value: expect.any(String),
42
+ expiresMs: expect.any(Number),
43
+ expiresAt: expect.any(Number),
44
+ expiresTimer: expect.any(Object),
45
+ inactiveMs: expect.any(Number),
46
+ inactiveAt: expect.any(Number),
47
+ inactiveTimer: expect.any(Object),
48
+ isNew: expect.any(Boolean),
49
+ sessionReplayActive: expect.any(Boolean),
50
+ sessionTraceActive: expect.any(Boolean),
51
+ storage: expect.any(Object)
52
+ });
53
+ });
54
+ test('can use sane defaults', () => {
55
+ const session = new _sessionEntity.SessionEntity({
56
+ agentIdentifier,
57
+ key
58
+ });
59
+ expect(session).toEqual(expect.objectContaining({
60
+ value: expect.any(String),
61
+ expiresAt: expect.any(Number),
62
+ inactiveAt: expect.any(Number),
63
+ sessionReplayActive: expect.any(Boolean),
64
+ sessionTraceActive: expect.any(Boolean)
65
+ }));
66
+ });
67
+ test('Workers are forced to use local memory', () => {
68
+ mockBrowserScope.mockReturnValueOnce(false);
69
+ const session = new _sessionEntity.SessionEntity({
70
+ agentIdentifier,
71
+ key,
72
+ storageAPI: new _localStorage.LocalStorage()
73
+ });
74
+ expect(session.storage instanceof _localMemory.LocalMemory).toEqual(true);
75
+ });
76
+ test('expiresAt is the correct future timestamp - new session', () => {
77
+ const now = Date.now();
78
+ jest.setSystemTime(now);
79
+ const session = new _sessionEntity.SessionEntity({
80
+ agentIdentifier,
81
+ key,
82
+ expiresMs: 100
83
+ });
84
+ expect(session.expiresAt).toEqual(now + 100);
85
+ });
86
+ test('expiresAt is the correct future timestamp - existing session', () => {
87
+ const now = Date.now();
88
+ jest.setSystemTime(now);
89
+ const existingData = new _localMemory.LocalMemory({
90
+ ["".concat(_constants.PREFIX, "_").concat(key)]: {
91
+ value,
92
+ expiresAt: now + 5000,
93
+ inactiveAt: Infinity
94
+ }
95
+ });
96
+ const session = new _sessionEntity.SessionEntity({
97
+ agentIdentifier,
98
+ key,
99
+ expiresMs: 100,
100
+ storageAPI: existingData
101
+ });
102
+ expect(session.expiresAt).toEqual(now + 5000);
103
+ });
104
+ test('expiresAt never expires if 0', () => {
105
+ const session = new _sessionEntity.SessionEntity({
106
+ agentIdentifier,
107
+ key,
108
+ expiresMs: 0
109
+ });
110
+ expect(session.expiresAt).toEqual(Infinity);
111
+ });
112
+ test('inactiveAt is the correct future timestamp - new session', () => {
113
+ const now = Date.now();
114
+ jest.setSystemTime(now);
115
+ const session = new _sessionEntity.SessionEntity({
116
+ agentIdentifier,
117
+ key,
118
+ inactiveMs: 100
119
+ });
120
+ expect(session.inactiveAt).toEqual(now + 100);
121
+ });
122
+ test('inactiveAt is the correct future timestamp - existing session', () => {
123
+ const now = Date.now();
124
+ jest.setSystemTime(now);
125
+ const existingData = new _localMemory.LocalMemory({
126
+ ["".concat(_constants.PREFIX, "_").concat(key)]: {
127
+ value,
128
+ inactiveAt: now + 5000,
129
+ expiresAt: Infinity
130
+ }
131
+ });
132
+ const session = new _sessionEntity.SessionEntity({
133
+ agentIdentifier,
134
+ key,
135
+ inactiveMs: 100,
136
+ storageAPI: existingData
137
+ });
138
+ expect(session.inactiveAt).toEqual(now + 5000);
139
+ });
140
+ test('inactiveAt never expires if 0', () => {
141
+ const session = new _sessionEntity.SessionEntity({
142
+ agentIdentifier,
143
+ key,
144
+ inactiveMs: 0
145
+ });
146
+ expect(session.inactiveAt).toEqual(Infinity);
147
+ });
148
+ test('should handle isNew', () => {
149
+ const newSession = new _sessionEntity.SessionEntity({
150
+ agentIdentifier,
151
+ key,
152
+ expiresMs: 10
153
+ });
154
+ expect(newSession.isNew).toBeTruthy();
155
+ const storageAPI = new _localMemory.LocalMemory({
156
+ ["".concat(_constants.PREFIX, "_").concat(key)]: {
157
+ value,
158
+ expiresAt: Infinity,
159
+ inactiveAt: Infinity
160
+ }
161
+ });
162
+ const existingSession = new _sessionEntity.SessionEntity({
163
+ agentIdentifier,
164
+ key,
165
+ expiresMs: 10,
166
+ storageAPI
167
+ });
168
+ expect(existingSession.isNew).toBeFalsy();
169
+ });
170
+ test('invalid stored values sets new defaults', () => {
171
+ // missing required fields
172
+ const storageAPI = new _localMemory.LocalMemory({
173
+ ["".concat(_constants.PREFIX, "_").concat(key)]: {
174
+ invalid_fields: true
175
+ }
176
+ });
177
+ const session = new _sessionEntity.SessionEntity({
178
+ agentIdentifier,
179
+ key,
180
+ storageAPI
181
+ });
182
+ expect(session).toEqual(expect.objectContaining({
183
+ value: expect.any(String),
184
+ expiresAt: expect.any(Number),
185
+ inactiveAt: expect.any(Number),
186
+ sessionReplayActive: expect.any(Boolean),
187
+ sessionTraceActive: expect.any(Boolean)
188
+ }));
189
+ });
190
+ test('expired expiresAt value in storage sets new defaults', () => {
191
+ const now = Date.now();
192
+ jest.setSystemTime(now);
193
+ const storageAPI = new _localMemory.LocalMemory({
194
+ ["".concat(_constants.PREFIX, "_").concat(key)]: {
195
+ value,
196
+ expiresAt: now - 100,
197
+ inactiveAt: Infinity
198
+ }
199
+ });
200
+ const session = new _sessionEntity.SessionEntity({
201
+ agentIdentifier,
202
+ key,
203
+ storageAPI
204
+ });
205
+ expect(session).toEqual(expect.objectContaining({
206
+ value: expect.any(String),
207
+ expiresAt: expect.any(Number),
208
+ inactiveAt: expect.any(Number),
209
+ sessionReplayActive: expect.any(Boolean),
210
+ sessionTraceActive: expect.any(Boolean)
211
+ }));
212
+ });
213
+ test('expired inactiveAt value in storage sets new defaults', () => {
214
+ const now = Date.now();
215
+ jest.setSystemTime(now);
216
+ const storageAPI = new _localMemory.LocalMemory({
217
+ ["".concat(_constants.PREFIX, "_").concat(key)]: {
218
+ value,
219
+ inactiveAt: now - 100,
220
+ expiresAt: Infinity
221
+ }
222
+ });
223
+ const session = new _sessionEntity.SessionEntity({
224
+ agentIdentifier,
225
+ key,
226
+ storageAPI
227
+ });
228
+ expect(session).toEqual(expect.objectContaining({
229
+ value: expect.any(String),
230
+ expiresAt: expect.any(Number),
231
+ inactiveAt: expect.any(Number),
232
+ sessionReplayActive: expect.any(Boolean),
233
+ sessionTraceActive: expect.any(Boolean)
234
+ }));
235
+ });
236
+ });
237
+ describe('reset()', () => {
238
+ test('should create new default values when resetting', () => {
239
+ const now = Date.now();
240
+ jest.setSystemTime(now);
241
+ const session = new _sessionEntity.SessionEntity({
242
+ agentIdentifier,
243
+ key,
244
+ expiresMs: 10
245
+ });
246
+ const sessionVal = session.value;
247
+ expect(session.value).toBeTruthy();
248
+ session.reset();
249
+ expect(session.value).toBeTruthy();
250
+ expect(session.value).not.toEqual(sessionVal);
251
+ });
252
+ test('custom data should be wiped on reset', () => {
253
+ const now = Date.now();
254
+ jest.setSystemTime(now);
255
+ const session = new _sessionEntity.SessionEntity({
256
+ agentIdentifier,
257
+ key,
258
+ expiresMs: 10
259
+ });
260
+ session.syncCustomAttribute('test', 123);
261
+ expect(session.custom.test).toEqual(123);
262
+ expect(session.read().custom.test).toEqual(123);
263
+
264
+ // simulate a timer expiring
265
+ session.reset();
266
+ expect(session.custom?.test).toEqual(undefined);
267
+ expect(session.read()?.custom?.test).toEqual(undefined);
268
+ });
269
+ });
270
+ describe('read()', () => {
271
+ test('"new" sessions get data from read()', () => {
272
+ const newSession = new _sessionEntity.SessionEntity({
273
+ agentIdentifier,
274
+ key,
275
+ expiresMs: 10
276
+ });
277
+ expect(newSession.isNew).toBeTruthy();
278
+ expect(newSession.read()).toEqual(expect.objectContaining({
279
+ value: expect.any(String),
280
+ expiresAt: expect.any(Number),
281
+ inactiveAt: expect.any(Number),
282
+ sessionReplayActive: expect.any(Boolean),
283
+ sessionTraceActive: expect.any(Boolean)
284
+ }));
285
+ });
286
+ test('"pre-existing" sessions get data from read()', () => {
287
+ const storageAPI = new _localMemory.LocalMemory({
288
+ ["".concat(_constants.PREFIX, "_").concat(key)]: {
289
+ value,
290
+ expiresAt: Infinity,
291
+ inactiveAt: Infinity
292
+ }
293
+ });
294
+ const session = new _sessionEntity.SessionEntity({
295
+ agentIdentifier,
296
+ key,
297
+ storageAPI
298
+ });
299
+ expect(session.isNew).toBeFalsy();
300
+ expect(session.read()).toEqual(expect.objectContaining({
301
+ value,
302
+ expiresAt: Infinity,
303
+ inactiveAt: Infinity
304
+ }));
305
+ });
306
+ });
307
+ describe('write()', () => {
308
+ test('write() sets data to top-level wrapper', () => {
309
+ const session = new _sessionEntity.SessionEntity({
310
+ agentIdentifier,
311
+ key
312
+ });
313
+ expect(session.value).not.toEqual(value);
314
+ expect(session.expiresAt).not.toEqual(Infinity);
315
+ expect(session.inactiveAt).not.toEqual(Infinity);
316
+ session.write({
317
+ value,
318
+ expiresAt: Infinity,
319
+ inactiveAt: Infinity
320
+ });
321
+ expect(session.value).toEqual(value);
322
+ expect(session.expiresAt).toEqual(Infinity);
323
+ expect(session.inactiveAt).toEqual(Infinity);
324
+ });
325
+ test('write() sets data that read() can access', () => {
326
+ const now = Date.now();
327
+ jest.setSystemTime(now);
328
+ const session = new _sessionEntity.SessionEntity({
329
+ agentIdentifier,
330
+ key
331
+ });
332
+ session.write({
333
+ value,
334
+ expiresAt: now + 100,
335
+ inactiveAt: now + 100
336
+ });
337
+ const read = session.read();
338
+ expect(read.value).toEqual(value);
339
+ expect(read.expiresAt).toEqual(now + 100);
340
+ expect(read.inactiveAt).toEqual(now + 100);
341
+ });
342
+ test('write() does not run with invalid data', () => {
343
+ const session = new _sessionEntity.SessionEntity({
344
+ agentIdentifier,
345
+ key
346
+ });
347
+ let out = session.write();
348
+ expect(out).toEqual(undefined);
349
+ out = session.write('string');
350
+ expect(out).toEqual(undefined);
351
+ out = session.write(123);
352
+ expect(out).toEqual(undefined);
353
+ out = session.write(true);
354
+ expect(out).toEqual(undefined);
355
+ out = session.write(false);
356
+ expect(out).toEqual(undefined);
357
+ });
358
+ });
359
+ describe('refresh()', () => {
360
+ test('refresh sets inactiveAt to future time', () => {
361
+ const now = Date.now();
362
+ jest.setSystemTime(now);
363
+ const session = new _sessionEntity.SessionEntity({
364
+ agentIdentifier,
365
+ key,
366
+ inactiveMs: 100
367
+ });
368
+ expect(session.inactiveAt).toEqual(now + 100);
369
+ jest.setSystemTime(now + 1000);
370
+ session.refresh();
371
+ expect(session.inactiveAt).toEqual(now + 100 + 1000);
372
+ });
373
+ test('refresh resets the entity if expiresTimer is invalid', () => {
374
+ const now = Date.now();
375
+ jest.setSystemTime(now);
376
+ const session = new _sessionEntity.SessionEntity({
377
+ agentIdentifier,
378
+ key,
379
+ value
380
+ });
381
+ expect(session.value).toEqual(value);
382
+ session.write({
383
+ ...session.read(),
384
+ expiresAt: now - 1
385
+ });
386
+ session.refresh();
387
+ expect(session.value).not.toEqual(value);
388
+ });
389
+ test('refresh resets the entity if inactiveTimer is invalid', () => {
390
+ const now = Date.now();
391
+ jest.setSystemTime(now);
392
+ const session = new _sessionEntity.SessionEntity({
393
+ agentIdentifier,
394
+ key,
395
+ value
396
+ });
397
+ expect(session.value).toEqual(value);
398
+ session.write({
399
+ ...session.read(),
400
+ inactiveAt: now - 1
401
+ });
402
+ session.refresh();
403
+ expect(session.value).not.toEqual(value);
404
+ });
405
+ });
406
+ describe('syncCustomAttribute()', () => {
407
+ test('Custom data can be managed by session entity', () => {
408
+ const session = new _sessionEntity.SessionEntity({
409
+ agentIdentifier,
410
+ key
411
+ });
412
+
413
+ // if custom has never been set, and a "delete" action is triggered, do nothing
414
+ session.syncCustomAttribute('test', null);
415
+ expect(session?.custom?.test).toEqual(undefined);
416
+ session.syncCustomAttribute('test', 1);
417
+ expect(session?.custom?.test).toEqual(1);
418
+ session.syncCustomAttribute('test', 'string');
419
+ expect(session?.custom?.test).toEqual('string');
420
+ session.syncCustomAttribute('test', false);
421
+ expect(session?.custom?.test).toEqual(false);
422
+
423
+ // null specifically deletes the object completely
424
+ session.syncCustomAttribute('test', null);
425
+ expect(session?.custom?.test).toEqual(undefined);
426
+ });
427
+ test('Only runs in browser scope', () => {
428
+ mockBrowserScope.mockReturnValue(false);
429
+ const session = new _sessionEntity.SessionEntity({
430
+ agentIdentifier,
431
+ key
432
+ });
433
+ session.syncCustomAttribute('test', 1);
434
+ expect(session.read().custom?.test).toEqual(undefined);
435
+ });
436
+ });
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.FirstPartyCookies = void 0;
7
+ class FirstPartyCookies {
8
+ constructor(domain) {
9
+ this.domain = domain;
10
+ }
11
+ get(name) {
12
+ try {
13
+ var match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
14
+ if (match) return match[2];
15
+ } catch (err) {
16
+ return '';
17
+ }
18
+ }
19
+ set(key, value) {
20
+ try {
21
+ const cookie = "".concat(key, "=").concat(value, "; Domain=").concat(domain, "; Path=/");
22
+ document.cookie = cookie;
23
+ } catch (err) {
24
+ return;
25
+ }
26
+ }
27
+ remove(key) {
28
+ try {
29
+ return document.cookie = "".concat(key, "=; expires=Thu, 01 Jan 1970 00:00:00 UTC; Domain=").concat(domain, "; Path=/");
30
+ } catch (err) {
31
+ return;
32
+ }
33
+ }
34
+ }
35
+ exports.FirstPartyCookies = FirstPartyCookies;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.LocalMemory = void 0;
7
+ class LocalMemory {
8
+ constructor() {
9
+ let initialState = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
10
+ this.state = initialState;
11
+ }
12
+ get(key) {
13
+ try {
14
+ return this.state[key];
15
+ } catch (err) {
16
+ return '';
17
+ }
18
+ }
19
+ set(key, value) {
20
+ try {
21
+ if (value === undefined || value === null) return this.remove(key);
22
+ this.state[key] = value;
23
+ } catch (err) {
24
+ return;
25
+ }
26
+ }
27
+ remove(key) {
28
+ try {
29
+ delete this.state[key];
30
+ } catch (err) {
31
+ return;
32
+ }
33
+ }
34
+ }
35
+ exports.LocalMemory = LocalMemory;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+
3
+ var _localMemory = require("./local-memory");
4
+ test('Local-memory', () => {
5
+ const LM = new _localMemory.LocalMemory({
6
+ test: 1
7
+ });
8
+ expect(LM.state).toEqual({
9
+ test: 1
10
+ });
11
+ expect(LM.get('test')).toEqual(1);
12
+ LM.set('test', 2);
13
+ expect(LM.get('test')).toEqual(2);
14
+ LM.set('test');
15
+ expect(LM.get('test')).toEqual(undefined);
16
+ LM.set('test', 2);
17
+ expect(LM.get('test')).toEqual(2);
18
+ LM.remove('test');
19
+ expect(LM.get('test')).toEqual(undefined);
20
+ });
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.LocalStorage = void 0;
7
+ class LocalStorage {
8
+ get(key) {
9
+ try {
10
+ // localStorage strangely type-casts non-existing data to "null"...
11
+ // Cast it back to undefined if it doesnt exist
12
+ return localStorage.getItem(key) || undefined;
13
+ } catch (err) {
14
+ return '';
15
+ }
16
+ }
17
+ set(key, value) {
18
+ try {
19
+ if (value === undefined || value === null) return this.remove(key);
20
+ return localStorage.setItem(key, value);
21
+ } catch (err) {
22
+ return;
23
+ }
24
+ }
25
+ remove(key) {
26
+ try {
27
+ localStorage.removeItem(key);
28
+ } catch (err) {
29
+ return;
30
+ }
31
+ }
32
+ }
33
+ exports.LocalStorage = LocalStorage;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+
3
+ var _localStorage = require("./local-storage");
4
+ test('Local-memory', () => {
5
+ const LS = new _localStorage.LocalStorage();
6
+ LS.set('test', 1);
7
+ expect(LS.get('test')).toEqual('1');
8
+ LS.set('test');
9
+ expect(LS.get('test')).toEqual(undefined);
10
+ LS.set('test', 2);
11
+ expect(LS.get('test')).toEqual('2');
12
+ LS.remove('test');
13
+ expect(LS.get('test')).toEqual(undefined);
14
+ });
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.InteractionTimer = void 0;
7
+ var _timer = require("./timer");
8
+ var _pageVisibility = require("../window/page-visibility");
9
+ var _invoke = require("../util/invoke");
10
+ var _globalScope = require("../util/global-scope");
11
+ class InteractionTimer extends _timer.Timer {
12
+ constructor(opts, ms) {
13
+ super(opts, ms);
14
+ this.onRefresh = opts.onRefresh;
15
+ this.onPause = opts.onPause;
16
+
17
+ // used by pause/resume
18
+ this.remainingMs = undefined;
19
+ if (!opts.refreshEvents) opts.refreshEvents = ['click', 'keydown', 'scroll'];
20
+
21
+ // the abort controller is used to "reset" the event listeners and prevent them from duplicating when new sessions are created
22
+ try {
23
+ this.abortController = new AbortController();
24
+ } catch (e) {
25
+ // this try-catch can be removed when IE11 is completely unsupported & gone
26
+ }
27
+ if (_globalScope.isBrowserScope && opts.ee) {
28
+ if (opts.ee) {
29
+ const debouncedRefresh = (0, _invoke.debounce)(this.refresh.bind(this), 500, {
30
+ leading: true
31
+ });
32
+ opts.ee.on('fn-end', evts => {
33
+ if (opts.refreshEvents.includes(evts?.[0]?.type)) {
34
+ debouncedRefresh();
35
+ }
36
+ });
37
+ }
38
+
39
+ // watch for the vis state changing. If the page is hidden, the local inactivity timer should be paused
40
+ // if the page is brought BACK to visibility and the timer hasnt "naturally" expired, refresh the timer...
41
+ // this is to support the concept that other tabs could be experiencing activity. The thought would be that
42
+ // "backgrounded" tabs would pause, while "closed" tabs that "reopen" will just instantiate a new SessionEntity class if restored
43
+ // which will do a "hard" check of the timestamps.
44
+
45
+ // NOTE -- this does not account for 2 browser windows open side by side, blurring/focusing between them
46
+ // IF DEEMED necessary, more event handling would be needed to account for this.
47
+ (0, _pageVisibility.subscribeToVisibilityChange)(state => {
48
+ if (state === 'hidden') this.pause();
49
+ // vis change --> visible is treated like a new interaction with the page
50
+ else this.refresh();
51
+ }, false, false, this.abortController?.signal);
52
+ }
53
+ }
54
+ abort() {
55
+ this.clear();
56
+ this.abortController?.abort();
57
+ }
58
+ pause() {
59
+ this.onPause?.();
60
+ clearTimeout(this.timer);
61
+ this.remainingMs = this.initialMs - (Date.now() - this.startTimestamp);
62
+ }
63
+ refresh(cb, ms) {
64
+ this.clear();
65
+ this.timer = this.create(cb, ms);
66
+ this.startTimestamp = Date.now();
67
+ this.remainingMs = undefined;
68
+ this.onRefresh?.();
69
+ }
70
+
71
+ // NOT CURRENTLY UTILIZED BY ANYTHING
72
+ // resume () {
73
+ // if (!this.remainingMs || !this.isValid()) return
74
+ // this.timer = this.create(this.cb, this.remainingMs)
75
+ // this.remainingMs = undefined
76
+ // }
77
+ }
78
+ exports.InteractionTimer = InteractionTimer;