whio-api-sdk 1.0.193-bet-staging → 1.0.195-beta-staging
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/src/sdk/modules/agent.module.d.ts +17 -0
- package/dist/src/sdk/modules/agent.module.js +93 -0
- package/dist/src/sdk/modules/audio.module.d.ts +31 -0
- package/dist/src/sdk/modules/audio.module.js +147 -0
- package/dist/src/sdk/modules/auth.module.d.ts +9 -0
- package/dist/src/sdk/modules/auth.module.js +59 -0
- package/dist/src/sdk/modules/base-client.d.ts +25 -0
- package/dist/src/sdk/modules/base-client.js +183 -0
- package/dist/src/sdk/modules/debug.module.d.ts +20 -0
- package/dist/src/sdk/modules/debug.module.js +54 -0
- package/dist/src/sdk/modules/external-integration.module.d.ts +9 -0
- package/dist/src/sdk/modules/external-integration.module.js +38 -0
- package/dist/src/sdk/modules/log.module.d.ts +63 -0
- package/dist/src/sdk/modules/log.module.js +222 -0
- package/dist/src/sdk/modules/organization.module.d.ts +13 -0
- package/dist/src/sdk/modules/organization.module.js +60 -0
- package/dist/src/sdk/modules/session.module.d.ts +16 -0
- package/dist/src/sdk/modules/session.module.js +58 -0
- package/dist/src/sdk/modules/team.module.d.ts +13 -0
- package/dist/src/sdk/modules/team.module.js +72 -0
- package/dist/src/sdk/modules/template.module.d.ts +33 -0
- package/dist/src/sdk/modules/template.module.js +240 -0
- package/dist/src/sdk/modules/user.module.d.ts +17 -0
- package/dist/src/sdk/modules/user.module.js +104 -0
- package/dist/src/sdk/modules/workflow.module.d.ts +10 -0
- package/dist/src/sdk/modules/workflow.module.js +53 -0
- package/dist/src/sdk/sdk.d.ts +169 -211
- package/dist/src/sdk/sdk.js +385 -869
- package/dist/src/sdk/sdk.old.d.ts +222 -0
- package/dist/src/sdk/sdk.old.js +1238 -0
- package/dist/src/sdk/types/agent.types.d.ts +51 -0
- package/dist/src/sdk/types/agent.types.js +1 -0
- package/dist/src/sdk/types/audio.types.d.ts +72 -0
- package/dist/src/sdk/types/audio.types.js +8 -0
- package/dist/src/sdk/types/auth.types.d.ts +21 -0
- package/dist/src/sdk/types/auth.types.js +1 -0
- package/dist/src/sdk/types/common.types.d.ts +20 -0
- package/dist/src/sdk/types/common.types.js +9 -0
- package/dist/src/sdk/types/external-integration.types.d.ts +31 -0
- package/dist/src/sdk/types/external-integration.types.js +1 -0
- package/dist/src/sdk/types/index.d.ts +12 -0
- package/dist/src/sdk/types/index.js +13 -0
- package/dist/src/sdk/types/log.types.d.ts +61 -0
- package/dist/src/sdk/types/log.types.js +1 -0
- package/dist/src/sdk/types/organization.types.d.ts +42 -0
- package/dist/src/sdk/types/organization.types.js +6 -0
- package/dist/src/sdk/types/session.types.d.ts +54 -0
- package/dist/src/sdk/types/session.types.js +1 -0
- package/dist/src/sdk/types/team.types.d.ts +39 -0
- package/dist/src/sdk/types/team.types.js +1 -0
- package/dist/src/sdk/types/template.types.d.ts +118 -0
- package/dist/src/sdk/types/template.types.js +1 -0
- package/dist/src/sdk/types/user.types.d.ts +41 -0
- package/dist/src/sdk/types/user.types.js +1 -0
- package/dist/src/sdk/types/workflow.types.d.ts +19 -0
- package/dist/src/sdk/types/workflow.types.js +1 -0
- package/dist/src/sdk/types.d.ts +1 -517
- package/dist/src/sdk/types.js +2 -23
- package/dist/src/sdk/types.old.d.ts +517 -0
- package/dist/src/sdk/types.old.js +23 -0
- package/dist/src/sdk/urls.d.ts +1 -0
- package/dist/src/sdk/urls.js +2 -0
- package/package.json +1 -1
- package/src/sdk/modules/agent.module.ts +74 -0
- package/src/sdk/modules/audio.module.ts +131 -0
- package/src/sdk/modules/auth.module.ts +53 -0
- package/src/sdk/modules/base-client.ts +214 -0
- package/src/sdk/modules/debug.module.ts +44 -0
- package/src/sdk/modules/external-integration.module.ts +50 -0
- package/src/sdk/modules/log.module.ts +213 -0
- package/src/sdk/modules/organization.module.ts +43 -0
- package/src/sdk/modules/session.module.ts +41 -0
- package/src/sdk/modules/team.module.ts +55 -0
- package/src/sdk/modules/template.module.ts +242 -0
- package/src/sdk/modules/user.module.ts +89 -0
- package/src/sdk/modules/workflow.module.ts +39 -0
- package/src/sdk/sdk.old.ts +1312 -0
- package/src/sdk/sdk.ts +401 -1089
- package/src/sdk/types/agent.types.ts +65 -0
- package/src/sdk/types/audio.types.ts +89 -0
- package/src/sdk/types/auth.types.ts +29 -0
- package/src/sdk/types/common.types.ts +26 -0
- package/src/sdk/types/external-integration.types.ts +37 -0
- package/src/sdk/types/index.ts +13 -0
- package/src/sdk/types/log.types.ts +68 -0
- package/src/sdk/types/organization.types.ts +55 -0
- package/src/sdk/types/session.types.ts +63 -0
- package/src/sdk/types/team.types.ts +48 -0
- package/src/sdk/types/template.types.ts +142 -0
- package/src/sdk/types/user.types.ts +50 -0
- package/src/sdk/types/workflow.types.ts +26 -0
- package/src/sdk/types.old.ts +649 -0
- package/src/sdk/types.ts +2 -649
- package/src/sdk/urls.ts +3 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { BaseClient } from './base-client';
|
|
2
|
+
import {
|
|
3
|
+
AudioFile,
|
|
4
|
+
AudioFileStatus,
|
|
5
|
+
UpdateAudioFileDto,
|
|
6
|
+
Base64AudioFile,
|
|
7
|
+
CreateBase64AudioFileDto,
|
|
8
|
+
UpdateBase64AudioFileDto,
|
|
9
|
+
AddBase64ChunkResponse,
|
|
10
|
+
} from '../types';
|
|
11
|
+
import urls from '../urls';
|
|
12
|
+
|
|
13
|
+
export class AudioModule extends BaseClient {
|
|
14
|
+
// ======================
|
|
15
|
+
// AUDIO FILE METHODS
|
|
16
|
+
// ======================
|
|
17
|
+
|
|
18
|
+
public async uploadAudioFileToSession(sessionId: string, file: File | Blob, fileName?: string, culturalTranscription?: string): Promise<AudioFile> {
|
|
19
|
+
const formData = new FormData();
|
|
20
|
+
formData.append('file', file, fileName);
|
|
21
|
+
|
|
22
|
+
if (culturalTranscription) {
|
|
23
|
+
formData.append('cultural_transcription', culturalTranscription);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return this.fileUploadRequest<AudioFile>(`${urls.audioFiles}/upload/${sessionId}`, formData);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public async uploadAudioFileWithTranscriptionQueue(sessionId: string, file: File | Blob, options?: { fileName?: string; culturalTranscription?: string }): Promise<AudioFile> {
|
|
30
|
+
const formData = new FormData();
|
|
31
|
+
formData.append('file', file, options?.fileName);
|
|
32
|
+
|
|
33
|
+
if (options?.culturalTranscription) {
|
|
34
|
+
formData.append('cultural_transcription', options.culturalTranscription);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return this.fileUploadRequest<AudioFile>(`${urls.audioFiles}/upload/${sessionId}`, formData);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public async getMyAudioFiles(): Promise<AudioFile[]> {
|
|
41
|
+
return this.request<AudioFile[]>(`${urls.audioFiles}/my-files`, 'GET');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public async getAllAudioFiles(): Promise<AudioFile[]> {
|
|
45
|
+
return this.request<AudioFile[]>(`${urls.audioFiles}/all`, 'GET');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public async getOrganizationAudioFiles(): Promise<AudioFile[]> {
|
|
49
|
+
return this.request<AudioFile[]>(`${urls.audioFiles}/organization`, 'GET');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
public async getAudioFilesBySession(sessionId: string): Promise<AudioFile[]> {
|
|
53
|
+
return this.request<AudioFile[]>(`${urls.audioFiles}/session/${sessionId}`, 'GET');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
public async getAudioFile(id: string): Promise<AudioFile> {
|
|
57
|
+
return this.request<AudioFile>(`${urls.audioFiles}/${id}`, 'GET');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
public async updateAudioFile(id: string, updates: UpdateAudioFileDto): Promise<AudioFile> {
|
|
61
|
+
return this.request<AudioFile>(`${urls.audioFiles}/${id}`, 'PATCH', updates);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
public async deleteAudioFile(id: string): Promise<void> {
|
|
65
|
+
await this.request(`${urls.audioFiles}/${id}`, 'DELETE');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
public async downloadAudioFile(id: string): Promise<Blob> {
|
|
69
|
+
return this.downloadRequest(`${urls.audioFiles}/${id}/download`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
public async downloadAudioFileAsUrl(id: string): Promise<string> {
|
|
73
|
+
const blob = await this.downloadAudioFile(id);
|
|
74
|
+
return URL.createObjectURL(blob);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// ======================
|
|
78
|
+
// TRANSCRIPTION QUEUE HELPER METHODS
|
|
79
|
+
// ======================
|
|
80
|
+
|
|
81
|
+
public async getTranscribedAudioFiles(): Promise<AudioFile[]> {
|
|
82
|
+
const audioFiles = await this.getMyAudioFiles();
|
|
83
|
+
return audioFiles.filter(file => file.status === AudioFileStatus.TRANSCRIBED && file.transcription);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
public async getProcessingAudioFiles(): Promise<AudioFile[]> {
|
|
87
|
+
const audioFiles = await this.getMyAudioFiles();
|
|
88
|
+
return audioFiles.filter(file => file.status === AudioFileStatus.PROCESSING);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
public async getFailedAudioFiles(): Promise<AudioFile[]> {
|
|
92
|
+
const audioFiles = await this.getMyAudioFiles();
|
|
93
|
+
return audioFiles.filter(file => file.status === AudioFileStatus.FAILED);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// ======================
|
|
97
|
+
// BASE64 AUDIO FILE METHODS
|
|
98
|
+
// ======================
|
|
99
|
+
|
|
100
|
+
public async createBase64AudioFile(dto: CreateBase64AudioFileDto): Promise<Base64AudioFile> {
|
|
101
|
+
return this.request<Base64AudioFile>(`${urls.audioFiles}/base64`, 'POST', dto);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
public async getAllBase64AudioFiles(): Promise<Base64AudioFile[]> {
|
|
105
|
+
return this.request<Base64AudioFile[]>(`${urls.audioFiles}/base64/all`, 'GET');
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
public async getBase64AudioFilesBySession(sessionId: string): Promise<Base64AudioFile[]> {
|
|
109
|
+
return this.request<Base64AudioFile[]>(`${urls.audioFiles}/base64/session/${sessionId}`, 'GET');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
public async getBase64AudioFile(id: string): Promise<Base64AudioFile> {
|
|
113
|
+
return this.request<Base64AudioFile>(`${urls.audioFiles}/base64/${id}`, 'GET');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
public async updateBase64AudioFile(id: string, updates: UpdateBase64AudioFileDto): Promise<Base64AudioFile> {
|
|
117
|
+
return this.request<Base64AudioFile>(`${urls.audioFiles}/base64/${id}`, 'PATCH', updates);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
public async deleteBase64AudioFile(id: string): Promise<void> {
|
|
121
|
+
await this.request(`${urls.audioFiles}/base64/${id}`, 'DELETE');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
public async addBase64Chunk(sessionId: string, base64Chunks: string[]): Promise<AddBase64ChunkResponse> {
|
|
125
|
+
return this.request<AddBase64ChunkResponse>(`${urls.audioFiles}/base64/add-chunk/${sessionId}`, 'POST', { base64Chunks });
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
public async queueSessionBase64AudioForTranscription(sessionId: string): Promise<{ success: boolean }> {
|
|
129
|
+
return this.request<{ success: boolean }>(`${urls.audioFiles}/session/${sessionId}/transcribe`, 'POST');
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { BaseClient } from './base-client';
|
|
2
|
+
import { LoginCredentials, LoginResponse, PasswordChangeResponse, ChangePasswordDto, AdminChangePasswordDto, User } from '../types';
|
|
3
|
+
import urls from '../urls';
|
|
4
|
+
|
|
5
|
+
export class AuthModule extends BaseClient {
|
|
6
|
+
public async login(credentials: LoginCredentials): Promise<LoginResponse> {
|
|
7
|
+
try {
|
|
8
|
+
const response = await this.request<LoginResponse>(
|
|
9
|
+
'/auth/login',
|
|
10
|
+
'POST',
|
|
11
|
+
credentials,
|
|
12
|
+
{},
|
|
13
|
+
true
|
|
14
|
+
);
|
|
15
|
+
this.accessToken = response.access_token;
|
|
16
|
+
this.refreshToken = response.refresh_token;
|
|
17
|
+
this.user = response.user;
|
|
18
|
+
|
|
19
|
+
await this.storage!.setItem('access_token', JSON.stringify(response.access_token));
|
|
20
|
+
await this.storage!.setItem('refresh_token', JSON.stringify(response.refresh_token));
|
|
21
|
+
await this.storage!.setItem('user', JSON.stringify(response.user));
|
|
22
|
+
|
|
23
|
+
return response;
|
|
24
|
+
} catch (error) {
|
|
25
|
+
await this.clearAuth();
|
|
26
|
+
throw error;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public async logout(): Promise<void> {
|
|
31
|
+
await this.clearAuth();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public async getProfile(): Promise<User> {
|
|
35
|
+
return this.request<User>(urls.profile, 'GET');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public async changePassword(currentPassword: string, newPassword: string): Promise<PasswordChangeResponse> {
|
|
39
|
+
const dto: ChangePasswordDto = {
|
|
40
|
+
currentPassword,
|
|
41
|
+
newPassword,
|
|
42
|
+
};
|
|
43
|
+
return this.request<PasswordChangeResponse>(urls.changePassword, 'PATCH', dto);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public async adminChangePassword(userId: string, newPassword: string): Promise<PasswordChangeResponse> {
|
|
47
|
+
const dto: AdminChangePasswordDto = {
|
|
48
|
+
userId,
|
|
49
|
+
newPassword,
|
|
50
|
+
};
|
|
51
|
+
return this.request<PasswordChangeResponse>(urls.adminChangePassword, 'PATCH', dto);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { jwtDecode } from 'jwt-decode';
|
|
2
|
+
import { SDKConfig, User, LoginResponse } from '../types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Base HTTP client for making authenticated requests
|
|
6
|
+
*/
|
|
7
|
+
export class BaseClient {
|
|
8
|
+
protected baseUrl: string;
|
|
9
|
+
protected storage: SDKConfig['storage'];
|
|
10
|
+
protected accessToken: string | null = null;
|
|
11
|
+
protected refreshToken: string | null = null;
|
|
12
|
+
protected user: User | null = null;
|
|
13
|
+
|
|
14
|
+
constructor(config: SDKConfig = {}) {
|
|
15
|
+
this.baseUrl = config.baseUrl || '/api';
|
|
16
|
+
this.storage = config.storage;
|
|
17
|
+
this.initialize();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
protected async initialize() {
|
|
21
|
+
const accessToken = await this.storage!.getItem('access_token');
|
|
22
|
+
const refreshToken = await this.storage!.getItem('refresh_token');
|
|
23
|
+
const userString = await this.storage!.getItem('user');
|
|
24
|
+
this.user = userString ? JSON.parse(userString) : null;
|
|
25
|
+
this.accessToken = accessToken ? JSON.parse(accessToken) : null;
|
|
26
|
+
this.refreshToken = refreshToken ? JSON.parse(refreshToken) : null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public async fetchConfig(url: string): Promise<void> {
|
|
30
|
+
const response = await fetch(url);
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
throw new Error(`Failed to fetch config from ${url}`);
|
|
33
|
+
}
|
|
34
|
+
const conf = await response.json();
|
|
35
|
+
this.baseUrl = conf.baseUrl || this.baseUrl;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
protected async getToken() {
|
|
39
|
+
const accessToken = await this.storage!.getItem('access_token');
|
|
40
|
+
this.accessToken = accessToken ? JSON.parse(accessToken) : null;
|
|
41
|
+
if (!this.accessToken) {
|
|
42
|
+
throw new Error('Access token not found');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (this.isTokenExpired(this.accessToken)) {
|
|
46
|
+
if (this.refreshToken) {
|
|
47
|
+
await this.refreshAccessToken();
|
|
48
|
+
} else {
|
|
49
|
+
throw new Error('Access token expired and no refresh token available');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
protected async request<T>(
|
|
55
|
+
endpoint: string,
|
|
56
|
+
method: string = 'GET',
|
|
57
|
+
body?: any,
|
|
58
|
+
headers: Record<string, string> = {},
|
|
59
|
+
noToken: boolean = false,
|
|
60
|
+
): Promise<T> {
|
|
61
|
+
const url = `${this.baseUrl}${endpoint}`;
|
|
62
|
+
const defaultHeaders: Record<string, string> = {
|
|
63
|
+
'Content-Type': 'application/json',
|
|
64
|
+
'ngrok-skip-browser-warning': 'true'
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
if (noToken) {
|
|
68
|
+
defaultHeaders['Authorization'] = '';
|
|
69
|
+
} else {
|
|
70
|
+
await this.getToken();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (this.accessToken) {
|
|
74
|
+
defaultHeaders['Authorization'] = `Bearer ${this.accessToken}`;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const response = await fetch(url, {
|
|
78
|
+
method,
|
|
79
|
+
headers: { ...defaultHeaders, ...headers },
|
|
80
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
if (!response.ok) {
|
|
84
|
+
const errorData = await response.json().catch(() => ({}));
|
|
85
|
+
throw new Error(
|
|
86
|
+
errorData.message || `Request failed with status ${response.status}`
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return response.json();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
protected async fileUploadRequest<T>(
|
|
94
|
+
endpoint: string,
|
|
95
|
+
body?: FormData,
|
|
96
|
+
headers: Record<string, string> = {}
|
|
97
|
+
): Promise<T> {
|
|
98
|
+
const url = `${this.baseUrl}${endpoint}`;
|
|
99
|
+
const defaultHeaders: Record<string, string> = {
|
|
100
|
+
'ngrok-skip-browser-warning': 'true'
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
if (this.accessToken) {
|
|
104
|
+
defaultHeaders['Authorization'] = `Bearer ${this.accessToken}`;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const response = await fetch(url, {
|
|
108
|
+
method: 'POST',
|
|
109
|
+
headers: { ...defaultHeaders, ...headers },
|
|
110
|
+
body,
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
if (!response.ok) {
|
|
114
|
+
const errorData = await response.json().catch(() => ({}));
|
|
115
|
+
throw new Error(
|
|
116
|
+
errorData.message || `Request failed with status ${response.status}`
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return response.json();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
protected async downloadRequest(endpoint: string): Promise<Blob> {
|
|
124
|
+
const url = `${this.baseUrl}${endpoint}`;
|
|
125
|
+
|
|
126
|
+
await this.getToken();
|
|
127
|
+
|
|
128
|
+
const defaultHeaders: Record<string, string> = {
|
|
129
|
+
'ngrok-skip-browser-warning': 'true'
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
if (this.accessToken) {
|
|
133
|
+
defaultHeaders['Authorization'] = `Bearer ${this.accessToken}`;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const response = await fetch(url, {
|
|
137
|
+
method: 'GET',
|
|
138
|
+
headers: defaultHeaders,
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
if (!response.ok) {
|
|
142
|
+
const errorData = await response.json().catch(() => ({}));
|
|
143
|
+
throw new Error(
|
|
144
|
+
errorData.message || `Download failed with status ${response.status}`
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return response.blob();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
protected async clearAuth(): Promise<void> {
|
|
152
|
+
this.accessToken = null;
|
|
153
|
+
this.refreshToken = null;
|
|
154
|
+
this.user = null;
|
|
155
|
+
await this.storage!.removeItem('access_token');
|
|
156
|
+
await this.storage!.removeItem('refresh_token');
|
|
157
|
+
await this.storage!.removeItem('user');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
protected isTokenExpired(token: string, bufferMinutes: number = 5): boolean {
|
|
161
|
+
try {
|
|
162
|
+
const decoded: any = jwtDecode(token);
|
|
163
|
+
const currentTime = Date.now() / 1000;
|
|
164
|
+
const bufferTime = bufferMinutes * 60;
|
|
165
|
+
|
|
166
|
+
return decoded.exp <= (currentTime + bufferTime);
|
|
167
|
+
} catch (error) {
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
protected async refreshAccessToken(): Promise<void> {
|
|
173
|
+
if (!this.refreshToken) {
|
|
174
|
+
throw new Error('No refresh token available');
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
try {
|
|
178
|
+
const response = await this.request<LoginResponse>(
|
|
179
|
+
'/auth/refresh',
|
|
180
|
+
'POST',
|
|
181
|
+
{ refresh_token: this.refreshToken },
|
|
182
|
+
{},
|
|
183
|
+
true
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
this.accessToken = response.access_token;
|
|
187
|
+
this.refreshToken = response.refresh_token;
|
|
188
|
+
this.user = response.user;
|
|
189
|
+
|
|
190
|
+
await this.storage!.setItem('access_token', JSON.stringify(response.access_token));
|
|
191
|
+
await this.storage!.setItem('refresh_token', JSON.stringify(response.refresh_token));
|
|
192
|
+
await this.storage!.setItem('user', JSON.stringify(response.user));
|
|
193
|
+
} catch (error) {
|
|
194
|
+
await this.clearAuth();
|
|
195
|
+
throw new Error('Failed to refresh access token');
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
public isAuthenticated(): boolean {
|
|
200
|
+
return !!this.accessToken;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
public getCurrentUser(): User | null {
|
|
204
|
+
return this.user;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
public getAccessToken(): string | null {
|
|
208
|
+
return this.accessToken;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
public getRefreshToken(): string | null {
|
|
212
|
+
return this.refreshToken;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { BaseClient } from './base-client';
|
|
2
|
+
import { DebugSessionSummary } from '../types';
|
|
3
|
+
import urls from '../urls';
|
|
4
|
+
|
|
5
|
+
export class DebugModule extends BaseClient {
|
|
6
|
+
/**
|
|
7
|
+
* Get sessions that do not have medical transcriptions and primary transcription summaries
|
|
8
|
+
*/
|
|
9
|
+
public async getSessionsWithoutMedicalTranscriptions(): Promise<DebugSessionSummary[]> {
|
|
10
|
+
return this.request<DebugSessionSummary[]>(`${urls.debug}/sessions/missing-medical-transcriptions`, 'GET');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Download a session as a ZIP file containing all related data (decrypted)
|
|
15
|
+
*/
|
|
16
|
+
public async downloadSessionAsZip(sessionId: string): Promise<Blob> {
|
|
17
|
+
return this.downloadRequest(`${urls.debug}/sessions/${sessionId}/download`);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Download a session as a ZIP file and create a download URL
|
|
22
|
+
*/
|
|
23
|
+
public async downloadSessionAsZipUrl(sessionId: string): Promise<string> {
|
|
24
|
+
const blob = await this.downloadSessionAsZip(sessionId);
|
|
25
|
+
return URL.createObjectURL(blob);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Download a session as a ZIP file and trigger browser download
|
|
30
|
+
*/
|
|
31
|
+
public async downloadSessionAndTriggerDownload(sessionId: string, filename?: string): Promise<void> {
|
|
32
|
+
const blob = await this.downloadSessionAsZip(sessionId);
|
|
33
|
+
const url = URL.createObjectURL(blob);
|
|
34
|
+
|
|
35
|
+
const link = document.createElement('a');
|
|
36
|
+
link.href = url;
|
|
37
|
+
link.download = filename || `session_${sessionId}_${new Date().toISOString().split('T')[0]}.zip`;
|
|
38
|
+
document.body.appendChild(link);
|
|
39
|
+
link.click();
|
|
40
|
+
document.body.removeChild(link);
|
|
41
|
+
|
|
42
|
+
URL.revokeObjectURL(url);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { BaseClient } from './base-client';
|
|
2
|
+
import {
|
|
3
|
+
ExternalIntegration,
|
|
4
|
+
CreateExternalIntegrationDto,
|
|
5
|
+
UpdateExternalIntegrationDto,
|
|
6
|
+
} from '../types';
|
|
7
|
+
import urls from '../urls';
|
|
8
|
+
|
|
9
|
+
export class ExternalIntegrationModule extends BaseClient {
|
|
10
|
+
public async createExternalIntegration(
|
|
11
|
+
data: CreateExternalIntegrationDto,
|
|
12
|
+
): Promise<ExternalIntegration> {
|
|
13
|
+
return this.request<ExternalIntegration>(
|
|
14
|
+
urls.externalIntegrations,
|
|
15
|
+
'POST',
|
|
16
|
+
data,
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public async getExternalIntegrations(): Promise<ExternalIntegration[]> {
|
|
21
|
+
return this.request<ExternalIntegration[]>(
|
|
22
|
+
urls.externalIntegrations,
|
|
23
|
+
'GET',
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public async getExternalIntegration(
|
|
28
|
+
id: string,
|
|
29
|
+
): Promise<ExternalIntegration> {
|
|
30
|
+
return this.request<ExternalIntegration>(
|
|
31
|
+
`${urls.externalIntegrations}/${id}`,
|
|
32
|
+
'GET',
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public async updateExternalIntegration(
|
|
37
|
+
id: string,
|
|
38
|
+
data: UpdateExternalIntegrationDto,
|
|
39
|
+
): Promise<ExternalIntegration> {
|
|
40
|
+
return this.request<ExternalIntegration>(
|
|
41
|
+
`${urls.externalIntegrations}/${id}`,
|
|
42
|
+
'PATCH',
|
|
43
|
+
data,
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public async deleteExternalIntegration(id: string): Promise<void> {
|
|
48
|
+
await this.request(`${urls.externalIntegrations}/${id}`, 'DELETE');
|
|
49
|
+
}
|
|
50
|
+
}
|