whio-api-sdk 1.0.154 → 1.0.156

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/quick-test.mjs ADDED
@@ -0,0 +1,155 @@
1
+ // Quick test of localhost:3000 API
2
+ console.log('🔍 Testing localhost:3000 API directly...\n');
3
+
4
+ // Test 1: Check if API is running
5
+ async function testAPIHealth() {
6
+ try {
7
+ console.log('1. 🏥 Testing API health...');
8
+ const response = await fetch('http://localhost:3000');
9
+ console.log('✅ API is running! Status:', response.status);
10
+ return true;
11
+ } catch (error) {
12
+ console.log('❌ API is not running:', error.message);
13
+ return false;
14
+ }
15
+ }
16
+
17
+ // Test 2: Try to create a user
18
+ async function testCreateUser() {
19
+ try {
20
+ console.log('\n2. 👤 Testing user creation...');
21
+ const userData = {
22
+ email: 'sdk-test@example.com',
23
+ password: 'testpassword123',
24
+ firstName: 'SDK',
25
+ lastName: 'Test'
26
+ };
27
+
28
+ const response = await fetch('http://localhost:3000/users', {
29
+ method: 'POST',
30
+ headers: {
31
+ 'Content-Type': 'application/json',
32
+ },
33
+ body: JSON.stringify(userData)
34
+ });
35
+
36
+ const responseData = await response.json().catch(() => null);
37
+
38
+ if (response.ok) {
39
+ console.log('✅ User created successfully!');
40
+ console.log('📧 Email:', responseData?.email);
41
+ return userData;
42
+ } else {
43
+ console.log('⚠️ User creation failed:', response.status, responseData?.message || 'Unknown error');
44
+ console.log('🔄 Will try to login with existing credentials...');
45
+ return userData; // Return credentials anyway for login test
46
+ }
47
+ } catch (error) {
48
+ console.log('❌ Error creating user:', error.message);
49
+ return null;
50
+ }
51
+ }
52
+
53
+ // Test 3: Try to login
54
+ async function testLogin(credentials) {
55
+ try {
56
+ console.log('\n3. 🔐 Testing login...');
57
+ const response = await fetch('http://localhost:3000/auth/login', {
58
+ method: 'POST',
59
+ headers: {
60
+ 'Content-Type': 'application/json',
61
+ },
62
+ body: JSON.stringify({
63
+ email: credentials.email,
64
+ password: credentials.password
65
+ })
66
+ });
67
+
68
+ const responseData = await response.json().catch(() => null);
69
+
70
+ if (response.ok && responseData?.access_token) {
71
+ console.log('✅ Login successful!');
72
+ console.log('🔑 Token received:', responseData.access_token.substring(0, 20) + '...');
73
+ console.log('👤 User ID:', responseData.user?.id);
74
+ return responseData;
75
+ } else {
76
+ console.log('❌ Login failed:', response.status, responseData?.message || 'Unknown error');
77
+ return null;
78
+ }
79
+ } catch (error) {
80
+ console.log('❌ Error during login:', error.message);
81
+ return null;
82
+ }
83
+ }
84
+
85
+ // Test 4: Test authenticated endpoint
86
+ async function testAuthenticatedEndpoint(token) {
87
+ try {
88
+ console.log('\n4. 🛡️ Testing authenticated endpoint (profile)...');
89
+ const response = await fetch('http://localhost:3000/auth/profile', {
90
+ method: 'GET',
91
+ headers: {
92
+ 'Authorization': `Bearer ${token}`,
93
+ 'Content-Type': 'application/json',
94
+ }
95
+ });
96
+
97
+ const responseData = await response.json().catch(() => null);
98
+
99
+ if (response.ok) {
100
+ console.log('✅ Profile retrieved successfully!');
101
+ console.log('📧 Email:', responseData?.email);
102
+ console.log('🏢 Organization ID:', responseData?.organizationId);
103
+ return responseData;
104
+ } else {
105
+ console.log('❌ Profile fetch failed:', response.status, responseData?.message || 'Unknown error');
106
+ return null;
107
+ }
108
+ } catch (error) {
109
+ console.log('❌ Error fetching profile:', error.message);
110
+ return null;
111
+ }
112
+ }
113
+
114
+ // Run all tests
115
+ async function runTests() {
116
+ console.log('🧪 Running API connectivity tests...\n');
117
+
118
+ const isHealthy = await testAPIHealth();
119
+ if (!isHealthy) {
120
+ console.log('\n❌ API is not running. Please start the medical-assistant-api on localhost:3000');
121
+ return;
122
+ }
123
+
124
+ const credentials = await testCreateUser();
125
+ if (!credentials) {
126
+ console.log('\n❌ Cannot proceed without user credentials');
127
+ return;
128
+ }
129
+
130
+ const loginData = await testLogin(credentials);
131
+ if (!loginData) {
132
+ console.log('\n❌ Cannot proceed without successful login');
133
+ return;
134
+ }
135
+
136
+ const profile = await testAuthenticatedEndpoint(loginData.access_token);
137
+ if (!profile) {
138
+ console.log('\n❌ Authentication is not working properly');
139
+ return;
140
+ }
141
+
142
+ console.log('\n🎉 Basic API tests passed!');
143
+ console.log('💡 The API is ready for SDK testing');
144
+ console.log('\n📋 Test Summary:');
145
+ console.log(' ✅ API is running on localhost:3000');
146
+ console.log(' ✅ User creation/login flow works');
147
+ console.log(' ✅ Authentication is working');
148
+ console.log(' ✅ Protected endpoints are accessible');
149
+
150
+ console.log('\n🔧 You can now use these credentials with the SDK:');
151
+ console.log(' 📧 Email:', credentials.email);
152
+ console.log(' 🔑 Password:', credentials.password);
153
+ }
154
+
155
+ runTests().catch(console.error);
package/src/sdk/index.ts CHANGED
@@ -1 +1,2 @@
1
- export { ApiSDK } from "./sdk";
1
+ export { ApiSDK } from "./sdk";
2
+ export * from "./types";
package/src/sdk/sdk.ts CHANGED
@@ -11,12 +11,19 @@ import {
11
11
  UpdateTemplateDto,
12
12
  GenerateTranscriptionSummaryDto,
13
13
  UpdateTranscriptionSummaryDto,
14
+ CreateTranscriptionSummaryDto,
14
15
  AssignOrganizationRoleDto,
15
16
  CreateUserTemplateDto,
16
17
  UpdateUserTemplateDto,
17
18
  CreateUserDto,
18
19
  UpdateUserDto,
20
+ CreateOrganizationDto,
21
+ UpdateOrganizationDto,
22
+ CreateTemplateCategoryDto,
23
+ UpdateTemplateCategoryDto,
24
+ AssignTeamTemplateDto,
19
25
  OrganizationRoleType,
26
+ RoleType,
20
27
  Organization,
21
28
  TemplateCategory,
22
29
  Template,
@@ -46,7 +53,7 @@ export class ApiSDK {
46
53
  this.initialize();
47
54
  }
48
55
 
49
- private async fetchConfig(url: string): Promise<void> {
56
+ public async fetchConfig(url: string): Promise<void> {
50
57
  const response = await fetch(url);
51
58
  if (!response.ok) {
52
59
  throw new Error(`Failed to fetch config from ${url}`);
@@ -117,7 +124,6 @@ export class ApiSDK {
117
124
  ): Promise<T> {
118
125
  const url = `${this.baseUrl}${endpoint}`;
119
126
  const defaultHeaders: Record<string, string> = {
120
- 'Content-Type': 'multipart/form-data',
121
127
  'ngrok-skip-browser-warning': 'true'
122
128
  };
123
129
 
@@ -125,6 +131,7 @@ export class ApiSDK {
125
131
  defaultHeaders['Authorization'] = `Bearer ${this.accessToken}`;
126
132
  }
127
133
 
134
+ // Don't set Content-Type for FormData - let browser set it with boundary
128
135
  const response = await fetch(url, {
129
136
  method: 'POST',
130
137
  headers: { ...defaultHeaders, ...headers },
@@ -151,7 +158,7 @@ export class ApiSDK {
151
158
  true
152
159
  );
153
160
  this.accessToken = response.access_token;
154
- this.refreshToken = response.referesh_token;
161
+ this.refreshToken = response.refresh_token;
155
162
 
156
163
  this.user = response.user;
157
164
 
@@ -277,12 +284,12 @@ export class ApiSDK {
277
284
  return this.request(urls.teams, 'POST', teamDto);
278
285
  }
279
286
 
280
- public async updateTeam(id: string, name: string, description: string): Promise<any> {
287
+ public async updateTeam(id: string, name: string, description: string): Promise<Team> {
281
288
  const teamDto: UpdateTeamDto = {
282
289
  name,
283
290
  description,
284
291
  };
285
- return this.request(`${urls.teams}/${id}`, 'PUT', teamDto);
292
+ return this.request<Team>(`${urls.teams}/${id}`, 'PATCH', teamDto);
286
293
  }
287
294
 
288
295
  public async addUserToTeam(teamId: string, userId: string, roleName: string): Promise<any> {
@@ -294,25 +301,31 @@ export class ApiSDK {
294
301
  return this.request(urls.teamRoles, 'POST', assignRoleDto);
295
302
  }
296
303
 
297
- public async removeUserFromTeam(teamId: string, userId: string): Promise<any> {
298
- const url = `${urls.teamRoles}/user/${userId}/team/${teamId}`;
299
- return this.request(urls.teamRoles, 'DELETE');
304
+ public async removeUserFromTeam(teamId: string, userId: string): Promise<void> {
305
+ await this.request(`${urls.teamRoles}/user/${userId}/team/${teamId}`, 'DELETE');
300
306
  }
301
- //unsure how we are going to deal with template categories just yet
302
- public async createTemplate(title: string, content: string): Promise<any> {
303
- const templateCategories = await this.request<TemplateCategory[]>(
304
- urls.templateCatedories,
305
- 'GET'
306
- );
307
+ public async createTemplate(title: string, content: string, categoryId?: string): Promise<Template> {
308
+ let finalCategoryId = categoryId;
309
+ if (!finalCategoryId) {
310
+ const templateCategories = await this.request<TemplateCategory[]>(
311
+ urls.templateCategories,
312
+ 'GET'
313
+ );
314
+ finalCategoryId = templateCategories[0]?.id;
315
+ if (!finalCategoryId) {
316
+ throw new Error('No template categories available. Please create one first.');
317
+ }
318
+ }
319
+
307
320
  const createTemplateDto: CreateTemplateDto = {
308
321
  title,
309
322
  content,
310
323
  isGlobal: false,
311
- categoryId: templateCategories[0]!.id,
324
+ categoryId: finalCategoryId,
312
325
  createdById: this.user!.id,
313
326
  organizationId: this.user!.organizationId,
314
327
  };
315
- return this.request(urls.templates, 'POST', createTemplateDto);
328
+ return this.request<Template>(urls.templates, 'POST', createTemplateDto);
316
329
  }
317
330
 
318
331
  public async createUserTemplate(
@@ -363,6 +376,10 @@ export class ApiSDK {
363
376
  return this.request<UserTemplate[]>(url, 'GET');
364
377
  }
365
378
 
379
+ // ======================
380
+ // trANSCRIPTION SUMMARY METHODS
381
+ // ======================
382
+
366
383
  public async generateTranscriptionSummary(
367
384
  transcript: string, templateId: string): Promise<TranscriptionSummary> {
368
385
  const generateSummaryDto: GenerateTranscriptionSummaryDto = {
@@ -379,6 +396,14 @@ export class ApiSDK {
379
396
  return transcriptionSummary;
380
397
  }
381
398
 
399
+ public async getByOrganizationTranscriptionSummaries(
400
+ organizationId: string): Promise<TranscriptionSummary[]> {
401
+ return this.request<TranscriptionSummary[]>(
402
+ `${urls.transcriptionSummaries}/organization/${organizationId}`,
403
+ 'GET'
404
+ );
405
+ }
406
+
382
407
  public async generateTranscriptionSummaryFromUserTemplate(
383
408
  transcript: string, userTemplateId: string): Promise<TranscriptionSummary> {
384
409
  const generateSummaryDto: GenerateTranscriptionSummaryDto = {
@@ -426,7 +451,7 @@ export class ApiSDK {
426
451
  return data;
427
452
  }
428
453
 
429
- public async transcribeBase64Audio(base64String: String): Promise<String> {
454
+ public async transcribeBase64Audio(base64String: string): Promise<string> {
430
455
  const transcript = await this.request<any>(
431
456
  urls.transcribeBase64Audio,
432
457
  'POST',
@@ -434,4 +459,177 @@ export class ApiSDK {
434
459
  return transcript.transcript;
435
460
  }
436
461
 
462
+ // ======================
463
+ // AUTH METHODS
464
+ // ======================
465
+
466
+ public async getProfile(): Promise<User> {
467
+ return this.request<User>(urls.profile, 'GET');
468
+ }
469
+
470
+ // ======================
471
+ // ORGANIZATION METHODS
472
+ // ======================
473
+
474
+ public async createOrganization(name: string, description?: string): Promise<Organization> {
475
+ const dto: CreateOrganizationDto = { name, description };
476
+ return this.request<Organization>(urls.organizations, 'POST', dto);
477
+ }
478
+
479
+ public async getOrganizations(): Promise<Organization[]> {
480
+ return this.request<Organization[]>(urls.organizations, 'GET');
481
+ }
482
+
483
+ public async getOrganization(id: string): Promise<Organization> {
484
+ return this.request<Organization>(`${urls.organizations}/${id}`, 'GET');
485
+ }
486
+
487
+ public async updateOrganization(id: string, name?: string, description?: string): Promise<Organization> {
488
+ const dto: UpdateOrganizationDto = { name, description };
489
+ return this.request<Organization>(`${urls.organizations}/${id}`, 'PATCH', dto);
490
+ }
491
+
492
+ public async deleteOrganization(id: string): Promise<void> {
493
+ await this.request(`${urls.organizations}/${id}`, 'DELETE');
494
+ }
495
+
496
+ public async addUserToOrganization(organizationId: string, userId: string): Promise<void> {
497
+ await this.request(`${urls.organizations}/${organizationId}/users/${userId}`, 'POST');
498
+ }
499
+
500
+ public async removeUserFromOrganization(organizationId: string, userId: string): Promise<void> {
501
+ await this.request(`${urls.organizations}/${organizationId}/users/${userId}`, 'DELETE');
502
+ }
503
+
504
+ // ======================
505
+ // USER METHODS
506
+ // ======================
507
+
508
+ public async getUsers(): Promise<User[]> {
509
+ return this.request<User[]>(urls.users, 'GET');
510
+ }
511
+
512
+ public async getUser(id: string): Promise<User> {
513
+ return this.request<User>(`${urls.users}/${id}`, 'GET');
514
+ }
515
+
516
+ public async getUsersByOrganization(organizationId: string): Promise<User[]> {
517
+ return this.request<User[]>(`${urls.users}/organization/${organizationId}`, 'GET');
518
+ }
519
+
520
+ public async updateUser(id: string, data: UpdateUserDto): Promise<User> {
521
+ return this.request<User>(`${urls.users}/${id}`, 'PATCH', data);
522
+ }
523
+
524
+ public async deleteUser(id: string): Promise<void> {
525
+ await this.request(`${urls.users}/${id}`, 'DELETE');
526
+ }
527
+
528
+ // ======================
529
+ // TEAM METHODS
530
+ // ======================
531
+
532
+ public async getTeams(): Promise<Team[]> {
533
+ return this.request<Team[]>(urls.teams, 'GET');
534
+ }
535
+
536
+ public async getTeam(id: string): Promise<Team> {
537
+ return this.request<Team>(`${urls.teams}/${id}`, 'GET');
538
+ }
539
+
540
+ public async getTeamsByOrganization(organizationId: string): Promise<Team[]> {
541
+ return this.request<Team[]>(`${urls.teams}/organization/${organizationId}`, 'GET');
542
+ }
543
+
544
+ public async deleteTeam(id: string): Promise<void> {
545
+ await this.request(`${urls.teams}/${id}`, 'DELETE');
546
+ }
547
+
548
+ // ======================
549
+ // TEMPLATE CATEGORY METHODS
550
+ // ======================
551
+
552
+ public async getTemplateCategories(): Promise<TemplateCategory[]> {
553
+ return this.request<TemplateCategory[]>(urls.templateCategories, 'GET');
554
+ }
555
+
556
+ public async getTemplateCategory(id: string): Promise<TemplateCategory> {
557
+ return this.request<TemplateCategory>(`${urls.templateCategories}/${id}`, 'GET');
558
+ }
559
+
560
+ public async createTemplateCategory(name: string): Promise<TemplateCategory> {
561
+ const dto: CreateTemplateCategoryDto = { name };
562
+ return this.request<TemplateCategory>(urls.templateCategories, 'POST', dto);
563
+ }
564
+
565
+ public async updateTemplateCategory(id: string, name: string): Promise<TemplateCategory> {
566
+ const dto: UpdateTemplateCategoryDto = { name };
567
+ return this.request<TemplateCategory>(`${urls.templateCategories}/${id}`, 'PATCH', dto);
568
+ }
569
+
570
+ public async deleteTemplateCategory(id: string): Promise<void> {
571
+ await this.request(`${urls.templateCategories}/${id}`, 'DELETE');
572
+ }
573
+
574
+ // ======================
575
+ // ENHANCED TEMPLATE METHODS
576
+ // ======================
577
+
578
+ public async getTemplate(id: string): Promise<Template> {
579
+ return this.request<Template>(`${urls.templates}/${id}`, 'GET');
580
+ }
581
+
582
+ public async deleteTemplate(id: string): Promise<void> {
583
+ await this.request(`${urls.templates}/${id}`, 'DELETE');
584
+ }
585
+
586
+ public async getUserTemplate(id: string): Promise<UserTemplate> {
587
+ return this.request<UserTemplate>(`${urls.userTemplates}/${id}`, 'GET');
588
+ }
589
+
590
+ public async deleteUserTemplate(id: string): Promise<void> {
591
+ await this.request(`${urls.userTemplates}/${id}`, 'DELETE');
592
+ }
593
+
594
+ // ======================
595
+ // TEAM TEMPLATE METHODS
596
+ // ======================
597
+
598
+ public async assignTemplateToTeam(teamId: string, templateId: string): Promise<void> {
599
+ const dto: AssignTeamTemplateDto = { teamId, templateId };
600
+ await this.request(urls.teamTemplates, 'POST', dto);
601
+ }
602
+
603
+ public async removeTemplateFromTeam(teamId: string, templateId: string): Promise<void> {
604
+ await this.request(`${urls.teamTemplates}/team/${teamId}/template/${templateId}`, 'DELETE');
605
+ }
606
+
607
+ // ======================
608
+ // TRANSCRIPTION SUMMARY METHODS
609
+ // ======================
610
+
611
+ public async getTranscriptionSummaries(): Promise<TranscriptionSummary[]> {
612
+ return this.request<TranscriptionSummary[]>(urls.transcriptionSummaries, 'GET');
613
+ }
614
+
615
+ public async getTranscriptionSummary(id: string): Promise<TranscriptionSummary> {
616
+ return this.request<TranscriptionSummary>(`${urls.transcriptionSummaries}/${id}`, 'GET');
617
+ }
618
+
619
+ public async getTranscriptionSummariesByUser(userId: string): Promise<TranscriptionSummary[]> {
620
+ return this.request<TranscriptionSummary[]>(`${urls.transcriptionSummaries}/user/${userId}`, 'GET');
621
+ }
622
+
623
+ public async deleteTranscriptionSummary(id: string): Promise<void> {
624
+ await this.request(`${urls.transcriptionSummaries}/${id}`, 'DELETE');
625
+ }
626
+
627
+ // ======================
628
+ // ENHANCED TEAM ROLE METHODS
629
+ // ======================
630
+
631
+ public async removeUserFromTeamFixed(teamId: string, userId: string): Promise<void> {
632
+ await this.request(`${urls.teamRoles}/user/${userId}/team/${teamId}`, 'DELETE');
633
+ }
634
+
437
635
  }
package/src/sdk/types.ts CHANGED
@@ -62,7 +62,7 @@ export interface User {
62
62
  // Login response type
63
63
  export interface LoginResponse {
64
64
  access_token: string;
65
- referesh_token: string;
65
+ refresh_token: string;
66
66
  user: User;
67
67
  }
68
68
 
@@ -276,12 +276,50 @@ export interface Team {
276
276
  }
277
277
 
278
278
  export interface TranscriptionAudioUploadResponse {
279
- success: Boolean,
280
- transcription: string,
281
- model_version: string,
282
- metadata: any[],
283
- duration: number,
284
- log: string,
279
+ success: boolean;
280
+ transcription: string;
281
+ model_version: string;
282
+ metadata: any[];
283
+ duration: number;
284
+ log: string;
285
285
  }
286
286
 
287
+ // Additional DTOs for missing functionality
288
+ export interface CreateOrganizationDto {
289
+ name: string;
290
+ description?: string;
291
+ }
292
+
293
+ export interface UpdateOrganizationDto {
294
+ name?: string;
295
+ description?: string;
296
+ }
297
+
298
+ export interface CreateTemplateCategoryDto {
299
+ name: string;
300
+ }
301
+
302
+ export interface UpdateTemplateCategoryDto {
303
+ name?: string;
304
+ }
287
305
 
306
+ export interface CreateTranscriptionSummaryDto {
307
+ userId: string;
308
+ templateId: string;
309
+ content: string;
310
+ anonymisedTranscript?: string;
311
+ metadata?: Record<string, any>;
312
+ }
313
+
314
+ export interface AssignTeamTemplateDto {
315
+ teamId: string;
316
+ templateId: string;
317
+ }
318
+
319
+ // Enum for global role types to match API
320
+ export enum RoleType {
321
+ SUPERUSER = 'SUPERUSER',
322
+ ADMIN = 'ADMIN',
323
+ TRIAL = 'TRIAL',
324
+ PAID = 'PAID',
325
+ }
package/src/sdk/urls.ts CHANGED
@@ -1,24 +1,40 @@
1
1
  const urls = {
2
+ // Auth
2
3
  login: '/auth/login',
4
+ profile: '/auth/profile',
3
5
  register: '/auth/register',
4
6
  refreshToken: '/auth/refresh-token',
5
7
  logout: '/auth/logout',
8
+
9
+ // Users
6
10
  user: '/users',
7
11
  users: '/users',
8
- roles: '/roles',
9
- teams: '/teams',
12
+
13
+ // Organizations
10
14
  organizations: '/organizations',
11
15
  organizationRoles: '/organization-roles',
12
- userRoles: '/user-roles',
16
+ userOrganizationRoles: '/user-organization-roles',
17
+
18
+ // Teams
19
+ teams: '/teams',
13
20
  teamRoles: '/team-roles',
21
+ teamTemplates: '/team-templates',
22
+
23
+ // Templates
14
24
  templates: '/templates',
15
- templateCatedories: '/template-categories',
25
+ templateCategories: '/template-categories',
16
26
  userTemplates: '/user-templates',
17
- userOrganizationRoles: '/user-organization-roles',
27
+
28
+ // Transcription Summaries
29
+ transcriptionSummaries: '/transcription-summaries',
18
30
  transcriptionSummary: '/transcription-summaries/generate',
19
31
  uploadAudioLarge: '/transcription-summaries/upload-audio-large',
20
32
  uploadAudio: '/transcription-summaries/upload-audio',
21
33
  transcribeBase64Audio: '/transcription-summaries/transcribe-base64',
34
+
35
+ // Roles
36
+ roles: '/roles',
37
+ userRoles: '/user-roles',
22
38
  }
23
39
 
24
40
  export default urls;