@esri/arcgis-rest-basemap-sessions 1.0.0 → 4.8.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.
@@ -1,376 +1,420 @@
1
1
  /* @preserve
2
- * @esri/arcgis-rest-basemap-sessions - v1.0.0 - Apache-2.0
3
- * Copyright (c) 2017-2025 Esri, Inc.
4
- * Wed Jul 30 2025 12:24:38 GMT-0700 (Pacific Daylight Time)
2
+ * @esri/arcgis-rest-basemap-sessions - v4.8.0 - Apache-2.0
3
+ * Copyright (c) 2017-2026 Esri, Inc.
4
+ * Fri Jan 16 2026 01:29:33 GMT+0000 (Coordinated Universal Time)
5
5
  */
6
6
  (function (global, factory) {
7
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@esri/arcgis-rest-request')) :
8
- typeof define === 'function' && define.amd ? define(['exports', '@esri/arcgis-rest-request'], factory) :
9
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.arcgisRest = global.arcgisRest || {}, global.arcgisRest));
7
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@esri/arcgis-rest-request')) :
8
+ typeof define === 'function' && define.amd ? define(['exports', '@esri/arcgis-rest-request'], factory) :
9
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.arcgisRest = global.arcgisRest || {}, global.arcgisRest));
10
10
  })(this, (function (exports, arcgisRestRequest) { 'use strict';
11
11
 
12
- function mitt(n){return {all:n=n||new Map,on:function(t,e){var i=n.get(t);i?i.push(e):n.set(t,[e]);},off:function(t,e){var i=n.get(t);i&&(e?i.splice(i.indexOf(e)>>>0,1):n.set(t,[]));},emit:function(t,e){var i=n.get(t);i&&i.slice().map(function(n){n(e);}),(i=n.get("*"))&&i.slice().map(function(n){n(t,e);});}}}
12
+ function mitt(n){return {all:n=n||new Map,on:function(t,e){var i=n.get(t);i?i.push(e):n.set(t,[e]);},off:function(t,e){var i=n.get(t);i&&(e?i.splice(i.indexOf(e)>>>0,1):n.set(t,[]));},emit:function(t,e){var i=n.get(t);i&&i.slice().map(function(n){n(e);}),(i=n.get("*"))&&i.slice().map(function(n){n(t,e);});}}}
13
13
 
14
- const DEFAULT_START_BASEMAP_STYLE_SESSION_URL = "https://basemapstyles-api.arcgis.com/arcgis/rest/services/styles/v2/sessions/start";
15
- const DEFAULT_SAFETY_MARGIN = 5 * 60; // Default to 5 minutes in seconds
16
- const DEFAULT_CHECK_EXPIRATION_INTERVAL = 10; // Default to 10 seconds
17
- const DEFAULT_DURATION = 12 * 60 * 60; // Default to 12 hours in seconds
14
+ const DEFAULT_START_BASEMAP_STYLE_SESSION_URL = "https://basemapstyles-api.arcgis.com/arcgis/rest/services/styles/v2/sessions/start";
15
+ const DEFAULT_SAFETY_MARGIN = 5 * 60; // Default to 5 minutes in seconds
16
+ const DEFAULT_CHECK_EXPIRATION_INTERVAL = 10; // Default to 10 seconds
17
+ const DEFAULT_DURATION = 12 * 60 * 60; // Default to 12 hours in seconds
18
18
 
19
- function startNewSession({ startSessionUrl, authentication, styleFamily = "arcgis", duration = DEFAULT_DURATION }) {
20
- return arcgisRestRequest.request(startSessionUrl, {
21
- httpMethod: "GET",
22
- authentication: authentication,
23
- params: { styleFamily, durationSeconds: duration }
24
- });
25
- }
19
+ function startNewSession({ startSessionUrl, authentication, styleFamily = "arcgis", duration = DEFAULT_DURATION }) {
20
+ return arcgisRestRequest.request(startSessionUrl, {
21
+ httpMethod: "GET",
22
+ authentication: authentication,
23
+ params: { styleFamily, durationSeconds: duration }
24
+ });
25
+ }
26
26
 
27
- function determineSafetyMargin(duration, safetyMargin) {
28
- if (safetyMargin) {
29
- return safetyMargin;
30
- }
31
- // common cases are
32
- // duration is 60 seconds, this will return a 1 second safety margin
33
- // duration is 43200 seconds, this will return a 300 second (5 minutes) safety margin
34
- return Math.min(Math.max(duration / 100, 1), DEFAULT_SAFETY_MARGIN);
35
- }
27
+ function determineSafetyMargin(duration, safetyMargin) {
28
+ if (safetyMargin) {
29
+ return safetyMargin;
30
+ }
31
+ // common cases are
32
+ // duration is 60 seconds, this will return a 1 second safety margin
33
+ // duration is 43200 seconds, this will return a 300 second (5 minutes) safety margin
34
+ return Math.min(Math.max(duration / 100, 1), DEFAULT_SAFETY_MARGIN);
35
+ }
36
36
 
37
- /**
38
- * The base class for all basemap sessions. This class implements the {@linkcode IAuthenticationManager} interface and provides methods to start, refresh, and check the expiration of a session.
39
- * This is not intendet to be used directly, but instead is extended by other classes such as {@linkcode BasemapStyleSession} and {@linkcode StaticBasemapTilesSession}.
40
- *
41
- * @abstract
42
- * @implements {IAuthenticationManager}
43
- */
44
- class BaseSession {
45
- /**
46
- * Creates a new instance of the BaseSession class. Generally you should not create an instance of this class directly, but instead use the static methods to start a session or deserialize a session.
47
- *
48
- * You may need to create an instance of this class directly if you are not using the built in deserialize method.
49
- *
50
- * @param params - The parameters for the session.
51
- * @param params.startSessionUrl - The URL to start the session.
52
- * @param params.token - The token for the session.
53
- * @param params.styleFamily - The style family of the session.
54
- * @param params.authentication - The authentication manager or token used for the session.
55
- * @param params.expires - The expiration date of the session.
56
- * @param params.startTime - The start time of the session.
57
- * @param params.endTime - The end time of the session.
58
- * @param params.safetyMargin - The safety margin in milliseconds.
59
- * @param params.duration - Indicates if this is a test session.
60
- */
61
- constructor(params) {
62
- /**
63
- * The ID of the timer used to check the expiration time of the session.
64
- */
65
- this.expirationTimerId = null;
66
- /**
67
- * A handler that is used to automatically refresh the session when it expires.
68
- */
69
- this.autoRefreshHandler = null;
70
- this.startSessionUrl = params.startSessionUrl;
71
- this.token = params.token;
72
- this.styleFamily = params.styleFamily || "arcgis";
73
- this.authentication = params.authentication;
74
- this.duration = params.duration || DEFAULT_DURATION;
75
- this.startTime = params.startTime;
76
- this.endTime = params.endTime;
77
- this.expires = params.expires;
78
- this.safetyMargin = params.safetyMargin;
79
- this.expirationCheckInterval =
80
- Math.min(this.duration / 100, DEFAULT_CHECK_EXPIRATION_INTERVAL) * 1000;
81
- this.emitter = mitt();
82
- }
83
- /**
84
- * Checks if the session is expired. If it is expired, it emits an "expired" event. The event will fire **before** the method returns true.
85
- *
86
- * @returns {boolean} - Returns true if the session is expired, otherwise false.
87
- */
88
- isSessionExpired() {
89
- if (this.isExpired) {
90
- this.emitter.emit("expired", {
91
- token: this.token,
92
- startTime: this.startTime,
93
- endTime: this.endTime,
94
- expires: this.expires
95
- });
96
- }
97
- return this.isExpired;
98
- }
99
- /**
100
- * Starts checking the expiration time of the session. This will check the expiration time immediately and then on an interval.
101
- * If the session is expired, it will emit an "expired" event.
102
- */
103
- startCheckingExpirationTime() {
104
- const check = () => {
105
- this.isSessionExpired();
106
- };
107
- if (!this.expirationTimerId) {
108
- this.expirationTimerId = setInterval(check,
109
- // check every 10 seconds or 1/100th of the duration, whichever is smaller
110
- this.expirationCheckInterval); // check immediatly then on an interval
111
- }
112
- setTimeout(() => {
113
- check(); // check immediately after starting the interval
114
- }, 10);
115
- return this.expirationTimerId; // return the timer ID so it can be stopped later
116
- }
117
- /**
118
- * Stops checking the expiration time of the session. This will clear the interval that was set by {@linkcode BaseSession.startCheckingExpirationTime}.
119
- */
120
- stopCheckingExpirationTime() {
121
- if (this.expirationTimerId) {
122
- clearInterval(this.expirationTimerId);
123
- this.expirationTimerId = null;
124
- }
125
- }
126
- /**
127
- * Indicates if the session is currently checking for expiration time.
128
- *
129
- * @returns {boolean} - Returns true if the session is checking for expiration time, otherwise false.
130
- */
131
- get checkingExpirationTime() {
132
- return !!this.expirationTimerId;
133
- }
134
- /**
135
- * Starts a new session using the provided parameters and returns an instance of the session class.
136
- *
137
- * @param params - The parameters for starting the session.
138
- * @param SessionClass - The class to use for the session.
139
- * @returns A promise that resolves to an instance of the session class.
140
- */
141
- static async startSession({ startSessionUrl, styleFamily = "arcgis", authentication, safetyMargin, duration = DEFAULT_DURATION, autoRefresh = true }, SessionClass) {
142
- const sessionResponse = await startNewSession({
143
- startSessionUrl,
144
- styleFamily,
145
- authentication,
146
- duration
147
- });
148
- const actualSafetyMargin = determineSafetyMargin(duration, safetyMargin);
149
- const session = new SessionClass({
150
- startSessionUrl: startSessionUrl,
151
- token: sessionResponse.sessionToken,
152
- styleFamily,
153
- authentication,
154
- safetyMargin: actualSafetyMargin,
155
- expires: new Date(sessionResponse.endTime - actualSafetyMargin * 1000),
156
- startTime: new Date(sessionResponse.startTime),
157
- endTime: new Date(sessionResponse.endTime),
158
- duration
159
- });
160
- session.startCheckingExpirationTime();
161
- if (autoRefresh) {
162
- session.startAutoRefresh();
163
- }
164
- return session;
165
- }
166
- /**
167
- * Checks if the session is expired.
168
- *
169
- */
170
- get isExpired() {
171
- return this.expires < new Date();
172
- }
173
- /**
174
- * Gets the session token. If the session is expired, it will refresh the credentials and return the new token.
175
- *
176
- * @returns A promise that resolves to the session token.
177
- */
178
- getToken() {
179
- if (this.isExpired) {
180
- return this.refreshCredentials().then(() => this.token);
181
- }
182
- return Promise.resolve(this.token);
183
- }
184
- /**
185
- * Indicates if the session can be refreshed. This is always true for this class.
186
- *
187
- * @returns {boolean} - Always returns true.
188
- */
189
- get canRefresh() {
190
- return true;
191
- }
192
- /**
193
- * Indicates if the session is set to automatically refresh when it expires.
194
- *
195
- * @returns {boolean} - Returns true if auto-refresh is enabled, otherwise false.
196
- */
197
- get autoRefresh() {
198
- return !!this.autoRefreshHandler && !!this.expirationTimerId;
199
- }
200
- /**
201
- * Refreshes the session credentials by starting a new session.
202
- * This will emit a "refreshed" event with the previous and current session details.
203
- *
204
- * @returns A promise that resolves to the current instance of the session.
205
- */
206
- async refreshCredentials() {
207
- // @TODO switch this to structured clone when we upgrade to Node 20+ types so we don't have to parse the dates later
208
- const previous = JSON.parse(JSON.stringify({
209
- token: this.token,
210
- startTime: this.startTime,
211
- endTime: this.endTime,
212
- expires: this.expires
213
- }));
214
- try {
215
- const newSession = await startNewSession({
216
- startSessionUrl: this.startSessionUrl,
217
- styleFamily: this.styleFamily,
218
- authentication: this.authentication,
219
- duration: this.duration
220
- });
221
- this.setToken(newSession.sessionToken);
222
- this.setStartTime(new Date(newSession.startTime));
223
- this.setEndTime(new Date(newSession.endTime));
224
- this.setExpires(new Date(newSession.endTime - this.safetyMargin * 1000));
225
- this.emitter.emit("refreshed", {
226
- previous: {
227
- token: previous.token,
228
- startTime: new Date(previous.startTime),
229
- endTime: new Date(previous.endTime),
230
- expires: new Date(previous.expires)
231
- },
232
- current: {
233
- token: this.token,
234
- startTime: this.startTime,
235
- endTime: this.endTime,
236
- expires: this.expires
237
- }
238
- });
239
- }
240
- catch (error) {
241
- this.emitter.emit("error", error);
242
- throw error;
243
- }
244
- return this;
245
- }
246
- /**
247
- * Enables auto-refresh for the session. This will automatically refresh the session when it expires.
248
- * It will also start checking the expiration time of the session if it is not already started via {@linkcode BaseSession.startCheckingExpirationTime}.
249
- */
250
- startAutoRefresh() {
251
- if (!this.expirationTimerId) {
252
- this.startCheckingExpirationTime();
253
- }
254
- this.autoRefreshHandler = () => {
255
- this.refreshCredentials().catch((error) => {
256
- this.emitter.emit("error", error);
257
- });
258
- };
259
- this.on("expired", this.autoRefreshHandler);
260
- }
261
- /**
262
- * Disables auto-refresh for the session. This will stop automatically refreshing the session when it expires.
263
- * This will **not** stop checking the expiration time of the session. If you want to stop automated expiration
264
- * checking, call {@linkcode BaseSession.stopCheckingExpirationTime} after calling this method.
265
- */
266
- stopAutoRefresh() {
267
- if (this.autoRefreshHandler) {
268
- this.off("expired", this.autoRefreshHandler);
269
- this.autoRefreshHandler = null;
270
- }
271
- }
272
- on(eventName, handler) {
273
- this.emitter.on(eventName, handler);
274
- this.isSessionExpired(); // check if the session is expired immediately after adding the handler
275
- }
276
- once(eventName, handler) {
277
- const fn = (e) => {
278
- this.emitter.off(eventName, fn);
279
- handler(e);
280
- };
281
- this.emitter.on(eventName, fn);
282
- }
283
- off(eventName, handler) {
284
- this.emitter.off(eventName, handler);
285
- }
286
- /**
287
- * These private methods are used to set the internal state of the session.
288
- */
289
- setToken(token) {
290
- this.token = token;
291
- }
292
- setStartTime(startTime) {
293
- this.startTime = startTime;
294
- }
295
- setEndTime(endTime) {
296
- this.endTime = endTime;
297
- }
298
- setExpires(expires) {
299
- this.expires = expires;
300
- }
301
- }
302
- // the static methods for event handlers are used to provide doc via typedoc and do not need to be tested.
303
- /* istanbul ignore next -- @preserve */
304
- /**
305
- * Event handler for when an error occurs during session management.
306
- */
307
- BaseSession.error = function error(e) { }; // eslint-disable-line @typescript-eslint/no-empty-function
308
- // the static methods for event handlers are used to provide doc via typedoc and do not need to be tested.
309
- /* istanbul ignore next -- @preserve */
310
- /**
311
- * Event handler for when a session expires and the `token` it no longer valid.
312
- *
313
- * @event expired
314
- * @param e - The parameters for the expired event.
315
- * @param e.token - The session token that expired.
316
- * @param e.startTime - The start time of the session.
317
- * @param e.endTime - The end time of the session.
318
- * @param e.expires - The expiration time of the session.
319
- */
320
- BaseSession.expired = function expired(e) { }; // eslint-disable-line @typescript-eslint/no-empty-function
321
- // the static methods for event handlers are used to provide doc via typedoc and do not need to be tested.
322
- /* istanbul ignore next -- @preserve */
323
- /**
324
- * Event handler for when a session refreshes and a new `token` is available.
325
- *
326
- * @event refreshed
327
- * @param e. - The parameters for the refreshed event.
328
- * @param e.previous - The previous session details.
329
- * @param e.previous.token - The previous session token.
330
- * @param e.previous.startTime - The start time of the previous session.
331
- * @param e.previous.endTime - The end time of the previous session.
332
- * @param e.previous.expires - The expiration time of the previous session.
333
- * @param e.current - The current session details.
334
- * @param e.current.token - The current session token.
335
- * @param e.current.startTime - The start time of the current token.
336
- * @param e.current.endTime - The end time of the current session.
337
- * @param e.current.expires - The expiration time of the current token.
338
- */
339
- BaseSession.refreshed = function refreshed(e) { }; // eslint-disable-line @typescript-eslint/no-empty-function
37
+ /**
38
+ * The base class for all basemap sessions. This class implements the {@linkcode @esri/arcgis-rest-request!IAuthenticationManager} interface and provides methods to start, refresh, and check the expiration of a session.
39
+ * This is not intended to be used directly, but instead is extended by other classes such as {@linkcode BasemapStyleSession} .
40
+ *
41
+ * @abstract
42
+ */
43
+ class BaseSession {
44
+ /**
45
+ * Creates a new instance of the BaseSession class. Generally you should not create an instance of this class directly, but instead use the static methods to start a session or deserialize a session.
46
+ *
47
+ * You may need to create an instance of this class directly if you are not using the built in deserialize method.
48
+ *
49
+ * @param params - The parameters for the session.
50
+ * @param params.startSessionUrl - The URL to start the session.
51
+ * @param params.token - The token for the session.
52
+ * @param params.styleFamily - The style family of the session.
53
+ * @param params.authentication - The authentication manager or token used for the session.
54
+ * @param params.expires - The expiration date of the session.
55
+ * @param params.startTime - The start time of the session.
56
+ * @param params.endTime - The end time of the session.
57
+ * @param params.safetyMargin - The safety margin in milliseconds.
58
+ * @param params.duration - Indicates if this is a test session.
59
+ */
60
+ constructor(params) {
61
+ /**
62
+ * The ID of the timer used to check the expiration time of the session.
63
+ */
64
+ this.expirationTimerId = null;
65
+ /**
66
+ * A pending session that is being refreshed. This is used to prevent multiple refreshes from happening at the same time.
67
+ */
68
+ this.pendingSession = null;
69
+ /**
70
+ * A handler that is used to automatically refresh the session when it expires.
71
+ */
72
+ this.autoRefreshHandler = null;
73
+ this.startSessionUrl = params.startSessionUrl;
74
+ this.token = params.token;
75
+ this.styleFamily = params.styleFamily || "arcgis";
76
+ this.authentication = params.authentication;
77
+ this.duration = params.duration || DEFAULT_DURATION;
78
+ this.startTime = params.startTime;
79
+ this.endTime = params.endTime;
80
+ this.expires = params.expires;
81
+ this.safetyMargin = params.safetyMargin;
82
+ this.expirationCheckInterval =
83
+ Math.min(this.duration / 100, DEFAULT_CHECK_EXPIRATION_INTERVAL) * 1000;
84
+ this.emitter = mitt();
85
+ }
86
+ /**
87
+ * Checks if the session is expired. If it is expired, it emits an "expired" event and disables expiration time checking. The event will fire **before** the method returns true.
88
+ *
89
+ * @returns {boolean} - Returns true if the session is expired, otherwise false.
90
+ */
91
+ isSessionExpired() {
92
+ if (this.isExpired) {
93
+ this.disableCheckingExpirationTime();
94
+ this.emitter.emit("expired", {
95
+ token: this.token,
96
+ startTime: this.startTime,
97
+ endTime: this.endTime,
98
+ expires: this.expires
99
+ });
100
+ }
101
+ return this.isExpired;
102
+ }
103
+ /**
104
+ * Starts checking the expiration time of the session. This will check the expiration time immediately and then on an interval.
105
+ * If the session is expired, it will emit an "expired" event.
106
+ */
107
+ enableCheckingExpirationTime() {
108
+ const check = () => {
109
+ this.isSessionExpired();
110
+ };
111
+ if (!this.expirationTimerId) {
112
+ this.expirationTimerId = setInterval(check,
113
+ // check every 10 seconds or 1/100th of the duration, whichever is smaller
114
+ this.expirationCheckInterval); // check immediately then on an interval
115
+ }
116
+ setTimeout(() => {
117
+ check(); // check immediately after starting the interval
118
+ }, 10);
119
+ return this.expirationTimerId; // return the timer ID so it can be stopped later
120
+ }
121
+ /**
122
+ * Stops checking the expiration time of the session. This will clear the `setInterval()` that was started by {@linkcode BaseSession.enableCheckingExpirationTime}.
123
+ */
124
+ disableCheckingExpirationTime() {
125
+ if (this.expirationTimerId) {
126
+ clearInterval(this.expirationTimerId);
127
+ this.expirationTimerId = null;
128
+ }
129
+ }
130
+ /**
131
+ * Starts a new session using the provided parameters and returns an instance of the session class.
132
+ *
133
+ * @param params - The parameters for starting the session.
134
+ * @param SessionClass - The class to use for the session.
135
+ * @returns A promise that resolves to an instance of the session class.
136
+ */
137
+ static async startSession({ startSessionUrl, styleFamily = "arcgis", authentication, safetyMargin, duration = DEFAULT_DURATION, autoRefresh = false }, SessionClass) {
138
+ if (duration < 10) {
139
+ throw new Error("Session duration must be at least 10 seconds.");
140
+ }
141
+ if (duration > 43200) {
142
+ throw new Error("Session duration cannot exceed 12 hours (43200 seconds).");
143
+ }
144
+ const sessionResponse = await startNewSession({
145
+ startSessionUrl,
146
+ styleFamily,
147
+ authentication,
148
+ duration
149
+ });
150
+ const actualSafetyMargin = determineSafetyMargin(duration, safetyMargin);
151
+ const session = new SessionClass({
152
+ startSessionUrl: startSessionUrl,
153
+ token: sessionResponse.sessionToken,
154
+ styleFamily,
155
+ authentication,
156
+ safetyMargin: actualSafetyMargin,
157
+ expires: new Date(sessionResponse.endTime - actualSafetyMargin * 1000),
158
+ startTime: new Date(sessionResponse.startTime),
159
+ endTime: new Date(sessionResponse.endTime),
160
+ duration
161
+ });
162
+ session.enableCheckingExpirationTime();
163
+ if (autoRefresh) {
164
+ session.enableAutoRefresh();
165
+ }
166
+ return session;
167
+ }
168
+ /**
169
+ * Indicates if the session is currently checking for expiration time.
170
+ *
171
+ * @returns {boolean} - Returns true if the session is checking for expiration time, otherwise false.
172
+ */
173
+ get checkingExpirationTime() {
174
+ return !!this.expirationTimerId;
175
+ }
176
+ /**
177
+ * Returns the number of seconds until the session is no longer valid rounded down. If the session is expired, it will return 0.
178
+ */
179
+ get secondsUntilExpiration() {
180
+ return Math.floor(this.millisecondsUntilExpiration / 1000);
181
+ }
182
+ /**
183
+ * Returns the number of milliseconds until the session token is no longer valid. If the session is expired, it will return 0.
184
+ */
185
+ get millisecondsUntilExpiration() {
186
+ if (this.isExpired) {
187
+ return 0;
188
+ }
189
+ const now = new Date();
190
+ const millisecondsLeft = this.endTime.getTime() - now.getTime();
191
+ return millisecondsLeft;
192
+ }
193
+ /**
194
+ * Checks if the session is expired.
195
+ *
196
+ */
197
+ get isExpired() {
198
+ return this.expires < new Date();
199
+ }
200
+ /**
201
+ * Gets the session token. If the session is expired, it will refresh the credentials and return the new token.
202
+ *
203
+ * @returns A promise that resolves to the session token.
204
+ */
205
+ getToken() {
206
+ if (this.isExpired) {
207
+ return this.refreshCredentials().then(() => this.token);
208
+ }
209
+ return Promise.resolve(this.token);
210
+ }
211
+ /**
212
+ * Indicates if the session can be refreshed. This is always true for this basemap sessions.
213
+ *
214
+ * @returns {boolean} - Always returns true.
215
+ */
216
+ get canRefresh() {
217
+ return true;
218
+ }
219
+ /**
220
+ * Indicates if the session is set to automatically refresh when it expires.
221
+ *
222
+ * @returns {boolean} - Returns true if auto-refresh is enabled, otherwise false.
223
+ */
224
+ get autoRefresh() {
225
+ return !!this.autoRefreshHandler && !!this.expirationTimerId;
226
+ }
227
+ /**
228
+ * Refreshes the session credentials by starting a new session.
229
+ * This will emit a "refreshed" event with the previous and current session details.
230
+ *
231
+ * @returns A promise that resolves to the current instance of the session.
232
+ */
233
+ async refreshCredentials() {
234
+ if (this.pendingSession) {
235
+ // if there is a pending session, wait for it to resolve
236
+ await this.pendingSession;
237
+ return this;
238
+ }
239
+ // @TODO switch this to structured clone when we upgrade to Node 20+ types so we don't have to parse the dates later
240
+ const previous = JSON.parse(JSON.stringify({
241
+ token: this.token,
242
+ startTime: this.startTime,
243
+ endTime: this.endTime,
244
+ expires: this.expires
245
+ }));
246
+ try {
247
+ this.pendingSession = startNewSession({
248
+ startSessionUrl: this.startSessionUrl,
249
+ styleFamily: this.styleFamily,
250
+ authentication: this.authentication,
251
+ duration: this.duration
252
+ });
253
+ const newSession = await this.pendingSession;
254
+ this.pendingSession = null; // reset the pending session
255
+ this.setToken(newSession.sessionToken);
256
+ this.setStartTime(new Date(newSession.startTime));
257
+ this.setEndTime(new Date(newSession.endTime));
258
+ this.setExpires(new Date(newSession.endTime - this.safetyMargin * 1000));
259
+ this.enableCheckingExpirationTime(); // restart checking expiration time after refreshing credentials
260
+ this.emitter.emit("refreshed", {
261
+ previous: {
262
+ token: previous.token,
263
+ startTime: new Date(previous.startTime),
264
+ endTime: new Date(previous.endTime),
265
+ expires: new Date(previous.expires)
266
+ },
267
+ current: {
268
+ token: this.token,
269
+ startTime: this.startTime,
270
+ endTime: this.endTime,
271
+ expires: this.expires
272
+ }
273
+ });
274
+ }
275
+ catch (error) {
276
+ this.emitter.emit("error", error);
277
+ throw error;
278
+ }
279
+ return this;
280
+ }
281
+ /**
282
+ * Enables auto-refresh for the session. This will automatically refresh the session when it expires.
283
+ * It will also start checking the expiration time of the session if it is not already started via {@linkcode BaseSession.enableCheckingExpirationTime}.
284
+ */
285
+ enableAutoRefresh() {
286
+ if (!this.expirationTimerId) {
287
+ this.enableCheckingExpirationTime();
288
+ }
289
+ this.autoRefreshHandler = () => {
290
+ this.refreshCredentials().catch((error) => {
291
+ this.emitter.emit("error", error);
292
+ });
293
+ };
294
+ this.on("expired", this.autoRefreshHandler);
295
+ }
296
+ /**
297
+ * Disables auto-refresh for the session. This will stop automatically refreshing the session when it expires.
298
+ * This will **not** stop checking the expiration time of the session. If you want to stop automated expiration
299
+ * checking, call {@linkcode BaseSession.disableCheckingExpirationTime} after calling this method.
300
+ */
301
+ disableAutoRefresh() {
302
+ if (this.autoRefreshHandler) {
303
+ this.off("expired", this.autoRefreshHandler);
304
+ this.autoRefreshHandler = null;
305
+ }
306
+ }
307
+ /**
308
+ * Removes all event listeners and disables auto-refresh and expiration time checking. This is useful for cleaning up the session when it is no longer needed or replaced with a new session.
309
+ */
310
+ destroy() {
311
+ this.disableAutoRefresh();
312
+ this.disableCheckingExpirationTime();
313
+ this.emitter.off("expired");
314
+ this.emitter.off("refreshed");
315
+ this.emitter.off("error");
316
+ this.emitter.off("*");
317
+ }
318
+ on(event, handler) {
319
+ this.emitter.on(event, handler);
320
+ this.isSessionExpired(); // check if the session is expired immediately after adding the handler
321
+ }
322
+ once(event, handler) {
323
+ const fn = (e) => {
324
+ this.emitter.off(event, fn);
325
+ handler(e);
326
+ };
327
+ this.emitter.on(event, fn);
328
+ }
329
+ off(event, handler) {
330
+ this.emitter.off(event, handler);
331
+ }
332
+ /**
333
+ * These private methods are used to set the internal state of the session.
334
+ */
335
+ setToken(token) {
336
+ this.token = token;
337
+ }
338
+ setStartTime(startTime) {
339
+ this.startTime = startTime;
340
+ }
341
+ setEndTime(endTime) {
342
+ this.endTime = endTime;
343
+ }
344
+ setExpires(expires) {
345
+ this.expires = expires;
346
+ }
347
+ }
348
+ // the static methods for event handlers are used to provide doc via typedoc and do not need to be tested.
349
+ /* istanbul ignore next -- @preserve */
350
+ /**
351
+ * Event handler for when an error occurs during session management.
352
+ */
353
+ BaseSession.error = function error(e) { };
354
+ // the static methods for event handlers are used to provide doc via typedoc and do not need to be tested.
355
+ /* istanbul ignore next -- @preserve */
356
+ /**
357
+ * Event handler for when the current session expires and the session token it no longer valid. This event will only fire if {@linkcode BaseSession.checkingExpirationTime}
358
+ * is `true` which is the default. Once this event fires, {@linkcode BaseSession.checkingExpirationTime} will be set to `false` until the session is refreshed with
359
+ * {@linkcode BaseSession.refreshCredentials}.
360
+ *
361
+ * @event expired
362
+ * @param e.token - The session token that expired.
363
+ * @param e.startTime - The start time of the session.
364
+ * @param e.endTime - The end time of the session.
365
+ * @param e.expires - The expiration time of the session.
366
+ */
367
+ BaseSession.expired = function expired(e) { };
368
+ // the static methods for event handlers are used to provide doc via typedoc and do not need to be tested.
369
+ /* istanbul ignore next -- @preserve */
370
+ /**
371
+ * Event handler for when a session refreshes and a new `token` is available.
372
+ *
373
+ * @event refreshed
374
+ * @param e.previous - The previous session details.
375
+ * @param e.previous.token - The previous session token.
376
+ * @param e.previous.startTime - The start time of the previous session.
377
+ * @param e.previous.endTime - The end time of the previous session.
378
+ * @param e.previous.expires - The expiration time of the previous session.
379
+ * @param e.current - The current session details.
380
+ * @param e.current.token - The current session token.
381
+ * @param e.current.startTime - The start time of the current token.
382
+ * @param e.current.endTime - The end time of the current session.
383
+ * @param e.current.expires - The expiration time of the current token.
384
+ */
385
+ BaseSession.refreshed = function refreshed(e) { };
340
386
 
341
- /**
342
- * `BasemapStyleSession` is a class that extends {@linkcode BaseSession} to manage sessions
343
- * for basemap styles. It provides methods to {@linkcode BasemapStyleSession.start} a new session
344
- * which should be used instead of constructing a new instance directly.
345
- *
346
- * @class BasemapStyleSession
347
- * @extends BaseSession
348
- */
349
- class BasemapStyleSession extends BaseSession {
350
- /**
351
- * Creates an instance of `BasemapStyleSession`. Constructing `BasemapStyleSession` directly is discouraged.
352
- * Instead, use the static method {@linkcode BasemapStyleSession.start} to start a new session.
353
- */
354
- constructor(params) {
355
- super(params);
356
- }
357
- /**
358
- * Starts a new basemap style session.
359
- */
360
- static async start(params) {
361
- return BaseSession.startSession(Object.assign(Object.assign({}, params), { startSessionUrl: (params === null || params === void 0 ? void 0 : params.startSessionUrl) || DEFAULT_START_BASEMAP_STYLE_SESSION_URL }), BasemapStyleSession);
362
- }
363
- }
387
+ /**
388
+ * `BasemapStyleSession` is a class that extends {@linkcode BaseSession} to manage sessions
389
+ * for basemap styles. It provides methods to {@linkcode BasemapStyleSession.start} a new session
390
+ * which should be used instead of constructing a new instance directly.
391
+ *
392
+ * @class BasemapStyleSession
393
+ * @extends BaseSession
394
+ */
395
+ class BasemapStyleSession extends BaseSession {
396
+ /**
397
+ * Creates an instance of `BasemapStyleSession`. Constructing `BasemapStyleSession` directly is discouraged.
398
+ * Instead, use the static method {@linkcode BasemapStyleSession.start} to start a new session.
399
+ */
400
+ constructor(params) {
401
+ super(params);
402
+ }
403
+ /**
404
+ * Starts a new basemap style session.
405
+ */
406
+ static async start(params) {
407
+ return BaseSession.startSession(Object.assign(Object.assign({}, params), { startSessionUrl: (params === null || params === void 0 ? void 0 : params.startSessionUrl) || DEFAULT_START_BASEMAP_STYLE_SESSION_URL }), BasemapStyleSession);
408
+ }
409
+ }
364
410
 
365
- exports.BaseSession = BaseSession;
366
- exports.BasemapStyleSession = BasemapStyleSession;
367
- exports.DEFAULT_CHECK_EXPIRATION_INTERVAL = DEFAULT_CHECK_EXPIRATION_INTERVAL;
368
- exports.DEFAULT_DURATION = DEFAULT_DURATION;
369
- exports.DEFAULT_SAFETY_MARGIN = DEFAULT_SAFETY_MARGIN;
370
- exports.DEFAULT_START_BASEMAP_STYLE_SESSION_URL = DEFAULT_START_BASEMAP_STYLE_SESSION_URL;
371
- exports.startNewSession = startNewSession;
372
-
373
- Object.defineProperty(exports, '__esModule', { value: true });
411
+ exports.BaseSession = BaseSession;
412
+ exports.BasemapStyleSession = BasemapStyleSession;
413
+ exports.DEFAULT_CHECK_EXPIRATION_INTERVAL = DEFAULT_CHECK_EXPIRATION_INTERVAL;
414
+ exports.DEFAULT_DURATION = DEFAULT_DURATION;
415
+ exports.DEFAULT_SAFETY_MARGIN = DEFAULT_SAFETY_MARGIN;
416
+ exports.DEFAULT_START_BASEMAP_STYLE_SESSION_URL = DEFAULT_START_BASEMAP_STYLE_SESSION_URL;
417
+ exports.startNewSession = startNewSession;
374
418
 
375
419
  }));
376
420
  //# sourceMappingURL=basemap-sessions.umd.js.map