@leanbase-giangnd/js 0.0.0

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.
Files changed (49) hide show
  1. package/README.md +143 -0
  2. package/dist/index.cjs +6012 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.ts +1484 -0
  5. package/dist/index.mjs +6010 -0
  6. package/dist/index.mjs.map +1 -0
  7. package/dist/leanbase.iife.js +13431 -0
  8. package/dist/leanbase.iife.js.map +1 -0
  9. package/package.json +48 -0
  10. package/src/autocapture-utils.ts +550 -0
  11. package/src/autocapture.ts +415 -0
  12. package/src/config.ts +8 -0
  13. package/src/constants.ts +108 -0
  14. package/src/extensions/rageclick.ts +34 -0
  15. package/src/extensions/replay/external/config.ts +278 -0
  16. package/src/extensions/replay/external/denylist.ts +32 -0
  17. package/src/extensions/replay/external/lazy-loaded-session-recorder.ts +1376 -0
  18. package/src/extensions/replay/external/mutation-throttler.ts +109 -0
  19. package/src/extensions/replay/external/network-plugin.ts +701 -0
  20. package/src/extensions/replay/external/sessionrecording-utils.ts +141 -0
  21. package/src/extensions/replay/external/triggerMatching.ts +422 -0
  22. package/src/extensions/replay/rrweb-plugins/patch.ts +39 -0
  23. package/src/extensions/replay/session-recording.ts +285 -0
  24. package/src/extensions/replay/types/rrweb-types.ts +575 -0
  25. package/src/extensions/replay/types/rrweb.ts +114 -0
  26. package/src/extensions/sampling.ts +26 -0
  27. package/src/iife.ts +87 -0
  28. package/src/index.ts +2 -0
  29. package/src/leanbase-logger.ts +26 -0
  30. package/src/leanbase-persistence.ts +374 -0
  31. package/src/leanbase.ts +457 -0
  32. package/src/page-view.ts +124 -0
  33. package/src/scroll-manager.ts +103 -0
  34. package/src/session-props.ts +114 -0
  35. package/src/sessionid.ts +330 -0
  36. package/src/storage.ts +410 -0
  37. package/src/types/fflate.d.ts +5 -0
  38. package/src/types/rrweb-record.d.ts +8 -0
  39. package/src/types.ts +807 -0
  40. package/src/utils/blocked-uas.ts +162 -0
  41. package/src/utils/element-utils.ts +50 -0
  42. package/src/utils/event-utils.ts +304 -0
  43. package/src/utils/index.ts +222 -0
  44. package/src/utils/logger.ts +26 -0
  45. package/src/utils/request-utils.ts +128 -0
  46. package/src/utils/simple-event-emitter.ts +27 -0
  47. package/src/utils/user-agent-utils.ts +357 -0
  48. package/src/uuidv7.ts +268 -0
  49. package/src/version.ts +1 -0
