@anyreplay/browser 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/README.md +14 -10
- package/dist/index.cjs +58 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +58 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -504,6 +504,14 @@ interface ShellInfo {
|
|
|
504
504
|
appVersion?: string;
|
|
505
505
|
/** The hardware model (`iPhone15,2`, `Pixel 8`), ≤ 64. */
|
|
506
506
|
deviceModel?: string;
|
|
507
|
+
/**
|
|
508
|
+
* Called the moment a chunk number is reserved, before the request that
|
|
509
|
+
* uses it leaves. A shell that copies the recorder's keys into native
|
|
510
|
+
* storage copies them then: an app killed between a send and the shell's
|
|
511
|
+
* next periodic copy came back with the old number, and sent its first
|
|
512
|
+
* chunk under a number the server already held (seen on an iOS simulator).
|
|
513
|
+
*/
|
|
514
|
+
onStateChanged?: () => void;
|
|
507
515
|
}
|
|
508
516
|
type RecorderStatus = 'idle' | 'awaiting-consent' | 'recording' | 'sampled-out' | 'stopped';
|
|
509
517
|
interface IdentifyTraits {
|
package/dist/index.d.ts
CHANGED
|
@@ -504,6 +504,14 @@ interface ShellInfo {
|
|
|
504
504
|
appVersion?: string;
|
|
505
505
|
/** The hardware model (`iPhone15,2`, `Pixel 8`), ≤ 64. */
|
|
506
506
|
deviceModel?: string;
|
|
507
|
+
/**
|
|
508
|
+
* Called the moment a chunk number is reserved, before the request that
|
|
509
|
+
* uses it leaves. A shell that copies the recorder's keys into native
|
|
510
|
+
* storage copies them then: an app killed between a send and the shell's
|
|
511
|
+
* next periodic copy came back with the old number, and sent its first
|
|
512
|
+
* chunk under a number the server already held (seen on an iOS simulator).
|
|
513
|
+
*/
|
|
514
|
+
onStateChanged?: () => void;
|
|
507
515
|
}
|
|
508
516
|
type RecorderStatus = 'idle' | 'awaiting-consent' | 'recording' | 'sampled-out' | 'stopped';
|
|
509
517
|
interface IdentifyTraits {
|
package/dist/index.js
CHANGED
|
@@ -4149,6 +4149,39 @@ function shouldMaskValue(text, node, policy) {
|
|
|
4149
4149
|
return cardShaped(text);
|
|
4150
4150
|
}
|
|
4151
4151
|
var cardShaped = (text) => looksLikeCardNumber(text) || mayBecomeCardNumber(text);
|
|
4152
|
+
var DIGIT_RUN = /[0-9]+(?:[ -][0-9]+)*/g;
|
|
4153
|
+
function maskCardRuns(text) {
|
|
4154
|
+
if (!/[0-9]/.test(text)) return text;
|
|
4155
|
+
return text.replace(DIGIT_RUN, (run) => {
|
|
4156
|
+
const groups = run.split(/[ -]/);
|
|
4157
|
+
const starts = [];
|
|
4158
|
+
let at = 0;
|
|
4159
|
+
for (const group of groups) {
|
|
4160
|
+
starts.push(at);
|
|
4161
|
+
at += group.length + 1;
|
|
4162
|
+
}
|
|
4163
|
+
const chars2 = run.split("");
|
|
4164
|
+
let i = 0;
|
|
4165
|
+
while (i < groups.length) {
|
|
4166
|
+
let matched = -1;
|
|
4167
|
+
for (let j = groups.length - 1; j >= i; j -= 1) {
|
|
4168
|
+
const end2 = starts[j] + groups[j].length;
|
|
4169
|
+
if (cardShaped(run.slice(starts[i], end2).replace(/ /g, " "))) {
|
|
4170
|
+
matched = j;
|
|
4171
|
+
break;
|
|
4172
|
+
}
|
|
4173
|
+
}
|
|
4174
|
+
if (matched < 0) {
|
|
4175
|
+
i += 1;
|
|
4176
|
+
continue;
|
|
4177
|
+
}
|
|
4178
|
+
const end = starts[matched] + groups[matched].length;
|
|
4179
|
+
for (let k = starts[i]; k < end; k += 1) if (chars2[k] !== " " && chars2[k] !== "\xA0" && chars2[k] !== "-") chars2[k] = "*";
|
|
4180
|
+
i = matched + 1;
|
|
4181
|
+
}
|
|
4182
|
+
return chars2.join("");
|
|
4183
|
+
});
|
|
4184
|
+
}
|
|
4152
4185
|
var EDITABLE = '[contenteditable]:not([contenteditable="false"])';
|
|
4153
4186
|
function insideEditable(node) {
|
|
4154
4187
|
var _a;
|
|
@@ -4159,6 +4192,7 @@ function insideEditable(node) {
|
|
|
4159
4192
|
var isEditableSerialised = (attributes) => attributes.contenteditable !== void 0 && attributes.contenteditable !== "false";
|
|
4160
4193
|
var typedCardShaped = (text) => cardShaped(text.replace(/\u00a0/g, " ").trim());
|
|
4161
4194
|
var maskText = (text) => text.replace(/\S/g, "*");
|
|
4195
|
+
var maskTyped = (text) => typedCardShaped(text) ? maskText(text) : maskCardRuns(text);
|
|
4162
4196
|
var MUTATION = 0;
|
|
4163
4197
|
var INPUT = 5;
|
|
4164
4198
|
var ELEMENT_NODE = 2;
|
|
@@ -4173,14 +4207,20 @@ function maskTextChildren(node) {
|
|
|
4173
4207
|
maskTextChildren(child);
|
|
4174
4208
|
}
|
|
4175
4209
|
}
|
|
4210
|
+
function maskCardRunsInChildren(node) {
|
|
4211
|
+
var _a;
|
|
4212
|
+
for (const child of (_a = node.childNodes) != null ? _a : []) {
|
|
4213
|
+
if (child.type === TEXT_NODE && typeof child.textContent === "string") child.textContent = maskCardRuns(child.textContent);
|
|
4214
|
+
}
|
|
4215
|
+
}
|
|
4176
4216
|
function scrubTree(node, policy, masked, editable = false) {
|
|
4177
4217
|
var _a, _b;
|
|
4178
4218
|
if (!node) return;
|
|
4179
4219
|
const attributes = (_a = node.attributes) != null ? _a : {};
|
|
4180
4220
|
const inheritedMask = masked || hasClass(attributes, policy.maskClass);
|
|
4181
4221
|
const inheritedEditable = editable || node.type === ELEMENT_NODE && isEditableSerialised(attributes);
|
|
4182
|
-
if (editable && node.type === TEXT_NODE && typeof node.textContent === "string"
|
|
4183
|
-
node.textContent =
|
|
4222
|
+
if (editable && node.type === TEXT_NODE && typeof node.textContent === "string") {
|
|
4223
|
+
node.textContent = maskTyped(node.textContent);
|
|
4184
4224
|
}
|
|
4185
4225
|
if (node.type === ELEMENT_NODE && node.tagName && FIELD_TAGS.has(node.tagName.toLowerCase())) {
|
|
4186
4226
|
const value = attributes.value;
|
|
@@ -4188,6 +4228,9 @@ function scrubTree(node, policy, masked, editable = false) {
|
|
|
4188
4228
|
if (shouldMask) {
|
|
4189
4229
|
if (typeof value === "string" && value !== "") attributes.value = maskValue(value);
|
|
4190
4230
|
if (node.tagName.toLowerCase() === "textarea") maskTextChildren(node);
|
|
4231
|
+
} else {
|
|
4232
|
+
if (typeof value === "string") attributes.value = maskCardRuns(value);
|
|
4233
|
+
if (node.tagName.toLowerCase() === "textarea") maskCardRunsInChildren(node);
|
|
4191
4234
|
}
|
|
4192
4235
|
}
|
|
4193
4236
|
for (const child of (_b = node.childNodes) != null ? _b : []) scrubTree(child, policy, inheritedMask, inheritedEditable);
|
|
@@ -4206,7 +4249,7 @@ function scrubEvent(event, getNode, policy) {
|
|
|
4206
4249
|
const node = typeof data.id === "number" ? getNode(data.id) : null;
|
|
4207
4250
|
const type = ((_b = (_a = asElement(node)) == null ? void 0 : _a.type) != null ? _b : "").toLowerCase();
|
|
4208
4251
|
if (type === "checkbox" || type === "radio") return;
|
|
4209
|
-
|
|
4252
|
+
data.text = shouldMaskValue(data.text, node, policy) ? maskValue(data.text) : maskCardRuns(data.text);
|
|
4210
4253
|
return;
|
|
4211
4254
|
}
|
|
4212
4255
|
if (data.source !== MUTATION) return;
|
|
@@ -4214,15 +4257,15 @@ function scrubEvent(event, getNode, policy) {
|
|
|
4214
4257
|
const value = (_d = entry == null ? void 0 : entry.attributes) == null ? void 0 : _d.value;
|
|
4215
4258
|
if (typeof value !== "string" || value === "") continue;
|
|
4216
4259
|
const node = typeof entry.id === "number" ? getNode(entry.id) : null;
|
|
4217
|
-
|
|
4260
|
+
entry.attributes.value = shouldMaskValue(value, node, policy) ? maskValue(value) : maskCardRuns(value);
|
|
4218
4261
|
}
|
|
4219
4262
|
for (const add of (_e = data.adds) != null ? _e : []) {
|
|
4220
4263
|
const parent = typeof (add == null ? void 0 : add.parentId) === "number" ? getNode(add.parentId) : null;
|
|
4221
4264
|
scrubTree(add == null ? void 0 : add.node, policy, isMarkedByCustomer(parent, policy.maskClass), insideEditable(parent));
|
|
4222
4265
|
}
|
|
4223
4266
|
for (const change of (_f = data.texts) != null ? _f : []) {
|
|
4224
|
-
if (typeof (change == null ? void 0 : change.value) !== "string" ||
|
|
4225
|
-
if (typeof change.id === "number" && insideEditable(getNode(change.id))) change.value =
|
|
4267
|
+
if (typeof (change == null ? void 0 : change.value) !== "string" || !/[0-9]/.test(change.value)) continue;
|
|
4268
|
+
if (typeof change.id === "number" && insideEditable(getNode(change.id))) change.value = maskTyped(change.value);
|
|
4226
4269
|
}
|
|
4227
4270
|
}
|
|
4228
4271
|
|
|
@@ -5028,7 +5071,7 @@ var Transport = class {
|
|
|
5028
5071
|
|
|
5029
5072
|
// src/version.ts
|
|
5030
5073
|
var SDK_NAME = "@anyreplay/browser";
|
|
5031
|
-
var SDK_VERSION = true ? "0.2.
|
|
5074
|
+
var SDK_VERSION = true ? "0.2.2" : "0.0.0-dev";
|
|
5032
5075
|
var PLATFORM = "web";
|
|
5033
5076
|
|
|
5034
5077
|
// src/visitor.ts
|
|
@@ -5276,7 +5319,14 @@ function createRecorder(rawOptions, shell) {
|
|
|
5276
5319
|
initialSeq: who.nextSeq
|
|
5277
5320
|
},
|
|
5278
5321
|
{
|
|
5279
|
-
onSeqReserved: (next) =>
|
|
5322
|
+
onSeqReserved: (next) => {
|
|
5323
|
+
var _a;
|
|
5324
|
+
reserveSeq(session, next);
|
|
5325
|
+
try {
|
|
5326
|
+
(_a = shell == null ? void 0 : shell.onStateChanged) == null ? void 0 : _a.call(shell);
|
|
5327
|
+
} catch (e) {
|
|
5328
|
+
}
|
|
5329
|
+
},
|
|
5280
5330
|
onStopped: (reason) => {
|
|
5281
5331
|
status = "stopped";
|
|
5282
5332
|
stopRecording == null ? void 0 : stopRecording();
|