session.js ➔ updateSession   F
last analyzed

Complexity

Conditions 20

Size

Total Lines 60
Code Lines 38

Duplication

Lines 60
Ratio 100 %

Importance

Changes 0
Metric Value
eloc 38
dl 60
loc 60
c 0
b 0
f 0
rs 0
cc 20

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like session.js ➔ updateSession often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1 View Code Duplication
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
0 ignored issues
show
Bug introduced by
The variable Symbol seems to be never declared. If this is a global, consider adding a /** global: Symbol */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
2
3
const misc = require('./utils/misc.js');
4
const time = require('./utils/time.js');
5
6
/**
7
 * Creates a new `Session` object by setting certain default parameters. If optional @param context
8
 * is passed, the passed properties are applied to the session object.
9
 *
10
 * @param context (optional) additional properties to be applied to the returned session object
11
 *
12
 * @returns a new `Session` object
13
 */
14
function makeSession(context) {
15
  // Both timestamp and started are in seconds since the UNIX epoch.
16
  const startingTime = time.timestampInSeconds();
17
18
  const session = {
19
    sid: misc.uuid4(),
20
    init: true,
21
    timestamp: startingTime,
22
    started: startingTime,
23
    duration: 0,
24
    status: 'ok',
25
    errors: 0,
26
    ignoreDuration: false,
27
    toJSON: () => sessionToJSON(session),
28
  };
29
30
  if (context) {
31
    updateSession(session, context);
32
  }
33
34
  return session;
35
}
36
37
/**
38
 * Updates a session object with the properties passed in the context.
39
 *
40
 * Note that this function mutates the passed object and returns void.
41
 * (Had to do this instead of returning a new and updated session because closing and sending a session
42
 * makes an update to the session after it was passed to the sending logic.
43
 * @see Client.captureSession )
44
 *
45
 * @param session the `Session` to update
46
 * @param context the `SessionContext` holding the properties that should be updated in @param session
47
 */
48
// eslint-disable-next-line complexity
49
function updateSession(session, context = {}) {
50
  if (context.user) {
51
    if (!session.ipAddress && context.user.ip_address) {
52
      session.ipAddress = context.user.ip_address;
53
    }
54
55
    if (!session.did && !context.did) {
56
      session.did = context.user.id || context.user.email || context.user.username;
57
    }
58
  }
59
60
  session.timestamp = context.timestamp || time.timestampInSeconds();
61
62
  if (context.abnormal_mechanism) {
63
    session.abnormal_mechanism = context.abnormal_mechanism;
64
  }
65
66
  if (context.ignoreDuration) {
67
    session.ignoreDuration = context.ignoreDuration;
68
  }
69
  if (context.sid) {
70
    // Good enough uuid validation. — Kamil
71
    session.sid = context.sid.length === 32 ? context.sid : misc.uuid4();
72
  }
73
  if (context.init !== undefined) {
74
    session.init = context.init;
75
  }
76
  if (!session.did && context.did) {
77
    session.did = `${context.did}`;
78
  }
79
  if (typeof context.started === 'number') {
80
    session.started = context.started;
81
  }
82
  if (session.ignoreDuration) {
83
    session.duration = undefined;
84
  } else if (typeof context.duration === 'number') {
85
    session.duration = context.duration;
86
  } else {
87
    const duration = session.timestamp - session.started;
88
    session.duration = duration >= 0 ? duration : 0;
89
  }
90
  if (context.release) {
91
    session.release = context.release;
92
  }
93
  if (context.environment) {
94
    session.environment = context.environment;
95
  }
96
  if (!session.ipAddress && context.ipAddress) {
97
    session.ipAddress = context.ipAddress;
98
  }
99
  if (!session.userAgent && context.userAgent) {
100
    session.userAgent = context.userAgent;
101
  }
102
  if (typeof context.errors === 'number') {
103
    session.errors = context.errors;
104
  }
105
  if (context.status) {
106
    session.status = context.status;
107
  }
108
}
109
110
/**
111
 * Closes a session by setting its status and updating the session object with it.
112
 * Internally calls `updateSession` to update the passed session object.
113
 *
114
 * Note that this function mutates the passed session (@see updateSession for explanation).
115
 *
116
 * @param session the `Session` object to be closed
117
 * @param status the `SessionStatus` with which the session was closed. If you don't pass a status,
118
 *               this function will keep the previously set status, unless it was `'ok'` in which case
119
 *               it is changed to `'exited'`.
120
 */
121
function closeSession(session, status) {
122
  let context = {};
123
  if (status) {
124
    context = { status };
125
  } else if (session.status === 'ok') {
126
    context = { status: 'exited' };
127
  }
128
129
  updateSession(session, context);
130
}
131
132
/**
133
 * Serializes a passed session object to a JSON object with a slightly different structure.
134
 * This is necessary because the Sentry backend requires a slightly different schema of a session
135
 * than the one the JS SDKs use internally.
136
 *
137
 * @param session the session to be converted
138
 *
139
 * @returns a JSON object of the passed session
140
 */
141
function sessionToJSON(session) {
142
  return {
143
    sid: `${session.sid}`,
144
    init: session.init,
145
    // Make sure that sec is converted to ms for date constructor
146
    started: new Date(session.started * 1000).toISOString(),
147
    timestamp: new Date(session.timestamp * 1000).toISOString(),
148
    status: session.status,
149
    errors: session.errors,
150
    did: typeof session.did === 'number' || typeof session.did === 'string' ? `${session.did}` : undefined,
151
    duration: session.duration,
152
    abnormal_mechanism: session.abnormal_mechanism,
153
    attrs: {
154
      release: session.release,
155
      environment: session.environment,
156
      ip_address: session.ipAddress,
157
      user_agent: session.userAgent,
158
    },
159
  };
160
}
161
162
exports.closeSession = closeSession;
163
exports.makeSession = makeSession;
164
exports.updateSession = updateSession;
165
//# sourceMappingURL=session.js.map
166