feat: add snjs package
This commit is contained in:
81
packages/snjs/lib/Services/Settings/SNSettingsService.ts
Normal file
81
packages/snjs/lib/Services/Settings/SNSettingsService.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { SNApiService } from '../Api/ApiService'
|
||||
import { SettingsGateway } from './SettingsGateway'
|
||||
import { SNSessionManager } from '../Session/SessionManager'
|
||||
import {
|
||||
CloudProvider,
|
||||
EmailBackupFrequency,
|
||||
SettingName,
|
||||
SensitiveSettingName,
|
||||
SubscriptionSettingName,
|
||||
} from '@standardnotes/settings'
|
||||
import { ExtensionsServerURL } from '@Lib/Hosts'
|
||||
import { AbstractService, InternalEventBusInterface } from '@standardnotes/services'
|
||||
import { SettingsClientInterface } from './SettingsClientInterface'
|
||||
|
||||
export class SNSettingsService extends AbstractService implements SettingsClientInterface {
|
||||
private provider!: SettingsGateway
|
||||
private frequencyOptionsLabels = {
|
||||
[EmailBackupFrequency.Disabled]: 'No email backups',
|
||||
[EmailBackupFrequency.Daily]: 'Daily',
|
||||
[EmailBackupFrequency.Weekly]: 'Weekly',
|
||||
}
|
||||
|
||||
private cloudProviderIntegrationUrlEndpoints = {
|
||||
[CloudProvider.Dropbox]: 'dropbox',
|
||||
[CloudProvider.Google]: 'gdrive',
|
||||
[CloudProvider.OneDrive]: 'onedrive',
|
||||
}
|
||||
|
||||
constructor(
|
||||
private readonly sessionManager: SNSessionManager,
|
||||
private readonly apiService: SNApiService,
|
||||
protected override internalEventBus: InternalEventBusInterface,
|
||||
) {
|
||||
super(internalEventBus)
|
||||
}
|
||||
|
||||
initializeFromDisk(): void {
|
||||
this.provider = new SettingsGateway(this.apiService, this.sessionManager)
|
||||
}
|
||||
|
||||
async listSettings() {
|
||||
return this.provider.listSettings()
|
||||
}
|
||||
|
||||
async getSetting(name: SettingName) {
|
||||
return this.provider.getSetting(name)
|
||||
}
|
||||
|
||||
async getSubscriptionSetting(name: SubscriptionSettingName) {
|
||||
return this.provider.getSubscriptionSetting(name)
|
||||
}
|
||||
|
||||
async updateSetting(name: SettingName, payload: string, sensitive = false) {
|
||||
return this.provider.updateSetting(name, payload, sensitive)
|
||||
}
|
||||
|
||||
async getDoesSensitiveSettingExist(name: SensitiveSettingName) {
|
||||
return this.provider.getDoesSensitiveSettingExist(name)
|
||||
}
|
||||
|
||||
async deleteSetting(name: SettingName) {
|
||||
return this.provider.deleteSetting(name)
|
||||
}
|
||||
|
||||
getEmailBackupFrequencyOptionLabel(frequency: EmailBackupFrequency): string {
|
||||
return this.frequencyOptionsLabels[frequency]
|
||||
}
|
||||
|
||||
getCloudProviderIntegrationUrl(cloudProviderName: CloudProvider, isDevEnvironment: boolean): string {
|
||||
const { Dev, Prod } = ExtensionsServerURL
|
||||
const extServerUrl = isDevEnvironment ? Dev : Prod
|
||||
return `${extServerUrl}/${this.cloudProviderIntegrationUrlEndpoints[cloudProviderName]}?redirect_url=${extServerUrl}/components/cloudlink?`
|
||||
}
|
||||
|
||||
override deinit(): void {
|
||||
this.provider?.deinit()
|
||||
;(this.provider as unknown) = undefined
|
||||
;(this.sessionManager as unknown) = undefined
|
||||
;(this.apiService as unknown) = undefined
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { SettingName, SensitiveSettingName, EmailBackupFrequency } from '@standardnotes/settings'
|
||||
import { SettingsList } from './SettingsList'
|
||||
|
||||
export interface SettingsClientInterface {
|
||||
listSettings(): Promise<SettingsList>
|
||||
|
||||
getSetting(name: SettingName): Promise<string | undefined>
|
||||
|
||||
getDoesSensitiveSettingExist(name: SensitiveSettingName): Promise<boolean>
|
||||
|
||||
updateSetting(name: SettingName, payload: string, sensitive?: boolean): Promise<void>
|
||||
|
||||
deleteSetting(name: SettingName): Promise<void>
|
||||
|
||||
getEmailBackupFrequencyOptionLabel(frequency: EmailBackupFrequency): string
|
||||
}
|
||||
110
packages/snjs/lib/Services/Settings/SettingsGateway.ts
Normal file
110
packages/snjs/lib/Services/Settings/SettingsGateway.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
import { SettingsList } from './SettingsList'
|
||||
import { SettingName, SensitiveSettingName, SubscriptionSettingName } from '@standardnotes/settings'
|
||||
import * as messages from '../Api/Messages'
|
||||
import { StatusCode, User } from '@standardnotes/responses'
|
||||
import { SettingsServerInterface } from './SettingsServerInterface'
|
||||
|
||||
/**
|
||||
* SettingsGateway coordinates communication with the API service
|
||||
* wrapping the userUuid provision for simpler consumption
|
||||
*/
|
||||
export class SettingsGateway {
|
||||
constructor(
|
||||
private readonly settingsApi: SettingsServerInterface,
|
||||
private readonly userProvider: { getUser: () => User | undefined },
|
||||
) {}
|
||||
|
||||
isReadyForModification(): boolean {
|
||||
return this.getUser() != undefined
|
||||
}
|
||||
|
||||
private getUser() {
|
||||
return this.userProvider.getUser()
|
||||
}
|
||||
|
||||
private get userUuid() {
|
||||
const user = this.getUser()
|
||||
if (user == undefined || user.uuid == undefined) {
|
||||
throw new Error(messages.API_MESSAGE_INVALID_SESSION)
|
||||
}
|
||||
return user.uuid
|
||||
}
|
||||
|
||||
async listSettings() {
|
||||
const { error, data } = await this.settingsApi.listSettings(this.userUuid)
|
||||
|
||||
if (error != undefined) {
|
||||
throw new Error(error.message)
|
||||
}
|
||||
|
||||
if (data == undefined || data.settings == undefined) {
|
||||
return new SettingsList([])
|
||||
}
|
||||
|
||||
const settings: SettingsList = new SettingsList(data.settings)
|
||||
return settings
|
||||
}
|
||||
|
||||
async getSetting(name: SettingName): Promise<string | undefined> {
|
||||
const response = await this.settingsApi.getSetting(this.userUuid, name)
|
||||
|
||||
// Backend responds with 400 when setting doesn't exist
|
||||
if (response.status === StatusCode.HttpBadRequest) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
if (response.error != undefined) {
|
||||
throw new Error(response.error.message)
|
||||
}
|
||||
|
||||
return response?.data?.setting?.value ?? undefined
|
||||
}
|
||||
|
||||
async getSubscriptionSetting(name: SubscriptionSettingName): Promise<string | undefined> {
|
||||
const response = await this.settingsApi.getSubscriptionSetting(this.userUuid, name)
|
||||
|
||||
if (response.status === StatusCode.HttpBadRequest) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
if (response.error != undefined) {
|
||||
throw new Error(response.error.message)
|
||||
}
|
||||
|
||||
return response?.data?.setting?.value ?? undefined
|
||||
}
|
||||
|
||||
async getDoesSensitiveSettingExist(name: SensitiveSettingName): Promise<boolean> {
|
||||
const response = await this.settingsApi.getSetting(this.userUuid, name)
|
||||
|
||||
// Backend responds with 400 when setting doesn't exist
|
||||
if (response.status === StatusCode.HttpBadRequest) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (response.error != undefined) {
|
||||
throw new Error(response.error.message)
|
||||
}
|
||||
|
||||
return response.data?.success ?? false
|
||||
}
|
||||
|
||||
async updateSetting(name: SettingName, payload: string, sensitive: boolean): Promise<void> {
|
||||
const { error } = await this.settingsApi.updateSetting(this.userUuid, name, payload, sensitive)
|
||||
if (error != undefined) {
|
||||
throw new Error(error.message)
|
||||
}
|
||||
}
|
||||
|
||||
async deleteSetting(name: SettingName): Promise<void> {
|
||||
const { error } = await this.settingsApi.deleteSetting(this.userUuid, name)
|
||||
if (error != undefined) {
|
||||
throw new Error(error.message)
|
||||
}
|
||||
}
|
||||
|
||||
deinit() {
|
||||
;(this.settingsApi as unknown) = undefined
|
||||
;(this.userProvider as unknown) = undefined
|
||||
}
|
||||
}
|
||||
41
packages/snjs/lib/Services/Settings/SettingsList.ts
Normal file
41
packages/snjs/lib/Services/Settings/SettingsList.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { SettingData } from '@standardnotes/responses'
|
||||
import {
|
||||
OneDriveBackupFrequency,
|
||||
MuteSignInEmailsOption,
|
||||
MuteFailedCloudBackupsEmailsOption,
|
||||
MuteFailedBackupsEmailsOption,
|
||||
CloudProvider,
|
||||
DropboxBackupFrequency,
|
||||
EmailBackupFrequency,
|
||||
GoogleDriveBackupFrequency,
|
||||
ListedAuthorSecretsData,
|
||||
LogSessionUserAgentOption,
|
||||
SettingName,
|
||||
} from '@standardnotes/settings'
|
||||
|
||||
type SettingType =
|
||||
| CloudProvider
|
||||
| DropboxBackupFrequency
|
||||
| EmailBackupFrequency
|
||||
| GoogleDriveBackupFrequency
|
||||
| ListedAuthorSecretsData
|
||||
| LogSessionUserAgentOption
|
||||
| MuteFailedBackupsEmailsOption
|
||||
| MuteFailedCloudBackupsEmailsOption
|
||||
| MuteSignInEmailsOption
|
||||
| OneDriveBackupFrequency
|
||||
|
||||
export class SettingsList {
|
||||
private map: Partial<Record<SettingName, SettingData>> = {}
|
||||
|
||||
constructor(settings: SettingData[]) {
|
||||
for (const setting of settings) {
|
||||
this.map[setting.name as SettingName] = setting
|
||||
}
|
||||
}
|
||||
|
||||
getSettingValue<T = SettingType, D = SettingType>(setting: SettingName, defaultValue: D): T {
|
||||
const settingData = this.map[setting]
|
||||
return (settingData?.value as unknown as T) || (defaultValue as unknown as T)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import {
|
||||
DeleteSettingResponse,
|
||||
GetSettingResponse,
|
||||
ListSettingsResponse,
|
||||
UpdateSettingResponse,
|
||||
} from '@standardnotes/responses'
|
||||
import { UuidString } from '@Lib/Types/UuidString'
|
||||
|
||||
export interface SettingsServerInterface {
|
||||
listSettings(userUuid: UuidString): Promise<ListSettingsResponse>
|
||||
|
||||
updateSetting(
|
||||
userUuid: UuidString,
|
||||
settingName: string,
|
||||
settingValue: string,
|
||||
sensitive: boolean,
|
||||
): Promise<UpdateSettingResponse>
|
||||
|
||||
getSetting(userUuid: UuidString, settingName: string): Promise<GetSettingResponse>
|
||||
|
||||
getSubscriptionSetting(userUuid: UuidString, settingName: string): Promise<GetSettingResponse>
|
||||
|
||||
deleteSetting(userUuid: UuidString, settingName: string): Promise<DeleteSettingResponse>
|
||||
}
|
||||
1
packages/snjs/lib/Services/Settings/index.ts
Normal file
1
packages/snjs/lib/Services/Settings/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './SNSettingsService'
|
||||
Reference in New Issue
Block a user