@walkeros/web-source-session 3.0.2 → 4.0.0-next-1773967844643
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/dist/dev.d.mts +7 -5
- package/dist/dev.d.ts +7 -5
- 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 +4 -0
- package/dist/index.d.ts +4 -0
- 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 +21 -4
- package/package.json +7 -5
package/dist/dev.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as _walkeros_core_dev from '@walkeros/core/dev';
|
|
2
2
|
import { z } from '@walkeros/core/dev';
|
|
3
|
-
import { Flow,
|
|
3
|
+
import { Flow, Trigger } from '@walkeros/core';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Session source settings schema
|
|
@@ -43,13 +43,15 @@ declare namespace step {
|
|
|
43
43
|
export { step_newMarketingSession as newMarketingSession, step_returningVisitor as returningVisitor };
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
declare const createTrigger: Trigger.CreateFn<Record<string, unknown>, void>;
|
|
47
|
+
/** Prepares localStorage with session/device data before source init. */
|
|
48
|
+
declare const trigger: (input: unknown, env: Record<string, unknown>) => void;
|
|
48
49
|
|
|
49
|
-
declare const
|
|
50
|
+
declare const index_createTrigger: typeof createTrigger;
|
|
50
51
|
declare const index_step: typeof step;
|
|
52
|
+
declare const index_trigger: typeof trigger;
|
|
51
53
|
declare namespace index {
|
|
52
|
-
export {
|
|
54
|
+
export { index_createTrigger as createTrigger, index_step as step, index_trigger as trigger };
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
export { index as examples, index$1 as schemas };
|
package/dist/dev.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as _walkeros_core_dev from '@walkeros/core/dev';
|
|
2
2
|
import { z } from '@walkeros/core/dev';
|
|
3
|
-
import { Flow,
|
|
3
|
+
import { Flow, Trigger } from '@walkeros/core';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Session source settings schema
|
|
@@ -43,13 +43,15 @@ declare namespace step {
|
|
|
43
43
|
export { step_newMarketingSession as newMarketingSession, step_returningVisitor as returningVisitor };
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
declare const createTrigger: Trigger.CreateFn<Record<string, unknown>, void>;
|
|
47
|
+
/** Prepares localStorage with session/device data before source init. */
|
|
48
|
+
declare const trigger: (input: unknown, env: Record<string, unknown>) => void;
|
|
48
49
|
|
|
49
|
-
declare const
|
|
50
|
+
declare const index_createTrigger: typeof createTrigger;
|
|
50
51
|
declare const index_step: typeof step;
|
|
52
|
+
declare const index_trigger: typeof trigger;
|
|
51
53
|
declare namespace index {
|
|
52
|
-
export {
|
|
54
|
+
export { index_createTrigger as createTrigger, index_step as step, index_trigger as trigger };
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
export { index as examples, index$1 as schemas };
|
package/dist/dev.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e,s=Object.defineProperty,t=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,i=Object.prototype.hasOwnProperty,n=(e,t)=>{for(var o in t)s(e,o,{get:t[o],enumerable:!0})},r={};n(r,{examples:()=>g,schemas:()=>a}),module.exports=(e=r,((e,n,r,a)=>{if(n&&"object"==typeof n||"function"==typeof n)for(let c of o(n))i.call(e,c)||c===r||s(e,c,{get:()=>n[c],enumerable:!(a=t(n,c))||a.enumerable});return e})(s({},"__esModule",{value:!0}),e));var a={};n(a,{SettingsSchema:()=>d,settings:()=>u});var c=require("@walkeros/core/dev"),l=require("@walkeros/core/dev"),d=l.z.object({storage:l.z.boolean().default(!1).describe("Enable persistent storage for session/device IDs").optional(),consent:l.z.union([l.z.string(),l.z.array(l.z.string())]).describe("Consent key(s) required to enable storage mode").optional(),length:l.z.number().default(30).describe("Session timeout in minutes").optional(),pulse:l.z.boolean().default(!1).describe("Keep session alive on each event").optional(),sessionKey:l.z.string().default("elbSessionId").describe("Storage key for session ID").optional(),sessionStorage:l.z.enum(["local","session"]).default("local").describe("Storage type for session").optional(),deviceKey:l.z.string().default("elbDeviceId").describe("Storage key for device ID").optional(),deviceStorage:l.z.enum(["local","session"]).default("local").describe("Storage type for device").optional(),deviceAge:l.z.number().default(30).describe("Device ID age in days").optional(),cb:l.z.any().describe("Custom session callback function or false to disable").optional()}),u=(0,c.zodToSchema)(d),g={};n(g,{setup:()=>y,step:()=>p});var p={};n(p,{newMarketingSession:()=>b,returningVisitor:()=>f});var b={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"}},f={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=(e,s)=>{if(!e||"object"!=typeof e)return;const t=e;if(t.sessionData&&"object"==typeof t.sessionData){const e="string"==typeof t.sessionKey?t.sessionKey:"elbSessionId";s.localStorage.setItem(e,JSON.stringify(t.sessionData))}if("string"==typeof t.deviceId){const e="string"==typeof t.deviceKey?t.deviceKey:"elbDeviceId";s.localStorage.setItem(e,t.deviceId)}};//# sourceMappingURL=dev.js.map
|
|
1
|
+
"use strict";var e,n=Object.defineProperty,t=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.prototype.hasOwnProperty,i=(e,t)=>{for(var o in t)n(e,o,{get:t[o],enumerable:!0})},r={};i(r,{examples:()=>d,schemas:()=>a}),module.exports=(e=r,((e,i,r,a)=>{if(i&&"object"==typeof i||"function"==typeof i)for(let c of o(i))s.call(e,c)||c===r||n(e,c,{get:()=>i[c],enumerable:!(a=t(i,c))||a.enumerable});return e})(n({},"__esModule",{value:!0}),e));var a={};i(a,{SettingsSchema:()=>l,settings:()=>g});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()}),g=(0,c.zodToSchema)(l),d={};i(d,{createTrigger:()=>W,step:()=>f,trigger:()=>X});var f={};i(f,{newMarketingSession:()=>p,returningVisitor:()=>b});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"}},b={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"),h=require("@walkeros/core"),v=require("@walkeros/core"),m=require("@walkeros/core"),w=require("@walkeros/core"),k=require("@walkeros/core"),O=require("@walkeros/core"),j=require("@walkeros/core"),q=require("@walkeros/core"),S=require("@walkeros/core"),D=require("@walkeros/core"),C={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 I(e){var n;const t={};for(const[o,s]of Object.entries(e))(null==(n=s.config)?void 0:n.next)?t[o]={next:s.config.next}:t[o]={};return t}function A(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 P(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 x(e,n,t){if(n.init&&!n.config.init){const o=n.type||"unknown",s=e.logger.scope(`transformer:${o}`),i={collector:e,logger:s,id:t,config:n.config,env:$(n.config.env)};s.debug("init");const r=await(0,O.useHooks)(n.init,"TransformerInit",e.hooks)(i);if(!1===r)return!1;n.config={...r||n.config,env:(null==r?void 0:r.env)||n.config.env,init:!0},s.debug("init done")}return!0}async function E(e,n,t,o,s,i){const r=n.type||"unknown",a=e.logger.scope(`transformer:${r}`),c={collector:e,logger:a,id:t,ingest:s,config:n.config,env:{...$(n.config.env),...i?{respond:i}:{}}};a.debug("push",{event:o.name});const u=await(0,O.useHooks)(n.push,"TransformerPush",e.hooks)(o,c);return a.debug("push done"),u}async function z(e,n,t,o,s,i){let r=o,a=i;for(const o of t){const t=n[o];if(!t){e.logger.warn(`Transformer not found: ${o}`);continue}if(!await(0,O.tryCatchAsync)(x)(e,t,o))return e.logger.error(`Transformer init failed: ${o}`),null;const i=await(0,O.tryCatchAsync)(E,n=>(e.logger.scope(`transformer:${t.type||"unknown"}`).error("Push failed",{error:n}),!1))(e,t,o,r,s,a);if(!1===i)return null;if(i&&"object"==typeof i){const{event:t,respond:o,next:c}=i;if(o&&(a=o),c){const o=P(c,I(n));return o.length>0?z(e,n,o,t||r,s,a):(e.logger.warn(`Branch target not found: ${JSON.stringify(c)}`),null)}t&&(r=t)}}return r}function $(e){return e&&(0,O.isObject)(e)?e:{}}async function K(e,n,t){const{code:o,config:s={},env:i={},primary:r,next:a}=t;let c,u;const l=P(a,I(e.transformers)),g=e.logger.scope("source").scope(n),d={push:(t,o={})=>e.push(t,{...o,id:n,ingest:c,respond:u,mapping:s,preChain:l}),command:e.command,sources:e.sources,elb:e.sources.elb.push,logger:g,...i},f={collector:e,logger:g,id:n,config:s,env:d,setIngest:async n=>{c=s.ingest?await(0,k.getMappingValue)(n,s.ingest,{collector:e}):void 0},setRespond:e=>{u=e}},p=await(0,k.tryCatchAsync)(o)(f);if(!p)return;const b=p.type||"unknown",y=e.logger.scope(b).scope(n);return d.logger=y,r&&(p.config={...p.config,primary:r}),p}function R(e,n,t,o,s){if(!n.on)return;const i=n.type||"unknown",r=e.logger.scope(i).scope("on").scope(o),a={collector:e,logger:r,id:t,config:n.config,data:s,env:F(n.env,n.config.env)};(0,w.tryCatch)(n.on)(o,a)}async function H(e,n,t,o){let s,i=t||[];switch(t||(i=e.on[n]||[]),n){case C.Consent:s=o||e.consent;break;case C.Session:s=e.session;break;case C.User:s=o||e.user;break;case C.Custom:s=o||e.custom;break;case C.Globals:s=o||e.globals;break;case C.Config:s=o||e.config;break;case C.Ready:case C.Run:default:s=void 0}let r=!1;for(const t of Object.values(e.sources))t.on&&!1===await(0,w.tryCatchAsync)(t.on)(n,s)&&(r=!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});R(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 i=null==(t=s.config)?void 0:t.require;if(!i)continue;const r=i.indexOf(n);if(-1===r)continue;if(i.splice(r,1),i.length>0)continue;delete e.pending.sources[o];const a=await K(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 i=null==(o=s.config)?void 0:o.require;if(!i)continue;const r=i.indexOf(n);if(-1===r)continue;if(i.splice(r,1),i.length>0)continue;delete e.pending.destinations[t];const a=B(s);!1!==a.config.queue&&(a.queuePush=[...e.queue]),e.destinations[t]=a}}(e,n),!i.length)return!r;switch(n){case C.Consent:!function(e,n,t){const o=t||e.consent;n.forEach(n=>{Object.keys(o).filter(e=>e in n).forEach(t=>{(0,w.tryCatch)(n[t])(e,o)})})}(e,i,o);break;case C.Ready:case C.Run:c=i,(a=e).allowed&&c.forEach(e=>{(0,w.tryCatch)(e)(a)});break;case C.Session:!function(e,n){e.session&&n.forEach(n=>{(0,w.tryCatch)(n)(e,e.session)})}(e,i);break;default:i.forEach(n=>{"function"==typeof n&&(0,w.tryCatch)(n)(e,s)})}var a,c;return!r}async function M(e,n,t){const{code:o,config:s={},env:i={},before:r}=n;if(!(0,v.isFunction)(o.push))return G({ok:!1,failed:{invalid:{type:"invalid",error:"Destination code must have a push method"}}});const a=t||s||{init:!1},c=r?{...a,before:r}:a,u={...o,config:c,env:F(o.env,i)};let l=u.config.id;if(!l)do{l=(0,v.getId)(4)}while(e.destinations[l]);return e.destinations[l]=u,!1!==u.config.queue&&(u.queuePush=[...e.queue]),N(e,void 0,{},{[l]:u})}async function N(e,n,t={},o){const{allowed:s,consent:i,globals:r,user:a}=e;if(!s)return G({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;let l=(s.queuePush||[]).map(e=>({...e,consent:i}));if(s.queuePush=[],n){const e=(0,v.clone)(n);l.push(e)}if(!l.length&&!(null==(c=s.queueOn)?void 0:c.length))return{id:o,destination:s,skipped:!0};if(!l.length&&(null==(u=s.queueOn)?void 0:u.length)){const n=await(0,v.tryCatchAsync)(T)(e,s,o);return{id:o,destination:s,skipped:!n}}const g=[],d=l.filter(e=>{const n=(0,v.getGrantedConsent)(s.config.consent,i,e.consent);return!n||(e.consent=n,g.push(e),!1)});if(s.queuePush.push(...d),!g.length)return{id:o,destination:s,queue:l};if(!await(0,v.tryCatchAsync)(T)(e,s,o))return{id:o,destination:s,queue:l};let f,p;s.dlq||(s.dlq=[]);const b=function(e,n){const t=e.config.before;return t?P(t,I(n)):[]}(s,e.transformers);let y=0;return await Promise.all(g.map(async n=>{n.globals=(0,v.assign)(r,n.globals),n.user=(0,v.assign)(a,n.user);let i=n;if(b.length>0&&e.transformers&&Object.keys(e.transformers).length>0){const o=await z(e,e.transformers,b,n,t.ingest,t.respond);if(null===o)return n;i=o}const c=Date.now(),u=await(0,v.tryCatchAsync)(_,n=>{const t=s.type||"unknown";e.logger.scope(t).error("Push failed",{error:n,event:i.name}),f=n,s.dlq.push([i,n])})(e,s,o,i,t.ingest,t.respond);return y+=Date.now()-c,void 0!==u&&(p=u),n})),{id:o,destination:s,error:f,response:p,totalDuration:y}})),u={},l={},g={};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,g[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 G({event:n,...Object.keys(u).length&&{done:u},...Object.keys(l).length&&{queued:l},...Object.keys(g).length&&{failed:g}})}async function T(e,n,t){var o;if(n.init&&!n.config.init){const s=n.type||"unknown",i=e.logger.scope(s),r={collector:e,logger:i,id:t,config:n.config,env:F(n.env,n.config.env)};i.debug("init");const a=await(0,v.useHooks)(n.init,"DestinationInit",e.hooks)(r);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:i}of o)R(e,n,t,s,i)}i.debug("init done")}return!0}async function _(e,n,t,o,s,i){const{config:r}=n,a=await(0,v.processEventMapping)(o,r,e);if(a.ignore)return!1;const c=n.type||"unknown",u=e.logger.scope(c),l={collector:e,logger:u,id:t,config:r,data:a.data,rule:a.mapping,ingest:s,env:{...F(n.env,r.env),...i?{respond:i}:{}}},g=a.mapping,d=a.mappingKey||"* *";if(!(null==g?void 0:g.batch)||!n.pushBatch){u.debug("push",{event:a.event.name});const t=await(0,v.useHooks)(n.push,"DestinationPush",e.hooks)(a.event,l);return u.debug("push done"),t}{if(n.batches=n.batches||{},!n.batches[d]){const o={key:d,events:[],data:[]};n.batches[d]={batched:o,batchFn:(0,v.debounce)(()=>{const o=n.batches[d].batched,a={collector:e,logger:u,id:t,config:r,data:void 0,rule:g,ingest:s,env:{...F(n.env,r.env),...i?{respond:i}:{}}};u.debug("push batch",{events:o.events.length}),(0,v.useHooks)(n.pushBatch,"DestinationPushBatch",e.hooks)(o,a),u.debug("push batch done"),o.events=[],o.data=[]},g.batch)}}const o=n.batches[d];o.batched.events.push(a.event),(0,v.isDefined)(a.data)&&o.batched.data.push(a.data),o.batchFn()}return!0}function G(e){return{ok:!(null==e?void 0:e.failed),...e}}function B(e){const{code:n,config:t={},env:o={}}=e,{config:s}=A(e,"before"),i={...n.config,...t,...s},r=F(n.env,o);return{...n,config:i,env:r}}function F(e,n){return e||n?n?e&&(0,v.isObject)(e)&&(0,v.isObject)(n)?{...e,...n}:n:e:{}}async function J(e,n,t){const o=Object.entries(e).map(async([e,o])=>{var s;const i=o.destroy;if(!i)return;const r=o.type||"unknown",a=t.scope(r),c={id:e,config:o.config,env:null!=(s=o.env)?s:{},logger:a};try{await Promise.race([i(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 U(e,n,t,o){let s,i,r=!1,a=!1;switch(n){case C.Config:(0,q.isObject)(t)&&((0,j.assign)(e.config,t,{shallow:!1}),i=t,r=!0);break;case C.Consent:if((0,q.isObject)(t)){const{update:n,runQueue:o}=function(e,n){let t=!1;const o={};return Object.entries(n).forEach(([e,n])=>{const s=!!n;o[e]=s,t=t||s}),e.consent=(0,y.assign)(e.consent,o),{update:o,runQueue:t}}(e,t);i=n,r=!0,a=o}break;case C.Custom:(0,q.isObject)(t)&&(e.custom=(0,j.assign)(e.custom,t),i=t,r=!0);break;case C.Destination:(0,q.isObject)(t)&&("code"in t&&(0,q.isObject)(t.code)?s=await M(e,t,o):(0,j.isFunction)(t.push)&&(s=await M(e,{code:t},o)));break;case C.Globals:(0,q.isObject)(t)&&(e.globals=(0,j.assign)(e.globals,t),i=t,r=!0);break;case C.On:(0,j.isString)(t)&&await async function(e,n,t){const o=e.on,s=o[n]||[],i=(0,m.isArray)(t)?t:[t];i.forEach(e=>{s.push(e)}),o[n]=s,await H(e,n,i)}(e,t,o);break;case C.Ready:r=!0;break;case C.Run:s=await async function(e,n){return e.allowed=!0,e.count=0,e.group=(0,j.getId)(),e.timing=Date.now(),n&&(n.consent&&(e.consent=(0,j.assign)(e.consent,n.consent)),n.user&&(e.user=(0,j.assign)(e.user,n.user)),n.globals&&(e.globals=(0,j.assign)(e.config.globalsStatic||{},n.globals)),n.custom&&(e.custom=(0,j.assign)(e.custom,n.custom))),Object.values(e.destinations).forEach(e=>{e.queuePush=[]}),e.queue=[],e.round++,await N(e)}(e,t),r=!0;break;case C.Session:r=!0;break;case C.Shutdown:await async function(e){const n=e.logger;await J(e.sources,"source",n),await J(e.destinations,"destination",n),await J(e.transformers,"transformer",n),await J(e.stores,"store",n)}(e);break;case C.User:(0,q.isObject)(t)&&((0,j.assign)(e.user,t,{shallow:!1}),i=t,r=!0)}return r&&await H(e,n,void 0,i),a&&(s=await N(e)),s||G({ok:!0})}function V(e,n){return(0,S.useHooks)(async(t,o={})=>await(0,S.tryCatchAsync)(async()=>{const s=Date.now(),{id:i,ingest:r,respond:a,mapping:c,preChain:u}=o;let l=t;const g=r?Object.freeze(r):void 0;if(c){const n=await(0,S.processEventMapping)(l,c,e);if(n.ignore)return G({ok:!0});if(c.consent&&!(0,S.getGrantedConsent)(c.consent,e.consent,n.event.consent))return G({ok:!0});l=n.event}if((null==u?void 0:u.length)&&e.transformers&&Object.keys(e.transformers).length>0){const n=await z(e,e.transformers,u,l,g,a);if(null===n)return G({ok:!0});l=n}const d=n(l),f=function(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:i=e.group,count:r=e.count}=n,{name:a=`${t} ${o}`,data:c={},context:u={},globals:l=e.globals,custom:g={},user:d=e.user,nested:f=[],consent:p=e.consent,id:b=`${s}-${i}-${r}`,trigger:y="",entity:h=t,action:v=o,timing:m=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:g,user:d,nested:f,consent:p,id:b,trigger:y,entity:h,action:v,timestamp:s,timing:m,group:i,count:r,version:w,source:k}}(e,d),p=await N(e,f,{id:i,ingest:g,respond:a});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()-s}return p},()=>G({ok:!1}))(),"Push",e.hooks)}async function L(e){var n,t;const o=(0,h.assign)({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},i=(0,h.createLogger)(s),r={...o.globalsStatic,...e.globals},a={allowed:!1,config:o,consent:e.consent||{},count:0,custom:e.custom||{},destinations:{},transformers:{},stores:{},globals:r,group:"",hooks:{},logger:i,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.0.2",sources:{},pending:{sources:{},destinations:{}},push:void 0,command:void 0};var c,u;a.push=V(a,e=>({timing:Math.round((Date.now()-a.timing)/10)/100,source:{type:"collector",id:"",previous_id:""},...e})),a.command=(c=a,u=U,(0,D.useHooks)(async(e,n,t)=>await(0,D.tryCatchAsync)(async()=>await u(c,e,n,t),()=>G({ok:!1}))(),"Command",c.hooks));const l=e.stores||{};return a.stores=await async function(e,n={}){const t={};for(const[o,s]of Object.entries(n)){const{code:n,config:i={},env:r={}}=s,a=e.logger.scope("store").scope(o),c={collector:e,logger:a,id:o,config:i,env:r},u=await n(c);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.destinations=await async function(e,n={}){var t,o;const s={};for(const[i,r]of Object.entries(n))(null==(o=null==(t=r.config)?void 0:t.require)?void 0:o.length)?e.pending.destinations[i]=r:s[i]=B(r);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:i={}}=s,{config:r}=A(s,"next"),a=Object.keys(i).length>0?{...r,env:i}:r,c=e.logger.scope("transformer").scope(o),u={collector:e,logger:c,id:o,config:a,env:i},l=await n(u);t[o]=l}return t}(a,e.transformers||{}),a}async function Q(e){e=e||{};const n=await L(e),t=(o=n,{type:"elb",config:{},push:async(e,n,t,s,i,r)=>{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 G({ok:!1});a=e,n&&"object"==typeof n&&!Array.isArray(n)&&(a.data={...a.data||{},...n})}return s&&"object"==typeof s&&(a.context=s),i&&Array.isArray(i)&&(a.nested=i),r&&"object"==typeof r&&(a.custom=r),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 i=await K(e,o,s);i&&(t[o]=i)}return t}(n,e.sources||{});Object.assign(n.sources,s);const{consent:i,user:r,globals:a,custom:c}=e;i&&await n.command("consent",i),r&&await n.command("user",r),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),g=l.find(e=>e.config.primary);return g?u=g.push:l.length>0&&(u=l[0].push),{collector:n,elb:u}}var W=async e=>{let n;return{get flow(){return n},trigger:(t,o)=>async t=>{var s,i,r,a,c,u,l,g,d;const f=o||{};if(f.url){const e=new URL(f.url);window.history.replaceState({},"",e.pathname+e.search)}if(f.referrer&&Object.defineProperty(document,"referrer",{value:f.referrer,configurable:!0}),f.sessionData){const e=f.sessionKey||"elbSessionId";localStorage.setItem(e,JSON.stringify(f.sessionData))}if(f.deviceId){const e=f.deviceKey||"elbDeviceId";localStorage.setItem(e,f.deviceId)}if(!n){const t=await Q({...e,run:null==(s=e.run)||s});n={collector:t.collector,elb:t.elb};const o=f.sessionKey||(null==(c=null==(a=null==(r=null==(i=e.sources)?void 0:i.session)?void 0:r.config)?void 0:a.settings)?void 0:c.sessionKey)||"elbSessionId",p=f.deviceKey||(null==(d=null==(g=null==(l=null==(u=e.sources)?void 0:u.session)?void 0:l.config)?void 0:g.settings)?void 0:d.deviceKey)||"elbDeviceId";localStorage.removeItem(o),localStorage.removeItem(p),f.sessionData&&localStorage.setItem(o,JSON.stringify(f.sessionData)),f.deviceId&&localStorage.setItem(p,f.deviceId),e.consent&&await n.collector.command("consent",e.consent)}}}},X=(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)}};//# 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/setup.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 { setup } from './setup';\n","import type { Flow } from '@walkeros/core';\n\nexport const newMarketingSession: Flow.StepExample = {\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 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 { Source } from '@walkeros/core';\n\n/** Prepares localStorage with session/device data. */\nexport const setup: Source.SetupFn = (input, env) => {\n if (!input || typeof input !== 'object') return;\n const data = input as Record<string, unknown>;\n\n if (data.sessionData && typeof data.sessionData === 'object') {\n const key =\n typeof data.sessionKey === 'string' ? data.sessionKey : 'elbSessionId';\n env.localStorage.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 env.localStorage.setItem(key, data.deviceId);\n }\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,cAA4B;;;ACA5B,iBAAkB;AAKX,IAAM,iBAAiB,aAAE,OAAO;AAAA,EACrC,SAAS,aACN,QAAQ,EACR,QAAQ,KAAK,EACb,SAAS,kDAAkD,EAC3D,SAAS;AAAA,EAEZ,SAAS,aACN,MAAM,CAAC,aAAE,OAAO,GAAG,aAAE,MAAM,aAAE,OAAO,CAAC,CAAC,CAAC,EACvC,SAAS,gDAAgD,EACzD,SAAS;AAAA,EAEZ,QAAQ,aACL,OAAO,EACP,QAAQ,EAAE,EACV,SAAS,4BAA4B,EACrC,SAAS;AAAA,EAEZ,OAAO,aACJ,QAAQ,EACR,QAAQ,KAAK,EACb,SAAS,kCAAkC,EAC3C,SAAS;AAAA,EAEZ,YAAY,aACT,OAAO,EACP,QAAQ,cAAc,EACtB,SAAS,4BAA4B,EACrC,SAAS;AAAA,EAEZ,gBAAgB,aACb,KAAK,CAAC,SAAS,SAAS,CAAC,EACzB,QAAQ,OAAO,EACf,SAAS,0BAA0B,EACnC,SAAS;AAAA,EAEZ,WAAW,aACR,OAAO,EACP,QAAQ,aAAa,EACrB,SAAS,2BAA2B,EACpC,SAAS;AAAA,EAEZ,eAAe,aACZ,KAAK,CAAC,SAAS,SAAS,CAAC,EACzB,QAAQ,OAAO,EACf,SAAS,yBAAyB,EAClC,SAAS;AAAA,EAEZ,WAAW,aACR,OAAO,EACP,QAAQ,EAAE,EACV,SAAS,uBAAuB,EAChC,SAAS;AAAA;AAAA;AAAA,EAIZ,IAAI,aACD,IAAI,EACJ,SAAS,sDAAsD,EAC/D,SAAS;AACd,CAAC;;;AD1DM,IAAM,eAAW,yBAAY,cAAc;;;AEPlD;AAAA;AAAA;AAAA;AAAA;;;ACAA;AAAA;AAAA;AAAA;AAAA;AAEO,IAAM,sBAAwC;AAAA,EACnD,IAAI,EAAE,SAAS,KAAK;AAAA,EACpB,KAAK;AAAA,IACH,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,SAAS;AAAA,MACT,OAAO;AAAA,MACP,OAAO;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,IAAI;AAAA,MACJ,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,UAAU;AAAA,IACZ;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AACF;AAEO,IAAM,mBAAqC;AAAA,EAChD,IAAI,EAAE,SAAS,KAAK;AAAA,EACpB,KAAK;AAAA,IACH,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,SAAS;AAAA,MACT,OAAO;AAAA,MACP,OAAO;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,IAAI;AAAA,MACJ,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,UAAU;AAAA,IACZ;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AACF;;;ACxCO,IAAM,QAAwB,CAAC,OAAO,QAAQ;AACnD,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU;AACzC,QAAM,OAAO;AAEb,MAAI,KAAK,eAAe,OAAO,KAAK,gBAAgB,UAAU;AAC5D,UAAM,MACJ,OAAO,KAAK,eAAe,WAAW,KAAK,aAAa;AAC1D,QAAI,aAAa,QAAQ,KAAK,KAAK,UAAU,KAAK,WAAW,CAAC;AAAA,EAChE;AAEA,MAAI,OAAO,KAAK,aAAa,UAAU;AACrC,UAAM,MACJ,OAAO,KAAK,cAAc,WAAW,KAAK,YAAY;AACxD,QAAI,aAAa,QAAQ,KAAK,KAAK,QAAQ;AAAA,EAC7C;AACF;","names":["import_dev"]}
|
|
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"]}
|
package/dist/dev.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var e=Object.defineProperty,s=(s,t)=>{for(var o in t)e(s,o,{get:t[o],enumerable:!0})},t={};s(t,{SettingsSchema:()=>n,settings:()=>a});import{zodToSchema as o}from"@walkeros/core/dev";import{z as i}from"@walkeros/core/dev";var n=i.object({storage:i.boolean().default(!1).describe("Enable persistent storage for session/device IDs").optional(),consent:i.union([i.string(),i.array(i.string())]).describe("Consent key(s) required to enable storage mode").optional(),length:i.number().default(30).describe("Session timeout in minutes").optional(),pulse:i.boolean().default(!1).describe("Keep session alive on each event").optional(),sessionKey:i.string().default("elbSessionId").describe("Storage key for session ID").optional(),sessionStorage:i.enum(["local","session"]).default("local").describe("Storage type for session").optional(),deviceKey:i.string().default("elbDeviceId").describe("Storage key for device ID").optional(),deviceStorage:i.enum(["local","session"]).default("local").describe("Storage type for device").optional(),deviceAge:i.number().default(30).describe("Device ID age in days").optional(),cb:i.any().describe("Custom session callback function or false to disable").optional()}),a=o(n),r={};s(r,{setup:()=>g,step:()=>c});var c={};s(c,{newMarketingSession:()=>d,returningVisitor:()=>l});var d={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={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"}},g=(e,s)=>{if(!e||"object"!=typeof e)return;const t=e;if(t.sessionData&&"object"==typeof t.sessionData){const e="string"==typeof t.sessionKey?t.sessionKey:"elbSessionId";s.localStorage.setItem(e,JSON.stringify(t.sessionData))}if("string"==typeof t.deviceId){const e="string"==typeof t.deviceKey?t.deviceKey:"elbDeviceId";s.localStorage.setItem(e,t.deviceId)}};export{r 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:()=>r});import{zodToSchema as o}from"@walkeros/core/dev";import{z as s}from"@walkeros/core/dev";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()}),r=o(i),a={};n(a,{createTrigger:()=>fe,step:()=>c,trigger:()=>pe});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 g,createLogger as f}from"@walkeros/core";import{assign as p,clone as m,debounce as b,getId as v,getGrantedConsent as h,isDefined as y,isFunction as w,isObject as k,processEventMapping as O,tryCatchAsync as j,useHooks as S}from"@walkeros/core";import{isArray as D}from"@walkeros/core";import{tryCatch as q,tryCatchAsync as I}from"@walkeros/core";import{getMappingValue as C,tryCatchAsync as A}from"@walkeros/core";import{isObject as P,tryCatchAsync as x,useHooks as E}from"@walkeros/core";import{assign as $,getId as K,isFunction as R,isString as M}from"@walkeros/core";import{isObject as N}from"@walkeros/core";import{getGrantedConsent as T,processEventMapping as G,tryCatchAsync as H,useHooks as _}from"@walkeros/core";import{useHooks as B,tryCatchAsync as F}from"@walkeros/core";var J={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 U(e){var n;const t={};for(const[o,s]of Object.entries(e))(null==(n=s.config)?void 0:n.next)?t[o]={next:s.config.next}:t[o]={};return t}function V(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 L(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 z(e,n,t){if(n.init&&!n.config.init){const o=n.type||"unknown",s=e.logger.scope(`transformer:${o}`),i={collector:e,logger:s,id:t,config:n.config,env:X(n.config.env)};s.debug("init");const r=await E(n.init,"TransformerInit",e.hooks)(i);if(!1===r)return!1;n.config={...r||n.config,env:(null==r?void 0:r.env)||n.config.env,init:!0},s.debug("init done")}return!0}async function Q(e,n,t,o,s,i){const r=n.type||"unknown",a=e.logger.scope(`transformer:${r}`),c={collector:e,logger:a,id:t,ingest:s,config:n.config,env:{...X(n.config.env),...i?{respond:i}:{}}};a.debug("push",{event:o.name});const u=await E(n.push,"TransformerPush",e.hooks)(o,c);return a.debug("push done"),u}async function W(e,n,t,o,s,i){let r=o,a=i;for(const o of t){const t=n[o];if(!t){e.logger.warn(`Transformer not found: ${o}`);continue}if(!await x(z)(e,t,o))return e.logger.error(`Transformer init failed: ${o}`),null;const i=await x(Q,n=>(e.logger.scope(`transformer:${t.type||"unknown"}`).error("Push failed",{error:n}),!1))(e,t,o,r,s,a);if(!1===i)return null;if(i&&"object"==typeof i){const{event:t,respond:o,next:c}=i;if(o&&(a=o),c){const o=L(c,U(n));return o.length>0?W(e,n,o,t||r,s,a):(e.logger.warn(`Branch target not found: ${JSON.stringify(c)}`),null)}t&&(r=t)}}return r}function X(e){return e&&P(e)?e:{}}async function Y(e,n,t){const{code:o,config:s={},env:i={},primary:r,next:a}=t;let c,u;const l=L(a,U(e.transformers)),d=e.logger.scope("source").scope(n),g={push:(t,o={})=>e.push(t,{...o,id:n,ingest:c,respond:u,mapping:s,preChain:l}),command:e.command,sources:e.sources,elb:e.sources.elb.push,logger:d,...i},f={collector:e,logger:d,id:n,config:s,env:g,setIngest:async n=>{c=s.ingest?await C(n,s.ingest,{collector:e}):void 0},setRespond:e=>{u=e}},p=await A(o)(f);if(!p)return;const m=p.type||"unknown",b=e.logger.scope(m).scope(n);return g.logger=b,r&&(p.config={...p.config,primary:r}),p}function Z(e,n,t,o,s){if(!n.on)return;const i=n.type||"unknown",r=e.logger.scope(i).scope("on").scope(o),a={collector:e,logger:r,id:t,config:n.config,data:s,env:ae(n.env,n.config.env)};q(n.on)(o,a)}async function ee(e,n,t,o){let s,i=t||[];switch(t||(i=e.on[n]||[]),n){case J.Consent:s=o||e.consent;break;case J.Session:s=e.session;break;case J.User:s=o||e.user;break;case J.Custom:s=o||e.custom;break;case J.Globals:s=o||e.globals;break;case J.Config:s=o||e.config;break;case J.Ready:case J.Run:default:s=void 0}let r=!1;for(const t of Object.values(e.sources))t.on&&!1===await I(t.on)(n,s)&&(r=!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});Z(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 i=null==(t=s.config)?void 0:t.require;if(!i)continue;const r=i.indexOf(n);if(-1===r)continue;if(i.splice(r,1),i.length>0)continue;delete e.pending.sources[o];const a=await Y(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 i=null==(o=s.config)?void 0:o.require;if(!i)continue;const r=i.indexOf(n);if(-1===r)continue;if(i.splice(r,1),i.length>0)continue;delete e.pending.destinations[t];const a=re(s);!1!==a.config.queue&&(a.queuePush=[...e.queue]),e.destinations[t]=a}}(e,n),!i.length)return!r;switch(n){case J.Consent:!function(e,n,t){const o=t||e.consent;n.forEach(n=>{Object.keys(o).filter(e=>e in n).forEach(t=>{q(n[t])(e,o)})})}(e,i,o);break;case J.Ready:case J.Run:c=i,(a=e).allowed&&c.forEach(e=>{q(e)(a)});break;case J.Session:!function(e,n){e.session&&n.forEach(n=>{q(n)(e,e.session)})}(e,i);break;default:i.forEach(n=>{"function"==typeof n&&q(n)(e,s)})}var a,c;return!r}async function ne(e,n,t){const{code:o,config:s={},env:i={},before:r}=n;if(!w(o.push))return ie({ok:!1,failed:{invalid:{type:"invalid",error:"Destination code must have a push method"}}});const a=t||s||{init:!1},c=r?{...a,before:r}:a,u={...o,config:c,env:ae(o.env,i)};let l=u.config.id;if(!l)do{l=v(4)}while(e.destinations[l]);return e.destinations[l]=u,!1!==u.config.queue&&(u.queuePush=[...e.queue]),te(e,void 0,{},{[l]:u})}async function te(e,n,t={},o){const{allowed:s,consent:i,globals:r,user:a}=e;if(!s)return ie({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;let l=(s.queuePush||[]).map(e=>({...e,consent:i}));if(s.queuePush=[],n){const e=m(n);l.push(e)}if(!l.length&&!(null==(c=s.queueOn)?void 0:c.length))return{id:o,destination:s,skipped:!0};if(!l.length&&(null==(u=s.queueOn)?void 0:u.length)){const n=await j(oe)(e,s,o);return{id:o,destination:s,skipped:!n}}const d=[],g=l.filter(e=>{const n=h(s.config.consent,i,e.consent);return!n||(e.consent=n,d.push(e),!1)});if(s.queuePush.push(...g),!d.length)return{id:o,destination:s,queue:l};if(!await j(oe)(e,s,o))return{id:o,destination:s,queue:l};let f,b;s.dlq||(s.dlq=[]);const v=function(e,n){const t=e.config.before;return t?L(t,U(n)):[]}(s,e.transformers);let y=0;return await Promise.all(d.map(async n=>{n.globals=p(r,n.globals),n.user=p(a,n.user);let i=n;if(v.length>0&&e.transformers&&Object.keys(e.transformers).length>0){const o=await W(e,e.transformers,v,n,t.ingest,t.respond);if(null===o)return n;i=o}const c=Date.now(),u=await j(se,n=>{const t=s.type||"unknown";e.logger.scope(t).error("Push failed",{error:n,event:i.name}),f=n,s.dlq.push([i,n])})(e,s,o,i,t.ingest,t.respond);return y+=Date.now()-c,void 0!==u&&(b=u),n})),{id:o,destination:s,error:f,response:b,totalDuration:y}})),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 ie({event:n,...Object.keys(u).length&&{done:u},...Object.keys(l).length&&{queued:l},...Object.keys(d).length&&{failed:d}})}async function oe(e,n,t){var o;if(n.init&&!n.config.init){const s=n.type||"unknown",i=e.logger.scope(s),r={collector:e,logger:i,id:t,config:n.config,env:ae(n.env,n.config.env)};i.debug("init");const a=await S(n.init,"DestinationInit",e.hooks)(r);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:i}of o)Z(e,n,t,s,i)}i.debug("init done")}return!0}async function se(e,n,t,o,s,i){const{config:r}=n,a=await O(o,r,e);if(a.ignore)return!1;const c=n.type||"unknown",u=e.logger.scope(c),l={collector:e,logger:u,id:t,config:r,data:a.data,rule:a.mapping,ingest:s,env:{...ae(n.env,r.env),...i?{respond:i}:{}}},d=a.mapping,g=a.mappingKey||"* *";if(!(null==d?void 0:d.batch)||!n.pushBatch){u.debug("push",{event:a.event.name});const t=await S(n.push,"DestinationPush",e.hooks)(a.event,l);return u.debug("push done"),t}{if(n.batches=n.batches||{},!n.batches[g]){const o={key:g,events:[],data:[]};n.batches[g]={batched:o,batchFn:b(()=>{const o=n.batches[g].batched,a={collector:e,logger:u,id:t,config:r,data:void 0,rule:d,ingest:s,env:{...ae(n.env,r.env),...i?{respond:i}:{}}};u.debug("push batch",{events:o.events.length}),S(n.pushBatch,"DestinationPushBatch",e.hooks)(o,a),u.debug("push batch done"),o.events=[],o.data=[]},d.batch)}}const o=n.batches[g];o.batched.events.push(a.event),y(a.data)&&o.batched.data.push(a.data),o.batchFn()}return!0}function ie(e){return{ok:!(null==e?void 0:e.failed),...e}}function re(e){const{code:n,config:t={},env:o={}}=e,{config:s}=V(e,"before"),i={...n.config,...t,...s},r=ae(n.env,o);return{...n,config:i,env:r}}function ae(e,n){return e||n?n?e&&k(e)&&k(n)?{...e,...n}:n:e:{}}async function ce(e,n,t){const o=Object.entries(e).map(async([e,o])=>{var s;const i=o.destroy;if(!i)return;const r=o.type||"unknown",a=t.scope(r),c={id:e,config:o.config,env:null!=(s=o.env)?s:{},logger:a};try{await Promise.race([i(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 ue(e,n,t,o){let s,i,r=!1,a=!1;switch(n){case J.Config:N(t)&&($(e.config,t,{shallow:!1}),i=t,r=!0);break;case J.Consent:if(N(t)){const{update:n,runQueue:o}=function(e,n){let t=!1;const o={};return Object.entries(n).forEach(([e,n])=>{const s=!!n;o[e]=s,t=t||s}),e.consent=d(e.consent,o),{update:o,runQueue:t}}(e,t);i=n,r=!0,a=o}break;case J.Custom:N(t)&&(e.custom=$(e.custom,t),i=t,r=!0);break;case J.Destination:N(t)&&("code"in t&&N(t.code)?s=await ne(e,t,o):R(t.push)&&(s=await ne(e,{code:t},o)));break;case J.Globals:N(t)&&(e.globals=$(e.globals,t),i=t,r=!0);break;case J.On:M(t)&&await async function(e,n,t){const o=e.on,s=o[n]||[],i=D(t)?t:[t];i.forEach(e=>{s.push(e)}),o[n]=s,await ee(e,n,i)}(e,t,o);break;case J.Ready:r=!0;break;case J.Run:s=await async function(e,n){return e.allowed=!0,e.count=0,e.group=K(),e.timing=Date.now(),n&&(n.consent&&(e.consent=$(e.consent,n.consent)),n.user&&(e.user=$(e.user,n.user)),n.globals&&(e.globals=$(e.config.globalsStatic||{},n.globals)),n.custom&&(e.custom=$(e.custom,n.custom))),Object.values(e.destinations).forEach(e=>{e.queuePush=[]}),e.queue=[],e.round++,await te(e)}(e,t),r=!0;break;case J.Session:r=!0;break;case J.Shutdown:await async function(e){const n=e.logger;await ce(e.sources,"source",n),await ce(e.destinations,"destination",n),await ce(e.transformers,"transformer",n),await ce(e.stores,"store",n)}(e);break;case J.User:N(t)&&($(e.user,t,{shallow:!1}),i=t,r=!0)}return r&&await ee(e,n,void 0,i),a&&(s=await te(e)),s||ie({ok:!0})}function le(e,n){return _(async(t,o={})=>await H(async()=>{const s=Date.now(),{id:i,ingest:r,respond:a,mapping:c,preChain:u}=o;let l=t;const d=r?Object.freeze(r):void 0;if(c){const n=await G(l,c,e);if(n.ignore)return ie({ok:!0});if(c.consent&&!T(c.consent,e.consent,n.event.consent))return ie({ok:!0});l=n.event}if((null==u?void 0:u.length)&&e.transformers&&Object.keys(e.transformers).length>0){const n=await W(e,e.transformers,u,l,d,a);if(null===n)return ie({ok:!0});l=n}const g=n(l),f=function(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:i=e.group,count:r=e.count}=n,{name:a=`${t} ${o}`,data:c={},context:u={},globals:l=e.globals,custom:d={},user:g=e.user,nested:f=[],consent:p=e.consent,id:m=`${s}-${i}-${r}`,trigger:b="",entity:v=t,action:h=o,timing:y=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:g,nested:f,consent:p,id:m,trigger:b,entity:v,action:h,timestamp:s,timing:y,group:i,count:r,version:w,source:k}}(e,g),p=await te(e,f,{id:i,ingest:d,respond:a});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()-s}return p},()=>ie({ok:!1}))(),"Push",e.hooks)}async function de(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},i=f(s),r={...o.globalsStatic,...e.globals},a={allowed:!1,config:o,consent:e.consent||{},count:0,custom:e.custom||{},destinations:{},transformers:{},stores:{},globals:r,group:"",hooks:{},logger:i,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.0.2",sources:{},pending:{sources:{},destinations:{}},push:void 0,command:void 0};var c,u;a.push=le(a,e=>({timing:Math.round((Date.now()-a.timing)/10)/100,source:{type:"collector",id:"",previous_id:""},...e})),a.command=(u=ue,B(async(e,n,t)=>await F(async()=>await u(c,e,n,t),()=>ie({ok:!1}))(),"Command",(c=a).hooks));const l=e.stores||{};return a.stores=await async function(e,n={}){const t={};for(const[o,s]of Object.entries(n)){const{code:n,config:i={},env:r={}}=s,a=e.logger.scope("store").scope(o),c={collector:e,logger:a,id:o,config:i,env:r},u=await n(c);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.destinations=await async function(e,n={}){var t,o;const s={};for(const[i,r]of Object.entries(n))(null==(o=null==(t=r.config)?void 0:t.require)?void 0:o.length)?e.pending.destinations[i]=r:s[i]=re(r);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:i={}}=s,{config:r}=V(s,"next"),a=Object.keys(i).length>0?{...r,env:i}:r,c=e.logger.scope("transformer").scope(o),u={collector:e,logger:c,id:o,config:a,env:i},l=await n(u);t[o]=l}return t}(a,e.transformers||{}),a}async function ge(e){e=e||{};const n=await de(e),t=(o=n,{type:"elb",config:{},push:async(e,n,t,s,i,r)=>{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 ie({ok:!1});a=e,n&&"object"==typeof n&&!Array.isArray(n)&&(a.data={...a.data||{},...n})}return s&&"object"==typeof s&&(a.context=s),i&&Array.isArray(i)&&(a.nested=i),r&&"object"==typeof r&&(a.custom=r),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 i=await Y(e,o,s);i&&(t[o]=i)}return t}(n,e.sources||{});Object.assign(n.sources,s);const{consent:i,user:r,globals:a,custom:c}=e;i&&await n.command("consent",i),r&&await n.command("user",r),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 fe=async e=>{let n;return{get flow(){return n},trigger:(t,o)=>async t=>{var s,i,r,a,c,u,l,d,g;const f=o||{};if(f.url){const e=new URL(f.url);window.history.replaceState({},"",e.pathname+e.search)}if(f.referrer&&Object.defineProperty(document,"referrer",{value:f.referrer,configurable:!0}),f.sessionData){const e=f.sessionKey||"elbSessionId";localStorage.setItem(e,JSON.stringify(f.sessionData))}if(f.deviceId){const e=f.deviceKey||"elbDeviceId";localStorage.setItem(e,f.deviceId)}if(!n){const t=await ge({...e,run:null==(s=e.run)||s});n={collector:t.collector,elb:t.elb};const o=f.sessionKey||(null==(c=null==(a=null==(r=null==(i=e.sources)?void 0:i.session)?void 0:r.config)?void 0:a.settings)?void 0:c.sessionKey)||"elbSessionId",p=f.deviceKey||(null==(g=null==(d=null==(l=null==(u=e.sources)?void 0:u.session)?void 0:l.config)?void 0:d.settings)?void 0:g.deviceKey)||"elbDeviceId";localStorage.removeItem(o),localStorage.removeItem(p),f.sessionData&&localStorage.setItem(o,JSON.stringify(f.sessionData)),f.deviceId&&localStorage.setItem(p,f.deviceId),e.consent&&await n.collector.command("consent",e.consent)}}}},pe=(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
|
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/setup.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 { setup } from './setup';\n","import type { Flow } from '@walkeros/core';\n\nexport const newMarketingSession: Flow.StepExample = {\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 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 { Source } from '@walkeros/core';\n\n/** Prepares localStorage with session/device data. */\nexport const setup: Source.SetupFn = (input, env) => {\n if (!input || typeof input !== 'object') return;\n const data = input as Record<string, unknown>;\n\n if (data.sessionData && typeof data.sessionData === 'object') {\n const key =\n typeof data.sessionKey === 'string' ? data.sessionKey : 'elbSessionId';\n env.localStorage.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 env.localStorage.setItem(key, data.deviceId);\n }\n};\n"],"mappings":";;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAS,mBAAmB;;;ACA5B,SAAS,SAAS;AAKX,IAAM,iBAAiB,EAAE,OAAO;AAAA,EACrC,SAAS,EACN,QAAQ,EACR,QAAQ,KAAK,EACb,SAAS,kDAAkD,EAC3D,SAAS;AAAA,EAEZ,SAAS,EACN,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,EACvC,SAAS,gDAAgD,EACzD,SAAS;AAAA,EAEZ,QAAQ,EACL,OAAO,EACP,QAAQ,EAAE,EACV,SAAS,4BAA4B,EACrC,SAAS;AAAA,EAEZ,OAAO,EACJ,QAAQ,EACR,QAAQ,KAAK,EACb,SAAS,kCAAkC,EAC3C,SAAS;AAAA,EAEZ,YAAY,EACT,OAAO,EACP,QAAQ,cAAc,EACtB,SAAS,4BAA4B,EACrC,SAAS;AAAA,EAEZ,gBAAgB,EACb,KAAK,CAAC,SAAS,SAAS,CAAC,EACzB,QAAQ,OAAO,EACf,SAAS,0BAA0B,EACnC,SAAS;AAAA,EAEZ,WAAW,EACR,OAAO,EACP,QAAQ,aAAa,EACrB,SAAS,2BAA2B,EACpC,SAAS;AAAA,EAEZ,eAAe,EACZ,KAAK,CAAC,SAAS,SAAS,CAAC,EACzB,QAAQ,OAAO,EACf,SAAS,yBAAyB,EAClC,SAAS;AAAA,EAEZ,WAAW,EACR,OAAO,EACP,QAAQ,EAAE,EACV,SAAS,uBAAuB,EAChC,SAAS;AAAA;AAAA;AAAA,EAIZ,IAAI,EACD,IAAI,EACJ,SAAS,sDAAsD,EAC/D,SAAS;AACd,CAAC;;;AD1DM,IAAM,WAAW,YAAY,cAAc;;;AEPlD;AAAA;AAAA;AAAA;AAAA;;;ACAA;AAAA;AAAA;AAAA;AAAA;AAEO,IAAM,sBAAwC;AAAA,EACnD,IAAI,EAAE,SAAS,KAAK;AAAA,EACpB,KAAK;AAAA,IACH,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,SAAS;AAAA,MACT,OAAO;AAAA,MACP,OAAO;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,IAAI;AAAA,MACJ,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,UAAU;AAAA,IACZ;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AACF;AAEO,IAAM,mBAAqC;AAAA,EAChD,IAAI,EAAE,SAAS,KAAK;AAAA,EACpB,KAAK;AAAA,IACH,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,SAAS;AAAA,MACT,OAAO;AAAA,MACP,OAAO;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,IAAI;AAAA,MACJ,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,UAAU;AAAA,IACZ;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AACF;;;ACxCO,IAAM,QAAwB,CAAC,OAAO,QAAQ;AACnD,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU;AACzC,QAAM,OAAO;AAEb,MAAI,KAAK,eAAe,OAAO,KAAK,gBAAgB,UAAU;AAC5D,UAAM,MACJ,OAAO,KAAK,eAAe,WAAW,KAAK,aAAa;AAC1D,QAAI,aAAa,QAAQ,KAAK,KAAK,UAAU,KAAK,WAAW,CAAC;AAAA,EAChE;AAEA,MAAI,OAAO,KAAK,aAAa,UAAU;AACrC,UAAM,MACJ,OAAO,KAAK,cAAc,WAAW,KAAK,YAAY;AACxD,QAAI,aAAa,QAAQ,KAAK,KAAK,QAAQ;AAAA,EAC7C;AACF;","names":[]}
|
|
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"]}
|
package/dist/index.d.mts
CHANGED
|
@@ -7,6 +7,8 @@ interface SessionWindowConfig {
|
|
|
7
7
|
parameters?: MarketingParameters;
|
|
8
8
|
referrer?: string;
|
|
9
9
|
url?: string;
|
|
10
|
+
window?: Window & typeof globalThis;
|
|
11
|
+
document?: Document;
|
|
10
12
|
}
|
|
11
13
|
declare function sessionWindow(config?: SessionWindowConfig): Collector.SessionData;
|
|
12
14
|
|
|
@@ -38,6 +40,8 @@ interface Mapping {
|
|
|
38
40
|
}
|
|
39
41
|
type Push = Elb.Fn;
|
|
40
42
|
interface Env extends Source.BaseEnv {
|
|
43
|
+
window?: Window & typeof globalThis;
|
|
44
|
+
document?: Document;
|
|
41
45
|
}
|
|
42
46
|
type Types = Source.Types<Settings, Mapping, Push, Env, InitSettings>;
|
|
43
47
|
type Config = Source.Config<Types>;
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ interface SessionWindowConfig {
|
|
|
7
7
|
parameters?: MarketingParameters;
|
|
8
8
|
referrer?: string;
|
|
9
9
|
url?: string;
|
|
10
|
+
window?: Window & typeof globalThis;
|
|
11
|
+
document?: Document;
|
|
10
12
|
}
|
|
11
13
|
declare function sessionWindow(config?: SessionWindowConfig): Collector.SessionData;
|
|
12
14
|
|
|
@@ -38,6 +40,8 @@ interface Mapping {
|
|
|
38
40
|
}
|
|
39
41
|
type Push = Elb.Fn;
|
|
40
42
|
interface Env extends Source.BaseEnv {
|
|
43
|
+
window?: Window & typeof globalThis;
|
|
44
|
+
document?: Document;
|
|
41
45
|
}
|
|
42
46
|
type Types = Source.Types<Settings, Mapping, Push, Env, InitSettings>;
|
|
43
47
|
type Config = Source.Config<Types>;
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e,t=Object.defineProperty,
|
|
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,a)=>{if(s&&"object"==typeof s||"function"==typeof s)for(let c of r(s))o.call(e,c)||c===i||t(e,c,{get:()=>s[c],enumerable:!(a=n(s,c))||a.enumerable});return e})(t({},"__esModule",{value:!0}),e));var i=require("@walkeros/core"),a=require("@walkeros/web-core"),c=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 a=new URL(e.url||s.location.href),d=e.referrer||i.referrer,u=d&&new URL(d).hostname,l=(0,c.getMarketingParameters)(a,e.parameters);if(Object.keys(l).length&&(l.marketing||(l.marketing=!0),r=!0),!r){const t=e.domains||[];t.push(a.hostname),r=!t.includes(u)}return r?Object.assign({isStart:r,storage:!1,start:Date.now(),id:(0,c.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:c="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,a.storageRead)(e,n,g);return r||(r=(0,i.getId)(8),(0,a.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,a.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})(c,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,a.storageWrite)(c,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},a={push:r,group:void 0,command:o};g({...s,window:n.window,document:n.document,collector:a});return{type:"session",config:i,push:r,on:async e=>{"consent"===e&&g({...s,window:n.window,document:n.document,collector:a})}}},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 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 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 { 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 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);\n if (!id) {\n id = getId(8); // Create a new device ID\n storageWrite(key, id, age * 1440, storage); // 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(String(storageRead(key, storage)));\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(sessionKey, JSON.stringify(session), length * 2, sessionStorage);\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}\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 // Entry type\n if (!isStart) {\n // Only focus on linked or direct navigation types\n // and ignore reloads and all others\n const [perf] = performance.getEntriesByType(\n 'navigation',\n ) as PerformanceNavigationTiming[];\n if (perf.type !== 'navigate') return known;\n }\n\n const url = new URL(config.url || window.location.href);\n const ref = config.referrer || document.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\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 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"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getId as e,tryCatch as
|
|
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
|
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 { 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 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);\n if (!id) {\n id = getId(8); // Create a new device ID\n storageWrite(key, id, age * 1440, storage); // 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(String(storageRead(key, storage)));\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(sessionKey, JSON.stringify(session), length * 2, sessionStorage);\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}\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 // Entry type\n if (!isStart) {\n // Only focus on linked or direct navigation types\n // and ignore reloads and all others\n const [perf] = performance.getEntriesByType(\n 'navigation',\n ) as PerformanceNavigationTiming[];\n if (perf.type !== 'navigate') return known;\n }\n\n const url = new URL(config.url || window.location.href);\n const ref = config.referrer || document.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\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 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 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 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"]}
|
package/dist/walkerOS.json
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$meta": {
|
|
3
3
|
"package": "@walkeros/web-source-session",
|
|
4
|
-
"version": "3.0.
|
|
4
|
+
"version": "3.0.2",
|
|
5
5
|
"type": "source",
|
|
6
|
-
"platform":
|
|
6
|
+
"platform": [
|
|
7
|
+
"web"
|
|
8
|
+
],
|
|
7
9
|
"renderer": "codebox",
|
|
8
10
|
"docs": "https://www.walkeros.io/docs/sources/web/session/detection",
|
|
9
11
|
"source": "https://github.com/elbwalker/walkerOS/tree/main/packages/web/sources/session/src"
|
|
@@ -83,11 +85,17 @@
|
|
|
83
85
|
}
|
|
84
86
|
},
|
|
85
87
|
"examples": {
|
|
86
|
-
"
|
|
87
|
-
"$code": "(
|
|
88
|
+
"createTrigger": {
|
|
89
|
+
"$code": "async e=>{let n;return{get flow(){return n},trigger:(t,o)=>async t=>{var s,i,r,a,c,u,l,d,g;const f=o||{};if(f.url){const e=new URL(f.url);window.history.replaceState({},\"\",e.pathname+e.search)}if(f.referrer&&Object.defineProperty(document,\"referrer\",{value:f.referrer,configurable:!0}),f.sessionData){const e=f.sessionKey||\"elbSessionId\";localStorage.setItem(e,JSON.stringify(f.sessionData))}if(f.deviceId){const e=f.deviceKey||\"elbDeviceId\";localStorage.setItem(e,f.deviceId)}if(!n){const t=await ge({...e,run:null==(s=e.run)||s});n={collector:t.collector,elb:t.elb};const o=f.sessionKey||(null==(c=null==(a=null==(r=null==(i=e.sources)?void 0:i.session)?void 0:r.config)?void 0:a.settings)?void 0:c.sessionKey)||\"elbSessionId\",p=f.deviceKey||(null==(g=null==(d=null==(l=null==(u=e.sources)?void 0:u.session)?void 0:l.config)?void 0:d.settings)?void 0:g.deviceKey)||\"elbDeviceId\";localStorage.removeItem(o),localStorage.removeItem(p),f.sessionData&&localStorage.setItem(o,JSON.stringify(f.sessionData)),f.deviceId&&localStorage.setItem(p,f.deviceId),e.consent&&await n.collector.command(\"consent\",e.consent)}}}}"
|
|
88
90
|
},
|
|
89
91
|
"step": {
|
|
90
92
|
"newMarketingSession": {
|
|
93
|
+
"trigger": {
|
|
94
|
+
"type": "load",
|
|
95
|
+
"options": {
|
|
96
|
+
"url": "https://example.com/?utm_source=google&utm_medium=cpc&utm_campaign=winter-sale"
|
|
97
|
+
}
|
|
98
|
+
},
|
|
91
99
|
"in": {
|
|
92
100
|
"storage": true
|
|
93
101
|
},
|
|
@@ -112,6 +120,12 @@
|
|
|
112
120
|
}
|
|
113
121
|
},
|
|
114
122
|
"returningVisitor": {
|
|
123
|
+
"trigger": {
|
|
124
|
+
"type": "load",
|
|
125
|
+
"options": {
|
|
126
|
+
"referrer": "https://google.com"
|
|
127
|
+
}
|
|
128
|
+
},
|
|
115
129
|
"in": {
|
|
116
130
|
"storage": true
|
|
117
131
|
},
|
|
@@ -132,6 +146,9 @@
|
|
|
132
146
|
"action": "start"
|
|
133
147
|
}
|
|
134
148
|
}
|
|
149
|
+
},
|
|
150
|
+
"trigger": {
|
|
151
|
+
"$code": "(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)}}"
|
|
135
152
|
}
|
|
136
153
|
}
|
|
137
154
|
}
|
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": "
|
|
4
|
+
"version": "4.0.0-next-1773967844643",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"module": "./dist/index.mjs",
|
|
@@ -31,11 +31,11 @@
|
|
|
31
31
|
"update": "npx npm-check-updates -u && npm update"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@walkeros/core": "
|
|
35
|
-
"@walkeros/web-core": "
|
|
34
|
+
"@walkeros/core": "4.0.0-next-1773967844643",
|
|
35
|
+
"@walkeros/web-core": "4.0.0-next-1773967844643"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@walkeros/collector": "
|
|
38
|
+
"@walkeros/collector": "4.0.0-next-1773967844643"
|
|
39
39
|
},
|
|
40
40
|
"repository": {
|
|
41
41
|
"url": "git+https://github.com/elbwalker/walkerOS.git",
|
|
@@ -48,7 +48,9 @@
|
|
|
48
48
|
},
|
|
49
49
|
"walkerOS": {
|
|
50
50
|
"type": "source",
|
|
51
|
-
"platform":
|
|
51
|
+
"platform": [
|
|
52
|
+
"web"
|
|
53
|
+
],
|
|
52
54
|
"renderer": "codebox",
|
|
53
55
|
"docs": "https://www.walkeros.io/docs/sources/web/session/detection"
|
|
54
56
|
},
|