@go-avro/avro-js 0.0.2-beta.5 → 0.0.2-beta.50

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/README.md CHANGED
@@ -10,6 +10,7 @@ This SDK provides:
10
10
  - Typed API interfaces for Avro entities (users, jobs, teams, etc.)
11
11
  - Pluggable token storage (in-memory, localStorage, SecureStore, etc.)
12
12
  - XHR-based requests for compatibility with React Native WebViews and older environments
13
+ - Mutation and Data Hooks for easy plug-in use in React and React Native projects.
13
14
 
14
15
  ## Installation
15
16
 
@@ -26,7 +26,23 @@ export class AuthManager {
26
26
  'Authorization': `Bearer ${tokens.access_token}`,
27
27
  },
28
28
  });
29
- return response.ok;
29
+ if (response.ok) {
30
+ return true;
31
+ }
32
+ else {
33
+ // Attempt token refresh if validation fails
34
+ const newTokens = await this.refreshTokens();
35
+ if (newTokens && newTokens.access_token) {
36
+ const retryResponse = await fetch(`${this.baseUrl}/validate`, {
37
+ method: 'POST',
38
+ headers: {
39
+ 'Content-Type': 'application/json',
40
+ 'Authorization': `Bearer ${newTokens.access_token}`,
41
+ },
42
+ });
43
+ return retryResponse.ok;
44
+ }
45
+ }
30
46
  }
