pyxis-analytics 0.2.1 → 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/README.md +53 -26
- package/dist/core/options.d.ts +2 -0
- package/dist/core/privacy.d.ts +1 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -31,11 +31,12 @@ showing every batch it would send, with no request leaving the page.
|
|
|
31
31
|
|
|
32
32
|
## Ecosystem
|
|
33
33
|
|
|
34
|
-
| Repository | Role
|
|
35
|
-
| -------------------------------------------------------- |
|
|
36
|
-
| [pyxis-api](https://github.com/samuelcsantana/pyxis-api) | Ingestion, dashboard sign-in and queries, erasure, retention
|
|
37
|
-
| **pyxis-sdk** (this one) | Browser tracker published to npm as `pyxis-analytics`
|
|
38
|
-
| [pyxis-web](https://github.com/samuelcsantana/pyxis-web) | The dashboard: overview, funnels, features, requests
|
|
34
|
+
| Repository | Role |
|
|
35
|
+
| -------------------------------------------------------- | ---------------------------------------------------------------- |
|
|
36
|
+
| [pyxis-api](https://github.com/samuelcsantana/pyxis-api) | Ingestion, dashboard sign-in and queries, erasure, retention |
|
|
37
|
+
| **pyxis-sdk** (this one) | Browser tracker published to npm as `pyxis-analytics` |
|
|
38
|
+
| [pyxis-web](https://github.com/samuelcsantana/pyxis-web) | The dashboard: overview, funnels, features, requests |
|
|
39
|
+
| [pyxis-mcp](https://github.com/samuelcsantana/pyxis-mcp) | MCP server: Claude and other agents read the dashboard's numbers |
|
|
39
40
|
|
|
40
41
|
## Why it exists
|
|
41
42
|
|
|
@@ -45,6 +46,13 @@ tab, URLs reduced to path templates, query strings dropped except campaign tags,
|
|
|
45
46
|
track" signals honored before anything is queued. It is small enough to forget about: the budget
|
|
46
47
|
is 5 KB gzipped, enforced in CI.
|
|
47
48
|
|
|
49
|
+
Read more: [why Pyxis was built and what it never stores][post], the introduction post on the
|
|
50
|
+
author's blog, also in [Portuguese][post-pt] and [Spanish][post-es].
|
|
51
|
+
|
|
52
|
+
[post]: https://www.samuelsantana.dev/en/blog/pyxis-analytics-without-cookies-ip-or-personal-data
|
|
53
|
+
[post-pt]: https://www.samuelsantana.dev/blog/pyxis-analytics-sem-cookie-sem-ip-sem-dado-pessoal
|
|
54
|
+
[post-es]: https://www.samuelsantana.dev/es/blog/pyxis-analytics-sin-cookies-sin-ip-sin-datos-personales
|
|
55
|
+
|
|
48
56
|
## API
|
|
49
57
|
|
|
50
58
|
```ts
|
|
@@ -61,28 +69,39 @@ identify('user_8f2c');
|
|
|
61
69
|
reset();
|
|
62
70
|
```
|
|
63
71
|
|
|
64
|
-
| Function | Behavior
|
|
65
|
-
| ------------------------- |
|
|
66
|
-
| `init(options)` | Starts the tracker and records page views on navigation; no key means no-op
|
|
67
|
-
| `track(name, properties)` | A named event with up to 10 short properties
|
|
68
|
-
| `identify(userId)` | Attaches the site's internal user id to later events and links the current visit
|
|
69
|
-
| `reset()` | Sends what is queued, then starts a new anonymous visit (for sign-out)
|
|
70
|
-
| `optOut()` / `optIn()` | Stops or resumes tracking in this browser, effective at once in this page
|
|
71
|
-
| `trackingStatus()` | `'on'`, `'opted-out'` or `'blocked-by-browser'`, for an opt-out switch
|
|
72
|
-
| `trackRequest(request)` | The method, route template, status and duration of an HTTP call
|
|
73
|
-
|
|
74
|
-
| Option | Default
|
|
75
|
-
| --------------- |
|
|
76
|
-
| `key` | required
|
|
77
|
-
| `endpoint` | required
|
|
78
|
-
| `pathRules` | `[]`
|
|
79
|
-
| `autoPageViews` | `true`
|
|
80
|
-
| `
|
|
72
|
+
| Function | Behavior |
|
|
73
|
+
| ------------------------- | ----------------------------------------------------------------------------------------- |
|
|
74
|
+
| `init(options)` | Starts the tracker and records page views on navigation; no key or automation means no-op |
|
|
75
|
+
| `track(name, properties)` | A named event with up to 10 short properties |
|
|
76
|
+
| `identify(userId)` | Attaches the site's internal user id to later events and links the current visit |
|
|
77
|
+
| `reset()` | Sends what is queued, then starts a new anonymous visit (for sign-out) |
|
|
78
|
+
| `optOut()` / `optIn()` | Stops or resumes tracking in this browser, effective at once in this page |
|
|
79
|
+
| `trackingStatus()` | `'on'`, `'opted-out'` or `'blocked-by-browser'`, for an opt-out switch |
|
|
80
|
+
| `trackRequest(request)` | The method, route template, status and duration of an HTTP call |
|
|
81
|
+
|
|
82
|
+
| Option | Default | Meaning |
|
|
83
|
+
| --------------- | ------------------- | ------------------------------------------------------------------------------------------------ |
|
|
84
|
+
| `key` | required | The project's public key; empty or missing disables the SDK without an error |
|
|
85
|
+
| `endpoint` | required | The API's base URL, `http` or `https` |
|
|
86
|
+
| `pathRules` | `[]` | Templates tried before the default rules: `'/blog/:slug'` turns `/blog/hello` into `/blog/:slug` |
|
|
87
|
+
| `autoPageViews` | `true` | Record the landing page and every History API route change as a `page_view` |
|
|
88
|
+
| `referrer` | `document.referrer` | The address the visitor came from, for the first page view; `''` means none |
|
|
89
|
+
| `debug` | unset | `{ dryRun, onBatch }`: inspect batches, optionally without sending them |
|
|
81
90
|
|
|
82
91
|
A route change that keeps the same templated path records nothing, so routers that call
|
|
83
92
|
`replaceState` on their own do not inflate page views. Only the first page view of a visit carries
|
|
84
93
|
its attribution (referrer host, campaign tags, ad click flag).
|
|
85
94
|
|
|
95
|
+
A page that sends the visitor elsewhere as soon as it loads, such as a language redirect with
|
|
96
|
+
`location.replace`, leaves the next page with its own address as `document.referrer`, so the site
|
|
97
|
+
the visitor came from is lost and the visit counts as direct. Keep the first page's
|
|
98
|
+
`document.referrer` before moving (in `sessionStorage`, for instance) and pass it as `referrer` to
|
|
99
|
+
`init` on the page it opens:
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
init({ key: 'pyxis_pk_…', endpoint: 'https://api.pyxis.example.com', referrer: carriedReferrer });
|
|
103
|
+
```
|
|
104
|
+
|
|
86
105
|
Call `identify(userId)` on every load of the signed-in part of the site, not only right after
|
|
87
106
|
sign-in: the id lives in `sessionStorage`, so a new tab starts without it, and calling it again
|
|
88
107
|
for the same user sends nothing. Pass the site's internal id (`[A-Za-z0-9_-]{1,64}`), never an
|
|
@@ -124,16 +143,22 @@ status `0` means no response arrived. An optional `errorCode` carries your API's
|
|
|
124
143
|
become a single `from_ad_click: true`. Meta's `fbclid` is not counted as one: Meta adds it to
|
|
125
144
|
every link that leaves Facebook or Instagram, ads or not.
|
|
126
145
|
- Global Privacy Control and Do Not Track switch the tracker off.
|
|
146
|
+
- A browser driven by automation (`navigator.webdriver` is `true`, as under WebDriver or
|
|
147
|
+
Playwright) is not measured: `init()` does nothing, as without a key, and says why when `debug`
|
|
148
|
+
is set. To see events in your own end-to-end tests, launch Chromium with
|
|
149
|
+
`--disable-blink-features=AutomationControlled`, which makes `navigator.webdriver` false
|
|
150
|
+
([ADR 0005](docs/adr/0005-skip-automated-browsers.md)).
|
|
127
151
|
- `optOut()` writes a single `pyxis:opt-out` marker to `localStorage`, the only thing the SDK
|
|
128
152
|
keeps beyond the tab, so the choice holds on later visits. With storage blocked it still holds
|
|
129
153
|
for the rest of the page. Events not yet sent are dropped: the queue leaves every 5 seconds, or
|
|
130
154
|
with `sendBeacon` when the page is hidden.
|
|
131
155
|
- `optIn()` removes the marker and, if `init()` already ran, starts measuring in the same page,
|
|
132
|
-
beginning with a page view of the current page. Under Global Privacy Control
|
|
133
|
-
only removes the marker.
|
|
156
|
+
beginning with a page view of the current page. Under Global Privacy Control, Do Not Track or
|
|
157
|
+
automation it only removes the marker.
|
|
134
158
|
- `trackingStatus()` tells a site's switch which state it is in. Global Privacy Control and Do Not
|
|
135
159
|
Track win over the visitor's choice, since a switch cannot turn them off; outside a browser
|
|
136
|
-
(server rendering) it answers `'on'`, so read it again on the client.
|
|
160
|
+
(server rendering) it answers `'on'`, so read it again on the client. Automation does not change
|
|
161
|
+
it: the switch is for people, and their browsers block nothing.
|
|
137
162
|
- Batches are sent with `credentials: "omit"`: no cookie of any domain travels with them.
|
|
138
163
|
- No key configured means nothing runs, which keeps tests and local development clean.
|
|
139
164
|
|
|
@@ -179,7 +204,7 @@ npm run build && npm run size
|
|
|
179
204
|
npm run test:cov # unit tests in jsdom, 100% coverage required
|
|
180
205
|
npm run test:tooling # the lint rule and the scripts
|
|
181
206
|
npx vitest run src/contract.test.ts # the contract test alone
|
|
182
|
-
npm run test:e2e # the playground in Chromium: batches valid, nothing sent
|
|
207
|
+
npm run test:e2e # the playground in Chromium: batches valid, nothing sent, none if automated
|
|
183
208
|
```
|
|
184
209
|
|
|
185
210
|
Coverage must stay at **100% of statements, branches, functions and lines** of `src/`; CI fails
|
|
@@ -219,6 +244,7 @@ against the upstream document, so a breaking change in the API shows up here the
|
|
|
219
244
|
| [0002](docs/adr/0002-functional-core.md) | Functional core, thin shell |
|
|
220
245
|
| [0003](docs/adr/0003-zero-dependencies.md) | Zero runtime dependencies and a 3 KB size budget |
|
|
221
246
|
| [0004](docs/adr/0004-five-kilobyte-budget.md) | Raise the size budget to 5 KB |
|
|
247
|
+
| [0005](docs/adr/0005-skip-automated-browsers.md) | Do not measure browsers driven by automation |
|
|
222
248
|
|
|
223
249
|
## Roadmap
|
|
224
250
|
|
|
@@ -230,6 +256,7 @@ against the upstream document, so a breaking change in the API shows up here the
|
|
|
230
256
|
- [x] `trackRequest`
|
|
231
257
|
- [x] Playground on GitHub Pages
|
|
232
258
|
- [x] `trackingStatus()` for opt-out switches
|
|
259
|
+
- [x] Browsers driven by automation are not measured
|
|
233
260
|
|
|
234
261
|
## Contributing and license
|
|
235
262
|
|
package/dist/core/options.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export interface PyxisOptions {
|
|
|
8
8
|
readonly endpoint: string;
|
|
9
9
|
readonly pathRules?: readonly string[];
|
|
10
10
|
readonly autoPageViews?: boolean;
|
|
11
|
+
readonly referrer?: string;
|
|
11
12
|
readonly debug?: PyxisDebugOptions;
|
|
12
13
|
}
|
|
13
14
|
export interface ResolvedOptions {
|
|
@@ -15,6 +16,7 @@ export interface ResolvedOptions {
|
|
|
15
16
|
readonly batchUrl: string;
|
|
16
17
|
readonly pathRules: readonly string[];
|
|
17
18
|
readonly autoPageViews: boolean;
|
|
19
|
+
readonly referrer?: string;
|
|
18
20
|
readonly dryRun: boolean;
|
|
19
21
|
readonly onBatch?: (batch: Batch) => void;
|
|
20
22
|
}
|
package/dist/core/privacy.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export interface PrivacySignals {
|
|
|
4
4
|
readonly globalPrivacyControl: boolean;
|
|
5
5
|
readonly doNotTrack: boolean;
|
|
6
6
|
readonly optedOut: boolean;
|
|
7
|
+
readonly automated: boolean;
|
|
7
8
|
}
|
|
8
9
|
export declare function isDoNotTrack(values: readonly (string | null | undefined)[]): boolean;
|
|
9
10
|
export type TrackingStatus = 'on' | 'opted-out' | 'blocked-by-browser';
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function Se(e){return Array.from(e,t=>t.toString(16).padStart(2,"0")).join("")}function be(e){let t=Se(e),r=(parseInt(t.slice(16,18),16)&63|128).toString(16);return[t.slice(0,8),t.slice(8,12),`4${t.slice(13,16)}`,`${r}${t.slice(18,20)}`,t.slice(20,32)].join("-")}function q(e){return typeof e.randomUUID=="function"?e.randomUUID():be(e.getRandomValues(new Uint8Array(16)))}function ve(){let e=new Map;return{read:t=>e.get(t)??null,write:(t,r)=>{e.set(t,r)},remove:t=>{e.delete(t)}}}function _(e){let t=ve();return{read:r=>{try{return e().getItem(r)}catch{return t.read(r)}},write:(r,n)=>{try{e().setItem(r,n)}catch{t.write(r,n)}},remove:r=>{try{e().removeItem(r)}catch{t.remove(r)}}}}var _e=[1e3,2e3,4e3,8e3,16e3],$=.2,ke=429;function Y(e){if(e.kind==="network-error")return"retry";if(e.kind==="handed-off")return"done";let{status:t}=e;return t>=200&&t<300?"done":t===ke||t>=500?"retry":"drop"}function z(e,t,r){let n=_e[e];if(n===void 0)return;let o=Math.round(n*(1-$+t()*2*$));return r===void 0?o:Math.max(o,r*1e3)}function F(e){if(!(e===null||!/^\d+$/.test(e.trim())))return Number(e.trim())}var G="text/plain;charset=UTF-8";function K(e,t){let r=(o,i)=>t?.(o,new Blob([i],{type:G}))===!0?{kind:"handed-off"}:{kind:"network-error"},n=async(o,i)=>{if(e===void 0)throw new TypeError("fetch is not available");let a=await e(o,{method:"POST",body:i,keepalive:!0,credentials:"omit",headers:{"Content-Type":G}}),f=F(a.headers.get("Retry-After"));return f===void 0?{kind:"response",status:a.status}:{kind:"response",status:a.status,retryAfterSeconds:f}};return{send:async(o,i,a)=>{try{return await n(o,i)}catch{return a||e===void 0?r(o,i):{kind:"network-error"}}}}}function X(){return{now:()=>Date.now(),createId:()=>q(globalThis.crypto),random:Math.random,sessionStore:_(()=>window.sessionStorage),transport:K(typeof fetch=="function"?fetch.bind(globalThis):void 0,typeof navigator.sendBeacon=="function"?navigator.sendBeacon.bind(navigator):void 0)}}function Q(e,t){let{history:r}=t,n=r.pushState.bind(r),o=r.replaceState.bind(r);return r.pushState=(...i)=>{n(...i),e()},r.replaceState=(...i)=>{o(...i),e()},t.addEventListener("popstate",e),()=>{r.pushState=n,r.replaceState=o,t.removeEventListener("popstate",e)}}function W(e,t=document,r=window){let n=()=>{t.visibilityState==="hidden"&&e()};return t.addEventListener("visibilitychange",n),r.addEventListener("pagehide",e),()=>{t.removeEventListener("visibilitychange",n),r.removeEventListener("pagehide",e)}}var E="pyxis:opt-out";var xe=new Set(["1","yes"]);function J(e){return e.some(t=>t!=null&&xe.has(t))}function R(e){return e.globalPrivacyControl||e.doNotTrack?"blocked-by-browser":e.optedOut?"opted-out":"on"}function Z(e){return R(e)==="on"}function ee(e){return typeof e=="string"?e:null}function te(e,t,r){return{globalPrivacyControl:Reflect.get(e,"globalPrivacyControl")===!0,doNotTrack:J([ee(Reflect.get(e,"doNotTrack")),ee(Reflect.get(t,"doNotTrack"))]),optedOut:r.read(E)==="1"}}function S(e){return e.window!==void 0&&e.document!==void 0}var A="identify",Re=["page_view",A,"api_request"],we=10,Ae=100,Pe=/^[a-z][a-z0-9_]{0,63}$/,Oe=/^[a-z0-9_]{1,40}$/,Ne=/^[A-Za-z0-9_-]{1,64}$/;function re(e){return typeof e!="string"||!Pe.test(e)?"invalid":Re.includes(e)?"reserved":"ok"}function ne(e){return typeof e=="string"&&Ne.test(e)}function Ie(e){return typeof e=="boolean"||typeof e=="number"&&Number.isFinite(e)||typeof e=="string"&&e.length<=Ae}function oe(e){let t={},r=[],n=typeof e=="object"&&e!==null?Object.entries(e):[];for(let[o,i]of n)Oe.test(o)?Ie(i)?Object.keys(t).length>=we?r.push({key:o,reason:"too_many"}):t[o]=i:r.push({key:o,reason:"invalid_value"}):r.push({key:o,reason:"invalid_key"});return{properties:t,dropped:r}}var Ue="/v1/batch";function Be(e){let t;try{t=new URL(e)}catch{return}if(!(t.protocol!=="https:"&&t.protocol!=="http:"))return`${t.origin}${t.pathname.replace(/\/+$/,"")}${Ue}`}function ie(e){let t=e.key?.trim();if(!t)return{ok:!1,reason:"no-key"};let r=Be(e.endpoint);if(r===void 0)return{ok:!1,reason:"invalid-endpoint"};let n={key:t,batchUrl:r,pathRules:e.pathRules??[],autoPageViews:e.autoPageViews??!0,dryRun:e.debug?.dryRun??!1},o=e.debug?.onBatch;return{ok:!0,options:o===void 0?n:{...n,onBatch:o}}}var Ve=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,De=/^\d+$/,Le=/\d/g,Me=/%40/i;function He(e){return Ve.test(e)||De.test(e)||(e.match(Le)?.length??0)>=10||e.includes("@")||Me.test(e)}function P(e){let t=e.length;for(;t>0&&e.charAt(t-1)==="/";)t-=1;return t===0?"/":e.slice(0,t)}function Ce(e,t){let r=P(t).split("/");return r.length===e.length&&r.every((n,o)=>n.startsWith(":")||n===e[o])}function T(e,t){let r=P(e).split("/"),n=t.find(i=>Ce(r,i));return(n===void 0?r.map(i=>He(i)?":id":i).join("/"):P(n)).slice(0,256)}var ae="api_request",je=["GET","POST","PUT","PATCH","DELETE"],qe=100,$e=6e5,Ye=599,ze=/^[a-z0-9_.]{1,64}$/,Fe="http://relative.invalid";function Ge(e){return typeof e=="string"&&je.includes(e)}function se(e,t,r){return typeof e=="number"&&Number.isInteger(e)&&e>=t&&e<=r}function Ke(e,t){if(typeof e=="string")try{return T(new URL(e,Fe).pathname,t).slice(0,qe)}catch{return}}function de(e,t){if(!Ge(e.method))return{ok:!1,reason:"method"};let r=Ke(e.url,t);if(r===void 0)return{ok:!1,reason:"url"};if(!se(e.status,0,Ye))return{ok:!1,reason:"status"};if(!se(e.durationMs,0,$e))return{ok:!1,reason:"duration"};let{errorCode:n}=e,o=typeof n=="string"&&ze.test(n),i={method:e.method,route:r,status:e.status,duration_ms:e.durationMs};return{ok:!0,properties:o?{...i,error_code:n}:i,droppedErrorCode:n!==void 0&&!o}}var Xe=[["utm_source","source"],["utm_medium","medium"],["utm_campaign","campaign"]],Qe=["gclid","gbraid","wbraid","msclkid","ttclid","li_fat_id","twclid","dclid"];var We=/^[a-z0-9-]+(\.[a-z0-9-]+)*$/,ce=/^www\./;function Je(e){let t=Xe.flatMap(([r,n])=>{let o=e.get(r)?.trim().slice(0,64);return o?[[n,o]]:[]});return t.length===0?void 0:Object.fromEntries(t)}function Ze(e){try{return new URL(e).hostname.toLowerCase().replace(ce,"")}catch{return}}function et(e,t){let r=e?Ze(e):void 0;return r!==void 0&&r.length<=128&&We.test(r)&&r!==t.toLowerCase().replace(ce,"")?r:void 0}function ue(e){let t=new URLSearchParams(e.search),r=Je(t),n=et(e.referrer,e.ownHost);return{...n===void 0?{}:{referrer_host:n},...r===void 0?{}:{utm:r},from_ad_click:Qe.some(o=>t.has(o))}}var tt="page_view";function le(e,t,r){let n,o=r.referrer,i=()=>{let{pathname:a,search:f,hostname:u}=r.location(),y=T(a,t);if(y===n)return;n=y;let m=ue({search:f,referrer:o,ownHost:u});o=void 0,e.enqueue({name:tt,path:y,entryAttribution:m})};return r.guard(i),r.watch(()=>{r.guard(i)})}function O(e,t,r){return{key:e,sent_at:new Date(t).toISOString(),events:r}}function N(e){return JSON.stringify(e)}var rt=new TextEncoder;function nt(e){return rt.encode(e).length}function pe(e){return e>=10}function fe(e,t,r=500){return e.length>=r?{queue:e,accepted:!1}:{queue:[...e,t],accepted:!0}}function ye(e,t,r=50,n=32768){let o=[],i=[],a=[],f=u=>u.length<=r&&nt(t(u))<=n;for(let u of e){if(!f([u])){i.push(u);continue}let y=[...a,u];if(f(y)){a=y;continue}o.push(a),a=[u]}return a.length>0&&o.push(a),{chunks:o,oversized:i}}function I(e,t,r){return e!==void 0&&t-e.lastActivityAt<=18e5?{session:{...e,lastActivityAt:t},isNew:!1}:{session:e?.userId===void 0?{id:r(),lastActivityAt:t}:{id:r(),lastActivityAt:t,userId:e.userId},isNew:!0}}function ot(e){return typeof e=="object"&&e!==null}function U(e){if(e===null)return;let t;try{t=JSON.parse(e)}catch{return}if(!ot(t)||typeof t.id!="string"||typeof t.lastActivityAt!="number"||!Number.isFinite(t.lastActivityAt))return;let{id:r,lastActivityAt:n,userId:o,entryRecorded:i}=t;return{id:r,lastActivityAt:n,...typeof o=="string"?{userId:o}:{},...i===!0?{entryRecorded:i}:{}}}function he(e){return{...e,entryRecorded:!0}}function B(e){return JSON.stringify(e)}var b="pyxis:session",st={kind:"network-error"};function ge(e,t){let r=[],n,o=new Set,i=!1,a=s=>{let c=U(t.sessionStore.read(b)),{session:d}=I(c,t.now(),t.createId),l=s&&d.entryRecorded!==!0,g=l?he(d):d;return t.sessionStore.write(b,B(g)),{session:g,isEntry:l}},f=s=>{try{e.onBatch?.(s)}catch(c){console.warn("[pyxis] debug.onBatch threw; the batch is sent anyway",c)}},u=(s,c,d)=>{if(i||Y(d)!=="retry")return;let l=d.kind==="response"?d.retryAfterSeconds:void 0,g=z(c,t.random,l);if(g===void 0)return;let j=setTimeout(()=>{o.delete(j),y(s,c+1,!1)},g);o.add(j)},y=(s,c,d)=>{let l=O(e.key,t.now(),s);f(l),!e.dryRun&&t.transport.send(e.batchUrl,N(l),d).then(g=>{u(s,c,g)},()=>{u(s,c,st)})},m=(s=!1)=>{if(n!==void 0&&(clearTimeout(n),n=void 0),i||r.length===0)return;let{chunks:c}=ye(r,d=>N(O(e.key,t.now(),d)));r=[];for(let d of c)y(d,0,s)},C=s=>{if(i)return;let{session:c,isEntry:d}=a(s.entryAttribution!==void 0),l={id:t.createId(),name:s.name,occurred_at:new Date(t.now()).toISOString(),session_id:c.id,path:s.path,...c.userId===void 0?{}:{user_id:c.userId},...d?{attribution:s.entryAttribution}:{},...s.properties===void 0?{}:{properties:s.properties}};if(r=fe(r,l).queue,pe(r.length)){m();return}n??(n=setTimeout(()=>{n=void 0,m()},5e3))};return{enqueue:C,identify:(s,c)=>{if(i)return;let{session:d}=I(U(t.sessionStore.read(b)),t.now(),t.createId),l=d.userId===s;t.sessionStore.write(b,B({...d,userId:s})),l||C({name:A,path:c})},reset:()=>{i||(m(),t.sessionStore.remove(b))},flush:m,dispose:()=>{i=!0,r=[],n!==void 0&&clearTimeout(n),o.forEach(s=>{clearTimeout(s)}),o.clear()}}}var k,D=!1,p,V=[],x=[],L=!1;function me(e,t){try{return e()}catch(r){return D&&console.warn("[pyxis] ignored an internal error",r),t}}function h(e){me(e,void 0)}function v(e){D&&console.warn(`[pyxis] ${e}`)}function M(){return T(window.location.pathname,x)}function H(){return _(()=>window.localStorage)}function Te(){let e=te(navigator,window,H());return{...e,optedOut:e.optedOut||L}}function at(){V.forEach(e=>{e()}),p?.dispose(),V=[],p=void 0}function dt(e,t){return le(e,t,{location:()=>window.location,referrer:document.referrer,watch:r=>Q(r,window),guard:h})}function Ee(e){let t=ie(e);if(!t.ok||!Z(Te()))return;let r=ge(t.options,X());x=t.options.pathRules,p=r;let n=W(()=>{r.flush(!0)});V=t.options.autoPageViews?[n,dt(r,x)]:[n]}function nr(e){h(()=>{k!==void 0||!S(globalThis)||(k=e,D=e.debug!==void 0,Ee(e))})}function or(e,t){h(()=>{if(p===void 0)return;let r=re(e);if(r!=="ok"){v(`track() ignored "${e}": the name ${r==="reserved"?"is reserved for the SDK":"is not a valid event name"}`);return}let n=oe(t);for(let{key:i,reason:a}of n.dropped)v(`track("${e}") dropped the property "${i}" (${a})`);let o=Object.keys(n.properties).length>0;p.enqueue({name:e,path:M(),...o?{properties:n.properties}:{}})})}function ir(e){h(()=>{if(p!==void 0){if(!ne(e)){v("identify() ignored a user id outside [A-Za-z0-9_-]{1,64}; never pass an email");return}p.identify(e,M())}})}function sr(){h(()=>{p?.reset()})}function ar(e){h(()=>{if(p===void 0)return;let t=de(e,x);if(!t.ok){v(`trackRequest() ignored a request with an invalid ${t.reason}`);return}t.droppedErrorCode&&v("trackRequest() dropped an errorCode outside [a-z0-9_.]{1,64}"),p.enqueue({name:ae,path:M(),properties:t.properties})})}function dr(){h(()=>{S(globalThis)&&(L=!0,H().write(E,"1"),at())})}function cr(){return me(()=>S(globalThis)?R(Te()):"on","on")}function ur(){h(()=>{S(globalThis)&&(L=!1,H().remove(E),k!==void 0&&p===void 0&&Ee(k))})}export{ir as identify,nr as init,ur as optIn,dr as optOut,sr as reset,or as track,ar as trackRequest,cr as trackingStatus};
|
|
1
|
+
function Se(e){return Array.from(e,t=>t.toString(16).padStart(2,"0")).join("")}function be(e){let t=Se(e),r=(parseInt(t.slice(16,18),16)&63|128).toString(16);return[t.slice(0,8),t.slice(8,12),`4${t.slice(13,16)}`,`${r}${t.slice(18,20)}`,t.slice(20,32)].join("-")}function q(e){return typeof e.randomUUID=="function"?e.randomUUID():be(e.getRandomValues(new Uint8Array(16)))}function ve(){let e=new Map;return{read:t=>e.get(t)??null,write:(t,r)=>{e.set(t,r)},remove:t=>{e.delete(t)}}}function _(e){let t=ve();return{read:r=>{try{return e().getItem(r)}catch{return t.read(r)}},write:(r,n)=>{try{e().setItem(r,n)}catch{t.write(r,n)}},remove:r=>{try{e().removeItem(r)}catch{t.remove(r)}}}}var _e=[1e3,2e3,4e3,8e3,16e3],$=.2,ke=429;function Y(e){if(e.kind==="network-error")return"retry";if(e.kind==="handed-off")return"done";let{status:t}=e;return t>=200&&t<300?"done":t===ke||t>=500?"retry":"drop"}function z(e,t,r){let n=_e[e];if(n===void 0)return;let o=Math.round(n*(1-$+t()*2*$));return r===void 0?o:Math.max(o,r*1e3)}function F(e){if(!(e===null||!/^\d+$/.test(e.trim())))return Number(e.trim())}var G="text/plain;charset=UTF-8";function K(e,t){let r=(o,i)=>t?.(o,new Blob([i],{type:G}))===!0?{kind:"handed-off"}:{kind:"network-error"},n=async(o,i)=>{if(e===void 0)throw new TypeError("fetch is not available");let a=await e(o,{method:"POST",body:i,keepalive:!0,credentials:"omit",headers:{"Content-Type":G}}),f=F(a.headers.get("Retry-After"));return f===void 0?{kind:"response",status:a.status}:{kind:"response",status:a.status,retryAfterSeconds:f}};return{send:async(o,i,a)=>{try{return await n(o,i)}catch{return a||e===void 0?r(o,i):{kind:"network-error"}}}}}function X(){return{now:()=>Date.now(),createId:()=>q(globalThis.crypto),random:Math.random,sessionStore:_(()=>window.sessionStorage),transport:K(typeof fetch=="function"?fetch.bind(globalThis):void 0,typeof navigator.sendBeacon=="function"?navigator.sendBeacon.bind(navigator):void 0)}}function Q(e,t){let{history:r}=t,n=r.pushState.bind(r),o=r.replaceState.bind(r);return r.pushState=(...i)=>{n(...i),e()},r.replaceState=(...i)=>{o(...i),e()},t.addEventListener("popstate",e),()=>{r.pushState=n,r.replaceState=o,t.removeEventListener("popstate",e)}}function W(e,t=document,r=window){let n=()=>{t.visibilityState==="hidden"&&e()};return t.addEventListener("visibilitychange",n),r.addEventListener("pagehide",e),()=>{t.removeEventListener("visibilitychange",n),r.removeEventListener("pagehide",e)}}var S="pyxis:opt-out";var Re=new Set(["1","yes"]);function J(e){return e.some(t=>t!=null&&Re.has(t))}function x(e){return e.globalPrivacyControl||e.doNotTrack?"blocked-by-browser":e.optedOut?"opted-out":"on"}function Z(e){return!e.automated&&x(e)==="on"}function ee(e){return typeof e=="string"?e:null}function te(e,t,r){return{globalPrivacyControl:Reflect.get(e,"globalPrivacyControl")===!0,doNotTrack:J([ee(Reflect.get(e,"doNotTrack")),ee(Reflect.get(t,"doNotTrack"))]),optedOut:r.read(S)==="1",automated:Reflect.get(e,"webdriver")===!0}}function b(e){return e.window!==void 0&&e.document!==void 0}var A="identify",xe=["page_view",A,"api_request"],we=10,Ae=100,Pe=/^[a-z][a-z0-9_]{0,63}$/,Oe=/^[a-z0-9_]{1,40}$/,Ne=/^[A-Za-z0-9_-]{1,64}$/;function re(e){return typeof e!="string"||!Pe.test(e)?"invalid":xe.includes(e)?"reserved":"ok"}function ne(e){return typeof e=="string"&&Ne.test(e)}function Ie(e){return typeof e=="boolean"||typeof e=="number"&&Number.isFinite(e)||typeof e=="string"&&e.length<=Ae}function oe(e){let t={},r=[],n=typeof e=="object"&&e!==null?Object.entries(e):[];for(let[o,i]of n)Oe.test(o)?Ie(i)?Object.keys(t).length>=we?r.push({key:o,reason:"too_many"}):t[o]=i:r.push({key:o,reason:"invalid_value"}):r.push({key:o,reason:"invalid_key"});return{properties:t,dropped:r}}var Ue="/v1/batch";function Be(e){let t;try{t=new URL(e)}catch{return}if(!(t.protocol!=="https:"&&t.protocol!=="http:"))return`${t.origin}${t.pathname.replace(/\/+$/,"")}${Ue}`}function ie(e){let t=e.key?.trim();if(!t)return{ok:!1,reason:"no-key"};let r=Be(e.endpoint);if(r===void 0)return{ok:!1,reason:"invalid-endpoint"};let n={key:t,batchUrl:r,pathRules:e.pathRules??[],autoPageViews:e.autoPageViews??!0,...e.referrer===void 0?{}:{referrer:e.referrer},dryRun:e.debug?.dryRun??!1},o=e.debug?.onBatch;return{ok:!0,options:o===void 0?n:{...n,onBatch:o}}}var Ve=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,De=/^\d+$/,Le=/\d/g,Me=/%40/i;function He(e){return Ve.test(e)||De.test(e)||(e.match(Le)?.length??0)>=10||e.includes("@")||Me.test(e)}function P(e){let t=e.length;for(;t>0&&e.charAt(t-1)==="/";)t-=1;return t===0?"/":e.slice(0,t)}function Ce(e,t){let r=P(t).split("/");return r.length===e.length&&r.every((n,o)=>n.startsWith(":")||n===e[o])}function T(e,t){let r=P(e).split("/"),n=t.find(i=>Ce(r,i));return(n===void 0?r.map(i=>He(i)?":id":i).join("/"):P(n)).slice(0,256)}var ae="api_request",je=["GET","POST","PUT","PATCH","DELETE"],qe=100,$e=6e5,Ye=599,ze=/^[a-z0-9_.]{1,64}$/,Fe="http://relative.invalid";function Ge(e){return typeof e=="string"&&je.includes(e)}function se(e,t,r){return typeof e=="number"&&Number.isInteger(e)&&e>=t&&e<=r}function Ke(e,t){if(typeof e=="string")try{return T(new URL(e,Fe).pathname,t).slice(0,qe)}catch{return}}function de(e,t){if(!Ge(e.method))return{ok:!1,reason:"method"};let r=Ke(e.url,t);if(r===void 0)return{ok:!1,reason:"url"};if(!se(e.status,0,Ye))return{ok:!1,reason:"status"};if(!se(e.durationMs,0,$e))return{ok:!1,reason:"duration"};let{errorCode:n}=e,o=typeof n=="string"&&ze.test(n),i={method:e.method,route:r,status:e.status,duration_ms:e.durationMs};return{ok:!0,properties:o?{...i,error_code:n}:i,droppedErrorCode:n!==void 0&&!o}}var Xe=[["utm_source","source"],["utm_medium","medium"],["utm_campaign","campaign"]],Qe=["gclid","gbraid","wbraid","msclkid","ttclid","li_fat_id","twclid","dclid"];var We=/^[a-z0-9-]+(\.[a-z0-9-]+)*$/,ue=/^www\./;function Je(e){let t=Xe.flatMap(([r,n])=>{let o=e.get(r)?.trim().slice(0,64);return o?[[n,o]]:[]});return t.length===0?void 0:Object.fromEntries(t)}function Ze(e){try{return new URL(e).hostname.toLowerCase().replace(ue,"")}catch{return}}function et(e,t){let r=e?Ze(e):void 0;return r!==void 0&&r.length<=128&&We.test(r)&&r!==t.toLowerCase().replace(ue,"")?r:void 0}function ce(e){let t=new URLSearchParams(e.search),r=Je(t),n=et(e.referrer,e.ownHost);return{...n===void 0?{}:{referrer_host:n},...r===void 0?{}:{utm:r},from_ad_click:Qe.some(o=>t.has(o))}}var tt="page_view";function le(e,t,r){let n,o=r.referrer,i=()=>{let{pathname:a,search:f,hostname:c}=r.location(),y=T(a,t);if(y===n)return;n=y;let m=ce({search:f,referrer:o,ownHost:c});o=void 0,e.enqueue({name:tt,path:y,entryAttribution:m})};return r.guard(i),r.watch(()=>{r.guard(i)})}function O(e,t,r){return{key:e,sent_at:new Date(t).toISOString(),events:r}}function N(e){return JSON.stringify(e)}var rt=new TextEncoder;function nt(e){return rt.encode(e).length}function pe(e){return e>=10}function fe(e,t,r=500){return e.length>=r?{queue:e,accepted:!1}:{queue:[...e,t],accepted:!0}}function ye(e,t,r=50,n=32768){let o=[],i=[],a=[],f=c=>c.length<=r&&nt(t(c))<=n;for(let c of e){if(!f([c])){i.push(c);continue}let y=[...a,c];if(f(y)){a=y;continue}o.push(a),a=[c]}return a.length>0&&o.push(a),{chunks:o,oversized:i}}function I(e,t,r){return e!==void 0&&t-e.lastActivityAt<=18e5?{session:{...e,lastActivityAt:t},isNew:!1}:{session:e?.userId===void 0?{id:r(),lastActivityAt:t}:{id:r(),lastActivityAt:t,userId:e.userId},isNew:!0}}function ot(e){return typeof e=="object"&&e!==null}function U(e){if(e===null)return;let t;try{t=JSON.parse(e)}catch{return}if(!ot(t)||typeof t.id!="string"||typeof t.lastActivityAt!="number"||!Number.isFinite(t.lastActivityAt))return;let{id:r,lastActivityAt:n,userId:o,entryRecorded:i}=t;return{id:r,lastActivityAt:n,...typeof o=="string"?{userId:o}:{},...i===!0?{entryRecorded:i}:{}}}function he(e){return{...e,entryRecorded:!0}}function B(e){return JSON.stringify(e)}var v="pyxis:session",st={kind:"network-error"};function ge(e,t){let r=[],n,o=new Set,i=!1,a=s=>{let u=U(t.sessionStore.read(v)),{session:d}=I(u,t.now(),t.createId),l=s&&d.entryRecorded!==!0,g=l?he(d):d;return t.sessionStore.write(v,B(g)),{session:g,isEntry:l}},f=s=>{try{e.onBatch?.(s)}catch(u){console.warn("[pyxis] debug.onBatch threw; the batch is sent anyway",u)}},c=(s,u,d)=>{if(i||Y(d)!=="retry")return;let l=d.kind==="response"?d.retryAfterSeconds:void 0,g=z(u,t.random,l);if(g===void 0)return;let j=setTimeout(()=>{o.delete(j),y(s,u+1,!1)},g);o.add(j)},y=(s,u,d)=>{let l=O(e.key,t.now(),s);f(l),!e.dryRun&&t.transport.send(e.batchUrl,N(l),d).then(g=>{c(s,u,g)},()=>{c(s,u,st)})},m=(s=!1)=>{if(n!==void 0&&(clearTimeout(n),n=void 0),i||r.length===0)return;let{chunks:u}=ye(r,d=>N(O(e.key,t.now(),d)));r=[];for(let d of u)y(d,0,s)},C=s=>{if(i)return;let{session:u,isEntry:d}=a(s.entryAttribution!==void 0),l={id:t.createId(),name:s.name,occurred_at:new Date(t.now()).toISOString(),session_id:u.id,path:s.path,...u.userId===void 0?{}:{user_id:u.userId},...d?{attribution:s.entryAttribution}:{},...s.properties===void 0?{}:{properties:s.properties}};if(r=fe(r,l).queue,pe(r.length)){m();return}n??(n=setTimeout(()=>{n=void 0,m()},5e3))};return{enqueue:C,identify:(s,u)=>{if(i)return;let{session:d}=I(U(t.sessionStore.read(v)),t.now(),t.createId),l=d.userId===s;t.sessionStore.write(v,B({...d,userId:s})),l||C({name:A,path:u})},reset:()=>{i||(m(),t.sessionStore.remove(v))},flush:m,dispose:()=>{i=!0,r=[],n!==void 0&&clearTimeout(n),o.forEach(s=>{clearTimeout(s)}),o.clear()}}}var k,D=!1,p,V=[],R=[],L=!1;function me(e,t){try{return e()}catch(r){return D&&console.warn("[pyxis] ignored an internal error",r),t}}function h(e){me(e,void 0)}function E(e){D&&console.warn(`[pyxis] ${e}`)}function M(){return T(window.location.pathname,R)}function H(){return _(()=>window.localStorage)}function Te(){let e=te(navigator,window,H());return{...e,optedOut:e.optedOut||L}}function at(){V.forEach(e=>{e()}),p?.dispose(),V=[],p=void 0}function dt(e,t,r){return le(e,t,{location:()=>window.location,referrer:r??document.referrer,watch:n=>Q(n,window),guard:h})}function Ee(e){let t=ie(e);if(!t.ok)return;let r=Te();if(r.automated&&E("measuring is off in a browser driven by automation (navigator.webdriver is true)"),!Z(r))return;let n=ge(t.options,X());R=t.options.pathRules,p=n;let o=W(()=>{n.flush(!0)});V=t.options.autoPageViews?[o,dt(n,R,t.options.referrer)]:[o]}function nr(e){h(()=>{k!==void 0||!b(globalThis)||(k=e,D=e.debug!==void 0,Ee(e))})}function or(e,t){h(()=>{if(p===void 0)return;let r=re(e);if(r!=="ok"){E(`track() ignored "${e}": the name ${r==="reserved"?"is reserved for the SDK":"is not a valid event name"}`);return}let n=oe(t);for(let{key:i,reason:a}of n.dropped)E(`track("${e}") dropped the property "${i}" (${a})`);let o=Object.keys(n.properties).length>0;p.enqueue({name:e,path:M(),...o?{properties:n.properties}:{}})})}function ir(e){h(()=>{if(p!==void 0){if(!ne(e)){E("identify() ignored a user id outside [A-Za-z0-9_-]{1,64}; never pass an email");return}p.identify(e,M())}})}function sr(){h(()=>{p?.reset()})}function ar(e){h(()=>{if(p===void 0)return;let t=de(e,R);if(!t.ok){E(`trackRequest() ignored a request with an invalid ${t.reason}`);return}t.droppedErrorCode&&E("trackRequest() dropped an errorCode outside [a-z0-9_.]{1,64}"),p.enqueue({name:ae,path:M(),properties:t.properties})})}function dr(){h(()=>{b(globalThis)&&(L=!0,H().write(S,"1"),at())})}function ur(){return me(()=>b(globalThis)?x(Te()):"on","on")}function cr(){h(()=>{b(globalThis)&&(L=!1,H().remove(S),k!==void 0&&p===void 0&&Ee(k))})}export{ir as identify,nr as init,cr as optIn,dr as optOut,sr as reset,or as track,ar as trackRequest,ur as trackingStatus};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/adapters/ids.ts", "../src/adapters/storage.ts", "../src/core/retry-policy.ts", "../src/adapters/transport.ts", "../src/adapters/browser-dependencies.ts", "../src/adapters/navigation.ts", "../src/adapters/page-lifecycle.ts", "../src/core/privacy.ts", "../src/adapters/privacy-signals.ts", "../src/core/environment.ts", "../src/core/event-input.ts", "../src/core/options.ts", "../src/core/path-template.ts", "../src/core/tracked-request.ts", "../src/core/attribution.ts", "../src/page-views.ts", "../src/core/batch.ts", "../src/core/batch-policy.ts", "../src/core/session-policy.ts", "../src/tracker.ts", "../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["const UUID_BYTES = 16;\nconst VARIANT_MASK = 0x3f;\nconst VARIANT_BITS = 0x80;\n\nexport type UuidSource = Pick<Crypto, 'getRandomValues'> & Partial<Pick<Crypto, 'randomUUID'>>;\n\nfunction toHex(bytes: Uint8Array): string {\n return Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('');\n}\n\nexport function uuidFromBytes(bytes: Uint8Array): string {\n const hex = toHex(bytes);\n const variant = ((parseInt(hex.slice(16, 18), 16) & VARIANT_MASK) | VARIANT_BITS).toString(16);\n return [\n hex.slice(0, 8),\n hex.slice(8, 12),\n `4${hex.slice(13, 16)}`,\n `${variant}${hex.slice(18, 20)}`,\n hex.slice(20, 32),\n ].join('-');\n}\n\nexport function createUuid(source: UuidSource): string {\n if (typeof source.randomUUID === 'function') {\n return source.randomUUID();\n }\n return uuidFromBytes(source.getRandomValues(new Uint8Array(UUID_BYTES)));\n}\n", "export interface KeyValueStore {\n read(key: string): string | null;\n write(key: string, value: string): void;\n remove(key: string): void;\n}\n\nexport function memoryStore(): KeyValueStore {\n const values = new Map<string, string>();\n return {\n read: (key) => values.get(key) ?? null,\n write: (key, value) => {\n values.set(key, value);\n },\n remove: (key) => {\n values.delete(key);\n },\n };\n}\n\nexport function webStore(getStorage: () => Storage): KeyValueStore {\n const fallback = memoryStore();\n return {\n read: (key) => {\n try {\n return getStorage().getItem(key);\n } catch {\n return fallback.read(key);\n }\n },\n write: (key, value) => {\n try {\n getStorage().setItem(key, value);\n } catch {\n fallback.write(key, value);\n }\n },\n remove: (key) => {\n try {\n getStorage().removeItem(key);\n } catch {\n fallback.remove(key);\n }\n },\n };\n}\n", "export const RETRY_DELAYS_MS: readonly number[] = [1000, 2000, 4000, 8000, 16000];\nexport const RETRY_JITTER = 0.2;\n\nexport type SendOutcome =\n | { readonly kind: 'response'; readonly status: number; readonly retryAfterSeconds?: number }\n | { readonly kind: 'network-error' }\n | { readonly kind: 'handed-off' };\n\nexport type SendVerdict = 'done' | 'retry' | 'drop';\n\nconst TOO_MANY_REQUESTS = 429;\n\nexport function judgeOutcome(outcome: SendOutcome): SendVerdict {\n if (outcome.kind === 'network-error') {\n return 'retry';\n }\n if (outcome.kind === 'handed-off') {\n return 'done';\n }\n const { status } = outcome;\n if (status >= 200 && status < 300) {\n return 'done';\n }\n if (status === TOO_MANY_REQUESTS || status >= 500) {\n return 'retry';\n }\n return 'drop';\n}\n\nexport function retryDelay(\n attempt: number,\n random: () => number,\n retryAfterSeconds?: number,\n): number | undefined {\n const base = RETRY_DELAYS_MS[attempt];\n if (base === undefined) {\n return undefined;\n }\n const jittered = Math.round(base * (1 - RETRY_JITTER + random() * 2 * RETRY_JITTER));\n return retryAfterSeconds === undefined ? jittered : Math.max(jittered, retryAfterSeconds * 1000);\n}\n\nexport function parseRetryAfter(header: string | null): number | undefined {\n if (header === null || !/^\\d+$/.test(header.trim())) {\n return undefined;\n }\n return Number(header.trim());\n}\n", "import { parseRetryAfter, type SendOutcome } from '../core/retry-policy.js';\n\nexport interface Transport {\n send(url: string, body: string, pageHidden: boolean): Promise<SendOutcome>;\n}\n\nexport const BODY_CONTENT_TYPE = 'text/plain;charset=UTF-8';\n\nexport type FetchLike = (input: string, init: RequestInit) => Promise<Response>;\nexport type BeaconLike = (url: string, data: Blob) => boolean;\n\nexport function browserTransport(fetchImpl?: FetchLike, beacon?: BeaconLike): Transport {\n const viaBeacon = (url: string, body: string): SendOutcome =>\n beacon?.(url, new Blob([body], { type: BODY_CONTENT_TYPE })) === true\n ? { kind: 'handed-off' }\n : { kind: 'network-error' };\n\n const viaFetch = async (url: string, body: string): Promise<SendOutcome> => {\n if (fetchImpl === undefined) {\n throw new TypeError('fetch is not available');\n }\n const response = await fetchImpl(url, {\n method: 'POST',\n body,\n keepalive: true,\n credentials: 'omit',\n headers: { 'Content-Type': BODY_CONTENT_TYPE },\n });\n const retryAfterSeconds = parseRetryAfter(response.headers.get('Retry-After'));\n return retryAfterSeconds === undefined\n ? { kind: 'response', status: response.status }\n : { kind: 'response', status: response.status, retryAfterSeconds };\n };\n\n return {\n send: async (url, body, pageHidden) => {\n try {\n return await viaFetch(url, body);\n } catch {\n return pageHidden || fetchImpl === undefined\n ? viaBeacon(url, body)\n : { kind: 'network-error' };\n }\n },\n };\n}\n", "import type { TrackerDependencies } from '../tracker.js';\nimport { createUuid } from './ids.js';\nimport { webStore } from './storage.js';\nimport { browserTransport } from './transport.js';\n\nexport function createBrowserDependencies(): TrackerDependencies {\n return {\n now: () => Date.now(),\n createId: () => createUuid(globalThis.crypto),\n random: Math.random,\n sessionStore: webStore(() => window.sessionStorage),\n transport: browserTransport(\n typeof fetch === 'function' ? fetch.bind(globalThis) : undefined,\n typeof navigator.sendBeacon === 'function' ? navigator.sendBeacon.bind(navigator) : undefined,\n ),\n };\n}\n", "export interface NavigationTarget {\n readonly history: History;\n addEventListener(type: 'popstate', listener: () => void): void;\n removeEventListener(type: 'popstate', listener: () => void): void;\n}\n\nexport function watchNavigation(onNavigate: () => void, target: NavigationTarget): () => void {\n const { history } = target;\n const pushState = history.pushState.bind(history);\n const replaceState = history.replaceState.bind(history);\n history.pushState = (...args: Parameters<History['pushState']>) => {\n pushState(...args);\n onNavigate();\n };\n history.replaceState = (...args: Parameters<History['replaceState']>) => {\n replaceState(...args);\n onNavigate();\n };\n target.addEventListener('popstate', onNavigate);\n return () => {\n history.pushState = pushState;\n history.replaceState = replaceState;\n target.removeEventListener('popstate', onNavigate);\n };\n}\n", "export function onPageHide(\n listener: () => void,\n doc: Document = document,\n win: Window = window,\n): () => void {\n const onVisibilityChange = () => {\n if (doc.visibilityState === 'hidden') {\n listener();\n }\n };\n doc.addEventListener('visibilitychange', onVisibilityChange);\n win.addEventListener('pagehide', listener);\n return () => {\n doc.removeEventListener('visibilitychange', onVisibilityChange);\n win.removeEventListener('pagehide', listener);\n };\n}\n", "export const OPT_OUT_KEY = 'pyxis:opt-out';\nexport const OPT_OUT_VALUE = '1';\n\nconst DO_NOT_TRACK_VALUES = new Set(['1', 'yes']);\n\nexport interface PrivacySignals {\n readonly globalPrivacyControl: boolean;\n readonly doNotTrack: boolean;\n readonly optedOut: boolean;\n}\n\nexport function isDoNotTrack(values: readonly (string | null | undefined)[]): boolean {\n return values.some(\n (value) => value !== null && value !== undefined && DO_NOT_TRACK_VALUES.has(value),\n );\n}\n\nexport type TrackingStatus = 'on' | 'opted-out' | 'blocked-by-browser';\n\nexport function trackingStatusOf(signals: PrivacySignals): TrackingStatus {\n if (signals.globalPrivacyControl || signals.doNotTrack) {\n return 'blocked-by-browser';\n }\n return signals.optedOut ? 'opted-out' : 'on';\n}\n\nexport function isTrackingAllowed(signals: PrivacySignals): boolean {\n return trackingStatusOf(signals) === 'on';\n}\n", "import { isDoNotTrack, OPT_OUT_KEY, OPT_OUT_VALUE, type PrivacySignals } from '../core/privacy.js';\nimport type { KeyValueStore } from './storage.js';\n\nfunction textOrNull(value: unknown): string | null {\n return typeof value === 'string' ? value : null;\n}\n\nexport function readPrivacySignals(nav: object, win: object, store: KeyValueStore): PrivacySignals {\n return {\n globalPrivacyControl: Reflect.get(nav, 'globalPrivacyControl') === true,\n doNotTrack: isDoNotTrack([\n textOrNull(Reflect.get(nav, 'doNotTrack')),\n textOrNull(Reflect.get(win, 'doNotTrack')),\n ]),\n optedOut: store.read(OPT_OUT_KEY) === OPT_OUT_VALUE,\n };\n}\n", "export interface GlobalScope {\n readonly window?: unknown;\n readonly document?: unknown;\n}\n\nexport function isBrowserLike(scope: GlobalScope): boolean {\n return scope.window !== undefined && scope.document !== undefined;\n}\n", "import type { PropertyValue } from './batch.js';\n\nexport const IDENTIFY_EVENT = 'identify';\nexport const RESERVED_EVENT_NAMES: readonly string[] = ['page_view', IDENTIFY_EVENT, 'api_request'];\nexport const MAX_PROPERTIES = 10;\nexport const MAX_PROPERTY_STRING_LENGTH = 100;\n\nconst EVENT_NAME_PATTERN = /^[a-z][a-z0-9_]{0,63}$/;\nconst PROPERTY_KEY_PATTERN = /^[a-z0-9_]{1,40}$/;\nconst USER_ID_PATTERN = /^[A-Za-z0-9_-]{1,64}$/;\n\nexport type NameCheck = 'ok' | 'invalid' | 'reserved';\n\nexport type DropReason = 'invalid_key' | 'invalid_value' | 'too_many';\n\nexport interface DroppedProperty {\n readonly key: string;\n readonly reason: DropReason;\n}\n\nexport interface SanitizedProperties {\n readonly properties: Readonly<Record<string, PropertyValue>>;\n readonly dropped: readonly DroppedProperty[];\n}\n\nexport function checkEventName(name: unknown): NameCheck {\n if (typeof name !== 'string' || !EVENT_NAME_PATTERN.test(name)) {\n return 'invalid';\n }\n return RESERVED_EVENT_NAMES.includes(name) ? 'reserved' : 'ok';\n}\n\nexport function isValidUserId(userId: unknown): userId is string {\n return typeof userId === 'string' && USER_ID_PATTERN.test(userId);\n}\n\nfunction isPropertyValue(value: unknown): value is PropertyValue {\n return (\n typeof value === 'boolean' ||\n (typeof value === 'number' && Number.isFinite(value)) ||\n (typeof value === 'string' && value.length <= MAX_PROPERTY_STRING_LENGTH)\n );\n}\n\nexport function sanitizeProperties(input: unknown): SanitizedProperties {\n const kept: Record<string, PropertyValue> = {};\n const dropped: DroppedProperty[] = [];\n const entries = typeof input === 'object' && input !== null ? Object.entries(input) : [];\n for (const [key, value] of entries) {\n if (!PROPERTY_KEY_PATTERN.test(key)) {\n dropped.push({ key, reason: 'invalid_key' });\n } else if (!isPropertyValue(value)) {\n dropped.push({ key, reason: 'invalid_value' });\n } else if (Object.keys(kept).length >= MAX_PROPERTIES) {\n dropped.push({ key, reason: 'too_many' });\n } else {\n kept[key] = value;\n }\n }\n return { properties: kept, dropped };\n}\n", "import type { Batch } from './batch.js';\n\nexport interface PyxisDebugOptions {\n readonly dryRun?: boolean;\n readonly onBatch?: (batch: Batch) => void;\n}\n\nexport interface PyxisOptions {\n readonly key: string | undefined | null;\n readonly endpoint: string;\n readonly pathRules?: readonly string[];\n readonly autoPageViews?: boolean;\n readonly debug?: PyxisDebugOptions;\n}\n\nexport interface ResolvedOptions {\n readonly key: string;\n readonly batchUrl: string;\n readonly pathRules: readonly string[];\n readonly autoPageViews: boolean;\n readonly dryRun: boolean;\n readonly onBatch?: (batch: Batch) => void;\n}\n\nexport type OptionsResolution =\n | { readonly ok: true; readonly options: ResolvedOptions }\n | { readonly ok: false; readonly reason: 'no-key' | 'invalid-endpoint' };\n\nexport const BATCH_PATH = '/v1/batch';\n\nexport function batchUrlFor(endpoint: string): string | undefined {\n let url: URL;\n try {\n url = new URL(endpoint);\n } catch {\n return undefined;\n }\n if (url.protocol !== 'https:' && url.protocol !== 'http:') {\n return undefined;\n }\n return `${url.origin}${url.pathname.replace(/\\/+$/, '')}${BATCH_PATH}`;\n}\n\nexport function resolveOptions(options: PyxisOptions): OptionsResolution {\n const key = options.key?.trim();\n if (!key) {\n return { ok: false, reason: 'no-key' };\n }\n const batchUrl = batchUrlFor(options.endpoint);\n if (batchUrl === undefined) {\n return { ok: false, reason: 'invalid-endpoint' };\n }\n const base = {\n key,\n batchUrl,\n pathRules: options.pathRules ?? [],\n autoPageViews: options.autoPageViews ?? true,\n dryRun: options.debug?.dryRun ?? false,\n };\n const onBatch = options.debug?.onBatch;\n return { ok: true, options: onBatch === undefined ? base : { ...base, onBatch } };\n}\n", "export const MAX_PATH_LENGTH = 256;\nexport const ID_PLACEHOLDER = ':id';\n\nconst UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nconst ALL_DIGITS = /^\\d+$/;\nconst DIGIT = /\\d/g;\nconst ENCODED_AT_SIGN = /%40/i;\nconst MIN_ID_DIGITS = 10;\n\nfunction isIdentifier(segment: string): boolean {\n return (\n UUID_PATTERN.test(segment) ||\n ALL_DIGITS.test(segment) ||\n (segment.match(DIGIT)?.length ?? 0) >= MIN_ID_DIGITS ||\n segment.includes('@') ||\n ENCODED_AT_SIGN.test(segment)\n );\n}\n\nfunction withoutTrailingSlashes(path: string): string {\n let end = path.length;\n while (end > 0 && path.charAt(end - 1) === '/') {\n end -= 1;\n }\n return end === 0 ? '/' : path.slice(0, end);\n}\n\nfunction matchesRule(segments: readonly string[], rule: string): boolean {\n const ruleSegments = withoutTrailingSlashes(rule).split('/');\n return (\n ruleSegments.length === segments.length &&\n ruleSegments.every(\n (ruleSegment, index) => ruleSegment.startsWith(':') || ruleSegment === segments[index],\n )\n );\n}\n\nexport function templatePath(path: string, rules: readonly string[]): string {\n const segments = withoutTrailingSlashes(path).split('/');\n const rule = rules.find((candidate) => matchesRule(segments, candidate));\n const templated =\n rule === undefined\n ? segments.map((segment) => (isIdentifier(segment) ? ID_PLACEHOLDER : segment)).join('/')\n : withoutTrailingSlashes(rule);\n return templated.slice(0, MAX_PATH_LENGTH);\n}\n", "import type { PropertyValue } from './batch.js';\nimport { templatePath } from './path-template.js';\n\nexport const API_REQUEST_EVENT = 'api_request';\nexport const REQUEST_METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'] as const;\nexport const MAX_ROUTE_LENGTH = 100;\nexport const MAX_REQUEST_DURATION_MS = 600_000;\nexport const MAX_HTTP_STATUS = 599;\n\nconst ERROR_CODE_PATTERN = /^[a-z0-9_.]{1,64}$/;\nconst URL_BASE = 'http://relative.invalid';\n\nexport type RequestMethod = (typeof REQUEST_METHODS)[number];\n\nexport interface TrackedRequest {\n readonly method: RequestMethod;\n readonly url: string;\n readonly status: number;\n readonly durationMs: number;\n readonly errorCode?: string;\n}\n\nexport type RequestCheck =\n | {\n readonly ok: true;\n readonly properties: Readonly<Record<string, PropertyValue>>;\n readonly droppedErrorCode: boolean;\n }\n | { readonly ok: false; readonly reason: 'method' | 'url' | 'status' | 'duration' };\n\nfunction isMethod(value: unknown): value is RequestMethod {\n return typeof value === 'string' && (REQUEST_METHODS as readonly string[]).includes(value);\n}\n\nfunction isIntegerBetween(value: unknown, min: number, max: number): value is number {\n return typeof value === 'number' && Number.isInteger(value) && value >= min && value <= max;\n}\n\nexport function routeOf(url: unknown, rules: readonly string[]): string | undefined {\n if (typeof url !== 'string') {\n return undefined;\n }\n try {\n return templatePath(new URL(url, URL_BASE).pathname, rules).slice(0, MAX_ROUTE_LENGTH);\n } catch {\n return undefined;\n }\n}\n\nexport function checkTrackedRequest(\n request: TrackedRequest,\n rules: readonly string[],\n): RequestCheck {\n if (!isMethod(request.method)) {\n return { ok: false, reason: 'method' };\n }\n const route = routeOf(request.url, rules);\n if (route === undefined) {\n return { ok: false, reason: 'url' };\n }\n if (!isIntegerBetween(request.status, 0, MAX_HTTP_STATUS)) {\n return { ok: false, reason: 'status' };\n }\n if (!isIntegerBetween(request.durationMs, 0, MAX_REQUEST_DURATION_MS)) {\n return { ok: false, reason: 'duration' };\n }\n const { errorCode } = request;\n const keepsErrorCode = typeof errorCode === 'string' && ERROR_CODE_PATTERN.test(errorCode);\n const base = {\n method: request.method,\n route,\n status: request.status,\n duration_ms: request.durationMs,\n };\n return {\n ok: true,\n properties: keepsErrorCode ? { ...base, error_code: errorCode } : base,\n droppedErrorCode: errorCode !== undefined && !keepsErrorCode,\n };\n}\n", "import type { BatchAttribution } from './batch.js';\n\nexport const UTM_PARAMETERS = [\n ['utm_source', 'source'],\n ['utm_medium', 'medium'],\n ['utm_campaign', 'campaign'],\n] as const;\nexport const AD_CLICK_PARAMETERS = [\n 'gclid',\n 'gbraid',\n 'wbraid',\n 'msclkid',\n 'ttclid',\n 'li_fat_id',\n 'twclid',\n 'dclid',\n] as const;\nexport const MAX_UTM_VALUE_LENGTH = 64;\nexport const MAX_REFERRER_HOST_LENGTH = 128;\n\nconst HOSTNAME_PATTERN = /^[a-z0-9-]+(\\.[a-z0-9-]+)*$/;\nconst WWW_PREFIX = /^www\\./;\n\nexport interface AttributionSource {\n readonly search: string;\n readonly referrer: string | undefined;\n readonly ownHost: string;\n}\n\ntype Utm = NonNullable<BatchAttribution['utm']>;\n\nfunction readUtm(parameters: URLSearchParams): Utm | undefined {\n const entries = UTM_PARAMETERS.flatMap(([parameter, field]) => {\n const value = parameters.get(parameter)?.trim().slice(0, MAX_UTM_VALUE_LENGTH);\n return value ? [[field, value] as const] : [];\n });\n return entries.length === 0 ? undefined : Object.fromEntries(entries);\n}\n\nfunction hostOf(url: string): string | undefined {\n try {\n return new URL(url).hostname.toLowerCase().replace(WWW_PREFIX, '');\n } catch {\n return undefined;\n }\n}\n\nfunction referrerHost(referrer: string | undefined, ownHost: string): string | undefined {\n const host = referrer ? hostOf(referrer) : undefined;\n const isUsable =\n host !== undefined &&\n host.length <= MAX_REFERRER_HOST_LENGTH &&\n HOSTNAME_PATTERN.test(host) &&\n host !== ownHost.toLowerCase().replace(WWW_PREFIX, '');\n return isUsable ? host : undefined;\n}\n\nexport function buildAttribution(source: AttributionSource): BatchAttribution {\n const parameters = new URLSearchParams(source.search);\n const utm = readUtm(parameters);\n const host = referrerHost(source.referrer, source.ownHost);\n return {\n ...(host === undefined ? {} : { referrer_host: host }),\n ...(utm === undefined ? {} : { utm }),\n from_ad_click: AD_CLICK_PARAMETERS.some((parameter) => parameters.has(parameter)),\n };\n}\n", "import { buildAttribution } from './core/attribution.js';\nimport { templatePath } from './core/path-template.js';\nimport type { Tracker } from './tracker.js';\n\nexport const PAGE_VIEW = 'page_view';\n\nexport interface PageLocation {\n readonly pathname: string;\n readonly search: string;\n readonly hostname: string;\n}\n\nexport interface PageViewDependencies {\n readonly location: () => PageLocation;\n readonly referrer: string;\n readonly watch: (onNavigate: () => void) => () => void;\n readonly guard: (action: () => void) => void;\n}\n\nexport function startPageViews(\n tracker: Tracker,\n pathRules: readonly string[],\n deps: PageViewDependencies,\n): () => void {\n let lastPath: string | undefined;\n let referrer: string | undefined = deps.referrer;\n\n const recordPageView = (): void => {\n const { pathname, search, hostname } = deps.location();\n const path = templatePath(pathname, pathRules);\n if (path === lastPath) {\n return;\n }\n lastPath = path;\n const entryAttribution = buildAttribution({ search, referrer, ownHost: hostname });\n referrer = undefined;\n tracker.enqueue({ name: PAGE_VIEW, path, entryAttribution });\n };\n\n deps.guard(recordPageView);\n return deps.watch(() => {\n deps.guard(recordPageView);\n });\n}\n", "export type PropertyValue = string | number | boolean;\n\nexport interface BatchAttribution {\n readonly referrer_host?: string;\n readonly utm?: {\n readonly source?: string;\n readonly medium?: string;\n readonly campaign?: string;\n };\n readonly from_ad_click: boolean;\n}\n\nexport interface BatchEvent {\n readonly id: string;\n readonly name: string;\n readonly occurred_at: string;\n readonly session_id: string;\n readonly user_id?: string;\n readonly path: string;\n readonly attribution?: BatchAttribution;\n readonly properties?: Readonly<Record<string, PropertyValue>>;\n}\n\nexport interface Batch {\n readonly key: string;\n readonly sent_at: string;\n readonly events: readonly BatchEvent[];\n}\n\nexport function buildBatch(key: string, sentAt: number, events: readonly BatchEvent[]): Batch {\n return { key, sent_at: new Date(sentAt).toISOString(), events };\n}\n\nexport function serializeBatch(batch: Batch): string {\n return JSON.stringify(batch);\n}\n", "import type { BatchEvent } from './batch.js';\n\nexport const FLUSH_EVENT_COUNT = 10;\nexport const FLUSH_DELAY_MS = 5000;\nexport const MAX_EVENTS_PER_BATCH = 50;\nexport const MAX_BATCH_BYTES = 32 * 1024;\nexport const MAX_QUEUE_SIZE = 500;\n\nconst encoder = new TextEncoder();\n\nexport function byteLength(text: string): number {\n return encoder.encode(text).length;\n}\n\nexport function shouldFlushNow(queueLength: number): boolean {\n return queueLength >= FLUSH_EVENT_COUNT;\n}\n\nexport function enqueue(\n queue: readonly BatchEvent[],\n event: BatchEvent,\n capacity: number = MAX_QUEUE_SIZE,\n): { readonly queue: readonly BatchEvent[]; readonly accepted: boolean } {\n return queue.length >= capacity\n ? { queue, accepted: false }\n : { queue: [...queue, event], accepted: true };\n}\n\nexport interface ChunkResult {\n readonly chunks: readonly (readonly BatchEvent[])[];\n readonly oversized: readonly BatchEvent[];\n}\n\nexport function chunkEvents(\n events: readonly BatchEvent[],\n serialize: (events: readonly BatchEvent[]) => string,\n maxEvents: number = MAX_EVENTS_PER_BATCH,\n maxBytes: number = MAX_BATCH_BYTES,\n): ChunkResult {\n const chunks: BatchEvent[][] = [];\n const oversized: BatchEvent[] = [];\n let current: BatchEvent[] = [];\n const fits = (candidate: readonly BatchEvent[]) =>\n candidate.length <= maxEvents && byteLength(serialize(candidate)) <= maxBytes;\n\n for (const event of events) {\n if (!fits([event])) {\n oversized.push(event);\n continue;\n }\n const candidate = [...current, event];\n if (fits(candidate)) {\n current = candidate;\n continue;\n }\n chunks.push(current);\n current = [event];\n }\n if (current.length > 0) {\n chunks.push(current);\n }\n return { chunks, oversized };\n}\n", "export const SESSION_IDLE_TIMEOUT_MS = 30 * 60 * 1000;\n\nexport interface SessionState {\n readonly id: string;\n readonly lastActivityAt: number;\n readonly userId?: string;\n readonly entryRecorded?: true;\n}\n\nexport interface SessionTouch {\n readonly session: SessionState;\n readonly isNew: boolean;\n}\n\nexport function touchSession(\n current: SessionState | undefined,\n now: number,\n newId: () => string,\n): SessionTouch {\n if (current !== undefined && now - current.lastActivityAt <= SESSION_IDLE_TIMEOUT_MS) {\n return { session: { ...current, lastActivityAt: now }, isNew: false };\n }\n const session: SessionState =\n current?.userId === undefined\n ? { id: newId(), lastActivityAt: now }\n : { id: newId(), lastActivityAt: now, userId: current.userId };\n return { session, isNew: true };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nexport function parseSession(raw: string | null): SessionState | undefined {\n if (raw === null) {\n return undefined;\n }\n let value: unknown;\n try {\n value = JSON.parse(raw);\n } catch {\n return undefined;\n }\n if (\n !isRecord(value) ||\n typeof value.id !== 'string' ||\n typeof value.lastActivityAt !== 'number' ||\n !Number.isFinite(value.lastActivityAt)\n ) {\n return undefined;\n }\n const { id, lastActivityAt, userId, entryRecorded } = value;\n return {\n id,\n lastActivityAt,\n ...(typeof userId === 'string' ? { userId } : {}),\n ...(entryRecorded === true ? { entryRecorded } : {}),\n };\n}\n\nexport function recordEntry(session: SessionState): SessionState {\n return { ...session, entryRecorded: true };\n}\n\nexport function serializeSession(session: SessionState): string {\n return JSON.stringify(session);\n}\n", "import type { KeyValueStore } from './adapters/storage.js';\nimport type { Transport } from './adapters/transport.js';\nimport {\n type Batch,\n type BatchAttribution,\n type BatchEvent,\n buildBatch,\n type PropertyValue,\n serializeBatch,\n} from './core/batch.js';\nimport { chunkEvents, enqueue, FLUSH_DELAY_MS, shouldFlushNow } from './core/batch-policy.js';\nimport { IDENTIFY_EVENT } from './core/event-input.js';\nimport type { ResolvedOptions } from './core/options.js';\nimport { judgeOutcome, retryDelay, type SendOutcome } from './core/retry-policy.js';\nimport {\n parseSession,\n recordEntry,\n type SessionState,\n serializeSession,\n touchSession,\n} from './core/session-policy.js';\n\nexport const SESSION_KEY = 'pyxis:session';\n\nexport interface TrackerDependencies {\n readonly now: () => number;\n readonly createId: () => string;\n readonly random: () => number;\n readonly sessionStore: KeyValueStore;\n readonly transport: Transport;\n}\n\nexport interface EventInput {\n readonly name: string;\n readonly path: string;\n readonly entryAttribution?: BatchAttribution;\n readonly properties?: Readonly<Record<string, PropertyValue>>;\n}\n\nexport interface Tracker {\n enqueue(input: EventInput): void;\n identify(userId: string, path: string): void;\n reset(): void;\n flush(pageHidden?: boolean): void;\n dispose(): void;\n}\n\nconst NETWORK_ERROR: SendOutcome = { kind: 'network-error' };\n\nexport function createTracker(options: ResolvedOptions, deps: TrackerDependencies): Tracker {\n let queue: readonly BatchEvent[] = [];\n let flushTimer: ReturnType<typeof setTimeout> | undefined;\n const retryTimers = new Set<ReturnType<typeof setTimeout>>();\n let disposed = false;\n\n const touchCurrentSession = (\n claimsEntry: boolean,\n ): { session: SessionState; isEntry: boolean } => {\n const stored = parseSession(deps.sessionStore.read(SESSION_KEY));\n const { session } = touchSession(stored, deps.now(), deps.createId);\n const isEntry = claimsEntry && session.entryRecorded !== true;\n const updated = isEntry ? recordEntry(session) : session;\n deps.sessionStore.write(SESSION_KEY, serializeSession(updated));\n return { session: updated, isEntry };\n };\n\n const tryNotifyBatch = (batch: Batch): void => {\n try {\n options.onBatch?.(batch);\n } catch (error) {\n console.warn('[pyxis] debug.onBatch threw; the batch is sent anyway', error);\n }\n };\n\n const scheduleRetry = (\n events: readonly BatchEvent[],\n attempt: number,\n outcome: SendOutcome,\n ): void => {\n if (disposed || judgeOutcome(outcome) !== 'retry') {\n return;\n }\n const retryAfter = outcome.kind === 'response' ? outcome.retryAfterSeconds : undefined;\n const delay = retryDelay(attempt, deps.random, retryAfter);\n if (delay === undefined) {\n return;\n }\n const timer = setTimeout(() => {\n retryTimers.delete(timer);\n send(events, attempt + 1, false);\n }, delay);\n retryTimers.add(timer);\n };\n\n const send = (events: readonly BatchEvent[], attempt: number, pageHidden: boolean): void => {\n const batch = buildBatch(options.key, deps.now(), events);\n tryNotifyBatch(batch);\n if (options.dryRun) {\n return;\n }\n void deps.transport.send(options.batchUrl, serializeBatch(batch), pageHidden).then(\n (outcome) => {\n scheduleRetry(events, attempt, outcome);\n },\n () => {\n scheduleRetry(events, attempt, NETWORK_ERROR);\n },\n );\n };\n\n const flush = (pageHidden = false): void => {\n if (flushTimer !== undefined) {\n clearTimeout(flushTimer);\n flushTimer = undefined;\n }\n if (disposed || queue.length === 0) {\n return;\n }\n const { chunks } = chunkEvents(queue, (events) =>\n serializeBatch(buildBatch(options.key, deps.now(), events)),\n );\n queue = [];\n for (const chunk of chunks) {\n send(chunk, 0, pageHidden);\n }\n };\n\n const enqueueEvent = (input: EventInput): void => {\n if (disposed) {\n return;\n }\n const { session, isEntry } = touchCurrentSession(input.entryAttribution !== undefined);\n const event: BatchEvent = {\n id: deps.createId(),\n name: input.name,\n occurred_at: new Date(deps.now()).toISOString(),\n session_id: session.id,\n path: input.path,\n ...(session.userId === undefined ? {} : { user_id: session.userId }),\n ...(isEntry ? { attribution: input.entryAttribution } : {}),\n ...(input.properties === undefined ? {} : { properties: input.properties }),\n };\n queue = enqueue(queue, event).queue;\n if (shouldFlushNow(queue.length)) {\n flush();\n return;\n }\n flushTimer ??= setTimeout(() => {\n flushTimer = undefined;\n flush();\n }, FLUSH_DELAY_MS);\n };\n\n const identify = (userId: string, path: string): void => {\n if (disposed) {\n return;\n }\n const { session } = touchSession(\n parseSession(deps.sessionStore.read(SESSION_KEY)),\n deps.now(),\n deps.createId,\n );\n const alreadyIdentified = session.userId === userId;\n deps.sessionStore.write(SESSION_KEY, serializeSession({ ...session, userId }));\n if (!alreadyIdentified) {\n enqueueEvent({ name: IDENTIFY_EVENT, path });\n }\n };\n\n const reset = (): void => {\n if (disposed) {\n return;\n }\n flush();\n deps.sessionStore.remove(SESSION_KEY);\n };\n\n return {\n enqueue: enqueueEvent,\n identify,\n reset,\n flush,\n dispose: () => {\n disposed = true;\n queue = [];\n if (flushTimer !== undefined) {\n clearTimeout(flushTimer);\n }\n retryTimers.forEach((timer) => {\n clearTimeout(timer);\n });\n retryTimers.clear();\n },\n };\n}\n", "import { createBrowserDependencies } from './adapters/browser-dependencies.js';\nimport { watchNavigation } from './adapters/navigation.js';\nimport { onPageHide } from './adapters/page-lifecycle.js';\nimport { readPrivacySignals } from './adapters/privacy-signals.js';\nimport { webStore } from './adapters/storage.js';\nimport type { PropertyValue } from './core/batch.js';\nimport { isBrowserLike } from './core/environment.js';\nimport { checkEventName, isValidUserId, sanitizeProperties } from './core/event-input.js';\nimport { type PyxisOptions, resolveOptions } from './core/options.js';\nimport { templatePath } from './core/path-template.js';\nimport {\n API_REQUEST_EVENT,\n checkTrackedRequest,\n type TrackedRequest,\n} from './core/tracked-request.js';\nimport {\n isTrackingAllowed,\n OPT_OUT_KEY,\n OPT_OUT_VALUE,\n type PrivacySignals,\n type TrackingStatus,\n trackingStatusOf,\n} from './core/privacy.js';\nimport { startPageViews } from './page-views.js';\nimport { createTracker, type Tracker } from './tracker.js';\n\nexport type { Batch, BatchAttribution, BatchEvent, PropertyValue } from './core/batch.js';\nexport type { PyxisDebugOptions, PyxisOptions } from './core/options.js';\nexport type { TrackingStatus } from './core/privacy.js';\nexport type { RequestMethod, TrackedRequest } from './core/tracked-request.js';\n\nexport type Properties = Readonly<Record<string, PropertyValue>>;\n\nlet initOptions: PyxisOptions | undefined;\nlet debugEnabled = false;\nlet tracker: Tracker | undefined;\nlet stoppers: readonly (() => void)[] = [];\nlet pathRules: readonly string[] = [];\nlet optedOutThisPage = false;\n\nfunction guarded<Result>(action: () => Result, fallback: Result): Result {\n try {\n return action();\n } catch (error) {\n if (debugEnabled) {\n console.warn('[pyxis] ignored an internal error', error);\n }\n return fallback;\n }\n}\n\nfunction bestEffort(action: () => void): void {\n guarded(action, undefined);\n}\n\nfunction debugWarn(message: string): void {\n if (debugEnabled) {\n console.warn(`[pyxis] ${message}`);\n }\n}\n\nfunction currentPath(): string {\n return templatePath(window.location.pathname, pathRules);\n}\n\nfunction localStore() {\n return webStore(() => window.localStorage);\n}\n\nfunction currentPrivacySignals(): PrivacySignals {\n const signals = readPrivacySignals(navigator, window, localStore());\n return { ...signals, optedOut: signals.optedOut || optedOutThisPage };\n}\n\nfunction stop(): void {\n stoppers.forEach((stopOne) => {\n stopOne();\n });\n tracker?.dispose();\n stoppers = [];\n tracker = undefined;\n}\n\nfunction startAutoPageViews(current: Tracker, pathRules: readonly string[]): () => void {\n return startPageViews(current, pathRules, {\n location: () => window.location,\n referrer: document.referrer,\n watch: (onNavigate) => watchNavigation(onNavigate, window),\n guard: bestEffort,\n });\n}\n\nfunction start(options: PyxisOptions): void {\n const resolution = resolveOptions(options);\n if (!resolution.ok || !isTrackingAllowed(currentPrivacySignals())) {\n return;\n }\n const current = createTracker(resolution.options, createBrowserDependencies());\n pathRules = resolution.options.pathRules;\n tracker = current;\n const stopFlushingOnHide = onPageHide(() => {\n current.flush(true);\n });\n stoppers = resolution.options.autoPageViews\n ? [stopFlushingOnHide, startAutoPageViews(current, pathRules)]\n : [stopFlushingOnHide];\n}\n\nexport function init(options: PyxisOptions): void {\n bestEffort(() => {\n if (initOptions !== undefined || !isBrowserLike(globalThis)) {\n return;\n }\n initOptions = options;\n debugEnabled = options.debug !== undefined;\n start(options);\n });\n}\n\nexport function track(name: string, properties?: Properties): void {\n bestEffort(() => {\n if (tracker === undefined) {\n return;\n }\n const nameCheck = checkEventName(name);\n if (nameCheck !== 'ok') {\n const why =\n nameCheck === 'reserved' ? 'is reserved for the SDK' : 'is not a valid event name';\n debugWarn(`track() ignored \"${name}\": the name ${why}`);\n return;\n }\n const sanitized = sanitizeProperties(properties);\n for (const { key, reason } of sanitized.dropped) {\n debugWarn(`track(\"${name}\") dropped the property \"${key}\" (${reason})`);\n }\n const hasProperties = Object.keys(sanitized.properties).length > 0;\n tracker.enqueue({\n name,\n path: currentPath(),\n ...(hasProperties ? { properties: sanitized.properties } : {}),\n });\n });\n}\n\nexport function identify(userId: string): void {\n bestEffort(() => {\n if (tracker === undefined) {\n return;\n }\n if (!isValidUserId(userId)) {\n debugWarn('identify() ignored a user id outside [A-Za-z0-9_-]{1,64}; never pass an email');\n return;\n }\n tracker.identify(userId, currentPath());\n });\n}\n\nexport function reset(): void {\n bestEffort(() => {\n tracker?.reset();\n });\n}\n\nexport function trackRequest(request: TrackedRequest): void {\n bestEffort(() => {\n if (tracker === undefined) {\n return;\n }\n const check = checkTrackedRequest(request, pathRules);\n if (!check.ok) {\n debugWarn(`trackRequest() ignored a request with an invalid ${check.reason}`);\n return;\n }\n if (check.droppedErrorCode) {\n debugWarn('trackRequest() dropped an errorCode outside [a-z0-9_.]{1,64}');\n }\n tracker.enqueue({ name: API_REQUEST_EVENT, path: currentPath(), properties: check.properties });\n });\n}\n\nexport function optOut(): void {\n bestEffort(() => {\n if (!isBrowserLike(globalThis)) {\n return;\n }\n optedOutThisPage = true;\n localStore().write(OPT_OUT_KEY, OPT_OUT_VALUE);\n stop();\n });\n}\n\nexport function trackingStatus(): TrackingStatus {\n return guarded(\n () => (isBrowserLike(globalThis) ? trackingStatusOf(currentPrivacySignals()) : 'on'),\n 'on',\n );\n}\n\nexport function optIn(): void {\n bestEffort(() => {\n if (!isBrowserLike(globalThis)) {\n return;\n }\n optedOutThisPage = false;\n localStore().remove(OPT_OUT_KEY);\n if (initOptions !== undefined && tracker === undefined) {\n start(initOptions);\n }\n });\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["toHex", "bytes", "byte", "uuidFromBytes", "hex", "variant", "createUuid", "source", "memoryStore", "values", "key", "value", "webStore", "getStorage", "fallback", "RETRY_DELAYS_MS", "RETRY_JITTER", "TOO_MANY_REQUESTS", "judgeOutcome", "outcome", "status", "retryDelay", "attempt", "random", "retryAfterSeconds", "base", "jittered", "parseRetryAfter", "header", "BODY_CONTENT_TYPE", "browserTransport", "fetchImpl", "beacon", "viaBeacon", "url", "body", "viaFetch", "response", "retryAfterSeconds", "parseRetryAfter", "pageHidden", "createBrowserDependencies", "createUuid", "webStore", "browserTransport", "watchNavigation", "onNavigate", "target", "history", "pushState", "replaceState", "args", "onPageHide", "listener", "doc", "win", "onVisibilityChange", "OPT_OUT_KEY", "DO_NOT_TRACK_VALUES", "isDoNotTrack", "values", "value", "trackingStatusOf", "signals", "isTrackingAllowed", "textOrNull", "value", "readPrivacySignals", "nav", "win", "store", "isDoNotTrack", "OPT_OUT_KEY", "isBrowserLike", "scope", "IDENTIFY_EVENT", "RESERVED_EVENT_NAMES", "MAX_PROPERTIES", "MAX_PROPERTY_STRING_LENGTH", "EVENT_NAME_PATTERN", "PROPERTY_KEY_PATTERN", "USER_ID_PATTERN", "checkEventName", "name", "isValidUserId", "userId", "isPropertyValue", "value", "sanitizeProperties", "input", "kept", "dropped", "entries", "key", "BATCH_PATH", "batchUrlFor", "endpoint", "url", "resolveOptions", "options", "key", "batchUrl", "base", "onBatch", "UUID_PATTERN", "ALL_DIGITS", "DIGIT", "ENCODED_AT_SIGN", "isIdentifier", "segment", "UUID_PATTERN", "ALL_DIGITS", "DIGIT", "ENCODED_AT_SIGN", "withoutTrailingSlashes", "path", "end", "matchesRule", "segments", "rule", "ruleSegments", "ruleSegment", "index", "templatePath", "rules", "candidate", "API_REQUEST_EVENT", "REQUEST_METHODS", "MAX_ROUTE_LENGTH", "MAX_REQUEST_DURATION_MS", "MAX_HTTP_STATUS", "ERROR_CODE_PATTERN", "URL_BASE", "isMethod", "value", "isIntegerBetween", "min", "max", "routeOf", "url", "rules", "templatePath", "checkTrackedRequest", "request", "route", "errorCode", "keepsErrorCode", "base", "UTM_PARAMETERS", "AD_CLICK_PARAMETERS", "HOSTNAME_PATTERN", "WWW_PREFIX", "readUtm", "parameters", "entries", "UTM_PARAMETERS", "parameter", "field", "value", "hostOf", "url", "referrerHost", "referrer", "ownHost", "host", "buildAttribution", "source", "utm", "AD_CLICK_PARAMETERS", "PAGE_VIEW", "startPageViews", "tracker", "pathRules", "deps", "lastPath", "referrer", "recordPageView", "pathname", "search", "hostname", "path", "templatePath", "entryAttribution", "buildAttribution", "buildBatch", "key", "sentAt", "events", "serializeBatch", "batch", "encoder", "byteLength", "text", "shouldFlushNow", "queueLength", "enqueue", "queue", "event", "capacity", "chunkEvents", "events", "serialize", "maxEvents", "maxBytes", "chunks", "oversized", "current", "fits", "candidate", "touchSession", "current", "now", "newId", "isRecord", "value", "parseSession", "raw", "id", "lastActivityAt", "userId", "entryRecorded", "recordEntry", "session", "serializeSession", "SESSION_KEY", "NETWORK_ERROR", "createTracker", "options", "deps", "queue", "flushTimer", "retryTimers", "disposed", "touchCurrentSession", "claimsEntry", "stored", "parseSession", "session", "touchSession", "isEntry", "updated", "recordEntry", "serializeSession", "tryNotifyBatch", "batch", "error", "scheduleRetry", "events", "attempt", "outcome", "judgeOutcome", "retryAfter", "delay", "retryDelay", "timer", "send", "pageHidden", "buildBatch", "serializeBatch", "flush", "chunks", "chunkEvents", "chunk", "enqueueEvent", "input", "event", "enqueue", "shouldFlushNow", "userId", "path", "alreadyIdentified", "IDENTIFY_EVENT", "initOptions", "debugEnabled", "tracker", "stoppers", "pathRules", "optedOutThisPage", "guarded", "action", "fallback", "error", "bestEffort", "debugWarn", "message", "currentPath", "templatePath", "localStore", "webStore", "currentPrivacySignals", "signals", "readPrivacySignals", "stop", "stopOne", "startAutoPageViews", "current", "startPageViews", "onNavigate", "watchNavigation", "start", "options", "resolution", "resolveOptions", "isTrackingAllowed", "createTracker", "createBrowserDependencies", "stopFlushingOnHide", "onPageHide", "init", "isBrowserLike", "track", "name", "properties", "nameCheck", "checkEventName", "sanitized", "sanitizeProperties", "key", "reason", "hasProperties", "identify", "userId", "isValidUserId", "reset", "trackRequest", "request", "check", "checkTrackedRequest", "API_REQUEST_EVENT", "optOut", "OPT_OUT_KEY", "trackingStatus", "trackingStatusOf", "optIn"]
|
|
4
|
+
"sourcesContent": ["const UUID_BYTES = 16;\nconst VARIANT_MASK = 0x3f;\nconst VARIANT_BITS = 0x80;\n\nexport type UuidSource = Pick<Crypto, 'getRandomValues'> & Partial<Pick<Crypto, 'randomUUID'>>;\n\nfunction toHex(bytes: Uint8Array): string {\n return Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('');\n}\n\nexport function uuidFromBytes(bytes: Uint8Array): string {\n const hex = toHex(bytes);\n const variant = ((parseInt(hex.slice(16, 18), 16) & VARIANT_MASK) | VARIANT_BITS).toString(16);\n return [\n hex.slice(0, 8),\n hex.slice(8, 12),\n `4${hex.slice(13, 16)}`,\n `${variant}${hex.slice(18, 20)}`,\n hex.slice(20, 32),\n ].join('-');\n}\n\nexport function createUuid(source: UuidSource): string {\n if (typeof source.randomUUID === 'function') {\n return source.randomUUID();\n }\n return uuidFromBytes(source.getRandomValues(new Uint8Array(UUID_BYTES)));\n}\n", "export interface KeyValueStore {\n read(key: string): string | null;\n write(key: string, value: string): void;\n remove(key: string): void;\n}\n\nexport function memoryStore(): KeyValueStore {\n const values = new Map<string, string>();\n return {\n read: (key) => values.get(key) ?? null,\n write: (key, value) => {\n values.set(key, value);\n },\n remove: (key) => {\n values.delete(key);\n },\n };\n}\n\nexport function webStore(getStorage: () => Storage): KeyValueStore {\n const fallback = memoryStore();\n return {\n read: (key) => {\n try {\n return getStorage().getItem(key);\n } catch {\n return fallback.read(key);\n }\n },\n write: (key, value) => {\n try {\n getStorage().setItem(key, value);\n } catch {\n fallback.write(key, value);\n }\n },\n remove: (key) => {\n try {\n getStorage().removeItem(key);\n } catch {\n fallback.remove(key);\n }\n },\n };\n}\n", "export const RETRY_DELAYS_MS: readonly number[] = [1000, 2000, 4000, 8000, 16000];\nexport const RETRY_JITTER = 0.2;\n\nexport type SendOutcome =\n | { readonly kind: 'response'; readonly status: number; readonly retryAfterSeconds?: number }\n | { readonly kind: 'network-error' }\n | { readonly kind: 'handed-off' };\n\nexport type SendVerdict = 'done' | 'retry' | 'drop';\n\nconst TOO_MANY_REQUESTS = 429;\n\nexport function judgeOutcome(outcome: SendOutcome): SendVerdict {\n if (outcome.kind === 'network-error') {\n return 'retry';\n }\n if (outcome.kind === 'handed-off') {\n return 'done';\n }\n const { status } = outcome;\n if (status >= 200 && status < 300) {\n return 'done';\n }\n if (status === TOO_MANY_REQUESTS || status >= 500) {\n return 'retry';\n }\n return 'drop';\n}\n\nexport function retryDelay(\n attempt: number,\n random: () => number,\n retryAfterSeconds?: number,\n): number | undefined {\n const base = RETRY_DELAYS_MS[attempt];\n if (base === undefined) {\n return undefined;\n }\n const jittered = Math.round(base * (1 - RETRY_JITTER + random() * 2 * RETRY_JITTER));\n return retryAfterSeconds === undefined ? jittered : Math.max(jittered, retryAfterSeconds * 1000);\n}\n\nexport function parseRetryAfter(header: string | null): number | undefined {\n if (header === null || !/^\\d+$/.test(header.trim())) {\n return undefined;\n }\n return Number(header.trim());\n}\n", "import { parseRetryAfter, type SendOutcome } from '../core/retry-policy.js';\n\nexport interface Transport {\n send(url: string, body: string, pageHidden: boolean): Promise<SendOutcome>;\n}\n\nexport const BODY_CONTENT_TYPE = 'text/plain;charset=UTF-8';\n\nexport type FetchLike = (input: string, init: RequestInit) => Promise<Response>;\nexport type BeaconLike = (url: string, data: Blob) => boolean;\n\nexport function browserTransport(fetchImpl?: FetchLike, beacon?: BeaconLike): Transport {\n const viaBeacon = (url: string, body: string): SendOutcome =>\n beacon?.(url, new Blob([body], { type: BODY_CONTENT_TYPE })) === true\n ? { kind: 'handed-off' }\n : { kind: 'network-error' };\n\n const viaFetch = async (url: string, body: string): Promise<SendOutcome> => {\n if (fetchImpl === undefined) {\n throw new TypeError('fetch is not available');\n }\n const response = await fetchImpl(url, {\n method: 'POST',\n body,\n keepalive: true,\n credentials: 'omit',\n headers: { 'Content-Type': BODY_CONTENT_TYPE },\n });\n const retryAfterSeconds = parseRetryAfter(response.headers.get('Retry-After'));\n return retryAfterSeconds === undefined\n ? { kind: 'response', status: response.status }\n : { kind: 'response', status: response.status, retryAfterSeconds };\n };\n\n return {\n send: async (url, body, pageHidden) => {\n try {\n return await viaFetch(url, body);\n } catch {\n return pageHidden || fetchImpl === undefined\n ? viaBeacon(url, body)\n : { kind: 'network-error' };\n }\n },\n };\n}\n", "import type { TrackerDependencies } from '../tracker.js';\nimport { createUuid } from './ids.js';\nimport { webStore } from './storage.js';\nimport { browserTransport } from './transport.js';\n\nexport function createBrowserDependencies(): TrackerDependencies {\n return {\n now: () => Date.now(),\n createId: () => createUuid(globalThis.crypto),\n random: Math.random,\n sessionStore: webStore(() => window.sessionStorage),\n transport: browserTransport(\n typeof fetch === 'function' ? fetch.bind(globalThis) : undefined,\n typeof navigator.sendBeacon === 'function' ? navigator.sendBeacon.bind(navigator) : undefined,\n ),\n };\n}\n", "export interface NavigationTarget {\n readonly history: History;\n addEventListener(type: 'popstate', listener: () => void): void;\n removeEventListener(type: 'popstate', listener: () => void): void;\n}\n\nexport function watchNavigation(onNavigate: () => void, target: NavigationTarget): () => void {\n const { history } = target;\n const pushState = history.pushState.bind(history);\n const replaceState = history.replaceState.bind(history);\n history.pushState = (...args: Parameters<History['pushState']>) => {\n pushState(...args);\n onNavigate();\n };\n history.replaceState = (...args: Parameters<History['replaceState']>) => {\n replaceState(...args);\n onNavigate();\n };\n target.addEventListener('popstate', onNavigate);\n return () => {\n history.pushState = pushState;\n history.replaceState = replaceState;\n target.removeEventListener('popstate', onNavigate);\n };\n}\n", "export function onPageHide(\n listener: () => void,\n doc: Document = document,\n win: Window = window,\n): () => void {\n const onVisibilityChange = () => {\n if (doc.visibilityState === 'hidden') {\n listener();\n }\n };\n doc.addEventListener('visibilitychange', onVisibilityChange);\n win.addEventListener('pagehide', listener);\n return () => {\n doc.removeEventListener('visibilitychange', onVisibilityChange);\n win.removeEventListener('pagehide', listener);\n };\n}\n", "export const OPT_OUT_KEY = 'pyxis:opt-out';\nexport const OPT_OUT_VALUE = '1';\n\nconst DO_NOT_TRACK_VALUES = new Set(['1', 'yes']);\n\nexport interface PrivacySignals {\n readonly globalPrivacyControl: boolean;\n readonly doNotTrack: boolean;\n readonly optedOut: boolean;\n readonly automated: boolean;\n}\n\nexport function isDoNotTrack(values: readonly (string | null | undefined)[]): boolean {\n return values.some(\n (value) => value !== null && value !== undefined && DO_NOT_TRACK_VALUES.has(value),\n );\n}\n\nexport type TrackingStatus = 'on' | 'opted-out' | 'blocked-by-browser';\n\nexport function trackingStatusOf(signals: PrivacySignals): TrackingStatus {\n if (signals.globalPrivacyControl || signals.doNotTrack) {\n return 'blocked-by-browser';\n }\n return signals.optedOut ? 'opted-out' : 'on';\n}\n\nexport function isTrackingAllowed(signals: PrivacySignals): boolean {\n return !signals.automated && trackingStatusOf(signals) === 'on';\n}\n", "import { isDoNotTrack, OPT_OUT_KEY, OPT_OUT_VALUE, type PrivacySignals } from '../core/privacy.js';\nimport type { KeyValueStore } from './storage.js';\n\nfunction textOrNull(value: unknown): string | null {\n return typeof value === 'string' ? value : null;\n}\n\nexport function readPrivacySignals(nav: object, win: object, store: KeyValueStore): PrivacySignals {\n return {\n globalPrivacyControl: Reflect.get(nav, 'globalPrivacyControl') === true,\n doNotTrack: isDoNotTrack([\n textOrNull(Reflect.get(nav, 'doNotTrack')),\n textOrNull(Reflect.get(win, 'doNotTrack')),\n ]),\n optedOut: store.read(OPT_OUT_KEY) === OPT_OUT_VALUE,\n automated: Reflect.get(nav, 'webdriver') === true,\n };\n}\n", "export interface GlobalScope {\n readonly window?: unknown;\n readonly document?: unknown;\n}\n\nexport function isBrowserLike(scope: GlobalScope): boolean {\n return scope.window !== undefined && scope.document !== undefined;\n}\n", "import type { PropertyValue } from './batch.js';\n\nexport const IDENTIFY_EVENT = 'identify';\nexport const RESERVED_EVENT_NAMES: readonly string[] = ['page_view', IDENTIFY_EVENT, 'api_request'];\nexport const MAX_PROPERTIES = 10;\nexport const MAX_PROPERTY_STRING_LENGTH = 100;\n\nconst EVENT_NAME_PATTERN = /^[a-z][a-z0-9_]{0,63}$/;\nconst PROPERTY_KEY_PATTERN = /^[a-z0-9_]{1,40}$/;\nconst USER_ID_PATTERN = /^[A-Za-z0-9_-]{1,64}$/;\n\nexport type NameCheck = 'ok' | 'invalid' | 'reserved';\n\nexport type DropReason = 'invalid_key' | 'invalid_value' | 'too_many';\n\nexport interface DroppedProperty {\n readonly key: string;\n readonly reason: DropReason;\n}\n\nexport interface SanitizedProperties {\n readonly properties: Readonly<Record<string, PropertyValue>>;\n readonly dropped: readonly DroppedProperty[];\n}\n\nexport function checkEventName(name: unknown): NameCheck {\n if (typeof name !== 'string' || !EVENT_NAME_PATTERN.test(name)) {\n return 'invalid';\n }\n return RESERVED_EVENT_NAMES.includes(name) ? 'reserved' : 'ok';\n}\n\nexport function isValidUserId(userId: unknown): userId is string {\n return typeof userId === 'string' && USER_ID_PATTERN.test(userId);\n}\n\nfunction isPropertyValue(value: unknown): value is PropertyValue {\n return (\n typeof value === 'boolean' ||\n (typeof value === 'number' && Number.isFinite(value)) ||\n (typeof value === 'string' && value.length <= MAX_PROPERTY_STRING_LENGTH)\n );\n}\n\nexport function sanitizeProperties(input: unknown): SanitizedProperties {\n const kept: Record<string, PropertyValue> = {};\n const dropped: DroppedProperty[] = [];\n const entries = typeof input === 'object' && input !== null ? Object.entries(input) : [];\n for (const [key, value] of entries) {\n if (!PROPERTY_KEY_PATTERN.test(key)) {\n dropped.push({ key, reason: 'invalid_key' });\n } else if (!isPropertyValue(value)) {\n dropped.push({ key, reason: 'invalid_value' });\n } else if (Object.keys(kept).length >= MAX_PROPERTIES) {\n dropped.push({ key, reason: 'too_many' });\n } else {\n kept[key] = value;\n }\n }\n return { properties: kept, dropped };\n}\n", "import type { Batch } from './batch.js';\n\nexport interface PyxisDebugOptions {\n readonly dryRun?: boolean;\n readonly onBatch?: (batch: Batch) => void;\n}\n\nexport interface PyxisOptions {\n readonly key: string | undefined | null;\n readonly endpoint: string;\n readonly pathRules?: readonly string[];\n readonly autoPageViews?: boolean;\n readonly referrer?: string;\n readonly debug?: PyxisDebugOptions;\n}\n\nexport interface ResolvedOptions {\n readonly key: string;\n readonly batchUrl: string;\n readonly pathRules: readonly string[];\n readonly autoPageViews: boolean;\n readonly referrer?: string;\n readonly dryRun: boolean;\n readonly onBatch?: (batch: Batch) => void;\n}\n\nexport type OptionsResolution =\n | { readonly ok: true; readonly options: ResolvedOptions }\n | { readonly ok: false; readonly reason: 'no-key' | 'invalid-endpoint' };\n\nexport const BATCH_PATH = '/v1/batch';\n\nexport function batchUrlFor(endpoint: string): string | undefined {\n let url: URL;\n try {\n url = new URL(endpoint);\n } catch {\n return undefined;\n }\n if (url.protocol !== 'https:' && url.protocol !== 'http:') {\n return undefined;\n }\n return `${url.origin}${url.pathname.replace(/\\/+$/, '')}${BATCH_PATH}`;\n}\n\nexport function resolveOptions(options: PyxisOptions): OptionsResolution {\n const key = options.key?.trim();\n if (!key) {\n return { ok: false, reason: 'no-key' };\n }\n const batchUrl = batchUrlFor(options.endpoint);\n if (batchUrl === undefined) {\n return { ok: false, reason: 'invalid-endpoint' };\n }\n const base = {\n key,\n batchUrl,\n pathRules: options.pathRules ?? [],\n autoPageViews: options.autoPageViews ?? true,\n ...(options.referrer === undefined ? {} : { referrer: options.referrer }),\n dryRun: options.debug?.dryRun ?? false,\n };\n const onBatch = options.debug?.onBatch;\n return { ok: true, options: onBatch === undefined ? base : { ...base, onBatch } };\n}\n", "export const MAX_PATH_LENGTH = 256;\nexport const ID_PLACEHOLDER = ':id';\n\nconst UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nconst ALL_DIGITS = /^\\d+$/;\nconst DIGIT = /\\d/g;\nconst ENCODED_AT_SIGN = /%40/i;\nconst MIN_ID_DIGITS = 10;\n\nfunction isIdentifier(segment: string): boolean {\n return (\n UUID_PATTERN.test(segment) ||\n ALL_DIGITS.test(segment) ||\n (segment.match(DIGIT)?.length ?? 0) >= MIN_ID_DIGITS ||\n segment.includes('@') ||\n ENCODED_AT_SIGN.test(segment)\n );\n}\n\nfunction withoutTrailingSlashes(path: string): string {\n let end = path.length;\n while (end > 0 && path.charAt(end - 1) === '/') {\n end -= 1;\n }\n return end === 0 ? '/' : path.slice(0, end);\n}\n\nfunction matchesRule(segments: readonly string[], rule: string): boolean {\n const ruleSegments = withoutTrailingSlashes(rule).split('/');\n return (\n ruleSegments.length === segments.length &&\n ruleSegments.every(\n (ruleSegment, index) => ruleSegment.startsWith(':') || ruleSegment === segments[index],\n )\n );\n}\n\nexport function templatePath(path: string, rules: readonly string[]): string {\n const segments = withoutTrailingSlashes(path).split('/');\n const rule = rules.find((candidate) => matchesRule(segments, candidate));\n const templated =\n rule === undefined\n ? segments.map((segment) => (isIdentifier(segment) ? ID_PLACEHOLDER : segment)).join('/')\n : withoutTrailingSlashes(rule);\n return templated.slice(0, MAX_PATH_LENGTH);\n}\n", "import type { PropertyValue } from './batch.js';\nimport { templatePath } from './path-template.js';\n\nexport const API_REQUEST_EVENT = 'api_request';\nexport const REQUEST_METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'] as const;\nexport const MAX_ROUTE_LENGTH = 100;\nexport const MAX_REQUEST_DURATION_MS = 600_000;\nexport const MAX_HTTP_STATUS = 599;\n\nconst ERROR_CODE_PATTERN = /^[a-z0-9_.]{1,64}$/;\nconst URL_BASE = 'http://relative.invalid';\n\nexport type RequestMethod = (typeof REQUEST_METHODS)[number];\n\nexport interface TrackedRequest {\n readonly method: RequestMethod;\n readonly url: string;\n readonly status: number;\n readonly durationMs: number;\n readonly errorCode?: string;\n}\n\nexport type RequestCheck =\n | {\n readonly ok: true;\n readonly properties: Readonly<Record<string, PropertyValue>>;\n readonly droppedErrorCode: boolean;\n }\n | { readonly ok: false; readonly reason: 'method' | 'url' | 'status' | 'duration' };\n\nfunction isMethod(value: unknown): value is RequestMethod {\n return typeof value === 'string' && (REQUEST_METHODS as readonly string[]).includes(value);\n}\n\nfunction isIntegerBetween(value: unknown, min: number, max: number): value is number {\n return typeof value === 'number' && Number.isInteger(value) && value >= min && value <= max;\n}\n\nexport function routeOf(url: unknown, rules: readonly string[]): string | undefined {\n if (typeof url !== 'string') {\n return undefined;\n }\n try {\n return templatePath(new URL(url, URL_BASE).pathname, rules).slice(0, MAX_ROUTE_LENGTH);\n } catch {\n return undefined;\n }\n}\n\nexport function checkTrackedRequest(\n request: TrackedRequest,\n rules: readonly string[],\n): RequestCheck {\n if (!isMethod(request.method)) {\n return { ok: false, reason: 'method' };\n }\n const route = routeOf(request.url, rules);\n if (route === undefined) {\n return { ok: false, reason: 'url' };\n }\n if (!isIntegerBetween(request.status, 0, MAX_HTTP_STATUS)) {\n return { ok: false, reason: 'status' };\n }\n if (!isIntegerBetween(request.durationMs, 0, MAX_REQUEST_DURATION_MS)) {\n return { ok: false, reason: 'duration' };\n }\n const { errorCode } = request;\n const keepsErrorCode = typeof errorCode === 'string' && ERROR_CODE_PATTERN.test(errorCode);\n const base = {\n method: request.method,\n route,\n status: request.status,\n duration_ms: request.durationMs,\n };\n return {\n ok: true,\n properties: keepsErrorCode ? { ...base, error_code: errorCode } : base,\n droppedErrorCode: errorCode !== undefined && !keepsErrorCode,\n };\n}\n", "import type { BatchAttribution } from './batch.js';\n\nexport const UTM_PARAMETERS = [\n ['utm_source', 'source'],\n ['utm_medium', 'medium'],\n ['utm_campaign', 'campaign'],\n] as const;\nexport const AD_CLICK_PARAMETERS = [\n 'gclid',\n 'gbraid',\n 'wbraid',\n 'msclkid',\n 'ttclid',\n 'li_fat_id',\n 'twclid',\n 'dclid',\n] as const;\nexport const MAX_UTM_VALUE_LENGTH = 64;\nexport const MAX_REFERRER_HOST_LENGTH = 128;\n\nconst HOSTNAME_PATTERN = /^[a-z0-9-]+(\\.[a-z0-9-]+)*$/;\nconst WWW_PREFIX = /^www\\./;\n\nexport interface AttributionSource {\n readonly search: string;\n readonly referrer: string | undefined;\n readonly ownHost: string;\n}\n\ntype Utm = NonNullable<BatchAttribution['utm']>;\n\nfunction readUtm(parameters: URLSearchParams): Utm | undefined {\n const entries = UTM_PARAMETERS.flatMap(([parameter, field]) => {\n const value = parameters.get(parameter)?.trim().slice(0, MAX_UTM_VALUE_LENGTH);\n return value ? [[field, value] as const] : [];\n });\n return entries.length === 0 ? undefined : Object.fromEntries(entries);\n}\n\nfunction hostOf(url: string): string | undefined {\n try {\n return new URL(url).hostname.toLowerCase().replace(WWW_PREFIX, '');\n } catch {\n return undefined;\n }\n}\n\nfunction referrerHost(referrer: string | undefined, ownHost: string): string | undefined {\n const host = referrer ? hostOf(referrer) : undefined;\n const isUsable =\n host !== undefined &&\n host.length <= MAX_REFERRER_HOST_LENGTH &&\n HOSTNAME_PATTERN.test(host) &&\n host !== ownHost.toLowerCase().replace(WWW_PREFIX, '');\n return isUsable ? host : undefined;\n}\n\nexport function buildAttribution(source: AttributionSource): BatchAttribution {\n const parameters = new URLSearchParams(source.search);\n const utm = readUtm(parameters);\n const host = referrerHost(source.referrer, source.ownHost);\n return {\n ...(host === undefined ? {} : { referrer_host: host }),\n ...(utm === undefined ? {} : { utm }),\n from_ad_click: AD_CLICK_PARAMETERS.some((parameter) => parameters.has(parameter)),\n };\n}\n", "import { buildAttribution } from './core/attribution.js';\nimport { templatePath } from './core/path-template.js';\nimport type { Tracker } from './tracker.js';\n\nexport const PAGE_VIEW = 'page_view';\n\nexport interface PageLocation {\n readonly pathname: string;\n readonly search: string;\n readonly hostname: string;\n}\n\nexport interface PageViewDependencies {\n readonly location: () => PageLocation;\n readonly referrer: string;\n readonly watch: (onNavigate: () => void) => () => void;\n readonly guard: (action: () => void) => void;\n}\n\nexport function startPageViews(\n tracker: Tracker,\n pathRules: readonly string[],\n deps: PageViewDependencies,\n): () => void {\n let lastPath: string | undefined;\n let referrer: string | undefined = deps.referrer;\n\n const recordPageView = (): void => {\n const { pathname, search, hostname } = deps.location();\n const path = templatePath(pathname, pathRules);\n if (path === lastPath) {\n return;\n }\n lastPath = path;\n const entryAttribution = buildAttribution({ search, referrer, ownHost: hostname });\n referrer = undefined;\n tracker.enqueue({ name: PAGE_VIEW, path, entryAttribution });\n };\n\n deps.guard(recordPageView);\n return deps.watch(() => {\n deps.guard(recordPageView);\n });\n}\n", "export type PropertyValue = string | number | boolean;\n\nexport interface BatchAttribution {\n readonly referrer_host?: string;\n readonly utm?: {\n readonly source?: string;\n readonly medium?: string;\n readonly campaign?: string;\n };\n readonly from_ad_click: boolean;\n}\n\nexport interface BatchEvent {\n readonly id: string;\n readonly name: string;\n readonly occurred_at: string;\n readonly session_id: string;\n readonly user_id?: string;\n readonly path: string;\n readonly attribution?: BatchAttribution;\n readonly properties?: Readonly<Record<string, PropertyValue>>;\n}\n\nexport interface Batch {\n readonly key: string;\n readonly sent_at: string;\n readonly events: readonly BatchEvent[];\n}\n\nexport function buildBatch(key: string, sentAt: number, events: readonly BatchEvent[]): Batch {\n return { key, sent_at: new Date(sentAt).toISOString(), events };\n}\n\nexport function serializeBatch(batch: Batch): string {\n return JSON.stringify(batch);\n}\n", "import type { BatchEvent } from './batch.js';\n\nexport const FLUSH_EVENT_COUNT = 10;\nexport const FLUSH_DELAY_MS = 5000;\nexport const MAX_EVENTS_PER_BATCH = 50;\nexport const MAX_BATCH_BYTES = 32 * 1024;\nexport const MAX_QUEUE_SIZE = 500;\n\nconst encoder = new TextEncoder();\n\nexport function byteLength(text: string): number {\n return encoder.encode(text).length;\n}\n\nexport function shouldFlushNow(queueLength: number): boolean {\n return queueLength >= FLUSH_EVENT_COUNT;\n}\n\nexport function enqueue(\n queue: readonly BatchEvent[],\n event: BatchEvent,\n capacity: number = MAX_QUEUE_SIZE,\n): { readonly queue: readonly BatchEvent[]; readonly accepted: boolean } {\n return queue.length >= capacity\n ? { queue, accepted: false }\n : { queue: [...queue, event], accepted: true };\n}\n\nexport interface ChunkResult {\n readonly chunks: readonly (readonly BatchEvent[])[];\n readonly oversized: readonly BatchEvent[];\n}\n\nexport function chunkEvents(\n events: readonly BatchEvent[],\n serialize: (events: readonly BatchEvent[]) => string,\n maxEvents: number = MAX_EVENTS_PER_BATCH,\n maxBytes: number = MAX_BATCH_BYTES,\n): ChunkResult {\n const chunks: BatchEvent[][] = [];\n const oversized: BatchEvent[] = [];\n let current: BatchEvent[] = [];\n const fits = (candidate: readonly BatchEvent[]) =>\n candidate.length <= maxEvents && byteLength(serialize(candidate)) <= maxBytes;\n\n for (const event of events) {\n if (!fits([event])) {\n oversized.push(event);\n continue;\n }\n const candidate = [...current, event];\n if (fits(candidate)) {\n current = candidate;\n continue;\n }\n chunks.push(current);\n current = [event];\n }\n if (current.length > 0) {\n chunks.push(current);\n }\n return { chunks, oversized };\n}\n", "export const SESSION_IDLE_TIMEOUT_MS = 30 * 60 * 1000;\n\nexport interface SessionState {\n readonly id: string;\n readonly lastActivityAt: number;\n readonly userId?: string;\n readonly entryRecorded?: true;\n}\n\nexport interface SessionTouch {\n readonly session: SessionState;\n readonly isNew: boolean;\n}\n\nexport function touchSession(\n current: SessionState | undefined,\n now: number,\n newId: () => string,\n): SessionTouch {\n if (current !== undefined && now - current.lastActivityAt <= SESSION_IDLE_TIMEOUT_MS) {\n return { session: { ...current, lastActivityAt: now }, isNew: false };\n }\n const session: SessionState =\n current?.userId === undefined\n ? { id: newId(), lastActivityAt: now }\n : { id: newId(), lastActivityAt: now, userId: current.userId };\n return { session, isNew: true };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nexport function parseSession(raw: string | null): SessionState | undefined {\n if (raw === null) {\n return undefined;\n }\n let value: unknown;\n try {\n value = JSON.parse(raw);\n } catch {\n return undefined;\n }\n if (\n !isRecord(value) ||\n typeof value.id !== 'string' ||\n typeof value.lastActivityAt !== 'number' ||\n !Number.isFinite(value.lastActivityAt)\n ) {\n return undefined;\n }\n const { id, lastActivityAt, userId, entryRecorded } = value;\n return {\n id,\n lastActivityAt,\n ...(typeof userId === 'string' ? { userId } : {}),\n ...(entryRecorded === true ? { entryRecorded } : {}),\n };\n}\n\nexport function recordEntry(session: SessionState): SessionState {\n return { ...session, entryRecorded: true };\n}\n\nexport function serializeSession(session: SessionState): string {\n return JSON.stringify(session);\n}\n", "import type { KeyValueStore } from './adapters/storage.js';\nimport type { Transport } from './adapters/transport.js';\nimport {\n type Batch,\n type BatchAttribution,\n type BatchEvent,\n buildBatch,\n type PropertyValue,\n serializeBatch,\n} from './core/batch.js';\nimport { chunkEvents, enqueue, FLUSH_DELAY_MS, shouldFlushNow } from './core/batch-policy.js';\nimport { IDENTIFY_EVENT } from './core/event-input.js';\nimport type { ResolvedOptions } from './core/options.js';\nimport { judgeOutcome, retryDelay, type SendOutcome } from './core/retry-policy.js';\nimport {\n parseSession,\n recordEntry,\n type SessionState,\n serializeSession,\n touchSession,\n} from './core/session-policy.js';\n\nexport const SESSION_KEY = 'pyxis:session';\n\nexport interface TrackerDependencies {\n readonly now: () => number;\n readonly createId: () => string;\n readonly random: () => number;\n readonly sessionStore: KeyValueStore;\n readonly transport: Transport;\n}\n\nexport interface EventInput {\n readonly name: string;\n readonly path: string;\n readonly entryAttribution?: BatchAttribution;\n readonly properties?: Readonly<Record<string, PropertyValue>>;\n}\n\nexport interface Tracker {\n enqueue(input: EventInput): void;\n identify(userId: string, path: string): void;\n reset(): void;\n flush(pageHidden?: boolean): void;\n dispose(): void;\n}\n\nconst NETWORK_ERROR: SendOutcome = { kind: 'network-error' };\n\nexport function createTracker(options: ResolvedOptions, deps: TrackerDependencies): Tracker {\n let queue: readonly BatchEvent[] = [];\n let flushTimer: ReturnType<typeof setTimeout> | undefined;\n const retryTimers = new Set<ReturnType<typeof setTimeout>>();\n let disposed = false;\n\n const touchCurrentSession = (\n claimsEntry: boolean,\n ): { session: SessionState; isEntry: boolean } => {\n const stored = parseSession(deps.sessionStore.read(SESSION_KEY));\n const { session } = touchSession(stored, deps.now(), deps.createId);\n const isEntry = claimsEntry && session.entryRecorded !== true;\n const updated = isEntry ? recordEntry(session) : session;\n deps.sessionStore.write(SESSION_KEY, serializeSession(updated));\n return { session: updated, isEntry };\n };\n\n const tryNotifyBatch = (batch: Batch): void => {\n try {\n options.onBatch?.(batch);\n } catch (error) {\n console.warn('[pyxis] debug.onBatch threw; the batch is sent anyway', error);\n }\n };\n\n const scheduleRetry = (\n events: readonly BatchEvent[],\n attempt: number,\n outcome: SendOutcome,\n ): void => {\n if (disposed || judgeOutcome(outcome) !== 'retry') {\n return;\n }\n const retryAfter = outcome.kind === 'response' ? outcome.retryAfterSeconds : undefined;\n const delay = retryDelay(attempt, deps.random, retryAfter);\n if (delay === undefined) {\n return;\n }\n const timer = setTimeout(() => {\n retryTimers.delete(timer);\n send(events, attempt + 1, false);\n }, delay);\n retryTimers.add(timer);\n };\n\n const send = (events: readonly BatchEvent[], attempt: number, pageHidden: boolean): void => {\n const batch = buildBatch(options.key, deps.now(), events);\n tryNotifyBatch(batch);\n if (options.dryRun) {\n return;\n }\n void deps.transport.send(options.batchUrl, serializeBatch(batch), pageHidden).then(\n (outcome) => {\n scheduleRetry(events, attempt, outcome);\n },\n () => {\n scheduleRetry(events, attempt, NETWORK_ERROR);\n },\n );\n };\n\n const flush = (pageHidden = false): void => {\n if (flushTimer !== undefined) {\n clearTimeout(flushTimer);\n flushTimer = undefined;\n }\n if (disposed || queue.length === 0) {\n return;\n }\n const { chunks } = chunkEvents(queue, (events) =>\n serializeBatch(buildBatch(options.key, deps.now(), events)),\n );\n queue = [];\n for (const chunk of chunks) {\n send(chunk, 0, pageHidden);\n }\n };\n\n const enqueueEvent = (input: EventInput): void => {\n if (disposed) {\n return;\n }\n const { session, isEntry } = touchCurrentSession(input.entryAttribution !== undefined);\n const event: BatchEvent = {\n id: deps.createId(),\n name: input.name,\n occurred_at: new Date(deps.now()).toISOString(),\n session_id: session.id,\n path: input.path,\n ...(session.userId === undefined ? {} : { user_id: session.userId }),\n ...(isEntry ? { attribution: input.entryAttribution } : {}),\n ...(input.properties === undefined ? {} : { properties: input.properties }),\n };\n queue = enqueue(queue, event).queue;\n if (shouldFlushNow(queue.length)) {\n flush();\n return;\n }\n flushTimer ??= setTimeout(() => {\n flushTimer = undefined;\n flush();\n }, FLUSH_DELAY_MS);\n };\n\n const identify = (userId: string, path: string): void => {\n if (disposed) {\n return;\n }\n const { session } = touchSession(\n parseSession(deps.sessionStore.read(SESSION_KEY)),\n deps.now(),\n deps.createId,\n );\n const alreadyIdentified = session.userId === userId;\n deps.sessionStore.write(SESSION_KEY, serializeSession({ ...session, userId }));\n if (!alreadyIdentified) {\n enqueueEvent({ name: IDENTIFY_EVENT, path });\n }\n };\n\n const reset = (): void => {\n if (disposed) {\n return;\n }\n flush();\n deps.sessionStore.remove(SESSION_KEY);\n };\n\n return {\n enqueue: enqueueEvent,\n identify,\n reset,\n flush,\n dispose: () => {\n disposed = true;\n queue = [];\n if (flushTimer !== undefined) {\n clearTimeout(flushTimer);\n }\n retryTimers.forEach((timer) => {\n clearTimeout(timer);\n });\n retryTimers.clear();\n },\n };\n}\n", "import { createBrowserDependencies } from './adapters/browser-dependencies.js';\nimport { watchNavigation } from './adapters/navigation.js';\nimport { onPageHide } from './adapters/page-lifecycle.js';\nimport { readPrivacySignals } from './adapters/privacy-signals.js';\nimport { webStore } from './adapters/storage.js';\nimport type { PropertyValue } from './core/batch.js';\nimport { isBrowserLike } from './core/environment.js';\nimport { checkEventName, isValidUserId, sanitizeProperties } from './core/event-input.js';\nimport { type PyxisOptions, resolveOptions } from './core/options.js';\nimport { templatePath } from './core/path-template.js';\nimport {\n API_REQUEST_EVENT,\n checkTrackedRequest,\n type TrackedRequest,\n} from './core/tracked-request.js';\nimport {\n isTrackingAllowed,\n OPT_OUT_KEY,\n OPT_OUT_VALUE,\n type PrivacySignals,\n type TrackingStatus,\n trackingStatusOf,\n} from './core/privacy.js';\nimport { startPageViews } from './page-views.js';\nimport { createTracker, type Tracker } from './tracker.js';\n\nexport type { Batch, BatchAttribution, BatchEvent, PropertyValue } from './core/batch.js';\nexport type { PyxisDebugOptions, PyxisOptions } from './core/options.js';\nexport type { TrackingStatus } from './core/privacy.js';\nexport type { RequestMethod, TrackedRequest } from './core/tracked-request.js';\n\nexport type Properties = Readonly<Record<string, PropertyValue>>;\n\nlet initOptions: PyxisOptions | undefined;\nlet debugEnabled = false;\nlet tracker: Tracker | undefined;\nlet stoppers: readonly (() => void)[] = [];\nlet pathRules: readonly string[] = [];\nlet optedOutThisPage = false;\n\nfunction guarded<Result>(action: () => Result, fallback: Result): Result {\n try {\n return action();\n } catch (error) {\n if (debugEnabled) {\n console.warn('[pyxis] ignored an internal error', error);\n }\n return fallback;\n }\n}\n\nfunction bestEffort(action: () => void): void {\n guarded(action, undefined);\n}\n\nfunction debugWarn(message: string): void {\n if (debugEnabled) {\n console.warn(`[pyxis] ${message}`);\n }\n}\n\nfunction currentPath(): string {\n return templatePath(window.location.pathname, pathRules);\n}\n\nfunction localStore() {\n return webStore(() => window.localStorage);\n}\n\nfunction currentPrivacySignals(): PrivacySignals {\n const signals = readPrivacySignals(navigator, window, localStore());\n return { ...signals, optedOut: signals.optedOut || optedOutThisPage };\n}\n\nfunction stop(): void {\n stoppers.forEach((stopOne) => {\n stopOne();\n });\n tracker?.dispose();\n stoppers = [];\n tracker = undefined;\n}\n\nfunction startAutoPageViews(\n current: Tracker,\n pathRules: readonly string[],\n referrer: string | undefined,\n): () => void {\n return startPageViews(current, pathRules, {\n location: () => window.location,\n referrer: referrer ?? document.referrer,\n watch: (onNavigate) => watchNavigation(onNavigate, window),\n guard: bestEffort,\n });\n}\n\nfunction start(options: PyxisOptions): void {\n const resolution = resolveOptions(options);\n if (!resolution.ok) {\n return;\n }\n const signals = currentPrivacySignals();\n if (signals.automated) {\n debugWarn('measuring is off in a browser driven by automation (navigator.webdriver is true)');\n }\n if (!isTrackingAllowed(signals)) {\n return;\n }\n const current = createTracker(resolution.options, createBrowserDependencies());\n pathRules = resolution.options.pathRules;\n tracker = current;\n const stopFlushingOnHide = onPageHide(() => {\n current.flush(true);\n });\n stoppers = resolution.options.autoPageViews\n ? [stopFlushingOnHide, startAutoPageViews(current, pathRules, resolution.options.referrer)]\n : [stopFlushingOnHide];\n}\n\nexport function init(options: PyxisOptions): void {\n bestEffort(() => {\n if (initOptions !== undefined || !isBrowserLike(globalThis)) {\n return;\n }\n initOptions = options;\n debugEnabled = options.debug !== undefined;\n start(options);\n });\n}\n\nexport function track(name: string, properties?: Properties): void {\n bestEffort(() => {\n if (tracker === undefined) {\n return;\n }\n const nameCheck = checkEventName(name);\n if (nameCheck !== 'ok') {\n const why =\n nameCheck === 'reserved' ? 'is reserved for the SDK' : 'is not a valid event name';\n debugWarn(`track() ignored \"${name}\": the name ${why}`);\n return;\n }\n const sanitized = sanitizeProperties(properties);\n for (const { key, reason } of sanitized.dropped) {\n debugWarn(`track(\"${name}\") dropped the property \"${key}\" (${reason})`);\n }\n const hasProperties = Object.keys(sanitized.properties).length > 0;\n tracker.enqueue({\n name,\n path: currentPath(),\n ...(hasProperties ? { properties: sanitized.properties } : {}),\n });\n });\n}\n\nexport function identify(userId: string): void {\n bestEffort(() => {\n if (tracker === undefined) {\n return;\n }\n if (!isValidUserId(userId)) {\n debugWarn('identify() ignored a user id outside [A-Za-z0-9_-]{1,64}; never pass an email');\n return;\n }\n tracker.identify(userId, currentPath());\n });\n}\n\nexport function reset(): void {\n bestEffort(() => {\n tracker?.reset();\n });\n}\n\nexport function trackRequest(request: TrackedRequest): void {\n bestEffort(() => {\n if (tracker === undefined) {\n return;\n }\n const check = checkTrackedRequest(request, pathRules);\n if (!check.ok) {\n debugWarn(`trackRequest() ignored a request with an invalid ${check.reason}`);\n return;\n }\n if (check.droppedErrorCode) {\n debugWarn('trackRequest() dropped an errorCode outside [a-z0-9_.]{1,64}');\n }\n tracker.enqueue({ name: API_REQUEST_EVENT, path: currentPath(), properties: check.properties });\n });\n}\n\nexport function optOut(): void {\n bestEffort(() => {\n if (!isBrowserLike(globalThis)) {\n return;\n }\n optedOutThisPage = true;\n localStore().write(OPT_OUT_KEY, OPT_OUT_VALUE);\n stop();\n });\n}\n\nexport function trackingStatus(): TrackingStatus {\n return guarded(\n () => (isBrowserLike(globalThis) ? trackingStatusOf(currentPrivacySignals()) : 'on'),\n 'on',\n );\n}\n\nexport function optIn(): void {\n bestEffort(() => {\n if (!isBrowserLike(globalThis)) {\n return;\n }\n optedOutThisPage = false;\n localStore().remove(OPT_OUT_KEY);\n if (initOptions !== undefined && tracker === undefined) {\n start(initOptions);\n }\n });\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["toHex", "bytes", "byte", "uuidFromBytes", "hex", "variant", "createUuid", "source", "memoryStore", "values", "key", "value", "webStore", "getStorage", "fallback", "RETRY_DELAYS_MS", "RETRY_JITTER", "TOO_MANY_REQUESTS", "judgeOutcome", "outcome", "status", "retryDelay", "attempt", "random", "retryAfterSeconds", "base", "jittered", "parseRetryAfter", "header", "BODY_CONTENT_TYPE", "browserTransport", "fetchImpl", "beacon", "viaBeacon", "url", "body", "viaFetch", "response", "retryAfterSeconds", "parseRetryAfter", "pageHidden", "createBrowserDependencies", "createUuid", "webStore", "browserTransport", "watchNavigation", "onNavigate", "target", "history", "pushState", "replaceState", "args", "onPageHide", "listener", "doc", "win", "onVisibilityChange", "OPT_OUT_KEY", "DO_NOT_TRACK_VALUES", "isDoNotTrack", "values", "value", "trackingStatusOf", "signals", "isTrackingAllowed", "textOrNull", "value", "readPrivacySignals", "nav", "win", "store", "isDoNotTrack", "OPT_OUT_KEY", "isBrowserLike", "scope", "IDENTIFY_EVENT", "RESERVED_EVENT_NAMES", "MAX_PROPERTIES", "MAX_PROPERTY_STRING_LENGTH", "EVENT_NAME_PATTERN", "PROPERTY_KEY_PATTERN", "USER_ID_PATTERN", "checkEventName", "name", "isValidUserId", "userId", "isPropertyValue", "value", "sanitizeProperties", "input", "kept", "dropped", "entries", "key", "BATCH_PATH", "batchUrlFor", "endpoint", "url", "resolveOptions", "options", "key", "batchUrl", "base", "onBatch", "UUID_PATTERN", "ALL_DIGITS", "DIGIT", "ENCODED_AT_SIGN", "isIdentifier", "segment", "UUID_PATTERN", "ALL_DIGITS", "DIGIT", "ENCODED_AT_SIGN", "withoutTrailingSlashes", "path", "end", "matchesRule", "segments", "rule", "ruleSegments", "ruleSegment", "index", "templatePath", "rules", "candidate", "API_REQUEST_EVENT", "REQUEST_METHODS", "MAX_ROUTE_LENGTH", "MAX_REQUEST_DURATION_MS", "MAX_HTTP_STATUS", "ERROR_CODE_PATTERN", "URL_BASE", "isMethod", "value", "isIntegerBetween", "min", "max", "routeOf", "url", "rules", "templatePath", "checkTrackedRequest", "request", "route", "errorCode", "keepsErrorCode", "base", "UTM_PARAMETERS", "AD_CLICK_PARAMETERS", "HOSTNAME_PATTERN", "WWW_PREFIX", "readUtm", "parameters", "entries", "UTM_PARAMETERS", "parameter", "field", "value", "hostOf", "url", "referrerHost", "referrer", "ownHost", "host", "buildAttribution", "source", "utm", "AD_CLICK_PARAMETERS", "PAGE_VIEW", "startPageViews", "tracker", "pathRules", "deps", "lastPath", "referrer", "recordPageView", "pathname", "search", "hostname", "path", "templatePath", "entryAttribution", "buildAttribution", "buildBatch", "key", "sentAt", "events", "serializeBatch", "batch", "encoder", "byteLength", "text", "shouldFlushNow", "queueLength", "enqueue", "queue", "event", "capacity", "chunkEvents", "events", "serialize", "maxEvents", "maxBytes", "chunks", "oversized", "current", "fits", "candidate", "touchSession", "current", "now", "newId", "isRecord", "value", "parseSession", "raw", "id", "lastActivityAt", "userId", "entryRecorded", "recordEntry", "session", "serializeSession", "SESSION_KEY", "NETWORK_ERROR", "createTracker", "options", "deps", "queue", "flushTimer", "retryTimers", "disposed", "touchCurrentSession", "claimsEntry", "stored", "parseSession", "session", "touchSession", "isEntry", "updated", "recordEntry", "serializeSession", "tryNotifyBatch", "batch", "error", "scheduleRetry", "events", "attempt", "outcome", "judgeOutcome", "retryAfter", "delay", "retryDelay", "timer", "send", "pageHidden", "buildBatch", "serializeBatch", "flush", "chunks", "chunkEvents", "chunk", "enqueueEvent", "input", "event", "enqueue", "shouldFlushNow", "userId", "path", "alreadyIdentified", "IDENTIFY_EVENT", "initOptions", "debugEnabled", "tracker", "stoppers", "pathRules", "optedOutThisPage", "guarded", "action", "fallback", "error", "bestEffort", "debugWarn", "message", "currentPath", "templatePath", "localStore", "webStore", "currentPrivacySignals", "signals", "readPrivacySignals", "stop", "stopOne", "startAutoPageViews", "current", "referrer", "startPageViews", "onNavigate", "watchNavigation", "start", "options", "resolution", "resolveOptions", "isTrackingAllowed", "createTracker", "createBrowserDependencies", "stopFlushingOnHide", "onPageHide", "init", "isBrowserLike", "track", "name", "properties", "nameCheck", "checkEventName", "sanitized", "sanitizeProperties", "key", "reason", "hasProperties", "identify", "userId", "isValidUserId", "reset", "trackRequest", "request", "check", "checkTrackedRequest", "API_REQUEST_EVENT", "optOut", "OPT_OUT_KEY", "trackingStatus", "trackingStatusOf", "optIn"]
|
|
7
7
|
}
|