@flexbe/sdk 0.2.28 → 0.2.30

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.
@@ -7,12 +7,32 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { NotFoundException, ForbiddenException, BadRequestException, UnauthorizedException, ServerException, TimeoutException } from '../types';
11
- import { FlexbeAuth } from './auth';
10
+ import { NotFoundException, ForbiddenException, BadRequestException, UnauthorizedException, ServerException, TimeoutException, FlexbeAuthType } from '../types';
11
+ import { TokenManager } from './token-manager';
12
12
  export class ApiClient {
13
13
  constructor(config) {
14
14
  this.config = config;
15
- this.auth = new FlexbeAuth(config);
15
+ this.tokenManager = TokenManager.getInstance();
16
+ if (this.config.authType === FlexbeAuthType.BEARER) {
17
+ // Start initialization but don't wait for it
18
+ void this.tokenManager.getToken(); // just warm up the token manager before any request
19
+ }
20
+ }
21
+ getAuthHeaders() {
22
+ return __awaiter(this, void 0, void 0, function* () {
23
+ const headers = {};
24
+ if (this.config.authType === FlexbeAuthType.API_KEY) {
25
+ headers['x-api-key'] = this.config.apiKey;
26
+ }
27
+ else if (this.config.authType === FlexbeAuthType.BEARER) {
28
+ const token = yield this.tokenManager.getToken();
29
+ if (!token) {
30
+ throw new Error('No valid bearer token available');
31
+ }
32
+ headers['Authorization'] = `Bearer ${token}`;
33
+ }
34
+ return headers;
35
+ });
16
36
  }
17
37
  buildUrl(path, params) {
18
38
  const searchParams = new URLSearchParams();
@@ -27,12 +47,12 @@ export class ApiClient {
27
47
  }
28
48
  request(config) {
29
49
  return __awaiter(this, void 0, void 0, function* () {
50
+ var _a, _b;
30
51
  try {
31
- yield this.auth.ensureInitialized();
32
52
  const controller = new AbortController();
33
53
  const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
34
54
  const url = this.buildUrl(config.url, config.params);
35
- const headers = Object.assign(Object.assign({}, (yield this.auth.getAuthHeaders())), config.headers);
55
+ const headers = Object.assign(Object.assign({ 'Content-Type': 'application/json' }, (yield this.getAuthHeaders())), config.headers);
36
56
  const response = yield fetch(this.config.baseUrl + url, Object.assign(Object.assign({}, config), { headers, signal: controller.signal }));
37
57
  clearTimeout(timeoutId);
38
58
  if (!response.ok) {
@@ -44,23 +64,24 @@ export class ApiClient {
44
64
  const errorData = yield response.json().catch(() => defaultError);
45
65
  switch (errorData.statusCode) {
46
66
  case 400:
47
- throw new BadRequestException(errorData.message);
67
+ throw new BadRequestException(errorData.message, errorData.error, errorData.errors);
48
68
  case 401:
49
- throw new UnauthorizedException(errorData.message);
69
+ throw new UnauthorizedException(errorData.message, errorData.error, errorData.errors);
50
70
  case 403:
51
- throw new ForbiddenException(errorData.message);
71
+ throw new ForbiddenException(errorData.message, errorData.error, errorData.errors);
52
72
  case 404:
53
- throw new NotFoundException(errorData.message);
73
+ throw new NotFoundException(errorData.message, errorData.error, errorData.errors);
54
74
  case 500:
55
75
  case 502:
56
76
  case 503:
57
77
  case 504:
58
- throw new ServerException(errorData.message, errorData.statusCode);
78
+ throw new ServerException(errorData.message, errorData.error, errorData.statusCode, errorData.errors);
59
79
  default:
60
80
  throw {
61
81
  message: errorData.message,
62
82
  error: errorData.error,
63
- statusCode: errorData.statusCode
83
+ statusCode: errorData.statusCode,
84
+ errors: errorData.errors
64
85
  };
65
86
  }
66
87
  }
@@ -80,6 +101,9 @@ export class ApiClient {
80
101
  };
81
102
  }
82
103
  catch (error) {
104
+ if (error instanceof UnauthorizedException) {
105
+ (_b = (_a = this.config.hooks) === null || _a === void 0 ? void 0 : _a.onUnauthorized) === null || _b === void 0 ? void 0 : _b.call(_a);
106
+ }
83
107
  if (error instanceof Error && error.name === 'AbortError') {
84
108
  throw new TimeoutException('Request timeout');
85
109
  }
@@ -21,12 +21,13 @@ export class FlexbeClient {
21
21
  }
22
22
  return undefined;
23
23
  };
24
- this.config = {
25
- baseUrl: (config === null || config === void 0 ? void 0 : config.baseUrl) || getEnvVar('FLEXBE_API_URL') || 'https://api.flexbe.com',
26
- timeout: (config === null || config === void 0 ? void 0 : config.timeout) || 30000,
27
- apiKey: (config === null || config === void 0 ? void 0 : config.apiKey) || getEnvVar('FLEXBE_API_KEY') || '',
28
- authType: (config === null || config === void 0 ? void 0 : config.authType) || FlexbeAuthType.API_KEY,
24
+ const defaultConfig = {
25
+ baseUrl: getEnvVar('FLEXBE_API_URL') || 'https://api.flexbe.com',
26
+ timeout: 30000,
27
+ apiKey: getEnvVar('FLEXBE_API_KEY') || '',
28
+ authType: FlexbeAuthType.API_KEY,
29
29
  };
30
+ this.config = Object.assign(Object.assign({}, defaultConfig), config);
30
31
  if (this.config.authType === 'apiKey' && !this.config.apiKey) {
31
32
  throw new Error('API key is required when using apiKey authentication. Please provide it either through config or FLEXBE_API_KEY environment variable.');
32
33
  }
@@ -7,19 +7,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
+ import { UnauthorizedException } from '../types';
10
11
  const TOKEN_STORAGE_KEY = 'flexbe_jwt_token';
11
- const REFRESH_THRESHOLD = 0.8; // Refresh when 80% of token lifetime has passed
12
- const REFRESH_CHECK_INTERVAL = 30 * 1000; // Check every 30 seconds
13
- const MAX_REFRESH_DELAY = 10000; // Maximum random delay of 10 seconds
12
+ const TOKEN_REFRESH_THRESHOLD = 5 * 60 * 1000; // update token 5 minutes before expiration
14
13
  export class TokenManager {
15
14
  constructor() {
16
- this.token = null;
17
- this.refreshInterval = null;
18
- this.refreshTimeout = null;
19
15
  this.tokenPromise = null;
20
- this.debug = false;
21
- this.initializeFromStorage();
22
- this.setupStorageListener();
23
16
  }
24
17
  static getInstance() {
25
18
  if (!TokenManager.instance) {
@@ -27,85 +20,65 @@ export class TokenManager {
27
20
  }
28
21
  return TokenManager.instance;
29
22
  }
30
- initializeFromStorage() {
31
- if (typeof window === 'undefined')
32
- return;
33
- const storedToken = localStorage.getItem(TOKEN_STORAGE_KEY);
34
- if (!storedToken)
35
- return;
36
- try {
37
- this.token = JSON.parse(storedToken);
38
- if (this.token.expiresAt > Date.now()) {
39
- this.logTokenStatus('Token loaded from storage');
40
- this.startRefreshInterval();
41
- }
42
- else {
43
- this.clearToken();
23
+ getToken() {
24
+ return __awaiter(this, void 0, void 0, function* () {
25
+ var _a;
26
+ const token = this.getStoredToken();
27
+ if (token && token.expiresAt > Date.now()) {
28
+ // TODO check if token expire less that 1 minute
29
+ // if so, retrieve a new token
30
+ if (token.expiresAt - Date.now() < TOKEN_REFRESH_THRESHOLD) {
31
+ void this.retrieveToken();
32
+ }
33
+ return token.accessToken;
44
34
  }
45
- }
46
- catch (error) {
47
- console.error('Failed to parse stored token:', error);
48
- this.clearToken();
49
- }
35
+ yield this.retrieveToken();
36
+ const retrievedToken = this.getStoredToken();
37
+ return (_a = retrievedToken === null || retrievedToken === void 0 ? void 0 : retrievedToken.accessToken) !== null && _a !== void 0 ? _a : null;
38
+ });
50
39
  }
51
- setupStorageListener() {
52
- if (typeof window === 'undefined')
53
- return;
54
- window.addEventListener('storage', (event) => {
55
- if (event.key !== TOKEN_STORAGE_KEY)
56
- return;
57
- if (!event.newValue) {
58
- this.clearToken();
59
- // void this.retrieveToken();
40
+ revokeToken() {
41
+ return __awaiter(this, void 0, void 0, function* () {
42
+ const token = this.getStoredToken();
43
+ this.clearToken();
44
+ if (!token)
60
45
  return;
61
- }
62
46
  try {
63
- const newToken = JSON.parse(event.newValue);
64
- // Skip if the new token is exactly the same as current token
65
- if (this.token &&
66
- this.token.accessToken === newToken.accessToken &&
67
- this.token.expiresAt === newToken.expiresAt) {
68
- return;
69
- }
70
- if (newToken.expiresAt > Date.now()) {
71
- this.token = newToken;
72
- this.logTokenStatus('Token updated from storage');
73
- this.startRefreshInterval();
74
- }
75
- else {
76
- this.clearToken();
77
- void this.retrieveToken();
78
- }
47
+ const controller = new AbortController();
48
+ const timeoutId = setTimeout(() => controller.abort(), 30000);
49
+ yield fetch('/oauth/revoke', {
50
+ method: 'POST',
51
+ headers: {
52
+ 'Content-Type': 'application/json',
53
+ 'Authorization': `Bearer ${token.accessToken}`
54
+ },
55
+ body: JSON.stringify({ token: token.accessToken }),
56
+ credentials: 'include',
57
+ signal: controller.signal,
58
+ });
59
+ clearTimeout(timeoutId);
79
60
  }
80
61
  catch (error) {
81
- console.error('Failed to parse token from storage event:', error);
82
- this.clearToken();
83
- void this.retrieveToken();
62
+ console.error('Failed to revoke token:', error);
84
63
  }
85
64
  });
86
65
  }
87
- getExpirationFromToken(token) {
66
+ getStoredToken() {
67
+ if (typeof window === 'undefined')
68
+ return null;
69
+ const storedToken = localStorage.getItem(TOKEN_STORAGE_KEY);
70
+ if (!storedToken) {
71
+ return null;
72
+ }
88
73
  try {
89
- const [, payload] = token.split('.');
90
- const decodedPayload = JSON.parse(atob(payload));
91
- return decodedPayload.exp * 1000; // Convert to milliseconds
74
+ const token = JSON.parse(storedToken);
75
+ return token;
92
76
  }
93
77
  catch (error) {
94
- console.error('Failed to parse token expiration:', error);
95
- return Date.now() + (4 * 60 * 1000); // Default to 4 minutes if parsing fails
78
+ console.error('getStoredToken: Failed to parse stored token:', error);
79
+ return null;
96
80
  }
97
81
  }
98
- getToken() {
99
- return __awaiter(this, void 0, void 0, function* () {
100
- var _a, _b;
101
- const token = this.token;
102
- if (token && token.expiresAt && token.expiresAt > Date.now()) {
103
- return token.accessToken;
104
- }
105
- yield this.retrieveToken();
106
- return (_b = (_a = this.token) === null || _a === void 0 ? void 0 : _a.accessToken) !== null && _b !== void 0 ? _b : null;
107
- });
108
- }
109
82
  retrieveToken() {
110
83
  return __awaiter(this, void 0, void 0, function* () {
111
84
  if (this.tokenPromise) {
@@ -136,130 +109,44 @@ export class TokenManager {
136
109
  clearTimeout(timeoutId);
137
110
  if (!response.ok) {
138
111
  const errorData = yield response.json().catch(() => ({ message: response.statusText }));
112
+ if (response.status === 401) {
113
+ throw new UnauthorizedException(errorData.message || response.statusText);
114
+ }
139
115
  throw new Error(errorData.message || response.statusText);
140
116
  }
141
117
  const data = yield response.json();
142
118
  this.setToken(data);
143
119
  }
144
120
  catch (error) {
145
- console.error('Failed to retrieve token:', error);
146
- this.clearToken();
147
- // Schedule a retry after REFRESH_CHECK_INTERVAL
148
- setTimeout(() => {
149
- void this.retrieveToken();
150
- }, REFRESH_CHECK_INTERVAL);
151
121
  throw error;
152
122
  }
153
123
  });
154
124
  }
155
- startRefreshInterval() {
156
- this.clearRefreshTimers();
157
- if (!this.token)
158
- return;
159
- const tokenLifetime = this.token.expiresAt - Date.now();
160
- const refreshThreshold = Math.round(tokenLifetime * REFRESH_THRESHOLD);
161
- const timeUntilRefresh = refreshThreshold - (Math.random() * MAX_REFRESH_DELAY);
162
- this.logTokenStatus('Starting refresh interval', {
163
- tokenLifetime: `${Math.round(tokenLifetime / 1000)} seconds`,
164
- refreshThreshold: `${Math.round(refreshThreshold / 1000)} seconds`,
165
- timeUntilRefresh: `${Math.round(timeUntilRefresh / 1000)} seconds`,
166
- });
167
- this.scheduleRefresh(timeUntilRefresh);
168
- this.refreshInterval = window.setInterval(() => {
169
- if (!this.token)
170
- return;
171
- const timeUntilExpiry = this.token.expiresAt - Date.now();
172
- if (timeUntilExpiry <= 0) {
173
- this.logTokenStatus('Token expired');
174
- this.clearToken();
175
- void this.retrieveToken();
176
- return;
177
- }
178
- const refreshThreshold = Math.round(timeUntilExpiry * REFRESH_THRESHOLD);
179
- if (timeUntilExpiry <= refreshThreshold) {
180
- this.logTokenStatus('Refreshing token', {
181
- timeUntilExpiry: `${Math.round(timeUntilExpiry / 1000)} seconds`,
182
- refreshThreshold: `${Math.round(refreshThreshold / 1000)} seconds`,
183
- });
184
- this.scheduleRefresh(refreshThreshold - (Math.random() * MAX_REFRESH_DELAY));
185
- }
186
- }, REFRESH_CHECK_INTERVAL);
187
- }
188
- scheduleRefresh(delay) {
189
- if (this.refreshTimeout) {
190
- window.clearTimeout(this.refreshTimeout);
191
- }
192
- this.refreshTimeout = window.setTimeout(() => {
193
- const token = this.token;
194
- if (token && token.expiresAt - Date.now() <= token.expiresAt * REFRESH_THRESHOLD) {
195
- void this.retrieveToken();
196
- }
197
- }, delay);
198
- }
199
- clearRefreshTimers() {
200
- if (this.refreshInterval) {
201
- clearInterval(this.refreshInterval);
202
- this.refreshInterval = null;
203
- }
204
- if (this.refreshTimeout) {
205
- window.clearTimeout(this.refreshTimeout);
206
- this.refreshTimeout = null;
207
- }
208
- }
209
- logTokenStatus(message, additionalInfo = {}) {
210
- if (!this.debug)
211
- return;
212
- const token = this.token;
213
- if (!token)
214
- return;
215
- console.log(message, Object.assign({ expiresIn: `${Math.round((token.expiresAt - Date.now()) / 1000)} seconds`, expiresAt: new Date(token.expiresAt).toISOString() }, additionalInfo));
216
- }
217
125
  setToken(tokenResponse) {
218
126
  const expiresAt = this.getExpirationFromToken(tokenResponse.accessToken);
219
- this.token = {
127
+ const token = {
220
128
  accessToken: tokenResponse.accessToken,
221
129
  expiresAt,
222
130
  };
223
- this.logTokenStatus('Token set', {
224
- expiresAt: new Date(expiresAt).toISOString(),
225
- });
226
131
  if (typeof window !== 'undefined') {
227
- localStorage.setItem(TOKEN_STORAGE_KEY, JSON.stringify(this.token));
132
+ localStorage.setItem(TOKEN_STORAGE_KEY, JSON.stringify(token));
228
133
  }
229
- this.startRefreshInterval();
230
134
  }
231
- clearToken() {
232
- this.token = null;
233
- this.clearRefreshTimers();
234
- if (typeof window !== 'undefined') {
235
- localStorage.removeItem(TOKEN_STORAGE_KEY);
135
+ getExpirationFromToken(token) {
136
+ try {
137
+ const [, payload] = token.split('.');
138
+ const decodedPayload = JSON.parse(atob(payload));
139
+ return decodedPayload.exp * 1000; // Convert to milliseconds
140
+ }
141
+ catch (error) {
142
+ console.error('getExpirationFromToken: Failed to parse token expiration:', error);
143
+ return Date.now() + (4 * 60 * 1000); // Default to 4 minutes if parsing fails
236
144
  }
237
145
  }
238
- revokeToken() {
239
- return __awaiter(this, void 0, void 0, function* () {
240
- const token = this.token;
241
- this.clearToken();
242
- if (!token)
243
- return;
244
- try {
245
- const controller = new AbortController();
246
- const timeoutId = setTimeout(() => controller.abort(), 30000);
247
- yield fetch('/oauth/revoke', {
248
- method: 'POST',
249
- headers: {
250
- 'Content-Type': 'application/json',
251
- 'Authorization': `Bearer ${token.accessToken}`
252
- },
253
- body: JSON.stringify({ token: token.accessToken }),
254
- credentials: 'include',
255
- signal: controller.signal,
256
- });
257
- clearTimeout(timeoutId);
258
- }
259
- catch (error) {
260
- console.error('Failed to revoke token:', error);
261
- // Even if revocation fails, we still want to clear the local token
262
- }
263
- });
146
+ clearToken() {
147
+ if (typeof window === 'undefined') {
148
+ return;
149
+ }
150
+ localStorage.removeItem(TOKEN_STORAGE_KEY);
264
151
  }
265
152
  }
@@ -4,44 +4,56 @@ export var FlexbeAuthType;
4
4
  FlexbeAuthType["BEARER"] = "bearer";
5
5
  })(FlexbeAuthType || (FlexbeAuthType = {}));
6
6
  export class NotFoundException extends Error {
7
- constructor(message) {
7
+ constructor(message, error, errors) {
8
8
  super(Array.isArray(message) ? message.join(', ') : message);
9
9
  this.statusCode = 404;
10
10
  this.name = 'NotFoundException';
11
+ this.error = error || 'not_found';
12
+ this.errors = errors;
11
13
  }
12
14
  }
13
15
  export class ForbiddenException extends Error {
14
- constructor(message) {
16
+ constructor(message, error, errors) {
15
17
  super(Array.isArray(message) ? message.join(', ') : message);
16
18
  this.statusCode = 403;
17
19
  this.name = 'ForbiddenException';
20
+ this.error = error || 'forbidden';
21
+ this.errors = errors;
18
22
  }
19
23
  }
20
24
  export class BadRequestException extends Error {
21
- constructor(message) {
25
+ constructor(message, error, errors) {
22
26
  super(Array.isArray(message) ? message.join(', ') : message);
23
27
  this.statusCode = 400;
24
28
  this.name = 'BadRequestException';
29
+ this.error = error || 'bad_request';
30
+ this.errors = errors;
25
31
  }
26
32
  }
27
33
  export class UnauthorizedException extends Error {
28
- constructor(message) {
34
+ constructor(message, error, errors) {
29
35
  super(Array.isArray(message) ? message.join(', ') : message);
30
36
  this.statusCode = 401;
31
37
  this.name = 'UnauthorizedException';
38
+ this.error = error || 'unauthorized';
39
+ this.errors = errors;
32
40
  }
33
41
  }
34
42
  export class ServerException extends Error {
35
- constructor(message, statusCode = 500) {
43
+ constructor(message, error, statusCode = 500, errors) {
36
44
  super(Array.isArray(message) ? message.join(', ') : message);
37
45
  this.name = 'ServerException';
46
+ this.error = error || 'server_error';
38
47
  this.statusCode = statusCode;
48
+ this.errors = errors;
39
49
  }
40
50
  }
41
51
  export class TimeoutException extends Error {
42
- constructor(message) {
52
+ constructor(message, error, errors) {
43
53
  super(Array.isArray(message) ? message.join(', ') : message);
44
54
  this.statusCode = 408;
45
55
  this.name = 'TimeoutException';
56
+ this.error = error || 'timeout';
57
+ this.errors = errors;
46
58
  }
47
59
  }
@@ -2,11 +2,29 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ApiClient = void 0;
4
4
  const types_1 = require("../types");
5
- const auth_1 = require("./auth");
5
+ const token_manager_1 = require("./token-manager");
6
6
  class ApiClient {
7
7
  constructor(config) {
8
8
  this.config = config;
9
- this.auth = new auth_1.FlexbeAuth(config);
9
+ this.tokenManager = token_manager_1.TokenManager.getInstance();
10
+ if (this.config.authType === types_1.FlexbeAuthType.BEARER) {
11
+ // Start initialization but don't wait for it
12
+ void this.tokenManager.getToken(); // just warm up the token manager before any request
13
+ }
14
+ }
15
+ async getAuthHeaders() {
16
+ const headers = {};
17
+ if (this.config.authType === types_1.FlexbeAuthType.API_KEY) {
18
+ headers['x-api-key'] = this.config.apiKey;
19
+ }
20
+ else if (this.config.authType === types_1.FlexbeAuthType.BEARER) {
21
+ const token = await this.tokenManager.getToken();
22
+ if (!token) {
23
+ throw new Error('No valid bearer token available');
24
+ }
25
+ headers['Authorization'] = `Bearer ${token}`;
26
+ }
27
+ return headers;
10
28
  }
11
29
  buildUrl(path, params) {
12
30
  const searchParams = new URLSearchParams();
@@ -21,12 +39,12 @@ class ApiClient {
21
39
  }
22
40
  async request(config) {
23
41
  try {
24
- await this.auth.ensureInitialized();
25
42
  const controller = new AbortController();
26
43
  const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
27
44
  const url = this.buildUrl(config.url, config.params);
28
45
  const headers = {
29
- ...(await this.auth.getAuthHeaders()),
46
+ 'Content-Type': 'application/json',
47
+ ...(await this.getAuthHeaders()),
30
48
  ...config.headers,
31
49
  };
32
50
  const response = await fetch(this.config.baseUrl + url, {
@@ -44,23 +62,24 @@ class ApiClient {
44
62
  const errorData = await response.json().catch(() => defaultError);
45
63
  switch (errorData.statusCode) {
46
64
  case 400:
47
- throw new types_1.BadRequestException(errorData.message);
65
+ throw new types_1.BadRequestException(errorData.message, errorData.error, errorData.errors);
48
66
  case 401:
49
- throw new types_1.UnauthorizedException(errorData.message);
67
+ throw new types_1.UnauthorizedException(errorData.message, errorData.error, errorData.errors);
50
68
  case 403:
51
- throw new types_1.ForbiddenException(errorData.message);
69
+ throw new types_1.ForbiddenException(errorData.message, errorData.error, errorData.errors);
52
70
  case 404:
53
- throw new types_1.NotFoundException(errorData.message);
71
+ throw new types_1.NotFoundException(errorData.message, errorData.error, errorData.errors);
54
72
  case 500:
55
73
  case 502:
56
74
  case 503:
57
75
  case 504:
58
- throw new types_1.ServerException(errorData.message, errorData.statusCode);
76
+ throw new types_1.ServerException(errorData.message, errorData.error, errorData.statusCode, errorData.errors);
59
77
  default:
60
78
  throw {
61
79
  message: errorData.message,
62
80
  error: errorData.error,
63
- statusCode: errorData.statusCode
81
+ statusCode: errorData.statusCode,
82
+ errors: errorData.errors
64
83
  };
65
84
  }
66
85
  }
@@ -80,6 +99,9 @@ class ApiClient {
80
99
  };
81
100
  }
82
101
  catch (error) {
102
+ if (error instanceof types_1.UnauthorizedException) {
103
+ this.config.hooks?.onUnauthorized?.();
104
+ }
83
105
  if (error instanceof Error && error.name === 'AbortError') {
84
106
  throw new types_1.TimeoutException('Request timeout');
85
107
  }
@@ -15,11 +15,15 @@ class FlexbeClient {
15
15
  }
16
16
  return undefined;
17
17
  };
18
+ const defaultConfig = {
19
+ baseUrl: getEnvVar('FLEXBE_API_URL') || 'https://api.flexbe.com',
20
+ timeout: 30000,
21
+ apiKey: getEnvVar('FLEXBE_API_KEY') || '',
22
+ authType: types_1.FlexbeAuthType.API_KEY,
23
+ };
18
24
  this.config = {
19
- baseUrl: config?.baseUrl || getEnvVar('FLEXBE_API_URL') || 'https://api.flexbe.com',
20
- timeout: config?.timeout || 30000,
21
- apiKey: config?.apiKey || getEnvVar('FLEXBE_API_KEY') || '',
22
- authType: config?.authType || types_1.FlexbeAuthType.API_KEY,
25
+ ...defaultConfig,
26
+ ...config,
23
27
  };
24
28
  if (this.config.authType === 'apiKey' && !this.config.apiKey) {
25
29
  throw new Error('API key is required when using apiKey authentication. Please provide it either through config or FLEXBE_API_KEY environment variable.');