chore: upgrade eslint and prettier (#2376)

* chore: upgrade eslint and prettier

* chore: add restrict-template-expressions
This commit is contained in:
Mo
2023-07-27 14:36:05 -05:00
committed by GitHub
parent acc41edb02
commit 4a29e2a24c
1283 changed files with 4416 additions and 5131 deletions

View File

@@ -28,7 +28,7 @@
"devDependencies": {
"@types/jest": "^29.2.3",
"@typescript-eslint/eslint-plugin": "*",
"eslint": "^8.27.0",
"eslint": "*",
"eslint-plugin-prettier": "*",
"jest": "^29.3.1",
"ts-jest": "^29.0.3",

View File

@@ -19,7 +19,10 @@ import { UserUpdateResponse } from '../../Response/User/UserUpdateResponse'
export class UserApiService implements UserApiServiceInterface {
private operationsInProgress: Map<UserApiOperations, boolean>
constructor(private userServer: UserServerInterface, private userRequestServer: UserRequestServerInterface) {
constructor(
private userServer: UserServerInterface,
private userRequestServer: UserRequestServerInterface,
) {
this.operationsInProgress = new Map()
}

View File

@@ -28,7 +28,11 @@ export class HttpService implements HttpServiceInterface {
private requestHandler: RequestHandlerInterface
constructor(private environment: Environment, private appVersion: string, private snjsVersion: string) {
constructor(
private environment: Environment,
private appVersion: string,
private snjsVersion: string,
) {
this.requestHandler = new FetchRequestHandler(this.snjsVersion, this.appVersion, this.environment)
}

View File

@@ -24,7 +24,7 @@
"babel-loader": "^9.1.0",
"copy-webpack-plugin": "11.0.0",
"eslint": "*",
"eslint-config-prettier": "^8.5.0",
"eslint-config-prettier": "^8.9.0",
"ts-loader": "^9.4.2",
"typescript": "*",
"web-ext": "^7.5.0",

View File

@@ -9,7 +9,7 @@ export const RuntimeMessageTypes = {
CaptureVisibleTab: 'capture-visible-tab',
} as const
export type RuntimeMessageType = typeof RuntimeMessageTypes[keyof typeof RuntimeMessageTypes]
export type RuntimeMessageType = (typeof RuntimeMessageTypes)[keyof typeof RuntimeMessageTypes]
type MessagesWithClipPayload = typeof RuntimeMessageTypes.OpenPopupWithSelection

View File

@@ -1,4 +1,5 @@
dist/
app/dist/
test/data/tmp/
CHANGELOG.md
CHANGELOG.md
app/grantLinuxPasswordsAccess.html

View File

@@ -1,95 +1,97 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Standard Notes</title>
<link rel="stylesheet" media="all" href="web/app.css" />
<link rel="stylesheet" media="all" href="stylesheets/renderer.css" />
</head>
<body class="main-ui">
<div class="sk-modal">
<div class="challenge-modal sk-modal-content" style="margin: 2rem">
<div class="sn-component">
<div class="sk-panel">
<div class="sk-panel-header">
<div class="sk-panel-header-title capitalize">Password service access</div>
</div>
<div class="sk-panel-content" style="padding-bottom: 2rem">
<h1 class="sk-h1">Choose how you want Standard Notes to store your account keys</h1>
<p class="sk-p">
Standard Notes can either use your operating system's password manager or its own local storage
facility.
</p>
<p class="sk-p">
<strong>Standard Notes currently does not have access to your system password service.</strong>
If you grant it access, you must quit the app for the change to come into effect.
</p>
<div class="sk-panel-row">
<div class="sk-button-group">
<button class="sk-button info" id="quit-button">
<div class="sk-label capitalize">Use password service (quit)</div>
</button>
<button class="sk-button neutral capitalize" id="use-storage-button">
<div class="sk-label">Use local storage (continue)</div>
</button>
</div>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Standard Notes</title>
<link rel="stylesheet" media="all" href="web/app.css" />
<link rel="stylesheet" media="all" href="stylesheets/renderer.css" />
</head>
<body class="main-ui">
<div class="sk-modal">
<div class="challenge-modal sk-modal-content" style="margin: 2rem">
<div class="sn-component">
<div class="sk-panel">
<div class="sk-panel-header">
<div class="sk-panel-header-title capitalize">Password service access</div>
</div>
<div class="sk-panel-content" style="padding-bottom: 2rem">
<h1 class="sk-h1">Choose how you want Standard Notes to store your account keys</h1>
<p class="sk-p">
Standard Notes can either use your operating system's password manager or its own local storage
facility.
</p>
<p class="sk-p">
<strong>Standard Notes currently does not have access to your system password service.</strong>
If you grant it access, you must quit the app for the change to come into effect.
</p>
<div class="sk-panel-row">
<div class="sk-button-group">
<button class="sk-button info" id="quit-button">
<div class="sk-label capitalize">Use password service (quit)</div>
</button>
<button class="sk-button neutral capitalize" id="use-storage-button">
<div class="sk-label">Use local storage (continue)</div>
</button>
</div>
<div class="sk-panel-row"></div>
<a class="sk-a capitalize" id="learn-more">Learn more</a>
<div style="display: none" id="more-info">
<div class="sk-panel-section">
<h1 class="sk-h1">What's the difference?</h1>
<p class="sk-p">
Using local storage, your account keys may be more easily accessible by third-party programs, unlike
in your password manager which has additional protections built-in.
</p>
<p class="sk-p">
In either cases, the strongest way to protect your account keys is to use a strong passcode, which
will be used to encrypt your keys and prevent any software or operating system from reading them.
<strong> If you plan on setting a passcode, you can safely use local storage. </strong>
</p>
<div class="sk-panel-row"></div>
<h2 class="sk-h2">Granting Standard Notes access to your system password service</h2>
<p class="sk-p">
Note that
<strong>
granting access to your system password service will allow Standard Notes to read, write, and
delete <em>any</em> of your saved passwords.
</strong>
Standard Notes will never use this privilege to do anything more than reading and writing to its own
entry.
</p>
<ol>
<li class="sk-li">Quit Standard Notes</li>
<li class="sk-li">Open your software store (Ubuntu Software Center/Snap Store)</li>
<li class="sk-li">In your installed apps list, click on Standard Notes</li>
<li class="sk-li">Look for a <em>Permissions</em> button</li>
<li class="sk-li">
Make sure the permission associated with reading and writing passwords is checked
</li>
<li class="sk-li">Open Standard Notes again</li>
</ol>
<h2 class="sk-h2">
Granting Standard Notes access to your system password service from the command line
</h2>
<p class="sk-p">
Run the following command:<br />
<code>snap connect standard-notes:password-manager-service</code>
</p>
</div>
<p>
<em>
Note: Password Service may also be referred to as keyring, saved passwords, stored passwords,
password manager, passwords, or secrets, depending on your Linux configuration.
</em>
</div>
<div class="sk-panel-row"></div>
<a class="sk-a capitalize" id="learn-more">Learn more</a>
<div style="display: none" id="more-info">
<div class="sk-panel-section">
<h1 class="sk-h1">What's the difference?</h1>
<p class="sk-p">
Using local storage, your account keys may be more easily accessible by third-party programs, unlike
in your password manager which has additional protections built-in.
</p>
<p class="sk-p">
In either cases, the strongest way to protect your account keys is to use a strong passcode, which
will be used to encrypt your keys and prevent any software or operating system from reading them.
<strong> If you plan on setting a passcode, you can safely use local storage. </strong>
</p>
<div class="sk-panel-row"></div>
<h2 class="sk-h2">Granting Standard Notes access to your system password service</h2>
<p class="sk-p">
Note that
<strong>
granting access to your system password service will allow Standard Notes to read, write, and
delete <em>any</em> of your saved passwords.
</strong>
Standard Notes will never use this privilege to do anything more than reading and writing to its own
entry.
</p>
<ol>
<li class="sk-li">Quit Standard Notes</li>
<li class="sk-li">Open your software store (Ubuntu Software Center/Snap Store)</li>
<li class="sk-li">In your installed apps list, click on Standard Notes</li>
<li class="sk-li">Look for a <em>Permissions</em> button</li>
<li class="sk-li">
Make sure the permission associated with reading and writing passwords is checked
</li>
<li class="sk-li">Open Standard Notes again</li>
</ol>
<h2 class="sk-h2">
Granting Standard Notes access to your system password service from the command line
</h2>
<p class="sk-p">
Run the following command:<br />
<code>snap connect standard-notes:password-manager-service</code>
</p>
</div>
<p>
<em>
Note: Password Service may also be referred to as keyring, saved passwords, stored passwords,
password manager, passwords, or secrets, depending on your Linux configuration.
</em>
</p>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
</div>
</body>
</html>

View File

@@ -72,6 +72,7 @@ export class FilesManager implements FilesManagerInterface {
if (!stat.isDirectory()) {
throw new Error('Tried to create a directory where a file of the same ' + `name already exists: ${dirPath}`)
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
if (error.code === FileErrorCodes.FileDoesNotExist) {
/**
@@ -83,6 +84,7 @@ export class FilesManager implements FilesManagerInterface {
/** Now that its parent(s) exist, create the directory */
try {
await fs.promises.mkdir(dirPath)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
if (error.code === FileErrorCodes.FileAlreadyExists) {
/**
@@ -257,6 +259,7 @@ export class FilesManager implements FilesManagerInterface {
try {
await this.ensureDirectoryExists(path.dirname(filepath))
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
return tryReject(error)
}
@@ -299,6 +302,7 @@ export class FilesManager implements FilesManagerInterface {
try {
await fs.promises.unlink(filePath)
break
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
if (error.code === FileErrorCodes.OperationNotPermitted || error.code === FileErrorCodes.DeviceIsBusy) {
await new Promise((resolve) => setTimeout(resolve, 300))

View File

@@ -4,7 +4,12 @@ import { downloadData } from './FileNetworking'
export class FileDownloader {
writeStream: WriteStream
constructor(private chunkSizes: number[], private valetToken: string, private url: string, filePath: string) {
constructor(
private chunkSizes: number[],
private valetToken: string,
private url: string,
filePath: string,
) {
this.writeStream = createWriteStream(filePath, { flags: 'a' })
}

View File

@@ -33,7 +33,10 @@ export class HomeServerManager implements HomeServerManagerInterface {
private homeServer?: TempHomeServerInterface
constructor(private webContents: WebContents, private filesManager: FilesManagerInterface) {}
constructor(
private webContents: WebContents,
private filesManager: FilesManagerInterface,
) {}
async getHomeServerUrl(): Promise<string | undefined> {
const homeServerConfiguration = await this.getHomeServerConfigurationObject()

View File

@@ -17,9 +17,7 @@ import { TrayManager } from '../TrayManager'
import { autoUpdatingAvailable } from '../Types/Constants'
import { isLinux, isMac } from '../Types/Platforms'
import { checkForUpdate, openChangelog, showUpdateInstallationDialog } from '../UpdateManager'
import { handleTestMessage } from '../Utils/Testing'
import { isDev, isTesting } from '../Utils/Utils'
import { MessageType } from './../../../../test/TestIpcMessage'
import { isDev } from '../Utils/Utils'
import { SpellcheckerManager } from './../SpellcheckerManager'
import { MenuManagerInterface } from './MenuManagerInterface'
@@ -123,42 +121,7 @@ export function createMenuManager({
}): MenuManagerInterface {
let menu: Menu
if (isTesting()) {
// eslint-disable-next-line no-var
var hasReloaded = false
// eslint-disable-next-line no-var
var hasReloadedTimeout: any
handleTestMessage(MessageType.AppMenuItems, () =>
menu.items.map((item) => ({
label: item.label,
role: item.role,
submenu: {
items: item.submenu?.items?.map((subItem) => ({
id: subItem.id,
label: subItem.label,
})),
},
})),
)
handleTestMessage(MessageType.ClickLanguage, (code) => {
menu.getMenuItemById(MessageType.ClickLanguage + code)!.click()
})
handleTestMessage(MessageType.HasReloadedMenu, () => hasReloaded)
}
function reload() {
if (isTesting()) {
// eslint-disable-next-line block-scoped-var
hasReloaded = true
// eslint-disable-next-line block-scoped-var
clearTimeout(hasReloadedTimeout)
// eslint-disable-next-line block-scoped-var
hasReloadedTimeout = setTimeout(() => {
// eslint-disable-next-line block-scoped-var
hasReloaded = false
}, 300)
}
menu = Menu.buildFromTemplate([
...(isMac() ? [macAppMenu(app.name)] : []),
editMenu(spellcheckerManager, reload),
@@ -270,7 +233,10 @@ function macAppMenu(appName: string): MenuItemConstructorOptions {
}
}
function editMenu(spellcheckerManager: SpellcheckerManager | undefined, reload: () => any): MenuItemConstructorOptions {
function editMenu(
spellcheckerManager: SpellcheckerManager | undefined,
reload: () => void,
): MenuItemConstructorOptions {
if (isDev()) {
/** Check for invalid state */
if (!isMac() && spellcheckerManager === undefined) {
@@ -323,13 +289,13 @@ function macSpeechMenu(): MenuItemConstructorOptions {
}
}
function spellcheckerMenu(spellcheckerManager: SpellcheckerManager, reload: () => any): MenuItemConstructorOptions {
function spellcheckerMenu(spellcheckerManager: SpellcheckerManager, reload: () => void): MenuItemConstructorOptions {
return {
id: MenuId.SpellcheckerLanguages,
label: str().spellcheckerLanguages,
submenu: spellcheckerManager.languages().map(
({ name, code, enabled }): MenuItemConstructorOptions => ({
...(isTesting() ? { id: MessageType.ClickLanguage + code } : {}),
...{},
label: name,
type: MenuItemTypes.CheckBox,
checked: enabled,
@@ -346,7 +312,7 @@ function spellcheckerMenu(spellcheckerManager: SpellcheckerManager, reload: () =
}
}
function viewMenu(window: Electron.BrowserWindow, store: Store, reload: () => any): MenuItemConstructorOptions {
function viewMenu(window: Electron.BrowserWindow, store: Store, reload: () => void): MenuItemConstructorOptions {
return {
label: str().view,
submenu: [
@@ -375,7 +341,7 @@ function viewMenu(window: Electron.BrowserWindow, store: Store, reload: () => an
}
}
function menuBarOptions(window: Electron.BrowserWindow, store: Store, reload: () => any) {
function menuBarOptions(window: Electron.BrowserWindow, store: Store, reload: () => void) {
const useSystemMenuBar = store.get(StoreKeys.UseSystemMenuBar)
let isMenuBarVisible = store.get(StoreKeys.MenuBarVisible)
window.setMenuBarVisibility(isMenuBarVisible)
@@ -406,7 +372,7 @@ function menuBarOptions(window: Electron.BrowserWindow, store: Store, reload: ()
]
}
function windowMenu(store: Store, trayManager: TrayManager, reload: () => any): MenuItemConstructorOptions {
function windowMenu(store: Store, trayManager: TrayManager, reload: () => void): MenuItemConstructorOptions {
return {
role: Roles.Window,
submenu: [
@@ -446,7 +412,7 @@ function macWindowItems(): MenuItemConstructorOptions[] {
]
}
function minimizeToTrayItem(store: Store, trayManager: TrayManager, reload: () => any) {
function minimizeToTrayItem(store: Store, trayManager: TrayManager, reload: () => void) {
const minimizeToTray = trayManager.shouldMinimizeToTray()
return {
label: str().minimizeToTrayOnClose,

View File

@@ -48,7 +48,10 @@ class MappingFileHandler {
return new MappingFileHandler(mapping, filesManager)
}
constructor(private mapping: MappingFile, private filesManager: FilesManagerInterface) {}
constructor(
private mapping: MappingFile,
private filesManager: FilesManagerInterface,
) {}
get = (componendId: string) => {
return this.mapping[componendId]

View File

@@ -5,6 +5,7 @@ import { StoreData, StoreKeys } from './StoreKeys'
import { logError } from './Store'
import { FileErrorCodes } from '../File/FileErrorCodes'
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function createSanitizedStoreData(data: any = {}): StoreData {
return {
[StoreKeys.MenuBarVisible]: ensureIsBoolean(data[StoreKeys.MenuBarVisible], true),
@@ -27,6 +28,8 @@ export function createSanitizedStoreData(data: any = {}): StoreData {
[StoreKeys.LegacyFileBackupsLocation]: data[StoreKeys.LegacyFileBackupsLocation],
}
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function sanitizeZoomFactor(factor?: any): number {
if (typeof factor === 'number' && factor > 0) {
return factor
@@ -67,7 +70,9 @@ export function parseDataFile(filePath: string) {
const fileData = fs.readFileSync(filePath)
const userData = JSON.parse(fileData.toString())
return createSanitizedStoreData(userData)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
// eslint-disable-next-line no-console
console.log('Error reading store file', error)
if (error.code !== FileErrorCodes.FileDoesNotExist) {
logError(error)

View File

@@ -65,7 +65,7 @@
"electron-builder": "23.6.0",
"electron-notarize": "^1.2.1",
"eslint": "*",
"eslint-config-prettier": "^8.5.0",
"eslint-config-prettier": "^8.9.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^6.1.1",
@@ -79,7 +79,7 @@
"ts-node": "^10.9.1",
"typescript": "*",
"webpack": "*",
"webpack-merge": "^5.8.0"
"webpack-merge": "*"
},
"build": {
"appId": "org.standardnotes.standardnotes",

View File

@@ -29,35 +29,35 @@ export const V002Algorithm = Object.freeze({
EncryptionIvLength: 128,
})
export enum V003Algorithm {
SaltSeedLength = 256,
PbkdfCost = 110000,
PbkdfOutputLength = 768,
EncryptionKeyLength = 256,
EncryptionIvLength = 128,
}
export const V003Algorithm = Object.freeze({
SaltSeedLength: 256,
PbkdfCost: 110000,
PbkdfOutputLength: 768,
EncryptionKeyLength: 256,
EncryptionIvLength: 128,
})
export enum V004Algorithm {
ArgonSaltSeedLength = 256,
ArgonSaltLength = 128,
ArgonIterations = 5,
ArgonMemLimit = 67108864,
ArgonOutputKeyBytes = 64,
export const V004Algorithm = Object.freeze({
ArgonSaltSeedLength: 256,
ArgonSaltLength: 128,
ArgonIterations: 5,
ArgonMemLimit: 67108864,
ArgonOutputKeyBytes: 64,
EncryptionKeyLength = 256,
EncryptionNonceLength = 192,
EncryptionKeyLength: 256,
EncryptionNonceLength: 192,
AsymmetricEncryptionNonceLength = 192,
AsymmetricEncryptionNonceLength: 192,
MasterKeyEncryptionKeyPairSubKeyNumber = 1,
MasterKeyEncryptionKeyPairSubKeyContext = 'sn-pkc-e',
MasterKeyEncryptionKeyPairSubKeyBytes = SodiumConstant.crypto_box_SEEDBYTES,
MasterKeyEncryptionKeyPairSubKeyNumber: 1,
MasterKeyEncryptionKeyPairSubKeyContext: 'sn-pkc-e',
MasterKeyEncryptionKeyPairSubKeyBytes: SodiumConstant.crypto_box_SEEDBYTES,
MasterKeySigningKeyPairSubKeyNumber = 2,
MasterKeySigningKeyPairSubKeyContext = 'sn-pkc-s',
MasterKeySigningKeyPairSubKeyBytes = SodiumConstant.crypto_sign_SEEDBYTES,
MasterKeySigningKeyPairSubKeyNumber: 2,
MasterKeySigningKeyPairSubKeyContext: 'sn-pkc-s',
MasterKeySigningKeyPairSubKeyBytes: SodiumConstant.crypto_sign_SEEDBYTES,
PayloadKeyHashingKeySubKeyNumber = 1,
PayloadKeyHashingKeySubKeyContext = 'sn-sym-h',
PayloadKeyHashingKeySubKeyBytes = SodiumConstant.crypto_generichash_KEYBYTES,
}
PayloadKeyHashingKeySubKeyNumber: 1,
PayloadKeyHashingKeySubKeyContext: 'sn-sym-h',
PayloadKeyHashingKeySubKeyBytes: SodiumConstant.crypto_generichash_KEYBYTES,
})

View File

@@ -16,6 +16,6 @@ export function createOperatorForVersion(version: ProtocolVersion, crypto: PureC
} else if (version === ProtocolVersion.V004) {
return new SNProtocolOperator004(crypto)
} else {
throw Error(`Unable to find operator for version ${version}`)
throw Error(`Unable to find operator for version ${version as string}`)
}
}

View File

@@ -1,5 +1,8 @@
export class StandardException {
constructor(public readonly message: string, log = false) {
constructor(
public readonly message: string,
log = false,
) {
if (log) {
console.error('StandardException raised: ', message)
}

View File

@@ -36,6 +36,6 @@
"eslint-plugin-prettier": "*",
"jest": "^29.3.1",
"ts-jest": "^29.0.3",
"typescript": "4.9.3"
"typescript": "*"
}
}

View File

@@ -3,6 +3,7 @@ import { saveFile } from '../utils'
export class ClassicFileSaver {
public loggingEnabled = false
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private log(...args: any[]): void {
if (!this.loggingEnabled) {
return

View File

@@ -8,6 +8,7 @@ export class StreamingFileSaver {
constructor(private name: string) {}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private log(...args: any[]): void {
if (!this.loggingEnabled) {
return

View File

@@ -5,8 +5,12 @@ export class ByteChunker {
private bytes = new Uint8Array()
private index = 1
constructor(private minimumChunkSize: number, private onChunk: OnChunkCallbackNoProgress) {}
constructor(
private minimumChunkSize: number,
private onChunk: OnChunkCallbackNoProgress,
) {}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private log(...args: any[]): void {
if (!this.loggingEnabled) {
return

View File

@@ -1,4 +1,4 @@
import { PureCryptoInterface, StreamDecryptor, SodiumConstant } from '@standardnotes/sncrypto-common'
import { PureCryptoInterface, StreamDecryptor, SodiumTag } from '@standardnotes/sncrypto-common'
import { FileContent } from '@standardnotes/models'
export class FileDecryptor {
@@ -22,7 +22,7 @@ export class FileDecryptor {
return undefined
}
const isFinal = result.tag === SodiumConstant.CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL
const isFinal = result.tag === SodiumTag.CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL
return { decryptedBytes: result.message, isFinalChunk: isFinal }
}

View File

@@ -1,5 +1,5 @@
import { FileContent } from '@standardnotes/models'
import { PureCryptoInterface, StreamEncryptor, SodiumConstant } from '@standardnotes/sncrypto-common'
import { PureCryptoInterface, StreamEncryptor, SodiumTag } from '@standardnotes/sncrypto-common'
import { FileEncryptor } from './FileEncryptor'
describe('file encryptor', () => {
@@ -46,7 +46,7 @@ describe('file encryptor', () => {
expect.any(Object),
decryptedBytes,
file.remoteIdentifier,
SodiumConstant.CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL,
SodiumTag.CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL,
)
})

View File

@@ -1,5 +1,5 @@
import { FileContent } from '@standardnotes/models'
import { PureCryptoInterface, StreamEncryptor, SodiumConstant } from '@standardnotes/sncrypto-common'
import { PureCryptoInterface, StreamEncryptor, SodiumTag } from '@standardnotes/sncrypto-common'
export class FileEncryptor {
private stream!: StreamEncryptor
@@ -20,7 +20,7 @@ export class FileEncryptor {
throw new Error('FileEncryptor must call initializeHeader first')
}
const tag = isFinalChunk ? SodiumConstant.CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL : undefined
const tag = isFinalChunk ? SodiumTag.CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL : undefined
const encryptedBytes = this.crypto.xchacha20StreamEncryptorPush(
this.stream,

View File

@@ -45,13 +45,13 @@
"@typescript-eslint/parser": "*",
"babel-jest": "^29.3.1",
"detox": "^20.0.3",
"eslint": "^8.27.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint": "*",
"eslint-plugin-prettier": "*",
"get-yarn-workspaces": "^1.0.2",
"metro-react-native-babel-preset": "^0.76.7",
"npm-check-updates": "*",
"pod-install": "^0.1.38",
"prettier": "^2.7.1",
"prettier": "*",
"prettier-plugin-organize-imports": "^3.2.0",
"react": "18.2.0",
"react-native": "0.72.3",

View File

@@ -2,7 +2,10 @@ import { DatabaseItemMetadata, isNotUndefined, TransferPayload } from '@standard
import { FlashKeyValueStore } from './FlashKeyValueStore'
export class DatabaseMetadata {
constructor(private identifier: string, private flashStorage: FlashKeyValueStore) {}
constructor(
private identifier: string,
private flashStorage: FlashKeyValueStore,
) {}
runMigration(payloads: TransferPayload[]) {
const metadataItems = this.setMetadataForPayloads(payloads)

View File

@@ -423,7 +423,7 @@ export class MobileDevice implements MobileDeviceInterface {
failOnCancel: false,
})
} catch (error) {
this.consoleLog(`${error}`)
this.consoleLog(error)
} finally {
if (downloadedTempFilePath) {
void this.deleteFileAtPathIfExists(downloadedTempFilePath)
@@ -456,7 +456,7 @@ export class MobileDevice implements MobileDeviceInterface {
await writeFile(path, base64.replace(/data.*base64,/, ''), 'base64')
return path
} catch (error) {
this.consoleLog(`${error}`)
this.consoleLog(error)
}
}

View File

@@ -38,7 +38,7 @@ export function FillItemContent<C extends ItemContent = ItemContent>(content: Pa
}
if (!content.appData[DefaultAppDomain][AppDataField.UserModifiedDate]) {
content.appData[DefaultAppDomain][AppDataField.UserModifiedDate] = `${new Date()}`
content.appData[DefaultAppDomain][AppDataField.UserModifiedDate] = new Date().toString()
}
return content as C

View File

@@ -7,13 +7,14 @@ import { LegacyAnonymousReference } from './LegacyAnonymousReference'
import { LegacyTagToNoteReference } from './LegacyTagToNoteReference'
import { Reference } from './Reference'
import { TagToParentTagReference } from './TagToParentTagReference'
import { AnonymousReference } from './AnonymousReference'
export const isLegacyAnonymousReference = (x: ContentReference): x is LegacyAnonymousReference => {
return (x as any).reference_type === undefined
return (x as AnonymousReference).reference_type === undefined
}
export const isReference = (x: ContentReference): x is Reference => {
return (x as any).reference_type !== undefined
return (x as AnonymousReference).reference_type !== undefined
}
export const isLegacyTagToNoteReference = (

View File

@@ -24,7 +24,10 @@ export class ItemCounter implements SNIndex {
private displayOptions?: AnyDisplayOptions
private vaultDisplayOptions?: VaultDisplayOptions
constructor(private collection: ItemCollection, public observers: TagItemCountChangeObserver[] = []) {}
constructor(
private collection: ItemCollection,
public observers: TagItemCountChangeObserver[] = [],
) {}
public addCountChangeObserver(observer: TagItemCountChangeObserver): () => void {
this.observers.push(observer)

View File

@@ -3,7 +3,10 @@ import { ReadonlyItemCollection } from '../Types'
import { CriteriaValidatorInterface } from './CriteriaValidatorInterface'
export class CollectionCriteriaValidator implements CriteriaValidatorInterface {
constructor(private collection: ReadonlyItemCollection, private element: ItemInterface) {}
constructor(
private collection: ReadonlyItemCollection,
private element: ItemInterface,
) {}
public passes(): boolean {
return this.collection.has(this.element.uuid)

View File

@@ -3,7 +3,10 @@ import { DisplayControllerCustomFilter } from '../Types'
import { CriteriaValidatorInterface } from './CriteriaValidatorInterface'
export class CustomFilterCriteriaValidator implements CriteriaValidatorInterface {
constructor(private customFilter: DisplayControllerCustomFilter, private element: DecryptedItemInterface) {}
constructor(
private customFilter: DisplayControllerCustomFilter,
private element: DecryptedItemInterface,
) {}
public passes(): boolean {
return this.customFilter(this.element)

View File

@@ -3,7 +3,10 @@ import { DecryptedItemInterface } from '../../../Abstract/Item'
import { KeySystemIdentifier } from '../../../Syncable/KeySystemRootKey/KeySystemIdentifier'
export class ExcludeVaultsCriteriaValidator implements CriteriaValidatorInterface {
constructor(private excludeVaults: KeySystemIdentifier[], private element: DecryptedItemInterface) {}
constructor(
private excludeVaults: KeySystemIdentifier[],
private element: DecryptedItemInterface,
) {}
public passes(): boolean {
const doesElementBelongToExcludedVault = this.excludeVaults.some(

View File

@@ -3,7 +3,10 @@ import { DecryptedItemInterface } from '../../../Abstract/Item'
import { KeySystemIdentifier } from '../../../Syncable/KeySystemRootKey/KeySystemIdentifier'
export class ExclusiveVaultCriteriaValidator implements CriteriaValidatorInterface {
constructor(private exclusiveVault: KeySystemIdentifier, private element: DecryptedItemInterface) {}
constructor(
private exclusiveVault: KeySystemIdentifier,
private element: DecryptedItemInterface,
) {}
public passes(): boolean {
return this.element.key_system_identifier === this.exclusiveVault

View File

@@ -2,7 +2,10 @@ import { DecryptedItemInterface } from './../../../Abstract/Item/Interfaces/Decr
import { CriteriaValidatorInterface } from './CriteriaValidatorInterface'
export class HiddenContentCriteriaValidator implements CriteriaValidatorInterface {
constructor(private hiddenContentTypes: string[], private element: DecryptedItemInterface) {}
constructor(
private hiddenContentTypes: string[],
private element: DecryptedItemInterface,
) {}
public passes(): boolean {
return !this.hiddenContentTypes.includes(this.element.content_type)

View File

@@ -81,7 +81,7 @@ export function predicateFromDSLString<T extends PredicateTarget>(dsl: string):
const predicateJson = predicateDSLArrayToJsonPredicate(components as RawPredicateInArrayForm)
return predicateFromJson(predicateJson)
} catch (e) {
throw Error(`Invalid smart view syntax ${e}`)
throw Error(`Invalid smart view syntax ${JSON.stringify(e)}`)
}
}

View File

@@ -1,7 +1,10 @@
import { PredicateTarget, PredicateInterface, PredicateJsonForm, StringKey } from './Interface'
export class IncludesPredicate<T extends PredicateTarget> implements PredicateInterface<T> {
constructor(private readonly keypath: StringKey<T>, public readonly predicate: PredicateInterface<T>) {}
constructor(
private readonly keypath: StringKey<T>,
public readonly predicate: PredicateInterface<T>,
) {}
matchesItem(item: T): boolean {
const keyPathComponents = this.keypath.split('.') as StringKey<T>[]

View File

@@ -13,7 +13,7 @@ export interface PredicateJsonForm {
}
export const AllPredicateCompoundOperators = ['and', 'or'] as const
export type PredicateCompoundOperator = typeof AllPredicateCompoundOperators[number]
export type PredicateCompoundOperator = (typeof AllPredicateCompoundOperators)[number]
export const AllNonCompoundPredicateOperators = [
'!=',
@@ -31,7 +31,7 @@ export const AllNonCompoundPredicateOperators = [
export const AllPredicateOperators = [...AllPredicateCompoundOperators, ...AllNonCompoundPredicateOperators] as const
export type PredicateOperator = typeof AllPredicateOperators[number]
export type PredicateOperator = (typeof AllPredicateOperators)[number]
export type SureValue = number | number[] | string[] | string | Date | boolean | false | ''

View File

@@ -1,7 +1,11 @@
import { HttpErrorResponse, getErrorFromErrorResponse } from '../Http'
export class ClientDisplayableError {
constructor(public text: string, public title?: string, public tag?: string) {
constructor(
public text: string,
public title?: string,
public tag?: string,
) {
console.error('Client Displayable Error:', text, title || '', tag || '')
}

View File

@@ -33,7 +33,7 @@
"@types/node": "^20.2.5",
"@typescript-eslint/eslint-plugin": "*",
"@typescript-eslint/parser": "*",
"eslint": "^8.27.0",
"eslint": "*",
"eslint-plugin-prettier": "*",
"jest": "^29.3.1",
"ts-jest": "^29.0.3",

View File

@@ -3,7 +3,10 @@ import { MutatorClientInterface } from '../../Mutator/MutatorClientInterface'
import { TrustedContactInterface, TrustedContactMutator } from '@standardnotes/models'
export class EditContact {
constructor(private mutator: MutatorClientInterface, private sync: SyncServiceInterface) {}
constructor(
private mutator: MutatorClientInterface,
private sync: SyncServiceInterface,
) {}
async execute(
contact: TrustedContactInterface,

View File

@@ -4,7 +4,10 @@ import { ReuploadAllInvites } from '../../VaultInvite/UseCase/ReuploadAllInvites
import { ResendAllMessages } from '../../AsymmetricMessage/UseCase/ResendAllMessages'
export class HandleKeyPairChange implements UseCaseInterface<void> {
constructor(private reuploadAllInvites: ReuploadAllInvites, private resendAllMessages: ResendAllMessages) {}
constructor(
private reuploadAllInvites: ReuploadAllInvites,
private resendAllMessages: ResendAllMessages,
) {}
async execute(dto: {
newKeys: {

View File

@@ -10,7 +10,10 @@ import { EncryptMessage } from '../../Encryption/UseCase/Asymmetric/EncryptMessa
import { Result, UseCaseInterface } from '@standardnotes/domain-core'
export class SendOwnContactChangeMessage implements UseCaseInterface<AsymmetricMessageServerHash> {
constructor(private encryptMessage: EncryptMessage, private sendMessage: SendMessage) {}
constructor(
private encryptMessage: EncryptMessage,
private sendMessage: SendMessage,
) {}
async execute(params: {
senderOldKeyPair: PkcKeyPair

View File

@@ -7,7 +7,10 @@ import { ContentTypesUsingRootKeyEncryption } from '@standardnotes/models'
* When the user root key changes, we must re-encrypt all relevant items with this new root key (by simply re-syncing).
*/
export class ReencryptTypeAItems implements UseCaseInterface<void> {
constructor(private items: ItemManagerInterface, private mutator: MutatorClientInterface) {}
constructor(
private items: ItemManagerInterface,
private mutator: MutatorClientInterface,
) {}
public async execute(): Promise<Result<void>> {
const items = this.items.getItems(ContentTypesUsingRootKeyEncryption())

View File

@@ -31,7 +31,7 @@ export class IntegrityService
const integrityCheckResponse = await this.integrityApi.checkIntegrity(this.payloadManager.integrityPayloads)
if (isErrorResponse(integrityCheckResponse)) {
this.log(`Could not obtain integrity check: ${integrityCheckResponse.data.error}`)
this.log(`Could not obtain integrity check: ${integrityCheckResponse.data.error?.message}`)
return
}
@@ -52,7 +52,7 @@ export class IntegrityService
) {
this.log(
`Could not obtain item for integrity adjustments: ${
isErrorResponse(serverItemResponse) ? serverItemResponse.data.error : ''
isErrorResponse(serverItemResponse) ? serverItemResponse.data.error?.message : ''
}`,
)

View File

@@ -129,7 +129,7 @@ export class RootKeyManager extends AbstractService<RootKeyManagerEvent> {
case KeyMode.RootKeyPlusWrapper:
return true
default:
throw Error(`Unhandled keyMode value '${this.keyMode}'.`)
throw Error('Unhandled keyMode value.')
}
}
@@ -369,7 +369,7 @@ export class RootKeyManager extends AbstractService<RootKeyManagerEvent> {
/** Root key is simply changing, mode stays the same */
/** this.keyMode = this.keyMode; */
} else {
throw Error(`Unhandled key mode for setNewRootKey ${this.keyMode}`)
throw Error('Unhandled key mode for setNewRootKey')
}
this.setRootKeyInstance(key)
@@ -396,7 +396,7 @@ export class RootKeyManager extends AbstractService<RootKeyManagerEvent> {
} else if (this.keyMode === KeyMode.RootKeyNone) {
return undefined
} else {
throw `Unhandled key mode for getRootKeyParams ${this.keyMode}`
throw 'Unhandled key mode for getRootKeyParams'
}
}

View File

@@ -20,7 +20,7 @@ export class ConvertToSharedVault {
const serverResult = await this.sharedVaultServer.createSharedVault()
if (isErrorResponse(serverResult)) {
return ClientDisplayableError.FromString(`Failed to create shared vault ${serverResult}`)
return ClientDisplayableError.FromString(`Failed to create shared vault ${JSON.stringify(serverResult)}`)
}
const serverVaultHash = serverResult.data.sharedVault

View File

@@ -17,7 +17,7 @@ export class DeleteSharedVault {
})
if (isErrorResponse(response)) {
return ClientDisplayableError.FromString(`Failed to delete vault ${response}`)
return ClientDisplayableError.FromString(`Failed to delete vault ${JSON.stringify(response)}`)
}
await this.deleteVault.execute(params.sharedVault)

View File

@@ -4,7 +4,10 @@ import { SharedVaultListingInterface } from '@standardnotes/models'
import { GetSharedVaults } from './GetSharedVaults'
export class GetOwnedSharedVaults implements SyncUseCaseInterface<SharedVaultListingInterface[]> {
constructor(private getSharedVaults: GetSharedVaults, private isVaultOwnwer: IsVaultOwner) {}
constructor(
private getSharedVaults: GetSharedVaults,
private isVaultOwnwer: IsVaultOwner,
) {}
execute(dto: { userUuid: string }): Result<SharedVaultListingInterface[]> {
const sharedVaults = this.getSharedVaults.execute().getValue()

View File

@@ -99,7 +99,7 @@ export class NotifyVaultUsersOfKeyRotation implements UseCaseInterface<void> {
})
if (isErrorResponse(response)) {
return Result.fail(`Failed to delete existing invites ${response}`)
return Result.fail(`Failed to delete existing invites ${JSON.stringify(response)}`)
}
return Result.ok()
@@ -109,7 +109,7 @@ export class NotifyVaultUsersOfKeyRotation implements UseCaseInterface<void> {
const response = await this.inviteServer.getOutboundUserInvites()
if (isErrorResponse(response)) {
return Result.fail(`Failed to get outbound user invites ${response}`)
return Result.fail(`Failed to get outbound user invites ${JSON.stringify(response)}`)
}
const invites = response.data.invites

View File

@@ -4,7 +4,10 @@ import { AnyItemInterface } from '@standardnotes/models'
import { Uuids } from '@standardnotes/utils'
export class DiscardItemsLocally {
constructor(private readonly items: ItemManagerInterface, private readonly storage: StorageServiceInterface) {}
constructor(
private readonly items: ItemManagerInterface,
private readonly storage: StorageServiceInterface,
) {}
async execute(items: AnyItemInterface[]): Promise<void> {
this.items.removeItemsFromMemory(items)

View File

@@ -66,7 +66,7 @@ export class ReuploadAllInvites implements UseCaseInterface<void> {
const response = await this.inviteServer.getOutboundUserInvites()
if (isErrorResponse(response)) {
return Result.fail(`Failed to get outbound user invites ${response}`)
return Result.fail(`Failed to get outbound user invites ${JSON.stringify(response)}`)
}
const invites = response.data.invites
@@ -78,7 +78,7 @@ export class ReuploadAllInvites implements UseCaseInterface<void> {
const response = await this.inviteServer.deleteAllOutboundInvites()
if (isErrorResponse(response)) {
return Result.fail(`Failed to delete existing invites ${response}`)
return Result.fail(`Failed to delete existing invites ${JSON.stringify(response)}`)
}
return Result.ok()

View File

@@ -64,7 +64,7 @@ export class ReuploadVaultInvites implements UseCaseInterface<void> {
const response = await this.inviteServer.getOutboundUserInvites()
if (isErrorResponse(response)) {
return Result.fail(`Failed to get outbound user invites ${response}`)
return Result.fail(`Failed to get outbound user invites ${JSON.stringify(response)}`)
}
const invites = response.data.invites
@@ -78,7 +78,7 @@ export class ReuploadVaultInvites implements UseCaseInterface<void> {
})
if (isErrorResponse(response)) {
return Result.fail(`Failed to delete existing invites ${response}`)
return Result.fail(`Failed to delete existing invites ${JSON.stringify(response)}`)
}
return Result.ok()

View File

@@ -109,7 +109,7 @@ export class VaultInviteService
const response = await this.invitesServer.getInboundUserInvites()
if (isErrorResponse(response)) {
return ClientDisplayableError.FromString(`Failed to get inbound user invites ${response}`)
return ClientDisplayableError.FromString(`Failed to get inbound user invites ${JSON.stringify(response)}`)
}
this.pendingInvites = {}
@@ -125,7 +125,7 @@ export class VaultInviteService
const response = await this.invitesServer.getOutboundUserInvites()
if (isErrorResponse(response)) {
return ClientDisplayableError.FromString(`Failed to get outbound user invites ${response}`)
return ClientDisplayableError.FromString(`Failed to get outbound user invites ${JSON.stringify(response)}`)
}
if (sharedVault) {
@@ -220,7 +220,7 @@ export class VaultInviteService
})
if (isErrorResponse(response)) {
return ClientDisplayableError.FromString(`Failed to delete invite ${response}`)
return ClientDisplayableError.FromString(`Failed to delete invite ${JSON.stringify(response)}`)
}
delete this.pendingInvites[invite.uuid]

View File

@@ -5,7 +5,10 @@ import { FindContact } from '../../Contacts/UseCase/FindContact'
import { Result, UseCaseInterface } from '@standardnotes/domain-core'
export class GetVaultContacts implements UseCaseInterface<TrustedContactInterface[]> {
constructor(private findContact: FindContact, private getVaultUsers: GetVaultUsers) {}
constructor(
private findContact: FindContact,
private getVaultUsers: GetVaultUsers,
) {}
async execute(dto: { sharedVaultUuid: string; readFromCache: boolean }): Promise<Result<TrustedContactInterface[]>> {
const users = await this.getVaultUsers.execute({

View File

@@ -4,7 +4,10 @@ import { SharedVaultUsersServerInterface } from '@standardnotes/api'
import { Result, UseCaseInterface } from '@standardnotes/domain-core'
export class GetVaultUsers implements UseCaseInterface<SharedVaultUserServerHash[]> {
constructor(private vaultUsersServer: SharedVaultUsersServerInterface, private cache: VaultUserCache) {}
constructor(
private vaultUsersServer: SharedVaultUsersServerInterface,
private cache: VaultUserCache,
) {}
async execute(params: {
sharedVaultUuid: string

View File

@@ -27,7 +27,7 @@
"@typescript-eslint/eslint-plugin": "*",
"@typescript-eslint/parser": "*",
"eslint": "*",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-prettier": "*",
"typescript": "*"
},
"dependencies": {

View File

@@ -1,8 +1,7 @@
import { PkcKeyPair } from '../Types'
import { PkcKeyPair, SodiumTag } from '../Types'
import { Base64String } from '../Types/Base64String'
import { Base64URLSafeString } from '../Types/Base64URLSafeString'
import { HexString } from '../Types/HexString'
import { SodiumConstant } from '../Types/SodiumConstant'
import { StreamDecryptor } from '../Types/StreamDecryptor'
import { StreamEncryptor } from '../Types/StreamEncryptor'
import { Utf8String } from '../Types/Utf8String'
@@ -122,7 +121,7 @@ export interface PureCryptoInterface {
encryptor: StreamEncryptor,
plainBuffer: Uint8Array,
assocData: Utf8String,
tag?: SodiumConstant,
tag?: SodiumTag,
): Uint8Array
xchacha20StreamInitDecryptor(header: Base64String, key: HexString): StreamDecryptor
@@ -131,7 +130,7 @@ export interface PureCryptoInterface {
decryptor: StreamDecryptor,
encryptedBuffer: Uint8Array,
assocData: Utf8String,
): { message: Uint8Array; tag: SodiumConstant } | false
): { message: Uint8Array; tag: SodiumTag } | false
sodiumCryptoBoxEasyEncrypt(
message: Utf8String,

View File

@@ -1,14 +1,10 @@
export enum SodiumConstant {
CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_STATEBYTES = 52,
CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES = 17,
CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES = 24,
CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES = 32,
CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PUSH = 0,
CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PULL = 1,
CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY = 2,
CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL = 3,
CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX = 0x3fffffff80,
crypto_box_SEEDBYTES = 32,
crypto_sign_SEEDBYTES = 32,
crypto_generichash_KEYBYTES = 32,
export const SodiumConstant = {
CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_STATEBYTES: 52,
CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES: 17,
CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES: 24,
CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES: 32,
CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX: 0x3fffffff80,
crypto_box_SEEDBYTES: 32,
crypto_sign_SEEDBYTES: 32,
crypto_generichash_KEYBYTES: 32,
}

View File

@@ -0,0 +1,6 @@
export enum SodiumTag {
CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PUSH = 0,
CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PULL = 1,
CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY = 2,
CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL = 3,
}

View File

@@ -1,6 +1,6 @@
import { SodiumConstant } from './SodiumConstant'
import { SodiumTag } from './SodiumTag'
export type StreamDecryptorResult = {
message: Uint8Array
tag: SodiumConstant
tag: SodiumTag
}

View File

@@ -1,11 +1,12 @@
export * from './Base64String'
export * from './Base64URLSafeString'
export * from './HexString'
export * from './PkcKeyPair'
export * from './SodiumConstant'
export * from './SodiumStateAddress'
export * from './SodiumTag'
export * from './StreamDecryptor'
export * from './StreamDecryptorResult'
export * from './StreamEncryptor'
export * from './Unencrypted'
export * from './Utf8String'
export * from './PkcKeyPair'

View File

@@ -2,6 +2,7 @@ import {
StreamEncryptor,
StreamDecryptor,
SodiumConstant,
SodiumTag,
StreamDecryptorResult,
Base64String,
Base64URLSafeString,
@@ -299,7 +300,7 @@ export class SNWebCrypto implements PureCryptoInterface {
encryptor: StreamEncryptor,
plainBuffer: Uint8Array,
assocData?: Utf8String,
tag: SodiumConstant = SodiumConstant.CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PUSH,
tag: SodiumTag = SodiumTag.CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PUSH,
): Uint8Array {
const encryptedBuffer = sodium.crypto_secretstream_xchacha20poly1305_push(
encryptor.state as sodium.StateAddress,

View File

@@ -1,3 +1,3 @@
export * from './crypto'
export * from './utils'
export { SodiumConstant } from '@standardnotes/sncrypto-common'
export { SodiumConstant, SodiumTag } from '@standardnotes/sncrypto-common'

View File

@@ -1,24 +1,23 @@
import { ApplicationEvent, SyncEvent } from '@standardnotes/services'
export { SyncEvent }
export function applicationEventForSyncEvent(syncEvent: SyncEvent) {
return (
{
[SyncEvent.SyncCompletedWithAllItemsUploaded]: ApplicationEvent.CompletedFullSync,
[SyncEvent.PaginatedSyncRequestCompleted]: ApplicationEvent.CompletedIncrementalSync,
[SyncEvent.SyncError]: ApplicationEvent.FailedSync,
[SyncEvent.SyncTakingTooLong]: ApplicationEvent.HighLatencySync,
[SyncEvent.EnterOutOfSync]: ApplicationEvent.EnteredOutOfSync,
[SyncEvent.ExitOutOfSync]: ApplicationEvent.ExitedOutOfSync,
[SyncEvent.LocalDataLoaded]: ApplicationEvent.LocalDataLoaded,
[SyncEvent.MajorDataChange]: ApplicationEvent.MajorDataChange,
[SyncEvent.LocalDataIncrementalLoad]: ApplicationEvent.LocalDataIncrementalLoad,
[SyncEvent.StatusChanged]: ApplicationEvent.SyncStatusChanged,
[SyncEvent.SyncDidBeginProcessing]: ApplicationEvent.WillSync,
[SyncEvent.InvalidSession]: ApplicationEvent.InvalidSyncSession,
[SyncEvent.DatabaseReadError]: ApplicationEvent.LocalDatabaseReadError,
[SyncEvent.DatabaseWriteError]: ApplicationEvent.LocalDatabaseWriteError,
[SyncEvent.DownloadFirstSyncCompleted]: ApplicationEvent.CompletedInitialSync,
} as any
)[syncEvent]
const map: Record<string, ApplicationEvent> = {
[SyncEvent.SyncCompletedWithAllItemsUploaded]: ApplicationEvent.CompletedFullSync,
[SyncEvent.PaginatedSyncRequestCompleted]: ApplicationEvent.CompletedIncrementalSync,
[SyncEvent.SyncError]: ApplicationEvent.FailedSync,
[SyncEvent.SyncTakingTooLong]: ApplicationEvent.HighLatencySync,
[SyncEvent.EnterOutOfSync]: ApplicationEvent.EnteredOutOfSync,
[SyncEvent.ExitOutOfSync]: ApplicationEvent.ExitedOutOfSync,
[SyncEvent.LocalDataLoaded]: ApplicationEvent.LocalDataLoaded,
[SyncEvent.MajorDataChange]: ApplicationEvent.MajorDataChange,
[SyncEvent.LocalDataIncrementalLoad]: ApplicationEvent.LocalDataIncrementalLoad,
[SyncEvent.StatusChanged]: ApplicationEvent.SyncStatusChanged,
[SyncEvent.SyncDidBeginProcessing]: ApplicationEvent.WillSync,
[SyncEvent.InvalidSession]: ApplicationEvent.InvalidSyncSession,
[SyncEvent.DatabaseReadError]: ApplicationEvent.LocalDatabaseReadError,
[SyncEvent.DatabaseWriteError]: ApplicationEvent.LocalDatabaseWriteError,
[SyncEvent.DownloadFirstSyncCompleted]: ApplicationEvent.CompletedInitialSync,
}
export function applicationEventForSyncEvent(syncEvent: SyncEvent): ApplicationEvent | undefined {
return map[syncEvent]
}

View File

@@ -26,7 +26,10 @@ export class SNApplicationGroup<D extends DeviceInterface = DeviceInterface> ext
private descriptorRecord!: DescriptorRecord
callback!: AppGroupCallback<D>
constructor(public device: D, internalEventBus?: InternalEventBusInterface) {
constructor(
public device: D,
internalEventBus?: InternalEventBusInterface,
) {
if (internalEventBus === undefined) {
internalEventBus = new InternalEventBus()
}

View File

@@ -5,7 +5,10 @@ import { SettingName } from '@standardnotes/settings'
import { SettingsClientInterface } from '@Lib/Services/Settings/SettingsClientInterface'
export class GetRecoveryCodes implements UseCaseInterface<string> {
constructor(private authClient: AuthClientInterface, private settingsClient: SettingsClientInterface) {}
constructor(
private authClient: AuthClientInterface,
private settingsClient: SettingsClientInterface,
) {}
async execute(): Promise<Result<string>> {
const existingRecoveryCodes = await this.settingsClient.getSetting(

View File

@@ -4,7 +4,10 @@ import { ComponentInterface, PrefKey, SNTag } from '@standardnotes/models'
import { ItemManagerInterface, PreferenceServiceInterface } from '@standardnotes/services'
export class GetDefaultEditorIdentifier implements SyncUseCaseInterface<string> {
constructor(private preferences: PreferenceServiceInterface, private items: ItemManagerInterface) {}
constructor(
private preferences: PreferenceServiceInterface,
private items: ItemManagerInterface,
) {}
execute(currentTag?: SNTag): Result<string> {
if (currentTag) {

View File

@@ -250,7 +250,7 @@ export class FeaturesService
return this.downloadOfflineRoles(offlineRepo)
} catch (err) {
return new ClientDisplayableError(`${API_MESSAGE_FAILED_OFFLINE_ACTIVATION}, ${err}`)
return new ClientDisplayableError(`${API_MESSAGE_FAILED_OFFLINE_ACTIVATION}, ${JSON.stringify(err)}`)
}
}

View File

@@ -4,7 +4,10 @@ import { MutatorClientInterface } from '@standardnotes/services'
import { SettingName } from '@standardnotes/settings'
export class MigrateFeatureRepoToUserSettingUseCase {
constructor(private mutator: MutatorClientInterface, private settings: SettingsClientInterface) {}
constructor(
private mutator: MutatorClientInterface,
private settings: SettingsClientInterface,
) {}
async execute(featureRepos: SNFeatureRepo[] = []): Promise<void> {
for (const item of featureRepos) {

View File

@@ -641,7 +641,7 @@ export class SyncService
} else if (useStrategy === SyncQueueStrategy.ForceSpawnNew) {
return this.queueStrategyForceSpawnNew(options)
} else {
throw Error(`Unhandled timing strategy ${useStrategy}`)
throw Error('Unhandled timing strategy')
}
}

View File

@@ -81,6 +81,6 @@
"uuid": "^9.0.0",
"webpack": "*",
"webpack-cli": "*",
"webpack-merge": "^5.8.0"
"webpack-merge": "*"
}
}

View File

@@ -62,7 +62,7 @@ export class ArchiveManager {
}
formattedDateForExports() {
const string = `${new Date()}`
const string = new Date().toString()
// Match up to the first parenthesis, i.e do not include '(Central Standard Time)'
const matches = string.match(/^(.*?) \(/)
if (matches && matches.length >= 2) {

View File

@@ -12,7 +12,10 @@ export class ChangelogService implements ChangelogServiceInterface {
private changeLog?: Changelog
private lastReadChangeListeners: ChangelogLastReadVersionListener[] = []
constructor(private environment: Environment, private diskService: StorageServiceInterface) {}
constructor(
private environment: Environment,
private diskService: StorageServiceInterface,
) {}
public addLastReadChangeListener(listener: ChangelogLastReadVersionListener) {
this.lastReadChangeListeners.push(listener)

View File

@@ -12,7 +12,10 @@ export class KeyboardService {
private commandHandlers = new Set<KeyboardCommandHandler>()
private commandMap = new Map<KeyboardCommand, KeyboardShortcut>()
constructor(private platform: Platform, environment: Environment) {
constructor(
private platform: Platform,
environment: Environment,
) {
window.addEventListener('keydown', this.handleKeyDown)
window.addEventListener('keyup', this.handleKeyUp)
window.addEventListener('blur', this.handleWindowBlur)

View File

@@ -14,4 +14,4 @@ const PREFERENCE_IDS = [
'whats-new',
] as const
export type PreferenceId = typeof PREFERENCE_IDS[number]
export type PreferenceId = (typeof PREFERENCE_IDS)[number]

View File

@@ -1,3 +1,3 @@
export const ValidAppViewRoutes = ['u2f', 'extension'] as const
export type AppViewRouteParam = typeof ValidAppViewRoutes[number]
export type AppViewRouteParam = (typeof ValidAppViewRoutes)[number]

View File

@@ -6,7 +6,10 @@ import { Uuid } from '@standardnotes/domain-core'
export class ActiveThemeList {
private list: (NativeFeatureIdentifier | Uuid)[] = []
constructor(private items: ItemManagerInterface, initialList?: (NativeFeatureIdentifier | Uuid)[]) {
constructor(
private items: ItemManagerInterface,
initialList?: (NativeFeatureIdentifier | Uuid)[],
) {
if (initialList) {
this.list = initialList
}

View File

@@ -1,3 +1,8 @@
export const classNames = (...values: any[]): string => {
return values.map((value) => (typeof value === 'string' ? value : null)).join(' ')
import { isNotUndefined } from './Utils'
export const classNames = (...values: (string | null | undefined | boolean)[]): string => {
return values
.map((value) => (typeof value === 'string' ? value : null))
.filter(isNotUndefined)
.join(' ')
}

View File

@@ -69,8 +69,8 @@
"dayjs": "^1.11.7",
"dotenv": "^16.0.3",
"eslint": "*",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-react": "^7.31.11",
"eslint-config-prettier": "^8.9.0",
"eslint-plugin-react": "^7.33.0",
"eslint-plugin-react-hooks": "^4.6.0",
"html-webpack-plugin": "^5.5.3",
"identity-obj-proxy": "^3.0.0",
@@ -87,7 +87,7 @@
"postcss": "^8.4.19",
"postcss-loader": "^7.0.2",
"prettier": "*",
"prettier-plugin-tailwindcss": "^0.4.0",
"prettier-plugin-tailwindcss": "^0.4.1",
"qrcode.react": "^3.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
@@ -101,7 +101,7 @@
"webextension-polyfill": "^0.10.0",
"webpack": "*",
"webpack-dev-server": "*",
"webpack-merge": "^5.8.0"
"webpack-merge": "*"
},
"lint-staged": {
"app/**/*.{js,ts,jsx,tsx}": "eslint --cache --fix",

View File

@@ -1,7 +0,0 @@
module.exports = {
singleQuote: true,
trailingComma: 'all',
printWidth: 120,
semi: false,
plugins: [require('prettier-plugin-tailwindcss')],
}

View File

@@ -0,0 +1,7 @@
{
"singleQuote": true,
"trailingComma": "all",
"printWidth": 120,
"semi": false,
"plugins": ["prettier-plugin-tailwindcss"]
}

View File

@@ -20,7 +20,10 @@ export class Database {
private locked = true
private db?: IDBDatabase
constructor(public databaseName: string, private alertService?: AlertService) {}
constructor(
public databaseName: string,
private alertService?: AlertService,
) {}
public deinit(): void {
;(this.alertService as unknown) = undefined

View File

@@ -24,7 +24,11 @@ const createApplication = (
}
export class WebApplicationGroup extends SNApplicationGroup<WebOrDesktopDevice> {
constructor(private defaultSyncServerHost: string, device: WebOrDesktopDevice, private webSocketUrl: string) {
constructor(
private defaultSyncServerHost: string,
device: WebOrDesktopDevice,
private webSocketUrl: string,
) {
super(device)
}

View File

@@ -4,14 +4,17 @@ import { ViewControllerManager } from '@/Controllers/ViewControllerManager'
import { autorun, IReactionDisposer, IReactionPublic } from 'mobx'
import { Component } from 'react'
export type PureComponentState = Partial<Record<string, any>>
export type PureComponentProps = Partial<Record<string, any>>
export type PureComponentState = Partial<Record<string, unknown>>
export type PureComponentProps = Partial<Record<string, unknown>>
export abstract class AbstractComponent<P = PureComponentProps, S = PureComponentState> extends Component<P, S> {
private unsubApp!: () => void
private reactionDisposers: IReactionDisposer[] = []
constructor(props: P, protected application: WebApplication) {
constructor(
props: P,
protected application: WebApplication,
) {
super(props)
}

View File

@@ -108,7 +108,7 @@ const ContentListHeader = ({
<div className="flex">
<div className="relative" ref={displayOptionsContainerRef}>
<RoundIconButton
className={classNames(showDisplayOptionsMenu && 'bg-contrast')}
className={classNames(showDisplayOptionsMenu ? 'bg-contrast' : undefined)}
onClick={toggleDisplayOptionsMenu}
ref={displayOptionsButtonRef}
icon="sort-descending"

View File

@@ -136,9 +136,9 @@ export const InfinteScroller = forwardRef<InfiniteScrollerInterface, Props>(
const _paginateFront = useCallback(() => {
if (direction === 'vertical') {
setScrollSize(scrollArea!.current!.scrollHeight)
setScrollSize(scrollArea.current!.scrollHeight)
} else {
setScrollSize(scrollArea!.current!.scrollWidth)
setScrollSize(scrollArea.current!.scrollWidth)
}
setDidPaginateFront(true)
paginateFront()

View File

@@ -77,6 +77,7 @@ class Footer extends AbstractComponent<Props, State> {
this.onNewUpdateAvailable()
break
case WebAppEvent.EditorFocused:
// eslint-disable-next-line @typescript-eslint/no-explicit-any
if ((data as any).eventSource === EditorEventSource.UserInteraction) {
this.closeAccountMenu()
}
@@ -87,6 +88,7 @@ class Footer extends AbstractComponent<Props, State> {
case WebAppEvent.EndedBackupDownload: {
const successMessage = 'Successfully saved backup.'
const errorMessage = 'Unable to save local backup.'
// eslint-disable-next-line @typescript-eslint/no-explicit-any
statusService.setMessage((data as any).success ? successMessage : errorMessage)
const twoSeconds = 2000

View File

@@ -28,7 +28,7 @@ const IconPicker = ({ selectedValue, onIconChange, platform, className, useIconG
label: value,
value: value,
icon: value,
} as DropdownItem),
}) as DropdownItem,
),
[iconKeys],
)

View File

@@ -99,7 +99,7 @@ const ImportModalFileItem = ({
{file.status === 'pending' && 'Could not auto-detect service. Please select manually.'}
{file.status === 'parsing' && 'Parsing...'}
{file.status === 'importing' && 'Importing...'}
{file.status === 'error' && `${file.error}`}
{file.status === 'error' && JSON.stringify(file.error)}
{file.status === 'success' && file.successMessage}
</div>
</div>

View File

@@ -8,7 +8,10 @@ export class FileViewController implements ItemViewControllerInterface {
private removeStreamObserver?: () => void
public runtimeId = `${Math.random()}`
constructor(private application: SNApplication, public item: FileItem) {}
constructor(
private application: SNApplication,
public item: FileItem,
) {}
deinit() {
this.dealloced = true

View File

@@ -18,7 +18,10 @@ export class PreferencesSessionController {
private _menu: PreferencesMenuItem[]
private _extensionLatestVersions: PackageProvider = new PackageProvider(new Map())
constructor(private application: WebApplication, private readonly _enableUnfinishedFeatures: boolean) {
constructor(
private application: WebApplication,
private readonly _enableUnfinishedFeatures: boolean,
) {
const menuItems = this._enableUnfinishedFeatures
? PREFERENCES_MENU_ITEMS.slice()
: READY_PREFERENCES_MENU_ITEMS.slice()

View File

@@ -86,6 +86,7 @@ const DataBackups = ({ application, viewControllerManager }: Props) => {
}
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const readFile = async (file: File): Promise<any> => {
if (file.type === 'application/zip') {
application.alerts.alert(STRING_IMPORTING_ZIP_FILE).catch(console.error)

View File

@@ -16,7 +16,10 @@ export class TwoFactorAuth {
private _status: TwoFactorStatus | 'fetching' = 'fetching'
private _errorMessage: string | null
constructor(private readonly mfaProvider: MfaProvider, private readonly userProvider: UserProvider) {
constructor(
private readonly mfaProvider: MfaProvider,
private readonly userProvider: UserProvider,
) {
this._errorMessage = null
makeAutoObservable<TwoFactorAuth, '_status' | '_errorMessage' | 'deactivateMfa' | 'startActivation'>(

View File

@@ -156,7 +156,7 @@ const SuperNoteConverter = ({
return (
<Modal
title={`Convert to ${name}`}
title={`Convert to ${uiFeature.displayName}`}
close={closeDialog}
actions={modalActions}
className={{

View File

@@ -31,7 +31,9 @@ export function handleEditorChange(
onChange?.(stringifiedEditorState, previewText)
} catch (error) {
window.alert(
`An invalid change was made inside the Super editor. Your change was not saved. Please report this error to the team: ${error}`,
`An invalid change was made inside the Super editor. Your change was not saved. Please report this error to the team: ${JSON.stringify(
error,
)}`,
)
}
}

View File

@@ -10,7 +10,10 @@ export abstract class AbstractViewController<Event = void, EventData = void> {
protected disposers: Disposer[] = []
private eventObservers: ControllerEventObserver<Event, EventData>[] = []
constructor(public application: WebApplication, protected eventBus: InternalEventBusInterface) {}
constructor(
public application: WebApplication,
protected eventBus: InternalEventBusInterface,
) {}
protected async publishCrossControllerEventSync(name: CrossControllerEvent, data?: unknown): Promise<void> {
await this.eventBus.publishSync({ type: name, payload: data }, InternalEventPublishStrategy.SEQUENCE)

View File

@@ -8,7 +8,10 @@ export class PersistenceService {
private unsubAppEventObserver: () => void
private didHydrateOnce = false
constructor(private application: WebApplication, private eventBus: InternalEventBusInterface) {
constructor(
private application: WebApplication,
private eventBus: InternalEventBusInterface,
) {
this.unsubAppEventObserver = this.application.addEventObserver(async (eventName) => {
if (!this.application) {
return

View File

@@ -46,8 +46,8 @@ export class FilePreviewModalController {
deinit = () => {
this.eventObservers.forEach((observer) => observer())
;(this.currentFile as any) = undefined
;(this.otherFiles as any) = undefined
;(this.currentFile as unknown) = undefined
;(this.otherFiles as unknown) = undefined
}
setCurrentFile = (currentFile: FileItem) => {

View File

@@ -27,7 +27,10 @@ export class ImportModalController {
files: ImportModalFile[] = []
importTag: SNTag | undefined = undefined
constructor(private application: WebApplication, private navigationController: NavigationController) {
constructor(
private application: WebApplication,
private navigationController: NavigationController,
) {
makeObservable(this, {
isVisible: observable,
setIsVisible: action,

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