roboto-js 1.7.1 → 1.7.5
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/.last-build +1 -0
- package/dist/cjs/cookie_storage_adaptor.cjs +429 -0
- package/dist/cjs/index.cjs +57 -5
- package/dist/cjs/rbt_api.cjs +600 -481
- package/dist/cookie_storage_adaptor.js +415 -0
- package/dist/esm/cookie_storage_adaptor.js +226 -0
- package/dist/esm/index.js +37 -5
- package/dist/esm/rbt_api.js +81 -24
- package/dist/index.js +66 -40
- package/dist/rbt_api.js +613 -501
- package/dist/rbt_file.js +10 -16
- package/dist/rbt_metrics_api.js +6 -12
- package/dist/rbt_object.js +30 -36
- package/dist/rbt_user.js +11 -17
- package/package.json +1 -1
- package/src/cookie_storage_adaptor.js +246 -0
- package/src/index.js +41 -5
- package/src/rbt_api.js +76 -22
package/src/index.js
CHANGED
|
@@ -3,11 +3,13 @@ import RbtApi from './rbt_api.js';
|
|
|
3
3
|
import RbtObject from './rbt_object.js';
|
|
4
4
|
import RbtFile from './rbt_file.js';
|
|
5
5
|
import RbtMetricsApi from './rbt_metrics_api.js';
|
|
6
|
+
import CookieStorageAdaptor from './cookie_storage_adaptor.js';
|
|
6
7
|
|
|
7
8
|
export {
|
|
8
9
|
RbtApi,
|
|
9
10
|
RbtObject,
|
|
10
|
-
RbtFile
|
|
11
|
+
RbtFile,
|
|
12
|
+
CookieStorageAdaptor
|
|
11
13
|
//User,
|
|
12
14
|
//Site
|
|
13
15
|
};
|
|
@@ -15,10 +17,10 @@ export {
|
|
|
15
17
|
export default class Roboto{
|
|
16
18
|
|
|
17
19
|
getVersion(){
|
|
18
|
-
return '1.7.
|
|
20
|
+
return '1.7.3';
|
|
19
21
|
}
|
|
20
22
|
|
|
21
|
-
constructor({ host, accessKey, localStorageAdaptor, disableWebSocket = false, metricsHost }, proxyReq = null) {
|
|
23
|
+
constructor({ host, accessKey, localStorageAdaptor, disableWebSocket = false, metricsHost, useCookies = true }, proxyReq = null) {
|
|
22
24
|
|
|
23
25
|
if (Roboto.instance && !proxyReq) {
|
|
24
26
|
// if on client, there can only be one instance
|
|
@@ -28,10 +30,30 @@ export default class Roboto{
|
|
|
28
30
|
|
|
29
31
|
const isBrowser = typeof window !== "undefined";
|
|
30
32
|
this.data = {};
|
|
33
|
+
|
|
34
|
+
// Auto-configure storage adaptor
|
|
35
|
+
let storageAdaptor = localStorageAdaptor;
|
|
36
|
+
if (!storageAdaptor && isBrowser && useCookies) {
|
|
37
|
+
// Use cookies by default in browser for better server-side compatibility
|
|
38
|
+
storageAdaptor = new CookieStorageAdaptor({
|
|
39
|
+
secure: window.location.protocol === 'https:',
|
|
40
|
+
sameSite: 'Lax',
|
|
41
|
+
maxAge: 24 * 60 * 60 // 24 hours
|
|
42
|
+
});
|
|
43
|
+
console.log('[Roboto] Using CookieStorageAdaptor for authentication tokens');
|
|
44
|
+
|
|
45
|
+
// Set accessKey for server-side authentication (handled automatically by adapter)
|
|
46
|
+
if (accessKey) {
|
|
47
|
+
storageAdaptor.setItem('accessKey', accessKey).catch(e =>
|
|
48
|
+
console.warn('[Roboto] Failed to set accessKey cookie:', e)
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
31
53
|
this.config = {
|
|
32
54
|
accessKey: accessKey, // Use passed accessKey
|
|
33
55
|
baseUrl: `https://${host}`, // Use passed host
|
|
34
|
-
localStorageAdaptor:
|
|
56
|
+
localStorageAdaptor: storageAdaptor
|
|
35
57
|
};
|
|
36
58
|
|
|
37
59
|
// DEVELOPMENT
|
|
@@ -58,6 +80,12 @@ export default class Roboto{
|
|
|
58
80
|
this.api = new RbtApi(this.config);
|
|
59
81
|
if (isBrowser) {
|
|
60
82
|
this.api.initLocalDb();
|
|
83
|
+
|
|
84
|
+
// Add global debug method for cookie storage adapter
|
|
85
|
+
if (this.config.localStorageAdaptor && this.config.localStorageAdaptor.debugState) {
|
|
86
|
+
window.debugRobotoCookies = () => this.config.localStorageAdaptor.debugState();
|
|
87
|
+
console.log('[Roboto] Added global debug method: window.debugRobotoCookies()');
|
|
88
|
+
}
|
|
61
89
|
}
|
|
62
90
|
|
|
63
91
|
// METRICS API instance (separate host or same)
|
|
@@ -155,7 +183,15 @@ export default class Roboto{
|
|
|
155
183
|
return this.api.loginWithOauth(params);
|
|
156
184
|
}
|
|
157
185
|
async logout(){
|
|
158
|
-
|
|
186
|
+
const result = await this.api.logout();
|
|
187
|
+
|
|
188
|
+
// Clear accessKey and authtoken using standard localStorage interface
|
|
189
|
+
if (this.config.localStorageAdaptor) {
|
|
190
|
+
await this.config.localStorageAdaptor.removeItem('accessKey');
|
|
191
|
+
await this.config.localStorageAdaptor.removeItem('authtoken');
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return result;
|
|
159
195
|
}
|
|
160
196
|
async refreshAuthToken(){
|
|
161
197
|
return this.api.refreshAuthToken(this.config.authtoken);
|
package/src/rbt_api.js
CHANGED
|
@@ -43,26 +43,9 @@ export default class RbtApi {
|
|
|
43
43
|
};
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
//
|
|
47
|
-
if
|
|
48
|
-
|
|
49
|
-
const token = localStorage.getItem('authtoken');
|
|
50
|
-
if (token) {
|
|
51
|
-
this.authtoken = token;
|
|
52
|
-
this.axios.defaults.headers.common['authtoken'] = token;
|
|
53
|
-
}
|
|
54
|
-
} catch {}
|
|
55
|
-
try {
|
|
56
|
-
const cachedUser = localStorage.getItem('rbtUser');
|
|
57
|
-
if (cachedUser) {
|
|
58
|
-
const parsed = JSON.parse(cachedUser);
|
|
59
|
-
if (parsed && parsed.id) {
|
|
60
|
-
this.currentUser = new RbtUser({ id: parsed.id }, this.axios);
|
|
61
|
-
this.currentUser.setData(parsed);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
} catch {}
|
|
65
|
-
}
|
|
46
|
+
// Asynchronous browser hydration: set auth header and in-memory user
|
|
47
|
+
// Use storage adaptor if available, otherwise fallback to localStorage
|
|
48
|
+
this._initializeFromStorage().catch(e => console.warn('[RbtApi] Storage initialization failed:', e));
|
|
66
49
|
this.localDb = null;
|
|
67
50
|
this.iac_session = null;
|
|
68
51
|
this.appServiceHost = baseUrl;
|
|
@@ -77,6 +60,52 @@ export default class RbtApi {
|
|
|
77
60
|
|
|
78
61
|
}
|
|
79
62
|
|
|
63
|
+
// Initialize authtoken and user from storage (cookies or localStorage)
|
|
64
|
+
async _initializeFromStorage() {
|
|
65
|
+
if (!this.localStorageAdaptor) return;
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
// Try to get authtoken from storage adaptor (prefixed: rbt_authtoken)
|
|
69
|
+
let token = await this.localStorageAdaptor.getItem('authtoken');
|
|
70
|
+
|
|
71
|
+
// If not found in prefixed storage, try raw cookie (like accessKey)
|
|
72
|
+
if (!token && typeof document !== 'undefined') {
|
|
73
|
+
// Try to get from raw cookie
|
|
74
|
+
const cookies = document.cookie.split(';');
|
|
75
|
+
for (let cookie of cookies) {
|
|
76
|
+
const [name, value] = cookie.trim().split('=');
|
|
77
|
+
if (name === 'authtoken') {
|
|
78
|
+
token = decodeURIComponent(value);
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (token) {
|
|
85
|
+
this.authtoken = token;
|
|
86
|
+
this.axios.defaults.headers.common['authtoken'] = token;
|
|
87
|
+
console.log('[RbtApi] Loaded authtoken from storage adaptor');
|
|
88
|
+
}
|
|
89
|
+
} catch (e) {
|
|
90
|
+
console.warn('[RbtApi] Failed to load authtoken from storage adaptor:', e);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
// Try to get user from storage adaptor
|
|
95
|
+
const cachedUser = await this.localStorageAdaptor.getItem('rbtUser');
|
|
96
|
+
if (cachedUser) {
|
|
97
|
+
const parsed = typeof cachedUser === 'string' ? JSON.parse(cachedUser) : cachedUser;
|
|
98
|
+
if (parsed && parsed.id) {
|
|
99
|
+
this.currentUser = new RbtUser({ id: parsed.id }, this.axios);
|
|
100
|
+
this.currentUser.setData(parsed);
|
|
101
|
+
console.log('[RbtApi] Loaded user from storage adaptor');
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
} catch (e) {
|
|
105
|
+
console.warn('[RbtApi] Failed to load user from storage adaptor:', e);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
80
109
|
getWebSocketClient() {
|
|
81
110
|
// Reuse existing WebSocket if it's OPEN or CONNECTING (to prevent race condition)
|
|
82
111
|
if (this.websocketClient &&
|
|
@@ -277,6 +306,8 @@ export default class RbtApi {
|
|
|
277
306
|
if (this.iac_session?.user) {
|
|
278
307
|
await this.localStorageAdaptor.setItem('rbtUser', JSON.stringify(this.iac_session.user));
|
|
279
308
|
}
|
|
309
|
+
|
|
310
|
+
// authtoken is automatically stored for server-side access by the adapter
|
|
280
311
|
}
|
|
281
312
|
|
|
282
313
|
return response.data;
|
|
@@ -662,6 +693,10 @@ export default class RbtApi {
|
|
|
662
693
|
* - limit: An object to control the pagination of results. It includes:
|
|
663
694
|
* - offset: The starting point from where to fetch the results.
|
|
664
695
|
* - results: The maximum number of results to return.
|
|
696
|
+
* - requestAttrs: An array of attribute paths to include in the response (e.g., ['id', 'configs.title', 'configs.description']).
|
|
697
|
+
* If not provided, all attributes are returned.
|
|
698
|
+
* - excludeAttrs: An array of attribute paths to exclude from the response (e.g., ['details.log', 'internalData']).
|
|
699
|
+
* Excludes the specified paths and all their subpaths.
|
|
665
700
|
* - resolveReferences: An array of attribute names whose references should be resolved in the returned objects.
|
|
666
701
|
* - timeout: A numerical value in milliseconds to set a maximum time limit for the query execution.
|
|
667
702
|
*
|
|
@@ -670,6 +705,8 @@ export default class RbtApi {
|
|
|
670
705
|
* where: 'email="tom@pospa.com"',
|
|
671
706
|
* orderBy: { column: 'timeCreated', direction: 'DESC' },
|
|
672
707
|
* limit: { offset: 0, results: 50 },
|
|
708
|
+
* requestAttrs: ['id', 'configs.title'],
|
|
709
|
+
* excludeAttrs: ['details.log'],
|
|
673
710
|
* resolveReferences: ['translatableContent']
|
|
674
711
|
* });
|
|
675
712
|
*
|
|
@@ -681,6 +718,19 @@ export default class RbtApi {
|
|
|
681
718
|
let paramsKey;
|
|
682
719
|
try {
|
|
683
720
|
//console.log('RBTAPI.query INIT', type, params);
|
|
721
|
+
|
|
722
|
+
// Validate parameters - reject invalid parameter names
|
|
723
|
+
const validParams = ['type', 'where', 'orderBy', 'limit', 'resolveReferences', 'requestAttrs', 'excludeAttrs', 'timeout', 'enableRealtime'];
|
|
724
|
+
const invalidParams = Object.keys(params).filter(key => !validParams.includes(key));
|
|
725
|
+
if (invalidParams.length > 0) {
|
|
726
|
+
throw new Error(`Invalid query parameter(s): ${invalidParams.join(', ')}. Valid parameters are: ${validParams.join(', ')}`);
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
// Warn if enableRealtime is passed to query() - it should only be used by load()
|
|
730
|
+
if (params.enableRealtime) {
|
|
731
|
+
console.warn('[roboto-js] enableRealtime should not be passed to query(), only to load(). This parameter will be ignored.');
|
|
732
|
+
}
|
|
733
|
+
|
|
684
734
|
params.type = type;
|
|
685
735
|
|
|
686
736
|
// Default ordering and pagination
|
|
@@ -812,7 +862,9 @@ export default class RbtApi {
|
|
|
812
862
|
this._loggedCacheEvents.add(bulkMissLogKey);
|
|
813
863
|
}
|
|
814
864
|
|
|
815
|
-
|
|
865
|
+
// Remove load-specific params that shouldn't be passed to query
|
|
866
|
+
const { enableRealtime, ...queryParams } = params;
|
|
867
|
+
mergedParams = { ...queryParams, where: `id IN ("${missingIds.join(`","`)}")` };
|
|
816
868
|
loadedObjects = await this.query(type, mergedParams);
|
|
817
869
|
|
|
818
870
|
// Cache the newly loaded objects
|
|
@@ -882,7 +934,9 @@ export default class RbtApi {
|
|
|
882
934
|
// Create the loading promise and store it to prevent duplicate requests
|
|
883
935
|
const loadPromise = (async () => {
|
|
884
936
|
try {
|
|
885
|
-
|
|
937
|
+
// Remove load-specific params that shouldn't be passed to query
|
|
938
|
+
const { enableRealtime, ...queryParams } = params;
|
|
939
|
+
mergedParams = { ...queryParams, where: `id="${ids}"` };
|
|
886
940
|
let res = await this.query(type, mergedParams);
|
|
887
941
|
const obj = res[0];
|
|
888
942
|
|