feat: add services package
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
import { WebClientRequiresDesktopMethods } from './DesktopWebCommunication'
|
||||
import { DeviceInterface } from './DeviceInterface'
|
||||
import { Environment } from './Environments'
|
||||
import { WebOrDesktopDeviceInterface } from './WebOrDesktopDeviceInterface'
|
||||
|
||||
/* istanbul ignore file */
|
||||
|
||||
export function isDesktopDevice(x: DeviceInterface): x is DesktopDeviceInterface {
|
||||
return x.environment === Environment.Desktop
|
||||
}
|
||||
|
||||
export interface DesktopDeviceInterface extends WebOrDesktopDeviceInterface, WebClientRequiresDesktopMethods {
|
||||
environment: Environment.Desktop
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { DecryptedTransferPayload } from '@standardnotes/models'
|
||||
import { FileBackupsDevice } from './FileBackupsDevice'
|
||||
|
||||
export interface WebClientRequiresDesktopMethods extends FileBackupsDevice {
|
||||
localBackupsCount(): Promise<number>
|
||||
|
||||
viewlocalBackups(): void
|
||||
|
||||
deleteLocalBackups(): Promise<void>
|
||||
|
||||
syncComponents(payloads: unknown[]): void
|
||||
|
||||
onMajorDataChange(): void
|
||||
|
||||
onInitialDataLoad(): void
|
||||
|
||||
onSearch(text?: string): void
|
||||
|
||||
downloadBackup(): void | Promise<void>
|
||||
|
||||
get extensionsServerHost(): string
|
||||
}
|
||||
|
||||
export interface DesktopClientRequiresWebMethods {
|
||||
updateAvailable(): void
|
||||
|
||||
windowGainedFocus(): void
|
||||
|
||||
windowLostFocus(): void
|
||||
|
||||
onComponentInstallationComplete(componentData: DecryptedTransferPayload, error: unknown): Promise<void>
|
||||
|
||||
requestBackupFile(): Promise<string | undefined>
|
||||
|
||||
didBeginBackup(): void
|
||||
|
||||
didFinishBackup(success: boolean): void
|
||||
}
|
||||
84
packages/services/src/Domain/Device/DeviceInterface.ts
Normal file
84
packages/services/src/Domain/Device/DeviceInterface.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import { Environment } from './Environments'
|
||||
import { ApplicationIdentifier } from '@standardnotes/common'
|
||||
import {
|
||||
FullyFormedTransferPayload,
|
||||
TransferPayload,
|
||||
LegacyRawKeychainValue,
|
||||
NamespacedRootKeyInKeychain,
|
||||
} from '@standardnotes/models'
|
||||
|
||||
/**
|
||||
* Platforms must override this class to provide platform specific utilities
|
||||
* and access to the migration service, such as exposing an interface to read
|
||||
* raw values from the database or value storage.
|
||||
*/
|
||||
export interface DeviceInterface {
|
||||
environment: Environment
|
||||
|
||||
deinit(): void
|
||||
|
||||
getRawStorageValue(key: string): Promise<string | undefined>
|
||||
|
||||
getJsonParsedRawStorageValue(key: string): Promise<unknown | undefined>
|
||||
|
||||
getAllRawStorageKeyValues(): Promise<{ key: string; value: unknown }[]>
|
||||
|
||||
setRawStorageValue(key: string, value: string): Promise<void>
|
||||
|
||||
removeRawStorageValue(key: string): Promise<void>
|
||||
|
||||
removeAllRawStorageValues(): Promise<void>
|
||||
|
||||
/**
|
||||
* On web platforms, databased created may be new.
|
||||
* New databases can be because of new sessions, or if the browser deleted it.
|
||||
* In this case, callers should orchestrate with the server to redownload all items
|
||||
* from scratch.
|
||||
* @returns { isNewDatabase } - True if the database was newly created
|
||||
*/
|
||||
openDatabase(identifier: ApplicationIdentifier): Promise<{ isNewDatabase?: boolean } | undefined>
|
||||
|
||||
/**
|
||||
* In a key/value database, this function returns just the keys.
|
||||
*/
|
||||
getDatabaseKeys(): Promise<string[]>
|
||||
|
||||
/**
|
||||
* Remove all keychain and database data from device.
|
||||
* @param workspaceIdentifiers An array of identifiers present during time of function call. Used in case
|
||||
* caller needs to reference the identifiers. This param should not be used to selectively clear workspaces.
|
||||
* @returns true for killsApplication if the clear data operation kills the application process completely.
|
||||
* This tends to be the case for the desktop application.
|
||||
*/
|
||||
clearAllDataFromDevice(workspaceIdentifiers: ApplicationIdentifier[]): Promise<{ killsApplication: boolean }>
|
||||
|
||||
getAllRawDatabasePayloads<T extends FullyFormedTransferPayload = FullyFormedTransferPayload>(
|
||||
identifier: ApplicationIdentifier,
|
||||
): Promise<T[]>
|
||||
|
||||
saveRawDatabasePayload(payload: TransferPayload, identifier: ApplicationIdentifier): Promise<void>
|
||||
|
||||
saveRawDatabasePayloads(payloads: TransferPayload[], identifier: ApplicationIdentifier): Promise<void>
|
||||
|
||||
removeRawDatabasePayloadWithId(id: string, identifier: ApplicationIdentifier): Promise<void>
|
||||
|
||||
removeAllRawDatabasePayloads(identifier: ApplicationIdentifier): Promise<void>
|
||||
|
||||
getNamespacedKeychainValue(identifier: ApplicationIdentifier): Promise<NamespacedRootKeyInKeychain | undefined>
|
||||
|
||||
setNamespacedKeychainValue(value: NamespacedRootKeyInKeychain, identifier: ApplicationIdentifier): Promise<void>
|
||||
|
||||
clearNamespacedKeychainValue(identifier: ApplicationIdentifier): Promise<void>
|
||||
|
||||
setLegacyRawKeychainValue(value: LegacyRawKeychainValue): Promise<void>
|
||||
|
||||
clearRawKeychainValue(): Promise<void>
|
||||
|
||||
openUrl(url: string): void
|
||||
|
||||
performSoftReset(): void
|
||||
|
||||
performHardReset(): void
|
||||
|
||||
isDeviceDestroyed(): boolean
|
||||
}
|
||||
16
packages/services/src/Domain/Device/Environments.ts
Normal file
16
packages/services/src/Domain/Device/Environments.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
export enum Environment {
|
||||
Web = 1,
|
||||
Desktop = 2,
|
||||
Mobile = 3,
|
||||
}
|
||||
|
||||
export enum Platform {
|
||||
Ios = 1,
|
||||
Android = 2,
|
||||
MacWeb = 3,
|
||||
MacDesktop = 4,
|
||||
WindowsWeb = 5,
|
||||
WindowsDesktop = 6,
|
||||
LinuxWeb = 7,
|
||||
LinuxDesktop = 8,
|
||||
}
|
||||
51
packages/services/src/Domain/Device/FileBackupsDevice.ts
Normal file
51
packages/services/src/Domain/Device/FileBackupsDevice.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { Uuid } from '@standardnotes/common'
|
||||
import { BackupFileEncryptedContextualPayload } from '@standardnotes/models'
|
||||
|
||||
/* istanbul ignore file */
|
||||
|
||||
export const FileBackupsConstantsV1 = {
|
||||
Version: '1.0.0',
|
||||
MetadataFileName: 'metadata.sn.json',
|
||||
BinaryFileName: 'file.encrypted',
|
||||
}
|
||||
|
||||
export interface FileBackupMetadataFile {
|
||||
info: Record<string, string>
|
||||
file: BackupFileEncryptedContextualPayload
|
||||
itemsKey: BackupFileEncryptedContextualPayload
|
||||
version: '1.0.0'
|
||||
}
|
||||
|
||||
export interface FileBackupsMapping {
|
||||
version: typeof FileBackupsConstantsV1.Version
|
||||
files: Record<
|
||||
Uuid,
|
||||
{
|
||||
backedUpOn: Date
|
||||
absolutePath: string
|
||||
relativePath: string
|
||||
metadataFileName: typeof FileBackupsConstantsV1.MetadataFileName
|
||||
binaryFileName: typeof FileBackupsConstantsV1.BinaryFileName
|
||||
version: typeof FileBackupsConstantsV1.Version
|
||||
}
|
||||
>
|
||||
}
|
||||
|
||||
export interface FileBackupsDevice {
|
||||
getFilesBackupsMappingFile(): Promise<FileBackupsMapping>
|
||||
saveFilesBackupsFile(
|
||||
uuid: Uuid,
|
||||
metaFile: string,
|
||||
downloadRequest: {
|
||||
chunkSizes: number[]
|
||||
valetToken: string
|
||||
url: string
|
||||
},
|
||||
): Promise<'success' | 'failed'>
|
||||
isFilesBackupsEnabled(): Promise<boolean>
|
||||
enableFilesBackups(): Promise<void>
|
||||
disableFilesBackups(): Promise<void>
|
||||
changeFilesBackupsLocation(): Promise<string | undefined>
|
||||
getFilesBackupsLocation(): Promise<string>
|
||||
openFilesBackupsLocation(): Promise<void>
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { DeviceInterface } from './DeviceInterface'
|
||||
import { Environment } from './Environments'
|
||||
import { RawKeychainValue } from '@standardnotes/models'
|
||||
|
||||
export interface MobileDeviceInterface extends DeviceInterface {
|
||||
environment: Environment.Mobile
|
||||
|
||||
getRawKeychainValue(): Promise<RawKeychainValue | undefined>
|
||||
}
|
||||
18
packages/services/src/Domain/Device/TypeCheck.spec.ts
Normal file
18
packages/services/src/Domain/Device/TypeCheck.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { DeviceInterface } from './DeviceInterface'
|
||||
import { Environment } from './Environments'
|
||||
import { MobileDeviceInterface } from './MobileDeviceInterface'
|
||||
import { isMobileDevice } from './TypeCheck'
|
||||
|
||||
describe('device type check', () => {
|
||||
it('should return true for mobile devices', () => {
|
||||
const device = { environment: Environment.Mobile } as jest.Mocked<MobileDeviceInterface>
|
||||
|
||||
expect(isMobileDevice(device)).toBeTruthy()
|
||||
})
|
||||
|
||||
it('should return false for non mobile devices', () => {
|
||||
const device = { environment: Environment.Web } as jest.Mocked<DeviceInterface>
|
||||
|
||||
expect(isMobileDevice(device)).toBeFalsy()
|
||||
})
|
||||
})
|
||||
9
packages/services/src/Domain/Device/TypeCheck.ts
Normal file
9
packages/services/src/Domain/Device/TypeCheck.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Environment } from './Environments'
|
||||
import { MobileDeviceInterface } from './MobileDeviceInterface'
|
||||
import { DeviceInterface } from './DeviceInterface'
|
||||
|
||||
/* istanbul ignore file */
|
||||
|
||||
export function isMobileDevice(x: DeviceInterface): x is MobileDeviceInterface {
|
||||
return x.environment === Environment.Mobile
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { DeviceInterface } from './DeviceInterface'
|
||||
import { RawKeychainValue } from '@standardnotes/models'
|
||||
|
||||
export interface WebOrDesktopDeviceInterface extends DeviceInterface {
|
||||
readonly appVersion: string
|
||||
|
||||
getKeychainValue(): Promise<RawKeychainValue>
|
||||
|
||||
setKeychainValue(value: RawKeychainValue): Promise<void>
|
||||
}
|
||||
Reference in New Issue
Block a user