on-zero 0.6.2 → 0.6.3
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/cjs/helpers/recoverZeroClient.cjs +64 -7
- package/dist/cjs/helpers/recoverZeroClient.native.js +72 -9
- package/dist/cjs/helpers/recoverZeroClient.native.js.map +1 -1
- package/dist/cjs/helpers/recoverZeroClient.test.cjs +60 -0
- package/dist/cjs/helpers/recoverZeroClient.test.native.js +60 -0
- package/dist/cjs/helpers/recoverZeroClient.test.native.js.map +1 -1
- package/dist/cjs/index.cjs +1 -0
- package/dist/cjs/index.native.js +1 -0
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/esm/helpers/recoverZeroClient.mjs +64 -8
- package/dist/esm/helpers/recoverZeroClient.mjs.map +1 -1
- package/dist/esm/helpers/recoverZeroClient.native.js +72 -10
- package/dist/esm/helpers/recoverZeroClient.native.js.map +1 -1
- package/dist/esm/helpers/recoverZeroClient.test.mjs +61 -1
- package/dist/esm/helpers/recoverZeroClient.test.mjs.map +1 -1
- package/dist/esm/helpers/recoverZeroClient.test.native.js +61 -1
- package/dist/esm/helpers/recoverZeroClient.test.native.js.map +1 -1
- package/dist/esm/index.js +2 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.mjs +2 -2
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js +2 -2
- package/dist/esm/index.native.js.map +1 -1
- package/package.json +2 -2
- package/src/helpers/recoverZeroClient.test.ts +66 -0
- package/src/helpers/recoverZeroClient.ts +91 -15
- package/src/index.ts +3 -0
- package/types/helpers/recoverZeroClient.d.ts +9 -1
- package/types/helpers/recoverZeroClient.d.ts.map +1 -1
- package/types/index.d.ts +1 -1
- package/types/index.d.ts.map +1 -1
|
@@ -22,6 +22,7 @@ var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
|
|
|
22
22
|
}), mod);
|
|
23
23
|
var recoverZeroClient_exports = {};
|
|
24
24
|
__export(recoverZeroClient_exports, {
|
|
25
|
+
classifyZeroRecoveryLog: () => classifyZeroRecoveryLog,
|
|
25
26
|
composeRecoveryLogSink: () => composeRecoveryLogSink,
|
|
26
27
|
makeZeroRecovery: () => makeZeroRecovery,
|
|
27
28
|
resetRecoveryStateForTests: () => resetRecoveryStateForTests
|
|
@@ -29,17 +30,25 @@ __export(recoverZeroClient_exports, {
|
|
|
29
30
|
module.exports = __toCommonJS(recoverZeroClient_exports);
|
|
30
31
|
const RECOVER_GUARD_MS = 6e4;
|
|
31
32
|
const LOCAL_STORE_LOST = "Expected IndexedDB not found";
|
|
33
|
+
const SQLITE_ERROR_NAME = "SqliteError";
|
|
34
|
+
const SQLITE_STATEMENT_FINALIZED = "This statement has been finalized";
|
|
35
|
+
const STORE_CLOSED = "Store is closed";
|
|
36
|
+
const STORE_CLOSED_REPEAT_MIN_MS = 2e3;
|
|
37
|
+
const STORE_CLOSED_REPEAT_MAX_MS = 6e4;
|
|
32
38
|
let reloadScheduled = false;
|
|
33
39
|
const pendingDeletes = [];
|
|
34
40
|
function recoveryGuardOpen(reasonKey) {
|
|
35
41
|
try {
|
|
36
42
|
const key = `on-zero-recover-${reasonKey}`;
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
43
|
+
const rawLast = window.sessionStorage.getItem(key);
|
|
44
|
+
const now = Date.now();
|
|
45
|
+
const last = rawLast ? Number(rawLast) : 0;
|
|
46
|
+
if (last > 0 && now - last < RECOVER_GUARD_MS) return false;
|
|
47
|
+
window.sessionStorage.setItem(key, String(now));
|
|
40
48
|
} catch {}
|
|
41
49
|
return true;
|
|
42
50
|
}
|
|
51
|
+
let lastStoreClosedAtMs = 0;
|
|
43
52
|
function recover(deps, reasonKey, message, dropLocalState) {
|
|
44
53
|
if (typeof window === "undefined") return;
|
|
45
54
|
if (dropLocalState) {
|
|
@@ -79,15 +88,62 @@ function logToConsole(level, context, ...args) {
|
|
|
79
88
|
const method = level === "debug" ? "debug" : level;
|
|
80
89
|
console[method](...(prefix ? [prefix] : []), ...args);
|
|
81
90
|
}
|
|
91
|
+
function logArgText(arg) {
|
|
92
|
+
if (typeof arg === "string") return arg;
|
|
93
|
+
if (arg instanceof Error) return `${arg.name} ${arg.message} ${arg.stack || ""}`;
|
|
94
|
+
if (arg && typeof arg === "object") {
|
|
95
|
+
const message = "message" in arg ? arg.message : void 0;
|
|
96
|
+
const name = "name" in arg ? arg.name : void 0;
|
|
97
|
+
if (typeof message === "string") return `${typeof name === "string" ? name : ""} ${message}`;
|
|
98
|
+
}
|
|
99
|
+
return "";
|
|
100
|
+
}
|
|
101
|
+
function isBenignStoreClosedLog(text) {
|
|
102
|
+
if (/Mutator\s+".*"\s+error on server/i.test(text)) return true;
|
|
103
|
+
if (/Mutator\s+".*"\s+app error on client/i.test(text)) return true;
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
function classifyZeroRecoveryLog(level, args, nowMs = Date.now()) {
|
|
107
|
+
if (level !== "error") return void 0;
|
|
108
|
+
const text = args.map(logArgText).join(" ");
|
|
109
|
+
if (text.includes(LOCAL_STORE_LOST)) {
|
|
110
|
+
return {
|
|
111
|
+
reason: "indexeddb-not-found",
|
|
112
|
+
reasonKey: "local-store",
|
|
113
|
+
message: "local store lost",
|
|
114
|
+
dropLocalState: true
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
if (text.includes(SQLITE_ERROR_NAME) && text.includes(SQLITE_STATEMENT_FINALIZED)) {
|
|
118
|
+
return {
|
|
119
|
+
reason: "sqlite-statement-finalized",
|
|
120
|
+
reasonKey: "sqlite-statement-finalized",
|
|
121
|
+
message: "sqlite statement finalized",
|
|
122
|
+
dropLocalState: true
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
if (text.includes(STORE_CLOSED) && !isBenignStoreClosedLog(text)) {
|
|
126
|
+
const prevMs = lastStoreClosedAtMs;
|
|
127
|
+
lastStoreClosedAtMs = nowMs;
|
|
128
|
+
if (prevMs > 0 && nowMs - prevMs >= STORE_CLOSED_REPEAT_MIN_MS && nowMs - prevMs <= STORE_CLOSED_REPEAT_MAX_MS) {
|
|
129
|
+
return {
|
|
130
|
+
reason: "store-closed-repeat",
|
|
131
|
+
reasonKey: "store-closed-repeat",
|
|
132
|
+
message: "local store closed repeatedly",
|
|
133
|
+
dropLocalState: true
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return void 0;
|
|
138
|
+
}
|
|
82
139
|
function composeRecoveryLogSink(deps, consumerLogSink) {
|
|
83
140
|
const consumerFlush = consumerLogSink?.flush;
|
|
84
141
|
return {
|
|
85
142
|
log(level, context, ...args) {
|
|
86
143
|
if (consumerLogSink) consumerLogSink.log(level, context, ...args);else logToConsole(level, context, ...args);
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
recover(deps, "local-store", "local store lost", true);
|
|
144
|
+
const recovery = classifyZeroRecoveryLog(level, args);
|
|
145
|
+
if (recovery) {
|
|
146
|
+
recover(deps, recovery.reasonKey, recovery.message, recovery.dropLocalState);
|
|
91
147
|
}
|
|
92
148
|
},
|
|
93
149
|
// call through the consumer sink so a class-based sink keeps its `this`,
|
|
@@ -98,4 +154,5 @@ function composeRecoveryLogSink(deps, consumerLogSink) {
|
|
|
98
154
|
function resetRecoveryStateForTests() {
|
|
99
155
|
reloadScheduled = false;
|
|
100
156
|
pendingDeletes.length = 0;
|
|
157
|
+
lastStoreClosedAtMs = 0;
|
|
101
158
|
}
|
|
@@ -24,11 +24,19 @@ var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
|
|
|
24
24
|
}), mod);
|
|
25
25
|
var recoverZeroClient_exports = {};
|
|
26
26
|
__export(recoverZeroClient_exports, {
|
|
27
|
+
classifyZeroRecoveryLog: () => classifyZeroRecoveryLog,
|
|
27
28
|
composeRecoveryLogSink: () => composeRecoveryLogSink,
|
|
28
29
|
makeZeroRecovery: () => makeZeroRecovery,
|
|
29
30
|
resetRecoveryStateForTests: () => resetRecoveryStateForTests
|
|
30
31
|
});
|
|
31
32
|
module.exports = __toCommonJS(recoverZeroClient_exports);
|
|
33
|
+
function _instanceof(left, right) {
|
|
34
|
+
if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
|
|
35
|
+
return !!right[Symbol.hasInstance](left);
|
|
36
|
+
} else {
|
|
37
|
+
return left instanceof right;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
32
40
|
function _type_of(obj) {
|
|
33
41
|
"@swc/helpers - typeof";
|
|
34
42
|
|
|
@@ -36,17 +44,25 @@ function _type_of(obj) {
|
|
|
36
44
|
}
|
|
37
45
|
var RECOVER_GUARD_MS = 6e4;
|
|
38
46
|
var LOCAL_STORE_LOST = "Expected IndexedDB not found";
|
|
47
|
+
var SQLITE_ERROR_NAME = "SqliteError";
|
|
48
|
+
var SQLITE_STATEMENT_FINALIZED = "This statement has been finalized";
|
|
49
|
+
var STORE_CLOSED = "Store is closed";
|
|
50
|
+
var STORE_CLOSED_REPEAT_MIN_MS = 2e3;
|
|
51
|
+
var STORE_CLOSED_REPEAT_MAX_MS = 6e4;
|
|
39
52
|
var reloadScheduled = false;
|
|
40
53
|
var pendingDeletes = [];
|
|
41
54
|
function recoveryGuardOpen(reasonKey) {
|
|
42
55
|
try {
|
|
43
56
|
var key = `on-zero-recover-${reasonKey}`;
|
|
44
|
-
var
|
|
45
|
-
|
|
46
|
-
|
|
57
|
+
var rawLast = window.sessionStorage.getItem(key);
|
|
58
|
+
var now = Date.now();
|
|
59
|
+
var last = rawLast ? Number(rawLast) : 0;
|
|
60
|
+
if (last > 0 && now - last < RECOVER_GUARD_MS) return false;
|
|
61
|
+
window.sessionStorage.setItem(key, String(now));
|
|
47
62
|
} catch (e) {}
|
|
48
63
|
return true;
|
|
49
64
|
}
|
|
65
|
+
var lastStoreClosedAtMs = 0;
|
|
50
66
|
function recover(deps, reasonKey, message, dropLocalState) {
|
|
51
67
|
if (typeof window === "undefined") return;
|
|
52
68
|
if (dropLocalState) {
|
|
@@ -101,6 +117,55 @@ function logToConsole(level, context) {
|
|
|
101
117
|
var method = level === "debug" ? "debug" : level;
|
|
102
118
|
console[method](...(prefix ? [prefix] : []), ...args);
|
|
103
119
|
}
|
|
120
|
+
function logArgText(arg) {
|
|
121
|
+
if (typeof arg === "string") return arg;
|
|
122
|
+
if (_instanceof(arg, Error)) return `${arg.name} ${arg.message} ${arg.stack || ""}`;
|
|
123
|
+
if (arg && (typeof arg === "undefined" ? "undefined" : _type_of(arg)) === "object") {
|
|
124
|
+
var message = "message" in arg ? arg.message : void 0;
|
|
125
|
+
var name = "name" in arg ? arg.name : void 0;
|
|
126
|
+
if (typeof message === "string") return `${typeof name === "string" ? name : ""} ${message}`;
|
|
127
|
+
}
|
|
128
|
+
return "";
|
|
129
|
+
}
|
|
130
|
+
function isBenignStoreClosedLog(text) {
|
|
131
|
+
if (/Mutator\s+".*"\s+error on server/i.test(text)) return true;
|
|
132
|
+
if (/Mutator\s+".*"\s+app error on client/i.test(text)) return true;
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
function classifyZeroRecoveryLog(level, args) {
|
|
136
|
+
var nowMs = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : Date.now();
|
|
137
|
+
if (level !== "error") return void 0;
|
|
138
|
+
var text = args.map(logArgText).join(" ");
|
|
139
|
+
if (text.includes(LOCAL_STORE_LOST)) {
|
|
140
|
+
return {
|
|
141
|
+
reason: "indexeddb-not-found",
|
|
142
|
+
reasonKey: "local-store",
|
|
143
|
+
message: "local store lost",
|
|
144
|
+
dropLocalState: true
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
if (text.includes(SQLITE_ERROR_NAME) && text.includes(SQLITE_STATEMENT_FINALIZED)) {
|
|
148
|
+
return {
|
|
149
|
+
reason: "sqlite-statement-finalized",
|
|
150
|
+
reasonKey: "sqlite-statement-finalized",
|
|
151
|
+
message: "sqlite statement finalized",
|
|
152
|
+
dropLocalState: true
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
if (text.includes(STORE_CLOSED) && !isBenignStoreClosedLog(text)) {
|
|
156
|
+
var prevMs = lastStoreClosedAtMs;
|
|
157
|
+
lastStoreClosedAtMs = nowMs;
|
|
158
|
+
if (prevMs > 0 && nowMs - prevMs >= STORE_CLOSED_REPEAT_MIN_MS && nowMs - prevMs <= STORE_CLOSED_REPEAT_MAX_MS) {
|
|
159
|
+
return {
|
|
160
|
+
reason: "store-closed-repeat",
|
|
161
|
+
reasonKey: "store-closed-repeat",
|
|
162
|
+
message: "local store closed repeatedly",
|
|
163
|
+
dropLocalState: true
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return void 0;
|
|
168
|
+
}
|
|
104
169
|
function composeRecoveryLogSink(deps, consumerLogSink) {
|
|
105
170
|
var consumerFlush = consumerLogSink === null || consumerLogSink === void 0 ? void 0 : consumerLogSink.flush;
|
|
106
171
|
return {
|
|
@@ -109,12 +174,9 @@ function composeRecoveryLogSink(deps, consumerLogSink) {
|
|
|
109
174
|
args[_key - 2] = arguments[_key];
|
|
110
175
|
}
|
|
111
176
|
if (consumerLogSink) consumerLogSink.log(level, context, ...args);else logToConsole(level, context, ...args);
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}).join(" ");
|
|
116
|
-
if (text.includes(LOCAL_STORE_LOST)) {
|
|
117
|
-
recover(deps, "local-store", "local store lost", true);
|
|
177
|
+
var recovery = classifyZeroRecoveryLog(level, args);
|
|
178
|
+
if (recovery) {
|
|
179
|
+
recover(deps, recovery.reasonKey, recovery.message, recovery.dropLocalState);
|
|
118
180
|
}
|
|
119
181
|
},
|
|
120
182
|
// call through the consumer sink so a class-based sink keeps its `this`,
|
|
@@ -127,5 +189,6 @@ function composeRecoveryLogSink(deps, consumerLogSink) {
|
|
|
127
189
|
function resetRecoveryStateForTests() {
|
|
128
190
|
reloadScheduled = false;
|
|
129
191
|
pendingDeletes.length = 0;
|
|
192
|
+
lastStoreClosedAtMs = 0;
|
|
130
193
|
}
|
|
131
194
|
//# sourceMappingURL=recoverZeroClient.native.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["__toCommonJS","mod","__copyProps","__defProp","value","recoverZeroClient_exports","__export","composeRecoveryLogSink","makeZeroRecovery","resetRecoveryStateForTests","module","exports","
|
|
1
|
+
{"version":3,"names":["__toCommonJS","mod","__copyProps","__defProp","value","recoverZeroClient_exports","__export","classifyZeroRecoveryLog","composeRecoveryLogSink","makeZeroRecovery","resetRecoveryStateForTests","module","exports","_instanceof","left","right","Symbol","hasInstance","_type_of","obj","constructor","RECOVER_GUARD_MS","LOCAL_STORE_LOST","SQLITE_ERROR_NAME","SQLITE_STATEMENT_FINALIZED","STORE_CLOSED","STORE_CLOSED_REPEAT_MIN_MS","STORE_CLOSED_REPEAT_MAX_MS","reloadScheduled","pendingDeletes","recoveryGuardOpen","reasonKey","key","rawLast","window","sessionStorage","getItem","now","Date","last","Number","setItem","String","e","lastStoreClosedAtMs","recover","deps","message","dropLocalState","push","Promise","resolve","then","deleteLocalState","catch","console","error","zeroEvents","emit","type","reason","warn","_deps_reload","doReload","reload","_globalThis_location_reload","_globalThis_location","globalThis","location","call","allSettled","_deps_beforeReload","beforeReload","finally","onUpdateNeeded","onClientStateNotFound","logToConsole","level","context","_len","arguments","length","args","Array","_key","prefix","Object","entries","map","param","join","method","logArgText","arg","Error","name","stack","isBenignStoreClosedLog","text","test","nowMs","includes","prevMs"],"sources":["../../../src/helpers/recoverZeroClient.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|
|
@@ -150,6 +150,45 @@ async function flush() {
|
|
|
150
150
|
(0, import_vitest.expect)(deleteLocalState).toHaveBeenCalledTimes(1);
|
|
151
151
|
(0, import_vitest.expect)(reload).toHaveBeenCalledTimes(1);
|
|
152
152
|
});
|
|
153
|
+
(0, import_vitest.test)("logSink recovers on native sqlite finalized-statement local-store loss", async () => {
|
|
154
|
+
const {
|
|
155
|
+
deps,
|
|
156
|
+
deleteLocalState,
|
|
157
|
+
reload
|
|
158
|
+
} = setup();
|
|
159
|
+
const sqliteError = new Error("This statement has been finalized");
|
|
160
|
+
sqliteError.name = "SqliteError";
|
|
161
|
+
const sink = (0, import_recoverZeroClient.composeRecoveryLogSink)(deps);
|
|
162
|
+
sink.log("error", {
|
|
163
|
+
bgIntervalProcess: "Heartbeat"
|
|
164
|
+
}, "Error running.", sqliteError);
|
|
165
|
+
await flush();
|
|
166
|
+
(0, import_vitest.expect)(deleteLocalState).toHaveBeenCalledTimes(1);
|
|
167
|
+
(0, import_vitest.expect)(reload).toHaveBeenCalledTimes(1);
|
|
168
|
+
});
|
|
169
|
+
(0, import_vitest.test)("logSink recovers on repeated store-closed local-store loss", async () => {
|
|
170
|
+
const nowSpy = import_vitest.vi.spyOn(Date, "now");
|
|
171
|
+
const {
|
|
172
|
+
deps,
|
|
173
|
+
deleteLocalState,
|
|
174
|
+
reload
|
|
175
|
+
} = setup();
|
|
176
|
+
try {
|
|
177
|
+
const sink = (0, import_recoverZeroClient.composeRecoveryLogSink)(deps);
|
|
178
|
+
nowSpy.mockReturnValue(1e4);
|
|
179
|
+
sink.log("error", void 0, "Failed to connect.", new Error("Store is closed"));
|
|
180
|
+
await flush();
|
|
181
|
+
(0, import_vitest.expect)(deleteLocalState).not.toHaveBeenCalled();
|
|
182
|
+
(0, import_vitest.expect)(reload).not.toHaveBeenCalled();
|
|
183
|
+
nowSpy.mockReturnValue(13e3);
|
|
184
|
+
sink.log("error", void 0, "Failed to connect.", new Error("Store is closed"));
|
|
185
|
+
await flush();
|
|
186
|
+
(0, import_vitest.expect)(deleteLocalState).toHaveBeenCalledTimes(1);
|
|
187
|
+
(0, import_vitest.expect)(reload).toHaveBeenCalledTimes(1);
|
|
188
|
+
} finally {
|
|
189
|
+
nowSpy.mockRestore();
|
|
190
|
+
}
|
|
191
|
+
});
|
|
153
192
|
(0, import_vitest.test)("logSink with no consumer preserves console output and still watches", async () => {
|
|
154
193
|
const {
|
|
155
194
|
deps,
|
|
@@ -198,6 +237,27 @@ async function flush() {
|
|
|
198
237
|
(0, import_vitest.expect)(deleteLocalState).not.toHaveBeenCalled();
|
|
199
238
|
(0, import_vitest.expect)(reload).not.toHaveBeenCalled();
|
|
200
239
|
});
|
|
240
|
+
(0, import_vitest.test)("recovery log classification is narrow", () => {
|
|
241
|
+
const sqliteError = new Error("This statement has been finalized");
|
|
242
|
+
sqliteError.name = "SqliteError";
|
|
243
|
+
(0, import_vitest.expect)((0, import_recoverZeroClient.classifyZeroRecoveryLog)("error", ["Error running.", sqliteError])).toMatchObject({
|
|
244
|
+
reason: "sqlite-statement-finalized",
|
|
245
|
+
dropLocalState: true
|
|
246
|
+
});
|
|
247
|
+
(0, import_vitest.expect)((0, import_recoverZeroClient.classifyZeroRecoveryLog)("error", [{
|
|
248
|
+
name: "SqliteError",
|
|
249
|
+
message: "database is locked"
|
|
250
|
+
}])).toBeUndefined();
|
|
251
|
+
(0, import_vitest.expect)((0, import_recoverZeroClient.classifyZeroRecoveryLog)("warn", ["Expected IndexedDB not found"])).toBeUndefined();
|
|
252
|
+
(0, import_vitest.expect)((0, import_recoverZeroClient.classifyZeroRecoveryLog)("error", ["Store is closed"], 1e4)).toBeUndefined();
|
|
253
|
+
(0, import_vitest.expect)((0, import_recoverZeroClient.classifyZeroRecoveryLog)("error", ["Store is closed"], 11e3)).toBeUndefined();
|
|
254
|
+
(0, import_vitest.expect)((0, import_recoverZeroClient.classifyZeroRecoveryLog)("error", ["Store is closed"], 14e3)).toMatchObject({
|
|
255
|
+
reason: "store-closed-repeat",
|
|
256
|
+
dropLocalState: true
|
|
257
|
+
});
|
|
258
|
+
(0, import_recoverZeroClient.resetRecoveryStateForTests)();
|
|
259
|
+
(0, import_vitest.expect)((0, import_recoverZeroClient.classifyZeroRecoveryLog)("error", ['Mutator "send" error on server', "Store is closed"], 2e4)).toBeUndefined();
|
|
260
|
+
});
|
|
201
261
|
(0, import_vitest.test)("default reload path is a safe no-op when location is absent", async () => {
|
|
202
262
|
const events = [];
|
|
203
263
|
const zeroEvents = (0, import_helpers.createEmitter)(`test-recover-${emitterSeq++}`, null);
|
|
@@ -192,6 +192,45 @@ async function flush() {
|
|
|
192
192
|
(0, import_vitest.expect)(deleteLocalState).toHaveBeenCalledTimes(1);
|
|
193
193
|
(0, import_vitest.expect)(reload).toHaveBeenCalledTimes(1);
|
|
194
194
|
});
|
|
195
|
+
(0, import_vitest.test)("logSink recovers on native sqlite finalized-statement local-store loss", async function () {
|
|
196
|
+
var {
|
|
197
|
+
deps,
|
|
198
|
+
deleteLocalState,
|
|
199
|
+
reload
|
|
200
|
+
} = setup();
|
|
201
|
+
var sqliteError = new Error("This statement has been finalized");
|
|
202
|
+
sqliteError.name = "SqliteError";
|
|
203
|
+
var sink = (0, import_recoverZeroClient.composeRecoveryLogSink)(deps);
|
|
204
|
+
sink.log("error", {
|
|
205
|
+
bgIntervalProcess: "Heartbeat"
|
|
206
|
+
}, "Error running.", sqliteError);
|
|
207
|
+
await flush();
|
|
208
|
+
(0, import_vitest.expect)(deleteLocalState).toHaveBeenCalledTimes(1);
|
|
209
|
+
(0, import_vitest.expect)(reload).toHaveBeenCalledTimes(1);
|
|
210
|
+
});
|
|
211
|
+
(0, import_vitest.test)("logSink recovers on repeated store-closed local-store loss", async function () {
|
|
212
|
+
var nowSpy = import_vitest.vi.spyOn(Date, "now");
|
|
213
|
+
var {
|
|
214
|
+
deps,
|
|
215
|
+
deleteLocalState,
|
|
216
|
+
reload
|
|
217
|
+
} = setup();
|
|
218
|
+
try {
|
|
219
|
+
var sink = (0, import_recoverZeroClient.composeRecoveryLogSink)(deps);
|
|
220
|
+
nowSpy.mockReturnValue(1e4);
|
|
221
|
+
sink.log("error", void 0, "Failed to connect.", new Error("Store is closed"));
|
|
222
|
+
await flush();
|
|
223
|
+
(0, import_vitest.expect)(deleteLocalState).not.toHaveBeenCalled();
|
|
224
|
+
(0, import_vitest.expect)(reload).not.toHaveBeenCalled();
|
|
225
|
+
nowSpy.mockReturnValue(13e3);
|
|
226
|
+
sink.log("error", void 0, "Failed to connect.", new Error("Store is closed"));
|
|
227
|
+
await flush();
|
|
228
|
+
(0, import_vitest.expect)(deleteLocalState).toHaveBeenCalledTimes(1);
|
|
229
|
+
(0, import_vitest.expect)(reload).toHaveBeenCalledTimes(1);
|
|
230
|
+
} finally {
|
|
231
|
+
nowSpy.mockRestore();
|
|
232
|
+
}
|
|
233
|
+
});
|
|
195
234
|
(0, import_vitest.test)("logSink with no consumer preserves console output and still watches", async function () {
|
|
196
235
|
var {
|
|
197
236
|
deps,
|
|
@@ -252,6 +291,27 @@ async function flush() {
|
|
|
252
291
|
(0, import_vitest.expect)(deleteLocalState).not.toHaveBeenCalled();
|
|
253
292
|
(0, import_vitest.expect)(reload).not.toHaveBeenCalled();
|
|
254
293
|
});
|
|
294
|
+
(0, import_vitest.test)("recovery log classification is narrow", function () {
|
|
295
|
+
var sqliteError = new Error("This statement has been finalized");
|
|
296
|
+
sqliteError.name = "SqliteError";
|
|
297
|
+
(0, import_vitest.expect)((0, import_recoverZeroClient.classifyZeroRecoveryLog)("error", ["Error running.", sqliteError])).toMatchObject({
|
|
298
|
+
reason: "sqlite-statement-finalized",
|
|
299
|
+
dropLocalState: true
|
|
300
|
+
});
|
|
301
|
+
(0, import_vitest.expect)((0, import_recoverZeroClient.classifyZeroRecoveryLog)("error", [{
|
|
302
|
+
name: "SqliteError",
|
|
303
|
+
message: "database is locked"
|
|
304
|
+
}])).toBeUndefined();
|
|
305
|
+
(0, import_vitest.expect)((0, import_recoverZeroClient.classifyZeroRecoveryLog)("warn", ["Expected IndexedDB not found"])).toBeUndefined();
|
|
306
|
+
(0, import_vitest.expect)((0, import_recoverZeroClient.classifyZeroRecoveryLog)("error", ["Store is closed"], 1e4)).toBeUndefined();
|
|
307
|
+
(0, import_vitest.expect)((0, import_recoverZeroClient.classifyZeroRecoveryLog)("error", ["Store is closed"], 11e3)).toBeUndefined();
|
|
308
|
+
(0, import_vitest.expect)((0, import_recoverZeroClient.classifyZeroRecoveryLog)("error", ["Store is closed"], 14e3)).toMatchObject({
|
|
309
|
+
reason: "store-closed-repeat",
|
|
310
|
+
dropLocalState: true
|
|
311
|
+
});
|
|
312
|
+
(0, import_recoverZeroClient.resetRecoveryStateForTests)();
|
|
313
|
+
(0, import_vitest.expect)((0, import_recoverZeroClient.classifyZeroRecoveryLog)("error", ['Mutator "send" error on server', "Store is closed"], 2e4)).toBeUndefined();
|
|
314
|
+
});
|
|
255
315
|
(0, import_vitest.test)("default reload path is a safe no-op when location is absent", async function () {
|
|
256
316
|
var events = [];
|
|
257
317
|
var zeroEvents = (0, import_helpers.createEmitter)(`test-recover-${emitterSeq++}`, null);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["import_helpers","require","import_zero","import_vitest","import_recoverZeroClient","_class_call_check","instance","Constructor","TypeError","_defineProperties","target","props","i","length","descriptor","enumerable","configurable","writable","Object","defineProperty","key","_create_class","protoProps","staticProps","prototype","_define_property","obj","value","emitterSeq","setup","events","zeroEvents","createEmitter","listen","event","push","deleteLocalState","vi","fn","Promise","resolve","reload","deps","flush","setTimeout","beforeEach","window","sessionStorage","clear","resetRecoveryStateForTests","describe","test","makeZeroRecovery","onUpdateNeeded","type","UpdateNeededReasonType","SchemaVersionNotSupported","expect","toEqual","reason","stringContaining","toHaveBeenCalledTimes","recovery","NewClientGroup","VersionNotSupported","not","toHaveBeenCalled","onClientStateNotFound","a","b","mock","calls","toBe","filter","some","consumer","log","sink","composeRecoveryLogSink","
|
|
1
|
+
{"version":3,"names":["import_helpers","require","import_zero","import_vitest","import_recoverZeroClient","_class_call_check","instance","Constructor","TypeError","_defineProperties","target","props","i","length","descriptor","enumerable","configurable","writable","Object","defineProperty","key","_create_class","protoProps","staticProps","prototype","_define_property","obj","value","emitterSeq","setup","events","zeroEvents","createEmitter","listen","event","push","deleteLocalState","vi","fn","Promise","resolve","reload","deps","flush","setTimeout","beforeEach","window","sessionStorage","clear","resetRecoveryStateForTests","describe","test","makeZeroRecovery","onUpdateNeeded","type","UpdateNeededReasonType","SchemaVersionNotSupported","expect","toEqual","reason","stringContaining","toHaveBeenCalledTimes","recovery","NewClientGroup","VersionNotSupported","not","toHaveBeenCalled","onClientStateNotFound","a","b","mock","calls","toBe","filter","some","consumer","log","sink","composeRecoveryLogSink","sqliteError","Error","name","bgIntervalProcess","nowSpy","spyOn","Date","mockReturnValue","mockRestore","infoSpy","console","mockImplementation","worker","toHaveBeenCalledWith","_sink_flush","ClassSink","ClassSink2","flush2","flushed"],"sources":["../../../src/helpers/recoverZeroClient.test.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -23,6 +23,7 @@ var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
|
|
|
23
23
|
}), mod);
|
|
24
24
|
var index_exports = {};
|
|
25
25
|
__export(index_exports, {
|
|
26
|
+
classifyZeroRecoveryLog: () => import_recoverZeroClient.classifyZeroRecoveryLog,
|
|
26
27
|
clearZeroClientData: () => import_clearZeroClientData.clearZeroClientData,
|
|
27
28
|
composeRecoveryLogSink: () => import_recoverZeroClient.composeRecoveryLogSink,
|
|
28
29
|
createZeroClient: () => import_createZeroClient.createZeroClient,
|
package/dist/cjs/index.native.js
CHANGED
|
@@ -25,6 +25,7 @@ var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
|
|
|
25
25
|
}), mod);
|
|
26
26
|
var index_exports = {};
|
|
27
27
|
__export(index_exports, {
|
|
28
|
+
classifyZeroRecoveryLog: () => import_recoverZeroClient.classifyZeroRecoveryLog,
|
|
28
29
|
clearZeroClientData: () => import_clearZeroClientData.clearZeroClientData,
|
|
29
30
|
composeRecoveryLogSink: () => import_recoverZeroClient.composeRecoveryLogSink,
|
|
30
31
|
createZeroClient: () => import_createZeroClient.createZeroClient,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["__toCommonJS","mod","__copyProps","__defProp","value","index_exports","__export","clearZeroClientData","import_clearZeroClientData","composeRecoveryLogSink","
|
|
1
|
+
{"version":3,"names":["__toCommonJS","mod","__copyProps","__defProp","value","index_exports","__export","classifyZeroRecoveryLog","import_recoverZeroClient","clearZeroClientData","import_clearZeroClientData","composeRecoveryLogSink","createZeroClient","import_createZeroClient","defineQueries","import_zero","defineQuery","ensureAuth","import_getAuth","getAuth","makeZeroRecovery","resetShownZeroClientError","import_showZeroClientError","setAuthData","import_state","setEnvironment","setRunner","import_zeroRunner","showZeroClientErrorOnce","module","exports","__reExport","require"],"sources":["../../src/index.ts"],"sourcesContent":[null],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,YAAA,GAAAC,GAAA,IAAAC,WAAA,CAAAC,SAAA;EAAAC,KAAA;AAAA,IAAAH,GAAA;AAAA,IAAAI,aAAA;AAAAC,QAAA,CAAAD,aAAA;EAAAE,uBAAA,EAAAA,CAAA,KAAAC,wBAAA,CAAAD,uBAAA;EAAAE,mBAAA,EAAAA,CAAA,KAAAC,0BAAA,CAAAD,mBAAA;EAAAE,sBAAA,EAAAA,CAAA,KAAAH,wBAAA,CAAAG,sBAAA;EAAAC,gBAAA,EAAAA,CAAA,KAAAC,uBAAA,CAAAD,gBAAA;EAAAE,aAAA,EAAAA,CAAA,KAAAC,WAAA,CAAAD,aAAA;EAAAE,WAAA,EAAAA,CAAA,KAAAD,WAAA,CAAAC,WAAA;EAAAC,UAAA,EAAAA,CAAA,KAAAC,cAAA,CAAAD,UAAA;EAAAE,OAAA,EAAAA,CAAA,KAAAD,cAAA,CAAAC,OAAA;EAAAC,gBAAA,EAAAA,CAAA,KAAAZ,wBAAA,CAAAY,gBAAA;EAAAC,yBAAA,EAAAA,CAAA,KAAAC,0BAAA,CAAAD,yBAAA;EAAAE,WAAA,EAAAA,CAAA,KAAAC,YAAA,CAAAD,WAAA;EAAAE,cAAA,EAAAA,CAAA,KAAAD,YAAA,CAAAC,cAAA;EAAAC,SAAA,EAAAA,CAAA,KAAAC,iBAAA,CAAAD,SAAA;EAAAE,uBAAA,EAAAA,CAAA,KAAAN,0BAAA,CAAAM;AAAA;AAAAC,MAAA,CAAAC,OAAA,GAAA9B,YAAc,CAAAK,aAAA;AACd0B,UAAA,CAAA1B,aAAA,EAAc2B,OAAA,gCADd,GAAAH,MAAA,CAAAC,OAAA;AAEAC,UAAA,CAAA1B,aAAA,EAAc2B,OAAA,+BAAAH,MAFd,CAAAC,OAAA;AAGAC,UAAA,CAAA1B,aAAA,EAAc2B,OAAA,oCAAAH,MAHd,CAAAC,OAAA;AAIAC,UAAA,CAAA1B,aAAA,EAAc2B,OAAA,wCAJdH,MAAA,CAAAC,OAAA;AAKAC,UAAA,CAAA1B,aAAA,EAAc2B,OAAA,wCALdH,MAAA,CAAAC,OAAA;AAMAC,UAAA,CAAA1B,aAAA,EAAc2B,OAAA,qCANd,GAAAH,MAAA,CAAAC,OAAA;AAOAC,UAAA,CAAA1B,aAAoC,EAAA2B,OAAA,qCAAAH,MAAA,CAAAC,OAAA;AACpC,IAAAZ,cAAA,GAA4Cc,OAAA;AAE5C,IAAAR,YAAA,GAAAQ,OAAA,oBAKO;AACP,IAAAnB,uBAAc,GAAAmB,OAAA,+BAhBd;AAiBAD,UAAA,CAAA1B,aAAA,EAAc2B,OAAA,gCAjBd,GAAAH,MAAA,CAAAC,OAAA;AAkBAC,UAAA,CAAA1B,aAAA,EAAc2B,OAAA,8BAlBd,EAAAH,MAAA,CAAAC,OAAA;AAmBAC,UAAA,CAAA1B,aAAA,EAAc2B,OAAA,2BAnBd,GAAAH,MAAA,CAAAC,OAAA;AAoBAC,UAAA,CAAA1B,aAA2C,EAAA2B,OAAA,qBAAAH,MAAA,CAAAC,OAAA;AAC3C,IAAAH,iBAAA,GAAAK,OAAc;AACdD,UAAA,CAAA1B,aAAA,EAAc2B,OAAA,wBAtBd,GAAAH,MAAA,CAAAC,OAAA;AAuBAC,UAAA,CAAA1B,aAAA,EAAc2B,OAAA,uBAAAH,MAvBd,CAAAC,OAAA;AAwBAC,UAAA,CAAA1B,aAAA,EAAc2B,OAAA,0BAxBd,GAAAH,MAAA,CAAAC,OAAA;AAyBAC,UAAA,CAAA1B,aAA2C,EAAA2B,OAAA,qBAAAH,MAAA,CAAAC,OAAA;AAQ3C,IAAAf,WAAA,GAAAiB,OAAA,iBAGO;AACP,IAAAtB,0BAAA,GAKOsB,OAAA;AACP,IAAAV,0BAAA,GAOOU,OAAA","ignoreList":[]}
|
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
const RECOVER_GUARD_MS = 6e4;
|
|
2
2
|
const LOCAL_STORE_LOST = "Expected IndexedDB not found";
|
|
3
|
+
const SQLITE_ERROR_NAME = "SqliteError";
|
|
4
|
+
const SQLITE_STATEMENT_FINALIZED = "This statement has been finalized";
|
|
5
|
+
const STORE_CLOSED = "Store is closed";
|
|
6
|
+
const STORE_CLOSED_REPEAT_MIN_MS = 2e3;
|
|
7
|
+
const STORE_CLOSED_REPEAT_MAX_MS = 6e4;
|
|
3
8
|
let reloadScheduled = false;
|
|
4
9
|
const pendingDeletes = [];
|
|
5
10
|
function recoveryGuardOpen(reasonKey) {
|
|
6
11
|
try {
|
|
7
12
|
const key = `on-zero-recover-${reasonKey}`;
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
13
|
+
const rawLast = window.sessionStorage.getItem(key);
|
|
14
|
+
const now = Date.now();
|
|
15
|
+
const last = rawLast ? Number(rawLast) : 0;
|
|
16
|
+
if (last > 0 && now - last < RECOVER_GUARD_MS) return false;
|
|
17
|
+
window.sessionStorage.setItem(key, String(now));
|
|
11
18
|
} catch {}
|
|
12
19
|
return true;
|
|
13
20
|
}
|
|
21
|
+
let lastStoreClosedAtMs = 0;
|
|
14
22
|
function recover(deps, reasonKey, message, dropLocalState) {
|
|
15
23
|
if (typeof window === "undefined") return;
|
|
16
24
|
if (dropLocalState) {
|
|
@@ -50,15 +58,62 @@ function logToConsole(level, context, ...args) {
|
|
|
50
58
|
const method = level === "debug" ? "debug" : level;
|
|
51
59
|
console[method](...(prefix ? [prefix] : []), ...args);
|
|
52
60
|
}
|
|
61
|
+
function logArgText(arg) {
|
|
62
|
+
if (typeof arg === "string") return arg;
|
|
63
|
+
if (arg instanceof Error) return `${arg.name} ${arg.message} ${arg.stack || ""}`;
|
|
64
|
+
if (arg && typeof arg === "object") {
|
|
65
|
+
const message = "message" in arg ? arg.message : void 0;
|
|
66
|
+
const name = "name" in arg ? arg.name : void 0;
|
|
67
|
+
if (typeof message === "string") return `${typeof name === "string" ? name : ""} ${message}`;
|
|
68
|
+
}
|
|
69
|
+
return "";
|
|
70
|
+
}
|
|
71
|
+
function isBenignStoreClosedLog(text) {
|
|
72
|
+
if (/Mutator\s+".*"\s+error on server/i.test(text)) return true;
|
|
73
|
+
if (/Mutator\s+".*"\s+app error on client/i.test(text)) return true;
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
function classifyZeroRecoveryLog(level, args, nowMs = Date.now()) {
|
|
77
|
+
if (level !== "error") return void 0;
|
|
78
|
+
const text = args.map(logArgText).join(" ");
|
|
79
|
+
if (text.includes(LOCAL_STORE_LOST)) {
|
|
80
|
+
return {
|
|
81
|
+
reason: "indexeddb-not-found",
|
|
82
|
+
reasonKey: "local-store",
|
|
83
|
+
message: "local store lost",
|
|
84
|
+
dropLocalState: true
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
if (text.includes(SQLITE_ERROR_NAME) && text.includes(SQLITE_STATEMENT_FINALIZED)) {
|
|
88
|
+
return {
|
|
89
|
+
reason: "sqlite-statement-finalized",
|
|
90
|
+
reasonKey: "sqlite-statement-finalized",
|
|
91
|
+
message: "sqlite statement finalized",
|
|
92
|
+
dropLocalState: true
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
if (text.includes(STORE_CLOSED) && !isBenignStoreClosedLog(text)) {
|
|
96
|
+
const prevMs = lastStoreClosedAtMs;
|
|
97
|
+
lastStoreClosedAtMs = nowMs;
|
|
98
|
+
if (prevMs > 0 && nowMs - prevMs >= STORE_CLOSED_REPEAT_MIN_MS && nowMs - prevMs <= STORE_CLOSED_REPEAT_MAX_MS) {
|
|
99
|
+
return {
|
|
100
|
+
reason: "store-closed-repeat",
|
|
101
|
+
reasonKey: "store-closed-repeat",
|
|
102
|
+
message: "local store closed repeatedly",
|
|
103
|
+
dropLocalState: true
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return void 0;
|
|
108
|
+
}
|
|
53
109
|
function composeRecoveryLogSink(deps, consumerLogSink) {
|
|
54
110
|
const consumerFlush = consumerLogSink?.flush;
|
|
55
111
|
return {
|
|
56
112
|
log(level, context, ...args) {
|
|
57
113
|
if (consumerLogSink) consumerLogSink.log(level, context, ...args);else logToConsole(level, context, ...args);
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
recover(deps, "local-store", "local store lost", true);
|
|
114
|
+
const recovery = classifyZeroRecoveryLog(level, args);
|
|
115
|
+
if (recovery) {
|
|
116
|
+
recover(deps, recovery.reasonKey, recovery.message, recovery.dropLocalState);
|
|
62
117
|
}
|
|
63
118
|
},
|
|
64
119
|
// call through the consumer sink so a class-based sink keeps its `this`,
|
|
@@ -69,6 +124,7 @@ function composeRecoveryLogSink(deps, consumerLogSink) {
|
|
|
69
124
|
function resetRecoveryStateForTests() {
|
|
70
125
|
reloadScheduled = false;
|
|
71
126
|
pendingDeletes.length = 0;
|
|
127
|
+
lastStoreClosedAtMs = 0;
|
|
72
128
|
}
|
|
73
|
-
export { composeRecoveryLogSink, makeZeroRecovery, resetRecoveryStateForTests };
|
|
129
|
+
export { classifyZeroRecoveryLog, composeRecoveryLogSink, makeZeroRecovery, resetRecoveryStateForTests };
|
|
74
130
|
//# sourceMappingURL=recoverZeroClient.mjs.map
|