diff --git a/src/electron-main.ts b/src/electron-main.ts index 31109341..9059896c 100644 --- a/src/electron-main.ts +++ b/src/electron-main.ts @@ -41,6 +41,7 @@ import { getProfileFromDeeplink, protocolInit } from "./protocol"; import { _t, AppLocalization } from "./language-helper"; import { setDisplayMediaCallback } from "./displayMediaCallback"; import { setupMacosTitleBar } from "./macos-titlebar"; +import { loadJsonFile } from "./utils"; const argv = minimist(process.argv, { alias: { help: "h" }, @@ -143,8 +144,7 @@ async function loadConfig(): Promise { const asarPath = await getAsarPath(); try { - // eslint-disable-next-line @typescript-eslint/no-var-requires - global.vectorConfig = require(asarPath + "config.json"); + global.vectorConfig = loadJsonFile(asarPath, "config.json"); } catch (e) { // it would be nice to check the error code here and bail if the config // is unparsable, but we get MODULE_NOT_FOUND in the case of a missing @@ -155,8 +155,7 @@ async function loadConfig(): Promise { try { // Load local config and use it to override values from the one baked with the build - // eslint-disable-next-line @typescript-eslint/no-var-requires - const localConfig = require(path.join(app.getPath("userData"), "config.json")); + const localConfig = loadJsonFile(app.getPath("userData"), "config.json"); // If the local config has a homeserver defined, don't use the homeserver from the build // config. This is to avoid a problem where Riot thinks there are multiple homeservers diff --git a/src/language-helper.ts b/src/language-helper.ts index b705ab6b..731fca1a 100644 --- a/src/language-helper.ts +++ b/src/language-helper.ts @@ -19,6 +19,7 @@ import { TranslationKey as TKey } from "matrix-web-i18n"; import type Store from "electron-store"; import type EN from "./i18n/strings/en_EN.json"; +import { loadJsonFile } from "./utils"; const FALLBACK_LOCALE = "en"; @@ -105,7 +106,7 @@ export class AppLocalization { public fetchTranslationJson(locale: string): Record { try { console.log("Fetching translation json for locale: " + locale); - return require(`./i18n/strings/${this.denormalize(locale)}.json`); + return loadJsonFile(`./i18n/strings/${this.denormalize(locale)}.json`); } catch (e) { console.log(`Could not fetch translation json for locale: '${locale}'`, e); return {}; diff --git a/src/utils.ts b/src/utils.ts index 334721e8..2aab2928 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -15,6 +15,8 @@ limitations under the License. */ import crypto from "crypto"; +import fs from "node:fs"; +import path from "node:path"; export async function randomArray(size: number): Promise { return new Promise((resolve, reject) => { @@ -27,3 +29,20 @@ export async function randomArray(size: number): Promise { }); }); } + +type JsonValue = null | string | number; +type JsonArray = Array; +interface JsonObject { + [key: string]: JsonObject | JsonArray | JsonValue; +} +type Json = JsonArray | JsonObject; + +/** + * Synchronously load a JSON file from the local filesystem. + * Unlike `require`, will never execute any javascript in a loaded file. + * @param paths - An array of path segments which will be joined using the system's path delimiter. + */ +export function loadJsonFile(...paths: string[]): T { + const file = fs.readFileSync(path.join(...paths), { encoding: "utf-8" }); + return JSON.parse(file); +}