mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2026-04-02 08:13:37 +01:00
Remove use of __dirname from main process
This commit is contained in:
@@ -11,8 +11,9 @@ import type { OptionalResourceService } from './OptionalResourceService.main.js'
|
||||
import { SignalService as Proto } from '../ts/protobuf/index.std.js';
|
||||
import { parseUnknown } from '../ts/util/schemas.std.js';
|
||||
import { utf16ToEmoji } from '../ts/util/utf16ToEmoji.node.js';
|
||||
import { getAppRootDir } from '../ts/util/appRootDir.main.js';
|
||||
|
||||
const MANIFEST_PATH = join(__dirname, '..', 'build', 'jumbomoji.json');
|
||||
const MANIFEST_PATH = join(getAppRootDir(), 'build', 'jumbomoji.json');
|
||||
|
||||
const manifestSchema = z.record(z.string(), z.string().array());
|
||||
|
||||
|
||||
@@ -15,15 +15,15 @@ import type {
|
||||
} from '../ts/types/OptionalResource.std.js';
|
||||
import { OptionalResourcesDictSchema } from '../ts/types/OptionalResource.std.js';
|
||||
import { createLogger } from '../ts/logging/log.std.js';
|
||||
import { getGotOptions } from '../ts/updater/got.node.js';
|
||||
import { getGotOptions } from '../ts/updater/got.main.js';
|
||||
import { drop } from '../ts/util/drop.std.js';
|
||||
import { parseUnknown } from '../ts/util/schemas.std.js';
|
||||
import { getAppRootDir } from '../ts/util/appRootDir.main.js';
|
||||
|
||||
const log = createLogger('OptionalResourceService');
|
||||
|
||||
const RESOURCES_DICT_PATH = join(
|
||||
__dirname,
|
||||
'..',
|
||||
getAppRootDir(),
|
||||
'build',
|
||||
'optional-resources.json'
|
||||
);
|
||||
|
||||
@@ -8,6 +8,7 @@ import { join } from 'node:path';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { createLogger } from '../ts/logging/log.std.js';
|
||||
import type { LocalizerType } from '../ts/types/I18N.std.js';
|
||||
import { getAppRootDir } from '../ts/util/appRootDir.main.js';
|
||||
|
||||
const log = createLogger('SystemTrayService');
|
||||
|
||||
@@ -285,8 +286,7 @@ function getTrayIconImagePath(size: number, unreadCount: number): string {
|
||||
}
|
||||
|
||||
const iconPath = join(
|
||||
__dirname,
|
||||
'..',
|
||||
getAppRootDir(),
|
||||
'images',
|
||||
'tray-icons',
|
||||
dirName,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2017 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { ipcMain as ipc, app } from 'electron';
|
||||
import { ipcMain as ipc } from 'electron';
|
||||
import type { IpcMainInvokeEvent } from 'electron';
|
||||
import { join } from 'node:path';
|
||||
import { Worker } from 'node:worker_threads';
|
||||
@@ -15,6 +15,7 @@ import type {
|
||||
import { WindowsNotificationDataSchema } from '../ts/types/notifications.std.js';
|
||||
import OS from '../ts/util/os/osMain.node.js';
|
||||
import { createLogger } from '../ts/logging/log.std.js';
|
||||
import { getAppRootDir } from '../ts/util/appRootDir.main.js';
|
||||
|
||||
const log = createLogger('WindowsNotifications');
|
||||
|
||||
@@ -22,7 +23,7 @@ let worker: Worker | undefined;
|
||||
|
||||
if (OS.isWindows()) {
|
||||
const scriptPath = join(
|
||||
app.getAppPath(),
|
||||
getAppRootDir(),
|
||||
'app',
|
||||
'WindowsNotificationsWorker.node.js'
|
||||
);
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
parseEnvironment,
|
||||
} from '../ts/environment.std.js';
|
||||
import { createLogger } from '../ts/logging/log.std.js';
|
||||
import { getAppRootDir } from '../ts/util/appRootDir.main.js';
|
||||
|
||||
const log = createLogger('config');
|
||||
|
||||
@@ -28,7 +29,6 @@ if (app.isPackaged) {
|
||||
|
||||
// Set environment vars to configure node-config before requiring it
|
||||
process.env.NODE_ENV = getEnvironment();
|
||||
process.env.NODE_CONFIG_DIR = join(__dirname, '..', 'config');
|
||||
|
||||
if (getEnvironment() === Environment.PackagedApp) {
|
||||
// harden production config against the local env
|
||||
@@ -43,8 +43,12 @@ if (getEnvironment() === Environment.PackagedApp) {
|
||||
process.env.SIGNAL_CI_CONFIG = '';
|
||||
process.env.GENERATE_PRELOAD_CACHE = '';
|
||||
process.env.REACT_DEVTOOLS = '';
|
||||
process.env.IS_BUNDLED = '1';
|
||||
}
|
||||
|
||||
// Call `getAppRootDir()` after hardening since it relies on env variables
|
||||
process.env.NODE_CONFIG_DIR = join(getAppRootDir(), 'config');
|
||||
|
||||
// We load config after we've made our modifications to NODE_ENV
|
||||
// Note: we use `require()` because esbuild moves the imports to the top of
|
||||
// the module regardless of their actual placement in the file.
|
||||
|
||||
@@ -6,6 +6,7 @@ import { readFile } from 'node:fs/promises';
|
||||
import { DNSFallbackSchema } from '../ts/types/DNSFallback.std.js';
|
||||
import type { DNSFallbackType } from '../ts/types/DNSFallback.std.js';
|
||||
import { parseUnknown } from '../ts/util/schemas.std.js';
|
||||
import { getAppRootDir } from '../ts/util/appRootDir.main.js';
|
||||
import { createLogger } from '../ts/logging/log.std.js';
|
||||
|
||||
const log = createLogger('dns-fallback');
|
||||
@@ -17,7 +18,7 @@ export async function getDNSFallback(): Promise<DNSFallbackType> {
|
||||
return cached;
|
||||
}
|
||||
|
||||
const configPath = join(__dirname, '..', 'build', 'dns-fallback.json');
|
||||
const configPath = join(getAppRootDir(), 'build', 'dns-fallback.json');
|
||||
let str: string;
|
||||
try {
|
||||
str = await readFile(configPath, 'utf8');
|
||||
@@ -20,19 +20,25 @@ const { merge } = lodash;
|
||||
type CompactLocaleMessagesType = ReadonlyArray<string | null>;
|
||||
type CompactLocaleKeysType = ReadonlyArray<string>;
|
||||
|
||||
function getLocaleMessages(locale: string): LocaleMessagesType {
|
||||
const targetFile = join(__dirname, '..', '_locales', locale, 'messages.json');
|
||||
function getLocaleMessages(
|
||||
rootDir: string,
|
||||
locale: string
|
||||
): LocaleMessagesType {
|
||||
const targetFile = join(rootDir, '_locales', locale, 'messages.json');
|
||||
|
||||
return JSON.parse(readFileSync(targetFile, 'utf-8'));
|
||||
}
|
||||
|
||||
function getCompactLocaleKeys(): CompactLocaleKeysType {
|
||||
const targetFile = join(__dirname, '..', '_locales', 'keys.json');
|
||||
function getCompactLocaleKeys(rootDir: string): CompactLocaleKeysType {
|
||||
const targetFile = join(rootDir, '_locales', 'keys.json');
|
||||
return JSON.parse(readFileSync(targetFile, 'utf-8'));
|
||||
}
|
||||
|
||||
function getCompactLocaleValues(locale: string): CompactLocaleMessagesType {
|
||||
const targetFile = join(__dirname, '..', '_locales', locale, 'values.json');
|
||||
function getCompactLocaleValues(
|
||||
rootDir: string,
|
||||
locale: string
|
||||
): CompactLocaleMessagesType {
|
||||
const targetFile = join(rootDir, '_locales', locale, 'values.json');
|
||||
|
||||
return JSON.parse(readFileSync(targetFile, 'utf-8'));
|
||||
}
|
||||
@@ -40,23 +46,13 @@ function getCompactLocaleValues(locale: string): CompactLocaleMessagesType {
|
||||
export type LocaleDisplayNames = Record<string, Record<string, string>>;
|
||||
export type CountryDisplayNames = Record<string, Record<string, string>>;
|
||||
|
||||
function getLocaleDisplayNames(): LocaleDisplayNames {
|
||||
const targetFile = join(
|
||||
__dirname,
|
||||
'..',
|
||||
'build',
|
||||
'locale-display-names.json'
|
||||
);
|
||||
function getLocaleDisplayNames(rootDir: string): LocaleDisplayNames {
|
||||
const targetFile = join(rootDir, 'build', 'locale-display-names.json');
|
||||
return JSON.parse(readFileSync(targetFile, 'utf-8'));
|
||||
}
|
||||
|
||||
function getCountryDisplayNames(): CountryDisplayNames {
|
||||
const targetFile = join(
|
||||
__dirname,
|
||||
'..',
|
||||
'build',
|
||||
'country-display-names.json'
|
||||
);
|
||||
function getCountryDisplayNames(rootDir: string): CountryDisplayNames {
|
||||
const targetFile = join(rootDir, 'build', 'country-display-names.json');
|
||||
return JSON.parse(readFileSync(targetFile, 'utf-8'));
|
||||
}
|
||||
|
||||
@@ -77,16 +73,14 @@ function getLocaleDirection(localeName: string): LocaleDirection {
|
||||
return new Intl.Locale(localeName).getTextInfo().direction ?? 'ltr';
|
||||
}
|
||||
|
||||
export function _getAvailableLocales(): Array<string> {
|
||||
export function _getAvailableLocales(rootDir: string): Array<string> {
|
||||
return JSON.parse(
|
||||
readFileSync(
|
||||
join(__dirname, '..', 'build', 'available-locales.json'),
|
||||
'utf-8'
|
||||
)
|
||||
readFileSync(join(rootDir, 'build', 'available-locales.json'), 'utf-8')
|
||||
) as Array<string>;
|
||||
}
|
||||
|
||||
export function load({
|
||||
rootDir,
|
||||
hourCyclePreference,
|
||||
isPackaged,
|
||||
localeDirectionTestingOverride,
|
||||
@@ -94,6 +88,7 @@ export function load({
|
||||
logger,
|
||||
preferredSystemLocales,
|
||||
}: {
|
||||
rootDir: string;
|
||||
hourCyclePreference: HourCyclePreference;
|
||||
isPackaged: boolean;
|
||||
localeDirectionTestingOverride: LocaleDirection | null;
|
||||
@@ -109,7 +104,7 @@ export function load({
|
||||
logger.warn('locale: `preferredSystemLocales` was empty');
|
||||
}
|
||||
|
||||
const availableLocales = _getAvailableLocales();
|
||||
const availableLocales = _getAvailableLocales(rootDir);
|
||||
|
||||
logger.info('locale: Supported locales:', availableLocales.join(', '));
|
||||
logger.info('locale: Preferred locales:', preferredSystemLocales.join(', '));
|
||||
@@ -124,14 +119,17 @@ export function load({
|
||||
|
||||
logger.info(`locale: Matched locale: ${matchedLocale}`);
|
||||
|
||||
const localeDisplayNames = getLocaleDisplayNames();
|
||||
const countryDisplayNames = getCountryDisplayNames();
|
||||
const localeDisplayNames = getLocaleDisplayNames(rootDir);
|
||||
const countryDisplayNames = getCountryDisplayNames(rootDir);
|
||||
|
||||
let finalMessages: LocaleMessagesType;
|
||||
if (isPackaged) {
|
||||
const matchedLocaleMessages = getCompactLocaleValues(matchedLocale);
|
||||
const englishMessages = getCompactLocaleValues('en');
|
||||
const keys = getCompactLocaleKeys();
|
||||
const matchedLocaleMessages = getCompactLocaleValues(
|
||||
rootDir,
|
||||
matchedLocale
|
||||
);
|
||||
const englishMessages = getCompactLocaleValues(rootDir, 'en');
|
||||
const keys = getCompactLocaleKeys(rootDir);
|
||||
if (matchedLocaleMessages.length !== keys.length) {
|
||||
throw new Error(
|
||||
`Invalid "${matchedLocale}" entry count, ` +
|
||||
@@ -153,8 +151,8 @@ export function load({
|
||||
};
|
||||
}
|
||||
} else {
|
||||
const matchedLocaleMessages = getLocaleMessages(matchedLocale);
|
||||
const englishMessages = getLocaleMessages('en');
|
||||
const matchedLocaleMessages = getLocaleMessages(rootDir, matchedLocale);
|
||||
const englishMessages = getLocaleMessages(rootDir, 'en');
|
||||
|
||||
// We start with english, then overwrite that with anything present in locale
|
||||
finalMessages = merge(englishMessages, matchedLocaleMessages);
|
||||
|
||||
@@ -32,15 +32,12 @@ import {
|
||||
import type { MenuItemConstructorOptions, Settings } from 'electron';
|
||||
import { z } from 'zod';
|
||||
|
||||
import {
|
||||
version as packageVersion,
|
||||
productName,
|
||||
} from '../ts/util/packageJson.node.js';
|
||||
import { packageJson } from '../ts/util/packageJson.main.js';
|
||||
import * as GlobalErrors from './global_errors.main.js';
|
||||
import { setup as setupCrashReports } from './crashReports.main.js';
|
||||
import { setup as setupSpellChecker } from './spell_check.main.js';
|
||||
import { getDNSFallback } from './dns-fallback.node.js';
|
||||
import { redactAll, addSensitivePath } from '../ts/util/privacy.node.js';
|
||||
import { getDNSFallback } from './dns-fallback.main.js';
|
||||
import { redactAll, addSensitivePath } from './privacy.main.js';
|
||||
import { createSupportUrl } from '../ts/util/createSupportUrl.std.js';
|
||||
import { missingCaseError } from '../ts/util/missingCaseError.std.js';
|
||||
import { strictAssert } from '../ts/util/assert.std.js';
|
||||
@@ -137,6 +134,7 @@ import { safeParseLoose, safeParseUnknown } from '../ts/util/schemas.std.js';
|
||||
import { getAppErrorIcon } from '../ts/util/getAppErrorIcon.node.js';
|
||||
import { promptOSAuth } from '../ts/util/os/promptOSAuthMain.main.js';
|
||||
import { appRelaunch } from '../ts/util/relaunch.main.js';
|
||||
import { getAppRootDir } from '../ts/util/appRootDir.main.js';
|
||||
import {
|
||||
sendDummyKeystroke,
|
||||
show as showWindowsNotification,
|
||||
@@ -626,13 +624,14 @@ function isVisible(window: BoundsType, bounds: BoundsType) {
|
||||
}
|
||||
|
||||
let windowIcon: string;
|
||||
const rootDir = getAppRootDir();
|
||||
|
||||
if (OS.isWindows()) {
|
||||
windowIcon = join(__dirname, '../build/icons/win/icon.ico');
|
||||
windowIcon = join(rootDir, 'build', 'icons', 'win', 'icon.ico');
|
||||
} else if (OS.isLinux()) {
|
||||
windowIcon = join(__dirname, '../images/signal-logo-desktop-linux.png');
|
||||
windowIcon = join(rootDir, 'images', 'signal-logo-desktop-linux.png');
|
||||
} else {
|
||||
windowIcon = join(__dirname, '../build/icons/png/512x512.png');
|
||||
windowIcon = join(rootDir, 'build', 'icons', 'png', '512x512.png');
|
||||
}
|
||||
|
||||
// The titlebar is hidden on:
|
||||
@@ -722,10 +721,10 @@ async function createWindow() {
|
||||
sandbox: false,
|
||||
contextIsolation: !isTestEnvironment(getEnvironment()),
|
||||
preload: join(
|
||||
__dirname,
|
||||
usePreloadBundle
|
||||
? '../preload.wrapper.js'
|
||||
: '../ts/windows/main/preload.preload.js'
|
||||
rootDir,
|
||||
...(usePreloadBundle
|
||||
? ['preload.wrapper.js']
|
||||
: ['ts', 'windows', 'main', 'preload.preload.js'])
|
||||
),
|
||||
spellcheck,
|
||||
},
|
||||
@@ -1056,8 +1055,8 @@ async function createWindow() {
|
||||
await safeLoadURL(
|
||||
mainWindow,
|
||||
getEnvironment() === Environment.Test
|
||||
? await prepareFileUrl([__dirname, '../test/index.html'])
|
||||
: await prepareFileUrl([__dirname, '../background.html'])
|
||||
? await prepareFileUrl([rootDir, 'test', 'index.html'])
|
||||
: await prepareFileUrl([rootDir, 'background.html'])
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1304,7 +1303,7 @@ async function showScreenShareWindow(sourceName: string | undefined) {
|
||||
nodeIntegrationInWorker: false,
|
||||
sandbox: true,
|
||||
contextIsolation: true,
|
||||
preload: join(__dirname, '../bundles/screenShare/preload.preload.js'),
|
||||
preload: join(rootDir, 'bundles', 'screenShare', 'preload.preload.js'),
|
||||
},
|
||||
x: Math.floor(display.size.width / 2) - width / 2,
|
||||
y: 24,
|
||||
@@ -1326,7 +1325,7 @@ async function showScreenShareWindow(sourceName: string | undefined) {
|
||||
|
||||
await safeLoadURL(
|
||||
screenShareWindow,
|
||||
await prepareFileUrl([__dirname, '../screenShare.html'], { sourceName })
|
||||
await prepareFileUrl([rootDir, 'screenShare.html'], { sourceName })
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1352,7 +1351,7 @@ async function showAbout() {
|
||||
nodeIntegrationInWorker: false,
|
||||
sandbox: true,
|
||||
contextIsolation: true,
|
||||
preload: join(__dirname, '../bundles/about/preload.preload.js'),
|
||||
preload: join(rootDir, 'bundles', 'about', 'preload.preload.js'),
|
||||
nativeWindowOpen: true,
|
||||
},
|
||||
};
|
||||
@@ -1371,10 +1370,7 @@ async function showAbout() {
|
||||
}
|
||||
});
|
||||
|
||||
await safeLoadURL(
|
||||
aboutWindow,
|
||||
await prepareFileUrl([__dirname, '../about.html'])
|
||||
);
|
||||
await safeLoadURL(aboutWindow, await prepareFileUrl([rootDir, 'about.html']));
|
||||
}
|
||||
|
||||
async function getIsLinked() {
|
||||
@@ -1416,7 +1412,7 @@ async function showDebugLogWindow(options: DebugLogWindowOptions = {}) {
|
||||
if (debugLogWindow) {
|
||||
if (debugLogCurrentMode !== newMode) {
|
||||
debugLogCurrentMode = newMode;
|
||||
const url = pathToFileURL(join(__dirname, '../debug_log.html'));
|
||||
const url = pathToFileURL(join(rootDir, 'debug_log.html'));
|
||||
url.searchParams.set('mode', newMode);
|
||||
await safeLoadURL(debugLogWindow, url.href);
|
||||
}
|
||||
@@ -1457,7 +1453,7 @@ async function showDebugLogWindow(options: DebugLogWindowOptions = {}) {
|
||||
nodeIntegrationInWorker: false,
|
||||
sandbox: true,
|
||||
contextIsolation: true,
|
||||
preload: join(__dirname, '../bundles/debuglog/preload.preload.js'),
|
||||
preload: join(rootDir, 'bundles', 'debuglog', 'preload.preload.js'),
|
||||
},
|
||||
parent: mainWindow,
|
||||
};
|
||||
@@ -1480,7 +1476,7 @@ async function showDebugLogWindow(options: DebugLogWindowOptions = {}) {
|
||||
}
|
||||
});
|
||||
|
||||
const url = pathToFileURL(join(__dirname, '../debug_log.html'));
|
||||
const url = pathToFileURL(join(rootDir, 'debug_log.html'));
|
||||
if (options.mode) {
|
||||
url.searchParams.set('mode', options.mode);
|
||||
}
|
||||
@@ -1527,7 +1523,7 @@ async function showCallDiagnosticWindow() {
|
||||
nodeIntegrationInWorker: false,
|
||||
sandbox: true,
|
||||
contextIsolation: true,
|
||||
preload: join(__dirname, '../bundles/calldiagnostic/preload.preload.js'),
|
||||
preload: join(rootDir, 'bundles', 'calldiagnostic', 'preload.preload.js'),
|
||||
},
|
||||
parent: mainWindow,
|
||||
};
|
||||
@@ -1549,7 +1545,7 @@ async function showCallDiagnosticWindow() {
|
||||
}
|
||||
});
|
||||
|
||||
const url = pathToFileURL(join(__dirname, '../call_diagnostic.html'));
|
||||
const url = pathToFileURL(join(rootDir, 'call_diagnostic.html'));
|
||||
await safeLoadURL(callDiagnosticWindow, url.href);
|
||||
}
|
||||
|
||||
@@ -1586,7 +1582,7 @@ function showPermissionsPopupWindow(forCalling: boolean, forCamera: boolean) {
|
||||
nodeIntegrationInWorker: false,
|
||||
sandbox: true,
|
||||
contextIsolation: true,
|
||||
preload: join(__dirname, '../bundles/permissions/preload.preload.js'),
|
||||
preload: join(rootDir, 'bundles', 'permissions', 'preload.preload.js'),
|
||||
nativeWindowOpen: true,
|
||||
},
|
||||
parent: mainWindow,
|
||||
@@ -1612,7 +1608,7 @@ function showPermissionsPopupWindow(forCalling: boolean, forCamera: boolean) {
|
||||
|
||||
await safeLoadURL(
|
||||
permissionsPopupWindow,
|
||||
await prepareFileUrl([__dirname, '../permissions_popup.html'], {
|
||||
await prepareFileUrl([rootDir, 'permissions_popup.html'], {
|
||||
forCalling,
|
||||
forCamera,
|
||||
})
|
||||
@@ -1790,7 +1786,7 @@ function handleSafeStorageDecryptionError(): 'continue' | 'quit' {
|
||||
cancelId: copyErrorAndQuitIndex,
|
||||
message,
|
||||
detail,
|
||||
icon: getAppErrorIcon(),
|
||||
icon: getAppErrorIcon(rootDir),
|
||||
noLink: true,
|
||||
});
|
||||
if (resultIndex === copyErrorAndQuitIndex) {
|
||||
@@ -1951,7 +1947,7 @@ const onDatabaseInitializationError = async (error: Error) => {
|
||||
cancelId: copyErrorAndQuitButtonIndex,
|
||||
message: messageTitle,
|
||||
detail: messageDetail,
|
||||
icon: getAppErrorIcon(),
|
||||
icon: getAppErrorIcon(rootDir),
|
||||
noLink: true,
|
||||
});
|
||||
|
||||
@@ -1977,7 +1973,7 @@ const onDatabaseInitializationError = async (error: Error) => {
|
||||
cancelId: cancelButtonIndex,
|
||||
message: i18n('icu:databaseError__deleteDataConfirmation'),
|
||||
detail: i18n('icu:databaseError__deleteDataConfirmation__detail'),
|
||||
icon: getAppErrorIcon(),
|
||||
icon: getAppErrorIcon(rootDir),
|
||||
noLink: true,
|
||||
});
|
||||
|
||||
@@ -2080,7 +2076,7 @@ app.on('ready', async () => {
|
||||
const [userDataPath, crashDumpsPath, installPath] = await Promise.all([
|
||||
realpath(app.getPath('userData')),
|
||||
realpath(app.getPath('crashDumps')),
|
||||
realpath(app.getAppPath()),
|
||||
realpath(rootDir),
|
||||
]);
|
||||
|
||||
updateDefaultSession(session.defaultSession, log);
|
||||
@@ -2120,6 +2116,7 @@ app.on('ready', async () => {
|
||||
|
||||
log.info('app.ready: preferred system locales:', preferredSystemLocales);
|
||||
resolvedTranslationsLocale = loadLocale({
|
||||
rootDir,
|
||||
hourCyclePreference,
|
||||
isPackaged: app.isPackaged,
|
||||
localeDirectionTestingOverride,
|
||||
@@ -2233,7 +2230,7 @@ app.on('ready', async () => {
|
||||
}
|
||||
|
||||
log.info('app ready');
|
||||
log.info(`starting version ${packageVersion}`);
|
||||
log.info(`starting version ${packageJson.version}`);
|
||||
|
||||
// This logging helps us debug user reports about broken devices.
|
||||
{
|
||||
@@ -2292,7 +2289,7 @@ app.on('ready', async () => {
|
||||
nodeIntegration: false,
|
||||
sandbox: true,
|
||||
contextIsolation: true,
|
||||
preload: join(__dirname, '../bundles/loading/preload.preload.js'),
|
||||
preload: join(rootDir, 'bundles', 'loading', 'preload.preload.js'),
|
||||
},
|
||||
icon: windowIcon,
|
||||
});
|
||||
@@ -2310,7 +2307,7 @@ app.on('ready', async () => {
|
||||
|
||||
await safeLoadURL(
|
||||
loadingWindow,
|
||||
await prepareFileUrl([__dirname, '../loading.html'])
|
||||
await prepareFileUrl([rootDir, 'loading.html'])
|
||||
);
|
||||
})
|
||||
);
|
||||
@@ -2863,7 +2860,7 @@ ipc.on('get-config', async event => {
|
||||
}
|
||||
|
||||
const parsed = safeParseLoose(rendererConfigSchema, {
|
||||
name: productName,
|
||||
name: packageJson.productName,
|
||||
availableLocales: getResolvedMessagesLocale().availableLocales,
|
||||
resolvedTranslationsLocale: getResolvedMessagesLocale().name,
|
||||
resolvedTranslationsLocaleDirection: getResolvedMessagesLocale().direction,
|
||||
@@ -2915,7 +2912,7 @@ ipc.on('get-config', async event => {
|
||||
// paths
|
||||
crashDumpsPath: app.getPath('crashDumps'),
|
||||
homePath: app.getPath('home'),
|
||||
installPath: app.getAppPath(),
|
||||
installPath: rootDir,
|
||||
userDataPath: app.getPath('userData'),
|
||||
|
||||
directoryConfig: directoryConfig.data,
|
||||
@@ -3411,8 +3408,11 @@ async function showStickerCreatorWindow() {
|
||||
sandbox: true,
|
||||
contextIsolation: true,
|
||||
preload: join(
|
||||
__dirname,
|
||||
'../ts/windows/sticker-creator/preload.preload.js'
|
||||
rootDir,
|
||||
'ts',
|
||||
'windows',
|
||||
'sticker-creator',
|
||||
'preload.preload.js'
|
||||
),
|
||||
nativeWindowOpen: true,
|
||||
},
|
||||
@@ -3432,7 +3432,7 @@ async function showStickerCreatorWindow() {
|
||||
|
||||
await safeLoadURL(
|
||||
stickerCreatorWindow,
|
||||
await prepareFileUrl([__dirname, '../sticker-creator/dist/index.html'])
|
||||
await prepareFileUrl([rootDir, 'sticker-creator', 'dist', 'index.html'])
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
9
app/privacy.main.ts
Normal file
9
app/privacy.main.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
// Copyright 2026 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { redactAll, addSensitivePath } from '../ts/util/privacy.node.js';
|
||||
import { getAppRootDir } from '../ts/util/appRootDir.main.js';
|
||||
|
||||
addSensitivePath(getAppRootDir());
|
||||
|
||||
export { redactAll, addSensitivePath };
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
import { app } from 'electron';
|
||||
|
||||
import { name } from '../ts/util/packageJson.node.js';
|
||||
import { packageJson } from '../ts/util/packageJson.main.js';
|
||||
import { createLogger } from '../ts/logging/log.std.js';
|
||||
import * as GlobalErrors from './global_errors.main.js';
|
||||
|
||||
@@ -15,7 +15,7 @@ GlobalErrors.addHandler();
|
||||
// set such that only we have read access to our files
|
||||
process.umask(0o077);
|
||||
|
||||
export const AUMID = `org.whispersystems.${name}`;
|
||||
export const AUMID = `org.whispersystems.${packageJson.name}`;
|
||||
log.info('Set Windows Application User Model ID (AUMID)', {
|
||||
AUMID,
|
||||
});
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
"generate:phase-1": "run-p --aggregate-output --print-label generate:phase-1:bundle build:icu-types build:compact-locales build:styles get-expire-time copy-components build:policy-files",
|
||||
"generate:phase-1:bundle": "run-s build:protobuf build:esbuild:bundle",
|
||||
"build-release": "pnpm run build",
|
||||
"sign-release": "node ts/updater/generateSignature.js",
|
||||
"notarize": "echo 'No longer necessary'",
|
||||
"get-strings": "ts-node ts/scripts/get-strings.node.ts && ts-node ts/scripts/gen-nsis-script.node.ts && ts-node ts/scripts/gen-locales-config.node.ts && run-p get-strings:locales get-strings:countries get-strings:emoji mark-unusued-strings-deleted && run-p build:compact-locales",
|
||||
"get-strings:locales": "ts-node ./ts/scripts/build-localized-display-names.node.ts locales ts/scripts/locale-data/locale-display-names.csv build/locale-display-names.json",
|
||||
|
||||
@@ -7,7 +7,7 @@ const chaiAsPromised = require('chai-as-promised');
|
||||
const { Crypto } = require('../ts/context/Crypto.node.js');
|
||||
const { setEnvironment, Environment } = require('../ts/environment.std.js');
|
||||
const { HourCyclePreference } = require('../ts/types/I18N.std.js');
|
||||
const { default: package } = require('../ts/util/packageJson.node.js');
|
||||
const { packageJson } = require('../ts/util/packageJson.node.js');
|
||||
|
||||
chai.use(chaiAsPromised);
|
||||
|
||||
@@ -20,14 +20,14 @@ global.window = {
|
||||
SignalContext: {
|
||||
i18n: key => `i18n(${key})`,
|
||||
getPath: () => '/tmp',
|
||||
getVersion: () => package.version,
|
||||
getVersion: () => packageJson.version,
|
||||
config: {
|
||||
serverUrl: 'https://127.0.0.1:9',
|
||||
storageUrl: 'https://127.0.0.1:9',
|
||||
updatesUrl: 'https://127.0.0.1:9',
|
||||
resourcesUrl: 'https://127.0.0.1:9',
|
||||
certificateAuthority: package.certificateAuthority,
|
||||
version: package.version,
|
||||
certificateAuthority: packageJson.certificateAuthority,
|
||||
version: packageJson.version,
|
||||
},
|
||||
crypto: new Crypto(),
|
||||
getResolvedMessagesLocale: () => 'en',
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
import { parse } from 'csv-parse';
|
||||
import fs from 'node:fs/promises';
|
||||
import { join } from 'node:path';
|
||||
import { z } from 'zod';
|
||||
import { _getAvailableLocales } from '../../app/locale.node.js';
|
||||
import { parseUnknown } from '../util/schemas.std.js';
|
||||
@@ -21,8 +22,9 @@ if (!process.argv[4]) {
|
||||
throw new Error('Missing third argument: output json file');
|
||||
}
|
||||
const localeDisplayNamesBuildPath = process.argv[4];
|
||||
const rootDir = join(__dirname, '..', '..');
|
||||
|
||||
const availableLocales = _getAvailableLocales();
|
||||
const availableLocales = _getAvailableLocales(rootDir);
|
||||
|
||||
const LocaleString = z.string().refine(arg => {
|
||||
try {
|
||||
|
||||
@@ -14,7 +14,7 @@ import { Format, NtExecutable } from 'pe-library';
|
||||
import ELECTRON_BINARY from 'electron';
|
||||
|
||||
import { drop } from '../util/drop.std.js';
|
||||
import packageJson from '../util/packageJson.node.js';
|
||||
import { packageJson } from '../util/packageJson.node.js';
|
||||
|
||||
const { ImageDosHeader, ImageNtHeaders, ImageDirectoryEntry } = Format;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import { execSync } from 'node:child_process';
|
||||
import { writeFileSync } from 'node:fs';
|
||||
|
||||
import { DAY } from '../util/durations/index.std.js';
|
||||
import { version } from '../util/packageJson.node.js';
|
||||
import { packageJson } from '../util/packageJson.node.js';
|
||||
import { isNotUpdatable } from '../util/version.std.js';
|
||||
|
||||
const unixTimestamp = parseInt(
|
||||
@@ -18,7 +18,7 @@ const buildCreation = unixTimestamp * 1000;
|
||||
|
||||
// NB: Build expirations are also determined via users' auto-update settings; see
|
||||
// getExpirationTimestamp
|
||||
const validDuration = isNotUpdatable(version) ? DAY * 30 : DAY * 90;
|
||||
const validDuration = isNotUpdatable(packageJson.version) ? DAY * 30 : DAY * 90;
|
||||
const buildExpiration = buildCreation + validDuration;
|
||||
|
||||
const localProductionPath = join(
|
||||
@@ -29,7 +29,7 @@ const localProductionPath = join(
|
||||
const localProductionConfig = {
|
||||
buildCreation,
|
||||
buildExpiration,
|
||||
...(isNotUpdatable(version) ? { updatesEnabled: false } : {}),
|
||||
...(isNotUpdatable(packageJson.version) ? { updatesEnabled: false } : {}),
|
||||
};
|
||||
|
||||
writeFileSync(
|
||||
|
||||
@@ -5,7 +5,7 @@ import type { BuildResult } from 'electron-builder';
|
||||
|
||||
import { notarize } from '@electron/notarize';
|
||||
|
||||
import { build } from '../util/packageJson.node.js';
|
||||
import { packageJson } from '../util/packageJson.node.js';
|
||||
|
||||
export async function afterAllArtifactBuild({
|
||||
platformToTargets,
|
||||
@@ -24,7 +24,7 @@ export async function afterAllArtifactBuild({
|
||||
return;
|
||||
}
|
||||
|
||||
const appBundleId = build.appId;
|
||||
const appBundleId = packageJson.build.appId;
|
||||
if (!appBundleId) {
|
||||
throw new Error(
|
||||
'appBundleId must be provided in package.json: build.appId'
|
||||
|
||||
@@ -6,7 +6,7 @@ import type { AfterPackContext } from 'electron-builder';
|
||||
|
||||
import { notarize } from '@electron/notarize';
|
||||
|
||||
import { build } from '../util/packageJson.node.js';
|
||||
import { packageJson } from '../util/packageJson.node.js';
|
||||
|
||||
export async function afterSign({
|
||||
appOutDir,
|
||||
@@ -22,7 +22,7 @@ export async function afterSign({
|
||||
|
||||
const appPath = path.join(appOutDir, `${productFilename}.app`);
|
||||
|
||||
const appBundleId = build.appId;
|
||||
const appBundleId = packageJson.build.appId;
|
||||
if (!appBundleId) {
|
||||
throw new Error(
|
||||
'appBundleId must be provided in package.json: build.appId'
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
import { stat } from 'node:fs/promises';
|
||||
import { join } from 'node:path';
|
||||
|
||||
import { name as NAME, version as VERSION } from '../util/packageJson.node.js';
|
||||
import { packageJson } from '../util/packageJson.node.js';
|
||||
|
||||
const NAME = packageJson.name;
|
||||
const VERSION = packageJson.version;
|
||||
|
||||
const SUPPORT_CONFIG = new Set([
|
||||
'linux',
|
||||
|
||||
@@ -9,7 +9,7 @@ import { mkdtemp, cp } from 'node:fs/promises';
|
||||
import { constants as fsConstants } from 'node:fs';
|
||||
import { _electron as electron } from 'playwright';
|
||||
|
||||
import { productName, name } from '../util/packageJson.node.js';
|
||||
import { packageJson } from '../util/packageJson.node.js';
|
||||
import { gracefulRmRecursive } from '../util/gracefulFs.node.js';
|
||||
import { consoleLogger } from '../util/consoleLogger.std.js';
|
||||
|
||||
@@ -21,24 +21,24 @@ let exe: string;
|
||||
if (process.platform === 'darwin') {
|
||||
archive = join(
|
||||
'mac-arm64',
|
||||
`${productName}.app`,
|
||||
`${packageJson.productName}.app`,
|
||||
'Contents',
|
||||
'Resources',
|
||||
'app.asar'
|
||||
);
|
||||
exe = join(
|
||||
'mac-arm64',
|
||||
`${productName}.app`,
|
||||
`${packageJson.productName}.app`,
|
||||
'Contents',
|
||||
'MacOS',
|
||||
productName
|
||||
packageJson.productName
|
||||
);
|
||||
} else if (process.platform === 'win32') {
|
||||
archive = join('win-unpacked', 'resources', 'app.asar');
|
||||
exe = join('win-unpacked', `${productName}.exe`);
|
||||
exe = join('win-unpacked', `${packageJson.productName}.exe`);
|
||||
} else if (process.platform === 'linux') {
|
||||
archive = join('linux-unpacked', 'resources', 'app.asar');
|
||||
exe = join('linux-unpacked', name);
|
||||
exe = join('linux-unpacked', packageJson.name);
|
||||
} else {
|
||||
throw new Error(`Unsupported platform: ${process.platform}`);
|
||||
}
|
||||
@@ -87,7 +87,7 @@ const main = async () => {
|
||||
);
|
||||
|
||||
console.log('Checking window title');
|
||||
assert.strictEqual(await window.title(), productName);
|
||||
assert.strictEqual(await window.title(), packageJson.productName);
|
||||
|
||||
await app.close();
|
||||
} finally {
|
||||
|
||||
@@ -8,6 +8,7 @@ import { app } from 'electron';
|
||||
|
||||
import { strictAssert } from '../util/assert.std.js';
|
||||
import { explodePromise } from '../util/explodePromise.std.js';
|
||||
import { getAppRootDir } from '../util/appRootDir.main.js';
|
||||
import type { LoggerType } from '../types/Logging.std.js';
|
||||
import * as Errors from '../types/errors.std.js';
|
||||
import { SqliteErrorKind } from './errors.std.js';
|
||||
@@ -551,12 +552,7 @@ export class MainSQL {
|
||||
}
|
||||
|
||||
#createWorker(): CreateWorkerResultType {
|
||||
const scriptPath = join(
|
||||
app.getAppPath(),
|
||||
'ts',
|
||||
'sql',
|
||||
'mainWorker.node.js'
|
||||
);
|
||||
const scriptPath = join(getAppRootDir(), 'ts', 'sql', 'mainWorker.node.js');
|
||||
|
||||
const worker = new Worker(scriptPath);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { join } from 'node:path';
|
||||
import { assert } from 'chai';
|
||||
import { stub } from 'sinon';
|
||||
import * as LocaleMatcher from '@formatjs/intl-localematcher';
|
||||
@@ -8,6 +9,8 @@ import { load, _getAvailableLocales } from '../../../app/locale.node.js';
|
||||
import { FAKE_DEFAULT_LOCALE } from '../../../app/spell_check.main.js';
|
||||
import { HourCyclePreference } from '../../types/I18N.std.js';
|
||||
|
||||
const rootDir = join(__dirname, '..', '..', '..');
|
||||
|
||||
describe('locale', async () => {
|
||||
describe('load', () => {
|
||||
it('resolves expected locales correctly', async () => {
|
||||
@@ -26,6 +29,7 @@ describe('locale', async () => {
|
||||
expectedLocale: string
|
||||
) {
|
||||
const actualLocale = await load({
|
||||
rootDir,
|
||||
hourCyclePreference: HourCyclePreference.UnknownPreference,
|
||||
isPackaged: false,
|
||||
localeDirectionTestingOverride: null,
|
||||
@@ -150,7 +154,7 @@ describe('locale', async () => {
|
||||
'VE',
|
||||
];
|
||||
|
||||
const availableLocales = _getAvailableLocales();
|
||||
const availableLocales = _getAvailableLocales(rootDir);
|
||||
|
||||
for (const locale of SINGLE_REGION_LOCALES) {
|
||||
const { language } = new Intl.Locale(locale);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2018 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { join } from 'node:path';
|
||||
import { assert } from 'chai';
|
||||
import { stub } from 'sinon';
|
||||
import type { MenuItemConstructorOptions } from 'electron';
|
||||
@@ -214,6 +215,7 @@ describe('createTemplate', () => {
|
||||
};
|
||||
|
||||
const { i18n } = loadLocale({
|
||||
rootDir: join(__dirname, '..', '..', '..'),
|
||||
hourCyclePreference: HourCyclePreference.UnknownPreference,
|
||||
isPackaged: false,
|
||||
localeDirectionTestingOverride: null,
|
||||
|
||||
@@ -9,14 +9,14 @@ import { tmpdir } from 'node:os';
|
||||
|
||||
import { strictAssert } from '../../util/assert.std.js';
|
||||
import * as durations from '../../util/durations/index.std.js';
|
||||
import { getGotOptions } from '../../updater/got.node.js';
|
||||
import { getGotOptions } from '../../updater/got.main.js';
|
||||
import {
|
||||
computeDiff,
|
||||
getBlockMapFileName,
|
||||
prepareDownload,
|
||||
isValidPreparedData,
|
||||
download,
|
||||
} from '../../updater/differential.node.js';
|
||||
} from '../../updater/differential.main.js';
|
||||
|
||||
const FIXTURES = path.join(__dirname, '..', '..', '..', 'fixtures');
|
||||
const CRLF = '\r\n';
|
||||
@@ -4,10 +4,12 @@
|
||||
import { assert } from 'chai';
|
||||
|
||||
import * as Privacy from '../../util/privacy.node.js';
|
||||
import { APP_ROOT_PATH } from '../../util/privacy.node.js';
|
||||
|
||||
Privacy.addSensitivePath('sensitive-path');
|
||||
|
||||
const APP_ROOT_PATH = __dirname;
|
||||
Privacy.addSensitivePath(APP_ROOT_PATH);
|
||||
|
||||
describe('Privacy', () => {
|
||||
describe('redactCardNumbers', () => {
|
||||
it('should redact anything that looks like a credit card', () => {
|
||||
|
||||
24
ts/types/packageJson.d.ts
vendored
Normal file
24
ts/types/packageJson.d.ts
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright 2026 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type { ReadonlyDeep } from 'type-fest';
|
||||
|
||||
export type PackageJsonType = ReadonlyDeep<{
|
||||
name: string;
|
||||
version: string;
|
||||
productName: string;
|
||||
build: {
|
||||
appId: string;
|
||||
mac: {
|
||||
releaseInfo: {
|
||||
vendor: {
|
||||
minOSVersion: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
deb: {
|
||||
depends: Array<string>;
|
||||
};
|
||||
files: Array<string | Record<string, unknown>>;
|
||||
};
|
||||
}>;
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright 2019 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
/* eslint-disable no-console */
|
||||
import { createWriteStream } from 'node:fs';
|
||||
import fsExtra from 'fs-extra';
|
||||
import { mkdir, readdir, stat, writeFile } from 'node:fs/promises';
|
||||
@@ -10,8 +9,6 @@ import { release as osRelease, tmpdir } from 'node:os';
|
||||
import { extname, join, normalize } from 'node:path';
|
||||
|
||||
import config from 'config';
|
||||
import type { ParserConfiguration } from 'dashdash';
|
||||
import { createParser } from 'dashdash';
|
||||
import { FAILSAFE_SCHEMA, load as loadYaml } from 'js-yaml';
|
||||
import { gt, gte, lt } from 'semver';
|
||||
import got from 'got';
|
||||
@@ -39,7 +36,7 @@ import {
|
||||
} from '../util/version.std.js';
|
||||
import { isPathInside } from '../util/isPathInside.node.js';
|
||||
|
||||
import { version as packageVersion } from '../util/packageJson.node.js';
|
||||
import { packageJson } from '../util/packageJson.main.js';
|
||||
|
||||
import {
|
||||
getSignatureFileName,
|
||||
@@ -51,8 +48,8 @@ import {
|
||||
getBlockMapFileName,
|
||||
isValidPreparedData as isValidDifferentialData,
|
||||
prepareDownload as prepareDifferentialDownload,
|
||||
} from './differential.node.js';
|
||||
import { getGotOptions } from './got.node.js';
|
||||
} from './differential.main.js';
|
||||
import { getGotOptions } from './got.main.js';
|
||||
import { checkIntegrity, isTimeToUpdate } from './util.node.js';
|
||||
import {
|
||||
gracefulRename,
|
||||
@@ -60,7 +57,7 @@ import {
|
||||
} from '../util/gracefulFs.node.js';
|
||||
|
||||
import type { LoggerType } from '../types/Logging.std.js';
|
||||
import type { PrepareDownloadResultType as DifferentialDownloadDataType } from './differential.node.js';
|
||||
import type { PrepareDownloadResultType as DifferentialDownloadDataType } from './differential.main.js';
|
||||
import type { MainSQL } from '../sql/main.main.js';
|
||||
|
||||
const { pathExists } = fsExtra;
|
||||
@@ -578,7 +575,7 @@ export abstract class Updater {
|
||||
async #checkForUpdates(
|
||||
checkType: CheckType
|
||||
): Promise<UpdateInformationType | undefined> {
|
||||
if (isNotUpdatable(packageVersion)) {
|
||||
if (isNotUpdatable(packageJson.version)) {
|
||||
this.logger.info(
|
||||
'checkForUpdates: not checking for updates, this is not an updatable build'
|
||||
);
|
||||
@@ -605,7 +602,7 @@ export abstract class Updater {
|
||||
|
||||
if (checkType === CheckType.Normal && !isVersionNewer(version)) {
|
||||
this.logger.info(
|
||||
`checkForUpdates: ${version} is not newer than ${packageVersion}; ` +
|
||||
`checkForUpdates: ${version} is not newer than ${packageJson.version}; ` +
|
||||
'no new update available'
|
||||
);
|
||||
|
||||
@@ -1007,27 +1004,27 @@ export function getUpdatesFileName(): string {
|
||||
}
|
||||
|
||||
function getChannel(): string {
|
||||
if (isNotUpdatable(packageVersion)) {
|
||||
if (isNotUpdatable(packageJson.version)) {
|
||||
// we don't want ad hoc versions to update
|
||||
return packageVersion;
|
||||
return packageJson.version;
|
||||
}
|
||||
if (isStaging(packageVersion)) {
|
||||
if (isStaging(packageJson.version)) {
|
||||
return 'staging';
|
||||
}
|
||||
if (isAlpha(packageVersion)) {
|
||||
if (isAlpha(packageJson.version)) {
|
||||
return 'alpha';
|
||||
}
|
||||
if (isAxolotl(packageVersion)) {
|
||||
if (isAxolotl(packageJson.version)) {
|
||||
return 'axolotl';
|
||||
}
|
||||
if (isBeta(packageVersion)) {
|
||||
if (isBeta(packageJson.version)) {
|
||||
return 'beta';
|
||||
}
|
||||
return 'latest';
|
||||
}
|
||||
|
||||
function isVersionNewer(newVersion: string): boolean {
|
||||
return gt(newVersion, packageVersion);
|
||||
return gt(newVersion, packageJson.version);
|
||||
}
|
||||
|
||||
export function getVersion(info: JSONUpdateSchema): string | null {
|
||||
@@ -1179,16 +1176,3 @@ export async function deleteTempDir(
|
||||
|
||||
await gracefulRmRecursive(logger, targetDir);
|
||||
}
|
||||
|
||||
export function getCliOptions<T>(options: ParserConfiguration['options']): T {
|
||||
const parser = createParser({ options });
|
||||
const cliOptions = parser.parse(process.argv);
|
||||
|
||||
if (cliOptions.help) {
|
||||
const help = parser.help().trimRight();
|
||||
console.log(help);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
return cliOptions as unknown as T;
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@ import Dicer from '@indutny/dicer';
|
||||
import { strictAssert } from '../util/assert.std.js';
|
||||
import { wrapEventEmitterOnce } from '../util/wrapEventEmitterOnce.node.js';
|
||||
import type { LoggerType } from '../types/Logging.std.js';
|
||||
import { getGotOptions } from './got.node.js';
|
||||
import type { GotOptions } from './got.node.js';
|
||||
import { getGotOptions } from './got.main.js';
|
||||
import type { GotOptions } from './got.main.js';
|
||||
import { checkIntegrity } from './util.node.js';
|
||||
|
||||
const { chunk: lodashChunk, noop } = lodash;
|
||||
@@ -1,48 +0,0 @@
|
||||
// Copyright 2019 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
/* eslint-disable no-console */
|
||||
import * as Errors from '../types/errors.std.js';
|
||||
import { getCliOptions } from './common.main.js';
|
||||
import { keyPair } from './curve.node.js';
|
||||
import { writeHexToPath } from './signature.node.js';
|
||||
|
||||
const OPTIONS = [
|
||||
{
|
||||
names: ['help', 'h'],
|
||||
type: 'bool',
|
||||
help: 'Print this help and exit.',
|
||||
},
|
||||
{
|
||||
names: ['key', 'k'],
|
||||
type: 'string',
|
||||
help: 'Path where public key will go',
|
||||
default: 'public.key',
|
||||
},
|
||||
{
|
||||
names: ['private', 'p'],
|
||||
type: 'string',
|
||||
help: 'Path where private key will go',
|
||||
default: 'private.key',
|
||||
},
|
||||
];
|
||||
|
||||
type OptionsType = {
|
||||
key: string;
|
||||
private: string;
|
||||
};
|
||||
|
||||
const cliOptions = getCliOptions<OptionsType>(OPTIONS);
|
||||
go(cliOptions).catch(error => {
|
||||
console.error('Something went wrong!', Errors.toLogFormat(error));
|
||||
});
|
||||
|
||||
async function go(options: OptionsType) {
|
||||
const { key: publicKeyPath, private: privateKeyPath } = options;
|
||||
const { publicKey, privateKey } = keyPair();
|
||||
|
||||
await Promise.all([
|
||||
writeHexToPath(publicKeyPath, publicKey),
|
||||
writeHexToPath(privateKeyPath, privateKey),
|
||||
]);
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
// Copyright 2019 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
/* eslint-disable no-console */
|
||||
import { join, resolve } from 'node:path';
|
||||
import { readdir as readdirCallback } from 'node:fs';
|
||||
|
||||
import pify from 'pify';
|
||||
|
||||
import * as Errors from '../types/errors.std.js';
|
||||
import { getCliOptions } from './common.main.js';
|
||||
import { writeSignature } from './signature.node.js';
|
||||
import { version as packageVersion } from '../util/packageJson.node.js';
|
||||
|
||||
const readdir = pify(readdirCallback);
|
||||
|
||||
const OPTIONS = [
|
||||
{
|
||||
names: ['help', 'h'],
|
||||
type: 'bool',
|
||||
help: 'Print this help and exit.',
|
||||
},
|
||||
{
|
||||
names: ['private', 'p'],
|
||||
type: 'string',
|
||||
help: 'Path to private key file (default: ./private.key)',
|
||||
default: 'private.key',
|
||||
},
|
||||
{
|
||||
names: ['update', 'u'],
|
||||
type: 'string',
|
||||
help: 'Path to the update package (default: the .exe or .zip in ./release)',
|
||||
},
|
||||
{
|
||||
names: ['version', 'v'],
|
||||
type: 'string',
|
||||
help: `Version number of this package (default: ${packageVersion})`,
|
||||
default: packageVersion,
|
||||
},
|
||||
];
|
||||
|
||||
type OptionsType = {
|
||||
private: string;
|
||||
update: string;
|
||||
version: string;
|
||||
};
|
||||
|
||||
const cliOptions = getCliOptions<OptionsType>(OPTIONS);
|
||||
go(cliOptions).catch(error => {
|
||||
console.error('Something went wrong!', Errors.toLogFormat(error));
|
||||
});
|
||||
|
||||
async function go(options: OptionsType) {
|
||||
const { private: privateKeyPath, version } = options;
|
||||
|
||||
let updatePaths: Array<string>;
|
||||
if (options.update) {
|
||||
updatePaths = [options.update];
|
||||
} else {
|
||||
updatePaths = await findUpdatePaths();
|
||||
}
|
||||
|
||||
await Promise.all(
|
||||
updatePaths.map(async updatePath => {
|
||||
console.log('Signing with...');
|
||||
console.log(` version: ${version}`);
|
||||
console.log(` update file: ${updatePath}`);
|
||||
console.log(` private key file: ${privateKeyPath}`);
|
||||
|
||||
await writeSignature(updatePath, version, privateKeyPath);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
const IS_EXE = /\.exe$/;
|
||||
const IS_ZIP = /\.zip$/;
|
||||
async function findUpdatePaths(): Promise<Array<string>> {
|
||||
const releaseDir = resolve('release');
|
||||
const files: Array<string> = await readdir(releaseDir);
|
||||
|
||||
const results = new Array<string>();
|
||||
for (const file of files) {
|
||||
const fullPath = join(releaseDir, file);
|
||||
|
||||
if (IS_EXE.test(file) || IS_ZIP.test(file)) {
|
||||
results.push(fullPath);
|
||||
}
|
||||
}
|
||||
|
||||
if (results.length === 0) {
|
||||
throw new Error("No suitable file found in 'release' folder!");
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import type { StrictOptions as GotOptions } from 'got';
|
||||
import config from 'config';
|
||||
import { Agent as HTTPAgent } from 'node:http';
|
||||
|
||||
import { version } from '../util/packageJson.node.js';
|
||||
import { packageJson } from '../util/packageJson.main.js';
|
||||
import { getUserAgent } from '../util/getUserAgent.node.js';
|
||||
import * as durations from '../util/durations/index.std.js';
|
||||
import { createHTTPSAgent } from '../util/createHTTPSAgent.node.js';
|
||||
@@ -46,7 +46,7 @@ export async function getGotOptions(): Promise<GotOptions> {
|
||||
},
|
||||
headers: {
|
||||
'Cache-Control': 'no-cache',
|
||||
'User-Agent': getUserAgent(version),
|
||||
'User-Agent': getUserAgent(packageJson.version),
|
||||
},
|
||||
timeout: {
|
||||
connect: GOT_CONNECT_TIMEOUT,
|
||||
@@ -14,6 +14,7 @@ import { DialogType } from '../types/Dialogs.std.js';
|
||||
import * as Errors from '../types/errors.std.js';
|
||||
import type { UpdaterOptionsType } from './common.main.js';
|
||||
import { appRelaunch } from '../util/relaunch.main.js';
|
||||
import { getAppRootDir } from '../util/appRootDir.main.js';
|
||||
|
||||
const MIN_UBUNTU_VERSION = '22.04';
|
||||
|
||||
@@ -69,7 +70,7 @@ export function initLinux({ logger, getMainWindow }: UpdaterOptionsType): void {
|
||||
// See our patch for app-builder-lib.
|
||||
//
|
||||
// /opt/Signal/resources/app.asar
|
||||
const asarPath = join(__dirname, '..', '..');
|
||||
const asarPath = getAppRootDir();
|
||||
if (!asarPath.endsWith('.asar')) {
|
||||
throw new Error('updater/linux: not running from ASAR');
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import { readdir as readdirCallback, unlink as unlinkCallback } from 'node:fs';
|
||||
import { app } from 'electron';
|
||||
import pify from 'pify';
|
||||
|
||||
import { getAppRootDir } from '../util/appRootDir.main.js';
|
||||
import { Updater } from './common.main.js';
|
||||
|
||||
const readdir = pify(readdirCallback);
|
||||
@@ -112,7 +113,7 @@ export class WindowsUpdater extends Updater {
|
||||
// Helpers
|
||||
|
||||
function getElevatePath() {
|
||||
const installPath = app.getAppPath();
|
||||
const installPath = getAppRootDir();
|
||||
|
||||
return join(installPath, 'resources', 'elevate.exe');
|
||||
}
|
||||
|
||||
14
ts/util/appRootDir.main.ts
Normal file
14
ts/util/appRootDir.main.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright 2026 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { app } from 'electron';
|
||||
import { join } from 'node:path';
|
||||
|
||||
export function getAppRootDir(): string {
|
||||
// We have this logic because test-node runs under `electron-mocha` that has
|
||||
// `app.getAppPath()` pointing within `electron-mocha`'s folder.
|
||||
if (app.isPackaged || process.env.IS_BUNDLED) {
|
||||
return app.getAppPath();
|
||||
}
|
||||
return join(__dirname, '..', '..');
|
||||
}
|
||||
@@ -5,13 +5,7 @@ import { nativeImage } from 'electron';
|
||||
import type { NativeImage } from 'electron';
|
||||
import { join } from 'node:path';
|
||||
|
||||
export function getAppErrorIcon(): NativeImage {
|
||||
const iconPath = join(
|
||||
__dirname,
|
||||
'..',
|
||||
'..',
|
||||
'images',
|
||||
'app-icon-with-error.png'
|
||||
);
|
||||
export function getAppErrorIcon(rootDir: string): NativeImage {
|
||||
const iconPath = join(rootDir, 'images', 'app-icon-with-error.png');
|
||||
return nativeImage.createFromPath(iconPath);
|
||||
}
|
||||
|
||||
13
ts/util/packageJson.main.ts
Normal file
13
ts/util/packageJson.main.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
// Copyright 2025 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import type { PackageJsonType } from '../types/packageJson.d.ts';
|
||||
import { getAppRootDir } from './appRootDir.main.js';
|
||||
|
||||
const PACKAGE_JSON_PATH = join(getAppRootDir(), 'package.json');
|
||||
|
||||
export const packageJson: PackageJsonType = JSON.parse(
|
||||
readFileSync(PACKAGE_JSON_PATH, 'utf8')
|
||||
);
|
||||
@@ -3,32 +3,10 @@
|
||||
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import type { PackageJsonType } from '../types/packageJson.d.ts';
|
||||
|
||||
const PACKAGE_JSON_PATH = join(__dirname, '..', '..', 'package.json');
|
||||
|
||||
const json: {
|
||||
name: string;
|
||||
version: string;
|
||||
productName: string;
|
||||
build: {
|
||||
appId: string;
|
||||
mac: {
|
||||
releaseInfo: {
|
||||
vendor: {
|
||||
minOSVersion: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
deb: {
|
||||
depends: Array<string>;
|
||||
};
|
||||
files: Array<string | Record<string, unknown>>;
|
||||
};
|
||||
} = JSON.parse(readFileSync(PACKAGE_JSON_PATH, 'utf8'));
|
||||
|
||||
export default json;
|
||||
|
||||
export const { name } = json;
|
||||
export const { version } = json;
|
||||
export const { productName } = json;
|
||||
export const { build } = json;
|
||||
export const packageJson: PackageJsonType = JSON.parse(
|
||||
readFileSync(PACKAGE_JSON_PATH, 'utf8')
|
||||
);
|
||||
|
||||
@@ -11,7 +11,6 @@ import lodash from 'lodash';
|
||||
import type { ExtendedStorageID } from '../types/StorageService.d.ts';
|
||||
import type { ConversationModel } from '../models/conversations.preload.js';
|
||||
|
||||
export const APP_ROOT_PATH = path.join(__dirname, '..', '..');
|
||||
const { escapeRegExp, isString, isRegExp } = lodash;
|
||||
|
||||
const { compose } = lodashFp;
|
||||
@@ -232,8 +231,6 @@ export const addSensitivePath = (filePath: string): void => {
|
||||
redactSensitivePaths = createRedactSensitivePaths(sensitivePaths);
|
||||
};
|
||||
|
||||
addSensitivePath(APP_ROOT_PATH);
|
||||
|
||||
export const redactAll: RedactFunction = text => {
|
||||
let result = text;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2024 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { version } from './packageJson.node.js';
|
||||
import { packageJson } from './packageJson.node.js';
|
||||
import { getUserAgent } from './getUserAgent.node.js';
|
||||
|
||||
type AuthenticateOptionsType = Readonly<{
|
||||
@@ -36,6 +36,6 @@ export async function authenticate({
|
||||
|
||||
return new Headers({
|
||||
authorization: `${auth.tokenType} ${auth.accessToken}`,
|
||||
'user-agent': getUserAgent(version),
|
||||
'user-agent': getUserAgent(packageJson.version),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
import { join } from 'node:path';
|
||||
import { Worker } from 'node:worker_threads';
|
||||
import { app } from 'electron';
|
||||
import { getAppRootDir } from '../util/appRootDir.main.js';
|
||||
|
||||
export type WrappedWorkerRequest = {
|
||||
readonly uuid: string;
|
||||
@@ -21,7 +21,7 @@ export function getHeicConverter(): (
|
||||
data: Uint8Array<ArrayBuffer>
|
||||
) => Promise<WrappedWorkerResponse> {
|
||||
const scriptDir = join(
|
||||
app.getAppPath(),
|
||||
getAppRootDir(),
|
||||
'ts',
|
||||
'workers',
|
||||
'heicConverterWorker.node.js'
|
||||
|
||||
Reference in New Issue
Block a user