@walkeros/web-source-session 3.2.0 → 3.3.0-next-1776098542393
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 +6 -0
- package/dist/dev.d.mts +4 -0
- package/dist/dev.d.ts +4 -0
- package/dist/dev.js +1 -1
- package/dist/dev.js.map +1 -1
- package/dist/dev.mjs +1 -1
- package/dist/dev.mjs.map +1 -1
- package/dist/index.d.mts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/walkerOS.json +24 -2
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -145,6 +145,12 @@ When a new session is detected, the source pushes a `session start` event:
|
|
|
145
145
|
}
|
|
146
146
|
```
|
|
147
147
|
|
|
148
|
+
Marketing click IDs detected in the URL (e.g. `gclid`, `fbclid`) resolve to a
|
|
149
|
+
canonical `platform` field on the session data (e.g. `google`, `meta`). Extend
|
|
150
|
+
or override the built-in registry via `settings.clickIds` — entries with a
|
|
151
|
+
`param` matching a default override the platform name in place, new params
|
|
152
|
+
append to the priority list.
|
|
153
|
+
|
|
148
154
|
## Migration from Browser Source
|
|
149
155
|
|
|
150
156
|
If you were using the browser source with session enabled:
|
package/dist/dev.d.mts
CHANGED
|
@@ -22,6 +22,10 @@ declare const SettingsSchema: z.ZodObject<{
|
|
|
22
22
|
}>>>;
|
|
23
23
|
deviceAge: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
|
|
24
24
|
cb: z.ZodOptional<z.ZodAny>;
|
|
25
|
+
clickIds: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
26
|
+
param: z.ZodString;
|
|
27
|
+
platform: z.ZodString;
|
|
28
|
+
}, z.core.$strip>>>;
|
|
25
29
|
}, z.core.$strip>;
|
|
26
30
|
type Settings = z.infer<typeof SettingsSchema>;
|
|
27
31
|
|
package/dist/dev.d.ts
CHANGED
|
@@ -22,6 +22,10 @@ declare const SettingsSchema: z.ZodObject<{
|
|
|
22
22
|
}>>>;
|
|
23
23
|
deviceAge: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
|
|
24
24
|
cb: z.ZodOptional<z.ZodAny>;
|
|
25
|
+
clickIds: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
26
|
+
param: z.ZodString;
|
|
27
|
+
platform: z.ZodString;
|
|
28
|
+
}, z.core.$strip>>>;
|
|
25
29
|
}, z.core.$strip>;
|
|
26
30
|
type Settings = z.infer<typeof SettingsSchema>;
|
|
27
31
|
|
package/dist/dev.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.prototype.hasOwnProperty,r=(e,n)=>{for(var o in n)t(e,o,{get:n[o],enumerable:!0})},i={};r(i,{examples:()=>f,schemas:()=>a}),module.exports=(e=i,((e,r,i,a)=>{if(r&&"object"==typeof r||"function"==typeof r)for(let c of o(r))s.call(e,c)||c===i||t(e,c,{get:()=>r[c],enumerable:!(a=n(r,c))||a.enumerable});return e})(t({},"__esModule",{value:!0}),e));var a={};r(a,{SettingsSchema:()=>l,settings:()=>d});var c=require("@walkeros/core/dev"),u=require("@walkeros/core/dev"),l=u.z.object({storage:u.z.boolean().default(!1).describe("Enable persistent storage for session/device IDs").optional(),consent:u.z.union([u.z.string(),u.z.array(u.z.string())]).describe("Consent key(s) required to enable storage mode").optional(),length:u.z.number().default(30).describe("Session timeout in minutes").optional(),pulse:u.z.boolean().default(!1).describe("Keep session alive on each event").optional(),sessionKey:u.z.string().default("elbSessionId").describe("Storage key for session ID").optional(),sessionStorage:u.z.enum(["local","session"]).default("local").describe("Storage type for session").optional(),deviceKey:u.z.string().default("elbDeviceId").describe("Storage key for device ID").optional(),deviceStorage:u.z.enum(["local","session"]).default("local").describe("Storage type for device").optional(),deviceAge:u.z.number().default(30).describe("Device ID age in days").optional(),cb:u.z.any().describe("Custom session callback function or false to disable").optional()}),d=(0,c.zodToSchema)(l),f={};r(f,{createTrigger:()=>Z,step:()=>g,trigger:()=>ee});var g={};r(g,{newMarketingSession:()=>p,returningVisitor:()=>v});var p={trigger:{type:"load",options:{url:"https://example.com/?utm_source=google&utm_medium=cpc&utm_campaign=winter-sale"}},in:{storage:!0},out:{name:"session start",data:{isStart:!0,isNew:!0,count:1,runs:1,storage:!0,id:"s3ss10n-id",device:"d3v1c3-id",start:17e11,marketing:!0,source:"google",medium:"cpc",campaign:"winter-sale"},entity:"session",action:"start"}},v={trigger:{type:"load",options:{referrer:"https://google.com"}},in:{storage:!0},out:{name:"session start",data:{isStart:!0,isNew:!1,count:3,runs:1,storage:!0,id:"n3w-s3ss10n",device:"d3v1c3-id",start:1700001e6,referrer:"google.com"},entity:"session",action:"start"}},h=require("@walkeros/core"),y=require("@walkeros/core"),m=require("@walkeros/core"),b=require("@walkeros/core"),w=require("@walkeros/core"),k=require("@walkeros/core"),O=require("@walkeros/core"),x=require("@walkeros/core"),C=require("@walkeros/core"),j=require("@walkeros/core"),S=require("@walkeros/core"),A=require("@walkeros/core"),I={Action:"action",Actions:"actions",Config:"config",Consent:"consent",Context:"context",Custom:"custom",Destination:"destination",Elb:"elb",Globals:"globals",Hook:"hook",Init:"init",Link:"link",On:"on",Prefix:"data-elb",Ready:"ready",Run:"run",Session:"session",Shutdown:"shutdown",User:"user",Walker:"walker"};function q(e,t){return e.storeId&&t.stores[e.storeId]?t.stores[e.storeId]:t.stores.__cache}function D(e){var t;const n={};for(const[o,s]of Object.entries(e)){const e=null==(t=s.config)?void 0:t.next;e&&!(0,O.isRouteArray)(e)?n[o]={next:e}:n[o]={}}return n}function _(e,t){const n=e.config||{},o=e[t];return void 0!==o?{config:{...n,[t]:o},chainValue:o}:{config:n,chainValue:void 0}}function $(e,t={}){if(!e)return[];if(Array.isArray(e))return e;const n=[],o=new Set;let s=e;for(;s&&t[s]&&!o.has(s);){o.add(s),n.push(s);const e=t[s].next;if(Array.isArray(e)){n.push(...e);break}s=e}return n}async function P(e,t,n){if(t.init&&!t.config.init){const o=t.type||"unknown",s=e.logger.scope(`transformer:${o}`),r={collector:e,logger:s,id:n,ingest:(0,O.createIngest)(n),config:t.config,env:R(t.config.env)};s.debug("init");const i=await(0,O.useHooks)(t.init,"TransformerInit",e.hooks)(r);if(!1===i)return!1;t.config={...i||t.config,env:(null==i?void 0:i.env)||t.config.env,init:!0},s.debug("init done")}return!0}async function N(e,t,n,o,s,r){const i=t.type||"unknown",a=e.logger.scope(`transformer:${i}`),c={collector:e,logger:a,id:n,ingest:s,config:t.config,env:{...R(t.config.env),...r?{respond:r}:{}}};a.debug("push",{event:o.name});const u=await(0,O.useHooks)(t.push,"TransformerPush",e.hooks)(o,c);return a.debug("push done"),u}async function E(e,t,n,o,s,r,i){var a,c,u,l,d,f;i&&(null==s?void 0:s._meta)&&(s._meta.chainPath=i);let g=o,p=r;for(const o of n){const r=t[o];if(!r){e.logger.warn(`Transformer not found: ${o}`);continue}if(s&&s._meta&&s._meta.path.length>256)return e.logger.error(`Max path length exceeded at ${o}`),{event:null,respond:p};if(s&&s._meta&&(s._meta.hops++,s._meta.path.push(o)),!await(0,O.tryCatchAsync)(P)(e,r,o))return e.logger.error(`Transformer init failed: ${o}`),{event:null,respond:p};if(i&&void 0!==(null==(c=null==(a=r.config)?void 0:a.chainMocks)?void 0:c[i])){const t=r.config.chainMocks[i];e.logger.scope(`transformer:${r.type||"unknown"}`).debug("chainMock",{chain:i}),g=t;continue}if(void 0!==(null==(u=r.config)?void 0:u.mock)){e.logger.scope(`transformer:${r.type||"unknown"}`).debug("mock"),g=r.config.mock;continue}if(null==(l=r.config)?void 0:l.disabled)continue;const v=null==(d=r.config)?void 0:d.cache,h=v?(0,O.compileCache)(v):void 0,y=h?q(h,e):void 0;let m;if(h&&y){const e=(0,O.buildCacheContext)(s,g),t=(0,O.checkCache)(h,y,e,`t:${o}`);if("HIT"===(null==t?void 0:t.status)&&t.value){if(g=t.value,h.full)return{event:g,respond:p};continue}"MISS"===(null==t?void 0:t.status)&&(m={key:t.key,ttl:t.rule.ttl})}const b=r.config.before;if(b){const n=$("string"==typeof b||Array.isArray(b)&&!(0,O.isRouteArray)(b)?b:(0,O.resolveNext)((0,O.compileNext)(b),(0,O.buildCacheContext)(s,g))||void 0,D(t));if(n.length>0){const o=await E(e,t,n,g,s,p,i);if(null===o.event)return{event:null,respond:null!=(f=o.respond)?f:p};o.respond&&(p=o.respond),g=Array.isArray(o.event)?o.event[0]:o.event}}const w=await(0,O.tryCatchAsync)(N,t=>(e.logger.scope(`transformer:${r.type||"unknown"}`).error("Push failed",{error:t}),!1))(e,r,o,g,s,p);if(!1===w)return{event:null,respond:p};if(Array.isArray(w)){const r=n.slice(n.indexOf(o)+1),a=await Promise.all(w.map(async n=>{const o=n.event||g,a=s?{...s,_meta:{...s._meta,path:[...s._meta.path]}}:(0,O.createIngest)("unknown");if(n.next){let s=n.next;if((0,O.isRouteArray)(n.next)){const e=(0,O.compileNext)(n.next);s=(0,O.resolveNext)(e,(0,O.buildCacheContext)(a,o))}if(s){const n=$(s,D(t));if(n.length>0)return E(e,t,n,o,a,p,i)}return{event:o,respond:p}}return r.length>0?E(e,t,r,o,a,p,i):{event:o,respond:p}}));let c=p;const u=[];for(const e of a.flat())if(null!==e)if(e&&"object"==typeof e&&"event"in e){const t=e;if(t.respond&&(c=t.respond),null===t.event)continue;Array.isArray(t.event)?u.push(...t.event):u.push(t.event)}else u.push(e);return 0===u.length?{event:null,respond:c}:1===u.length?{event:u[0],respond:c}:{event:u,respond:c}}if(w&&"object"==typeof w){const{event:n,respond:o,next:r}=w;if(o&&(p=o),r){let o=r;if((0,O.isRouteArray)(r)){const e=(0,O.compileNext)(r);if(o=(0,O.resolveNext)(e,(0,O.buildCacheContext)(s,g)),!o){n&&(g=n);continue}}const a=$(o,D(t));return a.length>0?E(e,t,a,n||g,s,p,i):(e.logger.warn(`Branch target not found: ${JSON.stringify(r)}`),{event:null,respond:p})}n&&(g=n)}if(m&&y&&(0,O.storeCache)(y,m.key,g,m.ttl),(!w||"object"==typeof w&&!w.next)&&r.config.next&&(0,O.isRouteArray)(r.config.next)){const n=r.config.next,o=(0,O.compileNext)(n),a=(0,O.resolveNext)(o,(0,O.buildCacheContext)(s,g));if(a){const n=$(a,D(t));if(n.length>0)return E(e,t,n,g,s,p,i)}return{event:g,respond:p}}}return{event:g,respond:p}}function R(e){return e&&(0,O.isObject)(e)?e:{}}async function M(e,t,n){var o;const{code:s,config:r={},env:i={},primary:a,next:c,before:u,cache:l}=n;let d,f=(0,k.createIngest)(t);const g=l?(0,k.compileCache)({...l,full:null==(o=l.full)||o}):void 0,p=(0,k.compileNext)(c),v=Array.isArray(c)&&(0,k.isRouteArray)(c)||!p?void 0:$((0,k.resolveNext)(p),D(e.transformers)),h=(0,k.compileNext)(u),y=Array.isArray(u)&&(0,k.isRouteArray)(u)||!h?void 0:$((0,k.resolveNext)(h),D(e.transformers)),m=e.logger.scope("source").scope(t),b={push:async(n,o={})=>{let s=n;const i=null!=y?y:h?$((0,k.resolveNext)(h,(0,k.buildCacheContext)(f)),D(e.transformers)):[];if(i.length>0&&e.transformers&&Object.keys(e.transformers).length>0){const n=await E(e,e.transformers,i,s,f,d,`source.${t}.before`);if(null===n.event)return{ok:!0};n.respond&&(d=n.respond),s=Array.isArray(n.event)?n.event[0]:n.event}if(g){const n=q(g,e);if(n){const e=(0,k.buildCacheContext)(f),o=(0,k.checkCache)(g,n,e,`s:${t}`);if(o){if("HIT"===o.status&&void 0!==o.value&&g.full){let t=o.value;return o.rule.update&&(t=await(0,k.applyUpdate)(t,o.rule.update,{...e,cache:{status:"HIT"}})),null==d||d(t),{ok:!0}}if("MISS"===o.status&&g.full&&d){const t=d,s=o.rule.update,r={...e,cache:{status:"MISS"}};d=e=>{(0,k.storeCache)(n,o.key,e,o.rule.ttl),s?(0,k.applyUpdate)(e,s,r).then(e=>t(e)):t(e)}}"MISS"!==o.status||g.full||(0,k.storeCache)(n,o.key,!0,o.rule.ttl)}}}const a=null!=v?v:p?$((0,k.resolveNext)(p,(0,k.buildCacheContext)(f)),D(e.transformers)):[];return e.push(s,{...o,id:t,ingest:f,respond:d,mapping:r,preChain:a})},command:e.command,sources:e.sources,elb:e.sources.elb.push,logger:m,...i},w={collector:e,logger:m,id:t,config:r,env:b,setIngest:async n=>{if(!r.ingest)return void(f=(0,k.createIngest)(t));const o=await(0,k.getMappingValue)(n,r.ingest,{collector:e}),s=(0,k.createIngest)(t);f={...s,...o,_meta:s._meta}},setRespond:e=>{d=e}},O=await(0,k.tryCatchAsync)(s)(w);if(!O)return;const x=O.type||"unknown",C=e.logger.scope(x).scope(t);return b.logger=C,a&&(O.config={...O.config,primary:a}),O}function z(e,t,n,o,s){if(!t.on)return;const r=t.type||"unknown",i=e.logger.scope(r).scope("on").scope(o),a={collector:e,logger:i,id:n,config:t.config,data:s,env:V(t.env,t.config.env)};(0,w.tryCatch)(t.on)(o,a)}async function H(e,t,n,o){let s,r=n||[];switch(n||(r=e.on[t]||[]),t){case I.Consent:s=o||e.consent;break;case I.Session:s=e.session;break;case I.User:s=o||e.user;break;case I.Custom:s=o||e.custom;break;case I.Globals:s=o||e.globals;break;case I.Config:s=o||e.config;break;case I.Ready:case I.Run:default:s=void 0}let i=!1;for(const n of Object.values(e.sources))n.on&&!1===await(0,w.tryCatchAsync)(n.on)(t,s)&&(i=!0);if(Object.entries(e.destinations).forEach(([n,o])=>{if(o.on){if(!o.config.init)return o.queueOn=o.queueOn||[],void o.queueOn.push({type:t,data:s});z(e,o,n,t,s)}}),(Object.keys(e.pending.sources).length>0||Object.keys(e.pending.destinations).length>0)&&await async function(e,t){var n,o;for(const[o,s]of Object.entries(e.pending.sources)){if(!e.pending.sources[o]||e.sources[o])continue;const r=null==(n=s.config)?void 0:n.require;if(!r)continue;const i=r.indexOf(t);if(-1===i)continue;if(r.splice(i,1),r.length>0)continue;delete e.pending.sources[o];const a=await M(e,o,s);a&&(e.sources[o]=a)}for(const[n,s]of Object.entries(e.pending.destinations)){if(!e.pending.destinations[n]||e.destinations[n])continue;const r=null==(o=s.config)?void 0:o.require;if(!r)continue;const i=r.indexOf(t);if(-1===i)continue;if(r.splice(i,1),r.length>0)continue;delete e.pending.destinations[n];const a=J(s);!1!==a.config.queue&&(a.queuePush=[...e.queue]),e.destinations[n]=a}}(e,t),!r.length)return!i;switch(t){case I.Consent:!function(e,t,n){const o=n||e.consent;t.forEach(t=>{Object.keys(o).filter(e=>e in t).forEach(n=>{(0,w.tryCatch)(t[n])(e,o)})})}(e,r,o);break;case I.Ready:case I.Run:c=r,(a=e).allowed&&c.forEach(e=>{(0,w.tryCatch)(e)(a)});break;case I.Session:!function(e,t){e.session&&t.forEach(t=>{(0,w.tryCatch)(t)(e,e.session)})}(e,r);break;default:r.forEach(t=>{"function"==typeof t&&(0,w.tryCatch)(t)(e,s)})}var a,c;return!i}function K(e,t,n,o){if(!e)return[];if(t){const e=(0,m.resolveNext)(t,(0,m.buildCacheContext)(o));return e?$(e,D(n)):[]}return $(e,D(n))}async function T(e,t,n){const{code:o,config:s={},env:r={},before:i,next:a,cache:c}=t;if(!(0,m.isFunction)(o.push))return F({ok:!1,failed:{invalid:{type:"invalid",error:"Destination code must have a push method"}}});const u=n||s||{init:!1};let l=i?{...u,before:i}:{...u};a&&(l={...l,next:a}),c&&(l={...l,cache:c});const d={...o,config:l,env:V(o.env,r)};let f=d.config.id;if(!f)do{f=(0,m.getId)(4)}while(e.destinations[f]);return e.destinations[f]=d,!1!==d.config.queue&&(d.queuePush=[...e.queue]),G(e,void 0,{},{[f]:d})}async function G(e,t,n={},o){const{allowed:s,consent:r,globals:i,user:a}=e;if(!s)return F({ok:!1});t&&(e.queue.push(t),e.status.in++),o||(o=e.destinations);const c=await Promise.all(Object.entries(o||{}).map(async([o,s])=>{var c,u,l;if(s.config.disabled)return{id:o,destination:s,skipped:!0};let d=(s.queuePush||[]).map(e=>({...e,consent:r,user:a,globals:i}));s.queuePush=[];const f=n.ingest?{...n.ingest,_meta:{...n.ingest._meta,path:[...n.ingest._meta.path]}}:(0,m.createIngest)("unknown");if(t){const e=(0,m.clone)(t);d.push(e)}if(!d.length&&!(null==(c=s.queueOn)?void 0:c.length))return{id:o,destination:s,skipped:!0};if(!d.length&&(null==(u=s.queueOn)?void 0:u.length)){const t=await(0,m.tryCatchAsync)(U)(e,s,o);return{id:o,destination:s,skipped:!t}}const g=[],p=d.filter(e=>{const t=(0,m.getGrantedConsent)(s.config.consent,r,e.consent);return!t||(e.consent=t,g.push(e),!1)});if(s.queuePush.push(...p),!g.length)return{id:o,destination:s,queue:d};if(!await(0,m.tryCatchAsync)(U)(e,s,o))return{id:o,destination:s,queue:d};let v,h;s.dlq||(s.dlq=[]);const y=s.config.before,b=K(y,y&&(0,m.isRouteArray)(y)?(0,m.compileNext)(y):void 0,e.transformers,f),w=s.config.next,k=w&&(0,m.isRouteArray)(w)?(0,m.compileNext)(w):void 0,O=null==(l=s.config)?void 0:l.cache,x=O?(0,m.compileCache)(O):void 0,C=x?q(x,e):void 0;let j=0;return await Promise.all(g.map(async t=>{let r;if((null==x?void 0:x.full)&&C){const e=(0,m.buildCacheContext)(f,t),n=(0,m.checkCache)(x,C,e,`d:${o}`);if("HIT"===(null==n?void 0:n.status))return t;"MISS"===(null==n?void 0:n.status)&&(r={key:n.key,ttl:n.rule.ttl})}let i=t,a=n.respond;if(b.length>0&&e.transformers&&Object.keys(e.transformers).length>0){const s=await E(e,e.transformers,b,t,f,n.respond,`destination.${o}.before`);if(null===s.event)return t;s.respond&&(a=s.respond),i=Array.isArray(s.event)?s.event[0]:s.event}if(x&&!x.full&&C){const e=(0,m.buildCacheContext)(f,i),n=(0,m.checkCache)(x,C,e,`d:${o}`);if("HIT"===(null==n?void 0:n.status))return t;"MISS"===(null==n?void 0:n.status)&&(r={key:n.key,ttl:n.rule.ttl})}const c=Date.now();let u=!1;const l=await(0,m.tryCatchAsync)(B,t=>{const n=s.type||"unknown";e.logger.scope(n).error("Push failed",{error:t,event:i.name}),v=t,u=!0,s.dlq.push([i,t])})(e,s,o,i,f,a);if(j+=Date.now()-c,r&&C&&void 0===s.config.mock&&(0,m.storeCache)(C,r.key,null==l||l,r.ttl),void 0!==l&&(h=l),!u&&w){void 0!==l&&(f._response=l);const t=K(w,k,e.transformers,f);if(t.length>0&&e.transformers&&Object.keys(e.transformers).length>0){const n=await E(e,e.transformers,t,i,f,a,`destination.${o}.next`);n.respond&&(a=n.respond)}}return t})),{id:o,destination:s,error:v,response:h,totalDuration:j}})),u={},l={},d={};for(const t of c){if(t.skipped)continue;const n={type:t.destination.type||"unknown",data:t.response};e.status.destinations[t.id]||(e.status.destinations[t.id]={count:0,failed:0,duration:0});const o=e.status.destinations[t.id],s=Date.now();t.error?(n.error=t.error,d[t.id]=n,o.failed++,o.lastAt=s,o.duration+=t.totalDuration||0,e.status.failed++):t.queue&&t.queue.length?l[t.id]=n:(u[t.id]=n,o.count++,o.lastAt=s,o.duration+=t.totalDuration||0,e.status.out++)}return F({event:t,...Object.keys(u).length&&{done:u},...Object.keys(l).length&&{queued:l},...Object.keys(d).length&&{failed:d}})}async function U(e,t,n){var o;if(t.init&&!t.config.init){const s=t.type||"unknown",r=e.logger.scope(s),i={collector:e,logger:r,id:n,config:t.config,env:V(t.env,t.config.env)};r.debug("init");const a=await(0,m.useHooks)(t.init,"DestinationInit",e.hooks)(i);if(!1===a)return a;if(t.config={...a||t.config,init:!0},null==(o=t.queueOn)?void 0:o.length){const o=t.queueOn;t.queueOn=[];for(const{type:s,data:r}of o)z(e,t,n,s,r)}r.debug("init done")}return!0}async function B(e,t,n,o,s,r){const{config:i}=t,a=await(0,m.processEventMapping)(o,i,e);if(a.ignore)return!1;const c=t.type||"unknown",u=e.logger.scope(c),l={collector:e,logger:u,id:n,config:i,data:a.data,rule:a.mapping,ingest:s,env:{...V(t.env,i.env),...r?{respond:r}:{}}};if(void 0!==i.mock)return u.debug("mock",{event:a.event.name}),i.mock;const d=a.mapping,f=a.mappingKey||"* *";if(!(null==d?void 0:d.batch)||!t.pushBatch||void 0!==i.mock){u.debug("push",{event:a.event.name});const n=await(0,m.useHooks)(t.push,"DestinationPush",e.hooks)(a.event,l);return u.debug("push done"),n}{if(t.batches=t.batches||{},!t.batches[f]){const o={key:f,events:[],data:[]};t.batches[f]={batched:o,batchFn:(0,m.debounce)(()=>{const o=t.batches[f].batched,a={collector:e,logger:u,id:n,config:i,data:void 0,rule:d,ingest:s,env:{...V(t.env,i.env),...r?{respond:r}:{}}};u.debug("push batch",{events:o.events.length}),(0,m.useHooks)(t.pushBatch,"DestinationPushBatch",e.hooks)(o,a),u.debug("push batch done"),o.events=[],o.data=[]},d.batch)}}const o=t.batches[f];o.batched.events.push(a.event),(0,m.isDefined)(a.data)&&o.batched.data.push(a.data),o.batchFn()}return!0}function F(e){return{ok:!(null==e?void 0:e.failed),...e}}function J(e){const{code:t,config:n={},env:o={},cache:s}=e,{config:r}=_(e,"before"),{config:i}=_({...e,config:r},"next"),a={...t.config,...n,...i};s&&(a.cache=s);const c=V(t.env,o);return{...t,config:a,env:c}}function V(e,t){return e||t?t?e&&(0,m.isObject)(e)&&(0,m.isObject)(t)?{...e,...t}:t:e:{}}async function L(e,t,n){const o=Object.entries(e).map(async([e,o])=>{var s;const r=o.destroy;if(!r)return;const i=o.type||"unknown",a=n.scope(i),c={id:e,config:o.config,env:null!=(s=o.env)?s:{},logger:a};try{await Promise.race([r(c),new Promise((n,o)=>setTimeout(()=>o(new Error(`${t} '${e}' destroy timed out`)),5e3))])}catch(n){a.error(`${t} '${e}' destroy failed: ${n}`)}});await Promise.allSettled(o)}async function W(e,t,n,o){let s,r,i=!1;switch(t){case I.Config:(0,C.isObject)(n)&&((0,x.assign)(e.config,n,{shallow:!1}),r=n,i=!0);break;case I.Consent:if((0,C.isObject)(n)){const{update:t}=function(e,t){const n={};return Object.entries(t).forEach(([e,t])=>{n[e]=!!t}),e.consent=(0,h.assign)(e.consent,n),{update:n}}(e,n);r=t,i=!0}break;case I.Custom:(0,C.isObject)(n)&&(e.custom=(0,x.assign)(e.custom,n),r=n,i=!0);break;case I.Destination:(0,C.isObject)(n)&&("code"in n&&(0,C.isObject)(n.code)?s=await T(e,n,o):(0,x.isFunction)(n.push)&&(s=await T(e,{code:n},o)));break;case I.Globals:(0,C.isObject)(n)&&(e.globals=(0,x.assign)(e.globals,n),r=n,i=!0);break;case I.On:(0,x.isString)(n)&&await async function(e,t,n){const o=e.on,s=o[t]||[],r=(0,b.isArray)(n)?n:[n];r.forEach(e=>{s.push(e)}),o[t]=s,await H(e,t,r)}(e,n,o);break;case I.Ready:i=!0;break;case I.Run:s=await async function(e,t){return e.allowed=!0,e.count=0,e.group=(0,x.getId)(),e.timing=Date.now(),t&&(t.consent&&(e.consent=(0,x.assign)(e.consent,t.consent)),t.user&&(e.user=(0,x.assign)(e.user,t.user)),t.globals&&(e.globals=(0,x.assign)(e.config.globalsStatic||{},t.globals)),t.custom&&(e.custom=(0,x.assign)(e.custom,t.custom))),Object.values(e.destinations).forEach(e=>{e.queuePush=[]}),e.queue=[],e.round++,await G(e)}(e,n),i=!0;break;case I.Session:i=!0;break;case I.Shutdown:await async function(e){const t=e.logger;await L(e.sources,"source",t),await L(e.destinations,"destination",t),await L(e.transformers,"transformer",t),await L(e.stores,"store",t)}(e);break;case I.User:(0,C.isObject)(n)&&((0,x.assign)(e.user,n,{shallow:!1}),r=n,i=!0)}return i&&(await H(e,t,void 0,r),s=await G(e)),s||F({ok:!0})}function Q(e,t){if(!t.name)throw new Error("Event name is required");const[n,o]=t.name.split(" ");if(!n||!o)throw new Error("Event name is invalid");++e.count;const{timestamp:s=Date.now(),group:r=e.group,count:i=e.count}=t,{name:a=`${n} ${o}`,data:c={},context:u={},globals:l=e.globals,custom:d={},user:f=e.user,nested:g=[],consent:p=e.consent,id:v=`${s}-${r}-${i}`,trigger:h="",entity:y=n,action:m=o,timing:b=0,version:w={source:e.version,tagging:e.config.tagging||0},source:k={type:"collector",id:"",previous_id:""}}=t;return{name:a,data:c,context:u,globals:l,custom:d,user:f,nested:g,consent:p,id:v,trigger:h,entity:y,action:m,timestamp:s,timing:b,group:r,count:i,version:w,source:k}}async function X(e){var t,n;const o=(0,y.assign)({globalsStatic:{},sessionStatic:{},tagging:0,run:!0},e,{merge:!1,extend:!1}),s={level:null==(t=e.logger)?void 0:t.level,handler:null==(n=e.logger)?void 0:n.handler},r=(0,y.createLogger)(s),i={...o.globalsStatic,...e.globals},a={allowed:!1,config:o,consent:e.consent||{},count:0,custom:e.custom||{},destinations:{},transformers:{},stores:{},globals:i,group:"",hooks:e.hooks||{},logger:r,on:{},queue:[],round:0,session:void 0,status:{startedAt:Date.now(),in:0,out:0,failed:0,sources:{},destinations:{}},timing:Date.now(),user:e.user||{},version:"3.1.1",sources:{},pending:{sources:{},destinations:{}},push:void 0,command:void 0};var c,u;a.push=function(e,t){return(0,j.useHooks)(async(n,o={})=>await(0,j.tryCatchAsync)(async()=>{var s;const r=Date.now(),{id:i,ingest:a,respond:c,mapping:u,preChain:l,include:d,exclude:f}=o;let g=c,p=n;const v=d||f?function(e,t,n){let o=e;return t&&(o=Object.fromEntries(Object.entries(o).filter(([e])=>t.includes(e)))),n&&(o=Object.fromEntries(Object.entries(o).filter(([e])=>!n.includes(e)))),o}(e.destinations,d,f):void 0,h=null!=a?a:(0,j.createIngest)(i||"unknown");if(u){const t=await(0,j.processEventMapping)(p,u,e);if(t.ignore)return F({ok:!0});if(u.consent&&!(0,j.getGrantedConsent)(u.consent,e.consent,t.event.consent))return F({ok:!0});p=t.event}if((null==l?void 0:l.length)&&e.transformers&&Object.keys(e.transformers).length>0){const n=await E(e,e.transformers,l,p,h,g,i?`source.${i}.next`:void 0);if(null===n.event)return F({ok:!0});if(n.respond&&(g=n.respond),Array.isArray(n.event)){const o=await Promise.all(n.event.map(async n=>{const o=t(n),s=Q(e,o);return G(e,s,{id:i,ingest:h,respond:g},v)}));if(i){e.status.sources[i]||(e.status.sources[i]={count:0,duration:0});const t=e.status.sources[i];t.count+=n.event.length,t.lastAt=Date.now(),t.duration+=Date.now()-r}return null!=(s=o[0])?s:F({ok:!0})}p=n.event}const y=t(p),m=Q(e,y),b=await G(e,m,{id:i,ingest:h,respond:g},v);if(i){e.status.sources[i]||(e.status.sources[i]={count:0,duration:0});const t=e.status.sources[i];t.count++,t.lastAt=Date.now(),t.duration+=Date.now()-r}return b},()=>F({ok:!1}))(),"Push",e.hooks)}(a,e=>({timing:Math.round((Date.now()-a.timing)/10)/100,source:{type:"collector",id:"",previous_id:""},...e})),a.command=(c=a,u=W,(0,S.useHooks)(async(e,t,n)=>await(0,S.tryCatchAsync)(async()=>await u(c,e,t,n),()=>F({ok:!1}))(),"Command",c.hooks));const l=e.stores||{};if(a.stores=await async function(e,t={}){const n={};for(const[o,s]of Object.entries(t)){const{code:t,config:r={},env:i={}}=s,a=e.logger.scope("store").scope(o),c={collector:e,logger:a,id:o,config:r,env:i},u=await t(c),l=u.get,d=u.set,f=u.delete;u.get=(0,A.useHooks)(l,"StoreGet",e.hooks),u.set=(0,A.useHooks)(d,"StoreSet",e.hooks),u.delete=(0,A.useHooks)(f,"StoreDelete",e.hooks),n[o]=u}return n}(a,l),function(e,t,n){const o=new Map;for(const[n,s]of Object.entries(e))t[n]&&o.set(s,t[n]);if(0!==o.size)for(const e of[n.transformers,n.destinations,n.sources])if(e)for(const t of Object.values(e))s(t.env);function s(e){if(e)for(const[t,n]of Object.entries(e))if("object"==typeof n&&null!==n){const s=o.get(n);s&&(e[t]=s)}}}(l,a.stores,e),!a.stores.__cache){const e=new Map;a.stores.__cache={type:"memory",config:{},get:t=>{const n=e.get(t);if(n){if(!(n.expires&&Date.now()>n.expires))return n.value;e.delete(t)}},set:(t,n,o)=>{e.set(t,{value:n,expires:o?Date.now()+o:void 0})},delete:t=>{e.delete(t)}}}return a.destinations=await async function(e,t={}){var n,o;const s={};for(const[r,i]of Object.entries(t))(null==(o=null==(n=i.config)?void 0:n.require)?void 0:o.length)?e.pending.destinations[r]=i:s[r]=J(i);return s}(a,e.destinations||{}),a.transformers=await async function(e,t={}){const n={};for(const[o,s]of Object.entries(t)){const{code:t,env:r={}}=s,{config:i}=_(s,"before"),{config:a}=_({...s,config:i},"next"),c=Object.keys(r).length>0?{...a,env:r}:a,{cache:u}=s,l=u?{...c,cache:u}:c,d=e.logger.scope("transformer").scope(o),f={collector:e,logger:d,id:o,ingest:(0,O.createIngest)(o),config:l,env:r},g=await t(f);n[o]=g}return n}(a,e.transformers||{}),a}async function Y(e){e=e||{};const t=await X(e),n=(o=t,{type:"elb",config:{},push:async(e,t,n,s,r,i)=>{if("string"==typeof e&&e.startsWith("walker ")){const s=e.replace("walker ","");return o.command(s,t,n)}let a;if("string"==typeof e)a={name:e},t&&"object"==typeof t&&!Array.isArray(t)&&(a.data=t);else{if(!e||"object"!=typeof e)return F({ok:!1});a=e,t&&"object"==typeof t&&!Array.isArray(t)&&(a.data={...a.data||{},...t})}return s&&"object"==typeof s&&(a.context=s),r&&Array.isArray(r)&&(a.nested=r),i&&"object"==typeof i&&(a.custom=i),o.push(a)}});var o;t.sources.elb=n;const s=await async function(e,t={}){const n={};for(const[o,s]of Object.entries(t)){const{config:t={}}=s;if(t.require&&t.require.length>0){e.pending.sources[o]=s;continue}const r=await M(e,o,s);r&&(n[o]=r)}return n}(t,e.sources||{});Object.assign(t.sources,s);const{consent:r,user:i,globals:a,custom:c}=e;r&&await t.command("consent",r),i&&await t.command("user",i),a&&Object.assign(t.globals,a),c&&Object.assign(t.custom,c),t.config.run&&await t.command("run");let u=n.push;const l=Object.values(t.sources).filter(e=>"elb"!==e.type),d=l.find(e=>e.config.primary);return d?u=d.push:l.length>0&&(u=l[0].push),{collector:t,elb:u}}var Z=async e=>{let t;return{get flow(){return t},trigger:(n,o)=>async n=>{var s,r,i,a,c,u,l,d,f;const g=o||{};if(g.url){const e=new URL(g.url);window.history.replaceState({},"",e.pathname+e.search)}if(g.referrer&&Object.defineProperty(document,"referrer",{value:g.referrer,configurable:!0}),g.sessionData){const e=g.sessionKey||"elbSessionId";localStorage.setItem(e,JSON.stringify(g.sessionData))}if(g.deviceId){const e=g.deviceKey||"elbDeviceId";localStorage.setItem(e,g.deviceId)}if(!t){const n=await Y({...e,run:null==(s=e.run)||s});t={collector:n.collector,elb:n.elb};const o=g.sessionKey||(null==(c=null==(a=null==(i=null==(r=e.sources)?void 0:r.session)?void 0:i.config)?void 0:a.settings)?void 0:c.sessionKey)||"elbSessionId",p=g.deviceKey||(null==(f=null==(d=null==(l=null==(u=e.sources)?void 0:u.session)?void 0:l.config)?void 0:d.settings)?void 0:f.deviceKey)||"elbDeviceId";localStorage.removeItem(o),localStorage.removeItem(p),g.sessionData&&localStorage.setItem(o,JSON.stringify(g.sessionData)),g.deviceId&&localStorage.setItem(p,g.deviceId),e.consent&&await t.collector.command("consent",e.consent)}}}},ee=(e,t)=>{if(!e||"object"!=typeof e)return;const n=e,o=t.localStorage;if(n.sessionData&&"object"==typeof n.sessionData){const e="string"==typeof n.sessionKey?n.sessionKey:"elbSessionId";o.setItem(e,JSON.stringify(n.sessionData))}if("string"==typeof n.deviceId){const e="string"==typeof n.deviceKey?n.deviceKey:"elbDeviceId";o.setItem(e,n.deviceId)}};//# sourceMappingURL=dev.js.map
|
|
1
|
+
"use strict";var e,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.prototype.hasOwnProperty,r=(e,n)=>{for(var o in n)t(e,o,{get:n[o],enumerable:!0})},i={};r(i,{examples:()=>g,schemas:()=>a}),module.exports=(e=i,((e,r,i,a)=>{if(r&&"object"==typeof r||"function"==typeof r)for(let c of o(r))s.call(e,c)||c===i||t(e,c,{get:()=>r[c],enumerable:!(a=n(r,c))||a.enumerable});return e})(t({},"__esModule",{value:!0}),e));var a={};r(a,{SettingsSchema:()=>d,settings:()=>f});var c=require("@walkeros/core/dev"),u=require("@walkeros/core/dev"),l=require("@walkeros/core"),d=u.z.object({storage:u.z.boolean().default(!1).describe("Enable persistent storage for session/device IDs").optional(),consent:u.z.union([u.z.string(),u.z.array(u.z.string())]).describe("Consent key(s) required to enable storage mode").optional(),length:u.z.number().default(30).describe("Session timeout in minutes").optional(),pulse:u.z.boolean().default(!1).describe("Keep session alive on each event").optional(),sessionKey:u.z.string().default("elbSessionId").describe("Storage key for session ID").optional(),sessionStorage:u.z.enum(["local","session"]).default("local").describe("Storage type for session").optional(),deviceKey:u.z.string().default("elbDeviceId").describe("Storage key for device ID").optional(),deviceStorage:u.z.enum(["local","session"]).default("local").describe("Storage type for device").optional(),deviceAge:u.z.number().default(30).describe("Device ID age in days").optional(),cb:u.z.any().describe("Custom session callback function or false to disable").optional(),clickIds:u.z.array(l.ClickIdEntrySchema).describe("Custom click-ID registry. Entries with a `param` matching a default override the platform name in place; new params append to the end of the priority list.").optional()}),f=(0,c.zodToSchema)(d),g={};r(g,{createTrigger:()=>ee,step:()=>p,trigger:()=>te});var p={};r(p,{newMarketingSession:()=>v,returningVisitor:()=>h});var v={trigger:{type:"load",options:{url:"https://example.com/?utm_source=google&utm_medium=cpc&utm_campaign=winter-sale"}},in:{storage:!0},out:{name:"session start",data:{isStart:!0,isNew:!0,count:1,runs:1,storage:!0,id:"s3ss10n-id",device:"d3v1c3-id",start:17e11,marketing:!0,source:"google",medium:"cpc",campaign:"winter-sale"},entity:"session",action:"start"}},h={trigger:{type:"load",options:{referrer:"https://google.com"}},in:{storage:!0},out:{name:"session start",data:{isStart:!0,isNew:!1,count:3,runs:1,storage:!0,id:"n3w-s3ss10n",device:"d3v1c3-id",start:1700001e6,referrer:"google.com"},entity:"session",action:"start"}},y=require("@walkeros/core"),m=require("@walkeros/core"),b=require("@walkeros/core"),w=require("@walkeros/core"),k=require("@walkeros/core"),O=require("@walkeros/core"),x=require("@walkeros/core"),C=require("@walkeros/core"),j=require("@walkeros/core"),S=require("@walkeros/core"),I=require("@walkeros/core"),A=require("@walkeros/core"),q={Action:"action",Actions:"actions",Config:"config",Consent:"consent",Context:"context",Custom:"custom",Destination:"destination",Elb:"elb",Globals:"globals",Hook:"hook",Init:"init",Link:"link",On:"on",Prefix:"data-elb",Ready:"ready",Run:"run",Session:"session",Shutdown:"shutdown",User:"user",Walker:"walker"};function D(e,t){return e.storeId&&t.stores[e.storeId]?t.stores[e.storeId]:t.stores.__cache}function _(e){var t;const n={};for(const[o,s]of Object.entries(e)){const e=null==(t=s.config)?void 0:t.next;e&&!(0,x.isRouteArray)(e)?n[o]={next:e}:n[o]={}}return n}function $(e,t){const n=e.config||{},o=e[t];return void 0!==o?{config:{...n,[t]:o},chainValue:o}:{config:n,chainValue:void 0}}function P(e,t={}){if(!e)return[];if(Array.isArray(e))return e;const n=[],o=new Set;let s=e;for(;s&&t[s]&&!o.has(s);){o.add(s),n.push(s);const e=t[s].next;if(Array.isArray(e)){n.push(...e);break}s=e}return n}async function N(e,t,n){if(t.init&&!t.config.init){const o=t.type||"unknown",s=e.logger.scope(`transformer:${o}`),r={collector:e,logger:s,id:n,ingest:(0,x.createIngest)(n),config:t.config,env:M(t.config.env)};s.debug("init");const i=await(0,x.useHooks)(t.init,"TransformerInit",e.hooks)(r);if(!1===i)return!1;t.config={...i||t.config,env:(null==i?void 0:i.env)||t.config.env,init:!0},s.debug("init done")}return!0}async function E(e,t,n,o,s,r){const i=t.type||"unknown",a=e.logger.scope(`transformer:${i}`),c={collector:e,logger:a,id:n,ingest:s,config:t.config,env:{...M(t.config.env),...r?{respond:r}:{}}};a.debug("push",{event:o.name});const u=await(0,x.useHooks)(t.push,"TransformerPush",e.hooks)(o,c);return a.debug("push done"),u}async function R(e,t,n,o,s,r,i){var a,c,u,l,d,f;i&&(null==s?void 0:s._meta)&&(s._meta.chainPath=i);let g=o,p=r;for(const o of n){const r=t[o];if(!r){e.logger.warn(`Transformer not found: ${o}`);continue}if(s&&s._meta&&s._meta.path.length>256)return e.logger.error(`Max path length exceeded at ${o}`),{event:null,respond:p};if(s&&s._meta&&(s._meta.hops++,s._meta.path.push(o)),!await(0,x.tryCatchAsync)(N)(e,r,o))return e.logger.error(`Transformer init failed: ${o}`),{event:null,respond:p};if(i&&void 0!==(null==(c=null==(a=r.config)?void 0:a.chainMocks)?void 0:c[i])){const t=r.config.chainMocks[i];e.logger.scope(`transformer:${r.type||"unknown"}`).debug("chainMock",{chain:i}),g=t;continue}if(void 0!==(null==(u=r.config)?void 0:u.mock)){e.logger.scope(`transformer:${r.type||"unknown"}`).debug("mock"),g=r.config.mock;continue}if(null==(l=r.config)?void 0:l.disabled)continue;const v=null==(d=r.config)?void 0:d.cache,h=v?(0,x.compileCache)(v):void 0,y=h?D(h,e):void 0;let m;if(h&&y){const e=(0,x.buildCacheContext)(s,g),t=(0,x.checkCache)(h,y,e,`t:${o}`);if("HIT"===(null==t?void 0:t.status)&&t.value){if(g=t.value,h.full)return{event:g,respond:p};continue}"MISS"===(null==t?void 0:t.status)&&(m={key:t.key,ttl:t.rule.ttl})}const b=r.config.before;if(b){const n=P("string"==typeof b||Array.isArray(b)&&!(0,x.isRouteArray)(b)?b:(0,x.resolveNext)((0,x.compileNext)(b),(0,x.buildCacheContext)(s,g))||void 0,_(t));if(n.length>0){const o=await R(e,t,n,g,s,p,i);if(null===o.event)return{event:null,respond:null!=(f=o.respond)?f:p};o.respond&&(p=o.respond),g=Array.isArray(o.event)?o.event[0]:o.event}}const w=await(0,x.tryCatchAsync)(E,t=>(e.logger.scope(`transformer:${r.type||"unknown"}`).error("Push failed",{error:t}),!1))(e,r,o,g,s,p);if(!1===w)return{event:null,respond:p};if(Array.isArray(w)){const r=n.slice(n.indexOf(o)+1),a=await Promise.all(w.map(async n=>{const o=n.event||g,a=s?{...s,_meta:{...s._meta,path:[...s._meta.path]}}:(0,x.createIngest)("unknown");if(n.next){let s=n.next;if((0,x.isRouteArray)(n.next)){const e=(0,x.compileNext)(n.next);s=(0,x.resolveNext)(e,(0,x.buildCacheContext)(a,o))}if(s){const n=P(s,_(t));if(n.length>0)return R(e,t,n,o,a,p,i)}return{event:o,respond:p}}return r.length>0?R(e,t,r,o,a,p,i):{event:o,respond:p}}));let c=p;const u=[];for(const e of a.flat())if(null!==e)if(e&&"object"==typeof e&&"event"in e){const t=e;if(t.respond&&(c=t.respond),null===t.event)continue;Array.isArray(t.event)?u.push(...t.event):u.push(t.event)}else u.push(e);return 0===u.length?{event:null,respond:c}:1===u.length?{event:u[0],respond:c}:{event:u,respond:c}}if(w&&"object"==typeof w){const{event:n,respond:o,next:r}=w;if(o&&(p=o),r){let o=r;if((0,x.isRouteArray)(r)){const e=(0,x.compileNext)(r);if(o=(0,x.resolveNext)(e,(0,x.buildCacheContext)(s,g)),!o){n&&(g=n);continue}}const a=P(o,_(t));return a.length>0?R(e,t,a,n||g,s,p,i):(e.logger.warn(`Branch target not found: ${JSON.stringify(r)}`),{event:null,respond:p})}n&&(g=n)}if(m&&y&&(0,x.storeCache)(y,m.key,g,m.ttl),(!w||"object"==typeof w&&!w.next)&&r.config.next&&(0,x.isRouteArray)(r.config.next)){const n=r.config.next,o=(0,x.compileNext)(n),a=(0,x.resolveNext)(o,(0,x.buildCacheContext)(s,g));if(a){const n=P(a,_(t));if(n.length>0)return R(e,t,n,g,s,p,i)}return{event:g,respond:p}}}return{event:g,respond:p}}function M(e){return e&&(0,x.isObject)(e)?e:{}}async function z(e,t,n){var o;const{code:s,config:r={},env:i={},primary:a,next:c,before:u,cache:l}=n;let d,f=(0,O.createIngest)(t);const g=l?(0,O.compileCache)({...l,full:null==(o=l.full)||o}):void 0,p=(0,O.compileNext)(c),v=Array.isArray(c)&&(0,O.isRouteArray)(c)||!p?void 0:P((0,O.resolveNext)(p),_(e.transformers)),h=(0,O.compileNext)(u),y=Array.isArray(u)&&(0,O.isRouteArray)(u)||!h?void 0:P((0,O.resolveNext)(h),_(e.transformers)),m=e.logger.scope("source").scope(t),b={push:async(n,o={})=>{let s=n;const i=null!=y?y:h?P((0,O.resolveNext)(h,(0,O.buildCacheContext)(f)),_(e.transformers)):[];if(i.length>0&&e.transformers&&Object.keys(e.transformers).length>0){const n=await R(e,e.transformers,i,s,f,d,`source.${t}.before`);if(null===n.event)return{ok:!0};n.respond&&(d=n.respond),s=Array.isArray(n.event)?n.event[0]:n.event}if(g){const n=D(g,e);if(n){const e=(0,O.buildCacheContext)(f),o=(0,O.checkCache)(g,n,e,`s:${t}`);if(o){if("HIT"===o.status&&void 0!==o.value&&g.full){let t=o.value;return o.rule.update&&(t=await(0,O.applyUpdate)(t,o.rule.update,{...e,cache:{status:"HIT"}})),null==d||d(t),{ok:!0}}if("MISS"===o.status&&g.full&&d){const t=d,s=o.rule.update,r={...e,cache:{status:"MISS"}};d=e=>{(0,O.storeCache)(n,o.key,e,o.rule.ttl),s?(0,O.applyUpdate)(e,s,r).then(e=>t(e)):t(e)}}"MISS"!==o.status||g.full||(0,O.storeCache)(n,o.key,!0,o.rule.ttl)}}}const a=null!=v?v:p?P((0,O.resolveNext)(p,(0,O.buildCacheContext)(f)),_(e.transformers)):[];return e.push(s,{...o,id:t,ingest:f,respond:d,mapping:r,preChain:a})},command:e.command,sources:e.sources,elb:e.sources.elb.push,logger:m,...i},w={collector:e,logger:m,id:t,config:r,env:b,setIngest:async n=>{if(!r.ingest)return void(f=(0,O.createIngest)(t));const o=await(0,O.getMappingValue)(n,r.ingest,{collector:e}),s=(0,O.createIngest)(t);f={...s,...o,_meta:s._meta}},setRespond:e=>{d=e}},k=await(0,O.tryCatchAsync)(s)(w);if(!k)return;const x=k.type||"unknown",C=e.logger.scope(x).scope(t);return b.logger=C,a&&(k.config={...k.config,primary:a}),k}function H(e,t,n,o,s){if(!t.on)return;const r=t.type||"unknown",i=e.logger.scope(r).scope("on").scope(o),a={collector:e,logger:i,id:n,config:t.config,data:s,env:L(t.env,t.config.env)};(0,k.tryCatch)(t.on)(o,a)}async function K(e,t,n,o){let s,r=n||[];switch(n||(r=e.on[t]||[]),t){case q.Consent:s=o||e.consent;break;case q.Session:s=e.session;break;case q.User:s=o||e.user;break;case q.Custom:s=o||e.custom;break;case q.Globals:s=o||e.globals;break;case q.Config:s=o||e.config;break;case q.Ready:case q.Run:default:s=void 0}let i=!1;for(const n of Object.values(e.sources))n.on&&!1===await(0,k.tryCatchAsync)(n.on)(t,s)&&(i=!0);if(Object.entries(e.destinations).forEach(([n,o])=>{if(o.on){if(!o.config.init)return o.queueOn=o.queueOn||[],void o.queueOn.push({type:t,data:s});H(e,o,n,t,s)}}),(Object.keys(e.pending.sources).length>0||Object.keys(e.pending.destinations).length>0)&&await async function(e,t){var n,o;for(const[o,s]of Object.entries(e.pending.sources)){if(!e.pending.sources[o]||e.sources[o])continue;const r=null==(n=s.config)?void 0:n.require;if(!r)continue;const i=r.indexOf(t);if(-1===i)continue;if(r.splice(i,1),r.length>0)continue;delete e.pending.sources[o];const a=await z(e,o,s);a&&(e.sources[o]=a)}for(const[n,s]of Object.entries(e.pending.destinations)){if(!e.pending.destinations[n]||e.destinations[n])continue;const r=null==(o=s.config)?void 0:o.require;if(!r)continue;const i=r.indexOf(t);if(-1===i)continue;if(r.splice(i,1),r.length>0)continue;delete e.pending.destinations[n];const a=V(s);!1!==a.config.queue&&(a.queuePush=[...e.queue]),e.destinations[n]=a}}(e,t),!r.length)return!i;switch(t){case q.Consent:!function(e,t,n){const o=n||e.consent;t.forEach(t=>{Object.keys(o).filter(e=>e in t).forEach(n=>{(0,k.tryCatch)(t[n])(e,o)})})}(e,r,o);break;case q.Ready:case q.Run:c=r,(a=e).allowed&&c.forEach(e=>{(0,k.tryCatch)(e)(a)});break;case q.Session:!function(e,t){e.session&&t.forEach(t=>{(0,k.tryCatch)(t)(e,e.session)})}(e,r);break;default:r.forEach(t=>{"function"==typeof t&&(0,k.tryCatch)(t)(e,s)})}var a,c;return!i}function T(e,t,n,o){if(!e)return[];if(t){const e=(0,b.resolveNext)(t,(0,b.buildCacheContext)(o));return e?P(e,_(n)):[]}return P(e,_(n))}async function G(e,t,n){const{code:o,config:s={},env:r={},before:i,next:a,cache:c}=t;if(!(0,b.isFunction)(o.push))return J({ok:!1,failed:{invalid:{type:"invalid",error:"Destination code must have a push method"}}});const u=n||s||{init:!1};let l=i?{...u,before:i}:{...u};a&&(l={...l,next:a}),c&&(l={...l,cache:c});const d={...o,config:l,env:L(o.env,r)};let f=d.config.id;if(!f)do{f=(0,b.getId)(4)}while(e.destinations[f]);return e.destinations[f]=d,!1!==d.config.queue&&(d.queuePush=[...e.queue]),U(e,void 0,{},{[f]:d})}async function U(e,t,n={},o){const{allowed:s,consent:r,globals:i,user:a}=e;if(!s)return J({ok:!1});t&&(e.queue.push(t),e.status.in++),o||(o=e.destinations);const c=await Promise.all(Object.entries(o||{}).map(async([o,s])=>{var c,u,l;if(s.config.disabled)return{id:o,destination:s,skipped:!0};let d=(s.queuePush||[]).map(e=>({...e,consent:r}));s.queuePush=[],t&&d.push((0,b.clone)(t));const f=n.ingest?{...n.ingest,_meta:{...n.ingest._meta,path:[...n.ingest._meta.path]}}:(0,b.createIngest)("unknown");if(!d.length&&!(null==(c=s.queueOn)?void 0:c.length))return{id:o,destination:s,skipped:!0};if(!d.length&&(null==(u=s.queueOn)?void 0:u.length)){const t=await(0,b.tryCatchAsync)(B)(e,s,o);return{id:o,destination:s,skipped:!t}}const g=[],p=d.filter(e=>{const t=(0,b.getGrantedConsent)(s.config.consent,r,e.consent);return!t||(e.consent=t,g.push(e),!1)});if(s.queuePush.push(...p),!g.length)return{id:o,destination:s,queue:d};if(!await(0,b.tryCatchAsync)(B)(e,s,o))return{id:o,destination:s,queue:d};let v,h;s.dlq||(s.dlq=[]);const y=s.config.before,m=T(y,y&&(0,b.isRouteArray)(y)?(0,b.compileNext)(y):void 0,e.transformers,f),w=s.config.next,k=w&&(0,b.isRouteArray)(w)?(0,b.compileNext)(w):void 0,O=null==(l=s.config)?void 0:l.cache,x=O?(0,b.compileCache)(O):void 0,C=x?D(x,e):void 0;let j=0;return await Promise.all(g.map(async t=>{let r;if(t.globals=(0,b.assign)(i,t.globals),t.user=(0,b.assign)(a,t.user),(null==x?void 0:x.full)&&C){const e=(0,b.buildCacheContext)(f,t),n=(0,b.checkCache)(x,C,e,`d:${o}`);if("HIT"===(null==n?void 0:n.status))return t;"MISS"===(null==n?void 0:n.status)&&(r={key:n.key,ttl:n.rule.ttl})}let c=t,u=n.respond;if(m.length>0&&e.transformers&&Object.keys(e.transformers).length>0){const s=await R(e,e.transformers,m,t,f,n.respond,`destination.${o}.before`);if(null===s.event)return t;s.respond&&(u=s.respond),c=Array.isArray(s.event)?s.event[0]:s.event}if(x&&!x.full&&C){const e=(0,b.buildCacheContext)(f,c),n=(0,b.checkCache)(x,C,e,`d:${o}`);if("HIT"===(null==n?void 0:n.status))return t;"MISS"===(null==n?void 0:n.status)&&(r={key:n.key,ttl:n.rule.ttl})}const l=Date.now();let d=!1;const g=await(0,b.tryCatchAsync)(F,t=>{const n=s.type||"unknown";e.logger.scope(n).error("Push failed",{error:t,event:c.name}),v=t,d=!0,s.dlq.push([c,t])})(e,s,o,c,f,u);if(j+=Date.now()-l,r&&C&&void 0===s.config.mock&&(0,b.storeCache)(C,r.key,null==g||g,r.ttl),void 0!==g&&(h=g),!d&&w){void 0!==g&&(f._response=g);const t=T(w,k,e.transformers,f);if(t.length>0&&e.transformers&&Object.keys(e.transformers).length>0){const n=await R(e,e.transformers,t,c,f,u,`destination.${o}.next`);n.respond&&(u=n.respond)}}return t})),{id:o,destination:s,error:v,response:h,totalDuration:j}})),u={},l={},d={};for(const t of c){if(t.skipped)continue;const n={type:t.destination.type||"unknown",data:t.response};e.status.destinations[t.id]||(e.status.destinations[t.id]={count:0,failed:0,duration:0});const o=e.status.destinations[t.id],s=Date.now();t.error?(n.error=t.error,d[t.id]=n,o.failed++,o.lastAt=s,o.duration+=t.totalDuration||0,e.status.failed++):t.queue&&t.queue.length?l[t.id]=n:(u[t.id]=n,o.count++,o.lastAt=s,o.duration+=t.totalDuration||0,e.status.out++)}return J({event:t,...Object.keys(u).length&&{done:u},...Object.keys(l).length&&{queued:l},...Object.keys(d).length&&{failed:d}})}async function B(e,t,n){var o;if(t.init&&!t.config.init){const s=t.type||"unknown",r=e.logger.scope(s),i={collector:e,logger:r,id:n,config:t.config,env:L(t.env,t.config.env)};r.debug("init");const a=await(0,b.useHooks)(t.init,"DestinationInit",e.hooks)(i);if(!1===a)return a;if(t.config={...a||t.config,init:!0},null==(o=t.queueOn)?void 0:o.length){const o=t.queueOn;t.queueOn=[];for(const{type:s,data:r}of o)H(e,t,n,s,r)}r.debug("init done")}return!0}async function F(e,t,n,o,s,r){const{config:i}=t,a=await(0,b.processEventMapping)(o,i,e);if(a.ignore)return!1;const c=t.type||"unknown",u=e.logger.scope(c),l={collector:e,logger:u,id:n,config:i,data:a.data,rule:a.mapping,ingest:s,env:{...L(t.env,i.env),...r?{respond:r}:{}}};if(void 0!==i.mock)return u.debug("mock",{event:a.event.name}),i.mock;const d=a.mapping,f=a.mappingKey||"* *";if(!(null==d?void 0:d.batch)||!t.pushBatch||void 0!==i.mock){u.debug("push",{event:a.event.name});const n=await(0,b.useHooks)(t.push,"DestinationPush",e.hooks)(a.event,l);return u.debug("push done"),n}{if(t.batches=t.batches||{},!t.batches[f]){const o={key:f,events:[],data:[]};t.batches[f]={batched:o,batchFn:(0,b.debounce)(()=>{const o=t.batches[f].batched,a={collector:e,logger:u,id:n,config:i,data:void 0,rule:d,ingest:s,env:{...L(t.env,i.env),...r?{respond:r}:{}}};u.debug("push batch",{events:o.events.length}),(0,b.useHooks)(t.pushBatch,"DestinationPushBatch",e.hooks)(o,a),u.debug("push batch done"),o.events=[],o.data=[]},d.batch)}}const o=t.batches[f];o.batched.events.push(a.event),(0,b.isDefined)(a.data)&&o.batched.data.push(a.data),o.batchFn()}return!0}function J(e){return{ok:!(null==e?void 0:e.failed),...e}}function V(e){const{code:t,config:n={},env:o={},cache:s}=e,{config:r}=$(e,"before"),{config:i}=$({...e,config:r},"next"),a={...t.config,...n,...i};s&&(a.cache=s);const c=L(t.env,o);return{...t,config:a,env:c}}function L(e,t){return e||t?t?e&&(0,b.isObject)(e)&&(0,b.isObject)(t)?{...e,...t}:t:e:{}}async function W(e,t,n){const o=Object.entries(e).map(async([e,o])=>{var s;const r=o.destroy;if(!r)return;const i=o.type||"unknown",a=n.scope(i),c={id:e,config:o.config,env:null!=(s=o.env)?s:{},logger:a};try{await Promise.race([r(c),new Promise((n,o)=>setTimeout(()=>o(new Error(`${t} '${e}' destroy timed out`)),5e3))])}catch(n){a.error(`${t} '${e}' destroy failed: ${n}`)}});await Promise.allSettled(o)}async function Q(e,t,n,o){let s,r,i=!1;switch(t){case q.Config:(0,j.isObject)(n)&&((0,C.assign)(e.config,n,{shallow:!1}),r=n,i=!0);break;case q.Consent:if((0,j.isObject)(n)){const{update:t}=function(e,t){const n={};return Object.entries(t).forEach(([e,t])=>{n[e]=!!t}),e.consent=(0,y.assign)(e.consent,n),{update:n}}(e,n);r=t,i=!0}break;case q.Custom:(0,j.isObject)(n)&&(e.custom=(0,C.assign)(e.custom,n),r=n,i=!0);break;case q.Destination:(0,j.isObject)(n)&&("code"in n&&(0,j.isObject)(n.code)?s=await G(e,n,o):(0,C.isFunction)(n.push)&&(s=await G(e,{code:n},o)));break;case q.Globals:(0,j.isObject)(n)&&(e.globals=(0,C.assign)(e.globals,n),r=n,i=!0);break;case q.On:(0,C.isString)(n)&&await async function(e,t,n){const o=e.on,s=o[t]||[],r=(0,w.isArray)(n)?n:[n];r.forEach(e=>{s.push(e)}),o[t]=s,await K(e,t,r)}(e,n,o);break;case q.Ready:i=!0;break;case q.Run:s=await async function(e,t){return e.allowed=!0,e.count=0,e.group=(0,C.getId)(),e.timing=Date.now(),t&&(t.consent&&(e.consent=(0,C.assign)(e.consent,t.consent)),t.user&&(e.user=(0,C.assign)(e.user,t.user)),t.globals&&(e.globals=(0,C.assign)(e.config.globalsStatic||{},t.globals)),t.custom&&(e.custom=(0,C.assign)(e.custom,t.custom))),Object.values(e.destinations).forEach(e=>{e.queuePush=[]}),e.queue=[],e.round++,await U(e)}(e,n),i=!0;break;case q.Session:i=!0;break;case q.Shutdown:await async function(e){const t=e.logger;await W(e.sources,"source",t),await W(e.destinations,"destination",t),await W(e.transformers,"transformer",t),await W(e.stores,"store",t)}(e);break;case q.User:(0,j.isObject)(n)&&((0,C.assign)(e.user,n,{shallow:!1}),r=n,i=!0)}return i&&(await K(e,t,void 0,r),s=await U(e)),s||J({ok:!0})}function X(e,t){if(!t.name)throw new Error("Event name is required");const[n,o]=t.name.split(" ");if(!n||!o)throw new Error("Event name is invalid");++e.count;const{timestamp:s=Date.now(),group:r=e.group,count:i=e.count}=t,{name:a=`${n} ${o}`,data:c={},context:u={},globals:l=e.globals,custom:d={},user:f=e.user,nested:g=[],consent:p=e.consent,id:v=`${s}-${r}-${i}`,trigger:h="",entity:y=n,action:m=o,timing:b=0,version:w={source:e.version,tagging:e.config.tagging||0},source:k={type:"collector",id:"",previous_id:""}}=t;return{name:a,data:c,context:u,globals:l,custom:d,user:f,nested:g,consent:p,id:v,trigger:h,entity:y,action:m,timestamp:s,timing:b,group:r,count:i,version:w,source:k}}async function Y(e){var t,n;const o=(0,m.assign)({globalsStatic:{},sessionStatic:{},tagging:0,run:!0},e,{merge:!1,extend:!1}),s={level:null==(t=e.logger)?void 0:t.level,handler:null==(n=e.logger)?void 0:n.handler},r=(0,m.createLogger)(s),i={...o.globalsStatic,...e.globals},a={allowed:!1,config:o,consent:e.consent||{},count:0,custom:e.custom||{},destinations:{},transformers:{},stores:{},globals:i,group:"",hooks:e.hooks||{},logger:r,on:{},queue:[],round:0,session:void 0,status:{startedAt:Date.now(),in:0,out:0,failed:0,sources:{},destinations:{}},timing:Date.now(),user:e.user||{},version:"3.2.0",sources:{},pending:{sources:{},destinations:{}},push:void 0,command:void 0};var c,u;a.push=function(e,t){return(0,S.useHooks)(async(n,o={})=>await(0,S.tryCatchAsync)(async()=>{var s;const r=Date.now(),{id:i,ingest:a,respond:c,mapping:u,preChain:l,include:d,exclude:f}=o;let g=c,p=n;const v=d||f?function(e,t,n){let o=e;return t&&(o=Object.fromEntries(Object.entries(o).filter(([e])=>t.includes(e)))),n&&(o=Object.fromEntries(Object.entries(o).filter(([e])=>!n.includes(e)))),o}(e.destinations,d,f):void 0,h=null!=a?a:(0,S.createIngest)(i||"unknown");if(u){const t=await(0,S.processEventMapping)(p,u,e);if(t.ignore)return J({ok:!0});if(u.consent&&!(0,S.getGrantedConsent)(u.consent,e.consent,t.event.consent))return J({ok:!0});p=t.event}if((null==l?void 0:l.length)&&e.transformers&&Object.keys(e.transformers).length>0){const n=await R(e,e.transformers,l,p,h,g,i?`source.${i}.next`:void 0);if(null===n.event)return J({ok:!0});if(n.respond&&(g=n.respond),Array.isArray(n.event)){const o=await Promise.all(n.event.map(async n=>{const o=t(n),s=X(e,o);return U(e,s,{id:i,ingest:h,respond:g},v)}));if(i){e.status.sources[i]||(e.status.sources[i]={count:0,duration:0});const t=e.status.sources[i];t.count+=n.event.length,t.lastAt=Date.now(),t.duration+=Date.now()-r}return null!=(s=o[0])?s:J({ok:!0})}p=n.event}const y=t(p),m=X(e,y),b=await U(e,m,{id:i,ingest:h,respond:g},v);if(i){e.status.sources[i]||(e.status.sources[i]={count:0,duration:0});const t=e.status.sources[i];t.count++,t.lastAt=Date.now(),t.duration+=Date.now()-r}return b},()=>J({ok:!1}))(),"Push",e.hooks)}(a,e=>({timing:Math.round((Date.now()-a.timing)/10)/100,source:{type:"collector",id:"",previous_id:""},...e})),a.command=(c=a,u=Q,(0,I.useHooks)(async(e,t,n)=>await(0,I.tryCatchAsync)(async()=>await u(c,e,t,n),()=>J({ok:!1}))(),"Command",c.hooks));const l=e.stores||{};if(a.stores=await async function(e,t={}){const n={};for(const[o,s]of Object.entries(t)){const{code:t,config:r={},env:i={}}=s,a=e.logger.scope("store").scope(o),c={collector:e,logger:a,id:o,config:r,env:i},u=await t(c),l=u.get,d=u.set,f=u.delete;u.get=(0,A.useHooks)(l,"StoreGet",e.hooks),u.set=(0,A.useHooks)(d,"StoreSet",e.hooks),u.delete=(0,A.useHooks)(f,"StoreDelete",e.hooks),n[o]=u}return n}(a,l),function(e,t,n){const o=new Map;for(const[n,s]of Object.entries(e))t[n]&&o.set(s,t[n]);if(0!==o.size)for(const e of[n.transformers,n.destinations,n.sources])if(e)for(const t of Object.values(e))s(t.env);function s(e){if(e)for(const[t,n]of Object.entries(e))if("object"==typeof n&&null!==n){const s=o.get(n);s&&(e[t]=s)}}}(l,a.stores,e),!a.stores.__cache){const e=new Map;a.stores.__cache={type:"memory",config:{},get:t=>{const n=e.get(t);if(n){if(!(n.expires&&Date.now()>n.expires))return n.value;e.delete(t)}},set:(t,n,o)=>{e.set(t,{value:n,expires:o?Date.now()+o:void 0})},delete:t=>{e.delete(t)}}}return a.destinations=await async function(e,t={}){var n,o;const s={};for(const[r,i]of Object.entries(t))(null==(o=null==(n=i.config)?void 0:n.require)?void 0:o.length)?e.pending.destinations[r]=i:s[r]=V(i);return s}(a,e.destinations||{}),a.transformers=await async function(e,t={}){const n={};for(const[o,s]of Object.entries(t)){const{code:t,env:r={}}=s,{config:i}=$(s,"before"),{config:a}=$({...s,config:i},"next"),c=Object.keys(r).length>0?{...a,env:r}:a,{cache:u}=s,l=u?{...c,cache:u}:c,d=e.logger.scope("transformer").scope(o),f={collector:e,logger:d,id:o,ingest:(0,x.createIngest)(o),config:l,env:r},g=await t(f);n[o]=g}return n}(a,e.transformers||{}),a}async function Z(e){e=e||{};const t=await Y(e),n=(o=t,{type:"elb",config:{},push:async(e,t,n,s,r,i)=>{if("string"==typeof e&&e.startsWith("walker ")){const s=e.replace("walker ","");return o.command(s,t,n)}let a;if("string"==typeof e)a={name:e},t&&"object"==typeof t&&!Array.isArray(t)&&(a.data=t);else{if(!e||"object"!=typeof e)return J({ok:!1});a=e,t&&"object"==typeof t&&!Array.isArray(t)&&(a.data={...a.data||{},...t})}return s&&"object"==typeof s&&(a.context=s),r&&Array.isArray(r)&&(a.nested=r),i&&"object"==typeof i&&(a.custom=i),o.push(a)}});var o;t.sources.elb=n;const s=await async function(e,t={}){const n={};for(const[o,s]of Object.entries(t)){const{config:t={}}=s;if(t.require&&t.require.length>0){e.pending.sources[o]=s;continue}const r=await z(e,o,s);r&&(n[o]=r)}return n}(t,e.sources||{});Object.assign(t.sources,s);const{consent:r,user:i,globals:a,custom:c}=e;r&&await t.command("consent",r),i&&await t.command("user",i),a&&Object.assign(t.globals,a),c&&Object.assign(t.custom,c),t.config.run&&await t.command("run");let u=n.push;const l=Object.values(t.sources).filter(e=>"elb"!==e.type),d=l.find(e=>e.config.primary);return d?u=d.push:l.length>0&&(u=l[0].push),{collector:t,elb:u}}var ee=async e=>{let t;return{get flow(){return t},trigger:(n,o)=>async n=>{var s,r,i,a,c,u,l,d,f;const g=o||{};if(g.url){const e=new URL(g.url);window.history.replaceState({},"",e.pathname+e.search)}if(g.referrer&&Object.defineProperty(document,"referrer",{value:g.referrer,configurable:!0}),g.sessionData){const e=g.sessionKey||"elbSessionId";localStorage.setItem(e,JSON.stringify(g.sessionData))}if(g.deviceId){const e=g.deviceKey||"elbDeviceId";localStorage.setItem(e,g.deviceId)}if(!t){const n=await Z({...e,run:null==(s=e.run)||s});t={collector:n.collector,elb:n.elb};const o=g.sessionKey||(null==(c=null==(a=null==(i=null==(r=e.sources)?void 0:r.session)?void 0:i.config)?void 0:a.settings)?void 0:c.sessionKey)||"elbSessionId",p=g.deviceKey||(null==(f=null==(d=null==(l=null==(u=e.sources)?void 0:u.session)?void 0:l.config)?void 0:d.settings)?void 0:f.deviceKey)||"elbDeviceId";localStorage.removeItem(o),localStorage.removeItem(p),g.sessionData&&localStorage.setItem(o,JSON.stringify(g.sessionData)),g.deviceId&&localStorage.setItem(p,g.deviceId),e.consent&&await t.collector.command("consent",e.consent)}}}},te=(e,t)=>{if(!e||"object"!=typeof e)return;const n=e,o=t.localStorage;if(n.sessionData&&"object"==typeof n.sessionData){const e="string"==typeof n.sessionKey?n.sessionKey:"elbSessionId";o.setItem(e,JSON.stringify(n.sessionData))}if("string"==typeof n.deviceId){const e="string"==typeof n.deviceKey?n.deviceKey:"elbDeviceId";o.setItem(e,n.deviceId)}};//# sourceMappingURL=dev.js.map
|
package/dist/dev.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/dev.ts","../src/schemas/index.ts","../src/schemas/settings.ts","../src/examples/index.ts","../src/examples/step.ts","../src/examples/trigger.ts"],"sourcesContent":["export * as schemas from './schemas';\nexport * as examples from './examples';\n","import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\n\n// Export Zod schemas and types\nexport { SettingsSchema, type Settings } from './settings';\n\n// JSON Schema exports (for website PropertyTable)\nexport const settings = zodToSchema(SettingsSchema);\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Session source settings schema\n */\nexport const SettingsSchema = z.object({\n storage: z\n .boolean()\n .default(false)\n .describe('Enable persistent storage for session/device IDs')\n .optional(),\n\n consent: z\n .union([z.string(), z.array(z.string())])\n .describe('Consent key(s) required to enable storage mode')\n .optional(),\n\n length: z\n .number()\n .default(30)\n .describe('Session timeout in minutes')\n .optional(),\n\n pulse: z\n .boolean()\n .default(false)\n .describe('Keep session alive on each event')\n .optional(),\n\n sessionKey: z\n .string()\n .default('elbSessionId')\n .describe('Storage key for session ID')\n .optional(),\n\n sessionStorage: z\n .enum(['local', 'session'])\n .default('local')\n .describe('Storage type for session')\n .optional(),\n\n deviceKey: z\n .string()\n .default('elbDeviceId')\n .describe('Storage key for device ID')\n .optional(),\n\n deviceStorage: z\n .enum(['local', 'session'])\n .default('local')\n .describe('Storage type for device')\n .optional(),\n\n deviceAge: z\n .number()\n .default(30)\n .describe('Device ID age in days')\n .optional(),\n\n // Note: Using z.any() because z.custom() cannot be converted to JSON Schema\n // TypeScript types provide compile-time safety; runtime accepts function or false\n cb: z\n .any()\n .describe('Custom session callback function or false to disable')\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","export * as step from './step';\nexport { createTrigger, trigger } from './trigger';\n","import type { Flow } from '@walkeros/core';\n\nexport const newMarketingSession: Flow.StepExample = {\n trigger: {\n type: 'load',\n options: {\n url: 'https://example.com/?utm_source=google&utm_medium=cpc&utm_campaign=winter-sale',\n },\n },\n in: { storage: true },\n out: {\n name: 'session start',\n data: {\n isStart: true,\n isNew: true,\n count: 1,\n runs: 1,\n storage: true,\n id: 's3ss10n-id',\n device: 'd3v1c3-id',\n start: 1700000000000,\n marketing: true,\n source: 'google',\n medium: 'cpc',\n campaign: 'winter-sale',\n },\n entity: 'session',\n action: 'start',\n },\n};\n\nexport const returningVisitor: Flow.StepExample = {\n trigger: {\n type: 'load',\n options: {\n referrer: 'https://google.com',\n },\n },\n in: { storage: true },\n out: {\n name: 'session start',\n data: {\n isStart: true,\n isNew: false,\n count: 3,\n runs: 1,\n storage: true,\n id: 'n3w-s3ss10n',\n device: 'd3v1c3-id',\n start: 1700001000000,\n referrer: 'google.com',\n },\n entity: 'session',\n action: 'start',\n },\n};\n","import type { Trigger, Collector } from '@walkeros/core';\nimport { startFlow } from '@walkeros/collector';\n\ninterface SessionTriggerOptions {\n url?: string;\n referrer?: string;\n sessionData?: Record<string, unknown>;\n deviceId?: string;\n sessionKey?: string;\n deviceKey?: string;\n}\n\nconst createTrigger: Trigger.CreateFn<Record<string, unknown>, void> = async (\n config: Collector.InitConfig,\n) => {\n let flow: Trigger.FlowHandle | undefined;\n\n const trigger: Trigger.Fn<Record<string, unknown>, void> =\n (type?: string, opts?: unknown) =>\n async (content: Record<string, unknown>) => {\n const options = (opts || {}) as SessionTriggerOptions;\n\n // Pre-init: seed world state before source reads it\n if (options.url) {\n const urlObj = new URL(options.url);\n window.history.replaceState({}, '', urlObj.pathname + urlObj.search);\n }\n if (options.referrer) {\n Object.defineProperty(document, 'referrer', {\n value: options.referrer,\n configurable: true,\n });\n }\n if (options.sessionData) {\n const key = options.sessionKey || 'elbSessionId';\n localStorage.setItem(key, JSON.stringify(options.sessionData));\n }\n if (options.deviceId) {\n const key = options.deviceKey || 'elbDeviceId';\n localStorage.setItem(key, options.deviceId);\n }\n\n // Lazy startFlow — session source fires events during init, but\n // collector.allowed is false until command('run'). The initial\n // session event is dropped. After startFlow, clear the session\n // data written by the dropped init, re-seed, and trigger a consent\n // update to cause session re-init with allowed=true.\n if (!flow) {\n const result = await startFlow({ ...config, run: config.run ?? true });\n flow = { collector: result.collector, elb: result.elb };\n\n // Clear session data written by the dropped init\n const sessionKey =\n options.sessionKey ||\n ((\n config.sources?.session?.config?.settings as Record<string, unknown>\n )?.sessionKey as string) ||\n 'elbSessionId';\n const deviceKey =\n options.deviceKey ||\n ((\n config.sources?.session?.config?.settings as Record<string, unknown>\n )?.deviceKey as string) ||\n 'elbDeviceId';\n localStorage.removeItem(sessionKey);\n localStorage.removeItem(deviceKey);\n\n // Re-seed localStorage if trigger options specified session data\n if (options.sessionData) {\n localStorage.setItem(sessionKey, JSON.stringify(options.sessionData));\n }\n if (options.deviceId) {\n localStorage.setItem(deviceKey, options.deviceId);\n }\n\n // Re-apply consent to trigger session source on('consent') handler.\n // Now allowed=true so the session start event reaches destinations.\n if (config.consent) {\n await flow.collector.command('consent', config.consent);\n }\n }\n };\n\n return {\n get flow() {\n return flow;\n },\n trigger,\n };\n};\n\n/** Prepares localStorage with session/device data before source init. */\nconst trigger = (input: unknown, env: Record<string, unknown>): void => {\n if (!input || typeof input !== 'object') return;\n const data = input as Record<string, unknown>;\n const storage = env.localStorage as Storage;\n\n if (data.sessionData && typeof data.sessionData === 'object') {\n const key =\n typeof data.sessionKey === 'string' ? data.sessionKey : 'elbSessionId';\n storage.setItem(key, JSON.stringify(data.sessionData));\n }\n\n if (typeof data.deviceId === 'string') {\n const key =\n typeof data.deviceKey === 'string' ? data.deviceKey : 'elbDeviceId';\n storage.setItem(key, data.deviceId);\n }\n};\n\nexport { createTrigger, trigger };\n"],"mappings":"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","names":["import_dev","trigger","_e"]}
|
|
1
|
+
{"version":3,"sources":["../src/dev.ts","../src/schemas/index.ts","../src/schemas/settings.ts","../src/examples/index.ts","../src/examples/step.ts","../src/examples/trigger.ts"],"sourcesContent":["export * as schemas from './schemas';\nexport * as examples from './examples';\n","import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\n\n// Export Zod schemas and types\nexport { SettingsSchema, type Settings } from './settings';\n\n// JSON Schema exports (for website PropertyTable)\nexport const settings = zodToSchema(SettingsSchema);\n","import { z } from '@walkeros/core/dev';\nimport { ClickIdEntrySchema } from '@walkeros/core';\n\n/**\n * Session source settings schema\n */\nexport const SettingsSchema = z.object({\n storage: z\n .boolean()\n .default(false)\n .describe('Enable persistent storage for session/device IDs')\n .optional(),\n\n consent: z\n .union([z.string(), z.array(z.string())])\n .describe('Consent key(s) required to enable storage mode')\n .optional(),\n\n length: z\n .number()\n .default(30)\n .describe('Session timeout in minutes')\n .optional(),\n\n pulse: z\n .boolean()\n .default(false)\n .describe('Keep session alive on each event')\n .optional(),\n\n sessionKey: z\n .string()\n .default('elbSessionId')\n .describe('Storage key for session ID')\n .optional(),\n\n sessionStorage: z\n .enum(['local', 'session'])\n .default('local')\n .describe('Storage type for session')\n .optional(),\n\n deviceKey: z\n .string()\n .default('elbDeviceId')\n .describe('Storage key for device ID')\n .optional(),\n\n deviceStorage: z\n .enum(['local', 'session'])\n .default('local')\n .describe('Storage type for device')\n .optional(),\n\n deviceAge: z\n .number()\n .default(30)\n .describe('Device ID age in days')\n .optional(),\n\n // Note: Using z.any() because z.custom() cannot be converted to JSON Schema\n // TypeScript types provide compile-time safety; runtime accepts function or false\n cb: z\n .any()\n .describe('Custom session callback function or false to disable')\n .optional(),\n\n clickIds: z\n .array(ClickIdEntrySchema)\n .describe(\n 'Custom click-ID registry. Entries with a `param` matching a default override the platform name in place; new params append to the end of the priority list.',\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","export * as step from './step';\nexport { createTrigger, trigger } from './trigger';\n","import type { Flow } from '@walkeros/core';\n\nexport const newMarketingSession: Flow.StepExample = {\n trigger: {\n type: 'load',\n options: {\n url: 'https://example.com/?utm_source=google&utm_medium=cpc&utm_campaign=winter-sale',\n },\n },\n in: { storage: true },\n out: {\n name: 'session start',\n data: {\n isStart: true,\n isNew: true,\n count: 1,\n runs: 1,\n storage: true,\n id: 's3ss10n-id',\n device: 'd3v1c3-id',\n start: 1700000000000,\n marketing: true,\n source: 'google',\n medium: 'cpc',\n campaign: 'winter-sale',\n },\n entity: 'session',\n action: 'start',\n },\n};\n\nexport const returningVisitor: Flow.StepExample = {\n trigger: {\n type: 'load',\n options: {\n referrer: 'https://google.com',\n },\n },\n in: { storage: true },\n out: {\n name: 'session start',\n data: {\n isStart: true,\n isNew: false,\n count: 3,\n runs: 1,\n storage: true,\n id: 'n3w-s3ss10n',\n device: 'd3v1c3-id',\n start: 1700001000000,\n referrer: 'google.com',\n },\n entity: 'session',\n action: 'start',\n },\n};\n","import type { Trigger, Collector } from '@walkeros/core';\nimport { startFlow } from '@walkeros/collector';\n\ninterface SessionTriggerOptions {\n url?: string;\n referrer?: string;\n sessionData?: Record<string, unknown>;\n deviceId?: string;\n sessionKey?: string;\n deviceKey?: string;\n}\n\nconst createTrigger: Trigger.CreateFn<Record<string, unknown>, void> = async (\n config: Collector.InitConfig,\n) => {\n let flow: Trigger.FlowHandle | undefined;\n\n const trigger: Trigger.Fn<Record<string, unknown>, void> =\n (type?: string, opts?: unknown) =>\n async (content: Record<string, unknown>) => {\n const options = (opts || {}) as SessionTriggerOptions;\n\n // Pre-init: seed world state before source reads it\n if (options.url) {\n const urlObj = new URL(options.url);\n window.history.replaceState({}, '', urlObj.pathname + urlObj.search);\n }\n if (options.referrer) {\n Object.defineProperty(document, 'referrer', {\n value: options.referrer,\n configurable: true,\n });\n }\n if (options.sessionData) {\n const key = options.sessionKey || 'elbSessionId';\n localStorage.setItem(key, JSON.stringify(options.sessionData));\n }\n if (options.deviceId) {\n const key = options.deviceKey || 'elbDeviceId';\n localStorage.setItem(key, options.deviceId);\n }\n\n // Lazy startFlow — session source fires events during init, but\n // collector.allowed is false until command('run'). The initial\n // session event is dropped. After startFlow, clear the session\n // data written by the dropped init, re-seed, and trigger a consent\n // update to cause session re-init with allowed=true.\n if (!flow) {\n const result = await startFlow({ ...config, run: config.run ?? true });\n flow = { collector: result.collector, elb: result.elb };\n\n // Clear session data written by the dropped init\n const sessionKey =\n options.sessionKey ||\n ((\n config.sources?.session?.config?.settings as Record<string, unknown>\n )?.sessionKey as string) ||\n 'elbSessionId';\n const deviceKey =\n options.deviceKey ||\n ((\n config.sources?.session?.config?.settings as Record<string, unknown>\n )?.deviceKey as string) ||\n 'elbDeviceId';\n localStorage.removeItem(sessionKey);\n localStorage.removeItem(deviceKey);\n\n // Re-seed localStorage if trigger options specified session data\n if (options.sessionData) {\n localStorage.setItem(sessionKey, JSON.stringify(options.sessionData));\n }\n if (options.deviceId) {\n localStorage.setItem(deviceKey, options.deviceId);\n }\n\n // Re-apply consent to trigger session source on('consent') handler.\n // Now allowed=true so the session start event reaches destinations.\n if (config.consent) {\n await flow.collector.command('consent', config.consent);\n }\n }\n };\n\n return {\n get flow() {\n return flow;\n },\n trigger,\n };\n};\n\n/** Prepares localStorage with session/device data before source init. */\nconst trigger = (input: unknown, env: Record<string, unknown>): void => {\n if (!input || typeof input !== 'object') return;\n const data = input as Record<string, unknown>;\n const storage = env.localStorage as Storage;\n\n if (data.sessionData && typeof data.sessionData === 'object') {\n const key =\n typeof data.sessionKey === 'string' ? data.sessionKey : 'elbSessionId';\n storage.setItem(key, JSON.stringify(data.sessionData));\n }\n\n if (typeof data.deviceId === 'string') {\n const key =\n typeof data.deviceKey === 'string' ? data.deviceKey : 'elbDeviceId';\n storage.setItem(key, data.deviceId);\n }\n};\n\nexport { createTrigger, trigger };\n"],"mappings":"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","names":["import_dev","trigger","_e"]}
|
package/dist/dev.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var e=Object.defineProperty,n=(n,t)=>{for(var o in t)e(n,o,{get:t[o],enumerable:!0})},t={};n(t,{SettingsSchema:()=>r,settings:()=>i});import{zodToSchema as o}from"@walkeros/core/dev";import{z as s}from"@walkeros/core/dev";var r=s.object({storage:s.boolean().default(!1).describe("Enable persistent storage for session/device IDs").optional(),consent:s.union([s.string(),s.array(s.string())]).describe("Consent key(s) required to enable storage mode").optional(),length:s.number().default(30).describe("Session timeout in minutes").optional(),pulse:s.boolean().default(!1).describe("Keep session alive on each event").optional(),sessionKey:s.string().default("elbSessionId").describe("Storage key for session ID").optional(),sessionStorage:s.enum(["local","session"]).default("local").describe("Storage type for session").optional(),deviceKey:s.string().default("elbDeviceId").describe("Storage key for device ID").optional(),deviceStorage:s.enum(["local","session"]).default("local").describe("Storage type for device").optional(),deviceAge:s.number().default(30).describe("Device ID age in days").optional(),cb:s.any().describe("Custom session callback function or false to disable").optional()}),i=o(r),a={};n(a,{createTrigger:()=>Ge,step:()=>c,trigger:()=>Ue});var c={};n(c,{newMarketingSession:()=>u,returningVisitor:()=>l});var u={trigger:{type:"load",options:{url:"https://example.com/?utm_source=google&utm_medium=cpc&utm_campaign=winter-sale"}},in:{storage:!0},out:{name:"session start",data:{isStart:!0,isNew:!0,count:1,runs:1,storage:!0,id:"s3ss10n-id",device:"d3v1c3-id",start:17e11,marketing:!0,source:"google",medium:"cpc",campaign:"winter-sale"},entity:"session",action:"start"}},l={trigger:{type:"load",options:{referrer:"https://google.com"}},in:{storage:!0},out:{name:"session start",data:{isStart:!0,isNew:!1,count:3,runs:1,storage:!0,id:"n3w-s3ss10n",device:"d3v1c3-id",start:1700001e6,referrer:"google.com"},entity:"session",action:"start"}};import{assign as d}from"@walkeros/core";import{assign as f,createLogger as g}from"@walkeros/core";import{buildCacheContext as p,clone as v,compileCache as m,checkCache as h,storeCache as y,compileNext as b,createIngest as w,debounce as k,getId as O,getGrantedConsent as S,isDefined as j,isFunction as I,isObject as x,isRouteArray as A,processEventMapping as D,resolveNext as C,tryCatchAsync as q,useHooks as $}from"@walkeros/core";import{isArray as _}from"@walkeros/core";import{tryCatch as P,tryCatchAsync as E}from"@walkeros/core";import{createIngest as M,getMappingValue as K,tryCatchAsync as R,compileNext as N,resolveNext as H,isRouteArray as T,compileCache as G,checkCache as U,storeCache as B,applyUpdate as F,buildCacheContext as J}from"@walkeros/core";import{createIngest as V,isObject as L,tryCatchAsync as W,useHooks as z,compileNext as Q,resolveNext as X,isRouteArray as Y,compileCache as Z,checkCache as ee,storeCache as ne,buildCacheContext as te}from"@walkeros/core";import{assign as oe,getId as se,isFunction as re,isString as ie}from"@walkeros/core";import{isObject as ae}from"@walkeros/core";import{createIngest as ce,getGrantedConsent as ue,processEventMapping as le,tryCatchAsync as de,useHooks as fe}from"@walkeros/core";import{useHooks as ge,tryCatchAsync as pe}from"@walkeros/core";import{useHooks as ve}from"@walkeros/core";var me={Action:"action",Actions:"actions",Config:"config",Consent:"consent",Context:"context",Custom:"custom",Destination:"destination",Elb:"elb",Globals:"globals",Hook:"hook",Init:"init",Link:"link",On:"on",Prefix:"data-elb",Ready:"ready",Run:"run",Session:"session",Shutdown:"shutdown",User:"user",Walker:"walker"};function he(e,n){return e.storeId&&n.stores[e.storeId]?n.stores[e.storeId]:n.stores.__cache}function ye(e){var n;const t={};for(const[o,s]of Object.entries(e)){const e=null==(n=s.config)?void 0:n.next;e&&!Y(e)?t[o]={next:e}:t[o]={}}return t}function be(e,n){const t=e.config||{},o=e[n];return void 0!==o?{config:{...t,[n]:o},chainValue:o}:{config:t,chainValue:void 0}}function we(e,n={}){if(!e)return[];if(Array.isArray(e))return e;const t=[],o=new Set;let s=e;for(;s&&n[s]&&!o.has(s);){o.add(s),t.push(s);const e=n[s].next;if(Array.isArray(e)){t.push(...e);break}s=e}return t}async function ke(e,n,t){if(n.init&&!n.config.init){const o=n.type||"unknown",s=e.logger.scope(`transformer:${o}`),r={collector:e,logger:s,id:t,ingest:V(t),config:n.config,env:je(n.config.env)};s.debug("init");const i=await z(n.init,"TransformerInit",e.hooks)(r);if(!1===i)return!1;n.config={...i||n.config,env:(null==i?void 0:i.env)||n.config.env,init:!0},s.debug("init done")}return!0}async function Oe(e,n,t,o,s,r){const i=n.type||"unknown",a=e.logger.scope(`transformer:${i}`),c={collector:e,logger:a,id:t,ingest:s,config:n.config,env:{...je(n.config.env),...r?{respond:r}:{}}};a.debug("push",{event:o.name});const u=await z(n.push,"TransformerPush",e.hooks)(o,c);return a.debug("push done"),u}async function Se(e,n,t,o,s,r,i){var a,c,u,l,d,f;i&&(null==s?void 0:s._meta)&&(s._meta.chainPath=i);let g=o,p=r;for(const o of t){const r=n[o];if(!r){e.logger.warn(`Transformer not found: ${o}`);continue}if(s&&s._meta&&s._meta.path.length>256)return e.logger.error(`Max path length exceeded at ${o}`),{event:null,respond:p};if(s&&s._meta&&(s._meta.hops++,s._meta.path.push(o)),!await W(ke)(e,r,o))return e.logger.error(`Transformer init failed: ${o}`),{event:null,respond:p};if(i&&void 0!==(null==(c=null==(a=r.config)?void 0:a.chainMocks)?void 0:c[i])){const n=r.config.chainMocks[i];e.logger.scope(`transformer:${r.type||"unknown"}`).debug("chainMock",{chain:i}),g=n;continue}if(void 0!==(null==(u=r.config)?void 0:u.mock)){e.logger.scope(`transformer:${r.type||"unknown"}`).debug("mock"),g=r.config.mock;continue}if(null==(l=r.config)?void 0:l.disabled)continue;const v=null==(d=r.config)?void 0:d.cache,m=v?Z(v):void 0,h=m?he(m,e):void 0;let y;if(m&&h){const e=te(s,g),n=ee(m,h,e,`t:${o}`);if("HIT"===(null==n?void 0:n.status)&&n.value){if(g=n.value,m.full)return{event:g,respond:p};continue}"MISS"===(null==n?void 0:n.status)&&(y={key:n.key,ttl:n.rule.ttl})}const b=r.config.before;if(b){const t=we("string"==typeof b||Array.isArray(b)&&!Y(b)?b:X(Q(b),te(s,g))||void 0,ye(n));if(t.length>0){const o=await Se(e,n,t,g,s,p,i);if(null===o.event)return{event:null,respond:null!=(f=o.respond)?f:p};o.respond&&(p=o.respond),g=Array.isArray(o.event)?o.event[0]:o.event}}const w=await W(Oe,n=>(e.logger.scope(`transformer:${r.type||"unknown"}`).error("Push failed",{error:n}),!1))(e,r,o,g,s,p);if(!1===w)return{event:null,respond:p};if(Array.isArray(w)){const r=t.slice(t.indexOf(o)+1),a=await Promise.all(w.map(async t=>{const o=t.event||g,a=s?{...s,_meta:{...s._meta,path:[...s._meta.path]}}:V("unknown");if(t.next){let s=t.next;if(Y(t.next)){const e=Q(t.next);s=X(e,te(a,o))}if(s){const t=we(s,ye(n));if(t.length>0)return Se(e,n,t,o,a,p,i)}return{event:o,respond:p}}return r.length>0?Se(e,n,r,o,a,p,i):{event:o,respond:p}}));let c=p;const u=[];for(const e of a.flat())if(null!==e)if(e&&"object"==typeof e&&"event"in e){const n=e;if(n.respond&&(c=n.respond),null===n.event)continue;Array.isArray(n.event)?u.push(...n.event):u.push(n.event)}else u.push(e);return 0===u.length?{event:null,respond:c}:1===u.length?{event:u[0],respond:c}:{event:u,respond:c}}if(w&&"object"==typeof w){const{event:t,respond:o,next:r}=w;if(o&&(p=o),r){let o=r;if(Y(r)){const e=Q(r);if(o=X(e,te(s,g)),!o){t&&(g=t);continue}}const a=we(o,ye(n));return a.length>0?Se(e,n,a,t||g,s,p,i):(e.logger.warn(`Branch target not found: ${JSON.stringify(r)}`),{event:null,respond:p})}t&&(g=t)}if(y&&h&&ne(h,y.key,g,y.ttl),(!w||"object"==typeof w&&!w.next)&&r.config.next&&Y(r.config.next)){const t=r.config.next,o=Q(t),a=X(o,te(s,g));if(a){const t=we(a,ye(n));if(t.length>0)return Se(e,n,t,g,s,p,i)}return{event:g,respond:p}}}return{event:g,respond:p}}function je(e){return e&&L(e)?e:{}}async function Ie(e,n,t){var o;const{code:s,config:r={},env:i={},primary:a,next:c,before:u,cache:l}=t;let d,f=M(n);const g=l?G({...l,full:null==(o=l.full)||o}):void 0,p=N(c),v=Array.isArray(c)&&T(c)||!p?void 0:we(H(p),ye(e.transformers)),m=N(u),h=Array.isArray(u)&&T(u)||!m?void 0:we(H(m),ye(e.transformers)),y=e.logger.scope("source").scope(n),b={push:async(t,o={})=>{let s=t;const i=null!=h?h:m?we(H(m,J(f)),ye(e.transformers)):[];if(i.length>0&&e.transformers&&Object.keys(e.transformers).length>0){const t=await Se(e,e.transformers,i,s,f,d,`source.${n}.before`);if(null===t.event)return{ok:!0};t.respond&&(d=t.respond),s=Array.isArray(t.event)?t.event[0]:t.event}if(g){const t=he(g,e);if(t){const e=J(f),o=U(g,t,e,`s:${n}`);if(o){if("HIT"===o.status&&void 0!==o.value&&g.full){let n=o.value;return o.rule.update&&(n=await F(n,o.rule.update,{...e,cache:{status:"HIT"}})),null==d||d(n),{ok:!0}}if("MISS"===o.status&&g.full&&d){const n=d,s=o.rule.update,r={...e,cache:{status:"MISS"}};d=e=>{B(t,o.key,e,o.rule.ttl),s?F(e,s,r).then(e=>n(e)):n(e)}}"MISS"!==o.status||g.full||B(t,o.key,!0,o.rule.ttl)}}}const a=null!=v?v:p?we(H(p,J(f)),ye(e.transformers)):[];return e.push(s,{...o,id:n,ingest:f,respond:d,mapping:r,preChain:a})},command:e.command,sources:e.sources,elb:e.sources.elb.push,logger:y,...i},w={collector:e,logger:y,id:n,config:r,env:b,setIngest:async t=>{if(!r.ingest)return void(f=M(n));const o=await K(t,r.ingest,{collector:e}),s=M(n);f={...s,...o,_meta:s._meta}},setRespond:e=>{d=e}},k=await R(s)(w);if(!k)return;const O=k.type||"unknown",S=e.logger.scope(O).scope(n);return b.logger=S,a&&(k.config={...k.config,primary:a}),k}function xe(e,n,t,o,s){if(!n.on)return;const r=n.type||"unknown",i=e.logger.scope(r).scope("on").scope(o),a={collector:e,logger:i,id:t,config:n.config,data:s,env:Me(n.env,n.config.env)};P(n.on)(o,a)}async function Ae(e,n,t,o){let s,r=t||[];switch(t||(r=e.on[n]||[]),n){case me.Consent:s=o||e.consent;break;case me.Session:s=e.session;break;case me.User:s=o||e.user;break;case me.Custom:s=o||e.custom;break;case me.Globals:s=o||e.globals;break;case me.Config:s=o||e.config;break;case me.Ready:case me.Run:default:s=void 0}let i=!1;for(const t of Object.values(e.sources))t.on&&!1===await E(t.on)(n,s)&&(i=!0);if(Object.entries(e.destinations).forEach(([t,o])=>{if(o.on){if(!o.config.init)return o.queueOn=o.queueOn||[],void o.queueOn.push({type:n,data:s});xe(e,o,t,n,s)}}),(Object.keys(e.pending.sources).length>0||Object.keys(e.pending.destinations).length>0)&&await async function(e,n){var t,o;for(const[o,s]of Object.entries(e.pending.sources)){if(!e.pending.sources[o]||e.sources[o])continue;const r=null==(t=s.config)?void 0:t.require;if(!r)continue;const i=r.indexOf(n);if(-1===i)continue;if(r.splice(i,1),r.length>0)continue;delete e.pending.sources[o];const a=await Ie(e,o,s);a&&(e.sources[o]=a)}for(const[t,s]of Object.entries(e.pending.destinations)){if(!e.pending.destinations[t]||e.destinations[t])continue;const r=null==(o=s.config)?void 0:o.require;if(!r)continue;const i=r.indexOf(n);if(-1===i)continue;if(r.splice(i,1),r.length>0)continue;delete e.pending.destinations[t];const a=Ee(s);!1!==a.config.queue&&(a.queuePush=[...e.queue]),e.destinations[t]=a}}(e,n),!r.length)return!i;switch(n){case me.Consent:!function(e,n,t){const o=t||e.consent;n.forEach(n=>{Object.keys(o).filter(e=>e in n).forEach(t=>{P(n[t])(e,o)})})}(e,r,o);break;case me.Ready:case me.Run:c=r,(a=e).allowed&&c.forEach(e=>{P(e)(a)});break;case me.Session:!function(e,n){e.session&&n.forEach(n=>{P(n)(e,e.session)})}(e,r);break;default:r.forEach(n=>{"function"==typeof n&&P(n)(e,s)})}var a,c;return!i}function De(e,n,t,o){if(!e)return[];if(n){const e=C(n,p(o));return e?we(e,ye(t)):[]}return we(e,ye(t))}async function Ce(e,n,t){const{code:o,config:s={},env:r={},before:i,next:a,cache:c}=n;if(!I(o.push))return Pe({ok:!1,failed:{invalid:{type:"invalid",error:"Destination code must have a push method"}}});const u=t||s||{init:!1};let l=i?{...u,before:i}:{...u};a&&(l={...l,next:a}),c&&(l={...l,cache:c});const d={...o,config:l,env:Me(o.env,r)};let f=d.config.id;if(!f)do{f=O(4)}while(e.destinations[f]);return e.destinations[f]=d,!1!==d.config.queue&&(d.queuePush=[...e.queue]),qe(e,void 0,{},{[f]:d})}async function qe(e,n,t={},o){const{allowed:s,consent:r,globals:i,user:a}=e;if(!s)return Pe({ok:!1});n&&(e.queue.push(n),e.status.in++),o||(o=e.destinations);const c=await Promise.all(Object.entries(o||{}).map(async([o,s])=>{var c,u,l;if(s.config.disabled)return{id:o,destination:s,skipped:!0};let d=(s.queuePush||[]).map(e=>({...e,consent:r,user:a,globals:i}));s.queuePush=[];const f=t.ingest?{...t.ingest,_meta:{...t.ingest._meta,path:[...t.ingest._meta.path]}}:w("unknown");if(n){const e=v(n);d.push(e)}if(!d.length&&!(null==(c=s.queueOn)?void 0:c.length))return{id:o,destination:s,skipped:!0};if(!d.length&&(null==(u=s.queueOn)?void 0:u.length)){const n=await q($e)(e,s,o);return{id:o,destination:s,skipped:!n}}const g=[],k=d.filter(e=>{const n=S(s.config.consent,r,e.consent);return!n||(e.consent=n,g.push(e),!1)});if(s.queuePush.push(...k),!g.length)return{id:o,destination:s,queue:d};if(!await q($e)(e,s,o))return{id:o,destination:s,queue:d};let O,j;s.dlq||(s.dlq=[]);const I=s.config.before,x=De(I,I&&A(I)?b(I):void 0,e.transformers,f),D=s.config.next,C=D&&A(D)?b(D):void 0,$=null==(l=s.config)?void 0:l.cache,_=$?m($):void 0,P=_?he(_,e):void 0;let E=0;return await Promise.all(g.map(async n=>{let r;if((null==_?void 0:_.full)&&P){const e=p(f,n),t=h(_,P,e,`d:${o}`);if("HIT"===(null==t?void 0:t.status))return n;"MISS"===(null==t?void 0:t.status)&&(r={key:t.key,ttl:t.rule.ttl})}let i=n,a=t.respond;if(x.length>0&&e.transformers&&Object.keys(e.transformers).length>0){const s=await Se(e,e.transformers,x,n,f,t.respond,`destination.${o}.before`);if(null===s.event)return n;s.respond&&(a=s.respond),i=Array.isArray(s.event)?s.event[0]:s.event}if(_&&!_.full&&P){const e=p(f,i),t=h(_,P,e,`d:${o}`);if("HIT"===(null==t?void 0:t.status))return n;"MISS"===(null==t?void 0:t.status)&&(r={key:t.key,ttl:t.rule.ttl})}const c=Date.now();let u=!1;const l=await q(_e,n=>{const t=s.type||"unknown";e.logger.scope(t).error("Push failed",{error:n,event:i.name}),O=n,u=!0,s.dlq.push([i,n])})(e,s,o,i,f,a);if(E+=Date.now()-c,r&&P&&void 0===s.config.mock&&y(P,r.key,null==l||l,r.ttl),void 0!==l&&(j=l),!u&&D){void 0!==l&&(f._response=l);const n=De(D,C,e.transformers,f);if(n.length>0&&e.transformers&&Object.keys(e.transformers).length>0){const t=await Se(e,e.transformers,n,i,f,a,`destination.${o}.next`);t.respond&&(a=t.respond)}}return n})),{id:o,destination:s,error:O,response:j,totalDuration:E}})),u={},l={},d={};for(const n of c){if(n.skipped)continue;const t={type:n.destination.type||"unknown",data:n.response};e.status.destinations[n.id]||(e.status.destinations[n.id]={count:0,failed:0,duration:0});const o=e.status.destinations[n.id],s=Date.now();n.error?(t.error=n.error,d[n.id]=t,o.failed++,o.lastAt=s,o.duration+=n.totalDuration||0,e.status.failed++):n.queue&&n.queue.length?l[n.id]=t:(u[n.id]=t,o.count++,o.lastAt=s,o.duration+=n.totalDuration||0,e.status.out++)}return Pe({event:n,...Object.keys(u).length&&{done:u},...Object.keys(l).length&&{queued:l},...Object.keys(d).length&&{failed:d}})}async function $e(e,n,t){var o;if(n.init&&!n.config.init){const s=n.type||"unknown",r=e.logger.scope(s),i={collector:e,logger:r,id:t,config:n.config,env:Me(n.env,n.config.env)};r.debug("init");const a=await $(n.init,"DestinationInit",e.hooks)(i);if(!1===a)return a;if(n.config={...a||n.config,init:!0},null==(o=n.queueOn)?void 0:o.length){const o=n.queueOn;n.queueOn=[];for(const{type:s,data:r}of o)xe(e,n,t,s,r)}r.debug("init done")}return!0}async function _e(e,n,t,o,s,r){const{config:i}=n,a=await D(o,i,e);if(a.ignore)return!1;const c=n.type||"unknown",u=e.logger.scope(c),l={collector:e,logger:u,id:t,config:i,data:a.data,rule:a.mapping,ingest:s,env:{...Me(n.env,i.env),...r?{respond:r}:{}}};if(void 0!==i.mock)return u.debug("mock",{event:a.event.name}),i.mock;const d=a.mapping,f=a.mappingKey||"* *";if(!(null==d?void 0:d.batch)||!n.pushBatch||void 0!==i.mock){u.debug("push",{event:a.event.name});const t=await $(n.push,"DestinationPush",e.hooks)(a.event,l);return u.debug("push done"),t}{if(n.batches=n.batches||{},!n.batches[f]){const o={key:f,events:[],data:[]};n.batches[f]={batched:o,batchFn:k(()=>{const o=n.batches[f].batched,a={collector:e,logger:u,id:t,config:i,data:void 0,rule:d,ingest:s,env:{...Me(n.env,i.env),...r?{respond:r}:{}}};u.debug("push batch",{events:o.events.length}),$(n.pushBatch,"DestinationPushBatch",e.hooks)(o,a),u.debug("push batch done"),o.events=[],o.data=[]},d.batch)}}const o=n.batches[f];o.batched.events.push(a.event),j(a.data)&&o.batched.data.push(a.data),o.batchFn()}return!0}function Pe(e){return{ok:!(null==e?void 0:e.failed),...e}}function Ee(e){const{code:n,config:t={},env:o={},cache:s}=e,{config:r}=be(e,"before"),{config:i}=be({...e,config:r},"next"),a={...n.config,...t,...i};s&&(a.cache=s);const c=Me(n.env,o);return{...n,config:a,env:c}}function Me(e,n){return e||n?n?e&&x(e)&&x(n)?{...e,...n}:n:e:{}}async function Ke(e,n,t){const o=Object.entries(e).map(async([e,o])=>{var s;const r=o.destroy;if(!r)return;const i=o.type||"unknown",a=t.scope(i),c={id:e,config:o.config,env:null!=(s=o.env)?s:{},logger:a};try{await Promise.race([r(c),new Promise((t,o)=>setTimeout(()=>o(new Error(`${n} '${e}' destroy timed out`)),5e3))])}catch(t){a.error(`${n} '${e}' destroy failed: ${t}`)}});await Promise.allSettled(o)}async function Re(e,n,t,o){let s,r,i=!1;switch(n){case me.Config:ae(t)&&(oe(e.config,t,{shallow:!1}),r=t,i=!0);break;case me.Consent:if(ae(t)){const{update:n}=function(e,n){const t={};return Object.entries(n).forEach(([e,n])=>{t[e]=!!n}),e.consent=d(e.consent,t),{update:t}}(e,t);r=n,i=!0}break;case me.Custom:ae(t)&&(e.custom=oe(e.custom,t),r=t,i=!0);break;case me.Destination:ae(t)&&("code"in t&&ae(t.code)?s=await Ce(e,t,o):re(t.push)&&(s=await Ce(e,{code:t},o)));break;case me.Globals:ae(t)&&(e.globals=oe(e.globals,t),r=t,i=!0);break;case me.On:ie(t)&&await async function(e,n,t){const o=e.on,s=o[n]||[],r=_(t)?t:[t];r.forEach(e=>{s.push(e)}),o[n]=s,await Ae(e,n,r)}(e,t,o);break;case me.Ready:i=!0;break;case me.Run:s=await async function(e,n){return e.allowed=!0,e.count=0,e.group=se(),e.timing=Date.now(),n&&(n.consent&&(e.consent=oe(e.consent,n.consent)),n.user&&(e.user=oe(e.user,n.user)),n.globals&&(e.globals=oe(e.config.globalsStatic||{},n.globals)),n.custom&&(e.custom=oe(e.custom,n.custom))),Object.values(e.destinations).forEach(e=>{e.queuePush=[]}),e.queue=[],e.round++,await qe(e)}(e,t),i=!0;break;case me.Session:i=!0;break;case me.Shutdown:await async function(e){const n=e.logger;await Ke(e.sources,"source",n),await Ke(e.destinations,"destination",n),await Ke(e.transformers,"transformer",n),await Ke(e.stores,"store",n)}(e);break;case me.User:ae(t)&&(oe(e.user,t,{shallow:!1}),r=t,i=!0)}return i&&(await Ae(e,n,void 0,r),s=await qe(e)),s||Pe({ok:!0})}function Ne(e,n){if(!n.name)throw new Error("Event name is required");const[t,o]=n.name.split(" ");if(!t||!o)throw new Error("Event name is invalid");++e.count;const{timestamp:s=Date.now(),group:r=e.group,count:i=e.count}=n,{name:a=`${t} ${o}`,data:c={},context:u={},globals:l=e.globals,custom:d={},user:f=e.user,nested:g=[],consent:p=e.consent,id:v=`${s}-${r}-${i}`,trigger:m="",entity:h=t,action:y=o,timing:b=0,version:w={source:e.version,tagging:e.config.tagging||0},source:k={type:"collector",id:"",previous_id:""}}=n;return{name:a,data:c,context:u,globals:l,custom:d,user:f,nested:g,consent:p,id:v,trigger:m,entity:h,action:y,timestamp:s,timing:b,group:r,count:i,version:w,source:k}}async function He(e){var n,t;const o=f({globalsStatic:{},sessionStatic:{},tagging:0,run:!0},e,{merge:!1,extend:!1}),s={level:null==(n=e.logger)?void 0:n.level,handler:null==(t=e.logger)?void 0:t.handler},r=g(s),i={...o.globalsStatic,...e.globals},a={allowed:!1,config:o,consent:e.consent||{},count:0,custom:e.custom||{},destinations:{},transformers:{},stores:{},globals:i,group:"",hooks:e.hooks||{},logger:r,on:{},queue:[],round:0,session:void 0,status:{startedAt:Date.now(),in:0,out:0,failed:0,sources:{},destinations:{}},timing:Date.now(),user:e.user||{},version:"3.1.1",sources:{},pending:{sources:{},destinations:{}},push:void 0,command:void 0};var c,u;a.push=function(e,n){return fe(async(t,o={})=>await de(async()=>{var s;const r=Date.now(),{id:i,ingest:a,respond:c,mapping:u,preChain:l,include:d,exclude:f}=o;let g=c,p=t;const v=d||f?function(e,n,t){let o=e;return n&&(o=Object.fromEntries(Object.entries(o).filter(([e])=>n.includes(e)))),t&&(o=Object.fromEntries(Object.entries(o).filter(([e])=>!t.includes(e)))),o}(e.destinations,d,f):void 0,m=null!=a?a:ce(i||"unknown");if(u){const n=await le(p,u,e);if(n.ignore)return Pe({ok:!0});if(u.consent&&!ue(u.consent,e.consent,n.event.consent))return Pe({ok:!0});p=n.event}if((null==l?void 0:l.length)&&e.transformers&&Object.keys(e.transformers).length>0){const t=await Se(e,e.transformers,l,p,m,g,i?`source.${i}.next`:void 0);if(null===t.event)return Pe({ok:!0});if(t.respond&&(g=t.respond),Array.isArray(t.event)){const o=await Promise.all(t.event.map(async t=>{const o=n(t),s=Ne(e,o);return qe(e,s,{id:i,ingest:m,respond:g},v)}));if(i){e.status.sources[i]||(e.status.sources[i]={count:0,duration:0});const n=e.status.sources[i];n.count+=t.event.length,n.lastAt=Date.now(),n.duration+=Date.now()-r}return null!=(s=o[0])?s:Pe({ok:!0})}p=t.event}const h=n(p),y=Ne(e,h),b=await qe(e,y,{id:i,ingest:m,respond:g},v);if(i){e.status.sources[i]||(e.status.sources[i]={count:0,duration:0});const n=e.status.sources[i];n.count++,n.lastAt=Date.now(),n.duration+=Date.now()-r}return b},()=>Pe({ok:!1}))(),"Push",e.hooks)}(a,e=>({timing:Math.round((Date.now()-a.timing)/10)/100,source:{type:"collector",id:"",previous_id:""},...e})),a.command=(u=Re,ge(async(e,n,t)=>await pe(async()=>await u(c,e,n,t),()=>Pe({ok:!1}))(),"Command",(c=a).hooks));const l=e.stores||{};if(a.stores=await async function(e,n={}){const t={};for(const[o,s]of Object.entries(n)){const{code:n,config:r={},env:i={}}=s,a=e.logger.scope("store").scope(o),c={collector:e,logger:a,id:o,config:r,env:i},u=await n(c),l=u.get,d=u.set,f=u.delete;u.get=ve(l,"StoreGet",e.hooks),u.set=ve(d,"StoreSet",e.hooks),u.delete=ve(f,"StoreDelete",e.hooks),t[o]=u}return t}(a,l),function(e,n,t){const o=new Map;for(const[t,s]of Object.entries(e))n[t]&&o.set(s,n[t]);if(0!==o.size)for(const e of[t.transformers,t.destinations,t.sources])if(e)for(const n of Object.values(e))s(n.env);function s(e){if(e)for(const[n,t]of Object.entries(e))if("object"==typeof t&&null!==t){const s=o.get(t);s&&(e[n]=s)}}}(l,a.stores,e),!a.stores.__cache){const e=new Map;a.stores.__cache={type:"memory",config:{},get:n=>{const t=e.get(n);if(t){if(!(t.expires&&Date.now()>t.expires))return t.value;e.delete(n)}},set:(n,t,o)=>{e.set(n,{value:t,expires:o?Date.now()+o:void 0})},delete:n=>{e.delete(n)}}}return a.destinations=await async function(e,n={}){var t,o;const s={};for(const[r,i]of Object.entries(n))(null==(o=null==(t=i.config)?void 0:t.require)?void 0:o.length)?e.pending.destinations[r]=i:s[r]=Ee(i);return s}(a,e.destinations||{}),a.transformers=await async function(e,n={}){const t={};for(const[o,s]of Object.entries(n)){const{code:n,env:r={}}=s,{config:i}=be(s,"before"),{config:a}=be({...s,config:i},"next"),c=Object.keys(r).length>0?{...a,env:r}:a,{cache:u}=s,l=u?{...c,cache:u}:c,d=e.logger.scope("transformer").scope(o),f={collector:e,logger:d,id:o,ingest:V(o),config:l,env:r},g=await n(f);t[o]=g}return t}(a,e.transformers||{}),a}async function Te(e){e=e||{};const n=await He(e),t=(o=n,{type:"elb",config:{},push:async(e,n,t,s,r,i)=>{if("string"==typeof e&&e.startsWith("walker ")){const s=e.replace("walker ","");return o.command(s,n,t)}let a;if("string"==typeof e)a={name:e},n&&"object"==typeof n&&!Array.isArray(n)&&(a.data=n);else{if(!e||"object"!=typeof e)return Pe({ok:!1});a=e,n&&"object"==typeof n&&!Array.isArray(n)&&(a.data={...a.data||{},...n})}return s&&"object"==typeof s&&(a.context=s),r&&Array.isArray(r)&&(a.nested=r),i&&"object"==typeof i&&(a.custom=i),o.push(a)}});var o;n.sources.elb=t;const s=await async function(e,n={}){const t={};for(const[o,s]of Object.entries(n)){const{config:n={}}=s;if(n.require&&n.require.length>0){e.pending.sources[o]=s;continue}const r=await Ie(e,o,s);r&&(t[o]=r)}return t}(n,e.sources||{});Object.assign(n.sources,s);const{consent:r,user:i,globals:a,custom:c}=e;r&&await n.command("consent",r),i&&await n.command("user",i),a&&Object.assign(n.globals,a),c&&Object.assign(n.custom,c),n.config.run&&await n.command("run");let u=t.push;const l=Object.values(n.sources).filter(e=>"elb"!==e.type),d=l.find(e=>e.config.primary);return d?u=d.push:l.length>0&&(u=l[0].push),{collector:n,elb:u}}var Ge=async e=>{let n;return{get flow(){return n},trigger:(t,o)=>async t=>{var s,r,i,a,c,u,l,d,f;const g=o||{};if(g.url){const e=new URL(g.url);window.history.replaceState({},"",e.pathname+e.search)}if(g.referrer&&Object.defineProperty(document,"referrer",{value:g.referrer,configurable:!0}),g.sessionData){const e=g.sessionKey||"elbSessionId";localStorage.setItem(e,JSON.stringify(g.sessionData))}if(g.deviceId){const e=g.deviceKey||"elbDeviceId";localStorage.setItem(e,g.deviceId)}if(!n){const t=await Te({...e,run:null==(s=e.run)||s});n={collector:t.collector,elb:t.elb};const o=g.sessionKey||(null==(c=null==(a=null==(i=null==(r=e.sources)?void 0:r.session)?void 0:i.config)?void 0:a.settings)?void 0:c.sessionKey)||"elbSessionId",p=g.deviceKey||(null==(f=null==(d=null==(l=null==(u=e.sources)?void 0:u.session)?void 0:l.config)?void 0:d.settings)?void 0:f.deviceKey)||"elbDeviceId";localStorage.removeItem(o),localStorage.removeItem(p),g.sessionData&&localStorage.setItem(o,JSON.stringify(g.sessionData)),g.deviceId&&localStorage.setItem(p,g.deviceId),e.consent&&await n.collector.command("consent",e.consent)}}}},Ue=(e,n)=>{if(!e||"object"!=typeof e)return;const t=e,o=n.localStorage;if(t.sessionData&&"object"==typeof t.sessionData){const e="string"==typeof t.sessionKey?t.sessionKey:"elbSessionId";o.setItem(e,JSON.stringify(t.sessionData))}if("string"==typeof t.deviceId){const e="string"==typeof t.deviceKey?t.deviceKey:"elbDeviceId";o.setItem(e,t.deviceId)}};export{a as examples,t as schemas};//# sourceMappingURL=dev.mjs.map
|
|
1
|
+
var e=Object.defineProperty,n=(n,t)=>{for(var o in t)e(n,o,{get:t[o],enumerable:!0})},t={};n(t,{SettingsSchema:()=>i,settings:()=>a});import{zodToSchema as o}from"@walkeros/core/dev";import{z as s}from"@walkeros/core/dev";import{ClickIdEntrySchema as r}from"@walkeros/core";var i=s.object({storage:s.boolean().default(!1).describe("Enable persistent storage for session/device IDs").optional(),consent:s.union([s.string(),s.array(s.string())]).describe("Consent key(s) required to enable storage mode").optional(),length:s.number().default(30).describe("Session timeout in minutes").optional(),pulse:s.boolean().default(!1).describe("Keep session alive on each event").optional(),sessionKey:s.string().default("elbSessionId").describe("Storage key for session ID").optional(),sessionStorage:s.enum(["local","session"]).default("local").describe("Storage type for session").optional(),deviceKey:s.string().default("elbDeviceId").describe("Storage key for device ID").optional(),deviceStorage:s.enum(["local","session"]).default("local").describe("Storage type for device").optional(),deviceAge:s.number().default(30).describe("Device ID age in days").optional(),cb:s.any().describe("Custom session callback function or false to disable").optional(),clickIds:s.array(r).describe("Custom click-ID registry. Entries with a `param` matching a default override the platform name in place; new params append to the end of the priority list.").optional()}),a=o(i),c={};n(c,{createTrigger:()=>Be,step:()=>u,trigger:()=>Fe});var u={};n(u,{newMarketingSession:()=>l,returningVisitor:()=>d});var l={trigger:{type:"load",options:{url:"https://example.com/?utm_source=google&utm_medium=cpc&utm_campaign=winter-sale"}},in:{storage:!0},out:{name:"session start",data:{isStart:!0,isNew:!0,count:1,runs:1,storage:!0,id:"s3ss10n-id",device:"d3v1c3-id",start:17e11,marketing:!0,source:"google",medium:"cpc",campaign:"winter-sale"},entity:"session",action:"start"}},d={trigger:{type:"load",options:{referrer:"https://google.com"}},in:{storage:!0},out:{name:"session start",data:{isStart:!0,isNew:!1,count:3,runs:1,storage:!0,id:"n3w-s3ss10n",device:"d3v1c3-id",start:1700001e6,referrer:"google.com"},entity:"session",action:"start"}};import{assign as f}from"@walkeros/core";import{assign as g,createLogger as p}from"@walkeros/core";import{assign as v,buildCacheContext as m,clone as h,compileCache as y,checkCache as b,storeCache as w,compileNext as k,createIngest as O,debounce as S,getId as j,getGrantedConsent as I,isDefined as x,isFunction as A,isObject as D,isRouteArray as C,processEventMapping as q,resolveNext as $,tryCatchAsync as _,useHooks as P}from"@walkeros/core";import{isArray as E}from"@walkeros/core";import{tryCatch as M,tryCatchAsync as K}from"@walkeros/core";import{createIngest as R,getMappingValue as N,tryCatchAsync as H,compileNext as T,resolveNext as G,isRouteArray as U,compileCache as B,checkCache as F,storeCache as J,applyUpdate as V,buildCacheContext as L}from"@walkeros/core";import{createIngest as W,isObject as z,tryCatchAsync as Q,useHooks as X,compileNext as Y,resolveNext as Z,isRouteArray as ee,compileCache as ne,checkCache as te,storeCache as oe,buildCacheContext as se}from"@walkeros/core";import{assign as re,getId as ie,isFunction as ae,isString as ce}from"@walkeros/core";import{isObject as ue}from"@walkeros/core";import{createIngest as le,getGrantedConsent as de,processEventMapping as fe,tryCatchAsync as ge,useHooks as pe}from"@walkeros/core";import{useHooks as ve,tryCatchAsync as me}from"@walkeros/core";import{useHooks as he}from"@walkeros/core";var ye={Action:"action",Actions:"actions",Config:"config",Consent:"consent",Context:"context",Custom:"custom",Destination:"destination",Elb:"elb",Globals:"globals",Hook:"hook",Init:"init",Link:"link",On:"on",Prefix:"data-elb",Ready:"ready",Run:"run",Session:"session",Shutdown:"shutdown",User:"user",Walker:"walker"};function be(e,n){return e.storeId&&n.stores[e.storeId]?n.stores[e.storeId]:n.stores.__cache}function we(e){var n;const t={};for(const[o,s]of Object.entries(e)){const e=null==(n=s.config)?void 0:n.next;e&&!ee(e)?t[o]={next:e}:t[o]={}}return t}function ke(e,n){const t=e.config||{},o=e[n];return void 0!==o?{config:{...t,[n]:o},chainValue:o}:{config:t,chainValue:void 0}}function Oe(e,n={}){if(!e)return[];if(Array.isArray(e))return e;const t=[],o=new Set;let s=e;for(;s&&n[s]&&!o.has(s);){o.add(s),t.push(s);const e=n[s].next;if(Array.isArray(e)){t.push(...e);break}s=e}return t}async function Se(e,n,t){if(n.init&&!n.config.init){const o=n.type||"unknown",s=e.logger.scope(`transformer:${o}`),r={collector:e,logger:s,id:t,ingest:W(t),config:n.config,env:xe(n.config.env)};s.debug("init");const i=await X(n.init,"TransformerInit",e.hooks)(r);if(!1===i)return!1;n.config={...i||n.config,env:(null==i?void 0:i.env)||n.config.env,init:!0},s.debug("init done")}return!0}async function je(e,n,t,o,s,r){const i=n.type||"unknown",a=e.logger.scope(`transformer:${i}`),c={collector:e,logger:a,id:t,ingest:s,config:n.config,env:{...xe(n.config.env),...r?{respond:r}:{}}};a.debug("push",{event:o.name});const u=await X(n.push,"TransformerPush",e.hooks)(o,c);return a.debug("push done"),u}async function Ie(e,n,t,o,s,r,i){var a,c,u,l,d,f;i&&(null==s?void 0:s._meta)&&(s._meta.chainPath=i);let g=o,p=r;for(const o of t){const r=n[o];if(!r){e.logger.warn(`Transformer not found: ${o}`);continue}if(s&&s._meta&&s._meta.path.length>256)return e.logger.error(`Max path length exceeded at ${o}`),{event:null,respond:p};if(s&&s._meta&&(s._meta.hops++,s._meta.path.push(o)),!await Q(Se)(e,r,o))return e.logger.error(`Transformer init failed: ${o}`),{event:null,respond:p};if(i&&void 0!==(null==(c=null==(a=r.config)?void 0:a.chainMocks)?void 0:c[i])){const n=r.config.chainMocks[i];e.logger.scope(`transformer:${r.type||"unknown"}`).debug("chainMock",{chain:i}),g=n;continue}if(void 0!==(null==(u=r.config)?void 0:u.mock)){e.logger.scope(`transformer:${r.type||"unknown"}`).debug("mock"),g=r.config.mock;continue}if(null==(l=r.config)?void 0:l.disabled)continue;const v=null==(d=r.config)?void 0:d.cache,m=v?ne(v):void 0,h=m?be(m,e):void 0;let y;if(m&&h){const e=se(s,g),n=te(m,h,e,`t:${o}`);if("HIT"===(null==n?void 0:n.status)&&n.value){if(g=n.value,m.full)return{event:g,respond:p};continue}"MISS"===(null==n?void 0:n.status)&&(y={key:n.key,ttl:n.rule.ttl})}const b=r.config.before;if(b){const t=Oe("string"==typeof b||Array.isArray(b)&&!ee(b)?b:Z(Y(b),se(s,g))||void 0,we(n));if(t.length>0){const o=await Ie(e,n,t,g,s,p,i);if(null===o.event)return{event:null,respond:null!=(f=o.respond)?f:p};o.respond&&(p=o.respond),g=Array.isArray(o.event)?o.event[0]:o.event}}const w=await Q(je,n=>(e.logger.scope(`transformer:${r.type||"unknown"}`).error("Push failed",{error:n}),!1))(e,r,o,g,s,p);if(!1===w)return{event:null,respond:p};if(Array.isArray(w)){const r=t.slice(t.indexOf(o)+1),a=await Promise.all(w.map(async t=>{const o=t.event||g,a=s?{...s,_meta:{...s._meta,path:[...s._meta.path]}}:W("unknown");if(t.next){let s=t.next;if(ee(t.next)){const e=Y(t.next);s=Z(e,se(a,o))}if(s){const t=Oe(s,we(n));if(t.length>0)return Ie(e,n,t,o,a,p,i)}return{event:o,respond:p}}return r.length>0?Ie(e,n,r,o,a,p,i):{event:o,respond:p}}));let c=p;const u=[];for(const e of a.flat())if(null!==e)if(e&&"object"==typeof e&&"event"in e){const n=e;if(n.respond&&(c=n.respond),null===n.event)continue;Array.isArray(n.event)?u.push(...n.event):u.push(n.event)}else u.push(e);return 0===u.length?{event:null,respond:c}:1===u.length?{event:u[0],respond:c}:{event:u,respond:c}}if(w&&"object"==typeof w){const{event:t,respond:o,next:r}=w;if(o&&(p=o),r){let o=r;if(ee(r)){const e=Y(r);if(o=Z(e,se(s,g)),!o){t&&(g=t);continue}}const a=Oe(o,we(n));return a.length>0?Ie(e,n,a,t||g,s,p,i):(e.logger.warn(`Branch target not found: ${JSON.stringify(r)}`),{event:null,respond:p})}t&&(g=t)}if(y&&h&&oe(h,y.key,g,y.ttl),(!w||"object"==typeof w&&!w.next)&&r.config.next&&ee(r.config.next)){const t=r.config.next,o=Y(t),a=Z(o,se(s,g));if(a){const t=Oe(a,we(n));if(t.length>0)return Ie(e,n,t,g,s,p,i)}return{event:g,respond:p}}}return{event:g,respond:p}}function xe(e){return e&&z(e)?e:{}}async function Ae(e,n,t){var o;const{code:s,config:r={},env:i={},primary:a,next:c,before:u,cache:l}=t;let d,f=R(n);const g=l?B({...l,full:null==(o=l.full)||o}):void 0,p=T(c),v=Array.isArray(c)&&U(c)||!p?void 0:Oe(G(p),we(e.transformers)),m=T(u),h=Array.isArray(u)&&U(u)||!m?void 0:Oe(G(m),we(e.transformers)),y=e.logger.scope("source").scope(n),b={push:async(t,o={})=>{let s=t;const i=null!=h?h:m?Oe(G(m,L(f)),we(e.transformers)):[];if(i.length>0&&e.transformers&&Object.keys(e.transformers).length>0){const t=await Ie(e,e.transformers,i,s,f,d,`source.${n}.before`);if(null===t.event)return{ok:!0};t.respond&&(d=t.respond),s=Array.isArray(t.event)?t.event[0]:t.event}if(g){const t=be(g,e);if(t){const e=L(f),o=F(g,t,e,`s:${n}`);if(o){if("HIT"===o.status&&void 0!==o.value&&g.full){let n=o.value;return o.rule.update&&(n=await V(n,o.rule.update,{...e,cache:{status:"HIT"}})),null==d||d(n),{ok:!0}}if("MISS"===o.status&&g.full&&d){const n=d,s=o.rule.update,r={...e,cache:{status:"MISS"}};d=e=>{J(t,o.key,e,o.rule.ttl),s?V(e,s,r).then(e=>n(e)):n(e)}}"MISS"!==o.status||g.full||J(t,o.key,!0,o.rule.ttl)}}}const a=null!=v?v:p?Oe(G(p,L(f)),we(e.transformers)):[];return e.push(s,{...o,id:n,ingest:f,respond:d,mapping:r,preChain:a})},command:e.command,sources:e.sources,elb:e.sources.elb.push,logger:y,...i},w={collector:e,logger:y,id:n,config:r,env:b,setIngest:async t=>{if(!r.ingest)return void(f=R(n));const o=await N(t,r.ingest,{collector:e}),s=R(n);f={...s,...o,_meta:s._meta}},setRespond:e=>{d=e}},k=await H(s)(w);if(!k)return;const O=k.type||"unknown",S=e.logger.scope(O).scope(n);return b.logger=S,a&&(k.config={...k.config,primary:a}),k}function De(e,n,t,o,s){if(!n.on)return;const r=n.type||"unknown",i=e.logger.scope(r).scope("on").scope(o),a={collector:e,logger:i,id:t,config:n.config,data:s,env:Re(n.env,n.config.env)};M(n.on)(o,a)}async function Ce(e,n,t,o){let s,r=t||[];switch(t||(r=e.on[n]||[]),n){case ye.Consent:s=o||e.consent;break;case ye.Session:s=e.session;break;case ye.User:s=o||e.user;break;case ye.Custom:s=o||e.custom;break;case ye.Globals:s=o||e.globals;break;case ye.Config:s=o||e.config;break;case ye.Ready:case ye.Run:default:s=void 0}let i=!1;for(const t of Object.values(e.sources))t.on&&!1===await K(t.on)(n,s)&&(i=!0);if(Object.entries(e.destinations).forEach(([t,o])=>{if(o.on){if(!o.config.init)return o.queueOn=o.queueOn||[],void o.queueOn.push({type:n,data:s});De(e,o,t,n,s)}}),(Object.keys(e.pending.sources).length>0||Object.keys(e.pending.destinations).length>0)&&await async function(e,n){var t,o;for(const[o,s]of Object.entries(e.pending.sources)){if(!e.pending.sources[o]||e.sources[o])continue;const r=null==(t=s.config)?void 0:t.require;if(!r)continue;const i=r.indexOf(n);if(-1===i)continue;if(r.splice(i,1),r.length>0)continue;delete e.pending.sources[o];const a=await Ae(e,o,s);a&&(e.sources[o]=a)}for(const[t,s]of Object.entries(e.pending.destinations)){if(!e.pending.destinations[t]||e.destinations[t])continue;const r=null==(o=s.config)?void 0:o.require;if(!r)continue;const i=r.indexOf(n);if(-1===i)continue;if(r.splice(i,1),r.length>0)continue;delete e.pending.destinations[t];const a=Ke(s);!1!==a.config.queue&&(a.queuePush=[...e.queue]),e.destinations[t]=a}}(e,n),!r.length)return!i;switch(n){case ye.Consent:!function(e,n,t){const o=t||e.consent;n.forEach(n=>{Object.keys(o).filter(e=>e in n).forEach(t=>{M(n[t])(e,o)})})}(e,r,o);break;case ye.Ready:case ye.Run:c=r,(a=e).allowed&&c.forEach(e=>{M(e)(a)});break;case ye.Session:!function(e,n){e.session&&n.forEach(n=>{M(n)(e,e.session)})}(e,r);break;default:r.forEach(n=>{"function"==typeof n&&M(n)(e,s)})}var a,c;return!i}function qe(e,n,t,o){if(!e)return[];if(n){const e=$(n,m(o));return e?Oe(e,we(t)):[]}return Oe(e,we(t))}async function $e(e,n,t){const{code:o,config:s={},env:r={},before:i,next:a,cache:c}=n;if(!A(o.push))return Me({ok:!1,failed:{invalid:{type:"invalid",error:"Destination code must have a push method"}}});const u=t||s||{init:!1};let l=i?{...u,before:i}:{...u};a&&(l={...l,next:a}),c&&(l={...l,cache:c});const d={...o,config:l,env:Re(o.env,r)};let f=d.config.id;if(!f)do{f=j(4)}while(e.destinations[f]);return e.destinations[f]=d,!1!==d.config.queue&&(d.queuePush=[...e.queue]),_e(e,void 0,{},{[f]:d})}async function _e(e,n,t={},o){const{allowed:s,consent:r,globals:i,user:a}=e;if(!s)return Me({ok:!1});n&&(e.queue.push(n),e.status.in++),o||(o=e.destinations);const c=await Promise.all(Object.entries(o||{}).map(async([o,s])=>{var c,u,l;if(s.config.disabled)return{id:o,destination:s,skipped:!0};let d=(s.queuePush||[]).map(e=>({...e,consent:r}));s.queuePush=[],n&&d.push(h(n));const f=t.ingest?{...t.ingest,_meta:{...t.ingest._meta,path:[...t.ingest._meta.path]}}:O("unknown");if(!d.length&&!(null==(c=s.queueOn)?void 0:c.length))return{id:o,destination:s,skipped:!0};if(!d.length&&(null==(u=s.queueOn)?void 0:u.length)){const n=await _(Pe)(e,s,o);return{id:o,destination:s,skipped:!n}}const g=[],p=d.filter(e=>{const n=I(s.config.consent,r,e.consent);return!n||(e.consent=n,g.push(e),!1)});if(s.queuePush.push(...p),!g.length)return{id:o,destination:s,queue:d};if(!await _(Pe)(e,s,o))return{id:o,destination:s,queue:d};let S,j;s.dlq||(s.dlq=[]);const x=s.config.before,A=qe(x,x&&C(x)?k(x):void 0,e.transformers,f),D=s.config.next,q=D&&C(D)?k(D):void 0,$=null==(l=s.config)?void 0:l.cache,P=$?y($):void 0,E=P?be(P,e):void 0;let M=0;return await Promise.all(g.map(async n=>{let r;if(n.globals=v(i,n.globals),n.user=v(a,n.user),(null==P?void 0:P.full)&&E){const e=m(f,n),t=b(P,E,e,`d:${o}`);if("HIT"===(null==t?void 0:t.status))return n;"MISS"===(null==t?void 0:t.status)&&(r={key:t.key,ttl:t.rule.ttl})}let c=n,u=t.respond;if(A.length>0&&e.transformers&&Object.keys(e.transformers).length>0){const s=await Ie(e,e.transformers,A,n,f,t.respond,`destination.${o}.before`);if(null===s.event)return n;s.respond&&(u=s.respond),c=Array.isArray(s.event)?s.event[0]:s.event}if(P&&!P.full&&E){const e=m(f,c),t=b(P,E,e,`d:${o}`);if("HIT"===(null==t?void 0:t.status))return n;"MISS"===(null==t?void 0:t.status)&&(r={key:t.key,ttl:t.rule.ttl})}const l=Date.now();let d=!1;const g=await _(Ee,n=>{const t=s.type||"unknown";e.logger.scope(t).error("Push failed",{error:n,event:c.name}),S=n,d=!0,s.dlq.push([c,n])})(e,s,o,c,f,u);if(M+=Date.now()-l,r&&E&&void 0===s.config.mock&&w(E,r.key,null==g||g,r.ttl),void 0!==g&&(j=g),!d&&D){void 0!==g&&(f._response=g);const n=qe(D,q,e.transformers,f);if(n.length>0&&e.transformers&&Object.keys(e.transformers).length>0){const t=await Ie(e,e.transformers,n,c,f,u,`destination.${o}.next`);t.respond&&(u=t.respond)}}return n})),{id:o,destination:s,error:S,response:j,totalDuration:M}})),u={},l={},d={};for(const n of c){if(n.skipped)continue;const t={type:n.destination.type||"unknown",data:n.response};e.status.destinations[n.id]||(e.status.destinations[n.id]={count:0,failed:0,duration:0});const o=e.status.destinations[n.id],s=Date.now();n.error?(t.error=n.error,d[n.id]=t,o.failed++,o.lastAt=s,o.duration+=n.totalDuration||0,e.status.failed++):n.queue&&n.queue.length?l[n.id]=t:(u[n.id]=t,o.count++,o.lastAt=s,o.duration+=n.totalDuration||0,e.status.out++)}return Me({event:n,...Object.keys(u).length&&{done:u},...Object.keys(l).length&&{queued:l},...Object.keys(d).length&&{failed:d}})}async function Pe(e,n,t){var o;if(n.init&&!n.config.init){const s=n.type||"unknown",r=e.logger.scope(s),i={collector:e,logger:r,id:t,config:n.config,env:Re(n.env,n.config.env)};r.debug("init");const a=await P(n.init,"DestinationInit",e.hooks)(i);if(!1===a)return a;if(n.config={...a||n.config,init:!0},null==(o=n.queueOn)?void 0:o.length){const o=n.queueOn;n.queueOn=[];for(const{type:s,data:r}of o)De(e,n,t,s,r)}r.debug("init done")}return!0}async function Ee(e,n,t,o,s,r){const{config:i}=n,a=await q(o,i,e);if(a.ignore)return!1;const c=n.type||"unknown",u=e.logger.scope(c),l={collector:e,logger:u,id:t,config:i,data:a.data,rule:a.mapping,ingest:s,env:{...Re(n.env,i.env),...r?{respond:r}:{}}};if(void 0!==i.mock)return u.debug("mock",{event:a.event.name}),i.mock;const d=a.mapping,f=a.mappingKey||"* *";if(!(null==d?void 0:d.batch)||!n.pushBatch||void 0!==i.mock){u.debug("push",{event:a.event.name});const t=await P(n.push,"DestinationPush",e.hooks)(a.event,l);return u.debug("push done"),t}{if(n.batches=n.batches||{},!n.batches[f]){const o={key:f,events:[],data:[]};n.batches[f]={batched:o,batchFn:S(()=>{const o=n.batches[f].batched,a={collector:e,logger:u,id:t,config:i,data:void 0,rule:d,ingest:s,env:{...Re(n.env,i.env),...r?{respond:r}:{}}};u.debug("push batch",{events:o.events.length}),P(n.pushBatch,"DestinationPushBatch",e.hooks)(o,a),u.debug("push batch done"),o.events=[],o.data=[]},d.batch)}}const o=n.batches[f];o.batched.events.push(a.event),x(a.data)&&o.batched.data.push(a.data),o.batchFn()}return!0}function Me(e){return{ok:!(null==e?void 0:e.failed),...e}}function Ke(e){const{code:n,config:t={},env:o={},cache:s}=e,{config:r}=ke(e,"before"),{config:i}=ke({...e,config:r},"next"),a={...n.config,...t,...i};s&&(a.cache=s);const c=Re(n.env,o);return{...n,config:a,env:c}}function Re(e,n){return e||n?n?e&&D(e)&&D(n)?{...e,...n}:n:e:{}}async function Ne(e,n,t){const o=Object.entries(e).map(async([e,o])=>{var s;const r=o.destroy;if(!r)return;const i=o.type||"unknown",a=t.scope(i),c={id:e,config:o.config,env:null!=(s=o.env)?s:{},logger:a};try{await Promise.race([r(c),new Promise((t,o)=>setTimeout(()=>o(new Error(`${n} '${e}' destroy timed out`)),5e3))])}catch(t){a.error(`${n} '${e}' destroy failed: ${t}`)}});await Promise.allSettled(o)}async function He(e,n,t,o){let s,r,i=!1;switch(n){case ye.Config:ue(t)&&(re(e.config,t,{shallow:!1}),r=t,i=!0);break;case ye.Consent:if(ue(t)){const{update:n}=function(e,n){const t={};return Object.entries(n).forEach(([e,n])=>{t[e]=!!n}),e.consent=f(e.consent,t),{update:t}}(e,t);r=n,i=!0}break;case ye.Custom:ue(t)&&(e.custom=re(e.custom,t),r=t,i=!0);break;case ye.Destination:ue(t)&&("code"in t&&ue(t.code)?s=await $e(e,t,o):ae(t.push)&&(s=await $e(e,{code:t},o)));break;case ye.Globals:ue(t)&&(e.globals=re(e.globals,t),r=t,i=!0);break;case ye.On:ce(t)&&await async function(e,n,t){const o=e.on,s=o[n]||[],r=E(t)?t:[t];r.forEach(e=>{s.push(e)}),o[n]=s,await Ce(e,n,r)}(e,t,o);break;case ye.Ready:i=!0;break;case ye.Run:s=await async function(e,n){return e.allowed=!0,e.count=0,e.group=ie(),e.timing=Date.now(),n&&(n.consent&&(e.consent=re(e.consent,n.consent)),n.user&&(e.user=re(e.user,n.user)),n.globals&&(e.globals=re(e.config.globalsStatic||{},n.globals)),n.custom&&(e.custom=re(e.custom,n.custom))),Object.values(e.destinations).forEach(e=>{e.queuePush=[]}),e.queue=[],e.round++,await _e(e)}(e,t),i=!0;break;case ye.Session:i=!0;break;case ye.Shutdown:await async function(e){const n=e.logger;await Ne(e.sources,"source",n),await Ne(e.destinations,"destination",n),await Ne(e.transformers,"transformer",n),await Ne(e.stores,"store",n)}(e);break;case ye.User:ue(t)&&(re(e.user,t,{shallow:!1}),r=t,i=!0)}return i&&(await Ce(e,n,void 0,r),s=await _e(e)),s||Me({ok:!0})}function Te(e,n){if(!n.name)throw new Error("Event name is required");const[t,o]=n.name.split(" ");if(!t||!o)throw new Error("Event name is invalid");++e.count;const{timestamp:s=Date.now(),group:r=e.group,count:i=e.count}=n,{name:a=`${t} ${o}`,data:c={},context:u={},globals:l=e.globals,custom:d={},user:f=e.user,nested:g=[],consent:p=e.consent,id:v=`${s}-${r}-${i}`,trigger:m="",entity:h=t,action:y=o,timing:b=0,version:w={source:e.version,tagging:e.config.tagging||0},source:k={type:"collector",id:"",previous_id:""}}=n;return{name:a,data:c,context:u,globals:l,custom:d,user:f,nested:g,consent:p,id:v,trigger:m,entity:h,action:y,timestamp:s,timing:b,group:r,count:i,version:w,source:k}}async function Ge(e){var n,t;const o=g({globalsStatic:{},sessionStatic:{},tagging:0,run:!0},e,{merge:!1,extend:!1}),s={level:null==(n=e.logger)?void 0:n.level,handler:null==(t=e.logger)?void 0:t.handler},r=p(s),i={...o.globalsStatic,...e.globals},a={allowed:!1,config:o,consent:e.consent||{},count:0,custom:e.custom||{},destinations:{},transformers:{},stores:{},globals:i,group:"",hooks:e.hooks||{},logger:r,on:{},queue:[],round:0,session:void 0,status:{startedAt:Date.now(),in:0,out:0,failed:0,sources:{},destinations:{}},timing:Date.now(),user:e.user||{},version:"3.2.0",sources:{},pending:{sources:{},destinations:{}},push:void 0,command:void 0};var c,u;a.push=function(e,n){return pe(async(t,o={})=>await ge(async()=>{var s;const r=Date.now(),{id:i,ingest:a,respond:c,mapping:u,preChain:l,include:d,exclude:f}=o;let g=c,p=t;const v=d||f?function(e,n,t){let o=e;return n&&(o=Object.fromEntries(Object.entries(o).filter(([e])=>n.includes(e)))),t&&(o=Object.fromEntries(Object.entries(o).filter(([e])=>!t.includes(e)))),o}(e.destinations,d,f):void 0,m=null!=a?a:le(i||"unknown");if(u){const n=await fe(p,u,e);if(n.ignore)return Me({ok:!0});if(u.consent&&!de(u.consent,e.consent,n.event.consent))return Me({ok:!0});p=n.event}if((null==l?void 0:l.length)&&e.transformers&&Object.keys(e.transformers).length>0){const t=await Ie(e,e.transformers,l,p,m,g,i?`source.${i}.next`:void 0);if(null===t.event)return Me({ok:!0});if(t.respond&&(g=t.respond),Array.isArray(t.event)){const o=await Promise.all(t.event.map(async t=>{const o=n(t),s=Te(e,o);return _e(e,s,{id:i,ingest:m,respond:g},v)}));if(i){e.status.sources[i]||(e.status.sources[i]={count:0,duration:0});const n=e.status.sources[i];n.count+=t.event.length,n.lastAt=Date.now(),n.duration+=Date.now()-r}return null!=(s=o[0])?s:Me({ok:!0})}p=t.event}const h=n(p),y=Te(e,h),b=await _e(e,y,{id:i,ingest:m,respond:g},v);if(i){e.status.sources[i]||(e.status.sources[i]={count:0,duration:0});const n=e.status.sources[i];n.count++,n.lastAt=Date.now(),n.duration+=Date.now()-r}return b},()=>Me({ok:!1}))(),"Push",e.hooks)}(a,e=>({timing:Math.round((Date.now()-a.timing)/10)/100,source:{type:"collector",id:"",previous_id:""},...e})),a.command=(u=He,ve(async(e,n,t)=>await me(async()=>await u(c,e,n,t),()=>Me({ok:!1}))(),"Command",(c=a).hooks));const l=e.stores||{};if(a.stores=await async function(e,n={}){const t={};for(const[o,s]of Object.entries(n)){const{code:n,config:r={},env:i={}}=s,a=e.logger.scope("store").scope(o),c={collector:e,logger:a,id:o,config:r,env:i},u=await n(c),l=u.get,d=u.set,f=u.delete;u.get=he(l,"StoreGet",e.hooks),u.set=he(d,"StoreSet",e.hooks),u.delete=he(f,"StoreDelete",e.hooks),t[o]=u}return t}(a,l),function(e,n,t){const o=new Map;for(const[t,s]of Object.entries(e))n[t]&&o.set(s,n[t]);if(0!==o.size)for(const e of[t.transformers,t.destinations,t.sources])if(e)for(const n of Object.values(e))s(n.env);function s(e){if(e)for(const[n,t]of Object.entries(e))if("object"==typeof t&&null!==t){const s=o.get(t);s&&(e[n]=s)}}}(l,a.stores,e),!a.stores.__cache){const e=new Map;a.stores.__cache={type:"memory",config:{},get:n=>{const t=e.get(n);if(t){if(!(t.expires&&Date.now()>t.expires))return t.value;e.delete(n)}},set:(n,t,o)=>{e.set(n,{value:t,expires:o?Date.now()+o:void 0})},delete:n=>{e.delete(n)}}}return a.destinations=await async function(e,n={}){var t,o;const s={};for(const[r,i]of Object.entries(n))(null==(o=null==(t=i.config)?void 0:t.require)?void 0:o.length)?e.pending.destinations[r]=i:s[r]=Ke(i);return s}(a,e.destinations||{}),a.transformers=await async function(e,n={}){const t={};for(const[o,s]of Object.entries(n)){const{code:n,env:r={}}=s,{config:i}=ke(s,"before"),{config:a}=ke({...s,config:i},"next"),c=Object.keys(r).length>0?{...a,env:r}:a,{cache:u}=s,l=u?{...c,cache:u}:c,d=e.logger.scope("transformer").scope(o),f={collector:e,logger:d,id:o,ingest:W(o),config:l,env:r},g=await n(f);t[o]=g}return t}(a,e.transformers||{}),a}async function Ue(e){e=e||{};const n=await Ge(e),t=(o=n,{type:"elb",config:{},push:async(e,n,t,s,r,i)=>{if("string"==typeof e&&e.startsWith("walker ")){const s=e.replace("walker ","");return o.command(s,n,t)}let a;if("string"==typeof e)a={name:e},n&&"object"==typeof n&&!Array.isArray(n)&&(a.data=n);else{if(!e||"object"!=typeof e)return Me({ok:!1});a=e,n&&"object"==typeof n&&!Array.isArray(n)&&(a.data={...a.data||{},...n})}return s&&"object"==typeof s&&(a.context=s),r&&Array.isArray(r)&&(a.nested=r),i&&"object"==typeof i&&(a.custom=i),o.push(a)}});var o;n.sources.elb=t;const s=await async function(e,n={}){const t={};for(const[o,s]of Object.entries(n)){const{config:n={}}=s;if(n.require&&n.require.length>0){e.pending.sources[o]=s;continue}const r=await Ae(e,o,s);r&&(t[o]=r)}return t}(n,e.sources||{});Object.assign(n.sources,s);const{consent:r,user:i,globals:a,custom:c}=e;r&&await n.command("consent",r),i&&await n.command("user",i),a&&Object.assign(n.globals,a),c&&Object.assign(n.custom,c),n.config.run&&await n.command("run");let u=t.push;const l=Object.values(n.sources).filter(e=>"elb"!==e.type),d=l.find(e=>e.config.primary);return d?u=d.push:l.length>0&&(u=l[0].push),{collector:n,elb:u}}var Be=async e=>{let n;return{get flow(){return n},trigger:(t,o)=>async t=>{var s,r,i,a,c,u,l,d,f;const g=o||{};if(g.url){const e=new URL(g.url);window.history.replaceState({},"",e.pathname+e.search)}if(g.referrer&&Object.defineProperty(document,"referrer",{value:g.referrer,configurable:!0}),g.sessionData){const e=g.sessionKey||"elbSessionId";localStorage.setItem(e,JSON.stringify(g.sessionData))}if(g.deviceId){const e=g.deviceKey||"elbDeviceId";localStorage.setItem(e,g.deviceId)}if(!n){const t=await Ue({...e,run:null==(s=e.run)||s});n={collector:t.collector,elb:t.elb};const o=g.sessionKey||(null==(c=null==(a=null==(i=null==(r=e.sources)?void 0:r.session)?void 0:i.config)?void 0:a.settings)?void 0:c.sessionKey)||"elbSessionId",p=g.deviceKey||(null==(f=null==(d=null==(l=null==(u=e.sources)?void 0:u.session)?void 0:l.config)?void 0:d.settings)?void 0:f.deviceKey)||"elbDeviceId";localStorage.removeItem(o),localStorage.removeItem(p),g.sessionData&&localStorage.setItem(o,JSON.stringify(g.sessionData)),g.deviceId&&localStorage.setItem(p,g.deviceId),e.consent&&await n.collector.command("consent",e.consent)}}}},Fe=(e,n)=>{if(!e||"object"!=typeof e)return;const t=e,o=n.localStorage;if(t.sessionData&&"object"==typeof t.sessionData){const e="string"==typeof t.sessionKey?t.sessionKey:"elbSessionId";o.setItem(e,JSON.stringify(t.sessionData))}if("string"==typeof t.deviceId){const e="string"==typeof t.deviceKey?t.deviceKey:"elbDeviceId";o.setItem(e,t.deviceId)}};export{c as examples,t as schemas};//# sourceMappingURL=dev.mjs.map
|
package/dist/dev.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/schemas/index.ts","../src/schemas/settings.ts","../src/examples/index.ts","../src/examples/step.ts","../src/examples/trigger.ts"],"sourcesContent":["import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\n\n// Export Zod schemas and types\nexport { SettingsSchema, type Settings } from './settings';\n\n// JSON Schema exports (for website PropertyTable)\nexport const settings = zodToSchema(SettingsSchema);\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Session source settings schema\n */\nexport const SettingsSchema = z.object({\n storage: z\n .boolean()\n .default(false)\n .describe('Enable persistent storage for session/device IDs')\n .optional(),\n\n consent: z\n .union([z.string(), z.array(z.string())])\n .describe('Consent key(s) required to enable storage mode')\n .optional(),\n\n length: z\n .number()\n .default(30)\n .describe('Session timeout in minutes')\n .optional(),\n\n pulse: z\n .boolean()\n .default(false)\n .describe('Keep session alive on each event')\n .optional(),\n\n sessionKey: z\n .string()\n .default('elbSessionId')\n .describe('Storage key for session ID')\n .optional(),\n\n sessionStorage: z\n .enum(['local', 'session'])\n .default('local')\n .describe('Storage type for session')\n .optional(),\n\n deviceKey: z\n .string()\n .default('elbDeviceId')\n .describe('Storage key for device ID')\n .optional(),\n\n deviceStorage: z\n .enum(['local', 'session'])\n .default('local')\n .describe('Storage type for device')\n .optional(),\n\n deviceAge: z\n .number()\n .default(30)\n .describe('Device ID age in days')\n .optional(),\n\n // Note: Using z.any() because z.custom() cannot be converted to JSON Schema\n // TypeScript types provide compile-time safety; runtime accepts function or false\n cb: z\n .any()\n .describe('Custom session callback function or false to disable')\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","export * as step from './step';\nexport { createTrigger, trigger } from './trigger';\n","import type { Flow } from '@walkeros/core';\n\nexport const newMarketingSession: Flow.StepExample = {\n trigger: {\n type: 'load',\n options: {\n url: 'https://example.com/?utm_source=google&utm_medium=cpc&utm_campaign=winter-sale',\n },\n },\n in: { storage: true },\n out: {\n name: 'session start',\n data: {\n isStart: true,\n isNew: true,\n count: 1,\n runs: 1,\n storage: true,\n id: 's3ss10n-id',\n device: 'd3v1c3-id',\n start: 1700000000000,\n marketing: true,\n source: 'google',\n medium: 'cpc',\n campaign: 'winter-sale',\n },\n entity: 'session',\n action: 'start',\n },\n};\n\nexport const returningVisitor: Flow.StepExample = {\n trigger: {\n type: 'load',\n options: {\n referrer: 'https://google.com',\n },\n },\n in: { storage: true },\n out: {\n name: 'session start',\n data: {\n isStart: true,\n isNew: false,\n count: 3,\n runs: 1,\n storage: true,\n id: 'n3w-s3ss10n',\n device: 'd3v1c3-id',\n start: 1700001000000,\n referrer: 'google.com',\n },\n entity: 'session',\n action: 'start',\n },\n};\n","import type { Trigger, Collector } from '@walkeros/core';\nimport { startFlow } from '@walkeros/collector';\n\ninterface SessionTriggerOptions {\n url?: string;\n referrer?: string;\n sessionData?: Record<string, unknown>;\n deviceId?: string;\n sessionKey?: string;\n deviceKey?: string;\n}\n\nconst createTrigger: Trigger.CreateFn<Record<string, unknown>, void> = async (\n config: Collector.InitConfig,\n) => {\n let flow: Trigger.FlowHandle | undefined;\n\n const trigger: Trigger.Fn<Record<string, unknown>, void> =\n (type?: string, opts?: unknown) =>\n async (content: Record<string, unknown>) => {\n const options = (opts || {}) as SessionTriggerOptions;\n\n // Pre-init: seed world state before source reads it\n if (options.url) {\n const urlObj = new URL(options.url);\n window.history.replaceState({}, '', urlObj.pathname + urlObj.search);\n }\n if (options.referrer) {\n Object.defineProperty(document, 'referrer', {\n value: options.referrer,\n configurable: true,\n });\n }\n if (options.sessionData) {\n const key = options.sessionKey || 'elbSessionId';\n localStorage.setItem(key, JSON.stringify(options.sessionData));\n }\n if (options.deviceId) {\n const key = options.deviceKey || 'elbDeviceId';\n localStorage.setItem(key, options.deviceId);\n }\n\n // Lazy startFlow — session source fires events during init, but\n // collector.allowed is false until command('run'). The initial\n // session event is dropped. After startFlow, clear the session\n // data written by the dropped init, re-seed, and trigger a consent\n // update to cause session re-init with allowed=true.\n if (!flow) {\n const result = await startFlow({ ...config, run: config.run ?? true });\n flow = { collector: result.collector, elb: result.elb };\n\n // Clear session data written by the dropped init\n const sessionKey =\n options.sessionKey ||\n ((\n config.sources?.session?.config?.settings as Record<string, unknown>\n )?.sessionKey as string) ||\n 'elbSessionId';\n const deviceKey =\n options.deviceKey ||\n ((\n config.sources?.session?.config?.settings as Record<string, unknown>\n )?.deviceKey as string) ||\n 'elbDeviceId';\n localStorage.removeItem(sessionKey);\n localStorage.removeItem(deviceKey);\n\n // Re-seed localStorage if trigger options specified session data\n if (options.sessionData) {\n localStorage.setItem(sessionKey, JSON.stringify(options.sessionData));\n }\n if (options.deviceId) {\n localStorage.setItem(deviceKey, options.deviceId);\n }\n\n // Re-apply consent to trigger session source on('consent') handler.\n // Now allowed=true so the session start event reaches destinations.\n if (config.consent) {\n await flow.collector.command('consent', config.consent);\n }\n }\n };\n\n return {\n get flow() {\n return flow;\n },\n trigger,\n };\n};\n\n/** Prepares localStorage with session/device data before source init. */\nconst trigger = (input: unknown, env: Record<string, unknown>): void => {\n if (!input || typeof input !== 'object') return;\n const data = input as Record<string, unknown>;\n const storage = env.localStorage as Storage;\n\n if (data.sessionData && typeof data.sessionData === 'object') {\n const key =\n typeof data.sessionKey === 'string' ? data.sessionKey : 'elbSessionId';\n storage.setItem(key, JSON.stringify(data.sessionData));\n }\n\n if (typeof data.deviceId === 'string') {\n const key =\n typeof data.deviceKey === 'string' ? data.deviceKey : 'elbDeviceId';\n storage.setItem(key, data.deviceId);\n }\n};\n\nexport { createTrigger, trigger };\n"],"mappings":"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","names":["trigger","_e"]}
|
|
1
|
+
{"version":3,"sources":["../src/schemas/index.ts","../src/schemas/settings.ts","../src/examples/index.ts","../src/examples/step.ts","../src/examples/trigger.ts"],"sourcesContent":["import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\n\n// Export Zod schemas and types\nexport { SettingsSchema, type Settings } from './settings';\n\n// JSON Schema exports (for website PropertyTable)\nexport const settings = zodToSchema(SettingsSchema);\n","import { z } from '@walkeros/core/dev';\nimport { ClickIdEntrySchema } from '@walkeros/core';\n\n/**\n * Session source settings schema\n */\nexport const SettingsSchema = z.object({\n storage: z\n .boolean()\n .default(false)\n .describe('Enable persistent storage for session/device IDs')\n .optional(),\n\n consent: z\n .union([z.string(), z.array(z.string())])\n .describe('Consent key(s) required to enable storage mode')\n .optional(),\n\n length: z\n .number()\n .default(30)\n .describe('Session timeout in minutes')\n .optional(),\n\n pulse: z\n .boolean()\n .default(false)\n .describe('Keep session alive on each event')\n .optional(),\n\n sessionKey: z\n .string()\n .default('elbSessionId')\n .describe('Storage key for session ID')\n .optional(),\n\n sessionStorage: z\n .enum(['local', 'session'])\n .default('local')\n .describe('Storage type for session')\n .optional(),\n\n deviceKey: z\n .string()\n .default('elbDeviceId')\n .describe('Storage key for device ID')\n .optional(),\n\n deviceStorage: z\n .enum(['local', 'session'])\n .default('local')\n .describe('Storage type for device')\n .optional(),\n\n deviceAge: z\n .number()\n .default(30)\n .describe('Device ID age in days')\n .optional(),\n\n // Note: Using z.any() because z.custom() cannot be converted to JSON Schema\n // TypeScript types provide compile-time safety; runtime accepts function or false\n cb: z\n .any()\n .describe('Custom session callback function or false to disable')\n .optional(),\n\n clickIds: z\n .array(ClickIdEntrySchema)\n .describe(\n 'Custom click-ID registry. Entries with a `param` matching a default override the platform name in place; new params append to the end of the priority list.',\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","export * as step from './step';\nexport { createTrigger, trigger } from './trigger';\n","import type { Flow } from '@walkeros/core';\n\nexport const newMarketingSession: Flow.StepExample = {\n trigger: {\n type: 'load',\n options: {\n url: 'https://example.com/?utm_source=google&utm_medium=cpc&utm_campaign=winter-sale',\n },\n },\n in: { storage: true },\n out: {\n name: 'session start',\n data: {\n isStart: true,\n isNew: true,\n count: 1,\n runs: 1,\n storage: true,\n id: 's3ss10n-id',\n device: 'd3v1c3-id',\n start: 1700000000000,\n marketing: true,\n source: 'google',\n medium: 'cpc',\n campaign: 'winter-sale',\n },\n entity: 'session',\n action: 'start',\n },\n};\n\nexport const returningVisitor: Flow.StepExample = {\n trigger: {\n type: 'load',\n options: {\n referrer: 'https://google.com',\n },\n },\n in: { storage: true },\n out: {\n name: 'session start',\n data: {\n isStart: true,\n isNew: false,\n count: 3,\n runs: 1,\n storage: true,\n id: 'n3w-s3ss10n',\n device: 'd3v1c3-id',\n start: 1700001000000,\n referrer: 'google.com',\n },\n entity: 'session',\n action: 'start',\n },\n};\n","import type { Trigger, Collector } from '@walkeros/core';\nimport { startFlow } from '@walkeros/collector';\n\ninterface SessionTriggerOptions {\n url?: string;\n referrer?: string;\n sessionData?: Record<string, unknown>;\n deviceId?: string;\n sessionKey?: string;\n deviceKey?: string;\n}\n\nconst createTrigger: Trigger.CreateFn<Record<string, unknown>, void> = async (\n config: Collector.InitConfig,\n) => {\n let flow: Trigger.FlowHandle | undefined;\n\n const trigger: Trigger.Fn<Record<string, unknown>, void> =\n (type?: string, opts?: unknown) =>\n async (content: Record<string, unknown>) => {\n const options = (opts || {}) as SessionTriggerOptions;\n\n // Pre-init: seed world state before source reads it\n if (options.url) {\n const urlObj = new URL(options.url);\n window.history.replaceState({}, '', urlObj.pathname + urlObj.search);\n }\n if (options.referrer) {\n Object.defineProperty(document, 'referrer', {\n value: options.referrer,\n configurable: true,\n });\n }\n if (options.sessionData) {\n const key = options.sessionKey || 'elbSessionId';\n localStorage.setItem(key, JSON.stringify(options.sessionData));\n }\n if (options.deviceId) {\n const key = options.deviceKey || 'elbDeviceId';\n localStorage.setItem(key, options.deviceId);\n }\n\n // Lazy startFlow — session source fires events during init, but\n // collector.allowed is false until command('run'). The initial\n // session event is dropped. After startFlow, clear the session\n // data written by the dropped init, re-seed, and trigger a consent\n // update to cause session re-init with allowed=true.\n if (!flow) {\n const result = await startFlow({ ...config, run: config.run ?? true });\n flow = { collector: result.collector, elb: result.elb };\n\n // Clear session data written by the dropped init\n const sessionKey =\n options.sessionKey ||\n ((\n config.sources?.session?.config?.settings as Record<string, unknown>\n )?.sessionKey as string) ||\n 'elbSessionId';\n const deviceKey =\n options.deviceKey ||\n ((\n config.sources?.session?.config?.settings as Record<string, unknown>\n )?.deviceKey as string) ||\n 'elbDeviceId';\n localStorage.removeItem(sessionKey);\n localStorage.removeItem(deviceKey);\n\n // Re-seed localStorage if trigger options specified session data\n if (options.sessionData) {\n localStorage.setItem(sessionKey, JSON.stringify(options.sessionData));\n }\n if (options.deviceId) {\n localStorage.setItem(deviceKey, options.deviceId);\n }\n\n // Re-apply consent to trigger session source on('consent') handler.\n // Now allowed=true so the session start event reaches destinations.\n if (config.consent) {\n await flow.collector.command('consent', config.consent);\n }\n }\n };\n\n return {\n get flow() {\n return flow;\n },\n trigger,\n };\n};\n\n/** Prepares localStorage with session/device data before source init. */\nconst trigger = (input: unknown, env: Record<string, unknown>): void => {\n if (!input || typeof input !== 'object') return;\n const data = input as Record<string, unknown>;\n const storage = env.localStorage as Storage;\n\n if (data.sessionData && typeof data.sessionData === 'object') {\n const key =\n typeof data.sessionKey === 'string' ? data.sessionKey : 'elbSessionId';\n storage.setItem(key, JSON.stringify(data.sessionData));\n }\n\n if (typeof data.deviceId === 'string') {\n const key =\n typeof data.deviceKey === 'string' ? data.deviceKey : 'elbDeviceId';\n storage.setItem(key, data.deviceId);\n }\n};\n\nexport { createTrigger, trigger };\n"],"mappings":"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","names":["trigger","_e"]}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { WalkerOS, MarketingParameters, Collector, StorageType, Source, Elb } from '@walkeros/core';
|
|
1
|
+
import { ClickIdEntry, WalkerOS, MarketingParameters, Collector, StorageType, Source, Elb } from '@walkeros/core';
|
|
2
2
|
|
|
3
3
|
interface SessionWindowConfig {
|
|
4
|
+
clickIds?: ClickIdEntry[];
|
|
4
5
|
data?: WalkerOS.Properties;
|
|
5
6
|
domains?: string[];
|
|
6
7
|
isStart?: boolean;
|
|
@@ -24,6 +25,7 @@ interface SessionStorageConfig extends SessionWindowConfig {
|
|
|
24
25
|
declare function sessionStorage(config?: SessionStorageConfig): Collector.SessionData;
|
|
25
26
|
|
|
26
27
|
interface SessionConfig extends SessionStorageConfig {
|
|
28
|
+
clickIds?: ClickIdEntry[];
|
|
27
29
|
consent?: string | string[];
|
|
28
30
|
storage?: boolean;
|
|
29
31
|
cb?: SessionCallback | false;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { WalkerOS, MarketingParameters, Collector, StorageType, Source, Elb } from '@walkeros/core';
|
|
1
|
+
import { ClickIdEntry, WalkerOS, MarketingParameters, Collector, StorageType, Source, Elb } from '@walkeros/core';
|
|
2
2
|
|
|
3
3
|
interface SessionWindowConfig {
|
|
4
|
+
clickIds?: ClickIdEntry[];
|
|
4
5
|
data?: WalkerOS.Properties;
|
|
5
6
|
domains?: string[];
|
|
6
7
|
isStart?: boolean;
|
|
@@ -24,6 +25,7 @@ interface SessionStorageConfig extends SessionWindowConfig {
|
|
|
24
25
|
declare function sessionStorage(config?: SessionStorageConfig): Collector.SessionData;
|
|
25
26
|
|
|
26
27
|
interface SessionConfig extends SessionStorageConfig {
|
|
28
|
+
clickIds?: ClickIdEntry[];
|
|
27
29
|
consent?: string | string[];
|
|
28
30
|
storage?: boolean;
|
|
29
31
|
cb?: SessionCallback | false;
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,o=Object.prototype.hasOwnProperty,s={};((e,n)=>{for(var r in n)t(e,r,{get:n[r],enumerable:!0})})(s,{SourceSession:()=>f,default:()=>v,sessionStart:()=>g,sessionStorage:()=>u,sessionWindow:()=>d,sourceSession:()=>p}),module.exports=(e=s,((e,s,i,
|
|
1
|
+
"use strict";var e,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,o=Object.prototype.hasOwnProperty,s={};((e,n)=>{for(var r in n)t(e,r,{get:n[r],enumerable:!0})})(s,{SourceSession:()=>f,default:()=>v,sessionStart:()=>g,sessionStorage:()=>u,sessionWindow:()=>d,sourceSession:()=>p}),module.exports=(e=s,((e,s,i,c)=>{if(s&&"object"==typeof s||"function"==typeof s)for(let a of r(s))o.call(e,a)||a===i||t(e,a,{get:()=>s[a],enumerable:!(c=n(s,a))||c.enumerable});return e})(t({},"__esModule",{value:!0}),e));var i=require("@walkeros/core"),c=require("@walkeros/web-core"),a=require("@walkeros/core");function d(e={}){var t,n;let r=e.isStart||!1;const o={isStart:r,storage:!1};if(!1===e.isStart)return o;const s=null!=(t=e.window)?t:window,i=null!=(n=e.document)?n:document;if(!r){const[e]=s.performance.getEntriesByType("navigation");if("navigate"!==e.type)return o}const c=new URL(e.url||s.location.href),d=e.referrer||i.referrer,u=d&&new URL(d).hostname,l=(0,a.getMarketingParameters)(c,e.parameters,e.clickIds);if(Object.keys(l).length&&(l.marketing||(l.marketing=!0),r=!0),!r){const t=e.domains||[];t.push(c.hostname),r=!t.includes(u)}return r?Object.assign({isStart:r,storage:!1,start:Date.now(),id:(0,a.getId)(12),referrer:u},l,e.data):o}function u(e={}){const t=Date.now(),{length:n=30,deviceKey:r="elbDeviceId",deviceStorage:o="local",deviceAge:s=30,sessionKey:a="elbSessionId",sessionStorage:u="local",pulse:l=!1}=e,g=e.window||e.document?{window:e.window,document:e.document}:void 0,m=d(e);let w=!1;const f=(0,i.tryCatch)((e,t,n)=>{let r=(0,c.storageRead)(e,n,g);return r||(r=(0,i.getId)(8),(0,c.storageWrite)(e,r,1440*t,n,void 0,g)),String(r)})(r,s,o),p=(0,i.tryCatch)((e,r)=>{const o=JSON.parse(String((0,c.storageRead)(e,r,g)));return l||(o.isNew=!1,m.marketing&&(Object.assign(o,m),w=!0),w||o.updated+6e4*n<t?(delete o.id,delete o.referrer,o.start=t,o.count++,o.runs=1,w=!0):o.runs++),o},()=>{w=!0})(a,u)||{},v={id:(0,i.getId)(12),start:t,isNew:!0,count:1,runs:1},y=Object.assign(v,m,p,{device:f},{isStart:w,storage:!0,updated:t},e.data);return(0,c.storageWrite)(a,JSON.stringify(y),2*n,u,void 0,g),y}var l=require("@walkeros/core");function g(e={}){const{cb:t,consent:n,collector:r,storage:o}=e;if(!n)return m((o?u:d)(e),r,t);{const o=function(e,t){let n;const r=(r,o)=>{if((0,l.isDefined)(n)&&n===(null==r?void 0:r.group))return;n=null==r?void 0:r.group;let s=()=>d(e);if(e.consent){const t=((0,l.isArray)(e.consent)?e.consent:[e.consent]).reduce((e,t)=>({...e,[t]:!0}),{});(0,l.getGrantedConsent)(t,o)&&(s=()=>u(e))}return m(s(),r,t)};return r}(e,t),s=((0,l.isArray)(n)?n:[n]).reduce((e,t)=>({...e,[t]:o}),{});r&&r.command("on","consent",s)}}function m(e,t,n){return!1===n?e:(n||(n=w),n(e,t,w))}var w=(e,t)=>{const n={};return e.id&&(n.session=e.id),e.storage&&e.device&&(n.device=e.device),t&&(t.command("user",n),t.command("session",e)),e.isStart&&t&&t.push({name:"session start",data:e}),e},f={},p=async e=>{const{config:t,env:n}=e,{elb:r,command:o}=n,s={...null==t?void 0:t.settings},i={settings:s},c={push:r,group:void 0,command:o};g({...s,window:n.window,document:n.document,collector:c});return{type:"session",config:i,push:r,on:async e=>{"consent"===e&&g({...s,window:n.window,document:n.document,collector:c})}}},v=p;//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/lib/sessionStorage.ts","../src/lib/sessionWindow.ts","../src/lib/sessionStart.ts","../src/types/index.ts"],"sourcesContent":["import type { Source, On, Collector } from '@walkeros/core';\nimport type { Types, Settings } from './types';\nimport { sessionStart } from './lib';\n\n// Export types for external usage\nexport * as SourceSession from './types';\n\n// Export lib functions for direct usage\nexport { sessionStart, sessionStorage, sessionWindow } from './lib';\nexport type {\n SessionConfig,\n SessionCallback,\n SessionFunction,\n SessionStorageConfig,\n SessionWindowConfig,\n} from './lib';\n\n/**\n * Session source implementation.\n *\n * This source handles session detection and management.\n */\nexport const sourceSession: Source.Init<Types> = async (context) => {\n const { config, env } = context;\n const { elb, command } = env;\n\n const settings: Settings = {\n ...config?.settings,\n };\n\n const fullConfig: Source.Config<Types> = {\n settings,\n };\n\n // Create minimal collector interface for sessionStart\n const collectorInterface: Partial<Collector.Instance> = {\n push: elb,\n group: undefined,\n command,\n };\n\n // Initialize session using local lib\n sessionStart({\n ...settings,\n window: env.window,\n document: env.document,\n collector: collectorInterface as Collector.Instance,\n });\n\n // Handle events pushed from collector (consent, session, ready, run)\n const handleEvent = async (event: On.Types) => {\n if (event === 'consent') {\n // Re-initialize session on consent changes\n sessionStart({\n ...settings,\n window: env.window,\n document: env.document,\n collector: collectorInterface as Collector.Instance,\n });\n }\n };\n\n return {\n type: 'session',\n config: fullConfig,\n push: elb,\n on: handleEvent,\n };\n};\n\nexport default sourceSession;\n","import type { Collector } from '@walkeros/core';\nimport type { SessionWindowConfig } from './sessionWindow';\nimport type { StorageType } from '@walkeros/core';\nimport type { StorageEnv } from '@walkeros/web-core';\nimport { getId, tryCatch } from '@walkeros/core';\nimport { storageRead, storageWrite } from '@walkeros/web-core';\nimport { sessionWindow } from './sessionWindow';\n\nexport interface SessionStorageConfig extends SessionWindowConfig {\n deviceKey?: string;\n deviceStorage?: StorageType;\n deviceAge?: number;\n sessionKey?: string;\n sessionStorage?: StorageType;\n length?: number; // Minutes after last update to consider session as expired (default: 30)\n pulse?: boolean;\n}\n\nexport function sessionStorage(\n config: SessionStorageConfig = {},\n): Collector.SessionData {\n const now = Date.now();\n const {\n length = 30, // Session length in minutes\n deviceKey = 'elbDeviceId',\n deviceStorage = 'local',\n deviceAge = 30, // Device ID age in days\n sessionKey = 'elbSessionId',\n sessionStorage = 'local',\n pulse = false, // Handle the counting\n } = config;\n const storageEnv: StorageEnv | undefined =\n config.window || config.document\n ? { window: config.window, document: config.document }\n : undefined;\n const windowSession = sessionWindow(config); // Status based on window only\n let isStart = false;\n\n // Retrieve or create device ID\n const device = tryCatch((key: string, age: number, storage: StorageType) => {\n let id = storageRead(key, storage, storageEnv);\n if (!id) {\n id = getId(8); // Create a new device ID\n storageWrite(key, id, age * 1440, storage, undefined, storageEnv); // Write device ID to storage\n }\n return String(id);\n })(deviceKey, deviceAge, deviceStorage);\n\n // Retrieve or initialize session data\n const existingSession: Collector.SessionData =\n tryCatch(\n (key: string, storage?: StorageType) => {\n const session = JSON.parse(\n String(storageRead(key, storage, storageEnv)),\n );\n\n // Only update session if it's not a pulse check\n if (pulse) return session;\n\n // Mark session as not new by default\n session.isNew = false;\n\n // Handle new marketing entry\n if (windowSession.marketing) {\n Object.assign(session, windowSession); // Overwrite existing session with marketing data\n isStart = true; // This is a session start\n }\n\n // Check if session is still active\n if (isStart || session.updated + length * 60000 < now) {\n // Session has expired\n delete session.id; // Unset session ID\n delete session.referrer; // Unset referrer\n session.start = now; // Set new session start\n session.count++; // Increase session count\n session.runs = 1; // Reset runs\n isStart = true; // It's a new session\n } else {\n // Session is still active\n session.runs++; // Increase number of runs\n }\n\n return session;\n },\n () => {\n // No existing session or something went wrong\n isStart = true; // Start a new session\n },\n )(sessionKey, sessionStorage) || {};\n\n // Default session data\n const defaultSession: Partial<Collector.SessionData> = {\n id: getId(12),\n start: now,\n isNew: true,\n count: 1,\n runs: 1,\n };\n\n // Merge session data\n const session = Object.assign(\n defaultSession, // Default session values\n windowSession, // Basic session data based on window\n existingSession, // (Updated) existing session\n { device }, // Device ID\n { isStart, storage: true, updated: now }, // Status of the session\n config.data, // Given data has the highest priority\n );\n\n // Write (updated) session to storage\n storageWrite(\n sessionKey,\n JSON.stringify(session),\n length * 2,\n sessionStorage,\n undefined,\n storageEnv,\n );\n\n return session;\n}\n","import type { Collector, WalkerOS } from '@walkeros/core';\nimport {\n getId,\n getMarketingParameters,\n type MarketingParameters,\n} from '@walkeros/core';\n\nexport interface SessionWindowConfig {\n data?: WalkerOS.Properties;\n domains?: string[];\n isStart?: boolean;\n parameters?: MarketingParameters;\n referrer?: string;\n url?: string;\n window?: Window & typeof globalThis;\n document?: Document;\n}\n\nexport function sessionWindow(\n config: SessionWindowConfig = {},\n): Collector.SessionData {\n let isStart = config.isStart || false;\n const known = { isStart, storage: false };\n\n // If session has explicitly started, return known\n if (config.isStart === false) return known;\n\n const win = config.window ?? window;\n const doc = config.document ?? document;\n\n // Entry type\n if (!isStart) {\n // Only focus on linked or direct navigation types\n // and ignore reloads and all others\n const [perf] = win.performance.getEntriesByType(\n 'navigation',\n ) as PerformanceNavigationTiming[];\n if (perf.type !== 'navigate') return known;\n }\n\n const url = new URL(config.url || win.location.href);\n const ref = config.referrer || doc.referrer;\n const referrer = ref && new URL(ref).hostname;\n\n // Marketing\n const marketing = getMarketingParameters(url, config.parameters);\n if (Object.keys(marketing).length) {\n // Check for marketing parameters like UTM and add existing\n if (!marketing.marketing)\n // Flag as a marketing session without overwriting\n marketing.marketing = true;\n\n isStart = true;\n }\n\n // Referrer\n if (!isStart) {\n // Small chance of multiple unintended events for same users\n // https://en.wikipedia.org/wiki/HTTP_referer#Referrer_hiding\n // Use domains: [''] to disable direct or hidden referrer\n\n const domains = config.domains || [];\n domains.push(url.hostname);\n isStart = !domains.includes(referrer);\n }\n\n return isStart\n ? // It's a session start, moin\n Object.assign(\n {\n isStart,\n storage: false,\n start: Date.now(),\n id: getId(12),\n referrer,\n },\n marketing,\n config.data,\n )\n : // No session start\n known;\n}\n","import type { Collector, WalkerOS, On } from '@walkeros/core';\nimport type { SessionStorageConfig } from './sessionStorage';\nimport { sessionStorage } from './sessionStorage';\nimport { sessionWindow } from './sessionWindow';\nimport { getGrantedConsent, isArray, isDefined } from '@walkeros/core';\n\nexport interface SessionConfig extends SessionStorageConfig {\n consent?: string | string[];\n storage?: boolean;\n cb?: SessionCallback | false;\n collector?: Collector.Instance;\n}\n\nexport type SessionFunction = typeof sessionStorage | typeof sessionWindow;\nexport type SessionCallback = (\n session: Collector.SessionData,\n collector: Collector.Instance | undefined,\n defaultCb: SessionCallback,\n) => void;\n\nexport function sessionStart(\n config: SessionConfig = {},\n): Collector.SessionData | void {\n const { cb, consent, collector, storage } = config;\n const sessionFn: SessionFunction = storage ? sessionStorage : sessionWindow;\n\n // Consent\n if (consent) {\n const consentHandler = onConsentFn(config, cb);\n\n const consentConfig = (\n isArray(consent) ? consent : [consent]\n ).reduce<On.ConsentConfig>(\n (acc, key) => ({ ...acc, [key]: consentHandler }),\n {},\n );\n // Register consent handlers with the collector\n if (collector) {\n collector.command('on', 'consent', consentConfig);\n }\n // No fallback - session source always provides collector\n } else {\n // just do it\n return callFuncAndCb(sessionFn(config), collector, cb);\n }\n}\n\nfunction callFuncAndCb(\n session: Collector.SessionData,\n collector?: Collector.Instance,\n cb?: SessionCallback | false,\n) {\n if (cb === false) return session; // Callback is disabled\n if (!cb) cb = defaultCb; // Default callback if none is provided\n return cb(session, collector, defaultCb);\n}\n\nfunction onConsentFn(config: SessionConfig, cb?: SessionCallback | false) {\n // Track the last processed group to prevent duplicate processing\n let lastProcessedGroup: string | undefined;\n\n const func = (collector: Collector.Instance, consent: WalkerOS.Consent) => {\n // Skip if we've already processed this group\n if (\n isDefined(lastProcessedGroup) &&\n lastProcessedGroup === collector?.group\n )\n return;\n\n // Remember this group has been processed\n lastProcessedGroup = collector?.group;\n\n let sessionFn: SessionFunction = () => sessionWindow(config); // Window by default\n\n if (config.consent) {\n const consentKeys = (\n isArray(config.consent) ? config.consent : [config.consent]\n ).reduce<WalkerOS.Consent>((acc, key) => ({ ...acc, [key]: true }), {});\n\n if (getGrantedConsent(consentKeys, consent))\n // Use storage if consent is granted\n sessionFn = () => sessionStorage(config);\n }\n\n return callFuncAndCb(sessionFn(), collector, cb);\n };\n\n return func;\n}\n\nconst defaultCb: SessionCallback = (\n session,\n collector,\n): Collector.SessionData => {\n const user: WalkerOS.User = {};\n\n // User.session is the session ID\n if (session.id) user.session = session.id;\n\n // Set device ID only in storage mode\n if (session.storage && session.device) user.device = session.device;\n\n // Set user IDs and broadcast session data\n if (collector) {\n collector.command('user', user);\n collector.command('session', session);\n }\n // No fallback - session source always provides collector\n\n if (session.isStart) {\n // Convert session start to an event object\n if (collector) {\n collector.push({\n name: 'session start',\n data: session,\n });\n }\n // No fallback - session source always provides collector\n }\n\n return session;\n};\n","import type { Source, Elb } from '@walkeros/core';\nimport type { SessionConfig, SessionCallback } from '../lib';\n\n// Settings: configuration for session source\nexport interface Settings extends SessionConfig {\n // All settings inherited from SessionConfig:\n // - consent?: string | string[]\n // - storage?: boolean\n // - cb?: SessionCallback | false\n // - pulse?: boolean\n // - sessionStorage?: 'local' | 'session'\n // - deviceStorage?: 'local' | 'session'\n // - sessionKey?: string\n // - deviceKey?: string\n // - length?: number (session timeout in minutes)\n}\n\n// InitSettings: user input (all optional)\nexport type InitSettings = Partial<Settings>;\n\nexport interface Mapping {}\n\nexport type Push = Elb.Fn;\n\nexport interface Env extends Source.BaseEnv {\n window?: Window & typeof globalThis;\n document?: Document;\n}\n\nexport type Types = Source.Types<Settings, Mapping, Push, Env, InitSettings>;\n\nexport type Config = Source.Config<Types>;\n\n// Re-export session types from lib\nexport type {\n SessionConfig,\n SessionCallback,\n SessionFunction,\n SessionStorageConfig,\n SessionWindowConfig,\n} from '../lib';\n"],"mappings":"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","names":["import_core","sessionStorage","session","import_core"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/lib/sessionStorage.ts","../src/lib/sessionWindow.ts","../src/lib/sessionStart.ts","../src/types/index.ts"],"sourcesContent":["import type { Source, On, Collector } from '@walkeros/core';\nimport type { Types, Settings } from './types';\nimport { sessionStart } from './lib';\n\n// Export types for external usage\nexport * as SourceSession from './types';\n\n// Export lib functions for direct usage\nexport { sessionStart, sessionStorage, sessionWindow } from './lib';\nexport type {\n SessionConfig,\n SessionCallback,\n SessionFunction,\n SessionStorageConfig,\n SessionWindowConfig,\n} from './lib';\n\n/**\n * Session source implementation.\n *\n * This source handles session detection and management.\n */\nexport const sourceSession: Source.Init<Types> = async (context) => {\n const { config, env } = context;\n const { elb, command } = env;\n\n const settings: Settings = {\n ...config?.settings,\n };\n\n const fullConfig: Source.Config<Types> = {\n settings,\n };\n\n // Create minimal collector interface for sessionStart\n const collectorInterface: Partial<Collector.Instance> = {\n push: elb,\n group: undefined,\n command,\n };\n\n // Initialize session using local lib\n sessionStart({\n ...settings,\n window: env.window,\n document: env.document,\n collector: collectorInterface as Collector.Instance,\n });\n\n // Handle events pushed from collector (consent, session, ready, run)\n const handleEvent = async (event: On.Types) => {\n if (event === 'consent') {\n // Re-initialize session on consent changes\n sessionStart({\n ...settings,\n window: env.window,\n document: env.document,\n collector: collectorInterface as Collector.Instance,\n });\n }\n };\n\n return {\n type: 'session',\n config: fullConfig,\n push: elb,\n on: handleEvent,\n };\n};\n\nexport default sourceSession;\n","import type { Collector } from '@walkeros/core';\nimport type { SessionWindowConfig } from './sessionWindow';\nimport type { StorageType } from '@walkeros/core';\nimport type { StorageEnv } from '@walkeros/web-core';\nimport { getId, tryCatch } from '@walkeros/core';\nimport { storageRead, storageWrite } from '@walkeros/web-core';\nimport { sessionWindow } from './sessionWindow';\n\nexport interface SessionStorageConfig extends SessionWindowConfig {\n deviceKey?: string;\n deviceStorage?: StorageType;\n deviceAge?: number;\n sessionKey?: string;\n sessionStorage?: StorageType;\n length?: number; // Minutes after last update to consider session as expired (default: 30)\n pulse?: boolean;\n}\n\nexport function sessionStorage(\n config: SessionStorageConfig = {},\n): Collector.SessionData {\n const now = Date.now();\n const {\n length = 30, // Session length in minutes\n deviceKey = 'elbDeviceId',\n deviceStorage = 'local',\n deviceAge = 30, // Device ID age in days\n sessionKey = 'elbSessionId',\n sessionStorage = 'local',\n pulse = false, // Handle the counting\n } = config;\n const storageEnv: StorageEnv | undefined =\n config.window || config.document\n ? { window: config.window, document: config.document }\n : undefined;\n const windowSession = sessionWindow(config); // Status based on window only\n let isStart = false;\n\n // Retrieve or create device ID\n const device = tryCatch((key: string, age: number, storage: StorageType) => {\n let id = storageRead(key, storage, storageEnv);\n if (!id) {\n id = getId(8); // Create a new device ID\n storageWrite(key, id, age * 1440, storage, undefined, storageEnv); // Write device ID to storage\n }\n return String(id);\n })(deviceKey, deviceAge, deviceStorage);\n\n // Retrieve or initialize session data\n const existingSession: Collector.SessionData =\n tryCatch(\n (key: string, storage?: StorageType) => {\n const session = JSON.parse(\n String(storageRead(key, storage, storageEnv)),\n );\n\n // Only update session if it's not a pulse check\n if (pulse) return session;\n\n // Mark session as not new by default\n session.isNew = false;\n\n // Handle new marketing entry\n if (windowSession.marketing) {\n Object.assign(session, windowSession); // Overwrite existing session with marketing data\n isStart = true; // This is a session start\n }\n\n // Check if session is still active\n if (isStart || session.updated + length * 60000 < now) {\n // Session has expired\n delete session.id; // Unset session ID\n delete session.referrer; // Unset referrer\n session.start = now; // Set new session start\n session.count++; // Increase session count\n session.runs = 1; // Reset runs\n isStart = true; // It's a new session\n } else {\n // Session is still active\n session.runs++; // Increase number of runs\n }\n\n return session;\n },\n () => {\n // No existing session or something went wrong\n isStart = true; // Start a new session\n },\n )(sessionKey, sessionStorage) || {};\n\n // Default session data\n const defaultSession: Partial<Collector.SessionData> = {\n id: getId(12),\n start: now,\n isNew: true,\n count: 1,\n runs: 1,\n };\n\n // Merge session data\n const session = Object.assign(\n defaultSession, // Default session values\n windowSession, // Basic session data based on window\n existingSession, // (Updated) existing session\n { device }, // Device ID\n { isStart, storage: true, updated: now }, // Status of the session\n config.data, // Given data has the highest priority\n );\n\n // Write (updated) session to storage\n storageWrite(\n sessionKey,\n JSON.stringify(session),\n length * 2,\n sessionStorage,\n undefined,\n storageEnv,\n );\n\n return session;\n}\n","import type { Collector, WalkerOS } from '@walkeros/core';\nimport {\n getId,\n getMarketingParameters,\n type ClickIdEntry,\n type MarketingParameters,\n} from '@walkeros/core';\n\nexport interface SessionWindowConfig {\n clickIds?: ClickIdEntry[];\n data?: WalkerOS.Properties;\n domains?: string[];\n isStart?: boolean;\n parameters?: MarketingParameters;\n referrer?: string;\n url?: string;\n window?: Window & typeof globalThis;\n document?: Document;\n}\n\nexport function sessionWindow(\n config: SessionWindowConfig = {},\n): Collector.SessionData {\n let isStart = config.isStart || false;\n const known = { isStart, storage: false };\n\n // If session has explicitly started, return known\n if (config.isStart === false) return known;\n\n const win = config.window ?? window;\n const doc = config.document ?? document;\n\n // Entry type\n if (!isStart) {\n // Only focus on linked or direct navigation types\n // and ignore reloads and all others\n const [perf] = win.performance.getEntriesByType(\n 'navigation',\n ) as PerformanceNavigationTiming[];\n if (perf.type !== 'navigate') return known;\n }\n\n const url = new URL(config.url || win.location.href);\n const ref = config.referrer || doc.referrer;\n const referrer = ref && new URL(ref).hostname;\n\n // Marketing\n const marketing = getMarketingParameters(\n url,\n config.parameters,\n config.clickIds,\n );\n if (Object.keys(marketing).length) {\n // Check for marketing parameters like UTM and add existing\n if (!marketing.marketing)\n // Flag as a marketing session without overwriting\n marketing.marketing = true;\n\n isStart = true;\n }\n\n // Referrer\n if (!isStart) {\n // Small chance of multiple unintended events for same users\n // https://en.wikipedia.org/wiki/HTTP_referer#Referrer_hiding\n // Use domains: [''] to disable direct or hidden referrer\n\n const domains = config.domains || [];\n domains.push(url.hostname);\n isStart = !domains.includes(referrer);\n }\n\n return isStart\n ? // It's a session start, moin\n Object.assign(\n {\n isStart,\n storage: false,\n start: Date.now(),\n id: getId(12),\n referrer,\n },\n marketing,\n config.data,\n )\n : // No session start\n known;\n}\n","import type { Collector, WalkerOS, On, ClickIdEntry } from '@walkeros/core';\nimport type { SessionStorageConfig } from './sessionStorage';\nimport { sessionStorage } from './sessionStorage';\nimport { sessionWindow } from './sessionWindow';\nimport { getGrantedConsent, isArray, isDefined } from '@walkeros/core';\n\nexport interface SessionConfig extends SessionStorageConfig {\n clickIds?: ClickIdEntry[];\n consent?: string | string[];\n storage?: boolean;\n cb?: SessionCallback | false;\n collector?: Collector.Instance;\n}\n\nexport type SessionFunction = typeof sessionStorage | typeof sessionWindow;\nexport type SessionCallback = (\n session: Collector.SessionData,\n collector: Collector.Instance | undefined,\n defaultCb: SessionCallback,\n) => void;\n\nexport function sessionStart(\n config: SessionConfig = {},\n): Collector.SessionData | void {\n const { cb, consent, collector, storage } = config;\n const sessionFn: SessionFunction = storage ? sessionStorage : sessionWindow;\n\n // Consent\n if (consent) {\n const consentHandler = onConsentFn(config, cb);\n\n const consentConfig = (\n isArray(consent) ? consent : [consent]\n ).reduce<On.ConsentConfig>(\n (acc, key) => ({ ...acc, [key]: consentHandler }),\n {},\n );\n // Register consent handlers with the collector\n if (collector) {\n collector.command('on', 'consent', consentConfig);\n }\n // No fallback - session source always provides collector\n } else {\n // just do it\n return callFuncAndCb(sessionFn(config), collector, cb);\n }\n}\n\nfunction callFuncAndCb(\n session: Collector.SessionData,\n collector?: Collector.Instance,\n cb?: SessionCallback | false,\n) {\n if (cb === false) return session; // Callback is disabled\n if (!cb) cb = defaultCb; // Default callback if none is provided\n return cb(session, collector, defaultCb);\n}\n\nfunction onConsentFn(config: SessionConfig, cb?: SessionCallback | false) {\n // Track the last processed group to prevent duplicate processing\n let lastProcessedGroup: string | undefined;\n\n const func = (collector: Collector.Instance, consent: WalkerOS.Consent) => {\n // Skip if we've already processed this group\n if (\n isDefined(lastProcessedGroup) &&\n lastProcessedGroup === collector?.group\n )\n return;\n\n // Remember this group has been processed\n lastProcessedGroup = collector?.group;\n\n let sessionFn: SessionFunction = () => sessionWindow(config); // Window by default\n\n if (config.consent) {\n const consentKeys = (\n isArray(config.consent) ? config.consent : [config.consent]\n ).reduce<WalkerOS.Consent>((acc, key) => ({ ...acc, [key]: true }), {});\n\n if (getGrantedConsent(consentKeys, consent))\n // Use storage if consent is granted\n sessionFn = () => sessionStorage(config);\n }\n\n return callFuncAndCb(sessionFn(), collector, cb);\n };\n\n return func;\n}\n\nconst defaultCb: SessionCallback = (\n session,\n collector,\n): Collector.SessionData => {\n const user: WalkerOS.User = {};\n\n // User.session is the session ID\n if (session.id) user.session = session.id;\n\n // Set device ID only in storage mode\n if (session.storage && session.device) user.device = session.device;\n\n // Set user IDs and broadcast session data\n if (collector) {\n collector.command('user', user);\n collector.command('session', session);\n }\n // No fallback - session source always provides collector\n\n if (session.isStart) {\n // Convert session start to an event object\n if (collector) {\n collector.push({\n name: 'session start',\n data: session,\n });\n }\n // No fallback - session source always provides collector\n }\n\n return session;\n};\n","import type { Source, Elb } from '@walkeros/core';\nimport type { SessionConfig, SessionCallback } from '../lib';\n\n// Settings: configuration for session source\nexport interface Settings extends SessionConfig {\n // All settings inherited from SessionConfig:\n // - consent?: string | string[]\n // - storage?: boolean\n // - cb?: SessionCallback | false\n // - pulse?: boolean\n // - sessionStorage?: 'local' | 'session'\n // - deviceStorage?: 'local' | 'session'\n // - sessionKey?: string\n // - deviceKey?: string\n // - length?: number (session timeout in minutes)\n}\n\n// InitSettings: user input (all optional)\nexport type InitSettings = Partial<Settings>;\n\nexport interface Mapping {}\n\nexport type Push = Elb.Fn;\n\nexport interface Env extends Source.BaseEnv {\n window?: Window & typeof globalThis;\n document?: Document;\n}\n\nexport type Types = Source.Types<Settings, Mapping, Push, Env, InitSettings>;\n\nexport type Config = Source.Config<Types>;\n\n// Re-export session types from lib\nexport type {\n SessionConfig,\n SessionCallback,\n SessionFunction,\n SessionStorageConfig,\n SessionWindowConfig,\n} from '../lib';\n"],"mappings":"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","names":["import_core","sessionStorage","session","import_core"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getId as e,tryCatch as n}from"@walkeros/core";import{storageRead as t,storageWrite as o}from"@walkeros/web-core";import{getId as r,getMarketingParameters as s}from"@walkeros/core";function i(e={}){var n,t;let o=e.isStart||!1;const i={isStart:o,storage:!1};if(!1===e.isStart)return i;const c=null!=(n=e.window)?n:window,a=null!=(t=e.document)?t:document;if(!o){const[e]=c.performance.getEntriesByType("navigation");if("navigate"!==e.type)return i}const d=new URL(e.url||c.location.href),u=e.referrer||a.referrer,l=u&&new URL(u).hostname,m=s(d,e.parameters);if(Object.keys(m).length&&(m.marketing||(m.marketing=!0),o=!0),!o){const n=e.domains||[];n.push(d.hostname),o=!n.includes(l)}return o?Object.assign({isStart:o,storage:!1,start:Date.now(),id:r(12),referrer:l},m,e.data):i}function c(r={}){const s=Date.now(),{length:c=30,deviceKey:a="elbDeviceId",deviceStorage:d="local",deviceAge:u=30,sessionKey:l="elbSessionId",sessionStorage:m="local",pulse:g=!1}=r,w=r.window||r.document?{window:r.window,document:r.document}:void 0,f=i(r);let p=!1;const v=n((n,r,s)=>{let i=t(n,s,w);return i||(i=e(8),o(n,i,1440*r,s,void 0,w)),String(i)})(a,u,d),S=n((e,n)=>{const o=JSON.parse(String(t(e,n,w)));return g||(o.isNew=!1,f.marketing&&(Object.assign(o,f),p=!0),p||o.updated+6e4*c<s?(delete o.id,delete o.referrer,o.start=s,o.count++,o.runs=1,p=!0):o.runs++),o},()=>{p=!0})(l,m)||{},y={id:e(12),start:s,isNew:!0,count:1,runs:1},b=Object.assign(y,f,S,{device:v},{isStart:p,storage:!0,updated:s},r.data);return o(l,JSON.stringify(b),2*c,m,void 0,w),b}import{getGrantedConsent as a,isArray as d,isDefined as u}from"@walkeros/core";function l(e={}){const{cb:n,consent:t,collector:o,storage:r}=e;if(!t)return m((r?c:i)(e),o,n);{const r=function(e,n){let t;const o=(o,r)=>{if(u(t)&&t===(null==o?void 0:o.group))return;t=null==o?void 0:o.group;let s=()=>i(e);if(e.consent){const n=(d(e.consent)?e.consent:[e.consent]).reduce((e,n)=>({...e,[n]:!0}),{});a(n,r)&&(s=()=>c(e))}return m(s(),o,n)};return o}(e,n),s=(d(t)?t:[t]).reduce((e,n)=>({...e,[n]:r}),{});o&&o.command("on","consent",s)}}function m(e,n,t){return!1===t?e:(t||(t=g),t(e,n,g))}var g=(e,n)=>{const t={};return e.id&&(t.session=e.id),e.storage&&e.device&&(t.device=e.device),n&&(n.command("user",t),n.command("session",e)),e.isStart&&n&&n.push({name:"session start",data:e}),e},w={},f=async e=>{const{config:n,env:t}=e,{elb:o,command:r}=t,s={...null==n?void 0:n.settings},i={settings:s},c={push:o,group:void 0,command:r};l({...s,window:t.window,document:t.document,collector:c});return{type:"session",config:i,push:o,on:async e=>{"consent"===e&&l({...s,window:t.window,document:t.document,collector:c})}}},p=f;export{w as SourceSession,p as default,l as sessionStart,c as sessionStorage,i as sessionWindow,f as sourceSession};//# sourceMappingURL=index.mjs.map
|
|
1
|
+
import{getId as e,tryCatch as n}from"@walkeros/core";import{storageRead as t,storageWrite as o}from"@walkeros/web-core";import{getId as r,getMarketingParameters as s}from"@walkeros/core";function i(e={}){var n,t;let o=e.isStart||!1;const i={isStart:o,storage:!1};if(!1===e.isStart)return i;const c=null!=(n=e.window)?n:window,a=null!=(t=e.document)?t:document;if(!o){const[e]=c.performance.getEntriesByType("navigation");if("navigate"!==e.type)return i}const d=new URL(e.url||c.location.href),u=e.referrer||a.referrer,l=u&&new URL(u).hostname,m=s(d,e.parameters,e.clickIds);if(Object.keys(m).length&&(m.marketing||(m.marketing=!0),o=!0),!o){const n=e.domains||[];n.push(d.hostname),o=!n.includes(l)}return o?Object.assign({isStart:o,storage:!1,start:Date.now(),id:r(12),referrer:l},m,e.data):i}function c(r={}){const s=Date.now(),{length:c=30,deviceKey:a="elbDeviceId",deviceStorage:d="local",deviceAge:u=30,sessionKey:l="elbSessionId",sessionStorage:m="local",pulse:g=!1}=r,w=r.window||r.document?{window:r.window,document:r.document}:void 0,f=i(r);let p=!1;const v=n((n,r,s)=>{let i=t(n,s,w);return i||(i=e(8),o(n,i,1440*r,s,void 0,w)),String(i)})(a,u,d),S=n((e,n)=>{const o=JSON.parse(String(t(e,n,w)));return g||(o.isNew=!1,f.marketing&&(Object.assign(o,f),p=!0),p||o.updated+6e4*c<s?(delete o.id,delete o.referrer,o.start=s,o.count++,o.runs=1,p=!0):o.runs++),o},()=>{p=!0})(l,m)||{},y={id:e(12),start:s,isNew:!0,count:1,runs:1},b=Object.assign(y,f,S,{device:v},{isStart:p,storage:!0,updated:s},r.data);return o(l,JSON.stringify(b),2*c,m,void 0,w),b}import{getGrantedConsent as a,isArray as d,isDefined as u}from"@walkeros/core";function l(e={}){const{cb:n,consent:t,collector:o,storage:r}=e;if(!t)return m((r?c:i)(e),o,n);{const r=function(e,n){let t;const o=(o,r)=>{if(u(t)&&t===(null==o?void 0:o.group))return;t=null==o?void 0:o.group;let s=()=>i(e);if(e.consent){const n=(d(e.consent)?e.consent:[e.consent]).reduce((e,n)=>({...e,[n]:!0}),{});a(n,r)&&(s=()=>c(e))}return m(s(),o,n)};return o}(e,n),s=(d(t)?t:[t]).reduce((e,n)=>({...e,[n]:r}),{});o&&o.command("on","consent",s)}}function m(e,n,t){return!1===t?e:(t||(t=g),t(e,n,g))}var g=(e,n)=>{const t={};return e.id&&(t.session=e.id),e.storage&&e.device&&(t.device=e.device),n&&(n.command("user",t),n.command("session",e)),e.isStart&&n&&n.push({name:"session start",data:e}),e},w={},f=async e=>{const{config:n,env:t}=e,{elb:o,command:r}=t,s={...null==n?void 0:n.settings},i={settings:s},c={push:o,group:void 0,command:r};l({...s,window:t.window,document:t.document,collector:c});return{type:"session",config:i,push:o,on:async e=>{"consent"===e&&l({...s,window:t.window,document:t.document,collector:c})}}},p=f;export{w as SourceSession,p as default,l as sessionStart,c as sessionStorage,i as sessionWindow,f as sourceSession};//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/sessionStorage.ts","../src/lib/sessionWindow.ts","../src/lib/sessionStart.ts","../src/types/index.ts","../src/index.ts"],"sourcesContent":["import type { Collector } from '@walkeros/core';\nimport type { SessionWindowConfig } from './sessionWindow';\nimport type { StorageType } from '@walkeros/core';\nimport type { StorageEnv } from '@walkeros/web-core';\nimport { getId, tryCatch } from '@walkeros/core';\nimport { storageRead, storageWrite } from '@walkeros/web-core';\nimport { sessionWindow } from './sessionWindow';\n\nexport interface SessionStorageConfig extends SessionWindowConfig {\n deviceKey?: string;\n deviceStorage?: StorageType;\n deviceAge?: number;\n sessionKey?: string;\n sessionStorage?: StorageType;\n length?: number; // Minutes after last update to consider session as expired (default: 30)\n pulse?: boolean;\n}\n\nexport function sessionStorage(\n config: SessionStorageConfig = {},\n): Collector.SessionData {\n const now = Date.now();\n const {\n length = 30, // Session length in minutes\n deviceKey = 'elbDeviceId',\n deviceStorage = 'local',\n deviceAge = 30, // Device ID age in days\n sessionKey = 'elbSessionId',\n sessionStorage = 'local',\n pulse = false, // Handle the counting\n } = config;\n const storageEnv: StorageEnv | undefined =\n config.window || config.document\n ? { window: config.window, document: config.document }\n : undefined;\n const windowSession = sessionWindow(config); // Status based on window only\n let isStart = false;\n\n // Retrieve or create device ID\n const device = tryCatch((key: string, age: number, storage: StorageType) => {\n let id = storageRead(key, storage, storageEnv);\n if (!id) {\n id = getId(8); // Create a new device ID\n storageWrite(key, id, age * 1440, storage, undefined, storageEnv); // Write device ID to storage\n }\n return String(id);\n })(deviceKey, deviceAge, deviceStorage);\n\n // Retrieve or initialize session data\n const existingSession: Collector.SessionData =\n tryCatch(\n (key: string, storage?: StorageType) => {\n const session = JSON.parse(\n String(storageRead(key, storage, storageEnv)),\n );\n\n // Only update session if it's not a pulse check\n if (pulse) return session;\n\n // Mark session as not new by default\n session.isNew = false;\n\n // Handle new marketing entry\n if (windowSession.marketing) {\n Object.assign(session, windowSession); // Overwrite existing session with marketing data\n isStart = true; // This is a session start\n }\n\n // Check if session is still active\n if (isStart || session.updated + length * 60000 < now) {\n // Session has expired\n delete session.id; // Unset session ID\n delete session.referrer; // Unset referrer\n session.start = now; // Set new session start\n session.count++; // Increase session count\n session.runs = 1; // Reset runs\n isStart = true; // It's a new session\n } else {\n // Session is still active\n session.runs++; // Increase number of runs\n }\n\n return session;\n },\n () => {\n // No existing session or something went wrong\n isStart = true; // Start a new session\n },\n )(sessionKey, sessionStorage) || {};\n\n // Default session data\n const defaultSession: Partial<Collector.SessionData> = {\n id: getId(12),\n start: now,\n isNew: true,\n count: 1,\n runs: 1,\n };\n\n // Merge session data\n const session = Object.assign(\n defaultSession, // Default session values\n windowSession, // Basic session data based on window\n existingSession, // (Updated) existing session\n { device }, // Device ID\n { isStart, storage: true, updated: now }, // Status of the session\n config.data, // Given data has the highest priority\n );\n\n // Write (updated) session to storage\n storageWrite(\n sessionKey,\n JSON.stringify(session),\n length * 2,\n sessionStorage,\n undefined,\n storageEnv,\n );\n\n return session;\n}\n","import type { Collector, WalkerOS } from '@walkeros/core';\nimport {\n getId,\n getMarketingParameters,\n type MarketingParameters,\n} from '@walkeros/core';\n\nexport interface SessionWindowConfig {\n data?: WalkerOS.Properties;\n domains?: string[];\n isStart?: boolean;\n parameters?: MarketingParameters;\n referrer?: string;\n url?: string;\n window?: Window & typeof globalThis;\n document?: Document;\n}\n\nexport function sessionWindow(\n config: SessionWindowConfig = {},\n): Collector.SessionData {\n let isStart = config.isStart || false;\n const known = { isStart, storage: false };\n\n // If session has explicitly started, return known\n if (config.isStart === false) return known;\n\n const win = config.window ?? window;\n const doc = config.document ?? document;\n\n // Entry type\n if (!isStart) {\n // Only focus on linked or direct navigation types\n // and ignore reloads and all others\n const [perf] = win.performance.getEntriesByType(\n 'navigation',\n ) as PerformanceNavigationTiming[];\n if (perf.type !== 'navigate') return known;\n }\n\n const url = new URL(config.url || win.location.href);\n const ref = config.referrer || doc.referrer;\n const referrer = ref && new URL(ref).hostname;\n\n // Marketing\n const marketing = getMarketingParameters(url, config.parameters);\n if (Object.keys(marketing).length) {\n // Check for marketing parameters like UTM and add existing\n if (!marketing.marketing)\n // Flag as a marketing session without overwriting\n marketing.marketing = true;\n\n isStart = true;\n }\n\n // Referrer\n if (!isStart) {\n // Small chance of multiple unintended events for same users\n // https://en.wikipedia.org/wiki/HTTP_referer#Referrer_hiding\n // Use domains: [''] to disable direct or hidden referrer\n\n const domains = config.domains || [];\n domains.push(url.hostname);\n isStart = !domains.includes(referrer);\n }\n\n return isStart\n ? // It's a session start, moin\n Object.assign(\n {\n isStart,\n storage: false,\n start: Date.now(),\n id: getId(12),\n referrer,\n },\n marketing,\n config.data,\n )\n : // No session start\n known;\n}\n","import type { Collector, WalkerOS, On } from '@walkeros/core';\nimport type { SessionStorageConfig } from './sessionStorage';\nimport { sessionStorage } from './sessionStorage';\nimport { sessionWindow } from './sessionWindow';\nimport { getGrantedConsent, isArray, isDefined } from '@walkeros/core';\n\nexport interface SessionConfig extends SessionStorageConfig {\n consent?: string | string[];\n storage?: boolean;\n cb?: SessionCallback | false;\n collector?: Collector.Instance;\n}\n\nexport type SessionFunction = typeof sessionStorage | typeof sessionWindow;\nexport type SessionCallback = (\n session: Collector.SessionData,\n collector: Collector.Instance | undefined,\n defaultCb: SessionCallback,\n) => void;\n\nexport function sessionStart(\n config: SessionConfig = {},\n): Collector.SessionData | void {\n const { cb, consent, collector, storage } = config;\n const sessionFn: SessionFunction = storage ? sessionStorage : sessionWindow;\n\n // Consent\n if (consent) {\n const consentHandler = onConsentFn(config, cb);\n\n const consentConfig = (\n isArray(consent) ? consent : [consent]\n ).reduce<On.ConsentConfig>(\n (acc, key) => ({ ...acc, [key]: consentHandler }),\n {},\n );\n // Register consent handlers with the collector\n if (collector) {\n collector.command('on', 'consent', consentConfig);\n }\n // No fallback - session source always provides collector\n } else {\n // just do it\n return callFuncAndCb(sessionFn(config), collector, cb);\n }\n}\n\nfunction callFuncAndCb(\n session: Collector.SessionData,\n collector?: Collector.Instance,\n cb?: SessionCallback | false,\n) {\n if (cb === false) return session; // Callback is disabled\n if (!cb) cb = defaultCb; // Default callback if none is provided\n return cb(session, collector, defaultCb);\n}\n\nfunction onConsentFn(config: SessionConfig, cb?: SessionCallback | false) {\n // Track the last processed group to prevent duplicate processing\n let lastProcessedGroup: string | undefined;\n\n const func = (collector: Collector.Instance, consent: WalkerOS.Consent) => {\n // Skip if we've already processed this group\n if (\n isDefined(lastProcessedGroup) &&\n lastProcessedGroup === collector?.group\n )\n return;\n\n // Remember this group has been processed\n lastProcessedGroup = collector?.group;\n\n let sessionFn: SessionFunction = () => sessionWindow(config); // Window by default\n\n if (config.consent) {\n const consentKeys = (\n isArray(config.consent) ? config.consent : [config.consent]\n ).reduce<WalkerOS.Consent>((acc, key) => ({ ...acc, [key]: true }), {});\n\n if (getGrantedConsent(consentKeys, consent))\n // Use storage if consent is granted\n sessionFn = () => sessionStorage(config);\n }\n\n return callFuncAndCb(sessionFn(), collector, cb);\n };\n\n return func;\n}\n\nconst defaultCb: SessionCallback = (\n session,\n collector,\n): Collector.SessionData => {\n const user: WalkerOS.User = {};\n\n // User.session is the session ID\n if (session.id) user.session = session.id;\n\n // Set device ID only in storage mode\n if (session.storage && session.device) user.device = session.device;\n\n // Set user IDs and broadcast session data\n if (collector) {\n collector.command('user', user);\n collector.command('session', session);\n }\n // No fallback - session source always provides collector\n\n if (session.isStart) {\n // Convert session start to an event object\n if (collector) {\n collector.push({\n name: 'session start',\n data: session,\n });\n }\n // No fallback - session source always provides collector\n }\n\n return session;\n};\n","import type { Source, Elb } from '@walkeros/core';\nimport type { SessionConfig, SessionCallback } from '../lib';\n\n// Settings: configuration for session source\nexport interface Settings extends SessionConfig {\n // All settings inherited from SessionConfig:\n // - consent?: string | string[]\n // - storage?: boolean\n // - cb?: SessionCallback | false\n // - pulse?: boolean\n // - sessionStorage?: 'local' | 'session'\n // - deviceStorage?: 'local' | 'session'\n // - sessionKey?: string\n // - deviceKey?: string\n // - length?: number (session timeout in minutes)\n}\n\n// InitSettings: user input (all optional)\nexport type InitSettings = Partial<Settings>;\n\nexport interface Mapping {}\n\nexport type Push = Elb.Fn;\n\nexport interface Env extends Source.BaseEnv {\n window?: Window & typeof globalThis;\n document?: Document;\n}\n\nexport type Types = Source.Types<Settings, Mapping, Push, Env, InitSettings>;\n\nexport type Config = Source.Config<Types>;\n\n// Re-export session types from lib\nexport type {\n SessionConfig,\n SessionCallback,\n SessionFunction,\n SessionStorageConfig,\n SessionWindowConfig,\n} from '../lib';\n","import type { Source, On, Collector } from '@walkeros/core';\nimport type { Types, Settings } from './types';\nimport { sessionStart } from './lib';\n\n// Export types for external usage\nexport * as SourceSession from './types';\n\n// Export lib functions for direct usage\nexport { sessionStart, sessionStorage, sessionWindow } from './lib';\nexport type {\n SessionConfig,\n SessionCallback,\n SessionFunction,\n SessionStorageConfig,\n SessionWindowConfig,\n} from './lib';\n\n/**\n * Session source implementation.\n *\n * This source handles session detection and management.\n */\nexport const sourceSession: Source.Init<Types> = async (context) => {\n const { config, env } = context;\n const { elb, command } = env;\n\n const settings: Settings = {\n ...config?.settings,\n };\n\n const fullConfig: Source.Config<Types> = {\n settings,\n };\n\n // Create minimal collector interface for sessionStart\n const collectorInterface: Partial<Collector.Instance> = {\n push: elb,\n group: undefined,\n command,\n };\n\n // Initialize session using local lib\n sessionStart({\n ...settings,\n window: env.window,\n document: env.document,\n collector: collectorInterface as Collector.Instance,\n });\n\n // Handle events pushed from collector (consent, session, ready, run)\n const handleEvent = async (event: On.Types) => {\n if (event === 'consent') {\n // Re-initialize session on consent changes\n sessionStart({\n ...settings,\n window: env.window,\n document: env.document,\n collector: collectorInterface as Collector.Instance,\n });\n }\n };\n\n return {\n type: 'session',\n config: fullConfig,\n push: elb,\n on: handleEvent,\n };\n};\n\nexport default sourceSession;\n"],"mappings":"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","names":["getId","sessionStorage","getId","session"]}
|
|
1
|
+
{"version":3,"sources":["../src/lib/sessionStorage.ts","../src/lib/sessionWindow.ts","../src/lib/sessionStart.ts","../src/types/index.ts","../src/index.ts"],"sourcesContent":["import type { Collector } from '@walkeros/core';\nimport type { SessionWindowConfig } from './sessionWindow';\nimport type { StorageType } from '@walkeros/core';\nimport type { StorageEnv } from '@walkeros/web-core';\nimport { getId, tryCatch } from '@walkeros/core';\nimport { storageRead, storageWrite } from '@walkeros/web-core';\nimport { sessionWindow } from './sessionWindow';\n\nexport interface SessionStorageConfig extends SessionWindowConfig {\n deviceKey?: string;\n deviceStorage?: StorageType;\n deviceAge?: number;\n sessionKey?: string;\n sessionStorage?: StorageType;\n length?: number; // Minutes after last update to consider session as expired (default: 30)\n pulse?: boolean;\n}\n\nexport function sessionStorage(\n config: SessionStorageConfig = {},\n): Collector.SessionData {\n const now = Date.now();\n const {\n length = 30, // Session length in minutes\n deviceKey = 'elbDeviceId',\n deviceStorage = 'local',\n deviceAge = 30, // Device ID age in days\n sessionKey = 'elbSessionId',\n sessionStorage = 'local',\n pulse = false, // Handle the counting\n } = config;\n const storageEnv: StorageEnv | undefined =\n config.window || config.document\n ? { window: config.window, document: config.document }\n : undefined;\n const windowSession = sessionWindow(config); // Status based on window only\n let isStart = false;\n\n // Retrieve or create device ID\n const device = tryCatch((key: string, age: number, storage: StorageType) => {\n let id = storageRead(key, storage, storageEnv);\n if (!id) {\n id = getId(8); // Create a new device ID\n storageWrite(key, id, age * 1440, storage, undefined, storageEnv); // Write device ID to storage\n }\n return String(id);\n })(deviceKey, deviceAge, deviceStorage);\n\n // Retrieve or initialize session data\n const existingSession: Collector.SessionData =\n tryCatch(\n (key: string, storage?: StorageType) => {\n const session = JSON.parse(\n String(storageRead(key, storage, storageEnv)),\n );\n\n // Only update session if it's not a pulse check\n if (pulse) return session;\n\n // Mark session as not new by default\n session.isNew = false;\n\n // Handle new marketing entry\n if (windowSession.marketing) {\n Object.assign(session, windowSession); // Overwrite existing session with marketing data\n isStart = true; // This is a session start\n }\n\n // Check if session is still active\n if (isStart || session.updated + length * 60000 < now) {\n // Session has expired\n delete session.id; // Unset session ID\n delete session.referrer; // Unset referrer\n session.start = now; // Set new session start\n session.count++; // Increase session count\n session.runs = 1; // Reset runs\n isStart = true; // It's a new session\n } else {\n // Session is still active\n session.runs++; // Increase number of runs\n }\n\n return session;\n },\n () => {\n // No existing session or something went wrong\n isStart = true; // Start a new session\n },\n )(sessionKey, sessionStorage) || {};\n\n // Default session data\n const defaultSession: Partial<Collector.SessionData> = {\n id: getId(12),\n start: now,\n isNew: true,\n count: 1,\n runs: 1,\n };\n\n // Merge session data\n const session = Object.assign(\n defaultSession, // Default session values\n windowSession, // Basic session data based on window\n existingSession, // (Updated) existing session\n { device }, // Device ID\n { isStart, storage: true, updated: now }, // Status of the session\n config.data, // Given data has the highest priority\n );\n\n // Write (updated) session to storage\n storageWrite(\n sessionKey,\n JSON.stringify(session),\n length * 2,\n sessionStorage,\n undefined,\n storageEnv,\n );\n\n return session;\n}\n","import type { Collector, WalkerOS } from '@walkeros/core';\nimport {\n getId,\n getMarketingParameters,\n type ClickIdEntry,\n type MarketingParameters,\n} from '@walkeros/core';\n\nexport interface SessionWindowConfig {\n clickIds?: ClickIdEntry[];\n data?: WalkerOS.Properties;\n domains?: string[];\n isStart?: boolean;\n parameters?: MarketingParameters;\n referrer?: string;\n url?: string;\n window?: Window & typeof globalThis;\n document?: Document;\n}\n\nexport function sessionWindow(\n config: SessionWindowConfig = {},\n): Collector.SessionData {\n let isStart = config.isStart || false;\n const known = { isStart, storage: false };\n\n // If session has explicitly started, return known\n if (config.isStart === false) return known;\n\n const win = config.window ?? window;\n const doc = config.document ?? document;\n\n // Entry type\n if (!isStart) {\n // Only focus on linked or direct navigation types\n // and ignore reloads and all others\n const [perf] = win.performance.getEntriesByType(\n 'navigation',\n ) as PerformanceNavigationTiming[];\n if (perf.type !== 'navigate') return known;\n }\n\n const url = new URL(config.url || win.location.href);\n const ref = config.referrer || doc.referrer;\n const referrer = ref && new URL(ref).hostname;\n\n // Marketing\n const marketing = getMarketingParameters(\n url,\n config.parameters,\n config.clickIds,\n );\n if (Object.keys(marketing).length) {\n // Check for marketing parameters like UTM and add existing\n if (!marketing.marketing)\n // Flag as a marketing session without overwriting\n marketing.marketing = true;\n\n isStart = true;\n }\n\n // Referrer\n if (!isStart) {\n // Small chance of multiple unintended events for same users\n // https://en.wikipedia.org/wiki/HTTP_referer#Referrer_hiding\n // Use domains: [''] to disable direct or hidden referrer\n\n const domains = config.domains || [];\n domains.push(url.hostname);\n isStart = !domains.includes(referrer);\n }\n\n return isStart\n ? // It's a session start, moin\n Object.assign(\n {\n isStart,\n storage: false,\n start: Date.now(),\n id: getId(12),\n referrer,\n },\n marketing,\n config.data,\n )\n : // No session start\n known;\n}\n","import type { Collector, WalkerOS, On, ClickIdEntry } from '@walkeros/core';\nimport type { SessionStorageConfig } from './sessionStorage';\nimport { sessionStorage } from './sessionStorage';\nimport { sessionWindow } from './sessionWindow';\nimport { getGrantedConsent, isArray, isDefined } from '@walkeros/core';\n\nexport interface SessionConfig extends SessionStorageConfig {\n clickIds?: ClickIdEntry[];\n consent?: string | string[];\n storage?: boolean;\n cb?: SessionCallback | false;\n collector?: Collector.Instance;\n}\n\nexport type SessionFunction = typeof sessionStorage | typeof sessionWindow;\nexport type SessionCallback = (\n session: Collector.SessionData,\n collector: Collector.Instance | undefined,\n defaultCb: SessionCallback,\n) => void;\n\nexport function sessionStart(\n config: SessionConfig = {},\n): Collector.SessionData | void {\n const { cb, consent, collector, storage } = config;\n const sessionFn: SessionFunction = storage ? sessionStorage : sessionWindow;\n\n // Consent\n if (consent) {\n const consentHandler = onConsentFn(config, cb);\n\n const consentConfig = (\n isArray(consent) ? consent : [consent]\n ).reduce<On.ConsentConfig>(\n (acc, key) => ({ ...acc, [key]: consentHandler }),\n {},\n );\n // Register consent handlers with the collector\n if (collector) {\n collector.command('on', 'consent', consentConfig);\n }\n // No fallback - session source always provides collector\n } else {\n // just do it\n return callFuncAndCb(sessionFn(config), collector, cb);\n }\n}\n\nfunction callFuncAndCb(\n session: Collector.SessionData,\n collector?: Collector.Instance,\n cb?: SessionCallback | false,\n) {\n if (cb === false) return session; // Callback is disabled\n if (!cb) cb = defaultCb; // Default callback if none is provided\n return cb(session, collector, defaultCb);\n}\n\nfunction onConsentFn(config: SessionConfig, cb?: SessionCallback | false) {\n // Track the last processed group to prevent duplicate processing\n let lastProcessedGroup: string | undefined;\n\n const func = (collector: Collector.Instance, consent: WalkerOS.Consent) => {\n // Skip if we've already processed this group\n if (\n isDefined(lastProcessedGroup) &&\n lastProcessedGroup === collector?.group\n )\n return;\n\n // Remember this group has been processed\n lastProcessedGroup = collector?.group;\n\n let sessionFn: SessionFunction = () => sessionWindow(config); // Window by default\n\n if (config.consent) {\n const consentKeys = (\n isArray(config.consent) ? config.consent : [config.consent]\n ).reduce<WalkerOS.Consent>((acc, key) => ({ ...acc, [key]: true }), {});\n\n if (getGrantedConsent(consentKeys, consent))\n // Use storage if consent is granted\n sessionFn = () => sessionStorage(config);\n }\n\n return callFuncAndCb(sessionFn(), collector, cb);\n };\n\n return func;\n}\n\nconst defaultCb: SessionCallback = (\n session,\n collector,\n): Collector.SessionData => {\n const user: WalkerOS.User = {};\n\n // User.session is the session ID\n if (session.id) user.session = session.id;\n\n // Set device ID only in storage mode\n if (session.storage && session.device) user.device = session.device;\n\n // Set user IDs and broadcast session data\n if (collector) {\n collector.command('user', user);\n collector.command('session', session);\n }\n // No fallback - session source always provides collector\n\n if (session.isStart) {\n // Convert session start to an event object\n if (collector) {\n collector.push({\n name: 'session start',\n data: session,\n });\n }\n // No fallback - session source always provides collector\n }\n\n return session;\n};\n","import type { Source, Elb } from '@walkeros/core';\nimport type { SessionConfig, SessionCallback } from '../lib';\n\n// Settings: configuration for session source\nexport interface Settings extends SessionConfig {\n // All settings inherited from SessionConfig:\n // - consent?: string | string[]\n // - storage?: boolean\n // - cb?: SessionCallback | false\n // - pulse?: boolean\n // - sessionStorage?: 'local' | 'session'\n // - deviceStorage?: 'local' | 'session'\n // - sessionKey?: string\n // - deviceKey?: string\n // - length?: number (session timeout in minutes)\n}\n\n// InitSettings: user input (all optional)\nexport type InitSettings = Partial<Settings>;\n\nexport interface Mapping {}\n\nexport type Push = Elb.Fn;\n\nexport interface Env extends Source.BaseEnv {\n window?: Window & typeof globalThis;\n document?: Document;\n}\n\nexport type Types = Source.Types<Settings, Mapping, Push, Env, InitSettings>;\n\nexport type Config = Source.Config<Types>;\n\n// Re-export session types from lib\nexport type {\n SessionConfig,\n SessionCallback,\n SessionFunction,\n SessionStorageConfig,\n SessionWindowConfig,\n} from '../lib';\n","import type { Source, On, Collector } from '@walkeros/core';\nimport type { Types, Settings } from './types';\nimport { sessionStart } from './lib';\n\n// Export types for external usage\nexport * as SourceSession from './types';\n\n// Export lib functions for direct usage\nexport { sessionStart, sessionStorage, sessionWindow } from './lib';\nexport type {\n SessionConfig,\n SessionCallback,\n SessionFunction,\n SessionStorageConfig,\n SessionWindowConfig,\n} from './lib';\n\n/**\n * Session source implementation.\n *\n * This source handles session detection and management.\n */\nexport const sourceSession: Source.Init<Types> = async (context) => {\n const { config, env } = context;\n const { elb, command } = env;\n\n const settings: Settings = {\n ...config?.settings,\n };\n\n const fullConfig: Source.Config<Types> = {\n settings,\n };\n\n // Create minimal collector interface for sessionStart\n const collectorInterface: Partial<Collector.Instance> = {\n push: elb,\n group: undefined,\n command,\n };\n\n // Initialize session using local lib\n sessionStart({\n ...settings,\n window: env.window,\n document: env.document,\n collector: collectorInterface as Collector.Instance,\n });\n\n // Handle events pushed from collector (consent, session, ready, run)\n const handleEvent = async (event: On.Types) => {\n if (event === 'consent') {\n // Re-initialize session on consent changes\n sessionStart({\n ...settings,\n window: env.window,\n document: env.document,\n collector: collectorInterface as Collector.Instance,\n });\n }\n };\n\n return {\n type: 'session',\n config: fullConfig,\n push: elb,\n on: handleEvent,\n };\n};\n\nexport default sourceSession;\n"],"mappings":"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","names":["getId","sessionStorage","getId","session"]}
|
package/dist/walkerOS.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$meta": {
|
|
3
3
|
"package": "@walkeros/web-source-session",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.2.0",
|
|
5
5
|
"type": "source",
|
|
6
6
|
"platform": [
|
|
7
7
|
"web"
|
|
@@ -79,6 +79,28 @@
|
|
|
79
79
|
},
|
|
80
80
|
"cb": {
|
|
81
81
|
"description": "Custom session callback function or false to disable"
|
|
82
|
+
},
|
|
83
|
+
"clickIds": {
|
|
84
|
+
"type": "array",
|
|
85
|
+
"items": {
|
|
86
|
+
"type": "object",
|
|
87
|
+
"properties": {
|
|
88
|
+
"param": {
|
|
89
|
+
"type": "string",
|
|
90
|
+
"description": "Lowercase URL parameter name. Match is case-insensitive on lookup."
|
|
91
|
+
},
|
|
92
|
+
"platform": {
|
|
93
|
+
"type": "string",
|
|
94
|
+
"description": "Canonical platform identifier (lowercase, kebab-case)."
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
"required": [
|
|
98
|
+
"param",
|
|
99
|
+
"platform"
|
|
100
|
+
],
|
|
101
|
+
"additionalProperties": false
|
|
102
|
+
},
|
|
103
|
+
"description": "Custom click-ID registry. Entries with a `param` matching a default override the platform name in place; new params append to the end of the priority list."
|
|
82
104
|
}
|
|
83
105
|
},
|
|
84
106
|
"additionalProperties": false
|
|
@@ -86,7 +108,7 @@
|
|
|
86
108
|
},
|
|
87
109
|
"examples": {
|
|
88
110
|
"createTrigger": {
|
|
89
|
-
"$code": "async e=>{let n;return{get flow(){return n},trigger:(t,o)=>async t=>{var s,r,i,a,c,u,l,d,f;const g=o||{};if(g.url){const e=new URL(g.url);window.history.replaceState({},\"\",e.pathname+e.search)}if(g.referrer&&Object.defineProperty(document,\"referrer\",{value:g.referrer,configurable:!0}),g.sessionData){const e=g.sessionKey||\"elbSessionId\";localStorage.setItem(e,JSON.stringify(g.sessionData))}if(g.deviceId){const e=g.deviceKey||\"elbDeviceId\";localStorage.setItem(e,g.deviceId)}if(!n){const t=await
|
|
111
|
+
"$code": "async e=>{let n;return{get flow(){return n},trigger:(t,o)=>async t=>{var s,r,i,a,c,u,l,d,f;const g=o||{};if(g.url){const e=new URL(g.url);window.history.replaceState({},\"\",e.pathname+e.search)}if(g.referrer&&Object.defineProperty(document,\"referrer\",{value:g.referrer,configurable:!0}),g.sessionData){const e=g.sessionKey||\"elbSessionId\";localStorage.setItem(e,JSON.stringify(g.sessionData))}if(g.deviceId){const e=g.deviceKey||\"elbDeviceId\";localStorage.setItem(e,g.deviceId)}if(!n){const t=await Ue({...e,run:null==(s=e.run)||s});n={collector:t.collector,elb:t.elb};const o=g.sessionKey||(null==(c=null==(a=null==(i=null==(r=e.sources)?void 0:r.session)?void 0:i.config)?void 0:a.settings)?void 0:c.sessionKey)||\"elbSessionId\",p=g.deviceKey||(null==(f=null==(d=null==(l=null==(u=e.sources)?void 0:u.session)?void 0:l.config)?void 0:d.settings)?void 0:f.deviceKey)||\"elbDeviceId\";localStorage.removeItem(o),localStorage.removeItem(p),g.sessionData&&localStorage.setItem(o,JSON.stringify(g.sessionData)),g.deviceId&&localStorage.setItem(p,g.deviceId),e.consent&&await n.collector.command(\"consent\",e.consent)}}}}"
|
|
90
112
|
},
|
|
91
113
|
"step": {
|
|
92
114
|
"newMarketingSession": {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@walkeros/web-source-session",
|
|
3
3
|
"description": "Session source for walkerOS",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.3.0-next-1776098542393",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"module": "./dist/index.mjs",
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
"types": "./dist/dev.d.ts",
|
|
17
17
|
"import": "./dist/dev.mjs",
|
|
18
18
|
"require": "./dist/dev.js"
|
|
19
|
-
}
|
|
19
|
+
},
|
|
20
|
+
"./walkerOS.json": "./dist/walkerOS.json"
|
|
20
21
|
},
|
|
21
22
|
"files": [
|
|
22
23
|
"dist/**"
|
|
@@ -31,11 +32,11 @@
|
|
|
31
32
|
"update": "npx npm-check-updates -u && npm update"
|
|
32
33
|
},
|
|
33
34
|
"dependencies": {
|
|
34
|
-
"@walkeros/core": "
|
|
35
|
-
"@walkeros/web-core": "
|
|
35
|
+
"@walkeros/core": "3.3.0-next-1776098542393",
|
|
36
|
+
"@walkeros/web-core": "3.3.0-next-1776098542393"
|
|
36
37
|
},
|
|
37
38
|
"devDependencies": {
|
|
38
|
-
"@walkeros/collector": "
|
|
39
|
+
"@walkeros/collector": "3.3.0-next-1776098542393"
|
|
39
40
|
},
|
|
40
41
|
"repository": {
|
|
41
42
|
"url": "git+https://github.com/elbwalker/walkerOS.git",
|