The current object is represented as this
. You can always read its properties. Modifying its properties in an On Get
request will change the result that the client receives, while modifying its properties in an On Post
, On Put
, or On Validate
will change the value in the database.
// Example: On Validate
// If a property is too long, truncate it
if (this.message.length > 140) {
this.message = this.message.substring(0, 137) + '...';
}
Note: In some cases, the meaning of this
will change to something less useful inside of a function. If you are using functions such as Array.forEach()
, you may need to bind another variable to this
:
// Won't work - sum remains at 0
this.sum = 0;
this.targets.forEach(function(t) {
this.sum += t.points;
});
//Works as expected
var self = this;
this.sum = 0;
this.targets.forEach(function(t) {
self.sum += t.points;
});
The context of the request. This object contains everything from the request (request, response, body, headers, etc...):
// Example:
if (ctx && ctx.req && ctx.req.headers && ctx.req.headers.host !== '192.168.178.34:2403') {
cancel("You are not authorized to do that", 401);
}
The entire object is available as a gist here.
The currently logged in User from a User Collection. undefined
if no user is logged in.
// Example: On Post
// Save the creator's information
if (me) {
this.creatorId = me.id;
this.creatorName = me.name;
}
isMe(id)
Checks whether the current user matches the provided id
.
// Example: On Get /users
// Hide properties unless this is the current user
if (!isMe(this.id)) {
hide('privateVariable');
}
// Example: On Put
// Make sure that only the creator can edit a post
cancelUnless(isMe(this.id), "You are not authorized to edit that post", 401);
The query string object. On a specific query (such as /posts/a59551a90be9abd8
), this includes an id
property.
// Example: On Get
// Don't show the body of a post in a general query
if (!query.id) {
hide(this.body);
}
cancel(message, [statusCode])
Stops the current request with the provided error message and HTTP status code. Status code defaults to 400
. Commonly used for security and authorization.
It is strongly recommended that you cancel()
any events that are not accessible to your front-end, because your API is open to anyone.
// Example: On Post
// Don't allow non-admins to create items
if (!me.admin) {
cancel("You are not authorized to do that", 401);
}
Note: In a GET event where multiple values are queried (such as on /posts
), the cancel()
function will remove the current item from the results without an error message.
cancelIf(condition, message, [statusCode])
cancelUnless(condition, message, [statusCode])
Calls cancel(message, statusCode)
if the provided condition is truthy (for cancelIf()
) or falsy (for cancelUnless()
).
Example: On Post
// Prevent banned users from posting
cancelUnless(me, "You are not logged in", 401);
cancelIf(me.isBanned, "You are banned", 401);
error(key, message)
Adds an error message to an errors
object in the response. Cancels the request, but continues running the event so it can collect multiple errors to display to the user. Commonly used for validation.
// Example: On Validate
// Don't allow certain words
// Returns response {"errors": {"name": "Contains forbidden words"}}
if (!this.name.match(/(foo|bar)/)) {
error('name', "Contains forbidden words");
}
errorIf(condition, key, message)
errorUnless(condition, key, message)
Calls error(key, message)
if the provided condition is truthy (for errorIf()
) or falsy (for errorUnless()
).
// Example: On Validate
// Require message to be a certain length
errorUnless(this.message && this.message.length > 2, 'message', "Must be at least 2 characters");
hide(property)
Hides a property from the response.
// Example: On Get
// Don't show private information
if (!me || me.id !== this.creatorId) {
hide('secret');
}
protect(property)
Prevents a property from being updated. It is strongly recommended you protect()
any properties that should not be modified after an object is created.
// Example: On Put
// Protect a property
protect('createdDate');
// Example: On Put
// Only the creator can change the title
if (!(me && me.id === this.creatorId)) {
protect('title');
}
changed(property)
Returns whether a property has been updated.
// Example: On Put
// Validate the title when it changes
if(changed('title') && this.title.length < 5) {
error('title', 'must be over 5 characters');
}
An Object
containing the previous values of the item to be updated.
// Example: On Put
if(this.votes < previous.votes) {
emit('votes have decreased');
}
emit([userCollection, query], message, [data])
Emits a realtime message to the client.
// Example: On Post
// Alert clients that a new post has been created
emit('postCreated', this);
In the front end:
// Listen for new posts
dpd.on('postCreated', function(post) {
//do something...
});
You can use userCollection
and query
parameters to limit the message broadcast to specific users.
// Example: On Put
// Alert the owner that their post has been modified
if (me.id !== this.creatorId) {
emit(dpd.users, {id: this.creatorId}, 'postModified', this);
}
See Notifying Clients of Changes with Sockets for an overview on realtime functionality.
The entire dpd.js library, except for the realtime functions, is available in events. It will also properly bind this
in callbacks.
// Example: On Get
// If specific query, get comments
dpd.comments.get({postId: this.id}, function(results) {
this.comments = results;
});
// Example: On Delete
// Log item elsewhere
dpd.archived.post(this);
Dpd.js will prevent recursive requests if you set the $limitRecursion property. This works by returning null
from a dpd
function call that has already been called several times further up in the stack.
// Example: On Get /recursive
// Call self
dpd.recursive.get({$limitRecursion: 1}, function(results) {
if (results) this.recursive = results;
});
// GET /recursive
{
"id": "a59551a90be9abd8",
"recursive": [
{
"id": "a59551a90be9abd8"
}
]
}
Equal to true if this request has been sent by another script.
// Example: On GET /posts
// Posts with a parent are invisible, but are counted by their parent
if (this.parentId && !internal) cancel();
dpd.posts.get({parentId: this.id}, function(posts) {
this.childPosts = posts.length;
});
Equal to true if this request has been authenticated as root (has the dpd-ssh-key
header with the appropriate key; such as from the dashboard)
// Example: On PUT /users
// Protect reputation property - should only be calculated by a custom script.
if (!isRoot) protect('reputation');
console.log([arguments]...)
Logs the values provided to the command line. Useful for debugging.
Deployd exposes an HTTP API to your Collections which can be used by any platform or library that supports HTTP or AJAX. Though it does not strictly adhere to REST, it should also work with most libraries designed for REST.
The examples below use a Collection called /todos
with the following schema:
id
title
category
Your Collection is available at the URL you specified. If you are using the default development hostname of localhost:2403
, for example, the /todos
collection will be available at http://localhost:2403/todos
.
A request to the Deployd API should include the Content-Type
header. The following content types are supported:
application/json
(recommended)application/x-www-form-urlencoded
(All values will be parsed as strings)The Content-Type
header is not necessary for GET
or DELETE
requests which have no body.
Deployd will send standard HTTP status codes depending on the results on an operation. If the code is 200 (OK), the request was successful and the result is available in the body as JSON.
If the code is 204 (No Content), the request was successful, but there is no result.
If the code is 400 or greater, it will return the error message formatted as a JSON object:
status
(number): The HTTP status code of the request. Common codes include:
message
(string): A message describing the error. Not always present.errors
(object): A hash of error messages corresponding to the properties of the object that was sent - usually indicates validation errors. Not always present.Examples of errors:
{
"status": 401,
"message": "You are not allowed to access that collection!"
}
{
"status": 400,
"errors": {
"title": "Title must be less than 100 characters",
"category": "Not a valid category"
}
}
To retreive an array of objects in the collection, send a GET
request to your collection's path:
GET /todos
The response will be an array of objects:
200 OK
[
{
"id": "320d6151a9aad8ce",
"title": "Wash the dog",
"category": "pets"
}, {
"id": "320d6151a9aad8ce"
"title": "Write autobiography",
"category": "writing"
}
]
If the collection has no objects, it will be an empty array:
200 OK
[]
To filter results by the specified query object, send a GET
request to your collection's path with a query string. See Querying Collections for information on constructing a query.
GET /todos?category=pets
For more advanced queries, you will need to pass the query string as JSON instead:
GET /todos?{"category": "pets"}
The response body is an array of objects:
200 OK
[
{
"id": "320d6151a9aad8ce",
"title": "Wash the dog",
"category": "pets"
}
]
To retrieve a single object by its id
property, send a GET
request with the id
value as the path.
GET /todos/320d6151a9aad8ce
The response body is the object that you requested:
200 OK
{
"id": "320d6151a9aad8ce",
"title": "Wash the dog",
"category": "pets"
}
To create an object in the collection, send a POST
request with the object's properties in the body.
POST /todos
{
"title": "Walk the dog"
}
The response body is the object that you posted, with any additional calculated properties and the id
:
{
"id": "91c621a3026ca8ef",
"title": "Walk the dog"
}
To update an object that is already in the collection, send a POST
or PUT
request with the id
value as the path and with the properties you wish to update in the body. It will only change the properties that are provided. It is also possible to incrementally update certain properties; see Updating Objects in Collections for details.
PUT /todos/91c621a3026ca8ef
{
"title": "Walk the cat"
}
POST /todos/91c621a3026ca8ef
{
"title": "Walk the cat"
}
You can also omit the id
in the path if you provide an id
property in the body:
PUT /todos
{
"id": "91c621a3026ca8ef"
"title": "Walk the cat"
}
Finally, you can provide a query string to ensure that the object you are updating has the correct properties. You must still provide an id
. This can be useful as a failsafe.
PUT /todos/91c621a3026ca8ef?category=pets
{
"title": "Walk the cat"
}
The response body is the entire object after the update:
200 OK
{
"id": "91c621a3026ca8ef",
"title": "Walk the cat",
"category": "pets"
}
The PUT
verb will return an error if the id
and/or query
does not match any object in the collection:
400 Bad Request
{
"status": 400,
"message": "No object exists that matches that query"
}
To delete an object from the collection, send a DELETE
request with the id
value as a path.
DELETE /todos/91c621a3026ca8ef
You can also pass a query string to ensure that you are removing the correct object:
DELETE /todos/91c621a3026ca8ef?title=Walk the dog
You can omit the id
in the path if you provide it in the query string:
DELETE /todos?id=91c621a3026ca8ef&title=Walk the dog
The response body will always be empty.
Deployd uses Socket.io for its realtime functionality. If you are not using dpd.js, you can use the Socket.io client library.
var socket = io.connect('/');
socket.on('todos:create', function(todo) {
// Do something
});
The Socket.io community has created client libraries for other languages and platforms as well.
You can elevate your session to root access by adding the header dpd-ssh-key
. It must have the value of your app's key (you can find this by typing dpd showkey
into the command line); although in the development
environment, the dpd-ssh-key
header can have any value.
Sending a request as root has several effects. Most notably, you can use the {$skipEvents: true}
property in either the query string or request body. This will cause events not to run. This is useful for bypassing authentication or validation.
Your front-end app should never gain root access, and you should never store the app's key in a place where it can be accessed by users, even if they understand the system. This is primarily useful for writing data management utilities for yourself, other developers, and system administrators.
The examples below show how to use various JavaScript front-end libraries to access a Collection called /todos
.
$.ajax('/todos', {
type: "GET",
success: function(todos) {
// Do something
},
error: function(xhr) {
alert(xhr.responseText);
}
});
$.ajax('/todos', {
type: "POST",
contentType: "application/json",
data: JSON.stringify({
title: "Walk the dog"
}),
success: function(todo) {
// Do something
},
error: function(xhr) {
alert(xhr.responseText);
}
});
Note: When providing a request body, jQuery defaults to form encoding. Deployd works best with a JSON body, so you'll need to set the contentType option and manually convert to JSON.
var Todo = Backbone.Model.extend({});
var Todos = Backbone.Collection.extend({
model: Todo,
url: "/todos"
});
var todos = new Todos();
todos.fetch({
success: function(collection, response) {
// Do something
}, error: function(collection, response) {
alert(response);
}
});
todos.create({
title: "Walk the dog"
}, {
success: function(collection, response) {
// Do something
}, error: function(collection, response) {
alert(response);
}
});
Using $http:
function Controller($scope, $http) {
$http.get('/todos')
.success(function(todos) {
$scope.todos = todos;
})
.error(function(err) {
alert(err);
});
$http.post('/todos', {
title: "Walk the dog"
})
.success(function(todo) {
// Do something
})
.error(function(err) {
alert(err);
});
}
Using ngResource:
var myApp = angular.module('myApp', ['ngResource']);
myApp.factory('Todos', function($resource) {
return $resource('/todos/:todoId', {todoId: '@id'});
});
function Controller($scope, Todos) {
$scope.todos = Todos.query(function(response) {
// Do something
}, function(error) {
alert(error);
});
Todos.save({
title: "Walk the dog"
}, function(todo) {
// Do something
}, function(error) {
alert(error);
});
}
myApp.controller('Controller', Controller);
The most common bug when implementing a CORS client for Deploy is to include headers that are not allowed. A client must not send any custom headers besides the following:
Origin, Accept, Accept-Language, Content-Language, Content-Type, Last-Event-ID
This will not work on browsers that do not support Cross-Origin Resource Sharing (namely Internet Explorer 7 and below).
When using dpd.js, all the required CORS headers are sent by default to any domain. You don't have to make any changes to your requests. dpd.js takes care of it for you.
When using jQuery.ajax() on cross-origin requests the credentials are not sent along with the request automatically. You have to add them to each ajax() request using the xhrFields parameter. Here is an example of login followed by getting some data.
// Logging a user in.
$.ajax({
url: 'http://<domain>:<port>/users/login',
type: "POST",
data: {username:"un", password:"pw"},
cache: false,
xhrFields:{
withCredentials: true
},
success: function(data) {
console.log(data);
},
error: function(xhr) {
console.log(xhr.responseText);
}
});
// On subsequent requests or in the success callback above. (After having logged in)
$.ajax({
url: 'http://<domain>:<port>/<collection>',
type: "GET",
cache: false,
xhrFields:{
withCredentials: true
},
success: function(data) {
console.log(data);
},
error: function(xhr) {
console.log(xhr.responseText);
}
});
Provides faux HTTP method support.
Most browsers doesn’t support methods other than “GET” and “POST” when it comes to submitting forms. So It's support something like 'Rails'.
Pass an optional key to use when checking for a method override, othewise defaults to _method. The original method is available via req.originalMethod.
It's support both URL query and POST body
URL : ?_method=METHOD_NAME or
JSON body : { _method: 'METHOD_NAME' }
$.ajax({ type: "POST", url : "/todos/"+ todoId, data: { _method:"DELETE" }, success: function(res) {
$.ajax({
type : "POST",
url : "/todos/OBJECT_ID"
data : { _method:"DELETE" },
success: function(todo) {
// Object was deleted. response body empty.
},
error: function(xhr) {}
});
or
$.ajax({
type : "POST",
url : "/todos/OBJECT_ID?_method=DELETE",
success: function(todo) {
// Object was deleted. response body empty.
},
error: function(xhr) {}
});
Collections can be queried over HTTP using the query string.
This example will return all the posts
with an author "Joe":
GET /posts?author=Joe
When querying a Collection, you can use special commands to create a more advanced query.
Deployd supports all of MongoDB's conditional operators; only the common operators and Deployd's custom commands are documented here.
When using an advanced query in REST, you must pass JSON as the query string, for example:
GET /posts?{"likes": {"$gt": 10}}
If you are using dpd.js, this will be handled automatically.
Compares a Number property to a given value.
$gt
- Greater than$lt
- Less than$gte
- Greater than or equal to$lte
- Less than or equal to
// Finds all posts with more than 10 likes
{
likes: {$gt: 10}
}
The $ne
command lets you choose a value to exclude.
// Get all posts except those posted by Bob
{
author: {$ne: "Bob"}
}
The $in
command allows you to specify an array of possible matches.
// Get articles in the "food", "business", and "technology" categories
{
category: {$in: ["food", "business", "technology"]}
}
The $regex
command allows you to specify a regular expression to match a string property.
You can also use the $options
command to specify regular expression flags.
// Get usernames that might be email addresses (x@y.z)
{
"username": {$regex: "[a-z0-9\-]+@[a-z0-9\-]+\.[a-z0-9\-]+", $options: 'i' }
}
Query commands apply to the entire query, not just a single property.
The $fields
command allows you to include or exclude properties from your results.
// Exclude the "email" property
{
$fields: {email: 0}
}
// Only include the "title" property
{
$fields: {title: 1}
}
The $or
command allows you to specify multiple queries for an object to match in an array.
// Get all public posts and all posts by a specified user (even if those are private)
{
$or: [{
isPublic: true
}, {
creator: "Bob"
}]
}
The $sort
command allows you to order your results by the value of a property. The value can be 1 for ascending sort (lowest first; A-Z, 0-10) or -1 for descending (highest first; Z-A, 10-0)
// Sort posts by likes, descending
{
$sort: {likes: -1}
}
The $limit
command allows you to limit the amount of objects that are returned from a query. This is commonly used for paging, along with $skip
.
// Return the top 10 scores
{
$sort: {score: -1},
$limit: 10
}
The $skip
command allows you to exclude a given number of the first objects returned from a query. This is commonly used for paging, along with $limit
.
// Return the third page of posts, with 10 posts per page
{
$skip: 20,
$limit: 10
}
The $limitRecursion
command allows you to override the default recursive limits in Deployd. This is useful when you want to query a very deeply nested structure of data. Otherwise you can still query nested structures, but Deployd will stop the recursion after 2 levels. See the Collection Relationships guide for more info.
When updating an object in a Collection, you can use special modifier commands to more granularly change property values.
The $inc
command increments the value of a given Number property.
// Give a player 5 points
{
score: {$inc: 5}
}
The $push
command adds a value to an Array property.
// Add a follower to a user by storing their id.
{
followers: {$push: 'a59551a90be9abd8'}
}
The $pushAll
command adds multiple values to an Array property.
// Add mentions of users
{
mentions: {
$pushAll: ['a59551a90be9abd8', 'd0be45d1445d3809']
}
}
The $pull
command removes a value from an Array property.
// Remove a user from followers
{
followers: {$pull: 'a59551a90be9abd8'}
}
Note: If there is more than one matching value in the Array, this will remove all of them
The $pullAll
command removes multiple values from an Array property.
// Remove multiple users
{
followers: {$pullAll: ['a59551a90be9abd8', 'd0be45d1445d3809']}
}
Note: This will remove all of the matching values from the Array
dpd.js
is an auto-generated library that provides access to Collections and other Deployd features on the front-end. For a basic overview, see Accessing Collections with dpd.js.
The API for your Collection is automatically generated as dpd.[collectionname]
.
Examples:
dpd.todos
dpd.users
dpd.todolists
Note: If your Collection name has a dash in it (e.g. /todo-lists
), the dash is removed when accessing it in this way (e.g. dpd.todolists
).
You can also access your collection by using dpd(collectionName)
as a function.
Examples:
dpd('todos')
dpd('users')
dpd('todo-lists')
Note: Collections accessed in this way will not have helper functions besides get
, post
, put
, del
, and exec
(see Dpd.js for Custom Resources for details on these generic functions)
The examples below use a Collection called /todos
with the following schema:
id
title
category
Every function in the Collection API takes a callback function (represented by fn
in the docs) with the signature function(result, error)
.
The callback will be executed asynchronously when the API has received a response from the server.
The result
argument differs depending on the function. If the result failed, it will be null
and the error
argument will contain the error message.
The error
argument, if there was an error, is an object:
status
(number): The HTTP status code of the request. Common codes include:
message
(string): A message describing the error. Not always present.errors
(object): A hash of error messages corresponding to the properties of the object that were sent - usually indicates validation errors. Not always present.Examples of errors:
{
"status": 401,
"message": "You are not allowed to access that collection!"
}
{
"status": 400,
"errors": {
"title": "Title must be less than 100 characters",
"category": "Not a valid category"
}
}
Every function in the collection API returns a promise.
We use the ayepromise
library (which follows the Promises/A+ 1.1 specs).
To learn how to use promises, please, refer to this article.
The first callback contains the same result
same with the classic callbacks.
The second callback contains the error
object as described above.
Here's an example to use promises within dpd.js:
dpd.todos.post({message: "Hello world"}).then(function(todo) {
// do something with todo
console.log(todo); // display {id: "###", message: 'Hello world'}
}, function(err) {
// do something with the error
console.log(err); // display an error if the request failed
});
dpd.todos.get('1234324324').then(function(todo) {
// do something with todo
console.log(todo); // display {id: "###", message: 'Hello world'}
}, function(err) {
// do something with the error
console.log(err.errors.message); // display the error message
});
The .get(fn)
function returns an array of objects in the collection.
// Get all todos
dpd.todos.get(function(results, error) {
//Do something
});
results
is an array of objects:
[
{
"id": "320d6151a9aad8ce",
"title": "Wash the dog",
"category": "pets"
}, {
"id": "320d6151a9aad8ce"
"title": "Write autobiography",
"category": "writing"
}
]
If the collection has no objects, it will be an empty array:
[]
The .get(query, fn)
function filters results by the specified query object. See Querying Collections for information on constructing a query.
// Get all todos that are in the pets category
dpd.todos.get({category: 'pets'}, function(results, error) {
// Do something
});
results
is an array of objects:
[
{
"id": "320d6151a9aad8ce",
"title": "Wash the dog",
"category": "pets"
}
]
The .get(id, fn)
function returns a single object by its id
property.
// Get a specific todo
dpd.todos.get("320d6151a9aad8ce", function(result, error) {
// Do something
});
result
is the object that you requested:
{
"id": "320d6151a9aad8ce",
"title": "Wash the dog",
"category": "pets"
}
The .post(object, fn)
function creates an object in the collection with the specified properties.
// Create a todo
dpd.todos.post({title: "Walk the dog"}, function(result, error)) {
// Do something
});
result
is the object that you posted, with any additional calculated properties and the id
:
{
"id": "91c621a3026ca8ef",
"title": "Walk the dog"
}
The .post(id, object, fn)
function, or .post(object, fn)
where object
has an id
property, will update an object. Using the .post()
function in this way behaves the same as the put()
function.
This is useful when you want to insert an object if it does not exist and update it if it does.
The .put(id, object, fn)
function will update an object that is already in the collection. It will only change the properties that are provided. It is also possible to incrementally update certain properties; see Updating Objects in Collections for details.
// Update a todo
dpd.todos.put("91c621a3026ca8ef", {title: "Walk the cat"}, function(result, error)) {
// Do something
});
You can also use the syntax put(object, fn)
if object
has an id
property:
// Update a todo
dpd.todos.put({id: "91c621a3026ca8ef", title: "Walk the cat"}, function(result, error)) {
// Do something
});
Finally, you can provide a query
object to ensure that the object you are updating has the correct properties. You must still provide an id
property. This can be useful as a failsafe.
// Update a todo only if it is in the "pets" category
dpd.todos.put(
{id: "91c621a3026ca8ef", category: "pets"},
{title: "Walk the cat"},
function(result, error) {
// Do something
});
result
is the entire object after the update:
{
"id": "91c621a3026ca8ef",
"title": "Walk the cat",
"category": "pets"
}
The .put()
function will return an error if the id
and/or query
does not match any object in the collection:
{
"status":400,
"message":"No object exists that matches that query"
}
The .del(id, fn)
function will delete an object from the collection.
// Delete an object
dpd.todos.del("91c621a3026ca8ef", function(result, error) {
// Do something
});
You can also use the syntax .del(query, fn)
if object
has an id
property. You can add additional properties to the query
object to ensure that you are removing the correct object:
// Delete an object
dpd.todos.del({id: "91c621a3026ca8ef", title: "Walk the dog"}, function(result, error) {
// Do something
});
result
will always be null.
The dpd.on(message, fn)
function listens for realtime messages emitted from the server. See Notifying the Client of Changes for information on sending realtime messages with the emit()
function.
message
- The name of the message to listen forfn
- Callback function(messageData)
. Called every time the message is received. There is no error
argument.// Listen for a new todo
dpd.on('todos:create', function(post) {
// Do something
});
In your Collection Event:
// On Post
emit('todos:create', this);
Calling .on()
on the collection itself will namespace the message by the collection name:
// Same as dpd.on('todos:create', fn)
dpd.todos.on('create', function(post) {
// Do something
});
The dpd.off(message)
function stops listening for the specified message.
dpd.off('todos:create');
You can also provide a function that was originally set as a listener to remove only that function.
function onTodoCreated(post) {
// Do something
}
dpd.on('todos:create', onTodoCreated);
dpd.off('todos:create', onTodoCreated);
Calling .off()
on the collection itself will namespace the message by the collection name:
// Same as dpd.off('todos:create');
dpd.todos.off('create');
The dpd.once(message, fn)
function listens for a realtime message emitted by the server and runs the fn
callback exactly once.
dpd.once('todos:create', function(post) {
// Do something
});
Calling .once()
on the collection itself will namespace the message by the collection name:
// Same as dpd.once('todos:create');
dpd.todos.once('create', function(post) {
// Do something
});
The dpd.socketReady(fn)
function waits for a connection to be established to the server and executes the fn
callback with no arguments. If a connection has already been established, it will execute the fn
callback immediately.
It can sometimes take a second or more to establish a connection, and messages sent during this time will not be received by your front end. This function is useful for ensuring that you will receive an message when it is broadcast.
dpd.socketReady(function() {
// Do something
});
Let us know if you have any ideas to improve our docs. Open an issue on github, send us an email, or tweet us.
This entire site, including documentation written in markdown is available on github. Pull requests are appreciated!