All files / src/impl ContractsWrapper.impl.ts

86.95% Statements 20/23
100% Branches 0/0
90.9% Functions 10/11
86.95% Lines 20/23

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 8225x                               25x 165x                         165x       65x       165x       113x       76x               166x 166x 166x 166x 147x 147x   147x                   2x       165x 165x     165x 165x  
import { AutoClose, inlineAutoClose } from "@jonloucks/contracts-ts/api/AutoClose";
import { BindStrategyType } from "@jonloucks/contracts-ts/api/BindStrategy";
import { Contract } from "@jonloucks/contracts-ts/api/Contract";
import { Contracts } from "@jonloucks/contracts-ts/api/Contracts";
import { PromisorType } from "@jonloucks/contracts-ts/api/Promisor";
import { Repository } from "@jonloucks/contracts-ts/api/Repository";
import { OptionalType, RequiredType } from "@jonloucks/contracts-ts/api/Types";
 
/**
 * Wrapper method to create a Contracts wrapper which is responsible for managing
 * the lifecycle of the underlying Repository and Contracts instances.
 * 
 * @param contracts the underlying Contracts instance
 * @param repository the underlying Repository instance
 * @returns the Contracts implementation
 */
export function wrap(contracts: RequiredType<Contracts>, repository: RequiredType<Repository>): Contracts {
  return ContractsWrapper.internalCreate(contracts, repository);
}
 
// ---- Implementation details below ----
 
/**
 * The Contracts wrapper implementation
 * Contracts wrapper which is responsible for managing
 * the lifecycle of the underlying Repository and Contracts instances.
 */
class ContractsWrapper implements Contracts {
 
  static internalCreate(contracts: RequiredType<Contracts>, repository: RequiredType<Repository>): Contracts {
    return new ContractsWrapper(contracts, repository);
  }
 
  claim<T>(contract: Contract<T>): OptionalType<T> {
    return this.#contracts.claim(contract);
  }
 
  enforce<T>(contract: Contract<T>): RequiredType<T> {
    return this.#contracts.enforce(contract);
  }
 
  isBound<T>(contract: Contract<T>): boolean {
    return this.#contracts.isBound(contract);
  }
 
  bind<T>(contract: Contract<T>, promisor: PromisorType<T>, bindStrategy?: BindStrategyType): AutoClose {
    return this.#contracts.bind(contract, promisor, bindStrategy);
  }
 
  autoOpen(): AutoClose {
    return this.open();
  }
 
  open(): AutoClose {
    const closeRepository: AutoClose = this.#repository.open();
    try {
      const closeConcurrency: AutoClose = this.#contracts.open();
      return inlineAutoClose(() => {
        try {
          closeConcurrency.close();
        } finally {
          closeRepository.close(); // ensure repository is closed
        }
      });
    } catch (thrown) {
      closeRepository.close();
      throw thrown
    }
  }
 
  toString(): string {
    return this.#contracts.toString();
  }
 
  private constructor(contracts: RequiredType<Contracts>, repository: RequiredType<Repository>) {
    this.#contracts = contracts;
    this.#repository = repository;
  }
 
  readonly #contracts: RequiredType<Contracts>;
  readonly #repository: RequiredType<Repository>;
};