31
47
  catch (error) {
32
48
  console.error('Error validating access token:', error);
@@ -1,5 +1,8 @@
1
+ import { InfiniteData, UseInfiniteQueryResult, useMutation, UseQueryResult } from '@tanstack/react-query';
1
2
  import { AuthManager } from '../auth/AuthManager';
3
+ import { _Event, ApiInfo, Bill, Company, Job, LineItem, Route, ServiceMonth, Session, User } from '../types/api';
2
4
  import { CancelToken, RetryStrategy } from '../types/client';
5
+ import { StandardError } from '../types/error';
3
6
  export interface AvroQueryClientConfig {
4
7
  baseUrl: string;
5
8
  authManager: AuthManager;
@@ -7,12 +10,169 @@ export interface AvroQueryClientConfig {
7
10
  retryStrategy?: RetryStrategy;
8
11
  timeout?: number;
9
12
  }
13
+ declare module '../client/QueryClient' {
14
+ interface AvroQueryClient {
15
+ _xhr<T>(method: string, path: string, body: any, cancelToken?: CancelToken, headers?: Record<string, string>, isIdempotent?: boolean, retryCount?: number): Promise<T>;
16
+ _fetch<T>(method: string, path: string, body: any, cancelToken?: CancelToken, headers?: Record<string, string>, isIdempotent?: boolean, retryCount?: number): Promise<T>;
17
+ getDelay(strategy: RetryStrategy, attempt: number): number;
18
+ useGetRoot(): UseQueryResult<ApiInfo, StandardError>;
19
+ useGetJobs(companyGuid: string, body: {
20
+ amt?: number;
21
+ query?: string;
22
+ }, total: number, onProgress?: (fraction: number) => void, isMainLoad?: boolean): UseQueryResult<Job[], StandardError>;
23
+ useGetRoutes(companyGuid: string, body: {
24
+ amt?: number;
25
+ query?: string;
26
+ }, total: number, onProgress?: (fraction: number) => void): UseQueryResult<any[], StandardError>;
27
+ useGetEvents(companyGuid: string, body: {
28
+ amt?: number;
29
+ known_ids?: string[];
30
+ unknown_ids?: string[];
31
+ query?: string;
32
+ unbilled?: boolean;
33
+ billed?: boolean;
34
+ paid?: boolean;
35
+ jobId?: string;
36
+ }): UseInfiniteQueryResult<InfiniteData<_Event[], unknown>, StandardError>;
37
+ useGetMonths(companyGuid: string, body: {
38
+ amt?: number;
39
+ known_ids?: string[];
40
+ unknown_ids?: string[];
41
+ query?: string;
42
+ unbilled?: boolean;
43
+ billed?: boolean;
44
+ paid?: boolean;
45
+ jobId?: string;
46
+ }): UseInfiniteQueryResult<InfiniteData<ServiceMonth[], unknown>, StandardError>;
47
+ useGetBills(companyGuid: string, body: {
48
+ amt?: number;
49
+ known_ids?: string[];
50
+ unknown_ids?: string[];
51
+ query?: string;
52
+ paid?: boolean;
53
+ }): UseInfiniteQueryResult<InfiniteData<Bill[], unknown>, StandardError>;
54
+ useGetCompanies(options?: {}): UseQueryResult<{
55
+ name: string;
56
+ id: string;
57
+ }[], StandardError>;
58
+ useGetCompany(companyId: string): UseQueryResult<Company, StandardError>;
59
+ useGetJob(jobId: string): UseQueryResult<Job, StandardError>;
60
+ useGetEvent(eventId: string): UseQueryResult<_Event, StandardError>;
61
+ useGetUser(userId: string): UseQueryResult<User, StandardError>;
62
+ useGetSelf(): UseQueryResult<User, StandardError>;
63
+ useGetBill(billId: string): UseQueryResult<Bill, StandardError>;
64
+ useGetRoute(routeId: string): UseQueryResult<Route, StandardError>;
65
+ useGetUserSessions(): UseQueryResult<Session[], StandardError>;
66
+ useCreateEvent(): ReturnType<typeof useMutation<{
67
+ id: string;
68
+ }, StandardError, {
69
+ companyId: string;
70
+ eventData: Partial<_Event>;
71
+ }>>;
72
+ useCreateUserSession(): ReturnType<typeof useMutation<{
73
+ id: string;
74
+ }, StandardError, {
75
+ companyId: string;
76
+ sessionData: Partial<Session>;
77
+ }>>;
78
+ useCreateBill(): ReturnType<typeof useMutation<{
79
+ id: string;
80
+ invoice_id: number;
81
+ }, StandardError, {
82
+ companyId: string;
83
+ data: {
84
+ line_items: LineItem[];
85
+ due_date: number;
86
+ users: string[];
87
+ custom_emails: [string, string][];
88
+ };
89
+ }>>;
90
+ useCreateJob(): ReturnType<typeof useMutation<{
91
+ id: string;
92
+ }, StandardError, {
93
+ companyId: string;
94
+ jobData: Partial<Job>;
95
+ }>>;
96
+ useUpdateEvent(): ReturnType<typeof useMutation<{
97
+ msg: string;
98
+ }, StandardError, {
99
+ eventId: string;
100
+ updates: Partial<_Event>;
101
+ }>>;
102
+ useUpdateUserSession(): ReturnType<typeof useMutation<{
103
+ msg: string;
104
+ }, StandardError, {
105
+ sessionId: string;
106
+ updates: Partial<Session>;
107
+ }>>;
108
+ useUpdateJob(): ReturnType<typeof useMutation<{
109
+ msg: string;
110
+ }, StandardError, {
111
+ jobId: string;
112
+ updates: Partial<Job>;
113
+ }>>;
114
+ useUpdateBill(): ReturnType<typeof useMutation<{
115
+ msg: string;
116
+ }, StandardError, {
117
+ billId: string;
118
+ updates: Partial<Bill>;
119
+ }>>;
120
+ useUpdateRoute(): ReturnType<typeof useMutation<{
121
+ msg: string;
122
+ }, StandardError, {
123
+ routeId: string;
124
+ updates: Partial<Route>;
125
+ }>>;
126
+ useUpdateEvents(): ReturnType<typeof useMutation<void, StandardError, {
127
+ companyId: string;
128
+ events: (_Event & {
129
+ page?: number;
130
+ })[];
131
+ action: "billed" | "paid";
132
+ }>>;
133
+ useUpdateMonths(): ReturnType<typeof useMutation<void, StandardError, {
134
+ companyId: string;
135
+ months: (ServiceMonth & {
136
+ page?: number;
137
+ })[];
138
+ action: "billed" | "paid";
139
+ }>>;
140
+ useDeleteJob(): ReturnType<typeof useMutation<{
141
+ msg: string;
142
+ }, StandardError, {
143
+ jobId: string;
144
+ }>>;
145
+ useUpdateCompany(): ReturnType<typeof useMutation<{
146
+ msg: string;
147
+ }, StandardError, {
148
+ companyId: string;
149
+ companyData: Partial<Company | {
150
+ logo: File | null;
151
+ }>;
152
+ }>>;
153
+ useDeleteEvent(): ReturnType<typeof useMutation<{
154
+ msg: string;
155
+ }, StandardError, {
156
+ eventId: string;
157
+ }>>;
158
+ useDeleteBill(): ReturnType<typeof useMutation<{
159
+ msg: string;
160
+ }, StandardError, {
161
+ billId: string;
162
+ }>>;
163
+ useDeleteRoute(): ReturnType<typeof useMutation<{
164
+ msg: string;
165
+ }, StandardError, {
166
+ routeId: string;
167
+ }>>;
168
+ useDeleteSelf(): ReturnType<typeof useMutation<{
169
+ msg: string;
170
+ }, StandardError, void>>;
171
+ }
172
+ }
10
173
  export declare class AvroQueryClient {
11
- private config;
174
+ protected config: Required<AvroQueryClientConfig>;
12
175
  constructor(config: AvroQueryClientConfig);
13
- getDelay(strategy: RetryStrategy, attempt: number): number;
14
- private _xhr;
15
- private _fetch;
16
176
  get<T>(path: string, cancelToken?: CancelToken, headers?: Record<string, string>): Promise<T>;
17
177
  post<T>(path: string, data: any, cancelToken?: CancelToken, headers?: Record<string, string>): Promise<T>;
18
178
  put<T>(path: string, data: any, cancelToken?: CancelToken, headers?: Record<string, string>): Promise<T>;
@@ -22,5 +182,55 @@ export declare class AvroQueryClient {
22
182
  password: string;
23
183
  }, cancelToken?: CancelToken): Promise<Boolean>;
24
184
  logout(cancelToken?: CancelToken): Promise<void>;
25
- fetchJobs(companyGuid: string, amt?: number, knownIds?: string[], unknownIds?: string[], keyword?: string, offset?: number, cancelToken?: CancelToken, headers?: Record<string, string>): Promise<any>;
185
+ fetchJobs(companyGuid: string, body?: {
186
+ amt?: number;
187
+ known_ids?: string[];
188
+ unknown_ids?: string[];
189
+ query?: string;
190
+ offset?: number;
191
+ }, cancelToken?: CancelToken, headers?: Record<string, string>): Promise<any>;
192
+ fetchEvents(companyGuid: string, body?: {
193
+ amt?: number;
194
+ known_ids?: string[];
195
+ unknown_ids?: string[];
196
+ query?: string;
197
+ offset?: number;
198
+ unbilled?: boolean;
199
+ billed?: boolean;
200
+ paid?: boolean;
201
+ jobId?: string | null;
202
+ }, cancelToken?: CancelToken, headers?: Record<string, string>): Promise<any>;
203
+ fetchMonths(companyGuid: string, body?: {
204
+ amt?: number;
205
+ known_ids?: string[];
206
+ unknown_ids?: string[];
207
+ query?: string;
208
+ offset?: number;
209
+ unbilled?: boolean;
210
+ billed?: boolean;
211
+ paid?: boolean;
212
+ jobId?: string | null;
213
+ }, cancelToken?: CancelToken, headers?: Record<string, string>): Promise<any>;
214
+ fetchBills(companyGuid: string, body?: {
215
+ amt?: number;
216
+ known_ids?: string[];
217
+ unknown_ids?: string[];
218
+ query?: string;
219
+ offset?: number;
220
+ paid?: boolean;
221
+ }, cancelToken?: CancelToken, headers?: Record<string, string>): Promise<any>;
222
+ fetchRoutes(companyGuid: string, body?: {
223
+ amt?: number;
224
+ known_ids?: string[];
225
+ unknown_ids?: string[];
226
+ query?: string;
227
+ offset?: number;
228
+ }, cancelToken?: CancelToken, headers?: Record<string, string>): Promise<any>;
229
+ sendEmail(emailId: string, formData: FormData): Promise<void>;
230
+ createBill(companyGuid: string, data: {
231
+ line_items: LineItem[];
232
+ due_date: number;
233
+ users: string[];
234
+ custom_emails: [string, string][];
235
+ }, cancelToken?: CancelToken): Promise<any>;
26
236
  }
@@ -9,161 +9,6 @@ export class AvroQueryClient {
9
9
  timeout: config.timeout ?? 0,
10
10
  };
11
11
  }
