Bundle everything with rolldown

This commit is contained in:
Fedor Indutny 2026-03-30 11:54:59 -07:00 committed by GitHub
parent e158261fea
commit bb111a3107
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2317 changed files with 22672 additions and 63514 deletions

View File

@ -108,8 +108,6 @@ jobs:
- name: Build typescript
run: pnpm run generate
- name: Bundle
run: pnpm run build:esbuild:prod
- name: Create preload cache
run: xvfb-run --auto-servernum pnpm run build:preload-cache
@ -121,7 +119,8 @@ jobs:
- name: Run ${{ matrix.metric }}
run: |
set -o pipefail
xvfb-run --auto-servernum node ${{ matrix.script }} | tee benchmark.log
xvfb-run --auto-servernum ./node_modules/.bin/tsx \
${{ matrix.script }} | tee benchmark.log
timeout-minutes: 10
env:
NODE_ENV: production

View File

@ -114,9 +114,8 @@ jobs:
# CXX: sccache clang++
# SCCACHE_GHA_ENABLED: "true"
NPM_CONFIG_LOGLEVEL: verbose
- run: pnpm run generate
- run: pnpm run prepare-beta-build
- run: pnpm run generate
- run: pnpm run test-node
- run: pnpm run test-electron
env:
@ -135,9 +134,9 @@ jobs:
- name: Upload installer size
if: ${{ github.repository == 'signalapp/Signal-Desktop-Private' && github.ref == 'refs/heads/main' }}
run: |
node ts/scripts/publish-installer-size.node.js macos-arm64
node ts/scripts/publish-installer-size.node.js macos-x64
node ts/scripts/publish-installer-size.node.js macos-universal
./node_modules/.bin/tsx ts/scripts/publish-installer-size.node.ts macos-arm64
./node_modules/.bin/tsx ts/scripts/publish-installer-size.node.ts macos-x64
./node_modules/.bin/tsx ts/scripts/publish-installer-size.node.ts macos-universal
- run: pnpm run test-release
env:
NODE_ENV: production
@ -190,11 +189,9 @@ jobs:
# SCCACHE_GHA_ENABLED: "true"
NPM_CONFIG_LOGLEVEL: verbose
- run: pnpm run generate
- run: pnpm run prepare-beta-build
- run: pnpm run generate
- name: Create bundle
run: pnpm run build:esbuild:prod
- name: Create preload cache
run: xvfb-run --auto-servernum pnpm run build:preload-cache
env:
@ -219,7 +216,7 @@ jobs:
- name: Upload installer size
if: ${{ github.repository == 'signalapp/Signal-Desktop-Private' && github.ref == 'refs/heads/main' }}
run: node ts/scripts/publish-installer-size.node.js linux
run: ./node_modules/.bin/tsx ts/scripts/publish-installer-size.node.ts linux
- run: xvfb-run --auto-servernum pnpm run test-node
@ -272,15 +269,13 @@ jobs:
env:
NPM_CONFIG_LOGLEVEL: verbose
- run: pnpm run generate
- run: pnpm run test-node
- run: copy package.json temp.json
- run: del package.json
- run: type temp.json | findstr /v certificateSubjectName | findstr /v certificateSha1 > package.json
- run: pnpm run prepare-beta-build
- run: pnpm run generate
- run: pnpm run test-node
- name: Create bundle
run: pnpm run build:esbuild:prod
- name: Create preload cache
run: pnpm run build:preload-cache
env:
@ -299,7 +294,7 @@ jobs:
- name: Upload installer size
if: ${{ github.repository == 'signalapp/Signal-Desktop-Private' && github.ref == 'refs/heads/main' }}
run: node ts/scripts/publish-installer-size.node.js windows
run: ./node_modules/.bin/tsx ts/scripts/publish-installer-size.node.ts windows
- run: pnpm run test-electron
env:
@ -414,8 +409,6 @@ jobs:
- name: Build typescript
run: pnpm run generate
- name: Bundle
run: pnpm run build:esbuild:prod
- name: Create preload cache
run: xvfb-run --auto-servernum pnpm run build:preload-cache
env:
@ -490,4 +483,4 @@ jobs:
- run: pnpm generate:phase-0
- name: Run OS version check
run: |
node ts/scripts/check-min-os-version.node.js
./node_modules/.bin/tsx ts/scripts/check-min-os-version.node.ts

View File

@ -50,8 +50,8 @@ jobs:
- run: ./node_modules/.bin/run-p --race test:storybook:serve test:storybook:test
env:
ARTIFACTS_DIR: stories
- run: pnpm run build:esbuild
- run: node ts/scripts/compile-stories-icu-lookup.node.js stories
- run: pnpm run build:rolldown
- run: ./node_modules/.bin/tsx ts/scripts/compile-stories-icu-lookup.node.ts stories
- name: Upload test artifacts
if: github.event_name == 'workflow_dispatch'

1
.gitignore vendored
View File

