import {Awaitable, DecodedValue, EncodedValue, Instantiable, isInstantiable, KeyValue} from '../types' import * as uuid from 'uuid' /** * Error thrown when a key fails to decode an encoded value. */ export class InvalidKeyError extends Error { constructor() { super('The provided key is invalid and cannot be used to decode the payload.') } } /** * Base class for implementations that encode and decode values using some key. */ export abstract class Cryptor { /** Function used to instantiate the Cryptor. */ protected static factoryFunction?: (key: KeyValue) => Cryptor /** Generate a new, random encryption key. */ public static getNewKey(): string { return uuid.v4().replace(/-/g, '') } /** * Get a factory that produces an instance of this cryptor. */ public static getFactory(): (key: KeyValue) => Cryptor { if ( !this.factoryFunction ) { const ctor = this as typeof Cryptor if ( !isInstantiable(ctor) ) { throw new Error('Cannot create factory for abstract Cryptor.') } this.factoryFunction = key => new (ctor as Instantiable)(key) } return this.factoryFunction } constructor( /** The key used by this cryptor. */ protected key: KeyValue, ) {} /** * Using the key, encode the value. * @param value */ public abstract encode(value: DecodedValue): Awaitable /** * Using the key, decode the value. * @param payload */ public abstract decode(payload: EncodedValue): Awaitable /** Get the key used by this Cryptor. */ public getKey(): KeyValue { return this.key } }