All files / src/core Service.ts

100% Statements 3/3
100% Branches 2/2
100% Functions 2/2
100% Lines 3/3

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                                                          9x                 5x                                     2x              
import { APIResponse } from '@/types/APIResponse'
 
/**
 * @class
 *
 * Base class for every service — an adapter's and an application's alike.
 *
 * A service holds no per-request state: the runtime handle arrives as an
 * argument to each method, so one instance can be created at module scope and
 * reused. What this base contributes is the response contract — every method
 * returns an {@link APIResponse}, built through {@link Service.ok} or
 * {@link Service.fail} rather than assembled by hand, so a caller can map
 * `success` onto a status code without reading each service.
 *
 * @example
 * ```ts
 * export class ProfileService extends Service {
 *   public async get(env: Env, id: string): Promise<APIResponse> {
 *     const profile = await cache.get<Profile>(env, `profile:${id}`)
 *
 *     return profile ? this.ok('Profile found', profile) : this.fail(`Profile ${id} not found`)
 *   }
 * }
 * ```
 *
 * @author Bayu Dwiyan Satria
 * @version 1.0.0
 * @since 1.0.0
 */
export abstract class Service {
  /**
   * Builds a successful response.
   *
   * @param message Human-readable description of what happened.
   * @param data Payload returned to the caller.
   * @returns The response, with `success` set to `true`.
   */
  protected ok<T = unknown>(message: string, data: T = null): APIResponse {
    return {
      message,
      success: true,
      data
    }
  }
 
  /**
   * Builds a failed response.
   *
   * Reserved for outcomes the caller asked for and did not get — a missing
   * row, an absent object. Faults the caller cannot act on should throw
   * instead, so they surface as a `500` rather than a well-formed `false`.
   *
   * @param message Human-readable description of what went wrong.
   * @param data Payload returned to the caller.
   * @returns The response, with `success` set to `false`.
   */
  protected fail<T = unknown>(message: string, data: T = null): APIResponse {
    return {
      message,
      success: false,
      data
    }
  }
}