feat(files): refactor circular deps

This commit is contained in:
Karol Sójko
2022-08-04 16:21:46 +02:00
parent 7e251262d7
commit 696b82b9d3
33 changed files with 126 additions and 98 deletions

View File

@@ -35,7 +35,6 @@
"@standardnotes/filepicker": "workspace:*",
"@standardnotes/models": "workspace:*",
"@standardnotes/responses": "workspace:*",
"@standardnotes/services": "workspace:*",
"@standardnotes/sncrypto-common": "workspace:*",
"@standardnotes/utils": "workspace:*",
"reflect-metadata": "^0.1.13"

View File

@@ -0,0 +1,3 @@
export interface DirectoryHandle {
nativeHandle: unknown
}

View File

@@ -0,0 +1,3 @@
export interface FileHandleRead {
nativeHandle: unknown
}

View File

@@ -0,0 +1,4 @@
export interface FileHandleReadWrite {
nativeHandle: unknown
writableStream: unknown
}

View File

@@ -1,16 +1,8 @@
export interface DirectoryHandle {
nativeHandle: unknown
}
export interface FileHandleReadWrite {
nativeHandle: unknown
writableStream: unknown
}
export interface FileHandleRead {
nativeHandle: unknown
}
export type FileSystemResult = 'aborted' | 'success' | 'failed'
export type FileSystemNoSelection = 'aborted' | 'failed'
import { DirectoryHandle } from './DirectoryHandle'
import { FileHandleRead } from './FileHandleRead'
import { FileHandleReadWrite } from './FileHandleReadWrite'
import { FileSystemNoSelection } from './FileSystemNoSelection'
import { FileSystemResult } from './FileSystemResult'
export interface FileSystemApi {
selectDirectory(): Promise<DirectoryHandle | FileSystemNoSelection>

View File

@@ -0,0 +1 @@
export type FileSystemNoSelection = 'aborted' | 'failed'

View File

@@ -0,0 +1 @@
export type FileSystemResult = 'aborted' | 'success' | 'failed'

View File

@@ -0,0 +1,8 @@
import { BackupFileEncryptedContextualPayload } from '@standardnotes/models'
export interface FileBackupMetadataFile {
info: Record<string, string>
file: BackupFileEncryptedContextualPayload
itemsKey: BackupFileEncryptedContextualPayload
version: '1.0.0'
}

View File

@@ -0,0 +1,5 @@
export const FileBackupsConstantsV1 = {
Version: '1.0.0',
MetadataFileName: 'metadata.sn.json',
BinaryFileName: 'file.encrypted',
}

View File

@@ -0,0 +1,21 @@
import { Uuid } from '@standardnotes/common'
import { FileBackupsMapping } from './FileBackupsMapping'
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>
}

View File

@@ -0,0 +1,17 @@
import { Uuid } from '@standardnotes/common'
import { FileBackupsConstantsV1 } from './FileBackupsConstantsV1'
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
}
>
}

View File

