@neetru/sdk 3.1.0 → 3.1.2
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.cjs +159 -15
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +1 -1
- package/dist/auth.d.ts +1 -1
- package/dist/auth.mjs +159 -15
- package/dist/auth.mjs.map +1 -1
- package/dist/catalog.cjs +50 -2
- package/dist/catalog.cjs.map +1 -1
- package/dist/catalog.d.cts +1 -1
- package/dist/catalog.d.ts +1 -1
- package/dist/catalog.mjs +50 -2
- package/dist/catalog.mjs.map +1 -1
- package/dist/checkout.cjs +52 -3
- package/dist/checkout.cjs.map +1 -1
- package/dist/checkout.d.cts +1 -1
- package/dist/checkout.d.ts +1 -1
- package/dist/checkout.mjs +52 -3
- package/dist/checkout.mjs.map +1 -1
- package/dist/db-react.cjs +3 -1
- package/dist/db-react.cjs.map +1 -1
- package/dist/db-react.d.cts +1 -1
- package/dist/db-react.d.ts +1 -1
- package/dist/db-react.mjs +3 -1
- package/dist/db-react.mjs.map +1 -1
- package/dist/db.cjs +93 -6
- package/dist/db.cjs.map +1 -1
- package/dist/db.d.cts +1 -1
- package/dist/db.d.ts +1 -1
- package/dist/db.mjs +93 -6
- package/dist/db.mjs.map +1 -1
- package/dist/entitlements.cjs +50 -2
- package/dist/entitlements.cjs.map +1 -1
- package/dist/entitlements.d.cts +1 -1
- package/dist/entitlements.d.ts +1 -1
- package/dist/entitlements.mjs +50 -2
- package/dist/entitlements.mjs.map +1 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.cts +3 -1
- package/dist/errors.d.ts +3 -1
- package/dist/errors.mjs.map +1 -1
- package/dist/firestore-compat.cjs +29 -4
- package/dist/firestore-compat.cjs.map +1 -1
- package/dist/firestore-compat.d.cts +28 -3
- package/dist/firestore-compat.d.ts +28 -3
- package/dist/firestore-compat.mjs +29 -4
- package/dist/firestore-compat.mjs.map +1 -1
- package/dist/index.cjs +195 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -3
- package/dist/index.d.ts +9 -3
- package/dist/index.mjs +194 -17
- package/dist/index.mjs.map +1 -1
- package/dist/mocks.cjs.map +1 -1
- package/dist/mocks.d.cts +1 -1
- package/dist/mocks.d.ts +1 -1
- package/dist/mocks.mjs.map +1 -1
- package/dist/notifications.cjs +50 -2
- package/dist/notifications.cjs.map +1 -1
- package/dist/notifications.d.cts +1 -1
- package/dist/notifications.d.ts +1 -1
- package/dist/notifications.mjs +50 -2
- package/dist/notifications.mjs.map +1 -1
- package/dist/react.cjs +2 -3
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +22 -4
- package/dist/react.d.ts +22 -4
- package/dist/react.mjs +2 -3
- package/dist/react.mjs.map +1 -1
- package/dist/support.cjs +50 -2
- package/dist/support.cjs.map +1 -1
- package/dist/support.d.cts +1 -1
- package/dist/support.d.ts +1 -1
- package/dist/support.mjs +50 -2
- package/dist/support.mjs.map +1 -1
- package/dist/telemetry.cjs +65 -4
- package/dist/telemetry.cjs.map +1 -1
- package/dist/telemetry.d.cts +1 -1
- package/dist/telemetry.d.ts +1 -1
- package/dist/telemetry.mjs +65 -4
- package/dist/telemetry.mjs.map +1 -1
- package/dist/{types-BRv8wBxX.d.ts → types-B3XFHD4A.d.ts} +60 -1
- package/dist/{types-nwErcRX8.d.cts → types-DePdSU3P.d.cts} +60 -1
- package/dist/usage.cjs +50 -2
- package/dist/usage.cjs.map +1 -1
- package/dist/usage.d.cts +1 -1
- package/dist/usage.d.ts +1 -1
- package/dist/usage.mjs +50 -2
- package/dist/usage.mjs.map +1 -1
- package/dist/webhooks.cjs +83 -2
- package/dist/webhooks.cjs.map +1 -1
- package/dist/webhooks.d.cts +1 -1
- package/dist/webhooks.d.ts +1 -1
- package/dist/webhooks.mjs +83 -3
- package/dist/webhooks.mjs.map +1 -1
- package/package.json +1 -1
package/dist/auth.d.cts
CHANGED
package/dist/auth.d.ts
CHANGED
package/dist/auth.mjs
CHANGED
|
@@ -51,8 +51,47 @@ var init_idempotency = __esm({
|
|
|
51
51
|
// src/http.ts
|
|
52
52
|
var http_exports = {};
|
|
53
53
|
__export(http_exports, {
|
|
54
|
+
checkCoreVersionCompat: () => checkCoreVersionCompat,
|
|
54
55
|
httpRequest: () => httpRequest
|
|
55
56
|
});
|
|
57
|
+
function stripRevision(v) {
|
|
58
|
+
return v.split("+")[0] ?? v;
|
|
59
|
+
}
|
|
60
|
+
function compareCalVer(a, b) {
|
|
61
|
+
const partsA = stripRevision(a).split(".").map(Number);
|
|
62
|
+
const partsB = stripRevision(b).split(".").map(Number);
|
|
63
|
+
const len = Math.max(partsA.length, partsB.length);
|
|
64
|
+
for (let i = 0; i < len; i++) {
|
|
65
|
+
const pa = partsA[i] ?? 0;
|
|
66
|
+
const pb = partsB[i] ?? 0;
|
|
67
|
+
if (pa !== pb) return pa - pb;
|
|
68
|
+
}
|
|
69
|
+
return 0;
|
|
70
|
+
}
|
|
71
|
+
function getSdkMajor() {
|
|
72
|
+
try {
|
|
73
|
+
const ver = globalThis.__NEETRU_SDK_VERSION__;
|
|
74
|
+
if (ver) return parseInt(ver.split(".")[0] ?? "3", 10);
|
|
75
|
+
} catch {
|
|
76
|
+
}
|
|
77
|
+
return 3;
|
|
78
|
+
}
|
|
79
|
+
function checkCoreVersionCompat(coreVersion) {
|
|
80
|
+
if (!coreVersion) return;
|
|
81
|
+
const sdkMajor = getSdkMajor();
|
|
82
|
+
const minCore = COMPAT_MATRIX[sdkMajor];
|
|
83
|
+
if (!minCore) return;
|
|
84
|
+
const stripped = stripRevision(coreVersion);
|
|
85
|
+
if (compareCalVer(stripped, minCore) < 0) {
|
|
86
|
+
const key = `${sdkMajor}:${stripped}`;
|
|
87
|
+
if (!_warnedCoreTooOld.has(key)) {
|
|
88
|
+
_warnedCoreTooOld.add(key);
|
|
89
|
+
console.warn(
|
|
90
|
+
`[Neetru SDK] Aten\xE7\xE3o: Core vers\xE3o "${coreVersion}" \xE9 anterior ao m\xEDnimo recomendado "${minCore}" para SDK major ${sdkMajor}. Alguns recursos podem n\xE3o funcionar corretamente. Atualize o Core para a vers\xE3o mais recente.`
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
56
95
|
function backoffMs(attempt) {
|
|
57
96
|
const base = 200 * Math.pow(4, attempt);
|
|
58
97
|
const jitter = base * 0.2 * (Math.random() * 2 - 1);
|
|
@@ -61,11 +100,11 @@ function backoffMs(attempt) {
|
|
|
61
100
|
function parseRetryAfter(value) {
|
|
62
101
|
if (!value) return null;
|
|
63
102
|
const secs = Number(value);
|
|
64
|
-
if (Number.isFinite(secs) && secs >= 0) return Math.round(secs * 1e3);
|
|
103
|
+
if (Number.isFinite(secs) && secs >= 0) return Math.min(Math.round(secs * 1e3), MAX_RETRY_AFTER_MS);
|
|
65
104
|
const dateMs = Date.parse(value);
|
|
66
105
|
if (Number.isFinite(dateMs)) {
|
|
67
106
|
const delta = dateMs - Date.now();
|
|
68
|
-
if (delta > 0) return delta;
|
|
107
|
+
if (delta > 0) return Math.min(delta, MAX_RETRY_AFTER_MS);
|
|
69
108
|
}
|
|
70
109
|
return null;
|
|
71
110
|
}
|
|
@@ -76,6 +115,7 @@ function statusToCode(status) {
|
|
|
76
115
|
if (status === 401) return "unauthorized";
|
|
77
116
|
if (status === 403) return "forbidden";
|
|
78
117
|
if (status === 404) return "not_found";
|
|
118
|
+
if (status === 409) return "conflict";
|
|
79
119
|
if (status === 422 || status === 400) return "validation_failed";
|
|
80
120
|
if (status === 429) return "rate_limited";
|
|
81
121
|
if (status >= 500) return "server_error";
|
|
@@ -147,6 +187,8 @@ async function httpRequest(config, opts) {
|
|
|
147
187
|
}
|
|
148
188
|
const requestId = res.headers.get("x-request-id") ?? res.headers.get("x-correlation-id") ?? void 0;
|
|
149
189
|
if (res.ok) {
|
|
190
|
+
const coreVersion = res.headers.get("x-neetru-version");
|
|
191
|
+
if (coreVersion) checkCoreVersionCompat(coreVersion);
|
|
150
192
|
const parsed = await safeJson(res);
|
|
151
193
|
return parsed;
|
|
152
194
|
}
|
|
@@ -175,11 +217,17 @@ async function httpRequest(config, opts) {
|
|
|
175
217
|
}
|
|
176
218
|
throw lastError ?? new NeetruError("unknown", "unexpected httpRequest exit");
|
|
177
219
|
}
|
|
178
|
-
var DEFAULT_RETRIES_READ, DEFAULT_RETRIES_WRITE, READ_METHODS, RETRYABLE_CODES;
|
|
220
|
+
var COMPAT_MATRIX, _warnedCoreTooOld, DEFAULT_RETRIES_READ, DEFAULT_RETRIES_WRITE, READ_METHODS, RETRYABLE_CODES, MAX_RETRY_AFTER_MS;
|
|
179
221
|
var init_http = __esm({
|
|
180
222
|
"src/http.ts"() {
|
|
181
223
|
init_errors();
|
|
182
224
|
init_idempotency();
|
|
225
|
+
COMPAT_MATRIX = {
|
|
226
|
+
// SDK major 3.x requer Core ≥ 2026.05.1 (suporte a X-Neetru-Version header,
|
|
227
|
+
// runTransaction write-after-read, verifyWebhookRequest, webhooks 3.0+)
|
|
228
|
+
3: "2026.05.1"
|
|
229
|
+
};
|
|
230
|
+
_warnedCoreTooOld = /* @__PURE__ */ new Set();
|
|
183
231
|
DEFAULT_RETRIES_READ = 2;
|
|
184
232
|
DEFAULT_RETRIES_WRITE = 0;
|
|
185
233
|
READ_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD"]);
|
|
@@ -188,6 +236,7 @@ var init_http = __esm({
|
|
|
188
236
|
"server_error",
|
|
189
237
|
"network_error"
|
|
190
238
|
]);
|
|
239
|
+
MAX_RETRY_AFTER_MS = 6e4;
|
|
191
240
|
}
|
|
192
241
|
});
|
|
193
242
|
|
|
@@ -889,11 +938,11 @@ var TRACK_MAX_QUEUE = 50;
|
|
|
889
938
|
function createTelemetryNamespace(config) {
|
|
890
939
|
const queue = [];
|
|
891
940
|
let flushTimer = null;
|
|
941
|
+
let _inflightDrain = null;
|
|
892
942
|
async function drainQueue() {
|
|
893
943
|
if (queue.length === 0) return;
|
|
894
944
|
const batch = queue.splice(0, queue.length);
|
|
895
|
-
|
|
896
|
-
await Promise.allSettled(
|
|
945
|
+
const work = Promise.allSettled(
|
|
897
946
|
batch.map(async (ev) => {
|
|
898
947
|
try {
|
|
899
948
|
const body = { name: ev.name };
|
|
@@ -915,6 +964,14 @@ function createTelemetryNamespace(config) {
|
|
|
915
964
|
}
|
|
916
965
|
})
|
|
917
966
|
);
|
|
967
|
+
_inflightDrain = work.then(() => {
|
|
968
|
+
_inflightDrain = null;
|
|
969
|
+
});
|
|
970
|
+
await work;
|
|
971
|
+
flushTimer = null;
|
|
972
|
+
if (queue.length > 0) {
|
|
973
|
+
scheduleFlush();
|
|
974
|
+
}
|
|
918
975
|
}
|
|
919
976
|
function scheduleFlush() {
|
|
920
977
|
if (flushTimer) return;
|
|
@@ -977,6 +1034,10 @@ function createTelemetryNamespace(config) {
|
|
|
977
1034
|
if (input.name.length > 128) return;
|
|
978
1035
|
queue.push(input);
|
|
979
1036
|
if (queue.length >= TRACK_MAX_QUEUE) {
|
|
1037
|
+
if (flushTimer) {
|
|
1038
|
+
clearTimeout(flushTimer);
|
|
1039
|
+
flushTimer = null;
|
|
1040
|
+
}
|
|
980
1041
|
void drainQueue();
|
|
981
1042
|
} else {
|
|
982
1043
|
scheduleFlush();
|
|
@@ -991,6 +1052,7 @@ function createTelemetryNamespace(config) {
|
|
|
991
1052
|
clearTimeout(flushTimer);
|
|
992
1053
|
flushTimer = null;
|
|
993
1054
|
}
|
|
1055
|
+
if (_inflightDrain) await _inflightDrain;
|
|
994
1056
|
await drainQueue();
|
|
995
1057
|
},
|
|
996
1058
|
/**
|
|
@@ -1479,6 +1541,31 @@ var LocalStore = class {
|
|
|
1479
1541
|
this.db?.close();
|
|
1480
1542
|
this.db = null;
|
|
1481
1543
|
}
|
|
1544
|
+
/**
|
|
1545
|
+
* Apaga completamente o banco IndexedDB e o recria do zero.
|
|
1546
|
+
*
|
|
1547
|
+
* Ao contrário de `close()` + `open()` (que reabre o banco existente sem
|
|
1548
|
+
* apagar dados), `clearAll()` chama `indexedDB.deleteDatabase(dbName)` e
|
|
1549
|
+
* só então chama `open()` — garantindo que nenhum documento, mutação ou
|
|
1550
|
+
* metadado sobrevive.
|
|
1551
|
+
*
|
|
1552
|
+
* BUG fix: `clearCache()` em `NeetruDbDocumentsImpl` chamava close+open,
|
|
1553
|
+
* que reabre o mesmo banco. `clearAll()` é o método correto.
|
|
1554
|
+
*/
|
|
1555
|
+
async clearAll() {
|
|
1556
|
+
if (this.db !== null) {
|
|
1557
|
+
this.db.close();
|
|
1558
|
+
this.db = null;
|
|
1559
|
+
}
|
|
1560
|
+
await new Promise((resolve, reject) => {
|
|
1561
|
+
const req = indexedDB.deleteDatabase(this.dbName);
|
|
1562
|
+
req.onsuccess = () => resolve();
|
|
1563
|
+
req.onerror = () => reject(req.error);
|
|
1564
|
+
req.onblocked = () => {
|
|
1565
|
+
};
|
|
1566
|
+
});
|
|
1567
|
+
await this.open();
|
|
1568
|
+
}
|
|
1482
1569
|
assertOpen() {
|
|
1483
1570
|
if (this.db === null) {
|
|
1484
1571
|
throw new Error("LocalStore: banco n\xE3o est\xE1 aberto. Chame open() primeiro.");
|
|
@@ -1686,6 +1773,12 @@ var MemoryStore = class {
|
|
|
1686
1773
|
async open() {
|
|
1687
1774
|
}
|
|
1688
1775
|
async close() {
|
|
1776
|
+
}
|
|
1777
|
+
/**
|
|
1778
|
+
* Apaga todos os dados em memória — equivalente ao `indexedDB.deleteDatabase`
|
|
1779
|
+
* que `LocalStore.clearAll()` executa em ambientes com IndexedDB.
|
|
1780
|
+
*/
|
|
1781
|
+
async clearAll() {
|
|
1689
1782
|
this._docs.clear();
|
|
1690
1783
|
this._mutations.clear();
|
|
1691
1784
|
this._meta.clear();
|
|
@@ -2200,6 +2293,8 @@ var SyncEngine = class {
|
|
|
2200
2293
|
const phase1Ok = await this._phase1Push();
|
|
2201
2294
|
if (!phase1Ok) {
|
|
2202
2295
|
this._updateState({ status: "idle" });
|
|
2296
|
+
this._refreshPendingWrites().catch(() => {
|
|
2297
|
+
});
|
|
2203
2298
|
this._syncing = false;
|
|
2204
2299
|
return;
|
|
2205
2300
|
}
|
|
@@ -2586,7 +2681,7 @@ var SyncEngine = class {
|
|
|
2586
2681
|
ownerId: localDoc.meta.ownerId
|
|
2587
2682
|
}
|
|
2588
2683
|
};
|
|
2589
|
-
const pendingMuts = await this._queue.
|
|
2684
|
+
const pendingMuts = await this._queue.listAll();
|
|
2590
2685
|
const docMut = pendingMuts.find(
|
|
2591
2686
|
(m) => m.collection === serverDoc.collection && m.docId === serverDoc.id
|
|
2592
2687
|
);
|
|
@@ -3940,8 +4035,13 @@ var NeetruDbDocumentsImpl = class {
|
|
|
3940
4035
|
return this._engine.flush();
|
|
3941
4036
|
}
|
|
3942
4037
|
async clearCache() {
|
|
3943
|
-
|
|
3944
|
-
|
|
4038
|
+
const storeWithClear = this._store;
|
|
4039
|
+
if (typeof storeWithClear.clearAll === "function") {
|
|
4040
|
+
await storeWithClear.clearAll();
|
|
4041
|
+
} else {
|
|
4042
|
+
await this._store.close();
|
|
4043
|
+
await this._store.open();
|
|
4044
|
+
}
|
|
3945
4045
|
}
|
|
3946
4046
|
async getConflicts() {
|
|
3947
4047
|
return this._store.listConflicts();
|
|
@@ -4828,7 +4928,8 @@ function createHttpCheckoutNamespace(config) {
|
|
|
4828
4928
|
method: "POST",
|
|
4829
4929
|
path: "/api/v1/checkout/intents",
|
|
4830
4930
|
body,
|
|
4831
|
-
requireAuth: true
|
|
4931
|
+
requireAuth: true,
|
|
4932
|
+
idempotencyKey: true
|
|
4832
4933
|
});
|
|
4833
4934
|
const result = parseStartResponse(raw);
|
|
4834
4935
|
const shouldRedirect = input.autoRedirect !== false;
|
|
@@ -5583,6 +5684,7 @@ function createOidcAuthNamespace(config) {
|
|
|
5583
5684
|
const STORAGE_KEY = "neetru_id_token";
|
|
5584
5685
|
const listeners = /* @__PURE__ */ new Set();
|
|
5585
5686
|
let cachedUser = null;
|
|
5687
|
+
let _expiryTimerId = null;
|
|
5586
5688
|
function getStorage() {
|
|
5587
5689
|
try {
|
|
5588
5690
|
return typeof globalThis.localStorage !== "undefined" ? globalThis.localStorage : null;
|
|
@@ -5605,6 +5707,9 @@ function createOidcAuthNamespace(config) {
|
|
|
5605
5707
|
function tokenToUser(token) {
|
|
5606
5708
|
const payload = decodeJwtPayload(token);
|
|
5607
5709
|
if (!payload || typeof payload.sub !== "string") return null;
|
|
5710
|
+
if (typeof payload.exp === "number" && payload.exp * 1e3 < Date.now()) {
|
|
5711
|
+
return null;
|
|
5712
|
+
}
|
|
5608
5713
|
return {
|
|
5609
5714
|
uid: payload.sub,
|
|
5610
5715
|
email: typeof payload.email === "string" ? payload.email : "",
|
|
@@ -5618,12 +5723,28 @@ function createOidcAuthNamespace(config) {
|
|
|
5618
5723
|
};
|
|
5619
5724
|
}
|
|
5620
5725
|
function loadCachedUser() {
|
|
5621
|
-
if (cachedUser)
|
|
5726
|
+
if (cachedUser) {
|
|
5727
|
+
const exp = cachedUser.exp;
|
|
5728
|
+
if (typeof exp === "number" && exp * 1e3 < Date.now()) {
|
|
5729
|
+
cachedUser = null;
|
|
5730
|
+
const storage2 = getStorage();
|
|
5731
|
+
storage2?.removeItem(STORAGE_KEY);
|
|
5732
|
+
notify();
|
|
5733
|
+
return null;
|
|
5734
|
+
}
|
|
5735
|
+
return cachedUser;
|
|
5736
|
+
}
|
|
5622
5737
|
const storage = getStorage();
|
|
5623
5738
|
if (!storage) return null;
|
|
5624
5739
|
const token = storage.getItem(STORAGE_KEY);
|
|
5625
5740
|
if (!token) return null;
|
|
5626
|
-
|
|
5741
|
+
const user = tokenToUser(token);
|
|
5742
|
+
if (!user) {
|
|
5743
|
+
storage.removeItem(STORAGE_KEY);
|
|
5744
|
+
return null;
|
|
5745
|
+
}
|
|
5746
|
+
cachedUser = user;
|
|
5747
|
+
scheduleExpiryTimer(user);
|
|
5627
5748
|
return cachedUser;
|
|
5628
5749
|
}
|
|
5629
5750
|
function notify() {
|
|
@@ -5634,6 +5755,23 @@ function createOidcAuthNamespace(config) {
|
|
|
5634
5755
|
}
|
|
5635
5756
|
}
|
|
5636
5757
|
}
|
|
5758
|
+
function cancelExpiryTimer() {
|
|
5759
|
+
if (_expiryTimerId !== null) {
|
|
5760
|
+
clearTimeout(_expiryTimerId);
|
|
5761
|
+
_expiryTimerId = null;
|
|
5762
|
+
}
|
|
5763
|
+
}
|
|
5764
|
+
function scheduleExpiryTimer(user) {
|
|
5765
|
+
cancelExpiryTimer();
|
|
5766
|
+
const exp = user.exp;
|
|
5767
|
+
if (typeof exp !== "number") return;
|
|
5768
|
+
const msUntilExpiry = exp * 1e3 - Date.now();
|
|
5769
|
+
if (msUntilExpiry <= 0) return;
|
|
5770
|
+
_expiryTimerId = setTimeout(() => {
|
|
5771
|
+
_expiryTimerId = null;
|
|
5772
|
+
loadCachedUser();
|
|
5773
|
+
}, msUntilExpiry + 1);
|
|
5774
|
+
}
|
|
5637
5775
|
return {
|
|
5638
5776
|
async signIn(options) {
|
|
5639
5777
|
if (typeof globalThis.location !== "undefined" && typeof globalThis.location.assign === "function") {
|
|
@@ -5661,18 +5799,24 @@ function createOidcAuthNamespace(config) {
|
|
|
5661
5799
|
},
|
|
5662
5800
|
async signOut() {
|
|
5663
5801
|
const storage = getStorage();
|
|
5802
|
+
const storedToken = storage?.getItem(STORAGE_KEY) ?? null;
|
|
5664
5803
|
if (storage) storage.removeItem(STORAGE_KEY);
|
|
5804
|
+
cancelExpiryTimer();
|
|
5665
5805
|
cachedUser = null;
|
|
5666
5806
|
const overrideAuthUrl = typeof globalThis.NEETRU_AUTH_URL === "string" ? globalThis.NEETRU_AUTH_URL : null;
|
|
5667
5807
|
const idpOrigin = overrideAuthUrl ?? config.baseUrl.replace(/^https?:\/\/api\./, "https://auth.");
|
|
5668
5808
|
const revokeUrl = `${idpOrigin}/api/v1/oauth/revoke`;
|
|
5809
|
+
const revokeBody = storedToken ? JSON.stringify({ token: storedToken }) : null;
|
|
5669
5810
|
let revokeError = null;
|
|
5670
5811
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
5671
5812
|
try {
|
|
5672
|
-
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
|
|
5813
|
+
if (revokeBody) {
|
|
5814
|
+
await config.fetch(revokeUrl, {
|
|
5815
|
+
method: "POST",
|
|
5816
|
+
headers: { "content-type": "application/json" },
|
|
5817
|
+
body: revokeBody
|
|
5818
|
+
});
|
|
5819
|
+
}
|
|
5676
5820
|
revokeError = null;
|
|
5677
5821
|
break;
|
|
5678
5822
|
} catch (err) {
|