epicenter-libs 3.11.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/CHANGELOG.md +345 -0
- package/LICENSE.md +37 -0
- package/README.md +134 -0
- package/dist/browser/AckExtension-e67c6a28.js +129 -0
- package/dist/browser/AckExtension-e67c6a28.js.map +1 -0
- package/dist/browser/ReloadExtension-b1e50033.js +253 -0
- package/dist/browser/ReloadExtension-b1e50033.js.map +1 -0
- package/dist/browser/cometd-eeabdcd4.js +3438 -0
- package/dist/browser/cometd-eeabdcd4.js.map +1 -0
- package/dist/browser/epicenter-2cce2971.js +6086 -0
- package/dist/browser/epicenter-2cce2971.js.map +1 -0
- package/dist/browser/epicenter.js +2 -0
- package/dist/browser/epicenter.js.map +1 -0
- package/dist/cjs/AckExtension-f5178e19.js +131 -0
- package/dist/cjs/AckExtension-f5178e19.js.map +1 -0
- package/dist/cjs/ReloadExtension-65b036ba.js +255 -0
- package/dist/cjs/ReloadExtension-65b036ba.js.map +1 -0
- package/dist/cjs/cometd-473408f4.js +3441 -0
- package/dist/cjs/cometd-473408f4.js.map +1 -0
- package/dist/cjs/epicenter-12ceb814.js +7248 -0
- package/dist/cjs/epicenter-12ceb814.js.map +1 -0
- package/dist/cjs/epicenter.js +54 -0
- package/dist/cjs/epicenter.js.map +1 -0
- package/dist/epicenter.js +9895 -0
- package/dist/epicenter.js.map +1 -0
- package/dist/epicenter.min.js +2 -0
- package/dist/epicenter.min.js.map +1 -0
- package/dist/module/AckExtension-6181d8b5.js +129 -0
- package/dist/module/AckExtension-6181d8b5.js.map +1 -0
- package/dist/module/ReloadExtension-eaa8c42c.js +253 -0
- package/dist/module/ReloadExtension-eaa8c42c.js.map +1 -0
- package/dist/module/cometd-af78008d.js +3438 -0
- package/dist/module/cometd-af78008d.js.map +1 -0
- package/dist/module/epicenter-9b8c92a9.js +7213 -0
- package/dist/module/epicenter-9b8c92a9.js.map +1 -0
- package/dist/module/epicenter.js +7 -0
- package/dist/module/epicenter.js.map +1 -0
- package/dist/types/adapters/account.d.ts +44 -0
- package/dist/types/adapters/admin.d.ts +33 -0
- package/dist/types/adapters/asset.d.ts +46 -0
- package/dist/types/adapters/authentication.d.ts +62 -0
- package/dist/types/adapters/channel.d.ts +39 -0
- package/dist/types/adapters/chat.d.ts +105 -0
- package/dist/types/adapters/cometd.d.ts +25 -0
- package/dist/types/adapters/email.d.ts +86 -0
- package/dist/types/adapters/episode.d.ts +91 -0
- package/dist/types/adapters/group.d.ts +273 -0
- package/dist/types/adapters/index.d.ts +21 -0
- package/dist/types/adapters/leaderboard.d.ts +68 -0
- package/dist/types/adapters/presence.d.ts +35 -0
- package/dist/types/adapters/project.d.ts +99 -0
- package/dist/types/adapters/recaptcha.d.ts +1 -0
- package/dist/types/adapters/run.d.ts +253 -0
- package/dist/types/adapters/task.d.ts +154 -0
- package/dist/types/adapters/time.d.ts +2 -0
- package/dist/types/adapters/user.d.ts +38 -0
- package/dist/types/adapters/vault.d.ts +94 -0
- package/dist/types/adapters/world.d.ts +230 -0
- package/dist/types/epicenter.d.ts +10 -0
- package/dist/types/utils/config.d.ts +90 -0
- package/dist/types/utils/constants.d.ts +290 -0
- package/dist/types/utils/cookies.d.ts +16 -0
- package/dist/types/utils/error-manager.d.ts +21 -0
- package/dist/types/utils/error.d.ts +4 -0
- package/dist/types/utils/fault.d.ts +17 -0
- package/dist/types/utils/helpers.d.ts +4 -0
- package/dist/types/utils/identification.d.ts +47 -0
- package/dist/types/utils/index.d.ts +11 -0
- package/dist/types/utils/result.d.ts +6 -0
- package/dist/types/utils/router.d.ts +157 -0
- package/dist/types/utils/store.d.ts +31 -0
- package/package.json +103 -0
- package/src/adapters/account.ts +104 -0
- package/src/adapters/admin.ts +53 -0
- package/src/adapters/asset.ts +195 -0
- package/src/adapters/authentication.ts +173 -0
- package/src/adapters/channel.ts +83 -0
- package/src/adapters/chat.ts +186 -0
- package/src/adapters/cometd.ts +297 -0
- package/src/adapters/email.ts +146 -0
- package/src/adapters/episode.ts +163 -0
- package/src/adapters/group.ts +511 -0
- package/src/adapters/index.ts +43 -0
- package/src/adapters/leaderboard.ts +122 -0
- package/src/adapters/presence.ts +63 -0
- package/src/adapters/project.ts +123 -0
- package/src/adapters/recaptcha.ts +11 -0
- package/src/adapters/run.ts +726 -0
- package/src/adapters/task.ts +213 -0
- package/src/adapters/time.ts +36 -0
- package/src/adapters/user.ts +75 -0
- package/src/adapters/vault.ts +232 -0
- package/src/adapters/world.ts +412 -0
- package/src/epicenter.ts +96 -0
- package/src/globals.d.ts +16 -0
- package/src/utils/config.ts +168 -0
- package/src/utils/constants.ts +324 -0
- package/src/utils/cookies.ts +71 -0
- package/src/utils/error-manager.ts +66 -0
- package/src/utils/error.ts +9 -0
- package/src/utils/fault.ts +39 -0
- package/src/utils/helpers.ts +7 -0
- package/src/utils/identification.ts +128 -0
- package/src/utils/index.ts +11 -0
- package/src/utils/result.ts +15 -0
- package/src/utils/router.ts +547 -0
- package/src/utils/store.ts +82 -0
|
@@ -0,0 +1,511 @@
|
|
|
1
|
+
import type { UserSession } from '../utils/identification';
|
|
2
|
+
import type { RoutingOptions, Page, GenericSearchOptions } from '../utils/router';
|
|
3
|
+
import type { User } from './user';
|
|
4
|
+
|
|
5
|
+
import { Router, EpicenterError, identification, ROLE } from '../utils';
|
|
6
|
+
|
|
7
|
+
enum AUGMENT {
|
|
8
|
+
MEMBERS = 'MEMBERS',
|
|
9
|
+
QUANTIZED = 'QUANTIZED',
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface Pricing {
|
|
13
|
+
amount: number
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface FlightRecorder {
|
|
17
|
+
start: number,
|
|
18
|
+
stop: number,
|
|
19
|
+
enabled: boolean,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface GroupUpdate {
|
|
23
|
+
runLimit?: number,
|
|
24
|
+
organization?: string,
|
|
25
|
+
allowSelfRegistration?: boolean,
|
|
26
|
+
flightRecorder?: FlightRecorder,
|
|
27
|
+
event?: string,
|
|
28
|
+
allowMembershipChanges?: boolean,
|
|
29
|
+
pricing?: Pricing,
|
|
30
|
+
startDate?: Date,
|
|
31
|
+
expirationDate?: Date,
|
|
32
|
+
capacity?: number,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface GroupPermission {
|
|
36
|
+
available: boolean,
|
|
37
|
+
objectType: 'group',
|
|
38
|
+
role: keyof typeof ROLE,
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface Member extends GroupPermission {
|
|
42
|
+
user: User,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface Group extends GroupUpdate {
|
|
46
|
+
name: string,
|
|
47
|
+
groupKey: string,
|
|
48
|
+
members?: Member[],
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Provides information on a particular Epicenter group.
|
|
54
|
+
* @example
|
|
55
|
+
* import { authAdapter, groupAdapter } from 'epicenter';
|
|
56
|
+
* const session = authAdapter.getLocalSession();
|
|
57
|
+
* // include members of the group in the response
|
|
58
|
+
* const group = await groupAdapter.get(session.groupKey, { augment: 'MEMBERS' });
|
|
59
|
+
* // include metrics relating to the group in the response
|
|
60
|
+
* const group = await groupAdapter.get(session.groupKey, { augment: 'QUANTIZED' });
|
|
61
|
+
* @param [optionals] Optional arguments; pass network call options overrides here. Special arguments specific to this method are listed below if they exist.
|
|
62
|
+
* @param [optionals.augment] Specifies which additional information you'd like returned with the group
|
|
63
|
+
* @param [optionals.groupKey] Group key, if omitted will attempt to use the group associated with the current session
|
|
64
|
+
* @returns promise that resolves to a group
|
|
65
|
+
*/
|
|
66
|
+
export async function get(
|
|
67
|
+
optionals: {
|
|
68
|
+
augment?: keyof typeof AUGMENT,
|
|
69
|
+
groupKey?: string,
|
|
70
|
+
} & RoutingOptions = {}
|
|
71
|
+
): Promise<Group> {
|
|
72
|
+
const {
|
|
73
|
+
groupKey, augment,
|
|
74
|
+
...routingOptions
|
|
75
|
+
} = optionals;
|
|
76
|
+
let uriComponent = '';
|
|
77
|
+
if (augment === AUGMENT.MEMBERS) uriComponent = '/member';
|
|
78
|
+
if (augment === AUGMENT.QUANTIZED) uriComponent = '/quantized';
|
|
79
|
+
const session = identification.session as UserSession;
|
|
80
|
+
return await new Router()
|
|
81
|
+
.get(`/group${uriComponent}/${groupKey ?? session?.groupKey}`, routingOptions)
|
|
82
|
+
.then(({ body }) => body);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Deletes the group; available only to Epicenter admins
|
|
88
|
+
* @example
|
|
89
|
+
* epicenter.groupAdapter.destroy('0000017dd3bf540e5ada5b1e058f08f20461');
|
|
90
|
+
* @param groupKey Key associated with group
|
|
91
|
+
* @param [optionals] Optional arguments; pass network call options overrides here.
|
|
92
|
+
* @returns promise that resolves to undefined if successful
|
|
93
|
+
*/
|
|
94
|
+
export async function destroy(
|
|
95
|
+
groupKey: string,
|
|
96
|
+
optionals: RoutingOptions = {},
|
|
97
|
+
): Promise<void> {
|
|
98
|
+
|
|
99
|
+
return await new Router()
|
|
100
|
+
.delete(`/group/${groupKey}`, optionals)
|
|
101
|
+
.then(({ body }) => body);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Provides information on for all groups in the project
|
|
107
|
+
* @example
|
|
108
|
+
* const groups = await epicenter.groupAdapter.gather();
|
|
109
|
+
* @param [optionals] Optional arguments; pass network call options overrides here.
|
|
110
|
+
* @param [optionals.includeExpired] Indicates whether to include expired groups in the query
|
|
111
|
+
* @returns promise that resolves to a list of groups
|
|
112
|
+
*/
|
|
113
|
+
export async function gather(
|
|
114
|
+
optionals: { includeExpired?: boolean } & RoutingOptions = {}
|
|
115
|
+
): Promise<Group[]> {
|
|
116
|
+
const {
|
|
117
|
+
includeExpired,
|
|
118
|
+
...routingOptions
|
|
119
|
+
} = optionals;
|
|
120
|
+
|
|
121
|
+
return await new Router()
|
|
122
|
+
.withSearchParams({ includeExpired })
|
|
123
|
+
.get('/group', routingOptions)
|
|
124
|
+
.then(({ body }) => body);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Updates fields for a particular group; available only to Epicenter admins.
|
|
130
|
+
* @example
|
|
131
|
+
* epicenter.groupAdapter.update('0000017dd3bf540e5ada5b1e058f08f20461', { event: 'Orientation Day' });
|
|
132
|
+
* @param groupKey Key associated with group
|
|
133
|
+
* @param update Attributes you wish to update
|
|
134
|
+
* @param [update.runLimit] Defines the upper limit of runs allowed in the group
|
|
135
|
+
* @param [update.organization] Name of the organization owning the group
|
|
136
|
+
* @param [update.allowSelfRegistration] TODO -- this does something, it's just that the frontend devs don't know what yet
|
|
137
|
+
* @param [update.flightRecorder] Diagnostic tool for logging http requests for the server
|
|
138
|
+
* @param [update.flightRecorder].start Start time (epoch time)
|
|
139
|
+
* @param [update.flightRecorder].stop End time (epoch time)
|
|
140
|
+
* @param [update.flightRecorder].enabled Enabled flag for the flight recorder
|
|
141
|
+
* @param [update.event] Name of the event the group is playing for
|
|
142
|
+
* @param [update.allowMembershipChanges] TODO -- this does something, it's just that the frontend devs don't know what yet
|
|
143
|
+
* @param [update.pricing] TODO -- this does something, it's just that the frontend devs don't know what yet
|
|
144
|
+
* @param [update.pricing].number TODO -- this does something, it's just that the frontend devs don't know what yet
|
|
145
|
+
* @param [update.startDate] TODO -- this does something, it's just that the frontend devs don't know what yet
|
|
146
|
+
* @param [update.expirationDate] Date the group expires
|
|
147
|
+
* @param [update.capacity] Defines the upper limit on the number of users allowed in the group
|
|
148
|
+
* @param [optionals] Optional arguments; pass network call options overrides here.
|
|
149
|
+
* @returns promise that resolves to the updated group
|
|
150
|
+
*/
|
|
151
|
+
export async function update(
|
|
152
|
+
groupKey: string,
|
|
153
|
+
update: GroupUpdate,
|
|
154
|
+
optionals: RoutingOptions = {}
|
|
155
|
+
): Promise<Group> {
|
|
156
|
+
const {
|
|
157
|
+
runLimit, organization, allowSelfRegistration, flightRecorder,
|
|
158
|
+
event, allowMembershipChanges, pricing,
|
|
159
|
+
startDate, expirationDate, capacity,
|
|
160
|
+
} = update;
|
|
161
|
+
|
|
162
|
+
return await new Router()
|
|
163
|
+
.patch(`/group/${groupKey}`, {
|
|
164
|
+
body: {
|
|
165
|
+
runLimit, organization, allowSelfRegistration, flightRecorder,
|
|
166
|
+
event, allowMembershipChanges, pricing,
|
|
167
|
+
startDate, expirationDate, capacity,
|
|
168
|
+
},
|
|
169
|
+
...optionals,
|
|
170
|
+
})
|
|
171
|
+
.then(({ body }) => body);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Creates a new group; available only to Epicenter admins
|
|
177
|
+
* @example
|
|
178
|
+
* epicenter.groupAdapter.create({
|
|
179
|
+
* runLimit: 10,
|
|
180
|
+
* name: 'my-group-name',
|
|
181
|
+
* });
|
|
182
|
+
* @param group Group object
|
|
183
|
+
* @param group.name Group name (required)
|
|
184
|
+
* @param [group.runLimit] Defines the upper limit on the number of runs allowed in the group
|
|
185
|
+
* @param [group.organization] Name of the organization owning the group
|
|
186
|
+
* @param [group.allowSelfRegistration] TODO -- this does something, it's just that the frontend devs don't know what yet
|
|
187
|
+
* @param [group.flightRecorder] Diagnostic tool for loggin http requests for the server
|
|
188
|
+
* @param [group.flightRecorder.start] Start time (epoch time)
|
|
189
|
+
* @param [group.flightRecorder.stop] End time (epoch time)
|
|
190
|
+
* @param [group.flightRecorder.enabled] Enabled flag for the flight recorder
|
|
191
|
+
* @param [group.event] Name of the event the group is playing for
|
|
192
|
+
* @param [group.allowMembershipChanges] TODO -- this does something, it's just that the frontend devs don't know what yet
|
|
193
|
+
* @param [group.pricing] TODO -- this does something, it's just that the frontend devs don't know what yet
|
|
194
|
+
* @param [group.startDate] TODO -- this does something, it's just that the frontend devs don't know what yet
|
|
195
|
+
* @param [group.expirationDate] Date the group expires
|
|
196
|
+
* @param [group.capacity] Defines the upper limit on the number of users allowed in the group
|
|
197
|
+
* @param [optionals] Optional arguments; pass network call options overrides here.
|
|
198
|
+
* @returns promise that resolves to the newly created group
|
|
199
|
+
*/
|
|
200
|
+
export async function create(
|
|
201
|
+
group: Group,
|
|
202
|
+
optionals: RoutingOptions = {}
|
|
203
|
+
): Promise<Group> {
|
|
204
|
+
const {
|
|
205
|
+
name, runLimit, organization, allowSelfRegistration,
|
|
206
|
+
flightRecorder, event, allowMembershipChanges, pricing,
|
|
207
|
+
startDate, expirationDate, capacity,
|
|
208
|
+
} = group;
|
|
209
|
+
if (!name) throw new EpicenterError('Cannot create a group with no name');
|
|
210
|
+
return await new Router()
|
|
211
|
+
.post('/group', {
|
|
212
|
+
body: {
|
|
213
|
+
name, runLimit, organization, allowSelfRegistration,
|
|
214
|
+
flightRecorder, event, allowMembershipChanges, pricing,
|
|
215
|
+
startDate, expirationDate, capacity,
|
|
216
|
+
},
|
|
217
|
+
...optionals,
|
|
218
|
+
})
|
|
219
|
+
.then(({ body }) => body);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Queries for groups
|
|
225
|
+
* @example
|
|
226
|
+
* import { groupAdapter } from 'epicenter';
|
|
227
|
+
* const filter = [
|
|
228
|
+
* 'name|=group1|group2', // look for groups whose name is 'group1' or 'group2'
|
|
229
|
+
* 'groupKey=0000017dd3bf540e5ada5b1e058f08f20461', // look for groups with the specific group key
|
|
230
|
+
* 'approximateMemberCount>30', // look for groups larger than 30
|
|
231
|
+
* 'startDate<2022-01-03T20:30:53.054Z', // look for groups with start date before Jan 3rd 2022
|
|
232
|
+
* 'expirationDate<2022-01-03T20:30:53.054Z', // look for groups with expiration date before Jan 3rd 2022
|
|
233
|
+
* // 'account.shortName=acme', // specifies account, intended for admin use
|
|
234
|
+
* // 'project.shortName=simulations', // specifies project, intended for admin use
|
|
235
|
+
* ];
|
|
236
|
+
* groupAdapter.query({
|
|
237
|
+
* filter,
|
|
238
|
+
* sort: ['+group.name'] // sort all findings by group name ascending (lexigraphically)
|
|
239
|
+
* first: 3, // page should start with the 4th item found (will default to 0)
|
|
240
|
+
* max: 10, // page should only include the first 10 items
|
|
241
|
+
* });
|
|
242
|
+
* @param searchOptions Search options for the query
|
|
243
|
+
* @param [searchOptions.filter] Filters for searching
|
|
244
|
+
* @param [searchOptions.sort] Sorting criteria
|
|
245
|
+
* @param [searchOptions.first] The starting index of the page returned
|
|
246
|
+
* @param [searchOptions.max] The number of entries per page
|
|
247
|
+
* @param [optionals] Optional arguments; pass network call options overrides here.
|
|
248
|
+
* @returns promise that resolves to a page of groups
|
|
249
|
+
*/
|
|
250
|
+
export async function query(
|
|
251
|
+
searchOptions: { quantized?: boolean } & GenericSearchOptions,
|
|
252
|
+
optionals: RoutingOptions = {}
|
|
253
|
+
): Promise<Page<Group>> {
|
|
254
|
+
const { filter = [], sort = [], first, max, quantized } = searchOptions;
|
|
255
|
+
|
|
256
|
+
const searchParams = {
|
|
257
|
+
filter: filter.join(';') || undefined,
|
|
258
|
+
sort: sort.join(';') || undefined,
|
|
259
|
+
first, max,
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
return await new Router()
|
|
263
|
+
.withSearchParams(searchParams)
|
|
264
|
+
.get(`/group${quantized ? '/quantized' : ''}/search`, {
|
|
265
|
+
paginated: true,
|
|
266
|
+
...optionals,
|
|
267
|
+
})
|
|
268
|
+
.then(({ body }) => body);
|
|
269
|
+
}
|
|
270
|
+
/** DEPRECATED -- use groupAdapter.query instead */
|
|
271
|
+
export async function search(
|
|
272
|
+
optionals: { quantized?: boolean } & GenericSearchOptions & RoutingOptions = {}
|
|
273
|
+
): Promise<Page<Group>> {
|
|
274
|
+
console.warn('DEPRECATION WARNING: groupAdapter.search is deprecated and will be removed with the next release. Use groupAdapter.query instead.');
|
|
275
|
+
const { filter = [], sort = [], first, max, quantized, ...routingOptions } = optionals;
|
|
276
|
+
const searchOptions = { filter, sort, first, max, quantized };
|
|
277
|
+
return await query(searchOptions, routingOptions);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Retrieves a group with given group name
|
|
283
|
+
* @example
|
|
284
|
+
* epicenter.groupAdapter.withGroupName('my-group-name');
|
|
285
|
+
* @param name Name associated with the group
|
|
286
|
+
* @param [optionals] Optional arguments; pass network call options overrides here.
|
|
287
|
+
* @returns promise that resolves to a group
|
|
288
|
+
*/
|
|
289
|
+
export async function withGroupName(
|
|
290
|
+
name: string,
|
|
291
|
+
optionals: RoutingOptions = {}
|
|
292
|
+
): Promise<Group> {
|
|
293
|
+
|
|
294
|
+
return await new Router()
|
|
295
|
+
.get(`/group/with/${name}`, optionals)
|
|
296
|
+
.then(({ body }) => body);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Retrieves the list of groups a particular user is in; intended for admin use
|
|
302
|
+
* @example
|
|
303
|
+
* epicenter.groupAdapter.forUser(
|
|
304
|
+
* '000001796733eef0842f4d6d960997018a3b', // get groups where this user is a member of
|
|
305
|
+
* { role: ['FACILITATOR'] } // where this user is a facilitator in the group
|
|
306
|
+
* );
|
|
307
|
+
* @param userKey Name associated with the group
|
|
308
|
+
* @param [optionals] Optional arguments; pass network call options overrides here. Special arguments specific to this method are listed below if they exist.
|
|
309
|
+
* @param [optionals.includeExpired] Indicates whether to include expired groups in the query
|
|
310
|
+
* @param [optionals.includeAllMembers] Indicates whether to include the other members in the group (by default, only the requested user appears)
|
|
311
|
+
* @param [optionals.role] Role or list of possible roles the user holds in the group
|
|
312
|
+
* @returns promise that resolves to a list of groups
|
|
313
|
+
*/
|
|
314
|
+
export async function forUser(
|
|
315
|
+
userKey: string,
|
|
316
|
+
optionals: {
|
|
317
|
+
includeAllMembers?: boolean,
|
|
318
|
+
includeExpired?: boolean,
|
|
319
|
+
role?: string | string[],
|
|
320
|
+
} & RoutingOptions = {},
|
|
321
|
+
): Promise<Group[]> {
|
|
322
|
+
const {
|
|
323
|
+
includeExpired, includeAllMembers, role,
|
|
324
|
+
...routingOptions
|
|
325
|
+
} = optionals;
|
|
326
|
+
const isMultiple = Array.isArray(role) && role.length > 0;
|
|
327
|
+
const roleList = isMultiple ? role : [role];
|
|
328
|
+
const searchParams = {
|
|
329
|
+
includeExpired,
|
|
330
|
+
includeAllMembers,
|
|
331
|
+
role: role ? roleList : undefined,
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
return await new Router()
|
|
335
|
+
.withSearchParams(searchParams)
|
|
336
|
+
.get(`/group/member/for/${userKey}`, routingOptions)
|
|
337
|
+
.then(({ body }) => body);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Retrieves the list of groups particular to the current session
|
|
343
|
+
* @example
|
|
344
|
+
* const groups = await epicenter.groupAdapter.getSessionGroups();
|
|
345
|
+
* @param [optionals] Optional arguments; pass network call options overrides here.
|
|
346
|
+
* @param [optionals.includeExpired] Indicates whether to include expired groups in the query
|
|
347
|
+
* @param [optionals.includeAllMembers] Indicates whether to include the other members in the group (by default, only the requested user appears)
|
|
348
|
+
* @param [optionals.role] Role or list of possible roles the user holds in the group
|
|
349
|
+
* @returns promise that resolves to a list of groups
|
|
350
|
+
*/
|
|
351
|
+
export async function getSessionGroups(
|
|
352
|
+
optionals: {
|
|
353
|
+
includeAllMembers?: boolean,
|
|
354
|
+
includeExpired?: boolean,
|
|
355
|
+
role?: string | string[],
|
|
356
|
+
} & RoutingOptions = {},
|
|
357
|
+
): Promise<Group[]> {
|
|
358
|
+
const {
|
|
359
|
+
includeExpired, role,
|
|
360
|
+
...routingOptions
|
|
361
|
+
} = optionals;
|
|
362
|
+
const isMultiple = Array.isArray(role) && role.length > 0;
|
|
363
|
+
const roleList = isMultiple ? role : [role];
|
|
364
|
+
const searchParams = {
|
|
365
|
+
includeExpired,
|
|
366
|
+
role: role ? roleList : undefined,
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
return await new Router()
|
|
370
|
+
.withSearchParams(searchParams)
|
|
371
|
+
.get('/group/member', routingOptions)
|
|
372
|
+
.then(({ body }) => body);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Self-application for membership in a group; will only work if the group has the self-registration setting turned on.
|
|
378
|
+
* @example
|
|
379
|
+
* epicenter.groupAdapter.register('0000017dd3bf540e5ada5b1e058f08f20461');
|
|
380
|
+
* @param groupKey Key associated with group
|
|
381
|
+
* @param [optionals] Optional arguments; pass network call options overrides here.
|
|
382
|
+
* @returns promise that resolves in a group
|
|
383
|
+
*/
|
|
384
|
+
export async function register(
|
|
385
|
+
groupKey: string,
|
|
386
|
+
optionals: RoutingOptions = {}
|
|
387
|
+
): Promise<Group> {
|
|
388
|
+
|
|
389
|
+
return await new Router()
|
|
390
|
+
.post(`/group/selfRegistration/${groupKey}`, optionals)
|
|
391
|
+
.then(({ body }) => body);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
type UserInput = string | { userKey: string, role?: keyof typeof ROLE, available?: boolean };
|
|
396
|
+
/**
|
|
397
|
+
* Adds user(s) to the group
|
|
398
|
+
* @example
|
|
399
|
+
* epicenter.groupAdapter.addUser('000001796733eef0842f4d6d960997018a3b');
|
|
400
|
+
* epicenter.groupAdapter.addUser([{
|
|
401
|
+
* userKey: '000001796733eef0842f4d6d960997018a3b',
|
|
402
|
+
* role: 'REVIEWER',
|
|
403
|
+
* available: false,
|
|
404
|
+
* }]);
|
|
405
|
+
* @param usersInput List of user keys or user input objects (properties defined below)
|
|
406
|
+
* @param usersInput[].userKey User key
|
|
407
|
+
* @param [usersInput[].role] User's role -- defaults to PARTICIPANT if unset; See [ROLE](#ROLE) for all types
|
|
408
|
+
* @param [usersInput[].available] Indicates whether or not the user is 'active' (for semantic labeling) -- defaults to true if unset
|
|
409
|
+
* @param [optionals] Optional arguments; pass network call options overrides here. Special arguments specific to this method are listed below if they exist.
|
|
410
|
+
* @param [optionals.groupKey] Group key to do indicate the group; will default to the group key associated with the current session
|
|
411
|
+
* @returns promise that resolves to the group the user was added to
|
|
412
|
+
*/
|
|
413
|
+
export async function addUser(
|
|
414
|
+
usersInput: UserInput | UserInput[],
|
|
415
|
+
optionals: { groupKey?: string } & RoutingOptions = {}
|
|
416
|
+
):Promise<Group> {
|
|
417
|
+
const { groupKey, ...routingOptions } = optionals;
|
|
418
|
+
|
|
419
|
+
const users = Array.isArray(usersInput) ? usersInput : [usersInput];
|
|
420
|
+
const session = identification.session as UserSession;
|
|
421
|
+
return await new Router()
|
|
422
|
+
.post(`/group/member/${groupKey ?? session?.groupKey}`, {
|
|
423
|
+
body: users.map((u) => {
|
|
424
|
+
const userKey = typeof u === 'string' ? u : u.userKey;
|
|
425
|
+
const role = typeof u === 'string' ? ROLE.PARTICIPANT : u.role;
|
|
426
|
+
const available = typeof u === 'string' ? true : u.available;
|
|
427
|
+
|
|
428
|
+
return {
|
|
429
|
+
role,
|
|
430
|
+
userKey,
|
|
431
|
+
objectType: 'group',
|
|
432
|
+
available: available ?? true,
|
|
433
|
+
};
|
|
434
|
+
}),
|
|
435
|
+
...routingOptions,
|
|
436
|
+
})
|
|
437
|
+
.then(({ body }) => body);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Updates a user's group membership information
|
|
443
|
+
* @example
|
|
444
|
+
* epicenter.groupAdapter.updateUser('000001796733eef0842f4d6d960997018a3b', { role: 'LEADER' });
|
|
445
|
+
* @param userKey User key
|
|
446
|
+
* @param update Object containing the updates to a user's group membership information
|
|
447
|
+
* @param [update.role] User's role; See [ROLE](#ROLE) for all types
|
|
448
|
+
* @param [update.available] Indicates whether or not the user is 'active' (for semantic labeling)
|
|
449
|
+
* @param [optionals] Optional arguments; pass network call options overrides here.
|
|
450
|
+
* @returns promise that resolves to the membership information that was updated
|
|
451
|
+
*/
|
|
452
|
+
export async function updateUser(
|
|
453
|
+
userKey: string,
|
|
454
|
+
update: { role?: keyof typeof ROLE, available?: boolean },
|
|
455
|
+
optionals: { groupKey?: string } & RoutingOptions = {}
|
|
456
|
+
):Promise<GroupPermission> {
|
|
457
|
+
const { role, available } = update;
|
|
458
|
+
const { groupKey, ...routingOptions } = optionals;
|
|
459
|
+
const session = identification.session as UserSession;
|
|
460
|
+
return await new Router()
|
|
461
|
+
.patch(`/group/member/${groupKey ?? session?.groupKey}/${userKey}`, {
|
|
462
|
+
body: {
|
|
463
|
+
objectType: 'group',
|
|
464
|
+
role,
|
|
465
|
+
available,
|
|
466
|
+
},
|
|
467
|
+
...routingOptions,
|
|
468
|
+
})
|
|
469
|
+
.then(({ body }) => body);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* Removes user(s) from the group
|
|
475
|
+
* @example
|
|
476
|
+
* const userKeys = members.map(({ userKey }) => userKey);
|
|
477
|
+
* epicenter.groupAdapter.removeUsers(userKeys)
|
|
478
|
+
* @param userKey Key associated with the user or an array of user keys to remove from group
|
|
479
|
+
* @param [optionals] Optional arguments; pass network call options overrides here. Special arguments specific to this method are listed below if they exist.
|
|
480
|
+
* @param [optionals.groupKey] Group key for the group you want to remove from; defaults to the group in the current session
|
|
481
|
+
* @returns promise that resolves to undefined when successful
|
|
482
|
+
*/
|
|
483
|
+
export async function removeUser(
|
|
484
|
+
userKey: string | string[],
|
|
485
|
+
optionals: { groupKey?: string } & RoutingOptions = {}
|
|
486
|
+
): Promise<void> {
|
|
487
|
+
const { groupKey, ...routingOptions } = optionals;
|
|
488
|
+
const hasMultiple = Array.isArray(userKey) && userKey.length > 1;
|
|
489
|
+
const uriComponent = hasMultiple ? '' : `/${userKey.length === 1 ? userKey[0] : userKey}`;
|
|
490
|
+
const searchParams = hasMultiple ? { userKey } : undefined;
|
|
491
|
+
const session = identification.session as UserSession;
|
|
492
|
+
return await new Router()
|
|
493
|
+
.withSearchParams(searchParams)
|
|
494
|
+
.delete(`/group/member/${groupKey ?? session?.groupKey}${uriComponent}`, routingOptions)
|
|
495
|
+
.then(({ body }) => body);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
export async function statusUpdate(
|
|
500
|
+
code: string,
|
|
501
|
+
message: string,
|
|
502
|
+
optionals: { groupKey?: string } & RoutingOptions = {}
|
|
503
|
+
): Promise<Group> {
|
|
504
|
+
const { groupKey, ...routingOptions } = optionals;
|
|
505
|
+
const session = identification.session as UserSession;
|
|
506
|
+
return await new Router()
|
|
507
|
+
.patch(`/group/status/${groupKey ?? session?.groupKey}`, {
|
|
508
|
+
body: { code, message },
|
|
509
|
+
...routingOptions,
|
|
510
|
+
}).then(({ body }) => body);
|
|
511
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as accountAdapter from './account';
|
|
2
|
+
import * as adminAdapter from './admin';
|
|
3
|
+
import * as authAdapter from './authentication';
|
|
4
|
+
import * as assetAdapter from './asset';
|
|
5
|
+
import * as emailAdapter from './email';
|
|
6
|
+
import * as episodeAdapter from './episode';
|
|
7
|
+
import * as groupAdapter from './group';
|
|
8
|
+
import * as leaderboardAdapter from './leaderboard';
|
|
9
|
+
import * as presenceAdapter from './presence';
|
|
10
|
+
import * as projectAdapter from './project';
|
|
11
|
+
import * as recaptchaAdapter from './recaptcha';
|
|
12
|
+
import * as runAdapter from './run';
|
|
13
|
+
import * as userAdapter from './user';
|
|
14
|
+
import * as vaultAdapter from './vault';
|
|
15
|
+
import * as worldAdapter from './world';
|
|
16
|
+
import * as timeAdapter from './time';
|
|
17
|
+
import * as taskAdapter from './task';
|
|
18
|
+
import * as chatAdapter from './chat';
|
|
19
|
+
import { default as cometdAdapter } from './cometd';
|
|
20
|
+
import { default as Channel } from './channel';
|
|
21
|
+
|
|
22
|
+
export {
|
|
23
|
+
accountAdapter,
|
|
24
|
+
adminAdapter,
|
|
25
|
+
authAdapter,
|
|
26
|
+
assetAdapter,
|
|
27
|
+
chatAdapter,
|
|
28
|
+
cometdAdapter,
|
|
29
|
+
emailAdapter,
|
|
30
|
+
episodeAdapter,
|
|
31
|
+
groupAdapter,
|
|
32
|
+
leaderboardAdapter,
|
|
33
|
+
presenceAdapter,
|
|
34
|
+
projectAdapter,
|
|
35
|
+
recaptchaAdapter,
|
|
36
|
+
runAdapter,
|
|
37
|
+
timeAdapter,
|
|
38
|
+
userAdapter,
|
|
39
|
+
vaultAdapter,
|
|
40
|
+
worldAdapter,
|
|
41
|
+
taskAdapter,
|
|
42
|
+
Channel,
|
|
43
|
+
};
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import type { UserSession } from 'utils/identification';
|
|
2
|
+
import type { RoutingOptions, GenericSearchOptions } from 'utils/router';
|
|
3
|
+
import type { GenericScope } from 'utils/constants';
|
|
4
|
+
|
|
5
|
+
import { identification, Router } from 'utils';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
interface Score {
|
|
9
|
+
name: string,
|
|
10
|
+
quantity: number,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface Tag {
|
|
14
|
+
label: string,
|
|
15
|
+
content: string,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface Leaderboard {
|
|
19
|
+
lastUpdated: Date,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Creates a leaderboard entry.
|
|
25
|
+
* @example
|
|
26
|
+
* import { leaderboardAdapter } from 'epicenter';
|
|
27
|
+
* const leaderboard = await leaderboardAdapter.post(
|
|
28
|
+
* 'class-23-leaderboard',
|
|
29
|
+
* [{ name: 'total', quantity: 20 }, { name: 'extraCredit', quantity: 2 }],
|
|
30
|
+
* { scopeBoundary: SCOPE_BOUNDARY.GROUP, scopeKey: '0000017dd3bf540e5ada5b1e058f08f20461' },
|
|
31
|
+
* { tags: [{ label: 'role', content: 'doctor' }] }
|
|
32
|
+
* );
|
|
33
|
+
* @param collection Name of the leaderboard
|
|
34
|
+
* @param scope Scope attached to the leaderboard entry; allows for scoping
|
|
35
|
+
* @param scope.scopeBoundary Can be a couple things, commonly group, project, episode, or world
|
|
36
|
+
* @param scope.scopeKey Key of the resource defined by the scope boundary
|
|
37
|
+
* @param scope.userKey User key for the user creating the entry, if omitted will use the one in current session
|
|
38
|
+
* @param scores List of score objects
|
|
39
|
+
* @param scores[].name Name of the score
|
|
40
|
+
* @param scores[].quantity Value of the score
|
|
41
|
+
* @param [optionals] Optional arguments; pass network call options overrides here. Special arguments specific to this method are listed below if they exist.
|
|
42
|
+
* @params [optionals.tags] Tags for the leaderboard entry, helps to provide another layer of scope if needed
|
|
43
|
+
* @returns promise that resolves to the leaderboard entry created
|
|
44
|
+
*/
|
|
45
|
+
export async function update(
|
|
46
|
+
collection: string,
|
|
47
|
+
scope: { userKey?: string } & GenericScope,
|
|
48
|
+
scores: Score[],
|
|
49
|
+
optionals: { tags?: Tag[] } & RoutingOptions = {}
|
|
50
|
+
): Promise<Leaderboard> {
|
|
51
|
+
const { tags, ...routingOptions } = optionals;
|
|
52
|
+
const { scopeBoundary, scopeKey, userKey } = scope;
|
|
53
|
+
const session = identification.session as UserSession;
|
|
54
|
+
return await new Router()
|
|
55
|
+
.post('/leaderboard', {
|
|
56
|
+
body: {
|
|
57
|
+
scope: {
|
|
58
|
+
scopeBoundary,
|
|
59
|
+
scopeKey,
|
|
60
|
+
userKey: userKey ?? session?.userKey,
|
|
61
|
+
},
|
|
62
|
+
collection,
|
|
63
|
+
scores, tags,
|
|
64
|
+
},
|
|
65
|
+
...routingOptions,
|
|
66
|
+
}).then(({ body }) => body);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Gathers leaderboard information; not paginable (hence named 'list' and not 'query'). Technically there is no leader
|
|
71
|
+
* @example
|
|
72
|
+
* import { leaderboardAdapter } from 'epicenter';
|
|
73
|
+
* const leaderboard = await leaderboardAdapter.list('myLeaderboard', scope, {
|
|
74
|
+
* filter: [
|
|
75
|
+
* 'tag.role=doctor', // look for leaderboard entries tagged with role=doctor
|
|
76
|
+
* 'score.total>0' // where the users scored a total higher than 0
|
|
77
|
+
* ],
|
|
78
|
+
* sort: ['+score.total'], // sort results by 'total' in ascending order,
|
|
79
|
+
* first: 0,
|
|
80
|
+
* max: 20 // retrieve only the first 20 entries
|
|
81
|
+
* });
|
|
82
|
+
* @param collection Name of the leaderboard
|
|
83
|
+
* @param scope Scope attached to the leaderboard entry; allows for scoping
|
|
84
|
+
* @param scope.scopeBoundary Can be a couple things, commonly group, project, episode, or world
|
|
85
|
+
* @param scope.scopeKey Key of the resource defined by the scope boundary
|
|
86
|
+
* @param searchOptions Search options for the query
|
|
87
|
+
* @param [searchOptions.filter] Filters for searching
|
|
88
|
+
* @param [searchOptions.sort] Sorting criteria
|
|
89
|
+
* @param [searchOptions.first] The starting index of the list returned
|
|
90
|
+
* @param [searchOptions.max] The maximum number of entries in the list
|
|
91
|
+
* @param [optionals] Optional arguments; pass network call options overrides here.
|
|
92
|
+
* @returns promise that resolves to to a list of leaderboard entries
|
|
93
|
+
*/
|
|
94
|
+
export async function list(
|
|
95
|
+
collection: string,
|
|
96
|
+
scope: GenericScope,
|
|
97
|
+
searchOptions: GenericSearchOptions,
|
|
98
|
+
optionals: RoutingOptions = {}
|
|
99
|
+
): Promise<Leaderboard[]> {
|
|
100
|
+
const { scopeBoundary, scopeKey } = scope;
|
|
101
|
+
const { filter = [], sort = [], first, max } = searchOptions;
|
|
102
|
+
const searchParams = {
|
|
103
|
+
filter: filter.join(';') || undefined,
|
|
104
|
+
sort: sort.join(';') || undefined,
|
|
105
|
+
first, max,
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
return await new Router()
|
|
109
|
+
.withSearchParams(searchParams)
|
|
110
|
+
.get(`/leaderboard/${scopeBoundary}/${scopeKey}/${collection}`, optionals)
|
|
111
|
+
.then(({ body }) => body);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export async function get(
|
|
115
|
+
collection: string,
|
|
116
|
+
scope: GenericScope,
|
|
117
|
+
searchOptions: GenericSearchOptions,
|
|
118
|
+
optionals: RoutingOptions = {}
|
|
119
|
+
): Promise<Leaderboard[]> {
|
|
120
|
+
console.warn('DEPRECATION WARNING: leaderboardAdapter.get is deprecated and will be removed with the next release. Use leaderboardAdapter.list instead.');
|
|
121
|
+
return await list(collection, scope, searchOptions, optionals);
|
|
122
|
+
}
|