@@ -1,9 +1,9 @@
import { sleep } from '@standardnotes/utils'
import { PureCryptoInterface, StreamEncryptor } from '@standardnotes/sncrypto-common'
import { FileDownloadProgress } from '../Types/FileDownloadProgress'
import { FilesApiInterface } from '@standardnotes/services'
import { DownloadAndDecryptFileOperation } from './DownloadAndDecrypt'
import { FileContent } from '@standardnotes/models'
import { FilesApiInterface } from '../Api/FilesApiInterface'
describe('download and decrypt', () => {
let apiService: FilesApiInterface

View File

@@ -2,10 +2,10 @@ import { ClientDisplayableError } from '@standardnotes/responses'
import { AbortFunction, FileDownloader } from '../UseCase/FileDownloader'
import { FileDecryptor } from '../UseCase/FileDecryptor'
import { FileDownloadProgress } from '../Types/FileDownloadProgress'
import { FilesApiInterface } from '@standardnotes/services'
import { PureCryptoInterface } from '@standardnotes/sncrypto-common'
import { FileContent } from '@standardnotes/models'
import { DecryptedBytes, EncryptedBytes } from '@standardnotes/filepicker'
import { FilesApiInterface } from '../Api/FilesApiInterface'
export type DownloadAndDecryptResult = { success: boolean; error?: ClientDisplayableError; aborted?: boolean }

View File

@@ -1,8 +1,9 @@
import { EncryptAndUploadFileOperation } from './EncryptAndUpload'
import { PureCryptoInterface, StreamEncryptor } from '@standardnotes/sncrypto-common'
import { FilesApiInterface } from '@standardnotes/services'
import { FileContent } from '@standardnotes/models'
import { FilesApiInterface } from '../Api/FilesApiInterface'
describe('encrypt and upload', () => {
let apiService: FilesApiInterface
let operation: EncryptAndUploadFileOperation

View File

@@ -1,10 +1,10 @@
import { FileUploadProgress } from '../Types/FileUploadProgress'
import { FileUploadResult } from '../Types/FileUploadResult'
import { FilesApiInterface } from '@standardnotes/services'
import { FileUploader } from '../UseCase/FileUploader'
import { PureCryptoInterface } from '@standardnotes/sncrypto-common'
import { FileEncryptor } from '../UseCase/FileEncryptor'
import { FileContent } from '@standardnotes/models'
import { FilesApiInterface } from '../Api/FilesApiInterface'
export class EncryptAndUploadFileOperation {
public readonly encryptedChunkSizes: number[] = []

View File

@@ -2,7 +2,10 @@ import { EncryptAndUploadFileOperation } from '../Operations/EncryptAndUpload'
import { FileItem, FileMetadata } from '@standardnotes/models'
import { ClientDisplayableError } from '@standardnotes/responses'
import { FileDownloadProgress } from '../Types/FileDownloadProgress'
import { FileSystemApi, FileBackupMetadataFile, FileHandleRead, FileSystemNoSelection } from '@standardnotes/services'
import { FileSystemApi } from '../Api/FileSystemApi'
import { FileHandleRead } from '../Api/FileHandleRead'
import { FileSystemNoSelection } from '../Api/FileSystemNoSelection'
import { FileBackupMetadataFile } from '../Device/FileBackupMetadataFile'
export interface FilesClientInterface {
beginNewFileUpload(sizeInBytes: number): Promise<EncryptAndUploadFileOperation | ClientDisplayableError>

View File

@@ -1,8 +1,9 @@
import { FileContent } from '@standardnotes/models'
import { FileSystemApi, FileHandleRead } from '@standardnotes/services'
import { PureCryptoInterface } from '@standardnotes/sncrypto-common'
import { OrderedByteChunker } from '@standardnotes/filepicker'
import { FileDecryptor } from '../UseCase/FileDecryptor'
import { FileSystemApi } from '../Api/FileSystemApi'
import { FileHandleRead } from '../Api/FileHandleRead'
export async function readAndDecryptBackupFile(
fileHandle: FileHandleRead,

View File

@@ -1,5 +1,5 @@
import { FileContent } from '@standardnotes/models'
import { FilesApiInterface } from '@standardnotes/services'
import { FilesApiInterface } from '../Api/FilesApiInterface'
import { FileDownloader } from './FileDownloader'
describe('file downloader', () => {

View File

@@ -1,8 +1,8 @@
import { ClientDisplayableError } from '@standardnotes/responses'
import { FileDownloadProgress } from '../Types/FileDownloadProgress'
import { FilesApiInterface } from '@standardnotes/services'
import { Deferred } from '@standardnotes/utils'
import { FileContent } from '@standardnotes/models'
import { FilesApiInterface } from '../Api/FilesApiInterface'
export type AbortSignal = 'aborted'
export type AbortFunction = () => void

View File

@@ -1,4 +1,4 @@
import { FilesApiInterface } from '@standardnotes/services'
import { FilesApiInterface } from '../Api/FilesApiInterface'
import { FileUploader } from './FileUploader'
describe('file uploader', () => {

View File

@@ -1,4 +1,4 @@
import { FilesApiInterface } from '@standardnotes/services'
import { FilesApiInterface } from '../Api/FilesApiInterface'
export class FileUploader {
constructor(private apiService: FilesApiInterface) {}

View File

@@ -1,5 +1,16 @@
export * from './Service/FileService'
export * from './Api/DirectoryHandle'
export * from './Api/FileHandleRead'
export * from './Api/FileHandleReadWrite'
export * from './Api/FileSystemApi'
export * from './Api/FileSystemNoSelection'
export * from './Api/FileSystemResult'
export * from './Api/FilesApiInterface'
export * from './Device/FileBackupMetadataFile'
export * from './Device/FileBackupsConstantsV1'
export * from './Device/FileBackupsDevice'
export * from './Device/FileBackupsMapping'
export * from './Service/FilesClientInterface'
export * from './Service/ReadAndDecryptBackupFile'
export * from './Operations/DownloadAndDecrypt'
export * from './Operations/EncryptAndUpload'
export * from './UseCase/FileDecryptor'
@@ -9,4 +20,3 @@ export * from './UseCase/FileDownloader'
export * from './Types/FileDownloadProgress'
export * from './Types/FileUploadProgress'
export * from './Types/FileUploadResult'
export * from './Backups/BackupService'

View File

@@ -25,6 +25,7 @@
"dependencies": {
"@standardnotes/auth": "^3.19.4",
"@standardnotes/common": "^1.30.0",
"@standardnotes/files": "workspace:^",
"@standardnotes/models": "workspace:^",
"@standardnotes/responses": "workspace:*",
"@standardnotes/security": "^1.2.0",

View File

@@ -1,7 +1,7 @@
import { AbstractService } from '../Service/AbstractService'
import { Uuid } from '@standardnotes/common'
import { Role } from '@standardnotes/auth'
import { FilesApiInterface } from '../Files/FilesApiInterface'
import { FilesApiInterface } from '@standardnotes/files'
/* istanbul ignore file */

View File

@@ -1,7 +1,10 @@
import { ApplicationIdentifier, ContentType } from '@standardnotes/common'
import { BackupFile, DecryptedItemInterface, ItemStream, PrefKey, PrefValue } from '@standardnotes/models'
import { FilesClientInterface } from '@standardnotes/files'
import { AlertService } from '../Alert/AlertService'
import { ComponentManagerInterface } from '../Component/ComponentManagerInterface'
import { Platform } from '../Device/Environments'
import { ApplicationEvent } from '../Event/ApplicationEvent'
import { ApplicationEventCallback } from '../Event/ApplicationEventCallback'
import { FeaturesClientInterface } from '../Feature/FeaturesClientInterface'
@@ -12,6 +15,7 @@ import { StorageValueModes } from '../Storage/StorageTypes'
import { DeinitMode } from './DeinitMode'
import { DeinitSource } from './DeinitSource'
import { UserClientInterface } from './UserClientInterface'
import { DeviceInterface } from '../Device/DeviceInterface'
export interface ApplicationInterface {
deinit(mode: DeinitMode, source: DeinitSource): void
@@ -21,6 +25,7 @@ export interface ApplicationInterface {
addEventObserver(callback: ApplicationEventCallback, singleEvent?: ApplicationEvent): () => void
hasProtectionSources(): boolean
createEncryptedBackupFileForAutomatedDesktopBackups(): Promise<BackupFile | undefined>
createEncryptedBackupFile(): Promise<BackupFile | undefined>
createDecryptedBackupFile(): Promise<BackupFile | undefined>
hasPasscode(): boolean
lock(): Promise<void>
@@ -31,14 +36,20 @@ export interface ApplicationInterface {
getPreference<K extends PrefKey>(key: K): PrefValue[K] | undefined
getPreference<K extends PrefKey>(key: K, defaultValue: PrefValue[K]): PrefValue[K]
getPreference<K extends PrefKey>(key: K, defaultValue?: PrefValue[K]): PrefValue[K] | undefined
setPreference<K extends PrefKey>(key: K, value: PrefValue[K]): Promise<void>
streamItems<I extends DecryptedItemInterface = DecryptedItemInterface>(
contentType: ContentType | ContentType[],
stream: ItemStream<I>,
): () => void
hasAccount(): boolean
get features(): FeaturesClientInterface
get componentManager(): ComponentManagerInterface
get items(): ItemsClientInterface
get mutator(): MutatorClientInterface
get user(): UserClientInterface
get files(): FilesClientInterface
readonly identifier: ApplicationIdentifier
readonly platform: Platform
deviceInterface: DeviceInterface
alertService: AlertService
}

View File

@@ -2,16 +2,12 @@ import { ContentType, Uuid } from '@standardnotes/common'
import { EncryptionProvider } from '@standardnotes/encryption'
import { PayloadEmitSource, FileItem, CreateEncryptedBackupFileContextPayload } from '@standardnotes/models'
import { ClientDisplayableError } from '@standardnotes/responses'
import {
ItemManagerInterface,
FileBackupsDevice,
FileBackupsMapping,
AbstractService,
InternalEventBusInterface,
StatusServiceInterface,
FileBackupMetadataFile,
FilesApiInterface,
} from '@standardnotes/services'
import { FileBackupMetadataFile, FileBackupsDevice, FileBackupsMapping } from '../Device/FileBackupsDevice'
import { FilesApiInterface } from '@standardnotes/files'
import { InternalEventBusInterface } from '../Internal/InternalEventBusInterface'
import { ItemManagerInterface } from '../Item/ItemManagerInterface'
import { AbstractService } from '../Service/AbstractService'
import { StatusServiceInterface } from '../Status/StatusServiceInterface'
export class FilesBackupService extends AbstractService {
private itemsObserverDisposer: () => void

View File

@@ -20,4 +20,5 @@ export interface ComponentManagerInterface {
urlOverride?: string,
): ComponentViewerInterface
presentPermissionsDialog(_dialog: PermissionDialog): void
getDefaultEditor(): SNComponent
}

View File

@@ -1,51 +0,0 @@
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>
}

View File

@@ -1,8 +1,6 @@
import { DecryptedBytes, EncryptedBytes, FileMemoryCache, OrderedByteChunker } from '@standardnotes/filepicker'
import { ClientDisplayableError } from '@standardnotes/responses'
import { ContentType } from '@standardnotes/common'
import { DownloadAndDecryptFileOperation } from '../Operations/DownloadAndDecrypt'
import { EncryptAndUploadFileOperation } from '../Operations/EncryptAndUpload'
import {
FileItem,
FileProtocolV1Constants,
@@ -29,11 +27,15 @@ import {
ChallengeServiceInterface,
FileBackupsConstantsV1,
} from '@standardnotes/services'
import { FilesClientInterface } from './FilesClientInterface'
import { FileDownloadProgress } from '../Types/FileDownloadProgress'
import { readAndDecryptBackupFile } from './ReadAndDecryptBackupFile'
import { DecryptItemsKeyWithUserFallback, EncryptionProvider, SNItemsKey } from '@standardnotes/encryption'
import { FileDecryptor } from '../UseCase/FileDecryptor'
import {
DownloadAndDecryptFileOperation,
EncryptAndUploadFileOperation,
FileDecryptor,
FileDownloadProgress,
FilesClientInterface,
readAndDecryptBackupFile,
} from '@standardnotes/files'
const OneHundredMb = 100 * 1_000_000

View File

@@ -8,6 +8,7 @@ export * from './Application/DeinitSource'
export * from './Application/DeinitMode'
export * from './Application/UserClientInterface'
export * from './Application/WebApplicationInterface'
export * from './Backups/BackupService'
export * from './Challenge'
export * from './Component/ComponentManagerInterface'
export * from './Component/ComponentViewerError'
@@ -33,8 +34,6 @@ export * from './Feature/FeaturesClientInterface'
export * from './Feature/FeaturesEvent'
export * from './Feature/OfflineSubscriptionEntitlements'
export * from './Feature/SetOfflineFeaturesFunctionResponse'
export * from './Files/FilesApiInterface'
export * from './FileSystem/FileSystemApi'
export * from './Integrity/IntegrityApiInterface'
export * from './Integrity/IntegrityEvent'
export * from './Integrity/IntegrityEventPayload'

View File

@@ -6653,7 +6653,7 @@ __metadata:
languageName: unknown
linkType: soft
"@standardnotes/files@workspace:*, @standardnotes/files@workspace:packages/files":
"@standardnotes/files@workspace:*, @standardnotes/files@workspace:^, @standardnotes/files@workspace:packages/files":
version: 0.0.0-use.local
resolution: "@standardnotes/files@workspace:packages/files"
dependencies:
@@ -6662,7 +6662,6 @@ __metadata:
"@standardnotes/filepicker": "workspace:*"
"@standardnotes/models": "workspace:*"
"@standardnotes/responses": "workspace:*"
"@standardnotes/services": "workspace:*"
"@standardnotes/sncrypto-common": "workspace:*"
"@standardnotes/utils": "workspace:*"
"@types/jest": ^28.1.5
@@ -7182,6 +7181,7 @@ __metadata:
dependencies:
"@standardnotes/auth": ^3.19.4
"@standardnotes/common": ^1.30.0
"@standardnotes/files": "workspace:^"
"@standardnotes/models": "workspace:^"
"@standardnotes/responses": "workspace:*"
"@standardnotes/security": ^1.2.0