@posthog/browser-common 0.2.5 → 0.3.1
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 +4 -3
- package/dist/client.d.ts +3 -5
- package/dist/config.js +1 -1
- package/dist/config.mjs +1 -1
- package/dist/pubsub.d.ts +3 -2
- package/dist/types/remote-config.d.ts +7 -0
- package/dist/utils/autocapture-utils.js +56 -6
- package/dist/utils/autocapture-utils.mjs +56 -6
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -56,14 +56,15 @@ What an extension is given in `setup` — the adapter shared by extensions on th
|
|
|
56
56
|
|
|
57
57
|
- **identity and session**: `distinctId`, `anonymousId`, `groups`, `session`
|
|
58
58
|
- **events**: `capture(...)`, `registerDynamicEventProperties(...)`, `onEvent(...)`
|
|
59
|
-
- **server config**: `
|
|
59
|
+
- **server config**: `onRemoteConfig(...)`
|
|
60
60
|
- **transport**: `projectToken`, `sendRequest(path, init?)`
|
|
61
61
|
- **storage and logging**: `kv`, `logger`
|
|
62
62
|
|
|
63
63
|
Identity, session, and the public project token are always-ready synchronous
|
|
64
64
|
reads. Operations that may perform I/O, including `capture`, `sendRequest`,
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
and `kv`, are awaitable. `onRemoteConfig` immediately replays the latest known
|
|
66
|
+
success or failure and then reports subsequent outcomes. Extensions that want a
|
|
67
|
+
named log prefix can create a child with `client.logger.createLogger('[myExtension]')`.
|
|
67
68
|
|
|
68
69
|
### Host runtime
|
|
69
70
|
|
package/dist/client.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { Properties } from '@posthog/types';
|
|
|
3
3
|
import type { Disposable } from './disposable';
|
|
4
4
|
import type { KeyValueStore } from './persistence';
|
|
5
5
|
import type { Listener } from './pubsub';
|
|
6
|
-
import type {
|
|
6
|
+
import type { RemoteConfigResult } from './types/remote-config';
|
|
7
7
|
/** Recursively marks object properties as readonly while preserving callable values. */
|
|
8
8
|
export type DeepReadonly<T> = T extends (...args: never[]) => unknown ? T : T extends object ? {
|
|
9
9
|
readonly [K in keyof T]: DeepReadonly<T[K]>;
|
|
@@ -87,10 +87,8 @@ export interface Client {
|
|
|
87
87
|
registerDynamicEventProperties(producer: () => Record<string, unknown>): Disposable;
|
|
88
88
|
/** Fires for every captured event through a deeply readonly view. */
|
|
89
89
|
readonly onEvent: Listener<CapturedEventInfo>;
|
|
90
|
-
/**
|
|
91
|
-
|
|
92
|
-
/** Fires when server-provided config arrives or changes successfully. */
|
|
93
|
-
readonly onRemoteConfig: Listener<DeepReadonly<RemoteConfig>>;
|
|
90
|
+
/** Replays the latest remote-config outcome on subscription and fires for subsequent outcomes. */
|
|
91
|
+
readonly onRemoteConfig: Listener<DeepReadonly<RemoteConfigResult>>;
|
|
94
92
|
/** Public project token used to authenticate endpoint-specific requests. */
|
|
95
93
|
readonly projectToken: string;
|
|
96
94
|
/** Sends a request through the host SDK's transport. */
|
package/dist/config.js
CHANGED
|
@@ -26,7 +26,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
26
26
|
__webpack_require__.d(__webpack_exports__, {
|
|
27
27
|
default: ()=>__WEBPACK_DEFAULT_EXPORT__
|
|
28
28
|
});
|
|
29
|
-
const packageVersion = "0.
|
|
29
|
+
const packageVersion = "0.3.1";
|
|
30
30
|
const Config = {
|
|
31
31
|
DEBUG: false,
|
|
32
32
|
LIB_VERSION: packageVersion,
|
package/dist/config.mjs
CHANGED
package/dist/pubsub.d.ts
CHANGED
|
@@ -2,8 +2,9 @@ import { type Disposable } from './disposable';
|
|
|
2
2
|
/**
|
|
3
3
|
* Call it with a handler to start listening; dispose the returned
|
|
4
4
|
* {@link Disposable} to stop. There is one `Listener` per event type, so every
|
|
5
|
-
* event carries its own payload type. The handler is called synchronously
|
|
6
|
-
*
|
|
5
|
+
* event carries its own payload type. The handler is called synchronously, and
|
|
6
|
+
* stateful listeners may replay their current value during registration when
|
|
7
|
+
* documented. The returned disposable unregisters it from future payloads.
|
|
7
8
|
*/
|
|
8
9
|
export type Listener<T> = (handler: (payload: T) => void) => Disposable;
|
|
9
10
|
/**
|
|
@@ -178,3 +178,10 @@ export interface RemoteConfig {
|
|
|
178
178
|
/** Conversations widget configuration. */
|
|
179
179
|
conversations?: boolean | ConversationsRemoteConfig;
|
|
180
180
|
}
|
|
181
|
+
/** The latest outcome of loading remote configuration from PostHog. */
|
|
182
|
+
export type RemoteConfigResult = {
|
|
183
|
+
ok: true;
|
|
184
|
+
config: RemoteConfig;
|
|
185
|
+
} | {
|
|
186
|
+
ok: false;
|
|
187
|
+
};
|
|
@@ -334,18 +334,68 @@ function isSensitiveElement(el) {
|
|
|
334
334
|
}
|
|
335
335
|
const coreCCPattern = "(4[0-9]{12}(?:[0-9]{3})?)|(5[1-5][0-9]{14})|(6(?:011|5[0-9]{2})[0-9]{12})|(3[47][0-9]{13})|(3(?:0[0-5]|[68][0-9])[0-9]{11})|((?:2131|1800|35[0-9]{3})[0-9]{11})";
|
|
336
336
|
const anchoredCCRegex = new RegExp(`^(?:${coreCCPattern})$`);
|
|
337
|
-
const
|
|
337
|
+
const networkCCCandidateRegex = /(^|[^0-9A-Za-z_])([0-9][0-9 -]*[0-9])(?=$|[^0-9A-Za-z_])/g;
|
|
338
|
+
const networkCCLengths = [
|
|
339
|
+
16,
|
|
340
|
+
15,
|
|
341
|
+
14,
|
|
342
|
+
13
|
|
343
|
+
];
|
|
338
344
|
const coreSSNPattern = "\\d{3}-?\\d{2}-?\\d{4}";
|
|
339
345
|
const anchoredSSNRegex = new RegExp(`^(${coreSSNPattern})$`);
|
|
340
|
-
const
|
|
346
|
+
const networkSSNPattern = "(?!000|666)[0-9]{3}-?(?!00)[0-9]{2}-?(?!0000)[0-9]{4}";
|
|
347
|
+
const networkSSNCandidateRegex = new RegExp(`(^|[^0-9])(${networkSSNPattern})(?=$|([^0-9]))`, 'g');
|
|
348
|
+
const identifierCharacterRegex = /[0-9A-Za-z_]/;
|
|
349
|
+
function passesLuhnCheck(value) {
|
|
350
|
+
let sum = 0;
|
|
351
|
+
let shouldDouble = false;
|
|
352
|
+
for(let i = value.length - 1; i >= 0; i--){
|
|
353
|
+
let digit = value.charCodeAt(i) - 48;
|
|
354
|
+
if (shouldDouble) {
|
|
355
|
+
digit *= 2;
|
|
356
|
+
if (digit > 9) digit -= 9;
|
|
357
|
+
}
|
|
358
|
+
sum += digit;
|
|
359
|
+
shouldDouble = !shouldDouble;
|
|
360
|
+
}
|
|
361
|
+
return sum % 10 === 0;
|
|
362
|
+
}
|
|
363
|
+
function containsCreditCardNumber(value) {
|
|
364
|
+
networkCCCandidateRegex.lastIndex = 0;
|
|
365
|
+
let match;
|
|
366
|
+
while(match = networkCCCandidateRegex.exec(value)){
|
|
367
|
+
const matchedCandidate = match[2];
|
|
368
|
+
if (!matchedCandidate) continue;
|
|
369
|
+
const candidate = matchedCandidate.replace(/[- ]/g, '');
|
|
370
|
+
for(let start = 0; start < candidate.length; start++)for (const length of networkCCLengths){
|
|
371
|
+
const end = start + length;
|
|
372
|
+
if (end <= candidate.length) {
|
|
373
|
+
const possibleCardNumber = candidate.slice(start, end);
|
|
374
|
+
if (anchoredCCRegex.test(possibleCardNumber) && passesLuhnCheck(possibleCardNumber)) return true;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
return false;
|
|
379
|
+
}
|
|
380
|
+
function containsSSN(value) {
|
|
381
|
+
networkSSNCandidateRegex.lastIndex = 0;
|
|
382
|
+
let match;
|
|
383
|
+
while(match = networkSSNCandidateRegex.exec(value)){
|
|
384
|
+
const characterBefore = match[1];
|
|
385
|
+
const characterAfter = match[3];
|
|
386
|
+
if (characterBefore && characterAfter && identifierCharacterRegex.test(characterBefore) && identifierCharacterRegex.test(characterAfter)) continue;
|
|
387
|
+
return true;
|
|
388
|
+
}
|
|
389
|
+
return false;
|
|
390
|
+
}
|
|
341
391
|
function shouldCaptureValue(value, anchorRegexes = true) {
|
|
342
392
|
if ((0, core_namespaceObject.isNullish)(value)) return false;
|
|
343
393
|
if ((0, core_namespaceObject.isString)(value)) {
|
|
344
394
|
value = (0, core_namespaceObject.trim)(value);
|
|
345
|
-
const
|
|
346
|
-
if (
|
|
347
|
-
const
|
|
348
|
-
if (
|
|
395
|
+
const containsCreditCard = anchorRegexes ? anchoredCCRegex.test((value || '').replace(/[- ]/g, '')) : containsCreditCardNumber(value);
|
|
396
|
+
if (containsCreditCard) return false;
|
|
397
|
+
const containsSocialSecurityNumber = anchorRegexes ? anchoredSSNRegex.test(value) : containsSSN(value);
|
|
398
|
+
if (containsSocialSecurityNumber) return false;
|
|
349
399
|
}
|
|
350
400
|
return true;
|
|
351
401
|
}
|
|
@@ -286,18 +286,68 @@ function isSensitiveElement(el) {
|
|
|
286
286
|
}
|
|
287
287
|
const coreCCPattern = "(4[0-9]{12}(?:[0-9]{3})?)|(5[1-5][0-9]{14})|(6(?:011|5[0-9]{2})[0-9]{12})|(3[47][0-9]{13})|(3(?:0[0-5]|[68][0-9])[0-9]{11})|((?:2131|1800|35[0-9]{3})[0-9]{11})";
|
|
288
288
|
const anchoredCCRegex = new RegExp(`^(?:${coreCCPattern})$`);
|
|
289
|
-
const
|
|
289
|
+
const networkCCCandidateRegex = /(^|[^0-9A-Za-z_])([0-9][0-9 -]*[0-9])(?=$|[^0-9A-Za-z_])/g;
|
|
290
|
+
const networkCCLengths = [
|
|
291
|
+
16,
|
|
292
|
+
15,
|
|
293
|
+
14,
|
|
294
|
+
13
|
|
295
|
+
];
|
|
290
296
|
const coreSSNPattern = "\\d{3}-?\\d{2}-?\\d{4}";
|
|
291
297
|
const anchoredSSNRegex = new RegExp(`^(${coreSSNPattern})$`);
|
|
292
|
-
const
|
|
298
|
+
const networkSSNPattern = "(?!000|666)[0-9]{3}-?(?!00)[0-9]{2}-?(?!0000)[0-9]{4}";
|
|
299
|
+
const networkSSNCandidateRegex = new RegExp(`(^|[^0-9])(${networkSSNPattern})(?=$|([^0-9]))`, 'g');
|
|
300
|
+
const identifierCharacterRegex = /[0-9A-Za-z_]/;
|
|
301
|
+
function passesLuhnCheck(value) {
|
|
302
|
+
let sum = 0;
|
|
303
|
+
let shouldDouble = false;
|
|
304
|
+
for(let i = value.length - 1; i >= 0; i--){
|
|
305
|
+
let digit = value.charCodeAt(i) - 48;
|
|
306
|
+
if (shouldDouble) {
|
|
307
|
+
digit *= 2;
|
|
308
|
+
if (digit > 9) digit -= 9;
|
|
309
|
+
}
|
|
310
|
+
sum += digit;
|
|
311
|
+
shouldDouble = !shouldDouble;
|
|
312
|
+
}
|
|
313
|
+
return sum % 10 === 0;
|
|
314
|
+
}
|
|
315
|
+
function containsCreditCardNumber(value) {
|
|
316
|
+
networkCCCandidateRegex.lastIndex = 0;
|
|
317
|
+
let match;
|
|
318
|
+
while(match = networkCCCandidateRegex.exec(value)){
|
|
319
|
+
const matchedCandidate = match[2];
|
|
320
|
+
if (!matchedCandidate) continue;
|
|
321
|
+
const candidate = matchedCandidate.replace(/[- ]/g, '');
|
|
322
|
+
for(let start = 0; start < candidate.length; start++)for (const length of networkCCLengths){
|
|
323
|
+
const end = start + length;
|
|
324
|
+
if (end <= candidate.length) {
|
|
325
|
+
const possibleCardNumber = candidate.slice(start, end);
|
|
326
|
+
if (anchoredCCRegex.test(possibleCardNumber) && passesLuhnCheck(possibleCardNumber)) return true;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return false;
|
|
331
|
+
}
|
|
332
|
+
function containsSSN(value) {
|
|
333
|
+
networkSSNCandidateRegex.lastIndex = 0;
|
|
334
|
+
let match;
|
|
335
|
+
while(match = networkSSNCandidateRegex.exec(value)){
|
|
336
|
+
const characterBefore = match[1];
|
|
337
|
+
const characterAfter = match[3];
|
|
338
|
+
if (characterBefore && characterAfter && identifierCharacterRegex.test(characterBefore) && identifierCharacterRegex.test(characterAfter)) continue;
|
|
339
|
+
return true;
|
|
340
|
+
}
|
|
341
|
+
return false;
|
|
342
|
+
}
|
|
293
343
|
function shouldCaptureValue(value, anchorRegexes = true) {
|
|
294
344
|
if (isNullish(value)) return false;
|
|
295
345
|
if (isString(value)) {
|
|
296
346
|
value = trim(value);
|
|
297
|
-
const
|
|
298
|
-
if (
|
|
299
|
-
const
|
|
300
|
-
if (
|
|
347
|
+
const containsCreditCard = anchorRegexes ? anchoredCCRegex.test((value || '').replace(/[- ]/g, '')) : containsCreditCardNumber(value);
|
|
348
|
+
if (containsCreditCard) return false;
|
|
349
|
+
const containsSocialSecurityNumber = anchorRegexes ? anchoredSSNRegex.test(value) : containsSSN(value);
|
|
350
|
+
if (containsSocialSecurityNumber) return false;
|
|
301
351
|
}
|
|
302
352
|
return true;
|
|
303
353
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@posthog/browser-common",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Internal shared browser utilities and extension primitives for PostHog Browser SDKs",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -65,8 +65,8 @@
|
|
|
65
65
|
}
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
|
-
"@posthog/
|
|
69
|
-
"@posthog/
|
|
68
|
+
"@posthog/types": "^1.399.0",
|
|
69
|
+
"@posthog/core": "^1.46.0"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@rslib/core": "0.10.6",
|