@maple-dev/browser 0.3.0 → 0.4.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.
- package/LICENSE +21 -0
- package/README.md +36 -1
- package/dist/index.d.mts +92 -8
- package/dist/index.mjs +437 -727
- package/dist/replay-session-B_ACRogX.mjs +390 -0
- package/dist/sink-DHTfvFgl.mjs +1149 -0
- package/package.json +3 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Maple Tech Labs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -31,7 +31,9 @@ That single call:
|
|
|
31
31
|
ingest (`POST /v1/traces`);
|
|
32
32
|
- records the session with rrweb, chunking events (~5s / 100KB windows),
|
|
33
33
|
gzipping them with the native `CompressionStream`, and uploading to
|
|
34
|
-
`POST /v1/sessionReplays/blob
|
|
34
|
+
`POST /v1/sessionReplays/blob`. rrweb ships in a lazy code-split chunk loaded
|
|
35
|
+
only once a session is sampled in, so a `sampleRate` below 1 costs the
|
|
36
|
+
unsampled visitors nothing beyond the ~8 kB gzipped base SDK;
|
|
35
37
|
- writes session metadata at start (`active`) and on page hide (`ended`),
|
|
36
38
|
including the trace ids observed during the session.
|
|
37
39
|
|
|
@@ -44,16 +46,49 @@ metadata rows and stamped as `user.id` on future browser-created spans.
|
|
|
44
46
|
```ts
|
|
45
47
|
MapleBrowser.identify(user.id)
|
|
46
48
|
|
|
49
|
+
// or the full identity — email, name, and the company/team to group by
|
|
50
|
+
MapleBrowser.identify({
|
|
51
|
+
id: user.id,
|
|
52
|
+
email: user.email,
|
|
53
|
+
groupId: org.id,
|
|
54
|
+
groupName: org.name,
|
|
55
|
+
traits: { plan: "pro" },
|
|
56
|
+
})
|
|
57
|
+
|
|
47
58
|
// after sign-out
|
|
48
59
|
MapleBrowser.identify(null)
|
|
49
60
|
```
|
|
50
61
|
|
|
62
|
+
Each call replaces the identity rather than merging it.
|
|
63
|
+
|
|
64
|
+
## Custom events
|
|
65
|
+
|
|
66
|
+
`track(name, props)` records a product event as a `session_events` row with
|
|
67
|
+
`Type='custom'`, so it shows up inline in the session transcript rather than in
|
|
68
|
+
a separate analytics silo. Calls before `init()` finishes are queued.
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
MapleBrowser.track("checkout_completed", { plan: "pro", seats: 12 })
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Linking a marketing site to your app
|
|
75
|
+
|
|
76
|
+
The visitor id lives in localStorage **and** a cookie scoped to your registered
|
|
77
|
+
domain, so `example.com` and `app.example.com` resolve to the same `VisitorId`
|
|
78
|
+
and an anonymous pre-signup visit links to the account it becomes. Session ids
|
|
79
|
+
stay per-origin; `VisitorId` is the join key. Override the scope with
|
|
80
|
+
`privacy.crossSubdomainCookie` / `privacy.cookieDomain`.
|
|
81
|
+
|
|
51
82
|
## Privacy
|
|
52
83
|
|
|
53
84
|
`maskAllInputs` (default **on**) masks every `<input>` value. Use rrweb's
|
|
54
85
|
attribute hooks (`data-rr-block`, `.rr-block`, `.rr-ignore`) to block elements
|
|
55
86
|
or subtrees from capture.
|
|
56
87
|
|
|
88
|
+
`privacy.requireConsent` holds all capture until `MapleBrowser.setConsent(true)`.
|
|
89
|
+
Global Privacy Control is honored by default and suppresses the persistent
|
|
90
|
+
visitor id; `doNotTrack` is not, unless `privacy.respectDoNotTrack` is set.
|
|
91
|
+
|
|
57
92
|
## Notes
|
|
58
93
|
|
|
59
94
|
- Replay event blobs live in object storage; only small, queryable metadata is
|
package/dist/index.d.mts
CHANGED
|
@@ -1,3 +1,35 @@
|
|
|
1
|
+
//#region ../browser-session/src/identity.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Who the current visitor is.
|
|
4
|
+
*
|
|
5
|
+
* Held in module memory only — never written to localStorage/sessionStorage.
|
|
6
|
+
* An email at rest in browser storage is a PII surface with no upside here: the
|
|
7
|
+
* identity is re-attached to every metadata row the SDK posts, so there is
|
|
8
|
+
* nothing to persist across a reload that the host app won't re-`identify()`.
|
|
9
|
+
*/
|
|
10
|
+
/** Trait values a host app may pass. Coerced to strings before they leave. */
|
|
11
|
+
type TraitValue = string | number | boolean | null | undefined;
|
|
12
|
+
interface MapleIdentity {
|
|
13
|
+
readonly id?: string;
|
|
14
|
+
readonly email?: string;
|
|
15
|
+
readonly username?: string;
|
|
16
|
+
/** Company / team / tenant — the grouping dimension in the sessions UI. */
|
|
17
|
+
readonly groupId?: string;
|
|
18
|
+
readonly groupName?: string;
|
|
19
|
+
/** Open-ended attributes (plan, role, …). Capped; see `MAX_TRAITS`. */
|
|
20
|
+
readonly traits?: Readonly<Record<string, TraitValue>>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* `identify` accepts a bare user id as well as the full object — the string
|
|
24
|
+
* form is what every existing caller passes, and keeping it means this can ship
|
|
25
|
+
* without touching them.
|
|
26
|
+
*/
|
|
27
|
+
type IdentifyInput = string | null | undefined | MapleIdentity;
|
|
28
|
+
//#endregion
|
|
29
|
+
//#region ../browser-session/src/track.d.ts
|
|
30
|
+
/** Properties a host app may attach to a custom event. */
|
|
31
|
+
type TrackProps = Readonly<Record<string, unknown>>;
|
|
32
|
+
//#endregion
|
|
1
33
|
//#region src/config.d.ts
|
|
2
34
|
/** Public configuration for `MapleBrowser.init`. */
|
|
3
35
|
interface MapleBrowserConfig {
|
|
@@ -16,10 +48,18 @@ interface MapleBrowserConfig {
|
|
|
16
48
|
readonly serviceVersion?: string;
|
|
17
49
|
/** Deployment environment, e.g. "production". */
|
|
18
50
|
readonly environment?: string;
|
|
19
|
-
/**
|
|
51
|
+
/**
|
|
52
|
+
* Optional user id attached to replay sessions and future browser spans.
|
|
53
|
+
*
|
|
54
|
+
* @deprecated Pass `user` instead — it carries email, name, and the
|
|
55
|
+
* company/team grouping the Sessions UI can filter by.
|
|
56
|
+
*/
|
|
20
57
|
readonly userId?: string | null | undefined;
|
|
58
|
+
/** End-user identity attached to sessions and browser spans. */
|
|
59
|
+
readonly user?: MapleIdentity | undefined;
|
|
21
60
|
readonly tracing?: {
|
|
22
|
-
/** Default true. */
|
|
61
|
+
/** Default true. */
|
|
62
|
+
readonly enabled?: boolean;
|
|
23
63
|
/**
|
|
24
64
|
* Auto-instrument `fetch()` to create network spans. Default true. Set
|
|
25
65
|
* false when another tracer (e.g. the Effect client SDK) already
|
|
@@ -29,23 +69,52 @@ interface MapleBrowserConfig {
|
|
|
29
69
|
readonly instrumentFetch?: boolean;
|
|
30
70
|
};
|
|
31
71
|
readonly replay?: {
|
|
32
|
-
/** Default true. */
|
|
72
|
+
/** Default true. */
|
|
73
|
+
readonly enabled?: boolean;
|
|
74
|
+
/** Fraction of sessions to record, 0–1. Default 1. */
|
|
33
75
|
readonly sampleRate?: number;
|
|
34
76
|
};
|
|
35
77
|
readonly privacy?: {
|
|
36
|
-
/** Mask all `<input>` values. Default true. */
|
|
78
|
+
/** Mask all `<input>` values. Default true. */
|
|
79
|
+
readonly maskAllInputs?: boolean;
|
|
37
80
|
/**
|
|
38
81
|
* Mask all text in the rrweb recording and omit captured click target
|
|
39
82
|
* text from session events. Default false.
|
|
40
83
|
*/
|
|
41
84
|
readonly maskAllText?: boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Store a persistent visitor id (localStorage) so unique visitors and
|
|
87
|
+
* new-vs-returning are measurable. Default true. Turning it off also
|
|
88
|
+
* purges any id already stored.
|
|
89
|
+
*/
|
|
90
|
+
readonly persistVisitorId?: boolean;
|
|
91
|
+
/**
|
|
92
|
+
* Scope the visitor-id cookie to the registered domain, so a marketing site
|
|
93
|
+
* and an app on sibling subdomains (`example.com` and `app.example.com`)
|
|
94
|
+
* resolve to the same visitor and a pre-signup visit links to the account it
|
|
95
|
+
* becomes. Default true. Set false to keep the cookie host-only.
|
|
96
|
+
*/
|
|
97
|
+
readonly crossSubdomainCookie?: boolean;
|
|
98
|
+
/**
|
|
99
|
+
* Explicit cookie `Domain=` (no leading dot), e.g. `"example.com"`. Defaults
|
|
100
|
+
* to the broadest domain the browser accepts, discovered by probing. `""`
|
|
101
|
+
* forces a host-only cookie.
|
|
102
|
+
*/
|
|
103
|
+
readonly cookieDomain?: string;
|
|
104
|
+
/** Capture nothing until `MapleBrowser.setConsent(true)`. Default false. */
|
|
105
|
+
readonly requireConsent?: boolean;
|
|
106
|
+
/** Send `identify()`'s email to the warehouse. Default true. */
|
|
107
|
+
readonly captureUserEmail?: boolean;
|
|
108
|
+
/** Treat `navigator.doNotTrack` like Global Privacy Control. Default false. */
|
|
109
|
+
readonly respectDoNotTrack?: boolean;
|
|
42
110
|
};
|
|
43
111
|
}
|
|
44
112
|
//#endregion
|
|
45
113
|
//#region src/init.d.ts
|
|
46
114
|
interface MapleBrowserHandle {
|
|
115
|
+
/** Empty until consent is granted when `requireConsent` is enabled. */
|
|
47
116
|
readonly sessionId: string;
|
|
48
|
-
/** Tear down tracing +
|
|
117
|
+
/** Tear down tracing + session capture, flushing the final buffers. */
|
|
49
118
|
readonly shutdown: () => Promise<void>;
|
|
50
119
|
}
|
|
51
120
|
//#endregion
|
|
@@ -62,11 +131,26 @@ interface MapleBrowserHandle {
|
|
|
62
131
|
* ingestKey: "maple_pk_...",
|
|
63
132
|
* serviceName: "acme-web",
|
|
64
133
|
* })
|
|
134
|
+
*
|
|
135
|
+
* MapleBrowser.identify({ id: user.id, email: user.email, groupId: org.id, groupName: org.name })
|
|
136
|
+
* MapleBrowser.track("checkout_completed", { plan: "pro", seats: 5 })
|
|
65
137
|
* ```
|
|
66
138
|
*/
|
|
67
139
|
declare const MapleBrowser: {
|
|
68
|
-
init: (config: MapleBrowserConfig) => MapleBrowserHandle;
|
|
69
|
-
|
|
140
|
+
init: (config: MapleBrowserConfig) => MapleBrowserHandle;
|
|
141
|
+
/**
|
|
142
|
+
* Attach, replace, or clear the end-user identity on the active session.
|
|
143
|
+
* Accepts a bare user id or the full identity object. Safe to call repeatedly.
|
|
144
|
+
*/
|
|
145
|
+
identify: (input?: IdentifyInput) => void;
|
|
146
|
+
/**
|
|
147
|
+
* Record a custom product event against the active session. Safe to call
|
|
148
|
+
* before `init` — events are queued (capped) and drained once the session
|
|
149
|
+
* starts.
|
|
150
|
+
*/
|
|
151
|
+
track: (name: string, props?: TrackProps) => void;
|
|
152
|
+
/** Grant or revoke consent when `privacy.requireConsent` is on. */
|
|
153
|
+
setConsent: (granted: boolean) => void;
|
|
70
154
|
};
|
|
71
155
|
//#endregion
|
|
72
|
-
export { MapleBrowser, type MapleBrowserConfig, type MapleBrowserHandle };
|
|
156
|
+
export { type IdentifyInput, MapleBrowser, type MapleBrowserConfig, type MapleBrowserHandle, type MapleIdentity, type TrackProps, type TraitValue };
|