build: migrate eslint to v10 flat config and upgrade typescript
Replace .eslintrc.json with eslint.config.js using the new flat config format required by ESLint 10. Swap @typescript-eslint/eslint-plugin and @typescript-eslint/parser for the unified typescript-eslint package. Upgrade TypeScript to 5.9 and @types/node to 25. Apply automatic code fixes: remove unused catch bindings and preserve error cause in auth header parsing.
This commit is contained in:
1 parent
4a191afdec
commit
75908e624f
27 files changed
+1146
-1595
No files matched your search
@@ -1,36 +0,0 @@
|
|||||||
{
|
|
||||||
"env": {
|
|
||||||
"es2022": true,
|
|
||||||
"node": true
|
|
||||||
},
|
|
||||||
"parser": "@typescript-eslint/parser",
|
|
||||||
"parserOptions": {
|
|
||||||
"project": "./tsconfig.json"
|
|
||||||
},
|
|
||||||
"plugins": ["@typescript-eslint"],
|
|
||||||
"extends": [
|
|
||||||
"eslint:recommended",
|
|
||||||
"plugin:@typescript-eslint/recommended",
|
|
||||||
"prettier"
|
|
||||||
],
|
|
||||||
"rules": {
|
|
||||||
"no-shadow": ["error", { "allow": ["err"] }],
|
|
||||||
"handle-callback-err": "error",
|
|
||||||
"prefer-arrow-callback": "error",
|
|
||||||
"no-buffer-constructor": "error",
|
|
||||||
"prefer-const": ["error", { "destructuring": "all" }],
|
|
||||||
"eqeqeq": ["error", "always", { "null": "ignore" }],
|
|
||||||
"@typescript-eslint/no-explicit-any": 0,
|
|
||||||
"@typescript-eslint/no-use-before-define": [
|
|
||||||
"error",
|
|
||||||
{ "functions": false }
|
|
||||||
],
|
|
||||||
"@typescript-eslint/explicit-function-return-type": [
|
|
||||||
"error",
|
|
||||||
{ "allowExpressions": true }
|
|
||||||
],
|
|
||||||
"@typescript-eslint/no-floating-promises": "error",
|
|
||||||
"@typescript-eslint/no-misused-promises": "error",
|
|
||||||
"no-prototype-builtins": 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -55,6 +55,7 @@ process.on("message", (message) => {
|
|||||||
if (!script) {
|
if (!script) {
|
||||||
const cwd = process.env["GENIEACS_EXT_DIR"];
|
const cwd = process.env["GENIEACS_EXT_DIR"];
|
||||||
process.chdir(cwd);
|
process.chdir(cwd);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||||
script = require(`${cwd}/${fileName}`);
|
script = require(`${cwd}/${fileName}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import { defineConfig } from "@eslint/config-helpers";
|
||||||
|
import eslint from "@eslint/js";
|
||||||
|
import tseslint from "typescript-eslint";
|
||||||
|
import eslintConfigPrettier from "eslint-config-prettier";
|
||||||
|
import globals from "globals";
|
||||||
|
|
||||||
|
export default defineConfig(
|
||||||
|
{
|
||||||
|
ignores: ["dist/", "test/*.js"],
|
||||||
|
},
|
||||||
|
eslint.configs.recommended,
|
||||||
|
...tseslint.configs.recommended,
|
||||||
|
eslintConfigPrettier,
|
||||||
|
{
|
||||||
|
languageOptions: {
|
||||||
|
globals: {
|
||||||
|
...globals.es2022,
|
||||||
|
...globals.node,
|
||||||
|
},
|
||||||
|
parserOptions: {
|
||||||
|
projectService: true,
|
||||||
|
tsconfigRootDir: import.meta.dirname,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
"no-shadow": ["error", { allow: ["err"] }],
|
||||||
|
"handle-callback-err": "error",
|
||||||
|
"prefer-arrow-callback": "error",
|
||||||
|
"no-buffer-constructor": "error",
|
||||||
|
"prefer-const": ["error", { destructuring: "all" }],
|
||||||
|
eqeqeq: ["error", "always", { null: "ignore" }],
|
||||||
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
|
"@typescript-eslint/no-use-before-define": [
|
||||||
|
"error",
|
||||||
|
{ functions: false },
|
||||||
|
],
|
||||||
|
"@typescript-eslint/explicit-function-return-type": [
|
||||||
|
"error",
|
||||||
|
{ allowExpressions: true },
|
||||||
|
],
|
||||||
|
"@typescript-eslint/no-floating-promises": "error",
|
||||||
|
"@typescript-eslint/no-misused-promises": "error",
|
||||||
|
"no-prototype-builtins": "off",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ["ui/**/*.ts", "ui/**/*.tsx"],
|
||||||
|
languageOptions: {
|
||||||
|
globals: {
|
||||||
|
...globals.browser,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
@@ -103,7 +103,7 @@ export async function connectionRequest(
|
|||||||
let remoteAddress;
|
let remoteAddress;
|
||||||
try {
|
try {
|
||||||
remoteAddress = new URL(connectionRequestUrl).hostname;
|
remoteAddress = new URL(connectionRequestUrl).hostname;
|
||||||
} catch (err) {
|
} catch {
|
||||||
return "Invalid connection request URL";
|
return "Invalid connection request URL";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,7 +185,7 @@ export async function connectionRequest(
|
|||||||
() => true,
|
() => true,
|
||||||
() => false,
|
() => false,
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch {
|
||||||
// Ignore invalid address
|
// Ignore invalid address
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ function parseHeaderFeilds(str: string): Record<string, string> {
|
|||||||
try {
|
try {
|
||||||
value = JSON.parse(value);
|
value = JSON.parse(value);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error("Unable to parse auth header");
|
throw new Error("Unable to parse auth header", { cause: error });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res[name.trim()] = value;
|
res[name.trim()] = value;
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ export async function httpConnectionRequest(
|
|||||||
authHeader = auth.parseWwwAuthenticateHeader(
|
authHeader = auth.parseWwwAuthenticateHeader(
|
||||||
res.headers["www-authenticate"],
|
res.headers["www-authenticate"],
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch {
|
||||||
return "Connection request error: Error parsing www-authenticate header";
|
return "Connection request error: Error parsing www-authenticate header";
|
||||||
}
|
}
|
||||||
[username, password, authExp] = await extractAuth(authExp, false);
|
[username, password, authExp] = await extractAuth(authExp, false);
|
||||||
|
|||||||
+4
-4
@@ -89,7 +89,7 @@ async function authenticate(
|
|||||||
authentication = auth.parseAuthorizationHeader(
|
authentication = auth.parseAuthorizationHeader(
|
||||||
sessionContext.httpRequest.headers["authorization"],
|
sessionContext.httpRequest.headers["authorization"],
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1274,7 +1274,7 @@ async function clientError(
|
|||||||
body: string,
|
body: string,
|
||||||
msg: string,
|
msg: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
let debugEnabled = false;
|
let debugEnabled: boolean;
|
||||||
let deviceId: string = null;
|
let deviceId: string = null;
|
||||||
|
|
||||||
if (sessionContext) {
|
if (sessionContext) {
|
||||||
@@ -1312,7 +1312,7 @@ async function clientError(
|
|||||||
function decodeString(buffer: Buffer, charset: string): string {
|
function decodeString(buffer: Buffer, charset: string): string {
|
||||||
try {
|
try {
|
||||||
return buffer.toString(charset as BufferEncoding);
|
return buffer.toString(charset as BufferEncoding);
|
||||||
} catch (err) {
|
} catch {
|
||||||
if (encodingExists(charset)) return decode(buffer, charset);
|
if (encodingExists(charset)) return decode(buffer, charset);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -1383,7 +1383,7 @@ async function listenerAsync(
|
|||||||
// connection is closed before the stream is finished.
|
// connection is closed before the stream is finished.
|
||||||
// For Node 12.9+ we can just use stream.readableEnded
|
// For Node 12.9+ we can just use stream.readableEnded
|
||||||
if (!readableEnded) throw new Error("Connection closed");
|
if (!readableEnded) throw new Error("Connection closed");
|
||||||
} catch (err) {
|
} catch {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -78,7 +78,7 @@ export async function fetchDevice(
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
res.push([Path.parse(path), t, attrs]);
|
res.push([Path.parse(path), t, attrs]);
|
||||||
} catch (err) {
|
} catch {
|
||||||
// The path parser is now more strict so we might be in a situation where
|
// The path parser is now more strict so we might be in a situation where
|
||||||
// the database contains invalid paths from before this change So here we
|
// the database contains invalid paths from before this change So here we
|
||||||
// encode the invalid characters.
|
// encode the invalid characters.
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ async function fetchPresets(): Promise<[string, Preset[]]> {
|
|||||||
try {
|
try {
|
||||||
schedule.duration = +parts.shift() * 1000;
|
schedule.duration = +parts.shift() * 1000;
|
||||||
schedule.schedule = scheduling.parseCron(parts.join(" "));
|
schedule.schedule = scheduling.parseCron(parts.join(" "));
|
||||||
} catch (err) {
|
} catch {
|
||||||
logger.warn({
|
logger.warn({
|
||||||
message: "Invalid preset schedule",
|
message: "Invalid preset schedule",
|
||||||
preset: preset["_id"],
|
preset: preset["_id"],
|
||||||
@@ -97,7 +97,7 @@ async function fetchPresets(): Promise<[string, Preset[]]> {
|
|||||||
if (preset["precondition"]) {
|
if (preset["precondition"]) {
|
||||||
try {
|
try {
|
||||||
precondition = parse(preset["precondition"]);
|
precondition = parse(preset["precondition"]);
|
||||||
} catch (error) {
|
} catch {
|
||||||
precondition = convertOldPrecondition(
|
precondition = convertOldPrecondition(
|
||||||
JSON.parse(preset["precondition"]),
|
JSON.parse(preset["precondition"]),
|
||||||
);
|
);
|
||||||
|
|||||||
+2
-2
@@ -20,12 +20,12 @@ const cidrs: [IPv4 | IPv6, number][] = [];
|
|||||||
for (const str of FORWARDED_HEADER.split(",").map((s) => s.trim())) {
|
for (const str of FORWARDED_HEADER.split(",").map((s) => s.trim())) {
|
||||||
try {
|
try {
|
||||||
cidrs.push(parseCIDR(str));
|
cidrs.push(parseCIDR(str));
|
||||||
} catch (err) {
|
} catch {
|
||||||
// Not a valid CIDR format, try parsing as IP
|
// Not a valid CIDR format, try parsing as IP
|
||||||
try {
|
try {
|
||||||
const ip = parse(str);
|
const ip = parse(str);
|
||||||
cidrs.push([ip, ip.toByteArray().length * 8]);
|
cidrs.push([ip, ip.toByteArray().length * 8]);
|
||||||
} catch (err) {
|
} catch {
|
||||||
// Not a valid IP either, ignore
|
// Not a valid IP either, ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ function matchEtag(etag: string, header: string): boolean {
|
|||||||
if (t.startsWith("W/")) t = t.substring(2);
|
if (t.startsWith("W/")) t = t.substring(2);
|
||||||
try {
|
try {
|
||||||
t = JSON.parse(t);
|
t = JSON.parse(t);
|
||||||
} catch (e) {
|
} catch {
|
||||||
// Ignore
|
// Ignore
|
||||||
}
|
}
|
||||||
if (t === "*") return true;
|
if (t === "*") return true;
|
||||||
|
|||||||
+1
-1
@@ -501,7 +501,7 @@ async function handler(
|
|||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
await filesBucket.delete(filename as unknown as ObjectId);
|
await filesBucket.delete(filename as unknown as ObjectId);
|
||||||
} catch (err) {
|
} catch {
|
||||||
// Ignore error if file doesn't exist
|
// Ignore error if file doesn't exist
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -93,7 +93,7 @@ export function start(
|
|||||||
res.writeHead(500, { Connection: "close" });
|
res.writeHead(500, { Connection: "close" });
|
||||||
res.end(`${err.name}: ${err.message}`);
|
res.end(`${err.name}: ${err.message}`);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch {
|
||||||
// Ignore
|
// Ignore
|
||||||
}
|
}
|
||||||
throw err;
|
throw err;
|
||||||
|
|||||||
+3
-3
@@ -119,7 +119,7 @@ function parameterInfoList(xml: Element): [Path, boolean, boolean][] {
|
|||||||
if (param && !param.endsWith("."))
|
if (param && !param.endsWith("."))
|
||||||
return [Path.parse(param), false, parsed];
|
return [Path.parse(param), false, parsed];
|
||||||
else return [Path.parse(param.slice(0, -1)), true, parsed];
|
else return [Path.parse(param.slice(0, -1)), true, parsed];
|
||||||
} catch (err) {
|
} catch {
|
||||||
warnings.push({
|
warnings.push({
|
||||||
message: "Missing or invalid XML node",
|
message: "Missing or invalid XML node",
|
||||||
element: "Name",
|
element: "Name",
|
||||||
@@ -201,7 +201,7 @@ function parameterValueList(
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return [Path.parse(param), parsed, valueType];
|
return [Path.parse(param), parsed, valueType];
|
||||||
} catch (err) {
|
} catch {
|
||||||
warnings.push({
|
warnings.push({
|
||||||
message: "Missing or invalid XML node",
|
message: "Missing or invalid XML node",
|
||||||
element: "Name",
|
element: "Name",
|
||||||
@@ -250,7 +250,7 @@ function parameterAttributeList(xml: Element): [Path, number, string[]][] {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
return [Path.parse(param), notification, accessList];
|
return [Path.parse(param), notification, accessList];
|
||||||
} catch (err) {
|
} catch {
|
||||||
warnings.push({
|
warnings.push({
|
||||||
message: "Missing or invalid XML node",
|
message: "Missing or invalid XML node",
|
||||||
element: "Name",
|
element: "Name",
|
||||||
|
|||||||
+1
-1
@@ -519,7 +519,7 @@ router.put("/files/:id", async (ctx) => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await db.deleteFile(id);
|
await db.deleteFile(id);
|
||||||
} catch (err) {
|
} catch {
|
||||||
// File doesn't exist, ignore
|
// File doesn't exist, ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -260,7 +260,7 @@ function flattenPreset(
|
|||||||
try {
|
try {
|
||||||
// Try parse to check expression validity
|
// Try parse to check expression validity
|
||||||
parse(p.precondition as string);
|
parse(p.precondition as string);
|
||||||
} catch (error) {
|
} catch {
|
||||||
p.precondition = convertOldPrecondition(
|
p.precondition = convertOldPrecondition(
|
||||||
JSON.parse(p.precondition as string),
|
JSON.parse(p.precondition as string),
|
||||||
);
|
);
|
||||||
|
|||||||
+1
-1
@@ -41,7 +41,7 @@ export function parseXmlDeclaration(buffer: Buffer): Attribute[] {
|
|||||||
str = str.slice(0, str.indexOf("?>"));
|
str = str.slice(0, str.indexOf("?>"));
|
||||||
try {
|
try {
|
||||||
return parseAttrs(str.slice(5));
|
return parseAttrs(str.slice(5));
|
||||||
} catch (err) {
|
} catch {
|
||||||
// Ignore
|
// Ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+1050
-1517
File diff suppressed because it is too large.
Load diff
+6
-5
@@ -48,26 +48,27 @@
|
|||||||
"@codemirror/language": "^6.12.2",
|
"@codemirror/language": "^6.12.2",
|
||||||
"@codemirror/state": "^6.5.4",
|
"@codemirror/state": "^6.5.4",
|
||||||
"@codemirror/view": "^6.39.16",
|
"@codemirror/view": "^6.39.16",
|
||||||
|
"@eslint/js": "^10.0.1",
|
||||||
"@tailwindcss/cli": "^4.2.1",
|
"@tailwindcss/cli": "^4.2.1",
|
||||||
"@tailwindcss/forms": "^0.5.11",
|
"@tailwindcss/forms": "^0.5.11",
|
||||||
"@types/jsonwebtoken": "^9.0.10",
|
"@types/jsonwebtoken": "^9.0.10",
|
||||||
"@types/koa": "^2.15.0",
|
"@types/koa": "^2.15.0",
|
||||||
"@types/koa-compress": "^4.0.7",
|
"@types/koa-compress": "^4.0.7",
|
||||||
"@types/mithril": "^2.2.7",
|
"@types/mithril": "^2.2.7",
|
||||||
"@types/node": "^20.19.37",
|
"@types/node": "^25.3.5",
|
||||||
"@types/parsimmon": "^1.10.9",
|
"@types/parsimmon": "^1.10.9",
|
||||||
"@types/seedrandom": "^3.0.8",
|
"@types/seedrandom": "^3.0.8",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.18.0",
|
|
||||||
"@typescript-eslint/parser": "^7.18.0",
|
|
||||||
"esbuild": "^0.27.4",
|
"esbuild": "^0.27.4",
|
||||||
"eslint": "^8.57.1",
|
"eslint": "^10.0.3",
|
||||||
"eslint-config-prettier": "^9.1.2",
|
"eslint-config-prettier": "^10.1.8",
|
||||||
|
"globals": "^17.4.0",
|
||||||
"mithril": "^2.3.8",
|
"mithril": "^2.3.8",
|
||||||
"prettier": "^3.8.1",
|
"prettier": "^3.8.1",
|
||||||
"sql.js": "^1.14.1",
|
"sql.js": "^1.14.1",
|
||||||
"svgo": "^3.3.3",
|
"svgo": "^3.3.3",
|
||||||
"tailwindcss": "^4.2.1",
|
"tailwindcss": "^4.2.1",
|
||||||
"typescript": "^5.9.3",
|
"typescript": "^5.9.3",
|
||||||
|
"typescript-eslint": "^8.56.1",
|
||||||
"yaml": "^1.10.2"
|
"yaml": "^1.10.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"env": {
|
|
||||||
"browser": true,
|
|
||||||
"node": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -119,7 +119,9 @@ export default class Autocomplete {
|
|||||||
if (!this.visible) {
|
if (!this.visible) {
|
||||||
if (!this.hideTimeout) {
|
if (!this.hideTimeout) {
|
||||||
document.body.appendChild(this.container);
|
document.body.appendChild(this.container);
|
||||||
window.getComputedStyle(this.container).opacity;
|
// Force style recalc so the initial opacity is resolved before
|
||||||
|
// setting it to "1", allowing the CSS transition to play.
|
||||||
|
void window.getComputedStyle(this.container).opacity;
|
||||||
} else {
|
} else {
|
||||||
clearTimeout(this.hideTimeout);
|
clearTimeout(this.hideTimeout);
|
||||||
this.hideTimeout = null;
|
this.hideTimeout = null;
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ const component: ClosureComponent = (vn): Component => {
|
|||||||
try {
|
try {
|
||||||
const url = new URL(param.value[0]);
|
const url = new URL(param.value[0]);
|
||||||
h = url.hostname;
|
h = url.hostname;
|
||||||
} catch (err) {
|
} catch {
|
||||||
// Ignore
|
// Ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -31,7 +31,7 @@ function putActionHandler(action, _object, isNew?): Promise<ValidationErrors> {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
object.value = stringify(parse(object.value || ""));
|
object.value = stringify(parse(object.value || ""));
|
||||||
} catch (err) {
|
} catch {
|
||||||
return void resolve({
|
return void resolve({
|
||||||
value: "Config value must be valid expression",
|
value: "Config value must be valid expression",
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ const component: ClosureComponent<Attrs> = (initialVnode) => {
|
|||||||
const list = filterList.map((f, idx) => {
|
const list = filterList.map((f, idx) => {
|
||||||
try {
|
try {
|
||||||
return parseFilter(attrs.resource, f);
|
return parseFilter(attrs.resource, f);
|
||||||
} catch (err) {
|
} catch {
|
||||||
filterInvalid |= 1 << idx;
|
filterInvalid |= 1 << idx;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ function putActionHandler(action, _object, isNew): Promise<ValidationErrors> {
|
|||||||
if (object.filter) {
|
if (object.filter) {
|
||||||
try {
|
try {
|
||||||
object.filter = stringify(memoizedParse(object.filter));
|
object.filter = stringify(memoizedParse(object.filter));
|
||||||
} catch (err) {
|
} catch {
|
||||||
return void resolve({
|
return void resolve({
|
||||||
filter: "Filter must be valid expression",
|
filter: "Filter must be valid expression",
|
||||||
});
|
});
|
||||||
@@ -100,7 +100,7 @@ function putActionHandler(action, _object, isNew): Promise<ValidationErrors> {
|
|||||||
if (object.validate) {
|
if (object.validate) {
|
||||||
try {
|
try {
|
||||||
object.validate = stringify(memoizedParse(object.validate));
|
object.validate = stringify(memoizedParse(object.validate));
|
||||||
} catch (err) {
|
} catch {
|
||||||
return void resolve({
|
return void resolve({
|
||||||
validate: "Validate must be valid expression",
|
validate: "Validate must be valid expression",
|
||||||
});
|
});
|
||||||
|
|||||||
+1
-1
@@ -72,7 +72,7 @@ function putActionHandler(action, _object, isNew): Promise<ValidationErrors> {
|
|||||||
if (object.precondition) {
|
if (object.precondition) {
|
||||||
try {
|
try {
|
||||||
object.precondition = stringify(memoizedParse(object.precondition));
|
object.precondition = stringify(memoizedParse(object.precondition));
|
||||||
} catch (err) {
|
} catch {
|
||||||
return void resolve({
|
return void resolve({
|
||||||
precondition: "Precondition must be valid expression",
|
precondition: "Precondition must be valid expression",
|
||||||
});
|
});
|
||||||
|
|||||||
+4
-2
@@ -113,7 +113,7 @@ function checkConnection(): void {
|
|||||||
setTimestamp(now2);
|
setTimestamp(now2);
|
||||||
m.redraw();
|
m.redraw();
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch {
|
||||||
// Ignore in case of missing or invalid Date header
|
// Ignore in case of missing or invalid Date header
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,7 +200,9 @@ export async function xhrRequest(
|
|||||||
try {
|
try {
|
||||||
response = xhr.responseText ? JSON.parse(xhr.responseText) : null;
|
response = xhr.responseText ? JSON.parse(xhr.responseText) : null;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new Error("Invalid JSON: " + xhr.responseText.slice(0, 80));
|
throw new Error("Invalid JSON: " + xhr.responseText.slice(0, 80), {
|
||||||
|
cause: err,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
response = xhr.responseText;
|
response = xhr.responseText;
|
||||||
|
|||||||
Reference in new issue
Block a user