@ -38,6 +38,7 @@ build/ICUMessageParams.d.ts
build/**/*.js
app/*.js
ts/**/*.js
!ts/windows/main/tsx.js
ts/protobuf/*.d.ts
# CSS Modules

View File

@ -1,3 +1,4 @@
{
"checkLeaks": true
"checkLeaks": true,
"node-option": ["import=tsx"]
}

View File

@ -115,7 +115,6 @@ const NODE_PACKAGES = new Set([
'endanger',
'enhanced-resolve',
'enquirer',
'esbuild',
'execa',
'html-webpack-plugin',
'http-server',
@ -136,6 +135,7 @@ const NODE_PACKAGES = new Set([
'react-devtools',
'react-devtools-core',
'resolve-url-loader',
'rolldown',
'sass',
'sass-loader',
'style-loader',
@ -147,6 +147,7 @@ const NODE_PACKAGES = new Set([
'synckit',
'tailwindcss',
'terser-webpack-plugin',
'tsx',
'ts-node',
'typescript',
'wait-on',
@ -353,11 +354,11 @@ export const enforceFileSuffix = ESLintUtils.RuleCreator.withoutDocs({
* @param {string} source
*/
function trackLocalDep(node, source) {
if (!source.endsWith('.js')) {
if (!/\.tsx?/.test(source)) {
return;
}
const match = source.match(/\.([^.\/]+)(?:\.stories)?\.js$/);
const match = source.match(/\.([^.\/]+)(?:\.stories)?\.tsx?$/);
if (match == null) {
context.report({
node,

View File

@ -51,7 +51,7 @@ ruleTester.run('file-suffix', enforceFileSuffix, {
name: `importing ${depSuffix} from ${fileSuffix}`,
filename: `a.${fileSuffix}.ts`,
code: `
import { x } from './b.${depSuffix}.js';
import { x } from './b.${depSuffix}.ts';
${requiredLine}
`,
languageOptions: {
@ -66,7 +66,7 @@ ruleTester.run('file-suffix', enforceFileSuffix, {
{
name: 'type import should have no effect',
filename: 'a.std.ts',
code: `import type { ReadonlyDeep } from './b.dom.js'`,
code: `import type { ReadonlyDeep } from './b.dom.ts'`,
},
],
invalid: [
@ -76,7 +76,7 @@ ruleTester.run('file-suffix', enforceFileSuffix, {
return {
name: `importing ${depSuffix} from ${fileSuffix}`,
filename: `a.${fileSuffix}.ts`,
code: `import { x } from './b.${depSuffix}.js'`,
code: `import { x } from './b.${depSuffix}.ts'`,
errors: [
{
messageId: 'wrongFileSuffix',
@ -108,7 +108,7 @@ ruleTester.run('file-suffix', enforceFileSuffix, {
filename: 'a.main.ts',
code: `
import { autoUpdater } from 'electron';
import './b.preload.js';
import './b.preload.ts';
`,
errors: [
{
@ -122,7 +122,7 @@ ruleTester.run('file-suffix', enforceFileSuffix, {
filename: 'a.preload.ts',
code: `
import { ipcRenderer } from 'electron';
import './b.main.js';
import './b.main.ts';
`,
errors: [
{

View File

@ -1650,7 +1650,8 @@
"dangerfile.js",
"eslint-local-rules.js",
"test/setup-test-node.js",
"preload.wrapper.ts"
"preload.wrapper.ts",
"rolldown.config.ts"
],
"env": { "node": true }
},
@ -1695,7 +1696,8 @@
".*rc.js",
"ci.js",
"dangerfile.js",
"preload.wrapper.ts"
"preload.wrapper.ts",
"rolldown.config.ts"
],
"rules": {
"signal-desktop/enforce-file-suffix": "off"
@ -1723,7 +1725,8 @@
"ts/util/lint/**",
"ts/windows/main/*_test.*",
"dangerfile.js",
"preload.wrapper.ts"
"preload.wrapper.ts",
"rolldown.config.ts"
],
"rules": {
"eslint/no-restricted-globals": [

View File

@ -2,6 +2,6 @@
// SPDX-License-Identifier: AGPL-3.0-only
import type { Context } from 'react';
import type { ThemeType } from '../ts/types/Util.std.js';
import type { ThemeType } from '../ts/types/Util.std.ts';
export const StorybookThemeContext: Context<ThemeType>;

View File

@ -5,6 +5,7 @@ import '../ts/window.d.ts';
import React, { StrictMode } from 'react';
import '@signalapp/quill-cjs/dist/quill.core.css';
import '../stylesheets/manifest.scss';
import '../stylesheets/tailwind-config.css';
import * as styles from './styles.scss';
@ -16,26 +17,26 @@ import { combineReducers, createStore } from 'redux';
import { Globals } from '@react-spring/web';
import { StorybookThemeContext } from './StorybookThemeContext.std.js';
import { SystemThemeType, ThemeType } from '../ts/types/Util.std.js';
import { setupI18n } from '../ts/util/setupI18n.dom.js';
import { HourCyclePreference } from '../ts/types/I18N.std.js';
import { AxoProvider } from '../ts/axo/AxoProvider.dom.js';
import type { StateType } from '../ts/state/reducer.preload.js';
import { SystemThemeType, ThemeType } from '../ts/types/Util.std.ts';
import { setupI18n } from '../ts/util/setupI18n.dom.tsx';
import { HourCyclePreference } from '../ts/types/I18N.std.ts';
import { AxoProvider } from '../ts/axo/AxoProvider.dom.tsx';
import type { StateType } from '../ts/state/reducer.preload.ts';
import {
ScrollerLockContext,
createScrollerLock,
} from '../ts/hooks/useScrollLock.dom.js';
import { Environment, setEnvironment } from '../ts/environment.std.js';
import { parseUnknown } from '../ts/util/schemas.std.js';
import { LocaleEmojiListSchema } from '../ts/types/emoji.std.js';
import { FunProvider } from '../ts/components/fun/FunProvider.dom.js';
import { EmojiSkinTone } from '../ts/components/fun/data/emojis.std.js';
import { MOCK_GIFS_PAGINATED_ONE_PAGE } from '../ts/components/fun/mocks.dom.js';
import { NavTab } from '../ts/types/Nav.std.js';
} from '../ts/hooks/useScrollLock.dom.tsx';
import { Environment, setEnvironment } from '../ts/environment.std.ts';
import { parseUnknown } from '../ts/util/schemas.std.ts';
import { LocaleEmojiListSchema } from '../ts/types/emoji.std.ts';
import { FunProvider } from '../ts/components/fun/FunProvider.dom.tsx';
import { EmojiSkinTone } from '../ts/components/fun/data/emojis.std.ts';
import { MOCK_GIFS_PAGINATED_ONE_PAGE } from '../ts/components/fun/mocks.dom.tsx';
import { NavTab } from '../ts/types/Nav.std.ts';
import type { FunEmojiSelection } from '../ts/components/fun/panels/FunPanelEmojis.dom.js';
import type { FunGifSelection } from '../ts/components/fun/panels/FunPanelGifs.dom.js';
import type { FunStickerSelection } from '../ts/components/fun/panels/FunPanelStickers.dom.js';
import type { FunEmojiSelection } from '../ts/components/fun/panels/FunPanelEmojis.dom.tsx';
import type { FunGifSelection } from '../ts/components/fun/panels/FunPanelGifs.dom.tsx';
import type { FunStickerSelection } from '../ts/components/fun/panels/FunPanelStickers.dom.tsx';
setEnvironment(Environment.Development, true);

File diff suppressed because it is too large Load Diff

View File

@ -20,6 +20,6 @@
</head>
<body>
<div id="app"></div>
<script type="module" src="bundles/about/app.dom.js"></script>
<script type="module" src="bundles/dom/about.js"></script>
</body>
</html>

View File

@ -7,11 +7,11 @@ import * as z from 'zod';
import { protocol } from 'electron';
import { LRUCache } from 'lru-cache';
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';
import type { OptionalResourceService } from './OptionalResourceService.main.ts';
import { SignalService as Proto } from '../ts/protobuf/index.std.ts';
import { parseUnknown } from '../ts/util/schemas.std.ts';
import { utf16ToEmoji } from '../ts/util/utf16ToEmoji.node.ts';
import { getAppRootDir } from '../ts/util/appRootDir.main.ts';
const MANIFEST_PATH = join(getAppRootDir(), 'build', 'jumbomoji.json');

View File

@ -12,13 +12,13 @@ import PQueue from 'p-queue';
import type {
OptionalResourceType,
OptionalResourcesDictType,
} 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.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';
} from '../ts/types/OptionalResource.std.ts';
import { OptionalResourcesDictSchema } from '../ts/types/OptionalResource.std.ts';
import { createLogger } from '../ts/logging/log.std.ts';
import { getGotOptions } from '../ts/updater/got.main.ts';
import { drop } from '../ts/util/drop.std.ts';
import { parseUnknown } from '../ts/util/schemas.std.ts';
import { getAppRootDir } from '../ts/util/appRootDir.main.ts';
const log = createLogger('OptionalResourceService');

View File

@ -2,7 +2,7 @@
// SPDX-License-Identifier: AGPL-3.0-only
import type { PowerSaveBlocker } from 'electron';
import { createLogger } from '../ts/logging/log.std.js';
import { createLogger } from '../ts/logging/log.std.ts';
const log = createLogger('PreventDisplaySleepService');

View File

@ -6,9 +6,9 @@ import { Menu, Tray, app, nativeImage, nativeTheme, screen } from 'electron';
import os from 'node:os';
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';
import { createLogger } from '../ts/logging/log.std.ts';
import type { LocalizerType } from '../ts/types/I18N.std.ts';
import { getAppRootDir } from '../ts/util/appRootDir.main.ts';
const log = createLogger('SystemTrayService');

View File

@ -1,14 +1,14 @@
// Copyright 2017 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { createLogger } from '../ts/logging/log.std.js';
import OS from '../ts/util/os/osMain.node.js';
import { createLogger } from '../ts/logging/log.std.ts';
import OS from '../ts/util/os/osMain.node.ts';
import {
parseSystemTraySetting,
SystemTraySetting,
} from '../ts/types/SystemTraySetting.std.js';
import { isSystemTraySupported } from '../ts/types/Settings.std.js';
import type { ConfigType } from './base_config.node.js';
} from '../ts/types/SystemTraySetting.std.ts';
import { isSystemTraySupported } from '../ts/types/Settings.std.ts';
import type { ConfigType } from './base_config.node.ts';
const log = createLogger('SystemTraySettingCache');

View File

@ -3,77 +3,53 @@
import { ipcMain as ipc } from 'electron';
import type { IpcMainInvokeEvent } from 'electron';
import { join } from 'node:path';
import { Worker } from 'node:worker_threads';
import { AUMID } from './startup_config.main.js';
import type {
WindowsNotificationWorkerDataType,
WindowsNotificationRequestType,
WindowsNotificationData,
} from '../ts/types/notifications.std.js';
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';
import {
Notifier,
sendDummyKeystroke,
} from '@indutny/simple-windows-notifications';
import { createLogger } from '../ts/logging/log.std.ts';
import { AUMID } from './startup_config.main.ts';
import type { WindowsNotificationData } from '../ts/services/notifications.preload.ts';
import OS from '../ts/util/os/osMain.node.ts';
import { renderWindowsToast } from './renderWindowsToast.std.tsx';
export { sendDummyKeystroke };
const log = createLogger('WindowsNotifications');
let worker: Worker | undefined;
if (OS.isWindows()) {
const scriptPath = join(
getAppRootDir(),
'app',
'WindowsNotificationsWorker.node.js'
const notifier = new Notifier(AUMID);
const NOTIFICATION_ID = {
group: 'group',
tag: 'tag',
};
ipc.handle(
'windows-notifications:show',
(_event: IpcMainInvokeEvent, data: WindowsNotificationData) => {
try {
// First, clear all previous notifications - we want just one
// notification at a time
notifier.remove(NOTIFICATION_ID);
notifier.show(renderWindowsToast(data), NOTIFICATION_ID);
} catch (error) {
log.error(
`Windows Notifications: Failed to show notification: ${error.stack}`
);
}
}
);
worker = new Worker(scriptPath, {
workerData: {
AUMID,
} satisfies WindowsNotificationWorkerDataType,
ipc.handle('windows-notifications:clear-all', () => {
try {
notifier.remove(NOTIFICATION_ID);
} catch (error) {
log.error(
`Windows Notifications: Failed to clear notifications: ${error.stack}`
);
}
});
}
export function sendDummyKeystroke(): void {
if (worker == null) {
log.warn('sendDummyKeystroke without worker');
return;
}
worker.postMessage({
command: 'sendDummyKeystroke',
} satisfies WindowsNotificationRequestType);
}
export function show(notificationData: WindowsNotificationData): void {
if (worker == null) {
log.warn('show without worker');
return;
}
worker.postMessage({
command: 'show',
notificationData,
} satisfies WindowsNotificationRequestType);
}
ipc.handle(
'windows-notifications:show',
(_event: IpcMainInvokeEvent, data: unknown) => {
try {
const notificationData = WindowsNotificationDataSchema.parse(data);
show(notificationData);
} catch (error) {
log.error('failed to parse notification data', error.stack);
}
}
);
ipc.handle('windows-notifications:clear-all', () => {
if (worker == null) {
log.warn('clear all without worker');
return;
}
worker.postMessage({
command: 'clearAll',
} satisfies WindowsNotificationRequestType);
});

View File

@ -1,83 +0,0 @@
// Copyright 2025 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { parentPort, workerData } from 'node:worker_threads';
import {
Notifier,
sendDummyKeystroke,
} from '@indutny/simple-windows-notifications';
import { createLogger } from '../ts/logging/log.std.js';
import {
WindowsNotificationWorkerDataSchema,
WindowsNotificationRequestSchema,
} from '../ts/types/notifications.std.js';
import OS from '../ts/util/os/osMain.node.js';
import { missingCaseError } from '../ts/util/missingCaseError.std.js';
import { renderWindowsToast } from './renderWindowsToast.std.js';
if (!parentPort) {
throw new Error('Must run as a worker thread');
}
if (!OS.isWindows()) {
throw new Error('Runs only on Windows');
}
const port = parentPort;
const log = createLogger('WindowsNotificationsWorker');
const { AUMID } = WindowsNotificationWorkerDataSchema.parse(workerData);
const notifier = new Notifier(AUMID);
const NOTIFICATION_ID = {
group: 'group',
tag: 'tag',
};
port.on('message', (message: unknown) => {
const request = WindowsNotificationRequestSchema.parse(message);
if (request.command === 'show') {
try {
// First, clear all previous notifications - we want just one
// notification at a time
notifier.remove(NOTIFICATION_ID);
notifier.show(
renderWindowsToast(request.notificationData),
NOTIFICATION_ID
);
} catch (error) {
log.error(
`Windows Notifications: Failed to show notification: ${error.stack}`
);
}
return;
}
if (request.command === 'clearAll') {
try {
notifier.remove(NOTIFICATION_ID);
} catch (error) {
log.error(
`Windows Notifications: Failed to clear notifications: ${error.stack}`
);
}
return;
}
if (request.command === 'sendDummyKeystroke') {
try {
sendDummyKeystroke();
} catch (error) {
log.error(
`Windows Notifications: Failed to send dummy keystroke: ${error.stack}`
);
}
return;
}
throw missingCaseError(request);
});

View File

@ -26,30 +26,30 @@ import {
type DecryptAttachmentToSinkOptionsType,
decryptAttachmentV2ToSink,
type IntegrityCheckType,
} from '../ts/AttachmentCrypto.node.js';
import * as Bytes from '../ts/Bytes.std.js';
import type { MessageAttachmentsCursorType } from '../ts/sql/Interface.std.js';
import type { MainSQL } from '../ts/sql/main.main.js';
} from '../ts/AttachmentCrypto.node.ts';
import * as Bytes from '../ts/Bytes.std.ts';
import type { MessageAttachmentsCursorType } from '../ts/sql/Interface.std.ts';
import type { MainSQL } from '../ts/sql/main.main.ts';
import {
APPLICATION_OCTET_STREAM,
MIMETypeToString,
stringToMIMEType,
} from '../ts/types/MIME.std.js';
import * as Errors from '../ts/types/errors.std.js';
} from '../ts/types/MIME.std.ts';
import * as Errors from '../ts/types/errors.std.ts';
import {
isImageTypeSupported,
isVideoTypeSupported,
} from '../ts/util/GoogleChrome.std.js';
import { strictAssert } from '../ts/util/assert.std.js';
import { drop } from '../ts/util/drop.std.js';
import { SECOND } from '../ts/util/durations/index.std.js';
import { isPathInside } from '../ts/util/isPathInside.node.js';
import { missingCaseError } from '../ts/util/missingCaseError.std.js';
import { safeParseInteger } from '../ts/util/numbers.std.js';
import { parseLoose } from '../ts/util/schemas.std.js';
import { sleep } from '../ts/util/sleep.std.js';
import { toWebStream } from '../ts/util/toWebStream.node.js';
import { createLogger } from '../ts/logging/log.std.js';
} from '../ts/util/GoogleChrome.std.ts';
import { strictAssert } from '../ts/util/assert.std.ts';
import { drop } from '../ts/util/drop.std.ts';
import { SECOND } from '../ts/util/durations/index.std.ts';
import { isPathInside } from '../ts/util/isPathInside.node.ts';
import { missingCaseError } from '../ts/util/missingCaseError.std.ts';
import { safeParseInteger } from '../ts/util/numbers.std.ts';
import { parseLoose } from '../ts/util/schemas.std.ts';
import { sleep } from '../ts/util/sleep.std.ts';
import { toWebStream } from '../ts/util/toWebStream.node.ts';
import { createLogger } from '../ts/logging/log.std.ts';
import {
deleteAllAttachments,
deleteAllBadges,
@ -68,8 +68,8 @@ import {
getAttachmentsPath,
getStickersPath,
getTempPath,
} from './attachments.node.js';
import { isValidDigest, isValidPlaintextHash } from '../ts/types/Crypto.std.js';
} from './attachments.node.ts';
import { isValidDigest, isValidPlaintextHash } from '../ts/types/Crypto.std.ts';
const { isNumber } = lodash;

View File

@ -9,18 +9,18 @@ import fastGlob from 'fast-glob';
import fse from 'fs-extra';
import lodash from 'lodash';
import normalizePath from 'normalize-path';
import { isPathInside } from '../ts/util/isPathInside.node.js';
import { DAY } from '../ts/util/durations/index.std.js';
import { isOlderThan } from '../ts/util/timestamp.std.js';
import { isNotNil } from '../ts/util/isNotNil.std.js';
import { isPathInside } from '../ts/util/isPathInside.node.ts';
import { DAY } from '../ts/util/durations/index.std.ts';
import { isOlderThan } from '../ts/util/timestamp.std.ts';
import { isNotNil } from '../ts/util/isNotNil.std.ts';
import {
generateKeys,
decryptAttachmentV2ToSink,
encryptAttachmentV2ToDisk,
} from '../ts/AttachmentCrypto.node.js';
import type { LocalAttachmentV2Type } from '../ts/types/Attachment.std.js';
import * as Errors from '../ts/types/errors.std.js';
import { createLogger } from '../ts/logging/log.std.js';
} from '../ts/AttachmentCrypto.node.ts';
import type { LocalAttachmentV2Type } from '../ts/types/Attachment.std.ts';
import * as Errors from '../ts/types/errors.std.ts';
import { createLogger } from '../ts/logging/log.std.ts';
const { map, isString } = lodash;

View File

@ -6,8 +6,8 @@ import { sync as writeFileSync } from 'write-file-atomic';
import lodash from 'lodash';
import lodashFp from 'lodash/fp.js';
import { strictAssert } from '../ts/util/assert.std.js';
import { createLogger } from '../ts/logging/log.std.js';
import { strictAssert } from '../ts/util/assert.std.ts';
import { createLogger } from '../ts/logging/log.std.ts';
const { set } = lodashFp;

View File

@ -11,9 +11,9 @@ import {
getEnvironment,
setEnvironment,
parseEnvironment,
} from '../ts/environment.std.js';
import { createLogger } from '../ts/logging/log.std.js';
import { getAppRootDir } from '../ts/util/appRootDir.main.js';
} from '../ts/environment.std.ts';
import { createLogger } from '../ts/logging/log.std.ts';
import { getAppRootDir } from '../ts/util/appRootDir.main.ts';
const log = createLogger('config');

View File

@ -7,12 +7,12 @@ import { basename, join } from 'node:path';
import { toJSONString as dumpToJSONString } from '@signalapp/libsignal-client/dist/Minidump.js';
import z from 'zod';
import type { LoggerType } from '../ts/types/Logging.std.js';
import * as Errors from '../ts/types/errors.std.js';
import { isProduction } from '../ts/util/version.std.js';
import { isNotNil } from '../ts/util/isNotNil.std.js';
import OS from '../ts/util/os/osMain.node.js';
import { parseUnknown } from '../ts/util/schemas.std.js';
import type { LoggerType } from '../ts/types/Logging.std.ts';
import * as Errors from '../ts/types/errors.std.ts';
import { isProduction } from '../ts/util/version.std.ts';
import { isNotNil } from '../ts/util/isNotNil.std.ts';
import OS from '../ts/util/os/osMain.node.ts';
import { parseUnknown } from '../ts/util/schemas.std.ts';
const { realpath, readdir, readFile, unlink, stat } = fsExtra;

View File

@ -3,11 +3,11 @@
import { join } from 'node:path';
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';
import { DNSFallbackSchema } from '../ts/types/DNSFallback.std.ts';
import type { DNSFallbackType } from '../ts/types/DNSFallback.std.ts';
import { parseUnknown } from '../ts/util/schemas.std.ts';
import { getAppRootDir } from '../ts/util/appRootDir.main.ts';
import { createLogger } from '../ts/logging/log.std.ts';
const log = createLogger('dns-fallback');

View File

@ -5,7 +5,7 @@ import { join } from 'node:path';
import { app } from 'electron';
import { start } from './base_config.node.js';
import { start } from './base_config.node.ts';
const userDataPath = app.getPath('userData');
const targetPath = join(userDataPath, 'ephemeral.json');

View File

@ -4,11 +4,11 @@
import { app, dialog, clipboard } from 'electron';
import os from 'node:os';
import * as Errors from '../ts/types/errors.std.js';
import { redactAll } from '../ts/util/privacy.node.js';
import { createLogger } from '../ts/logging/log.std.js';
import { reallyJsonStringify } from '../ts/util/reallyJsonStringify.std.js';
import type { LocaleType } from './locale.node.js';
import * as Errors from '../ts/types/errors.std.ts';
import { redactAll } from '../ts/util/privacy.node.ts';
import { createLogger } from '../ts/logging/log.std.ts';
import { reallyJsonStringify } from '../ts/util/reallyJsonStringify.std.ts';
import type { LocaleType } from './locale.node.ts';
const log = createLogger('global_errors');

View File

@ -5,15 +5,15 @@ import { join } from 'node:path';
import { readFileSync } from 'node:fs';
import lodash from 'lodash';
import * as LocaleMatcher from '@formatjs/intl-localematcher';
import { setupI18n } from '../ts/util/setupI18nMain.std.js';
import { shouldNeverBeCalled } from '../ts/util/shouldNeverBeCalled.std.js';
import { setupI18n } from '../ts/util/setupI18nMain.std.ts';
import { shouldNeverBeCalled } from '../ts/util/shouldNeverBeCalled.std.ts';
import type { LoggerType } from '../ts/types/Logging.std.js';
import type { LoggerType } from '../ts/types/Logging.std.ts';
import type {
HourCyclePreference,
LocaleMessagesType,
} from '../ts/types/I18N.std.js';
import type { LocalizerType } from '../ts/types/Util.std.js';
} from '../ts/types/I18N.std.ts';
import type { LocalizerType } from '../ts/types/Util.std.ts';
const { merge } = lodash;

View File

@ -32,113 +32,109 @@ import {
import type { MenuItemConstructorOptions, Settings } from 'electron';
import { z } from 'zod';
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.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';
import { drop } from '../ts/util/drop.std.js';
import type { ThemeSettingType } from '../ts/util/theme.std.js';
import { ThemeType } from '../ts/types/Util.std.js';
import { NotificationType } from '../ts/types/notifications.std.js';
import * as Errors from '../ts/types/errors.std.js';
import { resolveCanonicalLocales } from '../ts/util/resolveCanonicalLocales.std.js';
import { createLogger } from '../ts/logging/log.std.js';
import * as debugLog from '../ts/logging/debuglogs.node.js';
import * as uploadDebugLog from '../ts/logging/uploadDebugLog.node.js';
import { explodePromise } from '../ts/util/explodePromise.std.js';
import { packageJson } from '../ts/util/packageJson.main.ts';
import * as GlobalErrors from './global_errors.main.ts';
import { setup as setupCrashReports } from './crashReports.main.ts';
import { setup as setupSpellChecker } from './spell_check.main.ts';
import { getDNSFallback } from './dns-fallback.main.ts';
import { redactAll, addSensitivePath } from './privacy.main.ts';
import { createSupportUrl } from '../ts/util/createSupportUrl.std.ts';
import { missingCaseError } from '../ts/util/missingCaseError.std.ts';
import { strictAssert } from '../ts/util/assert.std.ts';
import { drop } from '../ts/util/drop.std.ts';
import type { ThemeSettingType } from '../ts/util/theme.std.ts';
import { ThemeType } from '../ts/types/Util.std.ts';
import * as Errors from '../ts/types/errors.std.ts';
import { resolveCanonicalLocales } from '../ts/util/resolveCanonicalLocales.std.ts';
import { createLogger } from '../ts/logging/log.std.ts';
import * as debugLog from '../ts/logging/debuglogs.node.ts';
import * as uploadDebugLog from '../ts/logging/uploadDebugLog.node.ts';
import { explodePromise } from '../ts/util/explodePromise.std.ts';
import './startup_config.main.js';
import './startup_config.main.ts';
import type { RendererConfigType } from '../ts/types/RendererConfig.std.js';
import type { RendererConfigType } from '../ts/types/RendererConfig.std.ts';
import {
directoryConfigSchema,
rendererConfigSchema,
} from '../ts/types/RendererConfig.std.js';
import config from './config.main.js';
} from '../ts/types/RendererConfig.std.ts';
import config from './config.main.ts';
import {
Environment,
getEnvironment,
isTestEnvironment,
} from '../ts/environment.std.js';
} from '../ts/environment.std.ts';
// Very important to put before the single instance check, since it is based on the
// userData directory. (see requestSingleInstanceLock below)
import * as userConfig from './user_config.main.js';
import * as userConfig from './user_config.main.ts';
// We generally want to pull in our own modules after this point, after the user
// data directory has been set.
import * as attachments from './attachments.node.js';
import * as attachmentChannel from './attachment_channel.main.js';
import * as bounce from '../ts/services/bounce.main.js';
import * as updater from '../ts/updater/index.main.js';
import { updateDefaultSession } from './updateDefaultSession.main.js';
import { PreventDisplaySleepService } from './PreventDisplaySleepService.std.js';
import * as attachments from './attachments.node.ts';
import * as attachmentChannel from './attachment_channel.main.ts';
import * as bounce from '../ts/services/bounce.main.ts';
import * as updater from '../ts/updater/index.main.ts';
import { updateDefaultSession } from './updateDefaultSession.main.ts';
import { PreventDisplaySleepService } from './PreventDisplaySleepService.std.ts';
import {
SystemTrayService,
focusAndForceToTop,
} from './SystemTrayService.main.js';
import { SystemTraySettingCache } from './SystemTraySettingCache.node.js';
import { OptionalResourceService } from './OptionalResourceService.main.js';
import { EmojiService } from './EmojiService.main.js';
} from './SystemTrayService.main.ts';
import { SystemTraySettingCache } from './SystemTraySettingCache.node.ts';
import { OptionalResourceService } from './OptionalResourceService.main.ts';
import { EmojiService } from './EmojiService.main.ts';
import {
SystemTraySetting,
shouldMinimizeToSystemTray,
parseSystemTraySetting,
} from '../ts/types/SystemTraySetting.std.js';
} from '../ts/types/SystemTraySetting.std.ts';
import {
getDefaultSystemTraySetting,
isSystemTraySupported,
isContentProtectionEnabledByDefault,
} from '../ts/types/Settings.std.js';
import * as ephemeralConfig from './ephemeral_config.main.js';
import * as mainProcessLogging from '../ts/logging/main_process_logging.main.js';
import { MainSQL } from '../ts/sql/main.main.js';
import * as sqlChannels from './sql_channel.main.js';
import * as windowState from './window_state.std.js';
import type { CreateTemplateOptionsType } from './menu.std.js';
import { createTemplate } from './menu.std.js';
} from '../ts/types/Settings.std.ts';
import * as ephemeralConfig from './ephemeral_config.main.ts';
import * as mainProcessLogging from '../ts/logging/main_process_logging.main.ts';
import { MainSQL } from '../ts/sql/main.main.ts';
import * as sqlChannels from './sql_channel.main.ts';
import * as windowState from './window_state.std.ts';
import type { CreateTemplateOptionsType } from './menu.std.ts';
import { createTemplate } from './menu.std.ts';
import {
installFileHandler,
installWebHandler,
} from './protocol_filter.node.js';
import OS from '../ts/util/os/osMain.node.js';
import { isNightly, isProduction } from '../ts/util/version.std.js';
import { clearTimeoutIfNecessary } from '../ts/util/clearTimeoutIfNecessary.std.js';
import { toggleMaximizedBrowserWindow } from '../ts/util/toggleMaximizedBrowserWindow.std.js';
import { ChallengeMainHandler } from '../ts/main/challengeMain.main.js';
import { NativeThemeNotifier } from '../ts/main/NativeThemeNotifier.main.js';
import { PowerChannel } from '../ts/main/powerChannel.main.js';
import { SettingsChannel } from '../ts/main/settingsChannel.main.js';
import { maybeParseUrl, setUrlSearchParams } from '../ts/util/url.std.js';
import { getHeicConverter } from '../ts/workers/heicConverterMain.main.js';
} from './protocol_filter.node.ts';
import OS from '../ts/util/os/osMain.node.ts';
import { isNightly, isProduction } from '../ts/util/version.std.ts';
import { clearTimeoutIfNecessary } from '../ts/util/clearTimeoutIfNecessary.std.ts';
import { toggleMaximizedBrowserWindow } from '../ts/util/toggleMaximizedBrowserWindow.std.ts';
import { ChallengeMainHandler } from '../ts/main/challengeMain.main.ts';
import { NativeThemeNotifier } from '../ts/main/NativeThemeNotifier.main.ts';
import { PowerChannel } from '../ts/main/powerChannel.main.ts';
import { SettingsChannel } from '../ts/main/settingsChannel.main.ts';
import { maybeParseUrl, setUrlSearchParams } from '../ts/util/url.std.ts';
import { getHeicConverter } from '../ts/workers/heicConverterMain.main.ts';
import type { LocaleDirection, LocaleType } from './locale.node.js';
import { load as loadLocale } from './locale.node.js';
import type { LocaleDirection, LocaleType } from './locale.node.ts';
import { load as loadLocale } from './locale.node.ts';
import { HourCyclePreference } from '../ts/types/I18N.std.js';
import { ScreenShareStatus } from '../ts/types/Calling.std.js';
import type { ParsedSignalRoute } from '../ts/util/signalRoutes.std.js';
import { parseSignalRoute } from '../ts/util/signalRoutes.std.js';
import * as dns from '../ts/util/dns.node.js';
import { ZoomFactorService } from '../ts/services/ZoomFactorService.main.js';
import { SafeStorageBackendChangeError } from '../ts/types/SafeStorageBackendChangeError.std.js';
import { SafeStorageDecryptionError } from '../ts/types/SafeStorageDecryptionError.std.js';
import { LINUX_PASSWORD_STORE_FLAGS } from '../ts/util/linuxPasswordStoreFlags.std.js';
import { getOwn } from '../ts/util/getOwn.std.js';
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,
} from './WindowsNotifications.main.js';
import { HourCyclePreference } from '../ts/types/I18N.std.ts';
import { ScreenShareStatus } from '../ts/types/Calling.std.ts';
import type { ParsedSignalRoute } from '../ts/util/signalRoutes.std.ts';
import { parseSignalRoute } from '../ts/util/signalRoutes.std.ts';
import * as dns from '../ts/util/dns.node.ts';
import { ZoomFactorService } from '../ts/services/ZoomFactorService.main.ts';
import { SafeStorageBackendChangeError } from '../ts/types/SafeStorageBackendChangeError.std.ts';
import { SafeStorageDecryptionError } from '../ts/types/SafeStorageDecryptionError.std.ts';
import { LINUX_PASSWORD_STORE_FLAGS } from '../ts/util/linuxPasswordStoreFlags.std.ts';
import { getOwn } from '../ts/util/getOwn.std.ts';
import { safeParseLoose, safeParseUnknown } from '../ts/util/schemas.std.ts';
import { getAppErrorIcon } from '../ts/util/getAppErrorIcon.node.ts';
import { promptOSAuth } from '../ts/util/os/promptOSAuthMain.main.ts';
import { appRelaunch } from '../ts/util/relaunch.main.ts';
import { getAppRootDir } from '../ts/util/appRootDir.main.ts';
import { sendDummyKeystroke } from './WindowsNotifications.main.ts';
const { chmod, realpath, writeFile } = fsExtra;
const { get, pick, isNumber, isBoolean, some, debounce, noop } = lodash;
@ -180,7 +176,6 @@ const development =
getEnvironment() === Environment.Staging;
const ciMode = config.get<'full' | 'benchmark' | false>('ciMode');
const forcePreloadBundle = config.get<boolean>('forcePreloadBundle');
const localeDirectionTestingOverride = config.has(
'localeDirectionTestingOverride'
)
@ -678,9 +673,6 @@ async function safeLoadURL(window: BrowserWindow, url: string): Promise<void> {
}
async function createWindow() {
const usePreloadBundle =
!isTestEnvironment(getEnvironment()) || forcePreloadBundle;
const primaryDisplay = screen.getPrimaryDisplay();
const { width: maxWidth, height: maxHeight } = primaryDisplay.workAreaSize;
const width = windowConfig
@ -720,12 +712,9 @@ async function createWindow() {
nodeIntegrationInWorker: false,
sandbox: false,
contextIsolation: !isTestEnvironment(getEnvironment()),
preload: join(
rootDir,
...(usePreloadBundle
? ['preload.wrapper.js']
: ['ts', 'windows', 'main', 'preload.preload.js'])
),
preload: isTestEnvironment(getEnvironment())
? join(rootDir, 'ts', 'windows', 'main', 'tsx.preload.js')
: join(rootDir, 'bundles', 'preload', 'wrapper.js'),
spellcheck,
},
icon: windowIcon,
@ -936,43 +925,27 @@ async function createWindow() {
!windowState.shouldQuit() &&
(usingTrayIcon || OS.isMacOS())
) {
if (!usingTrayIcon) {
return;
}
if (usingTrayIcon) {
const shownTrayNotice = ephemeralConfig.get('shown-tray-notice');
if (shownTrayNotice) {
log.info('close: not showing tray notice');
return;
}
const shownTrayNotice = ephemeralConfig.get('shown-tray-notice');
if (shownTrayNotice) {
log.info('close: not showing tray notice');
return;
}
ephemeralConfig.set('shown-tray-notice', true);
log.info('close: showing tray notice');
ephemeralConfig.set('shown-tray-notice', true);
log.info('close: showing tray notice');
if (OS.isWindows()) {
showWindowsNotification({
type: NotificationType.MinimizedToTray,
token: 'unused',
heading: getResolvedMessagesLocale().i18n(
const n = new Notification({
title: getResolvedMessagesLocale().i18n(
'icu:minimizeToTrayNotification--title'
),
body: getResolvedMessagesLocale().i18n(
'icu:minimizeToTrayNotification--body'
),
});
return;
n.show();
}
const n = new Notification({
title: getResolvedMessagesLocale().i18n(
'icu:minimizeToTrayNotification--title'
),
body: getResolvedMessagesLocale().i18n(
'icu:minimizeToTrayNotification--body'
),
});
n.show();
return;
}
@ -1307,7 +1280,7 @@ async function showScreenShareWindow(sourceName: string | undefined) {
nodeIntegrationInWorker: false,
sandbox: true,
contextIsolation: true,
preload: join(rootDir, 'bundles', 'screenShare', 'preload.preload.js'),
preload: join(rootDir, 'bundles', 'preload', 'screenShare.js'),
},
x: Math.floor(display.size.width / 2) - width / 2,
y: 24,
@ -1355,7 +1328,7 @@ async function showAbout() {
nodeIntegrationInWorker: false,
sandbox: true,
contextIsolation: true,
preload: join(rootDir, 'bundles', 'about', 'preload.preload.js'),
preload: join(rootDir, 'bundles', 'preload', 'about.js'),
nativeWindowOpen: true,
},
};
@ -1457,7 +1430,7 @@ async function showDebugLogWindow(options: DebugLogWindowOptions = {}) {
nodeIntegrationInWorker: false,
sandbox: true,
contextIsolation: true,
preload: join(rootDir, 'bundles', 'debuglog', 'preload.preload.js'),
preload: join(rootDir, 'bundles', 'preload', 'debuglog.js'),
},
parent: mainWindow,
};
@ -1527,7 +1500,7 @@ async function showCallDiagnosticWindow() {
nodeIntegrationInWorker: false,
sandbox: true,
contextIsolation: true,
preload: join(rootDir, 'bundles', 'calldiagnostic', 'preload.preload.js'),
preload: join(rootDir, 'bundles', 'preload', 'calldiagnostic.js'),
},
parent: mainWindow,
};
@ -1586,7 +1559,7 @@ function showPermissionsPopupWindow(forCalling: boolean, forCamera: boolean) {
nodeIntegrationInWorker: false,
sandbox: true,
contextIsolation: true,
preload: join(rootDir, 'bundles', 'permissions', 'preload.preload.js'),
preload: join(rootDir, 'bundles', 'preload', 'permissions.js'),
nativeWindowOpen: true,
},
parent: mainWindow,
@ -2294,7 +2267,7 @@ app.on('ready', async () => {
nodeIntegration: false,
sandbox: true,
contextIsolation: true,
preload: join(rootDir, 'bundles', 'loading', 'preload.preload.js'),
preload: join(rootDir, 'bundles', 'preload', 'loading.js'),
},
icon: windowIcon,
});
@ -3414,13 +3387,7 @@ async function showStickerCreatorWindow() {
nodeIntegrationInWorker: false,
sandbox: true,
contextIsolation: true,
preload: join(
rootDir,
'ts',
'windows',
'sticker-creator',
'preload.preload.js'
),
preload: join(rootDir, 'bundles', 'sticker-creator', 'preload.js'),
nativeWindowOpen: true,
},
};

View File

@ -3,13 +3,13 @@
import lodash from 'lodash';
import type { LocalizerType } from '../ts/types/I18N.std.js';
import type { LocalizerType } from '../ts/types/I18N.std.ts';
import type {
MenuListType,
MenuOptionsType,
MenuActionsType,
} from '../ts/types/menu.std.js';
import { strictAssert } from '../ts/util/assert.std.js';
} from '../ts/types/menu.std.ts';
import { strictAssert } from '../ts/util/assert.std.ts';
const { isString } = lodash;

View File

@ -6,8 +6,8 @@
import type { session as ElectronSession, Session } from 'electron';
import type { ConfigType } from './base_config.node.js';
import { createLogger } from '../ts/logging/log.std.js';
import type { ConfigType } from './base_config.node.ts';
import { createLogger } from '../ts/logging/log.std.ts';
const log = createLogger('permissions');

View File

@ -1,8 +1,8 @@
// 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';
import { redactAll, addSensitivePath } from '../ts/util/privacy.node.ts';
import { getAppRootDir } from '../ts/util/appRootDir.main.ts';
addSensitivePath(getAppRootDir());

View File

@ -14,8 +14,8 @@ import {
getStickersPath,
getTempPath,
getUpdateCachePath,
} from './attachments.node.js';
import { createLogger } from '../ts/logging/log.std.js';
} from './attachments.node.ts';
import { createLogger } from '../ts/logging/log.std.ts';
const log = createLogger('protocol_filter');

View File

@ -4,17 +4,16 @@
import React from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import {
type WindowsNotificationData,
NotificationType,
} from '../ts/types/notifications.std.js';
import { missingCaseError } from '../ts/util/missingCaseError.std.js';
import type { WindowsNotificationData } from '../ts/services/notifications.preload.ts';
import { NotificationType } from '../ts/types/notifications.std.ts';
import { missingCaseError } from '../ts/util/missingCaseError.std.ts';
import {
cancelPresentingRoute,
showConversationRoute,
showWindowRoute,
startCallLobbyRoute,
} from '../ts/util/signalRoutes.std.js';
} from '../ts/util/signalRoutes.std.ts';
function pathToUri(path: string) {
return `file:///${encodeURI(path.replace(/\\/g, '/'))}`;
@ -79,8 +78,6 @@ export function renderWindowsToast({
launch = showWindowRoute.toAppUrl({});
} else if (type === NotificationType.IsPresenting) {
launch = cancelPresentingRoute.toAppUrl({});
} else if (type === NotificationType.MinimizedToTray) {
launch = showWindowRoute.toAppUrl({});
} else {
throw missingCaseError(type);
}

View File

@ -5,14 +5,14 @@ import type { BrowserWindow } from 'electron';
import { Menu, clipboard, nativeImage } from 'electron';
import * as LocaleMatcher from '@formatjs/intl-localematcher';
import { maybeParseUrl } from '../ts/util/url.std.js';
import { maybeParseUrl } from '../ts/util/url.std.ts';
import type { MenuListType } from '../ts/types/menu.std.js';
import type { LocalizerType } from '../ts/types/Util.std.js';
import { strictAssert } from '../ts/util/assert.std.js';
import type { LoggerType } from '../ts/types/Logging.std.js';
import { createLogger } from '../ts/logging/log.std.js';
import { handleAttachmentRequest } from './attachment_channel.main.js';
import type { MenuListType } from '../ts/types/menu.std.ts';
import type { LocalizerType } from '../ts/types/Util.std.ts';
import { strictAssert } from '../ts/util/assert.std.ts';
import type { LoggerType } from '../ts/types/Logging.std.ts';
import { createLogger } from '../ts/logging/log.std.ts';
import { handleAttachmentRequest } from './attachment_channel.main.ts';
const log = createLogger('spell_check');

View File

@ -3,9 +3,9 @@
import { ipcMain } from 'electron';
import type { MainSQL } from '../ts/sql/main.main.js';
import { remove as removeUserConfig } from './user_config.main.js';
import { remove as removeEphemeralConfig } from './ephemeral_config.main.js';
import type { MainSQL } from '../ts/sql/main.main.ts';
import { remove as removeUserConfig } from './user_config.main.ts';
import { remove as removeEphemeralConfig } from './ephemeral_config.main.ts';
let sql:
| Pick<

View File

@ -3,9 +3,9 @@
import { app } from 'electron';
import { packageJson } from '../ts/util/packageJson.main.js';
import { createLogger } from '../ts/logging/log.std.js';
import * as GlobalErrors from './global_errors.main.js';
import { packageJson } from '../ts/util/packageJson.main.ts';
import { createLogger } from '../ts/logging/log.std.ts';
import * as GlobalErrors from './global_errors.main.ts';
const log = createLogger('startup_config');

View File

@ -5,10 +5,10 @@ import type { Session, DesktopCapturerSource, IpcMainEvent } from 'electron';
import { desktopCapturer, ipcMain, systemPreferences } from 'electron';
import { v4 as generateUuid } from 'uuid';
import OS from '../ts/util/os/osMain.node.js';
import type { LoggerType } from '../ts/types/Logging.std.js';
import { strictAssert } from '../ts/util/assert.std.js';
import type { IpcResponseType } from '../ts/util/desktopCapturer.preload.js';
import OS from '../ts/util/os/osMain.node.ts';
import type { LoggerType } from '../ts/types/Logging.std.ts';
import { strictAssert } from '../ts/util/assert.std.ts';
import type { IpcResponseType } from '../ts/util/desktopCapturer.preload.ts';
const SPELL_CHECKER_DICTIONARY_DOWNLOAD_URL = `https://updates.signal.org/desktop/hunspell_dictionaries/${process.versions.electron}/`;

View File

@ -5,10 +5,10 @@ import { join } from 'node:path';
import { mkdirSync } from 'node:fs';
import { app } from 'electron';
import { start } from './base_config.node.js';
import config from './config.main.js';
import * as Errors from '../ts/types/errors.std.js';
import OS from '../ts/util/os/osMain.node.js';
import { start } from './base_config.node.ts';
import config from './config.main.ts';
import * as Errors from '../ts/types/errors.std.ts';
import OS from '../ts/util/os/osMain.node.ts';
let userData: string | undefined;
// Use separate data directory for benchmarks & development

View File

@ -96,11 +96,7 @@
as="image"
crossorigin
/>
<link
href="node_modules/@signalapp/quill-cjs/dist/quill.core.css"
rel="stylesheet"
type="text/css"
/>
<link href="stylesheets/quill.css" rel="stylesheet" type="text/css" />
<link href="stylesheets/manifest.css" rel="stylesheet" type="text/css" />
<link href="stylesheets/tailwind.css" rel="stylesheet" type="text/css" />
</head>

View File

@ -11,17 +11,17 @@ import { readFile } from 'node:fs/promises';
import { join as pathJoin, relative as pathRelative } from 'node:path';
import chalk from 'chalk';
import { deepEqual } from 'node:assert';
import type { Rule } from './utils/rule.std.js';
import type { Rule } from './utils/rule.std.ts';
import icuPrefix from './rules/icuPrefix.std.js';
import wrapEmoji from './rules/wrapEmoji.std.js';
import onePlural from './rules/onePlural.std.js';
import noLegacyVariables from './rules/noLegacyVariables.std.js';
import noNestedChoice from './rules/noNestedChoice.std.js';
import noOffset from './rules/noOffset.std.js';
import noOneChoice from './rules/noOneChoice.std.js';
import noOrdinal from './rules/noOrdinal.std.js';
import pluralPound from './rules/pluralPound.std.js';
import icuPrefix from './rules/icuPrefix.std.ts';
import wrapEmoji from './rules/wrapEmoji.std.ts';
import onePlural from './rules/onePlural.std.ts';
import noLegacyVariables from './rules/noLegacyVariables.std.ts';
import noNestedChoice from './rules/noNestedChoice.std.ts';
import noOffset from './rules/noOffset.std.ts';
import noOneChoice from './rules/noOneChoice.std.ts';
import noOrdinal from './rules/noOrdinal.std.ts';
import pluralPound from './rules/pluralPound.std.ts';
const RULES = [
icuPrefix,

View File

@ -1,7 +1,7 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { rule } from '../utils/rule.std.js';
import { rule } from '../utils/rule.std.ts';
export default rule('icuPrefix', context => {
if (!context.messageId.startsWith('icu:')) {

View File

@ -1,7 +1,7 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { rule } from '../utils/rule.std.js';
import { rule } from '../utils/rule.std.ts';
export default rule('noLegacyVariables', context => {
return {

View File

@ -1,8 +1,8 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import type { Element } from '../utils/rule.std.js';
import { rule } from '../utils/rule.std.js';
import type { Element } from '../utils/rule.std.ts';
import { rule } from '../utils/rule.std.ts';
export default rule('noNestedChoice', context => {
let insideChoice = false;

View File

@ -1,7 +1,7 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { rule } from '../utils/rule.std.js';
import { rule } from '../utils/rule.std.ts';
export default rule('noOffset', context => {
return {

View File

@ -1,7 +1,7 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { rule } from '../utils/rule.std.js';
import { rule } from '../utils/rule.std.ts';
export default rule('noOneChoice', context => {
return {

View File

@ -1,7 +1,7 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { rule } from '../utils/rule.std.js';
import { rule } from '../utils/rule.std.ts';
export default rule('noOrdinal', context => {
return {

View File

@ -1,7 +1,7 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { rule } from '../utils/rule.std.js';
import { rule } from '../utils/rule.std.ts';
export default rule('onePlural', context => {
let plurals = 0;

View File

@ -2,7 +2,7 @@
// SPDX-License-Identifier: AGPL-3.0-only
import type { PluralElement } from '@formatjs/icu-messageformat-parser';
import { rule } from '../utils/rule.std.js';
import { rule } from '../utils/rule.std.ts';
export default rule('pluralPound', context => {
const stack: Array<PluralElement> = [];

View File

@ -10,7 +10,7 @@ import {
isTagElement,
isLiteralElement,
} from '@formatjs/icu-messageformat-parser';
import { rule } from '../utils/rule.std.js';
import { rule } from '../utils/rule.std.ts';
function isEmojifyTag(
element: MessageFormatElement | null

View File

@ -5,8 +5,8 @@ import type {
MessageFormatElement,
Location,
} from '@formatjs/icu-messageformat-parser';
import type { Visitor } from './traverse.std.js';
import { traverse } from './traverse.std.js';
import type { Visitor } from './traverse.std.ts';
import { traverse } from './traverse.std.ts';
export type Element = MessageFormatElement;
export type { Location };

View File

@ -20,6 +20,6 @@
</head>
<body>
<div id="app"></div>
<script type="module" src="bundles/calldiagnostic/app.dom.js"></script>
<script type="module" src="bundles/dom/calldiagnostic.js"></script>
</body>
</html>

4
ci.js
View File

@ -3,8 +3,8 @@
const CI_CONFIG = JSON.parse(process.env.SIGNAL_CI_CONFIG || '');
const config = require('./app/config.main.js').default;
const config = require('./bundles/config.js').default;
config.util.extendDeep(config, CI_CONFIG);
require('./app/main.main.js');
require('./bundles/main.js');

View File

@ -0,0 +1,46 @@
// Copyright 2026 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { existsSync } from 'node:fs';
import { join, dirname } from 'node:path';
export default function transform() {
function ImportOrExport({ node }, { filename }) {
if (
!node.source ||
!node.source.value.startsWith('.') ||
!node.source.value.endsWith('.js') ||
// js file with .d.ts file
node.source.value.endsWith('/StorybookThemeContext.std.js') ||
// protobuf
node.source.value.endsWith('/compiled.std.js')
) {
return;
}
const ts = node.source.value.replace(/\.js$/, '.ts');
const tsx = node.source.value.replace(/\.js$/, '.tsx');
const dts = node.source.value.replace(/\.js$/, '.d.ts');
const dir = dirname(filename);
if (existsSync(join(dir, ts))) {
// oxlint-disable-next-line no-param-reassign
node.source.value = ts;
} else if (existsSync(join(dir, tsx))) {
// oxlint-disable-next-line no-param-reassign
node.source.value = tsx;
} else if (existsSync(join(dir, dts))) {
// oxlint-disable-next-line no-param-reassign
node.source.value = dts;
} else {
throw new Error(`File not found: ${join(dir, node.source.value)}`);
}
}
return {
visitor: {
ImportDeclaration: ImportOrExport,
ExportAllDeclaration: ImportOrExport,
ExportNamedDeclaration: ImportOrExport,
},
};
}

View File

@ -69,10 +69,6 @@ if (ENVIRONMENT_IS_NODE) {
Module['readBinary'] = function readBinary(filename) { return Module['read'](filename, true) };
Module['load'] = function load(f) {
globalEval(read(f));
};
if (!Module['thisProgram']) {
if (process['argv'].length > 1) {
Module['thisProgram'] = process['argv'][1].replace(/\\/g, '/');
@ -164,14 +160,6 @@ else {
throw 'Unknown runtime environment. Where are we?';
}
function globalEval(x) {
eval.call(null, x);
}
if (!Module['load'] && Module['read']) {
Module['load'] = function load(f) {
globalEval(Module['read'](f));
};
}
if (!Module['print']) {
Module['print'] = function(){};
}

View File

@ -1,5 +1,3 @@
importScripts("Mp3LameEncoder.min.js");
var NUM_CH = 2, // constant
sampleRate = 44100,
options = undefined,

View File

@ -19,7 +19,6 @@
"updatesEnabled": false,
"ciMode": false,
"ciForceUnprocessed": false,
"forcePreloadBundle": false,
"openDevTools": false,
"buildCreation": 0,
"buildExpiration": 0,

View File

@ -20,6 +20,6 @@
</head>
<body>
<div id="app"></div>
<script type="module" src="bundles/debuglog/app.dom.js"></script>
<script type="module" src="bundles/dom/debuglog.js"></script>
</body>
</html>

46699
js/Mp3LameEncoder.min.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -31,6 +31,6 @@
</div>
<div id="message"></div>
</div>
<script type="module" src="bundles/loading/start.dom.js"></script>
<script type="module" src="bundles/dom/loading.js"></script>
</body>
</html>

View File

@ -13,62 +13,61 @@
"email": "support@signal.org"
},
"browserslist": "last 1 chrome versions",
"main": "app/main.main.js",
"main": "bundles/main.js",
"scripts": {
"postinstall": "pnpm run build:acknowledgments && pnpm run electron:install-app-deps",
"postuninstall": "pnpm run build:acknowledgments",
"start": "electron .",
"generate": "run-s generate:phase-0 generate:phase-1",
"generate:phase-0": "run-p build:esbuild:scripts",
"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",
"generate:phase-0": "run-s build:protobuf build:rolldown:prod",
"generate:phase-1": "run-p --aggregate-output --print-label build:icu-types build:compact-locales build:styles:prod get-expire-time build:webaudio-recorder build:policy-files",
"build-release": "pnpm run build",
"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",
"get-strings:countries": "ts-node ./ts/scripts/build-localized-display-names.node.ts countries ts/scripts/locale-data/country-display-names.csv build/country-display-names.json",
"get-strings:emoji": "ts-node ./ts/scripts/get-emoji-locales.node.ts",
"push-strings": "node ts/scripts/remove-strings.node.js && node ts/scripts/push-strings.node.js",
"mark-unusued-strings-deleted": "ts-node ./ts/scripts/mark-unused-strings-deleted.node.ts",
"get-expire-time": "node ts/scripts/get-expire-time.node.js",
"copy-components": "node ts/scripts/copy.node.js",
"get-strings": "tsx ts/scripts/get-strings.node.ts && tsx ts/scripts/gen-nsis-script.node.ts && tsx 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": "tsx ./ts/scripts/build-localized-display-names.node.ts locales ts/scripts/locale-data/locale-display-names.csv build/locale-display-names.json",
"get-strings:countries": "tsx ./ts/scripts/build-localized-display-names.node.ts countries ts/scripts/locale-data/country-display-names.csv build/country-display-names.json",
"get-strings:emoji": "tsx ./ts/scripts/get-emoji-locales.node.ts",
"push-strings": "tsx ts/scripts/remove-strings.node.ts && tsx ts/scripts/push-strings.node.ts",
"mark-unusued-strings-deleted": "tsx ./ts/scripts/mark-unused-strings-deleted.node.ts",
"get-expire-time": "tsx ts/scripts/get-expire-time.node.ts",
"build:webaudio-recorder": "terser --compress ecma=2025 --toplevel components/mp3lameencoder/lib/Mp3LameEncoder.js components/webaudiorecorder/lib/WebAudioRecorderMp3.js -o js/WebAudioRecorderMp3.js",
"build:protobuf": "protopiler --module cjs --output ts/protobuf/compiled.std.js --typedefs ts/protobuf/compiled.std.d.ts protos",
"clean:protobuf": "rm -f ts/protobuf/compiled.std.d.ts ts/protobuf/compiled.std.js",
"prepare-beta-build": "node scripts/prepare_beta_build.js",
"prepare-alpha-build": "node scripts/prepare_alpha_build.js",
"prepare-alpha-version": "node scripts/prepare_tagged_version.js alpha",
"prepare-axolotl-build": "node scripts/prepare_axolotl_build.js",
"prepare-axolotl-version": "node scripts/prepare_tagged_version.js axolotl",
"prepare-adhoc-build": "node scripts/prepare_adhoc_build.js",
"prepare-adhoc-version": "node scripts/prepare_tagged_version.js adhoc",
"prepare-staging-build": "node scripts/prepare_staging_build.js",
"prepare-linux-build": "node scripts/prepare_linux_build.js",
"prepare-beta-build": "tsx scripts/prepare_beta_build.js",
"prepare-alpha-build": "tsx scripts/prepare_alpha_build.js",
"prepare-alpha-version": "tsx scripts/prepare_tagged_version.js alpha",
"prepare-axolotl-build": "tsx scripts/prepare_axolotl_build.js",
"prepare-axolotl-version": "tsx scripts/prepare_tagged_version.js axolotl",
"prepare-adhoc-build": "tsx scripts/prepare_adhoc_build.js",
"prepare-adhoc-version": "tsx scripts/prepare_tagged_version.js adhoc",
"prepare-staging-build": "tsx scripts/prepare_staging_build.js",
"prepare-linux-build": "tsx scripts/prepare_linux_build.js",
"test": "run-s test-node test-electron test-lint-intl test-oxlint",
"test-electron": "node ts/scripts/test-electron.node.js",
"test-release": "node ts/scripts/test-release.node.js",
"test-node": "cross-env NODE_ENV=test LANG=en-us electron-mocha --timeout 10000 --file test/setup-test-node.js --recursive ts/test-node",
"test-mock": "node ts/scripts/mocha-separator.node.js --require ts/test-mock/setup-ci.node.js -- ts/test-mock/**/*_test.node.js",
"test-mock-docker": "mocha --require ts/test-mock/setup-ci.node.js ts/test-mock/**/*_test.docker.node.js",
"test-electron": "tsx ts/scripts/test-electron.node.ts",
"test-release": "tsx ts/scripts/test-release.node.ts",
"test-node": "cross-env NODE_ENV=test NODE_OPTIONS='--import=tsx' LANG=en-us electron-mocha --timeout 10000 --file ts/test-node/setup.preload.ts --recursive ts/test-node/**/*.ts ts/test-node/**/*.tsx",
"test-mock": "tsx ts/scripts/mocha-separator.node.ts --require ts/test-mock/setup-ci.node.ts -- ts/test-mock/**/*_test.node.ts",
"test-mock-docker": "mocha --require ts/test-mock/setup-ci.node.ts ts/test-mock/**/*_test.docker.node.ts",
"test-oxlint": "mocha --require .oxlint/test-setup.mjs .oxlint/rules/**/*.test.mjs",
"test-lint-intl": "ts-node ./build/intl-linter/linter.node.ts --test",
"test-lint-intl": "tsx ./build/intl-linter/linter.node.ts --test",
"oxlint": "oxlint",
"lint": "run-p --aggregate-output --print-label lint-prettier lint-css check:types oxlint",
"lint-deps": "node ts/util/lint/linter.node.js",
"lint-license-comments": "ts-node ts/util/lint/license_comments.node.ts",
"lint-deps": "tsx ts/util/lint/linter.node.ts",
"lint-license-comments": "tsx ts/util/lint/license_comments.node.ts",
"lint-prettier": "pprettier --check '**/*.{ts,tsx,d.ts,js,json,html,scss,md,yml,yaml}' '!node_modules/**'",
"lint-intl": "ts-node ./build/intl-linter/linter.node.ts",
"lint-intl": "tsx ./build/intl-linter/linter.node.ts",
"lint-css": "stylelint '**/*.scss' --cache",
"danger:local": "./danger/danger.sh local --base main",
"danger:ci": "./danger/danger.sh ci --base origin/main",
"format": "pprettier --write '**/*.{ts,tsx,d.ts,js,json,html,scss,md,yml,yaml}' '!node_modules/**'",
"svgo": "svgo --multipass images/**/*.svg images/*.svg",
"transpile": "run-p check:types build:esbuild",
"transpile": "run-p check:types build:rolldown",
"check:types": "tsgo --noEmit",
"clean-transpile": "node ./scripts/clean-transpile.js",
"ready": "npm-run-all --print-label clean-transpile generate --parallel lint lint-deps lint-intl test-node test-electron",
"dev": "pnpm run build:protobuf && cross-env SIGNAL_ENV=storybook storybook dev --port 6006",
"dev:transpile": "run-p \"check:types --watch\" dev:esbuild dev:icu-types dev:protobuf",
"dev:esbuild": "node scripts/esbuild.js --watch",
"dev:transpile": "run-p \"check:types --watch\" dev:rolldown dev:icu-types dev:protobuf",
"dev:rolldown": "pnpm build:rolldown --watch",
"dev:styles": "pnpm run '/^dev:styles:(sass|tailwind)$/'",
"dev:styles:sass": "pnpm run build:styles:sass --watch",
"dev:styles:tailwind": "pnpm run build:styles:tailwind --watch",
@ -78,33 +77,35 @@
"test:storybook": "pnpm run build:storybook && run-p --race test:storybook:*",
"test:storybook:serve": "http-server storybook-static --port 6006 --silent",
"test:storybook:test": "wait-on http://127.0.0.1:6006/ --timeout 5000 && test-storybook --testTimeout 60000",
"build": "run-s --print-label generate build:esbuild:prod build:release",
"build-win32-all": "run-s --print-label generate build:esbuild:prod build:release-win32-all",
"build-linux": "run-s build:policy-files generate build:esbuild:prod && pnpm run build:release --publish=never",
"build": "run-s --print-label generate build:rolldown:prod build:release",
"build-win32-all": "run-s --print-label generate build:rolldown:prod build:release-win32-all",
"build-linux": "run-s build:policy-files generate build:rolldown:prod && pnpm run build:release --publish=never",
"build:acknowledgments": "node scripts/generate-acknowledgments.js",
"build:dns-fallback": "node ts/scripts/generate-dns-fallback.node.js",
"build:icu-types": "node ts/scripts/generate-icu-types.node.js",
"build:compact-locales": "node ts/scripts/generate-compact-locales.node.js",
"build:tray-icons": "ts-node ts/scripts/generate-tray-icons.node.ts",
"build:dev": "run-s --print-label generate build:esbuild:prod",
"build:esbuild": "node scripts/esbuild.js",
"build:esbuild:scripts": "node scripts/esbuild.js --no-bundle",
"build:esbuild:bundle": "node scripts/esbuild.js --no-scripts",
"build:esbuild:prod": "node scripts/esbuild.js --prod",
"build:policy-files": "node ts/scripts/gen-policy-files.node.js",
"build:styles": "pnpm run \"/^build:styles:.*/\"",
"build:styles:sass": "sass stylesheets/manifest.scss:stylesheets/manifest.css stylesheets/manifest_bridge.scss:stylesheets/manifest_bridge.css --fatal-deprecation=1.80.7",
"build:dns-fallback": "tsx ts/scripts/generate-dns-fallback.node.ts",
"build:icu-types": "tsx ts/scripts/generate-icu-types.node.ts",
"build:compact-locales": "tsx ts/scripts/generate-compact-locales.node.ts",
"build:tray-icons": "tsx ts/scripts/generate-tray-icons.node.ts",
"build:dev": "run-s --print-label generate build:rolldown:prod",
"build:rolldown": "rolldown -c",
"build:rolldown:prod": "pnpm build:rolldown --minify",
"build:esbuild:prod": "pnpm build:rolldown:prod",
"build:policy-files": "tsx ts/scripts/gen-policy-files.node.ts",
"build:styles": "pnpm run \"/^build:styles:(sass|tailwind)$/\"",
"build:styles:prod": "pnpm run \"/^build:styles:(sass|tailwind):prod$/\"",
"build:styles:sass": "sass stylesheets/manifest.scss:stylesheets/manifest.css stylesheets/manifest_bridge.scss:stylesheets/manifest_bridge.css node_modules/@signalapp/quill-cjs/dist/quill.core.css:stylesheets/quill.css --fatal-deprecation=1.80.7",
"build:styles:tailwind": "tailwindcss -i ./stylesheets/tailwind-config.css -o ./stylesheets/tailwind.css",
"build:electron": "electron-builder --config.extraMetadata.environment=$SIGNAL_ENV",
"build:styles:sass:prod": "pnpm run build:styles:sass --style=compressed",
"build:styles:tailwind:prod": "pnpm run build:styles:tailwind --minify",
"build:electron": "cross-env NODE_OPTIONS='--import=tsx' electron-builder --config.extraMetadata.environment=$SIGNAL_ENV",
"build:release": "cross-env SIGNAL_ENV=production pnpm run build:electron --config.directories.output=release",
"build:mas-dev": "bash ./scripts/build-mas-dev.sh",
"build:release-win32-all": "pnpm run build:release --arm64 --x64",
"build:preload-cache": "node ts/scripts/generate-preload-cache.node.js",
"build:preload-cache": "tsx ts/scripts/generate-preload-cache.node.ts",
"build:emoji": "run-p build:emoji:32 build:emoji:64",
"build:emoji:32": "cwebp -progress -mt -preset icon -alpha_filter best -alpha_q 20 -pass 10 -q 75 ./node_modules/emoji-datasource-apple/img/apple/sheets/32.png -o ./images/emoji-sheet-32.webp",
"build:emoji:64": "cwebp -progress -mt -preset icon -alpha_filter best -alpha_q 20 -pass 10 -q 75 ./node_modules/emoji-datasource-apple/img/apple/sheets/64.png -o ./images/emoji-sheet-64.webp",
"electron:install-app-deps": "electron-builder install-app-deps",
"check-upgradeable-deps": "ts-node ts/scripts/check-upgradeable-deps.node.ts",
"check-upgradeable-deps": "tsx ts/scripts/check-upgradeable-deps.node.ts",
"react-devtools": "react-devtools",
"run-with-devtools": "cross-env REACT_DEVTOOLS=1 run-p --print-label react-devtools start"
},
@ -112,113 +113,25 @@
"fs-xattr": "0.3.0"
},
"dependencies": {
"@electron/asar": "3.4.1",
"@formatjs/fast-memoize": "2.2.3",
"@formatjs/icu-messageformat-parser": "2.9.3",
"@formatjs/intl-localematcher": "0.2.32",
"@indutny/dicer": "0.3.2",
"@indutny/mac-screen-share": "1.0.13",
"@indutny/protopiler": "3.2.4",
"@indutny/range-finder": "1.3.4",
"@indutny/simple-windows-notifications": "2.0.16",
"@indutny/sneequals": "4.0.0",
"@internationalized/date": "3.12.0",
"@popperjs/core": "2.11.8",
"@react-aria/focus": "3.21.5",
"@react-aria/interactions": "3.27.1",
"@react-aria/utils": "3.33.1",
"@react-spring/web": "10.0.3",
"@react-types/shared": "3.33.1",
"@signalapp/libsignal-client": "0.90.0",
"@signalapp/minimask": "1.0.1",
"@signalapp/mute-state-change": "workspace:1.0.0",
"@signalapp/quill-cjs": "2.1.2",
"@signalapp/ringrtc": "2.67.0",
"@signalapp/sqlcipher": "3.2.1",
"@signalapp/windows-ucv": "1.0.1",
"@tanstack/react-virtual": "3.11.2",
"@types/dom-mediacapture-transform": "0.1.11",
"@types/fabric": "4.5.3",
"@typescript/native-preview": "7.0.0-dev.20260303.1",
"blob-util": "2.0.2",
"blueimp-load-image": "5.16.0",
"blurhash": "2.0.5",
"buffer": "6.0.3",
"card-validator": "10.0.3",
"changedpi": "1.0.4",
"cirbuf": "1.0.2",
"classnames": "2.5.1",
"config": "3.3.12",
"copy-text-to-clipboard": "2.1.0",
"country-codes-list": "2.0.0",
"credit-card-type": "10.0.2",
"dashdash": "2.0.0",
"direction": "1.0.4",
"dom-accessibility-api": "0.7.0",
"emoji-datasource": "16.0.0",
"emoji-datasource-apple": "16.0.0",
"emoji-regex": "10.4.0",
"encoding": "0.1.13",
"fabric": "4.6.0",
"fast-glob": "3.3.2",
"filesize": "9.0.11",
"firstline": "2.0.2",
"focus-trap-react": "10.3.1",
"form-data": "4.0.1",
"fs-extra": "11.2.0",
"fuse.js": "6.5.3",
"google-libphonenumber": "3.2.39",
"got": "11.8.5",
"growing-file": "0.1.3",
"heic-convert": "2.1.0",
"humanize-duration": "3.27.1",
"intl-tel-input": "24.7.0",
"js-yaml": "4.1.0",
"linkify-it": "5.0.0",
"lodash": "4.17.21",
"lru-cache": "11.0.2",
"memoizee": "0.4.17",
"moment": "2.30.1",
"motion": "12.35.1",
"mp4box": "0.5.3",
"node-fetch": "2.6.7",
"nop": "1.0.0",
"normalize-path": "3.0.0",
"p-map": "7.0.4",
"p-queue": "6.6.2",
"p-timeout": "4.1.0",
"parsecurrency": "1.1.1",
"pify": "3.0.0",
"pino": "9.8.0",
"proxy-agent": "6.4.0",
"qrcode-generator": "1.4.4",
"radix-ui": "1.4.3",
"react": "19.2.4",
"react-aria": "3.47.0",
"react-aria-components": "1.16.0",
"react-blurhash": "0.3.0",
"react-dom": "19.2.4",
"react-intl": "7.1.11",
"react-popper": "2.3.0",
"react-redux": "9.2.0",
"react-virtualized": "9.22.6",
"read-last-lines": "1.8.0",
"redux": "5.0.1",
"redux-logger": "3.0.6",
"redux-promise-middleware": "6.2.0",
"redux-thunk": "3.1.0",
"reselect": "5.1.1",
"semver": "7.6.3",
"split2": "4.2.0",
"tinykeys": "3.0.0",
"type-fest": "4.26.1",
"url": "0.11.4",
"urlpattern-polyfill": "10.0.0",
"uuid": "11.0.2",
"write-file-atomic": "6.0.0",
"zod": "3.23.8"
"proxy-agent": "6.4.0"
},
"devDependencies": {
"linkify-it": "5.0.0",
"@babel/core": "7.26.0",
"@babel/plugin-proposal-class-properties": "7.18.6",
"@babel/plugin-proposal-nullish-coalescing-operator": "7.18.6",
@ -227,14 +140,31 @@
"@babel/plugin-transform-typescript": "7.25.9",
"@babel/preset-react": "7.25.9",
"@babel/preset-typescript": "7.26.0",
"@electron/asar": "3.4.1",
"@electron/fuses": "1.5.0",
"@electron/notarize": "2.1.0",
"@electron/symbolicate-mac": "2.3.1",
"@formatjs/fast-memoize": "2.2.3",
"@formatjs/icu-messageformat-parser": "2.9.3",
"@formatjs/intl": "2.10.14",
"@formatjs/intl-localematcher": "0.2.32",
"@indutny/dicer": "0.3.2",
"@indutny/parallel-prettier": "3.0.0",
"@indutny/protopiler": "3.2.4",
"@indutny/range-finder": "1.3.4",
"@indutny/rezip-electron": "3.0.2",
"@indutny/sneequals": "4.0.0",
"@internationalized/date": "3.12.0",
"@napi-rs/canvas": "0.1.61",
"@popperjs/core": "2.11.8",
"@react-aria/focus": "3.21.5",
"@react-aria/interactions": "3.27.1",
"@react-aria/utils": "3.33.1",
"@react-spring/web": "10.0.3",
"@react-types/shared": "3.33.1",
"@signalapp/minimask": "1.0.1",
"@signalapp/mock-server": "18.3.0",
"@signalapp/quill-cjs": "2.1.2",
"@storybook/addon-a11y": "8.4.4",
"@storybook/addon-actions": "8.4.4",
"@storybook/addon-controls": "8.4.4",
@ -253,6 +183,7 @@
"@storybook/types": "8.1.11",
"@tailwindcss/cli": "4.1.7",
"@tailwindcss/postcss": "4.1.7",
"@tanstack/react-virtual": "3.11.2",
"@types/blueimp-load-image": "5.16.6",
"@types/chai": "4.3.16",
"@types/chai-as-promised": "7.1.4",
@ -260,6 +191,8 @@
"@types/dashdash": "1.14.3",
"@types/debug": "4.1.12",
"@types/direction": "1.0.0",
"@types/dom-mediacapture-transform": "0.1.11",
"@types/fabric": "4.5.3",
"@types/fs-extra": "11.0.4",
"@types/google-libphonenumber": "7.4.30",
"@types/humanize-duration": "3.18.1",
@ -294,46 +227,87 @@
"@typescript-eslint/parser": "8.57.2",
"@typescript-eslint/rule-tester": "8.57.2",
"@typescript-eslint/utils": "8.57.2",
"@typescript/native-preview": "7.0.0-dev.20260303.1",
"axe-core": "4.10.2",
"babel-core": "7.0.0-bridge.0",
"babel-loader": "9.2.1",
"babel-plugin-lodash": "3.3.4",
"better-blockmap": "2.0.1",
"blob-util": "2.0.2",
"blueimp-load-image": "5.16.0",
"blurhash": "2.0.5",
"buffer": "6.0.3",
"card-validator": "10.0.3",
"casual": "1.6.2",
"chai": "4.4.1",
"chai-as-promised": "7.1.1",
"chalk": "4.1.2",
"changedpi": "1.0.4",
"chokidar-cli": "3.0.0",
"cirbuf": "1.0.2",
"classnames": "2.5.1",
"config": "3.3.12",
"copy-text-to-clipboard": "2.1.0",
"country-codes-list": "2.0.0",
"credit-card-type": "10.0.2",
"cross-env": "7.0.3",
"css-loader": "7.1.2",
"csv-parse": "5.5.6",
"danger": "12.3.3",
"dashdash": "2.0.0",
"debug": "4.3.7",
"direction": "1.0.4",
"dom-accessibility-api": "0.7.0",
"electron": "40.8.5",
"electron-builder": "26.0.14",
"electron-mocha": "13.0.1",
"emoji-regex": "10.4.0",
"encoding": "0.1.13",
"endanger": "7.0.4",
"enhanced-resolve": "5.18.3",
"enquirer": "2.4.1",
"esbuild": "0.25.9",
"eslint": "10.1.0",
"eslint-plugin-better-tailwindcss": "4.3.2",
"execa": "5.1.1",
"fabric": "4.6.0",
"fast-glob": "3.3.2",
"filesize": "9.0.11",
"firstline": "2.0.2",
"focus-trap-react": "10.3.1",
"form-data": "4.0.1",
"fuse.js": "6.5.3",
"growing-file": "0.1.3",
"heic-convert": "2.1.0",
"html-webpack-plugin": "5.6.3",
"http-server": "14.1.1",
"humanize-duration": "3.27.1",
"is-glob": "4.0.3",
"js-yaml": "4.1.0",
"json-to-ast": "2.1.0",
"lodash": "4.17.21",
"log-symbols": "4.1.0",
"lru-cache": "11.0.2",
"memoizee": "0.4.17",
"micromatch": "4.0.8",
"mini-css-extract-plugin": "2.9.2",
"mocha": "10.8.2",
"moment": "2.30.1",
"motion": "12.35.1",
"mp4box": "0.5.3",
"node-gyp": "11.0.0",
"node-gyp-build": "4.8.4",
"nop": "1.0.0",
"normalize-path": "3.0.0",
"npm-run-all": "4.1.5",
"oxlint": "1.57.0",
"oxlint-tsgolint": "0.17.4",
"p-limit": "3.1.0",
"p-map": "7.0.4",
"p-queue": "6.6.2",
"p-timeout": "4.1.0",
"parsecurrency": "1.1.1",
"pe-library": "2.0.1",
"pify": "3.0.0",
"pixelmatch": "5.3.0",
"playwright": "1.58.2",
"pngjs": "7.0.0",
@ -341,12 +315,32 @@
"postcss-loader": "8.1.1",
"prettier": "3.7.4",
"prettier-plugin-tailwindcss": "0.7.2",
"qrcode-generator": "1.4.4",
"radix-ui": "1.4.3",
"react": "19.2.4",
"react-aria": "3.47.0",
"react-aria-components": "1.16.0",
"react-blurhash": "0.3.0",
"react-devtools": "6.0.1",
"react-devtools-core": "6.0.1",
"react-dom": "19.2.4",
"react-intl": "7.1.11",
"react-popper": "2.3.0",
"react-redux": "9.2.0",
"react-virtualized": "9.22.6",
"read-last-lines": "1.8.0",
"redux": "5.0.1",
"redux-logger": "3.0.6",
"redux-promise-middleware": "6.2.0",
"redux-thunk": "3.1.0",
"reselect": "5.1.1",
"resolve-url-loader": "5.0.0",
"rolldown": "1.0.0-rc.9",
"sass": "1.80.7",
"sass-loader": "16.0.3",
"semver": "7.6.3",
"sinon": "19.0.2",
"split2": "4.2.0",
"storybook": "8.4.4",
"style-loader": "4.0.0",
"stylelint": "16.10.0",
@ -356,13 +350,21 @@
"svgo": "3.3.2",
"synckit": "0.11.11",
"tailwindcss": "4.2.1",
"terser": "5.46.1",
"terser-webpack-plugin": "5.3.10",
"ts-node": "10.9.2",
"tinykeys": "3.0.0",
"tsx": "4.21.0",
"type-fest": "4.26.1",
"typescript": "5.9.3",
"url": "0.11.4",
"urlpattern-polyfill": "10.0.0",
"uuid": "11.0.2",
"wait-on": "8.0.1",
"webpack": "5.96.1",
"webpack-cli": "5.1.4",
"webpack-dev-server": "5.1.0"
"webpack-dev-server": "5.1.0",
"write-file-atomic": "6.0.0",
"zod": "3.23.8"
},
"pnpm": {
"overrides": {
@ -392,7 +394,8 @@
"fs-xattr": "patches/fs-xattr.patch",
"@types/chai": "patches/@types__chai.patch",
"@napi-rs/canvas@0.1.61": "patches/@napi-rs__canvas@0.1.61.patch",
"playwright-core@1.58.2": "patches/playwright-core@1.58.2.patch"
"playwright-core@1.58.2": "patches/playwright-core@1.58.2.patch",
"tsx": "patches/tsx.patch"
},
"onlyBuiltDependencies": [
"@indutny/mac-screen-share",
@ -405,7 +408,6 @@
"@swc/core",
"@tailwindcss/oxide",
"electron",
"esbuild",
"fs-xattr"
],
"ignoredBuiltDependencies": [
@ -435,7 +437,7 @@
}
],
"mergeASARs": true,
"sign": "./ts/scripts/sign-macos.node.js",
"sign": "./ts/scripts/sign-macos.node.ts",
"releaseInfo": {
"vendor": {
"minOSVersion": "21.0.1"
@ -503,7 +505,7 @@
"certificateSubjectName": "Signal Messenger, LLC",
"certificateSha1": "8D5E3CD800736C5E1FE459A1F5AA48287D4F6EC6",
"publisherName": "Signal Messenger, LLC",
"sign": "./ts/scripts/sign-windows.node.js",
"sign": "./ts/scripts/sign-windows.node.ts",
"signingHashAlgorithms": [
"sha256"
]
@ -601,10 +603,10 @@
"signalcaptcha"
]
},
"artifactBuildCompleted": "ts/scripts/artifact-build-completed.node.js",
"afterSign": "ts/scripts/after-sign.node.js",
"afterPack": "ts/scripts/after-pack.node.js",
"afterAllArtifactBuild": "ts/scripts/after-all-artifact-build.node.js",
"artifactBuildCompleted": "ts/scripts/artifact-build-completed.node.ts",
"afterSign": "ts/scripts/after-sign.node.ts",
"afterPack": "ts/scripts/after-pack.node.ts",
"afterAllArtifactBuild": "ts/scripts/after-all-artifact-build.node.ts",
"asar": {
"smartUnpack": false
},
@ -635,8 +637,6 @@
},
"js/**",
"libtextsecure/**",
"ts/**/*.js",
"ts/*.js",
"!ts/scripts/**",
"!build",
"!ts/{storybook,test-helpers,test-node,test-mock,test-electron}",
@ -658,17 +658,12 @@
"!js/register.js",
"!fixtures",
"stylesheets/*.css",
"app/*",
"!app/*.ts",
"preload.bundle.js",
"preload.wrapper.js",
"preload.bundle.cache",
"preload_utils.js",
"main.js",
"images/**",
"fonts/**",
"sounds/*",
"build/icons",
"build/icons/png/512x512.png",
"build/icons/win/icon.ico",
"build/available-locales.json",
"build/locale-display-names.json",
"build/country-display-names.json",
@ -701,8 +696,8 @@
"!node_modules/@signalapp/ringrtc/scripts/*",
"node_modules/@signalapp/ringrtc/build/${platform}/*${arch}*.node",
"node_modules/@signalapp/windows-ucv/build/Release/*.node",
"!node_modules/@signalapp/mute-state-change/build/Release/*.mm",
"node_modules/@signalapp/mute-state-change/build/Release/*.node",
"node_modules/@signalapp/mute-state-change/build/Release/*.mm",
"node_modules/@indutny/simple-windows-notifications/prebuilds/${platform}-${arch}/*.node",
"node_modules/@indutny/mac-screen-share/build/Release/*.node",
"node_modules/fs-xattr/build/Release/*.node",
@ -721,8 +716,6 @@
"!node_modules/mp4box/**",
"node_modules/mp4box/package.json",
"node_modules/mp4box/dist/mp4box.all.js",
"!node_modules/@signalapp/quill-cjs/**",
"node_modules/@signalapp/quill-cjs/dist/*.css",
"!node_modules/node_modules/fabric/src/**",
"!node_modules/react-blurhash/docs/**",
"!node_modules/motion/**",

BIN
patches/tsx.patch Normal file

Binary file not shown.

View File

@ -20,6 +20,6 @@
</head>
<body>
<div id="app"></div>
<script type="module" src="bundles/permissions/app.dom.js"></script>
<script type="module" src="bundles/dom/permissions.js"></script>
</body>
</html>

1131
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -6,8 +6,10 @@ import { join } from 'node:path';
import { Script, constants } from 'node:vm';
import { ipcRenderer } from 'electron';
const srcPath = join(__dirname, 'preload.bundle.js');
const cachePath = join(__dirname, 'preload.bundle.cache');
// This file is in root dir, but the bundled file that we run is in
// bundles/preload
const srcPath = join(__dirname, 'main.js');
const cachePath = join(__dirname, '..', '..', 'preload.bundle.cache');
let cachedData: Buffer<ArrayBuffer> | undefined;
try {
@ -40,7 +42,7 @@ const filename = process.env.GENERATE_PRELOAD_CACHE
: srcPath;
const script = new Script(
`(function(require, __dirname){${source.toString()}})`,
`(function(require, __dirname, exports){${source.toString()}})`,
{
filename,
lineOffset: 0,
@ -63,13 +65,13 @@ const fn = script.runInThisContext({
if (process.env.GENERATE_PRELOAD_CACHE) {
// Use hottest cache possible in CI
if (process.env.CI) {
fn(require, __dirname);
fn(require, __dirname, {});
window.startApp();
}
writeFileSync(cachePath, script.createCachedData());
ipcRenderer.send('shutdown');
} else {
fn(require, __dirname);
fn(require, __dirname, {});
window.SignalCI?.setPreloadCacheHit(
cachedData != null && !cachedDataRejected
);

142
rolldown.config.ts Normal file
View File

@ -0,0 +1,142 @@
// Copyright 2026 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { rmSync } from 'node:fs';
import { join } from 'node:path';
import { defineConfig } from 'rolldown';
const external = [
// Native libraries
'@signalapp/libsignal-client',
/^@signalapp\/libsignal-client\/.*/,
'@signalapp/ringrtc',
'@signalapp/sqlcipher',
'@signalapp/mute-state-change',
'@signalapp/windows-ucv',
'@indutny/simple-windows-notifications',
'@indutny/mac-screen-share',
'@napi-rs/canvas',
'electron',
'fs-xattr',
'fsevents',
'mac-screen-capture-permissions',
'sass',
// Things that don't bundle well
'got',
'node-fetch',
'pino',
'proxy-agent',
// Large libraries (3.7mb total)
// See: https://esbuild.github.io/api/#analyze
'emoji-datasource',
'google-libphonenumber',
// Imported, but not used in production builds
'mocha',
// Electron's internal module
'original-fs',
// Uses fast-glob and dynamic requires
'./preload_test.preload.ts',
];
const isProd = process.argv.some(arg => arg === '--minify');
const transform = {
define: {
'process.env.NODE_ENV': isProd ? '"production"' : '"development"',
'process.env.IS_BUNDLED': 'true',
},
};
const nonIsolated = {
// Preloads
'preload/wrapper': 'preload.wrapper.ts',
'preload/main': 'ts/windows/main/preload.preload.ts',
// Workers
'workers/sql': 'ts/sql/mainWorker.node.ts',
'workers/heic': 'ts/workers/heicConverterWorker.node.ts',
};
const contextIsolated = {
// Preload
'preload/about': 'ts/windows/about/preload.preload.ts',
'preload/calldiagnostic': 'ts/windows/calldiagnostic/preload.preload.ts',
'preload/debuglog': 'ts/windows/debuglog/preload.preload.ts',
'preload/permissions': 'ts/windows/permissions/preload.preload.ts',
'preload/screenShare': 'ts/windows/screenShare/preload.preload.ts',
'preload/sticker-creator': 'ts/windows/sticker-creator/preload.preload.ts',
// DOM
'dom/about': 'ts/windows/about/app.dom.tsx',
'dom/calldiagnostic': 'ts/windows/calldiagnostic/app.dom.tsx',
'dom/debuglog': 'ts/windows/debuglog/app.dom.tsx',
'dom/loading': 'ts/windows/loading/start.dom.ts',
'dom/permissions': 'ts/windows/permissions/app.dom.tsx',
'dom/screenShare': 'ts/windows/screenShare/app.dom.tsx',
};
const defaults = {
transform,
external,
output: {
format: 'cjs',
dir: 'bundles',
exports: 'named',
chunkFileNames: 'chunks/[name]-[hash].js',
generatedCode: {
symbols: false,
},
},
};
if (isProd) {
try {
rmSync(join(__dirname, 'bundles'), { recursive: true });
} catch (error) {
if (error.code !== 'ENOENT') {
throw error;
}
}
}
export default defineConfig([
{
...defaults,
input: nonIsolated,
},
// Each context isolated bundle has to be separate from the rest since
// they cannot use `require()`
...Object.entries(contextIsolated).map(([key, value]) => {
return {
...defaults,
external: ['electron'],
platform: 'browser',
input: { [key]: value },
output: {
...defaults.output,
codeSplitting: false,
},
};
}),
{
...defaults,
// Main
input: {
main: 'app/main.main.ts',
config: 'app/config.main.js',
},
// Do not override process.env.NODE_ENV in main process
transform: {
define: {
'process.env.IS_BUNDLED': 'true',
},
},
},
]);

View File

@ -20,6 +20,6 @@
</head>
<body>
<div id="app"></div>
<script type="module" src="bundles/screenShare/app.dom.js"></script>
<script type="module" src="bundles/dom/screenShare.js"></script>
</body>
</html>

View File

@ -9,6 +9,7 @@ const repoRoot = join(__dirname, '..');
const PATTERNS = [
'sticker-creator/dist',
'build/**/*.js',
'app/**/*.js',
'app/*.js',
'ts/**/*.js',
@ -18,6 +19,8 @@ const PATTERNS = [
'preload.bundle.cache',
];
const EXCEPTIONS = new Set(['ts/windows/main/tsx.preload.js']);
async function main() {
const readable = fastGlob.stream(PATTERNS, {
cwd: repoRoot,
@ -26,6 +29,9 @@ async function main() {
const promises = [];
let count = 0;
for await (const entry of readable) {
if (EXCEPTIONS.has(entry)) {
continue;
}
count += 1;
promises.push(rm(entry, { recursive: true, force: true }));
}

View File

@ -1,212 +0,0 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
const esbuild = require('esbuild');
const path = require('node:path');
const fs = require('node:fs');
const fastGlob = require('fast-glob');
const ROOT_DIR = path.join(__dirname, '..');
const BUNDLES_DIR = 'bundles';
const NODE_MODULES_DIR = path.join(ROOT_DIR, 'node_modules');
const watch = process.argv.some(argv => argv === '-w' || argv === '--watch');
const isProd = process.argv.some(argv => argv === '-prod' || argv === '--prod');
const noBundle = process.argv.some(argv => argv === '--no-bundle');
const noScripts = process.argv.some(argv => argv === '--no-scripts');
const nodeDefaults = {
platform: 'node',
target: 'es2023',
// Disabled even in dev because the debugger is broken
sourcemap: false,
logLevel: 'info',
plugins: [
{
name: 'resolve-ts',
setup(b) {
b.onResolve({ filter: /\.js$/ }, args => {
if (!args.path.startsWith('.')) {
return undefined;
}
const targetPath = path.join(args.resolveDir, args.path);
if (targetPath.startsWith(NODE_MODULES_DIR)) {
return undefined;
}
const tsPath = targetPath.replace(/\.js$/, '.ts');
const tsxPath = targetPath.replace(/\.js$/, '.tsx');
if (fs.existsSync(tsPath)) {
return { path: tsPath };
}
if (fs.existsSync(tsxPath)) {
return { path: tsxPath };
}
return undefined;
});
},
},
],
};
const bundleDefaults = {
...nodeDefaults,
define: {
'process.env.NODE_ENV': isProd ? '"production"' : '"development"',
},
bundle: true,
minify: isProd,
external: [
// Native libraries
'@signalapp/libsignal-client',
'@signalapp/libsignal-client/zkgroup',
'@signalapp/ringrtc',
'@signalapp/sqlcipher',
'@signalapp/mute-state-change',
'@indutny/mac-screen-share',
'electron',
'fs-xattr',
'fsevents',
'mac-screen-capture-permissions',
'sass',
// Things that don't bundle well
'got',
'node-fetch',
'pino',
'proxy-agent',
// Large libraries (3.7mb total)
// See: https://esbuild.github.io/api/#analyze
'emoji-datasource',
'fabric',
'google-libphonenumber',
'moment',
'quill',
// Imported, but not used in production builds
'mocha',
// Uses fast-glob and dynamic requires
'./preload_test.preload.js',
],
};
const sandboxedPreloadDefaults = {
...nodeDefaults,
define: {
'process.env.NODE_ENV': isProd ? '"production"' : '"development"',
},
external: ['electron'],
bundle: true,
minify: isProd,
};
const sandboxedBrowserDefaults = {
...sandboxedPreloadDefaults,
chunkNames: 'chunks/[name]-[hash]',
format: 'esm',
outdir: path.join(ROOT_DIR, BUNDLES_DIR),
platform: 'browser',
splitting: true,
};
async function build(config) {
const instance = await esbuild.context(config);
if (watch) {
await instance.watch();
} else {
await instance.rebuild();
await instance.dispose();
}
}
async function main() {
await Promise.all([
!noScripts &&
build({
...nodeDefaults,
format: 'cjs',
mainFields: ['browser', 'main'],
entryPoints: [
'preload.wrapper.ts',
...fastGlob
.sync('{app,ts,build}/**/*.{ts,tsx}', {
onlyFiles: true,
cwd: ROOT_DIR,
})
.filter(file => !file.endsWith('.d.ts')),
],
outdir: path.join(ROOT_DIR),
}),
!noBundle &&
build({
...bundleDefaults,
mainFields: ['browser', 'main'],
entryPoints: [
path.join(ROOT_DIR, 'ts', 'windows', 'main', 'preload.preload.ts'),
],
outfile: path.join(ROOT_DIR, 'preload.bundle.js'),
}),
!noBundle &&
build({
...sandboxedBrowserDefaults,
mainFields: ['browser', 'main'],
entryPoints: [
path.join(ROOT_DIR, 'ts', 'windows', 'about', 'app.dom.tsx'),
path.join(ROOT_DIR, 'ts', 'windows', 'calldiagnostic', 'app.dom.tsx'),
path.join(ROOT_DIR, 'ts', 'windows', 'debuglog', 'app.dom.tsx'),
path.join(ROOT_DIR, 'ts', 'windows', 'loading', 'start.dom.ts'),
path.join(ROOT_DIR, 'ts', 'windows', 'permissions', 'app.dom.tsx'),
path.join(ROOT_DIR, 'ts', 'windows', 'screenShare', 'app.dom.tsx'),
],
}),
!noBundle &&
build({
...sandboxedPreloadDefaults,
mainFields: ['browser', 'main'],
entryPoints: [
path.join(ROOT_DIR, 'ts', 'windows', 'about', 'preload.preload.ts'),
path.join(
ROOT_DIR,
'ts',
'windows',
'calldiagnostic',
'preload.preload.ts'
),
path.join(
ROOT_DIR,
'ts',
'windows',
'debuglog',
'preload.preload.ts'
),
path.join(ROOT_DIR, 'ts', 'windows', 'loading', 'preload.preload.ts'),
path.join(
ROOT_DIR,
'ts',
'windows',
'permissions',
'preload.preload.ts'
),
path.join(
ROOT_DIR,
'ts',
'windows',
'screenShare',
'preload.preload.ts'
),
],
format: 'cjs',
outdir: 'bundles',
}),
]);
}
// oxlint-disable-next-line promise/prefer-await-to-then
main().catch(error => {
console.error(error.stack);
process.exit(1);
});

View File

@ -14,7 +14,11 @@ const { default: packageJson } = require('./packageJson.js');
// Enable this flag to throw an error.
const REQUIRE_SIGNAL_LIB_FILES = Boolean(process.env.REQUIRE_SIGNAL_LIB_FILES);
const { dependencies = {}, optionalDependencies = {} } = packageJson;
const {
dependencies = {},
devDependencies = {},
optionalDependencies = {},
} = packageJson;
const SIGNAL_LIBS = [
'@signalapp/libsignal-client',
@ -117,6 +121,7 @@ async function main() {
const dependencyNames = [
...Object.keys(dependencies),
...Object.keys(devDependencies),
...Object.keys(optionalDependencies),
]
.filter(name => !SKIPPED_DEPENDENCIES.has(name))

View File

@ -4,7 +4,7 @@
const fs = require('node:fs');
const _ = require('lodash');
const { execSync } = require('node:child_process');
const { isAdhoc } = require('../ts/util/version.std.js');
const { isAdhoc } = require('../ts/util/version.std.ts');
const { default: packageJson, version } = require('./packageJson.js');
// You might be wondering why this file is necessary. It comes down to our desire to allow

View File

@ -4,7 +4,7 @@
const fs = require('node:fs');
const _ = require('lodash');
const { isAlpha } = require('../ts/util/version.std.js');
const { isAlpha } = require('../ts/util/version.std.ts');
const { default: packageJson, version } = require('./packageJson.js');
// You might be wondering why this file is necessary. It comes down to our desire to allow

View File

@ -4,7 +4,7 @@
const fs = require('node:fs');
const _ = require('lodash');
const { isAxolotl } = require('../ts/util/version.std.js');
const { isAxolotl } = require('../ts/util/version.std.ts');
const { default: packageJson, version } = require('./packageJson.js');
// You might be wondering why this file is necessary. It comes down to our desire to allow

View File

@ -4,7 +4,7 @@
const fs = require('node:fs');
const _ = require('lodash');
const { isBeta } = require('../ts/util/version.std.js');
const { isBeta } = require('../ts/util/version.std.ts');
const { default: packageJson, version } = require('./packageJson.js');
// You might be wondering why this file is necessary. It comes down to our desire to allow

View File

@ -4,7 +4,7 @@
const fs = require('node:fs');
const _ = require('lodash');
const { isAlpha } = require('../ts/util/version.std.js');
const { isAlpha } = require('../ts/util/version.std.ts');
const { default: packageJson, version } = require('./packageJson.js');
// You might be wondering why this file is necessary. It comes down to our desire to allow

View File

@ -16,7 +16,7 @@ if (release !== 'alpha' && release !== 'axolotl' && release !== 'adhoc') {
process.exit(1);
}
const { generateTaggedVersion } = require('../ts/util/version.std.js');
const { generateTaggedVersion } = require('../ts/util/version.std.ts');
const shortSha = execSync('git rev-parse --short=9 HEAD')
.toString('utf8')

View File

@ -1,53 +0,0 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
const chai = require('chai');
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 { packageJson } = require('../ts/util/packageJson.node.js');
chai.use(chaiAsPromised);
setEnvironment(Environment.Test, true);
// To replicate logic we have on the client side
global.window = {
Date,
performance,
SignalContext: {
i18n: key => `i18n(${key})`,
getPath: () => '/tmp',
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: packageJson.certificateAuthority,
version: packageJson.version,
},
crypto: new Crypto(),
getResolvedMessagesLocale: () => 'en',
getResolvedMessagesLocaleDirection: () => 'ltr',
getHourCyclePreference: () => HourCyclePreference.UnknownPreference,
getPreferredSystemLocales: () => ['en'],
getLocaleOverride: () => null,
},
};
// For ducks/network.getEmptyState()
global.navigator = {};
global.WebSocket = {};
// For GlobalAudioContext.tsx
global.AudioContext = class {};
// oxlint-disable-next-line max-classes-per-file
global.Audio = class {
// oxlint-disable-next-line typescript/no-empty-function
pause() {}
// oxlint-disable-next-line typescript/no-empty-function
addEventListener() {}
};

View File

@ -26,7 +26,7 @@ import {
import type { ChunkSizeChoice } from '@signalapp/libsignal-client/dist/incremental_mac.js';
import { isAbsolute } from 'node:path';
import { createLogger } from './logging/log.std.js';
import { createLogger } from './logging/log.std.ts';
import {
HashType,
CipherType,
@ -36,24 +36,24 @@ import {
DIGEST_LENGTH,
ATTACHMENT_MAC_LENGTH,
AES_KEY_LENGTH,
} from './types/Crypto.std.js';
import { constantTimeEqual } from './Crypto.node.js';
import { createName, getRelativePath } from './util/attachmentPath.node.js';
import { appendPaddingStream } from './util/logPadding.node.js';
import { prependStream } from './util/prependStream.node.js';
import { appendMacStream } from './util/appendMacStream.node.js';
import { finalStream } from './util/finalStream.node.js';
import { getMacAndUpdateHmac } from './util/getMacAndUpdateHmac.node.js';
import { trimPadding } from './util/trimPadding.node.js';
import { assertDev, strictAssert } from './util/assert.std.js';
import * as Errors from './types/errors.std.js';
import { isNotNil } from './util/isNotNil.std.js';
import { missingCaseError } from './util/missingCaseError.std.js';
import { getEnvironment, Environment } from './environment.std.js';
import { isNotEmpty, toBase64, toHex } from './Bytes.std.js';
import { decipherWithAesKey } from './util/decipherWithAesKey.node.js';
import { getAttachmentCiphertextSize } from './util/AttachmentCrypto.std.js';
import { MediaTier } from './types/AttachmentDownload.std.js';
} from './types/Crypto.std.ts';
import { constantTimeEqual } from './Crypto.node.ts';
import { createName, getRelativePath } from './util/attachmentPath.node.ts';
import { appendPaddingStream } from './util/logPadding.node.ts';
import { prependStream } from './util/prependStream.node.ts';
import { appendMacStream } from './util/appendMacStream.node.ts';
import { finalStream } from './util/finalStream.node.ts';
import { getMacAndUpdateHmac } from './util/getMacAndUpdateHmac.node.ts';
import { trimPadding } from './util/trimPadding.node.ts';
import { assertDev, strictAssert } from './util/assert.std.ts';
import * as Errors from './types/errors.std.ts';
import { isNotNil } from './util/isNotNil.std.ts';
import { missingCaseError } from './util/missingCaseError.std.ts';
import { getEnvironment, Environment } from './environment.std.ts';
import { isNotEmpty, toBase64, toHex } from './Bytes.std.ts';
import { decipherWithAesKey } from './util/decipherWithAesKey.node.ts';
import { getAttachmentCiphertextSize } from './util/AttachmentCrypto.std.ts';
import { MediaTier } from './types/AttachmentDownload.std.ts';
const { ensureFile } = fsExtra;

View File

@ -1,7 +1,7 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { Bytes } from './context/Bytes.std.js';
import { Bytes } from './context/Bytes.std.ts';
const bytes = globalThis.window?.SignalContext?.bytes || new Bytes();

View File

@ -4,23 +4,23 @@
import { format } from 'node:util';
import { ipcRenderer } from 'electron';
import type { IPCResponse as ChallengeResponseType } from './challenge.dom.js';
import type { IPCResponse as ChallengeResponseType } from './challenge.dom.ts';
import type { MessageAttributesType } from './model-types.d.ts';
import { createLogger } from './logging/log.std.js';
import { explodePromise } from './util/explodePromise.std.js';
import { AccessType, ipcInvoke } from './sql/channels.preload.js';
import { backupsService } from './services/backups/index.preload.js';
import { notificationService } from './services/notifications.preload.js';
import { challengeHandler } from './services/challengeHandler.preload.js';
import { AttachmentBackupManager } from './jobs/AttachmentBackupManager.preload.js';
import { migrateAllMessages } from './messages/migrateMessageData.preload.js';
import { SECOND } from './util/durations/index.std.js';
import { isSignalRoute } from './util/signalRoutes.std.js';
import { strictAssert } from './util/assert.std.js';
import { MessageModel } from './models/messages.preload.js';
import type { SocketStatuses } from './textsecure/SocketManager.preload.js';
import { itemStorage } from './textsecure/Storage.preload.js';
import { BackupLevel } from './services/backups/types.std.js';
import { createLogger } from './logging/log.std.ts';
import { explodePromise } from './util/explodePromise.std.ts';
import { AccessType, ipcInvoke } from './sql/channels.preload.ts';
import { backupsService } from './services/backups/index.preload.ts';
import { notificationService } from './services/notifications.preload.ts';
import { challengeHandler } from './services/challengeHandler.preload.ts';
import { AttachmentBackupManager } from './jobs/AttachmentBackupManager.preload.ts';
import { migrateAllMessages } from './messages/migrateMessageData.preload.ts';
import { SECOND } from './util/durations/index.std.ts';
import { isSignalRoute } from './util/signalRoutes.std.ts';
import { strictAssert } from './util/assert.std.ts';
import { MessageModel } from './models/messages.preload.ts';
import type { SocketStatuses } from './textsecure/SocketManager.preload.ts';
import { itemStorage } from './textsecure/Storage.preload.ts';
import { BackupLevel } from './services/backups/types.std.ts';
const log = createLogger('CI');

View File

@ -3,23 +3,23 @@
import { v4 as uuid } from 'uuid';
import { incrementMessageCounter } from '../util/incrementMessageCounter.preload.js';
import { ReadStatus } from '../messages/MessageReadStatus.std.js';
import { SendStatus } from '../messages/MessageSendState.std.js';
import { DataWriter } from '../sql/Client.preload.js';
import { BodyRange } from '../types/BodyRange.std.js';
import { CURRENT_SCHEMA_VERSION } from '../types/Message2.preload.js';
import { strictAssert } from '../util/assert.std.js';
import { MINUTE } from '../util/durations/index.std.js';
import { isOlderThan } from '../util/timestamp.std.js';
import { sleep } from '../util/sleep.std.js';
import { stats } from '../util/benchmark/stats.std.js';
import type { StatsType } from '../util/benchmark/stats.std.js';
import { incrementMessageCounter } from '../util/incrementMessageCounter.preload.ts';
import { ReadStatus } from '../messages/MessageReadStatus.std.ts';
import { SendStatus } from '../messages/MessageSendState.std.ts';
import { DataWriter } from '../sql/Client.preload.ts';
import { BodyRange } from '../types/BodyRange.std.ts';
import { CURRENT_SCHEMA_VERSION } from '../types/Message2.preload.ts';
import { strictAssert } from '../util/assert.std.ts';
import { MINUTE } from '../util/durations/index.std.ts';
import { isOlderThan } from '../util/timestamp.std.ts';
import { sleep } from '../util/sleep.std.ts';
import { stats } from '../util/benchmark/stats.std.ts';
import type { StatsType } from '../util/benchmark/stats.std.ts';
import type { MessageAttributesType } from '../model-types.d.ts';
import { createLogger } from '../logging/log.std.js';
import { postSaveUpdates } from '../util/cleanup.preload.js';
import { itemStorage } from '../textsecure/Storage.preload.js';
import { getSelectedConversationId } from '../state/selectors/nav.std.js';
import { createLogger } from '../logging/log.std.ts';
import { postSaveUpdates } from '../util/cleanup.preload.ts';
import { itemStorage } from '../textsecure/Storage.preload.ts';
import { getSelectedConversationId } from '../state/selectors/nav.std.ts';
const log = createLogger('benchmarkConversationOpen');

View File

@ -5,53 +5,53 @@ import lodash from 'lodash';
import PQueue from 'p-queue';
import { v4 as generateUuid } from 'uuid';
import { DataReader, DataWriter } from './sql/Client.preload.js';
import { createLogger } from './logging/log.std.js';
import * as Errors from './types/errors.std.js';
import { getAuthorId } from './messages/sources.preload.js';
import { maybeDeriveGroupV2Id } from './groups.preload.js';
import { assertDev, strictAssert } from './util/assert.std.js';
import { drop } from './util/drop.std.js';
import { DataReader, DataWriter } from './sql/Client.preload.ts';
import { createLogger } from './logging/log.std.ts';
import * as Errors from './types/errors.std.ts';
import { getAuthorId } from './messages/sources.preload.ts';
import { maybeDeriveGroupV2Id } from './groups.preload.ts';
import { assertDev, strictAssert } from './util/assert.std.ts';
import { drop } from './util/drop.std.ts';
import {
isDirectConversation,
isGroup,
isGroupV1,
isGroupV2,
} from './util/whatTypeOfConversation.dom.js';
} from './util/whatTypeOfConversation.dom.ts';
import {
doesAttachmentExist,
maybeDeleteAttachmentFile,
} from './util/migrations.preload.js';
} from './util/migrations.preload.ts';
import {
isServiceIdString,
normalizePni,
normalizeServiceId,
} from './types/ServiceId.std.js';
import { normalizeAci } from './util/normalizeAci.std.js';
import { sleep } from './util/sleep.std.js';
import { isNotNil } from './util/isNotNil.std.js';
import { MINUTE, SECOND } from './util/durations/index.std.js';
import { getServiceIdsForE164s } from './util/getServiceIdsForE164s.dom.js';
} from './types/ServiceId.std.ts';
import { normalizeAci } from './util/normalizeAci.std.ts';
import { sleep } from './util/sleep.std.ts';
import { isNotNil } from './util/isNotNil.std.ts';
import { MINUTE, SECOND } from './util/durations/index.std.ts';
import { getServiceIdsForE164s } from './util/getServiceIdsForE164s.dom.ts';
import {
SIGNAL_ACI,
SIGNAL_AVATAR_PATH,
} from './types/SignalConversation.std.js';
import { getTitleNoDefault } from './util/getTitle.preload.js';
import * as StorageService from './services/storage.preload.js';
import { cdsLookup } from './textsecure/WebAPI.preload.js';
import type { ConversationPropsForUnreadStats } from './util/countUnreadStats.std.js';
import { countAllConversationsUnreadStats } from './util/countUnreadStats.std.js';
import { isTestOrMockEnvironment } from './environment.std.js';
import { isConversationAccepted } from './util/isConversationAccepted.preload.js';
import { areWePending } from './util/groupMembershipUtils.preload.js';
import { conversationJobQueue } from './jobs/conversationJobQueue.preload.js';
import { createBatcher } from './util/batcher.std.js';
import { validateConversation } from './util/validateConversation.dom.js';
import { ConversationModel } from './models/conversations.preload.js';
import { INITIAL_EXPIRE_TIMER_VERSION } from './util/expirationTimer.std.js';
import { missingCaseError } from './util/missingCaseError.std.js';
import { removeConversation } from './util/Conversation.preload.js';
import { signalProtocolStore } from './SignalProtocolStore.preload.js';
} from './types/SignalConversation.std.ts';
import { getTitleNoDefault } from './util/getTitle.preload.ts';
import * as StorageService from './services/storage.preload.ts';
import { cdsLookup } from './textsecure/WebAPI.preload.ts';
import type { ConversationPropsForUnreadStats } from './util/countUnreadStats.std.ts';
import { countAllConversationsUnreadStats } from './util/countUnreadStats.std.ts';
import { isTestOrMockEnvironment } from './environment.std.ts';
import { isConversationAccepted } from './util/isConversationAccepted.preload.ts';
import { areWePending } from './util/groupMembershipUtils.preload.ts';
import { conversationJobQueue } from './jobs/conversationJobQueue.preload.ts';
import { createBatcher } from './util/batcher.std.ts';
import { validateConversation } from './util/validateConversation.dom.ts';
import { ConversationModel } from './models/conversations.preload.ts';
import { INITIAL_EXPIRE_TIMER_VERSION } from './util/expirationTimer.std.ts';
import { missingCaseError } from './util/missingCaseError.std.ts';
import { removeConversation } from './util/Conversation.preload.ts';
import { signalProtocolStore } from './SignalProtocolStore.preload.ts';
import type {
ConversationAttributesType,
@ -63,10 +63,10 @@ import type {
ServiceIdString,
AciString,
PniString,
} from './types/ServiceId.std.js';
import { itemStorage } from './textsecure/Storage.preload.js';
import { getSelectedConversationId } from './state/selectors/nav.std.js';
import { unencodeNumber } from './util/unencodeNumber.std.js';
} from './types/ServiceId.std.ts';
import { itemStorage } from './textsecure/Storage.preload.ts';
import { getSelectedConversationId } from './state/selectors/nav.std.ts';
import { unencodeNumber } from './util/unencodeNumber.std.ts';
const { debounce, pick, uniq, without } = lodash;

View File

@ -6,19 +6,19 @@ import { Aci, Pni, hkdf } from '@signalapp/libsignal-client';
import type { PublicKey, PrivateKey } from '@signalapp/libsignal-client';
import { AccountEntropyPool } from '@signalapp/libsignal-client/dist/AccountKeys.js';
import * as Bytes from './Bytes.std.js';
import { Crypto } from './context/Crypto.node.js';
import { calculateAgreement, generateKeyPair } from './Curve.node.js';
import { HashType, CipherType } from './types/Crypto.std.js';
import { AVATAR_COLOR_COUNT, AvatarColors } from './types/Colors.std.js';
import { ProfileDecryptError } from './types/errors.std.js';
import { getBytesSubarray } from './util/uuidToBytes.std.js';
import { logPadSize } from './util/logPadSize.std.js';
import { Environment, getEnvironment } from './environment.std.js';
import { toWebSafeBase64 } from './util/webSafeBase64.std.js';
import * as Bytes from './Bytes.std.ts';
import { Crypto } from './context/Crypto.node.ts';
import { calculateAgreement, generateKeyPair } from './Curve.node.ts';
import { HashType, CipherType } from './types/Crypto.std.ts';
import { AVATAR_COLOR_COUNT, AvatarColors } from './types/Colors.std.ts';
import { ProfileDecryptError } from './types/errors.std.ts';
import { getBytesSubarray } from './util/uuidToBytes.std.ts';
import { logPadSize } from './util/logPadSize.std.ts';
import { Environment, getEnvironment } from './environment.std.ts';
import { toWebSafeBase64 } from './util/webSafeBase64.std.ts';
import type { AciString, PniString } from './types/ServiceId.std.js';
import type { AvatarColorType } from './types/Colors.std.js';
import type { AciString, PniString } from './types/ServiceId.std.ts';
import type { AvatarColorType } from './types/Colors.std.ts';
const { sample } = lodash;

View File

@ -4,14 +4,14 @@
import * as client from '@signalapp/libsignal-client';
import type { KyberPreKeyRecord } from '@signalapp/libsignal-client';
import * as Bytes from './Bytes.std.js';
import { constantTimeEqual } from './Crypto.node.js';
import * as Bytes from './Bytes.std.ts';
import { constantTimeEqual } from './Crypto.node.ts';
import type {
KeyPairType,
CompatPreKeyType,
CompatSignedPreKeyType,
} from './textsecure/Types.d.ts';
import { createLogger } from './logging/log.std.js';
import { createLogger } from './logging/log.std.ts';
const log = createLogger('Curve');

View File

@ -2,8 +2,8 @@
// SPDX-License-Identifier: AGPL-3.0-only
import EventEmitter from 'node:events';
import { createLogger } from './logging/log.std.js';
import { clearTimeoutIfNecessary } from './util/clearTimeoutIfNecessary.std.js';
import { createLogger } from './logging/log.std.ts';
import { clearTimeoutIfNecessary } from './util/clearTimeoutIfNecessary.std.ts';
const log = createLogger('IdleDetector');

View File

@ -26,13 +26,13 @@ import {
SignedPreKeyStore,
} from '@signalapp/libsignal-client';
import type { Store as KeyTransparencyStoreInterface } from '@signalapp/libsignal-client/dist/net/KeyTransparency.d.ts';
import { Address } from './types/Address.std.js';
import { QualifiedAddress } from './types/QualifiedAddress.std.js';
import type { ServiceIdString } from './types/ServiceId.std.js';
import { normalizeServiceId } from './types/ServiceId.std.js';
import type { SignalProtocolStore } from './SignalProtocolStore.preload.js';
import { Address } from './types/Address.std.ts';
import { QualifiedAddress } from './types/QualifiedAddress.std.ts';
import type { ServiceIdString } from './types/ServiceId.std.ts';
import { normalizeServiceId } from './types/ServiceId.std.ts';
import type { SignalProtocolStore } from './SignalProtocolStore.preload.ts';
import type { Zone } from './util/Zone.std.js';
import type { Zone } from './util/Zone.std.ts';
const { isNumber } = lodash;

View File

@ -6,10 +6,10 @@ import {
REMOTE_CONFIG_KEYS as KeysExpectedByLibsignalNet,
} from '@signalapp/libsignal-client/dist/net.js';
import { isProduction } from './util/version.std.js';
import * as RemoteConfig from './RemoteConfig.dom.js';
import type { AddPrefix, ArrayValues } from './types/Util.std.js';
import { createLogger } from './logging/log.std.js';
import { isProduction } from './util/version.std.ts';
import * as RemoteConfig from './RemoteConfig.dom.ts';
import type { AddPrefix, ArrayValues } from './types/Util.std.ts';
import { createLogger } from './logging/log.std.ts';
const log = createLogger('LibsignalNetRemoteConfig');

View File

@ -5,24 +5,24 @@ import lodash from 'lodash';
import semver from 'semver';
import type { REMOTE_CONFIG_KEYS as KeysExpectedByLibsignalNet } from '@signalapp/libsignal-client/dist/net.js';
import type { getConfig } from './textsecure/WebAPI.preload.js';
import { createLogger } from './logging/log.std.js';
import type { AciString } from './types/ServiceId.std.js';
import { parseIntOrThrow } from './util/parseIntOrThrow.std.js';
import { HOUR } from './util/durations/index.std.js';
import * as Bytes from './Bytes.std.js';
import { uuidToBytes } from './util/uuidToBytes.std.js';
import { HashType } from './types/Crypto.std.js';
import { getCountryCode } from './types/PhoneNumber.std.js';
import { parseRemoteClientExpiration } from './util/parseRemoteClientExpiration.dom.js';
import type { getConfig } from './textsecure/WebAPI.preload.ts';
import { createLogger } from './logging/log.std.ts';
import type { AciString } from './types/ServiceId.std.ts';
import { parseIntOrThrow } from './util/parseIntOrThrow.std.ts';
import { HOUR } from './util/durations/index.std.ts';
import * as Bytes from './Bytes.std.ts';
import { uuidToBytes } from './util/uuidToBytes.std.ts';
import { HashType } from './types/Crypto.std.ts';
import { getCountryCode } from './types/PhoneNumber.std.ts';
import { parseRemoteClientExpiration } from './util/parseRemoteClientExpiration.dom.ts';
import type { StorageInterface } from './types/Storage.d.ts';
import { ToastType } from './types/Toast.dom.js';
import { assertDev, strictAssert } from './util/assert.std.js';
import { ToastType } from './types/Toast.dom.tsx';
import { assertDev, strictAssert } from './util/assert.std.ts';
import type {
ArrayValues,
AssertSameMembers,
StripPrefix,
} from './types/Util.std.js';
} from './types/Util.std.ts';
const { get, throttle } = lodash;

View File

@ -20,15 +20,15 @@ import {
SignedPreKeyRecord,
} from '@signalapp/libsignal-client';
import { DataReader, DataWriter } from './sql/Client.preload.js';
import type { ItemType, KyberPreKeyTripleType } from './sql/Interface.std.js';
import * as Bytes from './Bytes.std.js';
import { constantTimeEqual, sha256 } from './Crypto.node.js';
import { assertDev, strictAssert } from './util/assert.std.js';
import { isNotNil } from './util/isNotNil.std.js';
import { drop } from './util/drop.std.js';
import { Zone } from './util/Zone.std.js';
import { isMoreRecentThan } from './util/timestamp.std.js';
import { DataReader, DataWriter } from './sql/Client.preload.ts';
import type { ItemType, KyberPreKeyTripleType } from './sql/Interface.std.ts';
import * as Bytes from './Bytes.std.ts';
import { constantTimeEqual, sha256 } from './Crypto.node.ts';
import { assertDev, strictAssert } from './util/assert.std.ts';
import { isNotNil } from './util/isNotNil.std.ts';
import { drop } from './util/drop.std.ts';
import { Zone } from './util/Zone.std.ts';
import { isMoreRecentThan } from './util/timestamp.std.ts';
import type {
DeviceType,
IdentityKeyType,
@ -54,26 +54,26 @@ import type {
ServiceIdString,
PniString,
AciString,
} from './types/ServiceId.std.js';
} from './types/ServiceId.std.ts';
import {
isServiceIdString,
ServiceIdKind,
fromAciObject,
} from './types/ServiceId.std.js';
import type { Address } from './types/Address.std.js';
import type { QualifiedAddressStringType } from './types/QualifiedAddress.std.js';
import { QualifiedAddress } from './types/QualifiedAddress.std.js';
import { createLogger } from './logging/log.std.js';
import * as Errors from './types/errors.std.js';
import { MINUTE } from './util/durations/index.std.js';
} from './types/ServiceId.std.ts';
import type { Address } from './types/Address.std.ts';
import type { QualifiedAddressStringType } from './types/QualifiedAddress.std.ts';
import { QualifiedAddress } from './types/QualifiedAddress.std.ts';
import { createLogger } from './logging/log.std.ts';
import * as Errors from './types/errors.std.ts';
import { MINUTE } from './util/durations/index.std.ts';
import {
KYBER_KEY_ID_KEY,
SIGNED_PRE_KEY_ID_KEY,
} from './textsecure/AccountManager.preload.js';
import { formatGroups, groupWhile } from './util/groupWhile.std.js';
import { parseUnknown } from './util/schemas.std.js';
import { wrappingAdd24 } from './util/wrappingAdd.std.js';
import { itemStorage } from './textsecure/Storage.preload.js';
} from './textsecure/AccountManager.preload.ts';
import { formatGroups, groupWhile } from './util/groupWhile.std.ts';
import { parseUnknown } from './util/schemas.std.ts';
import { wrappingAdd24 } from './util/wrappingAdd.std.ts';
import { itemStorage } from './textsecure/Storage.preload.ts';
const { omit } = lodash;

View File

@ -3,7 +3,7 @@
const { timers } = window.SignalContext;
export type { Timeout } from './context/Timers.node.js';
export type { Timeout } from './context/Timers.node.ts';
export function setTimeout(
...args: Parameters<typeof timers.setTimeout>

View File

@ -4,9 +4,9 @@ import type { ReactNode } from 'react';
import React, { useId } from 'react';
import type { Meta } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { AriaClickable } from './AriaClickable.dom.js';
import { AxoButton } from './AxoButton.dom.js';
import { tw } from './tw.dom.js';
import { AriaClickable } from './AriaClickable.dom.tsx';
import { AxoButton } from './AxoButton.dom.tsx';
import { tw } from './tw.dom.tsx';
export default {
title: 'Axo/AriaClickable',

View File

@ -11,13 +11,13 @@ import React, {
import type { ReactNode, MouseEvent, FC, ForwardedRef } from 'react';
import { useLayoutEffect, mergeRefs } from '@react-aria/utils';
import { computeAccessibleName } from 'dom-accessibility-api';
import { tw } from './tw.dom.js';
import { assert } from './_internal/assert.std.js';
import { tw } from './tw.dom.tsx';
import { assert } from './_internal/assert.std.tsx';
import {
createStrictContext,
useStrictContext,
} from './_internal/StrictContext.dom.js';
import { isTestOrMockEnvironment } from '../environment.std.js';
} from './_internal/StrictContext.dom.tsx';
import { isTestOrMockEnvironment } from '../environment.std.ts';
const Namespace = 'AriaClickable';

View File

@ -4,8 +4,8 @@
import type { Meta } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import React, { useState } from 'react';
import { AxoAlertDialog } from './AxoAlertDialog.dom.js';
import { AxoButton } from './AxoButton.dom.js';
import { AxoAlertDialog } from './AxoAlertDialog.dom.tsx';
import { AxoButton } from './AxoButton.dom.tsx';
export default {
title: 'Axo/AxoAlertDialog',

View File

@ -4,12 +4,12 @@
import { AlertDialog } from 'radix-ui';
import type { FC, MouseEvent, ReactNode } from 'react';
import React, { memo } from 'react';
import { AxoButton } from './AxoButton.dom.js';
import { tw } from './tw.dom.js';
import { AxoBaseDialog } from './_internal/AxoBaseDialog.dom.js';
import { AxoScrollArea } from './AxoScrollArea.dom.js';
import type { AxoSymbol } from './AxoSymbol.dom.js';
import { FlexWrapDetector } from './_internal/FlexWrapDetector.dom.js';
import { AxoButton } from './AxoButton.dom.tsx';
import { tw } from './tw.dom.tsx';
import { AxoBaseDialog } from './_internal/AxoBaseDialog.dom.tsx';
import { AxoScrollArea } from './AxoScrollArea.dom.tsx';
import type { AxoSymbol } from './AxoSymbol.dom.tsx';
import { FlexWrapDetector } from './_internal/FlexWrapDetector.dom.tsx';
const Namespace = 'AxoAlertDialog';

View File

@ -4,11 +4,11 @@ import type { Meta } from '@storybook/react';
import type { JSX, ReactNode } from 'react';
import React from 'react';
import { action } from '@storybook/addon-actions';
import { AxoAvatar } from './AxoAvatar.dom.js';
import { tw } from './tw.dom.js';
import { BADGES_FIXTURE } from './_internal/storybook-fixtures.std.js';
import { _getAllAxoSymbolIconNames } from './_internal/AxoSymbolDefs.generated.std.js';
import { AxoTokens } from './AxoTokens.std.js';
import { AxoAvatar } from './AxoAvatar.dom.tsx';
import { tw } from './tw.dom.tsx';
import { BADGES_FIXTURE } from './_internal/storybook-fixtures.std.tsx';
import { _getAllAxoSymbolIconNames } from './_internal/AxoSymbolDefs.generated.std.ts';
import { AxoTokens } from './AxoTokens.std.ts';
export default {
title: 'Axo/AxoAvatar',

View File

@ -9,15 +9,15 @@ import type {
ReactNode,
} from 'react';
import React, { memo, useCallback, useMemo, useRef, useState } from 'react';
import { AxoSymbol } from './AxoSymbol.dom.js';
import type { TailwindStyles } from './tw.dom.js';
import { tw } from './tw.dom.js';
import { AxoSymbol } from './AxoSymbol.dom.tsx';
import type { TailwindStyles } from './tw.dom.tsx';
import { tw } from './tw.dom.tsx';
import {
createStrictContext,
useStrictContext,
} from './_internal/StrictContext.dom.js';
import { assert } from './_internal/assert.std.js';
import { AxoTokens } from './AxoTokens.std.js';
} from './_internal/StrictContext.dom.tsx';
import { assert } from './_internal/assert.std.tsx';
import { AxoTokens } from './AxoTokens.std.ts';
const Namespace = 'AxoAvatar';

View File

@ -2,8 +2,8 @@
// SPDX-License-Identifier: AGPL-3.0-only
import type { Meta } from '@storybook/react';
import React from 'react';
import { ExperimentalAxoBadge } from './AxoBadge.dom.js';
import { tw } from './tw.dom.js';
import { ExperimentalAxoBadge } from './AxoBadge.dom.tsx';
import { tw } from './tw.dom.tsx';
export default {
title: 'Axo/AriaBadge (Experimental)',

View File

@ -2,10 +2,10 @@
// SPDX-License-Identifier: AGPL-3.0-only
import type { FC } from 'react';
import React, { memo, useMemo } from 'react';
import { AxoSymbol } from './AxoSymbol.dom.js';
import type { TailwindStyles } from './tw.dom.js';
import { tw } from './tw.dom.js';
import { unreachable } from './_internal/assert.std.js';
import { AxoSymbol } from './AxoSymbol.dom.tsx';
import type { TailwindStyles } from './tw.dom.tsx';
import { tw } from './tw.dom.tsx';
import { unreachable } from './_internal/assert.std.tsx';
const Namespace = 'AxoBadge';

View File

@ -8,9 +8,9 @@ import {
_getAllAxoButtonVariants,
_getAllAxoButtonSizes,
AxoButton,
} from './AxoButton.dom.js';
import { tw } from './tw.dom.js';
import { AxoSwitch } from './AxoSwitch.dom.js';
} from './AxoButton.dom.tsx';
import { tw } from './tw.dom.tsx';
import { AxoSwitch } from './AxoSwitch.dom.tsx';
export default {
title: 'Axo/AxoButton',

Some files were not shown because too many files have changed in this diff Show More