whio-api-sdk 1.0.209-beta-staging → 1.0.211-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.
@@ -1,4 +1,5 @@
1
1
  import { SDKConfig, User } from '../types';
2
+ import { BaseClientEvents } from '../types/base-client.types';
2
3
  /**
3
4
  * Base HTTP client for making authenticated requests
4
5
  */
@@ -8,6 +9,7 @@ export declare class BaseClient {
8
9
  protected accessToken: string | null;
9
10
  protected refreshToken: string | null;
10
11
  protected user: User | null;
12
+ private baseEventHandlers;
11
13
  constructor(config?: SDKConfig);
12
14
  protected initialize(): Promise<void>;
13
15
  fetchConfig(url: string): Promise<void>;
@@ -22,4 +24,7 @@ export declare class BaseClient {
22
24
  getCurrentUser(): User | null;
23
25
  getAccessToken(): string | null;
24
26
  getRefreshToken(): string | null;
27
+ onUploadProgress(handler: (uploadPercentage: number) => void): void;
28
+ offUploadProgress(handler: (uploadPercentage: number) => void): void;
29
+ protected emitEvent<K extends keyof BaseClientEvents>(event: K, ...args: Parameters<BaseClientEvents[K]>): void;
25
30
  }
@@ -16,6 +16,7 @@ export class BaseClient {
16
16
  this.accessToken = null;
17
17
  this.refreshToken = null;
18
18
  this.user = null;
19
+ this.baseEventHandlers = new Map();
19
20
  this.baseUrl = config.baseUrl || '/api';
20
21
  this.storage = config.storage;
21
22
  this.initialize();
@@ -94,16 +95,45 @@ export class BaseClient {
94
95
  if (this.accessToken) {
95
96
  defaultHeaders['Authorization'] = `Bearer ${this.accessToken}`;
96
97
  }
97
- const response = yield fetch(url, {
98
- method: 'POST',
99
- headers: Object.assign(Object.assign({}, defaultHeaders), headers),
100
- body,
98
+ return new Promise((resolve, reject) => {
99
+ const xhr = new XMLHttpRequest();
100
+ xhr.upload.addEventListener('progress', (event) => {
101
+ if (event.lengthComputable) {
102
+ const percentage = Math.round((event.loaded / event.total) * 100);
103
+ this.emitEvent('upload-progress', percentage);
104
+ }
105
+ });
106
+ xhr.addEventListener('load', () => {
107
+ if (xhr.status >= 200 && xhr.status < 300) {
108
+ try {
109
+ const result = JSON.parse(xhr.responseText);
110
+ resolve(result);
111
+ }
112
+ catch (error) {
113
+ reject(new Error('Failed to parse response'));
114
+ }
115
+ }
116
+ else {
117
+ let errorMessage = `Request failed with status ${xhr.status}`;
118
+ try {
119
+ const errorData = JSON.parse(xhr.responseText);
120
+ errorMessage = errorData.message || errorMessage;
121
+ }
122
+ catch (error) {
123
+ // Use default error message
124
+ }
125
+ reject(new Error(errorMessage));
126
+ }
127
+ });
128
+ xhr.addEventListener('error', () => {
129
+ reject(new Error('Network error occurred'));
130
+ });
131
+ xhr.open('POST', url);
132
+ Object.entries(Object.assign(Object.assign({}, defaultHeaders), headers)).forEach(([key, value]) => {
133
+ xhr.setRequestHeader(key, value);
134
+ });
135
+ xhr.send(body);
101
136
  });
102
- if (!response.ok) {
103
- const errorData = yield response.json().catch(() => ({}));
104
- throw new Error(errorData.message || `Request failed with status ${response.status}`);
105
- }
106
- return response.json();
107
137
  });
108
138
  }
109
139
  downloadRequest(endpoint) {
@@ -180,4 +210,32 @@ export class BaseClient {
180
210
  getRefreshToken() {
181
211
  return this.refreshToken;
182
212
  }
213
+ onUploadProgress(handler) {
214
+ if (!this.baseEventHandlers.has('upload-progress')) {
215
+ this.baseEventHandlers.set('upload-progress', []);
216
+ }
217
+ this.baseEventHandlers.get('upload-progress').push(handler);
218
+ }
219
+ offUploadProgress(handler) {
220
+ const handlers = this.baseEventHandlers.get('upload-progress');
221
+ if (handlers) {
222
+ const index = handlers.indexOf(handler);
223
+ if (index > -1) {
224
+ handlers.splice(index, 1);
225
+ }
226
+ }
227
+ }
228
+ emitEvent(event, ...args) {
229
+ const handlers = this.baseEventHandlers.get(event);
230
+ if (handlers) {
231
+ handlers.forEach(handler => {
232
+ try {
233
+ handler(...args);
234
+ }
235
+ catch (error) {
236
+ console.error(`Error in BaseClient event handler for ${event}:`, error);
237
+ }
238
+ });
239
+ }
240
+ }
183
241
  }
@@ -197,4 +197,6 @@ export declare class ApiSDK extends BaseClient {
197
197
  getWebSocketStats(): import("./types").WebSocketConnectionStats;
198
198
  subscribe(...args: Parameters<WebSocketModule['on']>): void;
199
199
  unsubscribe(...args: Parameters<WebSocketModule['off']>): void;
200
+ onUploadProgress(handler: (uploadPercentage: number) => void): void;
201
+ offUploadProgress(handler: (uploadPercentage: number) => void): void;
200
202
  }
@@ -806,4 +806,11 @@ export class ApiSDK extends BaseClient {
806
806
  unsubscribe(...args) {
807
807
  return this.websocket.off(...args);
808
808
  }
809
+ // Upload progress methods
810
+ onUploadProgress(handler) {
811
+ return super.onUploadProgress(handler);
812
+ }
813
+ offUploadProgress(handler) {
814
+ return super.offUploadProgress(handler);
815
+ }
809
816
  }
@@ -0,0 +1,3 @@
1
+ export interface BaseClientEvents {
2
+ 'upload-progress': (uploadPercentage: number) => void;
3
+ }
@@ -0,0 +1,2 @@
1
+ // Base client event types
2
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "whio-api-sdk",
3
- "version": "1.0.209-beta-staging",
3
+ "version": "1.0.211-beta-staging",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -1,5 +1,6 @@
1
1
  import { jwtDecode } from 'jwt-decode';
2
2
  import { SDKConfig, User, LoginResponse } from '../types';
3
+ import { BaseClientEvents } from '../types/base-client.types';
3
4
 
4
5
  /**
5
6
  * Base HTTP client for making authenticated requests
@@ -10,6 +11,7 @@ export class BaseClient {
10
11
  protected accessToken: string | null = null;
11
12
  protected refreshToken: string | null = null;
12
13
  protected user: User | null = null;
14
+ private baseEventHandlers: Map<keyof BaseClientEvents, Function[]> = new Map();
13
15
 
14
16
  constructor(config: SDKConfig = {}) {
15
17
  this.baseUrl = config.baseUrl || '/api';
@@ -104,20 +106,48 @@ export class BaseClient {
104
106
  defaultHeaders['Authorization'] = `Bearer ${this.accessToken}`;
105
107
  }
106
108
 
107
- const response = await fetch(url, {
108
- method: 'POST',
109
- headers: { ...defaultHeaders, ...headers },
110
- body,
109
+ return new Promise((resolve, reject) => {
110
+ const xhr = new XMLHttpRequest();
111
+
112
+ xhr.upload.addEventListener('progress', (event) => {
113
+ if (event.lengthComputable) {
114
+ const percentage = Math.round((event.loaded / event.total) * 100);
115
+ this.emitEvent('upload-progress', percentage);
116
+ }
117
+ });
118
+
119
+ xhr.addEventListener('load', () => {
120
+ if (xhr.status >= 200 && xhr.status < 300) {
121
+ try {
122
+ const result = JSON.parse(xhr.responseText);
123
+ resolve(result);
124
+ } catch (error) {
125
+ reject(new Error('Failed to parse response'));
126
+ }
127
+ } else {
128
+ let errorMessage = `Request failed with status ${xhr.status}`;
129
+ try {
130
+ const errorData = JSON.parse(xhr.responseText);
131
+ errorMessage = errorData.message || errorMessage;
132
+ } catch (error) {
133
+ // Use default error message
134
+ }
135
+ reject(new Error(errorMessage));
136
+ }
137
+ });
138
+
139
+ xhr.addEventListener('error', () => {
140
+ reject(new Error('Network error occurred'));
141
+ });
142
+
143
+ xhr.open('POST', url);
144
+
145
+ Object.entries({ ...defaultHeaders, ...headers }).forEach(([key, value]) => {
146
+ xhr.setRequestHeader(key, value);
147
+ });
148
+
149
+ xhr.send(body);
111
150
  });
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
151
  }
122
152
 
123
153
  protected async downloadRequest(endpoint: string): Promise<Blob> {
@@ -211,4 +241,37 @@ export class BaseClient {
211
241
  public getRefreshToken(): string | null {
212
242
  return this.refreshToken;
213
243
  }
244
+
245
+ public onUploadProgress(handler: (uploadPercentage: number) => void): void {
246
+ if (!this.baseEventHandlers.has('upload-progress')) {
247
+ this.baseEventHandlers.set('upload-progress', []);
248
+ }
249
+ this.baseEventHandlers.get('upload-progress')!.push(handler);
250
+ }
251
+
252
+ public offUploadProgress(handler: (uploadPercentage: number) => void): void {
253
+ const handlers = this.baseEventHandlers.get('upload-progress');
254
+ if (handlers) {
255
+ const index = handlers.indexOf(handler);
256
+ if (index > -1) {
257
+ handlers.splice(index, 1);
258
+ }
259
+ }
260
+ }
261
+
262
+ protected emitEvent<K extends keyof BaseClientEvents>(
263
+ event: K,
264
+ ...args: Parameters<BaseClientEvents[K]>
265
+ ): void {
266
+ const handlers = this.baseEventHandlers.get(event);
267
+ if (handlers) {
268
+ handlers.forEach(handler => {
269
+ try {
270
+ (handler as Function)(...args);
271
+ } catch (error) {
272
+ console.error(`Error in BaseClient event handler for ${event}:`, error);
273
+ }
274
+ });
275
+ }
276
+ }
214
277
  }
package/src/sdk/sdk.ts CHANGED
@@ -684,4 +684,13 @@ export class ApiSDK extends BaseClient {
684
684
  public unsubscribe(...args: Parameters<WebSocketModule['off']>) {
685
685
  return this.websocket.off(...args);
686
686
  }
687
+
688
+ // Upload progress methods
689
+ public onUploadProgress(handler: (uploadPercentage: number) => void): void {
690
+ return super.onUploadProgress(handler);
691
+ }
692
+
693
+ public offUploadProgress(handler: (uploadPercentage: number) => void): void {
694
+ return super.offUploadProgress(handler);
695
+ }
687
696
  }
@@ -0,0 +1,5 @@
1
+ // Base client event types
2
+
3
+ export interface BaseClientEvents {
4
+ 'upload-progress': (uploadPercentage: number) => void;
5
+ }