@go-avro/avro-js 0.0.2-beta.80 → 0.0.2-beta.81

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.
@@ -17,6 +17,7 @@ declare module '../client/QueryClient' {
17
17
  _xhr<T>(method: string, path: string, body: any, cancelToken?: CancelToken, headers?: Record<string, string>, isIdempotent?: boolean, retryCount?: number, progressUpdateCallback?: (loaded: number, total: number) => void): Promise<T>;
18
18
  _fetch<T>(method: string, path: string, body: any, cancelToken?: CancelToken, headers?: Record<string, string>, isIdempotent?: boolean, retryCount?: number): Promise<T>;
19
19
  getDelay(strategy: RetryStrategy, attempt: number): number;
20
+ sleep(ms: number): Promise<void>;
20
21
  useGetRoot(): UseQueryResult<ApiInfo, StandardError>;
21
22
  useGetJobs(companyGuid: string, body: {
22
23
  amt?: number;
@@ -104,7 +104,7 @@ export class AvroQueryClient {
104
104
  const queryClient = useQueryClient();
105
105
  return useMutation({
106
106
  mutationFn: async ({ token, cancelToken }) => {
107
- const resp = await this._fetch('POST', `/google/authorize?token=${token}`, {}, cancelToken, { 'Content-Type': 'application/json' });
107
+ const resp = await this._xhr('POST', `/google/authorize?token=${token}`, {}, cancelToken, { 'Content-Type': 'application/json' });
108
108
  if (!resp || !('access_token' in resp)) {
109
109
  if (resp.msg === "TOTP email sent") {
110
110
  return LoginResponse.NEEDS_TOTP;
@@ -123,7 +123,7 @@ export class AvroQueryClient {
123
123
  },
124
124
  onError: (err) => {
125
125
  this.config.authManager.clearTokens();
126
- throw new StandardError(401, err.message || 'Google Login failed');
126
+ throw new StandardError(err.status, err.message || 'Google Login failed');
127
127
  }
128
128
  });
129
129
  }
@@ -1,67 +1,63 @@
1
1
  import { AvroQueryClient } from '../../client/QueryClient';
2
2
  import { StandardError } from '../../types/error';
3
- AvroQueryClient.prototype._fetch = function (method, path, body, cancelToken, headers = {}, isIdempotent = false, retryCount = 0) {
3
+ AvroQueryClient.prototype._fetch = async function (method, path, body, cancelToken, headers = {}, isIdempotent = false, retryCount = 0) {
4
4
  const checkCancelled = () => {
5
5
  try {
6
6
  if (cancelToken?.isCancelled()) {
7
- return new StandardError(0, 'Request cancelled');
7
+ throw new StandardError(0, 'Request cancelled');
8
8
  }
9
9
  }
10
10
  catch (error) {
11
- throw new StandardError(0, `Error checking cancellation (${typeof cancelToken}): ${error}`);
11
+ throw new StandardError(0, `Error checking cancellation: ${error.message}`);
12
12
  }
13
- return null;
14
13
  };
15
- return this.config.authManager.accessToken().then(token => {
16
- const cancelErr = checkCancelled();
17
- if (cancelErr)
18
- return Promise.reject(cancelErr);
14
+ try {
15
+ checkCancelled();
16
+ const token = await this.config.authManager.accessToken();
17
+ checkCancelled();
19
18
  const url = this.config.baseUrl + path;
20
19
  const requestHeaders = {
21
20
  'Content-Type': 'application/json',
21
+ Authorization: `Bearer ${token}`,
22
22
  ...headers,
23
23
  };
24
- if (token) {
25
- requestHeaders['Authorization'] = `Bearer ${token}`;
26
- }
27
24
  const options = {
28
25
  method,
29
26
  headers: requestHeaders,
30
- body: body ? JSON.stringify(body) : null,
27
+ body: body ? JSON.stringify(body) : undefined,
31
28
  };
32
- return fetch(url, options).then(response => {
33
- if (response.status === 401 && this.config.authManager.refreshTokens && retryCount === 0) {
34
- return this.config.authManager
35
- .refreshTokens()
36
- .then(() => this._fetch(method, path, body, cancelToken, headers, isIdempotent, retryCount + 1))
37
- .catch(() => Promise.reject(new StandardError(401, 'Unauthorized (refresh failed)')));
38
- }
39
- if (!response.ok) {
40
- if (retryCount < this.config.maxRetries) {
41
- const delay = this.getDelay(this.config.retryStrategy, retryCount);
42
- return new Promise((resolve, reject) => {
43
- setTimeout(() => {
44
- this._fetch(method, path, body, cancelToken, headers, isIdempotent, retryCount + 1)
45
- .then(resolve)
46
- .catch(reject);
47
- }, delay);
48
- });
49
- }
50
- else {
51
- return response.text().then(text => {
52
- let msg = response.statusText;
53
- try {
54
- const parsed = JSON.parse(text);
55
- msg = parsed.message || msg;
56
- }
57
- catch {
58
- console.warn('Failed to parse error response:', text);
59
- }
60
- throw new StandardError(response.status, msg);
61
- });
62
- }
29
+ const response = await fetch(url, options);
30
+ if (response.ok) {
31
+ const text = await response.text();
32
+ if (!text) {
33
+ return undefined;
63
34
  }
64
- return response.json();
65
- });
66
- });
35
+ return JSON.parse(text);
36
+ }
37
+ if (response.status === 401 && this.config.authManager.refreshTokens && retryCount === 0) {
38
+ await this.config.authManager.refreshTokens();
39
+ return this._fetch(method, path, body, cancelToken, headers, isIdempotent, 1);
40
+ }
41
+ if (retryCount < this.config.maxRetries) {
42
+ const delay = this.getDelay(this.config.retryStrategy, retryCount);
43
+ await this.sleep(delay);
44
+ return this._fetch(method, path, body, cancelToken, headers, isIdempotent, retryCount + 1);
45
+ }
46
+ let errorMessage = response.statusText;
47
+ try {
48
+ const parsedError = await response.json();
49
+ errorMessage = parsedError.message ?? parsedError.msg ?? errorMessage;
50
+ }
51
+ catch (e) {
52
+ console.error('Ignoring:', e);
53
+ }
54
+ throw new StandardError(response.status, errorMessage);
55
+ }
56
+ catch (error) {
57
+ if (error instanceof StandardError) {
58
+ throw error;
59
+ }
60
+ const message = error instanceof Error ? error.message : String(error);
61
+ throw new StandardError(0, `Request failed: ${message}`);
62
+ }
67
63
  };
@@ -11,3 +11,4 @@ AvroQueryClient.prototype.getDelay = function (strategy, attempt) {
11
11
  }
12
12
  throw new Error(`Invalid retry strategy: ${strategy}`);
13
13
  };
14
+ AvroQueryClient.prototype.sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
@@ -1,87 +1,84 @@
1
1
  import { AvroQueryClient } from '../../client/QueryClient';
2
2
  import { StandardError } from '../../types/error';
3
- AvroQueryClient.prototype._xhr = function (method, path, body, cancelToken, headers = {}, isIdempotent = false, retryCount = 0, progressUpdateCallback) {
3
+ AvroQueryClient.prototype._xhr = async function (method, path, body, cancelToken, headers = {}, isIdempotent = false, retryCount = 0, progressUpdateCallback) {
4
4
  const checkCancelled = () => {
5
5
  if (cancelToken?.isCancelled()) {
6
- return new StandardError(0, 'Request cancelled');
6
+ throw new StandardError(0, 'Request cancelled');
7
7
  }
8
- return null;
9
8
  };
10
- return new Promise((resolve, reject) => {
11
- this.config.authManager.accessToken().then(token => {
12
- const cancelErr = checkCancelled();
13
- if (cancelErr)
14
- return reject(cancelErr);
15
- const xhr = new XMLHttpRequest();
16
- const url = this.config.baseUrl + path;
17
- xhr.open(method, url, true);
18
- if (token)
19
- xhr.setRequestHeader('Authorization', `Bearer ${token}`);
20
- Object.entries(headers).forEach(([key, value]) => xhr.setRequestHeader(key, value));
21
- xhr.onload = () => {
22
- const cancelErr = checkCancelled();
23
- if (cancelErr)
24
- return reject(cancelErr);
25
- if (xhr.status === 401 && this.config.authManager.refreshTokens && retryCount === 0) {
26
- this.config.authManager
27
- .refreshTokens()
28
- .then(() => {
29
- this._xhr(method, path, body, cancelToken, headers, isIdempotent, retryCount + 1).then(resolve, reject);
30
- })
31
- .catch(() => reject(new StandardError(401, 'Unauthorized (refresh failed)')));
32
- return;
33
- }
34
- if (xhr.status >= 200 && xhr.status < 300) {
35
- try {
36
- resolve(JSON.parse(xhr.responseText));
37
- }
38
- catch {
39
- resolve(xhr.responseText);
40
- }
41
- }
42
- else {
43
- if (retryCount < this.config.maxRetries) {
44
- const delay = this.getDelay(this.config.retryStrategy, retryCount);
45
- setTimeout(() => {
46
- this._xhr(method, path, body, cancelToken, headers, isIdempotent, retryCount + 1).then(resolve, reject);
47
- }, delay);
9
+ for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {
10
+ try {
11
+ checkCancelled();
12
+ const token = await this.config.authManager.accessToken();
13
+ checkCancelled();
14
+ const result = await new Promise((resolve, reject) => {
15
+ const xhr = new XMLHttpRequest();
16
+ const url = this.config.baseUrl + path;
17
+ xhr.open(method, url, true);
18
+ if (token)
19
+ xhr.setRequestHeader('Authorization', `Bearer ${token}`);
20
+ Object.entries(headers).forEach(([key, value]) => xhr.setRequestHeader(key, value));
21
+ xhr.onload = () => {
22
+ if (xhr.status >= 200 && xhr.status < 300) {
23
+ try {
24
+ const responseText = xhr.responseText;
25
+ if (!responseText) {
26
+ return resolve(undefined);
27
+ }
28
+ resolve(JSON.parse(responseText));
29
+ }
30
+ catch (e) {
31
+ reject(new StandardError(0, `Failed to parse successful response: ${e.message}`));
32
+ }
48
33
  }
49
34
  else {
50
- let msg = xhr.statusText;
35
+ let msg = xhr.responseText || xhr.statusText;
51
36
  try {
52
37
  const parsed = JSON.parse(xhr.responseText);
53
- msg = parsed.msg || msg;
38
+ msg = parsed.message ?? parsed.msg ?? msg;
54
39
  }
55
- catch {
56
- console.warn('Failed to parse error response:', xhr.responseText);
40
+ catch (e) {
41
+ console.error('Ignoring:', e);
57
42
  }
58
43
  reject(new StandardError(xhr.status, msg));
59
44
  }
60
- }
61
- };
62
- if (progressUpdateCallback && xhr.upload) {
63
- xhr.upload.onprogress = (event) => {
64
- if (event.lengthComputable) {
65
- progressUpdateCallback(event.loaded, event.total);
66
- }
67
45
  };
46
+ xhr.onerror = () => reject(new StandardError(0, 'Network Error'));
47
+ if (this.config.timeout) {
48
+ xhr.timeout = this.config.timeout;
49
+ xhr.ontimeout = () => reject(new StandardError(0, 'Request timed out'));
50
+ }
51
+ if (progressUpdateCallback && xhr.upload) {
52
+ xhr.upload.onprogress = (event) => {
53
+ if (event.lengthComputable) {
54
+ progressUpdateCallback(event.loaded, event.total);
55
+ }
56
+ };
57
+ }
58
+ xhr.send(body);
59
+ });
60
+ return result;
61
+ }
62
+ catch (error) {
63
+ if (!(error instanceof StandardError)) {
64
+ const message = error instanceof Error ? error.message : String(error);
65
+ throw new StandardError(0, `An unexpected error occurred: ${message}`);
68
66
  }
69
- xhr.onerror = () => {
70
- if (retryCount < this.config.maxRetries) {
71
- const delay = this.getDelay(this.config.retryStrategy, retryCount);
72
- setTimeout(() => {
73
- this._xhr(method, path, body, cancelToken, headers, isIdempotent, retryCount + 1).then(resolve, reject);
74
- }, delay);
67
+ if (error.status === 401 && this.config.authManager.refreshTokens && attempt === 0) {
68
+ try {
69
+ await this.config.authManager.refreshTokens();
70
+ continue;
75
71
  }
76
- else {
77
- reject(new StandardError(0, 'Network Error'));
72
+ catch (refreshError) {
73
+ throw new StandardError(401, 'Unauthorized (refresh failed)');
78
74
  }
79
- };
80
- if (this.config.timeout) {
81
- xhr.timeout = this.config.timeout;
82
- xhr.ontimeout = () => reject(new StandardError(0, 'Request timed out'));
83
75
  }
84
- xhr.send(body);
85
- });
86
- });
76
+ if (attempt >= this.config.maxRetries) {
77
+ throw error;
78
+ }
79
+ const delay = this.getDelay(this.config.retryStrategy, attempt);
80
+ await this.sleep(delay);
81
+ }
82
+ }
83
+ throw new StandardError(0, 'Request failed after maximum retries.');
87
84
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@go-avro/avro-js",
3
- "version": "0.0.2-beta.80",
3
+ "version": "0.0.2-beta.81",
4
4
  "description": "JS client for Avro backend integration.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",