Skip to content

Commit

Permalink
Add JSDoc to devDependencies; document RedisClient
Browse files Browse the repository at this point in the history
This is the first step towards properly documenting all of the classes
that comprise the application.
  • Loading branch information
mbland committed Dec 9, 2017
1 parent 42960b6 commit 9596eb0
Show file tree
Hide file tree
Showing 7 changed files with 277 additions and 34 deletions.
11 changes: 11 additions & 0 deletions .config/jsdoc.json
@@ -0,0 +1,11 @@
{
"source": {
"include": ["index.js", "lib", "public/app.js"]
},
"opts": {
"recurse": true,
"destination": "./jsdoc",
"encoding": "utf8",
"readme": "./README.md"
}
}
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -5,6 +5,7 @@
coverage/
appendonly.aof
dump.rdb
jsdoc/
node_modules/
npm.log
redis.log
Expand Down
8 changes: 8 additions & 0 deletions README.md
Expand Up @@ -228,6 +228,14 @@ browser` to collect coverage using [NYC][]/[Istanbul][].
Also see the [Caveat: Karma and Safari](#caveat-karma-and-safari) section below
if you plan to test against Apple's Safari browser.

#### Generating and viewing code documentation

Run `cl jsdoc` to generate documentation using [JSDoc][] and automatically view
it in your browser via [live-server][].

[JSDoc]: http://usejsdoc.org/
[live-server]: https://www.npmjs.com/package/live-server

#### Local environment variables

Read through the `.config/env.template` file, and consider making a copy as
Expand Down
93 changes: 93 additions & 0 deletions lib/redis-client.js
Expand Up @@ -2,21 +2,47 @@

module.exports = RedisClient

/**
* Internal wrapper for the `redis` npm client created by
* `redis.createClient`.
*
* The interface of this class comprises our own internal API for data store
* operations.
*
* Methods that return `Promises` will return the error object from the
* underlying Redis client call on rejection.
*
* @constructor
* @param {redis} client - instance of the `redis` npm client
*/
function RedisClient(client, getTimestamp) {
this.client = client
this.getTimestamp = getTimestamp || (() => new Date().getTime())
}

// Helper function that Promisifies common Redis client operations
function expectResult(expected, func) {
return new Promise((resolve, reject) => {
func((err, result) => err ? reject(err) : resolve(result === expected))
})
}

/**
* Determines whether or not a user has logged into the system
*
* @param {string} userId - username, email address, or other identifier
* @returns {Promise} true if the user exists, false otherwise
*/
RedisClient.prototype.userExists = function(userId) {
return expectResult(1, done => this.client.exists(userId, done))
}

/**
* Creates a new user record if one doesn't already exist
*
* @param {string} userId - username, email address, or other identifier
* @returns {Promise} true if the user exists, false otherwise
*/
RedisClient.prototype.findOrCreateUser = function(userId) {
return this.userExists(userId)
.then(exists => {
Expand All @@ -27,6 +53,14 @@ RedisClient.prototype.findOrCreateUser = function(userId) {
})
}

/**
* Returns all the information for a custom link
*
* The key convention for all custom links is that they all begin with `/`.
*
* @param {string} link - The custom link for which to retrieve information
* @returns {Promise} The information pertaining to `link`
*/
RedisClient.prototype.getLink = function(link) {
return new Promise((resolve, reject) => {
this.client.hgetall(link, (err, linkData) => {
Expand All @@ -40,6 +74,14 @@ RedisClient.prototype.getLink = function(link) {
})
}

/**
* Returns a list of custom links
*
* Currently returns all custom links, but will be refactored to support a
* custom search pattern.
*
* @returns {Promise} a list of custom link records
*/
RedisClient.prototype.getLinks = function() {
var links = []
var cursor = 0
Expand Down Expand Up @@ -67,12 +109,27 @@ RedisClient.prototype.getLinks = function() {
))
}

/**
* Increments the access count for the specified link
*
* Keeps track of how many times a custom link has been followed.
*
* @param {string} link - the custom link accessed
* @returns {Promise}
*/
RedisClient.prototype.recordAccess = function(link) {
return new Promise((resolve, reject) => {
this.client.hincrby(link, 'clicks', 1, err => err ? reject(err) : resolve())
})
}

/**
* Assigns ownership of a custom link to a user
*
* @param {string} owner - the user ID of the new owner of `link`
* @param {string} link - the custom link to assign to `owner`
* @returns {Promise} true if ownership was assigned, false otherwise
*/
RedisClient.prototype.addLinkToOwner = function(owner, link) {
return new Promise((resolve, reject) => {
this.client.lpushx(owner, link, (err, result) => {
Expand All @@ -81,10 +138,25 @@ RedisClient.prototype.addLinkToOwner = function(owner, link) {
})
}

/**
* Removes ownership of a custom link from a user
*
* @param {string} owner - the user ID of the current owner of `link`
* @param {string} link - the custom link to remove from `owner`
* @returns {Promise} true if ownership was removed, false otherwise
*/
RedisClient.prototype.removeLinkFromOwner = function(owner, link) {
return expectResult(1, done => this.client.lrem(owner, 1, link, done))
}

/**
* Creates a new custom link record
*
* @param {string} link - custom link to create; must begin with '/'
* @param {string} target - the target URL for the custom link
* @param {string} owner - user ID of the link owner; must already exist
* @returns {Promise} true if the link was created, false otherwise
*/
RedisClient.prototype.createLink = function(link, target, owner) {
return new Promise((resolve, reject) => {
var createdStamp = this.getTimestamp()
Expand All @@ -111,6 +183,12 @@ RedisClient.prototype.createLink = function(link, target, owner) {
})
}

/**
* Returns the list of links owned by a particular user
*
* @param {string} owner - user ID for which to retrieve custom links
* @returns {Promise} the list of custom links owned by `owner`
*/
RedisClient.prototype.getOwnedLinks = function(owner) {
return new Promise((resolve, reject) => {
this.client.lrange(owner, 0, -1, (err, data) => {
Expand All @@ -125,6 +203,15 @@ RedisClient.prototype.getOwnedLinks = function(owner) {
})
}

/**
* Updates an arbitrary property of a custom link record
*
* @param {string} link - custom link to update
* @param {string} property - name of the property to update
* @param {string} value - value to assign to the property
* @returns {Promise} true if `link` exists and the property was updated, false
* otherwise
*/
RedisClient.prototype.updateProperty = function(link, property, value) {
return this.getLink(link)
.then(linkData => {
Expand All @@ -140,6 +227,12 @@ RedisClient.prototype.updateProperty = function(link, property, value) {
})
}

/**
* Deletes a custom link record
*
* @param {string} link - custom link to update
* @returns {Promise} true if the link was deleted, false otherwise
*/
RedisClient.prototype.deleteLink = function(link) {
return expectResult(1, done => this.client.del(link, done))
}

0 comments on commit 9596eb0

Please sign in to comment.