feat: add services package
This commit is contained in:
24
packages/services/src/Domain/Storage/InMemoryStore.spec.ts
Normal file
24
packages/services/src/Domain/Storage/InMemoryStore.spec.ts
Normal 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()
|
||||
})
|
||||
})
|
||||
22
packages/services/src/Domain/Storage/InMemoryStore.ts
Normal file
22
packages/services/src/Domain/Storage/InMemoryStore.ts
Normal 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)
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
7
packages/services/src/Domain/Storage/StorageKeys.spec.ts
Normal file
7
packages/services/src/Domain/Storage/StorageKeys.spec.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { namespacedKey } from './StorageKeys'
|
||||
|
||||
describe('StorageKeys', () => {
|
||||
it('namespacedKey', () => {
|
||||
expect(namespacedKey('namespace', 'key')).toEqual('namespace-key')
|
||||
})
|
||||
})
|
||||
66
packages/services/src/Domain/Storage/StorageKeys.ts
Normal file
66
packages/services/src/Domain/Storage/StorageKeys.ts
Normal 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',
|
||||
}
|
||||
@@ -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>
|
||||
}
|
||||
39
packages/services/src/Domain/Storage/StorageTypes.ts
Normal file
39
packages/services/src/Domain/Storage/StorageTypes.ts
Normal 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
|
||||
}
|
||||
Reference in New Issue
Block a user