12
- getDelay(strategy, attempt) {
13
- if (typeof strategy === 'function') {
14
- return strategy(attempt);
15
- }
16
- else if (strategy === 'fixed') {
17
- return 1000;
18
- }
19
- else if (strategy === 'exponential') {
20
- return Math.pow(2, attempt) * 100;
21
- }
22
- throw new Error(`Invalid retry strategy: ${strategy}`);
23
- }
24
- _xhr(method, path, body, cancelToken, headers = {}, isIdempotent = false, retryCount = 0) {
25
- const checkCancelled = () => {
26
- if (cancelToken?.isCancelled()) {
27
- return new StandardError(0, 'Request cancelled');
28
- }
29
- return null;
30
- };
31
- return this.config.authManager.accessToken().then(token => {
32
- return new Promise((resolve, reject) => {
33
- const cancelErr = checkCancelled();
34
- if (cancelErr)
35
- return reject(cancelErr);
36
- const xhr = new XMLHttpRequest();
37
- const url = this.config.baseUrl + path;
38
- xhr.open(method, url, true);
39
- if (token) {
40
- xhr.setRequestHeader('Authorization', `Bearer ${token}`);
41
- }
42
- Object.entries(headers).forEach(([key, value]) => {
43
- xhr.setRequestHeader(key, value);
44
- });
45
- xhr.onload = () => {
46
- const cancelErr = checkCancelled();
47
- if (cancelErr)
48
- return reject(cancelErr);
49
- if (xhr.status === 401 && this.config.authManager.refreshTokens && retryCount === 0) {
50
- this.config.authManager
51
- .refreshTokens()
52
- .then(() => {
53
- this._xhr(method, path, body, cancelToken, headers, isIdempotent, retryCount + 1).then(resolve, reject);
54
- })
55
- .catch(() => {
56
- reject(new StandardError(401, 'Unauthorized (refresh failed)'));
57
- });
58
- return;
59
- }
60
- if (xhr.status >= 200 && xhr.status < 300) {
61
- try {
62
- resolve(JSON.parse(xhr.responseText));
63
- }
64
- catch {
65
- resolve(xhr.responseText);
66
- }
67
- }
68
- else {
69
- if (retryCount < this.config.maxRetries) {
70
- const delay = this.getDelay(this.config.retryStrategy, retryCount);
71
- setTimeout(() => {
72
- this._xhr(method, path, body, cancelToken, headers, isIdempotent, retryCount + 1).then(resolve, reject);
73
- }, delay);
74
- }
75
- else {
76
- let msg = xhr.statusText;
77
- try {
78
- const parsed = JSON.parse(xhr.responseText);
79
- msg = parsed.message || msg;
80
- }
81
- catch {
82
- console.warn('Failed to parse error response:', xhr.responseText);
83
- }
84
- reject(new StandardError(xhr.status, msg));
85
- }
86
- }
87
- };
88
- xhr.onerror = () => {
89
- if (retryCount < this.config.maxRetries) {
90
- const delay = this.getDelay(this.config.retryStrategy, retryCount);
91
- setTimeout(() => {
92
- this._xhr(method, path, body, cancelToken, headers, isIdempotent, retryCount + 1).then(resolve, reject);
93
- }, delay);
94
- }
95
- else {
96
- reject(new StandardError(0, 'Network Error'));
97
- }
98
- };
99
- if (this.config.timeout) {
100
- xhr.timeout = this.config.timeout;
101
- xhr.ontimeout = () => reject(new StandardError(0, 'Request timed out'));
102
- }
103
- xhr.send(body);
104
- });
105
- });
106
- }
107
- _fetch(method, path, body, cancelToken, headers = {}, isIdempotent = false, retryCount = 0) {
108
- const checkCancelled = () => {
109
- if (cancelToken?.isCancelled()) {
110
- return new StandardError(0, 'Request cancelled');
111
- }
112
- return null;
113
- };
114
- return this.config.authManager.accessToken().then(token => {
115
- const cancelErr = checkCancelled();
116
- if (cancelErr)
117
- return Promise.reject(cancelErr);
118
- const url = this.config.baseUrl + path;
119
- const requestHeaders = {
120
- 'Content-Type': 'application/json',
121
- ...headers,
122
- };
123
- if (token) {
124
- requestHeaders['Authorization'] = `Bearer ${token}`;
125
- }
126
- const options = {
127
- method,
128
- headers: requestHeaders,
129
- body: body ? JSON.stringify(body) : null,
130
- };
131
- return fetch(url, options).then(response => {
132
- if (response.status === 401 && this.config.authManager.refreshTokens && retryCount === 0) {
133
- return this.config.authManager
134
- .refreshTokens()
135
- .then(() => this._fetch(method, path, body, cancelToken, headers, isIdempotent, retryCount + 1))
136
- .catch(() => Promise.reject(new StandardError(401, 'Unauthorized (refresh failed)')));
137
- }
138
- if (!response.ok) {
139
- if (retryCount < this.config.maxRetries) {
140
- const delay = this.getDelay(this.config.retryStrategy, retryCount);
141
- return new Promise((resolve, reject) => {
142
- setTimeout(() => {
143
- this._fetch(method, path, body, cancelToken, headers, isIdempotent, retryCount + 1)
144
- .then(resolve)
145
- .catch(reject);
146
- }, delay);
147
- });
148
- }
149
- else {
150
- return response.text().then(text => {
151
- let msg = response.statusText;
152
- try {
153
- const parsed = JSON.parse(text);
154
- msg = parsed.message || msg;
155
- }
156
- catch {
157
- console.warn('Failed to parse error response:', text);
158
- }
159
- throw new StandardError(response.status, msg);
160
- });
161
- }
162
- }
163
- return response.json();
164
- });
165
- });
166
- }
167
12
  get(path, cancelToken, headers = {}) {
168
13
  return this._xhr('GET', path, null, cancelToken, headers, true);
169
14
  }
