@flexbe/sdk 0.1.2 → 0.1.4
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/dist/browser/client/api-client.js +4 -4
- package/dist/browser/client/auth.js +24 -68
- package/dist/browser/client/client.js +2 -1
- package/dist/browser/client/pages.js +18 -0
- package/dist/browser/client/token-manager.js +179 -73
- package/dist/browser/types/index.js +5 -1
- package/dist/cjs/client/api-client.js +4 -4
- package/dist/cjs/client/auth.js +24 -68
- package/dist/cjs/client/client.js +2 -1
- package/dist/cjs/client/pages.js +14 -0
- package/dist/cjs/client/token-manager.js +167 -73
- package/dist/cjs/types/index.js +6 -0
- package/dist/esm/client/api-client.js +4 -4
- package/dist/esm/client/auth.js +24 -68
- package/dist/esm/client/client.js +2 -1
- package/dist/esm/client/pages.js +14 -0
- package/dist/esm/client/token-manager.js +167 -73
- package/dist/esm/types/index.js +5 -1
- package/dist/types/client/api-client.d.ts +4 -4
- package/dist/types/client/auth.d.ts +2 -3
- package/dist/types/client/pages.d.ts +9 -1
- package/dist/types/client/token-manager.d.ts +9 -1
- package/dist/types/types/index.d.ts +9 -1
- package/dist/types/types/pages.d.ts +12 -7
- package/package.json +1 -1
|
@@ -72,15 +72,15 @@ export class ApiClient {
|
|
|
72
72
|
});
|
|
73
73
|
}
|
|
74
74
|
get(url, config) {
|
|
75
|
-
return this.request(Object.assign(Object.assign({}, config), { method: 'GET'
|
|
75
|
+
return this.request(Object.assign(Object.assign({}, config), { url, method: 'GET' }));
|
|
76
76
|
}
|
|
77
77
|
post(url, data, config) {
|
|
78
|
-
return this.request(Object.assign(Object.assign({}, config), { method: 'POST',
|
|
78
|
+
return this.request(Object.assign(Object.assign({}, config), { url, method: 'POST', body: JSON.stringify(data) }));
|
|
79
79
|
}
|
|
80
80
|
put(url, data, config) {
|
|
81
|
-
return this.request(Object.assign(Object.assign({}, config), { method: 'PUT',
|
|
81
|
+
return this.request(Object.assign(Object.assign({}, config), { url, method: 'PUT', body: JSON.stringify(data) }));
|
|
82
82
|
}
|
|
83
83
|
delete(url, config) {
|
|
84
|
-
return this.request(Object.assign(Object.assign({}, config), { method: 'DELETE'
|
|
84
|
+
return this.request(Object.assign(Object.assign({}, config), { url, method: 'DELETE' }));
|
|
85
85
|
}
|
|
86
86
|
}
|
|
@@ -7,81 +7,49 @@ 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 { FlexbeAuthType } from '../types';
|
|
10
11
|
import { TokenManager } from './token-manager';
|
|
11
12
|
export class FlexbeAuth {
|
|
12
13
|
constructor(config) {
|
|
13
14
|
this.initialized = false;
|
|
14
|
-
this.
|
|
15
|
+
this.initializationPromise = null;
|
|
15
16
|
this.config = config;
|
|
16
17
|
this.tokenManager = TokenManager.getInstance();
|
|
17
|
-
if (this.config.authType ===
|
|
18
|
-
//
|
|
19
|
-
|
|
20
|
-
if (existingToken) {
|
|
21
|
-
this.initialized = true;
|
|
22
|
-
}
|
|
23
|
-
// Don't start initialization here, let ensureInitialized handle it
|
|
18
|
+
if (this.config.authType === FlexbeAuthType.BEARER) {
|
|
19
|
+
// Start initialization but don't wait for it
|
|
20
|
+
this.initializationPromise = this.initialize();
|
|
24
21
|
}
|
|
25
22
|
else {
|
|
26
23
|
this.initialized = true;
|
|
27
24
|
}
|
|
28
25
|
}
|
|
29
|
-
|
|
26
|
+
initialize() {
|
|
30
27
|
return __awaiter(this, void 0, void 0, function* () {
|
|
31
|
-
if (this.initializing) {
|
|
32
|
-
// Wait for the ongoing initialization to complete
|
|
33
|
-
while (this.initializing) {
|
|
34
|
-
yield new Promise(resolve => setTimeout(resolve, 100));
|
|
35
|
-
}
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
28
|
try {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
42
|
-
const response = yield fetch('/oauth/token', {
|
|
43
|
-
method: 'POST',
|
|
44
|
-
headers: {
|
|
45
|
-
'Content-Type': 'application/json',
|
|
46
|
-
},
|
|
47
|
-
body: JSON.stringify({
|
|
48
|
-
grant_type: 'client_credentials',
|
|
49
|
-
}),
|
|
50
|
-
credentials: 'include',
|
|
51
|
-
signal: controller.signal,
|
|
52
|
-
});
|
|
53
|
-
clearTimeout(timeoutId);
|
|
54
|
-
if (!response.ok) {
|
|
55
|
-
const defaultError = { message: response.statusText };
|
|
56
|
-
const errorData = yield response.json().catch(() => defaultError);
|
|
57
|
-
const error = {
|
|
58
|
-
message: errorData.message || response.statusText,
|
|
59
|
-
code: errorData.code,
|
|
60
|
-
status: response.status,
|
|
61
|
-
details: errorData.details,
|
|
62
|
-
};
|
|
63
|
-
throw error;
|
|
64
|
-
}
|
|
65
|
-
const data = yield response.json();
|
|
66
|
-
this.tokenManager.setToken(data);
|
|
67
|
-
this.initialized = true;
|
|
29
|
+
const token = yield this.tokenManager.getToken();
|
|
30
|
+
this.initialized = !!token;
|
|
68
31
|
}
|
|
69
32
|
catch (error) {
|
|
70
|
-
console.error('Failed to initialize
|
|
71
|
-
this.initialized = false;
|
|
72
|
-
throw error;
|
|
33
|
+
console.error('Failed to initialize auth:', error);
|
|
34
|
+
this.initialized = false;
|
|
73
35
|
}
|
|
74
36
|
finally {
|
|
75
|
-
this.
|
|
37
|
+
this.initializationPromise = null;
|
|
76
38
|
}
|
|
77
39
|
});
|
|
78
40
|
}
|
|
79
41
|
ensureInitialized() {
|
|
80
42
|
return __awaiter(this, void 0, void 0, function* () {
|
|
81
|
-
if (this.config.authType !==
|
|
43
|
+
if (this.config.authType !== FlexbeAuthType.BEARER || this.initialized) {
|
|
82
44
|
return;
|
|
83
45
|
}
|
|
84
|
-
|
|
46
|
+
// If initialization is in progress, wait for it
|
|
47
|
+
if (this.initializationPromise) {
|
|
48
|
+
yield this.initializationPromise;
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
// If not initialized and no initialization in progress, start one
|
|
52
|
+
yield this.initialize();
|
|
85
53
|
});
|
|
86
54
|
}
|
|
87
55
|
getAuthHeaders() {
|
|
@@ -90,29 +58,17 @@ export class FlexbeAuth {
|
|
|
90
58
|
const headers = {
|
|
91
59
|
'Content-Type': 'application/json',
|
|
92
60
|
};
|
|
93
|
-
if (this.config.authType ===
|
|
61
|
+
if (this.config.authType === FlexbeAuthType.API_KEY) {
|
|
94
62
|
headers['x-api-key'] = this.config.apiKey;
|
|
95
63
|
}
|
|
96
|
-
else if (this.config.authType ===
|
|
97
|
-
const token = this.tokenManager.getToken();
|
|
64
|
+
else if (this.config.authType === FlexbeAuthType.BEARER) {
|
|
65
|
+
const token = yield this.tokenManager.getToken();
|
|
98
66
|
if (!token) {
|
|
99
|
-
|
|
100
|
-
this.initialized = false;
|
|
101
|
-
yield this.ensureInitialized();
|
|
102
|
-
const newToken = this.tokenManager.getToken();
|
|
103
|
-
if (!newToken) {
|
|
104
|
-
throw new Error('No valid bearer token available');
|
|
105
|
-
}
|
|
106
|
-
headers['Authorization'] = `Bearer ${newToken}`;
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
headers['Authorization'] = `Bearer ${token}`;
|
|
67
|
+
throw new Error('No valid bearer token available');
|
|
110
68
|
}
|
|
69
|
+
headers['Authorization'] = `Bearer ${token}`;
|
|
111
70
|
}
|
|
112
71
|
return headers;
|
|
113
72
|
});
|
|
114
73
|
}
|
|
115
|
-
isInitialized() {
|
|
116
|
-
return this.initialized;
|
|
117
|
-
}
|
|
118
74
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { FlexbeAuthType } from '../types';
|
|
1
2
|
import { Pages } from './pages';
|
|
2
3
|
import { ApiClient } from './api-client';
|
|
3
4
|
export class FlexbeClient {
|
|
@@ -13,7 +14,7 @@ export class FlexbeClient {
|
|
|
13
14
|
timeout: (config === null || config === void 0 ? void 0 : config.timeout) || 30000,
|
|
14
15
|
apiKey: (config === null || config === void 0 ? void 0 : config.apiKey) || getEnvVar('FLEXBE_API_KEY') || '',
|
|
15
16
|
siteId: (config === null || config === void 0 ? void 0 : config.siteId) || getEnvVar('FLEXBE_SITE_ID'),
|
|
16
|
-
authType: (config === null || config === void 0 ? void 0 : config.authType) ||
|
|
17
|
+
authType: (config === null || config === void 0 ? void 0 : config.authType) || FlexbeAuthType.API_KEY,
|
|
17
18
|
};
|
|
18
19
|
if (this.config.authType === 'apiKey' && !this.config.apiKey) {
|
|
19
20
|
throw new Error('API key is required when using apiKey authentication. Please provide it either through config or FLEXBE_API_KEY environment variable.');
|
|
@@ -29,4 +29,22 @@ export class Pages {
|
|
|
29
29
|
return response.data;
|
|
30
30
|
});
|
|
31
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Get list of folders for a site
|
|
34
|
+
*/
|
|
35
|
+
getFolders() {
|
|
36
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
37
|
+
const response = yield this.api.get('/sites/:siteId:/pages-folders');
|
|
38
|
+
return response.data;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Get a single folder by ID
|
|
43
|
+
*/
|
|
44
|
+
getFolder(folderId) {
|
|
45
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
46
|
+
const response = yield this.api.get(`/sites/:siteId:/pages-folders/${folderId}`);
|
|
47
|
+
return response.data;
|
|
48
|
+
});
|
|
49
|
+
}
|
|
32
50
|
}
|
|
@@ -1,9 +1,23 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
1
10
|
const TOKEN_STORAGE_KEY = 'flexbe_jwt_token';
|
|
2
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
|
|
3
14
|
export class TokenManager {
|
|
4
15
|
constructor() {
|
|
5
16
|
this.token = null;
|
|
6
17
|
this.refreshInterval = null;
|
|
18
|
+
this.refreshTimeout = null;
|
|
19
|
+
this.tokenPromise = null;
|
|
20
|
+
this.debug = false;
|
|
7
21
|
this.initializeFromStorage();
|
|
8
22
|
this.setupStorageListener();
|
|
9
23
|
}
|
|
@@ -14,59 +28,61 @@ export class TokenManager {
|
|
|
14
28
|
return TokenManager.instance;
|
|
15
29
|
}
|
|
16
30
|
initializeFromStorage() {
|
|
17
|
-
if (typeof window
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
this.clearToken();
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
catch (error) {
|
|
34
|
-
console.error('Failed to parse stored token:', error);
|
|
35
|
-
this.clearToken();
|
|
36
|
-
}
|
|
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();
|
|
37
44
|
}
|
|
38
45
|
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
console.error('Failed to parse stored token:', error);
|
|
48
|
+
this.clearToken();
|
|
49
|
+
}
|
|
39
50
|
}
|
|
40
51
|
setupStorageListener() {
|
|
41
|
-
if (typeof window
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
59
|
-
catch (error) {
|
|
60
|
-
console.error('Failed to parse token from storage event:', error);
|
|
61
|
-
this.clearToken();
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
else {
|
|
65
|
-
this.clearToken();
|
|
66
|
-
}
|
|
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();
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
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;
|
|
67
69
|
}
|
|
68
|
-
|
|
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
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
console.error('Failed to parse token from storage event:', error);
|
|
82
|
+
this.clearToken();
|
|
83
|
+
void this.retrieveToken();
|
|
84
|
+
}
|
|
85
|
+
});
|
|
70
86
|
}
|
|
71
87
|
getExpirationFromToken(token) {
|
|
72
88
|
try {
|
|
@@ -79,32 +95,132 @@ export class TokenManager {
|
|
|
79
95
|
return Date.now() + (4 * 60 * 1000); // Default to 4 minutes if parsing fails
|
|
80
96
|
}
|
|
81
97
|
}
|
|
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
|
+
retrieveToken() {
|
|
110
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
111
|
+
if (this.tokenPromise) {
|
|
112
|
+
yield this.tokenPromise;
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
this.tokenPromise = this.doRetrieveToken();
|
|
116
|
+
try {
|
|
117
|
+
yield this.tokenPromise;
|
|
118
|
+
}
|
|
119
|
+
finally {
|
|
120
|
+
this.tokenPromise = null;
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
doRetrieveToken() {
|
|
125
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
126
|
+
const controller = new AbortController();
|
|
127
|
+
const timeoutId = setTimeout(() => controller.abort(), 30000);
|
|
128
|
+
try {
|
|
129
|
+
const response = yield fetch('/oauth/token', {
|
|
130
|
+
method: 'POST',
|
|
131
|
+
headers: { 'Content-Type': 'application/json' },
|
|
132
|
+
body: JSON.stringify({ grant_type: 'client_credentials' }),
|
|
133
|
+
credentials: 'include',
|
|
134
|
+
signal: controller.signal,
|
|
135
|
+
});
|
|
136
|
+
clearTimeout(timeoutId);
|
|
137
|
+
if (!response.ok) {
|
|
138
|
+
const errorData = yield response.json().catch(() => ({ message: response.statusText }));
|
|
139
|
+
throw new Error(errorData.message || response.statusText);
|
|
140
|
+
}
|
|
141
|
+
const data = yield response.json();
|
|
142
|
+
this.setToken(data);
|
|
143
|
+
}
|
|
144
|
+
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
|
+
throw error;
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
}
|
|
82
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() {
|
|
83
200
|
if (this.refreshInterval) {
|
|
84
201
|
clearInterval(this.refreshInterval);
|
|
202
|
+
this.refreshInterval = null;
|
|
85
203
|
}
|
|
86
|
-
if (this.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
console.log('Setting up token refresh:', {
|
|
90
|
-
tokenLifetime: `${Math.round(tokenLifetime / 1000)} seconds`,
|
|
91
|
-
refreshIn: `${Math.round(refreshTime / 1000)} seconds`,
|
|
92
|
-
refreshAt: new Date(Date.now() + refreshTime).toISOString(),
|
|
93
|
-
});
|
|
94
|
-
this.refreshInterval = window.setInterval(() => {
|
|
95
|
-
this.clearToken();
|
|
96
|
-
}, refreshTime);
|
|
204
|
+
if (this.refreshTimeout) {
|
|
205
|
+
window.clearTimeout(this.refreshTimeout);
|
|
206
|
+
this.refreshTimeout = null;
|
|
97
207
|
}
|
|
98
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
|
+
}
|
|
99
217
|
setToken(tokenResponse) {
|
|
100
218
|
const expiresAt = this.getExpirationFromToken(tokenResponse.accessToken);
|
|
101
219
|
this.token = {
|
|
102
220
|
accessToken: tokenResponse.accessToken,
|
|
103
221
|
expiresAt,
|
|
104
222
|
};
|
|
105
|
-
|
|
106
|
-
console.log('New access token obtained:', {
|
|
107
|
-
expiresIn: `${expiresIn} seconds`,
|
|
223
|
+
this.logTokenStatus('Token set', {
|
|
108
224
|
expiresAt: new Date(expiresAt).toISOString(),
|
|
109
225
|
});
|
|
110
226
|
if (typeof window !== 'undefined') {
|
|
@@ -112,19 +228,9 @@ export class TokenManager {
|
|
|
112
228
|
}
|
|
113
229
|
this.startRefreshInterval();
|
|
114
230
|
}
|
|
115
|
-
getToken() {
|
|
116
|
-
if (this.token && this.token.expiresAt > Date.now()) {
|
|
117
|
-
return this.token.accessToken;
|
|
118
|
-
}
|
|
119
|
-
this.clearToken();
|
|
120
|
-
return null;
|
|
121
|
-
}
|
|
122
231
|
clearToken() {
|
|
123
232
|
this.token = null;
|
|
124
|
-
|
|
125
|
-
clearInterval(this.refreshInterval);
|
|
126
|
-
this.refreshInterval = null;
|
|
127
|
-
}
|
|
233
|
+
this.clearRefreshTimers();
|
|
128
234
|
if (typeof window !== 'undefined') {
|
|
129
235
|
localStorage.removeItem(TOKEN_STORAGE_KEY);
|
|
130
236
|
}
|
|
@@ -71,16 +71,16 @@ class ApiClient {
|
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
get(url, config) {
|
|
74
|
-
return this.request({ ...config, method: 'GET'
|
|
74
|
+
return this.request({ ...config, url, method: 'GET' });
|
|
75
75
|
}
|
|
76
76
|
post(url, data, config) {
|
|
77
|
-
return this.request({ ...config, method: 'POST',
|
|
77
|
+
return this.request({ ...config, url, method: 'POST', body: JSON.stringify(data) });
|
|
78
78
|
}
|
|
79
79
|
put(url, data, config) {
|
|
80
|
-
return this.request({ ...config, method: 'PUT',
|
|
80
|
+
return this.request({ ...config, url, method: 'PUT', body: JSON.stringify(data) });
|
|
81
81
|
}
|
|
82
82
|
delete(url, config) {
|
|
83
|
-
return this.request({ ...config, method: 'DELETE'
|
|
83
|
+
return this.request({ ...config, url, method: 'DELETE' });
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
exports.ApiClient = ApiClient;
|
package/dist/cjs/client/auth.js
CHANGED
|
@@ -1,107 +1,63 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.FlexbeAuth = void 0;
|
|
4
|
+
const types_1 = require("../types");
|
|
4
5
|
const token_manager_1 = require("./token-manager");
|
|
5
6
|
class FlexbeAuth {
|
|
6
7
|
constructor(config) {
|
|
7
8
|
this.initialized = false;
|
|
8
|
-
this.
|
|
9
|
+
this.initializationPromise = null;
|
|
9
10
|
this.config = config;
|
|
10
11
|
this.tokenManager = token_manager_1.TokenManager.getInstance();
|
|
11
|
-
if (this.config.authType ===
|
|
12
|
-
//
|
|
13
|
-
|
|
14
|
-
if (existingToken) {
|
|
15
|
-
this.initialized = true;
|
|
16
|
-
}
|
|
17
|
-
// Don't start initialization here, let ensureInitialized handle it
|
|
12
|
+
if (this.config.authType === types_1.FlexbeAuthType.BEARER) {
|
|
13
|
+
// Start initialization but don't wait for it
|
|
14
|
+
this.initializationPromise = this.initialize();
|
|
18
15
|
}
|
|
19
16
|
else {
|
|
20
17
|
this.initialized = true;
|
|
21
18
|
}
|
|
22
19
|
}
|
|
23
|
-
async
|
|
24
|
-
if (this.initializing) {
|
|
25
|
-
// Wait for the ongoing initialization to complete
|
|
26
|
-
while (this.initializing) {
|
|
27
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
28
|
-
}
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
20
|
+
async initialize() {
|
|
31
21
|
try {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
35
|
-
const response = await fetch('/oauth/token', {
|
|
36
|
-
method: 'POST',
|
|
37
|
-
headers: {
|
|
38
|
-
'Content-Type': 'application/json',
|
|
39
|
-
},
|
|
40
|
-
body: JSON.stringify({
|
|
41
|
-
grant_type: 'client_credentials',
|
|
42
|
-
}),
|
|
43
|
-
credentials: 'include',
|
|
44
|
-
signal: controller.signal,
|
|
45
|
-
});
|
|
46
|
-
clearTimeout(timeoutId);
|
|
47
|
-
if (!response.ok) {
|
|
48
|
-
const defaultError = { message: response.statusText };
|
|
49
|
-
const errorData = await response.json().catch(() => defaultError);
|
|
50
|
-
const error = {
|
|
51
|
-
message: errorData.message || response.statusText,
|
|
52
|
-
code: errorData.code,
|
|
53
|
-
status: response.status,
|
|
54
|
-
details: errorData.details,
|
|
55
|
-
};
|
|
56
|
-
throw error;
|
|
57
|
-
}
|
|
58
|
-
const data = await response.json();
|
|
59
|
-
this.tokenManager.setToken(data);
|
|
60
|
-
this.initialized = true;
|
|
22
|
+
const token = await this.tokenManager.getToken();
|
|
23
|
+
this.initialized = !!token;
|
|
61
24
|
}
|
|
62
25
|
catch (error) {
|
|
63
|
-
console.error('Failed to initialize
|
|
64
|
-
this.initialized = false;
|
|
65
|
-
throw error;
|
|
26
|
+
console.error('Failed to initialize auth:', error);
|
|
27
|
+
this.initialized = false;
|
|
66
28
|
}
|
|
67
29
|
finally {
|
|
68
|
-
this.
|
|
30
|
+
this.initializationPromise = null;
|
|
69
31
|
}
|
|
70
32
|
}
|
|
71
33
|
async ensureInitialized() {
|
|
72
|
-
if (this.config.authType !==
|
|
34
|
+
if (this.config.authType !== types_1.FlexbeAuthType.BEARER || this.initialized) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
// If initialization is in progress, wait for it
|
|
38
|
+
if (this.initializationPromise) {
|
|
39
|
+
await this.initializationPromise;
|
|
73
40
|
return;
|
|
74
41
|
}
|
|
75
|
-
|
|
42
|
+
// If not initialized and no initialization in progress, start one
|
|
43
|
+
await this.initialize();
|
|
76
44
|
}
|
|
77
45
|
async getAuthHeaders() {
|
|
78
46
|
await this.ensureInitialized();
|
|
79
47
|
const headers = {
|
|
80
48
|
'Content-Type': 'application/json',
|
|
81
49
|
};
|
|
82
|
-
if (this.config.authType ===
|
|
50
|
+
if (this.config.authType === types_1.FlexbeAuthType.API_KEY) {
|
|
83
51
|
headers['x-api-key'] = this.config.apiKey;
|
|
84
52
|
}
|
|
85
|
-
else if (this.config.authType ===
|
|
86
|
-
const token = this.tokenManager.getToken();
|
|
53
|
+
else if (this.config.authType === types_1.FlexbeAuthType.BEARER) {
|
|
54
|
+
const token = await this.tokenManager.getToken();
|
|
87
55
|
if (!token) {
|
|
88
|
-
|
|
89
|
-
this.initialized = false;
|
|
90
|
-
await this.ensureInitialized();
|
|
91
|
-
const newToken = this.tokenManager.getToken();
|
|
92
|
-
if (!newToken) {
|
|
93
|
-
throw new Error('No valid bearer token available');
|
|
94
|
-
}
|
|
95
|
-
headers['Authorization'] = `Bearer ${newToken}`;
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
headers['Authorization'] = `Bearer ${token}`;
|
|
56
|
+
throw new Error('No valid bearer token available');
|
|
99
57
|
}
|
|
58
|
+
headers['Authorization'] = `Bearer ${token}`;
|
|
100
59
|
}
|
|
101
60
|
return headers;
|
|
102
61
|
}
|
|
103
|
-
isInitialized() {
|
|
104
|
-
return this.initialized;
|
|
105
|
-
}
|
|
106
62
|
}
|
|
107
63
|
exports.FlexbeAuth = FlexbeAuth;
|