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.
- package/CHANGELOG.md +17 -0
- package/dist/browser/epicenter.js +105 -2
- package/dist/browser/epicenter.js.map +1 -1
- package/dist/cjs/epicenter.js +105 -2
- package/dist/cjs/epicenter.js.map +1 -1
- package/dist/epicenter.js +105 -2
- package/dist/epicenter.js.map +1 -1
- package/dist/epicenter.min.js +1 -1
- package/dist/epicenter.min.js.map +1 -1
- package/dist/module/epicenter.js +105 -2
- package/dist/module/epicenter.js.map +1 -1
- package/dist/types/adapters/chat.d.ts +63 -0
- package/package.json +1 -1
- package/src/adapters/chat.ts +95 -0
- package/src/utils/identification.ts +4 -0
- package/dist/test/_virtual/runtime.js +0 -3
- package/dist/test/_virtual/runtime2.js +0 -3
- package/dist/test/adapters/account.js +0 -169
- package/dist/test/adapters/admin.js +0 -53
- package/dist/test/adapters/asset.js +0 -425
- package/dist/test/adapters/authentication.js +0 -349
- package/dist/test/adapters/channel.js +0 -201
- package/dist/test/adapters/chat.js +0 -199
- package/dist/test/adapters/cometd.js +0 -514
- package/dist/test/adapters/consensus.js +0 -484
- package/dist/test/adapters/daily.js +0 -244
- package/dist/test/adapters/email.js +0 -179
- package/dist/test/adapters/episode.js +0 -175
- package/dist/test/adapters/group.js +0 -655
- package/dist/test/adapters/leaderboard.js +0 -162
- package/dist/test/adapters/matchmaker.js +0 -159
- package/dist/test/adapters/presence.js +0 -85
- package/dist/test/adapters/project.js +0 -94
- package/dist/test/adapters/recaptcha.js +0 -24
- package/dist/test/adapters/run.js +0 -1008
- package/dist/test/adapters/somebody.js +0 -154
- package/dist/test/adapters/task.js +0 -192
- package/dist/test/adapters/time.js +0 -28
- package/dist/test/adapters/user.js +0 -105
- package/dist/test/adapters/vault.js +0 -403
- package/dist/test/adapters/video.js +0 -249
- package/dist/test/adapters/vonage.js +0 -130
- package/dist/test/adapters/wallet.js +0 -130
- package/dist/test/adapters/world.js +0 -507
- package/dist/test/apis/video.js +0 -294
- package/dist/test/apis/vonage.js +0 -121
- package/dist/test/epicenter.js +0 -121
- package/dist/test/node_modules/@babel/runtime/helpers/esm/defineProperty.js +0 -12
- package/dist/test/node_modules/@babel/runtime/helpers/esm/toPrimitive.js +0 -14
- package/dist/test/node_modules/@babel/runtime/helpers/esm/toPropertyKey.js +0 -9
- package/dist/test/node_modules/@babel/runtime/helpers/esm/typeof.js +0 -11
- package/dist/test/node_modules/cometd/AckExtension.js +0 -91
- package/dist/test/node_modules/cometd/CallbackPollingTransport.js +0 -148
- package/dist/test/node_modules/cometd/Client.js +0 -2160
- package/dist/test/node_modules/cometd/Extension.js +0 -47
- package/dist/test/node_modules/cometd/LongPollingTransport.js +0 -135
- package/dist/test/node_modules/cometd/ReloadExtension.js +0 -214
- package/dist/test/node_modules/cometd/RequestTransport.js +0 -252
- package/dist/test/node_modules/cometd/Transport.js +0 -167
- package/dist/test/node_modules/cometd/TransportRegistry.js +0 -107
- package/dist/test/node_modules/cometd/WebSocketTransport.js +0 -384
- package/dist/test/node_modules/cometd/cometd.js +0 -9
- package/dist/test/node_modules/regenerator-runtime/runtime.js +0 -773
- package/dist/test/utilities.js +0 -17
- package/dist/test/utils/config.js +0 -189
- package/dist/test/utils/constants.js +0 -293
- package/dist/test/utils/cookies.js +0 -75
- package/dist/test/utils/error-manager.js +0 -57
- package/dist/test/utils/error.js +0 -12
- package/dist/test/utils/fault.js +0 -34
- package/dist/test/utils/filter-parser.js +0 -68
- package/dist/test/utils/helpers.js +0 -9
- package/dist/test/utils/identification.js +0 -161
- package/dist/test/utils/result.js +0 -20
- package/dist/test/utils/router.js +0 -551
- package/dist/test/utils/store.js +0 -79
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
import { ROLE } from '../utils/constants.js';
|
|
2
|
-
import '../utils/helpers.js';
|
|
3
|
-
import Fault from '../utils/fault.js';
|
|
4
|
-
import '../utils/config.js';
|
|
5
|
-
import '../utils/identification.js';
|
|
6
|
-
import '../utils/error-manager.js';
|
|
7
|
-
import Router from '../utils/router.js';
|
|
8
|
-
import { getDirectoryURL, getURL } from './video.js';
|
|
9
|
-
|
|
10
|
-
const sleep = ms => new Promise(r => setTimeout(r, ms));
|
|
11
|
-
const randRange = (min, max) => {
|
|
12
|
-
return min + Math.random() * (max - min);
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
/* eslint-disable no-magic-numbers */
|
|
16
|
-
const RETRY_RANGES = [[6000, 10000], [11000, 20000], [30000, 45000]];
|
|
17
|
-
/* eslint-enable no-magic-numbers */
|
|
18
|
-
|
|
19
|
-
const RATE_LIMIT_REACHED = 429;
|
|
20
|
-
async function handleRateLimit(requestFunction, retryNumber = 0) {
|
|
21
|
-
let response;
|
|
22
|
-
try {
|
|
23
|
-
response = await requestFunction();
|
|
24
|
-
} catch (error) {
|
|
25
|
-
if (error instanceof Fault && error.status === RATE_LIMIT_REACHED && retryNumber <= RETRY_RANGES.length) {
|
|
26
|
-
const [min, max] = RETRY_RANGES[retryNumber];
|
|
27
|
-
await sleep(randRange(min, max));
|
|
28
|
-
response = await handleRateLimit(requestFunction, retryNumber + 1);
|
|
29
|
-
} else {
|
|
30
|
-
throw error;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return response;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Gets the daily configuration for the epicenter account. Requires Support auth
|
|
38
|
-
*
|
|
39
|
-
* Base URL: GET `https://forio.com/api/v3/{ACCOUNT}/{PROJECT}/daily/v1`
|
|
40
|
-
*
|
|
41
|
-
* @example
|
|
42
|
-
* import { dailyAdapter } from 'epicenter-libs';
|
|
43
|
-
* const config = await dailyAdapter.getConfig();
|
|
44
|
-
*
|
|
45
|
-
* @param [optionals] Optional arguments; pass network call options overrides here.
|
|
46
|
-
* @returns promise that resolves to the daily object
|
|
47
|
-
*/
|
|
48
|
-
async function getConfig(optionals = {}
|
|
49
|
-
// TODO: investigate actual return type
|
|
50
|
-
) {
|
|
51
|
-
return await new Router().get('/daily/v1', optionals).then(({
|
|
52
|
-
body
|
|
53
|
-
}) => body);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Creates a new daily meeting room
|
|
58
|
-
* Base URL: POST `https://forio.com/api/v3/{ACCOUNT}/{PROJECT}/daily/v1/room`
|
|
59
|
-
*
|
|
60
|
-
* @example
|
|
61
|
-
* import { dailyAdapter, SCOPE_BOUNDARY } from 'epicenter-libs';
|
|
62
|
-
* const room = await dailyAdapter.createRoom({
|
|
63
|
-
* scopeBoundary: SCOPE_BOUNDARY.GROUP,
|
|
64
|
-
* scopeKey: '0000017dd3bf540e5ada5b1e058f08f20461'
|
|
65
|
-
* });
|
|
66
|
-
*
|
|
67
|
-
* @param scope Scope associated with your room
|
|
68
|
-
* @param scope.scopeBoundary Scope boundary, defines the type of scope; See [scope boundary](#SCOPE_BOUNDARY) for all types
|
|
69
|
-
* @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.
|
|
70
|
-
* @param [scope.userKey] Optional key to scope the room to a user
|
|
71
|
-
* @param [optionals] Optional arguments; pass network call options overrides here. Special arguments specific to this method are listed below if they exist.
|
|
72
|
-
* @param [optionals.readLock] Role allowed to read
|
|
73
|
-
* @param [optionals.writeLock] Role allowed to write
|
|
74
|
-
* @param [optionals.ttlSeconds] Life span of any recording made (how long before it is deleted); defaults to 604,800 (1 week), max of 31,536,000 (1 year)
|
|
75
|
-
* @param [optionals.privacy] Whether the room is private or not; currently can only be set to PRIVATE
|
|
76
|
-
* @param [optionals.exp] When the room will be deleted in epoch seconds. Defaults to 24 hours. Max of 24 hours.
|
|
77
|
-
* @param [optionals.enable_recording] The type of Daily recording method to use. Only CLOUD is currently permitted.
|
|
78
|
-
* @param [optionals.streaming_endpoints] Details for daily streaming features.
|
|
79
|
-
* @param [optionals.streaming_endpoints.name] Name of the stream
|
|
80
|
-
* @param [optionals.streaming_endpoints.type] Type of the stream; only HLS is currently permitted
|
|
81
|
-
* @param [optionals.streaming_endpoints.hls_config] Options for hls stream
|
|
82
|
-
* @param [optionals.streaming_endpoints.hls_config.save_hls_recording] Whether or not to record the hls stream
|
|
83
|
-
* @param [optionals.streaming_endpoints.hls_config.storage] Storage details for hls stream
|
|
84
|
-
* @param [optionals.streaming_endpoints.hls_config.path] S3 storage path
|
|
85
|
-
* @param [optionals.streaming_endpoints.hls_config.bucket_region] S3 bucket region
|
|
86
|
-
* @param [optionals.streaming_endpoints.hls_config.assume_role_arn] S3 role ARN for permission to alter S3 resources
|
|
87
|
-
* @param [optionals.streaming_endpoints.hls_config.bucket_name] S3 bucket name
|
|
88
|
-
* @param [optionals.disableRateLimitHandling] Disable automatic rate limit retry handling
|
|
89
|
-
* @returns promise that resolves to the newly created room details
|
|
90
|
-
*/
|
|
91
|
-
async function createRoom(scope, optionals = {}) {
|
|
92
|
-
const {
|
|
93
|
-
readLock,
|
|
94
|
-
writeLock,
|
|
95
|
-
ttlSeconds,
|
|
96
|
-
privacy,
|
|
97
|
-
exp,
|
|
98
|
-
enable_recording,
|
|
99
|
-
streaming_endpoints,
|
|
100
|
-
disableRateLimitHandling,
|
|
101
|
-
...routingOptions
|
|
102
|
-
} = optionals;
|
|
103
|
-
const {
|
|
104
|
-
PARTICIPANT
|
|
105
|
-
} = ROLE;
|
|
106
|
-
const callAPI = async () => {
|
|
107
|
-
return await new Router().post('/daily/v1/room', {
|
|
108
|
-
body: {
|
|
109
|
-
epicenter: {
|
|
110
|
-
ttlSeconds,
|
|
111
|
-
scope,
|
|
112
|
-
permit: {
|
|
113
|
-
readLock: readLock || PARTICIPANT,
|
|
114
|
-
writeLock: writeLock || PARTICIPANT
|
|
115
|
-
}
|
|
116
|
-
},
|
|
117
|
-
properties: {
|
|
118
|
-
exp,
|
|
119
|
-
enable_recording,
|
|
120
|
-
streaming_endpoints
|
|
121
|
-
},
|
|
122
|
-
privacy
|
|
123
|
-
},
|
|
124
|
-
...routingOptions
|
|
125
|
-
}).then(({
|
|
126
|
-
body
|
|
127
|
-
}) => body);
|
|
128
|
-
};
|
|
129
|
-
return handleRateLimit(callAPI, disableRateLimitHandling ? RETRY_RANGES.length + 1 : 0);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Creates a token for a daily meeting room
|
|
134
|
-
* Base URL: POST `https://forio.com/api/v3/{ACCOUNT}/{PROJECT}/daily/v1/meetingToken`
|
|
135
|
-
*
|
|
136
|
-
* @example
|
|
137
|
-
* import { dailyAdapter } from 'epicenter-libs';
|
|
138
|
-
* const token = await dailyAdapter.createToken('my-room-name');
|
|
139
|
-
*
|
|
140
|
-
* @param room_name Name of the room to create a token for
|
|
141
|
-
* @param [optionals] Optional arguments; pass network call options overrides here. Special arguments specific to this method are listed below if they exist.
|
|
142
|
-
* @param [optionals.start_video_off] Whether the user should have their video off upon joining the meeting; defaults to true.
|
|
143
|
-
* @param [optionals.is_owner] Whether the user has owner permissions; owner permissions are required to start a stream (not a recording); defaults to false
|
|
144
|
-
* @param [optionals.user_name] Username to display in daily's system. This is relevant if the daily call is open in a separate window
|
|
145
|
-
* @param [optionals.close_tab_on_exit] Whether to close the tab on the end of the call. This is relevant if the daily call is open in a separate window
|
|
146
|
-
* @param [optionals.exp] When the token will be deleted in epoch seconds. Defaults to 24 hours. Max of 24 hours.
|
|
147
|
-
* @param [optionals.enable_recording] The type of Daily recording method to permit. Only CLOUD is currently permitted.
|
|
148
|
-
* @param [optionals.disableRateLimitHandling] Disable automatic rate limit retry handling
|
|
149
|
-
* @param [optionals.selfSign] Whether to self-sign the token; defaults to true
|
|
150
|
-
* @returns promise that resolves to the newly created token details
|
|
151
|
-
*/
|
|
152
|
-
async function createToken(room_name, optionals = {}) {
|
|
153
|
-
const {
|
|
154
|
-
start_video_off,
|
|
155
|
-
is_owner,
|
|
156
|
-
user_name,
|
|
157
|
-
close_tab_on_exit,
|
|
158
|
-
exp,
|
|
159
|
-
enable_recording,
|
|
160
|
-
disableRateLimitHandling,
|
|
161
|
-
selfSign = true,
|
|
162
|
-
...routingOptions
|
|
163
|
-
} = optionals;
|
|
164
|
-
const callAPI = async () => {
|
|
165
|
-
return await new Router().withSearchParams({
|
|
166
|
-
selfSign
|
|
167
|
-
}).post('/daily/v1/meetingToken', {
|
|
168
|
-
body: {
|
|
169
|
-
properties: {
|
|
170
|
-
room_name,
|
|
171
|
-
start_video_off,
|
|
172
|
-
is_owner,
|
|
173
|
-
user_name,
|
|
174
|
-
close_tab_on_exit,
|
|
175
|
-
exp,
|
|
176
|
-
enable_recording
|
|
177
|
-
}
|
|
178
|
-
},
|
|
179
|
-
...routingOptions
|
|
180
|
-
}).then(({
|
|
181
|
-
body
|
|
182
|
-
}) => body);
|
|
183
|
-
};
|
|
184
|
-
return handleRateLimit(callAPI, disableRateLimitHandling ? RETRY_RANGES.length + 1 : 0);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Convenience function for retrieving the most recent recording for a Daily room
|
|
189
|
-
*
|
|
190
|
-
* @example
|
|
191
|
-
* import { dailyAdapter, SCOPE_BOUNDARY } from 'epicenter-libs';
|
|
192
|
-
* const videoUrl = await dailyAdapter.getVideoByRecordingId('my-room', 'recording_instance_id', {
|
|
193
|
-
* scopeBoundary: SCOPE_BOUNDARY.GROUP,
|
|
194
|
-
* scopeKey: '0000017dd3bf540e5ada5b1e058f08f20461'
|
|
195
|
-
* });
|
|
196
|
-
*
|
|
197
|
-
* @param room_name Name of the room
|
|
198
|
-
* @param recordingId Recording instance ID
|
|
199
|
-
* @param scope Scope associated with the room
|
|
200
|
-
* @param scope.scopeBoundary Scope boundary, defines the type of scope; See [scope boundary](#SCOPE_BOUNDARY) for all types
|
|
201
|
-
* @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.
|
|
202
|
-
* @param [scope.userKey] Optional key to scope the room to a user
|
|
203
|
-
* @param [optionals] Optional arguments; pass network call options overrides here.
|
|
204
|
-
* @returns promise that resolves to a url if a video exists or null if it does not
|
|
205
|
-
*/
|
|
206
|
-
async function getVideoByRecordingId(room_name, recordingId, scope, optionals = {}) {
|
|
207
|
-
const filePathInfo = await getDirectoryURL({
|
|
208
|
-
scope,
|
|
209
|
-
affiliate: 'DAILY',
|
|
210
|
-
family: room_name,
|
|
211
|
-
...optionals
|
|
212
|
-
});
|
|
213
|
-
const filePaths = filePathInfo.contents;
|
|
214
|
-
if (!(filePaths !== null && filePaths !== void 0 && filePaths.length)) return null;
|
|
215
|
-
filePaths.sort((a, b) => Number(b.split('.')[0]) - Number(a.split('.')[0]));
|
|
216
|
-
const filePath = filePaths.find(p => p.includes(recordingId) && p.includes('.mp4'));
|
|
217
|
-
if (!filePath) return null;
|
|
218
|
-
return await getURL(filePath, {
|
|
219
|
-
scope,
|
|
220
|
-
affiliate: 'DAILY',
|
|
221
|
-
family: room_name,
|
|
222
|
-
...optionals
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Sets the daily family/room to a recording status of recorded; necessary to prevent videos from deleting automatically within 1 hour
|
|
228
|
-
* Base URL: DELETE `https://forio.com/api/v3/{ACCOUNT}/{PROJECT}/daily/v1/meetingToken/{ROOM_NAME}`
|
|
229
|
-
*
|
|
230
|
-
* @example
|
|
231
|
-
* import { dailyAdapter } from 'epicenter-libs';
|
|
232
|
-
* const success = await dailyAdapter.updateRecordingStatus('my-room');
|
|
233
|
-
*
|
|
234
|
-
* @param room_name Name of the room
|
|
235
|
-
* @param [optionals] Optional arguments; pass network call options overrides here.
|
|
236
|
-
* @returns promise that resolves to true if successful
|
|
237
|
-
*/
|
|
238
|
-
async function updateRecordingStatus(room_name, optionals = {}) {
|
|
239
|
-
return await new Router().delete(`/daily/v1/meetingToken/${room_name}`, optionals).then(({
|
|
240
|
-
body
|
|
241
|
-
}) => body);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
export { createRoom, createToken, getConfig, getVideoByRecordingId, updateRecordingStatus };
|
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
import Router from '../utils/router.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Sends an email to an individual user; requires following authentication levels:
|
|
5
|
-
* - /email/user/{groupKey}/{userKey} - PARTICIPANT
|
|
6
|
-
* - /email/user/{groupKey}/{userKey}/from/{from} - REVIEWER
|
|
7
|
-
* - /email/user/{groupKey}/{userKey}/from/{from}/{replyTo} - REVIEWER
|
|
8
|
-
* - /email/user/{groupKey}/{userKey}/as/{fromUserKey} - REVIEWER
|
|
9
|
-
* Base URL: POST `https://forio.com/api/v3/{ACCOUNT}/{PROJECT}/email/user/{GROUP_KEY}/{USER_KEY}` or POST `https://forio.com/api/v3/{ACCOUNT}/{PROJECT}/email/user/{GROUP_KEY}/{USER_KEY}/from/{FROM}` or POST `https://forio.com/api/v3/{ACCOUNT}/{PROJECT}/email/user/{GROUP_KEY}/{USER_KEY}/from/{FROM}/{REPLY_TO}` or POST `https://forio.com/api/v3/{ACCOUNT}/{PROJECT}/email/user/{GROUP_KEY}/{USER_KEY}/as/{FROM_USER_KEY}`
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* import { emailAdapter, authAdapter } from 'epicenter-libs';
|
|
13
|
-
* // Sends an email with a smiley face png attachment
|
|
14
|
-
* const groupKey = authAdapter.getLocalSession().groupKey;
|
|
15
|
-
* const subject = 'check out this drawing!';
|
|
16
|
-
* const emailBody = 'I hope you enjoy this smiley face!';
|
|
17
|
-
* const attachments = [{
|
|
18
|
-
* encoding: 'BASE_64',
|
|
19
|
-
* name: 'testPic',
|
|
20
|
-
* contentType: 'image/png',
|
|
21
|
-
* data: 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAIxJREFUWEdjZBhgwDjA9jMQ5YAvzmb/efaewquWGDXYPDvqgNEQGA2B0RAYGiFAy+KaqBAYdcDICgFQtQryMaHql1qhgjURklu3IzuKWDNwOoCSUCAlFHFmQ2J9gB4VpFgO0kvVZhaplhPlAJgPCSVKciwn6ACY5TDD8aV8Qg7EpXe0KB4NgdEQGA0BAF7VgCFTeobfAAAAAElFTkSuQmCC',
|
|
22
|
-
* }];
|
|
23
|
-
*
|
|
24
|
-
* // Sends an email to the address associated with the provided user key, sender will be seen as "System"
|
|
25
|
-
* await emailAdapter.sendEmail(groupKey, '000001796733eef0842f4d6d960997018a3b', subject, emailBody, { attachments });
|
|
26
|
-
* // Sends an email to the address associated with the provided user key, sender will be seen as the address provided by the "from" field
|
|
27
|
-
* await emailAdapter.sendEmail(groupKey, '000001796733eef0842f4d6d960997018a3b', subject, emailBody, { attachments, from: 'sender@test.com' });
|
|
28
|
-
* // Sends an email to the address defined at "replyTo", sender will be seen as the address provided by the "from" field
|
|
29
|
-
* await emailAdapter.sendEmail(groupKey, '000001796733eef0842f4d6d960997018a3b', subject, emailBody, { attachments, from: 'sender@test.com', replyTo: 'receiver@test.com' });
|
|
30
|
-
* // Sends an email to the address associated with the provided user key, sender will be seen as the user associated with the "fromUserKey"
|
|
31
|
-
* await emailAdapter.sendEmail(groupKey, '000001796733eef0842f4d6d960997018a3b', subject, emailBody, { attachments, fromUserKey: '000001796733eef0842f4d6d960997018a33' });
|
|
32
|
-
*
|
|
33
|
-
* @param groupKey The groupKey in which the email target user exists
|
|
34
|
-
* @param userKey The unique userKey for the email target user
|
|
35
|
-
* @param subject The subject line for the email.
|
|
36
|
-
* @param emailBody The body for the email
|
|
37
|
-
* @param [optionals] Optional parameters
|
|
38
|
-
* @param [optionals.familyNameFirst] Specifies whether email target's family name will come before their given name. Defaults to false.
|
|
39
|
-
* @param [optionals.html] Whether to treat the body as HTML (true) or as plain text (false). Defaults to false.
|
|
40
|
-
* @param [optionals.from] The email address from which the message will appear to have been sent from. Will be overridden by fromUserKey.
|
|
41
|
-
* @param [optionals.replyTo] The email address that will be replied to by the recipient. Must be used in conjunction with optionals.from.
|
|
42
|
-
* @param [optionals.fromUserKey] The userKey from which the email will appear to have been sent. The default response address will also be this email.
|
|
43
|
-
* @param [optionals.attachments] An array of (binary) objects to include as attachments. All four properties must be included.
|
|
44
|
-
* @param [optionals.attachments[].encoding] A string specifying the encoding method. See ENCODING for possible values.
|
|
45
|
-
* @param [optionals.attachments[].data] A string containing the data for the attachment.
|
|
46
|
-
* @param [optionals.attachments[].name] A string containing the name of the attachment.
|
|
47
|
-
* @param [optionals.attachments[].contentType] A string specifying the attachment MIME Type.
|
|
48
|
-
* @returns undefined indicating success
|
|
49
|
-
*/
|
|
50
|
-
async function sendEmail(groupKey, userKey, subject, emailBody, optionals = {}) {
|
|
51
|
-
const {
|
|
52
|
-
accountShortName,
|
|
53
|
-
projectShortName,
|
|
54
|
-
server,
|
|
55
|
-
familyNameFirst,
|
|
56
|
-
html,
|
|
57
|
-
from,
|
|
58
|
-
replyTo,
|
|
59
|
-
fromUserKey,
|
|
60
|
-
attachments,
|
|
61
|
-
...routingOptions
|
|
62
|
-
} = optionals;
|
|
63
|
-
let fromString = '';
|
|
64
|
-
if (fromUserKey) {
|
|
65
|
-
fromString += `/as/${fromUserKey}`;
|
|
66
|
-
} else if (from) {
|
|
67
|
-
fromString += `/from/${from}`;
|
|
68
|
-
if (replyTo) {
|
|
69
|
-
fromString += `/${replyTo}`;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
return await new Router().withServer(server).withAccountShortName(accountShortName).withProjectShortName(projectShortName).post(`/email/user/${groupKey}/${userKey}${fromString}`, {
|
|
73
|
-
body: {
|
|
74
|
-
subject,
|
|
75
|
-
body: emailBody,
|
|
76
|
-
familyNameFirst,
|
|
77
|
-
html,
|
|
78
|
-
attachments
|
|
79
|
-
},
|
|
80
|
-
...routingOptions
|
|
81
|
-
}).then(({
|
|
82
|
-
body
|
|
83
|
-
}) => body);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Sends an email to an individual admin (someone with epicenter account); Requires support level authentication
|
|
88
|
-
* Base URL: POST `https://forio.com/api/v3/{ACCOUNT}/{PROJECT}/email/admin/{ADMIN_KEY}`
|
|
89
|
-
*
|
|
90
|
-
* @example
|
|
91
|
-
* import { emailAdapter } from 'epicenter-libs';
|
|
92
|
-
* await emailAdapter.sendEmailToAdmin('adminKey123', 'Subject Line', 'Email body content');
|
|
93
|
-
*
|
|
94
|
-
* @param adminKey The unique adminKey for the email target
|
|
95
|
-
* @param subject The subject line for the email.
|
|
96
|
-
* @param emailBody The body for the email
|
|
97
|
-
* @param [optionals] Optional parameters
|
|
98
|
-
* @param [optionals.familyNameFirst] Specifies whether email target's family name will come before their given name. Defaults to false.
|
|
99
|
-
* @param [optionals.html] Whether to treat the body as HTML (true) or as plain text (false). Defaults to false.
|
|
100
|
-
* @param [optionals.attachments] An array of (binary) objects to include as attachments. All four properties must be included.
|
|
101
|
-
* @param [optionals.attachments[].encoding] A string specifying the encoding method. See ENCODING for possible values.
|
|
102
|
-
* @param [optionals.attachments[].data] A string containing the data for the attachment.
|
|
103
|
-
* @param [optionals.attachments[].name] A string containing the name of the attachment.
|
|
104
|
-
* @param [optionals.attachments[].contentType] A string specifying the attachment MIME Type.
|
|
105
|
-
* @returns undefined indicating success
|
|
106
|
-
*/
|
|
107
|
-
async function sendEmailToAdmin(adminKey, subject, emailBody, optionals = {}) {
|
|
108
|
-
const {
|
|
109
|
-
accountShortName,
|
|
110
|
-
projectShortName,
|
|
111
|
-
server,
|
|
112
|
-
familyNameFirst,
|
|
113
|
-
html,
|
|
114
|
-
attachments,
|
|
115
|
-
...routingOptions
|
|
116
|
-
} = optionals;
|
|
117
|
-
return await new Router().withServer(server).withAccountShortName(accountShortName).withProjectShortName(projectShortName).post(`/email/admin/${adminKey}`, {
|
|
118
|
-
body: {
|
|
119
|
-
subject,
|
|
120
|
-
body: emailBody,
|
|
121
|
-
familyNameFirst,
|
|
122
|
-
html,
|
|
123
|
-
attachments
|
|
124
|
-
},
|
|
125
|
-
...routingOptions
|
|
126
|
-
}).then(({
|
|
127
|
-
body
|
|
128
|
-
}) => body);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Sends an email to Epicenter support; Requires participant authentication
|
|
133
|
-
* Base URL: POST `https://forio.com/api/v3/{ACCOUNT}/{PROJECT}/email/to/support`
|
|
134
|
-
*
|
|
135
|
-
* @example
|
|
136
|
-
* import { emailAdapter } from 'epicenter-libs';
|
|
137
|
-
* await emailAdapter.sendEmailToSupport('Help Request', 'I need assistance with my project');
|
|
138
|
-
*
|
|
139
|
-
* @param subject The subject line for the email.
|
|
140
|
-
* @param emailBody The body for the email
|
|
141
|
-
* @param [optionals] Optional parameters
|
|
142
|
-
* @param [optionals.supportType] A string indicating the type of support request
|
|
143
|
-
* @param [optionals.familyNameFirst] Specifies whether email target's family name will come before their given name. Defaults to false.
|
|
144
|
-
* @param [optionals.html] Whether to treat the body as HTML (true) or as plain text (false). Defaults to false.
|
|
145
|
-
* @param [optionals.attachments] An array of (binary) objects to include as attachments. All four properties must be included.
|
|
146
|
-
* @param [optionals.attachments[].encoding] A string specifying the encoding method. See ENCODING for possible values.
|
|
147
|
-
* @param [optionals.attachments[].data] A string containing the data for the attachment.
|
|
148
|
-
* @param [optionals.attachments[].name] A string containing the name of the attachment.
|
|
149
|
-
* @param [optionals.attachments[].contentType] A string specifying the attachment MIME Type.
|
|
150
|
-
* @returns undefined indicating success
|
|
151
|
-
*/
|
|
152
|
-
async function sendEmailToSupport(subject, emailBody, optionals = {}) {
|
|
153
|
-
const {
|
|
154
|
-
accountShortName,
|
|
155
|
-
projectShortName,
|
|
156
|
-
server,
|
|
157
|
-
supportType,
|
|
158
|
-
familyNameFirst,
|
|
159
|
-
html,
|
|
160
|
-
attachments,
|
|
161
|
-
...routingOptions
|
|
162
|
-
} = optionals;
|
|
163
|
-
return await new Router().withServer(server).withAccountShortName(accountShortName).withProjectShortName(projectShortName).withSearchParams({
|
|
164
|
-
supportType
|
|
165
|
-
}).post('/email/to/support', {
|
|
166
|
-
body: {
|
|
167
|
-
subject,
|
|
168
|
-
body: emailBody,
|
|
169
|
-
familyNameFirst,
|
|
170
|
-
html,
|
|
171
|
-
attachments
|
|
172
|
-
},
|
|
173
|
-
...routingOptions
|
|
174
|
-
}).then(({
|
|
175
|
-
body
|
|
176
|
-
}) => body);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
export { sendEmail, sendEmailToAdmin, sendEmailToSupport };
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
import '../utils/helpers.js';
|
|
2
|
-
import { parseFilterInput } from '../utils/filter-parser.js';
|
|
3
|
-
import '../utils/config.js';
|
|
4
|
-
import identification from '../utils/identification.js';
|
|
5
|
-
import '../utils/error-manager.js';
|
|
6
|
-
import Router from '../utils/router.js';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Create an episode.
|
|
10
|
-
* Base URL: POST `https://forio.com/api/v3/{ACCOUNT}/{PROJECT}/episode/{GROUP_NAME}`
|
|
11
|
-
*
|
|
12
|
-
* @example
|
|
13
|
-
* import { episodeAdapter } from 'epicenter-libs';
|
|
14
|
-
* const episode = await episodeAdapter.create('myEpisode', 'myGroupName', {
|
|
15
|
-
* runLimit: 20,
|
|
16
|
-
* draft: true,
|
|
17
|
-
* });
|
|
18
|
-
*
|
|
19
|
-
* @param name Episode name
|
|
20
|
-
* @param groupName Group to make the episode under
|
|
21
|
-
* @param [optionals] Optional arguments; pass network call options overrides here. Special arguments specific to this method are listed below if they exist.
|
|
22
|
-
* @param [optionals.draft] Flag to indicate the episode is a draft (intended when used for settings scoping)
|
|
23
|
-
* @param [optionals.runLimit] Optional argument to define the number of runs that can be made using this episode as the scope
|
|
24
|
-
* @param [optionals.category] Optional argument to allow for establishing episode hierarchies
|
|
25
|
-
* @returns promise that resolves to the newly created episode
|
|
26
|
-
*/
|
|
27
|
-
async function create(name, groupName, optionals = {}) {
|
|
28
|
-
const {
|
|
29
|
-
draft,
|
|
30
|
-
runLimit,
|
|
31
|
-
category,
|
|
32
|
-
...routingOptions
|
|
33
|
-
} = optionals;
|
|
34
|
-
return await new Router().post(`/episode/${groupName}`, {
|
|
35
|
-
body: {
|
|
36
|
-
name,
|
|
37
|
-
draft,
|
|
38
|
-
runLimit,
|
|
39
|
-
category
|
|
40
|
-
},
|
|
41
|
-
...routingOptions
|
|
42
|
-
}).then(({
|
|
43
|
-
body
|
|
44
|
-
}) => body);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Gets a specific episode.
|
|
49
|
-
* Base URL: GET `https://forio.com/api/v3/{ACCOUNT}/{PROJECT}/episode/{EPISODE_KEY}`
|
|
50
|
-
*
|
|
51
|
-
* @example
|
|
52
|
-
* import { episodeAdapter } from 'epicenter-libs';
|
|
53
|
-
* const episode = await episodeAdapter.get('000001796733eef0842f4d6d960997018a37');
|
|
54
|
-
*
|
|
55
|
-
* @param episodeKey The episode key
|
|
56
|
-
* @param [optionals] Optional arguments; pass network call options overrides here.
|
|
57
|
-
* @returns promise that resolves to an episode
|
|
58
|
-
*/
|
|
59
|
-
async function get(episodeKey, optionals = {}) {
|
|
60
|
-
return await new Router().get(`/episode/${episodeKey}`, optionals).then(({
|
|
61
|
-
body
|
|
62
|
-
}) => body);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Gets episodes.
|
|
67
|
-
* Base URL: GET `https://forio.com/api/v3/{ACCOUNT}/{PROJECT}/episode/search`
|
|
68
|
-
*
|
|
69
|
-
* @example
|
|
70
|
-
* import { episodeAdapter } from 'epicenter-libs';
|
|
71
|
-
* const filter = [
|
|
72
|
-
* 'name|=one|two', // searches only for episodes named 'one' or 'two'
|
|
73
|
-
* 'draft=false', // searches only for episodes that aren't drafts
|
|
74
|
-
* 'created>=2022-01-03T20:30:53.054Z', // looks for any episodes created after Jan 3rd 2022
|
|
75
|
-
* 'account.shortName=acme', // specifies the account, intended for admin use
|
|
76
|
-
* 'project.shortName=simulations', // specifies the project, intended for admin use
|
|
77
|
-
* 'group.name=my-group-name', // specifies a group name, intended for admin use
|
|
78
|
-
* 'group.groupKey=0000017dd3bf540e5ada5b1e058f08f20461', // specifies a group key, intended for admin use
|
|
79
|
-
* ];
|
|
80
|
-
* const episodes = await episodeAdapter.query({
|
|
81
|
-
* filter,
|
|
82
|
-
* sort: ['+episode.created'], // sort all findings by the 'created' field (ascending)
|
|
83
|
-
* first: 3, // page should start with the 4th item found (will default to 0)
|
|
84
|
-
* max: 10, // page should only include the first 10 items
|
|
85
|
-
* });
|
|
86
|
-
*
|
|
87
|
-
* @param searchOptions Search options for the query
|
|
88
|
-
* @param [searchOptions.filter] Filters for searching
|
|
89
|
-
* @param [searchOptions.sort] Sorting criteria
|
|
90
|
-
* @param [searchOptions.first] The starting index of the page returned
|
|
91
|
-
* @param [searchOptions.max] The number of entries per page
|
|
92
|
-
* @param [optionals] Optional arguments; pass network call options overrides here.
|
|
93
|
-
* @returns promise that resolves to a page of episodes
|
|
94
|
-
*/
|
|
95
|
-
async function query(searchOptions, optionals = {}) {
|
|
96
|
-
const {
|
|
97
|
-
filter,
|
|
98
|
-
sort = [],
|
|
99
|
-
first = 0,
|
|
100
|
-
max
|
|
101
|
-
} = searchOptions;
|
|
102
|
-
return await new Router().withSearchParams({
|
|
103
|
-
filter: parseFilterInput(filter),
|
|
104
|
-
sort: sort.join(';') || undefined,
|
|
105
|
-
first,
|
|
106
|
-
max
|
|
107
|
-
}).get('/episode/search', {
|
|
108
|
-
paginated: true,
|
|
109
|
-
...optionals
|
|
110
|
-
}).then(({
|
|
111
|
-
body
|
|
112
|
-
}) => body);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Gets episodes based on a group key
|
|
117
|
-
* Base URL: GET `https://forio.com/api/v3/{ACCOUNT}/{PROJECT}/episode/in/{GROUP_KEY}`
|
|
118
|
-
*
|
|
119
|
-
* @example
|
|
120
|
-
* import { episodeAdapter } from 'epicenter-libs';
|
|
121
|
-
* const episodes = await episodeAdapter.forGroup('0000017dd3bf540e5ada5b1e058f08f20461');
|
|
122
|
-
*
|
|
123
|
-
* @param groupKey The group key
|
|
124
|
-
* @param [optionals] Optional arguments; pass network call options overrides here.
|
|
125
|
-
* @returns promise resolving to a list of episodes
|
|
126
|
-
*/
|
|
127
|
-
async function forGroup(groupKey, optionals = {}) {
|
|
128
|
-
return await new Router().get(`/episode/in/${groupKey}`, optionals).then(({
|
|
129
|
-
body
|
|
130
|
-
}) => body);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Gets episode based on group name and episode name
|
|
135
|
-
* Base URL: GET `https://forio.com/api/v3/{ACCOUNT}/{PROJECT}/episode/with/{GROUP_NAME}/{EPISODE_NAME}`
|
|
136
|
-
*
|
|
137
|
-
* @example
|
|
138
|
-
* import { episodeAdapter } from 'epicenter-libs';
|
|
139
|
-
* const episode = await episodeAdapter.withName('myEpisodeName');
|
|
140
|
-
*
|
|
141
|
-
* @param name The episode name
|
|
142
|
-
* @param [optionals] Optional arguments; pass network call options overrides here. Special arguments specific to this method are listed below if they exist.
|
|
143
|
-
* @param [optionals.groupName] Name of the group, if omitted will use the group name associated with the current session
|
|
144
|
-
* @returns promise that resolves to an episode
|
|
145
|
-
*/
|
|
146
|
-
async function withName(name, optionals = {}) {
|
|
147
|
-
const {
|
|
148
|
-
groupName,
|
|
149
|
-
...routingOptions
|
|
150
|
-
} = optionals;
|
|
151
|
-
const session = identification.session;
|
|
152
|
-
return await new Router().get(`/episode/with/${groupName !== null && groupName !== void 0 ? groupName : session === null || session === void 0 ? void 0 : session.groupName}/${name}`, routingOptions).then(({
|
|
153
|
-
body
|
|
154
|
-
}) => body);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Deletes an episode
|
|
159
|
-
* Base URL: DELETE `https://forio.com/api/v3/{ACCOUNT}/{PROJECT}/episode/{EPISODE_KEY}`
|
|
160
|
-
*
|
|
161
|
-
* @example
|
|
162
|
-
* import { episodeAdapter } from 'epicenter-libs';
|
|
163
|
-
* await episodeAdapter.remove('000001796733eef0842f4d6d960997018a3b');
|
|
164
|
-
*
|
|
165
|
-
* @param episodeKey The episode key
|
|
166
|
-
* @param [optionals] Optional arguments; pass network call options overrides here.
|
|
167
|
-
* @returns promise that resolves to undefined if successful
|
|
168
|
-
*/
|
|
169
|
-
async function remove(episodeKey, optionals = {}) {
|
|
170
|
-
return await new Router().delete(`/episode/${episodeKey}`, optionals).then(({
|
|
171
|
-
body
|
|
172
|
-
}) => body);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
export { create, forGroup, get, query, remove, withName };
|