Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | 26x 26x 26x 1457x 26x 2455x 5x 2450x 993x 1457x 1211x 246x 243x 3x 1244x 1244x 1244x 1225x 2035x 4x 26x 7x 2x 5x 4x 1x | import { OptionalType, RequiredType, guardFunctions, isConstructor, isNotPresent } from "@jonloucks/contracts-ts/api/Types";
import { presentCheck } from "@jonloucks/contracts-ts/auxiliary/Checks";
/**
* Interface for providing a deliverable for a Contract
* The main and required implementation is demand().
* There are optional methods with appropriate defaults.
* @param <T> The type of the deliverable
*/
export interface Promisor<T> {
/**
* Return the deliverable promised for a Contract
* @return the current deliverable
*/
demand(): OptionalType<T>;
/**
* Reference counting used for advanced resource management
* Incremented when bound or by other Promisors
* Every successful 'open' must be followed by a 'close' at the appropriate time
* @return the usage count. This might be a constant
*/
incrementUsage(): number;
/**
* Reference counting used for advanced resource management
* Decremented when no longer used
* Every successful 'open' must be followed by a 'close' at the appropriate time
* @return the usage count. This might be a constant
*/
decrementUsage(): number;
}
/**
* Check if an instance is a Promisor
* @param instance the instance to check
* @returns true if the instance is a Promisor, false otherwise
*/
export function guard<T>(instance: unknown): instance is RequiredType<Promisor<T>> {
return guardFunctions(instance, 'demand', 'incrementUsage', 'decrementUsage');
}
/**
* A type that can be converted to a Promisor
*/
export type PromisorType<T> = (new () => T) | Promisor<T> | (() => OptionalType<T>) | (() => () => T) | T | null | undefined;
/**
* Convert a PromisorType to a Promisor
*
* @param type the type to convert
* @returns the Promisor
*/
export function typeToPromisor<T>(type: PromisorType<T>): RequiredType<Promisor<T>> {
if (isNotPresent(type)) {
return wrapPromisor<T>(type, () => type); // supplier of null or undefined
} else if (isConstructor<T>(type)) {
return wrapPromisor<T>(type, () => new type()); // supplier of new instance
} else if (guard(type)) {
return type; // already a Promisor
} else if (typeof type === 'function') {
return wrapPromisor<T>(type, type as () => T);
} else {
return wrapPromisor<T>(type, () => type); // instance of T, runtime type-guard happens in demand
}
}
/**
* Wrapper interface for Promisor to provide unwrapping capability
*/
interface PromisorWrapper<T> extends Promisor<T> {
/**
* Unwrap to get the original Promisor.
*/
unwrapPromisorType(): PromisorType<T>;
}
/**
* Create a simple inline Promisor from a demand function
*
* @param type the PromisorType
* @param demand the demand function
* @returns the Promisor
*/
function wrapPromisor<T>(type: PromisorType<T>, demand: () => OptionalType<T>): RequiredType<PromisorWrapper<T>> {
const validDemand = presentCheck(demand, "Promisor demand function must be present.");
let usageCount: number = 0;
return {
demand: validDemand,
incrementUsage: () => ++usageCount,
decrementUsage: () => --usageCount,
unwrapPromisorType: () => type
};
}
/**
* Unwrap a Promisor to get the original type.
*
* @param promisor the Promisor to unwrap
* @returns the original PromisorType
*/
export function unwrapPromisorType<T>(promisor: OptionalType<Promisor<T>>): OptionalType<PromisorType<T>> {
if (isNotPresent(promisor)) {
return promisor;
}
if ('unwrapPromisorType' in promisor && typeof promisor.unwrapPromisorType === 'function') {
return promisor.unwrapPromisorType();
}
return promisor
}
|