samples/todolist/src/frontend/api.js
/*
* 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;