@neetru/sdk 3.0.2 → 3.1.1
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/CHANGELOG.md +554 -530
- package/dist/auth.cjs +219 -54
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +1 -2
- package/dist/auth.d.ts +1 -2
- package/dist/auth.mjs +219 -54
- 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 -2
- package/dist/catalog.d.ts +1 -2
- 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 -2
- package/dist/checkout.d.ts +1 -2
- package/dist/checkout.mjs +52 -3
- package/dist/checkout.mjs.map +1 -1
- package/dist/db-react.cjs +18 -6
- package/dist/db-react.cjs.map +1 -1
- package/dist/db-react.d.cts +35 -13
- package/dist/db-react.d.ts +35 -13
- package/dist/db-react.mjs +18 -6
- package/dist/db-react.mjs.map +1 -1
- package/dist/db.cjs +164 -56
- package/dist/db.cjs.map +1 -1
- package/dist/db.d.cts +1 -2
- package/dist/db.d.ts +1 -2
- package/dist/db.mjs +164 -56
- 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 -2
- package/dist/entitlements.d.ts +1 -2
- 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 +411 -0
- package/dist/firestore-compat.cjs.map +1 -0
- package/dist/firestore-compat.d.cts +319 -0
- package/dist/firestore-compat.d.ts +319 -0
- package/dist/firestore-compat.mjs +383 -0
- package/dist/firestore-compat.mjs.map +1 -0
- package/dist/index.cjs +266 -66
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -4
- package/dist/index.d.ts +9 -4
- package/dist/index.mjs +265 -67
- package/dist/index.mjs.map +1 -1
- package/dist/mocks.cjs.map +1 -1
- package/dist/mocks.d.cts +1 -2
- package/dist/mocks.d.ts +1 -2
- 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 -2
- package/dist/notifications.d.ts +1 -2
- package/dist/notifications.mjs +50 -2
- package/dist/notifications.mjs.map +1 -1
- package/dist/react.cjs +268 -2
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +135 -3
- package/dist/react.d.ts +135 -3
- package/dist/react.mjs +266 -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 -2
- package/dist/support.d.ts +1 -2
- 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 -2
- package/dist/telemetry.d.ts +1 -2
- package/dist/telemetry.mjs +65 -4
- package/dist/telemetry.mjs.map +1 -1
- package/dist/{types-D7zVkO3n.d.ts → types-B3XFHD4A.d.ts} +640 -2
- package/dist/{types-Dc4bjrrt.d.cts → types-DePdSU3P.d.cts} +640 -2
- package/dist/usage.cjs +50 -2
- package/dist/usage.cjs.map +1 -1
- package/dist/usage.d.cts +1 -2
- package/dist/usage.d.ts +1 -2
- 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 -2
- package/dist/webhooks.d.ts +1 -2
- package/dist/webhooks.mjs +83 -3
- package/dist/webhooks.mjs.map +1 -1
- package/package.json +156 -151
- package/dist/collection-ref-BDdfD87k.d.cts +0 -581
- package/dist/collection-ref-BDdfD87k.d.ts +0 -581
package/dist/db.cjs
CHANGED
|
@@ -87,8 +87,47 @@ var init_idempotency = __esm({
|
|
|
87
87
|
// src/http.ts
|
|
88
88
|
var http_exports = {};
|
|
89
89
|
__export(http_exports, {
|
|
90
|
+
checkCoreVersionCompat: () => checkCoreVersionCompat,
|
|
90
91
|
httpRequest: () => httpRequest
|
|
91
92
|
});
|
|
93
|
+
function stripRevision(v) {
|
|
94
|
+
return v.split("+")[0] ?? v;
|
|
95
|
+
}
|
|
96
|
+
function compareCalVer(a, b) {
|
|
97
|
+
const partsA = stripRevision(a).split(".").map(Number);
|
|
98
|
+
const partsB = stripRevision(b).split(".").map(Number);
|
|
99
|
+
const len = Math.max(partsA.length, partsB.length);
|
|
100
|
+
for (let i = 0; i < len; i++) {
|
|
101
|
+
const pa = partsA[i] ?? 0;
|
|
102
|
+
const pb = partsB[i] ?? 0;
|
|
103
|
+
if (pa !== pb) return pa - pb;
|
|
104
|
+
}
|
|
105
|
+
return 0;
|
|
106
|
+
}
|
|
107
|
+
function getSdkMajor() {
|
|
108
|
+
try {
|
|
109
|
+
const ver = globalThis.__NEETRU_SDK_VERSION__;
|
|
110
|
+
if (ver) return parseInt(ver.split(".")[0] ?? "3", 10);
|
|
111
|
+
} catch {
|
|
112
|
+
}
|
|
113
|
+
return 3;
|
|
114
|
+
}
|
|
115
|
+
function checkCoreVersionCompat(coreVersion) {
|
|
116
|
+
if (!coreVersion) return;
|
|
117
|
+
const sdkMajor = getSdkMajor();
|
|
118
|
+
const minCore = COMPAT_MATRIX[sdkMajor];
|
|
119
|
+
if (!minCore) return;
|
|
120
|
+
const stripped = stripRevision(coreVersion);
|
|
121
|
+
if (compareCalVer(stripped, minCore) < 0) {
|
|
122
|
+
const key = `${sdkMajor}:${stripped}`;
|
|
123
|
+
if (!_warnedCoreTooOld.has(key)) {
|
|
124
|
+
_warnedCoreTooOld.add(key);
|
|
125
|
+
console.warn(
|
|
126
|
+
`[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.`
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
92
131
|
function backoffMs(attempt) {
|
|
93
132
|
const base = 200 * Math.pow(4, attempt);
|
|
94
133
|
const jitter = base * 0.2 * (Math.random() * 2 - 1);
|
|
@@ -97,11 +136,11 @@ function backoffMs(attempt) {
|
|
|
97
136
|
function parseRetryAfter(value) {
|
|
98
137
|
if (!value) return null;
|
|
99
138
|
const secs = Number(value);
|
|
100
|
-
if (Number.isFinite(secs) && secs >= 0) return Math.round(secs * 1e3);
|
|
139
|
+
if (Number.isFinite(secs) && secs >= 0) return Math.min(Math.round(secs * 1e3), MAX_RETRY_AFTER_MS);
|
|
101
140
|
const dateMs = Date.parse(value);
|
|
102
141
|
if (Number.isFinite(dateMs)) {
|
|
103
142
|
const delta = dateMs - Date.now();
|
|
104
|
-
if (delta > 0) return delta;
|
|
143
|
+
if (delta > 0) return Math.min(delta, MAX_RETRY_AFTER_MS);
|
|
105
144
|
}
|
|
106
145
|
return null;
|
|
107
146
|
}
|
|
@@ -112,6 +151,7 @@ function statusToCode(status) {
|
|
|
112
151
|
if (status === 401) return "unauthorized";
|
|
113
152
|
if (status === 403) return "forbidden";
|
|
114
153
|
if (status === 404) return "not_found";
|
|
154
|
+
if (status === 409) return "conflict";
|
|
115
155
|
if (status === 422 || status === 400) return "validation_failed";
|
|
116
156
|
if (status === 429) return "rate_limited";
|
|
117
157
|
if (status >= 500) return "server_error";
|
|
@@ -183,6 +223,8 @@ async function httpRequest(config, opts) {
|
|
|
183
223
|
}
|
|
184
224
|
const requestId = res.headers.get("x-request-id") ?? res.headers.get("x-correlation-id") ?? void 0;
|
|
185
225
|
if (res.ok) {
|
|
226
|
+
const coreVersion = res.headers.get("x-neetru-version");
|
|
227
|
+
if (coreVersion) checkCoreVersionCompat(coreVersion);
|
|
186
228
|
const parsed = await safeJson(res);
|
|
187
229
|
return parsed;
|
|
188
230
|
}
|
|
@@ -211,11 +253,17 @@ async function httpRequest(config, opts) {
|
|
|
211
253
|
}
|
|
212
254
|
throw lastError ?? new NeetruError("unknown", "unexpected httpRequest exit");
|
|
213
255
|
}
|
|
214
|
-
var DEFAULT_RETRIES_READ, DEFAULT_RETRIES_WRITE, READ_METHODS, RETRYABLE_CODES2;
|
|
256
|
+
var COMPAT_MATRIX, _warnedCoreTooOld, DEFAULT_RETRIES_READ, DEFAULT_RETRIES_WRITE, READ_METHODS, RETRYABLE_CODES2, MAX_RETRY_AFTER_MS;
|
|
215
257
|
var init_http = __esm({
|
|
216
258
|
"src/http.ts"() {
|
|
217
259
|
init_errors();
|
|
218
260
|
init_idempotency();
|
|
261
|
+
COMPAT_MATRIX = {
|
|
262
|
+
// SDK major 3.x requer Core ≥ 2026.05.1 (suporte a X-Neetru-Version header,
|
|
263
|
+
// runTransaction write-after-read, verifyWebhookRequest, webhooks 3.0+)
|
|
264
|
+
3: "2026.05.1"
|
|
265
|
+
};
|
|
266
|
+
_warnedCoreTooOld = /* @__PURE__ */ new Set();
|
|
219
267
|
DEFAULT_RETRIES_READ = 2;
|
|
220
268
|
DEFAULT_RETRIES_WRITE = 0;
|
|
221
269
|
READ_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD"]);
|
|
@@ -224,6 +272,7 @@ var init_http = __esm({
|
|
|
224
272
|
"server_error",
|
|
225
273
|
"network_error"
|
|
226
274
|
]);
|
|
275
|
+
MAX_RETRY_AFTER_MS = 6e4;
|
|
227
276
|
}
|
|
228
277
|
});
|
|
229
278
|
|
|
@@ -790,6 +839,31 @@ var LocalStore = class {
|
|
|
790
839
|
this.db?.close();
|
|
791
840
|
this.db = null;
|
|
792
841
|
}
|
|
842
|
+
/**
|
|
843
|
+
* Apaga completamente o banco IndexedDB e o recria do zero.
|
|
844
|
+
*
|
|
845
|
+
* Ao contrário de `close()` + `open()` (que reabre o banco existente sem
|
|
846
|
+
* apagar dados), `clearAll()` chama `indexedDB.deleteDatabase(dbName)` e
|
|
847
|
+
* só então chama `open()` — garantindo que nenhum documento, mutação ou
|
|
848
|
+
* metadado sobrevive.
|
|
849
|
+
*
|
|
850
|
+
* BUG fix: `clearCache()` em `NeetruDbDocumentsImpl` chamava close+open,
|
|
851
|
+
* que reabre o mesmo banco. `clearAll()` é o método correto.
|
|
852
|
+
*/
|
|
853
|
+
async clearAll() {
|
|
854
|
+
if (this.db !== null) {
|
|
855
|
+
this.db.close();
|
|
856
|
+
this.db = null;
|
|
857
|
+
}
|
|
858
|
+
await new Promise((resolve, reject) => {
|
|
859
|
+
const req = indexedDB.deleteDatabase(this.dbName);
|
|
860
|
+
req.onsuccess = () => resolve();
|
|
861
|
+
req.onerror = () => reject(req.error);
|
|
862
|
+
req.onblocked = () => {
|
|
863
|
+
};
|
|
864
|
+
});
|
|
865
|
+
await this.open();
|
|
866
|
+
}
|
|
793
867
|
assertOpen() {
|
|
794
868
|
if (this.db === null) {
|
|
795
869
|
throw new Error("LocalStore: banco n\xE3o est\xE1 aberto. Chame open() primeiro.");
|
|
@@ -997,6 +1071,12 @@ var MemoryStore = class {
|
|
|
997
1071
|
async open() {
|
|
998
1072
|
}
|
|
999
1073
|
async close() {
|
|
1074
|
+
}
|
|
1075
|
+
/**
|
|
1076
|
+
* Apaga todos os dados em memória — equivalente ao `indexedDB.deleteDatabase`
|
|
1077
|
+
* que `LocalStore.clearAll()` executa em ambientes com IndexedDB.
|
|
1078
|
+
*/
|
|
1079
|
+
async clearAll() {
|
|
1000
1080
|
this._docs.clear();
|
|
1001
1081
|
this._mutations.clear();
|
|
1002
1082
|
this._meta.clear();
|
|
@@ -1352,7 +1432,71 @@ var MutationQueue = class {
|
|
|
1352
1432
|
}
|
|
1353
1433
|
};
|
|
1354
1434
|
|
|
1435
|
+
// src/db/field-value.ts
|
|
1436
|
+
var NEETRU_SENTINEL_KEY = "__neetru__";
|
|
1437
|
+
function serverTimestamp() {
|
|
1438
|
+
return { __neetru__: "serverTimestamp" };
|
|
1439
|
+
}
|
|
1440
|
+
function increment(n) {
|
|
1441
|
+
if (typeof n !== "number" || !Number.isFinite(n)) {
|
|
1442
|
+
throw new TypeError(
|
|
1443
|
+
`increment(n): n deve ser um n\xFAmero finito (recebido: ${String(n)}).`
|
|
1444
|
+
);
|
|
1445
|
+
}
|
|
1446
|
+
return { __neetru__: "increment", operand: n };
|
|
1447
|
+
}
|
|
1448
|
+
function isFieldSentinel(v) {
|
|
1449
|
+
return typeof v === "object" && v !== null && NEETRU_SENTINEL_KEY in v && typeof v[NEETRU_SENTINEL_KEY] === "string";
|
|
1450
|
+
}
|
|
1451
|
+
function isServerTimestampSentinel(v) {
|
|
1452
|
+
return isFieldSentinel(v) && v.__neetru__ === "serverTimestamp";
|
|
1453
|
+
}
|
|
1454
|
+
function isIncrementSentinel(v) {
|
|
1455
|
+
return isFieldSentinel(v) && v.__neetru__ === "increment" && typeof v.operand === "number" && Number.isFinite(v.operand);
|
|
1456
|
+
}
|
|
1457
|
+
function resolveSentinelLocally(value, baseValue) {
|
|
1458
|
+
if (isServerTimestampSentinel(value)) {
|
|
1459
|
+
return Date.now();
|
|
1460
|
+
}
|
|
1461
|
+
if (isIncrementSentinel(value)) {
|
|
1462
|
+
const base = typeof baseValue === "number" && Number.isFinite(baseValue) ? baseValue : 0;
|
|
1463
|
+
return base + value.operand;
|
|
1464
|
+
}
|
|
1465
|
+
return value;
|
|
1466
|
+
}
|
|
1467
|
+
function resolveSentinelsLocally(data, existing) {
|
|
1468
|
+
let touched = false;
|
|
1469
|
+
const out = {};
|
|
1470
|
+
for (const [k, v] of Object.entries(data)) {
|
|
1471
|
+
if (isFieldSentinel(v)) {
|
|
1472
|
+
touched = true;
|
|
1473
|
+
out[k] = resolveSentinelLocally(v, existing?.[k]);
|
|
1474
|
+
} else {
|
|
1475
|
+
out[k] = v;
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
return touched ? out : data;
|
|
1479
|
+
}
|
|
1480
|
+
function hasFieldSentinel(data) {
|
|
1481
|
+
for (const v of Object.values(data)) {
|
|
1482
|
+
if (isFieldSentinel(v)) return true;
|
|
1483
|
+
}
|
|
1484
|
+
return false;
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1355
1487
|
// src/db/offline/sync-engine.ts
|
|
1488
|
+
function hasSentinels(payload) {
|
|
1489
|
+
return payload !== null && hasFieldSentinel(payload);
|
|
1490
|
+
}
|
|
1491
|
+
function sanitizeSentinelPayload(payload) {
|
|
1492
|
+
if (payload === null) return null;
|
|
1493
|
+
if (!hasFieldSentinel(payload)) return payload;
|
|
1494
|
+
const out = {};
|
|
1495
|
+
for (const [k, v] of Object.entries(payload)) {
|
|
1496
|
+
if (!isFieldSentinel(v)) out[k] = v;
|
|
1497
|
+
}
|
|
1498
|
+
return out;
|
|
1499
|
+
}
|
|
1356
1500
|
var SyncEngine = class {
|
|
1357
1501
|
_store;
|
|
1358
1502
|
_queue;
|
|
@@ -1458,6 +1602,8 @@ var SyncEngine = class {
|
|
|
1458
1602
|
const phase1Ok = await this._phase1Push();
|
|
1459
1603
|
if (!phase1Ok) {
|
|
1460
1604
|
this._updateState({ status: "idle" });
|
|
1605
|
+
this._refreshPendingWrites().catch(() => {
|
|
1606
|
+
});
|
|
1461
1607
|
this._syncing = false;
|
|
1462
1608
|
return;
|
|
1463
1609
|
}
|
|
@@ -1560,11 +1706,16 @@ var SyncEngine = class {
|
|
|
1560
1706
|
}
|
|
1561
1707
|
return;
|
|
1562
1708
|
}
|
|
1563
|
-
const
|
|
1709
|
+
const literalPayload = sanitizeSentinelPayload(mut.payload);
|
|
1710
|
+
const newData = literalPayload ?? (existing?.data ?? {});
|
|
1564
1711
|
const updatedDoc = {
|
|
1565
1712
|
collection,
|
|
1566
1713
|
id: docId,
|
|
1567
|
-
data: mut.op === "update" ? { ...existing?.data ?? {}, ...newData } :
|
|
1714
|
+
data: mut.op === "update" ? { ...existing?.data ?? {}, ...newData } : (
|
|
1715
|
+
// add/set: se o payload tinha sentinels, o cache otimista (existing.data)
|
|
1716
|
+
// é a fonte de verdade até o pull; senão usa o payload literal.
|
|
1717
|
+
hasSentinels(mut.payload) ? { ...existing?.data ?? {}, ...newData } : newData
|
|
1718
|
+
),
|
|
1568
1719
|
meta: {
|
|
1569
1720
|
serverVersion,
|
|
1570
1721
|
updatedAtServer: serverTimestamp2,
|
|
@@ -1839,7 +1990,7 @@ var SyncEngine = class {
|
|
|
1839
1990
|
ownerId: localDoc.meta.ownerId
|
|
1840
1991
|
}
|
|
1841
1992
|
};
|
|
1842
|
-
const pendingMuts = await this._queue.
|
|
1993
|
+
const pendingMuts = await this._queue.listAll();
|
|
1843
1994
|
const docMut = pendingMuts.find(
|
|
1844
1995
|
(m) => m.collection === serverDoc.collection && m.docId === serverDoc.id
|
|
1845
1996
|
);
|
|
@@ -2646,54 +2797,6 @@ var TabCoordinator = class {
|
|
|
2646
2797
|
|
|
2647
2798
|
// src/db/collection-ref.ts
|
|
2648
2799
|
init_db_errors();
|
|
2649
|
-
|
|
2650
|
-
// src/db/field-value.ts
|
|
2651
|
-
var NEETRU_SENTINEL_KEY = "__neetru__";
|
|
2652
|
-
function serverTimestamp() {
|
|
2653
|
-
return { __neetru__: "serverTimestamp" };
|
|
2654
|
-
}
|
|
2655
|
-
function increment(n) {
|
|
2656
|
-
if (typeof n !== "number" || !Number.isFinite(n)) {
|
|
2657
|
-
throw new TypeError(
|
|
2658
|
-
`increment(n): n deve ser um n\xFAmero finito (recebido: ${String(n)}).`
|
|
2659
|
-
);
|
|
2660
|
-
}
|
|
2661
|
-
return { __neetru__: "increment", operand: n };
|
|
2662
|
-
}
|
|
2663
|
-
function isFieldSentinel(v) {
|
|
2664
|
-
return typeof v === "object" && v !== null && NEETRU_SENTINEL_KEY in v && typeof v[NEETRU_SENTINEL_KEY] === "string";
|
|
2665
|
-
}
|
|
2666
|
-
function isServerTimestampSentinel(v) {
|
|
2667
|
-
return isFieldSentinel(v) && v.__neetru__ === "serverTimestamp";
|
|
2668
|
-
}
|
|
2669
|
-
function isIncrementSentinel(v) {
|
|
2670
|
-
return isFieldSentinel(v) && v.__neetru__ === "increment" && typeof v.operand === "number" && Number.isFinite(v.operand);
|
|
2671
|
-
}
|
|
2672
|
-
function resolveSentinelLocally(value, baseValue) {
|
|
2673
|
-
if (isServerTimestampSentinel(value)) {
|
|
2674
|
-
return Date.now();
|
|
2675
|
-
}
|
|
2676
|
-
if (isIncrementSentinel(value)) {
|
|
2677
|
-
const base = typeof baseValue === "number" && Number.isFinite(baseValue) ? baseValue : 0;
|
|
2678
|
-
return base + value.operand;
|
|
2679
|
-
}
|
|
2680
|
-
return value;
|
|
2681
|
-
}
|
|
2682
|
-
function resolveSentinelsLocally(data, existing) {
|
|
2683
|
-
let touched = false;
|
|
2684
|
-
const out = {};
|
|
2685
|
-
for (const [k, v] of Object.entries(data)) {
|
|
2686
|
-
if (isFieldSentinel(v)) {
|
|
2687
|
-
touched = true;
|
|
2688
|
-
out[k] = resolveSentinelLocally(v, existing?.[k]);
|
|
2689
|
-
} else {
|
|
2690
|
-
out[k] = v;
|
|
2691
|
-
}
|
|
2692
|
-
}
|
|
2693
|
-
return touched ? out : data;
|
|
2694
|
-
}
|
|
2695
|
-
|
|
2696
|
-
// src/db/collection-ref.ts
|
|
2697
2800
|
function isIndexedDBUnavailable() {
|
|
2698
2801
|
return typeof indexedDB === "undefined" || typeof window === "undefined";
|
|
2699
2802
|
}
|
|
@@ -3241,8 +3344,13 @@ var NeetruDbDocumentsImpl = class {
|
|
|
3241
3344
|
return this._engine.flush();
|
|
3242
3345
|
}
|
|
3243
3346
|
async clearCache() {
|
|
3244
|
-
|
|
3245
|
-
|
|
3347
|
+
const storeWithClear = this._store;
|
|
3348
|
+
if (typeof storeWithClear.clearAll === "function") {
|
|
3349
|
+
await storeWithClear.clearAll();
|
|
3350
|
+
} else {
|
|
3351
|
+
await this._store.close();
|
|
3352
|
+
await this._store.open();
|
|
3353
|
+
}
|
|
3246
3354
|
}
|
|
3247
3355
|
async getConflicts() {
|
|
3248
3356
|
return this._store.listConflicts();
|