@@ -0,0 +1,575 @@
1
+ // Type definitions copied from @rrweb/types@2.0.0-alpha.17 and rrweb-snapshot@2.0.0-alpha.17
2
+ // Both packages are MIT licensed: https://github.com/rrweb-io/rrweb
3
+ //
4
+ // These types are copied here to avoid requiring users to install peer dependencies
5
+ // solely for TypeScript type information.
6
+ //
7
+ // Original sources:
8
+ // - @rrweb/types: https://github.com/rrweb-io/rrweb/tree/main/packages/@rrweb/types
9
+ // - rrweb-snapshot: https://github.com/rrweb-io/rrweb/tree/main/packages/rrweb-snapshot
10
+
11
+ // ===== Types from rrweb-snapshot =====
12
+ // These are needed by @rrweb/types
13
+
14
+ export type DataURLOptions = Partial<{
15
+ type: string
16
+ quality: number
17
+ }>
18
+
19
+ export interface INode extends Node {
20
+ __sn: serializedNodeWithId
21
+ }
22
+
23
+ export interface IMirror<TNode> {
24
+ getId(n: TNode | undefined | null): number
25
+ getNode(id: number): TNode | null
26
+ getIds(): number[]
27
+ getMeta(n: TNode): serializedNodeWithId | null
28
+ removeNodeFromMap(n: TNode): void
29
+ has(id: number): boolean
30
+ hasNode(node: TNode): boolean
31
+ add(n: TNode, meta: serializedNodeWithId): void
32
+ replace(id: number, n: TNode): void
33
+ reset(): void
34
+ }
35
+
36
+ export declare class Mirror implements IMirror<Node> {
37
+ // eslint-disable-next-line @typescript-eslint/naming-convention
38
+ private idNodeMap
39
+ // eslint-disable-next-line @typescript-eslint/naming-convention
40
+ private nodeMetaMap
41
+ getId(n: Node | undefined | null): number
42
+ getNode(id: number): Node | null
43
+ getIds(): number[]
44
+ getMeta(n: Node): serializedNodeWithId | null
45
+ removeNodeFromMap(n: Node): void
46
+ has(id: number): boolean
47
+ hasNode(node: Node): boolean
48
+ add(n: Node, meta: serializedNodeWithId): void
49
+ replace(id: number, n: Node): void
50
+ reset(): void
51
+ }
52
+
53
+ export type attributes = {
54
+ [key: string]: string | number | true | null
55
+ }
56
+
57
+ export enum NodeType {
58
+ Document = 0,
59
+ DocumentType = 1,
60
+ Element = 2,
61
+ Text = 3,
62
+ CDATA = 4,
63
+ Comment = 5,
64
+ }
65
+
66
+ export type documentNode = {
67
+ type: NodeType.Document
68
+ childNodes: serializedNodeWithId[]
69
+ compatMode?: string
70
+ }
71
+
72
+ export type documentTypeNode = {
73
+ type: NodeType.DocumentType
74
+ name: string
75
+ publicId: string
76
+ systemId: string
77
+ }
78
+
79
+ export type elementNode = {
80
+ type: NodeType.Element
81
+ tagName: string
82
+ attributes: attributes
83
+ childNodes: serializedNodeWithId[]
84
+ isSVG?: true
85
+ needBlock?: boolean
86
+ isCustom?: true
87
+ }
88
+
89
+ export type textNode = {
90
+ type: NodeType.Text
91
+ textContent: string
92
+ isStyle?: true
93
+ }
94
+
95
+ export type cdataNode = {
96
+ type: NodeType.CDATA
97
+ textContent: ''
98
+ }
99
+
100
+ export type commentNode = {
101
+ type: NodeType.Comment
102
+ textContent: string
103
+ }
104
+
105
+ export type serializedNode = (documentNode | documentTypeNode | elementNode | textNode | cdataNode | commentNode) & {
106
+ rootId?: number
107
+ isShadowHost?: boolean
108
+ isShadow?: boolean
109
+ }
110
+
111
+ export type serializedNodeWithId = serializedNode & {
112
+ id: number
113
+ }
114
+
115
+ // ===== Types from @rrweb/types =====
116
+
117
+ export type blockClass = string | RegExp
118
+
119
+ export type maskTextClass = string | RegExp
120
+
121
+ export type IWindow = Window & typeof globalThis
122
+
123
+ export type listenerHandler = () => void
124
+
125
+ export type KeepIframeSrcFn = (src: string) => boolean
126
+
127
+ export type PackFn = (event: eventWithTime) => string
128
+
129
+ export enum EventType {
130
+ DomContentLoaded = 0,
131
+ Load = 1,
132
+ FullSnapshot = 2,
133
+ IncrementalSnapshot = 3,
134
+ Meta = 4,
135
+ Custom = 5,
136
+ Plugin = 6,
137
+ }
138
+
139
+ export enum IncrementalSource {
140
+ Mutation = 0,
141
+ MouseMove = 1,
142
+ MouseInteraction = 2,
143
+ Scroll = 3,
144
+ ViewportResize = 4,
145
+ Input = 5,
146
+ TouchMove = 6,
147
+ MediaInteraction = 7,
148
+ StyleSheetRule = 8,
149
+ CanvasMutation = 9,
150
+ Font = 10,
151
+ Log = 11,
152
+ Drag = 12,
153
+ StyleDeclaration = 13,
154
+ Selection = 14,
155
+ AdoptedStyleSheet = 15,
156
+ CustomElement = 16,
157
+ }
158
+
159
+ export type domContentLoadedEvent = {
160
+ type: EventType.DomContentLoaded
161
+ data: unknown
162
+ }
163
+
164
+ export type loadedEvent = {
165
+ type: EventType.Load
166
+ data: unknown
167
+ }
168
+
169
+ export type fullSnapshotEvent = {
170
+ type: EventType.FullSnapshot
171
+ data: {
172
+ node: serializedNodeWithId
173
+ initialOffset: {
174
+ top: number
175
+ left: number
176
+ }
177
+ }
178
+ }
179
+
180
+ export type metaEvent = {
181
+ type: EventType.Meta
182
+ data: {
183
+ href: string
184
+ width: number
185
+ height: number
186
+ }
187
+ }
188
+
189
+ export type customEvent<T = unknown> = {
190
+ type: EventType.Custom
191
+ data: {
192
+ tag: string
193
+ payload: T
194
+ }
195
+ }
196
+
197
+ export type pluginEvent<T = unknown> = {
198
+ type: EventType.Plugin
199
+ data: {
200
+ plugin: string
201
+ payload: T
202
+ }
203
+ }
204
+
205
+ export type styleOMValue = {
206
+ [key: string]: styleValueWithPriority | string | false
207
+ }
208
+
209
+ export type styleValueWithPriority = [string, string]
210
+
211
+ export type textMutation = {
212
+ id: number
213
+ value: string | null
214
+ }
215
+
216
+ export type attributeMutation = {
217
+ id: number
218
+ attributes: {
219
+ [key: string]: string | styleOMValue | null
220
+ }
221
+ }
222
+
223
+ export type removedNodeMutation = {
224
+ parentId: number
225
+ id: number
226
+ isShadow?: boolean
227
+ }
228
+
229
+ export type addedNodeMutation = {
230
+ parentId: number
231
+ previousId?: number | null
232
+ nextId: number | null
233
+ node: serializedNodeWithId
234
+ }
235
+
236
+ export type mutationCallbackParam = {
237
+ texts: textMutation[]
238
+ attributes: attributeMutation[]
239
+ removes: removedNodeMutation[]
240
+ adds: addedNodeMutation[]
241
+ isAttachIframe?: true
242
+ }
243
+
244
+ export type mutationData = {
245
+ source: IncrementalSource.Mutation
246
+ } & mutationCallbackParam
247
+
248
+ export type mousePosition = {
249
+ x: number
250
+ y: number
251
+ id: number
252
+ timeOffset: number
253
+ }
254
+
255
+ export enum MouseInteractions {
256
+ MouseUp = 0,
257
+ MouseDown = 1,
258
+ Click = 2,
259
+ ContextMenu = 3,
260
+ DblClick = 4,
261
+ Focus = 5,
262
+ Blur = 6,
263
+ TouchStart = 7,
264
+ TouchMove_Departed = 8,
265
+ TouchEnd = 9,
266
+ TouchCancel = 10,
267
+ }
268
+
269
+ export enum PointerTypes {
270
+ Mouse = 0,
271
+ Pen = 1,
272
+ Touch = 2,
273
+ }
274
+
275
+ type mouseInteractionParam = {
276
+ type: MouseInteractions
277
+ id: number
278
+ x?: number
279
+ y?: number
280
+ pointerType?: PointerTypes
281
+ }
282
+
283
+ export type mouseInteractionData = {
284
+ source: IncrementalSource.MouseInteraction
285
+ } & mouseInteractionParam
286
+
287
+ export type mousemoveData = {
288
+ source: IncrementalSource.MouseMove | IncrementalSource.TouchMove | IncrementalSource.Drag
289
+ positions: mousePosition[]
290
+ }
291
+
292
+ export type scrollPosition = {
293
+ id: number
294
+ x: number
295
+ y: number
296
+ }
297
+
298
+ export type scrollData = {
299
+ source: IncrementalSource.Scroll
300
+ } & scrollPosition
301
+
302
+ export type viewportResizeDimension = {
303
+ width: number
304
+ height: number
305
+ }
306
+
307
+ export type viewportResizeData = {
308
+ source: IncrementalSource.ViewportResize
309
+ } & viewportResizeDimension
310
+
311
+ export type inputValue = {
312
+ text: string
313
+ isChecked: boolean
314
+ userTriggered?: boolean
315
+ }
316
+
317
+ export type inputData = {
318
+ source: IncrementalSource.Input
319
+ id: number
320
+ } & inputValue
321
+
322
+ export enum MediaInteractions {
323
+ Play = 0,
324
+ Pause = 1,
325
+ Seeked = 2,
326
+ VolumeChange = 3,
327
+ RateChange = 4,
328
+ }
329
+
330
+ export type mediaInteractionParam = {
331
+ type: MediaInteractions
332
+ id: number
333
+ currentTime?: number
334
+ volume?: number
335
+ muted?: boolean
336
+ loop?: boolean
337
+ playbackRate?: number
338
+ }
339
+
340
+ export type mediaInteractionData = {
341
+ source: IncrementalSource.MediaInteraction
342
+ } & mediaInteractionParam
343
+
344
+ export type styleSheetAddRule = {
345
+ rule: string
346
+ index?: number | number[]
347
+ }
348
+
349
+ export type styleSheetDeleteRule = {
350
+ index: number | number[]
351
+ }
352
+
353
+ export type styleSheetRuleParam = {
354
+ id?: number
355
+ styleId?: number
356
+ removes?: styleSheetDeleteRule[]
357
+ adds?: styleSheetAddRule[]
358
+ replace?: string
359
+ replaceSync?: string
360
+ }
361
+
362
+ export type styleSheetRuleData = {
363
+ source: IncrementalSource.StyleSheetRule
364
+ } & styleSheetRuleParam
365
+
366
+ export enum CanvasContext {
367
+ '2D' = 0,
368
+ WebGL = 1,
369
+ WebGL2 = 2,
370
+ }
371
+
372
+ export type canvasMutationCommand = {
373
+ property: string
374
+ args: Array<unknown>
375
+ setter?: true
376
+ }
377
+
378
+ export type canvasMutationParam =
379
+ | {
380
+ id: number
381
+ type: CanvasContext
382
+ commands: canvasMutationCommand[]
383
+ }
384
+ | ({
385
+ id: number
386
+ type: CanvasContext
387
+ } & canvasMutationCommand)
388
+
389
+ export type canvasMutationData = {
390
+ source: IncrementalSource.CanvasMutation
391
+ } & canvasMutationParam
392
+
393
+ export type fontParam = {
394
+ family: string
395
+ fontSource: string
396
+ buffer: boolean
397
+ descriptors?: FontFaceDescriptors
398
+ }
399
+
400
+ export type fontData = {
401
+ source: IncrementalSource.Font
402
+ } & fontParam
403
+
404
+ export type SelectionRange = {
405
+ start: number
406
+ startOffset: number
407
+ end: number
408
+ endOffset: number
409
+ }
410
+
411
+ export type selectionParam = {
412
+ ranges: Array<SelectionRange>
413
+ }
414
+
415
+ export type selectionData = {
416
+ source: IncrementalSource.Selection
417
+ } & selectionParam
418
+
419
+ export type styleDeclarationParam = {
420
+ id?: number
421
+ styleId?: number
422
+ index: number[]
423
+ set?: {
424
+ property: string
425
+ value: string | null
426
+ priority: string | undefined
427
+ }
428
+ remove?: {
429
+ property: string
430
+ }
431
+ }
432
+
433
+ export type styleDeclarationData = {
434
+ source: IncrementalSource.StyleDeclaration
435
+ } & styleDeclarationParam
436
+
437
+ export type adoptedStyleSheetParam = {
438
+ id: number
439
+ styles?: {
440
+ styleId: number
441
+ rules: styleSheetAddRule[]
442
+ }[]
443
+ styleIds: number[]
444
+ }
445
+
446
+ export type adoptedStyleSheetData = {
447
+ source: IncrementalSource.AdoptedStyleSheet
448
+ } & adoptedStyleSheetParam
449
+
450
+ export type customElementParam = {
451
+ define?: {
452
+ name: string
453
+ }
454
+ }
455
+
456
+ export type customElementData = {
457
+ source: IncrementalSource.CustomElement
458
+ } & customElementParam
459
+
460
+ export type incrementalData =
461
+ | mutationData
462
+ | mousemoveData
463
+ | mouseInteractionData
464
+ | scrollData
465
+ | viewportResizeData
466
+ | inputData
467
+ | mediaInteractionData
468
+ | styleSheetRuleData
469
+ | canvasMutationData
470
+ | fontData
471
+ | selectionData
472
+ | styleDeclarationData
473
+ | adoptedStyleSheetData
474
+ | customElementData
475
+
476
+ export type incrementalSnapshotEvent = {
477
+ type: EventType.IncrementalSnapshot
478
+ data: incrementalData
479
+ }
480
+
481
+ export type eventWithoutTime =
482
+ | domContentLoadedEvent
483
+ | loadedEvent
484
+ | fullSnapshotEvent
485
+ | incrementalSnapshotEvent
486
+ | metaEvent
487
+ | customEvent
488
+ | pluginEvent
489
+
490
+ export type eventWithTime = eventWithoutTime & {
491
+ timestamp: number
492
+ delay?: number
493
+ }
494
+
495
+ export type mutationCallBack = (m: mutationCallbackParam) => void
496
+
497
+ export type mousemoveCallBack = (
498
+ p: mousePosition[],
499
+ source: IncrementalSource.MouseMove | IncrementalSource.TouchMove | IncrementalSource.Drag
500
+ ) => void
501
+
502
+ export type mouseInteractionCallBack = (d: mouseInteractionParam) => void
503
+
504
+ export type scrollCallback = (p: scrollPosition) => void
505
+
506
+ export type viewportResizeCallback = (d: viewportResizeDimension) => void
507
+
508
+ export type inputCallback = (v: inputValue & { id: number }) => void
509
+
510
+ export type mediaInteractionCallback = (p: mediaInteractionParam) => void
511
+
512
+ export type styleSheetRuleCallback = (s: styleSheetRuleParam) => void
513
+
514
+ export type styleDeclarationCallback = (s: styleDeclarationParam) => void
515
+
516
+ export type canvasMutationCallback = (p: canvasMutationParam) => void
517
+
518
+ export type fontCallback = (p: fontParam) => void
519
+
520
+ export type selectionCallback = (p: selectionParam) => void
521
+
522
+ export type customElementCallback = (c: customElementParam) => void
523
+
524
+ export type adoptedStyleSheetCallback = (a: adoptedStyleSheetParam) => void
525
+
526
+ export type hooksParam = {
527
+ mutation?: mutationCallBack
528
+ mousemove?: mousemoveCallBack
529
+ mouseInteraction?: mouseInteractionCallBack
530
+ scroll?: scrollCallback
531
+ viewportResize?: viewportResizeCallback
532
+ input?: inputCallback
533
+ mediaInteaction?: mediaInteractionCallback
534
+ styleSheetRule?: styleSheetRuleCallback
535
+ styleDeclaration?: styleDeclarationCallback
536
+ canvasMutation?: canvasMutationCallback
537
+ font?: fontCallback
538
+ selection?: selectionCallback
539
+ customElement?: customElementCallback
540
+ }
541
+
542
+ export type SamplingStrategy = Partial<{
543
+ mousemove: boolean | number
544
+ mousemoveCallback: number
545
+ mouseInteraction: boolean | Record<string, boolean | undefined>
546
+ scroll: number
547
+ media: number
548
+ input: 'all' | 'last'
549
+ canvas: 'all' | number
550
+ }>
551
+
552
+ export interface ICrossOriginIframeMirror {
553
+ getId(
554
+ iframe: HTMLIFrameElement,
555
+ remoteId: number,
556
+ parentToRemoteMap?: Map<number, number>,
557
+ remoteToParentMap?: Map<number, number>
558
+ ): number
559
+ getIds(iframe: HTMLIFrameElement, remoteId: number[]): number[]
560
+ getRemoteId(iframe: HTMLIFrameElement, parentId: number, map?: Map<number, number>): number
561
+ getRemoteIds(iframe: HTMLIFrameElement, parentId: number[]): number[]
562
+ reset(iframe?: HTMLIFrameElement): void
563
+ }
564
+
565
+ export type RecordPlugin<TOptions = unknown> = {
566
+ name: string
567
+ observer?: (cb: (...args: Array<unknown>) => void, win: IWindow, options: TOptions) => listenerHandler
568
+ eventProcessor?: <TExtend>(event: eventWithTime) => eventWithTime & TExtend
569
+ getMirror?: (mirrors: {
570
+ nodeMirror: Mirror
571
+ crossOriginIframeMirror: ICrossOriginIframeMirror
572
+ crossOriginIframeStyleMirror: ICrossOriginIframeMirror
573
+ }) => void
574
+ options: TOptions
575
+ }
@@ -0,0 +1,114 @@
1
+ // This file is supposed to replicate some of the types hidden inside `@rrweb/record`
2
+ // to guarantee that our users can use this library - and validate types - without
3
+ // having to install `@rrweb/record`
4
+ //
5
+ // NOTE: This file should be updated and kept in sync with `@rrweb/record` if we ever update it.
6
+ // NOTE²: The initial types are not exported, we're only exporting the two types at the bottom.
7
+ // They're only here to allow the bottom types to be more easily defined.
8
+
9
+ import type {
10
+ blockClass,
11
+ eventWithTime,
12
+ hooksParam,
13
+ KeepIframeSrcFn,
14
+ maskTextClass,
15
+ PackFn,
16
+ RecordPlugin,
17
+ SamplingStrategy,
18
+ } from './rrweb-types'
19
+
20
+ // Replication of `MaskInputOptions` from inside `@rrweb/record/rrweb-snapshot`
21
+ type MaskInputOptions = Partial<{
22
+ color: boolean
23
+ date: boolean
24
+ 'datetime-local': boolean
25
+ email: boolean
26
+ month: boolean
27
+ number: boolean
28
+ range: boolean
29
+ search: boolean
30
+ tel: boolean
31
+ text: boolean
32
+ time: boolean
33
+ url: boolean
34
+ week: boolean
35
+ textarea: boolean
36
+ select: boolean
37
+ password: boolean
38
+ }>
39
+
40
+ // Replication of `MaskInputFn` from inside `@rrweb/record/rrweb-snapshot`
41
+ type MaskInputFn = (text: string, element: HTMLElement) => string
42
+
43
+ // Replication of `MaskTextFn` from inside `@rrweb/record/rrweb-snapshot`
44
+ type MaskTextFn = (text: string, element: HTMLElement | null) => string
45
+
46
+ // Replication of `SlimDOMOptions` from inside `@rrweb/record/rrweb-snapshot`
47
+ type SlimDOMOptions = Partial<{
48
+ script: boolean
49
+ comment: boolean
50
+ headFavicon: boolean
51
+ headWhitespace: boolean
52
+ headMetaDescKeywords: boolean
53
+ headMetaSocial: boolean
54
+ headMetaRobots: boolean
55
+ headMetaHttpEquiv: boolean
56
+ headMetaAuthorship: boolean
57
+ headMetaVerification: boolean
58
+ headTitleMutations: boolean
59
+ }>
60
+
61
+ // Replication of `DataURLOptions` from inside `@rrweb/record/rrweb-snapshot`
62
+ type DataURLOptions = Partial<{
63
+ type: string
64
+ quality: number
65
+ }>
66
+
67
+ // Replication of `ErrorHandler` from inside `@rrweb/record`
68
+ type ErrorHandler = (error: unknown) => void | boolean
69
+
70
+ // Replication of `recordOptions` from inside `@rrweb/record`
71
+ export type recordOptions = {
72
+ emit?: (e: eventWithTime, isCheckout?: boolean) => void
73
+ checkoutEveryNth?: number
74
+ checkoutEveryNms?: number
75
+ blockClass?: blockClass
76
+ blockSelector?: string
77
+ ignoreClass?: string
78
+ ignoreSelector?: string
79
+ maskTextClass?: maskTextClass
80
+ maskTextSelector?: string
81
+ maskAllInputs?: boolean
82
+ maskInputOptions?: MaskInputOptions
83
+ maskInputFn?: MaskInputFn
84
+ maskTextFn?: MaskTextFn
85
+ slimDOMOptions?: SlimDOMOptions | 'all' | true
86
+ ignoreCSSAttributes?: Set<string>
87
+ inlineStylesheet?: boolean
88
+ hooks?: hooksParam
89
+ packFn?: PackFn
90
+ sampling?: SamplingStrategy
91
+ dataURLOptions?: DataURLOptions
92
+ recordDOM?: boolean
93
+ recordCanvas?: boolean
94
+ recordCrossOriginIframes?: boolean
95
+ recordAfter?: 'DOMContentLoaded' | 'load'
96
+ userTriggeredOnInput?: boolean
97
+ collectFonts?: boolean
98
+ inlineImages?: boolean
99
+ plugins?: RecordPlugin[]
100
+ mousemoveWait?: number
101
+ keepIframeSrcFn?: KeepIframeSrcFn
102
+ errorHandler?: ErrorHandler
103
+ }
104
+
105
+ // Replication of `record` from inside `@rrweb/record`
106
+ export type rrwebRecord = {
107
+ (options: recordOptions): () => void
108
+ addCustomEvent: (tag: string, payload: any) => void
109
+ takeFullSnapshot: () => void
110
+ mirror: {
111
+ getId(n: Node | undefined | null): number
112
+ getNode(id: number): Node | null
113
+ }
114
+ }
@@ -0,0 +1,26 @@
1
+ import { isArray, isUndefined, clampToRange } from '@posthog/core'
2
+ import { logger } from '../utils/logger'
3
+
4
+ export function appendArray(currentValue: string[] | undefined, sampleType: string | string[]): string[] {
5
+ return [...(currentValue ? currentValue : []), ...(isArray(sampleType) ? sampleType : [sampleType])]
6
+ }
7
+
8
+ export function updateThreshold(currentValue: number | undefined, percent: number): number {
9
+ return (isUndefined(currentValue) ? 1 : currentValue) * percent
10
+ }
11
+
12
+ export function simpleHash(str: string) {
13
+ let hash = 0
14
+ for (let i = 0; i < str.length; i++) {
15
+ hash = (hash << 5) - hash + str.charCodeAt(i) // (hash * 31) + char code
16
+ hash |= 0 // Convert to 32bit integer
17
+ }
18
+ return Math.abs(hash)
19
+ }
20
+
21
+ /*
22
+ * receives percent as a number between 0 and 1
23
+ */
24
+ export function sampleOnProperty(prop: string, percent: number): boolean {
25
+ return simpleHash(prop) % 100 < clampToRange(percent * 100, 0, 100, logger)
26
+ }