humanbehavior-js 0.0.4 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/index.js CHANGED
@@ -19,17 +19,6 @@ PERFORMANCE OF THIS SOFTWARE.
19
19
  /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
20
20
 
21
21
 
22
- var __assign = function() {
23
- __assign = Object.assign || function __assign(t) {
24
- for (var s, i = 1, n = arguments.length; i < n; i++) {
25
- s = arguments[i];
26
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
27
- }
28
- return t;
29
- };
30
- return __assign.apply(this, arguments);
31
- };
32
-
33
22
  function __awaiter$1(thisArg, _arguments, P, generator) {
34
23
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
35
24
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -40,44 +29,6 @@ function __awaiter$1(thisArg, _arguments, P, generator) {
40
29
  });
41
30
  }
42
31
 
43
- function __generator(thisArg, body) {
44
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
45
- return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
46
- function verb(n) { return function (v) { return step([n, v]); }; }
47
- function step(op) {
48
- if (f) throw new TypeError("Generator is already executing.");
49
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
50
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
51
- if (y = 0, t) op = [op[0] & 2, t.value];
52
- switch (op[0]) {
53
- case 0: case 1: t = op; break;
54
- case 4: _.label++; return { value: op[1], done: false };
55
- case 5: _.label++; y = op[1]; op = [0]; continue;
56
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
57
- default:
58
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
59
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
60
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
61
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
62
- if (t[2]) _.ops.pop();
63
- _.trys.pop(); continue;
64
- }
65
- op = body.call(thisArg, _);
66
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
67
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
68
- }
69
- }
70
-
71
- function __spreadArray(to, from, pack) {
72
- if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
73
- if (ar || !(i in from)) {
74
- if (!ar) ar = Array.prototype.slice.call(from, 0, i);
75
- ar[i] = from[i];
76
- }
77
- }
78
- return to.concat(ar || Array.prototype.slice.call(from));
79
- }
80
-
81
32
  typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
82
33
  var e = new Error(message);
83
34
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
@@ -4102,340 +4053,271 @@ function v1Bytes(rnds, msecs, nsecs, clockseq, node, buf, offset = 0) {
4102
4053
  return buf;
4103
4054
  }
4104
4055
 
