@prisme.ai/sdk 1.0.1 → 1.0.2
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/dist/_virtual/_tslib.js +17 -8
- package/dist/lib/ImportProcessing.d.ts +19 -0
- package/dist/lib/WorkspacesEndpoint.d.ts +10 -0
- package/dist/lib/api.d.ts +18 -3
- package/dist/lib/endpoints/users.d.ts +6 -2
- package/dist/lib/endpoints/workspaces.d.ts +16 -0
- package/dist/lib/endpoints/workspacesVersions.d.ts +2 -2
- package/dist/lib/events.d.ts +3 -1
- package/dist/lib/fetch.d.ts +2 -0
- package/dist/lib/fetcher.d.ts +2 -1
- package/dist/lib/interpolate.d.ts +2 -0
- package/dist/lib/interpolate.test.d.ts +1 -0
- package/dist/lib/interpolateVars.d.ts +2 -0
- package/dist/lib/utils.d.ts +3 -0
- package/dist/sdk/lib/ImportProcessing.js +17 -0
- package/dist/sdk/lib/WorkspacesEndpoint.js +19 -0
- package/dist/sdk/lib/api.js +86 -24
- package/dist/sdk/lib/endpoints/users.js +57 -6
- package/dist/sdk/lib/endpoints/workspaces.js +121 -0
- package/dist/sdk/lib/endpoints/workspacesVersions.js +4 -4
- package/dist/sdk/lib/events.js +40 -13
- package/dist/sdk/lib/fetch.js +12 -0
- package/dist/sdk/lib/fetcher.js +74 -36
- package/dist/sdk/lib/interpolate.js +26 -0
- package/dist/sdk/lib/interpolateVars.js +26 -0
- package/dist/sdk/lib/utils.js +48 -1
- package/lib/ImportProcessing.ts +22 -0
- package/lib/api.test.ts +20 -5
- package/lib/api.ts +111 -33
- package/lib/endpoints/users.ts +40 -4
- package/lib/endpoints/workspaces.ts +103 -0
- package/lib/endpoints/workspacesVersions.ts +13 -9
- package/lib/events.ts +54 -12
- package/lib/fetcher.ts +42 -7
- package/lib/utils.ts +39 -0
- package/package.json +2 -1
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type ImportProcessing = {
|
|
2
|
+
processing?: boolean;
|
|
3
|
+
message?: string;
|
|
4
|
+
};
|
|
5
|
+
export class ImportProcessingError extends Error {
|
|
6
|
+
error: ImportProcessing;
|
|
7
|
+
constructor(error: ImportProcessing) {
|
|
8
|
+
super();
|
|
9
|
+
this.error = error;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export type ImportSuccess = {
|
|
13
|
+
createdWorkspaceIds?: string[];
|
|
14
|
+
updatedWorkspaceIds?: string[];
|
|
15
|
+
imported: string[];
|
|
16
|
+
errors?: {
|
|
17
|
+
[name: string]: any;
|
|
18
|
+
}[];
|
|
19
|
+
workspace?: Prismeai.DSULReadOnly;
|
|
20
|
+
publishedApps?: Prismeai.App[];
|
|
21
|
+
deleted?: string[];
|
|
22
|
+
};
|
package/lib/api.test.ts
CHANGED
|
@@ -47,11 +47,7 @@ it('should call /login/anonymous', async () => {
|
|
|
47
47
|
const api = new Api({ host: '/fake/' });
|
|
48
48
|
api.post = jest.fn();
|
|
49
49
|
const user = await api.createAnonymousSession();
|
|
50
|
-
expect(api.post).toHaveBeenCalledWith(
|
|
51
|
-
'/login/anonymous',
|
|
52
|
-
{},
|
|
53
|
-
{ credentials: 'omit' }
|
|
54
|
-
);
|
|
50
|
+
expect(api.post).toHaveBeenCalledWith('/login/anonymous');
|
|
55
51
|
expect(api.user).toBe(user);
|
|
56
52
|
});
|
|
57
53
|
|
|
@@ -706,6 +702,25 @@ it('should call automation', () => {
|
|
|
706
702
|
);
|
|
707
703
|
});
|
|
708
704
|
|
|
705
|
+
it('should get automation from url', () => {
|
|
706
|
+
api.host = 'https://host.com';
|
|
707
|
+
expect(api.getAutomationFromUrl('13234', 'https://www.prisme.ai')).toBe(
|
|
708
|
+
false
|
|
709
|
+
);
|
|
710
|
+
expect(
|
|
711
|
+
api.getAutomationFromUrl(
|
|
712
|
+
'1234',
|
|
713
|
+
'https://host.com/workspaces/1234/webhooks/endpoint'
|
|
714
|
+
)
|
|
715
|
+
).toBe('endpoint');
|
|
716
|
+
expect(
|
|
717
|
+
api.getAutomationFromUrl(
|
|
718
|
+
'1235',
|
|
719
|
+
'https://host.com/workspaces/1234/webhooks/endpoint'
|
|
720
|
+
)
|
|
721
|
+
).toBe(false);
|
|
722
|
+
});
|
|
723
|
+
|
|
709
724
|
it('should get workspace usage', () => {
|
|
710
725
|
const api = new Api({ host: '/fake/' });
|
|
711
726
|
const get: jest.Mock = (api.get = jest.fn((): any => {}));
|
package/lib/api.ts
CHANGED
|
@@ -7,6 +7,11 @@ import { removedUndefinedProperties } from './utils';
|
|
|
7
7
|
import WorkspacesEndpoint from './endpoints/workspaces';
|
|
8
8
|
import ApiError from './ApiError';
|
|
9
9
|
import UsersEndpoint from './endpoints/users';
|
|
10
|
+
import {
|
|
11
|
+
ImportProcessing,
|
|
12
|
+
ImportProcessingError,
|
|
13
|
+
ImportSuccess,
|
|
14
|
+
} from './ImportProcessing';
|
|
10
15
|
|
|
11
16
|
interface PageWithMetadata extends Prismeai.Page {
|
|
12
17
|
createdAt: string;
|
|
@@ -34,6 +39,9 @@ export interface ApiOptions {
|
|
|
34
39
|
clientIdHeader?: string;
|
|
35
40
|
redirectUri: string;
|
|
36
41
|
};
|
|
42
|
+
websockets?: {
|
|
43
|
+
transports?: string[];
|
|
44
|
+
};
|
|
37
45
|
}
|
|
38
46
|
|
|
39
47
|
export interface AccessToken {
|
|
@@ -91,6 +99,10 @@ export class Api extends Fetcher {
|
|
|
91
99
|
redirectUri: 'http://studio.local.prisme.ai:3000/signin',
|
|
92
100
|
...opts.oidc,
|
|
93
101
|
},
|
|
102
|
+
websockets: {
|
|
103
|
+
...opts.websockets,
|
|
104
|
+
transports: opts.websockets?.transports || ['polling', 'websocket'],
|
|
105
|
+
},
|
|
94
106
|
};
|
|
95
107
|
}
|
|
96
108
|
|
|
@@ -195,13 +207,7 @@ export class Api extends Fetcher {
|
|
|
195
207
|
Prismeai.User & {
|
|
196
208
|
token: string;
|
|
197
209
|
}
|
|
198
|
-
>(
|
|
199
|
-
'/login/anonymous',
|
|
200
|
-
{},
|
|
201
|
-
{
|
|
202
|
-
credentials: 'omit',
|
|
203
|
-
}
|
|
204
|
-
);
|
|
210
|
+
>('/login/anonymous');
|
|
205
211
|
this._user = user;
|
|
206
212
|
return user;
|
|
207
213
|
}
|
|
@@ -217,13 +223,19 @@ export class Api extends Fetcher {
|
|
|
217
223
|
token: string;
|
|
218
224
|
}
|
|
219
225
|
> {
|
|
220
|
-
return await this.post(
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
226
|
+
return await this.post(
|
|
227
|
+
'/signup',
|
|
228
|
+
{
|
|
229
|
+
email: email,
|
|
230
|
+
password,
|
|
231
|
+
firstName,
|
|
232
|
+
lastName,
|
|
233
|
+
language,
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
credentials: 'omit',
|
|
237
|
+
}
|
|
238
|
+
);
|
|
227
239
|
}
|
|
228
240
|
|
|
229
241
|
getSignoutURL(redirectUri?: string) {
|
|
@@ -259,7 +271,7 @@ export class Api extends Fetcher {
|
|
|
259
271
|
|
|
260
272
|
// Workspaces
|
|
261
273
|
async getWorkspaces(): Promise<Workspace[]> {
|
|
262
|
-
return await this.get('/workspaces?limit=
|
|
274
|
+
return await this.get('/workspaces?limit=2000');
|
|
263
275
|
}
|
|
264
276
|
|
|
265
277
|
async getWorkspace(
|
|
@@ -287,14 +299,41 @@ export class Api extends Fetcher {
|
|
|
287
299
|
return await this.get(`/workspaces/${id}/security/roles`);
|
|
288
300
|
}
|
|
289
301
|
|
|
290
|
-
async
|
|
291
|
-
|
|
302
|
+
async getWorkspaceSecrets(
|
|
303
|
+
id: string
|
|
304
|
+
): Promise<Fetched<PrismeaiAPI.GetWorkspaceSecrets.Responses.$200>> {
|
|
305
|
+
return await this.get(`/workspaces/${id}/security/secrets`);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
async updateWorkspaceSecrets(
|
|
309
|
+
id: string,
|
|
310
|
+
newSecrets: any
|
|
311
|
+
): Promise<Workspace> {
|
|
312
|
+
return await this.patch(`/workspaces/${id}/security/secrets`, {
|
|
313
|
+
...newSecrets,
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
async deleteWorkspaceSecrets(
|
|
318
|
+
id: string,
|
|
319
|
+
secretName: string
|
|
320
|
+
): Promise<Workspace> {
|
|
321
|
+
return await this.delete(
|
|
322
|
+
`/workspaces/${id}/security/secrets/${secretName}`
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
async createWorkspace(
|
|
327
|
+
newWorkspace: Partial<Prismeai.Workspace>
|
|
328
|
+
): Promise<Workspace> {
|
|
329
|
+
return await this.post('/workspaces', newWorkspace);
|
|
292
330
|
}
|
|
293
331
|
|
|
294
332
|
async duplicateWorkspace({ id }: { id: string }): Promise<Workspace | null> {
|
|
295
333
|
return await this.post(`/workspaces/${id}/versions/current/duplicate`, {});
|
|
296
334
|
}
|
|
297
335
|
|
|
336
|
+
// @deprecated. Use api.workspaces(id).update() instead
|
|
298
337
|
async updateWorkspace(
|
|
299
338
|
workspace: Prismeai.DSULPatch
|
|
300
339
|
): Promise<Fetched<PrismeaiAPI.UpdateWorkspace.Responses.$200> | null> {
|
|
@@ -305,6 +344,7 @@ export class Api extends Fetcher {
|
|
|
305
344
|
);
|
|
306
345
|
}
|
|
307
346
|
|
|
347
|
+
// @deprecated. Use api.workspaces(id).delete() instead
|
|
308
348
|
async deleteWorkspace(workspaceId: Workspace['id']): Promise<Workspace> {
|
|
309
349
|
return await this.delete(`/workspaces/${workspaceId}`);
|
|
310
350
|
}
|
|
@@ -366,7 +406,9 @@ export class Api extends Fetcher {
|
|
|
366
406
|
automationSlug: string
|
|
367
407
|
): Promise<Fetched<PrismeaiAPI.GetAutomation.Responses.$200>> {
|
|
368
408
|
return await this.get(
|
|
369
|
-
`/workspaces/${workspaceId}/automations/${
|
|
409
|
+
`/workspaces/${workspaceId}/automations/${encodeURIComponent(
|
|
410
|
+
automationSlug
|
|
411
|
+
)}`
|
|
370
412
|
);
|
|
371
413
|
}
|
|
372
414
|
|
|
@@ -385,13 +427,15 @@ export class Api extends Fetcher {
|
|
|
385
427
|
automation: Prismeai.Automation
|
|
386
428
|
): Promise<Fetched<Prismeai.Automation & { slug: string }>> {
|
|
387
429
|
return await this.patch(
|
|
388
|
-
`/workspaces/${workspaceId}/automations/${slug}`,
|
|
430
|
+
`/workspaces/${workspaceId}/automations/${encodeURIComponent(slug)}`,
|
|
389
431
|
await this.replaceAllImagesData(automation, workspaceId)
|
|
390
432
|
);
|
|
391
433
|
}
|
|
392
434
|
|
|
393
435
|
async deleteAutomation(workspaceId: string, slug: string): Promise<string> {
|
|
394
|
-
return await this.delete(
|
|
436
|
+
return await this.delete(
|
|
437
|
+
`/workspaces/${workspaceId}/automations/${encodeURIComponent(slug)}`
|
|
438
|
+
);
|
|
395
439
|
}
|
|
396
440
|
|
|
397
441
|
// Pages
|
|
@@ -471,6 +515,7 @@ export class Api extends Fetcher {
|
|
|
471
515
|
if (filters && filters['source.sessionId'] === true) {
|
|
472
516
|
if (this.sessionId) {
|
|
473
517
|
filters['source.sessionId'] = this.sessionId;
|
|
518
|
+
filters['target.userTopic'] = ''; // We do not want to receive userTopics emitted by ourself for this session listener
|
|
474
519
|
} else {
|
|
475
520
|
delete filters['source.sessionId'];
|
|
476
521
|
}
|
|
@@ -483,6 +528,7 @@ export class Api extends Fetcher {
|
|
|
483
528
|
apiHost: this.host,
|
|
484
529
|
filters,
|
|
485
530
|
api: this,
|
|
531
|
+
transports: this.opts?.websockets?.transports,
|
|
486
532
|
});
|
|
487
533
|
return new Promise((resolve, reject) => {
|
|
488
534
|
const off = events.once('connect_error', () => {
|
|
@@ -590,7 +636,6 @@ export class Api extends Fetcher {
|
|
|
590
636
|
{
|
|
591
637
|
error: 'CollaboratorNotFound',
|
|
592
638
|
message: 'This user does not exist',
|
|
593
|
-
details: { email },
|
|
594
639
|
},
|
|
595
640
|
404
|
|
596
641
|
);
|
|
@@ -645,6 +690,14 @@ export class Api extends Fetcher {
|
|
|
645
690
|
return await this.get(`/apps?${params.toString()}`);
|
|
646
691
|
}
|
|
647
692
|
|
|
693
|
+
async getApp({
|
|
694
|
+
slug = '',
|
|
695
|
+
}: {
|
|
696
|
+
slug?: PrismeaiAPI.GetApp.PathParameters['appSlug'];
|
|
697
|
+
}): Promise<Fetched<PrismeaiAPI.GetApp.Responses.$200>> {
|
|
698
|
+
return await this.get(`/apps/${encodeURIComponent(slug)}`);
|
|
699
|
+
}
|
|
700
|
+
|
|
648
701
|
async installApp(
|
|
649
702
|
workspaceId: PrismeaiAPI.InstallAppInstance.PathParameters['workspaceId'],
|
|
650
703
|
body: PrismeaiAPI.InstallAppInstance.RequestBody
|
|
@@ -673,6 +726,7 @@ export class Api extends Fetcher {
|
|
|
673
726
|
return await this.post(`/apps`, body);
|
|
674
727
|
}
|
|
675
728
|
|
|
729
|
+
// @deprecated. Use api.workspaces(id).listAppInstances())
|
|
676
730
|
async listAppInstances(
|
|
677
731
|
workspaceId: PrismeaiAPI.ListAppInstances.PathParameters['workspaceId']
|
|
678
732
|
): Promise<Fetched<PrismeaiAPI.ListAppInstances.Responses.$200>> {
|
|
@@ -720,13 +774,31 @@ export class Api extends Fetcher {
|
|
|
720
774
|
return response;
|
|
721
775
|
}
|
|
722
776
|
|
|
723
|
-
|
|
777
|
+
// @deprecated. Use api.workspaces(id).uploadFiles()
|
|
778
|
+
async uploadFiles(
|
|
779
|
+
files: string | string[],
|
|
780
|
+
workspaceId: string,
|
|
781
|
+
opts?: {
|
|
782
|
+
expiresAfter?: number;
|
|
783
|
+
public?: boolean;
|
|
784
|
+
shareToken?: boolean;
|
|
785
|
+
}
|
|
786
|
+
) {
|
|
724
787
|
const formData = new FormData();
|
|
725
788
|
(Array.isArray(files) ? files : [files]).forEach((file) => {
|
|
726
789
|
try {
|
|
727
790
|
formData.append('file', ...dataURItoBlob(file));
|
|
728
791
|
} catch {}
|
|
729
792
|
});
|
|
793
|
+
if (opts?.expiresAfter) {
|
|
794
|
+
formData.append('expiresAfter', `${opts?.expiresAfter}`);
|
|
795
|
+
}
|
|
796
|
+
if (typeof opts?.public === 'boolean') {
|
|
797
|
+
formData.append('public', `${opts?.public}`);
|
|
798
|
+
}
|
|
799
|
+
if (typeof opts?.shareToken === 'boolean') {
|
|
800
|
+
formData.append('shareToken', `${opts?.shareToken}`);
|
|
801
|
+
}
|
|
730
802
|
try {
|
|
731
803
|
return await this._fetch<PrismeaiAPI.UploadFile.Responses.$200>(
|
|
732
804
|
`/workspaces/${workspaceId}/files`,
|
|
@@ -783,6 +855,13 @@ export class Api extends Fetcher {
|
|
|
783
855
|
return replaced;
|
|
784
856
|
}
|
|
785
857
|
|
|
858
|
+
getAutomationFromUrl(workspaceId: string, url: string) {
|
|
859
|
+
const match = url.match(
|
|
860
|
+
`${this.host}/workspaces/${workspaceId}/webhooks\/(.*$)`
|
|
861
|
+
);
|
|
862
|
+
return match ? match[1] : false;
|
|
863
|
+
}
|
|
864
|
+
|
|
786
865
|
async callAutomation(
|
|
787
866
|
workspaceId: string,
|
|
788
867
|
automation: string,
|
|
@@ -808,6 +887,7 @@ export class Api extends Fetcher {
|
|
|
808
887
|
});
|
|
809
888
|
}
|
|
810
889
|
|
|
890
|
+
// @deprecated. Use api.workspaces(id).getUsage())
|
|
811
891
|
async getWorkspaceUsage(
|
|
812
892
|
workspaceId: PrismeaiAPI.WorkspaceUsage.Parameters.WorkspaceId,
|
|
813
893
|
{
|
|
@@ -834,24 +914,22 @@ export class Api extends Fetcher {
|
|
|
834
914
|
return this.get(`/workspaces/${workspaceId}/usage?${params.toString()}`);
|
|
835
915
|
}
|
|
836
916
|
|
|
837
|
-
async importArchive(
|
|
838
|
-
archive: File
|
|
839
|
-
): Promise<PrismeaiAPI.ImportNewWorkspace.Responses.$200> {
|
|
917
|
+
async importArchive(archive: File): Promise<ImportSuccess> {
|
|
840
918
|
return new Promise((resolve) => {
|
|
841
919
|
const fileReader = new FileReader();
|
|
842
920
|
fileReader.addEventListener('load', async ({ target }) => {
|
|
843
921
|
const file = target?.result as string;
|
|
844
922
|
const formData = new FormData();
|
|
845
923
|
formData.append('archive', ...dataURItoBlob(file));
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
method: 'POST',
|
|
851
|
-
body: formData,
|
|
852
|
-
}
|
|
853
|
-
)
|
|
924
|
+
|
|
925
|
+
const result = await this.post<ImportProcessing | ImportSuccess>(
|
|
926
|
+
`/workspaces/import`,
|
|
927
|
+
formData
|
|
854
928
|
);
|
|
929
|
+
if ((result as ImportProcessing).processing) {
|
|
930
|
+
throw new ImportProcessingError(result as ImportProcessing);
|
|
931
|
+
}
|
|
932
|
+
resolve(result as ImportSuccess);
|
|
855
933
|
});
|
|
856
934
|
fileReader.readAsDataURL(archive);
|
|
857
935
|
});
|
package/lib/endpoints/users.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Api } from '../api';
|
|
2
|
+
import { dataURItoBlob, isDataURL } from '../utils';
|
|
2
3
|
|
|
3
4
|
export class UsersEndpoint {
|
|
4
5
|
private id: string;
|
|
@@ -9,13 +10,48 @@ export class UsersEndpoint {
|
|
|
9
10
|
this.api = api;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
async
|
|
13
|
-
|
|
13
|
+
async update(
|
|
14
|
+
data: Partial<Prismeai.User>
|
|
15
|
+
): Promise<PrismeaiAPI.PatchUser.Responses.$200> {
|
|
16
|
+
if (isDataURL(data.photo)) {
|
|
17
|
+
await this.updatePhoto(data.photo);
|
|
18
|
+
delete data.photo;
|
|
19
|
+
}
|
|
20
|
+
return await this.api.patch('/user', data);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async updatePhoto(
|
|
24
|
+
photo: string
|
|
25
|
+
): Promise<PrismeaiAPI.PostUserPhoto.Responses.$200> {
|
|
26
|
+
if (!isDataURL(photo)) {
|
|
27
|
+
throw new Error('Photo must be a dataurl file');
|
|
28
|
+
}
|
|
29
|
+
const formData = new FormData();
|
|
30
|
+
formData.append('photo', ...dataURItoBlob(photo));
|
|
31
|
+
|
|
32
|
+
return await this.api.post<PrismeaiAPI.PostUserPhoto.Responses.$200>(
|
|
33
|
+
`/user/photo`,
|
|
34
|
+
formData
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async setMeta(
|
|
39
|
+
k: string,
|
|
40
|
+
v: any
|
|
41
|
+
): Promise<PrismeaiAPI.SetMeta.Responses.$200> {
|
|
42
|
+
return await this.api.post(`/user/meta`, {
|
|
14
43
|
[k]: v,
|
|
15
44
|
});
|
|
16
45
|
}
|
|
17
|
-
async deleteMeta(k: string) {
|
|
18
|
-
await this.api.delete(`/user/meta/${k}`);
|
|
46
|
+
async deleteMeta(k: string): Promise<PrismeaiAPI.DeleteMeta.Responses.$200> {
|
|
47
|
+
return await this.api.delete(`/user/meta/${k}`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async sendDeleteValidation() {
|
|
51
|
+
return await this.api.delete(`/user`);
|
|
52
|
+
}
|
|
53
|
+
async delete(token?: string) {
|
|
54
|
+
return await this.api.delete(`/users/${this.id}?token=${token}`);
|
|
19
55
|
}
|
|
20
56
|
}
|
|
21
57
|
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import { Api } from '../api';
|
|
2
|
+
import { Fetched } from '../fetcher';
|
|
3
|
+
import {
|
|
4
|
+
ImportProcessing,
|
|
5
|
+
ImportProcessingError,
|
|
6
|
+
ImportSuccess,
|
|
7
|
+
} from '../ImportProcessing';
|
|
8
|
+
import { dataURItoBlob, removedUndefinedProperties } from '../utils';
|
|
2
9
|
import WorkspacesVersionsEndpoint from './workspacesVersions';
|
|
3
10
|
|
|
4
11
|
export class WorkspacesEndpoint {
|
|
@@ -13,6 +20,102 @@ export class WorkspacesEndpoint {
|
|
|
13
20
|
get versions() {
|
|
14
21
|
return new WorkspacesVersionsEndpoint(this.id, this.api);
|
|
15
22
|
}
|
|
23
|
+
|
|
24
|
+
async update(
|
|
25
|
+
workspace: Prismeai.DSULPatch
|
|
26
|
+
): Promise<Fetched<PrismeaiAPI.UpdateWorkspace.Responses.$200> | null> {
|
|
27
|
+
return await this.api.patch(
|
|
28
|
+
`/workspaces/${this.id}`,
|
|
29
|
+
await this.api.replaceAllImagesData(workspace, this.id)
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async delete(): Promise<PrismeaiAPI.DeleteWorkspace.Responses.$200> {
|
|
34
|
+
return await this.api.delete(`/workspaces/${this.id}`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async uploadFiles(
|
|
38
|
+
files: string | string[],
|
|
39
|
+
opts?: {
|
|
40
|
+
expiresAfter?: number;
|
|
41
|
+
public?: boolean;
|
|
42
|
+
shareToken?: boolean;
|
|
43
|
+
}
|
|
44
|
+
) {
|
|
45
|
+
const formData = new FormData();
|
|
46
|
+
(Array.isArray(files) ? files : [files]).forEach((file) => {
|
|
47
|
+
try {
|
|
48
|
+
formData.append('file', ...dataURItoBlob(file));
|
|
49
|
+
} catch {}
|
|
50
|
+
});
|
|
51
|
+
if (opts?.expiresAfter) {
|
|
52
|
+
formData.append('expiresAfter', `${opts?.expiresAfter}`);
|
|
53
|
+
}
|
|
54
|
+
if (typeof opts?.public === 'boolean') {
|
|
55
|
+
formData.append('public', `${opts?.public}`);
|
|
56
|
+
}
|
|
57
|
+
if (typeof opts?.shareToken === 'boolean') {
|
|
58
|
+
formData.append('shareToken', `${opts?.shareToken}`);
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
return await this.api.post<PrismeaiAPI.UploadFile.Responses.$200>(
|
|
62
|
+
`/workspaces/${this.id}/files`,
|
|
63
|
+
formData
|
|
64
|
+
);
|
|
65
|
+
} catch (e) {
|
|
66
|
+
console.error(e);
|
|
67
|
+
}
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async listAppInstances(): Promise<
|
|
72
|
+
Fetched<PrismeaiAPI.ListAppInstances.Responses.$200>
|
|
73
|
+
> {
|
|
74
|
+
return await this.api.get(`/workspaces/${this.id}/apps`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async getUsage({
|
|
78
|
+
afterDate,
|
|
79
|
+
beforeDate,
|
|
80
|
+
details,
|
|
81
|
+
}: {
|
|
82
|
+
afterDate?: PrismeaiAPI.WorkspaceUsage.Parameters.AfterDate;
|
|
83
|
+
beforeDate?: PrismeaiAPI.WorkspaceUsage.Parameters.BeforeDate;
|
|
84
|
+
details?: PrismeaiAPI.WorkspaceUsage.Parameters.Details;
|
|
85
|
+
} = {}): Promise<Fetched<PrismeaiAPI.WorkspaceUsage.Responses.$200>> {
|
|
86
|
+
const params = new URLSearchParams(
|
|
87
|
+
removedUndefinedProperties(
|
|
88
|
+
{
|
|
89
|
+
afterDate: `${afterDate || ''}`,
|
|
90
|
+
beforeDate: `${beforeDate || ''}`,
|
|
91
|
+
details: `${details || ''}`,
|
|
92
|
+
},
|
|
93
|
+
true
|
|
94
|
+
)
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
return this.api.get(`/workspaces/${this.id}/usage?${params.toString()}`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async importArchive(archive: File): Promise<ImportSuccess> {
|
|
101
|
+
return new Promise((resolve) => {
|
|
102
|
+
const fileReader = new FileReader();
|
|
103
|
+
fileReader.addEventListener('load', async ({ target }) => {
|
|
104
|
+
const file = target?.result as string;
|
|
105
|
+
const formData = new FormData();
|
|
106
|
+
formData.append('archive', ...dataURItoBlob(file));
|
|
107
|
+
const result = await this.api.post<ImportProcessing | ImportSuccess>(
|
|
108
|
+
`/workspaces/${this.id}/import`,
|
|
109
|
+
formData
|
|
110
|
+
);
|
|
111
|
+
if ((result as ImportProcessing).processing) {
|
|
112
|
+
throw new ImportProcessingError(result as ImportProcessing);
|
|
113
|
+
}
|
|
114
|
+
resolve(result as ImportSuccess);
|
|
115
|
+
});
|
|
116
|
+
fileReader.readAsDataURL(archive);
|
|
117
|
+
});
|
|
118
|
+
}
|
|
16
119
|
}
|
|
17
120
|
|
|
18
121
|
export default WorkspacesEndpoint;
|
|
@@ -10,24 +10,28 @@ export class WorkspacesVersionsEndpoint {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
create(version?: PrismeaiAPI.PublishWorkspaceVersion.RequestBody) {
|
|
13
|
-
this.api.post(`/workspaces/${this.workspaceId}/versions`, version);
|
|
13
|
+
return this.api.post(`/workspaces/${this.workspaceId}/versions`, version);
|
|
14
14
|
}
|
|
15
15
|
rollback(
|
|
16
|
-
versionId: PrismeaiAPI.
|
|
16
|
+
versionId: PrismeaiAPI.PullWorkspaceVersion.PathParameters['versionId'],
|
|
17
|
+
opts?: PrismeaiAPI.PullWorkspaceVersion.RequestBody
|
|
17
18
|
) {
|
|
18
|
-
this.api.post(
|
|
19
|
-
`/workspaces/${this.workspaceId}/versions/${versionId}/
|
|
19
|
+
return this.api.post(
|
|
20
|
+
`/workspaces/${this.workspaceId}/versions/${versionId}/pull`,
|
|
21
|
+
opts
|
|
20
22
|
);
|
|
21
23
|
}
|
|
22
24
|
|
|
23
|
-
async export(
|
|
25
|
+
async export(
|
|
26
|
+
version: PrismeaiAPI.ExportWorkspaceVersion.Parameters.VersionId = 'current'
|
|
27
|
+
) {
|
|
24
28
|
const res = await this.api.prepareRequest(
|
|
25
|
-
`/workspaces/${this.workspaceId}/versions/${version}/export`,
|
|
26
|
-
|
|
29
|
+
`/workspaces/${this.workspaceId}/versions/${version}/export`,
|
|
30
|
+
{
|
|
31
|
+
method: 'post',
|
|
27
32
|
}
|
|
28
|
-
)
|
|
33
|
+
);
|
|
29
34
|
return new Blob([await res.arrayBuffer()], { type: 'application/zip' });
|
|
30
|
-
|
|
31
35
|
}
|
|
32
36
|
}
|
|
33
37
|
|
package/lib/events.ts
CHANGED
|
@@ -20,6 +20,7 @@ export class Events {
|
|
|
20
20
|
private listenedUserTopics: Map<string, string[]>;
|
|
21
21
|
private listeners: Map<string, Function[]> = new Map();
|
|
22
22
|
private lastReceivedEventDate: Date;
|
|
23
|
+
private socketId?: string;
|
|
23
24
|
|
|
24
25
|
constructor({
|
|
25
26
|
workspaceId,
|
|
@@ -29,6 +30,7 @@ export class Events {
|
|
|
29
30
|
apiHost = 'https://api.eda.prisme.ai',
|
|
30
31
|
filters,
|
|
31
32
|
api,
|
|
33
|
+
transports,
|
|
32
34
|
}: {
|
|
33
35
|
workspaceId: string;
|
|
34
36
|
token: string;
|
|
@@ -37,33 +39,62 @@ export class Events {
|
|
|
37
39
|
apiHost?: string;
|
|
38
40
|
filters?: Record<string, any>;
|
|
39
41
|
api: Api;
|
|
42
|
+
transports?: string[];
|
|
40
43
|
}) {
|
|
41
44
|
this.workspaceId = workspaceId;
|
|
42
45
|
const queryString = new URLSearchParams(filters || {}).toString();
|
|
43
46
|
const fullQueryString = queryString ? `?${queryString}` : '';
|
|
44
47
|
const extraHeaders: any = token
|
|
45
48
|
? {
|
|
46
|
-
|
|
49
|
+
authorization: `Bearer ${token}`,
|
|
47
50
|
}
|
|
48
51
|
: { 'x-prismeai-token': legacyToken };
|
|
49
52
|
this.lastReceivedEventDate = new Date();
|
|
50
53
|
if (apiKey) {
|
|
51
54
|
extraHeaders['x-prismeai-api-key'] = apiKey;
|
|
52
55
|
}
|
|
56
|
+
this.filters = [filters || {}];
|
|
57
|
+
this.listenedUserTopics = new Map();
|
|
53
58
|
|
|
54
59
|
this.client = io(
|
|
55
60
|
`${apiHost}/workspaces/${workspaceId}/events${fullQueryString}`,
|
|
56
61
|
{
|
|
57
62
|
extraHeaders,
|
|
58
|
-
withCredentials:
|
|
63
|
+
withCredentials: !extraHeaders.authorization,
|
|
64
|
+
transports: transports || ['polling', 'websocket'],
|
|
65
|
+
auth: (cb) => {
|
|
66
|
+
cb({
|
|
67
|
+
// Browser websockets cannot send extraHeaders, so we use socketio-client auth instead
|
|
68
|
+
extraHeaders:
|
|
69
|
+
transports && transports[0] === 'websocket' ? extraHeaders : {},
|
|
70
|
+
|
|
71
|
+
filters: {
|
|
72
|
+
payloadQuery: this.filters,
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
reuseSocketId: this.socketId,
|
|
76
|
+
});
|
|
77
|
+
},
|
|
59
78
|
}
|
|
60
79
|
);
|
|
61
80
|
|
|
81
|
+
this.client.on('connect_error', (err) => {
|
|
82
|
+
console.error(`Failed websocket connection : `, err);
|
|
83
|
+
// revert to classic upgrade
|
|
84
|
+
this.client.io.opts.transports = ['polling', 'websocket'];
|
|
85
|
+
});
|
|
86
|
+
this.client.on('error', (err) => {
|
|
87
|
+
this.client.io.opts.transports = ['polling', 'websocket'];
|
|
88
|
+
});
|
|
89
|
+
|
|
62
90
|
const onConnect = () => {
|
|
63
|
-
//
|
|
64
|
-
this.
|
|
65
|
-
|
|
66
|
-
|
|
91
|
+
// First connection
|
|
92
|
+
if (!this.socketId) {
|
|
93
|
+
this.socketId = this.client.id;
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Retrieve lost history on reconnection
|
|
67
98
|
setTimeout(async () => {
|
|
68
99
|
const events = await api.getEvents(workspaceId, {
|
|
69
100
|
...this.filters[this.filters.length - 1],
|
|
@@ -76,16 +107,23 @@ export class Events {
|
|
|
76
107
|
});
|
|
77
108
|
}, 2000);
|
|
78
109
|
};
|
|
110
|
+
this.client.on('connect', onConnect);
|
|
111
|
+
|
|
79
112
|
this.client.on('disconnect', () => {
|
|
80
113
|
if (!this.lastReceivedEventDate) {
|
|
81
114
|
this.lastReceivedEventDate = new Date();
|
|
82
115
|
}
|
|
116
|
+
// Make sure we reconnect with current filters & socketId
|
|
117
|
+
this.client.auth = {
|
|
118
|
+
...this.client.auth,
|
|
119
|
+
filters: {
|
|
120
|
+
payloadQuery: this.filters,
|
|
121
|
+
},
|
|
122
|
+
reuseSocketId: this.socketId,
|
|
123
|
+
};
|
|
83
124
|
this.client.off('connect', onConnect);
|
|
84
125
|
this.client.on('connect', onConnect);
|
|
85
126
|
});
|
|
86
|
-
|
|
87
|
-
this.filters = [filters || {}];
|
|
88
|
-
this.listenedUserTopics = new Map();
|
|
89
127
|
}
|
|
90
128
|
|
|
91
129
|
get socket() {
|
|
@@ -105,12 +143,16 @@ export class Events {
|
|
|
105
143
|
}
|
|
106
144
|
|
|
107
145
|
all(listener: (eventName: string, eventData: Prismeai.PrismeEvent) => void) {
|
|
108
|
-
|
|
146
|
+
const anyListener = (
|
|
147
|
+
eventName: string,
|
|
148
|
+
eventData: Prismeai.PrismeEvent
|
|
149
|
+
) => {
|
|
109
150
|
this.lastReceivedEventDate = new Date(eventData?.createdAt);
|
|
110
151
|
return listener(eventName, eventData);
|
|
111
|
-
}
|
|
152
|
+
};
|
|
153
|
+
this.client.onAny(anyListener);
|
|
112
154
|
|
|
113
|
-
return () => this.client.offAny(
|
|
155
|
+
return () => this.client.offAny(anyListener);
|
|
114
156
|
}
|
|
115
157
|
|
|
116
158
|
on(ev: string, listener: (eventData: Prismeai.PrismeEvent) => void) {
|