feat: New one-click Home Server, now in Labs. Launch your own self-hosted server instance with just 1 click from the Preferences window. (#2341)
This commit is contained in:
@@ -30,6 +30,7 @@ import { DeinitMode } from './DeinitMode'
|
||||
import { DeinitSource } from './DeinitSource'
|
||||
import { UserClientInterface } from '../User/UserClientInterface'
|
||||
import { SessionsClientInterface } from '../Session/SessionsClientInterface'
|
||||
import { HomeServerServiceInterface } from '../HomeServer/HomeServerServiceInterface'
|
||||
import { User } from '@standardnotes/responses'
|
||||
|
||||
export interface ApplicationInterface {
|
||||
@@ -61,6 +62,9 @@ export interface ApplicationInterface {
|
||||
|
||||
getUser(): User | undefined
|
||||
hasAccount(): boolean
|
||||
setCustomHost(host: string): Promise<void>
|
||||
isThirdPartyHostUsed(): boolean
|
||||
isUsingHomeServer(): Promise<boolean>
|
||||
|
||||
importData(data: BackupFile, awaitSync?: boolean): Promise<ImportDataReturnType>
|
||||
/**
|
||||
@@ -94,6 +98,7 @@ export interface ApplicationInterface {
|
||||
get subscriptions(): SubscriptionClientInterface
|
||||
get fileBackups(): BackupServiceInterface | undefined
|
||||
get sessions(): SessionsClientInterface
|
||||
get homeServer(): HomeServerServiceInterface | undefined
|
||||
get vaults(): VaultServiceInterface
|
||||
get challenges(): ChallengeServiceInterface
|
||||
get alerts(): AlertService
|
||||
|
||||
@@ -11,7 +11,7 @@ import { InternalEventBusInterface } from '..'
|
||||
import { AlertService } from '../Alert/AlertService'
|
||||
import { ApiServiceInterface } from '../Api/ApiServiceInterface'
|
||||
import { SyncServiceInterface } from '../Sync/SyncServiceInterface'
|
||||
import { FileBackupsDevice } from '@standardnotes/files'
|
||||
import { DirectoryManagerInterface, FileBackupsDevice } from '@standardnotes/files'
|
||||
|
||||
describe('backup service', () => {
|
||||
let apiService: ApiServiceInterface
|
||||
@@ -23,7 +23,7 @@ describe('backup service', () => {
|
||||
let encryptor: EncryptionProviderInterface
|
||||
let internalEventBus: InternalEventBusInterface
|
||||
let backupService: FilesBackupService
|
||||
let device: FileBackupsDevice
|
||||
let device: FileBackupsDevice & DirectoryManagerInterface
|
||||
let session: SessionsClientInterface
|
||||
let storage: StorageServiceInterface
|
||||
let payloads: PayloadManagerInterface
|
||||
@@ -42,7 +42,7 @@ describe('backup service', () => {
|
||||
|
||||
status = {} as jest.Mocked<StatusServiceInterface>
|
||||
|
||||
device = {} as jest.Mocked<FileBackupsDevice>
|
||||
device = {} as jest.Mocked<FileBackupsDevice & DirectoryManagerInterface>
|
||||
device.getFileBackupReadToken = jest.fn()
|
||||
device.readNextChunk = jest.fn()
|
||||
device.joinPaths = jest.fn()
|
||||
@@ -80,6 +80,7 @@ describe('backup service', () => {
|
||||
session,
|
||||
payloads,
|
||||
history,
|
||||
device,
|
||||
internalEventBus,
|
||||
)
|
||||
backupService.getFilesBackupsLocation = jest.fn().mockReturnValue('/')
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
BackupServiceInterface,
|
||||
DesktopWatchedDirectoriesChanges,
|
||||
SuperConverterServiceInterface,
|
||||
DirectoryManagerInterface,
|
||||
} from '@standardnotes/files'
|
||||
import { InternalEventBusInterface } from '../Internal/InternalEventBusInterface'
|
||||
import { ItemManagerInterface } from '../Item/ItemManagerInterface'
|
||||
@@ -59,6 +60,7 @@ export class FilesBackupService extends AbstractService implements BackupService
|
||||
private session: SessionsClientInterface,
|
||||
private payloads: PayloadManagerInterface,
|
||||
private history: HistoryServiceInterface,
|
||||
private directory: DirectoryManagerInterface,
|
||||
protected override internalEventBus: InternalEventBusInterface,
|
||||
) {
|
||||
super(internalEventBus)
|
||||
@@ -161,15 +163,15 @@ export class FilesBackupService extends AbstractService implements BackupService
|
||||
const textBackupsLocation = this.getTextBackupsLocation()
|
||||
|
||||
if (fileBackupsLocation) {
|
||||
void this.device.openLocation(fileBackupsLocation)
|
||||
void this.directory.openLocation(fileBackupsLocation)
|
||||
}
|
||||
|
||||
if (plaintextBackupsLocation) {
|
||||
void this.device.openLocation(plaintextBackupsLocation)
|
||||
void this.directory.openLocation(plaintextBackupsLocation)
|
||||
}
|
||||
|
||||
if (textBackupsLocation) {
|
||||
void this.device.openLocation(textBackupsLocation)
|
||||
void this.directory.openLocation(textBackupsLocation)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,7 +196,7 @@ export class FilesBackupService extends AbstractService implements BackupService
|
||||
async enableTextBackups(): Promise<void> {
|
||||
let location = this.getTextBackupsLocation()
|
||||
if (!location) {
|
||||
location = await this.device.presentDirectoryPickerForLocationChangeAndTransferOld(
|
||||
location = await this.directory.presentDirectoryPickerForLocationChangeAndTransferOld(
|
||||
await this.prependWorkspacePathForPath(TextBackupsDirectoryName),
|
||||
)
|
||||
if (!location) {
|
||||
@@ -217,13 +219,13 @@ export class FilesBackupService extends AbstractService implements BackupService
|
||||
async openTextBackupsLocation(): Promise<void> {
|
||||
const location = this.getTextBackupsLocation()
|
||||
if (location) {
|
||||
void this.device.openLocation(location)
|
||||
void this.directory.openLocation(location)
|
||||
}
|
||||
}
|
||||
|
||||
async changeTextBackupsLocation(): Promise<string | undefined> {
|
||||
const oldLocation = this.getTextBackupsLocation()
|
||||
const newLocation = await this.device.presentDirectoryPickerForLocationChangeAndTransferOld(
|
||||
const newLocation = await this.directory.presentDirectoryPickerForLocationChangeAndTransferOld(
|
||||
await this.prependWorkspacePathForPath(TextBackupsDirectoryName),
|
||||
oldLocation,
|
||||
)
|
||||
@@ -253,7 +255,7 @@ export class FilesBackupService extends AbstractService implements BackupService
|
||||
public async enablePlaintextBackups(): Promise<void> {
|
||||
let location = this.getPlaintextBackupsLocation()
|
||||
if (!location) {
|
||||
location = await this.device.presentDirectoryPickerForLocationChangeAndTransferOld(
|
||||
location = await this.directory.presentDirectoryPickerForLocationChangeAndTransferOld(
|
||||
await this.prependWorkspacePathForPath(PlaintextBackupsDirectoryName),
|
||||
)
|
||||
if (!location) {
|
||||
@@ -279,13 +281,13 @@ export class FilesBackupService extends AbstractService implements BackupService
|
||||
async openPlaintextBackupsLocation(): Promise<void> {
|
||||
const location = this.getPlaintextBackupsLocation()
|
||||
if (location) {
|
||||
void this.device.openLocation(location)
|
||||
void this.directory.openLocation(location)
|
||||
}
|
||||
}
|
||||
|
||||
async changePlaintextBackupsLocation(): Promise<string | undefined> {
|
||||
const oldLocation = this.getPlaintextBackupsLocation()
|
||||
const newLocation = await this.device.presentDirectoryPickerForLocationChangeAndTransferOld(
|
||||
const newLocation = await this.directory.presentDirectoryPickerForLocationChangeAndTransferOld(
|
||||
await this.prependWorkspacePathForPath(PlaintextBackupsDirectoryName),
|
||||
oldLocation,
|
||||
)
|
||||
@@ -302,7 +304,7 @@ export class FilesBackupService extends AbstractService implements BackupService
|
||||
public async enableFilesBackups(): Promise<void> {
|
||||
let location = this.getFilesBackupsLocation()
|
||||
if (!location) {
|
||||
location = await this.device.presentDirectoryPickerForLocationChangeAndTransferOld(
|
||||
location = await this.directory.presentDirectoryPickerForLocationChangeAndTransferOld(
|
||||
await this.prependWorkspacePathForPath(FileBackupsDirectoryName),
|
||||
)
|
||||
if (!location) {
|
||||
@@ -328,7 +330,7 @@ export class FilesBackupService extends AbstractService implements BackupService
|
||||
|
||||
public async changeFilesBackupsLocation(): Promise<string | undefined> {
|
||||
const oldLocation = this.getFilesBackupsLocation()
|
||||
const newLocation = await this.device.presentDirectoryPickerForLocationChangeAndTransferOld(
|
||||
const newLocation = await this.directory.presentDirectoryPickerForLocationChangeAndTransferOld(
|
||||
await this.prependWorkspacePathForPath(FileBackupsDirectoryName),
|
||||
oldLocation,
|
||||
)
|
||||
@@ -344,7 +346,7 @@ export class FilesBackupService extends AbstractService implements BackupService
|
||||
public async openFilesBackupsLocation(): Promise<void> {
|
||||
const location = this.getFilesBackupsLocation()
|
||||
if (location) {
|
||||
void this.device.openLocation(location)
|
||||
void this.directory.openLocation(location)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -389,7 +391,7 @@ export class FilesBackupService extends AbstractService implements BackupService
|
||||
|
||||
public async openFileBackup(record: FileBackupRecord): Promise<void> {
|
||||
const location = await this.getFileBackupAbsolutePath(record)
|
||||
await this.device.openLocation(location)
|
||||
await this.directory.openLocation(location)
|
||||
}
|
||||
|
||||
private async handleChangedFiles(files: FileItem[]): Promise<void> {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { ChallengeInterface } from './ChallengeInterface'
|
||||
import { ChallengePrompt } from './Prompt/ChallengePrompt'
|
||||
import { ChallengeReason } from './Types/ChallengeReason'
|
||||
import { ChallengeValidation } from './Types/ChallengeValidation'
|
||||
import { ChallengeValue } from './Types/ChallengeValue'
|
||||
|
||||
/**
|
||||
* A challenge is a stateless description of what the client needs to provide
|
||||
@@ -11,6 +12,7 @@ import { ChallengeValidation } from './Types/ChallengeValidation'
|
||||
*/
|
||||
export class Challenge implements ChallengeInterface {
|
||||
public readonly id = Math.random()
|
||||
customHandler?: (challenge: ChallengeInterface, values: ChallengeValue[]) => Promise<void>
|
||||
|
||||
constructor(
|
||||
public readonly prompts: ChallengePrompt[],
|
||||
@@ -18,9 +20,7 @@ export class Challenge implements ChallengeInterface {
|
||||
public readonly cancelable: boolean,
|
||||
public readonly _heading?: string,
|
||||
public readonly _subheading?: string,
|
||||
) {
|
||||
Object.freeze(this)
|
||||
}
|
||||
) {}
|
||||
|
||||
/** Outside of the modal, this is the title of the modal itself */
|
||||
get modalTitle(): string {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ChallengePromptInterface } from './Prompt/ChallengePromptInterface'
|
||||
import { ChallengeReason } from './Types/ChallengeReason'
|
||||
import { ChallengeValidation } from './Types/ChallengeValidation'
|
||||
import { ChallengeValue } from './Types/ChallengeValue'
|
||||
|
||||
export interface ChallengeInterface {
|
||||
readonly id: number
|
||||
@@ -8,6 +9,8 @@ export interface ChallengeInterface {
|
||||
readonly reason: ChallengeReason
|
||||
readonly cancelable: boolean
|
||||
|
||||
customHandler?: (challenge: ChallengeInterface, values: ChallengeValue[]) => Promise<void>
|
||||
|
||||
/** Outside of the modal, this is the title of the modal itself */
|
||||
get modalTitle(): string
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { Environment } from '@standardnotes/models'
|
||||
|
||||
import { HomeServerManagerInterface } from '../HomeServer/HomeServerManagerInterface'
|
||||
|
||||
import { WebClientRequiresDesktopMethods } from './DesktopWebCommunication'
|
||||
import { DeviceInterface } from './DeviceInterface'
|
||||
import { WebOrDesktopDeviceInterface } from './WebOrDesktopDeviceInterface'
|
||||
@@ -10,6 +12,9 @@ export function isDesktopDevice(x: DeviceInterface): x is DesktopDeviceInterface
|
||||
return x.environment === Environment.Desktop
|
||||
}
|
||||
|
||||
export interface DesktopDeviceInterface extends WebOrDesktopDeviceInterface, WebClientRequiresDesktopMethods {
|
||||
export interface DesktopDeviceInterface
|
||||
extends WebOrDesktopDeviceInterface,
|
||||
WebClientRequiresDesktopMethods,
|
||||
HomeServerManagerInterface {
|
||||
environment: Environment.Desktop
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { DecryptedTransferPayload } from '@standardnotes/models'
|
||||
import { DesktopWatchedDirectoriesChanges, FileBackupsDevice } from '@standardnotes/files'
|
||||
import { DesktopWatchedDirectoriesChanges, DirectoryManagerInterface, FileBackupsDevice } from '@standardnotes/files'
|
||||
|
||||
export interface WebClientRequiresDesktopMethods extends FileBackupsDevice {
|
||||
export interface WebClientRequiresDesktopMethods extends FileBackupsDevice, DirectoryManagerInterface {
|
||||
syncComponents(payloads: unknown[]): void
|
||||
|
||||
onSearch(text?: string): void
|
||||
@@ -21,4 +21,6 @@ export interface DesktopClientRequiresWebMethods {
|
||||
onComponentInstallationComplete(componentData: DecryptedTransferPayload, error: unknown): Promise<void>
|
||||
|
||||
handleWatchedDirectoriesChanges(changes: DesktopWatchedDirectoriesChanges): Promise<void>
|
||||
|
||||
handleHomeServerStarted(serverUrl: string): Promise<void>
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ApplicationInterface } from './../Application/ApplicationInterface'
|
||||
import { ApplicationIdentifier } from '@standardnotes/common'
|
||||
import {
|
||||
FullyFormedTransferPayload,
|
||||
@@ -31,6 +32,11 @@ export interface DeviceInterface {
|
||||
|
||||
removeAllRawStorageValues(): Promise<void>
|
||||
|
||||
removeRawStorageValuesForIdentifier(identifier: ApplicationIdentifier): Promise<void>
|
||||
|
||||
setApplication(application: ApplicationInterface): void
|
||||
removeApplication(application: ApplicationInterface): void
|
||||
|
||||
/**
|
||||
* On web platforms, databased created may be new.
|
||||
* New databases can be because of new sessions, or if the browser deleted it.
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
export interface HomeServerEnvironmentConfiguration {
|
||||
jwtSecret: string
|
||||
authJwtSecret: string
|
||||
encryptionServerKey: string
|
||||
pseudoKeyParamsKey: string
|
||||
valetTokenSecret: string
|
||||
port: number
|
||||
logLevel?: string
|
||||
databaseEngine: 'sqlite' | 'mysql'
|
||||
mysqlConfiguration?: {
|
||||
host: string
|
||||
port: number
|
||||
username: string
|
||||
password: string
|
||||
database: string
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
export interface HomeServerManagerInterface {
|
||||
startHomeServer(): Promise<string | undefined>
|
||||
setHomeServerConfiguration(configurationJSONString: string): Promise<void>
|
||||
getHomeServerConfiguration(): Promise<string | undefined>
|
||||
setHomeServerDataLocation(location: string): Promise<void>
|
||||
stopHomeServer(): Promise<string | undefined>
|
||||
activatePremiumFeatures(username: string): Promise<string | undefined>
|
||||
getHomeServerLogs(): Promise<string[]>
|
||||
isHomeServerRunning(): Promise<boolean>
|
||||
getHomeServerUrl(): Promise<string | undefined>
|
||||
getHomeServerLastErrorMessage(): Promise<string | undefined>
|
||||
}
|
||||
171
packages/services/src/Domain/HomeServer/HomeServerService.ts
Normal file
171
packages/services/src/Domain/HomeServer/HomeServerService.ts
Normal file
@@ -0,0 +1,171 @@
|
||||
import { Result } from '@standardnotes/domain-core'
|
||||
|
||||
import { ApplicationStage } from '../Application/ApplicationStage'
|
||||
import { DesktopDeviceInterface } from '../Device/DesktopDeviceInterface'
|
||||
import { InternalEventBusInterface } from '../Internal/InternalEventBusInterface'
|
||||
import { AbstractService } from '../Service/AbstractService'
|
||||
import { RawStorageKey } from '../Storage/StorageKeys'
|
||||
|
||||
import { HomeServerServiceInterface } from './HomeServerServiceInterface'
|
||||
import { HomeServerEnvironmentConfiguration } from './HomeServerEnvironmentConfiguration'
|
||||
import { HomeServerStatus } from './HomeServerStatus'
|
||||
|
||||
export class HomeServerService extends AbstractService implements HomeServerServiceInterface {
|
||||
private readonly HOME_SERVER_DATA_DIRECTORY_NAME = '.homeserver'
|
||||
|
||||
constructor(
|
||||
private desktopDevice: DesktopDeviceInterface,
|
||||
protected override internalEventBus: InternalEventBusInterface,
|
||||
) {
|
||||
super(internalEventBus)
|
||||
}
|
||||
|
||||
override deinit() {
|
||||
;(this.desktopDevice as unknown) = undefined
|
||||
super.deinit()
|
||||
}
|
||||
|
||||
override async handleApplicationStage(stage: ApplicationStage) {
|
||||
await super.handleApplicationStage(stage)
|
||||
|
||||
switch (stage) {
|
||||
case ApplicationStage.StorageDecrypted_09: {
|
||||
await this.setHomeServerDataLocationOnDevice()
|
||||
break
|
||||
}
|
||||
case ApplicationStage.Launched_10: {
|
||||
await this.startHomeServerIfItIsEnabled()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async getHomeServerStatus(): Promise<HomeServerStatus> {
|
||||
const isHomeServerRunning = await this.desktopDevice.isHomeServerRunning()
|
||||
|
||||
if (!isHomeServerRunning) {
|
||||
return { status: 'off', errorMessage: await this.desktopDevice.getHomeServerLastErrorMessage() }
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'on',
|
||||
url: await this.getHomeServerUrl(),
|
||||
}
|
||||
}
|
||||
|
||||
async getHomeServerLogs(): Promise<string[]> {
|
||||
return this.desktopDevice.getHomeServerLogs()
|
||||
}
|
||||
|
||||
async getHomeServerUrl(): Promise<string | undefined> {
|
||||
return this.desktopDevice.getHomeServerUrl()
|
||||
}
|
||||
|
||||
async startHomeServer(): Promise<string | undefined> {
|
||||
return this.desktopDevice.startHomeServer()
|
||||
}
|
||||
|
||||
async stopHomeServer(): Promise<string | undefined> {
|
||||
return this.desktopDevice.stopHomeServer()
|
||||
}
|
||||
|
||||
async isHomeServerRunning(): Promise<boolean> {
|
||||
return this.desktopDevice.isHomeServerRunning()
|
||||
}
|
||||
|
||||
async activatePremiumFeatures(username: string): Promise<Result<string>> {
|
||||
const result = await this.desktopDevice.activatePremiumFeatures(username)
|
||||
|
||||
if (result !== undefined) {
|
||||
return Result.fail(result)
|
||||
}
|
||||
|
||||
return Result.ok('Premium features activated')
|
||||
}
|
||||
|
||||
async setHomeServerConfiguration(config: HomeServerEnvironmentConfiguration): Promise<void> {
|
||||
await this.desktopDevice.setHomeServerConfiguration(JSON.stringify(config))
|
||||
}
|
||||
|
||||
async getHomeServerConfiguration(): Promise<HomeServerEnvironmentConfiguration | undefined> {
|
||||
const configurationJSONString = await this.desktopDevice.getHomeServerConfiguration()
|
||||
if (!configurationJSONString) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return JSON.parse(configurationJSONString) as HomeServerEnvironmentConfiguration
|
||||
}
|
||||
|
||||
async enableHomeServer(): Promise<void> {
|
||||
await this.desktopDevice.setRawStorageValue(RawStorageKey.HomeServerEnabled, 'true')
|
||||
|
||||
await this.startHomeServer()
|
||||
}
|
||||
|
||||
async isHomeServerEnabled(): Promise<boolean> {
|
||||
const value = await this.desktopDevice.getRawStorageValue(RawStorageKey.HomeServerEnabled)
|
||||
|
||||
return value === 'true'
|
||||
}
|
||||
|
||||
async getHomeServerDataLocation(): Promise<string | undefined> {
|
||||
return this.desktopDevice.getRawStorageValue(RawStorageKey.HomeServerDataLocation)
|
||||
}
|
||||
|
||||
async disableHomeServer(): Promise<Result<string>> {
|
||||
await this.desktopDevice.setRawStorageValue(RawStorageKey.HomeServerEnabled, 'false')
|
||||
|
||||
const result = await this.stopHomeServer()
|
||||
if (result !== undefined) {
|
||||
return Result.fail(result)
|
||||
}
|
||||
|
||||
return Result.ok('Home server disabled')
|
||||
}
|
||||
|
||||
async changeHomeServerDataLocation(): Promise<Result<string>> {
|
||||
const oldLocation = await this.getHomeServerDataLocation()
|
||||
const newLocation = await this.desktopDevice.presentDirectoryPickerForLocationChangeAndTransferOld(
|
||||
this.HOME_SERVER_DATA_DIRECTORY_NAME,
|
||||
oldLocation,
|
||||
)
|
||||
|
||||
if (!newLocation) {
|
||||
const lastErrorMessage = await this.desktopDevice.getDirectoryManagerLastErrorMessage()
|
||||
|
||||
return Result.fail(lastErrorMessage ?? 'No location selected')
|
||||
}
|
||||
|
||||
await this.desktopDevice.setRawStorageValue(RawStorageKey.HomeServerDataLocation, newLocation)
|
||||
|
||||
await this.desktopDevice.setHomeServerDataLocation(newLocation)
|
||||
|
||||
return Result.ok(newLocation)
|
||||
}
|
||||
|
||||
async openHomeServerDataLocation(): Promise<void> {
|
||||
const location = await this.getHomeServerDataLocation()
|
||||
if (location) {
|
||||
void this.desktopDevice.openLocation(location)
|
||||
}
|
||||
}
|
||||
|
||||
private async startHomeServerIfItIsEnabled(): Promise<void> {
|
||||
const homeServerIsEnabled = await this.isHomeServerEnabled()
|
||||
if (homeServerIsEnabled) {
|
||||
await this.startHomeServer()
|
||||
}
|
||||
}
|
||||
|
||||
private async setHomeServerDataLocationOnDevice(): Promise<void> {
|
||||
let location = await this.getHomeServerDataLocation()
|
||||
if (!location) {
|
||||
const documentsDirectory = await this.desktopDevice.getUserDocumentsDirectory()
|
||||
location = `${documentsDirectory}/${this.HOME_SERVER_DATA_DIRECTORY_NAME}`
|
||||
}
|
||||
|
||||
await this.desktopDevice.setRawStorageValue(RawStorageKey.HomeServerDataLocation, location)
|
||||
|
||||
await this.desktopDevice.setHomeServerDataLocation(location)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Result } from '@standardnotes/domain-core'
|
||||
|
||||
import { HomeServerEnvironmentConfiguration } from './HomeServerEnvironmentConfiguration'
|
||||
import { HomeServerStatus } from './HomeServerStatus'
|
||||
|
||||
export interface HomeServerServiceInterface {
|
||||
activatePremiumFeatures(username: string): Promise<Result<string>>
|
||||
isHomeServerRunning(): Promise<boolean>
|
||||
isHomeServerEnabled(): Promise<boolean>
|
||||
getHomeServerDataLocation(): Promise<string | undefined>
|
||||
enableHomeServer(): Promise<void>
|
||||
disableHomeServer(): Promise<Result<string>>
|
||||
startHomeServer(): Promise<string | undefined>
|
||||
stopHomeServer(): Promise<string | undefined>
|
||||
changeHomeServerDataLocation(): Promise<Result<string>>
|
||||
openHomeServerDataLocation(): Promise<void>
|
||||
getHomeServerConfiguration(): Promise<HomeServerEnvironmentConfiguration | undefined>
|
||||
setHomeServerConfiguration(config: HomeServerEnvironmentConfiguration): Promise<void>
|
||||
getHomeServerUrl(): Promise<string | undefined>
|
||||
getHomeServerStatus(): Promise<HomeServerStatus>
|
||||
getHomeServerLogs(): Promise<string[]>
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export type HomeServerStatus = {
|
||||
status: 'on' | 'off'
|
||||
url?: string
|
||||
errorMessage?: string
|
||||
}
|
||||
@@ -2,14 +2,14 @@
|
||||
|
||||
import { log, removeFromArray } from '@standardnotes/utils'
|
||||
import { EventObserver } from '../Event/EventObserver'
|
||||
import { ServiceInterface } from './ServiceInterface'
|
||||
import { ApplicationServiceInterface } from './ApplicationServiceInterface'
|
||||
import { InternalEventBusInterface } from '../Internal/InternalEventBusInterface'
|
||||
import { ApplicationStage } from '../Application/ApplicationStage'
|
||||
import { InternalEventPublishStrategy } from '../Internal/InternalEventPublishStrategy'
|
||||
import { DiagnosticInfo } from '../Diagnostics/ServiceDiagnostics'
|
||||
|
||||
export abstract class AbstractService<EventName = string, EventData = unknown>
|
||||
implements ServiceInterface<EventName, EventData>
|
||||
implements ApplicationServiceInterface<EventName, EventData>
|
||||
{
|
||||
private eventObservers: EventObserver<EventName, EventData>[] = []
|
||||
public loggingEnabled = false
|
||||
|
||||
@@ -2,7 +2,7 @@ import { ApplicationStage } from '../Application/ApplicationStage'
|
||||
import { ServiceDiagnostics } from '../Diagnostics/ServiceDiagnostics'
|
||||
import { EventObserver } from '../Event/EventObserver'
|
||||
|
||||
export interface ServiceInterface<E, D> extends ServiceDiagnostics {
|
||||
export interface ApplicationServiceInterface<E, D> extends ServiceDiagnostics {
|
||||
loggingEnabled: boolean
|
||||
addEventObserver(observer: EventObserver<E, D>): () => void
|
||||
blockDeinit(): Promise<void>
|
||||
@@ -12,6 +12,7 @@ export interface SessionsClientInterface {
|
||||
populateSessionFromDemoShareToken(token: Base64String): Promise<void>
|
||||
|
||||
getUser(): User | undefined
|
||||
isSignedIn(): boolean
|
||||
get userUuid(): string
|
||||
getSureUser(): User
|
||||
|
||||
@@ -24,7 +25,6 @@ export interface SessionsClientInterface {
|
||||
ephemeral: boolean,
|
||||
minAllowedVersion?: ProtocolVersion,
|
||||
): Promise<SessionManagerResponse>
|
||||
isSignedIn(): boolean
|
||||
bypassChecksAndSignInWithRootKey(
|
||||
email: string,
|
||||
rootKey: RootKeyInterface,
|
||||
|
||||
@@ -6,6 +6,8 @@ export enum RawStorageKey {
|
||||
StorageObject = 'storage',
|
||||
DescriptorRecord = 'descriptors',
|
||||
SnjsVersion = 'snjs_version',
|
||||
HomeServerEnabled = 'home_server_enabled',
|
||||
HomeServerDataLocation = 'home_serve_data_location',
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -51,7 +51,9 @@ export * from './Device/DeviceInterface'
|
||||
export * from './Device/MobileDeviceInterface'
|
||||
export * from './Device/TypeCheck'
|
||||
export * from './Device/WebOrDesktopDeviceInterface'
|
||||
|
||||
export * from './Device/DatabaseLoadOptions'
|
||||
export * from './Device/DatabaseItemMetadata'
|
||||
export * from './Device/DatabaseLoadSorter'
|
||||
export * from './Diagnostics/ServiceDiagnostics'
|
||||
|
||||
export * from './Encryption/DecryptBackupFileUseCase'
|
||||
@@ -77,7 +79,11 @@ export * from './Feature/SetOfflineFeaturesFunctionResponse'
|
||||
export * from './Files/FileService'
|
||||
|
||||
export * from './History/HistoryServiceInterface'
|
||||
|
||||
export * from './HomeServer/HomeServerEnvironmentConfiguration'
|
||||
export * from './HomeServer/HomeServerManagerInterface'
|
||||
export * from './HomeServer/HomeServerService'
|
||||
export * from './HomeServer/HomeServerServiceInterface'
|
||||
export * from './HomeServer/HomeServerStatus'
|
||||
export * from './Integrity/IntegrityApiInterface'
|
||||
export * from './Integrity/IntegrityEvent'
|
||||
export * from './Integrity/IntegrityEventPayload'
|
||||
@@ -114,8 +120,7 @@ export * from './Revision/RevisionClientInterface'
|
||||
export * from './Revision/RevisionManager'
|
||||
|
||||
export * from './Service/AbstractService'
|
||||
export * from './Service/ServiceInterface'
|
||||
|
||||
export * from './Service/ApplicationServiceInterface'
|
||||
export * from './Session/SessionManagerResponse'
|
||||
export * from './Session/SessionsClientInterface'
|
||||
export * from './Session/SessionEvent'
|
||||
|
||||
Reference in New Issue
Block a user