All files / data/src/querier querier.ts

100% Statements 136/136
100% Branches 1/1
100% Functions 1/1
100% Lines 136/136

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 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 1371x 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 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 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x  
import { Alias, provide, Provide } from '@sgrud/core';
import { Observable } from 'rxjs';
import { Model } from '../model/model';
 
/**
 * **Querier** namespace containing types and interfaces used and intended to be
 * used in conjunction with the abstract {@link Querier} base class and in
 * context of the {@link Model} data handling.
 *
 * @see {@link Querier}
 */
export namespace Querier {
 
  /**
   * Type alias for a string union type of all known {@link Operation}
   * **Type**s: `'mutation'`, `'query'` and `'subscription'`.
   */
  export type Type =
    'mutation' |
    'query' |
    'subscription';
 
  /**
   * String literal helper type. Enforces any assigned string to conform to the
   * standard form of an **Operation**: A string starting with the {@link Type},
   * followed by one whitespace and the operation content.
   */
  export type Operation = Alias<`${Type} ${string}`>;
 
  /**
   * Interface describing the shape of **Variables** which may be embedded
   * within {@link Operation}s. **Variables** are a simple key-value map, which
   * can be deeply nested.
   */
  export interface Variables {
 
    /**
     * Index signature allowing keys to be of type `string` and values of type
     * {@link Variables} or `unknown`.
     */
    readonly [key: string]: Variables | unknown;
 
  }
 
}
 
/**
 * Abstract **Querier** base class to implement {@link Model} **Querier**s. By
 * extending this abstract base class and providing the extending class to the
 * {@link Linker}, e.g., by {@link Target}ing it, the {@link priority} method of
 * the resulting class will be called whenever the {@link Model} requests or
 * persists data and, if this class claims the highest priority, its
 * {@link commit} method will be called.
 *
 * @decorator {@link Provide}
 *
 * @example
 * Simple **Querier** stub:
 * ```ts
 * import { Provider, Target } from '@sgrud/core';
 * import { type Querier } from '@sgrud/data';
 * import { type Observable } from 'rxjs';
 *
 * ⁠@Target()
 * export class ExampleQuerier
 *   extends Provider<typeof Querier>('sgrud.data.Querier') {
 *
 *   public override readonly types: Set<Querier.Type> = new Set<Querier.Type>([
 *     'query'
 *   ]);
 *
 *   public override commit(
 *     operation: Querier.Operation,
 *     variables: Querier.Variables
 *   ): Observable<unknown> {
 *     throw new Error('Stub!');
 *   }
 *
 *   public override priority(): number {
 *     return 0;
 *   }
 *
 * }
 * ```
 *
 * @see {@link Model}
 */
@Provide()
export abstract class Querier {
 
  /**
   * Magic string by which this class is {@link provide}d.
   *
   * @see {@link provide}
   */
  public static readonly [provide]: 'sgrud.data.Querier' = 'sgrud.data.Querier';
 
  /**
   * A set containing all **types** of queries this {@link Querier} can handle.
   * May contain any of the `'mutation'`, `'query'` and `'subscription'`
   * {@link Type}s.
   */
  public abstract readonly types: Set<Querier.Type>;
 
  /**
   * The overridden **commit** method of {@link Target}ed {@link Querier}s is
   * called by the {@link Model} to execute {@link Operation}s. The invocation
   * arguments are the `operation`, unraveled into a string, and all `variables`
   * embedded within this operation. The extending class has to serialize the
   * {@link Variables} and handle the operation. It's the callers responsibility
   * to unravel the {@link Operation} prior to invoking this method, and to
   * deserialize and (error) handle whatever response is received.
   *
   * @param operation - The {@link Operation} to be **commit**ted.
   * @param variables - Any {@link Variables} within the {@link Operation}.
   * @returns An {@link Observable} of the **commit**ted {@link Operation}.
   */
  public abstract commit(
    operation: Querier.Operation,
    variables?: Querier.Variables
  ): Observable<unknown>;
 
  /**
   * When the {@link Model} executes {@link Operation}s, all {@link Target}ed
   * and compatible {@link Querier}s, i.e., implementations of the this class
   * capable of handling the specific {@link Type} of the {@link Operation} to
   * {@link commit}, will be asked to prioritize themselves regarding the
   * respective {@link Model}. The querier claiming the highest **priority**
   * will be chosen and its {@link commit} method called.
   *
   * @param model - The {@link Model} to be {@link commit}ted.
   * @returns The numeric **priority** of this {@link Querier} implementation.
   */
  public abstract priority(model: Model.Type<Model>): number;
 
}