-
Notifications
You must be signed in to change notification settings - Fork 190
Expand file tree
/
Copy pathsessionState.ts
More file actions
139 lines (118 loc) · 4.28 KB
/
Copy pathsessionState.ts
File metadata and controls
139 lines (118 loc) · 4.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import { dateNow } from '@datadog/js-core/time'
import type { TimeStamp } from '@datadog/js-core/time'
import { generateUUID } from '@datadog/js-core/util'
import { isEmptyObject } from '../../tools/utils/objectUtils'
import { objectEntries } from '../../tools/utils/polyfills'
import type { Configuration } from '../configuration'
import { SESSION_EXPIRATION_DELAY, SESSION_TIME_OUT_DELAY } from './sessionConstants'
import { isValidSessionString, SESSION_ENTRY_REGEXP, SESSION_ENTRY_SEPARATOR } from './sessionStateValidation'
export const EXPIRED = '1'
export interface SessionState {
id?: string
created?: string
expire?: string
isExpired?: typeof EXPIRED
anonymousId?: string
[key: string]: string | undefined
}
export function getCreatedDate(state: SessionState): TimeStamp | undefined {
return state.created ? (Number(state.created) as TimeStamp) : undefined
}
export function getExpireDate(state: SessionState): TimeStamp | undefined {
const expireDate = state.expire && (Number(state.expire) as TimeStamp)
const createdDate = getCreatedDate(state)
if (expireDate && createdDate) {
return Math.min(expireDate, createdDate + SESSION_TIME_OUT_DELAY) as TimeStamp
}
}
export function getExpiredSessionState(
previousSessionState: { anonymousId?: string } | undefined,
configuration: Configuration
): SessionState {
const expiredSessionState: SessionState = {
isExpired: EXPIRED,
}
if (configuration.trackAnonymousUser && previousSessionState?.anonymousId) {
expiredSessionState.anonymousId = previousSessionState?.anonymousId
}
return expiredSessionState
}
export function isSessionInNotStartedState(session: SessionState) {
return isEmptyObject(session)
}
export function isSessionStarted(session: SessionState) {
return !isSessionInNotStartedState(session)
}
export function isSessionInExpiredState(session: SessionState) {
return session.isExpired !== undefined || !isActiveSession(session)
}
// An active session is a session in either `Tracked` or `NotTracked` state
function isActiveSession(sessionState: SessionState) {
const expireDate = getExpireDate(sessionState)
return expireDate ? dateNow() < expireDate : false
}
export function expandSessionState(session: SessionState) {
session.expire = String(dateNow() + SESSION_EXPIRATION_DELAY)
}
export function toSessionString(session: SessionState) {
return (
objectEntries(session)
// we use `aid` as a key for anonymousId
.map(([key, value]) => (key === 'anonymousId' ? `aid=${value}` : `${key}=${value}`))
.join(SESSION_ENTRY_SEPARATOR)
)
}
export function toSessionState(sessionString: string | undefined | null) {
const session: SessionState = {}
if (isValidSessionString(sessionString)) {
sessionString.split(SESSION_ENTRY_SEPARATOR).forEach((entry) => {
const matches = SESSION_ENTRY_REGEXP.exec(entry)
if (matches !== null) {
const [, key, value] = matches
if (key === 'aid') {
// we use `aid` as a key for anonymousId
session.anonymousId = value
} else {
session[key] = value
}
}
})
}
return session
}
export function initializeSession(state: SessionState, configuration: Configuration): SessionState {
if (isSessionInNotStartedState(state)) {
if (configuration.trackAnonymousUser) {
state.anonymousId = generateUUID()
}
return getExpiredSessionState(state, configuration)
}
return state
}
export function expandOrRenew(state: SessionState, configuration: Configuration): SessionState {
// prevent renewing if state is altered by a 3rd party (e.g. adblocker deleting the cookie)
if (isSessionInNotStartedState(state)) {
return state
}
let newState = state
if (isSessionInExpiredState(state)) {
newState = getExpiredSessionState(state, configuration)
}
if (!newState.id) {
newState.id = generateUUID()
newState.created = String(dateNow())
}
if (configuration.trackAnonymousUser && !newState.anonymousId) {
newState.anonymousId = generateUUID()
}
delete newState.isExpired
expandSessionState(newState)
return newState
}
export function expandOnly(state: SessionState): SessionState {
if (isSessionInExpiredState(state) || isSessionInNotStartedState(state) || !state.id) {
return state
}
expandSessionState(state)
return state
}