humanbehavior-js 0.0.5 → 0.0.8

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