@prisme.ai/sdk 1.0.0 → 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.
Files changed (38) hide show
  1. package/Readme.md +3 -1
  2. package/dist/_virtual/_tslib.js +17 -8
  3. package/dist/lib/ImportProcessing.d.ts +19 -0
  4. package/dist/lib/WorkspacesEndpoint.d.ts +10 -0
  5. package/dist/lib/api.d.ts +88 -29
  6. package/dist/lib/endpoints/users.d.ts +13 -0
  7. package/dist/lib/endpoints/workspaces.d.ts +16 -0
  8. package/dist/lib/endpoints/workspacesVersions.d.ts +2 -2
  9. package/dist/lib/events.d.ts +5 -1
  10. package/dist/lib/fetch.d.ts +2 -0
  11. package/dist/lib/fetcher.d.ts +11 -3
  12. package/dist/lib/interpolate.d.ts +2 -0
  13. package/dist/lib/interpolate.test.d.ts +1 -0
  14. package/dist/lib/interpolateVars.d.ts +2 -0
  15. package/dist/lib/utils.d.ts +3 -0
  16. package/dist/sdk/lib/ImportProcessing.js +17 -0
  17. package/dist/sdk/lib/WorkspacesEndpoint.js +19 -0
  18. package/dist/sdk/lib/api.js +248 -62
  19. package/dist/sdk/lib/endpoints/users.js +94 -0
  20. package/dist/sdk/lib/endpoints/workspaces.js +121 -0
  21. package/dist/sdk/lib/endpoints/workspacesVersions.js +4 -4
  22. package/dist/sdk/lib/events.js +51 -13
  23. package/dist/sdk/lib/fetch.js +12 -0
  24. package/dist/sdk/lib/fetcher.js +98 -42
  25. package/dist/sdk/lib/interpolate.js +26 -0
  26. package/dist/sdk/lib/interpolateVars.js +26 -0
  27. package/dist/sdk/lib/utils.js +48 -1
  28. package/lib/ImportProcessing.ts +22 -0
  29. package/lib/api.test.ts +90 -60
  30. package/lib/api.ts +318 -79
  31. package/lib/endpoints/users.ts +58 -0
  32. package/lib/endpoints/workspaces.ts +103 -0
  33. package/lib/endpoints/workspacesVersions.ts +13 -9
  34. package/lib/events.test.ts +2 -2
  35. package/lib/events.ts +60 -14
  36. package/lib/fetcher.ts +77 -12
  37. package/lib/utils.ts +39 -0
  38. package/package.json +3 -1
package/lib/api.ts CHANGED
@@ -1,10 +1,17 @@
1
1
  import QueryString from 'qs';
2
- import Fetcher from './fetcher';
2
+ import pkceChallenge from 'pkce-challenge';
3
+ import Fetcher, { Fetched } from './fetcher';
3
4
  import { Event, Workspace } from './types';
4
5
  import { Events } from './events';
5
6
  import { removedUndefinedProperties } from './utils';
6
7
  import WorkspacesEndpoint from './endpoints/workspaces';
7
8
  import ApiError from './ApiError';
9
+ import UsersEndpoint from './endpoints/users';
10
+ import {
11
+ ImportProcessing,
12
+ ImportProcessingError,
13
+ ImportSuccess,
14
+ } from './ImportProcessing';
8
15
 
9
16
  interface PageWithMetadata extends Prismeai.Page {
10
17
  createdAt: string;
@@ -24,10 +31,81 @@ export type UserPermissions = {
24
31
  };
25
32
  };
26
33
 
