pyxis-analytics 0.6.0 → 0.7.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 CHANGED
@@ -48,7 +48,7 @@ A tracker runs on every page of the site it measures, so it decides what leaves
48
48
  browser. This one is built so that nothing personal can: no cookie, no identifier that survives the
49
49
  tab, URLs reduced to path templates, query strings dropped except campaign tags, and "do not
50
50
  track" signals honored before anything is queued. It is small enough to forget about: the budget
51
- is 5 KB gzipped, enforced in CI.
51
+ is 6 KB gzipped, enforced in CI.
52
52
 
53
53
  Read more: [why Pyxis was built and what it never stores][post], the introduction post on the
54
54
  author's blog, also in [Portuguese][post-pt] and [Spanish][post-es].
@@ -135,7 +135,7 @@ reset();
135
135
 
136
136
  A route change that keeps the same templated path records nothing, so routers that call
137
137
  `replaceState` on their own do not inflate page views. Only the first page view of a visit carries
138
- its attribution (referrer host, campaign tags, ad click flag).
138
+ its attribution (referrer host, campaign tags, ad click flag) and its visitor kind (below).
139
139
 
140
140
  A page that sends the visitor elsewhere as soon as it loads, such as a language redirect with
141
141
  `location.replace`, leaves the next page with its own address as `document.referrer`, so the site
@@ -201,9 +201,9 @@ status `0` means no response arrived. An optional `errorCode` carries your API's
201
201
  is set. To see events in your own end-to-end tests, launch Chromium with
202
202
  `--disable-blink-features=AutomationControlled`, which makes `navigator.webdriver` false
203
203
  ([ADR 0005](docs/adr/0005-skip-automated-browsers.md)).
204
- - `optOut()` writes a single `pyxis:opt-out` marker to `localStorage`, the only thing the SDK
205
- keeps beyond the tab, so the choice holds on later visits. With storage blocked it still holds
206
- for the rest of the page. Events not yet sent are dropped: the queue leaves every 5 seconds, or
204
+ - `optOut()` writes a single `pyxis:opt-out` marker to `localStorage`, so the choice holds on later
205
+ visits, and deletes the visitor marker described below. With storage blocked it still holds for
206
+ the rest of the page. Events not yet sent are dropped: the queue leaves every 5 seconds, or
207
207
  with `sendBeacon` when the page is hidden.
208
208
  - `optIn()` removes the marker and, if `init()` already ran, starts measuring in the same page,
209
209
  beginning with a page view of the current page. Under Global Privacy Control, Do Not Track or
@@ -212,6 +212,18 @@ status `0` means no response arrived. An optional `errorCode` carries your API's
212
212
  Track win over the visitor's choice, since a switch cannot turn them off; outside a browser
213
213
  (server rendering) it answers `'on'`, so read it again on the client. Automation does not change
214
214
  it: the switch is for people, and their browsers block nothing.
215
+ - Unique visitors are counted without an identifier, and the browser keeps something for them only
216
+ when the project's owner turns the option on in the dashboard; the site's code does nothing. The
217
+ API then answers each batch with when the site's day and month end, two instants that are the
218
+ same for every visitor that day, and the tracker keeps only those two in `localStorage` as
219
+ `pyxis:period`. The first event of every visit carries `visitor`, told from that marker and the
220
+ device clock: `first_visit` without a marker, `first_this_month` once the month ended,
221
+ `first_today` once the day ended, `again_today` before that. It is sent on every visit, as
222
+ `first_visit` when there is no marker, and the API drops it when the option is off; the marker
223
+ itself is never sent. A successful answer without the period deletes the marker, and so do
224
+ `optOut()` and a browser that sends Global Privacy Control or Do Not Track, which sends nothing;
225
+ under automation nothing is read, written or sent
226
+ ([ADR 0008](docs/adr/0008-visitor-period-marker.md)).
215
227
  - Batches are sent with `credentials: "omit"`: no cookie of any domain travels with them.
216
228
  - No key configured means nothing runs, which keeps tests and local development clean.
217
229
 
@@ -222,13 +234,14 @@ flowchart LR
222
234
  subgraph Shell["Thin shell"]
223
235
  Navigation["History API"] --> Tracker
224
236
  Tracker --> Transport["fetch keepalive<br>sendBeacon"]
225
- Tracker --> Storage["sessionStorage<br>localStorage (opt-out)"]
237
+ Tracker --> Storage["sessionStorage<br>localStorage (opt-out, visitor period)"]
226
238
  end
227
239
  subgraph Core["Functional core (pure)"]
228
240
  Paths["path templates"]
229
241
  Query["query sanitizer"]
230
242
  Batching["batch policy"]
231
243
  Retry["retry policy"]
244
+ Visitor["visitor kind"]
232
245
  end
233
246
  Tracker --> Core
234
247
  Transport -- "POST /v1/batch" --> API["pyxis-api"]
@@ -259,7 +272,7 @@ npm run test:cov # unit tests in jsdom, 100% coverage required
259
272
  npm run test:tooling # the lint rule and the scripts
260
273
  npx vitest run src/contract.test.ts # the contract test alone
261
274
  npx vitest run property # the property-based tests alone
262
- npm run test:e2e # the playground in Chromium: batches valid, nothing sent, none if automated
275
+ npm run test:e2e # Chromium: the playground, the classic build, the visitor marker
263
276
  ```
264
277
 
265
278
  Coverage must stay at **100% of statements, branches, functions and lines** of `src/`; CI fails
@@ -273,16 +286,18 @@ counterexample. They cover path templating (identifier-shaped segments become `:
273
286
  cut between whole segments at 256 characters, a result the API's templating leaves unchanged),
274
287
  property sanitizing (the limits, every key kept or reported as dropped), batching (every event
275
288
  sent once, in order, within both limits), the retry delays and `Retry-After`, attribution (UTM
276
- limits, only the referrer's host) and request tracking (no query, fragment or e-mail address in
277
- the route, the same cut at 100 characters). `vitest.setup.ts` fixes the seed (`20261028`) and the
278
- run count for every file, so CI, the pre-commit hook and a local run test the same inputs; a
279
- failure prints the seed and path that replay it.
289
+ limits, only the referrer's host), the visitor kind (each boundary of the day and the month, a
290
+ marker that keeps only its two instants, garbage never read as one) and request tracking (no
291
+ query, fragment or e-mail address in the route, the same cut at 100 characters).
292
+ `vitest.setup.ts` fixes the seed (`20261028`) and the run count for every file, so CI, the
293
+ pre-commit hook and a local run test the same inputs; a failure prints the seed and path that
294
+ replay it.
280
295
 
281
296
  ## Project structure
282
297
 
