epicenter-libs 3.33.0 → 3.34.1

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.
Files changed (76) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/browser/epicenter.js +105 -2
  3. package/dist/browser/epicenter.js.map +1 -1
  4. package/dist/cjs/epicenter.js +105 -2
  5. package/dist/cjs/epicenter.js.map +1 -1
  6. package/dist/epicenter.js +105 -2
  7. package/dist/epicenter.js.map +1 -1
  8. package/dist/epicenter.min.js +1 -1
  9. package/dist/epicenter.min.js.map +1 -1
  10. package/dist/module/epicenter.js +105 -2
  11. package/dist/module/epicenter.js.map +1 -1
  12. package/dist/types/adapters/chat.d.ts +63 -0
  13. package/package.json +1 -1
  14. package/src/adapters/chat.ts +95 -0
  15. package/src/utils/identification.ts +4 -0
  16. package/dist/test/_virtual/runtime.js +0 -3
  17. package/dist/test/_virtual/runtime2.js +0 -3
  18. package/dist/test/adapters/account.js +0 -169
  19. package/dist/test/adapters/admin.js +0 -53
  20. package/dist/test/adapters/asset.js +0 -425
  21. package/dist/test/adapters/authentication.js +0 -349
  22. package/dist/test/adapters/channel.js +0 -201
  23. package/dist/test/adapters/chat.js +0 -199
  24. package/dist/test/adapters/cometd.js +0 -514
  25. package/dist/test/adapters/consensus.js +0 -484
  26. package/dist/test/adapters/daily.js +0 -244
  27. package/dist/test/adapters/email.js +0 -179
  28. package/dist/test/adapters/episode.js +0 -175
  29. package/dist/test/adapters/group.js +0 -655
  30. package/dist/test/adapters/leaderboard.js +0 -162
  31. package/dist/test/adapters/matchmaker.js +0 -159
  32. package/dist/test/adapters/presence.js +0 -85
  33. package/dist/test/adapters/project.js +0 -94
  34. package/dist/test/adapters/recaptcha.js +0 -24
  35. package/dist/test/adapters/run.js +0 -1008
  36. package/dist/test/adapters/somebody.js +0 -154
  37. package/dist/test/adapters/task.js +0 -192
  38. package/dist/test/adapters/time.js +0 -28
  39. package/dist/test/adapters/user.js +0 -105
  40. package/dist/test/adapters/vault.js +0 -403
  41. package/dist/test/adapters/video.js +0 -249
  42. package/dist/test/adapters/vonage.js +0 -130
  43. package/dist/test/adapters/wallet.js +0 -130
  44. package/dist/test/adapters/world.js +0 -507
  45. package/dist/test/apis/video.js +0 -294
  46. package/dist/test/apis/vonage.js +0 -121
  47. package/dist/test/epicenter.js +0 -121
  48. package/dist/test/node_modules/@babel/runtime/helpers/esm/defineProperty.js +0 -12
  49. package/dist/test/node_modules/@babel/runtime/helpers/esm/toPrimitive.js +0 -14
  50. package/dist/test/node_modules/@babel/runtime/helpers/esm/toPropertyKey.js +0 -9
  51. package/dist/test/node_modules/@babel/runtime/helpers/esm/typeof.js +0 -11
  52. package/dist/test/node_modules/cometd/AckExtension.js +0 -91
  53. package/dist/test/node_modules/cometd/CallbackPollingTransport.js +0 -148
  54. package/dist/test/node_modules/cometd/Client.js +0 -2160
  55. package/dist/test/node_modules/cometd/Extension.js +0 -47
  56. package/dist/test/node_modules/cometd/LongPollingTransport.js +0 -135
  57. package/dist/test/node_modules/cometd/ReloadExtension.js +0 -214
  58. package/dist/test/node_modules/cometd/RequestTransport.js +0 -252
  59. package/dist/test/node_modules/cometd/Transport.js +0 -167
  60. package/dist/test/node_modules/cometd/TransportRegistry.js +0 -107
  61. package/dist/test/node_modules/cometd/WebSocketTransport.js +0 -384
  62. package/dist/test/node_modules/cometd/cometd.js +0 -9
  63. package/dist/test/node_modules/regenerator-runtime/runtime.js +0 -773
  64. package/dist/test/utilities.js +0 -17
  65. package/dist/test/utils/config.js +0 -189
  66. package/dist/test/utils/constants.js +0 -293
  67. package/dist/test/utils/cookies.js +0 -75
  68. package/dist/test/utils/error-manager.js +0 -57
  69. package/dist/test/utils/error.js +0 -12
  70. package/dist/test/utils/fault.js +0 -34
  71. package/dist/test/utils/filter-parser.js +0 -68
  72. package/dist/test/utils/helpers.js +0 -9
  73. package/dist/test/utils/identification.js +0 -161
  74. package/dist/test/utils/result.js +0 -20
  75. package/dist/test/utils/router.js +0 -551
  76. package/dist/test/utils/store.js +0 -79
