@rebasepro/client 0.2.5 → 0.4.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/dist/auth.d.ts +8 -0
- package/dist/collection.d.ts +4 -3
- package/dist/index.es.js +315 -70
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +323 -69
- package/dist/index.umd.js.map +1 -1
- package/dist/query_builder.d.ts +1 -1
- package/dist/websocket.d.ts +6 -0
- package/package.json +4 -4
- package/src/auth.ts +64 -0
- package/src/collection.ts +112 -68
- package/src/index.ts +39 -9
- package/src/query_builder.ts +1 -1
- package/src/transport.ts +44 -10
- package/src/websocket.ts +135 -9
package/dist/index.umd.js
CHANGED
|
@@ -66,15 +66,33 @@
|
|
|
66
66
|
if (value === null) return "eq.null";
|
|
67
67
|
if (typeof value === "boolean") return `eq.${value}`;
|
|
68
68
|
if (typeof value === "number") return String(value);
|
|
69
|
-
if (Array.isArray(value)
|
|
70
|
-
const [
|
|
71
|
-
const
|
|
72
|
-
if (
|
|
73
|
-
|
|
74
|
-
|
|
69
|
+
if (Array.isArray(value)) {
|
|
70
|
+
const conditions = Array.isArray(value[0]) ? value : [value];
|
|
71
|
+
const [rawOp, val] = conditions[0] || [];
|
|
72
|
+
if (rawOp) {
|
|
73
|
+
const op = OP_MAP[rawOp] ?? rawOp;
|
|
74
|
+
if (val === null) return `${op}.null`;
|
|
75
|
+
if (Array.isArray(val)) return `${op}.(${val.join(",")})`;
|
|
76
|
+
return `${op}.${val}`;
|
|
77
|
+
}
|
|
75
78
|
}
|
|
76
79
|
return String(value);
|
|
77
80
|
}
|
|
81
|
+
function serializeLogicalCondition(cond) {
|
|
82
|
+
if ("type" in cond) {
|
|
83
|
+
const sub = cond.conditions.map(serializeLogicalCondition).join(",");
|
|
84
|
+
return `${cond.type}(${sub})`;
|
|
85
|
+
} else {
|
|
86
|
+
const op = OP_MAP[cond.operator] ?? cond.operator;
|
|
87
|
+
let formattedValue = cond.value;
|
|
88
|
+
if (Array.isArray(cond.value)) {
|
|
89
|
+
formattedValue = `(${cond.value.join(",")})`;
|
|
90
|
+
} else if (cond.value === null) {
|
|
91
|
+
formattedValue = "null";
|
|
92
|
+
}
|
|
93
|
+
return `${cond.column}.${op}.${formattedValue}`;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
78
96
|
function buildQueryString(params) {
|
|
79
97
|
if (!params) return "";
|
|
80
98
|
const parts = [];
|
|
@@ -90,10 +108,22 @@
|
|
|
90
108
|
if (params.include && params.include.length > 0) {
|
|
91
109
|
parts.push(`include=${encodeURIComponent(params.include.join(","))}`);
|
|
92
110
|
}
|
|
111
|
+
if (params.logical) {
|
|
112
|
+
const root = params.logical;
|
|
113
|
+
const serialized = root.conditions.map(serializeLogicalCondition).join(",");
|
|
114
|
+
parts.push(`${root.type}=${encodeURIComponent(`(${serialized})`)}`);
|
|
115
|
+
}
|
|
93
116
|
if (params.where) {
|
|
94
117
|
for (const [field, value] of Object.entries(params.where)) {
|
|
95
|
-
|
|
96
|
-
|
|
118
|
+
if (Array.isArray(value) && value.length > 0 && Array.isArray(value[0])) {
|
|
119
|
+
for (const subVal of value) {
|
|
120
|
+
const normalized = normalizeWhereValue(subVal);
|
|
121
|
+
parts.push(`${encodeURIComponent(field)}=${encodeURIComponent(normalized)}`);
|
|
122
|
+
}
|
|
123
|
+
} else {
|
|
124
|
+
const normalized = normalizeWhereValue(value);
|
|
125
|
+
parts.push(`${encodeURIComponent(field)}=${encodeURIComponent(normalized)}`);
|
|
126
|
+
}
|
|
97
127
|
}
|
|
98
128
|
}
|
|
99
129
|
return parts.length > 0 ? "?" + parts.join("&") : "";
|
|
@@ -703,6 +733,58 @@
|
|
|
703
733
|
onAuthStateChange
|
|
704
734
|
};
|
|
705
735
|
}
|
|
736
|
+
function createCookieStorage(options = {}) {
|
|
737
|
+
const defaultOptions = {
|
|
738
|
+
path: "/",
|
|
739
|
+
sameSite: "Lax",
|
|
740
|
+
...options
|
|
741
|
+
};
|
|
742
|
+
return {
|
|
743
|
+
getItem(key) {
|
|
744
|
+
if (typeof document === "undefined") return null;
|
|
745
|
+
const nameEQ = encodeURIComponent(key) + "=";
|
|
746
|
+
const ca = document.cookie.split(";");
|
|
747
|
+
for (let i = 0; i < ca.length; i++) {
|
|
748
|
+
let c = ca[i];
|
|
749
|
+
while (c.charAt(0) === " ") c = c.substring(1, c.length);
|
|
750
|
+
if (c.indexOf(nameEQ) === 0) {
|
|
751
|
+
return decodeURIComponent(c.substring(nameEQ.length, c.length));
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
return null;
|
|
755
|
+
},
|
|
756
|
+
setItem(key, value) {
|
|
757
|
+
if (typeof document === "undefined") return;
|
|
758
|
+
let cookieStr = `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
|
|
759
|
+
if (defaultOptions.path) {
|
|
760
|
+
cookieStr += `; path=${defaultOptions.path}`;
|
|
761
|
+
}
|
|
762
|
+
if (defaultOptions.domain) {
|
|
763
|
+
cookieStr += `; domain=${defaultOptions.domain}`;
|
|
764
|
+
}
|
|
765
|
+
if (defaultOptions.maxAge !== void 0) {
|
|
766
|
+
cookieStr += `; max-age=${defaultOptions.maxAge}`;
|
|
767
|
+
} else {
|
|
768
|
+
cookieStr += `; max-age=${365 * 24 * 60 * 60}`;
|
|
769
|
+
}
|
|
770
|
+
if (defaultOptions.secure) {
|
|
771
|
+
cookieStr += "; secure";
|
|
772
|
+
}
|
|
773
|
+
if (defaultOptions.sameSite) {
|
|
774
|
+
cookieStr += `; samesite=${defaultOptions.sameSite}`;
|
|
775
|
+
}
|
|
776
|
+
document.cookie = cookieStr;
|
|
777
|
+
},
|
|
778
|
+
removeItem(key) {
|
|
779
|
+
if (typeof document === "undefined") return;
|
|
780
|
+
let cookieStr = `${encodeURIComponent(key)}=; path=${defaultOptions.path || "/"}; max-age=-1`;
|
|
781
|
+
if (defaultOptions.domain) {
|
|
782
|
+
cookieStr += `; domain=${defaultOptions.domain}`;
|
|
783
|
+
}
|
|
784
|
+
document.cookie = cookieStr;
|
|
785
|
+
}
|
|
786
|
+
};
|
|
787
|
+
}
|
|
706
788
|
function createAdmin(transport, options) {
|
|
707
789
|
const opts = options || {};
|
|
708
790
|
const adminPath = opts.adminPath || "/admin";
|
|
@@ -803,44 +885,34 @@
|
|
|
803
885
|
function parseWhereFilter(where) {
|
|
804
886
|
if (!where) return void 0;
|
|
805
887
|
const filters = {};
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
888
|
+
const OP_TO_FILTER = {
|
|
889
|
+
"eq": "==",
|
|
890
|
+
"neq": "!=",
|
|
891
|
+
"gt": ">",
|
|
892
|
+
"gte": ">=",
|
|
893
|
+
"lt": "<",
|
|
894
|
+
"lte": "<=",
|
|
895
|
+
"==": "==",
|
|
896
|
+
"!=": "!=",
|
|
897
|
+
">": ">",
|
|
898
|
+
">=": ">=",
|
|
899
|
+
"<": "<",
|
|
900
|
+
"<=": "<=",
|
|
901
|
+
"in": "in",
|
|
902
|
+
"nin": "not-in",
|
|
903
|
+
"not-in": "not-in",
|
|
904
|
+
"cs": "array-contains",
|
|
905
|
+
"csa": "array-contains-any",
|
|
906
|
+
"array-contains": "array-contains",
|
|
907
|
+
"array-contains-any": "array-contains-any"
|
|
908
|
+
};
|
|
909
|
+
const parseSingle = (rawValue, fieldKey) => {
|
|
910
|
+
if (rawValue === null) return ["==", null];
|
|
911
|
+
if (typeof rawValue === "boolean") return ["==", rawValue];
|
|
912
|
+
if (typeof rawValue === "number") return ["==", rawValue];
|
|
913
|
+
if (Array.isArray(rawValue) && rawValue.length === 2 && typeof rawValue[0] === "string") {
|
|
820
914
|
const [rawOp, val] = rawValue;
|
|
821
|
-
|
|
822
|
-
"eq": "==",
|
|
823
|
-
"neq": "!=",
|
|
824
|
-
"gt": ">",
|
|
825
|
-
"gte": ">=",
|
|
826
|
-
"lt": "<",
|
|
827
|
-
"lte": "<=",
|
|
828
|
-
"==": "==",
|
|
829
|
-
"!=": "!=",
|
|
830
|
-
">": ">",
|
|
831
|
-
">=": ">=",
|
|
832
|
-
"<": "<",
|
|
833
|
-
"<=": "<=",
|
|
834
|
-
"in": "in",
|
|
835
|
-
"nin": "not-in",
|
|
836
|
-
"not-in": "not-in",
|
|
837
|
-
"cs": "array-contains",
|
|
838
|
-
"csa": "array-contains-any",
|
|
839
|
-
"array-contains": "array-contains",
|
|
840
|
-
"array-contains-any": "array-contains-any"
|
|
841
|
-
};
|
|
842
|
-
filters[key] = [OP_TO_FILTER[rawOp] ?? "==", val];
|
|
843
|
-
continue;
|
|
915
|
+
return [OP_TO_FILTER[rawOp] ?? "==", val];
|
|
844
916
|
}
|
|
845
917
|
const value = String(rawValue);
|
|
846
918
|
const dotIndex = value.indexOf(".");
|
|
@@ -890,10 +962,17 @@
|
|
|
890
962
|
if (val === "true") val = true;
|
|
891
963
|
else if (val === "false") val = false;
|
|
892
964
|
else if (val === "null") val = null;
|
|
893
|
-
else if (typeof val === "string" && /^[0-9]+(\.[0-9]+)?$/.test(val) &&
|
|
894
|
-
|
|
965
|
+
else if (typeof val === "string" && /^[0-9]+(\.[0-9]+)?$/.test(val) && fieldKey !== "id" && !fieldKey.endsWith("_id")) val = Number(val);
|
|
966
|
+
return [op, val];
|
|
967
|
+
} else {
|
|
968
|
+
return ["==", value];
|
|
969
|
+
}
|
|
970
|
+
};
|
|
971
|
+
for (const [key, rawValue] of Object.entries(where)) {
|
|
972
|
+
if (Array.isArray(rawValue) && rawValue.length > 0 && Array.isArray(rawValue[0])) {
|
|
973
|
+
filters[key] = rawValue.map((r) => parseSingle(r, key));
|
|
895
974
|
} else {
|
|
896
|
-
filters[key] =
|
|
975
|
+
filters[key] = parseSingle(rawValue, key);
|
|
897
976
|
}
|
|
898
977
|
}
|
|
899
978
|
return filters;
|
|
@@ -917,9 +996,16 @@
|
|
|
917
996
|
};
|
|
918
997
|
},
|
|
919
998
|
async findById(id) {
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
999
|
+
try {
|
|
1000
|
+
const raw = await transport.request(`${basePath}/${encodeURIComponent(String(id))}`, { method: "GET" });
|
|
1001
|
+
if (!raw) return void 0;
|
|
1002
|
+
return rowToEntity(raw, slug);
|
|
1003
|
+
} catch (err) {
|
|
1004
|
+
if (err instanceof RebaseApiError && err.status === 404) {
|
|
1005
|
+
return void 0;
|
|
1006
|
+
}
|
|
1007
|
+
throw err;
|
|
1008
|
+
}
|
|
923
1009
|
},
|
|
924
1010
|
async create(data, id) {
|
|
925
1011
|
const body = { ...data };
|
|
@@ -945,14 +1031,22 @@
|
|
|
945
1031
|
});
|
|
946
1032
|
},
|
|
947
1033
|
async count(params) {
|
|
948
|
-
const countParams = {
|
|
1034
|
+
const countParams = {
|
|
1035
|
+
...params,
|
|
1036
|
+
limit: void 0,
|
|
1037
|
+
offset: void 0
|
|
1038
|
+
};
|
|
949
1039
|
const qs = buildQueryString(countParams);
|
|
950
1040
|
const raw = await transport.request(basePath + "/count" + qs, { method: "GET" });
|
|
951
1041
|
return raw.count ?? 0;
|
|
952
1042
|
},
|
|
953
1043
|
// Fluent builder instantiation
|
|
954
|
-
where(
|
|
955
|
-
|
|
1044
|
+
where(columnOrCondition, operator, value) {
|
|
1045
|
+
const builder = new common.QueryBuilder(client);
|
|
1046
|
+
if (typeof columnOrCondition === "object") {
|
|
1047
|
+
return builder.where(columnOrCondition);
|
|
1048
|
+
}
|
|
1049
|
+
return builder.where(columnOrCondition, operator, value);
|
|
956
1050
|
},
|
|
957
1051
|
orderBy(column, ascending) {
|
|
958
1052
|
return new common.QueryBuilder(client).orderBy(column, ascending);
|
|
@@ -1089,9 +1183,12 @@
|
|
|
1089
1183
|
isAuthenticated = false;
|
|
1090
1184
|
authPromise = null;
|
|
1091
1185
|
WebSocketConstructor;
|
|
1186
|
+
onUnauthorized;
|
|
1187
|
+
refreshInProgress = null;
|
|
1092
1188
|
constructor(config) {
|
|
1093
1189
|
this.websocketUrl = config.websocketUrl;
|
|
1094
1190
|
this.getAuthToken = config.getAuthToken;
|
|
1191
|
+
this.onUnauthorized = config.onUnauthorized;
|
|
1095
1192
|
this.WebSocketConstructor = config.WebSocket || (typeof WebSocket !== "undefined" ? WebSocket : void 0);
|
|
1096
1193
|
if (!this.WebSocketConstructor) {
|
|
1097
1194
|
console.warn("WebSocket is not defined in this environment. Realtime subscriptions will not work unless you provide a WebSocket implementation in the config.");
|
|
@@ -1256,6 +1353,42 @@
|
|
|
1256
1353
|
this.initWebSocket();
|
|
1257
1354
|
}, delay);
|
|
1258
1355
|
}
|
|
1356
|
+
isAuthError(message) {
|
|
1357
|
+
if (message.type === "AUTH_ERROR") return true;
|
|
1358
|
+
const { errorMessage, errorCode } = extractMessageError(message);
|
|
1359
|
+
if (errorCode === "UNAUTHORIZED" || errorCode === "JWT_EXPIRED" || errorCode === "AUTH_ERROR") return true;
|
|
1360
|
+
const lowerMessage = errorMessage.toLowerCase();
|
|
1361
|
+
return lowerMessage.includes("unauthorized") || lowerMessage.includes("token expired") || lowerMessage.includes("token is expired") || lowerMessage.includes("invalid token") || lowerMessage.includes("session expired") || lowerMessage.includes("auth error");
|
|
1362
|
+
}
|
|
1363
|
+
async handleAuthFailure() {
|
|
1364
|
+
if (this.refreshInProgress) {
|
|
1365
|
+
return this.refreshInProgress;
|
|
1366
|
+
}
|
|
1367
|
+
this.refreshInProgress = (async () => {
|
|
1368
|
+
this.isAuthenticated = false;
|
|
1369
|
+
this.authPromise = null;
|
|
1370
|
+
if (this.onUnauthorized) {
|
|
1371
|
+
try {
|
|
1372
|
+
const refreshed = await this.onUnauthorized();
|
|
1373
|
+
if (refreshed && this.getAuthToken) {
|
|
1374
|
+
const token = await this.getAuthToken();
|
|
1375
|
+
if (token) {
|
|
1376
|
+
await this.authenticate(token);
|
|
1377
|
+
return true;
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
} catch (error) {
|
|
1381
|
+
console.error("WebSocket auth refresh failed:", error);
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
return false;
|
|
1385
|
+
})();
|
|
1386
|
+
try {
|
|
1387
|
+
return await this.refreshInProgress;
|
|
1388
|
+
} finally {
|
|
1389
|
+
this.refreshInProgress = null;
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1259
1392
|
handleWebSocketMessage(message) {
|
|
1260
1393
|
const {
|
|
1261
1394
|
type,
|
|
@@ -1263,16 +1396,28 @@
|
|
|
1263
1396
|
subscriptionId
|
|
1264
1397
|
} = message;
|
|
1265
1398
|
if (requestId && this.pendingRequests.has(requestId)) {
|
|
1266
|
-
const
|
|
1267
|
-
resolve,
|
|
1268
|
-
reject
|
|
1269
|
-
} = this.pendingRequests.get(requestId);
|
|
1270
|
-
this.pendingRequests.delete(requestId);
|
|
1399
|
+
const pendingReq = this.pendingRequests.get(requestId);
|
|
1271
1400
|
if (type === "ERROR" || type === "AUTH_ERROR" || message.error) {
|
|
1272
|
-
|
|
1273
|
-
|
|
1401
|
+
if (this.isAuthError(message)) {
|
|
1402
|
+
this.pendingRequests.delete(requestId);
|
|
1403
|
+
this.handleAuthFailure().then((refreshed) => {
|
|
1404
|
+
if (refreshed && pendingReq.message) {
|
|
1405
|
+
this.doSendMessage(pendingReq.message, pendingReq.resolve, pendingReq.reject).catch(pendingReq.reject);
|
|
1406
|
+
} else {
|
|
1407
|
+
const { errorMessage, errorCode } = extractMessageError(message);
|
|
1408
|
+
pendingReq.reject(new ApiError(errorMessage, errorMessage, errorCode));
|
|
1409
|
+
}
|
|
1410
|
+
}).catch((err) => {
|
|
1411
|
+
pendingReq.reject(err);
|
|
1412
|
+
});
|
|
1413
|
+
} else {
|
|
1414
|
+
this.pendingRequests.delete(requestId);
|
|
1415
|
+
const { errorMessage, errorCode } = extractMessageError(message);
|
|
1416
|
+
pendingReq.reject(new ApiError(errorMessage, errorMessage, errorCode));
|
|
1417
|
+
}
|
|
1274
1418
|
} else {
|
|
1275
|
-
|
|
1419
|
+
this.pendingRequests.delete(requestId);
|
|
1420
|
+
pendingReq.resolve(message.payload || message);
|
|
1276
1421
|
}
|
|
1277
1422
|
return;
|
|
1278
1423
|
}
|
|
@@ -1363,6 +1508,40 @@
|
|
|
1363
1508
|
if (collectionKey) {
|
|
1364
1509
|
const collectionSub = this.collectionSubscriptions.get(collectionKey);
|
|
1365
1510
|
if (collectionSub) {
|
|
1511
|
+
if (this.isAuthError(message)) {
|
|
1512
|
+
this.handleAuthFailure().then((refreshed) => {
|
|
1513
|
+
if (refreshed) {
|
|
1514
|
+
const oldBackendId = collectionSub.backendSubscriptionId;
|
|
1515
|
+
const newBackendId = `collection_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
1516
|
+
collectionSub.backendSubscriptionId = newBackendId;
|
|
1517
|
+
this.backendToCollectionKey.delete(oldBackendId);
|
|
1518
|
+
this.backendToCollectionKey.set(newBackendId, collectionKey);
|
|
1519
|
+
this.sendMessage({
|
|
1520
|
+
type: "subscribe_collection",
|
|
1521
|
+
payload: {
|
|
1522
|
+
...collectionSub.props,
|
|
1523
|
+
subscriptionId: newBackendId
|
|
1524
|
+
}
|
|
1525
|
+
}).catch((error2) => {
|
|
1526
|
+
console.error("[WS] Failed to re-subscribe collection after auth refresh:", collectionKey, error2);
|
|
1527
|
+
collectionSub.callbacks.forEach((callback) => {
|
|
1528
|
+
if (callback.onError) callback.onError(error2);
|
|
1529
|
+
});
|
|
1530
|
+
});
|
|
1531
|
+
} else {
|
|
1532
|
+
const { errorMessage: errorMessage2, errorCode: errorCode2 } = extractMessageError(message);
|
|
1533
|
+
const error2 = new ApiError(errorMessage2, errorMessage2, errorCode2);
|
|
1534
|
+
collectionSub.callbacks.forEach((callback) => {
|
|
1535
|
+
if (callback.onError) callback.onError(error2);
|
|
1536
|
+
});
|
|
1537
|
+
}
|
|
1538
|
+
}).catch((err) => {
|
|
1539
|
+
collectionSub.callbacks.forEach((callback) => {
|
|
1540
|
+
if (callback.onError) callback.onError(err);
|
|
1541
|
+
});
|
|
1542
|
+
});
|
|
1543
|
+
return;
|
|
1544
|
+
}
|
|
1366
1545
|
const { errorMessage, errorCode } = extractMessageError(message);
|
|
1367
1546
|
const error = new ApiError(errorMessage, errorMessage, errorCode);
|
|
1368
1547
|
collectionSub.callbacks.forEach((callback) => {
|
|
@@ -1377,6 +1556,40 @@
|
|
|
1377
1556
|
if (entityKey) {
|
|
1378
1557
|
const entitySub = this.entitySubscriptions.get(entityKey);
|
|
1379
1558
|
if (entitySub) {
|
|
1559
|
+
if (this.isAuthError(message)) {
|
|
1560
|
+
this.handleAuthFailure().then((refreshed) => {
|
|
1561
|
+
if (refreshed) {
|
|
1562
|
+
const oldBackendId = entitySub.backendSubscriptionId;
|
|
1563
|
+
const newBackendId = `entity_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
1564
|
+
entitySub.backendSubscriptionId = newBackendId;
|
|
1565
|
+
this.backendToEntityKey.delete(oldBackendId);
|
|
1566
|
+
this.backendToEntityKey.set(newBackendId, entityKey);
|
|
1567
|
+
this.sendMessage({
|
|
1568
|
+
type: "subscribe_entity",
|
|
1569
|
+
payload: {
|
|
1570
|
+
...entitySub.props,
|
|
1571
|
+
subscriptionId: newBackendId
|
|
1572
|
+
}
|
|
1573
|
+
}).catch((error2) => {
|
|
1574
|
+
console.error("[WS] Failed to re-subscribe entity after auth refresh:", entityKey, error2);
|
|
1575
|
+
entitySub.callbacks.forEach((callback) => {
|
|
1576
|
+
if (callback.onError) callback.onError(error2);
|
|
1577
|
+
});
|
|
1578
|
+
});
|
|
1579
|
+
} else {
|
|
1580
|
+
const { errorMessage: errorMessage2, errorCode: errorCode2 } = extractMessageError(message);
|
|
1581
|
+
const error2 = new ApiError(errorMessage2, errorMessage2, errorCode2);
|
|
1582
|
+
entitySub.callbacks.forEach((callback) => {
|
|
1583
|
+
if (callback.onError) callback.onError(error2);
|
|
1584
|
+
});
|
|
1585
|
+
}
|
|
1586
|
+
}).catch((err) => {
|
|
1587
|
+
entitySub.callbacks.forEach((callback) => {
|
|
1588
|
+
if (callback.onError) callback.onError(err);
|
|
1589
|
+
});
|
|
1590
|
+
});
|
|
1591
|
+
return;
|
|
1592
|
+
}
|
|
1380
1593
|
const { errorMessage, errorCode } = extractMessageError(message);
|
|
1381
1594
|
const error = new ApiError(errorMessage, errorMessage, errorCode);
|
|
1382
1595
|
entitySub.callbacks.forEach((callback) => {
|
|
@@ -2057,14 +2270,27 @@
|
|
|
2057
2270
|
};
|
|
2058
2271
|
}
|
|
2059
2272
|
function deriveWebSocketUrl(baseUrl) {
|
|
2060
|
-
if (
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2273
|
+
if (typeof window !== "undefined") {
|
|
2274
|
+
let absoluteUrl = "";
|
|
2275
|
+
if (!baseUrl) {
|
|
2276
|
+
absoluteUrl = window.location.origin;
|
|
2277
|
+
} else if (/^https?:\/\//i.test(baseUrl) || /^wss?:\/\//i.test(baseUrl)) {
|
|
2278
|
+
absoluteUrl = baseUrl;
|
|
2279
|
+
} else {
|
|
2280
|
+
try {
|
|
2281
|
+
absoluteUrl = new URL(baseUrl, window.location.href).origin;
|
|
2282
|
+
} catch {
|
|
2283
|
+
absoluteUrl = window.location.origin;
|
|
2284
|
+
}
|
|
2064
2285
|
}
|
|
2286
|
+
const protocol = absoluteUrl.startsWith("https:") || absoluteUrl.startsWith("wss:") ? "wss:" : "ws:";
|
|
2287
|
+
return absoluteUrl.replace(/^https?:\/\//i, `${protocol}//`).replace(/^wss?:\/\//i, `${protocol}//`).replace(/\/$/, "");
|
|
2288
|
+
}
|
|
2289
|
+
if (!baseUrl) return "";
|
|
2290
|
+
if (!/^https?:\/\//i.test(baseUrl) && !/^wss?:\/\//i.test(baseUrl)) {
|
|
2065
2291
|
return "";
|
|
2066
2292
|
}
|
|
2067
|
-
return baseUrl.replace(/^https
|
|
2293
|
+
return baseUrl.replace(/^https?:\/\//i, (match) => match.toLowerCase() === "https://" ? "wss://" : "ws://").replace(/\/$/, "");
|
|
2068
2294
|
}
|
|
2069
2295
|
function createRebaseClient(options) {
|
|
2070
2296
|
const transport = createTransport(options);
|
|
@@ -2076,12 +2302,27 @@
|
|
|
2076
2302
|
const resolvedWsUrl = options.websocketUrl ?? deriveWebSocketUrl(options.baseUrl);
|
|
2077
2303
|
let ws;
|
|
2078
2304
|
if (resolvedWsUrl) {
|
|
2305
|
+
const wsOnUnauthorized = options.onUnauthorized || (async () => {
|
|
2306
|
+
try {
|
|
2307
|
+
await auth.refreshSession();
|
|
2308
|
+
return true;
|
|
2309
|
+
} catch (e) {
|
|
2310
|
+
return false;
|
|
2311
|
+
}
|
|
2312
|
+
});
|
|
2079
2313
|
ws = new RebaseWebSocketClient({
|
|
2080
2314
|
websocketUrl: resolvedWsUrl,
|
|
2081
2315
|
getAuthToken: async () => {
|
|
2082
|
-
|
|
2316
|
+
let session = auth.getSession();
|
|
2317
|
+
if (session && session.expiresAt <= Date.now() + 1e4) {
|
|
2318
|
+
try {
|
|
2319
|
+
session = await auth.refreshSession();
|
|
2320
|
+
} catch (e) {
|
|
2321
|
+
}
|
|
2322
|
+
}
|
|
2083
2323
|
return session?.accessToken || options.token || "";
|
|
2084
|
-
}
|
|
2324
|
+
},
|
|
2325
|
+
onUnauthorized: wsOnUnauthorized
|
|
2085
2326
|
});
|
|
2086
2327
|
auth.onAuthStateChange((event, session) => {
|
|
2087
2328
|
if (!ws) return;
|
|
@@ -2155,6 +2396,18 @@
|
|
|
2155
2396
|
enumerable: true,
|
|
2156
2397
|
get: () => common.QueryBuilder
|
|
2157
2398
|
});
|
|
2399
|
+
Object.defineProperty(exports2, "and", {
|
|
2400
|
+
enumerable: true,
|
|
2401
|
+
get: () => common.and
|
|
2402
|
+
});
|
|
2403
|
+
Object.defineProperty(exports2, "cond", {
|
|
2404
|
+
enumerable: true,
|
|
2405
|
+
get: () => common.cond
|
|
2406
|
+
});
|
|
2407
|
+
Object.defineProperty(exports2, "or", {
|
|
2408
|
+
enumerable: true,
|
|
2409
|
+
get: () => common.or
|
|
2410
|
+
});
|
|
2158
2411
|
exports2.ApiError = ApiError;
|
|
2159
2412
|
exports2.RebaseApiError = RebaseApiError;
|
|
2160
2413
|
exports2.RebaseWebSocketClient = RebaseWebSocketClient;
|
|
@@ -2162,6 +2415,7 @@
|
|
|
2162
2415
|
exports2.createAdmin = createAdmin;
|
|
2163
2416
|
exports2.createAuth = createAuth;
|
|
2164
2417
|
exports2.createCollectionClient = createCollectionClient;
|
|
2418
|
+
exports2.createCookieStorage = createCookieStorage;
|
|
2165
2419
|
exports2.createCron = createCron;
|
|
2166
2420
|
exports2.createFunctionsClient = createFunctionsClient;
|
|
2167
2421
|
exports2.createMemoryStorage = createMemoryStorage;
|