feat: add services package

This commit is contained in:
Karol Sójko
2022-07-05 20:51:42 +02:00
parent b614c71e79
commit fbfed0a05c
85 changed files with 2418 additions and 28 deletions

View File

@@ -0,0 +1,24 @@
import { InMemoryStore } from './InMemoryStore'
import { StorageKey } from './StorageKeys'
describe('InMemoryStore', () => {
const createStore = () => new InMemoryStore()
it('should set and retrieve a value', () => {
const store = createStore()
store.setValue(StorageKey.CodeVerifier, 'test')
expect(store.getValue(StorageKey.CodeVerifier)).toEqual('test')
})
it('should remove a value', () => {
const store = createStore()
store.setValue(StorageKey.CodeVerifier, 'test')
store.removeValue(StorageKey.CodeVerifier)
expect(store.getValue(StorageKey.CodeVerifier)).toBeUndefined()
})
})

View File

@@ -0,0 +1,22 @@
import { KeyValueStoreInterface } from './KeyValueStoreInterface'
import { StorageKey } from './StorageKeys'
export class InMemoryStore implements KeyValueStoreInterface<string> {
private values: Map<StorageKey, string>
constructor() {
this.values = new Map<StorageKey, string>()
}
setValue(key: StorageKey, value: string): void {
this.values.set(key, value)
}
getValue(key: StorageKey): string | undefined {
return this.values.get(key)
}
removeValue(key: StorageKey): void {
this.values.delete(key)
}
}

View File

@@ -0,0 +1,7 @@
import { StorageKey } from './StorageKeys'
export interface KeyValueStoreInterface<T> {
setValue(key: StorageKey, value: T): void
getValue(key: StorageKey): T | undefined
removeValue(key: StorageKey): void
}

View File

@@ -0,0 +1,7 @@
import { namespacedKey } from './StorageKeys'
describe('StorageKeys', () => {
it('namespacedKey', () => {
expect(namespacedKey('namespace', 'key')).toEqual('namespace-key')
})
})

View File

@@ -0,0 +1,66 @@
/**
* Unmanaged keys stored in root storage.
* Raw storage keys exist outside of StorageManager domain
*/
export enum RawStorageKey {
StorageObject = 'storage',
DescriptorRecord = 'descriptors',
SnjsVersion = 'snjs_version',
}
/**
* Keys used for retrieving and saving simple key/value pairs.
* These keys are managed and are embedded inside RawStorageKey.StorageObject
*/
export enum StorageKey {
RootKeyParams = 'ROOT_KEY_PARAMS',
WrappedRootKey = 'WRAPPED_ROOT_KEY',
RootKeyWrapperKeyParams = 'ROOT_KEY_WRAPPER_KEY_PARAMS',
Session = 'session',
User = 'user',
ServerHost = 'server',
LegacyUuid = 'uuid',
LastSyncToken = 'syncToken',
PaginationToken = 'cursorToken',
BiometricsState = 'biometrics_state',
MobilePasscodeTiming = 'passcode_timing',
MobileBiometricsTiming = 'biometrics_timing',
MobilePasscodeKeyboardType = 'passcodeKeyboardType',
MobilePreferences = 'preferences',
MobileScreenshotPrivacyEnabled = 'screenshotPrivacy_enabled',
ProtectionExpirey = 'SessionExpiresAtKey',
ProtectionSessionLength = 'SessionLengthKey',
KeyRecoveryUndecryptableItems = 'key_recovery_undecryptable',
StorageEncryptionPolicy = 'storage_policy',
WebSocketUrl = 'webSocket_url',
UserRoles = 'user_roles',
UserFeatures = 'user_features',
ExperimentalFeatures = 'experimental_features',
DeinitMode = 'deinit_mode',
CodeVerifier = 'code_verifier',
}
export enum NonwrappedStorageKey {
MobileFirstRun = 'first_run',
}
export function namespacedKey(namespace: string, key: string) {
return `${namespace}-${key}`
}
export const LegacyKeys1_0_0 = {
WebPasscodeParamsKey: 'offlineParams',
MobilePasscodeParamsKey: 'pc_params',
AllAccountKeyParamsKey: 'auth_params',
WebEncryptedStorageKey: 'encryptedStorage',
MobileWrappedRootKeyKey: 'encrypted_account_keys',
MobileBiometricsPrefs: 'biometrics_prefs',
AllMigrations: 'migrations',
MobileThemesCache: 'ThemePreferencesKey',
MobileLightTheme: 'lightTheme',
MobileDarkTheme: 'darkTheme',
MobileLastExportDate: 'LastExportDateKey',
MobileDoNotWarnUnsupportedEditors: 'DoNotShowAgainUnsupportedEditorsKey',
MobileOptionsState: 'options',
MobilePasscodeKeyboardType: 'passcodeKeyboardType',
}

View File

@@ -0,0 +1,16 @@
import { PayloadInterface, RootKeyInterface } from '@standardnotes/models'
import { StorageValueModes } from './StorageTypes'
export interface StorageServiceInterface {
getValue<T>(key: string, mode?: StorageValueModes, defaultValue?: T): T
canDecryptWithKey(key: RootKeyInterface): Promise<boolean>
savePayload(payload: PayloadInterface): Promise<void>
savePayloads(decryptedPayloads: PayloadInterface[]): Promise<void>
setValue(key: string, value: unknown, mode?: StorageValueModes): void
removeValue(key: string, mode?: StorageValueModes): Promise<void>
}

View File

@@ -0,0 +1,39 @@
import { LocalStorageEncryptedContextualPayload, LocalStorageDecryptedContextualPayload } from '@standardnotes/models'
/* istanbul ignore file */
export enum StoragePersistencePolicies {
Default = 1,
Ephemeral = 2,
}
export enum StorageEncryptionPolicy {
Default = 1,
Disabled = 2,
}
export enum StorageValueModes {
/** Stored inside wrapped encrpyed storage object */
Default = 1,
/** Stored outside storage object, unencrypted */
Nonwrapped = 2,
}
export enum ValueModesKeys {
/* Is encrypted */
Wrapped = 'wrapped',
/* Is decrypted */
Unwrapped = 'unwrapped',
/* Lives outside of wrapped/unwrapped */
Nonwrapped = 'nonwrapped',
}
export type ValuesObjectRecord = Record<string, unknown>
export type WrappedStorageValue = LocalStorageEncryptedContextualPayload | LocalStorageDecryptedContextualPayload
export type StorageValuesObject = {
[ValueModesKeys.Wrapped]: WrappedStorageValue
[ValueModesKeys.Unwrapped]: ValuesObjectRecord
[ValueModesKeys.Nonwrapped]: ValuesObjectRecord
}