poulet 0.0.6 → 0.1.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 +270 -4
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +117 -0
- package/dist/index.d.ts +117 -0
- package/dist/index.global.js +2 -0
- package/dist/index.global.js.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/react.cjs +2 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +66 -0
- package/dist/react.d.ts +66 -0
- package/dist/react.js +2 -0
- package/dist/react.js.map +1 -0
- package/package.json +51 -52
- package/LICENSE +0 -22
- package/dist/.gitkeep +0 -0
- package/dist/poulet.common.js +0 -959
- package/dist/poulet.js +0 -962
- package/dist/poulet.min.js +0 -7
- package/dist/poulet.mjs +0 -957
- package/lib/Core/Component/_copyAccessor.js +0 -3
- package/lib/Core/Component/_defineReactive.js +0 -46
- package/lib/Core/Component/_mergeMixins.js +0 -53
- package/lib/Core/Component/index.js +0 -139
- package/lib/Core/Directive/_stringParser.js +0 -61
- package/lib/Core/Directive/index.js +0 -93
- package/lib/Core/Observer.js +0 -32
- package/lib/Core/index.js +0 -140
- package/lib/Directives/Class.js +0 -26
- package/lib/Directives/Html.js +0 -7
- package/lib/Directives/Model.js +0 -57
- package/lib/Directives/On.js +0 -13
- package/lib/Directives/Show.js +0 -9
- package/lib/Directives/Style.js +0 -7
- package/lib/Directives/Text.js +0 -7
- package/lib/Directives/index.js +0 -6
- package/lib/Mixins/index.js +0 -0
- package/lib/get.js +0 -10
- package/lib/index.js +0 -6
- package/lib/set.js +0 -10
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/utils.ts","../src/activity.ts","../src/antifraud.ts","../src/consent.ts","../src/transport.ts","../src/core.ts","../src/bug.ts"],"sourcesContent":["// src/index.ts\nimport { configure, openSession, closeSession, getSessionIdSafe } from './core';\nimport { setConsent as _setConsent, initConsent, setDNTPolicy, consentFlags } from './consent';\nimport { enqueue } from './transport';\nimport type { Config, EventPayload } from './types';\nimport { now } from './utils';\nexport * from './types';\nexport { reportBug } from './bug';\n\nlet initialized = false;\n\nexport function init(cfg: Config) {\n if (initialized) return;\n setDNTPolicy(cfg.privacy?.dntRespect ?? true);\n initConsent(cfg.consent?.default ?? 'pending');\n configure(cfg);\n // ouverture paresseuse : dès qu’il y a visibilité/activité\n if (document.visibilityState === 'visible') openSession();\n document.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'visible') openSession();\n });\n // Flush/close sur pagehide\n addEventListener('pagehide', () => closeSession('pagehide'));\n initialized = true;\n}\n\nexport function setConsent(flags: { analytics?: boolean; replay?: boolean }) {\n _setConsent(flags);\n if (document.visibilityState === 'visible') openSession();\n}\n\nexport function trackEvent(name: string, props?: Record<string, unknown>) {\n const sessionId = getSessionIdSafe();\n if (!sessionId) return;\n const ev: EventPayload = {\n type: 'event',\n sessionId,\n ts: now(),\n name,\n props,\n purpose: 'diagnostics',\n };\n enqueue(ev);\n}\n\nexport function shutdown() {\n closeSession('shutdown');\n}\n\nexport function getSessionId() {\n return getSessionIdSafe();\n}\n\nexport function forgetMe() {\n // côté core : rien de persistant par défaut (queue en mémoire).\n // si tu ajoutes IndexedDB/localStorage pour queue offline, purge ici.\n // Pour l’exemple, on ne stocke pas persistantement.\n closeSession('shutdown');\n}\n\nexport const _consentFlags = consentFlags;\n","// src/utils.ts\nexport const now = () => Date.now();\n\nexport const uuid = (): string =>\n (crypto?.randomUUID?.() ?? 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (crypto.getRandomValues(new Uint8Array(1))[0] & 0xf) >> 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n }));\n\nexport const isVisible = () => typeof document !== 'undefined' && document.visibilityState === 'visible';\n\nexport const on = <K extends keyof WindowEventMap>(t: Window, type: K, fn: (e: WindowEventMap[K]) => void) => {\n t.addEventListener(type, fn as any, { passive: true });\n return () => t.removeEventListener(type, fn as any);\n};\n\nexport const onDoc = <K extends keyof DocumentEventMap>(type: K, fn: (e: DocumentEventMap[K]) => void) => {\n document.addEventListener(type, fn as any, { passive: true });\n return () => document.removeEventListener(type, fn as any);\n};\n\nexport const clamp = (n: number, min: number, max: number) => Math.max(min, Math.min(max, n));\n\nexport const jitterMs = (baseMs: number, pct = 0.1) => {\n const delta = baseMs * pct;\n return baseMs + (Math.random() * 2 - 1) * delta;\n};\n\nexport const filterPII = (o: any): any => {\n if (!o || typeof o !== 'object') return o;\n const SUSPICIOUS = ['email', 'phone', 'password', 'ssn'];\n const out: any = Array.isArray(o) ? [] : {};\n for (const k of Object.keys(o)) {\n if (SUSPICIOUS.includes(k.toLowerCase())) continue;\n const v = (o as any)[k];\n out[k] = typeof v === 'object' ? filterPII(v) : v;\n }\n return out;\n};\n\nexport const log = (...args: any[]) => {\n if ((window as any).__POULET_DEBUG__) console.log('[poulet]', ...args);\n};\n\nexport const base64ToArrayBuffer = (b64: string) => Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));\n","// src/activity.ts\nimport { isVisible, onDoc, on } from './utils';\n\nlet lastActivity = Date.now();\nlet unsub: Array<() => void> = [];\n\nexport const getLastActivity = () => lastActivity;\n\nexport const startActivityTracking = () => {\n stopActivityTracking();\n const touch = () => { lastActivity = Date.now(); };\n const un1 = onDoc('mousemove', touch);\n const un2 = onDoc('keydown', touch);\n const un3 = onDoc('scroll', touch);\n const un4 = onDoc('touchstart', touch);\n const un5 = on(window, 'focus', touch);\n const un6 = on(window, 'blur', touch);\n const un7 = onDoc('visibilitychange' as any, touch);\n unsub = [un1, un2, un3, un4, un5, un6, un7];\n};\n\nexport const stopActivityTracking = () => {\n unsub.forEach((f) => f());\n unsub = [];\n};\n\nexport const isActive = (idleSec: number) => {\n const idleMs = idleSec * 1000;\n return isVisible() && (Date.now() - lastActivity) < idleMs;\n};\n","// src/antifraud.ts\nconst LS_KEY = 'poulet_leader_session';\nlet leader = false;\n\nexport const becomeLeaderIfFree = (sessionId: string): boolean => {\n const current = localStorage.getItem(LS_KEY);\n if (!current) {\n localStorage.setItem(LS_KEY, sessionId);\n leader = true;\n return true;\n }\n leader = current === sessionId;\n return leader;\n};\n\nexport const relinquishLeadership = (sessionId: string) => {\n const current = localStorage.getItem(LS_KEY);\n if (current === sessionId) {\n localStorage.removeItem(LS_KEY);\n }\n leader = false;\n};\n\nexport const isLeader = () => leader;\n\nexport const handleStorageLeadership = (sessionId: string, onChange: (isLeader: boolean)=>void) => {\n const listener = (e: StorageEvent) => {\n if (e.key !== LS_KEY) return;\n const now = localStorage.getItem(LS_KEY);\n const newLeader = now === sessionId || !now;\n if (!now) { // try claim\n localStorage.setItem(LS_KEY, sessionId);\n onChange(true);\n leader = true;\n } else {\n leader = now === sessionId;\n onChange(leader);\n }\n };\n window.addEventListener('storage', listener);\n return () => window.removeEventListener('storage', listener);\n};\n\nexport const fingerprintLite = () => ({\n ua: navigator.userAgent,\n tz: Intl.DateTimeFormat().resolvedOptions().timeZone ?? 'UTC',\n dpr: window.devicePixelRatio || 1,\n});\n","// src/consent.ts\nimport type { ConsentState } from './types';\n\nlet analyticsAllowed = false;\nlet replayAllowed = false;\nlet state: ConsentState = 'pending';\nlet dntRespected = true;\n\nexport const setDNTPolicy = (respect: boolean) => { dntRespected = respect; };\n\nexport const initConsent = (defaultState: ConsentState) => {\n state = defaultState;\n if (dntRespected && typeof navigator !== 'undefined' && (navigator as any).doNotTrack === '1') {\n analyticsAllowed = false;\n replayAllowed = false;\n state = 'denied';\n }\n};\n\nexport const setConsent = (flags: { analytics?: boolean; replay?: boolean }) => {\n if (typeof flags.analytics === 'boolean') {\n analyticsAllowed = flags.analytics;\n state = analyticsAllowed ? 'granted' : 'denied';\n }\n if (typeof flags.replay === 'boolean') replayAllowed = flags.replay;\n};\n\nexport const consentFlags = () => ({ analytics: analyticsAllowed, replay: replayAllowed, state });\nexport const analyticsOn = () => analyticsAllowed === true;\nexport const replayOn = () => replayAllowed === true;\n","// src/transport.ts\nimport { base64ToArrayBuffer, filterPII, log } from './utils';\nimport type { OutgoingPayload } from './types';\n\ntype TransportConfig = {\n endpoint: string;\n projectKey: string;\n hmacPublicKey?: string; // base64; optional\n debug?: boolean;\n};\n\nlet cfg: TransportConfig;\nlet queue: OutgoingPayload[] = [];\nlet flushing = false;\n\nasync function sign(body: string): Promise<string | undefined> {\n if (!cfg.hmacPublicKey || !('crypto' in window)) return undefined;\n try {\n const keyData = base64ToArrayBuffer(cfg.hmacPublicKey);\n const key = await crypto.subtle.importKey('raw', keyData, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);\n const sig = await crypto.subtle.sign('HMAC', key, new TextEncoder().encode(body));\n return btoa(String.fromCharCode(...new Uint8Array(sig)));\n } catch {\n return undefined;\n }\n}\n\nasync function postBatch(items: OutgoingPayload[]) {\n const sanitized = items.map((i) => filterPII(i));\n const body = JSON.stringify({ projectKey: cfg.projectKey, items: sanitized });\n const sig = await sign(body);\n\n // Try Beacon first\n if (navigator.sendBeacon && !cfg.debug) {\n const headers = { type: 'application/json' };\n const blob = new Blob([body], headers);\n const ok = navigator.sendBeacon(cfg.endpoint + '/ingest', blob);\n if (ok) return true;\n }\n\n // Fallback fetch\n const res = await fetch(cfg.endpoint + '/ingest', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...(sig ? { 'x-signature': sig } : {}) },\n body\n });\n return res.ok;\n}\n\nexport function initTransport(config: TransportConfig) {\n cfg = config;\n window.addEventListener('online', flush);\n setInterval(flush, 5000);\n}\n\nexport function enqueue(payload: OutgoingPayload) {\n queue.push(payload);\n if (queue.length >= 10) void flush();\n}\n\nexport async function flush() {\n if (flushing || queue.length === 0) return;\n flushing = true;\n try {\n const batch = queue.splice(0, 20);\n const ok = await postBatch(batch);\n if (!ok) {\n // put back\n queue.unshift(...batch);\n log('flush failed, will retry');\n }\n } catch (e) {\n log('flush error', e);\n } finally {\n flushing = false;\n }\n}\n","// src/core.ts\nimport { jitterMs, log, now } from './utils';\nimport { startActivityTracking, stopActivityTracking, isActive, getLastActivity } from './activity';\nimport { becomeLeaderIfFree, handleStorageLeadership, relinquishLeadership, isLeader, fingerprintLite } from './antifraud';\nimport { analyticsOn, consentFlags } from './consent';\nimport { initTransport, enqueue, flush } from './transport';\nimport type { Config, SessionState, HeartbeatPayload, SessionStart, SessionEnd } from './types';\n\nlet config: Required<Config>;\nlet session: SessionState | null = null;\nlet hbTimer: number | null = null;\nlet unStorage: (() => void) | undefined;\n\nconst DEFAULTS: Required<Config> = {\n projectKey: '',\n endpoint: '',\n consent: { default: 'pending' },\n user: {},\n billing: { heartbeatSec: 15, idleSec: 60, maxHoursPerDay: 6 },\n privacy: { piiFilter: true, dntRespect: true, countryHint: 'FR' },\n security: { hmacPublicKey: undefined as any },\n features: { bugReporter: true, replay: false, sentryBridge: false },\n sampling: { heartbeats: 1, events: 1, bugs: 1 },\n debug: false,\n};\n\nexport function configure(cfg: Config) {\n config = { ...DEFAULTS, ...cfg, consent: { ...DEFAULTS.consent, ...cfg.consent } } as Required<Config>;\n (window as any).__POULET_DEBUG__ = !!config.debug;\n initTransport({\n endpoint: config.endpoint,\n projectKey: config.projectKey,\n hmacPublicKey: config.security.hmacPublicKey,\n debug: config.debug,\n });\n}\n\nexport function openSession() {\n if (session) return;\n const id = crypto.randomUUID();\n const fp = fingerprintLite();\n session = {\n sessionId: id,\n startedAt: now(),\n lastActivityAt: now(),\n active: true,\n leader: becomeLeaderIfFree(id),\n };\n if (unStorage) unStorage();\n unStorage = handleStorageLeadership(id, (lead) => {\n if (session) session.leader = lead;\n });\n\n startActivityTracking();\n\n const startPayload: SessionStart = {\n type: 'session.start',\n sessionId: id,\n ts: now(),\n projectKey: config.projectKey,\n ua: fp.ua,\n tz: fp.tz,\n dpr: fp.dpr,\n consentFlags: { analytics: analyticsOn(), replay: false },\n };\n enqueue(startPayload);\n scheduleHeartbeats();\n log('session opened', id);\n}\n\nexport function closeSession(reason: SessionEnd['reason']) {\n if (!session) return;\n stopHeartbeats();\n stopActivityTracking();\n relinquishLeadership(session.sessionId);\n const endPayload: SessionEnd = { type: 'session.end', sessionId: session.sessionId, ts: now(), reason };\n enqueue(endPayload);\n void flush();\n if (unStorage) unStorage();\n session = null;\n log('session closed', reason);\n}\n\nfunction scheduleHeartbeats() {\n stopHeartbeats();\n const loop = () => {\n if (!session) return;\n if (!analyticsOn()) return; // consent required\n // @ts-ignore\n const idle = (now() - getLastActivity()) >= config.billing.idleSec * 1000;\n const vis = document.visibilityState === 'visible';\n const active = vis && !idle && session.leader;\n const fp = fingerprintLite();\n\n // @ts-ignore\n if (Math.random() <= config.sampling.heartbeats && active) {\n const hb: HeartbeatPayload = {\n type: 'heartbeat',\n sessionId: session.sessionId,\n ts: now(),\n active: true,\n vis,\n idle: false,\n jitter: Math.random(),\n ua: fp.ua,\n tz: fp.tz,\n dpr: fp.dpr,\n purpose: 'billing',\n };\n enqueue(hb);\n }\n\n // @ts-ignore\n const next = jitterMs(config.billing.heartbeatSec * 1000, 0.1);\n hbTimer = window.setTimeout(loop, next);\n };\n // @ts-ignore\n hbTimer = window.setTimeout(loop, jitterMs(config.billing.heartbeatSec * 1000, 0.1));\n}\n\nfunction stopHeartbeats() {\n if (hbTimer) {\n clearTimeout(hbTimer);\n hbTimer = null;\n }\n}\n\nexport const getSessionIdSafe = () => session?.sessionId ?? null;\n","// src/bug.ts\nimport { enqueue } from './transport';\nimport type { BugPayload } from './types';\nimport { now } from './utils';\nimport { getSessionIdSafe } from './core';\n\nexport function reportBug(payload: {\n title: string; description?: string;\n severity?: 'blocker'|'major'|'minor'|'ux';\n attachments?: Blob[];\n}) {\n const sessionId = getSessionIdSafe();\n if (!sessionId) return;\n const p: BugPayload = {\n type: 'bug',\n sessionId,\n ts: now(),\n title: payload.title,\n description: payload.description,\n severity: payload.severity,\n hasCapture: !!(payload.attachments && payload.attachments.length > 0),\n purpose: 'diagnostics'\n };\n enqueue(p);\n // NOTE: upload des pièces jointes = hors scope core (peut passer par un autre endpoint)\n}\n"],"mappings":"2cAAA,IAAAA,GAAA,GAAAC,GAAAD,GAAA,mBAAAE,GAAA,aAAAC,GAAA,iBAAAC,GAAA,SAAAC,GAAA,cAAAC,EAAA,eAAAC,GAAA,aAAAC,GAAA,eAAAC,KCCO,IAAMC,EAAM,IAAM,KAAK,IAAI,EAW3B,IAAMC,EAAK,CAAiCC,EAAWC,EAASC,KACnEF,EAAE,iBAAiBC,EAAMC,EAAW,CAAE,QAAS,EAAK,CAAC,EAC9C,IAAMF,EAAE,oBAAoBC,EAAMC,CAAS,GAGzCC,EAAQ,CAAmCF,EAASC,KAC7D,SAAS,iBAAiBD,EAAMC,EAAW,CAAE,QAAS,EAAK,CAAC,EACrD,IAAM,SAAS,oBAAoBD,EAAMC,CAAS,GAKtD,IAAME,EAAW,CAACC,EAAgBC,EAAM,KAAQ,CACnD,IAAMC,EAAQF,EAASC,EACvB,OAAOD,GAAU,KAAK,OAAO,EAAI,EAAI,GAAKE,CAC9C,EAEaC,EAAaC,GAAgB,CACtC,GAAI,CAACA,GAAK,OAAOA,GAAM,SAAU,OAAOA,EACxC,IAAMC,EAAa,CAAC,QAAS,QAAS,WAAY,KAAK,EACjDC,EAAW,MAAM,QAAQF,CAAC,EAAI,CAAC,EAAI,CAAC,EAC1C,QAAWG,KAAK,OAAO,KAAKH,CAAC,EAAG,CAC5B,GAAIC,EAAW,SAASE,EAAE,YAAY,CAAC,EAAG,SAC1C,IAAMC,EAAKJ,EAAUG,CAAC,EACtBD,EAAIC,CAAC,EAAI,OAAOC,GAAM,SAAWL,EAAUK,CAAC,EAAIA,CACpD,CACA,OAAOF,CACX,EAEaG,EAAM,IAAIC,IAAgB,CAC9B,OAAe,kBAAkB,QAAQ,IAAI,WAAY,GAAGA,CAAI,CACzE,EAEaC,EAAuBC,GAAgB,WAAW,KAAK,KAAKA,CAAG,EAAIC,GAAMA,EAAE,WAAW,CAAC,CAAC,EC1CrG,IAAIC,EAAe,KAAK,IAAI,EACxBC,EAA2B,CAAC,EAEnBC,EAAkB,IAAMF,EAExBG,EAAwB,IAAM,CACvCC,EAAqB,EACrB,IAAMC,EAAQ,IAAM,CAAEL,EAAe,KAAK,IAAI,CAAG,EAC3CM,EAAMC,EAAM,YAAaF,CAAK,EAC9BG,EAAMD,EAAM,UAAWF,CAAK,EAC5BI,EAAMF,EAAM,SAAUF,CAAK,EAC3BK,EAAMH,EAAM,aAAcF,CAAK,EAC/BM,EAAMC,EAAG,OAAQ,QAASP,CAAK,EAC/BQ,EAAMD,EAAG,OAAQ,OAAQP,CAAK,EAC9BS,EAAMP,EAAM,mBAA2BF,CAAK,EAClDJ,EAAQ,CAACK,EAAKE,EAAKC,EAAKC,EAAKC,EAAKE,EAAKC,CAAG,CAC9C,EAEaV,EAAuB,IAAM,CACtCH,EAAM,QAASc,GAAMA,EAAE,CAAC,EACxBd,EAAQ,CAAC,CACb,ECvBA,IAAMe,EAAS,wBACXC,EAAS,GAEAC,EAAsBC,GAA+B,CAC9D,IAAMC,EAAU,aAAa,QAAQJ,CAAM,EAC3C,OAAKI,GAKLH,EAASG,IAAYD,EACdF,IALH,aAAa,QAAQD,EAAQG,CAAS,EACtCF,EAAS,GACF,GAIf,EAEaI,EAAwBF,GAAsB,CACvC,aAAa,QAAQH,CAAM,IAC3BG,GACZ,aAAa,WAAWH,CAAM,EAElCC,EAAS,EACb,EAIO,IAAMK,EAA0B,CAACC,EAAmBC,IAAwC,CAC/F,IAAMC,EAAYC,GAAoB,CAClC,GAAIA,EAAE,MAAQC,EAAQ,OACtB,IAAMC,EAAM,aAAa,QAAQD,CAAM,EACjCE,EAAYD,IAAQL,GAAa,CAACK,EACnCA,GAKDE,EAASF,IAAQL,EACjBC,EAASM,CAAM,IALf,aAAa,QAAQH,EAAQJ,CAAS,EACtCC,EAAS,EAAI,EACbM,EAAS,GAKjB,EACA,cAAO,iBAAiB,UAAWL,CAAQ,EACpC,IAAM,OAAO,oBAAoB,UAAWA,CAAQ,CAC/D,EAEaM,EAAkB,IAAG,CA3ClC,IAAAC,EA2CsC,OAClC,GAAI,UAAU,UACd,IAAIA,EAAA,KAAK,eAAe,EAAE,gBAAgB,EAAE,WAAxC,KAAAA,EAAoD,MACxD,IAAK,OAAO,kBAAoB,CACpC,GC5CA,IAAIC,EAAmB,GACnBC,EAAgB,GAChBC,EAAsB,UACtBC,EAAe,GAENC,EAAgBC,GAAqB,CAAEF,EAAeE,CAAS,EAE/DC,EAAeC,GAA+B,CACvDL,EAAQK,EACJJ,GAAgB,OAAO,WAAc,aAAgB,UAAkB,aAAe,MACtFH,EAAmB,GACnBC,EAAgB,GAChBC,EAAQ,SAEhB,EAEaM,EAAcC,GAAqD,CACxE,OAAOA,EAAM,WAAc,YAC3BT,EAAmBS,EAAM,UACzBP,EAAQF,EAAmB,UAAY,UAEvC,OAAOS,EAAM,QAAW,YAAWR,EAAgBQ,EAAM,OACjE,EAEaC,EAAe,KAAO,CAAE,UAAWV,EAAkB,OAAQC,EAAe,MAAAC,CAAM,GAClFS,EAAc,IAAMX,IAAqB,GCjBtD,IAAIY,EACAC,EAA2B,CAAC,EAC5BC,EAAW,GAEf,eAAeC,GAAKC,EAA2C,CAC3D,GAAI,GAACJ,EAAI,eAAiB,EAAE,WAAY,SACxC,GAAI,CACA,IAAMK,EAAUC,EAAoBN,EAAI,aAAa,EAC/CO,EAAM,MAAM,OAAO,OAAO,UAAU,MAAOF,EAAS,CAAE,KAAM,OAAQ,KAAM,SAAU,EAAG,GAAO,CAAC,MAAM,CAAC,EACtGG,EAAM,MAAM,OAAO,OAAO,KAAK,OAAQD,EAAK,IAAI,YAAY,EAAE,OAAOH,CAAI,CAAC,EAChF,OAAO,KAAK,OAAO,aAAa,GAAG,IAAI,WAAWI,CAAG,CAAC,CAAC,CAC3D,OAAQC,EAAA,CACJ,MACJ,CACJ,CAEA,eAAeC,GAAUC,EAA0B,CAC/C,IAAMC,EAAYD,EAAM,IAAKE,GAAMC,EAAUD,CAAC,CAAC,EACzCT,EAAO,KAAK,UAAU,CAAE,WAAYJ,EAAI,WAAY,MAAOY,CAAU,CAAC,EACtEJ,EAAM,MAAML,GAAKC,CAAI,EAG3B,GAAI,UAAU,YAAc,CAACJ,EAAI,MAAO,CACpC,IAAMe,EAAU,CAAE,KAAM,kBAAmB,EACrCC,EAAO,IAAI,KAAK,CAACZ,CAAI,EAAGW,CAAO,EAErC,GADW,UAAU,WAAWf,EAAI,SAAW,UAAWgB,CAAI,EACtD,MAAO,EACnB,CAQA,OALY,MAAM,MAAMhB,EAAI,SAAW,UAAW,CAC9C,OAAQ,OACR,QAAS,CAAE,eAAgB,mBAAoB,GAAIQ,EAAM,CAAE,cAAeA,CAAI,EAAI,CAAC,CAAG,EACtF,KAAAJ,CACJ,CAAC,GACU,EACf,CAEO,SAASa,EAAcC,EAAyB,CACnDlB,EAAMkB,EACN,OAAO,iBAAiB,SAAUC,CAAK,EACvC,YAAYA,EAAO,GAAI,CAC3B,CAEO,SAASC,EAAQC,EAA0B,CAC9CpB,EAAM,KAAKoB,CAAO,EACdpB,EAAM,QAAU,IAASkB,EAAM,CACvC,CAEA,eAAsBA,GAAQ,CAC1B,GAAI,EAAAjB,GAAYD,EAAM,SAAW,GACjC,CAAAC,EAAW,GACX,GAAI,CACA,IAAMoB,EAAQrB,EAAM,OAAO,EAAG,EAAE,EACrB,MAAMS,GAAUY,CAAK,IAG5BrB,EAAM,QAAQ,GAAGqB,CAAK,EACtBC,EAAI,0BAA0B,EAEtC,OAAS,EAAG,CACRA,EAAI,cAAe,CAAC,CACxB,QAAE,CACErB,EAAW,EACf,EACJ,CCpEA,IAAIsB,EACAC,EAA+B,KAC/BC,EAAyB,KACzBC,EAEEC,EAA6B,CAC/B,WAAY,GACZ,SAAU,GACV,QAAS,CAAE,QAAS,SAAU,EAC9B,KAAM,CAAC,EACP,QAAS,CAAE,aAAc,GAAI,QAAS,GAAI,eAAgB,CAAE,EAC5D,QAAS,CAAE,UAAW,GAAM,WAAY,GAAM,YAAa,IAAK,EAChE,SAAU,CAAE,cAAe,MAAiB,EAC5C,SAAU,CAAE,YAAa,GAAM,OAAQ,GAAO,aAAc,EAAM,EAClE,SAAU,CAAE,WAAY,EAAG,OAAQ,EAAG,KAAM,CAAE,EAC9C,MAAO,EACX,EAEO,SAASC,EAAUC,EAAa,CACnCN,EAAS,CAAE,GAAGI,EAAU,GAAGE,EAAK,QAAS,CAAE,GAAGF,EAAS,QAAS,GAAGE,EAAI,OAAQ,CAAE,EAChF,OAAe,iBAAmB,CAAC,CAACN,EAAO,MAC5CO,EAAc,CACV,SAAUP,EAAO,SACjB,WAAYA,EAAO,WACnB,cAAeA,EAAO,SAAS,cAC/B,MAAOA,EAAO,KAClB,CAAC,CACL,CAEO,SAASQ,GAAc,CAC1B,GAAIP,EAAS,OACb,IAAMQ,EAAK,OAAO,WAAW,EACvBC,EAAKC,EAAgB,EAC3BV,EAAU,CACN,UAAWQ,EACX,UAAWG,EAAI,EACf,eAAgBA,EAAI,EACpB,OAAQ,GACR,OAAQC,EAAmBJ,CAAE,CACjC,EACIN,GAAWA,EAAU,EACzBA,EAAYW,EAAwBL,EAAKM,GAAS,CAC1Cd,IAASA,EAAQ,OAASc,EAClC,CAAC,EAEDC,EAAsB,EAEtB,IAAMC,EAA6B,CAC/B,KAAM,gBACN,UAAWR,EACX,GAAIG,EAAI,EACR,WAAYZ,EAAO,WACnB,GAAIU,EAAG,GACP,GAAIA,EAAG,GACP,IAAKA,EAAG,IACR,aAAc,CAAE,UAAWQ,EAAY,EAAG,OAAQ,EAAM,CAC5D,EACAC,EAAQF,CAAY,EACpBG,GAAmB,EACnBC,EAAI,iBAAkBZ,CAAE,CAC5B,CAEO,SAASa,EAAaC,EAA8B,CACvD,GAAI,CAACtB,EAAS,OACduB,EAAe,EACfC,EAAqB,EACrBC,EAAqBzB,EAAQ,SAAS,EACtC,IAAM0B,EAAyB,CAAE,KAAM,cAAe,UAAW1B,EAAQ,UAAW,GAAIW,EAAI,EAAG,OAAAW,CAAO,EACtGJ,EAAQQ,CAAU,EACbC,EAAM,EACPzB,GAAWA,EAAU,EACzBF,EAAU,KACVoB,EAAI,iBAAkBE,CAAM,CAChC,CAEA,SAASH,IAAqB,CAC1BI,EAAe,EACf,IAAMK,EAAO,IAAM,CAEf,GADI,CAAC5B,GACD,CAACiB,EAAY,EAAG,OAEpB,IAAMY,EAAQlB,EAAI,EAAImB,EAAgB,GAAM/B,EAAO,QAAQ,QAAU,IAC/DgC,EAAM,SAAS,kBAAoB,UACnCC,EAASD,GAAO,CAACF,GAAQ7B,EAAQ,OACjCS,EAAKC,EAAgB,EAG3B,GAAI,KAAK,OAAO,GAAKX,EAAO,SAAS,YAAciC,EAAQ,CACvD,IAAMC,EAAuB,CACzB,KAAM,YACN,UAAWjC,EAAQ,UACnB,GAAIW,EAAI,EACR,OAAQ,GACR,IAAAoB,EACA,KAAM,GACN,OAAQ,KAAK,OAAO,EACpB,GAAItB,EAAG,GACP,GAAIA,EAAG,GACP,IAAKA,EAAG,IACR,QAAS,SACb,EACAS,EAAQe,CAAE,CACd,CAGA,IAAMC,EAAOC,EAASpC,EAAO,QAAQ,aAAe,IAAM,EAAG,EAC7DE,EAAU,OAAO,WAAW2B,EAAMM,CAAI,CAC1C,EAEAjC,EAAU,OAAO,WAAW2B,EAAMO,EAASpC,EAAO,QAAQ,aAAe,IAAM,EAAG,CAAC,CACvF,CAEA,SAASwB,GAAiB,CAClBtB,IACA,aAAaA,CAAO,EACpBA,EAAU,KAElB,CAEO,IAAMmC,EAAmB,IAAG,CA/HnC,IAAAC,EA+HsC,OAAAA,EAAArC,GAAA,YAAAA,EAAS,YAAT,KAAAqC,EAAsB,MCzHrD,SAASC,EAAUC,EAIvB,CACC,IAAMC,EAAYC,EAAiB,EACnC,GAAI,CAACD,EAAW,OAChB,IAAME,EAAgB,CAClB,KAAM,MACN,UAAAF,EACA,GAAIG,EAAI,EACR,MAAOJ,EAAQ,MACf,YAAaA,EAAQ,YACrB,SAAUA,EAAQ,SAClB,WAAY,CAAC,EAAEA,EAAQ,aAAeA,EAAQ,YAAY,OAAS,GACnE,QAAS,aACb,EACAK,EAAQF,CAAC,CAEb,CPhBA,IAAIG,EAAc,GAEX,SAASC,GAAKC,EAAa,CAXlC,IAAAC,EAAAC,EAAAC,EAAAC,EAYQN,IACJO,GAAaH,GAAAD,EAAAD,EAAI,UAAJ,YAAAC,EAAa,aAAb,KAAAC,EAA2B,EAAI,EAC5CI,GAAYF,GAAAD,EAAAH,EAAI,UAAJ,YAAAG,EAAa,UAAb,KAAAC,EAAwB,SAAS,EAC7CG,EAAUP,CAAG,EAET,SAAS,kBAAoB,WAAWQ,EAAY,EACxD,SAAS,iBAAiB,mBAAoB,IAAM,CAC5C,SAAS,kBAAoB,WAAWA,EAAY,CAC5D,CAAC,EAED,iBAAiB,WAAY,IAAMC,EAAa,UAAU,CAAC,EAC3DX,EAAc,GAClB,CAEO,SAASY,GAAWC,EAAkD,CACzED,EAAYC,CAAK,EACb,SAAS,kBAAoB,WAAWH,EAAY,CAC5D,CAEO,SAASI,GAAWC,EAAcC,EAAiC,CACtE,IAAMC,EAAYC,EAAiB,EACnC,GAAI,CAACD,EAAW,OAChB,IAAME,EAAmB,CACrB,KAAM,QACN,UAAAF,EACA,GAAIG,EAAI,EACR,KAAAL,EACA,MAAAC,EACA,QAAS,aACb,EACAK,EAAQF,CAAE,CACd,CAEO,SAASG,IAAW,CACvBX,EAAa,UAAU,CAC3B,CAEO,SAASY,IAAe,CAC3B,OAAOL,EAAiB,CAC5B,CAEO,SAASM,IAAW,CAIvBb,EAAa,UAAU,CAC3B,CAEO,IAAMc,GAAgBC","names":["src_exports","__export","_consentFlags","forgetMe","getSessionId","init","reportBug","setConsent","shutdown","trackEvent","now","on","t","type","fn","onDoc","jitterMs","baseMs","pct","delta","filterPII","o","SUSPICIOUS","out","k","v","log","args","base64ToArrayBuffer","b64","c","lastActivity","unsub","getLastActivity","startActivityTracking","stopActivityTracking","touch","un1","onDoc","un2","un3","un4","un5","on","un6","un7","f","LS_KEY","leader","becomeLeaderIfFree","sessionId","current","relinquishLeadership","handleStorageLeadership","sessionId","onChange","listener","e","LS_KEY","now","newLeader","leader","fingerprintLite","_a","analyticsAllowed","replayAllowed","state","dntRespected","setDNTPolicy","respect","initConsent","defaultState","setConsent","flags","consentFlags","analyticsOn","cfg","queue","flushing","sign","body","keyData","base64ToArrayBuffer","key","sig","e","postBatch","items","sanitized","i","filterPII","headers","blob","initTransport","config","flush","enqueue","payload","batch","log","config","session","hbTimer","unStorage","DEFAULTS","configure","cfg","initTransport","openSession","id","fp","fingerprintLite","now","becomeLeaderIfFree","handleStorageLeadership","lead","startActivityTracking","startPayload","analyticsOn","enqueue","scheduleHeartbeats","log","closeSession","reason","stopHeartbeats","stopActivityTracking","relinquishLeadership","endPayload","flush","loop","idle","getLastActivity","vis","active","hb","next","jitterMs","getSessionIdSafe","_a","reportBug","payload","sessionId","getSessionIdSafe","p","now","enqueue","initialized","init","cfg","_a","_b","_c","_d","setDNTPolicy","initConsent","configure","openSession","closeSession","setConsent","flags","trackEvent","name","props","sessionId","getSessionIdSafe","ev","now","enqueue","shutdown","getSessionId","forgetMe","_consentFlags","consentFlags"]}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var s=()=>Date.now();var A=(e,t,n)=>(e.addEventListener(t,n,{passive:!0}),()=>e.removeEventListener(t,n)),f=(e,t)=>(document.addEventListener(e,t,{passive:!0}),()=>document.removeEventListener(e,t));var C=(e,t=.1)=>{let n=e*t;return e+(Math.random()*2-1)*n},E=e=>{if(!e||typeof e!="object")return e;let t=["email","phone","password","ssn"],n=Array.isArray(e)?[]:{};for(let o of Object.keys(e)){if(t.includes(o.toLowerCase()))continue;let i=e[o];n[o]=typeof i=="object"?E(i):i}return n},y=(...e)=>{window.__POULET_DEBUG__&&console.log("[poulet]",...e)},_=e=>Uint8Array.from(atob(e),t=>t.charCodeAt(0));var B=Date.now(),L=[],M=()=>B,O=()=>{T();let e=()=>{B=Date.now()},t=f("mousemove",e),n=f("keydown",e),o=f("scroll",e),i=f("touchstart",e),c=A(window,"focus",e),g=A(window,"blur",e),U=f("visibilitychange",e);L=[t,n,o,i,c,g,U]},T=()=>{L.forEach(e=>e()),L=[]};var u="poulet_leader_session",d=!1,F=e=>{let t=localStorage.getItem(u);return t?(d=t===e,d):(localStorage.setItem(u,e),d=!0,!0)},R=e=>{localStorage.getItem(u)===e&&localStorage.removeItem(u),d=!1};var q=(e,t)=>{let n=o=>{if(o.key!==u)return;let i=localStorage.getItem(u),c=i===e||!i;i?(d=i===e,t(d)):(localStorage.setItem(u,e),t(!0),d=!0)};return window.addEventListener("storage",n),()=>window.removeEventListener("storage",n)},K=()=>{var e;return{ua:navigator.userAgent,tz:(e=Intl.DateTimeFormat().resolvedOptions().timeZone)!=null?e:"UTC",dpr:window.devicePixelRatio||1}};var m=!1,k=!1,S="pending",H=!0,z=e=>{H=e},N=e=>{S=e,H&&typeof navigator!="undefined"&&navigator.doNotTrack==="1"&&(m=!1,k=!1,S="denied")},V=e=>{typeof e.analytics=="boolean"&&(m=e.analytics,S=m?"granted":"denied"),typeof e.replay=="boolean"&&(k=e.replay)},W=()=>({analytics:m,replay:k,state:S}),D=()=>m===!0;var p,x=[],j=!1;async function X(e){if(!(!p.hmacPublicKey||!("crypto"in window)))try{let t=_(p.hmacPublicKey),n=await crypto.subtle.importKey("raw",t,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),o=await crypto.subtle.sign("HMAC",n,new TextEncoder().encode(e));return btoa(String.fromCharCode(...new Uint8Array(o)))}catch(t){return}}async function $(e){let t=e.map(c=>E(c)),n=JSON.stringify({projectKey:p.projectKey,items:t}),o=await X(n);if(navigator.sendBeacon&&!p.debug){let c={type:"application/json"},g=new Blob([n],c);if(navigator.sendBeacon(p.endpoint+"/ingest",g))return!0}return(await fetch(p.endpoint+"/ingest",{method:"POST",headers:{"Content-Type":"application/json",...o?{"x-signature":o}:{}},body:n})).ok}function G(e){p=e,window.addEventListener("online",b),setInterval(b,5e3)}function l(e){x.push(e),x.length>=10&&b()}async function b(){if(!(j||x.length===0)){j=!0;try{let e=x.splice(0,20);await $(e)||(x.unshift(...e),y("flush failed, will retry"))}catch(e){y("flush error",e)}finally{j=!1}}}var a,r=null,v=null,h,J={projectKey:"",endpoint:"",consent:{default:"pending"},user:{},billing:{heartbeatSec:15,idleSec:60,maxHoursPerDay:6},privacy:{piiFilter:!0,dntRespect:!0,countryHint:"FR"},security:{hmacPublicKey:void 0},features:{bugReporter:!0,replay:!1,sentryBridge:!1},sampling:{heartbeats:1,events:1,bugs:1},debug:!1};function Y(e){a={...J,...e,consent:{...J.consent,...e.consent}},window.__POULET_DEBUG__=!!a.debug,G({endpoint:a.endpoint,projectKey:a.projectKey,hmacPublicKey:a.security.hmacPublicKey,debug:a.debug})}function I(){if(r)return;let e=crypto.randomUUID(),t=K();r={sessionId:e,startedAt:s(),lastActivityAt:s(),active:!0,leader:F(e)},h&&h(),h=q(e,o=>{r&&(r.leader=o)}),O();let n={type:"session.start",sessionId:e,ts:s(),projectKey:a.projectKey,ua:t.ua,tz:t.tz,dpr:t.dpr,consentFlags:{analytics:D(),replay:!1}};l(n),ee(),y("session opened",e)}function P(e){if(!r)return;Z(),T(),R(r.sessionId);let t={type:"session.end",sessionId:r.sessionId,ts:s(),reason:e};l(t),b(),h&&h(),r=null,y("session closed",e)}function ee(){Z();let e=()=>{if(!r||!D())return;let t=s()-M()>=a.billing.idleSec*1e3,n=document.visibilityState==="visible",o=n&&!t&&r.leader,i=K();if(Math.random()<=a.sampling.heartbeats&&o){let g={type:"heartbeat",sessionId:r.sessionId,ts:s(),active:!0,vis:n,idle:!1,jitter:Math.random(),ua:i.ua,tz:i.tz,dpr:i.dpr,purpose:"billing"};l(g)}let c=C(a.billing.heartbeatSec*1e3,.1);v=window.setTimeout(e,c)};v=window.setTimeout(e,C(a.billing.heartbeatSec*1e3,.1))}function Z(){v&&(clearTimeout(v),v=null)}var w=()=>{var e;return(e=r==null?void 0:r.sessionId)!=null?e:null};function te(e){let t=w();if(!t)return;let n={type:"bug",sessionId:t,ts:s(),title:e.title,description:e.description,severity:e.severity,hasCapture:!!(e.attachments&&e.attachments.length>0),purpose:"diagnostics"};l(n)}var Q=!1;function Ee(e){var t,n,o,i;Q||(z((n=(t=e.privacy)==null?void 0:t.dntRespect)!=null?n:!0),N((i=(o=e.consent)==null?void 0:o.default)!=null?i:"pending"),Y(e),document.visibilityState==="visible"&&I(),document.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&I()}),addEventListener("pagehide",()=>P("pagehide")),Q=!0)}function Le(e){V(e),document.visibilityState==="visible"&&I()}function Te(e,t){let n=w();if(!n)return;let o={type:"event",sessionId:n,ts:s(),name:e,props:t,purpose:"diagnostics"};l(o)}function Ke(){P("shutdown")}function ke(){return w()}function De(){P("shutdown")}var je=W;export{je as _consentFlags,De as forgetMe,ke as getSessionId,Ee as init,te as reportBug,Le as setConsent,Ke as shutdown,Te as trackEvent};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils.ts","../src/activity.ts","../src/antifraud.ts","../src/consent.ts","../src/transport.ts","../src/core.ts","../src/bug.ts","../src/index.ts"],"sourcesContent":["// src/utils.ts\nexport const now = () => Date.now();\n\nexport const uuid = (): string =>\n (crypto?.randomUUID?.() ?? 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (crypto.getRandomValues(new Uint8Array(1))[0] & 0xf) >> 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n }));\n\nexport const isVisible = () => typeof document !== 'undefined' && document.visibilityState === 'visible';\n\nexport const on = <K extends keyof WindowEventMap>(t: Window, type: K, fn: (e: WindowEventMap[K]) => void) => {\n t.addEventListener(type, fn as any, { passive: true });\n return () => t.removeEventListener(type, fn as any);\n};\n\nexport const onDoc = <K extends keyof DocumentEventMap>(type: K, fn: (e: DocumentEventMap[K]) => void) => {\n document.addEventListener(type, fn as any, { passive: true });\n return () => document.removeEventListener(type, fn as any);\n};\n\nexport const clamp = (n: number, min: number, max: number) => Math.max(min, Math.min(max, n));\n\nexport const jitterMs = (baseMs: number, pct = 0.1) => {\n const delta = baseMs * pct;\n return baseMs + (Math.random() * 2 - 1) * delta;\n};\n\nexport const filterPII = (o: any): any => {\n if (!o || typeof o !== 'object') return o;\n const SUSPICIOUS = ['email', 'phone', 'password', 'ssn'];\n const out: any = Array.isArray(o) ? [] : {};\n for (const k of Object.keys(o)) {\n if (SUSPICIOUS.includes(k.toLowerCase())) continue;\n const v = (o as any)[k];\n out[k] = typeof v === 'object' ? filterPII(v) : v;\n }\n return out;\n};\n\nexport const log = (...args: any[]) => {\n if ((window as any).__POULET_DEBUG__) console.log('[poulet]', ...args);\n};\n\nexport const base64ToArrayBuffer = (b64: string) => Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));\n","// src/activity.ts\nimport { isVisible, onDoc, on } from './utils';\n\nlet lastActivity = Date.now();\nlet unsub: Array<() => void> = [];\n\nexport const getLastActivity = () => lastActivity;\n\nexport const startActivityTracking = () => {\n stopActivityTracking();\n const touch = () => { lastActivity = Date.now(); };\n const un1 = onDoc('mousemove', touch);\n const un2 = onDoc('keydown', touch);\n const un3 = onDoc('scroll', touch);\n const un4 = onDoc('touchstart', touch);\n const un5 = on(window, 'focus', touch);\n const un6 = on(window, 'blur', touch);\n const un7 = onDoc('visibilitychange' as any, touch);\n unsub = [un1, un2, un3, un4, un5, un6, un7];\n};\n\nexport const stopActivityTracking = () => {\n unsub.forEach((f) => f());\n unsub = [];\n};\n\nexport const isActive = (idleSec: number) => {\n const idleMs = idleSec * 1000;\n return isVisible() && (Date.now() - lastActivity) < idleMs;\n};\n","// src/antifraud.ts\nconst LS_KEY = 'poulet_leader_session';\nlet leader = false;\n\nexport const becomeLeaderIfFree = (sessionId: string): boolean => {\n const current = localStorage.getItem(LS_KEY);\n if (!current) {\n localStorage.setItem(LS_KEY, sessionId);\n leader = true;\n return true;\n }\n leader = current === sessionId;\n return leader;\n};\n\nexport const relinquishLeadership = (sessionId: string) => {\n const current = localStorage.getItem(LS_KEY);\n if (current === sessionId) {\n localStorage.removeItem(LS_KEY);\n }\n leader = false;\n};\n\nexport const isLeader = () => leader;\n\nexport const handleStorageLeadership = (sessionId: string, onChange: (isLeader: boolean)=>void) => {\n const listener = (e: StorageEvent) => {\n if (e.key !== LS_KEY) return;\n const now = localStorage.getItem(LS_KEY);\n const newLeader = now === sessionId || !now;\n if (!now) { // try claim\n localStorage.setItem(LS_KEY, sessionId);\n onChange(true);\n leader = true;\n } else {\n leader = now === sessionId;\n onChange(leader);\n }\n };\n window.addEventListener('storage', listener);\n return () => window.removeEventListener('storage', listener);\n};\n\nexport const fingerprintLite = () => ({\n ua: navigator.userAgent,\n tz: Intl.DateTimeFormat().resolvedOptions().timeZone ?? 'UTC',\n dpr: window.devicePixelRatio || 1,\n});\n","// src/consent.ts\nimport type { ConsentState } from './types';\n\nlet analyticsAllowed = false;\nlet replayAllowed = false;\nlet state: ConsentState = 'pending';\nlet dntRespected = true;\n\nexport const setDNTPolicy = (respect: boolean) => { dntRespected = respect; };\n\nexport const initConsent = (defaultState: ConsentState) => {\n state = defaultState;\n if (dntRespected && typeof navigator !== 'undefined' && (navigator as any).doNotTrack === '1') {\n analyticsAllowed = false;\n replayAllowed = false;\n state = 'denied';\n }\n};\n\nexport const setConsent = (flags: { analytics?: boolean; replay?: boolean }) => {\n if (typeof flags.analytics === 'boolean') {\n analyticsAllowed = flags.analytics;\n state = analyticsAllowed ? 'granted' : 'denied';\n }\n if (typeof flags.replay === 'boolean') replayAllowed = flags.replay;\n};\n\nexport const consentFlags = () => ({ analytics: analyticsAllowed, replay: replayAllowed, state });\nexport const analyticsOn = () => analyticsAllowed === true;\nexport const replayOn = () => replayAllowed === true;\n","// src/transport.ts\nimport { base64ToArrayBuffer, filterPII, log } from './utils';\nimport type { OutgoingPayload } from './types';\n\ntype TransportConfig = {\n endpoint: string;\n projectKey: string;\n hmacPublicKey?: string; // base64; optional\n debug?: boolean;\n};\n\nlet cfg: TransportConfig;\nlet queue: OutgoingPayload[] = [];\nlet flushing = false;\n\nasync function sign(body: string): Promise<string | undefined> {\n if (!cfg.hmacPublicKey || !('crypto' in window)) return undefined;\n try {\n const keyData = base64ToArrayBuffer(cfg.hmacPublicKey);\n const key = await crypto.subtle.importKey('raw', keyData, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);\n const sig = await crypto.subtle.sign('HMAC', key, new TextEncoder().encode(body));\n return btoa(String.fromCharCode(...new Uint8Array(sig)));\n } catch {\n return undefined;\n }\n}\n\nasync function postBatch(items: OutgoingPayload[]) {\n const sanitized = items.map((i) => filterPII(i));\n const body = JSON.stringify({ projectKey: cfg.projectKey, items: sanitized });\n const sig = await sign(body);\n\n // Try Beacon first\n if (navigator.sendBeacon && !cfg.debug) {\n const headers = { type: 'application/json' };\n const blob = new Blob([body], headers);\n const ok = navigator.sendBeacon(cfg.endpoint + '/ingest', blob);\n if (ok) return true;\n }\n\n // Fallback fetch\n const res = await fetch(cfg.endpoint + '/ingest', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...(sig ? { 'x-signature': sig } : {}) },\n body\n });\n return res.ok;\n}\n\nexport function initTransport(config: TransportConfig) {\n cfg = config;\n window.addEventListener('online', flush);\n setInterval(flush, 5000);\n}\n\nexport function enqueue(payload: OutgoingPayload) {\n queue.push(payload);\n if (queue.length >= 10) void flush();\n}\n\nexport async function flush() {\n if (flushing || queue.length === 0) return;\n flushing = true;\n try {\n const batch = queue.splice(0, 20);\n const ok = await postBatch(batch);\n if (!ok) {\n // put back\n queue.unshift(...batch);\n log('flush failed, will retry');\n }\n } catch (e) {\n log('flush error', e);\n } finally {\n flushing = false;\n }\n}\n","// src/core.ts\nimport { jitterMs, log, now } from './utils';\nimport { startActivityTracking, stopActivityTracking, isActive, getLastActivity } from './activity';\nimport { becomeLeaderIfFree, handleStorageLeadership, relinquishLeadership, isLeader, fingerprintLite } from './antifraud';\nimport { analyticsOn, consentFlags } from './consent';\nimport { initTransport, enqueue, flush } from './transport';\nimport type { Config, SessionState, HeartbeatPayload, SessionStart, SessionEnd } from './types';\n\nlet config: Required<Config>;\nlet session: SessionState | null = null;\nlet hbTimer: number | null = null;\nlet unStorage: (() => void) | undefined;\n\nconst DEFAULTS: Required<Config> = {\n projectKey: '',\n endpoint: '',\n consent: { default: 'pending' },\n user: {},\n billing: { heartbeatSec: 15, idleSec: 60, maxHoursPerDay: 6 },\n privacy: { piiFilter: true, dntRespect: true, countryHint: 'FR' },\n security: { hmacPublicKey: undefined as any },\n features: { bugReporter: true, replay: false, sentryBridge: false },\n sampling: { heartbeats: 1, events: 1, bugs: 1 },\n debug: false,\n};\n\nexport function configure(cfg: Config) {\n config = { ...DEFAULTS, ...cfg, consent: { ...DEFAULTS.consent, ...cfg.consent } } as Required<Config>;\n (window as any).__POULET_DEBUG__ = !!config.debug;\n initTransport({\n endpoint: config.endpoint,\n projectKey: config.projectKey,\n hmacPublicKey: config.security.hmacPublicKey,\n debug: config.debug,\n });\n}\n\nexport function openSession() {\n if (session) return;\n const id = crypto.randomUUID();\n const fp = fingerprintLite();\n session = {\n sessionId: id,\n startedAt: now(),\n lastActivityAt: now(),\n active: true,\n leader: becomeLeaderIfFree(id),\n };\n if (unStorage) unStorage();\n unStorage = handleStorageLeadership(id, (lead) => {\n if (session) session.leader = lead;\n });\n\n startActivityTracking();\n\n const startPayload: SessionStart = {\n type: 'session.start',\n sessionId: id,\n ts: now(),\n projectKey: config.projectKey,\n ua: fp.ua,\n tz: fp.tz,\n dpr: fp.dpr,\n consentFlags: { analytics: analyticsOn(), replay: false },\n };\n enqueue(startPayload);\n scheduleHeartbeats();\n log('session opened', id);\n}\n\nexport function closeSession(reason: SessionEnd['reason']) {\n if (!session) return;\n stopHeartbeats();\n stopActivityTracking();\n relinquishLeadership(session.sessionId);\n const endPayload: SessionEnd = { type: 'session.end', sessionId: session.sessionId, ts: now(), reason };\n enqueue(endPayload);\n void flush();\n if (unStorage) unStorage();\n session = null;\n log('session closed', reason);\n}\n\nfunction scheduleHeartbeats() {\n stopHeartbeats();\n const loop = () => {\n if (!session) return;\n if (!analyticsOn()) return; // consent required\n // @ts-ignore\n const idle = (now() - getLastActivity()) >= config.billing.idleSec * 1000;\n const vis = document.visibilityState === 'visible';\n const active = vis && !idle && session.leader;\n const fp = fingerprintLite();\n\n // @ts-ignore\n if (Math.random() <= config.sampling.heartbeats && active) {\n const hb: HeartbeatPayload = {\n type: 'heartbeat',\n sessionId: session.sessionId,\n ts: now(),\n active: true,\n vis,\n idle: false,\n jitter: Math.random(),\n ua: fp.ua,\n tz: fp.tz,\n dpr: fp.dpr,\n purpose: 'billing',\n };\n enqueue(hb);\n }\n\n // @ts-ignore\n const next = jitterMs(config.billing.heartbeatSec * 1000, 0.1);\n hbTimer = window.setTimeout(loop, next);\n };\n // @ts-ignore\n hbTimer = window.setTimeout(loop, jitterMs(config.billing.heartbeatSec * 1000, 0.1));\n}\n\nfunction stopHeartbeats() {\n if (hbTimer) {\n clearTimeout(hbTimer);\n hbTimer = null;\n }\n}\n\nexport const getSessionIdSafe = () => session?.sessionId ?? null;\n","// src/bug.ts\nimport { enqueue } from './transport';\nimport type { BugPayload } from './types';\nimport { now } from './utils';\nimport { getSessionIdSafe } from './core';\n\nexport function reportBug(payload: {\n title: string; description?: string;\n severity?: 'blocker'|'major'|'minor'|'ux';\n attachments?: Blob[];\n}) {\n const sessionId = getSessionIdSafe();\n if (!sessionId) return;\n const p: BugPayload = {\n type: 'bug',\n sessionId,\n ts: now(),\n title: payload.title,\n description: payload.description,\n severity: payload.severity,\n hasCapture: !!(payload.attachments && payload.attachments.length > 0),\n purpose: 'diagnostics'\n };\n enqueue(p);\n // NOTE: upload des pièces jointes = hors scope core (peut passer par un autre endpoint)\n}\n","// src/index.ts\nimport { configure, openSession, closeSession, getSessionIdSafe } from './core';\nimport { setConsent as _setConsent, initConsent, setDNTPolicy, consentFlags } from './consent';\nimport { enqueue } from './transport';\nimport type { Config, EventPayload } from './types';\nimport { now } from './utils';\nexport * from './types';\nexport { reportBug } from './bug';\n\nlet initialized = false;\n\nexport function init(cfg: Config) {\n if (initialized) return;\n setDNTPolicy(cfg.privacy?.dntRespect ?? true);\n initConsent(cfg.consent?.default ?? 'pending');\n configure(cfg);\n // ouverture paresseuse : dès qu’il y a visibilité/activité\n if (document.visibilityState === 'visible') openSession();\n document.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'visible') openSession();\n });\n // Flush/close sur pagehide\n addEventListener('pagehide', () => closeSession('pagehide'));\n initialized = true;\n}\n\nexport function setConsent(flags: { analytics?: boolean; replay?: boolean }) {\n _setConsent(flags);\n if (document.visibilityState === 'visible') openSession();\n}\n\nexport function trackEvent(name: string, props?: Record<string, unknown>) {\n const sessionId = getSessionIdSafe();\n if (!sessionId) return;\n const ev: EventPayload = {\n type: 'event',\n sessionId,\n ts: now(),\n name,\n props,\n purpose: 'diagnostics',\n };\n enqueue(ev);\n}\n\nexport function shutdown() {\n closeSession('shutdown');\n}\n\nexport function getSessionId() {\n return getSessionIdSafe();\n}\n\nexport function forgetMe() {\n // côté core : rien de persistant par défaut (queue en mémoire).\n // si tu ajoutes IndexedDB/localStorage pour queue offline, purge ici.\n // Pour l’exemple, on ne stocke pas persistantement.\n closeSession('shutdown');\n}\n\nexport const _consentFlags = consentFlags;\n"],"mappings":"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","names":["now","on","t","type","fn","onDoc","jitterMs","baseMs","pct","delta","filterPII","o","SUSPICIOUS","out","k","v","log","args","base64ToArrayBuffer","b64","c","lastActivity","unsub","getLastActivity","startActivityTracking","stopActivityTracking","touch","un1","onDoc","un2","un3","un4","un5","on","un6","un7","f","LS_KEY","leader","becomeLeaderIfFree","sessionId","current","relinquishLeadership","handleStorageLeadership","sessionId","onChange","listener","e","LS_KEY","now","newLeader","leader","fingerprintLite","_a","analyticsAllowed","replayAllowed","state","dntRespected","setDNTPolicy","respect","initConsent","defaultState","setConsent","flags","consentFlags","analyticsOn","cfg","queue","flushing","sign","body","keyData","base64ToArrayBuffer","key","sig","e","postBatch","items","sanitized","i","filterPII","headers","blob","initTransport","config","flush","enqueue","payload","batch","log","config","session","hbTimer","unStorage","DEFAULTS","configure","cfg","initTransport","openSession","id","fp","fingerprintLite","now","becomeLeaderIfFree","handleStorageLeadership","lead","startActivityTracking","startPayload","analyticsOn","enqueue","scheduleHeartbeats","log","closeSession","reason","stopHeartbeats","stopActivityTracking","relinquishLeadership","endPayload","flush","loop","idle","getLastActivity","vis","active","hb","next","jitterMs","getSessionIdSafe","_a","reportBug","payload","sessionId","getSessionIdSafe","p","now","enqueue","initialized","init","cfg","_a","_b","_c","_d","setDNTPolicy","initConsent","configure","openSession","closeSession","setConsent","flags","trackEvent","name","props","sessionId","getSessionIdSafe","ev","now","enqueue","shutdown","getSessionId","forgetMe","_consentFlags","consentFlags"]}
|
package/dist/react.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var E=Object.defineProperty;var ae=Object.getOwnPropertyDescriptor;var ce=Object.getOwnPropertyNames;var le=Object.prototype.hasOwnProperty;var ue=(e,t)=>{for(var n in t)E(e,n,{get:t[n],enumerable:!0})},de=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of ce(t))!le.call(e,i)&&i!==n&&E(e,i,{get:()=>t[i],enumerable:!(o=ae(t,i))||o.enumerable});return e};var pe=e=>de(E({},"__esModule",{value:!0}),e);var be={};ue(be,{MetricsProvider:()=>me,useMetrics:()=>xe});module.exports=pe(be);var g=require("react");var s=()=>Date.now();var I=(e,t,n)=>(e.addEventListener(t,n,{passive:!0}),()=>e.removeEventListener(t,n)),f=(e,t)=>(document.addEventListener(e,t,{passive:!0}),()=>document.removeEventListener(e,t));var A=(e,t=.1)=>{let n=e*t;return e+(Math.random()*2-1)*n},L=e=>{if(!e||typeof e!="object")return e;let t=["email","phone","password","ssn"],n=Array.isArray(e)?[]:{};for(let o of Object.keys(e)){if(t.includes(o.toLowerCase()))continue;let i=e[o];n[o]=typeof i=="object"?L(i):i}return n},y=(...e)=>{window.__POULET_DEBUG__&&console.log("[poulet]",...e)},q=e=>Uint8Array.from(atob(e),t=>t.charCodeAt(0));var H=Date.now(),T=[],z=()=>H,N=()=>{k();let e=()=>{H=Date.now()},t=f("mousemove",e),n=f("keydown",e),o=f("scroll",e),i=f("touchstart",e),c=I(window,"focus",e),m=I(window,"blur",e),F=f("visibilitychange",e);T=[t,n,o,i,c,m,F]},k=()=>{T.forEach(e=>e()),T=[]};var u="poulet_leader_session",d=!1,V=e=>{let t=localStorage.getItem(u);return t?(d=t===e,d):(localStorage.setItem(u,e),d=!0,!0)},W=e=>{localStorage.getItem(u)===e&&localStorage.removeItem(u),d=!1};var G=(e,t)=>{let n=o=>{if(o.key!==u)return;let i=localStorage.getItem(u),c=i===e||!i;i?(d=i===e,t(d)):(localStorage.setItem(u,e),t(!0),d=!0)};return window.addEventListener("storage",n),()=>window.removeEventListener("storage",n)},K=()=>{var e;return{ua:navigator.userAgent,tz:(e=Intl.DateTimeFormat().resolvedOptions().timeZone)!=null?e:"UTC",dpr:window.devicePixelRatio||1}};var S=!1,J=!1,D="pending",Y=!0,Z=e=>{Y=e},Q=e=>{D=e,Y&&typeof navigator!="undefined"&&navigator.doNotTrack==="1"&&(S=!1,J=!1,D="denied")},X=e=>{typeof e.analytics=="boolean"&&(S=e.analytics,D=S?"granted":"denied"),typeof e.replay=="boolean"&&(J=e.replay)};var j=()=>S===!0;var p,x=[],M=!1;async function fe(e){if(!(!p.hmacPublicKey||!("crypto"in window)))try{let t=q(p.hmacPublicKey),n=await crypto.subtle.importKey("raw",t,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),o=await crypto.subtle.sign("HMAC",n,new TextEncoder().encode(e));return btoa(String.fromCharCode(...new Uint8Array(o)))}catch(t){return}}async function ye(e){let t=e.map(c=>L(c)),n=JSON.stringify({projectKey:p.projectKey,items:t}),o=await fe(n);if(navigator.sendBeacon&&!p.debug){let c={type:"application/json"},m=new Blob([n],c);if(navigator.sendBeacon(p.endpoint+"/ingest",m))return!0}return(await fetch(p.endpoint+"/ingest",{method:"POST",headers:{"Content-Type":"application/json",...o?{"x-signature":o}:{}},body:n})).ok}function $(e){p=e,window.addEventListener("online",b),setInterval(b,5e3)}function l(e){x.push(e),x.length>=10&&b()}async function b(){if(!(M||x.length===0)){M=!0;try{let e=x.splice(0,20);await ye(e)||(x.unshift(...e),y("flush failed, will retry"))}catch(e){y("flush error",e)}finally{M=!1}}}var a,r=null,v=null,h,ee={projectKey:"",endpoint:"",consent:{default:"pending"},user:{},billing:{heartbeatSec:15,idleSec:60,maxHoursPerDay:6},privacy:{piiFilter:!0,dntRespect:!0,countryHint:"FR"},security:{hmacPublicKey:void 0},features:{bugReporter:!0,replay:!1,sentryBridge:!1},sampling:{heartbeats:1,events:1,bugs:1},debug:!1};function te(e){a={...ee,...e,consent:{...ee.consent,...e.consent}},window.__POULET_DEBUG__=!!a.debug,$({endpoint:a.endpoint,projectKey:a.projectKey,hmacPublicKey:a.security.hmacPublicKey,debug:a.debug})}function C(){if(r)return;let e=crypto.randomUUID(),t=K();r={sessionId:e,startedAt:s(),lastActivityAt:s(),active:!0,leader:V(e)},h&&h(),h=G(e,o=>{r&&(r.leader=o)}),N();let n={type:"session.start",sessionId:e,ts:s(),projectKey:a.projectKey,ua:t.ua,tz:t.tz,dpr:t.dpr,consentFlags:{analytics:j(),replay:!1}};l(n),ge(),y("session opened",e)}function B(e){if(!r)return;ne(),k(),W(r.sessionId);let t={type:"session.end",sessionId:r.sessionId,ts:s(),reason:e};l(t),b(),h&&h(),r=null,y("session closed",e)}function ge(){ne();let e=()=>{if(!r||!j())return;let t=s()-z()>=a.billing.idleSec*1e3,n=document.visibilityState==="visible",o=n&&!t&&r.leader,i=K();if(Math.random()<=a.sampling.heartbeats&&o){let m={type:"heartbeat",sessionId:r.sessionId,ts:s(),active:!0,vis:n,idle:!1,jitter:Math.random(),ua:i.ua,tz:i.tz,dpr:i.dpr,purpose:"billing"};l(m)}let c=A(a.billing.heartbeatSec*1e3,.1);v=window.setTimeout(e,c)};v=window.setTimeout(e,A(a.billing.heartbeatSec*1e3,.1))}function ne(){v&&(clearTimeout(v),v=null)}var w=()=>{var e;return(e=r==null?void 0:r.sessionId)!=null?e:null};function P(e){let t=w();if(!t)return;let n={type:"bug",sessionId:t,ts:s(),title:e.title,description:e.description,severity:e.severity,hasCapture:!!(e.attachments&&e.attachments.length>0),purpose:"diagnostics"};l(n)}var oe=!1;function ie(e){var t,n,o,i;oe||(Z((n=(t=e.privacy)==null?void 0:t.dntRespect)!=null?n:!0),Q((i=(o=e.consent)==null?void 0:o.default)!=null?i:"pending"),te(e),document.visibilityState==="visible"&&C(),document.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&C()}),addEventListener("pagehide",()=>B("pagehide")),oe=!0)}function R(e){X(e),document.visibilityState==="visible"&&C()}function U(e,t){let n=w();if(!n)return;let o={type:"event",sessionId:n,ts:s(),name:e,props:t,purpose:"diagnostics"};l(o)}function _(){B("shutdown")}function O(){return w()}var se=require("react/jsx-runtime"),re=(0,g.createContext)({trackEvent:U,reportBug:P,setConsent:R,shutdown:_,getSessionId:O}),me=({config:e,children:t})=>((0,g.useEffect)(()=>{ie(e)},[]),(0,se.jsx)(re.Provider,{value:{trackEvent:U,reportBug:P,setConsent:R,shutdown:_,getSessionId:O},children:t})),xe=()=>(0,g.useContext)(re);0&&(module.exports={MetricsProvider,useMetrics});
|
|
2
|
+
//# sourceMappingURL=react.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/react.tsx","../src/utils.ts","../src/activity.ts","../src/antifraud.ts","../src/consent.ts","../src/transport.ts","../src/core.ts","../src/bug.ts","../src/index.ts"],"sourcesContent":["// src/react.tsx\nimport React, { createContext, useContext, useEffect } from 'react';\nimport type { Config } from './types';\nimport { init, trackEvent, reportBug, setConsent, shutdown, getSessionId } from './index';\n\nconst Ctx = createContext({ trackEvent, reportBug, setConsent, shutdown, getSessionId });\n\nexport const MetricsProvider: React.FC<{ config: Config; children: React.ReactNode }> = ({ config, children }) => {\n useEffect(() => { init(config); }, []); // eslint-disable-line\n return <Ctx.Provider value={{ trackEvent, reportBug, setConsent, shutdown, getSessionId }}>{children}</Ctx.Provider>;\n};\n\nexport const useMetrics = () => useContext(Ctx);\n","// src/utils.ts\nexport const now = () => Date.now();\n\nexport const uuid = (): string =>\n (crypto?.randomUUID?.() ?? 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (crypto.getRandomValues(new Uint8Array(1))[0] & 0xf) >> 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n }));\n\nexport const isVisible = () => typeof document !== 'undefined' && document.visibilityState === 'visible';\n\nexport const on = <K extends keyof WindowEventMap>(t: Window, type: K, fn: (e: WindowEventMap[K]) => void) => {\n t.addEventListener(type, fn as any, { passive: true });\n return () => t.removeEventListener(type, fn as any);\n};\n\nexport const onDoc = <K extends keyof DocumentEventMap>(type: K, fn: (e: DocumentEventMap[K]) => void) => {\n document.addEventListener(type, fn as any, { passive: true });\n return () => document.removeEventListener(type, fn as any);\n};\n\nexport const clamp = (n: number, min: number, max: number) => Math.max(min, Math.min(max, n));\n\nexport const jitterMs = (baseMs: number, pct = 0.1) => {\n const delta = baseMs * pct;\n return baseMs + (Math.random() * 2 - 1) * delta;\n};\n\nexport const filterPII = (o: any): any => {\n if (!o || typeof o !== 'object') return o;\n const SUSPICIOUS = ['email', 'phone', 'password', 'ssn'];\n const out: any = Array.isArray(o) ? [] : {};\n for (const k of Object.keys(o)) {\n if (SUSPICIOUS.includes(k.toLowerCase())) continue;\n const v = (o as any)[k];\n out[k] = typeof v === 'object' ? filterPII(v) : v;\n }\n return out;\n};\n\nexport const log = (...args: any[]) => {\n if ((window as any).__POULET_DEBUG__) console.log('[poulet]', ...args);\n};\n\nexport const base64ToArrayBuffer = (b64: string) => Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));\n","// src/activity.ts\nimport { isVisible, onDoc, on } from './utils';\n\nlet lastActivity = Date.now();\nlet unsub: Array<() => void> = [];\n\nexport const getLastActivity = () => lastActivity;\n\nexport const startActivityTracking = () => {\n stopActivityTracking();\n const touch = () => { lastActivity = Date.now(); };\n const un1 = onDoc('mousemove', touch);\n const un2 = onDoc('keydown', touch);\n const un3 = onDoc('scroll', touch);\n const un4 = onDoc('touchstart', touch);\n const un5 = on(window, 'focus', touch);\n const un6 = on(window, 'blur', touch);\n const un7 = onDoc('visibilitychange' as any, touch);\n unsub = [un1, un2, un3, un4, un5, un6, un7];\n};\n\nexport const stopActivityTracking = () => {\n unsub.forEach((f) => f());\n unsub = [];\n};\n\nexport const isActive = (idleSec: number) => {\n const idleMs = idleSec * 1000;\n return isVisible() && (Date.now() - lastActivity) < idleMs;\n};\n","// src/antifraud.ts\nconst LS_KEY = 'poulet_leader_session';\nlet leader = false;\n\nexport const becomeLeaderIfFree = (sessionId: string): boolean => {\n const current = localStorage.getItem(LS_KEY);\n if (!current) {\n localStorage.setItem(LS_KEY, sessionId);\n leader = true;\n return true;\n }\n leader = current === sessionId;\n return leader;\n};\n\nexport const relinquishLeadership = (sessionId: string) => {\n const current = localStorage.getItem(LS_KEY);\n if (current === sessionId) {\n localStorage.removeItem(LS_KEY);\n }\n leader = false;\n};\n\nexport const isLeader = () => leader;\n\nexport const handleStorageLeadership = (sessionId: string, onChange: (isLeader: boolean)=>void) => {\n const listener = (e: StorageEvent) => {\n if (e.key !== LS_KEY) return;\n const now = localStorage.getItem(LS_KEY);\n const newLeader = now === sessionId || !now;\n if (!now) { // try claim\n localStorage.setItem(LS_KEY, sessionId);\n onChange(true);\n leader = true;\n } else {\n leader = now === sessionId;\n onChange(leader);\n }\n };\n window.addEventListener('storage', listener);\n return () => window.removeEventListener('storage', listener);\n};\n\nexport const fingerprintLite = () => ({\n ua: navigator.userAgent,\n tz: Intl.DateTimeFormat().resolvedOptions().timeZone ?? 'UTC',\n dpr: window.devicePixelRatio || 1,\n});\n","// src/consent.ts\nimport type { ConsentState } from './types';\n\nlet analyticsAllowed = false;\nlet replayAllowed = false;\nlet state: ConsentState = 'pending';\nlet dntRespected = true;\n\nexport const setDNTPolicy = (respect: boolean) => { dntRespected = respect; };\n\nexport const initConsent = (defaultState: ConsentState) => {\n state = defaultState;\n if (dntRespected && typeof navigator !== 'undefined' && (navigator as any).doNotTrack === '1') {\n analyticsAllowed = false;\n replayAllowed = false;\n state = 'denied';\n }\n};\n\nexport const setConsent = (flags: { analytics?: boolean; replay?: boolean }) => {\n if (typeof flags.analytics === 'boolean') {\n analyticsAllowed = flags.analytics;\n state = analyticsAllowed ? 'granted' : 'denied';\n }\n if (typeof flags.replay === 'boolean') replayAllowed = flags.replay;\n};\n\nexport const consentFlags = () => ({ analytics: analyticsAllowed, replay: replayAllowed, state });\nexport const analyticsOn = () => analyticsAllowed === true;\nexport const replayOn = () => replayAllowed === true;\n","// src/transport.ts\nimport { base64ToArrayBuffer, filterPII, log } from './utils';\nimport type { OutgoingPayload } from './types';\n\ntype TransportConfig = {\n endpoint: string;\n projectKey: string;\n hmacPublicKey?: string; // base64; optional\n debug?: boolean;\n};\n\nlet cfg: TransportConfig;\nlet queue: OutgoingPayload[] = [];\nlet flushing = false;\n\nasync function sign(body: string): Promise<string | undefined> {\n if (!cfg.hmacPublicKey || !('crypto' in window)) return undefined;\n try {\n const keyData = base64ToArrayBuffer(cfg.hmacPublicKey);\n const key = await crypto.subtle.importKey('raw', keyData, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);\n const sig = await crypto.subtle.sign('HMAC', key, new TextEncoder().encode(body));\n return btoa(String.fromCharCode(...new Uint8Array(sig)));\n } catch {\n return undefined;\n }\n}\n\nasync function postBatch(items: OutgoingPayload[]) {\n const sanitized = items.map((i) => filterPII(i));\n const body = JSON.stringify({ projectKey: cfg.projectKey, items: sanitized });\n const sig = await sign(body);\n\n // Try Beacon first\n if (navigator.sendBeacon && !cfg.debug) {\n const headers = { type: 'application/json' };\n const blob = new Blob([body], headers);\n const ok = navigator.sendBeacon(cfg.endpoint + '/ingest', blob);\n if (ok) return true;\n }\n\n // Fallback fetch\n const res = await fetch(cfg.endpoint + '/ingest', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...(sig ? { 'x-signature': sig } : {}) },\n body\n });\n return res.ok;\n}\n\nexport function initTransport(config: TransportConfig) {\n cfg = config;\n window.addEventListener('online', flush);\n setInterval(flush, 5000);\n}\n\nexport function enqueue(payload: OutgoingPayload) {\n queue.push(payload);\n if (queue.length >= 10) void flush();\n}\n\nexport async function flush() {\n if (flushing || queue.length === 0) return;\n flushing = true;\n try {\n const batch = queue.splice(0, 20);\n const ok = await postBatch(batch);\n if (!ok) {\n // put back\n queue.unshift(...batch);\n log('flush failed, will retry');\n }\n } catch (e) {\n log('flush error', e);\n } finally {\n flushing = false;\n }\n}\n","// src/core.ts\nimport { jitterMs, log, now } from './utils';\nimport { startActivityTracking, stopActivityTracking, isActive, getLastActivity } from './activity';\nimport { becomeLeaderIfFree, handleStorageLeadership, relinquishLeadership, isLeader, fingerprintLite } from './antifraud';\nimport { analyticsOn, consentFlags } from './consent';\nimport { initTransport, enqueue, flush } from './transport';\nimport type { Config, SessionState, HeartbeatPayload, SessionStart, SessionEnd } from './types';\n\nlet config: Required<Config>;\nlet session: SessionState | null = null;\nlet hbTimer: number | null = null;\nlet unStorage: (() => void) | undefined;\n\nconst DEFAULTS: Required<Config> = {\n projectKey: '',\n endpoint: '',\n consent: { default: 'pending' },\n user: {},\n billing: { heartbeatSec: 15, idleSec: 60, maxHoursPerDay: 6 },\n privacy: { piiFilter: true, dntRespect: true, countryHint: 'FR' },\n security: { hmacPublicKey: undefined as any },\n features: { bugReporter: true, replay: false, sentryBridge: false },\n sampling: { heartbeats: 1, events: 1, bugs: 1 },\n debug: false,\n};\n\nexport function configure(cfg: Config) {\n config = { ...DEFAULTS, ...cfg, consent: { ...DEFAULTS.consent, ...cfg.consent } } as Required<Config>;\n (window as any).__POULET_DEBUG__ = !!config.debug;\n initTransport({\n endpoint: config.endpoint,\n projectKey: config.projectKey,\n hmacPublicKey: config.security.hmacPublicKey,\n debug: config.debug,\n });\n}\n\nexport function openSession() {\n if (session) return;\n const id = crypto.randomUUID();\n const fp = fingerprintLite();\n session = {\n sessionId: id,\n startedAt: now(),\n lastActivityAt: now(),\n active: true,\n leader: becomeLeaderIfFree(id),\n };\n if (unStorage) unStorage();\n unStorage = handleStorageLeadership(id, (lead) => {\n if (session) session.leader = lead;\n });\n\n startActivityTracking();\n\n const startPayload: SessionStart = {\n type: 'session.start',\n sessionId: id,\n ts: now(),\n projectKey: config.projectKey,\n ua: fp.ua,\n tz: fp.tz,\n dpr: fp.dpr,\n consentFlags: { analytics: analyticsOn(), replay: false },\n };\n enqueue(startPayload);\n scheduleHeartbeats();\n log('session opened', id);\n}\n\nexport function closeSession(reason: SessionEnd['reason']) {\n if (!session) return;\n stopHeartbeats();\n stopActivityTracking();\n relinquishLeadership(session.sessionId);\n const endPayload: SessionEnd = { type: 'session.end', sessionId: session.sessionId, ts: now(), reason };\n enqueue(endPayload);\n void flush();\n if (unStorage) unStorage();\n session = null;\n log('session closed', reason);\n}\n\nfunction scheduleHeartbeats() {\n stopHeartbeats();\n const loop = () => {\n if (!session) return;\n if (!analyticsOn()) return; // consent required\n // @ts-ignore\n const idle = (now() - getLastActivity()) >= config.billing.idleSec * 1000;\n const vis = document.visibilityState === 'visible';\n const active = vis && !idle && session.leader;\n const fp = fingerprintLite();\n\n // @ts-ignore\n if (Math.random() <= config.sampling.heartbeats && active) {\n const hb: HeartbeatPayload = {\n type: 'heartbeat',\n sessionId: session.sessionId,\n ts: now(),\n active: true,\n vis,\n idle: false,\n jitter: Math.random(),\n ua: fp.ua,\n tz: fp.tz,\n dpr: fp.dpr,\n purpose: 'billing',\n };\n enqueue(hb);\n }\n\n // @ts-ignore\n const next = jitterMs(config.billing.heartbeatSec * 1000, 0.1);\n hbTimer = window.setTimeout(loop, next);\n };\n // @ts-ignore\n hbTimer = window.setTimeout(loop, jitterMs(config.billing.heartbeatSec * 1000, 0.1));\n}\n\nfunction stopHeartbeats() {\n if (hbTimer) {\n clearTimeout(hbTimer);\n hbTimer = null;\n }\n}\n\nexport const getSessionIdSafe = () => session?.sessionId ?? null;\n","// src/bug.ts\nimport { enqueue } from './transport';\nimport type { BugPayload } from './types';\nimport { now } from './utils';\nimport { getSessionIdSafe } from './core';\n\nexport function reportBug(payload: {\n title: string; description?: string;\n severity?: 'blocker'|'major'|'minor'|'ux';\n attachments?: Blob[];\n}) {\n const sessionId = getSessionIdSafe();\n if (!sessionId) return;\n const p: BugPayload = {\n type: 'bug',\n sessionId,\n ts: now(),\n title: payload.title,\n description: payload.description,\n severity: payload.severity,\n hasCapture: !!(payload.attachments && payload.attachments.length > 0),\n purpose: 'diagnostics'\n };\n enqueue(p);\n // NOTE: upload des pièces jointes = hors scope core (peut passer par un autre endpoint)\n}\n","// src/index.ts\nimport { configure, openSession, closeSession, getSessionIdSafe } from './core';\nimport { setConsent as _setConsent, initConsent, setDNTPolicy, consentFlags } from './consent';\nimport { enqueue } from './transport';\nimport type { Config, EventPayload } from './types';\nimport { now } from './utils';\nexport * from './types';\nexport { reportBug } from './bug';\n\nlet initialized = false;\n\nexport function init(cfg: Config) {\n if (initialized) return;\n setDNTPolicy(cfg.privacy?.dntRespect ?? true);\n initConsent(cfg.consent?.default ?? 'pending');\n configure(cfg);\n // ouverture paresseuse : dès qu’il y a visibilité/activité\n if (document.visibilityState === 'visible') openSession();\n document.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'visible') openSession();\n });\n // Flush/close sur pagehide\n addEventListener('pagehide', () => closeSession('pagehide'));\n initialized = true;\n}\n\nexport function setConsent(flags: { analytics?: boolean; replay?: boolean }) {\n _setConsent(flags);\n if (document.visibilityState === 'visible') openSession();\n}\n\nexport function trackEvent(name: string, props?: Record<string, unknown>) {\n const sessionId = getSessionIdSafe();\n if (!sessionId) return;\n const ev: EventPayload = {\n type: 'event',\n sessionId,\n ts: now(),\n name,\n props,\n purpose: 'diagnostics',\n };\n enqueue(ev);\n}\n\nexport function shutdown() {\n closeSession('shutdown');\n}\n\nexport function getSessionId() {\n return getSessionIdSafe();\n}\n\nexport function forgetMe() {\n // côté core : rien de persistant par défaut (queue en mémoire).\n // si tu ajoutes IndexedDB/localStorage pour queue offline, purge ici.\n // Pour l’exemple, on ne stocke pas persistantement.\n closeSession('shutdown');\n}\n\nexport const _consentFlags = consentFlags;\n"],"mappings":"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","names":["react_exports","__export","MetricsProvider","useMetrics","__toCommonJS","import_react","now","on","t","type","fn","onDoc","jitterMs","baseMs","pct","delta","filterPII","o","SUSPICIOUS","out","k","v","log","args","base64ToArrayBuffer","b64","c","lastActivity","unsub","getLastActivity","startActivityTracking","stopActivityTracking","touch","un1","onDoc","un2","un3","un4","un5","on","un6","un7","f","LS_KEY","leader","becomeLeaderIfFree","sessionId","current","relinquishLeadership","handleStorageLeadership","sessionId","onChange","listener","e","LS_KEY","now","newLeader","leader","fingerprintLite","_a","analyticsAllowed","replayAllowed","state","dntRespected","setDNTPolicy","respect","initConsent","defaultState","setConsent","flags","analyticsOn","analyticsAllowed","cfg","queue","flushing","sign","body","keyData","base64ToArrayBuffer","key","sig","e","postBatch","items","sanitized","i","filterPII","headers","blob","initTransport","config","flush","enqueue","payload","batch","log","config","session","hbTimer","unStorage","DEFAULTS","configure","cfg","initTransport","openSession","id","fp","fingerprintLite","now","becomeLeaderIfFree","handleStorageLeadership","lead","startActivityTracking","startPayload","analyticsOn","enqueue","scheduleHeartbeats","log","closeSession","reason","stopHeartbeats","stopActivityTracking","relinquishLeadership","endPayload","flush","loop","idle","getLastActivity","vis","active","hb","next","jitterMs","getSessionIdSafe","_a","reportBug","payload","sessionId","getSessionIdSafe","p","now","enqueue","initialized","init","cfg","_a","_b","_c","_d","setDNTPolicy","initConsent","configure","openSession","closeSession","setConsent","flags","trackEvent","name","props","sessionId","getSessionIdSafe","ev","now","enqueue","shutdown","getSessionId","import_jsx_runtime","Ctx","trackEvent","reportBug","setConsent","shutdown","getSessionId","MetricsProvider","config","children","init","useMetrics"]}
|
package/dist/react.d.cts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
type ConsentState = 'pending' | 'granted' | 'denied';
|
|
4
|
+
type Config = {
|
|
5
|
+
projectKey: string;
|
|
6
|
+
endpoint: string;
|
|
7
|
+
consent?: {
|
|
8
|
+
default: ConsentState;
|
|
9
|
+
};
|
|
10
|
+
user?: {
|
|
11
|
+
testerPseudoId?: string;
|
|
12
|
+
};
|
|
13
|
+
billing?: {
|
|
14
|
+
heartbeatSec?: number;
|
|
15
|
+
idleSec?: number;
|
|
16
|
+
maxHoursPerDay?: number;
|
|
17
|
+
};
|
|
18
|
+
privacy?: {
|
|
19
|
+
piiFilter?: boolean;
|
|
20
|
+
dntRespect?: boolean;
|
|
21
|
+
countryHint?: string;
|
|
22
|
+
};
|
|
23
|
+
security?: {
|
|
24
|
+
hmacPublicKey?: string;
|
|
25
|
+
};
|
|
26
|
+
features?: {
|
|
27
|
+
bugReporter?: boolean;
|
|
28
|
+
replay?: boolean;
|
|
29
|
+
sentryBridge?: boolean;
|
|
30
|
+
};
|
|
31
|
+
sampling?: {
|
|
32
|
+
heartbeats?: number;
|
|
33
|
+
events?: number;
|
|
34
|
+
bugs?: number;
|
|
35
|
+
};
|
|
36
|
+
debug?: boolean;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
declare function reportBug(payload: {
|
|
40
|
+
title: string;
|
|
41
|
+
description?: string;
|
|
42
|
+
severity?: 'blocker' | 'major' | 'minor' | 'ux';
|
|
43
|
+
attachments?: Blob[];
|
|
44
|
+
}): void;
|
|
45
|
+
|
|
46
|
+
declare function setConsent(flags: {
|
|
47
|
+
analytics?: boolean;
|
|
48
|
+
replay?: boolean;
|
|
49
|
+
}): void;
|
|
50
|
+
declare function trackEvent(name: string, props?: Record<string, unknown>): void;
|
|
51
|
+
declare function shutdown(): void;
|
|
52
|
+
declare function getSessionId(): string | null;
|
|
53
|
+
|
|
54
|
+
declare const MetricsProvider: React.FC<{
|
|
55
|
+
config: Config;
|
|
56
|
+
children: React.ReactNode;
|
|
57
|
+
}>;
|
|
58
|
+
declare const useMetrics: () => {
|
|
59
|
+
trackEvent: typeof trackEvent;
|
|
60
|
+
reportBug: typeof reportBug;
|
|
61
|
+
setConsent: typeof setConsent;
|
|
62
|
+
shutdown: typeof shutdown;
|
|
63
|
+
getSessionId: typeof getSessionId;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export { MetricsProvider, useMetrics };
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
type ConsentState = 'pending' | 'granted' | 'denied';
|
|
4
|
+
type Config = {
|
|
5
|
+
projectKey: string;
|
|
6
|
+
endpoint: string;
|
|
7
|
+
consent?: {
|
|
8
|
+
default: ConsentState;
|
|
9
|
+
};
|
|
10
|
+
user?: {
|
|
11
|
+
testerPseudoId?: string;
|
|
12
|
+
};
|
|
13
|
+
billing?: {
|
|
14
|
+
heartbeatSec?: number;
|
|
15
|
+
idleSec?: number;
|
|
16
|
+
maxHoursPerDay?: number;
|
|
17
|
+
};
|
|
18
|
+
privacy?: {
|
|
19
|
+
piiFilter?: boolean;
|
|
20
|
+
dntRespect?: boolean;
|
|
21
|
+
countryHint?: string;
|
|
22
|
+
};
|
|
23
|
+
security?: {
|
|
24
|
+
hmacPublicKey?: string;
|
|
25
|
+
};
|
|
26
|
+
features?: {
|
|
27
|
+
bugReporter?: boolean;
|
|
28
|
+
replay?: boolean;
|
|
29
|
+
sentryBridge?: boolean;
|
|
30
|
+
};
|
|
31
|
+
sampling?: {
|
|
32
|
+
heartbeats?: number;
|
|
33
|
+
events?: number;
|
|
34
|
+
bugs?: number;
|
|
35
|
+
};
|
|
36
|
+
debug?: boolean;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
declare function reportBug(payload: {
|
|
40
|
+
title: string;
|
|
41
|
+
description?: string;
|
|
42
|
+
severity?: 'blocker' | 'major' | 'minor' | 'ux';
|
|
43
|
+
attachments?: Blob[];
|
|
44
|
+
}): void;
|
|
45
|
+
|
|
46
|
+
declare function setConsent(flags: {
|
|
47
|
+
analytics?: boolean;
|
|
48
|
+
replay?: boolean;
|
|
49
|
+
}): void;
|
|
50
|
+
declare function trackEvent(name: string, props?: Record<string, unknown>): void;
|
|
51
|
+
declare function shutdown(): void;
|
|
52
|
+
declare function getSessionId(): string | null;
|
|
53
|
+
|
|
54
|
+
declare const MetricsProvider: React.FC<{
|
|
55
|
+
config: Config;
|
|
56
|
+
children: React.ReactNode;
|
|
57
|
+
}>;
|
|
58
|
+
declare const useMetrics: () => {
|
|
59
|
+
trackEvent: typeof trackEvent;
|
|
60
|
+
reportBug: typeof reportBug;
|
|
61
|
+
setConsent: typeof setConsent;
|
|
62
|
+
shutdown: typeof shutdown;
|
|
63
|
+
getSessionId: typeof getSessionId;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export { MetricsProvider, useMetrics };
|
package/dist/react.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{createContext as ae,useContext as ce,useEffect as le}from"react";var s=()=>Date.now();var P=(e,t,n)=>(e.addEventListener(t,n,{passive:!0}),()=>e.removeEventListener(t,n)),f=(e,t)=>(document.addEventListener(e,t,{passive:!0}),()=>document.removeEventListener(e,t));var E=(e,t=.1)=>{let n=e*t;return e+(Math.random()*2-1)*n},I=e=>{if(!e||typeof e!="object")return e;let t=["email","phone","password","ssn"],n=Array.isArray(e)?[]:{};for(let o of Object.keys(e)){if(t.includes(o.toLowerCase()))continue;let i=e[o];n[o]=typeof i=="object"?I(i):i}return n},y=(...e)=>{window.__POULET_DEBUG__&&console.log("[poulet]",...e)},O=e=>Uint8Array.from(atob(e),t=>t.charCodeAt(0));var F=Date.now(),A=[],q=()=>F,H=()=>{L();let e=()=>{F=Date.now()},t=f("mousemove",e),n=f("keydown",e),o=f("scroll",e),i=f("touchstart",e),c=P(window,"focus",e),g=P(window,"blur",e),_=f("visibilitychange",e);A=[t,n,o,i,c,g,_]},L=()=>{A.forEach(e=>e()),A=[]};var u="poulet_leader_session",d=!1,z=e=>{let t=localStorage.getItem(u);return t?(d=t===e,d):(localStorage.setItem(u,e),d=!0,!0)},N=e=>{localStorage.getItem(u)===e&&localStorage.removeItem(u),d=!1};var V=(e,t)=>{let n=o=>{if(o.key!==u)return;let i=localStorage.getItem(u),c=i===e||!i;i?(d=i===e,t(d)):(localStorage.setItem(u,e),t(!0),d=!0)};return window.addEventListener("storage",n),()=>window.removeEventListener("storage",n)},T=()=>{var e;return{ua:navigator.userAgent,tz:(e=Intl.DateTimeFormat().resolvedOptions().timeZone)!=null?e:"UTC",dpr:window.devicePixelRatio||1}};var w=!1,W=!1,k="pending",G=!0,J=e=>{G=e},Y=e=>{k=e,G&&typeof navigator!="undefined"&&navigator.doNotTrack==="1"&&(w=!1,W=!1,k="denied")},Z=e=>{typeof e.analytics=="boolean"&&(w=e.analytics,k=w?"granted":"denied"),typeof e.replay=="boolean"&&(W=e.replay)};var K=()=>w===!0;var p,m=[],D=!1;async function ie(e){if(!(!p.hmacPublicKey||!("crypto"in window)))try{let t=O(p.hmacPublicKey),n=await crypto.subtle.importKey("raw",t,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),o=await crypto.subtle.sign("HMAC",n,new TextEncoder().encode(e));return btoa(String.fromCharCode(...new Uint8Array(o)))}catch(t){return}}async function re(e){let t=e.map(c=>I(c)),n=JSON.stringify({projectKey:p.projectKey,items:t}),o=await ie(n);if(navigator.sendBeacon&&!p.debug){let c={type:"application/json"},g=new Blob([n],c);if(navigator.sendBeacon(p.endpoint+"/ingest",g))return!0}return(await fetch(p.endpoint+"/ingest",{method:"POST",headers:{"Content-Type":"application/json",...o?{"x-signature":o}:{}},body:n})).ok}function Q(e){p=e,window.addEventListener("online",x),setInterval(x,5e3)}function l(e){m.push(e),m.length>=10&&x()}async function x(){if(!(D||m.length===0)){D=!0;try{let e=m.splice(0,20);await re(e)||(m.unshift(...e),y("flush failed, will retry"))}catch(e){y("flush error",e)}finally{D=!1}}}var a,r=null,b=null,v,X={projectKey:"",endpoint:"",consent:{default:"pending"},user:{},billing:{heartbeatSec:15,idleSec:60,maxHoursPerDay:6},privacy:{piiFilter:!0,dntRespect:!0,countryHint:"FR"},security:{hmacPublicKey:void 0},features:{bugReporter:!0,replay:!1,sentryBridge:!1},sampling:{heartbeats:1,events:1,bugs:1},debug:!1};function $(e){a={...X,...e,consent:{...X.consent,...e.consent}},window.__POULET_DEBUG__=!!a.debug,Q({endpoint:a.endpoint,projectKey:a.projectKey,hmacPublicKey:a.security.hmacPublicKey,debug:a.debug})}function S(){if(r)return;let e=crypto.randomUUID(),t=T();r={sessionId:e,startedAt:s(),lastActivityAt:s(),active:!0,leader:z(e)},v&&v(),v=V(e,o=>{r&&(r.leader=o)}),H();let n={type:"session.start",sessionId:e,ts:s(),projectKey:a.projectKey,ua:t.ua,tz:t.tz,dpr:t.dpr,consentFlags:{analytics:K(),replay:!1}};l(n),se(),y("session opened",e)}function j(e){if(!r)return;ee(),L(),N(r.sessionId);let t={type:"session.end",sessionId:r.sessionId,ts:s(),reason:e};l(t),x(),v&&v(),r=null,y("session closed",e)}function se(){ee();let e=()=>{if(!r||!K())return;let t=s()-q()>=a.billing.idleSec*1e3,n=document.visibilityState==="visible",o=n&&!t&&r.leader,i=T();if(Math.random()<=a.sampling.heartbeats&&o){let g={type:"heartbeat",sessionId:r.sessionId,ts:s(),active:!0,vis:n,idle:!1,jitter:Math.random(),ua:i.ua,tz:i.tz,dpr:i.dpr,purpose:"billing"};l(g)}let c=E(a.billing.heartbeatSec*1e3,.1);b=window.setTimeout(e,c)};b=window.setTimeout(e,E(a.billing.heartbeatSec*1e3,.1))}function ee(){b&&(clearTimeout(b),b=null)}var h=()=>{var e;return(e=r==null?void 0:r.sessionId)!=null?e:null};function C(e){let t=h();if(!t)return;let n={type:"bug",sessionId:t,ts:s(),title:e.title,description:e.description,severity:e.severity,hasCapture:!!(e.attachments&&e.attachments.length>0),purpose:"diagnostics"};l(n)}var te=!1;function ne(e){var t,n,o,i;te||(J((n=(t=e.privacy)==null?void 0:t.dntRespect)!=null?n:!0),Y((i=(o=e.consent)==null?void 0:o.default)!=null?i:"pending"),$(e),document.visibilityState==="visible"&&S(),document.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&S()}),addEventListener("pagehide",()=>j("pagehide")),te=!0)}function M(e){Z(e),document.visibilityState==="visible"&&S()}function B(e,t){let n=h();if(!n)return;let o={type:"event",sessionId:n,ts:s(),name:e,props:t,purpose:"diagnostics"};l(o)}function R(){j("shutdown")}function U(){return h()}import{jsx as ue}from"react/jsx-runtime";var oe=ae({trackEvent:B,reportBug:C,setConsent:M,shutdown:R,getSessionId:U}),ze=({config:e,children:t})=>(le(()=>{ne(e)},[]),ue(oe.Provider,{value:{trackEvent:B,reportBug:C,setConsent:M,shutdown:R,getSessionId:U},children:t})),Ne=()=>ce(oe);export{ze as MetricsProvider,Ne as useMetrics};
|
|
2
|
+
//# sourceMappingURL=react.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/react.tsx","../src/utils.ts","../src/activity.ts","../src/antifraud.ts","../src/consent.ts","../src/transport.ts","../src/core.ts","../src/bug.ts","../src/index.ts"],"sourcesContent":["// src/react.tsx\nimport React, { createContext, useContext, useEffect } from 'react';\nimport type { Config } from './types';\nimport { init, trackEvent, reportBug, setConsent, shutdown, getSessionId } from './index';\n\nconst Ctx = createContext({ trackEvent, reportBug, setConsent, shutdown, getSessionId });\n\nexport const MetricsProvider: React.FC<{ config: Config; children: React.ReactNode }> = ({ config, children }) => {\n useEffect(() => { init(config); }, []); // eslint-disable-line\n return <Ctx.Provider value={{ trackEvent, reportBug, setConsent, shutdown, getSessionId }}>{children}</Ctx.Provider>;\n};\n\nexport const useMetrics = () => useContext(Ctx);\n","// src/utils.ts\nexport const now = () => Date.now();\n\nexport const uuid = (): string =>\n (crypto?.randomUUID?.() ?? 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (crypto.getRandomValues(new Uint8Array(1))[0] & 0xf) >> 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n }));\n\nexport const isVisible = () => typeof document !== 'undefined' && document.visibilityState === 'visible';\n\nexport const on = <K extends keyof WindowEventMap>(t: Window, type: K, fn: (e: WindowEventMap[K]) => void) => {\n t.addEventListener(type, fn as any, { passive: true });\n return () => t.removeEventListener(type, fn as any);\n};\n\nexport const onDoc = <K extends keyof DocumentEventMap>(type: K, fn: (e: DocumentEventMap[K]) => void) => {\n document.addEventListener(type, fn as any, { passive: true });\n return () => document.removeEventListener(type, fn as any);\n};\n\nexport const clamp = (n: number, min: number, max: number) => Math.max(min, Math.min(max, n));\n\nexport const jitterMs = (baseMs: number, pct = 0.1) => {\n const delta = baseMs * pct;\n return baseMs + (Math.random() * 2 - 1) * delta;\n};\n\nexport const filterPII = (o: any): any => {\n if (!o || typeof o !== 'object') return o;\n const SUSPICIOUS = ['email', 'phone', 'password', 'ssn'];\n const out: any = Array.isArray(o) ? [] : {};\n for (const k of Object.keys(o)) {\n if (SUSPICIOUS.includes(k.toLowerCase())) continue;\n const v = (o as any)[k];\n out[k] = typeof v === 'object' ? filterPII(v) : v;\n }\n return out;\n};\n\nexport const log = (...args: any[]) => {\n if ((window as any).__POULET_DEBUG__) console.log('[poulet]', ...args);\n};\n\nexport const base64ToArrayBuffer = (b64: string) => Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));\n","// src/activity.ts\nimport { isVisible, onDoc, on } from './utils';\n\nlet lastActivity = Date.now();\nlet unsub: Array<() => void> = [];\n\nexport const getLastActivity = () => lastActivity;\n\nexport const startActivityTracking = () => {\n stopActivityTracking();\n const touch = () => { lastActivity = Date.now(); };\n const un1 = onDoc('mousemove', touch);\n const un2 = onDoc('keydown', touch);\n const un3 = onDoc('scroll', touch);\n const un4 = onDoc('touchstart', touch);\n const un5 = on(window, 'focus', touch);\n const un6 = on(window, 'blur', touch);\n const un7 = onDoc('visibilitychange' as any, touch);\n unsub = [un1, un2, un3, un4, un5, un6, un7];\n};\n\nexport const stopActivityTracking = () => {\n unsub.forEach((f) => f());\n unsub = [];\n};\n\nexport const isActive = (idleSec: number) => {\n const idleMs = idleSec * 1000;\n return isVisible() && (Date.now() - lastActivity) < idleMs;\n};\n","// src/antifraud.ts\nconst LS_KEY = 'poulet_leader_session';\nlet leader = false;\n\nexport const becomeLeaderIfFree = (sessionId: string): boolean => {\n const current = localStorage.getItem(LS_KEY);\n if (!current) {\n localStorage.setItem(LS_KEY, sessionId);\n leader = true;\n return true;\n }\n leader = current === sessionId;\n return leader;\n};\n\nexport const relinquishLeadership = (sessionId: string) => {\n const current = localStorage.getItem(LS_KEY);\n if (current === sessionId) {\n localStorage.removeItem(LS_KEY);\n }\n leader = false;\n};\n\nexport const isLeader = () => leader;\n\nexport const handleStorageLeadership = (sessionId: string, onChange: (isLeader: boolean)=>void) => {\n const listener = (e: StorageEvent) => {\n if (e.key !== LS_KEY) return;\n const now = localStorage.getItem(LS_KEY);\n const newLeader = now === sessionId || !now;\n if (!now) { // try claim\n localStorage.setItem(LS_KEY, sessionId);\n onChange(true);\n leader = true;\n } else {\n leader = now === sessionId;\n onChange(leader);\n }\n };\n window.addEventListener('storage', listener);\n return () => window.removeEventListener('storage', listener);\n};\n\nexport const fingerprintLite = () => ({\n ua: navigator.userAgent,\n tz: Intl.DateTimeFormat().resolvedOptions().timeZone ?? 'UTC',\n dpr: window.devicePixelRatio || 1,\n});\n","// src/consent.ts\nimport type { ConsentState } from './types';\n\nlet analyticsAllowed = false;\nlet replayAllowed = false;\nlet state: ConsentState = 'pending';\nlet dntRespected = true;\n\nexport const setDNTPolicy = (respect: boolean) => { dntRespected = respect; };\n\nexport const initConsent = (defaultState: ConsentState) => {\n state = defaultState;\n if (dntRespected && typeof navigator !== 'undefined' && (navigator as any).doNotTrack === '1') {\n analyticsAllowed = false;\n replayAllowed = false;\n state = 'denied';\n }\n};\n\nexport const setConsent = (flags: { analytics?: boolean; replay?: boolean }) => {\n if (typeof flags.analytics === 'boolean') {\n analyticsAllowed = flags.analytics;\n state = analyticsAllowed ? 'granted' : 'denied';\n }\n if (typeof flags.replay === 'boolean') replayAllowed = flags.replay;\n};\n\nexport const consentFlags = () => ({ analytics: analyticsAllowed, replay: replayAllowed, state });\nexport const analyticsOn = () => analyticsAllowed === true;\nexport const replayOn = () => replayAllowed === true;\n","// src/transport.ts\nimport { base64ToArrayBuffer, filterPII, log } from './utils';\nimport type { OutgoingPayload } from './types';\n\ntype TransportConfig = {\n endpoint: string;\n projectKey: string;\n hmacPublicKey?: string; // base64; optional\n debug?: boolean;\n};\n\nlet cfg: TransportConfig;\nlet queue: OutgoingPayload[] = [];\nlet flushing = false;\n\nasync function sign(body: string): Promise<string | undefined> {\n if (!cfg.hmacPublicKey || !('crypto' in window)) return undefined;\n try {\n const keyData = base64ToArrayBuffer(cfg.hmacPublicKey);\n const key = await crypto.subtle.importKey('raw', keyData, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);\n const sig = await crypto.subtle.sign('HMAC', key, new TextEncoder().encode(body));\n return btoa(String.fromCharCode(...new Uint8Array(sig)));\n } catch {\n return undefined;\n }\n}\n\nasync function postBatch(items: OutgoingPayload[]) {\n const sanitized = items.map((i) => filterPII(i));\n const body = JSON.stringify({ projectKey: cfg.projectKey, items: sanitized });\n const sig = await sign(body);\n\n // Try Beacon first\n if (navigator.sendBeacon && !cfg.debug) {\n const headers = { type: 'application/json' };\n const blob = new Blob([body], headers);\n const ok = navigator.sendBeacon(cfg.endpoint + '/ingest', blob);\n if (ok) return true;\n }\n\n // Fallback fetch\n const res = await fetch(cfg.endpoint + '/ingest', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...(sig ? { 'x-signature': sig } : {}) },\n body\n });\n return res.ok;\n}\n\nexport function initTransport(config: TransportConfig) {\n cfg = config;\n window.addEventListener('online', flush);\n setInterval(flush, 5000);\n}\n\nexport function enqueue(payload: OutgoingPayload) {\n queue.push(payload);\n if (queue.length >= 10) void flush();\n}\n\nexport async function flush() {\n if (flushing || queue.length === 0) return;\n flushing = true;\n try {\n const batch = queue.splice(0, 20);\n const ok = await postBatch(batch);\n if (!ok) {\n // put back\n queue.unshift(...batch);\n log('flush failed, will retry');\n }\n } catch (e) {\n log('flush error', e);\n } finally {\n flushing = false;\n }\n}\n","// src/core.ts\nimport { jitterMs, log, now } from './utils';\nimport { startActivityTracking, stopActivityTracking, isActive, getLastActivity } from './activity';\nimport { becomeLeaderIfFree, handleStorageLeadership, relinquishLeadership, isLeader, fingerprintLite } from './antifraud';\nimport { analyticsOn, consentFlags } from './consent';\nimport { initTransport, enqueue, flush } from './transport';\nimport type { Config, SessionState, HeartbeatPayload, SessionStart, SessionEnd } from './types';\n\nlet config: Required<Config>;\nlet session: SessionState | null = null;\nlet hbTimer: number | null = null;\nlet unStorage: (() => void) | undefined;\n\nconst DEFAULTS: Required<Config> = {\n projectKey: '',\n endpoint: '',\n consent: { default: 'pending' },\n user: {},\n billing: { heartbeatSec: 15, idleSec: 60, maxHoursPerDay: 6 },\n privacy: { piiFilter: true, dntRespect: true, countryHint: 'FR' },\n security: { hmacPublicKey: undefined as any },\n features: { bugReporter: true, replay: false, sentryBridge: false },\n sampling: { heartbeats: 1, events: 1, bugs: 1 },\n debug: false,\n};\n\nexport function configure(cfg: Config) {\n config = { ...DEFAULTS, ...cfg, consent: { ...DEFAULTS.consent, ...cfg.consent } } as Required<Config>;\n (window as any).__POULET_DEBUG__ = !!config.debug;\n initTransport({\n endpoint: config.endpoint,\n projectKey: config.projectKey,\n hmacPublicKey: config.security.hmacPublicKey,\n debug: config.debug,\n });\n}\n\nexport function openSession() {\n if (session) return;\n const id = crypto.randomUUID();\n const fp = fingerprintLite();\n session = {\n sessionId: id,\n startedAt: now(),\n lastActivityAt: now(),\n active: true,\n leader: becomeLeaderIfFree(id),\n };\n if (unStorage) unStorage();\n unStorage = handleStorageLeadership(id, (lead) => {\n if (session) session.leader = lead;\n });\n\n startActivityTracking();\n\n const startPayload: SessionStart = {\n type: 'session.start',\n sessionId: id,\n ts: now(),\n projectKey: config.projectKey,\n ua: fp.ua,\n tz: fp.tz,\n dpr: fp.dpr,\n consentFlags: { analytics: analyticsOn(), replay: false },\n };\n enqueue(startPayload);\n scheduleHeartbeats();\n log('session opened', id);\n}\n\nexport function closeSession(reason: SessionEnd['reason']) {\n if (!session) return;\n stopHeartbeats();\n stopActivityTracking();\n relinquishLeadership(session.sessionId);\n const endPayload: SessionEnd = { type: 'session.end', sessionId: session.sessionId, ts: now(), reason };\n enqueue(endPayload);\n void flush();\n if (unStorage) unStorage();\n session = null;\n log('session closed', reason);\n}\n\nfunction scheduleHeartbeats() {\n stopHeartbeats();\n const loop = () => {\n if (!session) return;\n if (!analyticsOn()) return; // consent required\n // @ts-ignore\n const idle = (now() - getLastActivity()) >= config.billing.idleSec * 1000;\n const vis = document.visibilityState === 'visible';\n const active = vis && !idle && session.leader;\n const fp = fingerprintLite();\n\n // @ts-ignore\n if (Math.random() <= config.sampling.heartbeats && active) {\n const hb: HeartbeatPayload = {\n type: 'heartbeat',\n sessionId: session.sessionId,\n ts: now(),\n active: true,\n vis,\n idle: false,\n jitter: Math.random(),\n ua: fp.ua,\n tz: fp.tz,\n dpr: fp.dpr,\n purpose: 'billing',\n };\n enqueue(hb);\n }\n\n // @ts-ignore\n const next = jitterMs(config.billing.heartbeatSec * 1000, 0.1);\n hbTimer = window.setTimeout(loop, next);\n };\n // @ts-ignore\n hbTimer = window.setTimeout(loop, jitterMs(config.billing.heartbeatSec * 1000, 0.1));\n}\n\nfunction stopHeartbeats() {\n if (hbTimer) {\n clearTimeout(hbTimer);\n hbTimer = null;\n }\n}\n\nexport const getSessionIdSafe = () => session?.sessionId ?? null;\n","// src/bug.ts\nimport { enqueue } from './transport';\nimport type { BugPayload } from './types';\nimport { now } from './utils';\nimport { getSessionIdSafe } from './core';\n\nexport function reportBug(payload: {\n title: string; description?: string;\n severity?: 'blocker'|'major'|'minor'|'ux';\n attachments?: Blob[];\n}) {\n const sessionId = getSessionIdSafe();\n if (!sessionId) return;\n const p: BugPayload = {\n type: 'bug',\n sessionId,\n ts: now(),\n title: payload.title,\n description: payload.description,\n severity: payload.severity,\n hasCapture: !!(payload.attachments && payload.attachments.length > 0),\n purpose: 'diagnostics'\n };\n enqueue(p);\n // NOTE: upload des pièces jointes = hors scope core (peut passer par un autre endpoint)\n}\n","// src/index.ts\nimport { configure, openSession, closeSession, getSessionIdSafe } from './core';\nimport { setConsent as _setConsent, initConsent, setDNTPolicy, consentFlags } from './consent';\nimport { enqueue } from './transport';\nimport type { Config, EventPayload } from './types';\nimport { now } from './utils';\nexport * from './types';\nexport { reportBug } from './bug';\n\nlet initialized = false;\n\nexport function init(cfg: Config) {\n if (initialized) return;\n setDNTPolicy(cfg.privacy?.dntRespect ?? true);\n initConsent(cfg.consent?.default ?? 'pending');\n configure(cfg);\n // ouverture paresseuse : dès qu’il y a visibilité/activité\n if (document.visibilityState === 'visible') openSession();\n document.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'visible') openSession();\n });\n // Flush/close sur pagehide\n addEventListener('pagehide', () => closeSession('pagehide'));\n initialized = true;\n}\n\nexport function setConsent(flags: { analytics?: boolean; replay?: boolean }) {\n _setConsent(flags);\n if (document.visibilityState === 'visible') openSession();\n}\n\nexport function trackEvent(name: string, props?: Record<string, unknown>) {\n const sessionId = getSessionIdSafe();\n if (!sessionId) return;\n const ev: EventPayload = {\n type: 'event',\n sessionId,\n ts: now(),\n name,\n props,\n purpose: 'diagnostics',\n };\n enqueue(ev);\n}\n\nexport function shutdown() {\n closeSession('shutdown');\n}\n\nexport function getSessionId() {\n return getSessionIdSafe();\n}\n\nexport function forgetMe() {\n // côté core : rien de persistant par défaut (queue en mémoire).\n // si tu ajoutes IndexedDB/localStorage pour queue offline, purge ici.\n // Pour l’exemple, on ne stocke pas persistantement.\n closeSession('shutdown');\n}\n\nexport const _consentFlags = consentFlags;\n"],"mappings":"AACA,OAAgB,iBAAAA,GAAe,cAAAC,GAAY,aAAAC,OAAiB,QCArD,IAAMC,EAAM,IAAM,KAAK,IAAI,EAW3B,IAAMC,EAAK,CAAiCC,EAAWC,EAASC,KACnEF,EAAE,iBAAiBC,EAAMC,EAAW,CAAE,QAAS,EAAK,CAAC,EAC9C,IAAMF,EAAE,oBAAoBC,EAAMC,CAAS,GAGzCC,EAAQ,CAAmCF,EAASC,KAC7D,SAAS,iBAAiBD,EAAMC,EAAW,CAAE,QAAS,EAAK,CAAC,EACrD,IAAM,SAAS,oBAAoBD,EAAMC,CAAS,GAKtD,IAAME,EAAW,CAACC,EAAgBC,EAAM,KAAQ,CACnD,IAAMC,EAAQF,EAASC,EACvB,OAAOD,GAAU,KAAK,OAAO,EAAI,EAAI,GAAKE,CAC9C,EAEaC,EAAaC,GAAgB,CACtC,GAAI,CAACA,GAAK,OAAOA,GAAM,SAAU,OAAOA,EACxC,IAAMC,EAAa,CAAC,QAAS,QAAS,WAAY,KAAK,EACjDC,EAAW,MAAM,QAAQF,CAAC,EAAI,CAAC,EAAI,CAAC,EAC1C,QAAWG,KAAK,OAAO,KAAKH,CAAC,EAAG,CAC5B,GAAIC,EAAW,SAASE,EAAE,YAAY,CAAC,EAAG,SAC1C,IAAMC,EAAKJ,EAAUG,CAAC,EACtBD,EAAIC,CAAC,EAAI,OAAOC,GAAM,SAAWL,EAAUK,CAAC,EAAIA,CACpD,CACA,OAAOF,CACX,EAEaG,EAAM,IAAIC,IAAgB,CAC9B,OAAe,kBAAkB,QAAQ,IAAI,WAAY,GAAGA,CAAI,CACzE,EAEaC,EAAuBC,GAAgB,WAAW,KAAK,KAAKA,CAAG,EAAIC,GAAMA,EAAE,WAAW,CAAC,CAAC,EC1CrG,IAAIC,EAAe,KAAK,IAAI,EACxBC,EAA2B,CAAC,EAEnBC,EAAkB,IAAMF,EAExBG,EAAwB,IAAM,CACvCC,EAAqB,EACrB,IAAMC,EAAQ,IAAM,CAAEL,EAAe,KAAK,IAAI,CAAG,EAC3CM,EAAMC,EAAM,YAAaF,CAAK,EAC9BG,EAAMD,EAAM,UAAWF,CAAK,EAC5BI,EAAMF,EAAM,SAAUF,CAAK,EAC3BK,EAAMH,EAAM,aAAcF,CAAK,EAC/BM,EAAMC,EAAG,OAAQ,QAASP,CAAK,EAC/BQ,EAAMD,EAAG,OAAQ,OAAQP,CAAK,EAC9BS,EAAMP,EAAM,mBAA2BF,CAAK,EAClDJ,EAAQ,CAACK,EAAKE,EAAKC,EAAKC,EAAKC,EAAKE,EAAKC,CAAG,CAC9C,EAEaV,EAAuB,IAAM,CACtCH,EAAM,QAASc,GAAMA,EAAE,CAAC,EACxBd,EAAQ,CAAC,CACb,ECvBA,IAAMe,EAAS,wBACXC,EAAS,GAEAC,EAAsBC,GAA+B,CAC9D,IAAMC,EAAU,aAAa,QAAQJ,CAAM,EAC3C,OAAKI,GAKLH,EAASG,IAAYD,EACdF,IALH,aAAa,QAAQD,EAAQG,CAAS,EACtCF,EAAS,GACF,GAIf,EAEaI,EAAwBF,GAAsB,CACvC,aAAa,QAAQH,CAAM,IAC3BG,GACZ,aAAa,WAAWH,CAAM,EAElCC,EAAS,EACb,EAIO,IAAMK,EAA0B,CAACC,EAAmBC,IAAwC,CAC/F,IAAMC,EAAYC,GAAoB,CAClC,GAAIA,EAAE,MAAQC,EAAQ,OACtB,IAAMC,EAAM,aAAa,QAAQD,CAAM,EACjCE,EAAYD,IAAQL,GAAa,CAACK,EACnCA,GAKDE,EAASF,IAAQL,EACjBC,EAASM,CAAM,IALf,aAAa,QAAQH,EAAQJ,CAAS,EACtCC,EAAS,EAAI,EACbM,EAAS,GAKjB,EACA,cAAO,iBAAiB,UAAWL,CAAQ,EACpC,IAAM,OAAO,oBAAoB,UAAWA,CAAQ,CAC/D,EAEaM,EAAkB,IAAG,CA3ClC,IAAAC,EA2CsC,OAClC,GAAI,UAAU,UACd,IAAIA,EAAA,KAAK,eAAe,EAAE,gBAAgB,EAAE,WAAxC,KAAAA,EAAoD,MACxD,IAAK,OAAO,kBAAoB,CACpC,GC5CA,IAAIC,EAAmB,GACnBC,EAAgB,GAChBC,EAAsB,UACtBC,EAAe,GAENC,EAAgBC,GAAqB,CAAEF,EAAeE,CAAS,EAE/DC,EAAeC,GAA+B,CACvDL,EAAQK,EACJJ,GAAgB,OAAO,WAAc,aAAgB,UAAkB,aAAe,MACtFH,EAAmB,GACnBC,EAAgB,GAChBC,EAAQ,SAEhB,EAEaM,EAAcC,GAAqD,CACxE,OAAOA,EAAM,WAAc,YAC3BT,EAAmBS,EAAM,UACzBP,EAAQF,EAAmB,UAAY,UAEvC,OAAOS,EAAM,QAAW,YAAWR,EAAgBQ,EAAM,OACjE,EAGO,IAAMC,EAAc,IAAMC,IAAqB,GCjBtD,IAAIC,EACAC,EAA2B,CAAC,EAC5BC,EAAW,GAEf,eAAeC,GAAKC,EAA2C,CAC3D,GAAI,GAACJ,EAAI,eAAiB,EAAE,WAAY,SACxC,GAAI,CACA,IAAMK,EAAUC,EAAoBN,EAAI,aAAa,EAC/CO,EAAM,MAAM,OAAO,OAAO,UAAU,MAAOF,EAAS,CAAE,KAAM,OAAQ,KAAM,SAAU,EAAG,GAAO,CAAC,MAAM,CAAC,EACtGG,EAAM,MAAM,OAAO,OAAO,KAAK,OAAQD,EAAK,IAAI,YAAY,EAAE,OAAOH,CAAI,CAAC,EAChF,OAAO,KAAK,OAAO,aAAa,GAAG,IAAI,WAAWI,CAAG,CAAC,CAAC,CAC3D,OAAQC,EAAA,CACJ,MACJ,CACJ,CAEA,eAAeC,GAAUC,EAA0B,CAC/C,IAAMC,EAAYD,EAAM,IAAKE,GAAMC,EAAUD,CAAC,CAAC,EACzCT,EAAO,KAAK,UAAU,CAAE,WAAYJ,EAAI,WAAY,MAAOY,CAAU,CAAC,EACtEJ,EAAM,MAAML,GAAKC,CAAI,EAG3B,GAAI,UAAU,YAAc,CAACJ,EAAI,MAAO,CACpC,IAAMe,EAAU,CAAE,KAAM,kBAAmB,EACrCC,EAAO,IAAI,KAAK,CAACZ,CAAI,EAAGW,CAAO,EAErC,GADW,UAAU,WAAWf,EAAI,SAAW,UAAWgB,CAAI,EACtD,MAAO,EACnB,CAQA,OALY,MAAM,MAAMhB,EAAI,SAAW,UAAW,CAC9C,OAAQ,OACR,QAAS,CAAE,eAAgB,mBAAoB,GAAIQ,EAAM,CAAE,cAAeA,CAAI,EAAI,CAAC,CAAG,EACtF,KAAAJ,CACJ,CAAC,GACU,EACf,CAEO,SAASa,EAAcC,EAAyB,CACnDlB,EAAMkB,EACN,OAAO,iBAAiB,SAAUC,CAAK,EACvC,YAAYA,EAAO,GAAI,CAC3B,CAEO,SAASC,EAAQC,EAA0B,CAC9CpB,EAAM,KAAKoB,CAAO,EACdpB,EAAM,QAAU,IAASkB,EAAM,CACvC,CAEA,eAAsBA,GAAQ,CAC1B,GAAI,EAAAjB,GAAYD,EAAM,SAAW,GACjC,CAAAC,EAAW,GACX,GAAI,CACA,IAAMoB,EAAQrB,EAAM,OAAO,EAAG,EAAE,EACrB,MAAMS,GAAUY,CAAK,IAG5BrB,EAAM,QAAQ,GAAGqB,CAAK,EACtBC,EAAI,0BAA0B,EAEtC,OAAS,EAAG,CACRA,EAAI,cAAe,CAAC,CACxB,QAAE,CACErB,EAAW,EACf,EACJ,CCpEA,IAAIsB,EACAC,EAA+B,KAC/BC,EAAyB,KACzBC,EAEEC,EAA6B,CAC/B,WAAY,GACZ,SAAU,GACV,QAAS,CAAE,QAAS,SAAU,EAC9B,KAAM,CAAC,EACP,QAAS,CAAE,aAAc,GAAI,QAAS,GAAI,eAAgB,CAAE,EAC5D,QAAS,CAAE,UAAW,GAAM,WAAY,GAAM,YAAa,IAAK,EAChE,SAAU,CAAE,cAAe,MAAiB,EAC5C,SAAU,CAAE,YAAa,GAAM,OAAQ,GAAO,aAAc,EAAM,EAClE,SAAU,CAAE,WAAY,EAAG,OAAQ,EAAG,KAAM,CAAE,EAC9C,MAAO,EACX,EAEO,SAASC,EAAUC,EAAa,CACnCN,EAAS,CAAE,GAAGI,EAAU,GAAGE,EAAK,QAAS,CAAE,GAAGF,EAAS,QAAS,GAAGE,EAAI,OAAQ,CAAE,EAChF,OAAe,iBAAmB,CAAC,CAACN,EAAO,MAC5CO,EAAc,CACV,SAAUP,EAAO,SACjB,WAAYA,EAAO,WACnB,cAAeA,EAAO,SAAS,cAC/B,MAAOA,EAAO,KAClB,CAAC,CACL,CAEO,SAASQ,GAAc,CAC1B,GAAIP,EAAS,OACb,IAAMQ,EAAK,OAAO,WAAW,EACvBC,EAAKC,EAAgB,EAC3BV,EAAU,CACN,UAAWQ,EACX,UAAWG,EAAI,EACf,eAAgBA,EAAI,EACpB,OAAQ,GACR,OAAQC,EAAmBJ,CAAE,CACjC,EACIN,GAAWA,EAAU,EACzBA,EAAYW,EAAwBL,EAAKM,GAAS,CAC1Cd,IAASA,EAAQ,OAASc,EAClC,CAAC,EAEDC,EAAsB,EAEtB,IAAMC,EAA6B,CAC/B,KAAM,gBACN,UAAWR,EACX,GAAIG,EAAI,EACR,WAAYZ,EAAO,WACnB,GAAIU,EAAG,GACP,GAAIA,EAAG,GACP,IAAKA,EAAG,IACR,aAAc,CAAE,UAAWQ,EAAY,EAAG,OAAQ,EAAM,CAC5D,EACAC,EAAQF,CAAY,EACpBG,GAAmB,EACnBC,EAAI,iBAAkBZ,CAAE,CAC5B,CAEO,SAASa,EAAaC,EAA8B,CACvD,GAAI,CAACtB,EAAS,OACduB,GAAe,EACfC,EAAqB,EACrBC,EAAqBzB,EAAQ,SAAS,EACtC,IAAM0B,EAAyB,CAAE,KAAM,cAAe,UAAW1B,EAAQ,UAAW,GAAIW,EAAI,EAAG,OAAAW,CAAO,EACtGJ,EAAQQ,CAAU,EACbC,EAAM,EACPzB,GAAWA,EAAU,EACzBF,EAAU,KACVoB,EAAI,iBAAkBE,CAAM,CAChC,CAEA,SAASH,IAAqB,CAC1BI,GAAe,EACf,IAAMK,EAAO,IAAM,CAEf,GADI,CAAC5B,GACD,CAACiB,EAAY,EAAG,OAEpB,IAAMY,EAAQlB,EAAI,EAAImB,EAAgB,GAAM/B,EAAO,QAAQ,QAAU,IAC/DgC,EAAM,SAAS,kBAAoB,UACnCC,EAASD,GAAO,CAACF,GAAQ7B,EAAQ,OACjCS,EAAKC,EAAgB,EAG3B,GAAI,KAAK,OAAO,GAAKX,EAAO,SAAS,YAAciC,EAAQ,CACvD,IAAMC,EAAuB,CACzB,KAAM,YACN,UAAWjC,EAAQ,UACnB,GAAIW,EAAI,EACR,OAAQ,GACR,IAAAoB,EACA,KAAM,GACN,OAAQ,KAAK,OAAO,EACpB,GAAItB,EAAG,GACP,GAAIA,EAAG,GACP,IAAKA,EAAG,IACR,QAAS,SACb,EACAS,EAAQe,CAAE,CACd,CAGA,IAAMC,EAAOC,EAASpC,EAAO,QAAQ,aAAe,IAAM,EAAG,EAC7DE,EAAU,OAAO,WAAW2B,EAAMM,CAAI,CAC1C,EAEAjC,EAAU,OAAO,WAAW2B,EAAMO,EAASpC,EAAO,QAAQ,aAAe,IAAM,EAAG,CAAC,CACvF,CAEA,SAASwB,IAAiB,CAClBtB,IACA,aAAaA,CAAO,EACpBA,EAAU,KAElB,CAEO,IAAMmC,EAAmB,IAAG,CA/HnC,IAAAC,EA+HsC,OAAAA,EAAArC,GAAA,YAAAA,EAAS,YAAT,KAAAqC,EAAsB,MCzHrD,SAASC,EAAUC,EAIvB,CACC,IAAMC,EAAYC,EAAiB,EACnC,GAAI,CAACD,EAAW,OAChB,IAAME,EAAgB,CAClB,KAAM,MACN,UAAAF,EACA,GAAIG,EAAI,EACR,MAAOJ,EAAQ,MACf,YAAaA,EAAQ,YACrB,SAAUA,EAAQ,SAClB,WAAY,CAAC,EAAEA,EAAQ,aAAeA,EAAQ,YAAY,OAAS,GACnE,QAAS,aACb,EACAK,EAAQF,CAAC,CAEb,CChBA,IAAIG,GAAc,GAEX,SAASC,GAAKC,EAAa,CAXlC,IAAAC,EAAAC,EAAAC,EAAAC,EAYQN,KACJO,GAAaH,GAAAD,EAAAD,EAAI,UAAJ,YAAAC,EAAa,aAAb,KAAAC,EAA2B,EAAI,EAC5CI,GAAYF,GAAAD,EAAAH,EAAI,UAAJ,YAAAG,EAAa,UAAb,KAAAC,EAAwB,SAAS,EAC7CG,EAAUP,CAAG,EAET,SAAS,kBAAoB,WAAWQ,EAAY,EACxD,SAAS,iBAAiB,mBAAoB,IAAM,CAC5C,SAAS,kBAAoB,WAAWA,EAAY,CAC5D,CAAC,EAED,iBAAiB,WAAY,IAAMC,EAAa,UAAU,CAAC,EAC3DX,GAAc,GAClB,CAEO,SAASY,EAAWC,EAAkD,CACzED,EAAYC,CAAK,EACb,SAAS,kBAAoB,WAAWH,EAAY,CAC5D,CAEO,SAASI,EAAWC,EAAcC,EAAiC,CACtE,IAAMC,EAAYC,EAAiB,EACnC,GAAI,CAACD,EAAW,OAChB,IAAME,EAAmB,CACrB,KAAM,QACN,UAAAF,EACA,GAAIG,EAAI,EACR,KAAAL,EACA,MAAAC,EACA,QAAS,aACb,EACAK,EAAQF,CAAE,CACd,CAEO,SAASG,GAAW,CACvBX,EAAa,UAAU,CAC3B,CAEO,SAASY,GAAe,CAC3B,OAAOL,EAAiB,CAC5B,CR1CW,cAAAM,OAAA,oBAJX,IAAMC,GAAMC,GAAc,CAAE,WAAAC,EAAY,UAAAC,EAAW,WAAAC,EAAY,SAAAC,EAAU,aAAAC,CAAa,CAAC,EAE1EC,GAA2E,CAAC,CAAE,OAAAC,EAAQ,SAAAC,CAAS,KACxGC,GAAU,IAAM,CAAEC,GAAKH,CAAM,CAAG,EAAG,CAAC,CAAC,EAC9BT,GAACC,GAAI,SAAJ,CAAa,MAAO,CAAE,WAAAE,EAAY,UAAAC,EAAW,WAAAC,EAAY,SAAAC,EAAU,aAAAC,CAAa,EAAI,SAAAG,EAAS,GAG5FG,GAAa,IAAMC,GAAWb,EAAG","names":["createContext","useContext","useEffect","now","on","t","type","fn","onDoc","jitterMs","baseMs","pct","delta","filterPII","o","SUSPICIOUS","out","k","v","log","args","base64ToArrayBuffer","b64","c","lastActivity","unsub","getLastActivity","startActivityTracking","stopActivityTracking","touch","un1","onDoc","un2","un3","un4","un5","on","un6","un7","f","LS_KEY","leader","becomeLeaderIfFree","sessionId","current","relinquishLeadership","handleStorageLeadership","sessionId","onChange","listener","e","LS_KEY","now","newLeader","leader","fingerprintLite","_a","analyticsAllowed","replayAllowed","state","dntRespected","setDNTPolicy","respect","initConsent","defaultState","setConsent","flags","analyticsOn","analyticsAllowed","cfg","queue","flushing","sign","body","keyData","base64ToArrayBuffer","key","sig","e","postBatch","items","sanitized","i","filterPII","headers","blob","initTransport","config","flush","enqueue","payload","batch","log","config","session","hbTimer","unStorage","DEFAULTS","configure","cfg","initTransport","openSession","id","fp","fingerprintLite","now","becomeLeaderIfFree","handleStorageLeadership","lead","startActivityTracking","startPayload","analyticsOn","enqueue","scheduleHeartbeats","log","closeSession","reason","stopHeartbeats","stopActivityTracking","relinquishLeadership","endPayload","flush","loop","idle","getLastActivity","vis","active","hb","next","jitterMs","getSessionIdSafe","_a","reportBug","payload","sessionId","getSessionIdSafe","p","now","enqueue","initialized","init","cfg","_a","_b","_c","_d","setDNTPolicy","initConsent","configure","openSession","closeSession","setConsent","flags","trackEvent","name","props","sessionId","getSessionIdSafe","ev","now","enqueue","shutdown","getSessionId","jsx","Ctx","createContext","trackEvent","reportBug","setConsent","shutdown","getSessionId","MetricsProvider","config","children","useEffect","init","useMetrics","useContext"]}
|
package/package.json
CHANGED
|
@@ -1,64 +1,63 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "poulet",
|
|
3
|
-
"version": "0.0
|
|
4
|
-
"description": "
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Mesure du temps actif, événements et bugs pour rémunérer les testeurs (Web, RGPD, anti-fraude).",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "dist/index.cjs",
|
|
8
|
+
"module": "dist/index.mjs",
|
|
9
|
+
"unpkg": "dist/index.global.js",
|
|
10
|
+
"jsdelivr": "dist/index.global.js",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"import": "./dist/index.mjs",
|
|
14
|
+
"require": "./dist/index.cjs"
|
|
15
|
+
},
|
|
16
|
+
"./react": {
|
|
17
|
+
"import": "./dist/react.mjs",
|
|
18
|
+
"require": "./dist/react.cjs"
|
|
19
|
+
},
|
|
20
|
+
"./iife": "./dist/index.global.js",
|
|
21
|
+
"./types": "./dist/index.d.ts"
|
|
22
|
+
},
|
|
23
|
+
"types": "dist/index.d.ts",
|
|
12
24
|
"files": [
|
|
13
|
-
"
|
|
14
|
-
"
|
|
25
|
+
"dist",
|
|
26
|
+
"README.md",
|
|
27
|
+
"LICENSE"
|
|
15
28
|
],
|
|
29
|
+
"sideEffects": false,
|
|
16
30
|
"scripts": {
|
|
17
|
-
"build": "
|
|
18
|
-
"
|
|
19
|
-
"lint": "eslint
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
"homepage": "https://bigyouth.org",
|
|
23
|
-
"author": {
|
|
24
|
-
"name": "Alex Toudic",
|
|
25
|
-
"mail": "alex@bigyouth.fr",
|
|
26
|
-
"url": "https://bigyouth.fr"
|
|
31
|
+
"build": "tsup",
|
|
32
|
+
"check": "tsc -p tsconfig.json --noEmit",
|
|
33
|
+
"lint": "eslint .",
|
|
34
|
+
"test": "echo \"(add vitest if needed)\"",
|
|
35
|
+
"prepublishOnly": "npm run check && npm run build"
|
|
27
36
|
},
|
|
28
|
-
"
|
|
29
|
-
|
|
30
|
-
"type": "git",
|
|
31
|
-
"url": "git+https://github.com/bigyouth/poulet.git"
|
|
32
|
-
},
|
|
33
|
-
"bugs": {
|
|
34
|
-
"url": "https://github.com/bigyouth/poulet/issues"
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"react": ">=17"
|
|
35
39
|
},
|
|
36
40
|
"devDependencies": {
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"eslint-config-standard": "^6.2.1",
|
|
46
|
-
"eslint-plugin-promise": "^3.4.0",
|
|
47
|
-
"eslint-plugin-standard": "^2.0.1",
|
|
48
|
-
"mkdirp": "^0.5.1",
|
|
49
|
-
"rollup": "^0.41.4",
|
|
50
|
-
"rollup-plugin-babel": "^2.7.1",
|
|
51
|
-
"rollup-plugin-local-resolve": "^1.0.7",
|
|
52
|
-
"uglify-js": "^2.7.5",
|
|
53
|
-
"webpack": "^2.2.1"
|
|
41
|
+
"@types/node": "^20.11.30",
|
|
42
|
+
"@types/react": "^18.3.0",
|
|
43
|
+
"eslint": "^8.57.0",
|
|
44
|
+
"eslint-config-prettier": "^9.1.0",
|
|
45
|
+
"eslint-plugin-import": "^2.29.1",
|
|
46
|
+
"eslint-plugin-react": "^7.35.0",
|
|
47
|
+
"tsup": "^8.0.1",
|
|
48
|
+
"typescript": "^5.5.4"
|
|
54
49
|
},
|
|
50
|
+
"keywords": [
|
|
51
|
+
"metrics",
|
|
52
|
+
"heartbeat",
|
|
53
|
+
"web",
|
|
54
|
+
"testing",
|
|
55
|
+
"stripe",
|
|
56
|
+
"rgpd",
|
|
57
|
+
"fraud"
|
|
58
|
+
],
|
|
55
59
|
"dependencies": {
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
},
|
|
59
|
-
"browserify": {
|
|
60
|
-
"transform": [
|
|
61
|
-
"babelify"
|
|
62
|
-
]
|
|
60
|
+
"cors": "^2.8.5",
|
|
61
|
+
"express": "^5.1.0"
|
|
63
62
|
}
|
|
64
63
|
}
|
package/LICENSE
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
The MIT License (MIT)
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2015 Alexandre Toudic
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
22
|
-
|
package/dist/.gitkeep
DELETED
|
File without changes
|