The Business Logic reference is split into two sections:
There are two types of business logic requests: collection hooks and custom endpoints. Collection hooks allow server-side processing pre and post data collection requests, while custom endpoints are independent on-demand requests.
A request to the Kinvey service goes through several standardized steps, similar to a pipeline.
For collection hooks, the pipeline is:
All requests to and from Kinvey execute steps 1, 2, 6 and 7. The
other steps are optional. For example, if the response.complete()
method is called during pre-processing (step 3), then processing jumps
to steps 6 and 7, completing immediately.
You can customize the behavior of this pipeline with the following functions:
Function (Hook) | When Called |
---|---|
onPreFetch(request, response, modules) | (Step 3) Called before a query or load (HTTP verb GET ). |
onPreSave(request, response, modules) | (Step 3) Called before a save or update (HTTP verb POST or PUT ). |
onPreInsert(request, response, modules) | (Step 3) Called before an insert (HTTP verb POST ). |
onPreUpdate(request, response, modules) | (Step 3) Called before an update (HTTP verb PUT ). |
onPreDelete(request, response, modules) | (Step 3) Called before a delete (HTTP verb DELETE ). |
onPreLogin(request, response, modules) | (Step 3) Called before a request to /login endpoint (HTTP verb POST ). |
onPostFetch(request, response, modules) | (Step 5) Called after a query or load (HTTP verb GET ). |
onPostSave(request, response, modules) | (Step 5) Called after a save or update (HTTP verb POST or PUT ). |
onPostInsert(request, response, modules) | (Step 5) Called after an insert (HTTP verb POST ). |
onPostUpdate(request, response, modules) | (Step 5) Called after an update (HTTP verb PUT ). |
onPostDelete(request, response, modules) | (Step 5) Called after a delete (HTTP verb DELETE ). |
onLoginSuccess(request, response, modules) | (Step 5) Called after a successful user login (HTTP verb POST ). |
onLoginFailure(request, response, modules) | (Step 5) Called after a failed user login (HTTP verb POST ). |
These can be modified by clicking on the pre- or post-request buttons on the console, and then selecting the action you want to have Business logic.
Custom endpoints have a more abbreviated request pipeline:
All custom endpoints use the onRequest
function for server-side logic:
Function (Hook) | When Called |
---|---|
onRequest(request, response, modules) | (Step 3) Called upon a HTTP verb POST . |
The parameters to all Business Logic hooks are:
Name | Value |
---|---|
request | The request that Kinvey received from a client |
response | The response that Kinvey will send to a client |
modules | Various JavaScript libraries available for use in your business logic |
The request object has the following fields/values:
Field | Value |
---|---|
method | The HTTP method of the request, GET , PUT , POST or DELETE |
headers | All headers that were set on the originating request |
body | An object representing the parsed body of the original request |
params | A list of all parameters in the URL query string |
username | DEPRECATED The username of the requesting user - use requestContext instead |
entityId | The requested entity, will be undefined if no entity present in request |
collectionName | The name of the collection that's executing this logic |
appKey | The app key for the current Kinvey backend |
The response object has the following fields/values:
Field | Value |
---|---|
headers | The headers that will be set on the outgoing response |
body | The current body of the outgoing response |
complete | A function that indicates the business logic is complete and that no further processing of the request should happen |
continue | A function that indicates the business logic is complete and that normal request processing should continue |
error | A function that indicates the business logic has encountered an error |
The three response functions (complete
, continue
, and error
) should be called following a return statement. For example:
return response.complete(201);
response.complete
and response.error
are available for custom endpoints. response.continue
is invalid in the custom endpoint context and will throw an exception if used.
response.body
can be set during pre-process business logic, however Kinvey may change
the contents of response.body
during further processing.
The following modules are available for use in your JavaScript:
logger
-- Log messages to the Kinvey console.collectionAccess
-- Access your raw data in MongoDB.push
-- Send push notifications to user's devices.email
-- Send email notifications.validation
-- Validate incoming requests.utils
-- Various utilities.request
-- HTTP request module.lodash
-- Implementation of lodash, a JavaScript toolkit.json2csv
-- Implementation of json2csv, used for converting JSON to CSV.moment
-- Implementation of moment.js, used for Date/Time functions.moment-timezone
-- Implementation of moment-timezone.js, used for timezone processing.xml2json
-- Implementation of xml2json, used for converting XML to JSON (and vice versa).xmldoc
-- Implementation of xmldoc, used for parsing XML documents.async
-- Implementation of async.js, used for asynchronous function processing.backendContext
-- Provides methods to access information about the current backend context.requestContext
-- Provides methods to access information about the current request context.bluebird
-- Promises librarykinvey
-- Kinvey Service APItwilio
-- Integration with Twilio SMS APIslack
-- Integration with Slack meesaging APIhipchat
-- Integration with the HipChat messaging APIfacebookMessenger
-- Integration with the Facebook Messenger send APIwatson
-- Integration with IBM WatsonUse the logger module to log a message that you can view in the console. Logging can be filtered and traced to a specific request.
Available Methods:
Method | Action |
---|---|
info(message, callback) | Log message as an informational message |
warn(message, callback) | Log message as a warning |
error(message, callback) | Log message as an error |
fatal(message, callback) | Log message as a fatal error |
For example:
var logger = modules.logger;
logger.info('Started BL processing', function(err, result) {
if (!request.body.name) {
logger.fatal('Request did not include a name...');
response.complete(400);
}
}
);
...
The logging level (info, warning, error, fatal) is just used in logging and will not affect the request in any way.
Use the collection access module to access your data in MongoDB. collectionAccess
provides an asynchronous interface to MongoDB collections.
Available Methods:
Method | Action | Options Supported |
---|---|---|
objectID(string) | Convert string to an internal Kinvey ObjectID representation | N/A |
collection(collectionName) | Return the internal collection object for the collection collectionName | N/A |
collectionExists(callback) | Checks to see if the current collection exists | N/A |
find(query, options, callback) | Find entities matching query , always returns an array | limit, sort, fields, skip |
findOne(query, options, callback) | Find an entity matching query , always returns a single object | sort, fields, skip |
insert(doc, callback) | Insert the document doc or an array of documents into the collection. | None |
remove(query, callback) | Remove all docs matching query from the collection | None |
save(doc, callback) | Insert or Update doc in collection | None |
distinct(key, query, callback) | Return all distinct values for the given keys | None |
update(query, doc, options, callback) | Updates doc in collection | upsert, multi, sort |
count(query, callback) | Return the number of items matching the query | None |
findAndModify(query, sort, doc, options, callback) | Find just one entity matching the query and modify it with doc . If query matches multiple entities, use sort to determine which single entity to modify. | remove, upsert, new |
findAndRemove(query, sort, callback) | Find just one entity matching the query and delete it. If query matches multiple entities, use sort to determine which single entity to delete. | None |
mapReduce(map, reduce, options, callback) | Perform a mapReduce jobs | sort, limit |
group(keys, condition, initial, reduce, finalize, command, callback) | Group entities by keys | None |
geoNear(x, y, options, callback) | Find entities near x (longitude) and y (latitude) | query, num, maxDistance, distanceMultiplier, spherical, includeLocs |
Collection()
website. Kinvey's collectionAccess implementation supports a subset of these options as specified in the table above.All collectionAccess
methods are asynchronous, so actions that need data from a collectionAccess
method need to be performed in the callback to the method (or in the promise fulfillment function, if using promises).
Below you can see examples of the find()
, findAndModify()
and update()
methods:
// Ignore the incoming request and return all items tagged with an age greater than 10
modules.collectionAccess.collection('myCollection').find({"age": {"$gt": 10}}, function (err, docs) {
if (err) {
logger.error('Query failed: '+ err);
} else {
response.body = docs;
response.complete(200);
}
});
// Find the user with the highest score on Easy difficulty and update his "firstPlace" to true
var myCollection = modules.collectionAccess.collection('myCollection');
myCollection.findAndModify({"difficulty": "Easy"}, [["score", -1]], { $set: { "firstPlace": "true" }}, function (err, docs) {
if (err) {
logger.error('Query failed: '+ err);
} else {
response.body = docs;
response.complete(200);
}
});
// Find all documents where the "age" has value of 18 or higher and set their "isAdult" to "true"
var myCollection = modules.collectionAccess.collection('myCollection');
myCollection.update({"age": {"$gt": 17}}, { $set: { "isAdult": "true" }}, { "multi": true }, function (err, status) {
if (err) {
logger.error('Query failed: '+ err);
} else {
response.complete(200);
}
});
remove
removing all of your data.
Additionally, Kinvey stores metadata and ACL information within your data. This data
is not guaranteed to stay the same or constant, and modifying this data may result in
your data becoming unavailable or accidentally releasing your data to everyone.
^
), and case sensitive. To do case insensitive search, create a normalized (i.e. all lowercase) field in your collection and perform the match on that field.
When an entity is created without explicitly specifying an _id
attribute, that entity's _id
will not be a regular JavaScript string; instead, it will be represented as a Kinvey ObjectID, which is a special internal object type. When searching for an entity with an _id
attribute that is stored as an ObjectID, you can use the collectionAccess.objectID
helper function to convert your string into the special type.
_id
field, regardless of whether or not that entity's _id
is stored as a String or as an ObjectID. The Kinvey REST API automatically checks whether the _id
field of an incoming request is an ObjectID, and acts accordingly. However, when using collectionAccess through business logic, you interact directly with your raw data, and thus you must handle any type casting yourself.
// To find an entity that has a String _id field, we must use the same to query for it
modules.collectionAccess.collection('myCollection').findOne({ _id: myIncomingStringId }, function(err, result) {
...
});
// To find an entity that has an ObjectID _id field, we must use the same to query for it
modules.collectionAccess.collection('myCollection').findOne({ _id: modules.collectionAccess.objectID(myIncomingStringId) }, function(err, result) {
...
});
All asynchronous collectionAccess
methods have sibling methods that return Promise
objects. (For more info on promises, see the Bluebird section below). The method signatures are the same as the callback-style methods, except "Async" is appended to the method name and there is no callback argument passed. Methods returning promises are:
Method | Action | Options Supported |
---|---|---|
collectionExistsAsync() | Checks to see if the current collection exists. Returns a Promise . | N/A |
findAsync(query, options) | Find entities matching query , always returns an array. Returns a Promise . | limit, sort, fields, skip |
findOneAsync(query, options) | Find an entity matching query , always returns a single object. Returns a Promise . | sort, fields, skip |
insertAsync(doc) | Insert the document doc or an array of documents into the collection. Returns a Promise . | None |
removeAsync(query) | Remove all docs matching query from the collection. Returns a Promise . | None |
saveAsync(doc) | Insert or Update doc in collection. Returns a Promise . | None |
distinctAsync(key, query) | Return all distinct values for the given keys . Returns a Promise . | None |
updateAsync(query, doc, options) | Updates doc in collection. Returns a Promise . | upsert, multi, sort |
countAsync(query) | Return the number of items matching the query . Returns a Promise . | None |
findAndModifyAsync(query, sort, doc, options) | Find just one entity matching the query and modify it with doc . If query matches multiple entities, use sort to determine which single entity to modify. Returns a Promise . | remove, upsert, new |
findAndRemoveAsync(query, sort) | Find just one entity matching the query and delete it. If query matches multiple entities, use sort to determine which single entity to delete. Returns a Promise . | None |
mapReduceAsync(map, reduce, options) | Perform a mapReduce jobs. Returns a Promise . | sort, limit |
groupAsync(keys, condition, initial, reduce, finalize, command) | Group entities by keys . Returns a Promise . | None |
geoNearAsync(x, y, options) | Find entities near x (longitude) and y (latitude). Returns a Promise . | query, num, maxDistance, distanceMultiplier, spherical, includeLocs |
Here's an example similar to the one above, using findAsync()
to return a Promise:
// Ignore the incoming request and return all items tagged with an age
// greater than 10.
var findData = modules.collectionAccess.collection('myCollection').findAsync({"age": {"$gt": 10}});
findData.then(function (docs) {
response.body = docs;
response.complete(200);
},
function(err){
logger.error('Query failed: '+ err);
});
Use the push module to send a push notification to a device registered with your app.
Available Methods:
Method | Action |
---|---|
broadcastMessage(message, callback) | Broadcasts a simple text-only message to all devices registered with this app |
sendMessage(users, message, callback) | Sends a simple text-only message to the users in users |
send(users, message, callback) | Alias for sendMessage() |
sendPayload(users, iOSAps, iOSExtras, androidPayload, callback) | Sends a custom payload to the users in users which allows for sending advanced options and data |
broadcastPayload(iOSAps, iOSExtras, androidPayload, callback) | Broadcasts custom payloads to all devices registered with this app which allows for sending advanced options and data |
For example, to send a broadcast message:
var push = modules.push;
if (request.body.sendMessageToAll){
push.broadcastMessage(request.body.message, function(err, result) {
response.continue();
});
}
The users
argument to send
is either an array of Kinvey User documents or a single user document. The message
will be sent to all iOS or Android devices that are contained in the documents in users
.
You can query the user
collection with the collectionAccess
module to get a list
of users.
For example:
var push = modules.push, collectionAccess = modules.collectionAccess;
collectionAccess.collection('user').find({"firstName": request.body.firstName}, function (err, userColl) {
if (err) {
logger.error('Query failed: '+ err);
} else {
userColl.forEach(function (user) {
logger.info('Pushing message to ' + user);
push.sendMessage(user, "People who are named " + user.firstName + " are awesome!", function(err, result) {
});
});
}
});
The methods sendPayload
and broadcastPayload
allow for more robust push
messages. For iOS, the payload consists of two arguments, iOSAps
and
iOSExtras
. iOSAps
is a JSON object that can have the following properties:
Field | Value |
---|---|
alert | An alert message to display to the user |
badge | The badge number to appear on the notification |
sound | The name of the sound file in the application package to play |
content-available | If set to 1, the remote notification acts as a "silent" notification |
iOSExtras
is a JSON object with custom name-value pairs to be included in the push notification.
For Android, the payload is contained in the androidPayload
attribute, which is any JSON object to be sent to Google Cloud Messaging (GCM).
Each of the arguments above are null-safe.
For example, to send a broadcast with payloads:
var iOSAps = { alert: "You have a new message", badge: 2, sound: "notification.wav" }
var iOSExtras = {from: "Kinvey", subject: "Welcome to Business Logic"}
var androidPayload = {message: "You have a new Message", from: "Kinvey", subject: "Welcome to BL" }
var push = modules.push;
push.broadcastPayload(iOSAps, iOSExtras, androidPayload, callback);
Use the email module to send email to any valid email address.
Available Methods:
Method | Action |
---|---|
send(from, to, subject, text_body, reply_to, html_body, cc, bcc, callback) | Send an email to to from from using the subject and body . reply_to is an optional argument for the reply to line of the message. For the email body, text_body is for the plain-text version of the email and is required. html_body is an optional parameter that accepts an HTML-formatted string, which creates an optional html body for the email message. cc and bcc are optional arguments for adding cc and bcc users. |
For example, to send a text email:
var email = modules.email;
email.send('my-app@my-app.com',
request.body.friendEmail,
'Join my octagon in my-app!',
"You've been invited to join " + request.body.name + "'s octagon in my-app!", function(err, result) {
response.continue();
});
To send an HTML email, it is important to note that the reply-to must be included; if you want the reply-to to be the same as the from address, you can either also pass the from address in the reply_to argument, or simply pass a null value (which will default the reply to to the from address). For example:""
var email = modules.email;
email.send('my-app@my-app.com',
request.body.friendEmail,
'Join my octacgon in my-app!',
"You've been invited to join " + request.body.name + "'s octagon in my-app!",
null,
'<html>You've been invited to join <b>'+request.body.first_name+'</b>'s octagon in my-app!</html>', callback);
Use the validation module to validate input on a request.
Available Methods:
Method | Action |
---|---|
doValidation(spec, doc) | Validate doc using spec |
For example:
var validation = modules.validation
, result, spec, doc;
spec = {
someRequiredField: {required: true},
age: {min: '0', max: '200'},
someTextField: {pattern: ['a regular expression']}
};
doc = request.body;
result = validation.doValidation(spec, doc);
if(result.length > 0) {
response.body.debug = result;
response.complete(400);
} else {
response.continue();
}
The spec syntax is an object where the properties are fields that are expected to be
present in the doc
argument to doValidation
, and the values are validation operators.
If an property is missing, doValidation
returns a string describing the failure.
Extra properties are allowed to be present in doc
. A property is allowed to have
multiple operators
Allowed validation operators are:
Operator | Accepted values |
---|---|
required | Accepts the argument true , if you don't want a property to be required, remove the required operator |
min | Accepts a number argument. doc is rejected if the property's value is numerically less than the argument |
max | Accepts a number argument. doc is rejected if the property's value is numerically greater than the argument |
pattern | Accepts a regular expression as an argument. The regular expression must not have the leading and trailing / character. The doc is rejected if the pattern fails to match the property |
Use the utils module for various utility helper functions.
Available Objects:
Method | Action |
---|---|
renderTemplate(spec, data) | Renders the template using the mustache template engine with specification spec using data |
kinveyEntity(options) | DEPRECATED (Please see the Kinvey Entity section of the Kinvey module for working with Kinvey Entities) Returns a JSON object with Kinvey metadata for use in AppData collections. |
tempObjectStore | Key-value store for persisting temporary data between a pre- and post-hook. |
base64 | Encode and decode strings to/from base64 |
convert | Convert between Kinvey data formats |
Used to render templates using the mustache template engine.
For example:
var render = modules.utils.renderTemplate
, spec
, output;
spec = 'Hello there {{data.name}} happy {{data.age}}th birthday!';
output = render(spec, {data: request.body});
response.body = {"message": output};
response.complete(200);
The render
method can take either a plain text or HTML-formatted string as a value for spec.
A complete guide on how to use mustache can be found in the Mustache Manual.
A key-value store for persisting temporary data between a pre- and post-hook. tempObjectStore
is an ephemeral store that only lives for the duration of a single request, but will allow for data that is written in a pre-hook to be read in a post-hook. The object implements three methods:
Method | Behavior |
---|---|
set(key, value) | Writes a value for the given key to the tempObjectStore |
get(key) | Returns the value of the supplied key |
getAll() | Returns all key/values in the tempObjectStore as an object |
For example, to store an item in an onPreSave hook:
function onPreSave(request, response, modules) {
var tempObjectStore = modules.utils.tempObjectStore;
tempObjectStore.set('token', request.body.token);
response.continue();
}
Then, to retrieve it:
function onPostSave(request, response, modules) {
var tempObjectStore = modules.utils.tempObjectStore;
var token = tempObjectStore.get('token');
response.body = { "message": "Object for token " + token + " was saved successfully."};
response.complete();
}
tempObjectStore
is meant for storing small, temporary amounts of data to be passed between pre- and post- hooks. Large amounts of data / large objects should not be stored in the tempObjectStore
, as there is a limit on the size of the payload that passes through Kinvey Business Logic.A utility for encoding utf8 strings to base64, and decoding base64 strings to utf8.
Method | Behavior |
---|---|
encode(str) | Encodes a string to base64 |
decode(str) | Decodes a base64 string to utf8 |
For example, to encode a string to base64:
function onPreSave(request, response, modules) {
var encoded = modules.utils.base64.encode(request.body.username);
request.body.username = encoded;
response.continue();
}
To decode a string from base64:
function onPreSave(request, response, modules) {
var decoded = modules.utils.base64.decode(request.body.username);
request.body.username = decoded;
response.continue();
}
A utility for converting data.
Method | Behavior |
---|---|
toKinveyDateString(date) | Converts a Date object, a moment, or a date string into the Kinvey date format. If the passed in date is not a valid date, "Invalid date" will be returned. |
fromKinveyDateString(str, format) | Decodes a Kinvey date string into the specified format. Valid formats are 'date', 'moment' and 'string'. If no format is provided, a JavaScript Date object is returned. If the passed in str is not a valid date, "Invalid date" will be returned. |
For example, to convert a date to to a Kinvey Date string:
myDate = new Date();
kinveyDate = modules.utils.convert.toKinveyDateString(myDate);
To convert a Kinvey Date string to a JavaScript date object:
myDate = modules.utils.convert.fromKinveyDateString(kinveyDate, 'date');
// note: this could also be accomplished via modules.utils.convert.fromKinveyDateString(kinveyDate);
To convert a Kinvey Date string to a moment:
myMoment = modules.utils.convert.fromKinveyDateString(kinveyDate, 'moment');
To convert a Kinvey Date into a standard ISO-8601 date string
myDateString = modules.utils.convert.fromKinveyDateString(kinveyDate, 'string');
Available Methods:
Method | Action |
---|---|
request(options, callback) | Make an arbitrary HTTP request |
get(options, callback) | request with method set to GET |
put(options, callback) | request with method set to PUT |
post(options, callback) | request with method set to POST |
del(options, callback) | request with method set to DELETE |
callback
is a function taking 3 arguments, error
, response
and body
:
error
-- Set to null
if no error, otherwise set to an error object with the failureresponse
-- The full response from the server (containing headers
, body
and status
)body
-- The returned HTTP body from the server.options
is an object that may contain the following properties:
Property | Description | Is Required? |
---|---|---|
uri | The HTTP endpoint to request | Yes |
qs | An object containing querystring values to append to the uri (NB: Query params may be directly placed in the URI) | No |
method | The HTTP method to use (May be one of "HEAD", "PUT", "POST", "GET" or "DELETE") | No |
headers | An object containing the HTTP headers to set | No |
body | The entity body for POST or PUT, must be string or buffer | No |
form | Used to send 'Content-type: application/x-www-form-urlencoded; charset=utf-8' data to a form | No |
json | When set to an object sends JSON encoded object to server, also JSON.decodes response | No |
followRedirect | Follow GET HTTP 3XX responses, defaults to true | No |
followAllRedirects | Follow all HTTP method 3XX responses, defaults to false | No |
maxRedirects | Maximum number of times to follow a 3XX redirect, defaults to 10 | No |
encoding | Specify the string encoding for the response | No |
timeout | Specifies the timeout for the request, must be less than 1500ms | No |
oauth | Options for OAUTH HMAC-SHA1 signing | No |
strictSSL | Set to true to force SSL cert validation defaults to false | No |
aws | Object containing AWS signing information (needs key , secret and possibly bucket | No |
For example:
var req = modules.request;
req.get({uri: 'http://api.example-api.com/v1/abcdefg',
method: 'GET'},
function(error, res, body){
if (error){
response.body = {error: error.message};
response.complete(434);
} else {
response.body = JSON.parse(body);
response.complete(res.status);
}
});
The body
value passed to your callback will be encoded differently based on the
data returned by the API you are requesting data from. All Kinvey libraries expect
the data returned via response.body
to be application/json
, so you should convert
the response from request to a JavaScript object prior to assigning it to response.body
.
If you've used the json
property in the options object, then this step has already
been completed. Otherwise, for JSON data you need to call JSON.parse(body)
.
request
and response
parameters
to your Business Logic function.
The request module supports SSL encryption. To enable SSL encryption, simply specify
a uri
starting with https://
. The module will use SSL if required. By default the
request module does not validate SSL certificates, which decreases the security of
https
requests. To force SSL verification set strictSSL
to true
in your options
.
This is recommended for the best security, but may limit your ability to access some
servers.
strictSSL
to true in your options
.
All request
methods have sibling methods that return Promise
objects. (For more documentation, see the Bluebird section below). The method signatures are the same as the callback-style methods, except "Async" is appended to the method name and there is no callback argument passed. Methods returning promises are:
Method | Action |
---|---|
requestAsync(options) | Make an arbitrary HTTP request. Returns a Promise object. |
getAsync(options) | request with method set to GET . Returns a Promise object. |
putAsync(options) | request with method set to PUT . Returns a Promise object. |
postAsync(options) | request with method set to POST . Returns a Promise object. |
delAsync(options) | request with method set to DELETE . Returns a Promise object. |
An example using the request module to return a Promise:
var req = modules.request;
var fetchData = req.getAsync({uri: 'http://api.example-api.com/v1/abcdefg'});
fetchData.then(
function(res, body){
response.body = JSON.parse(body);
response.complete(res.status);
},
function(error){
response.body = {error: error.message};
response.complete(434);
}
);
For more information on the request module, see Request -- Simplified HTTP request method.
A fork of underscore.js, lodash is a JavaScript toolkit which provides cross-platform methods for manipulating objects, collections, and more in a performant fashion.
The following methods from v4.0.0 of lodash are supported in Kinvey Business Logic:
Array | |||
---|---|---|---|
chunk | compact | concat | difference |
differenceBy | differenceWith | drop | dropRight |
dropRightWhile | dropWhile | fill | findIndex |
findLastIndex | first | flatMap | flatten |
flattenDeep | fromPairs | head | indexOf |
initial | intersection | intersectionBy | intersectionWith |
join | last | lastIndexOf | pull |
pullAll | pullAllBy | pullAt | remove |
slice | sortedIndex | sortedIndexBy | sortedIndexOf |
sortedLastIndex | sortedLastIndexBy | sortedLastIndexOf | sortedUniq |
sortedUniqBy | tail | take | takeRight |
takeRightWhile | takeWhile | union | unionBy |
unionWith | uniq | uniqBy | uniqWith |
unzip | unzipWith | without | xor |
xorBy | xorWith | zip | zipObject |
zipWith | .prototype.reverse |
Collection | |||
---|---|---|---|
countBy | each | eachRight | every |
filter | find | findLast | forEach |
forEachRight | groupBy | includes | invokeMap |
keyBy | map | orderBy | partition |
reduce | reduceRight | reject | sample |
sampleSize | shuffle | size | some |
sortBy |
Date | |||
---|---|---|---|
now |
Function | |||
---|---|---|---|
after | ary | before | bind |
bindKey | curry | curryRight | debounce |
defer | delay | flip | memoize |
negate | once | overArgs | partial |
partialRight | rearg | rest | spread |
throttle | unary | wrap |
Lang | |||
---|---|---|---|
clone | cloneDeep | cloneDeepWith | cloneWith |
eq | gt | gte | isArguments |
isArray | isArrayLike | isArrayLikeObject | isBoolean |
isDate | isElement | isEmpty | isEqual |
isEqualWith | isError | isFinite | isFunction |
isInteger | isLength | isMatch | isMatchWith |
isNaN | isNative | isNil | isNull |
isNumber | isObject | isObjectLike | isPlainObject |
isRegExp | isSafeInteger | isString | isSymbol |
isTypedArray | isUndefined | lt | lte |
toArray | toInteger | toLength | toNumber |
toPlainObject | toSafeInteger | toString |
Math | |||
---|---|---|---|
add | ceil | floor | max |
maxBy | mean | min | minBy |
round | subtract | sum | sumBy |
Number | |||
---|---|---|---|
clamp | inRange | random |
Object | |||
---|---|---|---|
assign | assignIn | assignInWith | assignWith |
at | create | defaults | defaultsDeep |
extend | extendWith | findKey | findLastKey |
forIn | forInRight | forOwn | forOwnRight |
functions | functionsIn | get | has |
hasIn | invert | invoke | keys |
keysIn | mapKeys | mapValues | merge |
mergeWith | omit | omitBy | pick |
pickBy | result | set | setWith |
toPairs | toPairsIn | transform | unset |
values | valuesIn |
Seq | |||
---|---|---|---|
_ | chain | tap | thru |
flatMap | prototype[Symbol.iterator] | at | chain |
commit | next | plant | reverse |
toJSON | value | valueOf |
String | |||
---|---|---|---|
camelCase | capitalize | deburr | endsWith |
escape | escapeRegExp | kebabCase | lowerCase |
lowerFirst | pad | padEnd | padStart |
parseInt | repeat | replace | snakeCase |
split | startCase | startsWith | template |
toLower | toUpper | trim | trimEnd |
trimStart | truncate | unescape | upperCase |
upperFirst | words |
Util | |||
---|---|---|---|
attempt | bindAll | cond | conforms |
constant | flow | flowRight | identity |
iteratee | matches | matchesProperty | method |
methodOf | mixin | noConflict | noop |
nthArg | over | overEvery | overSome |
property | propertyOf | range | rangeRight |
runInContext | times | toPath | uniqueId |
Methods |
---|
_.templateSettings.imports._ |
stringSize |
The lodash module also includes the following properties:
Properties |
---|
VERSION |
templateSettings |
templateSettings.escape |
templateSettings.evaluate |
templateSettings.imports |
templateSettings.interpolate |
templateSettings.variable |
For example:
function onPreFetch(request, response, modules){
var _ = modules.lodash; // Get lodash reference
var myArray = [1, 2, 3];
var reversedArray = _.reverse(myArray); // [3, 2, 1]
}
For reference on the lodash API and each of the methods listed above, see the lodash documentation.
json2csv is a module that converts JSON to CSV.
Signature:
json2csv(options, callback)
Example usage:
function onPostFetch(request, response, modules) {
var json2csv = modules.json2csv;
var fields = ['name', 'price']; // CSV columns
var bookResults = [
{
name: "Publication 1",
price: 19.50
},
{
name: "Publication 2",
price: 4.00
}
]; // These objects represent results from a Kinvey collection fetch
bookJson = JSON.stringify(bookResults); // json2csv input be serialized JSON
// Convert
json2csv({
data: bookResults,
fields: fields
}, function(err, csv) {
if (err)
response.complete(500);
var returnResult = { csvStringData: csv };
response.body=returnResult;
response.complete(200);
});
}
The contents of csvStringData
would be:
name, price
"Publication 1", 19.50
"Publication 2", 4.00
fields
array will be processed and included in CSV output.
You can also use dot notation to create CSV columns with nested JSON fields:
function onPostFetch(request, response, modules) {
var json2csv = modules.json2csv;
var fields = ['book.name', 'book.publisher', 'price', 'type']; // CSV columns
var bookResults = [
{
book: {
name: "Publication 1",
publisher: "Acme Publishing, Inc"
},
price: 19.50,
type: "paperback"
},
{
book: {
name: "Publication 2",
publisher: "Acme Publishing, Inc"
},
price: 4.00,
type: "paperback"
}
]; // These objects represent results from a Kinvey collection fetch
bookJson = JSON.stringify(bookResults); // json2csv input must be serialized JSON
// Convert
json2csv({
data: bookResults,
fields: fields
}, function(err, csv) {
if (err)
response.complete(500);
var returnResult = { csvStringData: csv };
response.body=returnResult;
response.complete(200);
});
}
The contents of csvStringData
would be:
book.name, book.publisher, price, type
"Publication 1", "Acme Publishing, Inc", 19.50, "paperback"
"Publication 2", "Acme Publishing, Inc", 4.00, "paperback"
For more examples and a complete options
reference, see the json2csv Github page.
A date library for parsing, validating, manipulating, and formatting dates, using
moment.js. A new moment
can be initialized with no arguments (to get the current date and time) or with the following arguments:
date
-- A string date or JavaScript Date()format
-- A moment.js format stringlocale
-- The locale of the momentThe following methods from v2.10.3 of moment.js are supported in Kinvey Business Logic:
Methods | ||
---|---|---|
add | subtract | dates |
date | day | days |
daysInMonth | dayOfYear | diff |
duration | humanize | format |
fromNow | from | get |
set | calendar | hour |
hours | isBefore | isSame |
isAfter | isLeapYear | isDST |
isValid | isMoment | lang |
min | max | millisecond or milliseconds |
minute or minutes | month or months | second or seconds |
week or weeks | isoWeek or isoWeeks | year or years |
startOf | endOf | toDate |
toArray | toJSON | toISOString |
utc | local | unix |
weekday | isoWeekday | weekYear |
isoWeekYear | zone | parseZone |
isDSTShifted | isLocal | isUtcOffset |
isUTC | isUtc | zoneAbbr |
zoneName |
In addition, the moment module supports moment duration objects with the following methods:
Methods | ||
---|---|---|
humanize | milliseconds | asMillisecons |
seconds | asSeconds | minutes |
asMinutes | hours | asHours |
days | asDays | months |
asMonths | years | asYears |
add | subtract | as |
get |
To declare a new moment object, create a modules.moment
, and call any of the supported methods on that object.
function onPreFetch(request, response, modules){
var theMoment = modules.moment();
theMoment.add('days', 7);
response.body={"thisTimeNextWeek" : theMoment};
response.complete(200);
}
To declare and use a duration object, create a modules.moment
object and invoke the duration
method, and then call any of the supported methods on the duration
object.
function onPreFetch(request, response, modules){
var duration = modules.moment().duration(24, 'hours');
response.body={"duration" : duration.humanize()};
response.complete(200);
}
For reference on the moment.js API and each of the methods listed above, see the moment.js documentation.
An extension of moment.js which adds extra methods for parsing and displaying dates in any time zone. The moment-timezone constructor takes the same parameters as moment but uses the final paremter as a time zone identifier.
var theMoment = moment.tz(1453234509, 'America/New_York').format() // 1970-01-17T14:40:34-05:00
In addition to all of the moment.js methods above, the following methods from v0.5.0 of moment-timezone.js are supported in Kinvey Business Logic:
Methods | ||
---|---|---|
format | zoneAbbr | zoneName |
setDefault | guess | add |
link | load | zone |
names | unpack | unpackBase60 |
pack | packBase60 | createLinks |
filterYears | filterLinkPack |
The moment-timezone.js module also supports Zone
object, which offers the following methods:
Methods |
---|
abbr |
offset |
parse |
name
property in the zone
namespace
To declare a new moment-timezone object:
function onPreFetch(request, response, modules){
var theMoment = modules.momentTimezone.tz('America/New_York'); // Creates a new moment using current date/time and 'America/New_York' time zone
theMoment.add('days', 7);
response.body={"thisTimeNextWeekWithTimeZone" : theMoment.format()};
response.complete(200);
}
To modify the time zone of an existing moment:
function onPreFetch(request, response, modules){
var theMoment = modules.momentTimezone('2000-01-01').tz('America/New_York');
response.body={"dateWithTimeZone" : theMoment.format()};
response.complete(200);
}
To use the zone
namespace:
function onPreFetch(request, response, modules){
var offset = modules.momentTimezone.tz.zone('America/New_York').offset(1453236443); // 480
var name = modules.momentTimezone.tz.zone('America/New_York').name; // America/New_York
response.body={
"tzOffset" : offset,
"tzName" : name
};
response.complete(200);
}
For reference on the moment-timezone.js API and each of the methods listed above, see the moment-timezone.js documentation.
xml2json is a utility module which converts XML to JSON and JSON to XML. The following methods from v0.9.0 of xml2json are supported in Kinvey Business Logic:
Methods | |
---|---|
toJson(xml, options) | Converts XML to JSON. If options param is null, xml2json uses its own defaults (see below) |
toXml(json) | Converts JSON to XML |
Example usage:
function onPreFetch(request, response, modules){
var parser = modules.xml2json;
// xml to json conversion
var xml = "<foo>bar</foo>";
var jsonResult = parser.toJson(xml); // Returns stringified JSON
response.body=JSON.parse(jsonResult); // { foo: bar }
response.complete(200);
}
toJson
options
param defaults:
var options = {
object: false,
reversible: false,
coerce: false,
sanitize: true,
trim: true,
arrayNotation: false
};
For reference on the xml2json API and each of the methods listed above, see the xml2json Github page.
xmldoc is a module that allows parsing of XML documents.
function onPreFetch(request, response, modules){
var xmldoc = modules.xmldoc;
var document = new xmldoc.XmlDocument('<hello>world</hello>');
...
}
Properties | |
---|---|
name | Node name. I.e. 'foo' for <foo> . Note: XML namespaces are ignored by the underlying parser. <foo:bar> returns 'foo:bar' |
attr | Dictionary containing attribute properties. E.g. fooNode.attr.bar for <foo bar="..."> |
val | String value of the node. E.g. 'bar' for <foo>bar</foo> |
children | an XmlElement array containing child nodes |
firstChild | Element's first child. null if non-existent |
lastChild | Element's last child. null if non-existent |
line | Element's line in the original XML string |
column | Element's column in the original XML string |
position | Element's position in the original XML string |
startTagPosition | Element's start tag position in the original XML string |
XmlDocument
and XmlElement
properties return 'sensible' values, such as []
for children, {}
for attr
, and ''
for val
Methods | |
---|---|
eachChild(callback) | Similar to forEach . Calls func(child, index, array) for each child node |
childNamed(name) | Returns first child node named name , or undefined |
childrenNamed(name) | Same as childNamed but returns all results in an array (or [] if no children found) |
childWithAttribute(name, value) | Returns first child with the given name attribute value. If value is omitted, returns first node with given attribute definition |
descendantWithPath(path) | Searches for a specific path with dot notation |
valueWithPath(path) | Similar to descendantWithPath but goes deeper and extracts the node value |
toString([options]) | JavaScript toString override. Used for debugging purposes |
XmlDocument
and XmlElement
objects contain the same properties and methods
Example usage:
function onPreFetch(request, response, modules){
var xmldoc = modules.xmldoc;
var document = new xmldoc.XmlDocument('<foo>bar</foo>');
var returnResult = {};
returnResult.name = document.name; // foo
returnResult.val = document.val; // bar
response.body=returnResult; // { name: 'foo', val: 'bar' }
response.complete(200);
}
For reference on the xmldoc API and each of the methods and properties above, see the xmldoc Github page.
Async is a utility module which provides straight-forward, powerful functions for working with asynchronous JavaScript, using async.js. The following methods from v1.4.2 of async.js are supported in Kinvey Business Logic:
Methods | ||
---|---|---|
each | forEach | eachSeries |
forEachSeries | eachLimit | forEachLimit |
map | mapSeries | mapLimit |
filter | select | filterSeries |
selectSeries | reject | rejectSeries |
reduce | inject | foldl |
rejectRight | foldr | detect |
detectSeries | sortBy | some |
any | every | all |
concat | concatSeries | series |
parallel | parallelLimit | whilst |
doWhilst | until | doUntil |
queue | cargo | times |
timesSeries | noConflict | nextTick |
setImmediate | eachOf | forEachOf |
eachOfSeries | forEachOfSeries | eachOfLimit |
forEachOfLimit | reduceRight | filterLimit |
selectLimit | rejectLimit | someLimit |
everyLimit | detectLimit | auth |
retry | waterfall | iterator |
apply | during | doDuring |
priorityQueue | log | dir |
memoize | unmemoize | timesLimit |
seq | compose | applyEach |
applyEachSeries | forever | ensureAsync |
constant | asyncify | wrapSync |
For example:
function onPreFetch(request, response, modules){
var async = modules.async;
var body = response.body;
var moment = modules.moment().format();
var logger = modules.logger.error;
var debug = modules.logger.info;
var req = modules.request;
var req = modules.request;
var getDate = function(callback) {
modules.request.get('http://date.jsontest.com', function(error, resp, body){
if (error){
callback(error);
} else {
callback(null, (JSON.parse(body)).date);
}
});
};
var getTime = function(callback) {
req.get('http://time.jsontest.com', function(error, resp, body){
if (error){
callback(error);
} else {
callback(null, (JSON.parse(body)).time);
}
});
};
var callback = function(error, results) {
if (error) {
response.body = {error: error.message};
response.complete(400);
return;
}
response.body.date = results[0];
response.body.time = results[1];
response.complete(200);
return;
};
async.parallel([getDate, getTime], callback);
}
For reference on the async.js API and each of the methods listed above, see the async.js Github page.
Used to return data and perform functions against the current backend context.
Method | Behavior |
---|---|
getAppKey() | Returns the current backend appKey |
getAppSecret() | Returns the current backend appSecret |
getMasterSecret() | Returns the current backend masterSecret |
getSecurityContext() | Returns the context of the current user - possible values are user for a user account, app for the app account with app secret, and master for the app account with master secret |
getAuthenticatedUsername() | DEPRECATED Returns the username of the user who submitted the request. |
One common use case for these functions is for calling requests against the current backend to provide a method to obtain the correct authentication credentials. This allows for BL scripts to be migrated from backend to backend without code changes, such as in the case of seperate development and production backends.
function onRequest(request, response, modules){
var context = modules.backendContext;
var utils = modules.utils;
var appKey = context.getAppKey();
var masterSecret = context.getMasterSecret();
var uri = 'https://' + request.headers.host + '/appdata/'+ appKey +'/myCollection/';
var authString = "Basic " + utils.base64.encode(appKey + ":" + masterSecret);
var requestOptions = {
uri:uri,
headers: {
"Authorization":authString
}
};
var auth = modules.request.get(requestOptions,function(error, res, body){
if (error){
response.error(error);
} else {
response.body = JSON.parse(body);
response.complete(res.status);
}
});
}
Used to return data and perform functions against the current request context.
Method | Behavior |
---|---|
getAuthenticatedUserId() | Returns the ID of the user who submitted the request. When the app or master secret is used to authenticate, the application ID is returned. |
getAuthenticatedUsername() | Returns the username of the user who submitted the request. |
getAuthoritativeUsername() | Returns the authoritative username of the user who submitted the request. The authoritative username is determined based on the type of user. If the user logged in with a token obtained from Mobile Identity Connect, and a MIC Enterprise ID is defined, this method returns the value defined in that field from the enterprise identity source. If the user logged in in with a MIC token and no MIC enterprise id is defined, or a social login, the social provider's id is used. If the user logs in with a Kinvey native login, the user.username value is used. |
Kinvey Client libraries provide API to pass Custom Request Properties when communicating with Kinvey services. The requestContext module provides methods to read and manipulate those properties.
Method | Behavior |
---|---|
getCustomRequestProperty(propertyName) | Takes string value propertyName and returns value of key propertyName from the Custom Request Properties object. Returns undefined if key propertyName does not exist. |
setCustomRequestProperty(propertyName, propertyValue) | Creates Custom Request Property propertyName using the provided string propertyName , and assigns propertyValue as its value. If propertyName doesn't exist, it will be created. propertyValue can be any valid JSON value. |
The Custom Request Properties object will be available throughout the entire Kinvey Request pipeline. For example, you can add/modify a Custom Request Property in a preFetch hook, and those changes will be available in a postFetch hook on the same transaction.
//Assume {officeLocation: 'Paris'} was provided as the Custom Request Properties object
function onPreFetch(request, response, modules){
var requestContext = modules.requestContext;
var officeLocation = requestContext.getCustomRequestProperty('officeLocation');
if (officeLocation === 'Paris'){
try {
//Perform some 'preprocessing' logic for requests from Paris
//...
//Set didPreprocess to true in the Custom Request Properties
requestContext.setCustomRequestProperty('didPreprocess', true);
} catch (error) {
//If preprocessing fails due to an error, set didPreprocess to false
requestContext.setCustomRequestProperty('didPreprocess', false);
}
}
//Continue the execution
response.continue();
}
The above code checks the Custom Request Properties for a property, officeLocation
. If the officeLocation
is Paris, then some custom pre-processing is done as part of the pre-fetch hook. If the pre-processing succeeds, we set didPreprocess
to true
in the Custom Request Properties. If an error is encountered during preprocessing, we set didPreprocess
to false
.
We could implement a post-fetch hook that looks for the didPreprocess
flag on the Custom Request Properties object:
//Assume {officeLocation: 'Paris', didPreprocess: true} was provided as the Custom Request Properties object
function onPostFetch(request, response, modules){
var requestContext = modules.requestContext;
var officeLocation = requestContext.getCustomRequestProperty('officeLocation');
var didPreprocess = requestContext.getCustomRequestProperty('didPreprocess');
if (officeLocation === 'Paris'){
if (didPreprocess === true) {
//perform some post-processing specific to pre-process success
} else {
//optionally perform some other post-processing
}
}
//Finish the execution
response.complete(200);
}
For details on passing Custom Request Properties to Kinvey backend services, please see the API reference for the Kinvey Client Library of your choice.
All of the Kinvey client libraries provide API to pass a client-app-specific version string (for implementation details, see the Kinvey Dev Center reference documentation for the library of your choice). The requestContext module provides a clientAppVersion
namespace, which includes API to retrieve details about the version of the client app making the request.
major.minor.patch
, where all values are integers and minor
and patch
are optional. The majorVersion()
, minorVersion()
and patchVersion()
methods defined below are convenience methods designed to work with version strings conforming to this pattern. If major
, minor
or patch
contain any non-digit characters (i.e. 'v1' contains a non-digit character, 'v'), the corresponding convenience method will return NaN
.
The requestContext.clientAppVersion namespace provides the following methods:
Method | Behavior |
---|---|
stringValue() | Returns the client app version value as a String . Returns null if no client app version is passed in. |
majorVersion() | Returns the first dot-separated field of the client app version string (or the entire version string if there are no 'dot' characters) as a Number , or NaN if that field contains any non-digit characters. See A note on version numbering above for details on formatting version strings. |
minorVersion() | Returns the second dot-separated field of the client-app version string as a Number , or NaN if that field contains any non-digit characters. See A note on version numbering above for details on formatting version strings. |
patchVersion() | Returns the third dot-separated field of the client-app version string as a Number , or NaN if that field contains any non-digit characters. See A note on version numbering above for details on formatting version strings. |
Assuming a client app version string of "1.1.5":
function onRequest(request, response, modules){
var context = modules.requestContext;
var majorVersion = context.clientAppVersion.majorVersion(); //majorVersion will be 1
var minorVersion = context.clientAppVersion.minorVersion(); //minorVersion will be 1
var patchVersion = context.clientAppVersion.patchVersion(); //patchVersion will be 5
if (majorVersion < 2) { //will be true
//Perform some version 1 compatible logic
if ((minorVersion >= 1) && (patchVersion === 5)) { //Will be true
//perform some logic for a specific patch release
}
} else if (majorVersion >= 2) { //Will be false
//Perform some version 2+ compatible logic
}
//Finish the execution
response.complete(200);
}
Assuming a client app version string of "1.0.1-beta":
function onRequest(request, response, modules){
var context = modules.backendContext;
var versionString = context.clientAppVersion.stringValue(); //versionString will be "1.0.1-beta"
var majorVersion = context.clientAppVersion.majorVersion(); //majorVersion will be 1
var patchVersion = context.clientAppVersion.patchVersion(); //patchVersion will be NaN
if (majorVersion < 2) { //Will be true
//Perform some version 1 compatible logic
if (patchVersion > 1) { //Will be FALSE as patchVersion is NaN
//Perform some patch-specific logic
}
}
if (versionString.match("beta") !== null){ //Will be true
//Perform some beta-specific logic
}
//Finish the execution
response.complete(200);
}
Promises functionality is provided through the Bluebird library. Promises present an alternative to callbacks for managing asynchronous program flow. They allow asynchronous activities to be 'chained' together rather than 'nested' as callback arguments to asynchronous functions. This can allow code that executes asynchronously to read like synchronous code.
For examples and further reading, see:
For specific information about the Bluebird library, refer to the following:
The Kinvey-provided modules that expose async APIs also have "promisified" methods that will return promises instead of requiring callbacks as parameters. See the examples in the Collection Access and Request modules.
The Kinvey module provides APIs to access Kinvey-specfic data and features.
A Kinvey Entity is a JSON object containing Kinvey-specific metadata for use with AppData collections. Kinvey Entities also contain methods to manipulate Kinvey metadata.
The Kinvey module provides the following Kinvey Entity methods:
Method | Behavior |
---|---|
entity() | Returns a Kinvey Entity with system generated _id . |
entity(id) | Returns a Kinvey Entity with the supplied id as the _id property. |
entity(JsonObject) | Updates JsonObject with Kinvey-specific metadata and functions, and returns a Kinvey Entity as the result. |
isKinveyEntity(someObject) | Returns true if someObject is a Kinvey Entity returned from one of the entity() methods above. |
For example, to create a Kinvey Entity with only Kinvey metadata:
function onPreFetch(request, response, modules){
response.body=modules.kinvey.entity();
response.complete(200);
}
The response would contain an entity containing no additional attributes, except for Kinvey metatada attributes:
{
"_acl": {
"creator": "kid_VT5YYv2KWJ"
},
"_kmd": {
"lmt": "2013-05-08T13:48:36+00:00",
"ect": "2013-05-08T13:48:36+00:00"
},
"_id": "518a57b4d79b4d4308000002"
}
To use your own _id
, you can simply pass that ID as a String
into the method:
function onPreFetch(request, response, modules){
var myID = "000-22-2343";
response.body=modules.kinvey.entity(myID);
response.complete(200);
}
{
"_acl": {
"creator": "kid_VT5YYv2KWJ"
},
"_kmd": {
"lmt": "2013-05-08T13:51:02+00:00",
"ect": "2013-05-08T13:51:02+00:00"
},
"_id": "000-22-2343"
}
You can add Kinvey metatada to your own JavaScript object by passing that object into the function.
function onPreFetch(request, response, modules){
function employee() {
this.firstName = "John";
this.lastName = "Doe";
this.status = "Active";
this.dob = "5/5/1985";
this.doh = "1/12/2012";
}
response.body=modules.kinvey.entity(new employee());
response.complete(200);
}
This example results in the Kinvey metadata being added to your employee object.
{
"firstName": "John",
"lastName": "Doe",
"status": "Active",
"dob": "5/5/1985",
"doh": "1/12/2012",
"_acl": {
"creator": "kid_VT5YYv2KWJ"
},
"_kmd": {
"ect": "2013-05-08T13:57:11+00:00",
"lmt": "2013-05-08T13:57:11+00:00"
},
"_id": "518a59b7d79b4d4308000003"
}
Note that you can add properties directly to a Kinvey Entity and pass it directly into a collectionAccess method that takes an entity as an argument:
function onPreFetch(request, response, modules) {
var entity = modules.kinvey.entity();
entity.name = "Sachin";
modules.collectionAccess.collection("People").save(entity, function(err){
if (err !== null){
//handle error
}else{
response.continue();
}
});
}
entity(JsonObject)
with an object that already contains Kinvey metadata, the original metadata will be maintained. Only lmt
will be updated with the current date and time.Kinvey Entities returned from entity()
are also imbued with an _acl
namespace containing methods for accessing that entity's user and group access privileges:
Method | Behavior |
---|---|
_acl.getCreator() | Return entity creator user ID as a String |
_acl.getReaders() | Return Array of String containing user IDs with read access |
_acl.getWriters() | Return Array of String containing user IDs with write access |
_acl.getReaderGroups() | Return Array of String containing group IDs with read access |
_acl.getWriterGroups() | Return Array of String containing group IDs with write access |
_acl.addReader(userId) | Grant read access to userId , passed as String . Returns the _acl namespace for method chaining. |
_acl.addWriter(userId) | Grant write access to userId , passed as String . Returns the _acl namespace for method chaining. |
_acl.addReaderGroup(groupId) | Grant read access to groupId , passed as String . Returns the _acl namespace for method chaining. |
_acl.addWriterGroup(groupId) | Grant write access to groupId , passed as String . Returns the _acl namespace for method chaining. |
_acl.removeReader(userId) | Revoke read access for userId , passed as String . Returns the _acl namespace for method chaining. (userId will retain read access if part of a group with read access) |
_acl.removeWriter(userId) | Revoke write access for userId , passed as String . Returns the _acl namespace for method chaining. (userId will retain write access if part of a group with write access) |
_acl.removeReaderGroup(groupId) | Revoke group read access for groupId , passed as String . Returns the _acl namespace for method chaining. |
_acl.removeWriterGroup(groupId) | Revoke group write access for groupId , passed as String . Returns the _acl namespace for method chaining. |
_acl.getGloballyReadable() | Return bool indicating whether entity is readable by all users |
_acl.getGloballyWritable() | Return bool indicating whether entity is writable by all users |
_acl.setGloballyReadable(gr) | Set global readability to gr , passed as bool . Returns the _acl namespace for method chaining. |
_acl.setGloballyWritable(gw) | Set global writability to gw , passed as bool . Returns the _acl namespace for method chaining. |
All _acl
methods can be chained to the modules.kinvey.entity()
by chaining the _acl
namespace followed by the desired method. Furthermore the _acl
modifier methods (those that return the _acl
namespace) can be chained to each other. Since the _acl
modifier methods return the _acl
namespace, there's no need to restate the _acl
namespace for the next method in the chain.
For example, the following line will create a Kinvey Entity, add a reader, add a writer, then return all readers. NOTE: Since getReaders() returns an array, no futher _acl
methods can be chained to it.
modules.kinvey.entity(someObject)._acl.addReader(readUserId).addWriter(writeUserId).getReaders();
The example below uses kinvey.entity()._acl
along with the Request Context module to grant write access on the requested entity to the user making the request:
function onPreFetch(request, response, modules) {
var currentUser = modules.requestContext.getAuthenticatedUserId();
var collectionName = request.collectionName;
var entityId = request.entityId;
modules.collectionAccess.collection(collectionName).findOne({"_id":entityId}, {}, function(err, doc){
if (err !== null){
//handle error
} else if (doc) {
var entity = modules.kinvey.entity(doc)._acl.addWriter(currentUser);
//Note we directly pass the Kinvey Entity to the save method.
modules.collectionAccess.collection(collectionName).save(entity, function(err){
response.continue();
});
} else {
// entity not found
response.error("Entity not found");
}
});
}
The Twilio module provides support for integrating with Twilio for outbound SMS support along with communications functions. This library exposes official Node Twilio Library The following methods from v2.5.1 of node-twilio
are supported in Kinvey Business Logic:
Methods | ||
---|---|---|
accountSid | authToken | host |
apiVersion | timeout | accounts |
list | get | post |
create | availablePhoneNumbers | outgoingCallerIds |
incomingPhoneNumbers | messages | sms |
applications | connectApps | authorizedConnectApps |
calls | conferences | queues |
recordings | tokens | transcriptions |
notifications | usage | sip |
addresses | sendSms | sendMms |
sendMessage | listSms | listMessages |
getSms | getMessage | makeCall |
listCalls | getCall |
For example:
function onPreFetch(request, response, modules){
//require the Twilio module and create a REST client
var twilio = modules.twilio('ACCOUNT_SID', 'AUTH_TOKEN');
//Send an SMS text message
twilio.sendMessage({
to:'+16175551242', // Any number Twilio can deliver to
from: '+15085551234', // A number you bought from Twilio and can use for outbound communication
body: 'Sending an SMS note.' // body of the SMS message
}, function(err, responseData) {
if (err) {
return response.error(err);
} else {
modules.logger.info(responseData);
response.body = {sentSMS: true}
return response.complete(200);
}
});
}
For reference on the twilio-node API and each of the methods listed above, see the twilio-node documentation.
The Slack module provides support for integrating with Slack via the Slack Web API. This library exposes the Slack.js library. The following methods from v7.5.6 of slack
are supported in Kinvey Business Logic:
Methods | ||
---|---|---|
api | auth | host |
channels | chat | describe |
dnd | emoji | files |
groups | im | mpim |
oauth | pins | reactions |
search | stars | team |
usergroups | users |
For example, to send a message to a channel or user:
function onPreFetch(request, response, modules){
//require the Slack module
var slack = modules.slack;
//Send a chat message
slack.chat.postMessage({
token: 'someaccesstoken',
channel: '@someuser',
message: 'Can you attend a meeting at 9:00 AM?'
}, function(err, data) {
if (err) {
return response.error(err);
}
response.body = data;
response.complete();
});
}
For reference on the slack API and each of the methods listed above, see the slack.js documentation.
The HipChat module provides support for integrating with HipChat. This library exposes the hipchat-client library. The hipchat client exposes access to rooms
and users
APIs.
The following methods from the rooms
object of v1.0.5 of hipchat-client
are supported in Kinvey Business Logic:
Methods | ||
---|---|---|
create | delete | history |
list | message | topic |
show | getByName | getByXmppJid |
The following methods from the users
object of v1.0.5 of hipchat-client
are supported in Kinvey Business Logic:
Methods | ||
---|---|---|
create | delete | list |
show | undelete | update |
getByMentionName | getByName | getByEmail |
getByStatus |
For example, to send a message to a channel:
function onPreFetch(request, response, modules){
//require the HipChat module
var HipChatClient = modules.hipchat;
var hipchat = new HipChatClient('auth_token');
hipchat.api.rooms.message({
room_id: 'Frontend',
from: 'HipChat Client',
message: 'Hello world!'
}, function (err, res) {
if (err) {
return response.error(err); }
}
response.body = res;
response.complete();
});
}
For reference on the slack API and each of the methods listed above, see the hipchat-client documentation.
The Facebook Messenger module provides support for integrating with the Facebook Messenger Send API. This library exposes the facebook-send-api library. The following methods from v1.0.3 of facebook-send-api
are supported in Kinvey Business Logic:
Methods | ||
---|---|---|
sendToFB | sendMessageToFB | sendGenericMessage |
sendButtonMessage | sendToFB | sendMessageToFB |
sendGenericMessage | sendButtonMessage | sendTextMessage |
sendQuickReplies | sendSenderAction | sendTypingIndicators |
sendReadReceipt |
For example, to send a message to a channel or user:
function onPreFetch(request, response, modules){
//require the Facebook Messenger module
var token = 'xyz';
var fb = modules.facebookMessenger;
var FBPlatform = new fb(token);
FBPlatform.sendTextMessage('someSenderId', 'hello');
response.complete();
}
For reference on the slack API and each of the methods listed above, see the Facebook Send API documentation.
The Watson module provides support for integrating with the IBM Watson APIs. This library exposes the watson-developer-cloud library. The following methods from v1.12.2 of watson-developer-cloud
are supported in Kinvey Business Logic:
Methods | ||
---|---|---|
visual_recognition | speech_to_text | text_to_speech |
concept_insights | tradeoff_analytics | personality_insights |
natural_language_classifier | authorization | language_translator |
tone_analyzer | dialog | retrieve_and_rank |
document_conversion | search | alchemy_language |
alchemy_vision | alchemy_data_news | conversation |
relationship_extraction |
For example, to use the conversation service to determine the intent of a message:
function onPreFetch(request, response, modules){
//require the watson module
var watson = modules.watson;
var conversation = watson.conversation({
username: '<username>',
password: '<password>',
version: 'v1',
version_date: '2016-07-01'
});
conversation.message({
input: 'What\'s the weather?',
workspace_id: '<workspace id>'
}, function(err, res) {
if (err) {
response.error(err);
} else {
response.body = res;
response.complete();
}
});
}
For reference on the slack API and each of the methods listed above, see the watson-developer-cloud documentation.