Skip to content
Snippets Groups Projects
Unverified Commit 1438e106 authored by Heatingdevice's avatar Heatingdevice
Browse files

Add jsdoc for Client

parent efccba82
No related branches found
No related tags found
No related merge requests found
import superagent from "superagent"; import superagent from "superagent";
class Client { class Client {
/**
* Create a client for the Elixire API
* @param {Object} options - Options to instantiate the client with
* @param {String} options.endpoint - Endpoint to prefix all requests with, including the trailing /api
* @param {String} [options.token=null] - Token to use for authenticated routes
*/
constructor(options) { constructor(options) {
if (!options.endpoint) throw new Error("No endpoint specified!"); if (!options.endpoint) throw new Error("No endpoint specified!");
this.token = options.token; /**
* The token used to make authenticated requests on the API
* @type {?String}
*/
this.token = options.token || null;
/**
* The endpoint to be prepended to API endpoints including the trailing /api
* @type {String}
*/
this.endpoint = this.endpoint =
(window.localStorage (window.localStorage
? window.localStorage.getItem("endpoint-override") ? window.localStorage.getItem("endpoint-override")
: null) || options.endpoint; : null) || options.endpoint;
/**
* The profile of the currently logged in user (Only set if getProfile() has been called)
* @type {?Object}
*/
this.profile = null;
// TODO: Profile class?
/**
* The quota of the currently logged in user (Only set if getQuota() has been called)
* @type {?Object}
*/
this.quota = null;
// TODO: Quota class?
/**
* The files and shortlinks created by the user
* @type {?Object}
*/
this.files = null;
} }
/**
* Gets the user's profile from the API
* @returns {Promise<Object>} The profile of the currently logged-in user
* @api public
*/
async getProfile() { async getProfile() {
if (!this.token) throw new Error("BAD_AUTH"); if (!this.token) throw new Error("BAD_AUTH");
try { try {
...@@ -22,6 +59,11 @@ class Client { ...@@ -22,6 +59,11 @@ class Client {
return this.profile; return this.profile;
} }
/**
* Gets the domains currently available to the user
* @returns {Promise<Object>} An Object mapping domain id to domain
* @api public
*/
async getDomains() { async getDomains() {
if (!this.token) throw new Error("BAD_AUTH"); if (!this.token) throw new Error("BAD_AUTH");
try { try {
...@@ -35,24 +77,40 @@ class Client { ...@@ -35,24 +77,40 @@ class Client {
return this.domains; return this.domains;
} }
/**
* Updates the account with the specified changes
* @param {Object} changes - The changes to be applied to the account
* @param {String} changes.password - The password to be used to authenticate the changes (required)
* @param {String} [changes.new_password] - Optional parameter to set the user's password
* @param {Number} [change.domain] - Optional parameter to set the user's upload domain
* @returns {Promise<Array>} An array containing the list of fields that were modified
* @api public
*/
async updateAccount(changes) { async updateAccount(changes) {
if (!this.token || !changes.password) throw new Error("BAD_AUTH"); if (!this.token || !changes.password) throw new Error("BAD_AUTH");
try { try {
const res = await this.request("patch", "/profile") const res = await this.request("patch", "/profile")
.send(changes) .send(changes)
.then(res => res.body); .then(res => res.body.updated_fields);
if (changes.new_password) { if (changes.new_password) {
await this.login(this.profile.username, changes.new_password); await this.login(this.profile.username, changes.new_password);
} }
return res;
} catch (err) { } catch (err) {
throw this.handleErr(err); throw this.handleErr(err);
} }
} }
/**
* Deletes a shortened URL
* @param {String} shortcode - The shortcode of the shortened link to delete
* @returns {Promise<Object>} The response body
* @api public
*/
async deleteLink(shortcode) { async deleteLink(shortcode) {
if (!this.token) throw new Error("BAD_AUTH"); if (!this.token) throw new Error("BAD_AUTH");
try { try {
const res = await this.request("delete", "/shortendelete") return await this.request("delete", "/shortendelete")
.send({ .send({
filename: shortcode filename: shortcode
}) })
...@@ -62,10 +120,16 @@ class Client { ...@@ -62,10 +120,16 @@ class Client {
} }
} }
/**
* Deletes an uploaded file
* @param {String} shorcode - The shortcode of the file to be deleted
* @returns {Promise<Object>} The response body
* @api public
*/
async deleteFile(shortcode) { async deleteFile(shortcode) {
if (!this.token) throw new Error("BAD_AUTH"); if (!this.token) throw new Error("BAD_AUTH");
try { try {
const res = await this.request("delete", "/delete") return await this.request("delete", "/delete")
.send({ .send({
filename: shortcode filename: shortcode
}) })
...@@ -75,6 +139,12 @@ class Client { ...@@ -75,6 +139,12 @@ class Client {
} }
} }
/**
* Generates an uploader API key
* @param {String} password - The user's password to authenticate with
* @returns {Promise<String>} The generated API key
* @api public
*/
generateToken(password) { generateToken(password) {
if (!this.token) return Promise.reject(new Error("BAD_AUTH")); if (!this.token) return Promise.reject(new Error("BAD_AUTH"));
try { try {
...@@ -90,19 +160,33 @@ class Client { ...@@ -90,19 +160,33 @@ class Client {
} }
} }
/**
* Revokes all the user's tokens (uploader tokens and api keys)
* @param {String} password - The user's password to authenticate with
* @returns {Promise<Object>} The response body
* @api public
*/
revokeTokens(password) { revokeTokens(password) {
if (!this.token) return Promise.reject(new Error("BAD_AUTH")); if (!this.token || !password) return Promise.reject(new Error("BAD_AUTH"));
try { try {
return this.request("post", "/revoke").send({ return this.request("post", "/revoke")
user: this.profile.username, .send({
password: password user: this.profile.username,
}); password: password
})
.then(req => req.body);
} catch (err) { } catch (err) {
throw this.handleErr(err); throw this.handleErr(err);
// TODO: handle the error properly ! // TODO: handle the error properly !
} }
} }
/**
* Uploads a file
* @param file {File} - The file to be uploaded
* @returns {superagent.Request} The request object for the upload
* @api public
*/
upload(file) { upload(file) {
if (!this.token) return Promise.reject(new Error("BAD_AUTH")); if (!this.token) return Promise.reject(new Error("BAD_AUTH"));
try { try {
...@@ -116,6 +200,12 @@ class Client { ...@@ -116,6 +200,12 @@ class Client {
} }
} }
/**
* Shortens a given URL
* @param {String} longUrl - The URL to be shortened
* @returns {Promise<String>} The shortened URL
* @api public
*/
async shortenUrl(longUrl) { async shortenUrl(longUrl) {
if (!this.token) throw new Error("BAD_AUTH"); if (!this.token) throw new Error("BAD_AUTH");
try { try {
...@@ -130,7 +220,13 @@ class Client { ...@@ -130,7 +220,13 @@ class Client {
} }
} }
/**
* Finds the user's quota
* @returns {Object} The quotas of the user
* @api public
*/
async getQuota() { async getQuota() {
// TODO: Quota class?
if (!this.token) throw new Error("BAD_AUTH"); if (!this.token) throw new Error("BAD_AUTH");
try { try {
this.quota = await this.request("get", "/limits").then(res => res.body); this.quota = await this.request("get", "/limits").then(res => res.body);
...@@ -141,10 +237,16 @@ class Client { ...@@ -141,10 +237,16 @@ class Client {
return this.quota; return this.quota;
} }
/**
* Gets a token for the given username/password pair
* @param {String} username - The username to login with
* @param {String} password - The password to login with
* @returns {Promise<String>} The API token created
* @api public
*/
async login(username, password) { async login(username, password) {
if (!username || !password) throw new Error("BAD_AUTH"); if (!username || !password) throw new Error("BAD_AUTH");
try { try {
this.user = username;
const res = await this.request("post", "/login").send({ const res = await this.request("post", "/login").send({
user: username, user: username,
password password
...@@ -156,7 +258,13 @@ class Client { ...@@ -156,7 +258,13 @@ class Client {
} }
} }
/**
* Gets a list of all the files the user has uploaded and the links they've shortened
* @returns {Promise<Object>} The files and shortens created by the user
* @api public
*/
async getFiles() { async getFiles() {
// TODO: Make a type for this so we can document the return value?
if (!this.token) throw new Error("BAD_AUTH"); if (!this.token) throw new Error("BAD_AUTH");
try { try {
...@@ -167,21 +275,12 @@ class Client { ...@@ -167,21 +275,12 @@ class Client {
} }
} }
async invalidateSessions(username, password) { /**
if (!username || !password) throw new Error("BAD_AUTH"); * Used internally to determine what type of error to throw
* @params {Error} err - The error encountered while sending the request
try { * @returns {Error} The error to be thrown
return await this.request("POST", "/revoke") * @api private
.send({ */
user: username,
password
})
.then(res => res.body.ok);
} catch (err) {
throw this.handleErr(err);
}
}
handleErr(err) { handleErr(err) {
console.log(err, err.status); console.log(err, err.status);
if (err.status == 403) { if (err.status == 403) {
...@@ -198,6 +297,13 @@ class Client { ...@@ -198,6 +297,13 @@ class Client {
return err; return err;
} }
/**
* Used internally to make requests to API endpoints, adds an Authorization header
* @param {String} method - The type of request to make (get, post, patch, etc)
* @param {String} url - The endpoint upon which to perform this request, is appended to the API base url of the client
* @returns {superagent.Request} The request created by this
* @api private
*/
request(method, url) { request(method, url) {
return superagent[method.toLowerCase()](this.endpoint + url).set( return superagent[method.toLowerCase()](this.endpoint + url).set(
"Authorization", "Authorization",
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment