@go-avro/avro-js 0.0.2-beta.6 → 0.0.2-beta.60

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
 
@@ -1,5 +1,9 @@
1
+ import { InfiniteData, UseInfiniteQueryResult, useMutation, UseQueryResult } from '@tanstack/react-query';
1
2
  import { AuthManager } from '../auth/AuthManager';
3
+ import { _Event, ApiInfo, Bill, Break, Company, Job, LineItem, Route, ServiceMonth, Session, User, UserCompanyAssociation } from '../types/api';
4
+ import { Tokens } from '../types/auth';
2
5
  import { CancelToken, RetryStrategy } from '../types/client';
6
+ import { StandardError } from '../types/error';
3
7
  export interface AvroQueryClientConfig {
4
8
  baseUrl: string;
5
9
  authManager: AuthManager;
@@ -7,20 +11,260 @@ export interface AvroQueryClientConfig {
7
11
  retryStrategy?: RetryStrategy;
8
12
  timeout?: number;
9
13
  }
14
+ declare module '../client/QueryClient' {
15
+ interface AvroQueryClient {
16
+ _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>;
17
+ _fetch<T>(method: string, path: string, body: any, cancelToken?: CancelToken, headers?: Record<string, string>, isIdempotent?: boolean, retryCount?: number): Promise<T>;
18
+ getDelay(strategy: RetryStrategy, attempt: number): number;
19
+ useGetRoot(): UseQueryResult<ApiInfo, StandardError>;
20
+ useGetJobs(companyGuid: string, body: {
21
+ amt?: number;
22
+ query?: string;
23
+ }, total: number, onProgress?: (fraction: number) => void, isMainLoad?: boolean): UseQueryResult<Job[], StandardError>;
24
+ useGetRoutes(companyGuid: string, body: {
25
+ amt?: number;
26
+ query?: string;
27
+ }, total: number, onProgress?: (fraction: number) => void): UseQueryResult<any[], StandardError>;
28
+ useGetEvents(companyGuid: string, body: {
29
+ amt?: number;
30
+ known_ids?: string[];
31
+ unknown_ids?: string[];
32
+ query?: string;
33
+ unbilled?: boolean;
34
+ billed?: boolean;
35
+ paid?: boolean;
36
+ jobId?: string;
37
+ }): UseInfiniteQueryResult<InfiniteData<_Event[], unknown>, StandardError>;
38
+ useGetMonths(companyGuid: string, body: {
39
+ amt?: number;
40
+ known_ids?: string[];
41
+ unknown_ids?: string[];
42
+ query?: string;
43
+ unbilled?: boolean;
44
+ billed?: boolean;
45
+ paid?: boolean;
46
+ jobId?: string;
47
+ }): UseInfiniteQueryResult<InfiniteData<ServiceMonth[], unknown>, StandardError>;
48
+ useGetBills(companyGuid: string, body: {
49
+ amt?: number;
50
+ known_ids?: string[];
51
+ unknown_ids?: string[];
52
+ query?: string;
53
+ paid?: boolean;
54
+ }): UseInfiniteQueryResult<InfiniteData<Bill[], unknown>, StandardError>;
55
+ useGetCompanies(options?: {}): UseQueryResult<{
56
+ name: string;
57
+ id: string;
58
+ }[], StandardError>;
59
+ useGetCompany(companyId: string): UseQueryResult<Company, StandardError>;
60
+ useGetJob(jobId: string): UseQueryResult<Job, StandardError>;
61
+ useGetEvent(eventId: string): UseQueryResult<_Event, StandardError>;
62
+ useGetUser(userId: string): UseQueryResult<User, StandardError>;
63
+ useGetSelf(): UseQueryResult<User, StandardError>;
64
+ useGetBill(billId: string): UseQueryResult<Bill, StandardError>;
65
+ useGetRoute(routeId: string): UseQueryResult<Route, StandardError>;
66
+ useGetUserSessions(): UseQueryResult<Session[], StandardError>;
67
+ useCreateEvent(): ReturnType<typeof useMutation<{
68
+ id: string;
69
+ }, StandardError, {
70
+ companyId: string;
71
+ eventData: Partial<_Event>;
72
+ }>>;
73
+ useCreateUserSession(): ReturnType<typeof useMutation<{
74
+ id: string;
75
+ }, StandardError, {
76
+ companyId: string;
77
+ sessionData: Partial<Session>;
78
+ }>>;
79
+ useCreateBill(): ReturnType<typeof useMutation<{
80
+ id: string;
81
+ invoice_id: number;
82
+ }, StandardError, {
83
+ companyId: string;
84
+ data: {
85
+ line_items: LineItem[];
86
+ due_date: number;
87
+ users: string[];
88
+ custom_emails: [string, string][];
89
+ };
90
+ }>>;
91
+ useCreateJob(): ReturnType<typeof useMutation<{
92
+ id: string;
93
+ }, StandardError, {
94
+ companyId: string;
95
+ jobData: Partial<Job>;
96
+ }>>;
97
+ useCreateSelf(): ReturnType<typeof useMutation<{
98
+ msg: string;
99
+ }, StandardError, {
100
+ username: string;
101
+ name: string;
102
+ email: string;
103
+ password: string;
104
+ phone_number: string;
105
+ }>>;
106
+ useCreateSessionBreak(): ReturnType<typeof useMutation<{
107
+ id: string;
108
+ }, StandardError, {
109
+ sessionId: string;
110
+ breakData: {
111
+ start_time: string;
112
+ end_time?: string;
113
+ };
114
+ }>>;
115
+ useUpdateEvent(): ReturnType<typeof useMutation<{
116
+ msg: string;
117
+ }, StandardError, {
118
+ eventId: string;
119
+ updates: Partial<_Event>;
120
+ }>>;
121
+ useUpdateUserSession(): ReturnType<typeof useMutation<{
122
+ msg: string;
123
+ }, StandardError, {
124
+ sessionId: string;
125
+ updates: Partial<Session>;
126
+ }>>;
127
+ useUpdateJob(): ReturnType<typeof useMutation<{
128
+ msg: string;
129
+ }, StandardError, {
130
+ jobId: string;
131
+ updates: Partial<Job>;
132
+ }>>;
133
+ useUpdateBill(): ReturnType<typeof useMutation<{
134
+ msg: string;
135
+ }, StandardError, {
136
+ billId: string;
137
+ updates: Partial<Bill>;
138
+ }>>;
139
+ useUpdateRoute(): ReturnType<typeof useMutation<{
140
+ msg: string;
141
+ }, StandardError, {
142
+ routeId: string;
143
+ updates: Partial<Route>;
144
+ }>>;
145
+ useUpdateEvents(): ReturnType<typeof useMutation<void, StandardError, {
146
+ companyId: string;
147
+ events: (_Event & {
148
+ page?: number;
149
+ })[];
150
+ action: "billed" | "paid";
151
+ }>>;
152
+ useUpdateMonths(): ReturnType<typeof useMutation<void, StandardError, {
153
+ companyId: string;
154
+ months: (ServiceMonth & {
155
+ page?: number;
156
+ })[];
157
+ action: "billed" | "paid";
158
+ }>>;
159
+ useUpdateUserCompany(): ReturnType<typeof useMutation<{
160
+ msg: string;
161
+ }, StandardError, {
162
+ company_id: string;
163
+ user_id: string;
164
+ data: Partial<UserCompanyAssociation>;
165
+ }>>;
166
+ useUpdateSessionBreak(): ReturnType<typeof useMutation<{
167
+ msg: string;
168
+ }, StandardError, {
169
+ breakId: string;
170
+ updates: Partial<Break>;
171
+ }>>;
172
+ useDeleteJob(): ReturnType<typeof useMutation<{
173
+ msg: string;
174
+ }, StandardError, {
175
+ jobId: string;
176
+ }>>;
177
+ useUpdateCompany(): ReturnType<typeof useMutation<{
178
+ msg: string;
179
+ }, StandardError, {
180
+ companyId: string;
181
+ companyData: Partial<Company | {
182
+ logo: File | null;
183
+ }>;
184
+ }>>;
185
+ useDeleteEvent(): ReturnType<typeof useMutation<{
186
+ msg: string;
187
+ }, StandardError, {
188
+ eventId: string;
189
+ }>>;
190
+ useDeleteBill(): ReturnType<typeof useMutation<{
191
+ msg: string;
192
+ }, StandardError, {
193
+ billId: string;
194
+ }>>;
195
+ useDeleteRoute(): ReturnType<typeof useMutation<{
196
+ msg: string;
197
+ }, StandardError, {
198
+ routeId: string;
199
+ }>>;
200
+ useDeleteSelf(): ReturnType<typeof useMutation<{
201
+ msg: string;
202
+ }, StandardError, void>>;
203
+ }
204
+ }
10
205
  export declare class AvroQueryClient {
11
- private config;
206
+ protected config: Required<AvroQueryClientConfig>;
12
207
  constructor(config: AvroQueryClientConfig);
13
- getDelay(strategy: RetryStrategy, attempt: number): number;
14
- private _xhr;
15
- private _fetch;
16
- get<T>(path: string, cancelToken?: CancelToken, headers?: Record<string, string>): Promise<T>;
17
- post<T>(path: string, data: any, cancelToken?: CancelToken, headers?: Record<string, string>): Promise<T>;
18
- put<T>(path: string, data: any, cancelToken?: CancelToken, headers?: Record<string, string>): Promise<T>;
19
- delete<T>(path: string, cancelToken?: CancelToken, headers?: Record<string, string>): Promise<T>;
208
+ get<T>(path: string, cancelToken?: CancelToken, headers?: Record<string, string>, progressUpdateCallback?: (loaded: number, total: number) => void): Promise<T>;
209
+ post<T>(path: string, data: any, cancelToken?: CancelToken, headers?: Record<string, string>, progressUpdateCallback?: (loaded: number, total: number) => void): Promise<T>;
210
+ put<T>(path: string, data: any, cancelToken?: CancelToken, headers?: Record<string, string>, progressUpdateCallback?: (loaded: number, total: number) => void): Promise<T>;
211
+ delete<T>(path: string, cancelToken?: CancelToken, headers?: Record<string, string>, progressUpdateCallback?: (loaded: number, total: number) => void): Promise<T>;
20
212
  login(data: {
21
213
  username: string;
22
214
  password: string;
23
215
  }, cancelToken?: CancelToken): Promise<Boolean>;
24
- 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>;
216
+ setTokens(tokens: Tokens): Promise<void>;
217
+ clearTokens(): Promise<void>;
218
+ useLogout(): ReturnType<typeof useMutation<void, StandardError, CancelToken | undefined>>;
219
+ fetchJobs(companyGuid: string, body?: {
220
+ amt?: number;
221
+ known_ids?: string[];
222
+ unknown_ids?: string[];
223
+ query?: string;
224
+ offset?: number;
225
+ }, cancelToken?: CancelToken, headers?: Record<string, string>): Promise<any>;
226
+ fetchEvents(companyGuid: string, body?: {
227
+ amt?: number;
228
+ known_ids?: string[];
229
+ unknown_ids?: string[];
230
+ query?: string;
231
+ offset?: number;
232
+ unbilled?: boolean;
233
+ billed?: boolean;
234
+ paid?: boolean;
235
+ jobId?: string | null;
236
+ }, cancelToken?: CancelToken, headers?: Record<string, string>): Promise<any>;
237
+ fetchMonths(companyGuid: string, body?: {
238
+ amt?: number;
239
+ known_ids?: string[];
240
+ unknown_ids?: string[];
241
+ query?: string;
242
+ offset?: number;
243
+ unbilled?: boolean;
244
+ billed?: boolean;
245
+ paid?: boolean;
246
+ jobId?: string | null;
247
+ }, cancelToken?: CancelToken, headers?: Record<string, string>): Promise<any>;
248
+ fetchBills(companyGuid: string, body?: {
249
+ amt?: number;
250
+ known_ids?: string[];
251
+ unknown_ids?: string[];
252
+ query?: string;
253
+ offset?: number;
254
+ paid?: boolean;
255
+ }, cancelToken?: CancelToken, headers?: Record<string, string>): Promise<any>;
256
+ fetchRoutes(companyGuid: string, body?: {
257
+ amt?: number;
258
+ known_ids?: string[];
259
+ unknown_ids?: string[];
260
+ query?: string;
261
+ offset?: number;
262
+ }, cancelToken?: CancelToken, headers?: Record<string, string>): Promise<any>;
263
+ sendEmail(emailId: string, formData: FormData, progressUpdateCallback?: (loaded: number, total: number) => void): Promise<void>;
264
+ createBill(companyGuid: string, data: {
265
+ line_items: LineItem[];
266
+ due_date: number;
267
+ users: string[];
268
+ custom_emails: [string, string][];
269
+ }, cancelToken?: CancelToken): Promise<any>;
26
270
  }
@@ -1,3 +1,4 @@
1
+ import { useMutation, useQueryClient } from '@tanstack/react-query';
1
2
  import { StandardError } from '../types/error';
2
3
  export class AvroQueryClient {
3
4
  constructor(config) {
@@ -9,172 +10,17 @@ export class AvroQueryClient {
9
10
  timeout: config.timeout ?? 0,
10
11
  };
11
12
  }
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}`);
13
+ get(path, cancelToken, headers = {}, progressUpdateCallback) {
14
+ return this._xhr('GET', path, null, cancelToken, headers, true, this.config.maxRetries, progressUpdateCallback);
23
15
  }
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
- });
16
+ post(path, data, cancelToken, headers = {}, progressUpdateCallback) {
17
+ return this._xhr('POST', path, data, cancelToken, headers, false, this.config.maxRetries, progressUpdateCallback);
106
18
  }
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
- get(path, cancelToken, headers = {}) {
168
- return this._xhr('GET', path, null, cancelToken, headers, true);
169
- }
170
- post(path, data, cancelToken, headers = {}) {
171
- return this._xhr('POST', path, data, cancelToken, headers, false);
19
+ put(path, data, cancelToken, headers = {}, progressUpdateCallback) {
20
+ return this._xhr('PUT', path, data, cancelToken, headers, true, this.config.maxRetries, progressUpdateCallback);
172
21
  }
173
- put(path, data, cancelToken, headers = {}) {
174
- return this._xhr('PUT', path, data, cancelToken, headers, true);
175
- }
176
- delete(path, cancelToken, headers = {}) {
177
- return this._xhr('DELETE', path, null, cancelToken, headers, false);
22
+ delete(path, cancelToken, headers = {}, progressUpdateCallback) {
23
+ return this._xhr('DELETE', path, null, cancelToken, headers, false, this.config.maxRetries, progressUpdateCallback);
178
24
  }
179
25
  login(data, cancelToken) {
180
26
  return this._fetch('POST', '/login', data, cancelToken)
@@ -189,25 +35,32 @@ export class AvroQueryClient {
189
35
  throw new StandardError(401, 'Login failed');
190
36
  });
191
37
  }
192
- logout(cancelToken) {
193
- return this._fetch('POST', '/logout', null, cancelToken)
194
- .then(() => this.config.authManager.clearTokens())
195
- .catch(err => {
196
- console.error('Logout failed:', err);
197
- throw new StandardError(500, 'Logout failed');
38
+ setTokens(tokens) {
39
+ return this.config.authManager.setTokens(tokens);
40
+ }
41
+ clearTokens() {
42
+ return this.config.authManager.clearTokens();
43
+ }
44
+ useLogout() {
45
+ const queryClient = useQueryClient();
46
+ return useMutation({
47
+ mutationFn: (cancelToken) => this._fetch('POST', '/logout', null, cancelToken)
48
+ .then(() => this.config.authManager.clearTokens()),
49
+ onSettled: () => {
50
+ queryClient.invalidateQueries();
51
+ },
52
+ onError: (err) => {
53
+ this.config.authManager.clearTokens();
54
+ console.error('Logout failed:', err);
55
+ throw new StandardError(500, 'Logout failed');
56
+ }
198
57
  });
199
58
  }
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) {
59
+ fetchJobs(companyGuid, body = {}, cancelToken, headers = {}) {
60
+ if (!companyGuid || companyGuid.trim() === '') {
208
61
  return Promise.reject(new StandardError(400, 'Company GUID is required'));
209
62
  }
210
- return this._fetch('POST', `/company/${companyGuid}/jobs?amt=${amt}&offset=${offset}`, body, cancelToken, headers)
63
+ return this._fetch('POST', `/company/${companyGuid}/jobs`, body, cancelToken, headers)
211
64
  .then(response => {
212
65
  if (!response || !Array.isArray(response)) {
213
66
  throw new StandardError(400, 'Invalid jobs response');
@@ -219,4 +72,97 @@ export class AvroQueryClient {
219
72
  throw new StandardError(500, 'Failed to fetch jobs');
220
73
  });
221
74
  }
75
+ fetchEvents(companyGuid, body = {}, cancelToken, headers = {}) {
76
+ if (!companyGuid || companyGuid.trim() === '') {
77
+ return Promise.reject(new StandardError(400, 'Company GUID is required'));
78
+ }
79
+ return this._fetch('POST', `/company/${companyGuid}/events`, body, cancelToken, headers)
80
+ .then(response => {
81
+ if (!response || !Array.isArray(response)) {
82
+ throw new StandardError(400, 'Invalid events response');
83
+ }
84
+ return response;
85
+ })
86
+ .catch(err => {
87
+ console.error('Failed to fetch events:', err);
88
+ throw new StandardError(500, 'Failed to fetch events');
89
+ });
90
+ }
91
+ fetchMonths(companyGuid, body = {}, cancelToken, headers = {}) {
92
+ if (!companyGuid || companyGuid.trim() === '') {
93
+ return Promise.reject(new StandardError(400, 'Company GUID is required'));
94
+ }
95
+ return this._fetch('POST', `/company/${companyGuid}/months`, body, cancelToken, headers)
96
+ .then(response => {
97
+ if (!response || !Array.isArray(response)) {
98
+ throw new StandardError(400, 'Invalid months response');
99
+ }
100
+ return response;
101
+ })
102
+ .catch(err => {
103
+ console.error('Failed to fetch months:', err);
104
+ throw new StandardError(500, 'Failed to fetch months');
105
+ });
106
+ }
107
+ fetchBills(companyGuid, body = {}, cancelToken, headers = {}) {
108
+ if (!companyGuid || companyGuid.trim() === '') {
109
+ return Promise.reject(new StandardError(400, 'Company GUID is required'));
110
+ }
111
+ return this._fetch('POST', `/company/${companyGuid}/bills`, body, cancelToken, headers)
112
+ .then(response => {
113
+ if (!response || !Array.isArray(response)) {
114
+ throw new StandardError(400, 'Invalid bills response');
115
+ }
116
+ return response;
117
+ })
118
+ .catch(err => {
119
+ console.error('Failed to fetch bills:', err);
120
+ throw new StandardError(500, 'Failed to fetch bills');
121
+ });
122
+ }
123
+ fetchRoutes(companyGuid, body = {}, cancelToken, headers = {}) {
124
+ if (!companyGuid || companyGuid.trim() === '') {
125
+ return Promise.reject(new StandardError(400, 'Company GUID is required'));
126
+ }
127
+ return this._fetch('POST', `/company/${companyGuid}/routes`, body, cancelToken, headers)
128
+ .then(response => {
129
+ if (!response || !Array.isArray(response)) {
130
+ throw new StandardError(400, 'Invalid routes response');
131
+ }
132
+ return response;
133
+ })
134
+ .catch(err => {
135
+ console.error('Failed to fetch routes:', err);
136
+ throw new StandardError(500, 'Failed to fetch routes');
137
+ });
138
+ }
139
+ sendEmail(emailId, formData, progressUpdateCallback) {
140
+ try {
141
+ return this.post(`/email/${emailId}`, formData, undefined, {}, progressUpdateCallback);
142
+ }
143
+ catch (error) {
144
+ throw new StandardError(500, `Failed to send email: ${error}`);
145
+ }
146
+ }
147
+ createBill(companyGuid, data, cancelToken) {
148
+ if (!companyGuid) {
149
+ return Promise.reject(new StandardError(400, 'Company GUID is required'));
150
+ }
151
+ const body = {
152
+ events: data.line_items.filter(item => item.line_item_type === 'EVENT').map(item => item.id),
153
+ months: data.line_items.filter(item => item.line_item_type === 'SERVICE_MONTH').map(item => item.id),
154
+ line_items: data.line_items.filter(item => item.line_item_type === 'CUSTOM'),
155
+ manual_emails: data.custom_emails,
156
+ users: data.users,
157
+ due_date: data.due_date,
158
+ };
159
+ try {
160
+ return this._xhr('POST', `/company/${companyGuid}/bill`, JSON.stringify(body), cancelToken, {
161
+ 'Content-Type': 'application/json',
162
+ });
163
+ }
164
+ catch (error) {
165
+ throw new StandardError(500, `Failed to create bill: ${error}`);
166
+ }
167
+ }
222
168
  }
@@ -0,0 +1 @@
1
+ export {};