4105
- var INGESTION_URL = process.env.HUMAN_BEHAVIOR_INGESTION_URL; // for development
4106
- var MAX_CHUNK_SIZE_BYTES = 1024 * 1024 * 10; // 10MB chunk size
4056
+ const MAX_CHUNK_SIZE_BYTES = 1024 * 1024 * 10; // 10MB chunk size
4107
4057
  function isChunkSizeExceeded(currentChunk, newEvent, sessionId) {
4108
- var nextChunkSize = new TextEncoder().encode(JSON.stringify({
4109
- sessionId: sessionId,
4110
- events: __spreadArray(__spreadArray([], currentChunk, true), [newEvent], false)
4058
+ const nextChunkSize = new TextEncoder().encode(JSON.stringify({
4059
+ sessionId,
4060
+ events: [...currentChunk, newEvent]
4111
4061
  })).length;
4112
4062
  return nextChunkSize > MAX_CHUNK_SIZE_BYTES;
4113
4063
  }
4114
4064
  function validateSingleEventSize(event, sessionId) {
4115
- var singleEventSize = new TextEncoder().encode(JSON.stringify({
4116
- sessionId: sessionId,
4065
+ const singleEventSize = new TextEncoder().encode(JSON.stringify({
4066
+ sessionId,
4117
4067
  events: [event]
4118
4068
  })).length;
4119
4069
  if (singleEventSize > MAX_CHUNK_SIZE_BYTES) {
4120
- throw new Error("Single event size (".concat(singleEventSize, " bytes) exceeds maximum chunk size (").concat(MAX_CHUNK_SIZE_BYTES, " bytes)"));
4070
+ throw new Error(`Single event size (${singleEventSize} bytes) exceeds maximum chunk size (${MAX_CHUNK_SIZE_BYTES} bytes)`);
4121
4071
  }
4122
4072
  }
4123
- var HumanBehaviorAPI = /** @class */ (function () {
4124
- function HumanBehaviorAPI(_a) {
4125
- var apiKey = _a.apiKey;
4073
+ class HumanBehaviorAPI {
4074
+ constructor({ apiKey, ingestionUrl }) {
4126
4075
  this.apiKey = apiKey;
4127
- if (!INGESTION_URL) {
4128
- throw new Error('HUMAN_BEHAVIOR_INGESTION_URL is not set');
4129
- }
4130
- this.baseUrl = INGESTION_URL;
4076
+ this.baseUrl = ingestionUrl;
4131
4077
  }
4132
- HumanBehaviorAPI.prototype.init = function (sessionId, userId) {
4133
- return __awaiter$1(this, void 0, void 0, function () {
4134
- var response, responseJson;
4135
- return __generator(this, function (_a) {
4136
- switch (_a.label) {
4137
- case 0: return [4 /*yield*/, fetch("".concat(this.baseUrl, "/api/ingestion/init"), {
4138
- method: 'POST',
4139
- headers: {
4140
- 'Content-Type': 'application/json',
4141
- 'Authorization': "Bearer ".concat(this.apiKey)
4142
- },
4143
- body: JSON.stringify({
4144
- sessionId: sessionId,
4145
- endUserId: userId
4146
- })
4147
- })];
4148
- case 1:
4149
- response = _a.sent();
4150
- if (!response.ok) {
4151
- throw new Error("Failed to initialize ingestion: ".concat(response.statusText));
4152
- }
4153
- return [4 /*yield*/, response.json()];
4154
- case 2:
4155
- responseJson = _a.sent();
4156
- return [2 /*return*/, {
4157
- sessionId: responseJson.sessionId,
4158
- endUserId: responseJson.endUserId
4159
- }];
4160
- }
4078
+ init(sessionId, userId) {
4079
+ return __awaiter$1(this, void 0, void 0, function* () {
4080
+ const response = yield fetch(`${this.baseUrl}/api/ingestion/init`, {
4081
+ method: 'POST',
4082
+ headers: {
4083
+ 'Content-Type': 'application/json',
4084
+ 'Authorization': `Bearer ${this.apiKey}`
4085
+ },
4086
+ body: JSON.stringify({
4087
+ sessionId: sessionId,
4088
+ endUserId: userId
4089
+ })
4161
4090
  });
4091
+ if (!response.ok) {
4092
+ throw new Error(`Failed to initialize ingestion: ${response.statusText}`);
4093
+ }
4094
+ const responseJson = yield response.json();
4095
+ return {
4096
+ sessionId: responseJson.sessionId,
4097
+ endUserId: responseJson.endUserId
4098
+ };
4162
4099
  });
4163
- };
4164
- HumanBehaviorAPI.prototype.sendEvents = function (events, sessionId, userId) {
4165
- return __awaiter$1(this, void 0, void 0, function () {
4166
- var response;
4167
- return __generator(this, function (_a) {
4168
- switch (_a.label) {
4169
- case 0: return [4 /*yield*/, fetch("".concat(this.baseUrl, "/api/ingestion/events"), {
4170
- method: 'POST',
4171
- headers: {
4172
- 'Content-Type': 'application/json',
4173
- 'Authorization': "Bearer ".concat(this.apiKey)
4174
- },
4175
- body: JSON.stringify({
4176
- sessionId: sessionId,
4177
- events: events,
4178
- endUserId: userId
4179
- })
4180
- })];
4181
- case 1:
4182
- response = _a.sent();
4183
- if (!response.ok) {
4184
- throw new Error("Failed to send events: ".concat(response.statusText));
4185
- }
4186
- return [2 /*return*/];
4187
- }
4100
+ }
4101
+ sendEvents(events, sessionId, userId) {
4102
+ return __awaiter$1(this, void 0, void 0, function* () {
4103
+ const response = yield fetch(`${this.baseUrl}/api/ingestion/events`, {
4104
+ method: 'POST',
4105
+ headers: {
4106
+ 'Content-Type': 'application/json',
4107
+ 'Authorization': `Bearer ${this.apiKey}`
4108
+ },
4109
+ body: JSON.stringify({
4110
+ sessionId,
4111
+ events: events,
4112
+ endUserId: userId
4113
+ })
4188
4114
  });
4115
+ if (!response.ok) {
4116
+ throw new Error(`Failed to send events: ${response.statusText}`);
4117
+ }
4189
4118
  });
4190
- };
4191
- HumanBehaviorAPI.prototype.sendEventsChunked = function (events, sessionId) {
4192
- return __awaiter$1(this, void 0, void 0, function () {
4193
- var results, currentChunk, _i, events_1, event_1, response, _a, _b, response, _c, _d, error_1;
4194
- return __generator(this, function (_e) {
4195
- switch (_e.label) {
4196
- case 0:
4197
- _e.trys.push([0, 11, , 12]);
4198
- results = [];
4199
- currentChunk = [];
4200
- _i = 0, events_1 = events;
4201
- _e.label = 1;
4202
- case 1:
4203
- if (!(_i < events_1.length)) return [3 /*break*/, 7];
4204
- event_1 = events_1[_i];
4205
- if (!isChunkSizeExceeded(currentChunk, event_1, sessionId)) return [3 /*break*/, 5];
4206
- if (!(currentChunk.length > 0)) return [3 /*break*/, 4];
4207
- return [4 /*yield*/, fetch("".concat(this.baseUrl, "/api/ingestion/events"), {
4119
+ }
4120
+ sendEventsChunked(events, sessionId) {
4121
+ return __awaiter$1(this, void 0, void 0, function* () {
4122
+ try {
4123
+ const results = [];
4124
+ let currentChunk = [];
4125
+ for (const event of events) {
4126
+ if (isChunkSizeExceeded(currentChunk, event, sessionId)) {
4127
+ // If current chunk is not empty, send it first
4128
+ if (currentChunk.length > 0) {
4129
+ const response = yield fetch(`${this.baseUrl}/api/ingestion/events`, {
4208
4130
  method: 'POST',
4209
4131
  headers: {
4210
4132
  'Content-Type': 'application/json',
4211
- 'Authorization': "Bearer ".concat(this.apiKey)
4133
+ 'Authorization': `Bearer ${this.apiKey}`
4212
4134
  },
4213
4135
  body: JSON.stringify({
4214
- sessionId: sessionId,
4136
+ sessionId,
4215
4137
  events: currentChunk
4216
4138
  })
4217
- })];
4218
- case 2:
4219
- response = _e.sent();
4220
- if (!response.ok) {
4221
- throw new Error("Failed to send events: ".concat(response.statusText));
4139
+ });
4140
+ if (!response.ok) {
4141
+ throw new Error(`Failed to send events: ${response.statusText}`);
4142
+ }
4143
+ results.push(yield response.json());
4144
+ currentChunk = [];
4222
4145
  }
4223
- _b = (_a = results).push;
4224
- return [4 /*yield*/, response.json()];
4225
- case 3:
4226
- _b.apply(_a, [_e.sent()]);
4227
- currentChunk = [];
4228
- _e.label = 4;
4229
- case 4:
4230
4146
  // Validate single event size
4231
- validateSingleEventSize(event_1, sessionId);
4147
+ validateSingleEventSize(event, sessionId);
4232
4148
  // Start new chunk with this event
4233
- currentChunk = [event_1];
4234
- return [3 /*break*/, 6];
4235
- case 5:
4149
+ currentChunk = [event];
4150
+ }
4151
+ else {
4236
4152
  // Add event to current chunk
4237
- currentChunk.push(event_1);
4238
- _e.label = 6;
4239
- case 6:
4240
- _i++;
4241
- return [3 /*break*/, 1];
4242
- case 7:
4243
- if (!(currentChunk.length > 0)) return [3 /*break*/, 10];
4244
- return [4 /*yield*/, fetch("".concat(this.baseUrl, "/api/ingestion/events"), {
4245
- method: 'POST',
4246
- headers: {
4247
- 'Content-Type': 'application/json',
4248
- 'Authorization': "Bearer ".concat(this.apiKey)
4249
- },
4250
- body: JSON.stringify({
4251
- sessionId: sessionId,
4252
- events: currentChunk
4253
- })
4254
- })];
4255
- case 8:
4256
- response = _e.sent();
4257
- if (!response.ok) {
4258
- throw new Error("Failed to send events: ".concat(response.statusText));
4259
- }
4260
- _d = (_c = results).push;
4261
- return [4 /*yield*/, response.json()];
4262
- case 9:
4263
- _d.apply(_c, [_e.sent()]);
4264
- _e.label = 10;
4265
- case 10: return [2 /*return*/, results.flat()];
4266
- case 11:
4267
- error_1 = _e.sent();
4268
- console.error('Error sending events:', error_1);
4269
- throw error_1;
4270
- case 12: return [2 /*return*/];
4153
+ currentChunk.push(event);
4154
+ }
4271
4155
  }
4272
- });
4156
+ // Send any remaining events
4157
+ if (currentChunk.length > 0) {
4158
+ const response = yield fetch(`${this.baseUrl}/api/ingestion/events`, {
4159
+ method: 'POST',
4160
+ headers: {
4161
+ 'Content-Type': 'application/json',
4162
+ 'Authorization': `Bearer ${this.apiKey}`
4163
+ },
4164
+ body: JSON.stringify({
4165
+ sessionId,
4166
+ events: currentChunk
4167
+ })
4168
+ });
4169
+ if (!response.ok) {
4170
+ throw new Error(`Failed to send events: ${response.statusText}`);
4171
+ }
4172
+ results.push(yield response.json());
4173
+ }
4174
+ return results.flat();
4175
+ }
4176
+ catch (error) {
4177
+ console.error('Error sending events:', error);
4178
+ throw error;
4179
+ }
4273
4180
  });
4274
- };
4275
- HumanBehaviorAPI.prototype.sendUserData = function (userId, userData, sessionId) {
4276
- return __awaiter$1(this, void 0, void 0, function () {
4277
- var response, error_2;
4278
- return __generator(this, function (_a) {
4279
- switch (_a.label) {
4280
- case 0:
4281
- _a.trys.push([0, 3, , 4]);
4282
- return [4 /*yield*/, fetch("".concat(this.baseUrl, "/api/ingestion/user"), {
4283
- method: 'POST',
4284
- headers: {
4285
- 'Content-Type': 'application/json',
4286
- 'Authorization': "Bearer ".concat(this.apiKey)
4287
- },
4288
- body: JSON.stringify({
4289
- userId: userId,
4290
- userAttributes: userData,
4291
- sessionId: sessionId
4292
- })
4293
- })];
4294
- case 1:
4295
- response = _a.sent();
4296
- if (!response.ok) {
4297
- throw new Error("Failed to send user data: ".concat(response.statusText, " with API key: ").concat(this.apiKey));
4298
- }
4299
- return [4 /*yield*/, response.json()];
4300
- case 2: return [2 /*return*/, _a.sent()];
4301
- case 3:
4302
- error_2 = _a.sent();
4303
- console.error('Error sending user data:', error_2);
4304
- throw error_2;
4305
- case 4: return [2 /*return*/];
4181
+ }
4182
+ sendUserData(userId, userData, sessionId) {
4183
+ return __awaiter$1(this, void 0, void 0, function* () {
4184
+ try {
4185
+ const response = yield fetch(`${this.baseUrl}/api/ingestion/user`, {
4186
+ method: 'POST',
4187
+ headers: {
4188
+ 'Content-Type': 'application/json',
4189
+ 'Authorization': `Bearer ${this.apiKey}`
4190
+ },
4191
+ body: JSON.stringify({
4192
+ userId: userId,
4193
+ userAttributes: userData,
4194
+ sessionId: sessionId
4195
+ })
4196
+ });
4197
+ if (!response.ok) {
4198
+ throw new Error(`Failed to send user data: ${response.statusText} with API key: ${this.apiKey}`);
4306
4199
  }
4307
- });
4200
+ return yield response.json();
4201
+ }
4202
+ catch (error) {
4203
+ console.error('Error sending user data:', error);
4204
+ throw error;
4205
+ }
4308
4206
  });
4309
- };
4310
- HumanBehaviorAPI.prototype.sendSessionComplete = function (sessionId) {
4311
- return __awaiter$1(this, void 0, void 0, function () {
4312
- var response;
4313
- return __generator(this, function (_a) {
4314
- switch (_a.label) {
4315
- case 0: return [4 /*yield*/, fetch("".concat(this.baseUrl, "/api/ingestion/sessionComplete"), {
4316
- method: 'POST',
4317
- headers: {
4318
- 'Content-Type': 'application/json',
4319
- 'Authorization': "Bearer ".concat(this.apiKey)
4320
- },
4321
- body: JSON.stringify({ sessionId: sessionId })
4322
- })];
4323
- case 1:
4324
- response = _a.sent();
4325
- if (!response.ok) {
4326
- throw new Error("Failed to send session complete: ".concat(response.statusText));
4327
- }
4328
- return [2 /*return*/];
4207
+ }
4208
+ sendUserAuth(userId, userData, sessionId, authFields) {
4209
+ return __awaiter$1(this, void 0, void 0, function* () {
4210
+ try {
4211
+ const response = yield fetch(`${this.baseUrl}/api/ingestion/user/auth`, {
4212
+ method: 'POST',
4213
+ headers: {
4214
+ 'Content-Type': 'application/json',
4215
+ 'Authorization': `Bearer ${this.apiKey}`
4216
+ },
4217
+ body: JSON.stringify({
4218
+ userId: userId,
4219
+ userAttributes: userData,
4220
+ sessionId: sessionId,
4221
+ authFields: authFields
4222
+ })
4223
+ });
4224
+ if (!response.ok) {
4225
+ throw new Error(`Failed to authenticate user: ${response.statusText} with API key: ${this.apiKey}`);
4329
4226
  }
4227
+ return yield response.json();
4228
+ }
4229
+ catch (error) {
4230
+ console.error('Error authenticating user:', error);
4231
+ throw error;
4232
+ }
4233
+ });
4234
+ }
4235
+ sendSessionComplete(sessionId) {
4236
+ return __awaiter$1(this, void 0, void 0, function* () {
4237
+ const response = yield fetch(`${this.baseUrl}/api/ingestion/sessionComplete`, {
4238
+ method: 'POST',
4239
+ headers: {
4240
+ 'Content-Type': 'application/json',
4241
+ 'Authorization': `Bearer ${this.apiKey}`
4242
+ },
4243
+ body: JSON.stringify({ sessionId })
4330
4244
  });
4245
+ if (!response.ok) {
4246
+ throw new Error(`Failed to send session complete: ${response.statusText}`);
4247
+ }
4331
4248
  });
4332
- };
4333
- HumanBehaviorAPI.prototype.sendCustomEvent = function (eventName, eventProperties, sessionId) {
4334
- return __awaiter$1(this, void 0, void 0, function () {
4335
- var maxRetries, retryCount, response, error_3;
4336
- return __generator(this, function (_a) {
4337
- switch (_a.label) {
4338
- case 0:
4339
- maxRetries = 3;
4340
- retryCount = 0;
4341
- _a.label = 1;
4342
- case 1:
4343
- if (!(retryCount < maxRetries)) return [3 /*break*/, 8];
4344
- _a.label = 2;
4345
- case 2:
4346
- _a.trys.push([2, 5, , 7]);
4347
- return [4 /*yield*/, fetch("".concat(this.baseUrl, "/api/ingestion/customEvent"), {
4348
- method: 'POST',
4349
- headers: {
4350
- 'Content-Type': 'application/json',
4351
- 'Authorization': "Bearer ".concat(this.apiKey)
4352
- },
4353
- body: JSON.stringify({
4354
- name: eventName,
4355
- properties: eventProperties,
4356
- sessionId: sessionId,
4357
- timestamp: new Date().toISOString()
4358
- })
4359
- })];
4360
- case 3:
4361
- response = _a.sent();
4362
- if (!response.ok) {
4363
- throw new Error("Failed to send custom event: ".concat(response.statusText));
4364
- }
4365
- return [4 /*yield*/, response.json()];
4366
- case 4: return [2 /*return*/, _a.sent()];
4367
- case 5:
4368
- error_3 = _a.sent();
4369
- retryCount++;
4370
- if (retryCount === maxRetries) {
4371
- console.error('Error sending custom event after max retries:', error_3);
4372
- throw error_3;
4373
- }
4374
- // Exponential backoff
4375
- return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, Math.pow(2, retryCount) * 1000); })];
4376
- case 6:
4377
- // Exponential backoff
4378
- _a.sent();
4379
- return [3 /*break*/, 7];
4380
- case 7: return [3 /*break*/, 1];
4381
- case 8: return [2 /*return*/];
4249
+ }
4250
+ sendCustomEvent(eventName, eventProperties, sessionId) {
4251
+ return __awaiter$1(this, void 0, void 0, function* () {
4252
+ const maxRetries = 3;
4253
+ let retryCount = 0;
4254
+ while (retryCount < maxRetries) {
4255
+ try {
4256
+ const response = yield fetch(`${this.baseUrl}/api/ingestion/customEvent`, {
4257
+ method: 'POST',
4258
+ headers: {
4259
+ 'Content-Type': 'application/json',
4260
+ 'Authorization': `Bearer ${this.apiKey}`
4261
+ },
4262
+ body: JSON.stringify({
4263
+ name: eventName,
4264
+ properties: eventProperties,
4265
+ sessionId: sessionId,
4266
+ timestamp: new Date().toISOString()
4267
+ })
4268
+ });
4269
+ if (!response.ok) {
4270
+ throw new Error(`Failed to send custom event: ${response.statusText}`);
4271
+ }
4272
+ return yield response.json();
4382
4273
  }
4383
- });
4274
+ catch (error) {
4275
+ retryCount++;
4276
+ if (retryCount === maxRetries) {
4277
+ console.error('Error sending custom event after max retries:', error);
4278
+ throw error;
4279
+ }
4280
+ // Exponential backoff
4281
+ yield new Promise(resolve => setTimeout(resolve, Math.pow(2, retryCount) * 1000));
4282
+ }
4283
+ }
4384
4284
  });
4385
- };
4386
- HumanBehaviorAPI.prototype.sendCustomEvents = function (events, sessionId) {
4387
- return __awaiter$1(this, void 0, void 0, function () {
4388
- var maxRetries, retryCount, response, error_4;
4389
- return __generator(this, function (_a) {
4390
- switch (_a.label) {
4391
- case 0:
4392
- maxRetries = 3;
4393
- retryCount = 0;
4394
- _a.label = 1;
4395
- case 1:
4396
- if (!(retryCount < maxRetries)) return [3 /*break*/, 8];
4397
- _a.label = 2;
4398
- case 2:
4399
- _a.trys.push([2, 5, , 7]);
4400
- return [4 /*yield*/, fetch("".concat(this.baseUrl, "/api/ingestion/customEvent/batch"), {
4401
- method: 'POST',
4402
- headers: {
4403
- 'Content-Type': 'application/json',
4404
- 'Authorization': "Bearer ".concat(this.apiKey)
4405
- },
4406
- body: JSON.stringify({
4407
- events: events.map(function (event) { return (__assign(__assign({}, event), { sessionId: sessionId })); })
4408
- })
4409
- })];
4410
- case 3:
4411
- response = _a.sent();
4412
- if (!response.ok) {
4413
- throw new Error("Failed to send custom events: ".concat(response.statusText));
4414
- }
4415
- return [4 /*yield*/, response.json()];
4416
- case 4: return [2 /*return*/, _a.sent()];
4417
- case 5:
4418
- error_4 = _a.sent();
4419
- retryCount++;
4420
- if (retryCount === maxRetries) {
4421
- console.error('Error sending custom events after max retries:', error_4);
4422
- throw error_4;
4423
- }
4424
- // Exponential backoff
4425
- return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, Math.pow(2, retryCount) * 1000); })];
4426
- case 6:
4427
- // Exponential backoff
4428
- _a.sent();
4429
- return [3 /*break*/, 7];
4430
- case 7: return [3 /*break*/, 1];
4431
- case 8: return [2 /*return*/];
4285
+ }
4286
+ sendCustomEvents(events, sessionId) {
4287
+ return __awaiter$1(this, void 0, void 0, function* () {
4288
+ const maxRetries = 3;
4289
+ let retryCount = 0;
4290
+ while (retryCount < maxRetries) {
4291
+ try {
4292
+ const response = yield fetch(`${this.baseUrl}/api/ingestion/customEvent/batch`, {
4293
+ method: 'POST',
4294
+ headers: {
4295
+ 'Content-Type': 'application/json',
4296
+ 'Authorization': `Bearer ${this.apiKey}`
4297
+ },
4298
+ body: JSON.stringify({
4299
+ events: events.map(event => (Object.assign(Object.assign({}, event), { sessionId: sessionId })))
4300
+ })
4301
+ });
4302
+ if (!response.ok) {
4303
+ throw new Error(`Failed to send custom events: ${response.statusText}`);
4304
+ }
4305
+ return yield response.json();
4432
4306
  }
4433
- });
4307
+ catch (error) {
4308
+ retryCount++;
4309
+ if (retryCount === maxRetries) {
4310
+ console.error('Error sending custom events after max retries:', error);
4311
+ throw error;
4312
+ }
4313
+ // Exponential backoff
4314
+ yield new Promise(resolve => setTimeout(resolve, Math.pow(2, retryCount) * 1000));
4315
+ }
4316
+ }
4434
4317
  });
4435
- };
4436
- HumanBehaviorAPI.prototype.sendBeaconEvents = function (events, sessionId, isSessionComplete) {
4437
- if (isSessionComplete === void 0) { isSessionComplete = false; }
4438
- var data = new URLSearchParams();
4318
+ }
4319
+ sendBeaconEvents(events, sessionId, isSessionComplete = false) {
4320
+ const data = new URLSearchParams();
4439
4321
  data.append('events', encodeURIComponent(JSON.stringify(events)));
4440
4322
  data.append('sessionId', encodeURIComponent(sessionId));
4441
4323
  data.append('timestamp', encodeURIComponent(Date.now().toString()));
@@ -4445,41 +4327,453 @@ var HumanBehaviorAPI = /** @class */ (function () {
4445
4327
  localStorage.setItem('koalaware_session_complete', Date.now().toString());
4446
4328
  data.append('sessionComplete', encodeURIComponent('true'));
4447
4329
  }
4448
- navigator.sendBeacon("".concat(this.baseUrl, "/api/ingestion/events"), data);
4330
+ navigator.sendBeacon(`${this.baseUrl}/api/ingestion/events`, data);
4449
4331
  // KoalawareTracker.logToStorage(`Sending events beacon: ${this.baseUrl}/api/ingestion/events`);
4450
4332
  // KoalawareTracker.logToStorage(`Events beacon success: ${success}`);
4451
- };
4452
- HumanBehaviorAPI.prototype.sendBeaconSessionComplete = function (sessionId) {
4453
- var data = new URLSearchParams();
4333
+ }
4334
+ sendBeaconSessionComplete(sessionId) {
4335
+ const data = new URLSearchParams();
4454
4336
  data.append('sessionId', sessionId);
4455
4337
  data.append('apiKey', this.apiKey);
4456
4338
  data.append('sessionComplete', 'true');
4457
- navigator.sendBeacon("".concat(this.baseUrl, "/api/ingestion/sessionComplete"), data);
4339
+ navigator.sendBeacon(`${this.baseUrl}/api/ingestion/sessionComplete`, data);
4458
4340
  // KoalawareTracker.logToStorage(`Sending completion beacon: ${this.baseUrl}/api/ingestion/sessionComplete`);
4459
4341
  // KoalawareTracker.logToStorage(`Complete beacon success: ${success}`);
4460
- };
4461
- HumanBehaviorAPI.prototype.sendBeaconCustomEvent = function (eventName, eventProperties, sessionId) {
4462
- var data = new URLSearchParams();
4342
+ }
4343
+ sendBeaconCustomEvent(eventName, eventProperties, sessionId) {
4344
+ const data = new URLSearchParams();
4463
4345
  data.append('name', encodeURIComponent(eventName));
4464
4346
  data.append('properties', encodeURIComponent(JSON.stringify(eventProperties)));
4465
4347
  data.append('sessionId', encodeURIComponent(sessionId));
4466
4348
  data.append('timestamp', encodeURIComponent(new Date().toISOString()));
4467
4349
  data.append('apiKey', encodeURIComponent(this.apiKey));
4468
- return navigator.sendBeacon("".concat(this.baseUrl, "/api/ingestion/customEvent"), data);
4469
- };
4470
- HumanBehaviorAPI.prototype.sendBeaconCustomEvents = function (events, sessionId) {
4471
- var data = new URLSearchParams();
4472
- data.append('events', encodeURIComponent(JSON.stringify(events.map(function (event) { return (__assign(__assign({}, event), { sessionId: sessionId })); }))));
4350
+ return navigator.sendBeacon(`${this.baseUrl}/api/ingestion/customEvent`, data);
4351
+ }
4352
+ sendBeaconCustomEvents(events, sessionId) {
4353
+ const data = new URLSearchParams();
4354
+ data.append('events', encodeURIComponent(JSON.stringify(events.map(event => (Object.assign(Object.assign({}, event), { sessionId: sessionId }))))));
4473
4355
  data.append('apiKey', encodeURIComponent(this.apiKey));
4474
- return navigator.sendBeacon("".concat(this.baseUrl, "/api/ingestion/customEvent/batch"), data);
4475
- };
4476
- return HumanBehaviorAPI;
4477
- }());
4356
+ return navigator.sendBeacon(`${this.baseUrl}/api/ingestion/customEvent/batch`, data);
4357
+ }
4358
+ }
4359
+
4360
+ // Redaction functionality for sensitive input fields
4361
+ // This module provides methods to redact sensitive input fields in event recordings
4362
+ // Check if we're in a browser environment
4363
+ const isBrowser$1 = typeof window !== 'undefined';
4364
+ class RedactionManager {
4365
+ constructor(options) {
4366
+ this.redactedText = '[REDACTED]';
4367
+ this.userSelectedFields = new Set(); // User-selected fields to redact
4368
+ this.excludeSelectors = [
4369
+ '[data-no-redact="true"]',
4370
+ '.human-behavior-no-redact'
4371
+ ];
4372
+ if (options === null || options === void 0 ? void 0 : options.redactedText) {
4373
+ this.redactedText = options.redactedText;
4374
+ }
4375
+ if (options === null || options === void 0 ? void 0 : options.excludeSelectors) {
4376
+ this.excludeSelectors = [...this.excludeSelectors, ...options.excludeSelectors];
4377
+ }
4378
+ if (options === null || options === void 0 ? void 0 : options.userFields) {
4379
+ this.setFieldsToRedact(options.userFields);
4380
+ }
4381
+ }
4382
+ /**
4383
+ * Set specific fields to be redacted
4384
+ * @param fields Array of CSS selectors for fields to redact
4385
+ */
4386
+ setFieldsToRedact(fields) {
4387
+ this.userSelectedFields.clear();
4388
+ fields.forEach(field => this.userSelectedFields.add(field));
4389
+ if (fields.length > 0) {
4390
+ console.log(`Redaction: Active for ${fields.length} field(s):`, fields);
4391
+ // Debug: Check if elements exist
4392
+ fields.forEach(selector => {
4393
+ const elements = document.querySelectorAll(selector);
4394
+ console.log(`Redaction: Found ${elements.length} element(s) for selector '${selector}'`);
4395
+ elements.forEach((el, index) => {
4396
+ console.log(`Redaction: Element ${index} for '${selector}':`, el);
4397
+ });
4398
+ });
4399
+ }
4400
+ else {
4401
+ console.log('Redaction: Disabled - no fields selected');
4402
+ }
4403
+ }
4404
+ /**
4405
+ * Check if redaction is currently active (has fields selected)
4406
+ */
4407
+ isActive() {
4408
+ return this.userSelectedFields.size > 0;
4409
+ }
4410
+ /**
4411
+ * Get the currently selected fields for redaction
4412
+ */
4413
+ getSelectedFields() {
4414
+ return Array.from(this.userSelectedFields);
4415
+ }
4416
+ /**
4417
+ * Process an event and redact sensitive data if needed
4418
+ */
4419
+ processEvent(event) {
4420
+ // Only process if we have fields selected for redaction
4421
+ if (this.userSelectedFields.size === 0) {
4422
+ return event;
4423
+ }
4424
+ // Clone the event to avoid modifying the original
4425
+ const processedEvent = JSON.parse(JSON.stringify(event));
4426
+ // Handle different event types
4427
+ if (processedEvent.type === 3) { // IncrementalSnapshot
4428
+ if (processedEvent.data.source === 5) { // Input event
4429
+ const shouldRedact = this.isFieldSelected(processedEvent.data);
4430
+ if (shouldRedact) {
4431
+ console.log('Redaction: Processing input event for redaction');
4432
+ this.redactInputEvent(processedEvent.data);
4433
+ }
4434
+ }
4435
+ // Also check for other sources that might contain text changes
4436
+ else if (processedEvent.data.source === 0) { // DOM mutations
4437
+ this.redactDOMEvent(processedEvent.data);
4438
+ }
4439
+ // Handle other sources that might contain text
4440
+ else if (processedEvent.data.source === 2) { // Mouse/Touch interaction
4441
+ this.redactMouseEvent(processedEvent.data);
4442
+ }
4443
+ }
4444
+ else if (processedEvent.type === 2) { // FullSnapshot
4445
+ this.redactFullSnapshot(processedEvent.data);
4446
+ }
4447
+ return processedEvent;
4448
+ }
4449
+ /**
4450
+ * Redact sensitive data in input events
4451
+ */
4452
+ redactInputEvent(inputData) {
4453
+ // Check if this input event is from a field we want to redact
4454
+ if (!this.isFieldSelected(inputData)) {
4455
+ return;
4456
+ }
4457
+ console.log('Redaction: Redacting input event with text:', inputData.text);
4458
+ // Redact all text-related properties that could contain input data
4459
+ const textProperties = ['text', 'value', 'content', 'data', 'input', 'textContent'];
4460
+ textProperties.forEach(prop => {
4461
+ if (inputData[prop] !== undefined && typeof inputData[prop] === 'string') {
4462
+ inputData[prop] = this.redactedText;
4463
+ console.log(`Redaction: Redacted property '${prop}'`);
4464
+ }
4465
+ });
4466
+ // Also check for any other string properties that might contain input data
4467
+ Object.keys(inputData).forEach(key => {
4468
+ if (typeof inputData[key] === 'string' && inputData[key].length > 0) {
4469
+ inputData[key] = this.redactedText;
4470
+ console.log(`Redaction: Redacted additional property '${key}'`);
4471
+ }
4472
+ });
4473
+ // Handle nested objects that might contain text data
4474
+ if (inputData.attributes && typeof inputData.attributes === 'object') {
4475
+ if (inputData.attributes.value && typeof inputData.attributes.value === 'string') {
4476
+ inputData.attributes.value = this.redactedText;
4477
+ console.log('Redaction: Redacted nested value attribute');
4478
+ }
4479
+ }
4480
+ console.log('Redaction: Input event redaction complete');
4481
+ }
4482
+ /**
4483
+ * Redact sensitive data in DOM mutation events
4484
+ */
4485
+ redactDOMEvent(domData) {
4486
+ // Check for text changes in DOM mutations
4487
+ if (domData.texts && Array.isArray(domData.texts)) {
4488
+ domData.texts.forEach((textChange) => {
4489
+ if (textChange.text && typeof textChange.text === 'string' &&
4490
+ this.shouldRedactDOMChange(textChange)) {
4491
+ textChange.text = this.redactedText;
4492
+ }
4493
+ });
4494
+ }
4495
+ // Also check for attribute changes that might contain input data
4496
+ if (domData.attributes && Array.isArray(domData.attributes)) {
4497
+ domData.attributes.forEach((attrChange) => {
4498
+ if (attrChange.attributes && attrChange.attributes.value &&
4499
+ typeof attrChange.attributes.value === 'string' &&
4500
+ this.shouldRedactDOMChange(attrChange)) {
4501
+ attrChange.attributes.value = this.redactedText;
4502
+ }
4503
+ });
4504
+ }
4505
+ // Check for any other properties that might contain text data
4506
+ if (domData.adds && Array.isArray(domData.adds)) {
4507
+ domData.adds.forEach((add) => {
4508
+ if (add.node && add.node.textContent && typeof add.node.textContent === 'string' &&
4509
+ this.shouldRedactDOMChange(add)) {
4510
+ add.node.textContent = this.redactedText;
4511
+ }
4512
+ });
4513
+ }
4514
+ }
4515
+ /**
4516
+ * Check if a DOM change should be redacted based on its ID
4517
+ */
4518
+ shouldRedactDOMChange(changeData) {
4519
+ if (!isBrowser$1)
4520
+ return false;
4521
+ try {
4522
+ // Check if this change has an ID that we can use to find the element
4523
+ const elementId = changeData.id;
4524
+ if (elementId !== undefined) {
4525
+ // Try to find the element by data-rrweb-id attribute
4526
+ let element = document.querySelector(`[data-rrweb-id="${elementId}"]`);
4527
+ if (element) {
4528
+ return this.shouldRedactElement(element);
4529
+ }
4530
+ }
4531
+ // Also check for nodeId which is another way rrweb identifies elements
4532
+ const nodeId = changeData.nodeId;
4533
+ if (nodeId !== undefined) {
4534
+ const element = document.querySelector(`[data-rrweb-id="${nodeId}"]`);
4535
+ if (element) {
4536
+ return this.shouldRedactElement(element);
4537
+ }
4538
+ }
4539
+ return false;
4540
+ }
4541
+ catch (e) {
4542
+ console.warn('Error checking if DOM change should be redacted:', e);
4543
+ return false;
4544
+ }
4545
+ }
4546
+ /**
4547
+ * Redact sensitive data in mouse/touch interaction events
4548
+ */
4549
+ redactMouseEvent(mouseData) {
4550
+ // Mouse events typically don't contain text data, but check for any text properties
4551
+ if (mouseData.text && typeof mouseData.text === 'string' &&
4552
+ this.isFieldSelected(mouseData)) {
4553
+ mouseData.text = this.redactedText;
4554
+ }
4555
+ }
4556
+ /**
4557
+ * Redact sensitive data in full snapshot events
4558
+ */
4559
+ redactFullSnapshot(snapshotData) {
4560
+ if (snapshotData.node && snapshotData.node.type === 2) { // Element node
4561
+ this.redactNode(snapshotData.node);
4562
+ }
4563
+ }
4564
+ /**
4565
+ * Recursively redact sensitive data in DOM nodes
4566
+ */
4567
+ redactNode(node) {
4568
+ if (!node)
4569
+ return;
4570
+ // Check if this node should be redacted
4571
+ if (node.type === 2 && node.tagName &&
4572
+ (node.tagName.toLowerCase() === 'input' || node.tagName.toLowerCase() === 'textarea')) {
4573
+ // Check if this input/textarea should be redacted
4574
+ if (this.shouldRedactNode(node)) {
4575
+ // Redact value attribute
4576
+ if (node.attributes && node.attributes.value) {
4577
+ node.attributes.value = this.redactedText;
4578
+ }
4579
+ // Redact text content
4580
+ if (node.textContent) {
4581
+ node.textContent = this.redactedText;
4582
+ }
4583
+ }
4584
+ }
4585
+ // Recursively process child nodes
4586
+ if (node.childNodes && Array.isArray(node.childNodes)) {
4587
+ node.childNodes.forEach((childNode) => {
4588
+ this.redactNode(childNode);
4589
+ });
4590
+ }
4591
+ }
4592
+ /**
4593
+ * Check if a node should be redacted based on its attributes
4594
+ */
4595
+ shouldRedactNode(node) {
4596
+ if (!node.attributes)
4597
+ return false;
4598
+ // Check if any of our selectors would match this node
4599
+ for (const selector of this.userSelectedFields) {
4600
+ if (this.selectorMatchesNode(selector, node)) {
4601
+ return true;
4602
+ }
4603
+ }
4604
+ return false;
4605
+ }
4606
+ /**
4607
+ * Check if a CSS selector would match a node based on its attributes
4608
+ */
4609
+ selectorMatchesNode(selector, node) {
4610
+ if (!node.attributes)
4611
+ return false;
4612
+ // Create a temporary element to test the selector
4613
+ try {
4614
+ const tempElement = document.createElement(node.tagName || 'div');
4615
+ // Copy attributes from the node to the temp element
4616
+ if (node.attributes) {
4617
+ Object.keys(node.attributes).forEach(key => {
4618
+ tempElement.setAttribute(key, node.attributes[key]);
4619
+ });
4620
+ }
4621
+ // Test if the selector matches this element
4622
+ return tempElement.matches(selector);
4623
+ }
4624
+ catch (e) {
4625
+ // If matches() is not supported or fails, fall back to basic attribute checking
4626
+ return this.basicSelectorMatch(selector, node);
4627
+ }
4628
+ }
4629
+ /**
4630
+ * Basic selector matching for environments where matches() is not available
4631
+ */
4632
+ basicSelectorMatch(selector, node) {
4633
+ if (!node.attributes)
4634
+ return false;
4635
+ // Handle simple selectors like 'input[type="password"]'
4636
+ if (selector.includes('input[type=')) {
4637
+ const typeMatch = selector.match(/input\[type="([^"]+)"\]/);
4638
+ if (typeMatch && node.tagName === 'input' && node.attributes.type === typeMatch[1]) {
4639
+ return true;
4640
+ }
4641
+ }
4642
+ // Handle ID selectors like '#email'
4643
+ if (selector.startsWith('#')) {
4644
+ const id = selector.substring(1);
4645
+ return node.attributes.id === id;
4646
+ }
4647
+ // Handle class selectors like '.sensitive-field'
4648
+ if (selector.startsWith('.')) {
4649
+ const className = selector.substring(1);
4650
+ return node.attributes.class && node.attributes.class.includes(className);
4651
+ }
4652
+ // Handle tag selectors like 'input'
4653
+ if (!selector.includes('[') && !selector.includes('.')) {
4654
+ return node.tagName && node.tagName.toLowerCase() === selector.toLowerCase();
4655
+ }
4656
+ return false;
4657
+ }
4658
+ /**
4659
+ * Check if an event is from a field that should be redacted
4660
+ */
4661
+ isFieldSelected(eventData) {
4662
+ if (!isBrowser$1)
4663
+ return false;
4664
+ try {
4665
+ // For input events (source 5), we need to determine if this is a sensitive field
4666
+ if (eventData.source === 5) { // Input event
4667
+ const elementId = eventData.id;
4668
+ if (elementId !== undefined) {
4669
+ // Try to find the element by data-rrweb-id attribute
4670
+ let element = document.querySelector(`[data-rrweb-id="${elementId}"]`);
4671
+ if (element) {
4672
+ return this.shouldRedactElement(element);
4673
+ }
4674
+ // Fallback: Try to find by nodeId if available
4675
+ if (eventData.nodeId !== undefined) {
4676
+ element = document.querySelector(`[data-rrweb-id="${eventData.nodeId}"]`);
4677
+ if (element) {
4678
+ return this.shouldRedactElement(element);
4679
+ }
4680
+ }
4681
+ // More aggressive approach: Check all elements that match our selectors
4682
+ // and see if any of them are currently focused or have the same ID
4683
+ for (const selector of this.userSelectedFields) {
4684
+ const matchingElements = document.querySelectorAll(selector);
4685
+ if (matchingElements.length > 0) {
4686
+ // Check if any of these elements are currently focused
4687
+ for (const el of matchingElements) {
4688
+ if (el === document.activeElement) {
4689
+ console.log('Redaction: Found focused element matching selector:', selector);
4690
+ return true;
4691
+ }
4692
+ }
4693
+ }
4694
+ }
4695
+ // If we still can't find it, try a more direct approach
4696
+ // Look for any input element that might be the active one
4697
+ const activeElement = document.activeElement;
4698
+ if (activeElement && this.shouldRedactElement(activeElement)) {
4699
+ console.log('Redaction: Active element should be redacted');
4700
+ return true;
4701
+ }
4702
+ return false;
4703
+ }
4704
+ }
4705
+ // For other event types, try to find the element
4706
+ const elementId = eventData.id;
4707
+ if (elementId !== undefined) {
4708
+ // First try to find by data-rrweb-id attribute
4709
+ let element = document.querySelector(`[data-rrweb-id="${elementId}"]`);
4710
+ if (element) {
4711
+ return this.shouldRedactElement(element);
4712
+ }
4713
+ }
4714
+ // Also check for nodeId which is another way rrweb identifies elements
4715
+ const nodeId = eventData.nodeId;
4716
+ if (nodeId !== undefined) {
4717
+ const element = document.querySelector(`[data-rrweb-id="${nodeId}"]`);
4718
+ if (element) {
4719
+ return this.shouldRedactElement(element);
4720
+ }
4721
+ }
4722
+ // For DOM mutations, check if the target element should be redacted
4723
+ if (eventData.target && eventData.target.id) {
4724
+ const element = document.querySelector(`[data-rrweb-id="${eventData.target.id}"]`);
4725
+ if (element) {
4726
+ return this.shouldRedactElement(element);
4727
+ }
4728
+ }
4729
+ return false;
4730
+ }
4731
+ catch (e) {
4732
+ console.warn('Error checking if field should be redacted:', e);
4733
+ return false;
4734
+ }
4735
+ }
4736
+ /**
4737
+ * Check if an element should be redacted based on user-selected fields
4738
+ */
4739
+ shouldRedactElement(element) {
4740
+ // Check if element is excluded from redaction
4741
+ for (const excludeSelector of this.excludeSelectors) {
4742
+ if (element.matches(excludeSelector) || element.closest(excludeSelector)) {
4743
+ return false;
4744
+ }
4745
+ }
4746
+ // Check if element matches any of the user-selected fields
4747
+ for (const selector of this.userSelectedFields) {
4748
+ if (element.matches(selector)) {
4749
+ return true;
4750
+ }
4751
+ }
4752
+ return false;
4753
+ }
4754
+ /**
4755
+ * Get the original value of a redacted element (for debugging)
4756
+ */
4757
+ getOriginalValue(element) {
4758
+ if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {
4759
+ return element.value;
4760
+ }
4761
+ return undefined;
4762
+ }
4763
+ /**
4764
+ * Check if an element is currently being redacted
4765
+ */
4766
+ isElementRedacted(element) {
4767
+ return this.shouldRedactElement(element);
4768
+ }
4769
+ }
4770
+ // Export a default instance
4771
+ const redactionManager = new RedactionManager();
4478
4772
 
4479
4773
  // Check if we're in a browser environment
4480
- var isBrowser = typeof window !== 'undefined';
4481
- var HumanBehaviorTracker = /** @class */ (function () {
4482
- function HumanBehaviorTracker(apiKey) {
4774
+ const isBrowser = typeof window !== 'undefined';
4775
+ class HumanBehaviorTracker {
4776
+ constructor(apiKey, ingestionUrl) {
4483
4777
  this.eventIngestionQueue = [];
4484
4778
  this.queueSizeBytes = 0;
4485
4779
  this.rejectedEvents = [];
@@ -4492,18 +4786,23 @@ var HumanBehaviorTracker = /** @class */ (function () {
4492
4786
  this.initialized = false;
4493
4787
  this.initializationPromise = null;
4494
4788
  if (!apiKey) {
4495
- throw new Error('Human Behavior apiKey is required');
4789
+ throw new Error('Human Behavior API Key is required');
4790
+ }
4791
+ if (!ingestionUrl) {
4792
+ throw new Error('Human Behavior Ingestion URL is required');
4496
4793
  }
4497
4794
  this.api = new HumanBehaviorAPI({
4498
4795
  apiKey: apiKey,
4796
+ ingestionUrl: ingestionUrl
4499
4797
  });
4500
4798
  this.apiKey = apiKey;
4799
+ this.redactionManager = new RedactionManager();
4501
4800
  // Check for existing session ID and last activity time in localStorage
4502
- var existingSessionId = isBrowser ? localStorage.getItem('human_behavior_session_id') : null;
4503
- var lastActivity = isBrowser ? localStorage.getItem('human_behavior_last_activity') : null;
4801
+ const existingSessionId = isBrowser ? localStorage.getItem('human_behavior_session_id') : null;
4802
+ const lastActivity = isBrowser ? localStorage.getItem('human_behavior_last_activity') : null;
4504
4803
  // If we have a last activity time, check if it's within 30 minutes
4505
- var thirtyMinutesAgo = Date.now() - (30 * 60 * 1000);
4506
- var shouldUseExistingSession = lastActivity && parseInt(lastActivity) > thirtyMinutesAgo;
4804
+ const thirtyMinutesAgo = Date.now() - (30 * 60 * 1000);
4805
+ const shouldUseExistingSession = lastActivity && parseInt(lastActivity) > thirtyMinutesAgo;
4507
4806
  this.sessionId = (existingSessionId && shouldUseExistingSession) ? existingSessionId : v1();
4508
4807
  // Store the session ID if it's new
4509
4808
  if ((!existingSessionId || !shouldUseExistingSession) && isBrowser) {
@@ -4512,305 +4811,305 @@ var HumanBehaviorTracker = /** @class */ (function () {
4512
4811
  // Start initialization immediately
4513
4812
  this.initializationPromise = this.init();
4514
4813
  }
4515
- HumanBehaviorTracker.prototype.init = function () {
4516
- return __awaiter$1(this, void 0, void 0, function () {
4517
- var userId, _a, sessionId, endUserId, error_1;
4518
- return __generator(this, function (_b) {
4519
- switch (_b.label) {
4520
- case 0:
4521
- _b.trys.push([0, 2, , 3]);
4522
- userId = this.getCookie("human_behavior_end_user_id_".concat(this.apiKey));
4523
- return [4 /*yield*/, this.api.init(this.sessionId, userId)];
4524
- case 1:
4525
- _a = _b.sent(), sessionId = _a.sessionId, endUserId = _a.endUserId;
4526
- this.sessionId = sessionId;
4527
- this.endUserId = endUserId;
4528
- this.setCookie("human_behavior_end_user_id_".concat(this.apiKey), endUserId, 365);
4529
- // Only setup browser-specific handlers when in browser environment
4530
- if (isBrowser) {
4531
- this.setupPageUnloadHandler();
4532
- this.start();
4533
- this.processRejectedEvents();
4534
- }
4535
- else {
4536
- console.warn('HumanBehaviorTracker initialized in a non-browser environment. Session tracking is disabled.');
4537
- }
4538
- this.initialized = true;
4539
- console.log('HumanBehaviorTracker initialized');
4540
- return [3 /*break*/, 3];
4541
- case 2:
4542
- error_1 = _b.sent();
4543
- console.error('Failed to initialize HumanBehaviorTracker:', error_1);
4544
- throw error_1;
4545
- case 3: return [2 /*return*/];
4814
+ init() {
4815
+ return __awaiter$1(this, void 0, void 0, function* () {
4816
+ try {
4817
+ const userId = this.getCookie(`human_behavior_end_user_id_${this.apiKey}`);
4818
+ const { sessionId, endUserId } = yield this.api.init(this.sessionId, userId);
4819
+ this.sessionId = sessionId;
4820
+ this.endUserId = endUserId;
4821
+ this.setCookie(`human_behavior_end_user_id_${this.apiKey}`, endUserId, 365);
4822
+ // Only setup browser-specific handlers when in browser environment
4823
+ if (isBrowser) {
4824
+ this.setupPageUnloadHandler();
4825
+ this.start();
4826
+ this.processRejectedEvents();
4546
4827
  }
4547
- });
4548
- });
4549
- };
4550
- HumanBehaviorTracker.prototype.ensureInitialized = function () {
4551
- return __awaiter$1(this, void 0, void 0, function () {
4552
- return __generator(this, function (_a) {
4553
- switch (_a.label) {
4554
- case 0:
4555
- if (!this.initializationPromise) {
4556
- throw new Error('HumanBehaviorTracker initialization failed');
4557
- }
4558
- return [4 /*yield*/, this.initializationPromise];
4559
- case 1:
4560
- _a.sent();
4561
- return [2 /*return*/];
4828
+ else {
4829
+ console.warn('HumanBehaviorTracker initialized in a non-browser environment. Session tracking is disabled.');
4562
4830
  }
4563
- });
4831
+ this.initialized = true;
4832
+ console.log('HumanBehaviorTracker initialized');
4833
+ }
4834
+ catch (error) {
4835
+ console.error('Failed to initialize HumanBehaviorTracker:', error);
4836
+ throw error;
4837
+ }
4564
4838
  });
4565
- };
4566
- HumanBehaviorTracker.logToStorage = function (message) {
4839
+ }
4840
+ ensureInitialized() {
4841
+ return __awaiter$1(this, void 0, void 0, function* () {
4842
+ if (!this.initializationPromise) {
4843
+ throw new Error('HumanBehaviorTracker initialization failed');
4844
+ }
4845
+ yield this.initializationPromise;
4846
+ });
4847
+ }
4848
+ static logToStorage(message) {
4567
4849
  try {
4568
- var logs = JSON.parse(localStorage.getItem('human_behavior_logs') || '[]');
4569
- logs.push("".concat(new Date().toISOString(), ": ").concat(message));
4850
+ const logs = JSON.parse(localStorage.getItem('human_behavior_logs') || '[]');
4851
+ logs.push(`${new Date().toISOString()}: ${message}`);
4570
4852
  localStorage.setItem('human_behavior_logs', JSON.stringify(logs));
4571
4853
  }
4572
4854
  catch (e) {
4573
4855
  console.error('Failed to log to storage:', e);
4574
4856
  }
4575
- };
4576
- HumanBehaviorTracker.prototype.setupPageUnloadHandler = function () {
4577
- var _this = this;
4857
+ }
4858
+ setupPageUnloadHandler() {
4578
4859
  if (!isBrowser)
4579
4860
  return;
4580
4861
  console.log('Setting up page unload handler');
4581
4862
  // Handle visibility changes for sending events
4582
- window.addEventListener('visibilitychange', function () {
4863
+ window.addEventListener('visibilitychange', () => {
4583
4864
  // Only send events when page becomes hidden
4584
4865
  if (document.visibilityState === 'hidden') {
4585
4866
  console.log('Page hidden - sending pending events');
4586
- _this.api.sendBeaconEvents(_this.eventIngestionQueue, _this.sessionId);
4867
+ this.api.sendBeaconEvents(this.eventIngestionQueue, this.sessionId);
4587
4868
  }
4588
4869
  });
4589
4870
  // Handle actual page unload/close
4590
- window.addEventListener('beforeunload', function () {
4871
+ window.addEventListener('beforeunload', () => {
4591
4872
  // Update last activity time
4592
4873
  localStorage.setItem('human_behavior_last_activity', Date.now().toString());
4593
4874
  // Send final events
4594
- _this.api.sendBeaconEvents(_this.eventIngestionQueue, _this.sessionId);
4875
+ this.api.sendBeaconEvents(this.eventIngestionQueue, this.sessionId);
4595
4876
  });
4596
4877
  // Update activity timestamp periodically
4597
- setInterval(function () {
4878
+ setInterval(() => {
4598
4879
  localStorage.setItem('human_behavior_last_activity', Date.now().toString());
4599
4880
  }, 60000); // Update every minute
4600
- };
4601
- HumanBehaviorTracker.prototype.viewLogs = function () {
4881
+ }
4882
+ viewLogs() {
4602
4883
  try {
4603
- var logs = JSON.parse(localStorage.getItem('human_behavior_logs') || '[]');
4884
+ const logs = JSON.parse(localStorage.getItem('human_behavior_logs') || '[]');
4604
4885
  console.log('HumanBehavior Logs:', logs);
4605
4886
  localStorage.removeItem('human_behavior_logs'); // Clear logs after viewing
4606
4887
  }
4607
4888
  catch (e) {
4608
4889
  console.error('Failed to read logs:', e);
4609
4890
  }
4610
- };
4611
- HumanBehaviorTracker.prototype.identifyUser = function (userProperties) {
4612
- return __awaiter$1(this, void 0, void 0, function () {
4613
- return __generator(this, function (_a) {
4614
- switch (_a.label) {
4615
- case 0: return [4 /*yield*/, this.ensureInitialized()];
4616
- case 1:
4617
- _a.sent();
4618
- this.userProperties = userProperties;
4619
- return [4 /*yield*/, this.api.sendUserData(this.endUserId, userProperties, this.sessionId)];
4620
- case 2:
4621
- _a.sent();
4622
- return [2 /*return*/];
4623
- }
4624
- });
4891
+ }
4892
+ addUserInfo(userProperties) {
4893
+ return __awaiter$1(this, void 0, void 0, function* () {
4894
+ yield this.ensureInitialized();
4895
+ if (!this.endUserId) {
4896
+ throw new Error('Cannot add user info before tracker initialization');
4897
+ }
4898
+ this.userProperties = userProperties;
4899
+ yield this.api.sendUserData(this.endUserId, userProperties, this.sessionId);
4625
4900
  });
4626
- };
4627
- HumanBehaviorTracker.prototype.customEvent = function (eventName_1) {
4628
- return __awaiter$1(this, arguments, void 0, function (eventName, eventProperties) {
4629
- if (eventProperties === void 0) { eventProperties = {}; }
4630
- return __generator(this, function (_a) {
4631
- switch (_a.label) {
4632
- case 0: return [4 /*yield*/, this.ensureInitialized()];
4633
- case 1:
4634
- _a.sent();
4635
- this.api.sendBeaconCustomEvent(eventName, eventProperties, this.sessionId);
4636
- return [2 /*return*/];
4637
- }
4638
- });
4901
+ }
4902
+ /**
4903
+ * Authenticate user using existing userInfo data
4904
+ * @param authFields Array of field names to check for existing users (e.g., ['email', 'phoneNumber'])
4905
+ */
4906
+ auth(authFields) {
4907
+ return __awaiter$1(this, void 0, void 0, function* () {
4908
+ yield this.ensureInitialized();
4909
+ if (!this.endUserId) {
4910
+ throw new Error('Cannot authenticate before tracker initialization');
4911
+ }
4912
+ if (!this.userProperties || Object.keys(this.userProperties).length === 0) {
4913
+ throw new Error('No user info available. Call addUserInfo() first.');
4914
+ }
4915
+ yield this.api.sendUserAuth(this.endUserId, this.userProperties, this.sessionId, authFields);
4639
4916
  });
4640
- };
4641
- HumanBehaviorTracker.prototype.start = function () {
4642
- return __awaiter$1(this, void 0, void 0, function () {
4643
- var _this = this;
4644
- return __generator(this, function (_a) {
4645
- switch (_a.label) {
4646
- case 0: return [4 /*yield*/, this.ensureInitialized()];
4647
- case 1:
4648
- _a.sent();
4649
- if (!isBrowser)
4650
- return [2 /*return*/];
4651
- // Start periodic flushing
4652
- this.flushInterval = window.setInterval(function () {
4653
- _this.flush();
4654
- }, this.FLUSH_INTERVAL_MS);
4655
- // Start recording
4656
- record({
4657
- emit: function (event) {
4658
- _this.addEvent(event);
4659
- },
4660
- });
4661
- return [2 /*return*/];
4662
- }
4663
- });
4917
+ }
4918
+ customEvent(eventName_1) {
4919
+ return __awaiter$1(this, arguments, void 0, function* (eventName, eventProperties = {}) {
4920
+ yield this.ensureInitialized();
4921
+ this.api.sendBeaconCustomEvent(eventName, eventProperties, this.sessionId);
4664
4922
  });
4665
- };
4666
- HumanBehaviorTracker.prototype.stop = function () {
4667
- return __awaiter$1(this, void 0, void 0, function () {
4668
- return __generator(this, function (_a) {
4669
- switch (_a.label) {
4670
- case 0: return [4 /*yield*/, this.ensureInitialized()];
4671
- case 1:
4672
- _a.sent();
4673
- if (!isBrowser)
4674
- return [2 /*return*/];
4675
- if (this.flushInterval) {
4676
- clearInterval(this.flushInterval);
4677
- this.flushInterval = null;
4678
- }
4679
- return [2 /*return*/];
4680
- }
4923
+ }
4924
+ start() {
4925
+ return __awaiter$1(this, void 0, void 0, function* () {
4926
+ yield this.ensureInitialized();
4927
+ if (!isBrowser)
4928
+ return;
4929
+ // Start periodic flushing
4930
+ this.flushInterval = window.setInterval(() => {
4931
+ this.flush();
4932
+ }, this.FLUSH_INTERVAL_MS);
4933
+ // Start recording with redaction enabled
4934
+ record({
4935
+ emit: (event) => {
4936
+ this.addEvent(event);
4937
+ },
4938
+ inlineStylesheet: true,
4939
+ recordCanvas: true,
4940
+ collectFonts: true,
4941
+ blockClass: 'rr-block',
4942
+ ignoreClass: 'rr-ignore',
4943
+ maskTextClass: 'rr-ignore'
4681
4944
  });
4682
4945
  });
4683
- };
4684
- HumanBehaviorTracker.prototype.addEvent = function (event) {
4685
- return __awaiter$1(this, void 0, void 0, function () {
4686
- var eventSize;
4687
- return __generator(this, function (_a) {
4688
- switch (_a.label) {
4689
- case 0: return [4 /*yield*/, this.ensureInitialized()];
4690
- case 1:
4691
- _a.sent();
4692
- eventSize = new TextEncoder().encode(JSON.stringify(event)).length;
4693
- this.eventIngestionQueue.push(event);
4694
- this.queueSizeBytes += eventSize;
4695
- return [2 /*return*/];
4696
- }
4697
- });
4946
+ }
4947
+ stop() {
4948
+ return __awaiter$1(this, void 0, void 0, function* () {
4949
+ yield this.ensureInitialized();
4950
+ if (!isBrowser)
4951
+ return;
4952
+ if (this.flushInterval) {
4953
+ clearInterval(this.flushInterval);
4954
+ this.flushInterval = null;
4955
+ }
4698
4956
  });
4699
- };
4700
- HumanBehaviorTracker.prototype.processRejectedEvents = function () {
4701
- return __awaiter$1(this, void 0, void 0, function () {
4702
- var newSessionId;
4703
- return __generator(this, function (_a) {
4704
- if (this.isProcessingRejectedEvents || this.rejectedEvents.length === 0)
4705
- return [2 /*return*/];
4706
- this.isProcessingRejectedEvents = true;
4707
- try {
4708
- newSessionId = v1();
4709
- if (isBrowser) {
4710
- localStorage.setItem('human_behavior_session_id', newSessionId);
4711
- }
4712
- // Try to send rejected events with new session ID using beacon
4713
- // sendBeacon returns true if the request was queued successfully
4714
- this.api.sendBeaconEvents(this.rejectedEvents, newSessionId);
4715
- // Clear rejected events and update session ID
4716
- // Note: We can't verify if the beacon data was actually sent,
4717
- // but we clear the events to prevent duplicate sending attempts
4718
- this.rejectedEvents = [];
4719
- this.sessionId = newSessionId;
4720
- }
4721
- catch (error) {
4722
- console.error('Failed to process rejected events:', error);
4723
- }
4724
- finally {
4725
- this.isProcessingRejectedEvents = false;
4957
+ }
4958
+ addEvent(event) {
4959
+ return __awaiter$1(this, void 0, void 0, function* () {
4960
+ yield this.ensureInitialized();
4961
+ // Process event through redaction manager if active
4962
+ const processedEvent = this.redactionManager.processEvent(event);
4963
+ const eventSize = new TextEncoder().encode(JSON.stringify(processedEvent)).length;
4964
+ this.eventIngestionQueue.push(processedEvent);
4965
+ this.queueSizeBytes += eventSize;
4966
+ });
4967
+ }
4968
+ processRejectedEvents() {
4969
+ return __awaiter$1(this, void 0, void 0, function* () {
4970
+ if (this.isProcessingRejectedEvents || this.rejectedEvents.length === 0)
4971
+ return;
4972
+ this.isProcessingRejectedEvents = true;
4973
+ try {
4974
+ // Create a new session ID for rejected events
4975
+ const newSessionId = v1();
4976
+ if (isBrowser) {
4977
+ localStorage.setItem('human_behavior_session_id', newSessionId);
4726
4978
  }
4727
- return [2 /*return*/];
4728
- });
4979
+ // Try to send rejected events with new session ID using beacon
4980
+ // sendBeacon returns true if the request was queued successfully
4981
+ this.api.sendBeaconEvents(this.rejectedEvents, newSessionId);
4982
+ // Clear rejected events and update session ID
4983
+ // Note: We can't verify if the beacon data was actually sent,
4984
+ // but we clear the events to prevent duplicate sending attempts
4985
+ this.rejectedEvents = [];
4986
+ this.sessionId = newSessionId;
4987
+ }
4988
+ catch (error) {
4989
+ console.error('Failed to process rejected events:', error);
4990
+ }
4991
+ finally {
4992
+ this.isProcessingRejectedEvents = false;
4993
+ }
4729
4994
  });
4730
- };
4731
- HumanBehaviorTracker.prototype.flush = function () {
4732
- return __awaiter$1(this, void 0, void 0, function () {
4733
- var eventsToProcess, error_2;
4995
+ }
4996
+ flush() {
4997
+ return __awaiter$1(this, void 0, void 0, function* () {
4734
4998
  var _a;
4735
- var _b;
4736
- return __generator(this, function (_c) {
4737
- switch (_c.label) {
4738
- case 0:
4739
- // Prevent concurrent flushes
4740
- if (this.isProcessing || !this.initialized) {
4741
- return [2 /*return*/];
4742
- }
4743
- this.isProcessing = true;
4744
- _c.label = 1;
4745
- case 1:
4746
- _c.trys.push([1, , 6, 7]);
4747
- eventsToProcess = this.eventIngestionQueue;
4748
- this.eventIngestionQueue = [];
4749
- this.queueSizeBytes = 0;
4750
- if (!(eventsToProcess.length > 0)) return [3 /*break*/, 5];
4751
- console.log('Flushing events:', eventsToProcess);
4752
- _c.label = 2;
4753
- case 2:
4754
- _c.trys.push([2, 4, , 5]);
4755
- return [4 /*yield*/, this.api.sendEvents(eventsToProcess, this.sessionId, this.endUserId)];
4756
- case 3:
4757
- _c.sent();
4758
- return [3 /*break*/, 5];
4759
- case 4:
4760
- error_2 = _c.sent();
4999
+ // Prevent concurrent flushes
5000
+ if (this.isProcessing || !this.initialized) {
5001
+ return;
5002
+ }
5003
+ this.isProcessing = true;
5004
+ try {
5005
+ // Swap the current queue with an empty one atomically
5006
+ const eventsToProcess = this.eventIngestionQueue;
5007
+ this.eventIngestionQueue = [];
5008
+ this.queueSizeBytes = 0;
5009
+ if (eventsToProcess.length > 0) {
5010
+ console.log('Flushing events:', eventsToProcess);
5011
+ try {
5012
+ yield this.api.sendEvents(eventsToProcess, this.sessionId, this.endUserId);
5013
+ }
5014
+ catch (error) {
4761
5015
  // If we get a 400 error, store events for retry
4762
- if ((_b = error_2.message) === null || _b === void 0 ? void 0 : _b.includes('ERROR: Session already completed')) {
5016
+ if ((_a = error.message) === null || _a === void 0 ? void 0 : _a.includes('ERROR: Session already completed')) {
4763
5017
  console.log('Session expired, storing events for retry');
4764
- (_a = this.rejectedEvents).push.apply(_a, eventsToProcess);
5018
+ this.rejectedEvents.push(...eventsToProcess);
4765
5019
  this.processRejectedEvents();
4766
5020
  }
4767
5021
  else {
4768
- throw error_2;
5022
+ throw error;
4769
5023
  }
4770
- return [3 /*break*/, 5];
4771
- case 5: return [3 /*break*/, 7];
4772
- case 6:
4773
- this.isProcessing = false;
4774
- return [7 /*endfinally*/];
4775
- case 7: return [2 /*return*/];
5024
+ }
4776
5025
  }
4777
- });
5026
+ }
5027
+ finally {
5028
+ this.isProcessing = false;
5029
+ }
4778
5030
  });
4779
- };
5031
+ }
4780
5032
  // Add helper methods for cookie management
4781
- HumanBehaviorTracker.prototype.setCookie = function (name, value, daysToExpire) {
5033
+ setCookie(name, value, daysToExpire) {
4782
5034
  if (!isBrowser)
4783
5035
  return;
4784
- var date = new Date();
5036
+ const date = new Date();
4785
5037
  date.setTime(date.getTime() + (daysToExpire * 24 * 60 * 60 * 1000));
4786
- var expires = "expires=".concat(date.toUTCString());
4787
- document.cookie = "".concat(name, "=").concat(value, ";").concat(expires, ";path=/;SameSite=Lax");
4788
- };
4789
- HumanBehaviorTracker.prototype.getCookie = function (name) {
5038
+ const expires = `expires=${date.toUTCString()}`;
5039
+ document.cookie = `${name}=${value};${expires};path=/;SameSite=Lax`;
5040
+ }
5041
+ getCookie(name) {
4790
5042
  if (!isBrowser)
4791
5043
  return null;
4792
- var nameEQ = name + "=";
4793
- var ca = document.cookie.split(';');
4794
- for (var i = 0; i < ca.length; i++) {
4795
- var c = ca[i];
5044
+ const nameEQ = name + "=";
5045
+ const ca = document.cookie.split(';');
5046
+ for (let i = 0; i < ca.length; i++) {
5047
+ let c = ca[i];
4796
5048
  while (c.charAt(0) === ' ')
4797
5049
  c = c.substring(1, c.length);
4798
5050
  if (c.indexOf(nameEQ) === 0)
4799
5051
  return c.substring(nameEQ.length, c.length);
4800
5052
  }
4801
5053
  return null;
4802
- };
4803
- return HumanBehaviorTracker;
4804
- }());
5054
+ }
5055
+ /**
5056
+ * Start redaction functionality for sensitive input fields
5057
+ * @param options Optional configuration for redaction behavior
5058
+ */
5059
+ redact(options) {
5060
+ return __awaiter$1(this, void 0, void 0, function* () {
5061
+ yield this.ensureInitialized();
5062
+ if (!isBrowser) {
5063
+ console.warn('Redaction is only available in browser environments');
5064
+ return;
5065
+ }
5066
+ // Create a new redaction manager with the provided options
5067
+ this.redactionManager = new RedactionManager(options);
5068
+ });
5069
+ }
5070
+ /**
5071
+ * Set specific fields to be redacted during session recording
5072
+ * @param fields Array of CSS selectors for fields to redact (e.g., ['input[type="password"]', '#email-field'])
5073
+ */
5074
+ setRedactedFields(fields) {
5075
+ if (!isBrowser) {
5076
+ console.warn('Redaction is only available in browser environments');
5077
+ return;
5078
+ }
5079
+ this.redactionManager.setFieldsToRedact(fields);
5080
+ }
5081
+ /**
5082
+ * Check if redaction is currently active
5083
+ */
5084
+ isRedactionActive() {
5085
+ return this.redactionManager.isActive();
5086
+ }
5087
+ /**
5088
+ * Get the currently selected fields for redaction
5089
+ */
5090
+ getRedactedFields() {
5091
+ return this.redactionManager.getSelectedFields();
5092
+ }
5093
+ }
4805
5094
  // Only expose to window object in browser environments
4806
5095
  if (isBrowser) {
4807
5096
  window.HumanBehaviorTracker = HumanBehaviorTracker;
4808
5097
  }
4809
5098
 
5099
+ /**
5100
+ * Main entry point for the HumanBehavior SDK
5101
+ */
5102
+ // For UMD builds, expose the main class globally
5103
+ if (typeof window !== 'undefined') {
5104
+ window.HumanBehaviorTracker = HumanBehaviorTracker;
5105
+ }
5106
+
4810
5107
  exports.HumanBehaviorAPI = HumanBehaviorAPI;
4811
5108
  exports.HumanBehaviorTracker = HumanBehaviorTracker;
4812
5109
  exports.MAX_CHUNK_SIZE_BYTES = MAX_CHUNK_SIZE_BYTES;
5110
+ exports.RedactionManager = RedactionManager;
4813
5111
  exports.default = HumanBehaviorTracker;
4814
5112
  exports.isChunkSizeExceeded = isChunkSizeExceeded;
5113
+ exports.redactionManager = redactionManager;
4815
5114
  exports.validateSingleEventSize = validateSingleEventSize;
4816
5115
  //# sourceMappingURL=index.js.map