283
298
  ```text
284
299
  src/
285
- ├── core/ pure rules: batching, retries, session, privacy, paths, attribution, input checks
300
+ ├── core/ pure rules: batching, retries, session, privacy, paths, attribution, visitors, checks
286
301
  ├── adapters/ browser edges: transport, storage, navigation, page lifecycle, ids
287
302
  ├── tracker.ts the queue, the session and the timers
288
303
  ├── page-views.ts automatic page views
@@ -310,10 +325,11 @@ against the upstream document, so a breaking change in the API shows up here the
310
325
  | [0001](docs/adr/0001-record-architecture-decisions.md) | Record architecture decisions |
311
326
  | [0002](docs/adr/0002-functional-core.md) | Functional core, thin shell |
312
327
  | [0003](docs/adr/0003-zero-dependencies.md) | Zero runtime dependencies and a 3 KB size budget |
313
- | [0004](docs/adr/0004-five-kilobyte-budget.md) | Raise the size budget to 5 KB |
328
+ | [0004](docs/adr/0004-five-kilobyte-budget.md) | Raise the size budget to 5 KB, amended to 6 KB |
314
329
  | [0005](docs/adr/0005-skip-automated-browsers.md) | Do not measure browsers driven by automation |
315
330
  | [0006](docs/adr/0006-stop-after-a-refused-batch.md) | Send nothing more after a refused batch |
316
331
  | [0007](docs/adr/0007-classic-script-build.md) | A classic script build that sets `window.pyxis` |
332
+ | [0008](docs/adr/0008-visitor-period-marker.md) | Tell a visit's kind from a period marker |
317
333
 
318
334
  ## Roadmap
319
335
 
@@ -1,3 +1,4 @@
1
+ import type { VisitorKind } from './visitor-kind.js';
1
2
  export type PropertyValue = string | number | boolean;
2
3
  export interface BatchAttribution {
3
4
  readonly referrer_host?: string;
@@ -16,6 +17,7 @@ export interface BatchEvent {
16
17
  readonly user_id?: string;
17
18
  readonly path: string;
18
19
  readonly attribution?: BatchAttribution;
20
+ readonly visitor?: VisitorKind;
19
21
  readonly properties?: Readonly<Record<string, PropertyValue>>;
20
22
  }
21
23
  export interface Batch {
@@ -1,9 +1,11 @@
1
+ import type { PeriodAnswer } from './visitor-kind.js';
1
2
  export declare const RETRY_DELAYS_MS: readonly number[];
2
3
  export declare const RETRY_JITTER = 0.2;
3
4
  export type SendOutcome = {
4
5
  readonly kind: 'response';
5
6
  readonly status: number;
6
7
  readonly retryAfterSeconds?: number;
8
+ readonly period?: PeriodAnswer;
7
9
  } | {
8
10
  readonly kind: 'network-error';
9
11
  } | {
@@ -0,0 +1,12 @@
1
+ export declare const PERIOD_KEY = "pyxis:period";
2
+ export type VisitorKind = 'first_visit' | 'first_this_month' | 'first_today' | 'again_today';
3
+ export interface VisitorPeriod {
4
+ readonly day_ends_at: string;
5
+ readonly month_ends_at: string;
6
+ }
7
+ export type PeriodAnswer = VisitorPeriod | 'off';
8
+ export declare function parseVisitorPeriod(value: unknown): VisitorPeriod | undefined;
9
+ export declare function parseStoredPeriod(raw: string | null): VisitorPeriod | undefined;
10
+ export declare function serializePeriod(period: VisitorPeriod): string;
11
+ export declare function periodAnswerOf(body: string): PeriodAnswer | undefined;
12
+ export declare function visitorKindOf(period: VisitorPeriod | undefined, now: number): VisitorKind;
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- function _e(e){return Array.from(e,t=>t.toString(16).padStart(2,"0")).join("")}function ke(e){let t=_e(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 $(e){return typeof e.randomUUID=="function"?e.randomUUID():ke(e.getRandomValues(new Uint8Array(16)))}function Re(){let e=new Map;return{read:t=>e.get(t)??null,write:(t,r)=>{e.set(t,r)},remove:t=>{e.delete(t)}}}function k(e){let t=Re();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 xe=[1e3,2e3,4e3,8e3,16e3],z=.2,we=401,Ae=403,Pe=429;function K(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===Pe||t>=500?"retry":t===we||t===Ae?"stop":"drop"}function G(e,t,r){let n=xe[e];if(n===void 0)return;let o=Math.round(n*(1-z+t()*2*z));return r===void 0?o:Math.max(o,r*1e3)}function X(e){if(e===null||!/^\d+$/.test(e.trim()))return;let t=Number(e.trim());return Number.isSafeInteger(t)?t:void 0}var W="text/plain;charset=UTF-8";function Q(e,t){let r=(o,i)=>t?.(o,new Blob([i],{type:W}))===!0?{kind:"handed-off"}:{kind:"network-error"},n=async(o,i)=>{if(e===void 0)throw new TypeError("fetch is not available");let u=await e(o,{method:"POST",body:i,keepalive:!0,credentials:"omit",headers:{"Content-Type":W}}),f=X(u.headers.get("Retry-After"));return f===void 0?{kind:"response",status:u.status}:{kind:"response",status:u.status,retryAfterSeconds:f}};return{send:async(o,i,u)=>{try{return await n(o,i)}catch{return u||e===void 0?r(o,i):{kind:"network-error"}}}}}function Z(){return{now:()=>Date.now(),createId:()=>$(globalThis.crypto),random:Math.random,sessionStore:k(()=>window.sessionStorage),transport:Q(typeof fetch=="function"?fetch.bind(globalThis):void 0,typeof navigator.sendBeacon=="function"?navigator.sendBeacon.bind(navigator):void 0)}}function J(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 ee(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 T="pyxis:opt-out";var Oe=new Set(["1","yes"]);function te(e){return e.some(t=>t!=null&&Oe.has(t))}function A(e){return e.globalPrivacyControl||e.doNotTrack?"blocked-by-browser":e.optedOut?"opted-out":"on"}function re(e){return!e.automated&&A(e)==="on"}function ne(e){return typeof e=="string"?e:null}function oe(e,t,r){return{globalPrivacyControl:Reflect.get(e,"globalPrivacyControl")===!0,doNotTrack:te([ne(Reflect.get(e,"doNotTrack")),ne(Reflect.get(t,"doNotTrack"))]),optedOut:r.read(T)==="1",automated:Reflect.get(e,"webdriver")===!0}}function S(e){return e.window!==void 0&&e.document!==void 0}var O="identify",Ie=["page_view",O,"api_request"],Ne=10,Ue=100,Be=/^[a-z][a-z0-9_]{0,63}$/,De=/^[a-z0-9_]{1,40}$/,Ve=/^[A-Za-z0-9_-]{1,64}$/,Le="__proto__";function ie(e){return typeof e!="string"||!Be.test(e)?"invalid":Ie.includes(e)?"reserved":"ok"}function se(e){return typeof e=="string"&&Ve.test(e)}function Me(e){return De.test(e)&&e!==Le}function He(e){return typeof e=="boolean"||typeof e=="number"&&Number.isFinite(e)||typeof e=="string"&&e.length<=Ue}function ae(e){let t={},r=[],n=typeof e=="object"&&e!==null?Object.entries(e):[];for(let[o,i]of n)Me(o)?He(i)?Object.keys(t).length>=Ne?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 Ce="/v1/batch";function je(e){let t;try{t=new URL(e)}catch{return}if(!(t.protocol!=="https:"&&t.protocol!=="http:"))return`${t.origin}${t.pathname.replace(/\/+$/,"")}${Ce}`}function de(e){let t=e.key?.trim();if(!t)return{ok:!1,reason:"no-key"};let r=je(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 qe=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,Fe=/^\d+$/,Ye=/\d/g,$e=/%40/i;function ze(e){return qe.test(e)||Fe.test(e)||(e.match(Ye)?.length??0)>=10||e.includes("@")||$e.test(e)}function R(e){let t=e.length;for(;t>0&&e.charAt(t-1)==="/";)t-=1;return t===0?"/":e.slice(0,t)}function Ke(e,t){let r=R(t).split("/");return r.length===e.length&&r.every((n,o)=>n.startsWith(":")||n===e[o])}function I(e,t){if(e.length<=t)return e;let r=e.lastIndexOf("/",t);return r>0?R(e.slice(0,r)):"/:id"}function E(e,t){let r=R(e).split("/"),n=t.find(i=>Ke(r,i)),o=n===void 0?r.map(i=>ze(i)?":id":i).join("/"):R(n);return I(o,256)}var ce="api_request",Ge=["GET","POST","PUT","PATCH","DELETE"],Xe=100,We=6e5,Qe=599,Ze=/^[a-z0-9_.]{1,64}$/,Je="http://relative.invalid";function et(e){return typeof e=="string"&&Ge.includes(e)}function ue(e,t,r){return typeof e=="number"&&Number.isInteger(e)&&e>=t&&e<=r}function tt(e,t){if(typeof e=="string")try{return I(E(new URL(e,Je).pathname,t),Xe)}catch{return}}function le(e,t){if(!et(e.method))return{ok:!1,reason:"method"};let r=tt(e.url,t);if(r===void 0)return{ok:!1,reason:"url"};if(!ue(e.status,0,Qe))return{ok:!1,reason:"status"};if(!ue(e.durationMs,0,We))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 rt=[["utm_source","source"],["utm_medium","medium"],["utm_campaign","campaign"]],nt=["gclid","gbraid","wbraid","msclkid","ttclid","li_fat_id","twclid","dclid"];var ot=/^[a-z0-9-]+(\.[a-z0-9-]+)*$/,pe=/^www\./;function it(e){let t=rt.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 st(e){try{return new URL(e).hostname.toLowerCase().replace(pe,"")}catch{return}}function at(e,t){let r=e?st(e):void 0;return r!==void 0&&r.length<=128&&ot.test(r)&&r!==t.toLowerCase().replace(pe,"")?r:void 0}function fe(e){let t=new URLSearchParams(e.search),r=it(t),n=at(e.referrer,e.ownHost);return{...n===void 0?{}:{referrer_host:n},...r===void 0?{}:{utm:r},from_ad_click:nt.some(o=>t.has(o))}}var dt="page_view";function ye(e,t,r){let n,o=r.referrer,i=()=>{let{pathname:u,search:f,hostname:l}=r.location(),y=E(u,t);if(y===n)return;n=y;let v=fe({search:f,referrer:o,ownHost:l});o=void 0,e.enqueue({name:dt,path:y,entryAttribution:v})};return r.guard(i),r.watch(()=>{r.guard(i)})}function N(e,t,r){return{key:e,sent_at:new Date(t).toISOString(),events:r}}function U(e){return JSON.stringify(e)}var ut=new TextEncoder;function ct(e){return ut.encode(e).length}function ge(e){return e>=10}function he(e,t,r=500){return e.length>=r?{queue:e,accepted:!1}:{queue:[...e,t],accepted:!0}}function me(e,t,r=50,n=32768){let o=[],i=[],u=[],f=l=>l.length<=r&&ct(t(l))<=n;for(let l of e){if(!f([l])){i.push(l);continue}let y=[...u,l];if(f(y)){u=y;continue}o.push(u),u=[l]}return u.length>0&&o.push(u),{chunks:o,oversized:i}}function B(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 lt(e){return typeof e=="object"&&e!==null}function D(e){if(e===null)return;let t;try{t=JSON.parse(e)}catch{return}if(!lt(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 Ee(e){return{...e,entryRecorded:!0}}function V(e){return JSON.stringify(e)}var b="pyxis:session",ft={kind:"network-error"},yt="the API refused the batch; nothing more is sent from this page";function Te(e,t){let r=[],n,o=new Set,i=!1,u=s=>{let d=D(t.sessionStore.read(b)),{session:a}=B(d,t.now(),t.createId),c=s&&a.entryRecorded!==!0,h=c?Ee(a):a;return t.sessionStore.write(b,V(h)),{session:h,isEntry:c}},f=s=>{try{e.onBatch?.(s)}catch(d){console.warn("[pyxis] debug.onBatch threw; the batch is sent anyway",d)}},l=()=>{i=!0,r=[],n!==void 0&&clearTimeout(n),o.forEach(s=>{clearTimeout(s)}),o.clear()},y=(s,d,a)=>{let c=a.kind==="response"?a.retryAfterSeconds:void 0,h=G(d,t.random,c);if(h===void 0)return;let Y=setTimeout(()=>{o.delete(Y),q(s,d+1,!1)},h);o.add(Y)},v=(s,d,a)=>{if(i)return;let c=K(a);if(c==="stop"){t.warn?.(yt),l();return}c==="retry"&&y(s,d,a)},q=(s,d,a)=>{let c=N(e.key,t.now(),s);f(c),!e.dryRun&&t.transport.send(e.batchUrl,U(c),a).then(h=>{v(s,d,h)},()=>{v(s,d,ft)})},_=(s=!1)=>{if(n!==void 0&&(clearTimeout(n),n=void 0),i||r.length===0)return;let{chunks:d}=me(r,a=>U(N(e.key,t.now(),a)));r=[];for(let a of d)q(a,0,s)},F=s=>{if(i)return;let{session:d,isEntry:a}=u(s.entryAttribution!==void 0),c={id:t.createId(),name:s.name,occurred_at:new Date(t.now()).toISOString(),session_id:d.id,path:s.path,...d.userId===void 0?{}:{user_id:d.userId},...a?{attribution:s.entryAttribution}:{},...s.properties===void 0?{}:{properties:s.properties}};if(r=he(r,c).queue,ge(r.length)){_();return}n??(n=setTimeout(()=>{n=void 0,_()},5e3))};return{enqueue:F,identify:(s,d)=>{if(i)return;let{session:a}=B(D(t.sessionStore.read(b)),t.now(),t.createId),c=a.userId===s;t.sessionStore.write(b,V({...a,userId:s})),c||F({name:O,path:d})},reset:()=>{i||(_(),t.sessionStore.remove(b))},flush:_,dispose:l}}var x,M=!1,p,L=[],w=[],H=!1;function Se(e,t){try{return e()}catch(r){return M&&console.warn("[pyxis] ignored an internal error",r),t}}function g(e){Se(e,void 0)}function m(e){M&&console.warn(`[pyxis] ${e}`)}function C(){return E(window.location.pathname,w)}function j(){return k(()=>window.localStorage)}function be(){let e=oe(navigator,window,j());return{...e,optedOut:e.optedOut||H}}function gt(){L.forEach(e=>{e()}),p?.dispose(),L=[],p=void 0}function ht(e,t,r){return ye(e,t,{location:()=>window.location,referrer:r??document.referrer,watch:n=>J(n,window),guard:g})}function ve(e){let t=de(e);if(!t.ok)return;let r=be();if(r.automated&&m("measuring is off in a browser driven by automation (navigator.webdriver is true)"),!re(r))return;let n=Te(t.options,{...Z(),warn:m});w=t.options.pathRules,p=n;let o=ee(()=>{n.flush(!0)});L=t.options.autoPageViews?[o,ht(n,w,t.options.referrer)]:[o]}function lr(e){g(()=>{x!==void 0||!S(globalThis)||(x=e,M=e.debug!==void 0,ve(e))})}function pr(e,t){g(()=>{if(p===void 0)return;let r=ie(e);if(r!=="ok"){m(`track() ignored "${e}": the name ${r==="reserved"?"is reserved for the SDK":"is not a valid event name"}`);return}let n=ae(t);for(let{key:i,reason:u}of n.dropped)m(`track("${e}") dropped the property "${i}" (${u})`);let o=Object.keys(n.properties).length>0;p.enqueue({name:e,path:C(),...o?{properties:n.properties}:{}})})}function fr(e){g(()=>{if(p!==void 0){if(!se(e)){m("identify() ignored a user id outside [A-Za-z0-9_-]{1,64}; never pass an email");return}p.identify(e,C())}})}function yr(){g(()=>{p?.reset()})}function gr(e){g(()=>{if(p===void 0)return;let t=le(e,w);if(!t.ok){m(`trackRequest() ignored a request with an invalid ${t.reason}`);return}t.droppedErrorCode&&m("trackRequest() dropped an errorCode outside [a-z0-9_.]{1,64}"),p.enqueue({name:ce,path:C(),properties:t.properties})})}function hr(){g(()=>{S(globalThis)&&(H=!0,j().write(T,"1"),gt())})}function mr(){return Se(()=>S(globalThis)?A(be()):"on","on")}function Er(){g(()=>{S(globalThis)&&(H=!1,j().remove(T),x!==void 0&&p===void 0&&ve(x))})}export{fr as identify,lr as init,Er as optIn,hr as optOut,yr as reset,pr as track,gr as trackRequest,mr as trackingStatus};
1
+ function Be(e){return Array.from(e,t=>t.toString(16).padStart(2,"0")).join("")}function Ve(e){let t=Be(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 z(e){return typeof e.randomUUID=="function"?e.randomUUID():Ve(e.getRandomValues(new Uint8Array(16)))}function De(){let e=new Map;return{read:t=>e.get(t)??null,write:(t,r)=>{e.set(t,r)},remove:t=>{e.delete(t)}}}function S(e){let t=De();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 Le=[1e3,2e3,4e3,8e3,16e3],G=.2,Me=401,He=403,Ce=429;function X(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===Ce||t>=500?"retry":t===Me||t===He?"stop":"drop"}function W(e,t,r){let n=Le[e];if(n===void 0)return;let o=Math.round(n*(1-G+t()*2*G));return r===void 0?o:Math.max(o,r*1e3)}function Q(e){if(e===null||!/^\d+$/.test(e.trim()))return;let t=Number(e.trim());return Number.isSafeInteger(t)?t:void 0}var h="pyxis:period",je=/^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d{3})?Z$/;function Z(e){return typeof e=="object"&&e!==null}function ee(e){try{return JSON.parse(e)}catch{return}}function J(e){return je.test(e)?Date.parse(e):Number.NaN}function te(e){if(!Z(e))return;let{day_ends_at:t,month_ends_at:r}=e;if(!(typeof t!="string"||typeof r!="string"))return J(t)<=J(r)?{day_ends_at:t,month_ends_at:r}:void 0}function re(e){return e===null?void 0:te(ee(e))}function ne(e){return JSON.stringify({day_ends_at:e.day_ends_at,month_ends_at:e.month_ends_at})}function oe(e){let t=ee(e);if(!(!Z(t)||typeof t.accepted!="number"))return t.visitor_period===void 0?"off":te(t.visitor_period)}function ie(e,t){return e===void 0?"first_visit":t>=Date.parse(e.month_ends_at)?"first_this_month":t>=Date.parse(e.day_ends_at)?"first_today":"again_today"}var se="text/plain;charset=UTF-8";function ae(e,t){let r=(o,i)=>t?.(o,new Blob([i],{type:se}))===!0?{kind:"handed-off"}:{kind:"network-error"},n=async(o,i)=>{if(e===void 0)throw new TypeError("fetch is not available");let u=await e(o,{method:"POST",body:i,keepalive:!0,credentials:"omit",headers:{"Content-Type":se}}),f=Q(u.headers.get("Retry-After")),c=u.ok?oe(await u.text().catch(()=>"")):void 0;return{kind:"response",status:u.status,...f===void 0?{}:{retryAfterSeconds:f},...c===void 0?{}:{period:c}}};return{send:async(o,i,u)=>{try{return await n(o,i)}catch{return u||e===void 0?r(o,i):{kind:"network-error"}}}}}function de(){return{now:()=>Date.now(),createId:()=>z(globalThis.crypto),random:Math.random,sessionStore:S(()=>window.sessionStorage),periodStore:S(()=>window.localStorage),transport:ae(typeof fetch=="function"?fetch.bind(globalThis):void 0,typeof navigator.sendBeacon=="function"?navigator.sendBeacon.bind(navigator):void 0)}}function ue(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 ce(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 T="pyxis:opt-out";var Ke=new Set(["1","yes"]);function pe(e){return e.some(t=>t!=null&&Ke.has(t))}function R(e){return e.globalPrivacyControl||e.doNotTrack?"blocked-by-browser":e.optedOut?"opted-out":"on"}function le(e){return!e.automated&&R(e)==="on"}function fe(e){return typeof e=="string"?e:null}function ye(e,t,r){return{globalPrivacyControl:Reflect.get(e,"globalPrivacyControl")===!0,doNotTrack:pe([fe(Reflect.get(e,"doNotTrack")),fe(Reflect.get(t,"doNotTrack"))]),optedOut:r.read(T)==="1",automated:Reflect.get(e,"webdriver")===!0}}function v(e){return e.window!==void 0&&e.document!==void 0}var I="identify",Ye=["page_view",I,"api_request"],qe=10,$e=100,Fe=/^[a-z][a-z0-9_]{0,63}$/,ze=/^[a-z0-9_]{1,40}$/,Ge=/^[A-Za-z0-9_-]{1,64}$/,Xe="__proto__";function me(e){return typeof e!="string"||!Fe.test(e)?"invalid":Ye.includes(e)?"reserved":"ok"}function ge(e){return typeof e=="string"&&Ge.test(e)}function We(e){return ze.test(e)&&e!==Xe}function Qe(e){return typeof e=="boolean"||typeof e=="number"&&Number.isFinite(e)||typeof e=="string"&&e.length<=$e}function he(e){let t={},r=[],n=typeof e=="object"&&e!==null?Object.entries(e):[];for(let[o,i]of n)We(o)?Qe(i)?Object.keys(t).length>=qe?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 Je="/v1/batch";function Ze(e){let t;try{t=new URL(e)}catch{return}if(!(t.protocol!=="https:"&&t.protocol!=="http:"))return`${t.origin}${t.pathname.replace(/\/+$/,"")}${Je}`}function _e(e){let t=e.key?.trim();if(!t)return{ok:!1,reason:"no-key"};let r=Ze(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 et=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,tt=/^\d+$/,rt=/\d/g,nt=/%40/i;function ot(e){return et.test(e)||tt.test(e)||(e.match(rt)?.length??0)>=10||e.includes("@")||nt.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 it(e,t){let r=P(t).split("/");return r.length===e.length&&r.every((n,o)=>n.startsWith(":")||n===e[o])}function U(e,t){if(e.length<=t)return e;let r=e.lastIndexOf("/",t);return r>0?P(e.slice(0,r)):"/:id"}function E(e,t){let r=P(e).split("/"),n=t.find(i=>it(r,i)),o=n===void 0?r.map(i=>ot(i)?":id":i).join("/"):P(n);return U(o,256)}var Se="api_request",st=["GET","POST","PUT","PATCH","DELETE"],at=100,dt=6e5,ut=599,ct=/^[a-z0-9_.]{1,64}$/,pt="http://relative.invalid";function lt(e){return typeof e=="string"&&st.includes(e)}function Ee(e,t,r){return typeof e=="number"&&Number.isInteger(e)&&e>=t&&e<=r}function ft(e,t){if(typeof e=="string")try{return U(E(new URL(e,pt).pathname,t),at)}catch{return}}function Te(e,t){if(!lt(e.method))return{ok:!1,reason:"method"};let r=ft(e.url,t);if(r===void 0)return{ok:!1,reason:"url"};if(!Ee(e.status,0,ut))return{ok:!1,reason:"status"};if(!Ee(e.durationMs,0,dt))return{ok:!1,reason:"duration"};let{errorCode:n}=e,o=typeof n=="string"&&ct.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 yt=[["utm_source","source"],["utm_medium","medium"],["utm_campaign","campaign"]],mt=["gclid","gbraid","wbraid","msclkid","ttclid","li_fat_id","twclid","dclid"];var gt=/^[a-z0-9-]+(\.[a-z0-9-]+)*$/,ve=/^www\./;function ht(e){let t=yt.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 _t(e){try{return new URL(e).hostname.toLowerCase().replace(ve,"")}catch{return}}function Et(e,t){let r=e?_t(e):void 0;return r!==void 0&&r.length<=128&&gt.test(r)&&r!==t.toLowerCase().replace(ve,"")?r:void 0}function be(e){let t=new URLSearchParams(e.search),r=ht(t),n=Et(e.referrer,e.ownHost);return{...n===void 0?{}:{referrer_host:n},...r===void 0?{}:{utm:r},from_ad_click:mt.some(o=>t.has(o))}}var St="page_view";function ke(e,t,r){let n,o=r.referrer,i=()=>{let{pathname:u,search:f,hostname:c}=r.location(),y=E(u,t);if(y===n)return;n=y;let k=be({search:f,referrer:o,ownHost:c});o=void 0,e.enqueue({name:St,path:y,entryAttribution:k})};return r.guard(i),r.watch(()=>{r.guard(i)})}function B(e,t,r){return{key:e,sent_at:new Date(t).toISOString(),events:r}}function V(e){return JSON.stringify(e)}var Tt=new TextEncoder;function vt(e){return Tt.encode(e).length}function xe(e){return e>=10}function Re(e,t,r=500){return e.length>=r?{queue:e,accepted:!1}:{queue:[...e,t],accepted:!0}}function Pe(e,t,r=50,n=32768){let o=[],i=[],u=[],f=c=>c.length<=r&&vt(t(c))<=n;for(let c of e){if(!f([c])){i.push(c);continue}let y=[...u,c];if(f(y)){u=y;continue}o.push(u),u=[c]}return u.length>0&&o.push(u),{chunks:o,oversized:i}}function D(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 bt(e){return typeof e=="object"&&e!==null}function L(e){if(e===null)return;let t;try{t=JSON.parse(e)}catch{return}if(!bt(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 we(e){return{...e,entryRecorded:!0}}function M(e){return JSON.stringify(e)}var b="pyxis:session",xt={kind:"network-error"},Rt="the API refused the batch; nothing more is sent from this page";function Ae(e,t){let r=[],n,o=new Set,i=!1,u=s=>{let a=L(t.sessionStore.read(b)),{session:d}=D(a,t.now(),t.createId),p=s&&d.entryRecorded!==!0,g=p?we(d):d;return t.sessionStore.write(b,M(g)),{session:g,isEntry:p}},f=()=>ie(re(t.periodStore.read(h)),t.now()),c=s=>{let a=s.kind==="response"?s.period:void 0;a==="off"?t.periodStore.remove(h):a!==void 0&&t.periodStore.write(h,ne(a))},y=s=>{try{e.onBatch?.(s)}catch(a){console.warn("[pyxis] debug.onBatch threw; the batch is sent anyway",a)}},k=()=>{i=!0,r=[],n!==void 0&&clearTimeout(n),o.forEach(s=>{clearTimeout(s)}),o.clear()},Ue=(s,a,d)=>{let p=d.kind==="response"?d.retryAfterSeconds:void 0,g=W(a,t.random,p);if(g===void 0)return;let F=setTimeout(()=>{o.delete(F),q(s,a+1,!1)},g);o.add(F)},Y=(s,a,d)=>{if(i)return;c(d);let p=X(d);if(p==="stop"){t.warn?.(Rt),k();return}p==="retry"&&Ue(s,a,d)},q=(s,a,d)=>{let p=B(e.key,t.now(),s);y(p),!e.dryRun&&t.transport.send(e.batchUrl,V(p),d).then(g=>{Y(s,a,g)},()=>{Y(s,a,xt)})},x=(s=!1)=>{if(n!==void 0&&(clearTimeout(n),n=void 0),i||r.length===0)return;let{chunks:a}=Pe(r,d=>V(B(e.key,t.now(),d)));r=[];for(let d of a)q(d,0,s)},$=s=>{if(i)return;let{session:a,isEntry:d}=u(s.entryAttribution!==void 0),p={id:t.createId(),name:s.name,occurred_at:new Date(t.now()).toISOString(),session_id:a.id,path:s.path,...a.userId===void 0?{}:{user_id:a.userId},...d?{attribution:s.entryAttribution,visitor:f()}:{},...s.properties===void 0?{}:{properties:s.properties}};if(r=Re(r,p).queue,xe(r.length)){x();return}n??(n=setTimeout(()=>{n=void 0,x()},5e3))};return{enqueue:$,identify:(s,a)=>{if(i)return;let{session:d}=D(L(t.sessionStore.read(b)),t.now(),t.createId),p=d.userId===s;t.sessionStore.write(b,M({...d,userId:s})),p||$({name:I,path:a})},reset:()=>{i||(x(),t.sessionStore.remove(b))},flush:x,dispose:k}}var w,C=!1,l,H=[],A=[],j=!1;function Oe(e,t){try{return e()}catch(r){return C&&console.warn("[pyxis] ignored an internal error",r),t}}function m(e){Oe(e,void 0)}function _(e){C&&console.warn(`[pyxis] ${e}`)}function K(){return E(window.location.pathname,A)}function O(){return S(()=>window.localStorage)}function Ne(){let e=ye(navigator,window,O());return{...e,optedOut:e.optedOut||j}}function Pt(){H.forEach(e=>{e()}),l?.dispose(),H=[],l=void 0}function wt(e,t,r){return ke(e,t,{location:()=>window.location,referrer:r??document.referrer,watch:n=>ue(n,window),guard:m})}function Ie(e){let t=_e(e);if(!t.ok)return;let r=Ne();if(r.automated&&_("measuring is off in a browser driven by automation (navigator.webdriver is true)"),R(r)!=="on"&&O().remove(h),!le(r))return;let n=Ae(t.options,{...de(),warn:_});A=t.options.pathRules,l=n;let o=ce(()=>{n.flush(!0)});H=t.options.autoPageViews?[o,wt(n,A,t.options.referrer)]:[o]}function Pr(e){m(()=>{w!==void 0||!v(globalThis)||(w=e,C=e.debug!==void 0,Ie(e))})}function wr(e,t){m(()=>{if(l===void 0)return;let r=me(e);if(r!=="ok"){_(`track() ignored "${e}": the name ${r==="reserved"?"is reserved for the SDK":"is not a valid event name"}`);return}let n=he(t);for(let{key:i,reason:u}of n.dropped)_(`track("${e}") dropped the property "${i}" (${u})`);let o=Object.keys(n.properties).length>0;l.enqueue({name:e,path:K(),...o?{properties:n.properties}:{}})})}function Ar(e){m(()=>{if(l!==void 0){if(!ge(e)){_("identify() ignored a user id outside [A-Za-z0-9_-]{1,64}; never pass an email");return}l.identify(e,K())}})}function Or(){m(()=>{l?.reset()})}function Nr(e){m(()=>{if(l===void 0)return;let t=Te(e,A);if(!t.ok){_(`trackRequest() ignored a request with an invalid ${t.reason}`);return}t.droppedErrorCode&&_("trackRequest() dropped an errorCode outside [a-z0-9_.]{1,64}"),l.enqueue({name:Se,path:K(),properties:t.properties})})}function Ir(){m(()=>{if(!v(globalThis))return;j=!0;let e=O();e.write(T,"1"),e.remove(h),Pt()})}function Ur(){return Oe(()=>v(globalThis)?R(Ne()):"on","on")}function Br(){m(()=>{v(globalThis)&&(j=!1,O().remove(T),w!==void 0&&l===void 0&&Ie(w))})}export{Ar as identify,Pr as init,Br as optIn,Ir as optOut,Or as reset,wr as track,Nr 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
- "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' | 'stop';\n\nconst UNAUTHORIZED = 401;\nconst FORBIDDEN = 403;\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 if (status === UNAUTHORIZED || status === FORBIDDEN) {\n return 'stop';\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 const seconds = Number(header.trim());\n return Number.isSafeInteger(seconds) ? seconds : undefined;\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}$/;\nconst PROTOTYPE_KEY = '__proto__';\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 isPropertyKey(key: string): boolean {\n return PROPERTY_KEY_PATTERN.test(key) && key !== PROTOTYPE_KEY;\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 (!isPropertyKey(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 cutToWholeSegments(path: string, maxLength: number): string {\n if (path.length <= maxLength) {\n return path;\n }\n const lastFittingSlash = path.lastIndexOf('/', maxLength);\n return lastFittingSlash > 0\n ? withoutTrailingSlashes(path.slice(0, lastFittingSlash))\n : `/${ID_PLACEHOLDER}`;\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 cutToWholeSegments(templated, MAX_PATH_LENGTH);\n}\n", "import type { PropertyValue } from './batch.js';\nimport { cutToWholeSegments, 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 cutToWholeSegments(\n templatePath(new URL(url, URL_BASE).pathname, rules),\n MAX_ROUTE_LENGTH,\n );\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 readonly warn?: (message: string) => void;\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' };\nexport const REFUSED_WARNING = 'the API refused the batch; nothing more is sent from this page';\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 dispose = (): void => {\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 const scheduleRetry = (\n events: readonly BatchEvent[],\n attempt: number,\n outcome: SendOutcome,\n ): void => {\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 handleOutcome = (\n events: readonly BatchEvent[],\n attempt: number,\n outcome: SendOutcome,\n ): void => {\n if (disposed) {\n return;\n }\n const verdict = judgeOutcome(outcome);\n if (verdict === 'stop') {\n deps.warn?.(REFUSED_WARNING);\n dispose();\n return;\n }\n if (verdict === 'retry') {\n scheduleRetry(events, attempt, outcome);\n }\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 handleOutcome(events, attempt, outcome);\n },\n () => {\n handleOutcome(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 };\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, {\n ...createBrowserDependencies(),\n warn: debugWarn,\n });\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", "UNAUTHORIZED", "FORBIDDEN", "TOO_MANY_REQUESTS", "judgeOutcome", "outcome", "status", "retryDelay", "attempt", "random", "retryAfterSeconds", "base", "jittered", "parseRetryAfter", "header", "seconds", "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", "PROTOTYPE_KEY", "checkEventName", "name", "isValidUserId", "userId", "isPropertyKey", "key", "isPropertyValue", "value", "sanitizeProperties", "input", "kept", "dropped", "entries", "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", "cutToWholeSegments", "maxLength", "lastFittingSlash", "templatePath", "rules", "candidate", "templated", "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", "cutToWholeSegments", "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", "REFUSED_WARNING", "createTracker", "options", "deps", "queue", "flushTimer", "retryTimers", "disposed", "touchCurrentSession", "claimsEntry", "stored", "parseSession", "session", "touchSession", "isEntry", "updated", "recordEntry", "serializeSession", "tryNotifyBatch", "batch", "error", "dispose", "timer", "scheduleRetry", "events", "attempt", "outcome", "retryAfter", "delay", "retryDelay", "send", "handleOutcome", "verdict", "judgeOutcome", "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"]
3
+ "sources": ["../src/adapters/ids.ts", "../src/adapters/storage.ts", "../src/core/retry-policy.ts", "../src/core/visitor-kind.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", "import type { PeriodAnswer } from './visitor-kind.js';\n\nexport const RETRY_DELAYS_MS: readonly number[] = [1000, 2000, 4000, 8000, 16000];\nexport const RETRY_JITTER = 0.2;\n\nexport type SendOutcome =\n | {\n readonly kind: 'response';\n readonly status: number;\n readonly retryAfterSeconds?: number;\n readonly period?: PeriodAnswer;\n }\n | { readonly kind: 'network-error' }\n | { readonly kind: 'handed-off' };\n\nexport type SendVerdict = 'done' | 'retry' | 'drop' | 'stop';\n\nconst UNAUTHORIZED = 401;\nconst FORBIDDEN = 403;\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 if (status === UNAUTHORIZED || status === FORBIDDEN) {\n return 'stop';\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 const seconds = Number(header.trim());\n return Number.isSafeInteger(seconds) ? seconds : undefined;\n}\n", "export const PERIOD_KEY = 'pyxis:period';\n\nexport type VisitorKind = 'first_visit' | 'first_this_month' | 'first_today' | 'again_today';\n\nexport interface VisitorPeriod {\n readonly day_ends_at: string;\n readonly month_ends_at: string;\n}\n\nexport type PeriodAnswer = VisitorPeriod | 'off';\n\nconst UTC_INSTANT = /^\\d{4}-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d(\\.\\d{3})?Z$/;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction parseJson(text: string): unknown {\n try {\n return JSON.parse(text);\n } catch {\n return undefined;\n }\n}\n\nfunction instantOf(text: string): number {\n return UTC_INSTANT.test(text) ? Date.parse(text) : Number.NaN;\n}\n\nexport function parseVisitorPeriod(value: unknown): VisitorPeriod | undefined {\n if (!isRecord(value)) {\n return undefined;\n }\n const { day_ends_at: dayEndsAt, month_ends_at: monthEndsAt } = value;\n if (typeof dayEndsAt !== 'string' || typeof monthEndsAt !== 'string') {\n return undefined;\n }\n return instantOf(dayEndsAt) <= instantOf(monthEndsAt)\n ? { day_ends_at: dayEndsAt, month_ends_at: monthEndsAt }\n : undefined;\n}\n\nexport function parseStoredPeriod(raw: string | null): VisitorPeriod | undefined {\n return raw === null ? undefined : parseVisitorPeriod(parseJson(raw));\n}\n\nexport function serializePeriod(period: VisitorPeriod): string {\n return JSON.stringify({ day_ends_at: period.day_ends_at, month_ends_at: period.month_ends_at });\n}\n\nexport function periodAnswerOf(body: string): PeriodAnswer | undefined {\n const answer = parseJson(body);\n if (!isRecord(answer) || typeof answer.accepted !== 'number') {\n return undefined;\n }\n return answer.visitor_period === undefined ? 'off' : parseVisitorPeriod(answer.visitor_period);\n}\n\nexport function visitorKindOf(period: VisitorPeriod | undefined, now: number): VisitorKind {\n if (period === undefined) {\n return 'first_visit';\n }\n if (now >= Date.parse(period.month_ends_at)) {\n return 'first_this_month';\n }\n return now >= Date.parse(period.day_ends_at) ? 'first_today' : 'again_today';\n}\n", "import { parseRetryAfter, type SendOutcome } from '../core/retry-policy.js';\nimport { periodAnswerOf } from '../core/visitor-kind.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 const period = response.ok ? periodAnswerOf(await response.text().catch(() => '')) : undefined;\n return {\n kind: 'response',\n status: response.status,\n ...(retryAfterSeconds === undefined ? {} : { retryAfterSeconds }),\n ...(period === undefined ? {} : { period }),\n };\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 periodStore: webStore(() => window.localStorage),\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}$/;\nconst PROTOTYPE_KEY = '__proto__';\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 isPropertyKey(key: string): boolean {\n return PROPERTY_KEY_PATTERN.test(key) && key !== PROTOTYPE_KEY;\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 (!isPropertyKey(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 cutToWholeSegments(path: string, maxLength: number): string {\n if (path.length <= maxLength) {\n return path;\n }\n const lastFittingSlash = path.lastIndexOf('/', maxLength);\n return lastFittingSlash > 0\n ? withoutTrailingSlashes(path.slice(0, lastFittingSlash))\n : `/${ID_PLACEHOLDER}`;\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 cutToWholeSegments(templated, MAX_PATH_LENGTH);\n}\n", "import type { PropertyValue } from './batch.js';\nimport { cutToWholeSegments, 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 cutToWholeSegments(\n templatePath(new URL(url, URL_BASE).pathname, rules),\n MAX_ROUTE_LENGTH,\n );\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", "import type { VisitorKind } from './visitor-kind.js';\n\nexport 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 visitor?: VisitorKind;\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';\nimport {\n parseStoredPeriod,\n PERIOD_KEY,\n serializePeriod,\n type VisitorKind,\n visitorKindOf,\n} from './core/visitor-kind.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 periodStore: KeyValueStore;\n readonly transport: Transport;\n readonly warn?: (message: string) => void;\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' };\nexport const REFUSED_WARNING = 'the API refused the batch; nothing more is sent from this page';\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 visitorKind = (): VisitorKind =>\n visitorKindOf(parseStoredPeriod(deps.periodStore.read(PERIOD_KEY)), deps.now());\n\n const keepPeriod = (outcome: SendOutcome): void => {\n const period = outcome.kind === 'response' ? outcome.period : undefined;\n if (period === 'off') {\n deps.periodStore.remove(PERIOD_KEY);\n } else if (period !== undefined) {\n deps.periodStore.write(PERIOD_KEY, serializePeriod(period));\n }\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 dispose = (): void => {\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 const scheduleRetry = (\n events: readonly BatchEvent[],\n attempt: number,\n outcome: SendOutcome,\n ): void => {\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 handleOutcome = (\n events: readonly BatchEvent[],\n attempt: number,\n outcome: SendOutcome,\n ): void => {\n if (disposed) {\n return;\n }\n keepPeriod(outcome);\n const verdict = judgeOutcome(outcome);\n if (verdict === 'stop') {\n deps.warn?.(REFUSED_WARNING);\n dispose();\n return;\n }\n if (verdict === 'retry') {\n scheduleRetry(events, attempt, outcome);\n }\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 handleOutcome(events, attempt, outcome);\n },\n () => {\n handleOutcome(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, visitor: visitorKind() } : {}),\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 };\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 { PERIOD_KEY } from './core/visitor-kind.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 (trackingStatusOf(signals) !== 'on') {\n localStore().remove(PERIOD_KEY);\n }\n if (!isTrackingAllowed(signals)) {\n return;\n }\n const current = createTracker(resolution.options, {\n ...createBrowserDependencies(),\n warn: debugWarn,\n });\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 const store = localStore();\n store.write(OPT_OUT_KEY, OPT_OUT_VALUE);\n store.remove(PERIOD_KEY);\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", "UNAUTHORIZED", "FORBIDDEN", "TOO_MANY_REQUESTS", "judgeOutcome", "outcome", "status", "retryDelay", "attempt", "random", "retryAfterSeconds", "base", "jittered", "parseRetryAfter", "header", "seconds", "PERIOD_KEY", "UTC_INSTANT", "isRecord", "value", "parseJson", "text", "instantOf", "parseVisitorPeriod", "dayEndsAt", "monthEndsAt", "parseStoredPeriod", "raw", "serializePeriod", "period", "periodAnswerOf", "body", "answer", "visitorKindOf", "now", "BODY_CONTENT_TYPE", "browserTransport", "fetchImpl", "beacon", "viaBeacon", "url", "body", "viaFetch", "response", "retryAfterSeconds", "parseRetryAfter", "period", "periodAnswerOf", "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", "PROTOTYPE_KEY", "checkEventName", "name", "isValidUserId", "userId", "isPropertyKey", "key", "isPropertyValue", "value", "sanitizeProperties", "input", "kept", "dropped", "entries", "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", "cutToWholeSegments", "maxLength", "lastFittingSlash", "templatePath", "rules", "candidate", "templated", "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", "cutToWholeSegments", "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", "REFUSED_WARNING", "createTracker", "options", "deps", "queue", "flushTimer", "retryTimers", "disposed", "touchCurrentSession", "claimsEntry", "stored", "parseSession", "session", "touchSession", "isEntry", "updated", "recordEntry", "serializeSession", "visitorKind", "visitorKindOf", "parseStoredPeriod", "PERIOD_KEY", "keepPeriod", "outcome", "period", "serializePeriod", "tryNotifyBatch", "batch", "error", "dispose", "timer", "scheduleRetry", "events", "attempt", "retryAfter", "delay", "retryDelay", "send", "handleOutcome", "verdict", "judgeOutcome", "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", "trackingStatusOf", "PERIOD_KEY", "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", "store", "OPT_OUT_KEY", "trackingStatus", "optIn"]
7
7
  }
@@ -1,2 +1,2 @@
1
- "use strict";(()=>{function Ie(e){return Array.from(e,t=>t.toString(16).padStart(2,"0")).join("")}function Ne(e){let t=Ie(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 $(e){return typeof e.randomUUID=="function"?e.randomUUID():Ne(e.getRandomValues(new Uint8Array(16)))}function Ue(){let e=new Map;return{read:t=>e.get(t)??null,write:(t,r)=>{e.set(t,r)},remove:t=>{e.delete(t)}}}function k(e){let t=Ue();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 Be=[1e3,2e3,4e3,8e3,16e3],z=.2,De=401,Ve=403,Le=429;function K(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===Le||t>=500?"retry":t===De||t===Ve?"stop":"drop"}function G(e,t,r){let n=Be[e];if(n===void 0)return;let o=Math.round(n*(1-z+t()*2*z));return r===void 0?o:Math.max(o,r*1e3)}function X(e){if(e===null||!/^\d+$/.test(e.trim()))return;let t=Number(e.trim());return Number.isSafeInteger(t)?t:void 0}var W="text/plain;charset=UTF-8";function Q(e,t){let r=(o,i)=>t?.(o,new Blob([i],{type:W}))===!0?{kind:"handed-off"}:{kind:"network-error"},n=async(o,i)=>{if(e===void 0)throw new TypeError("fetch is not available");let u=await e(o,{method:"POST",body:i,keepalive:!0,credentials:"omit",headers:{"Content-Type":W}}),f=X(u.headers.get("Retry-After"));return f===void 0?{kind:"response",status:u.status}:{kind:"response",status:u.status,retryAfterSeconds:f}};return{send:async(o,i,u)=>{try{return await n(o,i)}catch{return u||e===void 0?r(o,i):{kind:"network-error"}}}}}function Z(){return{now:()=>Date.now(),createId:()=>$(globalThis.crypto),random:Math.random,sessionStore:k(()=>window.sessionStorage),transport:Q(typeof fetch=="function"?fetch.bind(globalThis):void 0,typeof navigator.sendBeacon=="function"?navigator.sendBeacon.bind(navigator):void 0)}}function J(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 ee(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 T="pyxis:opt-out";var Me=new Set(["1","yes"]);function te(e){return e.some(t=>t!=null&&Me.has(t))}function A(e){return e.globalPrivacyControl||e.doNotTrack?"blocked-by-browser":e.optedOut?"opted-out":"on"}function re(e){return!e.automated&&A(e)==="on"}function ne(e){return typeof e=="string"?e:null}function oe(e,t,r){return{globalPrivacyControl:Reflect.get(e,"globalPrivacyControl")===!0,doNotTrack:te([ne(Reflect.get(e,"doNotTrack")),ne(Reflect.get(t,"doNotTrack"))]),optedOut:r.read(T)==="1",automated:Reflect.get(e,"webdriver")===!0}}function S(e){return e.window!==void 0&&e.document!==void 0}var O="identify",He=["page_view",O,"api_request"],Ce=10,je=100,qe=/^[a-z][a-z0-9_]{0,63}$/,Fe=/^[a-z0-9_]{1,40}$/,Ye=/^[A-Za-z0-9_-]{1,64}$/,$e="__proto__";function ie(e){return typeof e!="string"||!qe.test(e)?"invalid":He.includes(e)?"reserved":"ok"}function se(e){return typeof e=="string"&&Ye.test(e)}function ze(e){return Fe.test(e)&&e!==$e}function Ke(e){return typeof e=="boolean"||typeof e=="number"&&Number.isFinite(e)||typeof e=="string"&&e.length<=je}function ae(e){let t={},r=[],n=typeof e=="object"&&e!==null?Object.entries(e):[];for(let[o,i]of n)ze(o)?Ke(i)?Object.keys(t).length>=Ce?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 Ge="/v1/batch";function Xe(e){let t;try{t=new URL(e)}catch{return}if(!(t.protocol!=="https:"&&t.protocol!=="http:"))return`${t.origin}${t.pathname.replace(/\/+$/,"")}${Ge}`}function de(e){let t=e.key?.trim();if(!t)return{ok:!1,reason:"no-key"};let r=Xe(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 We=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,Qe=/^\d+$/,Ze=/\d/g,Je=/%40/i;function et(e){return We.test(e)||Qe.test(e)||(e.match(Ze)?.length??0)>=10||e.includes("@")||Je.test(e)}function R(e){let t=e.length;for(;t>0&&e.charAt(t-1)==="/";)t-=1;return t===0?"/":e.slice(0,t)}function tt(e,t){let r=R(t).split("/");return r.length===e.length&&r.every((n,o)=>n.startsWith(":")||n===e[o])}function I(e,t){if(e.length<=t)return e;let r=e.lastIndexOf("/",t);return r>0?R(e.slice(0,r)):"/:id"}function E(e,t){let r=R(e).split("/"),n=t.find(i=>tt(r,i)),o=n===void 0?r.map(i=>et(i)?":id":i).join("/"):R(n);return I(o,256)}var ce="api_request",rt=["GET","POST","PUT","PATCH","DELETE"],nt=100,ot=6e5,it=599,st=/^[a-z0-9_.]{1,64}$/,at="http://relative.invalid";function dt(e){return typeof e=="string"&&rt.includes(e)}function ue(e,t,r){return typeof e=="number"&&Number.isInteger(e)&&e>=t&&e<=r}function ut(e,t){if(typeof e=="string")try{return I(E(new URL(e,at).pathname,t),nt)}catch{return}}function le(e,t){if(!dt(e.method))return{ok:!1,reason:"method"};let r=ut(e.url,t);if(r===void 0)return{ok:!1,reason:"url"};if(!ue(e.status,0,it))return{ok:!1,reason:"status"};if(!ue(e.durationMs,0,ot))return{ok:!1,reason:"duration"};let{errorCode:n}=e,o=typeof n=="string"&&st.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 ct=[["utm_source","source"],["utm_medium","medium"],["utm_campaign","campaign"]],lt=["gclid","gbraid","wbraid","msclkid","ttclid","li_fat_id","twclid","dclid"];var pt=/^[a-z0-9-]+(\.[a-z0-9-]+)*$/,pe=/^www\./;function ft(e){let t=ct.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 yt(e){try{return new URL(e).hostname.toLowerCase().replace(pe,"")}catch{return}}function gt(e,t){let r=e?yt(e):void 0;return r!==void 0&&r.length<=128&&pt.test(r)&&r!==t.toLowerCase().replace(pe,"")?r:void 0}function fe(e){let t=new URLSearchParams(e.search),r=ft(t),n=gt(e.referrer,e.ownHost);return{...n===void 0?{}:{referrer_host:n},...r===void 0?{}:{utm:r},from_ad_click:lt.some(o=>t.has(o))}}var ht="page_view";function ye(e,t,r){let n,o=r.referrer,i=()=>{let{pathname:u,search:f,hostname:l}=r.location(),y=E(u,t);if(y===n)return;n=y;let v=fe({search:f,referrer:o,ownHost:l});o=void 0,e.enqueue({name:ht,path:y,entryAttribution:v})};return r.guard(i),r.watch(()=>{r.guard(i)})}function N(e,t,r){return{key:e,sent_at:new Date(t).toISOString(),events:r}}function U(e){return JSON.stringify(e)}var mt=new TextEncoder;function Et(e){return mt.encode(e).length}function ge(e){return e>=10}function he(e,t,r=500){return e.length>=r?{queue:e,accepted:!1}:{queue:[...e,t],accepted:!0}}function me(e,t,r=50,n=32768){let o=[],i=[],u=[],f=l=>l.length<=r&&Et(t(l))<=n;for(let l of e){if(!f([l])){i.push(l);continue}let y=[...u,l];if(f(y)){u=y;continue}o.push(u),u=[l]}return u.length>0&&o.push(u),{chunks:o,oversized:i}}function B(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 Tt(e){return typeof e=="object"&&e!==null}function D(e){if(e===null)return;let t;try{t=JSON.parse(e)}catch{return}if(!Tt(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 Ee(e){return{...e,entryRecorded:!0}}function V(e){return JSON.stringify(e)}var b="pyxis:session",bt={kind:"network-error"},vt="the API refused the batch; nothing more is sent from this page";function Te(e,t){let r=[],n,o=new Set,i=!1,u=s=>{let d=D(t.sessionStore.read(b)),{session:a}=B(d,t.now(),t.createId),c=s&&a.entryRecorded!==!0,h=c?Ee(a):a;return t.sessionStore.write(b,V(h)),{session:h,isEntry:c}},f=s=>{try{e.onBatch?.(s)}catch(d){console.warn("[pyxis] debug.onBatch threw; the batch is sent anyway",d)}},l=()=>{i=!0,r=[],n!==void 0&&clearTimeout(n),o.forEach(s=>{clearTimeout(s)}),o.clear()},y=(s,d,a)=>{let c=a.kind==="response"?a.retryAfterSeconds:void 0,h=G(d,t.random,c);if(h===void 0)return;let Y=setTimeout(()=>{o.delete(Y),q(s,d+1,!1)},h);o.add(Y)},v=(s,d,a)=>{if(i)return;let c=K(a);if(c==="stop"){t.warn?.(vt),l();return}c==="retry"&&y(s,d,a)},q=(s,d,a)=>{let c=N(e.key,t.now(),s);f(c),!e.dryRun&&t.transport.send(e.batchUrl,U(c),a).then(h=>{v(s,d,h)},()=>{v(s,d,bt)})},_=(s=!1)=>{if(n!==void 0&&(clearTimeout(n),n=void 0),i||r.length===0)return;let{chunks:d}=me(r,a=>U(N(e.key,t.now(),a)));r=[];for(let a of d)q(a,0,s)},F=s=>{if(i)return;let{session:d,isEntry:a}=u(s.entryAttribution!==void 0),c={id:t.createId(),name:s.name,occurred_at:new Date(t.now()).toISOString(),session_id:d.id,path:s.path,...d.userId===void 0?{}:{user_id:d.userId},...a?{attribution:s.entryAttribution}:{},...s.properties===void 0?{}:{properties:s.properties}};if(r=he(r,c).queue,ge(r.length)){_();return}n??(n=setTimeout(()=>{n=void 0,_()},5e3))};return{enqueue:F,identify:(s,d)=>{if(i)return;let{session:a}=B(D(t.sessionStore.read(b)),t.now(),t.createId),c=a.userId===s;t.sessionStore.write(b,V({...a,userId:s})),c||F({name:O,path:d})},reset:()=>{i||(_(),t.sessionStore.remove(b))},flush:_,dispose:l}}var x,M=!1,p,L=[],w=[],H=!1;function Se(e,t){try{return e()}catch(r){return M&&console.warn("[pyxis] ignored an internal error",r),t}}function g(e){Se(e,void 0)}function m(e){M&&console.warn(`[pyxis] ${e}`)}function C(){return E(window.location.pathname,w)}function j(){return k(()=>window.localStorage)}function be(){let e=oe(navigator,window,j());return{...e,optedOut:e.optedOut||H}}function _t(){L.forEach(e=>{e()}),p?.dispose(),L=[],p=void 0}function kt(e,t,r){return ye(e,t,{location:()=>window.location,referrer:r??document.referrer,watch:n=>J(n,window),guard:g})}function ve(e){let t=de(e);if(!t.ok)return;let r=be();if(r.automated&&m("measuring is off in a browser driven by automation (navigator.webdriver is true)"),!re(r))return;let n=Te(t.options,{...Z(),warn:m});w=t.options.pathRules,p=n;let o=ee(()=>{n.flush(!0)});L=t.options.autoPageViews?[o,kt(n,w,t.options.referrer)]:[o]}function _e(e){g(()=>{x!==void 0||!S(globalThis)||(x=e,M=e.debug!==void 0,ve(e))})}function ke(e,t){g(()=>{if(p===void 0)return;let r=ie(e);if(r!=="ok"){m(`track() ignored "${e}": the name ${r==="reserved"?"is reserved for the SDK":"is not a valid event name"}`);return}let n=ae(t);for(let{key:i,reason:u}of n.dropped)m(`track("${e}") dropped the property "${i}" (${u})`);let o=Object.keys(n.properties).length>0;p.enqueue({name:e,path:C(),...o?{properties:n.properties}:{}})})}function Re(e){g(()=>{if(p!==void 0){if(!se(e)){m("identify() ignored a user id outside [A-Za-z0-9_-]{1,64}; never pass an email");return}p.identify(e,C())}})}function xe(){g(()=>{p?.reset()})}function we(e){g(()=>{if(p===void 0)return;let t=le(e,w);if(!t.ok){m(`trackRequest() ignored a request with an invalid ${t.reason}`);return}t.droppedErrorCode&&m("trackRequest() dropped an errorCode outside [a-z0-9_.]{1,64}"),p.enqueue({name:ce,path:C(),properties:t.properties})})}function Ae(){g(()=>{S(globalThis)&&(H=!0,j().write(T,"1"),_t())})}function Pe(){return Se(()=>S(globalThis)?A(be()):"on","on")}function Oe(){g(()=>{S(globalThis)&&(H=!1,j().remove(T),x!==void 0&&p===void 0&&ve(x))})}Object.assign(globalThis,{pyxis:{init:_e,track:ke,identify:Re,reset:xe,trackRequest:we,optOut:Ae,optIn:Oe,trackingStatus:Pe}});})();
1
+ "use strict";(()=>{function Ke(e){return Array.from(e,t=>t.toString(16).padStart(2,"0")).join("")}function Ye(e){let t=Ke(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 z(e){return typeof e.randomUUID=="function"?e.randomUUID():Ye(e.getRandomValues(new Uint8Array(16)))}function qe(){let e=new Map;return{read:t=>e.get(t)??null,write:(t,r)=>{e.set(t,r)},remove:t=>{e.delete(t)}}}function S(e){let t=qe();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],G=.2,Fe=401,ze=403,Ge=429;function X(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===Ge||t>=500?"retry":t===Fe||t===ze?"stop":"drop"}function W(e,t,r){let n=$e[e];if(n===void 0)return;let o=Math.round(n*(1-G+t()*2*G));return r===void 0?o:Math.max(o,r*1e3)}function Q(e){if(e===null||!/^\d+$/.test(e.trim()))return;let t=Number(e.trim());return Number.isSafeInteger(t)?t:void 0}var h="pyxis:period",Xe=/^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d{3})?Z$/;function Z(e){return typeof e=="object"&&e!==null}function ee(e){try{return JSON.parse(e)}catch{return}}function J(e){return Xe.test(e)?Date.parse(e):Number.NaN}function te(e){if(!Z(e))return;let{day_ends_at:t,month_ends_at:r}=e;if(!(typeof t!="string"||typeof r!="string"))return J(t)<=J(r)?{day_ends_at:t,month_ends_at:r}:void 0}function re(e){return e===null?void 0:te(ee(e))}function ne(e){return JSON.stringify({day_ends_at:e.day_ends_at,month_ends_at:e.month_ends_at})}function oe(e){let t=ee(e);if(!(!Z(t)||typeof t.accepted!="number"))return t.visitor_period===void 0?"off":te(t.visitor_period)}function ie(e,t){return e===void 0?"first_visit":t>=Date.parse(e.month_ends_at)?"first_this_month":t>=Date.parse(e.day_ends_at)?"first_today":"again_today"}var se="text/plain;charset=UTF-8";function ae(e,t){let r=(o,i)=>t?.(o,new Blob([i],{type:se}))===!0?{kind:"handed-off"}:{kind:"network-error"},n=async(o,i)=>{if(e===void 0)throw new TypeError("fetch is not available");let u=await e(o,{method:"POST",body:i,keepalive:!0,credentials:"omit",headers:{"Content-Type":se}}),f=Q(u.headers.get("Retry-After")),c=u.ok?oe(await u.text().catch(()=>"")):void 0;return{kind:"response",status:u.status,...f===void 0?{}:{retryAfterSeconds:f},...c===void 0?{}:{period:c}}};return{send:async(o,i,u)=>{try{return await n(o,i)}catch{return u||e===void 0?r(o,i):{kind:"network-error"}}}}}function de(){return{now:()=>Date.now(),createId:()=>z(globalThis.crypto),random:Math.random,sessionStore:S(()=>window.sessionStorage),periodStore:S(()=>window.localStorage),transport:ae(typeof fetch=="function"?fetch.bind(globalThis):void 0,typeof navigator.sendBeacon=="function"?navigator.sendBeacon.bind(navigator):void 0)}}function ue(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 ce(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 T="pyxis:opt-out";var We=new Set(["1","yes"]);function pe(e){return e.some(t=>t!=null&&We.has(t))}function R(e){return e.globalPrivacyControl||e.doNotTrack?"blocked-by-browser":e.optedOut?"opted-out":"on"}function le(e){return!e.automated&&R(e)==="on"}function fe(e){return typeof e=="string"?e:null}function ye(e,t,r){return{globalPrivacyControl:Reflect.get(e,"globalPrivacyControl")===!0,doNotTrack:pe([fe(Reflect.get(e,"doNotTrack")),fe(Reflect.get(t,"doNotTrack"))]),optedOut:r.read(T)==="1",automated:Reflect.get(e,"webdriver")===!0}}function v(e){return e.window!==void 0&&e.document!==void 0}var I="identify",Qe=["page_view",I,"api_request"],Je=10,Ze=100,et=/^[a-z][a-z0-9_]{0,63}$/,tt=/^[a-z0-9_]{1,40}$/,rt=/^[A-Za-z0-9_-]{1,64}$/,nt="__proto__";function me(e){return typeof e!="string"||!et.test(e)?"invalid":Qe.includes(e)?"reserved":"ok"}function ge(e){return typeof e=="string"&&rt.test(e)}function ot(e){return tt.test(e)&&e!==nt}function it(e){return typeof e=="boolean"||typeof e=="number"&&Number.isFinite(e)||typeof e=="string"&&e.length<=Ze}function he(e){let t={},r=[],n=typeof e=="object"&&e!==null?Object.entries(e):[];for(let[o,i]of n)ot(o)?it(i)?Object.keys(t).length>=Je?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 st="/v1/batch";function at(e){let t;try{t=new URL(e)}catch{return}if(!(t.protocol!=="https:"&&t.protocol!=="http:"))return`${t.origin}${t.pathname.replace(/\/+$/,"")}${st}`}function _e(e){let t=e.key?.trim();if(!t)return{ok:!1,reason:"no-key"};let r=at(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 dt=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,ut=/^\d+$/,ct=/\d/g,pt=/%40/i;function lt(e){return dt.test(e)||ut.test(e)||(e.match(ct)?.length??0)>=10||e.includes("@")||pt.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 ft(e,t){let r=P(t).split("/");return r.length===e.length&&r.every((n,o)=>n.startsWith(":")||n===e[o])}function U(e,t){if(e.length<=t)return e;let r=e.lastIndexOf("/",t);return r>0?P(e.slice(0,r)):"/:id"}function E(e,t){let r=P(e).split("/"),n=t.find(i=>ft(r,i)),o=n===void 0?r.map(i=>lt(i)?":id":i).join("/"):P(n);return U(o,256)}var Se="api_request",yt=["GET","POST","PUT","PATCH","DELETE"],mt=100,gt=6e5,ht=599,_t=/^[a-z0-9_.]{1,64}$/,Et="http://relative.invalid";function St(e){return typeof e=="string"&&yt.includes(e)}function Ee(e,t,r){return typeof e=="number"&&Number.isInteger(e)&&e>=t&&e<=r}function Tt(e,t){if(typeof e=="string")try{return U(E(new URL(e,Et).pathname,t),mt)}catch{return}}function Te(e,t){if(!St(e.method))return{ok:!1,reason:"method"};let r=Tt(e.url,t);if(r===void 0)return{ok:!1,reason:"url"};if(!Ee(e.status,0,ht))return{ok:!1,reason:"status"};if(!Ee(e.durationMs,0,gt))return{ok:!1,reason:"duration"};let{errorCode:n}=e,o=typeof n=="string"&&_t.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 vt=[["utm_source","source"],["utm_medium","medium"],["utm_campaign","campaign"]],bt=["gclid","gbraid","wbraid","msclkid","ttclid","li_fat_id","twclid","dclid"];var kt=/^[a-z0-9-]+(\.[a-z0-9-]+)*$/,ve=/^www\./;function xt(e){let t=vt.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 Rt(e){try{return new URL(e).hostname.toLowerCase().replace(ve,"")}catch{return}}function Pt(e,t){let r=e?Rt(e):void 0;return r!==void 0&&r.length<=128&&kt.test(r)&&r!==t.toLowerCase().replace(ve,"")?r:void 0}function be(e){let t=new URLSearchParams(e.search),r=xt(t),n=Pt(e.referrer,e.ownHost);return{...n===void 0?{}:{referrer_host:n},...r===void 0?{}:{utm:r},from_ad_click:bt.some(o=>t.has(o))}}var wt="page_view";function ke(e,t,r){let n,o=r.referrer,i=()=>{let{pathname:u,search:f,hostname:c}=r.location(),y=E(u,t);if(y===n)return;n=y;let k=be({search:f,referrer:o,ownHost:c});o=void 0,e.enqueue({name:wt,path:y,entryAttribution:k})};return r.guard(i),r.watch(()=>{r.guard(i)})}function B(e,t,r){return{key:e,sent_at:new Date(t).toISOString(),events:r}}function V(e){return JSON.stringify(e)}var At=new TextEncoder;function Ot(e){return At.encode(e).length}function xe(e){return e>=10}function Re(e,t,r=500){return e.length>=r?{queue:e,accepted:!1}:{queue:[...e,t],accepted:!0}}function Pe(e,t,r=50,n=32768){let o=[],i=[],u=[],f=c=>c.length<=r&&Ot(t(c))<=n;for(let c of e){if(!f([c])){i.push(c);continue}let y=[...u,c];if(f(y)){u=y;continue}o.push(u),u=[c]}return u.length>0&&o.push(u),{chunks:o,oversized:i}}function D(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 Nt(e){return typeof e=="object"&&e!==null}function L(e){if(e===null)return;let t;try{t=JSON.parse(e)}catch{return}if(!Nt(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 we(e){return{...e,entryRecorded:!0}}function M(e){return JSON.stringify(e)}var b="pyxis:session",Ut={kind:"network-error"},Bt="the API refused the batch; nothing more is sent from this page";function Ae(e,t){let r=[],n,o=new Set,i=!1,u=s=>{let a=L(t.sessionStore.read(b)),{session:d}=D(a,t.now(),t.createId),p=s&&d.entryRecorded!==!0,g=p?we(d):d;return t.sessionStore.write(b,M(g)),{session:g,isEntry:p}},f=()=>ie(re(t.periodStore.read(h)),t.now()),c=s=>{let a=s.kind==="response"?s.period:void 0;a==="off"?t.periodStore.remove(h):a!==void 0&&t.periodStore.write(h,ne(a))},y=s=>{try{e.onBatch?.(s)}catch(a){console.warn("[pyxis] debug.onBatch threw; the batch is sent anyway",a)}},k=()=>{i=!0,r=[],n!==void 0&&clearTimeout(n),o.forEach(s=>{clearTimeout(s)}),o.clear()},je=(s,a,d)=>{let p=d.kind==="response"?d.retryAfterSeconds:void 0,g=W(a,t.random,p);if(g===void 0)return;let F=setTimeout(()=>{o.delete(F),q(s,a+1,!1)},g);o.add(F)},Y=(s,a,d)=>{if(i)return;c(d);let p=X(d);if(p==="stop"){t.warn?.(Bt),k();return}p==="retry"&&je(s,a,d)},q=(s,a,d)=>{let p=B(e.key,t.now(),s);y(p),!e.dryRun&&t.transport.send(e.batchUrl,V(p),d).then(g=>{Y(s,a,g)},()=>{Y(s,a,Ut)})},x=(s=!1)=>{if(n!==void 0&&(clearTimeout(n),n=void 0),i||r.length===0)return;let{chunks:a}=Pe(r,d=>V(B(e.key,t.now(),d)));r=[];for(let d of a)q(d,0,s)},$=s=>{if(i)return;let{session:a,isEntry:d}=u(s.entryAttribution!==void 0),p={id:t.createId(),name:s.name,occurred_at:new Date(t.now()).toISOString(),session_id:a.id,path:s.path,...a.userId===void 0?{}:{user_id:a.userId},...d?{attribution:s.entryAttribution,visitor:f()}:{},...s.properties===void 0?{}:{properties:s.properties}};if(r=Re(r,p).queue,xe(r.length)){x();return}n??(n=setTimeout(()=>{n=void 0,x()},5e3))};return{enqueue:$,identify:(s,a)=>{if(i)return;let{session:d}=D(L(t.sessionStore.read(b)),t.now(),t.createId),p=d.userId===s;t.sessionStore.write(b,M({...d,userId:s})),p||$({name:I,path:a})},reset:()=>{i||(x(),t.sessionStore.remove(b))},flush:x,dispose:k}}var w,C=!1,l,H=[],A=[],j=!1;function Oe(e,t){try{return e()}catch(r){return C&&console.warn("[pyxis] ignored an internal error",r),t}}function m(e){Oe(e,void 0)}function _(e){C&&console.warn(`[pyxis] ${e}`)}function K(){return E(window.location.pathname,A)}function O(){return S(()=>window.localStorage)}function Ne(){let e=ye(navigator,window,O());return{...e,optedOut:e.optedOut||j}}function Vt(){H.forEach(e=>{e()}),l?.dispose(),H=[],l=void 0}function Dt(e,t,r){return ke(e,t,{location:()=>window.location,referrer:r??document.referrer,watch:n=>ue(n,window),guard:m})}function Ie(e){let t=_e(e);if(!t.ok)return;let r=Ne();if(r.automated&&_("measuring is off in a browser driven by automation (navigator.webdriver is true)"),R(r)!=="on"&&O().remove(h),!le(r))return;let n=Ae(t.options,{...de(),warn:_});A=t.options.pathRules,l=n;let o=ce(()=>{n.flush(!0)});H=t.options.autoPageViews?[o,Dt(n,A,t.options.referrer)]:[o]}function Ue(e){m(()=>{w!==void 0||!v(globalThis)||(w=e,C=e.debug!==void 0,Ie(e))})}function Be(e,t){m(()=>{if(l===void 0)return;let r=me(e);if(r!=="ok"){_(`track() ignored "${e}": the name ${r==="reserved"?"is reserved for the SDK":"is not a valid event name"}`);return}let n=he(t);for(let{key:i,reason:u}of n.dropped)_(`track("${e}") dropped the property "${i}" (${u})`);let o=Object.keys(n.properties).length>0;l.enqueue({name:e,path:K(),...o?{properties:n.properties}:{}})})}function Ve(e){m(()=>{if(l!==void 0){if(!ge(e)){_("identify() ignored a user id outside [A-Za-z0-9_-]{1,64}; never pass an email");return}l.identify(e,K())}})}function De(){m(()=>{l?.reset()})}function Le(e){m(()=>{if(l===void 0)return;let t=Te(e,A);if(!t.ok){_(`trackRequest() ignored a request with an invalid ${t.reason}`);return}t.droppedErrorCode&&_("trackRequest() dropped an errorCode outside [a-z0-9_.]{1,64}"),l.enqueue({name:Se,path:K(),properties:t.properties})})}function Me(){m(()=>{if(!v(globalThis))return;j=!0;let e=O();e.write(T,"1"),e.remove(h),Vt()})}function He(){return Oe(()=>v(globalThis)?R(Ne()):"on","on")}function Ce(){m(()=>{v(globalThis)&&(j=!1,O().remove(T),w!==void 0&&l===void 0&&Ie(w))})}Object.assign(globalThis,{pyxis:{init:Ue,track:Be,identify:Ve,reset:De,trackRequest:Le,optOut:Me,optIn:Ce,trackingStatus:He}});})();
2
2
  //# sourceMappingURL=pyxis.global.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 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", "../src/global.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' | 'stop';\n\nconst UNAUTHORIZED = 401;\nconst FORBIDDEN = 403;\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 if (status === UNAUTHORIZED || status === FORBIDDEN) {\n return 'stop';\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 const seconds = Number(header.trim());\n return Number.isSafeInteger(seconds) ? seconds : undefined;\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}$/;\nconst PROTOTYPE_KEY = '__proto__';\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 isPropertyKey(key: string): boolean {\n return PROPERTY_KEY_PATTERN.test(key) && key !== PROTOTYPE_KEY;\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 (!isPropertyKey(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 cutToWholeSegments(path: string, maxLength: number): string {\n if (path.length <= maxLength) {\n return path;\n }\n const lastFittingSlash = path.lastIndexOf('/', maxLength);\n return lastFittingSlash > 0\n ? withoutTrailingSlashes(path.slice(0, lastFittingSlash))\n : `/${ID_PLACEHOLDER}`;\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 cutToWholeSegments(templated, MAX_PATH_LENGTH);\n}\n", "import type { PropertyValue } from './batch.js';\nimport { cutToWholeSegments, 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 cutToWholeSegments(\n templatePath(new URL(url, URL_BASE).pathname, rules),\n MAX_ROUTE_LENGTH,\n );\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 readonly warn?: (message: string) => void;\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' };\nexport const REFUSED_WARNING = 'the API refused the batch; nothing more is sent from this page';\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 dispose = (): void => {\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 const scheduleRetry = (\n events: readonly BatchEvent[],\n attempt: number,\n outcome: SendOutcome,\n ): void => {\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 handleOutcome = (\n events: readonly BatchEvent[],\n attempt: number,\n outcome: SendOutcome,\n ): void => {\n if (disposed) {\n return;\n }\n const verdict = judgeOutcome(outcome);\n if (verdict === 'stop') {\n deps.warn?.(REFUSED_WARNING);\n dispose();\n return;\n }\n if (verdict === 'retry') {\n scheduleRetry(events, attempt, outcome);\n }\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 handleOutcome(events, attempt, outcome);\n },\n () => {\n handleOutcome(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 };\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, {\n ...createBrowserDependencies(),\n warn: debugWarn,\n });\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", "import {\n identify,\n init,\n optIn,\n optOut,\n reset,\n track,\n trackingStatus,\n trackRequest,\n} from './index.js';\n\nObject.assign(globalThis, {\n pyxis: { init, track, identify, reset, trackRequest, optOut, optIn, trackingStatus },\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", "UNAUTHORIZED", "FORBIDDEN", "TOO_MANY_REQUESTS", "judgeOutcome", "outcome", "status", "retryDelay", "attempt", "random", "retryAfterSeconds", "base", "jittered", "parseRetryAfter", "header", "seconds", "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", "PROTOTYPE_KEY", "checkEventName", "name", "isValidUserId", "userId", "isPropertyKey", "key", "isPropertyValue", "value", "sanitizeProperties", "input", "kept", "dropped", "entries", "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", "cutToWholeSegments", "maxLength", "lastFittingSlash", "templatePath", "rules", "candidate", "templated", "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", "cutToWholeSegments", "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", "REFUSED_WARNING", "createTracker", "options", "deps", "queue", "flushTimer", "retryTimers", "disposed", "touchCurrentSession", "claimsEntry", "stored", "parseSession", "session", "touchSession", "isEntry", "updated", "recordEntry", "serializeSession", "tryNotifyBatch", "batch", "error", "dispose", "timer", "scheduleRetry", "events", "attempt", "outcome", "retryAfter", "delay", "retryDelay", "send", "handleOutcome", "verdict", "judgeOutcome", "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", "init", "track", "identify", "reset", "trackRequest", "optOut", "optIn", "trackingStatus"]
3
+ "sources": ["../src/adapters/ids.ts", "../src/adapters/storage.ts", "../src/core/retry-policy.ts", "../src/core/visitor-kind.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", "../src/global.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", "import type { PeriodAnswer } from './visitor-kind.js';\n\nexport const RETRY_DELAYS_MS: readonly number[] = [1000, 2000, 4000, 8000, 16000];\nexport const RETRY_JITTER = 0.2;\n\nexport type SendOutcome =\n | {\n readonly kind: 'response';\n readonly status: number;\n readonly retryAfterSeconds?: number;\n readonly period?: PeriodAnswer;\n }\n | { readonly kind: 'network-error' }\n | { readonly kind: 'handed-off' };\n\nexport type SendVerdict = 'done' | 'retry' | 'drop' | 'stop';\n\nconst UNAUTHORIZED = 401;\nconst FORBIDDEN = 403;\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 if (status === UNAUTHORIZED || status === FORBIDDEN) {\n return 'stop';\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 const seconds = Number(header.trim());\n return Number.isSafeInteger(seconds) ? seconds : undefined;\n}\n", "export const PERIOD_KEY = 'pyxis:period';\n\nexport type VisitorKind = 'first_visit' | 'first_this_month' | 'first_today' | 'again_today';\n\nexport interface VisitorPeriod {\n readonly day_ends_at: string;\n readonly month_ends_at: string;\n}\n\nexport type PeriodAnswer = VisitorPeriod | 'off';\n\nconst UTC_INSTANT = /^\\d{4}-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d(\\.\\d{3})?Z$/;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction parseJson(text: string): unknown {\n try {\n return JSON.parse(text);\n } catch {\n return undefined;\n }\n}\n\nfunction instantOf(text: string): number {\n return UTC_INSTANT.test(text) ? Date.parse(text) : Number.NaN;\n}\n\nexport function parseVisitorPeriod(value: unknown): VisitorPeriod | undefined {\n if (!isRecord(value)) {\n return undefined;\n }\n const { day_ends_at: dayEndsAt, month_ends_at: monthEndsAt } = value;\n if (typeof dayEndsAt !== 'string' || typeof monthEndsAt !== 'string') {\n return undefined;\n }\n return instantOf(dayEndsAt) <= instantOf(monthEndsAt)\n ? { day_ends_at: dayEndsAt, month_ends_at: monthEndsAt }\n : undefined;\n}\n\nexport function parseStoredPeriod(raw: string | null): VisitorPeriod | undefined {\n return raw === null ? undefined : parseVisitorPeriod(parseJson(raw));\n}\n\nexport function serializePeriod(period: VisitorPeriod): string {\n return JSON.stringify({ day_ends_at: period.day_ends_at, month_ends_at: period.month_ends_at });\n}\n\nexport function periodAnswerOf(body: string): PeriodAnswer | undefined {\n const answer = parseJson(body);\n if (!isRecord(answer) || typeof answer.accepted !== 'number') {\n return undefined;\n }\n return answer.visitor_period === undefined ? 'off' : parseVisitorPeriod(answer.visitor_period);\n}\n\nexport function visitorKindOf(period: VisitorPeriod | undefined, now: number): VisitorKind {\n if (period === undefined) {\n return 'first_visit';\n }\n if (now >= Date.parse(period.month_ends_at)) {\n return 'first_this_month';\n }\n return now >= Date.parse(period.day_ends_at) ? 'first_today' : 'again_today';\n}\n", "import { parseRetryAfter, type SendOutcome } from '../core/retry-policy.js';\nimport { periodAnswerOf } from '../core/visitor-kind.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 const period = response.ok ? periodAnswerOf(await response.text().catch(() => '')) : undefined;\n return {\n kind: 'response',\n status: response.status,\n ...(retryAfterSeconds === undefined ? {} : { retryAfterSeconds }),\n ...(period === undefined ? {} : { period }),\n };\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 periodStore: webStore(() => window.localStorage),\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}$/;\nconst PROTOTYPE_KEY = '__proto__';\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 isPropertyKey(key: string): boolean {\n return PROPERTY_KEY_PATTERN.test(key) && key !== PROTOTYPE_KEY;\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 (!isPropertyKey(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 cutToWholeSegments(path: string, maxLength: number): string {\n if (path.length <= maxLength) {\n return path;\n }\n const lastFittingSlash = path.lastIndexOf('/', maxLength);\n return lastFittingSlash > 0\n ? withoutTrailingSlashes(path.slice(0, lastFittingSlash))\n : `/${ID_PLACEHOLDER}`;\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 cutToWholeSegments(templated, MAX_PATH_LENGTH);\n}\n", "import type { PropertyValue } from './batch.js';\nimport { cutToWholeSegments, 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 cutToWholeSegments(\n templatePath(new URL(url, URL_BASE).pathname, rules),\n MAX_ROUTE_LENGTH,\n );\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", "import type { VisitorKind } from './visitor-kind.js';\n\nexport 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 visitor?: VisitorKind;\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';\nimport {\n parseStoredPeriod,\n PERIOD_KEY,\n serializePeriod,\n type VisitorKind,\n visitorKindOf,\n} from './core/visitor-kind.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 periodStore: KeyValueStore;\n readonly transport: Transport;\n readonly warn?: (message: string) => void;\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' };\nexport const REFUSED_WARNING = 'the API refused the batch; nothing more is sent from this page';\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 visitorKind = (): VisitorKind =>\n visitorKindOf(parseStoredPeriod(deps.periodStore.read(PERIOD_KEY)), deps.now());\n\n const keepPeriod = (outcome: SendOutcome): void => {\n const period = outcome.kind === 'response' ? outcome.period : undefined;\n if (period === 'off') {\n deps.periodStore.remove(PERIOD_KEY);\n } else if (period !== undefined) {\n deps.periodStore.write(PERIOD_KEY, serializePeriod(period));\n }\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 dispose = (): void => {\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 const scheduleRetry = (\n events: readonly BatchEvent[],\n attempt: number,\n outcome: SendOutcome,\n ): void => {\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 handleOutcome = (\n events: readonly BatchEvent[],\n attempt: number,\n outcome: SendOutcome,\n ): void => {\n if (disposed) {\n return;\n }\n keepPeriod(outcome);\n const verdict = judgeOutcome(outcome);\n if (verdict === 'stop') {\n deps.warn?.(REFUSED_WARNING);\n dispose();\n return;\n }\n if (verdict === 'retry') {\n scheduleRetry(events, attempt, outcome);\n }\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 handleOutcome(events, attempt, outcome);\n },\n () => {\n handleOutcome(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, visitor: visitorKind() } : {}),\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 };\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 { PERIOD_KEY } from './core/visitor-kind.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 (trackingStatusOf(signals) !== 'on') {\n localStore().remove(PERIOD_KEY);\n }\n if (!isTrackingAllowed(signals)) {\n return;\n }\n const current = createTracker(resolution.options, {\n ...createBrowserDependencies(),\n warn: debugWarn,\n });\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 const store = localStore();\n store.write(OPT_OUT_KEY, OPT_OUT_VALUE);\n store.remove(PERIOD_KEY);\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", "import {\n identify,\n init,\n optIn,\n optOut,\n reset,\n track,\n trackingStatus,\n trackRequest,\n} from './index.js';\n\nObject.assign(globalThis, {\n pyxis: { init, track, identify, reset, trackRequest, optOut, optIn, trackingStatus },\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", "UNAUTHORIZED", "FORBIDDEN", "TOO_MANY_REQUESTS", "judgeOutcome", "outcome", "status", "retryDelay", "attempt", "random", "retryAfterSeconds", "base", "jittered", "parseRetryAfter", "header", "seconds", "PERIOD_KEY", "UTC_INSTANT", "isRecord", "value", "parseJson", "text", "instantOf", "parseVisitorPeriod", "dayEndsAt", "monthEndsAt", "parseStoredPeriod", "raw", "serializePeriod", "period", "periodAnswerOf", "body", "answer", "visitorKindOf", "now", "BODY_CONTENT_TYPE", "browserTransport", "fetchImpl", "beacon", "viaBeacon", "url", "body", "viaFetch", "response", "retryAfterSeconds", "parseRetryAfter", "period", "periodAnswerOf", "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", "PROTOTYPE_KEY", "checkEventName", "name", "isValidUserId", "userId", "isPropertyKey", "key", "isPropertyValue", "value", "sanitizeProperties", "input", "kept", "dropped", "entries", "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", "cutToWholeSegments", "maxLength", "lastFittingSlash", "templatePath", "rules", "candidate", "templated", "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", "cutToWholeSegments", "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", "REFUSED_WARNING", "createTracker", "options", "deps", "queue", "flushTimer", "retryTimers", "disposed", "touchCurrentSession", "claimsEntry", "stored", "parseSession", "session", "touchSession", "isEntry", "updated", "recordEntry", "serializeSession", "visitorKind", "visitorKindOf", "parseStoredPeriod", "PERIOD_KEY", "keepPeriod", "outcome", "period", "serializePeriod", "tryNotifyBatch", "batch", "error", "dispose", "timer", "scheduleRetry", "events", "attempt", "retryAfter", "delay", "retryDelay", "send", "handleOutcome", "verdict", "judgeOutcome", "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", "trackingStatusOf", "PERIOD_KEY", "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", "store", "OPT_OUT_KEY", "trackingStatus", "optIn", "init", "track", "identify", "reset", "trackRequest", "optOut", "optIn", "trackingStatus"]
7
7
  }
package/dist/tracker.d.ts CHANGED
@@ -8,6 +8,7 @@ export interface TrackerDependencies {
8
8
  readonly createId: () => string;
9
9
  readonly random: () => number;
10
10
  readonly sessionStore: KeyValueStore;
11
+ readonly periodStore: KeyValueStore;
11
12
  readonly transport: Transport;
12
13
  readonly warn?: (message: string) => void;
13
14
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pyxis-analytics",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Privacy-first product analytics tracker for the browser: no cookies, no personal data, zero dependencies.",
5
5
  "keywords": [
6
6
  "analytics",