All files / core/src/super provide.ts

100% Statements 75/75
100% Branches 2/2
100% Functions 1/1
100% Lines 75/75

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 761x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 95x 95x 95x 95x 95x 95x 95x 95x 95x 95x 95x 95x 95x 95x  
import { Registration, Registry } from './registry';
 
/**
 * Unique symbol used as property key by the {@link Provide} type constraint.
 */
export const provide = Symbol('@sgrud/core/super/provide');
 
/**
 * Type helper enforcing the {@link provide} symbol property to contain a magic
 * string (typed as {@link Registration}) on base constructors decorated with
 * the corresponding {@link Provide} decorator. The **Provide** type helper is
 * also used by the {@link Provider} decorator.
 *
 * @typeParam K - The magic string {@link Registration} type.
 * @typeParam V - The registered class constructor type.
 *
 * @see {@link Provide}
 */
export type Provide<
  K extends Registration,
  V extends abstract new (...args: any[]) => InstanceType<V>
> = (abstract new (...args: any[]) => InstanceType<V>) & {
 
  /**
   * Enforced contract. This **provide** symbol property must be typed as
   * {@link Registration} and assigned a magic string used by the
   * {@link Provider} to lookup the providing class.
   */
  readonly [provide]: K extends Registration ? K : Registration;
 
};
 
/**
 * Class decorator factory. **Provide**s the decorated class to extending
 * classes. Applying the **Provide** decorator enforces the {@link Provide} type
 * which entails the declaration of a static {@link provide} property typed as
 * {@link Registration}. The magic string assigned to this static property is
 * used by the {@link Provider} factory function to get base classes from the
 * {@link Registry}.
 *
 * @typeParam K - The magic string {@link Registration} type.
 * @typeParam V - The registered class constructor type.
 * @returns A class constructor decorator.
 *
 * @example
 * **Provide** a base class:
 * ```ts
 * import { Provide, provide } from '@sgrud/core';
 *
 * ⁠@Provide()
 * export abstract class Base {
 *
 *   public static readonly [provide] = 'sgrud.example.Base' as const;
 *
 * }
 * ```
 *
 * @see {@link Provider}
 * @see {@link Registry}
 */
export function Provide<
  V extends Provide<K, V>,
  K extends Registration = V[typeof provide]
>() {
 
  /**
   * @param constructor - The class `constructor` to be decorated.
   */
  return function(constructor: V): void {
    new Registry([
      [constructor[provide], constructor]
    ]);
  };
 
}