@@ -197,17 +42,11 @@ export class AvroQueryClient {
197
42
  throw new StandardError(500, 'Logout failed');
198
43
  });
199
44
  }
200
- fetchJobs(companyGuid, amt = 50, knownIds = [], unknownIds = [], keyword = '', offset = 0, cancelToken, headers = {}) {
201
- const body = {
202
- amt,
203
- known_ids: knownIds,
204
- unknown_ids: unknownIds,
205
- query: keyword,
206
- };
207
- if (!companyGuid) {
45
+ fetchJobs(companyGuid, body = {}, cancelToken, headers = {}) {
46
+ if (!companyGuid || companyGuid.trim() === '') {
208
47
  return Promise.reject(new StandardError(400, 'Company GUID is required'));
209
48
  }
210
- return this._fetch('POST', `/company/${companyGuid}/jobs?amt=${amt}&offset=${offset}`, body, cancelToken, headers)
49
+ return this._fetch('POST', `/company/${companyGuid}/jobs`, body, cancelToken, headers)
211
50
  .then(response => {
212
51
  if (!response || !Array.isArray(response)) {
213
52
  throw new StandardError(400, 'Invalid jobs response');
@@ -219,4 +58,97 @@ export class AvroQueryClient {
219
58
  throw new StandardError(500, 'Failed to fetch jobs');
220
59
  });
221
60
  }
61
+ fetchEvents(companyGuid, body = {}, cancelToken, headers = {}) {
62
+ if (!companyGuid || companyGuid.trim() === '') {
63
+ return Promise.reject(new StandardError(400, 'Company GUID is required'));
64
+ }
65
+ return this._fetch('POST', `/company/${companyGuid}/events`, body, cancelToken, headers)
66
+ .then(response => {
67
+ if (!response || !Array.isArray(response)) {
68
+ throw new StandardError(400, 'Invalid events response');
69
+ }
70
+ return response;
71
+ })
72
+ .catch(err => {
73
+ console.error('Failed to fetch events:', err);
74
+ throw new StandardError(500, 'Failed to fetch events');
75
+ });
76
+ }
77
+ fetchMonths(companyGuid, body = {}, cancelToken, headers = {}) {
78
+ if (!companyGuid || companyGuid.trim() === '') {
79
+ return Promise.reject(new StandardError(400, 'Company GUID is required'));
80
+ }
81
+ return this._fetch('POST', `/company/${companyGuid}/months`, body, cancelToken, headers)
82
+ .then(response => {
83
+ if (!response || !Array.isArray(response)) {
84
+ throw new StandardError(400, 'Invalid months response');
85
+ }
86
+ return response;
87
+ })
88
+ .catch(err => {
89
+ console.error('Failed to fetch months:', err);
90
+ throw new StandardError(500, 'Failed to fetch months');
91
+ });
92
+ }
93
+ fetchBills(companyGuid, body = {}, cancelToken, headers = {}) {
94
+ if (!companyGuid || companyGuid.trim() === '') {
95
+ return Promise.reject(new StandardError(400, 'Company GUID is required'));
96
+ }
97
+ return this._fetch('POST', `/company/${companyGuid}/bills`, body, cancelToken, headers)
98
+ .then(response => {
99
+ if (!response || !Array.isArray(response)) {
100
+ throw new StandardError(400, 'Invalid bills response');
101
+ }
102
+ return response;
103
+ })
104
+ .catch(err => {
105
+ console.error('Failed to fetch bills:', err);
106
+ throw new StandardError(500, 'Failed to fetch bills');
107
+ });
108
+ }
109
+ fetchRoutes(companyGuid, body = {}, cancelToken, headers = {}) {
110
+ if (!companyGuid || companyGuid.trim() === '') {
111
+ return Promise.reject(new StandardError(400, 'Company GUID is required'));
112
+ }
113
+ return this._fetch('POST', `/company/${companyGuid}/routes`, body, cancelToken, headers)
114
+ .then(response => {
115
+ if (!response || !Array.isArray(response)) {
116
+ throw new StandardError(400, 'Invalid routes response');
117
+ }
118
+ return response;
119
+ })
120
+ .catch(err => {
121
+ console.error('Failed to fetch routes:', err);
122
+ throw new StandardError(500, 'Failed to fetch routes');
123
+ });
124
+ }
125
+ sendEmail(emailId, formData) {
126
+ try {
127
+ return this._xhr('POST', `/email/${emailId}`, formData);
128
+ }
129
+ catch (error) {
130
+ throw new StandardError(500, `Failed to send email: ${error}`);
131
+ }
132
+ }
133
+ createBill(companyGuid, data, cancelToken) {
134
+ if (!companyGuid) {
135
+ return Promise.reject(new StandardError(400, 'Company GUID is required'));
136
+ }
137
+ const body = {
138
+ events: data.line_items.filter(item => item.line_item_type === 'EVENT').map(item => item.id),
139
+ months: data.line_items.filter(item => item.line_item_type === 'SERVICE_MONTH').map(item => item.id),
140
+ line_items: data.line_items.filter(item => item.line_item_type === 'CUSTOM'),
141
+ manual_emails: data.custom_emails,
142
+ users: data.users,
143
+ due_date: data.due_date,
144
+ };
145
+ try {
146
+ return this._xhr('POST', `/company/${companyGuid}/bill`, JSON.stringify(body), cancelToken, {
147
+ 'Content-Type': 'application/json',
148
+ });
149
+ }
150
+ catch (error) {
151
+ throw new StandardError(500, `Failed to create bill: ${error}`);
152
+ }
153
+ }
222
154
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,67 @@
1
+ import { AvroQueryClient } from '../../client/QueryClient';
2
+ import { StandardError } from '../../types/error';
3
+ AvroQueryClient.prototype._fetch = function (method, path, body, cancelToken, headers = {}, isIdempotent = false, retryCount = 0) {
4
+ const checkCancelled = () => {
5
+ try {
6
+ if (cancelToken?.isCancelled()) {
7
+ return new StandardError(0, 'Request cancelled');
8
+ }
9
+ }
10
+ catch (error) {
11
+ throw new StandardError(0, `Error checking cancellation (${typeof cancelToken}): ${error}`);
12
+ }
13
+ return null;
14
+ };
15
+ return this.config.authManager.accessToken().then(token => {
16
+ const cancelErr = checkCancelled();
17
+ if (cancelErr)
18
+ return Promise.reject(cancelErr);
19
+ const url = this.config.baseUrl + path;
20
+ const requestHeaders = {
21
+ 'Content-Type': 'application/json',
22
+ ...headers,
23
+ };
24
+ if (token) {
25
+ requestHeaders['Authorization'] = `Bearer ${token}`;
26
+ }
27
+ const options = {
28
+ method,
29
+ headers: requestHeaders,
30
+ body: body ? JSON.stringify(body) : null,
31
+ };
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
+ }
63
+ }
64
+ return response.json();
65
+ });
66
+ });
67
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,13 @@
1
+ import { AvroQueryClient } from '../../client/QueryClient';
2
+ AvroQueryClient.prototype.getDelay = function (strategy, attempt) {
3
+ if (typeof strategy === 'function') {
4
+ return strategy(attempt);
5
+ }
6
+ else if (strategy === 'fixed') {
7
+ return 1000;
8
+ }
9
+ else if (strategy === 'exponential') {
10
+ return Math.pow(2, attempt) * 100;
11
+ }
12
+ throw new Error(`Invalid retry strategy: ${strategy}`);
13
+ };
@@ -0,0 +1 @@
1
+ export {};