@@ -1,349 +0,0 @@
1
- import '../utils/helpers.js';
2
- import '../utils/config.js';
3
- import identification from '../utils/identification.js';
4
- import '../utils/error-manager.js';
5
- import Router from '../utils/router.js';
6
- import cometdAdapter from './cometd.js';
7
-
8
- /**
9
- * Logs out of current Epicenter session. Also disconnects from CometD and removes user presence.
10
- * Priorities:
11
- * 1. Delete local session (even if 2 and 3 fail)
12
- * 2. Delete remote session (even if 3 fails)
13
- * 3. Other cleanup (disconnect CometD, delete presence)
14
- * Cleanup operations require authentication, so await cleanup before delete.
15
- * Base URL: DELETE `https://forio.com/api/v3/{ACCOUNT}/{PROJECT}/verification`
16
- *
17
- * @example
18
- * import { authAdapter } from 'epicenter-libs';
19
- * await authAdapter.logout();
20
- *
21
- * @param [verificationOptionals] Optional arguments; pass network call options overrides here.
22
- * @param [presenceOptionals] Optional arguments; pass network call options overrides here.
23
- * @returns promise that resolves when logout is complete
24
- */
25
- async function logout(verificationOptionals = {}, presenceOptionals = verificationOptionals) {
26
- var _identification$sessi;
27
- const cleanup = [cometdAdapter.disconnect()];
28
- const groupKey = identification === null || identification === void 0 || (_identification$sessi = identification.session) === null || _identification$sessi === void 0 ? void 0 : _identification$sessi.groupKey;
29
- if (groupKey) {
30
- cleanup.push(new Router().delete(`/presence/group/${groupKey}`, presenceOptionals));
31
- }
32
- await Promise.allSettled(cleanup);
33
- await new Router().delete('/verification', verificationOptionals).finally(() => identification.session = undefined);
34
- }
35
-
36
- /**
37
- * Retrieves the current session from the server
38
- * Base URL: GET `https://forio.com/api/v3/{ACCOUNT}/{PROJECT}/verification`
39
- *
40
- * @example
41
- * import { authAdapter } from 'epicenter-libs';
42
- * const session = await authAdapter.getSession();
43
- *
44
- * @param [optionals] Optional arguments; pass network call options overrides here.
45
- * @returns promise that resolves to the session object
46
- */
47
- async function getSession(optionals = {}) {
48
- const {
49
- body
50
- } = await new Router().get('/verification', optionals);
51
- identification.session = body;
52
- return body;
53
- }
54
-
55
- /**
56
- * Retrieves the session stored in memory
57
- *
58
- * @example
59
- * import { authAdapter } from 'epicenter-libs';
60
- * const session = authAdapter.getLocalSession();
61
- *
62
- * @returns the session object if it exists, undefined otherwise
63
- */
64
- function getLocalSession() {
65
- return identification.session;
66
- }
67
-
68
- /**
69
- * Stores a session in memory
70
- *
71
- * @example
72
- * import { authAdapter } from 'epicenter-libs';
73
- * authAdapter.setLocalSession(session);
74
- *
75
- * @param session The session object to store
76
- * @returns the stored session object
77
- */
78
- function setLocalSession(session) {
79
- return identification.session = session;
80
- }
81
-
82
- /**
83
- * Removes the session stored in memory and disconnects from CometD
84
- *
85
- * @example
86
- * import { authAdapter } from 'epicenter-libs';
87
- * await authAdapter.removeLocalSession();
88
- *
89
- * @returns promise that resolves when the session is removed and CometD is disconnected
90
- */
91
- async function removeLocalSession() {
92
- identification.session = undefined;
93
- await cometdAdapter.disconnect();
94
- }
95
-
96
- /**
97
- * Logs in a user or app and stores the session
98
- * Base URL: POST `https://forio.com/api/v3/{ACCOUNT}/{PROJECT}/authentication`
99
- *
100
- * @example
101
- * import { authAdapter } from 'epicenter-libs';
102
- * // User login
103
- * const session = await authAdapter.login({
104
- * handle: 'user@example.com',
105
- * password: 'myPassword',
106
- * groupKey: '00000165ad4e6a3cd22b993340b963820239',
107
- * });
108
- * // App login
109
- * const session = await authAdapter.login({
110
- * secretKey: 'my-secret-key',
111
- * });
112
- *
113
- * @param credentials User or app credentials
114
- * @param credentials.handle User handle (email or username)
115
- * @param credentials.password User password
116
- * @param [credentials.groupKey] Group key for user login
117
- * @param credentials.secretKey Secret key for app login
118
- * @param [optionals] Optional arguments; pass network call options overrides here. Special arguments specific to this method are listed below if they exist.
119
- * @param [optionals.objectType] Object type for authentication (defaults to 'user' or 'account' based on credentials)
120
- * @param [optionals.forcePathInclusion] Controls cookie path behavior: `true` forces project-specific path (even on custom domains), `false` forces root path (even for users/admins on Epicenter domain), `undefined` uses defaults (project-specific for users/admins on Epicenter domain, root for custom domains)
121
- * @returns promise that resolves to the session object
122
- */
123
- async function login(credentials, optionals = {}) {
124
- const {
125
- objectType,
126
- forcePathInclusion,
127
- ...routingOptions
128
- } = optionals;
129
- let payload;
130
- if (Object.prototype.hasOwnProperty.call(credentials, 'handle')) {
131
- const {
132
- handle,
133
- password,
134
- groupKey
135
- } = credentials;
136
- payload = {
137
- objectType: objectType !== null && objectType !== void 0 ? objectType : 'user',
138
- handle,
139
- password,
140
- groupKey: groupKey || undefined
141
- };
142
- }
143
- if (Object.prototype.hasOwnProperty.call(credentials, 'secretKey')) {
144
- const {
145
- secretKey
146
- } = credentials;
147
- payload = {
148
- objectType: objectType !== null && objectType !== void 0 ? objectType : 'account',
149
- secretKey
150
- };
151
- }
152
- const session = await new Router().post('/authentication', {
153
- inert: true,
154
- includeAuthorization: false,
155
- body: payload,
156
- ...routingOptions
157
- }).then(({
158
- body
159
- }) => body);
160
- await removeLocalSession();
161
- identification.setSessionWithOptions(session, forcePathInclusion);
162
- return session;
163
- }
164
-
165
- /**
166
- * Regenerates your Epicenter session with the appropriate context.
167
- * Base URL: PATCH `https://forio.com/api/v3/{ACCOUNT}/{PROJECT}/authentication`
168
- *
169
- * - For users: Updates session to the specified group context
170
- * - For admins: Updates session to the specified account/project context (uses platform's focus API)
171
- *
172
- * This is automatically called when switching between projects/groups if the session cookie
173
- * is scoped to a specific project path.
174
- *
175
- * Will fail if the user/admin does not already belong to the group/account.
176
- *
177
- * @example
178
- * import { authAdapter } from 'epicenter-libs';
179
- * // Changes the current user session to have a group context associated with the provided key
180
- * await authAdapter.regenerate('00000165ad4e6a3cd22b993340b963820239');
181
- * // Changes the current admin session to use the account context for the 'acme' account
182
- * await authAdapter.regenerate('acme', { objectType: 'admin' });
183
- *
184
- * @param groupOrAccount Group key or account name
185
- * @param [optionals] Optional arguments; pass network call options overrides here. Special arguments specific to this method are listed below if they exist.
186
- * @param [optionals.objectType] The object type to regenerate for (defaults to 'user')
187
- * @param [optionals.forcePathInclusion] Controls cookie path behavior: `true` forces project-specific path (even on custom domains), `false` forces root path (even for users/admins on Epicenter domain), `undefined` uses defaults (project-specific for users/admins on Epicenter domain, root for custom domains)
188
- * @returns promise that resolves to the new session object
189
- */
190
- async function regenerate(groupOrAccount, optionals = {}) {
191
- const {
192
- objectType = 'user',
193
- accountShortName,
194
- forcePathInclusion,
195
- ...routingOptions
196
- } = optionals;
197
- const session = await new Router().patch('/authentication', {
198
- accountShortName: objectType === 'admin' ? groupOrAccount : accountShortName,
199
- body: {
200
- objectType,
201
- groupKey: objectType === 'user' ? groupOrAccount : undefined
202
- },
203
- ...routingOptions
204
- }).then(({
205
- body
206
- }) => body);
207
- await removeLocalSession();
208
- identification.setSessionWithOptions(session, forcePathInclusion);
209
- return session;
210
- }
211
-
212
- /**
213
- * Authenticates using Single Sign-On (SSO)
214
- * Base URL: GET `https://forio.com/api/v3/{ACCOUNT}/{PROJECT}/registration/sso/user`
215
- *
216
- * @example
217
- * import { authAdapter } from 'epicenter-libs';
218
- * const session = await authAdapter.sso();
219
- *
220
- * @param [optionals] Optional arguments; pass network call options overrides here.
221
- * @returns promise that resolves to the session object
222
- */
223
- async function sso(optionals = {}) {
224
- const session = await new Router().get('/registration/sso/user', optionals).then(({
225
- body
226
- }) => body);
227
- identification.session = session;
228
- return session;
229
- }
230
-
231
- /**
232
- * Retrieves the SAML link from the SSO configuration
233
- * Base URL: GET `https://forio.com/api/v3/{ACCOUNT}/{PROJECT}/registration/sso/user/saml`
234
- *
235
- * @example
236
- * import { authAdapter } from 'epicenter-libs';
237
- * const samlLink = await authAdapter.getSAMLLink();
238
- *
239
- * @param [optionals] Optional arguments; pass network call options overrides here.
240
- * @returns promise that resolves to the SAML link
241
- */
242
- async function getSAMLLink(optionals = {}) {
243
- return await new Router().get('/registration/sso/user/saml', optionals).then(({
244
- body
245
- }) => body);
246
- }
247
-
248
- /**
249
- * Generates and returns an epicenter URL that will redirect to the SAML url
250
- *
251
- * @example
252
- * import { authAdapter } from 'epicenter-libs';
253
- * const samlURL = authAdapter.generateSAMLLINK();
254
- *
255
- * @param [optionals] Optional arguments; pass network call options overrides here.
256
- * @returns the generated SAML URL string
257
- */
258
- function generateSAMLLINK(optionals = {}) {
259
- return new Router().getURL('/registration/sso/user/saml', optionals).toString();
260
- }
261
-
262
- /**
263
- * Sends an outcome to an external link specified in project config. For example, sending a grade back to a third party platform.
264
- * Base URL: POST `https://forio.com/api/v3/{ACCOUNT}/{PROJECT}/lti/{LTI_VERSION}/outcome`
265
- *
266
- * @example
267
- * import { authAdapter } from 'epicenter-libs';
268
- * await authAdapter.ssoOutcome('1.3', {
269
- * value: 95,
270
- * sourcedId: 'student-assignment-123',
271
- * outcomeServiceUrl: 'https://lms.example.com/outcome',
272
- * });
273
- *
274
- * @param ltiVersion The version of LTI to use (valid versions: 1.1, 1.2, 1.3)
275
- * @param outcomeInformation Outcome information to send
276
- * @param outcomeInformation.value The value to pass back to the outcomeServiceUrl (e.g., the grade a student received)
277
- * @param outcomeInformation.sourcedId The id of the current assignment/student as provided by the client using the SSO service
278
- * @param outcomeInformation.outcomeServiceUrl The url called for passing back the outcome
279
- * @param [optionals] Optional arguments; pass network call options overrides here.
280
- * @returns promise that resolves to the response object
281
- */
282
- async function ssoOutcome(ltiVersion, outcomeInformation, optionals = {}) {
283
- const {
284
- ...routingOptions
285
- } = optionals;
286
- return await new Router().post(`/lti/${ltiVersion}/outcome`, {
287
- body: outcomeInformation,
288
- ...routingOptions
289
- }).then(({
290
- body
291
- }) => body);
292
- }
293
-
294
- /**
295
- * Sends a link to reset a user's password to their email
296
- * Base URL: POST `https://forio.com/api/v3/{ACCOUNT}/{PROJECT}/verification/password/user/{HANDLE}`
297
- *
298
- * @example
299
- * import { authAdapter } from 'epicenter-libs';
300
- * const subject = 'Please reset your password for the Acme simulation';
301
- * const redirectURL = 'https://forio.com/app/acme/simulations';
302
- * const handle = 'testUser@test.com';
303
- * await authAdapter.resetPassword(handle, { redirectURL, subject });
304
- *
305
- * @param handle Handle that user would use to login
306
- * @param [optionals] Optional arguments; pass network call options overrides here. Special arguments specific to this method are listed below if they exist.
307
- * @param [optionals.redirectURL] URL to redirect to after password reset is completed (must be in the forio domain)
308
- * @param [optionals.subject] The subject of the email that will be sent
309
- * @returns promise that resolves when the reset email is sent
310
- */
311
- async function resetPassword(handle, optionals = {}) {
312
- const {
313
- redirectURL,
314
- subject,
315
- ...routingOptions
316
- } = optionals;
317
- return await new Router().post(`/verification/password/user/${handle}`, {
318
- ...routingOptions,
319
- body: {
320
- redirectUrl: redirectURL,
321
- subject
322
- }
323
- }).then(({
324
- body
325
- }) => body);
326
- }
327
-
328
- /**
329
- * Verifies a token and retrieves the associated session
330
- * Base URL: GET `https://forio.com/api/v3/{ACCOUNT}/{PROJECT}/verification`
331
- *
332
- * @example
333
- * import { authAdapter } from 'epicenter-libs';
334
- * const session = await authAdapter.verify('my-auth-token');
335
- *
336
- * @param token Authorization token to verify
337
- * @param [optionals] Optional arguments; pass network call options overrides here.
338
- * @returns promise that resolves to the session object
339
- */
340
- async function verify(token, optionals = {}) {
341
- return await new Router().get('/verification', {
342
- authorization: `Bearer ${token}`,
343
- ...optionals
344
- }).then(({
345
- body
346
- }) => body);
347
- }
348
-
349
- export { generateSAMLLINK, getLocalSession, getSAMLLink, getSession, login, logout, regenerate, removeLocalSession, resetPassword, setLocalSession, sso, ssoOutcome, verify };
@@ -1,201 +0,0 @@
1
- import _defineProperty from '../node_modules/@babel/runtime/helpers/esm/defineProperty.js';
2
- import { SCOPE_BOUNDARY, PUSH_CATEGORY } from '../utils/constants.js';
3
- import '../utils/helpers.js';
4
- import EpicenterError from '../utils/error.js';
5
- import '../utils/config.js';
6
- import '../utils/identification.js';
7
- import '../utils/error-manager.js';
8
- import 'cross-fetch';
9
- import cometdAdapter from './cometd.js';
10
-
11
- // Generic type for push channel message custom data
12
-
13
- // Base structure for channel push messages
14
-
15
- const validateScope = scope => {
16
- if (!scope) throw new EpicenterError('No scope found where one was required');
17
- const {
18
- scopeBoundary,
19
- scopeKey,
20
- pushCategory
21
- } = scope;
22
- if (!scopeBoundary) throw new EpicenterError('Missing scope component: scopeBoundary');
23
- if (!scopeKey) throw new EpicenterError('Missing scope component: scopeKey');
24
- if (!pushCategory) throw new EpicenterError('Missing scope component: pushCategory');
25
- if (!Object.prototype.hasOwnProperty.call(SCOPE_BOUNDARY, scopeBoundary)) throw new EpicenterError(`Invalid scope boundary: ${scopeBoundary}`);
26
- if (!Object.prototype.hasOwnProperty.call(PUSH_CATEGORY, pushCategory)) throw new EpicenterError(`Invalid push category: ${pushCategory}`);
27
- };
28
-
29
- /**
30
- * Used to subscribe to CometD channels. Pass in a channel scope to instantiate, if a subscription to that scope already exists it will use it.
31
- *
32
- * @example
33
- * import { Channel, authAdapter, SCOPE_BOUNDARY, PUSH_CATEGORY } from 'epicenter-libs';
34
- * const session = authAdapter.getLocalSession();
35
- * const channel = new Channel({
36
- * scopeBoundary: SCOPE_BOUNDARY.GROUP,
37
- * scopeKey: session.groupKey,
38
- * pushCategory: PUSH_CATEGORY.CHAT,
39
- * });
40
- * await channel.subscribe((data) => {
41
- * console.log('Received message:', data);
42
- * });
43
- */
44
- class Channel {
45
- /**
46
- * Channel constructor
47
- *
48
- * @param scope Object with the scope boundary, scope key, and push category; defines the namespace for the channel
49
- * @param scope.scopeBoundary Scope boundary, defines the type of scope; See [scope boundary](#SCOPE_BOUNDARY) for all types
50
- * @param scope.scopeKey Scope key, a unique identifier tied to the scope. E.g., if your `scopeBoundary` is `GROUP`, your `scopeKey` will be your `groupKey`; for `EPISODE`, `episodeKey`, etc.
51
- * @param scope.pushCategory Push category, defines the type of channel; See [push category](#PUSH_CATEGORY) for all types
52
- */
53
- constructor(scope) {
54
- _defineProperty(this, "path", void 0);
55
- _defineProperty(this, "update", void 0);
56
- _defineProperty(this, "subscription", null);
57
- const {
58
- scopeBoundary,
59
- scopeKey,
60
- pushCategory
61
- } = scope;
62
- validateScope(scope);
63
- this.path = `/${scopeBoundary.toLowerCase()}/${scopeKey}/${pushCategory.toLowerCase()}`;
64
- if (cometdAdapter.subscriptions.has(this.path)) {
65
- this.subscription = cometdAdapter.subscriptions.get(this.path) || null;
66
- }
67
- }
68
-
69
- /**
70
- * Publishes content to the CometD channel
71
- *
72
- * @example
73
- * import { Channel, authAdapter, SCOPE_BOUNDARY, PUSH_CATEGORY } from 'epicenter-libs';
74
- * const session = authAdapter.getLocalSession();
75
- * const channel = new Channel({
76
- * scopeBoundary: SCOPE_BOUNDARY.GROUP,
77
- * scopeKey: session.groupKey,
78
- * pushCategory: PUSH_CATEGORY.CHAT,
79
- * });
80
- * await channel.publish({ message: 'Hello!' });
81
- *
82
- * @param content Content to publish to the channel
83
- * @returns promise that resolves to the CometD message response
84
- */
85
- publish(content) {
86
- return cometdAdapter.publish(this, content);
87
- }
88
-
89
- /**
90
- * Subscribes to the CometD channel, attaching a handler for any channel updates. If a subscription already exists it will first unsubscribe, ensuring that only one subscription is ever attached to the channel.
91
- *
92
- * @example
93
- * import { Channel, authAdapter, SCOPE_BOUNDARY, PUSH_CATEGORY } from 'epicenter-libs';
94
- * const session = authAdapter.getLocalSession();
95
- * const channel = new Channel({
96
- * scopeBoundary: SCOPE_BOUNDARY.GROUP,
97
- * scopeKey: session.groupKey,
98
- * pushCategory: PUSH_CATEGORY.CHAT,
99
- * });
100
- * await channel.subscribe((data) => {
101
- * console.log(data.content);
102
- * });
103
- *
104
- * @param update Function that is called whenever a channel update occurs
105
- * @param [options] Optional arguments
106
- * @param [options.inert] If true, creates an inert subscription that doesn't trigger reconnection
107
- * @returns promise that resolves to the subscription object returned by CometD after a successful subscribe
108
- */
109
- // eslint-disable-next-line complexity
110
- async subscribe(update, options = {}) {
111
- if (this.subscription) {
112
- try {
113
- await cometdAdapter.remove(this.subscription);
114
- } catch (error) {
115
- var _errorObj$information;
116
- const errorObj = error;
117
- const errorMessage = (errorObj === null || errorObj === void 0 ? void 0 : errorObj.message) || (errorObj === null || errorObj === void 0 || (_errorObj$information = errorObj.information) === null || _errorObj$information === void 0 ? void 0 : _errorObj$information.error) || '';
118
- if (errorMessage.includes('session_unknown') || errorMessage.includes('402')) ; else {
119
- // Re-throw other errors
120
- throw error;
121
- }
122
- }
123
- }
124
- this.update = update;
125
- let retryCount = 0;
126
- const maxRetries = 3;
127
- while (retryCount < maxRetries) {
128
- try {
129
- this.subscription = await cometdAdapter.add(this, update, options);
130
- return this.subscription;
131
- } catch (error) {
132
- var _errorObj$information2;
133
- const errorObj = error;
134
- const errorMessage = (errorObj === null || errorObj === void 0 ? void 0 : errorObj.message) || (errorObj === null || errorObj === void 0 || (_errorObj$information2 = errorObj.information) === null || _errorObj$information2 === void 0 ? void 0 : _errorObj$information2.error) || '';
135
- if ((errorMessage.includes('session_unknown') || errorMessage.includes('402')) && retryCount < maxRetries - 1) {
136
- retryCount++;
137
- // Force fresh handshake
138
- cometdAdapter.handshakeState = 'idle';
139
- cometdAdapter.handshakePromise = undefined;
140
-
141
- // Wait a moment before retrying
142
- const retryDelay = 1000;
143
- const currentRetry = retryCount;
144
- await new Promise(resolve => setTimeout(resolve, retryDelay * currentRetry));
145
- continue;
146
- }
147
-
148
- // Re-throw if not session_unknown or max retries exceeded
149
- throw error;
150
- }
151
- }
152
- throw new Error(`Failed to subscribe to ${this.path} after ${maxRetries} attempts`);
153
- }
154
-
155
- /**
156
- * Unsubscribes from the CometD channel
157
- *
158
- * @example
159
- * import { Channel, authAdapter, SCOPE_BOUNDARY, PUSH_CATEGORY } from 'epicenter-libs';
160
- * const session = authAdapter.getLocalSession();
161
- * const channel = new Channel({
162
- * scopeBoundary: SCOPE_BOUNDARY.GROUP,
163
- * scopeKey: session.groupKey,
164
- * pushCategory: PUSH_CATEGORY.CHAT,
165
- * });
166
- * await channel.subscribe((data) => console.log(data));
167
- * // Later...
168
- * await channel.unsubscribe();
169
- *
170
- * @returns promise that resolves when unsubscribed
171
- */
172
- async unsubscribe() {
173
- if (this.subscription) {
174
- await cometdAdapter.remove(this.subscription);
175
- this.subscription = null;
176
- }
177
- }
178
-
179
- /**
180
- * Unsubscribes from all CometD channels
181
- *
182
- * @example
183
- * import { Channel, authAdapter, SCOPE_BOUNDARY, PUSH_CATEGORY } from 'epicenter-libs';
184
- * const session = authAdapter.getLocalSession();
185
- * const channel = new Channel({
186
- * scopeBoundary: SCOPE_BOUNDARY.GROUP,
187
- * scopeKey: session.groupKey,
188
- * pushCategory: PUSH_CATEGORY.CHAT,
189
- * });
190
- * await channel.subscribe((data) => console.log(data));
191
- * // Later, unsubscribe from all channels...
192
- * await channel.unsubscribeAll();
193
- *
194
- * @returns promise that resolves when all channels are unsubscribed
195
- */
196
- async unsubscribeAll() {
197
- await cometdAdapter.empty();
198
- }
199
- }
200
-
201
- export { Channel as default };