/**
 * The OverrideCode class wraps given functions so that they can be later
 * overrided when used any where, including in external libraries.
 *
 * This is specially usefull when overrided library are imported by destructuring.
 * In this scenario, the code gets a direct reference to the library function,
 * so it can not be override later on.
 *
 * Exemple:
 *
 * ```typescript
 * import * as crypto from 'crypto';
 * OverrideCode.wrap(crypto, 'sign', 'crypto.sign');
 * OverrideCode.override('crypto.sign', (...args) => {
 *   // do anything...
 *
 *   // optionnally call original wrapped function
 *   const original = OverrideCode.getOriginal('crypto.sign');
 *   const result = original(...args);
 * });
 * ```
 */ export class OverrideCode { private static originalRefStore : { [ key ] : any ; } = { } ; private static overrideStore : { [ key ] : any ; } = { } ; param originalObject param functionName param key throws static wrap ( originalObject , functionName , key = functionName ) { if ( ! ( functionName in originalObject ) ) { throw new TypeError ( `Tried to wrap unexistant propery <${ functionName }> of object` ) ; } OverrideCode . originalRefStore [ key ] = originalObject [ functionName ] ; OverrideCode . overrideStore [ key ] = ( ... args ) => OverrideCode . originalRefStore [ key ] ( ... args ) ; originalObject [ functionName ] = ( ... args ) => OverrideCode . overrideStore [ key ] ( ... args ) ; } param key returns throws static getOriginal ( key ) { if ( ! ( key in OverrideCode . originalRefStore ) ) { throw new TypeError ( `Tried to get unknown wrapped <${ key }>` ) ; } return OverrideCode . originalRefStore [ key ] ; } param key param overrideFunction static override ( key , overrideFunction ) { OverrideCode . overrideStore [ key ] = overrideFunction ; } }