@prisme.ai/sdk 1.0.0 → 1.0.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/lib/api.ts CHANGED
@@ -1,10 +1,12 @@
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';
8
10
 
9
11
  interface PageWithMetadata extends Prismeai.Page {
10
12
  createdAt: string;
@@ -24,10 +26,74 @@ export type UserPermissions = {
24
26
  };
25
27
  };
26
28
 
29
+ export interface ApiOptions {
30
+ host: string;
31
+ oidc?: {
32
+ url: string;
33
+ clientId: string;
34
+ clientIdHeader?: string;
35
+ redirectUri: string;
36
+ };
37
+ }
38
+
39
+ export interface AccessToken {
40
+ access_token: string;
41
+ id_token: string;
42
+ scope: string;
43
+ expiresIn: number;
44
+ token_type: 'Bearer';
45
+ }
46
+
47
+ export interface InteractiveSignin {
48
+ interaction: string;
49
+ login: string;
50
+ password: string;
51
+ remember?: boolean;
52
+ }
53
+
54
+ function dataURItoBlob(dataURI: string): [Blob, string] {
55
+ // convert base64/URLEncoded data component to raw binary data held in a string
56
+ let byteString;
57
+ if (dataURI.split(',')[0].indexOf('base64') >= 0)
58
+ byteString = atob(dataURI.split(',')[1]);
59
+ else byteString = unescape(dataURI.split(',')[1]);
60
+ // separate out the mime component
61
+ const metadata = dataURI
62
+ .split(';')
63
+ .filter((v, k, all) => k < all.length - 1)
64
+ .map((v) => v.split(/:/));
65
+ const [, mimeString = ''] = metadata.find(([k, v]) => k === 'data') || [];
66
+ const [, ext] = mimeString.split(/\//);
67
+ const [, fileName = `file.${ext}`] =
68
+ metadata.find(([k, v]) => k === 'filename') || [];
69
+
70
+ // write the bytes of the string to a typed array
71
+ let ia = new Uint8Array(byteString.length);
72
+ for (var i = 0; i < byteString.length; i++) {
73
+ ia[i] = byteString.charCodeAt(i);
74
+ }
75
+
76
+ return [new Blob([ia], { type: mimeString }), fileName];
77
+ }
78
+
27
79
  export class Api extends Fetcher {
80
+ public opts: Required<ApiOptions>;
28
81
  private sessionId?: string;
29
82
  private _user?: Prismeai.User & { sessionId?: string };
30
83
 
84
+ constructor(opts: ApiOptions) {
85
+ super(opts.host, opts?.oidc?.clientIdHeader);
86
+ this.opts = {
87
+ ...opts,
88
+ oidc: {
89
+ url: 'http://studio.local.prisme.ai:3001',
90
+ clientId: 'local-client-id',
91
+ redirectUri: 'http://studio.local.prisme.ai:3000/signin',
92
+ ...opts.oidc,
93
+ },
94
+ };
95
+ }
96
+
31
97
  get user() {
32
98
  return this._user;
33
99
  }
@@ -39,24 +105,85 @@ export class Api extends Fetcher {
39
105
  return me;
40
106
  }
41
107
 
42
- async signin(
43
- email: string,
44
- password: string
45
- ): Promise<
46
- Prismeai.User & {
47
- token: string;
108
+ clientId(): string {
109
+ return this.overwriteClientId || this.opts?.oidc?.clientId;
110
+ }
111
+
112
+ async getAuthorizationURL(
113
+ overrideRedirectUri?: string,
114
+ authParams?: { max_age?: string; acr_values?: string },
115
+ locale = window?.navigator?.language
116
+ ? window.navigator.language.substring(0, 2)
117
+ : undefined
118
+ ) {
119
+ const url = new URL('/oidc/auth', this.opts.oidc.url);
120
+ url.searchParams.set('response_type', 'code');
121
+ url.searchParams.set('response_mode', 'query'); // Send the final authorization code as a query param to the redirect uri
122
+ url.searchParams.set(
123
+ 'redirect_uri',
124
+ overrideRedirectUri || this.opts.oidc?.redirectUri || ''
125
+ );
126
+ url.searchParams.set(
127
+ 'scope',
128
+ 'openid profile email settings offline_access events:write events:read webhooks pages:read files:write files:read'
129
+ );
130
+ const clientId = this.clientId();
131
+ url.searchParams.set('client_id', clientId);
132
+
133
+ url.searchParams.set('code_challenge_method', 'S256');
134
+ const { code_verifier: codeVerifier, code_challenge: codeChallenge } =
135
+ await pkceChallenge(64);
136
+ url.searchParams.set('code_challenge', codeChallenge);
137
+ if (locale) {
138
+ url.searchParams.set('locale', locale);
48
139
  }
49
- > {
50
- const user = await this.post<
51
- Prismeai.User & {
52
- token: string;
53
- }
54
- >('/login', {
55
- email,
56
- password,
140
+
141
+ Object.entries(authParams || {}).forEach(([k, v]) => {
142
+ url.searchParams.set(k, v);
57
143
  });
58
- this._user = user;
59
- return user;
144
+
145
+ return {
146
+ url: url.toString(),
147
+ codeVerifier,
148
+ clientId,
149
+ };
150
+ }
151
+
152
+ async signin(body: InteractiveSignin): Promise<{ redirectTo: string }> {
153
+ const url = new URL(
154
+ `/oidc/interaction/${body.interaction}/login`,
155
+ this.opts.oidc.url
156
+ );
157
+
158
+ // Do not follow redirects as we need to get redirected from browser itself to save final token in local storage
159
+ await this.post(url.toString(), new URLSearchParams(body as any), {
160
+ redirect: 'manual',
161
+ });
162
+ const redirectTo = new URL(
163
+ `/oidc/auth/${body.interaction}`,
164
+ this.opts.oidc.url
165
+ );
166
+ return { redirectTo: redirectTo.toString() };
167
+ }
168
+
169
+ async getToken(
170
+ authorizationCode: string,
171
+ codeVerifier: string,
172
+ overrideRedirectUri?: string
173
+ ): Promise<AccessToken> {
174
+ this.token = null;
175
+ const url = new URL('/oidc/token', this.opts.oidc.url);
176
+ const token = await this.post<AccessToken>(
177
+ url.toString(),
178
+ new URLSearchParams({
179
+ grant_type: 'authorization_code',
180
+ code: authorizationCode,
181
+ code_verifier: codeVerifier,
182
+ client_id: this.clientId(),
183
+ redirect_uri: overrideRedirectUri || this.opts.oidc.redirectUri,
184
+ })
185
+ );
186
+ return token;
60
187
  }
61
188
 
62
189
  async createAnonymousSession(): Promise<
@@ -68,7 +195,13 @@ export class Api extends Fetcher {
68
195
  Prismeai.User & {
69
196
  token: string;
70
197
  }
71
- >('/login/anonymous');
198
+ >(
199
+ '/login/anonymous',
200
+ {},
201
+ {
202
+ credentials: 'omit',
203
+ }
204
+ );
72
205
  this._user = user;
73
206
  return user;
74
207
  }
@@ -93,9 +226,17 @@ export class Api extends Fetcher {
93
226
  });
94
227
  }
95
228
 
96
- async signout() {
97
- await this.post('/logout');
98
- this.token = null;
229
+ getSignoutURL(redirectUri?: string) {
230
+ const params = new URLSearchParams();
231
+ params.set('client_id', this.clientId());
232
+ if (redirectUri) {
233
+ params.set('post_logout_redirect_uri', redirectUri);
234
+ }
235
+ const url = new URL(
236
+ `/oidc/session/end?${params.toString()}`,
237
+ this.opts.oidc.url
238
+ );
239
+ return url.toString();
99
240
  }
100
241
 
101
242
  // Mail validation
@@ -136,13 +277,13 @@ export class Api extends Fetcher {
136
277
  async updateWorkspaceSecurity(
137
278
  workspaceId: string,
138
279
  security: Prismeai.WorkspaceSecurity
139
- ): Promise<PrismeaiAPI.UpdateSecurity.Responses.$200> {
280
+ ): Promise<Fetched<PrismeaiAPI.UpdateSecurity.Responses.$200>> {
140
281
  return await this.put(`/workspaces/${workspaceId}/security`, security);
141
282
  }
142
283
 
143
284
  async getWorkspaceRoles(
144
285
  id: string
145
- ): Promise<PrismeaiAPI.GetRoles.Responses.$200> {
286
+ ): Promise<Fetched<PrismeaiAPI.GetRoles.Responses.$200>> {
146
287
  return await this.get(`/workspaces/${id}/security/roles`);
147
288
  }
148
289
 
@@ -156,7 +297,7 @@ export class Api extends Fetcher {
156
297
 
157
298
  async updateWorkspace(
158
299
  workspace: Prismeai.DSULPatch
159
- ): Promise<PrismeaiAPI.UpdateWorkspace.Responses.$200 | null> {
300
+ ): Promise<Fetched<PrismeaiAPI.UpdateWorkspace.Responses.$200> | null> {
160
301
  if (!workspace.id) return null;
161
302
  return await this.patch(
162
303
  `/workspaces/${workspace.id}`,
@@ -223,7 +364,7 @@ export class Api extends Fetcher {
223
364
  async getAutomation(
224
365
  workspaceId: string,
225
366
  automationSlug: string
226
- ): Promise<PrismeaiAPI.GetAutomation.Responses.$200> {
367
+ ): Promise<Fetched<PrismeaiAPI.GetAutomation.Responses.$200>> {
227
368
  return await this.get(
228
369
  `/workspaces/${workspaceId}/automations/${automationSlug}`
229
370
  );
@@ -232,7 +373,7 @@ export class Api extends Fetcher {
232
373
  async createAutomation(
233
374
  workspaceId: Workspace['id'],
234
375
  automation: Prismeai.Automation
235
- ): Promise<Prismeai.Automation & { slug: string }> {
376
+ ): Promise<Fetched<Prismeai.Automation & { slug: string }>> {
236
377
  return await this.post(`/workspaces/${workspaceId}/automations`, {
237
378
  ...automation,
238
379
  });
@@ -242,7 +383,7 @@ export class Api extends Fetcher {
242
383
  workspaceId: string,
243
384
  slug: string,
244
385
  automation: Prismeai.Automation
245
- ): Promise<Prismeai.Automation & { slug: string }> {
386
+ ): Promise<Fetched<Prismeai.Automation & { slug: string }>> {
246
387
  return await this.patch(
247
388
  `/workspaces/${workspaceId}/automations/${slug}`,
248
389
  await this.replaceAllImagesData(automation, workspaceId)
@@ -272,7 +413,7 @@ export class Api extends Fetcher {
272
413
  async getPage(
273
414
  workspaceId: PrismeaiAPI.GetPage.Parameters.WorkspaceId,
274
415
  pageSlug: PrismeaiAPI.GetPage.Parameters.Slug
275
- ): Promise<Prismeai.DetailedPage> {
416
+ ): Promise<Fetched<Prismeai.DetailedPage>> {
276
417
  return await this.get(
277
418
  `/workspaces/${workspaceId}/pages/${encodeURIComponent(pageSlug)}`
278
419
  );
@@ -281,7 +422,7 @@ export class Api extends Fetcher {
281
422
  async getPageBySlug(
282
423
  workspaceSlug: PrismeaiAPI.GetPageBySlug.Parameters.WorkspaceSlug,
283
424
  pageSlug: PrismeaiAPI.GetPageBySlug.Parameters.PageSlug
284
- ): Promise<Prismeai.DetailedPage> {
425
+ ): Promise<Fetched<Prismeai.DetailedPage>> {
285
426
  return await this.get(
286
427
  `/pages/${workspaceSlug}/${encodeURIComponent(pageSlug)}`
287
428
  );
@@ -316,7 +457,7 @@ export class Api extends Fetcher {
316
457
  async deletePage(
317
458
  workspaceId: PrismeaiAPI.DeletePage.Parameters.WorkspaceId,
318
459
  pageSlug: PrismeaiAPI.DeletePage.Parameters.Slug
319
- ): Promise<PrismeaiAPI.DeletePage.Responses.$200> {
460
+ ): Promise<Fetched<PrismeaiAPI.DeletePage.Responses.$200>> {
320
461
  return await this.delete(
321
462
  `/workspaces/${workspaceId}/pages/${encodeURIComponent(pageSlug)}`
322
463
  );
@@ -337,6 +478,7 @@ export class Api extends Fetcher {
337
478
  const events = new Events({
338
479
  workspaceId,
339
480
  token: this.token || '',
481
+ legacyToken: this.legacyToken || '',
340
482
  apiKey: this._apiKey ? this._apiKey : undefined,
341
483
  apiHost: this.host,
342
484
  filters,
@@ -474,7 +616,7 @@ export class Api extends Fetcher {
474
616
  subjectType: PrismeaiAPI.GetPermissions.Parameters.SubjectType,
475
617
  subjectId: string,
476
618
  id: string
477
- ): Promise<PrismeaiAPI.RevokePermissions.Responses.$200> {
619
+ ): Promise<Fetched<PrismeaiAPI.RevokePermissions.Responses.$200>> {
478
620
  return await this.delete(`/${subjectType}/${subjectId}/permissions/${id}`);
479
621
  }
480
622
 
@@ -488,7 +630,7 @@ export class Api extends Fetcher {
488
630
  page?: PrismeaiAPI.SearchApps.QueryParameters['page'];
489
631
  limit?: PrismeaiAPI.SearchApps.QueryParameters['limit'];
490
632
  workspaceId?: PrismeaiAPI.SearchApps.QueryParameters['workspaceId'];
491
- }): Promise<PrismeaiAPI.SearchApps.Responses.$200> {
633
+ }): Promise<Fetched<PrismeaiAPI.SearchApps.Responses.$200>> {
492
634
  const params = new URLSearchParams(
493
635
  removedUndefinedProperties(
494
636
  {
@@ -506,7 +648,7 @@ export class Api extends Fetcher {
506
648
  async installApp(
507
649
  workspaceId: PrismeaiAPI.InstallAppInstance.PathParameters['workspaceId'],
508
650
  body: PrismeaiAPI.InstallAppInstance.RequestBody
509
- ): Promise<PrismeaiAPI.InstallAppInstance.Responses.$200> {
651
+ ): Promise<Fetched<PrismeaiAPI.InstallAppInstance.Responses.$200>> {
510
652
  return await this.post(`/workspaces/${workspaceId}/apps`, body);
511
653
  }
512
654
 
@@ -514,26 +656,26 @@ export class Api extends Fetcher {
514
656
  workspaceId: PrismeaiAPI.ConfigureAppInstance.PathParameters['workspaceId'],
515
657
  slug: PrismeaiAPI.ConfigureAppInstance.PathParameters['slug'],
516
658
  body: PrismeaiAPI.ConfigureAppInstance.RequestBody
517
- ): Promise<PrismeaiAPI.ConfigureAppInstance.Responses.$200> {
659
+ ): Promise<Fetched<PrismeaiAPI.ConfigureAppInstance.Responses.$200>> {
518
660
  return await this.patch(`/workspaces/${workspaceId}/apps/${slug}`, body);
519
661
  }
520
662
 
521
663
  async uninstallApp(
522
664
  workspaceId: PrismeaiAPI.UninstallAppInstance.PathParameters['workspaceId'],
523
665
  slug: PrismeaiAPI.ConfigureAppInstance.PathParameters['slug']
524
- ): Promise<PrismeaiAPI.UninstallAppInstance.Responses.$200> {
666
+ ): Promise<Fetched<PrismeaiAPI.UninstallAppInstance.Responses.$200>> {
525
667
  return await this.delete(`/workspaces/${workspaceId}/apps/${slug}`);
526
668
  }
527
669
 
528
670
  async publishApp(
529
671
  body: PrismeaiAPI.PublishApp.RequestBody
530
- ): Promise<PrismeaiAPI.PublishApp.Responses.$200> {
672
+ ): Promise<Fetched<PrismeaiAPI.PublishApp.Responses.$200>> {
531
673
  return await this.post(`/apps`, body);
532
674
  }
533
675
 
534
676
  async listAppInstances(
535
677
  workspaceId: PrismeaiAPI.ListAppInstances.PathParameters['workspaceId']
536
- ): Promise<PrismeaiAPI.ListAppInstances.Responses.$200> {
678
+ ): Promise<Fetched<PrismeaiAPI.ListAppInstances.Responses.$200>> {
537
679
  return await this.get(`/workspaces/${workspaceId}/apps`);
538
680
  }
539
681
 
@@ -562,7 +704,7 @@ export class Api extends Fetcher {
562
704
  async getAppInstance(
563
705
  workspaceId: string,
564
706
  slug: string
565
- ): Promise<PrismeaiAPI.GetAppInstance.Responses.$200> {
707
+ ): Promise<Fetched<PrismeaiAPI.GetAppInstance.Responses.$200>> {
566
708
  return this.get(`/workspaces/${workspaceId}/apps/${slug}`);
567
709
  }
568
710
 
@@ -570,7 +712,7 @@ export class Api extends Fetcher {
570
712
  workspaceId: PrismeaiAPI.ConfigureAppInstance.Parameters.WorkspaceId,
571
713
  slug: PrismeaiAPI.ConfigureAppInstance.Parameters.Slug,
572
714
  appInstance: PrismeaiAPI.ConfigureAppInstance.RequestBody
573
- ): Promise<PrismeaiAPI.ConfigureAppInstance.Responses.$200> {
715
+ ): Promise<Fetched<PrismeaiAPI.ConfigureAppInstance.Responses.$200>> {
574
716
  const response = await this.patch<Prismeai.DetailedAppInstance>(
575
717
  `/workspaces/${workspaceId}/apps/${slug}`,
576
718
  { ...appInstance }
@@ -579,30 +721,6 @@ export class Api extends Fetcher {
579
721
  }
580
722
 
581
723
  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];
605
- }
606
724
  const formData = new FormData();
607
725
  (Array.isArray(files) ? files : [files]).forEach((file) => {
608
726
  try {
@@ -669,13 +787,27 @@ export class Api extends Fetcher {
669
787
  workspaceId: string,
670
788
  automation: string,
671
789
  params?: any
672
- ): Promise<any> {
790
+ ): Promise<Fetched<any>> {
673
791
  return this.post(
674
792
  `/workspaces/${workspaceId}/webhooks/${automation}`,
675
793
  params
676
794
  );
677
795
  }
678
796
 
797
+ async testAutomation({
798
+ workspaceId,
799
+ automation,
800
+ payload,
801
+ }: {
802
+ workspaceId: string;
803
+ automation: string;
804
+ payload?: Record<string, any>;
805
+ }): Promise<Fetched<any>> {
806
+ return this.post(`/workspaces/${workspaceId}/test/${automation}`, {
807
+ payload,
808
+ });
809
+ }
810
+
679
811
  async getWorkspaceUsage(
680
812
  workspaceId: PrismeaiAPI.WorkspaceUsage.Parameters.WorkspaceId,
681
813
  {
@@ -687,7 +819,7 @@ export class Api extends Fetcher {
687
819
  beforeDate?: PrismeaiAPI.WorkspaceUsage.Parameters.BeforeDate;
688
820
  details?: PrismeaiAPI.WorkspaceUsage.Parameters.Details;
689
821
  } = {}
690
- ): Promise<PrismeaiAPI.WorkspaceUsage.Responses.$200> {
822
+ ): Promise<Fetched<PrismeaiAPI.WorkspaceUsage.Responses.$200>> {
691
823
  const params = new URLSearchParams(
692
824
  removedUndefinedProperties(
693
825
  {
@@ -702,9 +834,38 @@ export class Api extends Fetcher {
702
834
  return this.get(`/workspaces/${workspaceId}/usage?${params.toString()}`);
703
835
  }
704
836
 
837
+ async importArchive(
838
+ archive: File
839
+ ): Promise<PrismeaiAPI.ImportNewWorkspace.Responses.$200> {
840
+ return new Promise((resolve) => {
841
+ const fileReader = new FileReader();
842
+ fileReader.addEventListener('load', async ({ target }) => {
843
+ const file = target?.result as string;
844
+ const formData = new FormData();
845
+ formData.append('archive', ...dataURItoBlob(file));
846
+ resolve(
847
+ await this._fetch<PrismeaiAPI.ImportNewWorkspace.Responses.$200>(
848
+ `/workspaces/import`,
849
+ {
850
+ method: 'POST',
851
+ body: formData,
852
+ }
853
+ )
854
+ );
855
+ });
856
+ fileReader.readAsDataURL(archive);
857
+ });
858
+ }
859
+
860
+ users(id: string = this.user?.id || '') {
861
+ if (!id) {
862
+ throw new Error();
863
+ }
864
+ return new UsersEndpoint(id, this);
865
+ }
705
866
  workspaces(id: string) {
706
867
  return new WorkspacesEndpoint(id, this);
707
868
  }
708
869
  }
709
870
 
710
- export default new Api('https://api.eda.prisme.ai');
871
+ export default new Api({ host: 'https://api.eda.prisme.ai' });
@@ -0,0 +1,22 @@
1
+ import { Api } from '../api';
2
+
3
+ export class UsersEndpoint {
4
+ private id: string;
5
+ private api: Api;
6
+
7
+ constructor(id: string, api: Api) {
8
+ this.id = id;
9
+ this.api = api;
10
+ }
11
+
12
+ async setMeta(k: string, v: any) {
13
+ await this.api.post(`/user/meta`, {
14
+ [k]: v,
15
+ });
16
+ }
17
+ async deleteMeta(k: string) {
18
+ await this.api.delete(`/user/meta/${k}`);
19
+ }
20
+ }
21
+
22
+ export default UsersEndpoint;
@@ -21,7 +21,7 @@ it('should connect to Websocket', () => {
21
21
  `https://api.eda.prisme.ai/workspaces/1/events`,
22
22
  {
23
23
  extraHeaders: {
24
- 'x-prismeai-token': 'abcde',
24
+ Authorization: 'Bearer abcde',
25
25
  },
26
26
  withCredentials: true,
27
27
  }
@@ -39,7 +39,7 @@ it('should connect to Websocket with apiKey', () => {
39
39
  `https://api.eda.prisme.ai/workspaces/1/events`,
40
40
  {
41
41
  extraHeaders: {
42
- 'x-prismeai-token': 'abcde',
42
+ Authorization: 'Bearer abcde',
43
43
  'x-prismeai-api-key': 'fghij',
44
44
  },
45
45
  withCredentials: true,
package/lib/events.ts CHANGED
@@ -24,6 +24,7 @@ export class Events {
24
24
  constructor({
25
25
  workspaceId,
26
26
  token,
27
+ legacyToken,
27
28
  apiKey,
28
29
  apiHost = 'https://api.eda.prisme.ai',
29
30
  filters,
@@ -31,6 +32,7 @@ export class Events {
31
32
  }: {
32
33
  workspaceId: string;
33
34
  token: string;
35
+ legacyToken?: string;
34
36
  apiKey?: string;
35
37
  apiHost?: string;
36
38
  filters?: Record<string, any>;
@@ -39,9 +41,11 @@ export class Events {
39
41
  this.workspaceId = workspaceId;
40
42
  const queryString = new URLSearchParams(filters || {}).toString();
41
43
  const fullQueryString = queryString ? `?${queryString}` : '';
42
- const extraHeaders: any = {
43
- 'x-prismeai-token': token,
44
- };
44
+ const extraHeaders: any = token
45
+ ? {
46
+ Authorization: `Bearer ${token}`,
47
+ }
48
+ : { 'x-prismeai-token': legacyToken };
45
49
  this.lastReceivedEventDate = new Date();
46
50
  if (apiKey) {
47
51
  extraHeaders['x-prismeai-api-key'] = apiKey;
package/lib/fetcher.ts CHANGED
@@ -10,26 +10,36 @@ const headersAsObject = (headers: Headers) =>
10
10
  {}
11
11
  );
12
12
 
13
+ export type Fetched<T> = T & {
14
+ headers?: Record<string, any>;
15
+ };
16
+
13
17
  export class Fetcher {
14
18
  public host: string;
15
19
  public token: string | null = null;
20
+ public legacyToken: string | null = null;
21
+ public overwriteClientId?: string;
22
+ private clientIdHeader?: string;
16
23
  protected _apiKey: string | null = null;
17
24
  public language: string | undefined;
25
+ public lastReceivedHeaders?: Record<string, any>;
18
26
 
19
- constructor(host: string) {
27
+ constructor(host: string, clientIdHeader?: string) {
20
28
  this.host = host;
29
+ this.clientIdHeader = clientIdHeader;
21
30
  }
22
31
 
23
32
  set apiKey(apiKey: string) {
24
33
  this._apiKey = apiKey;
25
34
  }
26
35
 
27
- prepareRequest(url: string,
28
- options: RequestInit = {}) {
36
+ prepareRequest(url: string, options: RequestInit = {}) {
29
37
  const headers = new Headers(options.headers || {});
30
38
 
31
- if (this.token && !headers.has('x-prismeai-token')) {
32
- headers.append('x-prismeai-token', this.token);
39
+ if (this.token && !headers.has('Authorization')) {
40
+ headers.append('Authorization', `Bearer ${this.token}`);
41
+ } else if (this.legacyToken && !headers.has('Authorization')) {
42
+ headers.append('x-prismeai-token', this.legacyToken);
33
43
  }
34
44
 
35
45
  if (this._apiKey && !headers.has('x-prismeai-apikey')) {
@@ -40,6 +50,10 @@ export class Fetcher {
40
50
  headers.append('accept-language', this.language);
41
51
  }
42
52
 
53
+ if (options.body instanceof URLSearchParams) {
54
+ headers.set('Content-Type', 'application/x-www-form-urlencoded');
55
+ }
56
+
43
57
  if (
44
58
  (!options.body || !(options.body instanceof FormData)) &&
45
59
  !headers.has('Content-Type')
@@ -47,9 +61,12 @@ export class Fetcher {
47
61
  headers.append('Content-Type', 'application/json');
48
62
  }
49
63
 
50
- headers.append('Access-Control-Allow-Origin', '*');
51
-
52
- return global.fetch(`${this.host}${url}`, {
64
+ const fullUrl =
65
+ url.startsWith('http://') || url.startsWith('https://')
66
+ ? url
67
+ : `${this.host}${url}`;
68
+ return global.fetch(fullUrl, {
69
+ credentials: 'include',
53
70
  ...options,
54
71
  headers,
55
72
  });
@@ -60,7 +77,14 @@ export class Fetcher {
60
77
  options: RequestInit = {}
61
78
  ): Promise<T> {
62
79
  const res = await this.prepareRequest(url, options);
80
+ if (options.redirect === 'manual' && res.status === 0) {
81
+ return { redirected: true } as T;
82
+ }
63
83
 
84
+ this.lastReceivedHeaders = headersAsObject(res.headers);
85
+ if (this.clientIdHeader && this.lastReceivedHeaders[this.clientIdHeader]) {
86
+ this.overwriteClientId = this.lastReceivedHeaders[this.clientIdHeader];
87
+ }
64
88
  if (!res.ok) {
65
89
  let error;
66
90
  try {
@@ -102,10 +126,16 @@ export class Fetcher {
102
126
  });
103
127
  }
104
128
 
105
- async post<T>(url: string, body?: Record<string, any>) {
129
+ async post<T>(url: string, body?: Record<string, any>, opts?: RequestInit) {
106
130
  return this._fetch<T>(url, {
107
131
  method: 'POST',
108
- body: body && !(body instanceof FormData) ? JSON.stringify(body) : body,
132
+ body:
133
+ body &&
134
+ !(body instanceof FormData) &&
135
+ !(body instanceof URLSearchParams)
136
+ ? JSON.stringify(body)
137
+ : body,
138
+ ...opts,
109
139
  });
110
140
  }
111
141
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prisme.ai/sdk",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Communicate with Prisme.ai API",
5
5
  "main": "dist/sdk/index.js",
6
6
  "scripts": {
@@ -10,6 +10,7 @@
10
10
  "license": "ISC",
11
11
  "dependencies": {
12
12
  "@prisme.ai/types": "^1.0.9",
13
+ "pkce-challenge": "^3.1.0",
13
14
  "qs": "^6.10.3",
14
15
  "socket.io-client": "^4.4.1"
15
16
  }