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