sgammon/GUST

View on GitHub
samples/todolist/src/frontend/api.js

Summary

Maintainability
A
0 mins
Test Coverage
/*
 * Copyright © 2020, The Gust Framework Authors. All rights reserved.
 *
 * The Gust/Elide framework and tools, and all associated source or object computer code, except where otherwise noted,
 * are licensed under the Zero Prosperity license, which is enclosed in this repository, in the file LICENSE.txt. Use of
 * this code in object or source form requires and implies consent and agreement to that license in principle and
 * practice. Source or object code not listing this header, or unless specified otherwise, remain the property of
 * Elide LLC and its suppliers, if any. The intellectual and technical concepts contained herein are proprietary to
 * Elide LLC and its suppliers and may be covered by U.S. and Foreign Patents, or patents in process, and are protected
 * by trade secret and copyright law. Dissemination of this information, or reproduction of this material, in any form,
 * is strictly forbidden except in adherence with assigned license requirements.
 */
/*global goog*/
goog.module('todolist.api');

const Core = goog.require('gust.Core');
const Empty = goog.require('proto.google.protobuf.Empty');
const TasksClient = goog.require('proto.todolist.TasksPromiseClient');
const logging = goog.require('gust.logging');


/**
 * Refers to the API binding type assigned for our use.
 *
 * @public
 * @typedef {!TasksClient}
 */
let TasksAPIClient;


/**
 * Describes the RPC endpoint to use.
 *
 * @const
 * @type {!string}
 * @private
 */
const endpoint_ = `https://${window.location.hostname}`;


/**
 * Singleton client instance for the Tasks API.
 *
 * @const
 * @type {!TasksAPIClient}
 * @private
 */
const client_ = new TasksClient(
    window.location.origin.indexOf(':8443') !== -1 ?
    `https://${window.location.hostname}:8443` :
    endpoint_, null, {});


/**
 * Empty proto singleton instance.
 *
 * @private
 * @const
 * @type {!Empty}
 */
const empty_ = new Empty();


/**
 * Base headers/gRPC metadata to apply to each and every RPC call, regardless of credential state.
 *
 * @const
 * @type {!Object<!string, *>}
 * @private
 */
const base_metadata_ = Object.seal({
  'X-API-Agent': `todolist v1; gust ${Core.getGustVersion()}`
});


/**
 * API facade for the Tasks API. Mediates access to the underlying RPC code, generated by `protoc` and the gRPC plugin
 * for web code (`grpc-web`).
 *
 * @public
 */
class TasksAPI {
  /**
   * Acquire an instance of the Tasks API client.
   *
   * @public
   * @return {!TasksAPI} API instance for speaking to the Tasks API.
   */
  static acquire() {
    return new TasksAPI();
  }

  /**
   * Compose metadata to affix to an RPC request bound for the Tasks API. Any data provided in `opt_overlay` (expected
   * to be an arbitrary object with string keys) is mixed-in to the standard headers before returning.
   *
   * @param {?Object<!string, *>=} opt_overlay Overlay data to apply to the returned metadata.
   * @returns {!Object<!string, *>} Merged headers to use as RPC metadata.
   */
  metadata(opt_overlay) {
    return Object.assign({}, opt_overlay || {}, base_metadata_);
  }

  /**
   * Retrieve the raw gRPC client.
   *
   * @public
   * @return {!TasksAPIClient} gRPC client singleton.
   */
  client() {
    return client_;
  }

  /**
   * Ping the Tasks API service. The resulting promise resolves then we get a valid response (which is empty). This
   * method may be used to measure latency to the service, or detect uptime changes.
   *
   * @public
   * @param {?Object<!string, *>=} opt_metadata Metadata to overlay into the RPC operation, if desired.
   * @return {!Promise<!number>} Promise for a future value, that resolves to the amount of latency it took to speak
   *   with the Tasks API service backend.
   */
  ping(opt_metadata) {
    const start = +(new Date());
    logging.log('Kicking off ping...');
    const operation = client_.health(empty_, this.metadata(opt_metadata));
    return new Promise((proceed, reject) => {
      operation.then(() => {
        const total = +(new Date()) - start;
        logging.info('Ping completed in ' + total + 'ms.');
        proceed(total);

      }, (error) => {
        logging.error('Ping failed. Error enclosed.', error);
        reject(error);

      });
    });
  }
}


exports.TasksAPI = TasksAPI;