34
+ export interface ApiOptions {
35
+ host: string;
36
+ oidc?: {
37
+ url: string;
38
+ clientId: string;
39
+ clientIdHeader?: string;
40
+ redirectUri: string;
41
+ };
42
+ websockets?: {
43
+ transports?: string[];
44
+ };
45
+ }
46
+
47
+ export interface AccessToken {
48
+ access_token: string;
49
+ id_token: string;
50
+ scope: string;
51
+ expiresIn: number;
52
+ token_type: 'Bearer';
53
+ }
54
+
55
+ export interface InteractiveSignin {
56
+ interaction: string;
57
+ login: string;
58
+ password: string;
59
+ remember?: boolean;
60
+ }
61
+
62
+ function dataURItoBlob(dataURI: string): [Blob, string] {
63
+ // convert base64/URLEncoded data component to raw binary data held in a string
64
+ let byteString;
65
+ if (dataURI.split(',')[0].indexOf('base64') >= 0)
66
+ byteString = atob(dataURI.split(',')[1]);
67
+ else byteString = unescape(dataURI.split(',')[1]);
68
+ // separate out the mime component
69
+ const metadata = dataURI
70
+ .split(';')
71
+ .filter((v, k, all) => k < all.length - 1)
72
+ .map((v) => v.split(/:/));
73
+ const [, mimeString = ''] = metadata.find(([k, v]) => k === 'data') || [];
74
+ const [, ext] = mimeString.split(/\//);
75
+ const [, fileName = `file.${ext}`] =
76
+ metadata.find(([k, v]) => k === 'filename') || [];
77
+
78
+ // write the bytes of the string to a typed array
79
+ let ia = new Uint8Array(byteString.length);
80
+ for (var i = 0; i < byteString.length; i++) {
81
+ ia[i] = byteString.charCodeAt(i);
82
+ }
83
+
84
+ return [new Blob([ia], { type: mimeString }), fileName];
85
+ }
86
+
27
87
  export class Api extends Fetcher {
88
+ public opts: Required<ApiOptions>;
28
89
  private sessionId?: string;
29
90
  private _user?: Prismeai.User & { sessionId?: string };
30
91
 
92
+ constructor(opts: ApiOptions) {
93
+ super(opts.host, opts?.oidc?.clientIdHeader);
94
+ this.opts = {
95
+ ...opts,
96
+ oidc: {
97
+ url: 'http://studio.local.prisme.ai:3001',
98
+ clientId: 'local-client-id',
99
+ redirectUri: 'http://studio.local.prisme.ai:3000/signin',
100
+ ...opts.oidc,
101
+ },
102
+ websockets: {
103
+ ...opts.websockets,
104
+ transports: opts.websockets?.transports || ['polling', 'websocket'],
105
+ },
106
+ };
107
+ }
108
+
31
109
  get user() {
32
110
  return this._user;
33
111
  }
@@ -39,24 +117,85 @@ export class Api extends Fetcher {
39
117
  return me;
40
118
  }
41
119
 
42
- async signin(
43
- email: string,
44
- password: string
45
- ): Promise<
46
- Prismeai.User & {
47
- token: string;
120
+ clientId(): string {
121
+ return this.overwriteClientId || this.opts?.oidc?.clientId;
122
+ }
123
+
124
+ async getAuthorizationURL(
125
+ overrideRedirectUri?: string,
126
+ authParams?: { max_age?: string; acr_values?: string },
127
+ locale = window?.navigator?.language
128
+ ? window.navigator.language.substring(0, 2)
129
+ : undefined
130
+ ) {
131
+ const url = new URL('/oidc/auth', this.opts.oidc.url);
132
+ url.searchParams.set('response_type', 'code');
133
+ url.searchParams.set('response_mode', 'query'); // Send the final authorization code as a query param to the redirect uri
134
+ url.searchParams.set(
135
+ 'redirect_uri',
136
+ overrideRedirectUri || this.opts.oidc?.redirectUri || ''
137
+ );
138
+ url.searchParams.set(
139
+ 'scope',
140
+ 'openid profile email settings offline_access events:write events:read webhooks pages:read files:write files:read'
141
+ );
142
+ const clientId = this.clientId();
143
+ url.searchParams.set('client_id', clientId);
144
+
145
+ url.searchParams.set('code_challenge_method', 'S256');
146
+ const { code_verifier: codeVerifier, code_challenge: codeChallenge } =
147
+ await pkceChallenge(64);
148
+ url.searchParams.set('code_challenge', codeChallenge);
149
+ if (locale) {
150
+ url.searchParams.set('locale', locale);
48
151
  }
49
- > {
50
- const user = await this.post<
51
- Prismeai.User & {
52
- token: string;
53
- }
54
- >('/login', {
55
- email,
56
- password,
152
+
153
+ Object.entries(authParams || {}).forEach(([k, v]) => {
154
+ url.searchParams.set(k, v);
57
155
  });
58
- this._user = user;
59
- return user;
156
+
157
+ return {
158
+ url: url.toString(),
159
+ codeVerifier,
160
+ clientId,
161
+ };
162
+ }
163
+
164
+ async signin(body: InteractiveSignin): Promise<{ redirectTo: string }> {
165
+ const url = new URL(
166
+ `/oidc/interaction/${body.interaction}/login`,
167
+ this.opts.oidc.url
168
+ );
169
+
170
+ // Do not follow redirects as we need to get redirected from browser itself to save final token in local storage
171
+ await this.post(url.toString(), new URLSearchParams(body as any), {
172
+ redirect: 'manual',
173
+ });
174
+ const redirectTo = new URL(
175
+ `/oidc/auth/${body.interaction}`,
176
+ this.opts.oidc.url
177
+ );
178
+ return { redirectTo: redirectTo.toString() };
179
+ }
180
+
181
+ async getToken(
182
+ authorizationCode: string,
183
+ codeVerifier: string,
184
+ overrideRedirectUri?: string
185
+ ): Promise<AccessToken> {
186
+ this.token = null;
187
+ const url = new URL('/oidc/token', this.opts.oidc.url);
188
+ const token = await this.post<AccessToken>(
189
+ url.toString(),
190
+ new URLSearchParams({
191
+ grant_type: 'authorization_code',
192
+ code: authorizationCode,
193
+ code_verifier: codeVerifier,
194
+ client_id: this.clientId(),
195
+ redirect_uri: overrideRedirectUri || this.opts.oidc.redirectUri,
196
+ })
197
+ );
198
+ return token;
60
199
  }
61
200
 
62
201
  async createAnonymousSession(): Promise<
@@ -84,18 +223,32 @@ export class Api extends Fetcher {
84
223
  token: string;
85
224
  }
86
225
  > {
87
- return await this.post('/signup', {
88
- email: email,
89
- password,
90
- firstName,
91
- lastName,
92
- language,
93
- });
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
+ );
94
239
  }
95
240
 
96
- async signout() {
97
- await this.post('/logout');
98
- this.token = null;
241
+ getSignoutURL(redirectUri?: string) {
242
+ const params = new URLSearchParams();
243
+ params.set('client_id', this.clientId());
244
+ if (redirectUri) {
245
+ params.set('post_logout_redirect_uri', redirectUri);
246
+ }
247
+ const url = new URL(
248
+ `/oidc/session/end?${params.toString()}`,
249
+ this.opts.oidc.url
250
+ );
251
+ return url.toString();
99
252
  }
100
253
 
101
254
  // Mail validation
@@ -118,7 +271,7 @@ export class Api extends Fetcher {
118
271
 
119
272
  // Workspaces
120
273
  async getWorkspaces(): Promise<Workspace[]> {
121
- return await this.get('/workspaces?limit=600');
274
+ return await this.get('/workspaces?limit=2000');
122
275
  }
123
276
 
124
277
  async getWorkspace(
@@ -136,27 +289,54 @@ export class Api extends Fetcher {
136
289
  async updateWorkspaceSecurity(
137
290
  workspaceId: string,
138
291
  security: Prismeai.WorkspaceSecurity
139
- ): Promise<PrismeaiAPI.UpdateSecurity.Responses.$200> {
292
+ ): Promise<Fetched<PrismeaiAPI.UpdateSecurity.Responses.$200>> {
140
293
  return await this.put(`/workspaces/${workspaceId}/security`, security);
141
294
  }
142
295
 
143
296
  async getWorkspaceRoles(
144
297
  id: string
145
- ): Promise<PrismeaiAPI.GetRoles.Responses.$200> {
298
+ ): Promise<Fetched<PrismeaiAPI.GetRoles.Responses.$200>> {
146
299
  return await this.get(`/workspaces/${id}/security/roles`);
147
300
  }
148
301
 
149
- async createWorkspace(name: string): Promise<Workspace> {
150
- return await this.post('/workspaces', { name });
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);
151
330
  }
152
331
 
153
332
  async duplicateWorkspace({ id }: { id: string }): Promise<Workspace | null> {
154
333
  return await this.post(`/workspaces/${id}/versions/current/duplicate`, {});
155
334
  }
156
335
 
336
+ // @deprecated. Use api.workspaces(id).update() instead
157
337
  async updateWorkspace(
158
338
  workspace: Prismeai.DSULPatch
159
- ): Promise<PrismeaiAPI.UpdateWorkspace.Responses.$200 | null> {
339
+ ): Promise<Fetched<PrismeaiAPI.UpdateWorkspace.Responses.$200> | null> {
160
340
  if (!workspace.id) return null;
161
341
  return await this.patch(
162
342
  `/workspaces/${workspace.id}`,
@@ -164,6 +344,7 @@ export class Api extends Fetcher {
164
344
  );
165
345
  }
166
346
 
347
+ // @deprecated. Use api.workspaces(id).delete() instead
167
348
  async deleteWorkspace(workspaceId: Workspace['id']): Promise<Workspace> {
168
349
  return await this.delete(`/workspaces/${workspaceId}`);
169
350
  }
@@ -223,16 +404,18 @@ export class Api extends Fetcher {
223
404
  async getAutomation(
224
405
  workspaceId: string,
225
406
  automationSlug: string
226
- ): Promise<PrismeaiAPI.GetAutomation.Responses.$200> {
407
+ ): Promise<Fetched<PrismeaiAPI.GetAutomation.Responses.$200>> {
227
408
  return await this.get(
228
- `/workspaces/${workspaceId}/automations/${automationSlug}`
409
+ `/workspaces/${workspaceId}/automations/${encodeURIComponent(
410
+ automationSlug
411
+ )}`
229
412
  );
230
413
  }
231
414
 
232
415
  async createAutomation(
233
416
  workspaceId: Workspace['id'],
234
417
  automation: Prismeai.Automation
235
- ): Promise<Prismeai.Automation & { slug: string }> {
418
+ ): Promise<Fetched<Prismeai.Automation & { slug: string }>> {
236
419
  return await this.post(`/workspaces/${workspaceId}/automations`, {
237
420
  ...automation,
238
421
  });
@@ -242,15 +425,17 @@ export class Api extends Fetcher {
242
425
  workspaceId: string,
243
426
  slug: string,
244
427
  automation: Prismeai.Automation
245
- ): Promise<Prismeai.Automation & { slug: string }> {
428
+ ): Promise<Fetched<Prismeai.Automation & { slug: string }>> {
246
429
  return await this.patch(
247
- `/workspaces/${workspaceId}/automations/${slug}`,
430
+ `/workspaces/${workspaceId}/automations/${encodeURIComponent(slug)}`,
248
431
  await this.replaceAllImagesData(automation, workspaceId)
249
432
  );
250
433
  }
251
434
 
252
435
  async deleteAutomation(workspaceId: string, slug: string): Promise<string> {
253
- return await this.delete(`/workspaces/${workspaceId}/automations/${slug}`);
436
+ return await this.delete(
437
+ `/workspaces/${workspaceId}/automations/${encodeURIComponent(slug)}`
438
+ );
254
439
  }
255
440
 
256
441
  // Pages
@@ -272,7 +457,7 @@ export class Api extends Fetcher {
272
457
  async getPage(
273
458
  workspaceId: PrismeaiAPI.GetPage.Parameters.WorkspaceId,
274
459
  pageSlug: PrismeaiAPI.GetPage.Parameters.Slug
275
- ): Promise<Prismeai.DetailedPage> {
460
+ ): Promise<Fetched<Prismeai.DetailedPage>> {
276
461
  return await this.get(
277
462
  `/workspaces/${workspaceId}/pages/${encodeURIComponent(pageSlug)}`
278
463
  );
@@ -281,7 +466,7 @@ export class Api extends Fetcher {
281
466
  async getPageBySlug(
282
467
  workspaceSlug: PrismeaiAPI.GetPageBySlug.Parameters.WorkspaceSlug,
283
468
  pageSlug: PrismeaiAPI.GetPageBySlug.Parameters.PageSlug
284
- ): Promise<Prismeai.DetailedPage> {
469
+ ): Promise<Fetched<Prismeai.DetailedPage>> {
285
470
  return await this.get(
286
471
  `/pages/${workspaceSlug}/${encodeURIComponent(pageSlug)}`
287
472
  );
@@ -316,7 +501,7 @@ export class Api extends Fetcher {
316
501
  async deletePage(
317
502
  workspaceId: PrismeaiAPI.DeletePage.Parameters.WorkspaceId,
318
503
  pageSlug: PrismeaiAPI.DeletePage.Parameters.Slug
319
- ): Promise<PrismeaiAPI.DeletePage.Responses.$200> {
504
+ ): Promise<Fetched<PrismeaiAPI.DeletePage.Responses.$200>> {
320
505
  return await this.delete(
321
506
  `/workspaces/${workspaceId}/pages/${encodeURIComponent(pageSlug)}`
322
507
  );
@@ -330,6 +515,7 @@ export class Api extends Fetcher {
330
515
  if (filters && filters['source.sessionId'] === true) {
331
516
  if (this.sessionId) {
332
517
  filters['source.sessionId'] = this.sessionId;
518
+ filters['target.userTopic'] = ''; // We do not want to receive userTopics emitted by ourself for this session listener
333
519
  } else {
334
520
  delete filters['source.sessionId'];
335
521
  }
@@ -337,10 +523,12 @@ export class Api extends Fetcher {
337
523
  const events = new Events({
338
524
  workspaceId,
339
525
  token: this.token || '',
526
+ legacyToken: this.legacyToken || '',
340
527
  apiKey: this._apiKey ? this._apiKey : undefined,
341
528
  apiHost: this.host,
342
529
  filters,
343
530
  api: this,
531
+ transports: this.opts?.websockets?.transports,
344
532
  });
345
533
  return new Promise((resolve, reject) => {
346
534
  const off = events.once('connect_error', () => {
@@ -448,7 +636,6 @@ export class Api extends Fetcher {
448
636
  {
449
637
  error: 'CollaboratorNotFound',
450
638
  message: 'This user does not exist',
451
- details: { email },
452
639
  },
453
640
  404
454
641
  );
@@ -474,7 +661,7 @@ export class Api extends Fetcher {
474
661
  subjectType: PrismeaiAPI.GetPermissions.Parameters.SubjectType,
475
662
  subjectId: string,
476
663
  id: string
477
- ): Promise<PrismeaiAPI.RevokePermissions.Responses.$200> {
664
+ ): Promise<Fetched<PrismeaiAPI.RevokePermissions.Responses.$200>> {
478
665
  return await this.delete(`/${subjectType}/${subjectId}/permissions/${id}`);
479
666
  }
480
667
 
@@ -488,7 +675,7 @@ export class Api extends Fetcher {
488
675
  page?: PrismeaiAPI.SearchApps.QueryParameters['page'];
489
676
  limit?: PrismeaiAPI.SearchApps.QueryParameters['limit'];
490
677
  workspaceId?: PrismeaiAPI.SearchApps.QueryParameters['workspaceId'];
491
- }): Promise<PrismeaiAPI.SearchApps.Responses.$200> {
678
+ }): Promise<Fetched<PrismeaiAPI.SearchApps.Responses.$200>> {
492
679
  const params = new URLSearchParams(
493
680
  removedUndefinedProperties(
494
681
  {
@@ -503,10 +690,18 @@ export class Api extends Fetcher {
503
690
  return await this.get(`/apps?${params.toString()}`);
504
691
  }
505
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
+
506
701
  async installApp(
507
702
  workspaceId: PrismeaiAPI.InstallAppInstance.PathParameters['workspaceId'],
508
703
  body: PrismeaiAPI.InstallAppInstance.RequestBody
509
- ): Promise<PrismeaiAPI.InstallAppInstance.Responses.$200> {
704
+ ): Promise<Fetched<PrismeaiAPI.InstallAppInstance.Responses.$200>> {
510
705
  return await this.post(`/workspaces/${workspaceId}/apps`, body);
511
706
  }
512
707
 
@@ -514,26 +709,27 @@ export class Api extends Fetcher {
514
709
  workspaceId: PrismeaiAPI.ConfigureAppInstance.PathParameters['workspaceId'],
515
710
  slug: PrismeaiAPI.ConfigureAppInstance.PathParameters['slug'],
516
711
  body: PrismeaiAPI.ConfigureAppInstance.RequestBody
517
- ): Promise<PrismeaiAPI.ConfigureAppInstance.Responses.$200> {
712
+ ): Promise<Fetched<PrismeaiAPI.ConfigureAppInstance.Responses.$200>> {
518
713
  return await this.patch(`/workspaces/${workspaceId}/apps/${slug}`, body);
519
714
  }
520
715
 
521
716
  async uninstallApp(
522
717
  workspaceId: PrismeaiAPI.UninstallAppInstance.PathParameters['workspaceId'],
523
718
  slug: PrismeaiAPI.ConfigureAppInstance.PathParameters['slug']
524
- ): Promise<PrismeaiAPI.UninstallAppInstance.Responses.$200> {
719
+ ): Promise<Fetched<PrismeaiAPI.UninstallAppInstance.Responses.$200>> {
525
720
  return await this.delete(`/workspaces/${workspaceId}/apps/${slug}`);
526
721
  }
527
722
 
528
723
  async publishApp(
529
724
  body: PrismeaiAPI.PublishApp.RequestBody
530
- ): Promise<PrismeaiAPI.PublishApp.Responses.$200> {
725
+ ): Promise<Fetched<PrismeaiAPI.PublishApp.Responses.$200>> {
531
726
  return await this.post(`/apps`, body);
532
727
  }
533
728
 
729
+ // @deprecated. Use api.workspaces(id).listAppInstances())
534
730
  async listAppInstances(
535
731
  workspaceId: PrismeaiAPI.ListAppInstances.PathParameters['workspaceId']
536
- ): Promise<PrismeaiAPI.ListAppInstances.Responses.$200> {
732
+ ): Promise<Fetched<PrismeaiAPI.ListAppInstances.Responses.$200>> {
537
733
  return await this.get(`/workspaces/${workspaceId}/apps`);
538
734
  }
539
735
 
@@ -562,7 +758,7 @@ export class Api extends Fetcher {
562
758
  async getAppInstance(
563
759
  workspaceId: string,
564
760
  slug: string
565
- ): Promise<PrismeaiAPI.GetAppInstance.Responses.$200> {
761
+ ): Promise<Fetched<PrismeaiAPI.GetAppInstance.Responses.$200>> {
566
762
  return this.get(`/workspaces/${workspaceId}/apps/${slug}`);
567
763
  }
568
764
 
@@ -570,7 +766,7 @@ export class Api extends Fetcher {
570
766
  workspaceId: PrismeaiAPI.ConfigureAppInstance.Parameters.WorkspaceId,
571
767
  slug: PrismeaiAPI.ConfigureAppInstance.Parameters.Slug,
572
768
  appInstance: PrismeaiAPI.ConfigureAppInstance.RequestBody
573
- ): Promise<PrismeaiAPI.ConfigureAppInstance.Responses.$200> {
769
+ ): Promise<Fetched<PrismeaiAPI.ConfigureAppInstance.Responses.$200>> {
574
770
  const response = await this.patch<Prismeai.DetailedAppInstance>(
575
771
  `/workspaces/${workspaceId}/apps/${slug}`,
576
772
  { ...appInstance }
@@ -578,37 +774,31 @@ export class Api extends Fetcher {
578
774
  return response;
579
775
  }
580
776
 
581
- async uploadFiles(files: string | string[], workspaceId: string) {
582
- function dataURItoBlob(dataURI: string): [Blob, string] {
583
- // convert base64/URLEncoded data component to raw binary data held in a string
584
- let byteString;
585
- if (dataURI.split(',')[0].indexOf('base64') >= 0)
586
- byteString = atob(dataURI.split(',')[1]);
587
- else byteString = unescape(dataURI.split(',')[1]);
588
- // separate out the mime component
589
- const metadata = dataURI
590
- .split(';')
591
- .filter((v, k, all) => k < all.length - 1)
592
- .map((v) => v.split(/:/));
593
- const [, mimeString = ''] = metadata.find(([k, v]) => k === 'data') || [];
594
- const [, ext] = mimeString.split(/\//);
595
- const [, fileName = `file.${ext}`] =
596
- metadata.find(([k, v]) => k === 'filename') || [];
597
-
598
- // write the bytes of the string to a typed array
599
- let ia = new Uint8Array(byteString.length);
600
- for (var i = 0; i < byteString.length; i++) {
601
- ia[i] = byteString.charCodeAt(i);
602
- }
603
-
604
- return [new Blob([ia], { type: mimeString }), fileName];
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;
605
785
  }
786
+ ) {
606
787
  const formData = new FormData();
607
788
  (Array.isArray(files) ? files : [files]).forEach((file) => {
608
789
  try {
609
790
  formData.append('file', ...dataURItoBlob(file));
610
791
  } catch {}
611
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
+ }
612
802
  try {
613
803
  return await this._fetch<PrismeaiAPI.UploadFile.Responses.$200>(
614
804
  `/workspaces/${workspaceId}/files`,
@@ -665,17 +855,39 @@ export class Api extends Fetcher {
665
855
  return replaced;
666
856
  }
667
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
+
668
865
  async callAutomation(
669
866
  workspaceId: string,
670
867
  automation: string,
671
868
  params?: any
672
- ): Promise<any> {
869
+ ): Promise<Fetched<any>> {
673
870
  return this.post(
674
871
  `/workspaces/${workspaceId}/webhooks/${automation}`,
675
872
  params
676
873
  );
677
874
  }
678
875
 
876
+ async testAutomation({
877
+ workspaceId,
878
+ automation,
879
+ payload,
880
+ }: {
881
+ workspaceId: string;
882
+ automation: string;
883
+ payload?: Record<string, any>;
884
+ }): Promise<Fetched<any>> {
885
+ return this.post(`/workspaces/${workspaceId}/test/${automation}`, {
886
+ payload,
887
+ });
888
+ }
889
+
890
+ // @deprecated. Use api.workspaces(id).getUsage())
679
891
  async getWorkspaceUsage(
680
892
  workspaceId: PrismeaiAPI.WorkspaceUsage.Parameters.WorkspaceId,
681
893
  {
@@ -687,7 +899,7 @@ export class Api extends Fetcher {
687
899
  beforeDate?: PrismeaiAPI.WorkspaceUsage.Parameters.BeforeDate;
688
900
  details?: PrismeaiAPI.WorkspaceUsage.Parameters.Details;
689
901
  } = {}
690
- ): Promise<PrismeaiAPI.WorkspaceUsage.Responses.$200> {
902
+ ): Promise<Fetched<PrismeaiAPI.WorkspaceUsage.Responses.$200>> {
691
903
  const params = new URLSearchParams(
692
904
  removedUndefinedProperties(
693
905
  {
@@ -702,9 +914,36 @@ export class Api extends Fetcher {
702
914
  return this.get(`/workspaces/${workspaceId}/usage?${params.toString()}`);
703
915
  }
704
916
 
917
+ async importArchive(archive: File): Promise<ImportSuccess> {
918
+ return new Promise((resolve) => {
919
+ const fileReader = new FileReader();
920
+ fileReader.addEventListener('load', async ({ target }) => {
921
+ const file = target?.result as string;
922
+ const formData = new FormData();
923
+ formData.append('archive', ...dataURItoBlob(file));
924
+
925
+ const result = await this.post<ImportProcessing | ImportSuccess>(
926
+ `/workspaces/import`,
927
+ formData
928
+ );
929
+ if ((result as ImportProcessing).processing) {
930
+ throw new ImportProcessingError(result as ImportProcessing);
931
+ }
932
+ resolve(result as ImportSuccess);
933
+ });
934
+ fileReader.readAsDataURL(archive);
935
+ });
936
+ }
937
+
938
+ users(id: string = this.user?.id || '') {
939
+ if (!id) {
940
+ throw new Error();
941
+ }
942
+ return new UsersEndpoint(id, this);
943
+ }
705
944
  workspaces(id: string) {
706
945
  return new WorkspacesEndpoint(id, this);
707
946
  }
708
947
  }
709
948
 
710
- export default new Api('https://api.eda.prisme.ai');
949
+ export default new Api({ host: 'https://api.eda.prisme.ai' });