@rendomnet/apiservice 1.0.0
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/LICENSE +21 -0
- package/README.md +53 -0
- package/dist/AccountManager.d.ts +27 -0
- package/dist/AccountManager.js +46 -0
- package/dist/CacheManager.d.ts +28 -0
- package/dist/CacheManager.js +62 -0
- package/dist/FetchError.d.ts +8 -0
- package/dist/FetchError.js +32 -0
- package/dist/HookManager.d.ts +28 -0
- package/dist/HookManager.js +70 -0
- package/dist/HttpClient.d.ts +26 -0
- package/dist/HttpClient.js +107 -0
- package/dist/RetryManager.d.ts +36 -0
- package/dist/RetryManager.js +81 -0
- package/dist/components.d.ts +8 -0
- package/dist/components.js +16 -0
- package/dist/form.d.ts +1 -0
- package/dist/form.js +48 -0
- package/dist/index.d.ts +50 -0
- package/dist/index.js +143 -0
- package/dist/types.d.ts +59 -0
- package/dist/types.js +2 -0
- package/package.json +49 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Rendom
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# ApiService
|
|
2
|
+
|
|
3
|
+
A robust TypeScript API service framework for making authenticated API calls with advanced features:
|
|
4
|
+
|
|
5
|
+
- ✅ Authentication handling with token management
|
|
6
|
+
- ✅ Request caching with configurable time periods
|
|
7
|
+
- ✅ Advanced retry mechanisms with exponential backoff
|
|
8
|
+
- ✅ Status code-specific hooks for handling errors
|
|
9
|
+
- ✅ Account state tracking
|
|
10
|
+
- ✅ File upload support
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
import ApiService from 'apiservice';
|
|
16
|
+
|
|
17
|
+
// Create and setup the API service
|
|
18
|
+
const api = new ApiService();
|
|
19
|
+
api.setup({
|
|
20
|
+
provider: 'my-service',
|
|
21
|
+
tokenService: myTokenService,
|
|
22
|
+
hooks: {
|
|
23
|
+
401: {
|
|
24
|
+
retryCall: true,
|
|
25
|
+
retryDelay: true,
|
|
26
|
+
callback: async (accountId, response) => {
|
|
27
|
+
// Handle token refresh logic
|
|
28
|
+
return { /* updated parameters */ };
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
cacheTime: 30000 // 30 seconds
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Make API calls
|
|
36
|
+
const result = await api.makeApiCall({
|
|
37
|
+
accountId: 'user123',
|
|
38
|
+
method: 'GET',
|
|
39
|
+
base: 'https://api.example.com',
|
|
40
|
+
route: '/users',
|
|
41
|
+
requireAuth: true
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Architecture
|
|
46
|
+
|
|
47
|
+
The codebase is built around a main `ApiService` class that coordinates several component managers:
|
|
48
|
+
|
|
49
|
+
- `HttpClient`: Handles the actual HTTP request creation and execution
|
|
50
|
+
- `CacheManager`: Implements data caching with customizable expiration times
|
|
51
|
+
- `RetryManager`: Manages retry logic with exponential backoff and other delay strategies
|
|
52
|
+
- `HookManager`: Provides a way to hook into specific status codes and handle them
|
|
53
|
+
- `AccountManager`: Tracks account state and handles account-specific data
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { AccountData } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Manages account data and state
|
|
4
|
+
*/
|
|
5
|
+
export declare class AccountManager {
|
|
6
|
+
private accounts;
|
|
7
|
+
/**
|
|
8
|
+
* Update account data for a specific account
|
|
9
|
+
*/
|
|
10
|
+
updateAccountData(accountId: string, data: Partial<AccountData>): void;
|
|
11
|
+
/**
|
|
12
|
+
* Get account data for a specific account
|
|
13
|
+
*/
|
|
14
|
+
getAccountData(accountId: string): AccountData;
|
|
15
|
+
/**
|
|
16
|
+
* Check if an account's last request failed
|
|
17
|
+
*/
|
|
18
|
+
didLastRequestFail(accountId: string): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Set account's last request as failed
|
|
21
|
+
*/
|
|
22
|
+
setLastRequestFailed(accountId: string, failed?: boolean): void;
|
|
23
|
+
/**
|
|
24
|
+
* Update the last request time for an account
|
|
25
|
+
*/
|
|
26
|
+
updateLastRequestTime(accountId: string): void;
|
|
27
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AccountManager = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Manages account data and state
|
|
6
|
+
*/
|
|
7
|
+
class AccountManager {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.accounts = {};
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Update account data for a specific account
|
|
13
|
+
*/
|
|
14
|
+
updateAccountData(accountId, data) {
|
|
15
|
+
this.accounts[accountId] = {
|
|
16
|
+
...this.accounts[accountId],
|
|
17
|
+
...data
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Get account data for a specific account
|
|
22
|
+
*/
|
|
23
|
+
getAccountData(accountId) {
|
|
24
|
+
return this.accounts[accountId] || {};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Check if an account's last request failed
|
|
28
|
+
*/
|
|
29
|
+
didLastRequestFail(accountId) {
|
|
30
|
+
var _a;
|
|
31
|
+
return !!((_a = this.accounts[accountId]) === null || _a === void 0 ? void 0 : _a.lastFailed);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Set account's last request as failed
|
|
35
|
+
*/
|
|
36
|
+
setLastRequestFailed(accountId, failed = true) {
|
|
37
|
+
this.updateAccountData(accountId, { lastFailed: failed });
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Update the last request time for an account
|
|
41
|
+
*/
|
|
42
|
+
updateLastRequestTime(accountId) {
|
|
43
|
+
this.updateAccountData(accountId, { lastRequestTime: Date.now() });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.AccountManager = AccountManager;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ApiCallParams } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Handles caching of API responses
|
|
4
|
+
*/
|
|
5
|
+
export declare class CacheManager {
|
|
6
|
+
private cache;
|
|
7
|
+
private cacheTime;
|
|
8
|
+
/**
|
|
9
|
+
* Get data from cache if available and not expired
|
|
10
|
+
*/
|
|
11
|
+
getFromCache(apiCallParams: ApiCallParams): any;
|
|
12
|
+
/**
|
|
13
|
+
* Save data to cache
|
|
14
|
+
*/
|
|
15
|
+
saveToCache(apiCallParams: ApiCallParams, data: any): void;
|
|
16
|
+
/**
|
|
17
|
+
* Generate a unique key for caching based on request parameters
|
|
18
|
+
*/
|
|
19
|
+
private getRequestKey;
|
|
20
|
+
/**
|
|
21
|
+
* Set the default cache time in milliseconds
|
|
22
|
+
*/
|
|
23
|
+
setCacheTime(milliseconds: number): void;
|
|
24
|
+
/**
|
|
25
|
+
* Clear the entire cache
|
|
26
|
+
*/
|
|
27
|
+
clearCache(): void;
|
|
28
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CacheManager = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Handles caching of API responses
|
|
6
|
+
*/
|
|
7
|
+
class CacheManager {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.cache = new Map();
|
|
10
|
+
this.cacheTime = 20000; // Default cache time of 20 seconds
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Get data from cache if available and not expired
|
|
14
|
+
*/
|
|
15
|
+
getFromCache(apiCallParams) {
|
|
16
|
+
var _a;
|
|
17
|
+
const requestKey = this.getRequestKey(apiCallParams);
|
|
18
|
+
const currentCacheTime = (_a = apiCallParams.cacheTime) !== null && _a !== void 0 ? _a : this.cacheTime;
|
|
19
|
+
const cached = this.cache.get(requestKey);
|
|
20
|
+
if (cached && (Date.now() - cached.timestamp < currentCacheTime)) {
|
|
21
|
+
return cached.data;
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Save data to cache
|
|
27
|
+
*/
|
|
28
|
+
saveToCache(apiCallParams, data) {
|
|
29
|
+
const requestKey = this.getRequestKey(apiCallParams);
|
|
30
|
+
this.cache.set(requestKey, {
|
|
31
|
+
data,
|
|
32
|
+
timestamp: Date.now()
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Generate a unique key for caching based on request parameters
|
|
37
|
+
*/
|
|
38
|
+
getRequestKey(apiCallParams) {
|
|
39
|
+
const { accountId, method, route, base, queryParams, body, data } = apiCallParams;
|
|
40
|
+
return JSON.stringify({
|
|
41
|
+
accountId,
|
|
42
|
+
method,
|
|
43
|
+
route,
|
|
44
|
+
base,
|
|
45
|
+
queryParams,
|
|
46
|
+
body: body || data,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Set the default cache time in milliseconds
|
|
51
|
+
*/
|
|
52
|
+
setCacheTime(milliseconds) {
|
|
53
|
+
this.cacheTime = milliseconds;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Clear the entire cache
|
|
57
|
+
*/
|
|
58
|
+
clearCache() {
|
|
59
|
+
this.cache.clear();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
exports.CacheManager = CacheManager;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FetchError = void 0;
|
|
4
|
+
class FetchError extends Error {
|
|
5
|
+
constructor(response, data = {}, code = 'FETCH_ERROR') {
|
|
6
|
+
super();
|
|
7
|
+
this.name = 'FetchError';
|
|
8
|
+
const defaultMessage = 'An unspecified error occurred';
|
|
9
|
+
const getMessage = (data, locations) => locations
|
|
10
|
+
.map((item) => {
|
|
11
|
+
const parts = item.split('.');
|
|
12
|
+
let value = data;
|
|
13
|
+
for (const part of parts) {
|
|
14
|
+
value = value === null || value === void 0 ? void 0 : value[part];
|
|
15
|
+
}
|
|
16
|
+
return value;
|
|
17
|
+
})
|
|
18
|
+
.find((message) => typeof message === 'string') || null;
|
|
19
|
+
const messageFromData = getMessage(data, [
|
|
20
|
+
'error.errors.0.message',
|
|
21
|
+
'error.message',
|
|
22
|
+
'message',
|
|
23
|
+
]);
|
|
24
|
+
this.message = messageFromData || response.statusText || defaultMessage;
|
|
25
|
+
this.status = response.status;
|
|
26
|
+
this.code = code;
|
|
27
|
+
this.data = data;
|
|
28
|
+
this.message = this.message || defaultMessage;
|
|
29
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.FetchError = FetchError;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { HookSettings, StatusCode } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Manages hooks for different status codes and their processing
|
|
4
|
+
*/
|
|
5
|
+
export declare class HookManager {
|
|
6
|
+
private hooks;
|
|
7
|
+
private hookPromises;
|
|
8
|
+
/**
|
|
9
|
+
* Set hooks for different status codes
|
|
10
|
+
*/
|
|
11
|
+
setHooks(hooks: Record<StatusCode, HookSettings>): void;
|
|
12
|
+
/**
|
|
13
|
+
* Get a hook for a specific status code
|
|
14
|
+
*/
|
|
15
|
+
getHook(status: StatusCode): HookSettings | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Process a hook for a specific status code
|
|
18
|
+
*/
|
|
19
|
+
processHook(accountId: string, status: StatusCode, error: any): Promise<Record<string, any> | null>;
|
|
20
|
+
/**
|
|
21
|
+
* Handle a retry failure with the appropriate hook
|
|
22
|
+
*/
|
|
23
|
+
handleRetryFailure(accountId: string, status: StatusCode, error: any): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Check if a hook exists and should retry for a given status
|
|
26
|
+
*/
|
|
27
|
+
shouldRetry(status: StatusCode): boolean;
|
|
28
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HookManager = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Manages hooks for different status codes and their processing
|
|
6
|
+
*/
|
|
7
|
+
class HookManager {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.hooks = {};
|
|
10
|
+
this.hookPromises = {};
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Set hooks for different status codes
|
|
14
|
+
*/
|
|
15
|
+
setHooks(hooks) {
|
|
16
|
+
this.hooks = { ...this.hooks, ...hooks };
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Get a hook for a specific status code
|
|
20
|
+
*/
|
|
21
|
+
getHook(status) {
|
|
22
|
+
return this.hooks[status];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Process a hook for a specific status code
|
|
26
|
+
*/
|
|
27
|
+
async processHook(accountId, status, error) {
|
|
28
|
+
const hook = this.hooks[status];
|
|
29
|
+
if (!hook || !hook.callback)
|
|
30
|
+
return null;
|
|
31
|
+
const hookKey = `${accountId}-${status}`;
|
|
32
|
+
try {
|
|
33
|
+
// Handle waiting for existing hook call if needed
|
|
34
|
+
if (hook.waitUntilFinished) {
|
|
35
|
+
if (!this.hookPromises[hookKey]) {
|
|
36
|
+
this.hookPromises[hookKey] = Promise.resolve(hook.callback(accountId, error.response) || {});
|
|
37
|
+
}
|
|
38
|
+
const result = await this.hookPromises[hookKey];
|
|
39
|
+
delete this.hookPromises[hookKey];
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
// Otherwise just call the hook directly
|
|
43
|
+
return await hook.callback(accountId, error.response) || {};
|
|
44
|
+
}
|
|
45
|
+
catch (hookError) {
|
|
46
|
+
console.error(`Hook callback failed for status ${status}:`, hookError);
|
|
47
|
+
if (hook.errorCallback) {
|
|
48
|
+
await hook.errorCallback(accountId, hookError);
|
|
49
|
+
}
|
|
50
|
+
throw hookError;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Handle a retry failure with the appropriate hook
|
|
55
|
+
*/
|
|
56
|
+
async handleRetryFailure(accountId, status, error) {
|
|
57
|
+
const hook = this.hooks[status];
|
|
58
|
+
if (hook === null || hook === void 0 ? void 0 : hook.onRetryFail) {
|
|
59
|
+
await hook.onRetryFail(accountId, error);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Check if a hook exists and should retry for a given status
|
|
64
|
+
*/
|
|
65
|
+
shouldRetry(status) {
|
|
66
|
+
const hook = this.hooks[status];
|
|
67
|
+
return !!hook && !!hook.retryCall;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.HookManager = HookManager;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ApiCallParams, Token } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Handles HTTP requests to external APIs
|
|
4
|
+
*/
|
|
5
|
+
export declare class HttpClient {
|
|
6
|
+
/**
|
|
7
|
+
* Make an HTTP request
|
|
8
|
+
*/
|
|
9
|
+
makeRequest(apiParams: ApiCallParams, authToken: Token | Record<string, any>): Promise<any>;
|
|
10
|
+
/**
|
|
11
|
+
* Build URL with query parameters
|
|
12
|
+
*/
|
|
13
|
+
private buildUrl;
|
|
14
|
+
/**
|
|
15
|
+
* Prepare form data for file uploads
|
|
16
|
+
*/
|
|
17
|
+
private prepareFormData;
|
|
18
|
+
/**
|
|
19
|
+
* Build fetch options for request
|
|
20
|
+
*/
|
|
21
|
+
private buildFetchOptions;
|
|
22
|
+
/**
|
|
23
|
+
* Handle API response
|
|
24
|
+
*/
|
|
25
|
+
private handleResponse;
|
|
26
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.HttpClient = void 0;
|
|
7
|
+
const qs_1 = __importDefault(require("qs"));
|
|
8
|
+
const FetchError_1 = require("./FetchError");
|
|
9
|
+
const form_1 = require("./form");
|
|
10
|
+
/**
|
|
11
|
+
* Handles HTTP requests to external APIs
|
|
12
|
+
*/
|
|
13
|
+
class HttpClient {
|
|
14
|
+
/**
|
|
15
|
+
* Make an HTTP request
|
|
16
|
+
*/
|
|
17
|
+
async makeRequest(apiParams, authToken) {
|
|
18
|
+
const { accountId, method, route, base, body, data, headers, queryParams, contentType = 'application/json', accessToken: forcedAccessToken, requireAuth = true, files, } = apiParams;
|
|
19
|
+
// Build URL and request body
|
|
20
|
+
const url = this.buildUrl(base, route, queryParams);
|
|
21
|
+
const requestBody = body || data;
|
|
22
|
+
const normalizedMethod = method === null || method === void 0 ? void 0 : method.toUpperCase();
|
|
23
|
+
// Handle file uploads
|
|
24
|
+
const formData = this.prepareFormData(files);
|
|
25
|
+
// Create fetch options
|
|
26
|
+
const fetchOptions = this.buildFetchOptions({
|
|
27
|
+
method: normalizedMethod,
|
|
28
|
+
body: requestBody,
|
|
29
|
+
formData,
|
|
30
|
+
contentType,
|
|
31
|
+
authToken,
|
|
32
|
+
forcedAccessToken,
|
|
33
|
+
requireAuth,
|
|
34
|
+
headers,
|
|
35
|
+
});
|
|
36
|
+
// Make the request
|
|
37
|
+
try {
|
|
38
|
+
console.log(`🔄 Making API call to ${url}`);
|
|
39
|
+
const response = await fetch(url, fetchOptions);
|
|
40
|
+
return await this.handleResponse(response);
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
console.error('🔄 Error making API call:', error);
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Build URL with query parameters
|
|
49
|
+
*/
|
|
50
|
+
buildUrl(base, route, queryParams) {
|
|
51
|
+
let url = `${base}${route || ''}`;
|
|
52
|
+
if (queryParams)
|
|
53
|
+
url += `?${qs_1.default.stringify(queryParams)}`;
|
|
54
|
+
return url;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Prepare form data for file uploads
|
|
58
|
+
*/
|
|
59
|
+
prepareFormData(files) {
|
|
60
|
+
if (!files)
|
|
61
|
+
return null;
|
|
62
|
+
const formData = (0, form_1.deserializeForm)(files);
|
|
63
|
+
// Use a workaround for TypeScript FormData entries() issue
|
|
64
|
+
const entries = formData;
|
|
65
|
+
for (let [key, value] of entries.entries()) {
|
|
66
|
+
console.log(`formdata ${key}:`, value);
|
|
67
|
+
}
|
|
68
|
+
return formData;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Build fetch options for request
|
|
72
|
+
*/
|
|
73
|
+
buildFetchOptions({ method, body, formData, contentType, authToken, forcedAccessToken, requireAuth, headers, }) {
|
|
74
|
+
const allowedMethods = ['POST', 'PUT', 'PATCH'];
|
|
75
|
+
return {
|
|
76
|
+
method,
|
|
77
|
+
headers: {
|
|
78
|
+
...(requireAuth && {
|
|
79
|
+
Authorization: `Bearer ${forcedAccessToken || authToken.access_token}`
|
|
80
|
+
}),
|
|
81
|
+
...(!formData && { 'content-type': contentType }),
|
|
82
|
+
...(headers || {}),
|
|
83
|
+
},
|
|
84
|
+
body: body && allowedMethods.includes(method)
|
|
85
|
+
? JSON.stringify(body)
|
|
86
|
+
: (formData || null),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Handle API response
|
|
91
|
+
*/
|
|
92
|
+
async handleResponse(response) {
|
|
93
|
+
let data = null;
|
|
94
|
+
try {
|
|
95
|
+
data = await response.json();
|
|
96
|
+
console.log('🔄 Response data:', data);
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
// Response wasn't JSON, continue with null data
|
|
100
|
+
}
|
|
101
|
+
if (!response.ok) {
|
|
102
|
+
throw new FetchError_1.FetchError(response, data);
|
|
103
|
+
}
|
|
104
|
+
return data;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
exports.HttpClient = HttpClient;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { HookSettings } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Handles retry logic and delay strategies for failed API calls
|
|
4
|
+
*/
|
|
5
|
+
export declare class RetryManager {
|
|
6
|
+
private defaultMaxDelay;
|
|
7
|
+
private defaultMaxRetries;
|
|
8
|
+
/**
|
|
9
|
+
* Default exponential backoff strategy with full jitter
|
|
10
|
+
*/
|
|
11
|
+
private defaultDelayStrategy;
|
|
12
|
+
/**
|
|
13
|
+
* Calculate and wait for appropriate delay time before retry
|
|
14
|
+
*/
|
|
15
|
+
calculateAndDelay(params: {
|
|
16
|
+
attempt: number;
|
|
17
|
+
response?: any;
|
|
18
|
+
hook: HookSettings;
|
|
19
|
+
}): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Extract retry-after value from response
|
|
22
|
+
*/
|
|
23
|
+
private getRetryAfterValue;
|
|
24
|
+
/**
|
|
25
|
+
* Get the default maximum number of retries
|
|
26
|
+
*/
|
|
27
|
+
getDefaultMaxRetries(): number;
|
|
28
|
+
/**
|
|
29
|
+
* Set the default maximum number of retries
|
|
30
|
+
*/
|
|
31
|
+
setDefaultMaxRetries(maxRetries: number): void;
|
|
32
|
+
/**
|
|
33
|
+
* Set the default maximum delay between retries
|
|
34
|
+
*/
|
|
35
|
+
setDefaultMaxDelay(maxDelay: number): void;
|
|
36
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RetryManager = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Handles retry logic and delay strategies for failed API calls
|
|
6
|
+
*/
|
|
7
|
+
class RetryManager {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.defaultMaxDelay = 60000; // Default max delay of 1 minute
|
|
10
|
+
this.defaultMaxRetries = 4;
|
|
11
|
+
/**
|
|
12
|
+
* Default exponential backoff strategy with full jitter
|
|
13
|
+
*/
|
|
14
|
+
this.defaultDelayStrategy = {
|
|
15
|
+
calculate: (attempt, response) => {
|
|
16
|
+
// Check for Retry-After header
|
|
17
|
+
const retryAfter = this.getRetryAfterValue(response);
|
|
18
|
+
if (retryAfter)
|
|
19
|
+
return retryAfter;
|
|
20
|
+
// Exponential backoff with full jitter
|
|
21
|
+
const baseDelay = 1000; // 1 second
|
|
22
|
+
const exponentialDelay = baseDelay * Math.pow(2, attempt - 1);
|
|
23
|
+
return Math.floor(Math.random() * exponentialDelay);
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Calculate and wait for appropriate delay time before retry
|
|
29
|
+
*/
|
|
30
|
+
async calculateAndDelay(params) {
|
|
31
|
+
const { attempt, response, hook } = params;
|
|
32
|
+
const delayStrategy = hook.delayStrategy || this.defaultDelayStrategy;
|
|
33
|
+
const maxDelay = hook.maxDelay || this.defaultMaxDelay;
|
|
34
|
+
const calculatedDelay = delayStrategy.calculate(attempt, response);
|
|
35
|
+
const finalDelay = Math.min(calculatedDelay, maxDelay);
|
|
36
|
+
console.log(`🔄 Waiting for ${finalDelay / 1000} seconds before retrying.`);
|
|
37
|
+
await new Promise(resolve => setTimeout(resolve, finalDelay));
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Extract retry-after value from response
|
|
41
|
+
*/
|
|
42
|
+
getRetryAfterValue(response) {
|
|
43
|
+
var _a;
|
|
44
|
+
if (!((_a = response === null || response === void 0 ? void 0 : response.headers) === null || _a === void 0 ? void 0 : _a.get))
|
|
45
|
+
return null;
|
|
46
|
+
const retryAfter = response.headers.get('Retry-After');
|
|
47
|
+
if (!retryAfter)
|
|
48
|
+
return null;
|
|
49
|
+
// Handle numeric retry-after
|
|
50
|
+
const parsedDelay = parseInt(retryAfter, 10);
|
|
51
|
+
if (!isNaN(parsedDelay)) {
|
|
52
|
+
return parsedDelay * 1000;
|
|
53
|
+
}
|
|
54
|
+
// Handle date retry-after
|
|
55
|
+
const date = new Date(retryAfter).getTime();
|
|
56
|
+
const now = Date.now();
|
|
57
|
+
if (date > now) {
|
|
58
|
+
return date - now;
|
|
59
|
+
}
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Get the default maximum number of retries
|
|
64
|
+
*/
|
|
65
|
+
getDefaultMaxRetries() {
|
|
66
|
+
return this.defaultMaxRetries;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Set the default maximum number of retries
|
|
70
|
+
*/
|
|
71
|
+
setDefaultMaxRetries(maxRetries) {
|
|
72
|
+
this.defaultMaxRetries = maxRetries;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Set the default maximum delay between retries
|
|
76
|
+
*/
|
|
77
|
+
setDefaultMaxDelay(maxDelay) {
|
|
78
|
+
this.defaultMaxDelay = maxDelay;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
exports.RetryManager = RetryManager;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Barrel file exporting all ApiService components
|
|
3
|
+
*/
|
|
4
|
+
export { CacheManager } from './CacheManager';
|
|
5
|
+
export { RetryManager } from './RetryManager';
|
|
6
|
+
export { HookManager } from './HookManager';
|
|
7
|
+
export { HttpClient } from './HttpClient';
|
|
8
|
+
export { AccountManager } from './AccountManager';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Barrel file exporting all ApiService components
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.AccountManager = exports.HttpClient = exports.HookManager = exports.RetryManager = exports.CacheManager = void 0;
|
|
7
|
+
var CacheManager_1 = require("./CacheManager");
|
|
8
|
+
Object.defineProperty(exports, "CacheManager", { enumerable: true, get: function () { return CacheManager_1.CacheManager; } });
|
|
9
|
+
var RetryManager_1 = require("./RetryManager");
|
|
10
|
+
Object.defineProperty(exports, "RetryManager", { enumerable: true, get: function () { return RetryManager_1.RetryManager; } });
|
|
11
|
+
var HookManager_1 = require("./HookManager");
|
|
12
|
+
Object.defineProperty(exports, "HookManager", { enumerable: true, get: function () { return HookManager_1.HookManager; } });
|
|
13
|
+
var HttpClient_1 = require("./HttpClient");
|
|
14
|
+
Object.defineProperty(exports, "HttpClient", { enumerable: true, get: function () { return HttpClient_1.HttpClient; } });
|
|
15
|
+
var AccountManager_1 = require("./AccountManager");
|
|
16
|
+
Object.defineProperty(exports, "AccountManager", { enumerable: true, get: function () { return AccountManager_1.AccountManager; } });
|
package/dist/form.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function deserializeForm(src: any): FormData;
|
package/dist/form.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deserializeForm = void 0;
|
|
4
|
+
function deserializeForm(src) {
|
|
5
|
+
const fd = new FormData();
|
|
6
|
+
switch (src.cls) {
|
|
7
|
+
case 'FormData': {
|
|
8
|
+
for (const [key, items] of src.value) {
|
|
9
|
+
for (const item of items) {
|
|
10
|
+
let deserializedItem = deserializeForm(item);
|
|
11
|
+
if (deserializedItem instanceof FormData) {
|
|
12
|
+
// Use a workaround for TypeScript FormData entries() issue
|
|
13
|
+
const entries = deserializedItem;
|
|
14
|
+
for (const [subKey, subValue] of entries.entries()) {
|
|
15
|
+
fd.append(`${key}[${subKey}]`, subValue);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
fd.append(key, deserializedItem);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
case 'Blob':
|
|
26
|
+
case 'File': {
|
|
27
|
+
const { type, name, lastModified } = src;
|
|
28
|
+
const binStr = atob(src.value);
|
|
29
|
+
const arr = new Uint8Array(binStr.length);
|
|
30
|
+
for (let i = 0; i < binStr.length; i++)
|
|
31
|
+
arr[i] = binStr.charCodeAt(i);
|
|
32
|
+
const data = [arr.buffer];
|
|
33
|
+
const fileOrBlob = src.cls === 'File'
|
|
34
|
+
? new File(data, name, { type, lastModified })
|
|
35
|
+
: new Blob(data, { type });
|
|
36
|
+
fd.append('file', fileOrBlob);
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
case 'json': {
|
|
40
|
+
fd.append('json', JSON.stringify(JSON.parse(src.value)));
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
default:
|
|
44
|
+
throw new Error('Unsupported type for deserialization');
|
|
45
|
+
}
|
|
46
|
+
return fd;
|
|
47
|
+
}
|
|
48
|
+
exports.deserializeForm = deserializeForm;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { TokenService, ApiCallParams, HookSettings, StatusCode } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* ApiService - Core API service for making authenticated API calls
|
|
4
|
+
* with caching, retry, and hook support.
|
|
5
|
+
*/
|
|
6
|
+
declare class ApiService {
|
|
7
|
+
provider: string;
|
|
8
|
+
private tokenService;
|
|
9
|
+
private cacheManager;
|
|
10
|
+
private retryManager;
|
|
11
|
+
private hookManager;
|
|
12
|
+
private httpClient;
|
|
13
|
+
private accountManager;
|
|
14
|
+
private maxAttempts;
|
|
15
|
+
constructor();
|
|
16
|
+
/**
|
|
17
|
+
* Setup the API service
|
|
18
|
+
*/
|
|
19
|
+
setup({ provider, tokenService, hooks, cacheTime, }: {
|
|
20
|
+
provider: string;
|
|
21
|
+
tokenService: TokenService;
|
|
22
|
+
hooks?: Record<StatusCode, HookSettings>;
|
|
23
|
+
cacheTime: number;
|
|
24
|
+
}): void;
|
|
25
|
+
/**
|
|
26
|
+
* Set the maximum number of retry attempts
|
|
27
|
+
*/
|
|
28
|
+
setMaxAttempts(attempts: number): void;
|
|
29
|
+
/**
|
|
30
|
+
* Update account data
|
|
31
|
+
*/
|
|
32
|
+
updateAccountData(accountId: string, data: Partial<Record<string, any>>): void;
|
|
33
|
+
/**
|
|
34
|
+
* Main API call method
|
|
35
|
+
*/
|
|
36
|
+
makeApiCall(apiCallParams: ApiCallParams): Promise<any>;
|
|
37
|
+
/**
|
|
38
|
+
* Make a request with retry capability
|
|
39
|
+
*/
|
|
40
|
+
private makeRequestWithRetry;
|
|
41
|
+
/**
|
|
42
|
+
* Set the cache time in milliseconds
|
|
43
|
+
*/
|
|
44
|
+
setCacheTime(milliseconds: number): void;
|
|
45
|
+
/**
|
|
46
|
+
* Clear the cache
|
|
47
|
+
*/
|
|
48
|
+
clearCache(): void;
|
|
49
|
+
}
|
|
50
|
+
export default ApiService;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const components_1 = require("./components");
|
|
4
|
+
/**
|
|
5
|
+
* ApiService - Core API service for making authenticated API calls
|
|
6
|
+
* with caching, retry, and hook support.
|
|
7
|
+
*/
|
|
8
|
+
class ApiService {
|
|
9
|
+
constructor() {
|
|
10
|
+
// Default max attempts for API calls
|
|
11
|
+
this.maxAttempts = 10;
|
|
12
|
+
this.provider = '';
|
|
13
|
+
this.tokenService = {};
|
|
14
|
+
// Initialize component managers
|
|
15
|
+
this.cacheManager = new components_1.CacheManager();
|
|
16
|
+
this.retryManager = new components_1.RetryManager();
|
|
17
|
+
this.hookManager = new components_1.HookManager();
|
|
18
|
+
this.httpClient = new components_1.HttpClient();
|
|
19
|
+
this.accountManager = new components_1.AccountManager();
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Setup the API service
|
|
23
|
+
*/
|
|
24
|
+
setup({ provider, tokenService, hooks, cacheTime, }) {
|
|
25
|
+
this.provider = provider;
|
|
26
|
+
this.tokenService = tokenService;
|
|
27
|
+
if (hooks) {
|
|
28
|
+
this.hookManager.setHooks(hooks);
|
|
29
|
+
}
|
|
30
|
+
if (typeof cacheTime !== 'undefined') {
|
|
31
|
+
this.cacheManager.setCacheTime(cacheTime);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Set the maximum number of retry attempts
|
|
36
|
+
*/
|
|
37
|
+
setMaxAttempts(attempts) {
|
|
38
|
+
this.maxAttempts = attempts;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Update account data
|
|
42
|
+
*/
|
|
43
|
+
updateAccountData(accountId, data) {
|
|
44
|
+
this.accountManager.updateAccountData(accountId, data);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Main API call method
|
|
48
|
+
*/
|
|
49
|
+
async makeApiCall(apiCallParams) {
|
|
50
|
+
console.log('🔄 makeApiCall', this.provider, apiCallParams.accountId);
|
|
51
|
+
// Check cache first
|
|
52
|
+
const cachedData = this.cacheManager.getFromCache(apiCallParams);
|
|
53
|
+
if (cachedData)
|
|
54
|
+
return cachedData;
|
|
55
|
+
// Make the API call with retry capability
|
|
56
|
+
const result = await this.makeRequestWithRetry(apiCallParams);
|
|
57
|
+
// Cache the result
|
|
58
|
+
this.cacheManager.saveToCache(apiCallParams, result);
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Make a request with retry capability
|
|
63
|
+
*/
|
|
64
|
+
async makeRequestWithRetry(apiCallParams) {
|
|
65
|
+
var _a;
|
|
66
|
+
const { accountId } = apiCallParams;
|
|
67
|
+
let attempts = 0;
|
|
68
|
+
const statusRetries = {};
|
|
69
|
+
// Copy the params to avoid mutation issues
|
|
70
|
+
let currentParams = { ...apiCallParams };
|
|
71
|
+
// Main retry loop
|
|
72
|
+
while (attempts < this.maxAttempts) {
|
|
73
|
+
attempts++;
|
|
74
|
+
try {
|
|
75
|
+
// Get authentication token if needed
|
|
76
|
+
const authToken = apiCallParams.requireAuth !== false
|
|
77
|
+
? await this.tokenService.get(accountId)
|
|
78
|
+
: {};
|
|
79
|
+
// Verify we have authentication if required
|
|
80
|
+
if (apiCallParams.requireAuth !== false && !apiCallParams.accessToken && !authToken.access_token) {
|
|
81
|
+
throw new Error(`${this.provider} credentials not found for account ID ${accountId}`);
|
|
82
|
+
}
|
|
83
|
+
// Make the actual API call
|
|
84
|
+
const response = await this.httpClient.makeRequest(currentParams, authToken);
|
|
85
|
+
// Success - update account status and return result
|
|
86
|
+
this.accountManager.setLastRequestFailed(accountId, false);
|
|
87
|
+
return response;
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
const status = error === null || error === void 0 ? void 0 : error.status;
|
|
91
|
+
// If no hook exists for this error, or we shouldn't retry, throw
|
|
92
|
+
if (!this.hookManager.shouldRetry(status)) {
|
|
93
|
+
throw error;
|
|
94
|
+
}
|
|
95
|
+
// Track retries for this status code
|
|
96
|
+
statusRetries[status] = (statusRetries[status] || 0) + 1;
|
|
97
|
+
const activeHook = this.hookManager.getHook(status);
|
|
98
|
+
const maxRetries = (_a = activeHook === null || activeHook === void 0 ? void 0 : activeHook.maxRetries) !== null && _a !== void 0 ? _a : this.retryManager.getDefaultMaxRetries();
|
|
99
|
+
// Check if we've exceeded retries for this status
|
|
100
|
+
if (statusRetries[status] > maxRetries) {
|
|
101
|
+
await this.hookManager.handleRetryFailure(accountId, status, error);
|
|
102
|
+
this.accountManager.setLastRequestFailed(accountId, true);
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
105
|
+
// Process the hook to get updated params
|
|
106
|
+
try {
|
|
107
|
+
const hookResult = await this.hookManager.processHook(accountId, status, error);
|
|
108
|
+
if (hookResult) {
|
|
109
|
+
currentParams = { ...currentParams, ...hookResult };
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
catch (hookError) {
|
|
113
|
+
this.accountManager.setLastRequestFailed(accountId, true);
|
|
114
|
+
throw hookError;
|
|
115
|
+
}
|
|
116
|
+
// Wait before retrying if needed
|
|
117
|
+
if (activeHook === null || activeHook === void 0 ? void 0 : activeHook.retryDelay) {
|
|
118
|
+
await this.retryManager.calculateAndDelay({
|
|
119
|
+
attempt: statusRetries[status],
|
|
120
|
+
response: error.response,
|
|
121
|
+
hook: activeHook,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// If we've reached here, we've exceeded our maximum attempts
|
|
127
|
+
this.accountManager.setLastRequestFailed(accountId, true);
|
|
128
|
+
throw new Error(`Exceeded maximum attempts (${this.maxAttempts}) for API call to ${accountId}`);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Set the cache time in milliseconds
|
|
132
|
+
*/
|
|
133
|
+
setCacheTime(milliseconds) {
|
|
134
|
+
this.cacheManager.setCacheTime(milliseconds);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Clear the cache
|
|
138
|
+
*/
|
|
139
|
+
clearCache() {
|
|
140
|
+
this.cacheManager.clearCache();
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
exports.default = ApiService;
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
interface OAuthToken {
|
|
2
|
+
access_token: string;
|
|
3
|
+
expires_in: number;
|
|
4
|
+
id_token: string;
|
|
5
|
+
refresh_token: string;
|
|
6
|
+
scope: string;
|
|
7
|
+
token_type: string;
|
|
8
|
+
}
|
|
9
|
+
interface Token {
|
|
10
|
+
accountId: string;
|
|
11
|
+
access_token: string;
|
|
12
|
+
refresh_token: string;
|
|
13
|
+
provider: string;
|
|
14
|
+
enabled?: boolean;
|
|
15
|
+
updatedAt?: string;
|
|
16
|
+
primary?: boolean;
|
|
17
|
+
}
|
|
18
|
+
interface AccountData {
|
|
19
|
+
lastRequestTime?: number;
|
|
20
|
+
lastFailed?: boolean;
|
|
21
|
+
token?: Token;
|
|
22
|
+
}
|
|
23
|
+
interface DelayStrategy {
|
|
24
|
+
calculate: (attempt: number, response?: any) => number;
|
|
25
|
+
}
|
|
26
|
+
interface ApiCallParams {
|
|
27
|
+
accountId: string;
|
|
28
|
+
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|
29
|
+
route: string;
|
|
30
|
+
base: string;
|
|
31
|
+
body?: object;
|
|
32
|
+
data?: object;
|
|
33
|
+
headers?: Record<string, string>;
|
|
34
|
+
queryParams?: URLSearchParams;
|
|
35
|
+
accessToken?: string;
|
|
36
|
+
requireAuth?: boolean;
|
|
37
|
+
noContentType?: boolean;
|
|
38
|
+
contentType?: string;
|
|
39
|
+
cacheTime?: number;
|
|
40
|
+
files?: File[];
|
|
41
|
+
}
|
|
42
|
+
interface HookSettings {
|
|
43
|
+
retryCall: boolean;
|
|
44
|
+
retryDelay: boolean;
|
|
45
|
+
waitUntilFinished?: boolean;
|
|
46
|
+
maxRetries?: number;
|
|
47
|
+
callback: (accountId: string, response: any) => Promise<any>;
|
|
48
|
+
onRetryFail?: (accountId: string, error: any) => Promise<void>;
|
|
49
|
+
errorCallback?: (accountId: string, error: any) => Promise<void>;
|
|
50
|
+
delayStrategy?: DelayStrategy;
|
|
51
|
+
maxDelay?: number;
|
|
52
|
+
}
|
|
53
|
+
type StatusCode = string | number;
|
|
54
|
+
type TokenService = {
|
|
55
|
+
get: (accountId: string) => Promise<Token>;
|
|
56
|
+
set: (accountId: string, token: Partial<Token>) => Promise<void>;
|
|
57
|
+
refresh?: (accountId: string, refreshToken: string) => Promise<OAuthToken>;
|
|
58
|
+
};
|
|
59
|
+
export { OAuthToken, DelayStrategy, Token, AccountData, ApiCallParams, HookSettings, StatusCode, TokenService, };
|
package/dist/types.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rendomnet/apiservice",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A robust TypeScript API service framework for making authenticated API calls",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"clean": "rimraf dist",
|
|
13
|
+
"prebuild": "npm run clean",
|
|
14
|
+
"prepublishOnly": "npm run build",
|
|
15
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
16
|
+
"prepare": "npm run build"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"api",
|
|
20
|
+
"service",
|
|
21
|
+
"typescript",
|
|
22
|
+
"fetch",
|
|
23
|
+
"retry",
|
|
24
|
+
"cache",
|
|
25
|
+
"hooks"
|
|
26
|
+
],
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "git+https://github.com/rendomnet/apiservice.git"
|
|
30
|
+
},
|
|
31
|
+
"author": "",
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/rendomnet/apiservice/issues"
|
|
35
|
+
},
|
|
36
|
+
"homepage": "https://github.com/rendomnet/apiservice#readme",
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"qs": "^6.11.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/node": "^18.0.0",
|
|
42
|
+
"@types/qs": "^6.9.7",
|
|
43
|
+
"rimraf": "^3.0.2",
|
|
44
|
+
"typescript": "^4.7.4"
|
|
45
|
+
},
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
}
|
|
49
|
+
}
|