clintplay-react-native 0.2.1 → 0.2.2

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/index.mjs CHANGED
@@ -49,7 +49,14 @@ var SessionManager = class {
49
49
  }
50
50
  create() {
51
51
  const ts = this.now();
52
- return { sessionId: uuid(), startedAt: ts, lastActivity: ts, userId: null };
52
+ return {
53
+ sessionId: uuid(),
54
+ startedAt: ts,
55
+ lastActivity: ts,
56
+ userId: null,
57
+ tags: /* @__PURE__ */ new Set(),
58
+ metadata: {}
59
+ };
53
60
  }
54
61
  current() {
55
62
  return this.state;
@@ -57,6 +64,19 @@ var SessionManager = class {
57
64
  touch() {
58
65
  this.state.lastActivity = this.now();
59
66
  }
67
+ addTag(tag2) {
68
+ if (this.state.tags.has(tag2)) {
69
+ return false;
70
+ }
71
+ this.state.tags.add(tag2);
72
+ return true;
73
+ }
74
+ hasTag(tag2) {
75
+ return this.state.tags.has(tag2);
76
+ }
77
+ setMetadata(data) {
78
+ this.state.metadata = { ...this.state.metadata, ...data };
79
+ }
60
80
  setUser(userId) {
61
81
  const prev = this.state.userId;
62
82
  if (prev !== null && (userId === null || prev !== userId)) {
@@ -911,7 +931,7 @@ function captureViewHierarchy() {
911
931
  }
912
932
 
913
933
  // package.json
914
- var version = "0.2.1";
934
+ var version = "0.2.2";
915
935
  var CLINTPLAY_MASK_ID = "clintplay-mask";
916
936
  var ClintplayMaskView = React5.forwardRef(function ClintplayMaskView2({ children, testID, ...rest }, ref) {
917
937
  return /* @__PURE__ */ jsx(
@@ -1223,6 +1243,124 @@ function ClintplayNavigationTracker({
1223
1243
  // src/index.ts
1224
1244
  var SDK_VERSION = version;
1225
1245
  var state = null;
1246
+ var METADATA_MAX_KEYS = 50;
1247
+ var METADATA_MAX_DEPTH = 3;
1248
+ var METADATA_MAX_STRING_LENGTH = 1024;
1249
+ var METADATA_MAX_BYTES = 8192;
1250
+ var TAG_MAX_LENGTH = 128;
1251
+ var pendingMetadata = {};
1252
+ var pendingTags = /* @__PURE__ */ new Set();
1253
+ function sanitizeTag(rawTag) {
1254
+ if (typeof rawTag !== "string") return null;
1255
+ const trimmed = rawTag.trim();
1256
+ if (trimmed.length === 0) return null;
1257
+ const normalized = typeof trimmed.normalize === "function" ? trimmed.normalize("NFC") : trimmed;
1258
+ return normalized.slice(0, TAG_MAX_LENGTH);
1259
+ }
1260
+ function isPlainObject(val) {
1261
+ return typeof val === "object" && val !== null && !Array.isArray(val);
1262
+ }
1263
+ function sanitizeMetadataValue(val, depth, seen) {
1264
+ if (val === null || val === void 0) {
1265
+ return val;
1266
+ }
1267
+ if (typeof val === "function" || typeof val === "symbol") {
1268
+ return void 0;
1269
+ }
1270
+ if (typeof val === "string") {
1271
+ return val.slice(0, METADATA_MAX_STRING_LENGTH);
1272
+ }
1273
+ if (typeof val === "number") {
1274
+ return Number.isFinite(val) ? val : null;
1275
+ }
1276
+ if (typeof val === "boolean") {
1277
+ return val;
1278
+ }
1279
+ if (typeof val === "bigint") {
1280
+ return val.toString();
1281
+ }
1282
+ if (val instanceof Date) {
1283
+ return Number.isNaN(val.getTime()) ? null : val.toISOString();
1284
+ }
1285
+ if (typeof val === "object") {
1286
+ if (seen.has(val)) {
1287
+ return "[Circular]";
1288
+ }
1289
+ seen.add(val);
1290
+ try {
1291
+ if (depth > METADATA_MAX_DEPTH) {
1292
+ return void 0;
1293
+ }
1294
+ if (Array.isArray(val)) {
1295
+ const arr = [];
1296
+ for (const item of val) {
1297
+ const cleaned = sanitizeMetadataValue(item, depth + 1, seen);
1298
+ if (cleaned !== void 0) {
1299
+ arr.push(cleaned);
1300
+ }
1301
+ }
1302
+ return arr;
1303
+ }
1304
+ const obj = {};
1305
+ const entries = Object.entries(val);
1306
+ let keyCount = 0;
1307
+ for (const [k, v] of entries) {
1308
+ if (k === "__proto__" || k === "constructor" || k === "prototype") {
1309
+ continue;
1310
+ }
1311
+ if (keyCount >= METADATA_MAX_KEYS) {
1312
+ break;
1313
+ }
1314
+ const cleaned = sanitizeMetadataValue(v, depth + 1, seen);
1315
+ if (cleaned !== void 0) {
1316
+ obj[k] = cleaned;
1317
+ keyCount++;
1318
+ }
1319
+ }
1320
+ return obj;
1321
+ } finally {
1322
+ seen.delete(val);
1323
+ }
1324
+ }
1325
+ return void 0;
1326
+ }
1327
+ function sanitizeMetadata(data) {
1328
+ if (!isPlainObject(data)) {
1329
+ return null;
1330
+ }
1331
+ const seen = /* @__PURE__ */ new Set();
1332
+ seen.add(data);
1333
+ const result = {};
1334
+ const entries = Object.entries(data);
1335
+ let keyCount = 0;
1336
+ for (const [k, v] of entries) {
1337
+ if (k === "__proto__" || k === "constructor" || k === "prototype") {
1338
+ continue;
1339
+ }
1340
+ if (keyCount >= METADATA_MAX_KEYS) {
1341
+ break;
1342
+ }
1343
+ const cleaned = sanitizeMetadataValue(v, 1, seen);
1344
+ if (cleaned !== void 0) {
1345
+ result[k] = cleaned;
1346
+ keyCount++;
1347
+ }
1348
+ }
1349
+ try {
1350
+ let json = JSON.stringify(result);
1351
+ if (json.length > METADATA_MAX_BYTES) {
1352
+ const keys = Object.keys(result);
1353
+ while (keys.length > 0 && json.length > METADATA_MAX_BYTES) {
1354
+ const lastKey = keys.pop();
1355
+ delete result[lastKey];
1356
+ json = JSON.stringify(result);
1357
+ }
1358
+ }
1359
+ } catch {
1360
+ return null;
1361
+ }
1362
+ return result;
1363
+ }
1226
1364
  function deviceInfo() {
1227
1365
  const os = Platform.OS;
1228
1366
  const platform = os === "ios" ? "ios" : os === "android" ? "android" : "web";
@@ -1368,6 +1506,30 @@ function init(rawConfig) {
1368
1506
  });
1369
1507
  }
1370
1508
  pushSessionMeta(local);
1509
+ if (Object.keys(pendingMetadata).length > 0) {
1510
+ local.session.setMetadata(pendingMetadata);
1511
+ if (!excluded.has("metadata")) {
1512
+ local.buffer.push({
1513
+ type: "metadata",
1514
+ ts: Date.now(),
1515
+ data: pendingMetadata
1516
+ });
1517
+ }
1518
+ pendingMetadata = {};
1519
+ }
1520
+ if (pendingTags.size > 0) {
1521
+ for (const t of pendingTags) {
1522
+ local.session.addTag(t);
1523
+ if (!excluded.has("tag")) {
1524
+ local.buffer.push({
1525
+ type: "tag",
1526
+ ts: Date.now(),
1527
+ data: { tag: t }
1528
+ });
1529
+ }
1530
+ }
1531
+ pendingTags.clear();
1532
+ }
1371
1533
  recorder.start();
1372
1534
  local.networkInterceptor?.start();
1373
1535
  local.consoleInterceptor?.start();
@@ -1459,11 +1621,54 @@ function reportError(err) {
1459
1621
  fatal: false
1460
1622
  });
1461
1623
  }
1624
+ function setMetadata(data) {
1625
+ const sanitized = sanitizeMetadata(data);
1626
+ if (!sanitized || Object.keys(sanitized).length === 0) return;
1627
+ if (!state?.active) {
1628
+ pendingMetadata = { ...pendingMetadata, ...sanitized };
1629
+ return;
1630
+ }
1631
+ state.session.setMetadata(sanitized);
1632
+ state.session.touch();
1633
+ if (!state.excluded.has("metadata")) {
1634
+ state.buffer.push({
1635
+ type: "metadata",
1636
+ ts: Date.now(),
1637
+ data: sanitized
1638
+ });
1639
+ if (state.buffer.size() >= state.config.flushSize) {
1640
+ void flushOnce(state);
1641
+ }
1642
+ }
1643
+ }
1644
+ function tag(tagName) {
1645
+ const cleaned = sanitizeTag(tagName);
1646
+ if (!cleaned) return;
1647
+ if (!state?.active) {
1648
+ pendingTags.add(cleaned);
1649
+ return;
1650
+ }
1651
+ if (state.session.addTag(cleaned)) {
1652
+ state.session.touch();
1653
+ if (!state.excluded.has("tag")) {
1654
+ state.buffer.push({
1655
+ type: "tag",
1656
+ ts: Date.now(),
1657
+ data: { tag: cleaned }
1658
+ });
1659
+ if (state.buffer.size() >= state.config.flushSize) {
1660
+ void flushOnce(state);
1661
+ }
1662
+ }
1663
+ }
1664
+ }
1462
1665
  async function flush() {
1463
1666
  if (!state?.active) return;
1464
1667
  await flushOnce(state);
1465
1668
  }
1466
1669
  async function stop() {
1670
+ pendingMetadata = {};
1671
+ pendingTags.clear();
1467
1672
  if (!state?.active) return;
1468
1673
  const s = state;
1469
1674
  s.active = false;
@@ -1493,12 +1698,14 @@ var Clintplay = {
1493
1698
  reset,
1494
1699
  trackScreen,
1495
1700
  reportError,
1701
+ setMetadata,
1702
+ tag,
1496
1703
  flush,
1497
1704
  stop,
1498
1705
  current,
1499
1706
  _getState
1500
1707
  };
1501
1708
 
1502
- export { CLINTPLAY_MASK_ID, Clintplay, ClintplayCaptureProvider, ClintplayMaskImage, ClintplayMaskTextInput, ClintplayMaskView, ClintplayNavigationTracker, SDK_VERSION, _resetLastTrackedRoute, createClintplayNavigationStateListener, formatEventForBatch, getActiveRouteName, init, sanitizeRoute, useClintplayNavigationTracking };
1709
+ export { CLINTPLAY_MASK_ID, Clintplay, ClintplayCaptureProvider, ClintplayMaskImage, ClintplayMaskTextInput, ClintplayMaskView, ClintplayNavigationTracker, METADATA_MAX_BYTES, METADATA_MAX_DEPTH, METADATA_MAX_KEYS, METADATA_MAX_STRING_LENGTH, SDK_VERSION, TAG_MAX_LENGTH, _resetLastTrackedRoute, createClintplayNavigationStateListener, formatEventForBatch, getActiveRouteName, init, sanitizeMetadata, sanitizeRoute, sanitizeTag, setMetadata, tag, useClintplayNavigationTracking };
1503
1710
  //# sourceMappingURL=index.mjs.map
1504
1711
  //# sourceMappingURL=index.mjs.map