@walkeros/web-source-session 4.1.0-next-1778668930820 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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 command,\n };\n\n // Initialize session using local lib\n sessionStart({\n ...settings,\n window: env.window,\n document: env.document,\n collector: collectorInterface as Collector.Instance,\n });\n\n // Handle events pushed from collector (consent, session, ready, run)\n const handleEvent = async (event: On.Types) => {\n if (event === 'consent') {\n // Re-initialize session on consent changes\n sessionStart({\n ...settings,\n window: env.window,\n document: env.document,\n collector: collectorInterface as Collector.Instance,\n });\n }\n };\n\n return {\n type: 'session',\n config: fullConfig,\n push: elb,\n on: handleEvent,\n };\n};\n\nexport default sourceSession;\n","import type { Collector } from '@walkeros/core';\nimport type { SessionWindowConfig } from './sessionWindow';\nimport type { StorageType } from '@walkeros/core';\nimport type { StorageEnv } from '@walkeros/web-core';\nimport { getId, tryCatch } from '@walkeros/core';\nimport { storageRead, storageWrite } from '@walkeros/web-core';\nimport { sessionWindow } from './sessionWindow';\n\nexport interface SessionStorageConfig extends SessionWindowConfig {\n deviceKey?: string;\n deviceStorage?: StorageType;\n deviceAge?: number;\n sessionKey?: string;\n sessionStorage?: StorageType;\n length?: number; // Minutes after last update to consider session as expired (default: 30)\n pulse?: boolean;\n}\n\nexport function sessionStorage(\n config: SessionStorageConfig = {},\n): Collector.SessionData {\n const now = Date.now();\n const {\n length = 30, // Session length in minutes\n deviceKey = 'elbDeviceId',\n deviceStorage = 'local',\n deviceAge = 30, // Device ID age in days\n sessionKey = 'elbSessionId',\n sessionStorage = 'local',\n pulse = false, // Handle the counting\n } = config;\n const storageEnv: StorageEnv | undefined =\n config.window || config.document\n ? { window: config.window, document: config.document }\n : undefined;\n const windowSession = sessionWindow(config); // Status based on window only\n let isStart = false;\n\n // Retrieve or create device ID\n const device = tryCatch((key: string, age: number, storage: StorageType) => {\n let id = storageRead(key, storage, storageEnv);\n if (!id) {\n id = getId(8); // Create a new device ID\n storageWrite(key, id, age * 1440, storage, undefined, storageEnv); // Write device ID to storage\n }\n return String(id);\n })(deviceKey, deviceAge, deviceStorage);\n\n // Retrieve or initialize session data\n const existingSession: Collector.SessionData =\n tryCatch(\n (key: string, storage?: StorageType) => {\n const session = JSON.parse(\n String(storageRead(key, storage, storageEnv)),\n );\n\n // Only update session if it's not a pulse check\n if (pulse) return session;\n\n // Mark session as not new by default\n session.isNew = false;\n\n // Handle new marketing entry\n if (windowSession.marketing) {\n Object.assign(session, windowSession); // Overwrite existing session with marketing data\n isStart = true; // This is a session start\n }\n\n // Check if session is still active\n if (isStart || session.updated + length * 60000 < now) {\n // Session has expired\n delete session.id; // Unset session ID\n delete session.referrer; // Unset referrer\n session.start = now; // Set new session start\n session.count++; // Increase session count\n session.runs = 1; // Reset runs\n isStart = true; // It's a new session\n } else {\n // Session is still active\n session.runs++; // Increase number of runs\n }\n\n return session;\n },\n () => {\n // No existing session or something went wrong\n isStart = true; // Start a new session\n },\n )(sessionKey, sessionStorage) || {};\n\n // Default session data\n const defaultSession: Partial<Collector.SessionData> = {\n id: getId(12),\n start: now,\n isNew: true,\n count: 1,\n runs: 1,\n };\n\n // Merge session data\n const session = Object.assign(\n defaultSession, // Default session values\n windowSession, // Basic session data based on window\n existingSession, // (Updated) existing session\n { device }, // Device ID\n { isStart, storage: true, updated: now }, // Status of the session\n config.data, // Given data has the highest priority\n );\n\n // Write (updated) session to storage\n storageWrite(\n sessionKey,\n JSON.stringify(session),\n length * 2,\n sessionStorage,\n undefined,\n storageEnv,\n );\n\n return session;\n}\n","import type { Collector, WalkerOS } from '@walkeros/core';\nimport {\n getId,\n getMarketingParameters,\n type ClickIdEntry,\n type MarketingParameters,\n} from '@walkeros/core';\n\nexport interface SessionWindowConfig {\n clickIds?: ClickIdEntry[];\n data?: WalkerOS.Properties;\n domains?: string[];\n isStart?: boolean;\n parameters?: MarketingParameters;\n referrer?: string;\n url?: string;\n window?: Window & typeof globalThis;\n document?: Document;\n}\n\nexport function sessionWindow(\n config: SessionWindowConfig = {},\n): Collector.SessionData {\n let isStart = config.isStart || false;\n const known = { isStart, storage: false };\n\n // If session has explicitly started, return known\n if (config.isStart === false) return known;\n\n const win = config.window ?? window;\n const doc = config.document ?? document;\n\n // Entry type\n if (!isStart) {\n // Only focus on linked or direct navigation types\n // and ignore reloads and all others\n const [perf] = win.performance.getEntriesByType(\n 'navigation',\n ) as PerformanceNavigationTiming[];\n if (perf.type !== 'navigate') return known;\n }\n\n const url = new URL(config.url || win.location.href);\n const ref = config.referrer || doc.referrer;\n const referrer = ref && new URL(ref).hostname;\n\n // Marketing\n const marketing = getMarketingParameters(\n url,\n config.parameters,\n config.clickIds,\n );\n if (Object.keys(marketing).length) {\n // Check for marketing parameters like UTM and add existing\n if (!marketing.marketing)\n // Flag as a marketing session without overwriting\n marketing.marketing = true;\n\n isStart = true;\n }\n\n // Referrer\n if (!isStart) {\n // Small chance of multiple unintended events for same users\n // https://en.wikipedia.org/wiki/HTTP_referer#Referrer_hiding\n // Use domains: [''] to disable direct or hidden referrer\n\n const domains = config.domains || [];\n domains.push(url.hostname);\n isStart = !domains.includes(referrer);\n }\n\n return isStart\n ? // It's a session start, moin\n Object.assign(\n {\n isStart,\n storage: false,\n start: Date.now(),\n id: getId(12),\n referrer,\n },\n marketing,\n config.data,\n )\n : // No session start\n known;\n}\n","import type { Collector, WalkerOS, On, ClickIdEntry } from '@walkeros/core';\nimport type { SessionStorageConfig } from './sessionStorage';\nimport { sessionStorage } from './sessionStorage';\nimport { sessionWindow } from './sessionWindow';\nimport { getGrantedConsent, isArray, isDefined } from '@walkeros/core';\n\nexport interface SessionConfig extends SessionStorageConfig {\n clickIds?: ClickIdEntry[];\n consent?: string | string[];\n storage?: boolean;\n cb?: SessionCallback | false;\n collector?: Collector.Instance;\n}\n\nexport type SessionFunction = typeof sessionStorage | typeof sessionWindow;\nexport type SessionCallback = (\n session: Collector.SessionData,\n collector: Collector.Instance | undefined,\n defaultCb: SessionCallback,\n) => void;\n\nexport function sessionStart(\n config: SessionConfig = {},\n): Collector.SessionData | void {\n const { cb, consent, collector, storage } = config;\n const sessionFn: SessionFunction = storage ? sessionStorage : sessionWindow;\n\n // Consent\n if (consent) {\n const consentHandler = onConsentFn(config, cb);\n\n const consentConfig = (\n isArray(consent) ? consent : [consent]\n ).reduce<On.ConsentRule>(\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(\n config: SessionConfig,\n cb?: SessionCallback | false,\n): On.ConsentFn {\n // Track the last processed round to prevent duplicate processing\n let lastProcessedRound: number | undefined;\n\n const func: On.ConsentFn = (consent, context) => {\n const collector = context.collector;\n\n // Skip if we've already processed this round\n if (\n isDefined(lastProcessedRound) &&\n lastProcessedRound === collector?.round\n )\n return;\n\n // Remember this round has been processed\n lastProcessedRound = collector?.round;\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 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\ndeclare module '@walkeros/core' {\n interface SourceMap {\n session: { type: 'session'; platform?: 'web' };\n }\n}\n\n// Settings: configuration for session source\nexport interface Settings extends SessionConfig {\n // All settings inherited from SessionConfig:\n // - consent?: string | string[]\n // - storage?: boolean\n // - cb?: SessionCallback | false\n // - pulse?: boolean\n // - sessionStorage?: 'local' | 'session'\n // - deviceStorage?: 'local' | 'session'\n // - sessionKey?: string\n // - deviceKey?: string\n // - length?: number (session timeout in minutes)\n}\n\n// InitSettings: user input (all optional)\nexport type InitSettings = Partial<Settings>;\n\nexport interface Mapping {}\n\nexport type Push = Elb.Fn;\n\nexport interface Env extends Source.BaseEnv {\n window?: Window & typeof globalThis;\n document?: Document;\n}\n\nexport type Types = Source.Types<Settings, Mapping, Push, Env, InitSettings>;\n\nexport type Config = Source.Config<Types>;\n\n// Re-export session types from lib\nexport type {\n SessionConfig,\n SessionCallback,\n SessionFunction,\n SessionStorageConfig,\n SessionWindowConfig,\n} from '../lib';\n"],"mappings":"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","names":["import_core","sessionStorage","session","import_core"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/lib/sessionStorage.ts","../src/lib/sessionWindow.ts","../src/lib/sessionStart.ts","../src/types/index.ts"],"sourcesContent":["import type { Source, On, Collector } from '@walkeros/core';\nimport type { Types, Settings } from './types';\nimport { sessionStart } from './lib';\n\n// Export types for external usage\nexport * as SourceSession from './types';\n\n// Export lib functions for direct usage\nexport { sessionStart, sessionStorage, sessionWindow } from './lib';\nexport type {\n SessionConfig,\n SessionCallback,\n SessionFunction,\n SessionStorageConfig,\n SessionWindowConfig,\n} from './lib';\n\n/**\n * Session source implementation.\n *\n * This source handles session detection and management.\n */\nexport const sourceSession: Source.Init<Types> = async (context) => {\n const { config, env } = context;\n const { elb, command } = env;\n\n const settings: Settings = {\n ...config?.settings,\n };\n\n const fullConfig: Source.Config<Types> = {\n settings,\n };\n\n // Create minimal collector interface for sessionStart\n const collectorInterface: Partial<Collector.Instance> = {\n push: elb,\n command,\n };\n\n // Initialize session using local lib\n sessionStart({\n ...settings,\n window: env.window,\n document: env.document,\n collector: collectorInterface as Collector.Instance,\n });\n\n // Handle events pushed from collector (consent, session, ready, run)\n const handleEvent = async (event: On.Types) => {\n if (event === 'consent') {\n // Re-initialize session on consent changes\n sessionStart({\n ...settings,\n window: env.window,\n document: env.document,\n collector: collectorInterface as Collector.Instance,\n });\n }\n };\n\n return {\n type: 'session',\n config: fullConfig,\n push: elb,\n on: handleEvent,\n };\n};\n\nexport default sourceSession;\n","import type { Collector } from '@walkeros/core';\nimport type { SessionWindowConfig } from './sessionWindow';\nimport type { StorageType } from '@walkeros/core';\nimport type { StorageEnv } from '@walkeros/web-core';\nimport { getId, tryCatch } from '@walkeros/core';\nimport { storageRead, storageWrite } from '@walkeros/web-core';\nimport { sessionWindow } from './sessionWindow';\n\nexport interface SessionStorageConfig extends SessionWindowConfig {\n deviceKey?: string;\n deviceStorage?: StorageType;\n deviceAge?: number;\n sessionKey?: string;\n sessionStorage?: StorageType;\n length?: number; // Minutes after last update to consider session as expired (default: 30)\n pulse?: boolean;\n}\n\nexport function sessionStorage(\n config: SessionStorageConfig = {},\n): Collector.SessionData {\n const now = Date.now();\n const {\n length = 30, // Session length in minutes\n deviceKey = 'elbDeviceId',\n deviceStorage = 'local',\n deviceAge = 30, // Device ID age in days\n sessionKey = 'elbSessionId',\n sessionStorage = 'local',\n pulse = false, // Handle the counting\n } = config;\n const storageEnv: StorageEnv | undefined =\n config.window || config.document\n ? { window: config.window, document: config.document }\n : undefined;\n const windowSession = sessionWindow(config); // Status based on window only\n let isStart = false;\n\n // Retrieve or create device ID\n const device = tryCatch((key: string, age: number, storage: StorageType) => {\n let id = storageRead(key, storage, storageEnv);\n if (!id) {\n id = getId(8); // Create a new device ID\n storageWrite(key, id, age * 1440, storage, undefined, storageEnv); // Write device ID to storage\n }\n return String(id);\n })(deviceKey, deviceAge, deviceStorage);\n\n // Retrieve or initialize session data\n const existingSession: Collector.SessionData =\n tryCatch(\n (key: string, storage?: StorageType) => {\n const session = JSON.parse(\n String(storageRead(key, storage, storageEnv)),\n );\n\n // Only update session if it's not a pulse check\n if (pulse) return session;\n\n // Mark session as not new by default\n session.isNew = false;\n\n // Handle new marketing entry\n if (windowSession.marketing) {\n Object.assign(session, windowSession); // Overwrite existing session with marketing data\n isStart = true; // This is a session start\n }\n\n // Check if session is still active\n if (isStart || session.updated + length * 60000 < now) {\n // Session has expired\n delete session.id; // Unset session ID\n delete session.referrer; // Unset referrer\n session.start = now; // Set new session start\n session.count++; // Increase session count\n session.runs = 1; // Reset runs\n isStart = true; // It's a new session\n } else {\n // Session is still active\n session.runs++; // Increase number of runs\n }\n\n return session;\n },\n () => {\n // No existing session or something went wrong\n isStart = true; // Start a new session\n },\n )(sessionKey, sessionStorage) || {};\n\n // Default session data\n const defaultSession: Partial<Collector.SessionData> = {\n id: getId(12),\n start: now,\n isNew: true,\n count: 1,\n runs: 1,\n };\n\n // Merge session data\n const session = Object.assign(\n defaultSession, // Default session values\n windowSession, // Basic session data based on window\n existingSession, // (Updated) existing session\n { device }, // Device ID\n { isStart, storage: true, updated: now }, // Status of the session\n config.data, // Given data has the highest priority\n );\n\n // Write (updated) session to storage\n storageWrite(\n sessionKey,\n JSON.stringify(session),\n length * 2,\n sessionStorage,\n undefined,\n storageEnv,\n );\n\n return session;\n}\n","import type { Collector, WalkerOS } from '@walkeros/core';\nimport {\n getId,\n getMarketingParameters,\n type ClickIdEntry,\n type MarketingParameters,\n} from '@walkeros/core';\n\nexport interface SessionWindowConfig {\n clickIds?: ClickIdEntry[];\n data?: WalkerOS.Properties;\n domains?: string[];\n isStart?: boolean;\n parameters?: MarketingParameters;\n referrer?: string;\n url?: string;\n window?: Window & typeof globalThis;\n document?: Document;\n}\n\nexport function sessionWindow(\n config: SessionWindowConfig = {},\n): Collector.SessionData {\n let isStart = config.isStart || false;\n const known = { isStart, storage: false };\n\n // If session has explicitly started, return known\n if (config.isStart === false) return known;\n\n const win = config.window ?? window;\n const doc = config.document ?? document;\n\n // Entry type\n if (!isStart) {\n // Only focus on linked or direct navigation types\n // and ignore reloads and all others\n const [perf] = win.performance.getEntriesByType(\n 'navigation',\n ) as PerformanceNavigationTiming[];\n if (perf.type !== 'navigate') return known;\n }\n\n const url = new URL(config.url || win.location.href);\n const ref = config.referrer || doc.referrer;\n const referrer = ref && new URL(ref).hostname;\n\n // Marketing\n const marketing = getMarketingParameters(\n url,\n config.parameters,\n config.clickIds,\n );\n if (Object.keys(marketing).length) {\n // Check for marketing parameters like UTM and add existing\n if (!marketing.marketing)\n // Flag as a marketing session without overwriting\n marketing.marketing = true;\n\n isStart = true;\n }\n\n // Referrer\n if (!isStart) {\n // Small chance of multiple unintended events for same users\n // https://en.wikipedia.org/wiki/HTTP_referer#Referrer_hiding\n // Use domains: [''] to disable direct or hidden referrer\n\n const domains = config.domains || [];\n domains.push(url.hostname);\n isStart = !domains.includes(referrer);\n }\n\n return isStart\n ? // It's a session start, moin\n Object.assign(\n {\n isStart,\n storage: false,\n start: Date.now(),\n id: getId(12),\n referrer,\n },\n marketing,\n config.data,\n )\n : // No session start\n known;\n}\n","import type { Collector, WalkerOS, On, ClickIdEntry } from '@walkeros/core';\nimport type { SessionStorageConfig } from './sessionStorage';\nimport { sessionStorage } from './sessionStorage';\nimport { sessionWindow } from './sessionWindow';\nimport { getGrantedConsent, isArray, isDefined } from '@walkeros/core';\n\nexport interface SessionConfig extends SessionStorageConfig {\n clickIds?: ClickIdEntry[];\n consent?: string | string[];\n storage?: boolean;\n cb?: SessionCallback | false;\n collector?: Collector.Instance;\n}\n\nexport type SessionFunction = typeof sessionStorage | typeof sessionWindow;\nexport type SessionCallback = (\n session: Collector.SessionData,\n collector: Collector.Instance | undefined,\n defaultCb: SessionCallback,\n) => void;\n\nexport function sessionStart(\n config: SessionConfig = {},\n): Collector.SessionData | void {\n const { cb, consent, collector, storage } = config;\n const sessionFn: SessionFunction = storage ? sessionStorage : sessionWindow;\n\n // Consent\n if (consent) {\n const consentHandler = onConsentFn(config, cb);\n\n const consentConfig = (\n isArray(consent) ? consent : [consent]\n ).reduce<On.ConsentRule>(\n (acc, key) => ({ ...acc, [key]: consentHandler }),\n {},\n );\n // Register consent handlers with the collector\n if (collector) {\n collector.command('on', { type: 'consent', rules: 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(\n config: SessionConfig,\n cb?: SessionCallback | false,\n): On.ConsentFn {\n // Track the last processed round to prevent duplicate processing\n let lastProcessedRound: number | undefined;\n\n const func: On.ConsentFn = (consent, context) => {\n const collector = context.collector;\n\n // Skip if we've already processed this round\n if (\n isDefined(lastProcessedRound) &&\n lastProcessedRound === collector?.round\n )\n return;\n\n // Remember this round has been processed\n lastProcessedRound = collector?.round;\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 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\ndeclare module '@walkeros/core' {\n interface SourceMap {\n session: { type: 'session'; platform?: 'web' };\n }\n}\n\n// Settings: configuration for session source\nexport interface Settings extends SessionConfig {\n // All settings inherited from SessionConfig:\n // - consent?: string | string[]\n // - storage?: boolean\n // - cb?: SessionCallback | false\n // - pulse?: boolean\n // - sessionStorage?: 'local' | 'session'\n // - deviceStorage?: 'local' | 'session'\n // - sessionKey?: string\n // - deviceKey?: string\n // - length?: number (session timeout in minutes)\n}\n\n// InitSettings: user input (all optional)\nexport type InitSettings = Partial<Settings>;\n\nexport interface Mapping {}\n\nexport type Push = Elb.Fn;\n\nexport interface Env extends Source.BaseEnv {\n window?: Window & typeof globalThis;\n document?: Document;\n}\n\nexport type Types = Source.Types<Settings, Mapping, Push, Env, InitSettings>;\n\nexport type Config = Source.Config<Types>;\n\n// Re-export session types from lib\nexport type {\n SessionConfig,\n SessionCallback,\n SessionFunction,\n SessionStorageConfig,\n SessionWindowConfig,\n} from '../lib';\n"],"mappings":"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","names":["import_core","sessionStorage","session","import_core"]}
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{getId as e,tryCatch as n}from"@walkeros/core";import{storageRead as t,storageWrite as o}from"@walkeros/web-core";import{getId as r,getMarketingParameters as s}from"@walkeros/core";function c(e={}){var n,t;let o=e.isStart||!1;const c={isStart:o,storage:!1};if(!1===e.isStart)return c;const i=null!=(n=e.window)?n:window,a=null!=(t=e.document)?t:document;if(!o){const[e]=i.performance.getEntriesByType("navigation");if("navigate"!==e.type)return c}const d=new URL(e.url||i.location.href),u=e.referrer||a.referrer,l=u&&new URL(u).hostname,m=s(d,e.parameters,e.clickIds);if(Object.keys(m).length&&(m.marketing||(m.marketing=!0),o=!0),!o){const n=e.domains||[];n.push(d.hostname),o=!n.includes(l)}return o?Object.assign({isStart:o,storage:!1,start:Date.now(),id:r(12),referrer:l},m,e.data):c}function i(r={}){const s=Date.now(),{length:i=30,deviceKey:a="elbDeviceId",deviceStorage:d="local",deviceAge:u=30,sessionKey:l="elbSessionId",sessionStorage:m="local",pulse:w=!1}=r,g=r.window||r.document?{window:r.window,document:r.document}:void 0,f=c(r);let v=!1;const p=n((n,r,s)=>{let c=t(n,s,g);return c||(c=e(8),o(n,c,1440*r,s,void 0,g)),String(c)})(a,u,d),S=n((e,n)=>{const o=JSON.parse(String(t(e,n,g)));return w||(o.isNew=!1,f.marketing&&(Object.assign(o,f),v=!0),v||o.updated+6e4*i<s?(delete o.id,delete o.referrer,o.start=s,o.count++,o.runs=1,v=!0):o.runs++),o},()=>{v=!0})(l,m)||{},y={id:e(12),start:s,isNew:!0,count:1,runs:1},b=Object.assign(y,f,S,{device:p},{isStart:v,storage:!0,updated:s},r.data);return o(l,JSON.stringify(b),2*i,m,void 0,g),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?i:c)(e),o,n);{const r=function(e,n){let t;const o=(o,r)=>{const s=r.collector;if(u(t)&&t===(null==s?void 0:s.round))return;t=null==s?void 0:s.round;let l=()=>c(e);if(e.consent){const n=(d(e.consent)?e.consent:[e.consent]).reduce((e,n)=>({...e,[n]:!0}),{});a(n,o)&&(l=()=>i(e))}m(l(),s,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=w),t(e,n,w))}var w=(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},g={},f=async e=>{const{config:n,env:t}=e,{elb:o,command:r}=t,s={...null==n?void 0:n.settings},c={settings:s},i={push:o,command:r};l({...s,window:t.window,document:t.document,collector:i});return{type:"session",config:c,push:o,on:async e=>{"consent"===e&&l({...s,window:t.window,document:t.document,collector:i})}}},v=f;export{g as SourceSession,v as default,l as sessionStart,i as sessionStorage,c as sessionWindow,f as sourceSession};//# sourceMappingURL=index.mjs.map
1
+ import{getId as e,tryCatch as n}from"@walkeros/core";import{storageRead as t,storageWrite as o}from"@walkeros/web-core";import{getId as r,getMarketingParameters as s}from"@walkeros/core";function c(e={}){var n,t;let o=e.isStart||!1;const c={isStart:o,storage:!1};if(!1===e.isStart)return c;const i=null!=(n=e.window)?n:window,a=null!=(t=e.document)?t:document;if(!o){const[e]=i.performance.getEntriesByType("navigation");if("navigate"!==e.type)return c}const d=new URL(e.url||i.location.href),u=e.referrer||a.referrer,l=u&&new URL(u).hostname,m=s(d,e.parameters,e.clickIds);if(Object.keys(m).length&&(m.marketing||(m.marketing=!0),o=!0),!o){const n=e.domains||[];n.push(d.hostname),o=!n.includes(l)}return o?Object.assign({isStart:o,storage:!1,start:Date.now(),id:r(12),referrer:l},m,e.data):c}function i(r={}){const s=Date.now(),{length:i=30,deviceKey:a="elbDeviceId",deviceStorage:d="local",deviceAge:u=30,sessionKey:l="elbSessionId",sessionStorage:m="local",pulse:w=!1}=r,g=r.window||r.document?{window:r.window,document:r.document}:void 0,f=c(r);let p=!1;const v=n((n,r,s)=>{let c=t(n,s,g);return c||(c=e(8),o(n,c,1440*r,s,void 0,g)),String(c)})(a,u,d),S=n((e,n)=>{const o=JSON.parse(String(t(e,n,g)));return w||(o.isNew=!1,f.marketing&&(Object.assign(o,f),p=!0),p||o.updated+6e4*i<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*i,m,void 0,g),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?i:c)(e),o,n);{const r=function(e,n){let t;const o=(o,r)=>{const s=r.collector;if(u(t)&&t===(null==s?void 0:s.round))return;t=null==s?void 0:s.round;let l=()=>c(e);if(e.consent){const n=(d(e.consent)?e.consent:[e.consent]).reduce((e,n)=>({...e,[n]:!0}),{});a(n,o)&&(l=()=>i(e))}m(l(),s,n)};return o}(e,n),s=(d(t)?t:[t]).reduce((e,n)=>({...e,[n]:r}),{});o&&o.command("on",{type:"consent",rules:s})}}function m(e,n,t){return!1===t?e:(t||(t=w),t(e,n,w))}var w=(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},g={},f=async e=>{const{config:n,env:t}=e,{elb:o,command:r}=t,s={...null==n?void 0:n.settings},c={settings:s},i={push:o,command:r};l({...s,window:t.window,document:t.document,collector:i});return{type:"session",config:c,push:o,on:async e=>{"consent"===e&&l({...s,window:t.window,document:t.document,collector:i})}}},p=f;export{g as SourceSession,p as default,l as sessionStart,i as sessionStorage,c as sessionWindow,f as sourceSession};//# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/sessionStorage.ts","../src/lib/sessionWindow.ts","../src/lib/sessionStart.ts","../src/types/index.ts","../src/index.ts"],"sourcesContent":["import type { Collector } from '@walkeros/core';\nimport type { SessionWindowConfig } from './sessionWindow';\nimport type { StorageType } from '@walkeros/core';\nimport type { StorageEnv } from '@walkeros/web-core';\nimport { getId, tryCatch } from '@walkeros/core';\nimport { storageRead, storageWrite } from '@walkeros/web-core';\nimport { sessionWindow } from './sessionWindow';\n\nexport interface SessionStorageConfig extends SessionWindowConfig {\n deviceKey?: string;\n deviceStorage?: StorageType;\n deviceAge?: number;\n sessionKey?: string;\n sessionStorage?: StorageType;\n length?: number; // Minutes after last update to consider session as expired (default: 30)\n pulse?: boolean;\n}\n\nexport function sessionStorage(\n config: SessionStorageConfig = {},\n): Collector.SessionData {\n const now = Date.now();\n const {\n length = 30, // Session length in minutes\n deviceKey = 'elbDeviceId',\n deviceStorage = 'local',\n deviceAge = 30, // Device ID age in days\n sessionKey = 'elbSessionId',\n sessionStorage = 'local',\n pulse = false, // Handle the counting\n } = config;\n const storageEnv: StorageEnv | undefined =\n config.window || config.document\n ? { window: config.window, document: config.document }\n : undefined;\n const windowSession = sessionWindow(config); // Status based on window only\n let isStart = false;\n\n // Retrieve or create device ID\n const device = tryCatch((key: string, age: number, storage: StorageType) => {\n let id = storageRead(key, storage, storageEnv);\n if (!id) {\n id = getId(8); // Create a new device ID\n storageWrite(key, id, age * 1440, storage, undefined, storageEnv); // Write device ID to storage\n }\n return String(id);\n })(deviceKey, deviceAge, deviceStorage);\n\n // Retrieve or initialize session data\n const existingSession: Collector.SessionData =\n tryCatch(\n (key: string, storage?: StorageType) => {\n const session = JSON.parse(\n String(storageRead(key, storage, storageEnv)),\n );\n\n // Only update session if it's not a pulse check\n if (pulse) return session;\n\n // Mark session as not new by default\n session.isNew = false;\n\n // Handle new marketing entry\n if (windowSession.marketing) {\n Object.assign(session, windowSession); // Overwrite existing session with marketing data\n isStart = true; // This is a session start\n }\n\n // Check if session is still active\n if (isStart || session.updated + length * 60000 < now) {\n // Session has expired\n delete session.id; // Unset session ID\n delete session.referrer; // Unset referrer\n session.start = now; // Set new session start\n session.count++; // Increase session count\n session.runs = 1; // Reset runs\n isStart = true; // It's a new session\n } else {\n // Session is still active\n session.runs++; // Increase number of runs\n }\n\n return session;\n },\n () => {\n // No existing session or something went wrong\n isStart = true; // Start a new session\n },\n )(sessionKey, sessionStorage) || {};\n\n // Default session data\n const defaultSession: Partial<Collector.SessionData> = {\n id: getId(12),\n start: now,\n isNew: true,\n count: 1,\n runs: 1,\n };\n\n // Merge session data\n const session = Object.assign(\n defaultSession, // Default session values\n windowSession, // Basic session data based on window\n existingSession, // (Updated) existing session\n { device }, // Device ID\n { isStart, storage: true, updated: now }, // Status of the session\n config.data, // Given data has the highest priority\n );\n\n // Write (updated) session to storage\n storageWrite(\n sessionKey,\n JSON.stringify(session),\n length * 2,\n sessionStorage,\n undefined,\n storageEnv,\n );\n\n return session;\n}\n","import type { Collector, WalkerOS } from '@walkeros/core';\nimport {\n getId,\n getMarketingParameters,\n type ClickIdEntry,\n type MarketingParameters,\n} from '@walkeros/core';\n\nexport interface SessionWindowConfig {\n clickIds?: ClickIdEntry[];\n data?: WalkerOS.Properties;\n domains?: string[];\n isStart?: boolean;\n parameters?: MarketingParameters;\n referrer?: string;\n url?: string;\n window?: Window & typeof globalThis;\n document?: Document;\n}\n\nexport function sessionWindow(\n config: SessionWindowConfig = {},\n): Collector.SessionData {\n let isStart = config.isStart || false;\n const known = { isStart, storage: false };\n\n // If session has explicitly started, return known\n if (config.isStart === false) return known;\n\n const win = config.window ?? window;\n const doc = config.document ?? document;\n\n // Entry type\n if (!isStart) {\n // Only focus on linked or direct navigation types\n // and ignore reloads and all others\n const [perf] = win.performance.getEntriesByType(\n 'navigation',\n ) as PerformanceNavigationTiming[];\n if (perf.type !== 'navigate') return known;\n }\n\n const url = new URL(config.url || win.location.href);\n const ref = config.referrer || doc.referrer;\n const referrer = ref && new URL(ref).hostname;\n\n // Marketing\n const marketing = getMarketingParameters(\n url,\n config.parameters,\n config.clickIds,\n );\n if (Object.keys(marketing).length) {\n // Check for marketing parameters like UTM and add existing\n if (!marketing.marketing)\n // Flag as a marketing session without overwriting\n marketing.marketing = true;\n\n isStart = true;\n }\n\n // Referrer\n if (!isStart) {\n // Small chance of multiple unintended events for same users\n // https://en.wikipedia.org/wiki/HTTP_referer#Referrer_hiding\n // Use domains: [''] to disable direct or hidden referrer\n\n const domains = config.domains || [];\n domains.push(url.hostname);\n isStart = !domains.includes(referrer);\n }\n\n return isStart\n ? // It's a session start, moin\n Object.assign(\n {\n isStart,\n storage: false,\n start: Date.now(),\n id: getId(12),\n referrer,\n },\n marketing,\n config.data,\n )\n : // No session start\n known;\n}\n","import type { Collector, WalkerOS, On, ClickIdEntry } from '@walkeros/core';\nimport type { SessionStorageConfig } from './sessionStorage';\nimport { sessionStorage } from './sessionStorage';\nimport { sessionWindow } from './sessionWindow';\nimport { getGrantedConsent, isArray, isDefined } from '@walkeros/core';\n\nexport interface SessionConfig extends SessionStorageConfig {\n clickIds?: ClickIdEntry[];\n consent?: string | string[];\n storage?: boolean;\n cb?: SessionCallback | false;\n collector?: Collector.Instance;\n}\n\nexport type SessionFunction = typeof sessionStorage | typeof sessionWindow;\nexport type SessionCallback = (\n session: Collector.SessionData,\n collector: Collector.Instance | undefined,\n defaultCb: SessionCallback,\n) => void;\n\nexport function sessionStart(\n config: SessionConfig = {},\n): Collector.SessionData | void {\n const { cb, consent, collector, storage } = config;\n const sessionFn: SessionFunction = storage ? sessionStorage : sessionWindow;\n\n // Consent\n if (consent) {\n const consentHandler = onConsentFn(config, cb);\n\n const consentConfig = (\n isArray(consent) ? consent : [consent]\n ).reduce<On.ConsentRule>(\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(\n config: SessionConfig,\n cb?: SessionCallback | false,\n): On.ConsentFn {\n // Track the last processed round to prevent duplicate processing\n let lastProcessedRound: number | undefined;\n\n const func: On.ConsentFn = (consent, context) => {\n const collector = context.collector;\n\n // Skip if we've already processed this round\n if (\n isDefined(lastProcessedRound) &&\n lastProcessedRound === collector?.round\n )\n return;\n\n // Remember this round has been processed\n lastProcessedRound = collector?.round;\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 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\ndeclare module '@walkeros/core' {\n interface SourceMap {\n session: { type: 'session'; platform?: 'web' };\n }\n}\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 command,\n };\n\n // Initialize session using local lib\n sessionStart({\n ...settings,\n window: env.window,\n document: env.document,\n collector: collectorInterface as Collector.Instance,\n });\n\n // Handle events pushed from collector (consent, session, ready, run)\n const handleEvent = async (event: On.Types) => {\n if (event === 'consent') {\n // Re-initialize session on consent changes\n sessionStart({\n ...settings,\n window: env.window,\n document: env.document,\n collector: collectorInterface as Collector.Instance,\n });\n }\n };\n\n return {\n type: 'session',\n config: fullConfig,\n push: elb,\n on: handleEvent,\n };\n};\n\nexport default sourceSession;\n"],"mappings":"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","names":["getId","sessionStorage","getId","session"]}
1
+ {"version":3,"sources":["../src/lib/sessionStorage.ts","../src/lib/sessionWindow.ts","../src/lib/sessionStart.ts","../src/types/index.ts","../src/index.ts"],"sourcesContent":["import type { Collector } from '@walkeros/core';\nimport type { SessionWindowConfig } from './sessionWindow';\nimport type { StorageType } from '@walkeros/core';\nimport type { StorageEnv } from '@walkeros/web-core';\nimport { getId, tryCatch } from '@walkeros/core';\nimport { storageRead, storageWrite } from '@walkeros/web-core';\nimport { sessionWindow } from './sessionWindow';\n\nexport interface SessionStorageConfig extends SessionWindowConfig {\n deviceKey?: string;\n deviceStorage?: StorageType;\n deviceAge?: number;\n sessionKey?: string;\n sessionStorage?: StorageType;\n length?: number; // Minutes after last update to consider session as expired (default: 30)\n pulse?: boolean;\n}\n\nexport function sessionStorage(\n config: SessionStorageConfig = {},\n): Collector.SessionData {\n const now = Date.now();\n const {\n length = 30, // Session length in minutes\n deviceKey = 'elbDeviceId',\n deviceStorage = 'local',\n deviceAge = 30, // Device ID age in days\n sessionKey = 'elbSessionId',\n sessionStorage = 'local',\n pulse = false, // Handle the counting\n } = config;\n const storageEnv: StorageEnv | undefined =\n config.window || config.document\n ? { window: config.window, document: config.document }\n : undefined;\n const windowSession = sessionWindow(config); // Status based on window only\n let isStart = false;\n\n // Retrieve or create device ID\n const device = tryCatch((key: string, age: number, storage: StorageType) => {\n let id = storageRead(key, storage, storageEnv);\n if (!id) {\n id = getId(8); // Create a new device ID\n storageWrite(key, id, age * 1440, storage, undefined, storageEnv); // Write device ID to storage\n }\n return String(id);\n })(deviceKey, deviceAge, deviceStorage);\n\n // Retrieve or initialize session data\n const existingSession: Collector.SessionData =\n tryCatch(\n (key: string, storage?: StorageType) => {\n const session = JSON.parse(\n String(storageRead(key, storage, storageEnv)),\n );\n\n // Only update session if it's not a pulse check\n if (pulse) return session;\n\n // Mark session as not new by default\n session.isNew = false;\n\n // Handle new marketing entry\n if (windowSession.marketing) {\n Object.assign(session, windowSession); // Overwrite existing session with marketing data\n isStart = true; // This is a session start\n }\n\n // Check if session is still active\n if (isStart || session.updated + length * 60000 < now) {\n // Session has expired\n delete session.id; // Unset session ID\n delete session.referrer; // Unset referrer\n session.start = now; // Set new session start\n session.count++; // Increase session count\n session.runs = 1; // Reset runs\n isStart = true; // It's a new session\n } else {\n // Session is still active\n session.runs++; // Increase number of runs\n }\n\n return session;\n },\n () => {\n // No existing session or something went wrong\n isStart = true; // Start a new session\n },\n )(sessionKey, sessionStorage) || {};\n\n // Default session data\n const defaultSession: Partial<Collector.SessionData> = {\n id: getId(12),\n start: now,\n isNew: true,\n count: 1,\n runs: 1,\n };\n\n // Merge session data\n const session = Object.assign(\n defaultSession, // Default session values\n windowSession, // Basic session data based on window\n existingSession, // (Updated) existing session\n { device }, // Device ID\n { isStart, storage: true, updated: now }, // Status of the session\n config.data, // Given data has the highest priority\n );\n\n // Write (updated) session to storage\n storageWrite(\n sessionKey,\n JSON.stringify(session),\n length * 2,\n sessionStorage,\n undefined,\n storageEnv,\n );\n\n return session;\n}\n","import type { Collector, WalkerOS } from '@walkeros/core';\nimport {\n getId,\n getMarketingParameters,\n type ClickIdEntry,\n type MarketingParameters,\n} from '@walkeros/core';\n\nexport interface SessionWindowConfig {\n clickIds?: ClickIdEntry[];\n data?: WalkerOS.Properties;\n domains?: string[];\n isStart?: boolean;\n parameters?: MarketingParameters;\n referrer?: string;\n url?: string;\n window?: Window & typeof globalThis;\n document?: Document;\n}\n\nexport function sessionWindow(\n config: SessionWindowConfig = {},\n): Collector.SessionData {\n let isStart = config.isStart || false;\n const known = { isStart, storage: false };\n\n // If session has explicitly started, return known\n if (config.isStart === false) return known;\n\n const win = config.window ?? window;\n const doc = config.document ?? document;\n\n // Entry type\n if (!isStart) {\n // Only focus on linked or direct navigation types\n // and ignore reloads and all others\n const [perf] = win.performance.getEntriesByType(\n 'navigation',\n ) as PerformanceNavigationTiming[];\n if (perf.type !== 'navigate') return known;\n }\n\n const url = new URL(config.url || win.location.href);\n const ref = config.referrer || doc.referrer;\n const referrer = ref && new URL(ref).hostname;\n\n // Marketing\n const marketing = getMarketingParameters(\n url,\n config.parameters,\n config.clickIds,\n );\n if (Object.keys(marketing).length) {\n // Check for marketing parameters like UTM and add existing\n if (!marketing.marketing)\n // Flag as a marketing session without overwriting\n marketing.marketing = true;\n\n isStart = true;\n }\n\n // Referrer\n if (!isStart) {\n // Small chance of multiple unintended events for same users\n // https://en.wikipedia.org/wiki/HTTP_referer#Referrer_hiding\n // Use domains: [''] to disable direct or hidden referrer\n\n const domains = config.domains || [];\n domains.push(url.hostname);\n isStart = !domains.includes(referrer);\n }\n\n return isStart\n ? // It's a session start, moin\n Object.assign(\n {\n isStart,\n storage: false,\n start: Date.now(),\n id: getId(12),\n referrer,\n },\n marketing,\n config.data,\n )\n : // No session start\n known;\n}\n","import type { Collector, WalkerOS, On, ClickIdEntry } from '@walkeros/core';\nimport type { SessionStorageConfig } from './sessionStorage';\nimport { sessionStorage } from './sessionStorage';\nimport { sessionWindow } from './sessionWindow';\nimport { getGrantedConsent, isArray, isDefined } from '@walkeros/core';\n\nexport interface SessionConfig extends SessionStorageConfig {\n clickIds?: ClickIdEntry[];\n consent?: string | string[];\n storage?: boolean;\n cb?: SessionCallback | false;\n collector?: Collector.Instance;\n}\n\nexport type SessionFunction = typeof sessionStorage | typeof sessionWindow;\nexport type SessionCallback = (\n session: Collector.SessionData,\n collector: Collector.Instance | undefined,\n defaultCb: SessionCallback,\n) => void;\n\nexport function sessionStart(\n config: SessionConfig = {},\n): Collector.SessionData | void {\n const { cb, consent, collector, storage } = config;\n const sessionFn: SessionFunction = storage ? sessionStorage : sessionWindow;\n\n // Consent\n if (consent) {\n const consentHandler = onConsentFn(config, cb);\n\n const consentConfig = (\n isArray(consent) ? consent : [consent]\n ).reduce<On.ConsentRule>(\n (acc, key) => ({ ...acc, [key]: consentHandler }),\n {},\n );\n // Register consent handlers with the collector\n if (collector) {\n collector.command('on', { type: 'consent', rules: 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(\n config: SessionConfig,\n cb?: SessionCallback | false,\n): On.ConsentFn {\n // Track the last processed round to prevent duplicate processing\n let lastProcessedRound: number | undefined;\n\n const func: On.ConsentFn = (consent, context) => {\n const collector = context.collector;\n\n // Skip if we've already processed this round\n if (\n isDefined(lastProcessedRound) &&\n lastProcessedRound === collector?.round\n )\n return;\n\n // Remember this round has been processed\n lastProcessedRound = collector?.round;\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 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\ndeclare module '@walkeros/core' {\n interface SourceMap {\n session: { type: 'session'; platform?: 'web' };\n }\n}\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 command,\n };\n\n // Initialize session using local lib\n sessionStart({\n ...settings,\n window: env.window,\n document: env.document,\n collector: collectorInterface as Collector.Instance,\n });\n\n // Handle events pushed from collector (consent, session, ready, run)\n const handleEvent = async (event: On.Types) => {\n if (event === 'consent') {\n // Re-initialize session on consent changes\n sessionStart({\n ...settings,\n window: env.window,\n document: env.document,\n collector: collectorInterface as Collector.Instance,\n });\n }\n };\n\n return {\n type: 'session',\n config: fullConfig,\n push: elb,\n on: handleEvent,\n };\n};\n\nexport default sourceSession;\n"],"mappings":"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","names":["getId","sessionStorage","getId","session"]}
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$meta": {
3
3
  "package": "@walkeros/web-source-session",
4
- "version": "4.1.0-next-1778668930820",
4
+ "version": "4.1.0",
5
5
  "type": "source",
6
6
  "platform": [
7
7
  "web"
@@ -108,7 +108,7 @@
108
108
  },
109
109
  "examples": {
110
110
  "createTrigger": {
111
- "$code": "async e=>{let n;return{get flow(){return n},trigger:(t,o)=>async t=>{var s,r,i,a,c,u,l,d,f;const g=o||{};if(g.url){const e=new URL(g.url);window.history.replaceState({},\"\",e.pathname+e.search)}if(g.referrer&&Object.defineProperty(document,\"referrer\",{value:g.referrer,configurable:!0}),g.sessionData){const e=g.sessionKey||\"elbSessionId\";localStorage.setItem(e,JSON.stringify(g.sessionData))}if(g.deviceId){const e=g.deviceKey||\"elbDeviceId\";localStorage.setItem(e,g.deviceId)}if(!n){const t=await Je({...e,run:null==(s=e.run)||s});n={collector:t.collector,elb:t.elb};const o=g.sessionKey||(null==(c=null==(a=null==(i=null==(r=e.sources)?void 0:r.session)?void 0:i.config)?void 0:a.settings)?void 0:c.sessionKey)||\"elbSessionId\",p=g.deviceKey||(null==(f=null==(d=null==(l=null==(u=e.sources)?void 0:u.session)?void 0:l.config)?void 0:d.settings)?void 0:f.deviceKey)||\"elbDeviceId\";localStorage.removeItem(o),localStorage.removeItem(p),g.sessionData&&localStorage.setItem(o,JSON.stringify(g.sessionData)),g.deviceId&&localStorage.setItem(p,g.deviceId),e.consent&&await n.collector.command(\"consent\",e.consent)}}}}"
111
+ "$code": "async e=>{let n;return{get flow(){return n},trigger:(t,o)=>async t=>{var s,r,i,a,c,l,u,d,f;const g=o||{};if(g.url){const e=new URL(g.url);window.history.replaceState({},\"\",e.pathname+e.search)}if(g.referrer&&Object.defineProperty(document,\"referrer\",{value:g.referrer,configurable:!0}),g.sessionData){const e=g.sessionKey||\"elbSessionId\";localStorage.setItem(e,JSON.stringify(g.sessionData))}if(g.deviceId){const e=g.deviceKey||\"elbDeviceId\";localStorage.setItem(e,g.deviceId)}if(!n){const t=await ln({...e,run:null==(s=e.run)||s});n={collector:t.collector,elb:t.elb};const o=g.sessionKey||(null==(c=null==(a=null==(i=null==(r=e.sources)?void 0:r.session)?void 0:i.config)?void 0:a.settings)?void 0:c.sessionKey)||\"elbSessionId\",p=g.deviceKey||(null==(f=null==(d=null==(u=null==(l=e.sources)?void 0:l.session)?void 0:u.config)?void 0:d.settings)?void 0:f.deviceKey)||\"elbDeviceId\";localStorage.removeItem(o),localStorage.removeItem(p),g.sessionData&&localStorage.setItem(o,JSON.stringify(g.sessionData)),g.deviceId&&localStorage.setItem(p,g.deviceId),e.consent&&await n.collector.command(\"consent\",e.consent)}}}}"
112
112
  },
113
113
  "step": {
114
114
  "newMarketingSession": {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@walkeros/web-source-session",
3
3
  "description": "Session source for walkerOS",
4
- "version": "4.1.0-next-1778668930820",
4
+ "version": "4.1.0",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.js",
7
7
  "module": "./dist/index.mjs",
@@ -20,7 +20,8 @@
20
20
  "./walkerOS.json": "./dist/walkerOS.json"
21
21
  },
22
22
  "files": [
23
- "dist/**"
23
+ "dist/**",
24
+ "CHANGELOG.md"
24
25
  ],
25
26
  "scripts": {
26
27
  "build": "tsup --silent",
@@ -32,11 +33,11 @@
32
33
  "update": "npx npm-check-updates -u && npm update"
33
34
  },
34
35
  "dependencies": {
35
- "@walkeros/core": "4.1.0-next-1778668930820",
36
- "@walkeros/web-core": "4.1.0-next-1778668930820"
36
+ "@walkeros/core": "4.1.0",
37
+ "@walkeros/web-core": "4.1.0"
37
38
  },
38
39
  "devDependencies": {
39
- "@walkeros/collector": "4.1.0-next-1778668930820"
40
+ "@walkeros/collector": "4.1.0"
40
41
  },
41
42
  "repository": {
42
43
  "url": "git+https://github.com/elbwalker/walkerOS.git",