FlexServices is a framework for developing low code, lightweight microservices that are used for data integrations, functional business logic, and integration with custom authentication providers. FlexServices utilizes the Flex SDK.
Contents:
Method | Description |
---|---|
flex.data.serviceObject(serviceObjectName) | Creates a service object |
flex.data.serviceObject(serviceObjectName)
Creates a service object that represents a data object or record on the remote system that you connect to using FlexData. Examples include an SQL table or view, a Sharepoint list, or an SAP RFC.
Name | Type | Default Value | Description |
---|---|---|---|
serviceObjectName | String | - | Name for the service object to be created |
// To register the "widgets" ServiceObject:
const widgets = flex.data.serviceObject('widgets');
Each ServiceObject exposes data events that are invoked by Kinvey collections. The data event takes a single data handler function to be executed.
FlexData Event | Description | Endpoint | HTTP Verb |
---|---|---|---|
onInsert(callback) | Creates a service object entity | /:serviceObject/ | POST |
onUpdate(callback) | Updates a service object entity | /:serviceObject/:id | PUT |
onDeleteById(callback) | Deletes a single service object entity by ID | /:serviceObject/:id | DELETE |
onDeleteByQuery(callback) | Deletes all service object entities that match a query | /:serviceObject/?{query} | DELETE |
onDeleteAll(callback) | Deletes all entities of a service object | /:serviceObject/ | DELETE |
onGetAll(callback) | Gets all entities in a service object | /:serviceObject/ | GET |
onGetById(callback) | Gets a single service object entity by ID | /:serviceObject/:id | GET |
onGetByQuery(callback) | Gets all service object entities that match a query | /:serviceObject/?{query} | GET |
onGetCount(callback) | Gets the count of the entities in a service object | /:serviceObject/_count | GET |
onGetCountByQuery(callback) | Gets the count of the entities in a query result | /:serviceObject/_count/?{query} | GET |
For response information, see the REST data store guide.
widgets.onGetAll(callbackFunction);
A function to be executed when a particular FlexData event takes place.
callback(context, complete, modules);
Argument | Type | Description |
---|---|---|
context | Object | Represents the current context of the FlexData request made to Kinvey |
complete | Object | Completion handler for completing the data request |
modules | Object | Contains libraries for accessing Kinvey functionality |
context
ObjectRepresents the current context of the FlexData request made to Kinvey.
Property | Description |
---|---|
method | The HTTP method (GET, POST, PUT, DELETE) |
headers | The HTTP request headers |
entityId | The Entity ID, if specified |
serviceObjectName | The name of the Service Object |
body | The HTTP body |
query | An object containing all query string parameters |
complete
ObjectCompletion handler for completing the data request. It follows a builder pattern for creating the handler's response.
complete()[.setBody(<entity>).<status>.done()|next()]
Example:
complete(myEntity).ok().next();
complete()
FunctionInitiates the completion process.
setBody()
FunctionAn optional context-altering method that sets the response body. It takes an entity, an array of entities, an error description, or an Error
object. The entity must be a JSON object or a JSON array.
Examples:
// Sets the response to include an entity.
complete().setBody({'foo':'bar'});
// Sets the response to include an array of entities
complete().setBody([{'foo':'bar'}, {'abc':'123'}]);
// Sets the response to an empty object
complete();
// Sets the response to an empty array
complete().setBody([]);
// Sets the response to an error string to be used with error status functions
complete().setBody('Record 123 was not found');
// Sets the response to an Error object to be used with error status functions
complete().setBody(new Error('Record 123 was not found');
Sets the status code for a Flex Data operation. Automatically sets the response body to a Kinvey-formatted error and uses the value passed into the status function or the setData()
function as the debug property, if it is present. Optional.
Function | Status Code | Description |
---|---|---|
ok | 200 | Normal success response |
created | 201 | New record has been created |
accepted | 202 | Request has been submitted for processing, but will be processed asynchronously |
notFound | 404 | Entity or entities could not be found |
badRequest | 400 | Invalid request |
unauthorized | 401 | Request is not authorized for the given user context |
forbidden | 403 | Request is forbidden for some reason |
notAllowed | 405 | Request or request method is not allowed |
notImplemented | 501 | Handler is not implemented |
runtimeError | 550 | Use for custom runtime errors |
Examples:
// Return that the record has been created
complete().setBody(myRecord).created();
// Entity wasn't found
complete().setBody("The given entity wasn't found").notFound();
End the processing of the handler request after setting the response status. Optional.
Function | Description |
---|---|
next() | Ends processing and continues the Kinvey request pipeline |
done() | Returns the response set in the completion handler and ends request processing without executing any further functions. |
Examples:
// Continue the request chain
complete().setBody(myEntity).ok().next();
// End the request chain with no further processing
complete().ok().done();
modules
ObjectAn object containing instances of all available modules.
Usage:
modules.[moduleName].[moduleMethodName()];
Examples:
// data handler
function onGetById(context, complete, modules) {
const appKey = modules.backendContext.getAppKey();
// ...
}
FlexData provides routes for CRUD and count operations. In your FlexService, you need to implement an event handler for each endpoint that you plan to use. See FlexData: Data Events for details.
Endpoint | HTTP Verb | Description | FlexData Event |
---|---|---|---|
/:serviceObject/ | POST | Creates a service object entity | onInsert |
/:serviceObject/:id | PUT | Updates a service object entity | onUpdate |
/:serviceObject/:id | DELETE | Deletes a single service object entity by ID | onDeleteById |
/:serviceObject/?{query} | DELETE | Deletes all service object entities that match a query | onDeleteByQuery |
/:serviceObject/ | DELETE | Deletes all entities of a service object | onDeleteAll |
/:serviceObject/ | GET | Gets all entities in a service object | onGetAll |
/:serviceObject/:id | GET | Gets a single service object entity by ID | onGetById |
/:serviceObject/?{query} | GET | Gets all service object entities that match a query | onGetByQuery |
/:serviceObject/_count | GET | Gets the count of the entities in a service object | onGetCount |
/:serviceObject/_count/?{query} | GET | Gets the count of the entities in a query result | onGetCountByQuery |
The FlexFunctions framework is used to execute RPC functions invoked by hooks
or endpoints
. You can access it through the SDK's functions
property.
const functions = flex.functions;
Method | Description |
---|---|
flex.functions.register(eventHandlerName, callback) | Registers a Flex function handler |
flex.functions.register(eventHandlerName, callback)
Registers a Flex function handler. This includes naming the handler and defining its logic.
Name | Type | Default Value | Description |
---|---|---|---|
eventHandlerName | String | - | Name for the Flex function handler. |
callback | Function | - | Function that defines the behavior of the handler |
const sdk = require('kinvey-flex-sdk');
const request = require('request'); // assumes that the request module was added to package.json
sdk.service(function(err, flex) {
const flexFunctions = flex.functions; // gets the FlexFunctions object from the service
function getRedLineSchedule(context, complete, modules) {
request.get('http://developer.mbta.com/Data/Red.json', (err, response, body) => {
// if error, return an error
if (err) {
return complete().setBody('Could not complete request').runtimeError().done();
}
//otherwise, return the results
return complete().setBody(body).ok().done();
});
}
// set the handler
flexFunctions.register('getRedLineData', getRedLineSchedule);
};
A function to be executed when a particular Flex function is called.
callback(context, complete, modules);
Argument | Type | Description |
---|---|---|
context | Object | Represents the current context of the request to Kinvey |
complete | Object | Completion handler for completing the function |
modules | Object | Contains libraries for accessing Kinvey functionality |
context
ObjectRepresents the current context of the request to Kinvey. Some of the object properties are set only at the appropriate stages of the Kinvey request pipeline.
Property | Description |
---|---|
method | The HTTP method (GET, POST, PUT, DELETE) |
headers | The HTTP request headers |
entityId | When the Flex function is used as a collection hook, this is the Entity ID included in the request, if specified. |
body | When the Flex function is used as a collection hook, this is a data entity or entities, or error message associated with the request. When the Flex function is used as a custom endpoint, this is the request body. |
query | An object containing all query string parameters |
hookType | The type of event hook: customEndpoint (default) for an endpoint hook, pre for a Before collection hook, post for an After collection hook |
userId | ID of the user making the request |
username | Username of the user making the request |
objectName | For Before and After collection hooks, this is the name of the collection. For custom endpoints, its value is undefined . |
complete
ObjectCompletion handler for completing the function. It follows a builder pattern for creating the handler's response.
complete().[setBody(<entity>).setQuery(<query>).<status>.done()|next()]
Example:
complete(myEntity).ok().next();
complete()
FunctionInitiates the completion process.
setBody()
FunctionAn optional context-altering method that sets the data entity or entities to be passed to the next step of the pipeline or as the final result. It takes an entity, an array of entities, an error description, or an Error
object. The entity must be a JSON object or a JSON array.
Examples:
// Sets the context to include an entity
complete().setBody({'foo':'bar'});
// Sets the response to include an array of entities
complete().setBody([{'foo':'bar'}, {'abc':'123'}]);
// Sets the response to an empty object
complete();
// Sets the response to an empty array
complete().setBody([]);
// Sets the response to an error string to be used with error status functions
complete().setBody('Record 123 was not found');
// Sets the response to an Error object to be used with error status functions
complete().setBody(new Error('Record 123 was not found');
setQuery()
FunctionReplaces the query object with an altered query object. This is only useful in Before collection hook functions. Optional.
Examples:
// Sets the context to include an entity and an altered query
complete().setBody({'foo':'bar'}).setQuery({query: {foo:'bar'}});
Sets the status code for a FlexFunctions operation. Automatically sets the response body to a Kinvey-formatted error and uses the value passed into the status function or the setBody()
function as the debug property, if it is present. Optional.
Function | Status Code | Description |
---|---|---|
ok | 200 | Normal success response |
created | 201 | New record has been created |
accepted | 202 | Request has been submitted for processing, but will be processed asynchronously |
notFound | 404 | Entity or entities could not be found |
badRequest | 400 | Invalid request |
unauthorized | 401 | Request is not authorized for the given user context |
forbidden | 403 | Request is forbidden for some reason |
notAllowed | 405 | Request or request method is not allowed |
notImplemented | 501 | Handler is not implemented |
runtimeError | 550 | Use for custom runtime errors |
Examples:
// Return that the record has been created
complete().setBody(myRecord).created();
// Entity wasn't found
complete().setBody("The given entity wasn't found").notFound();
End the processing of the handler request after setting the response status. Optional.
Function | Description |
---|---|
next() | Ends processing and continues the Kinvey request pipeline |
done() | Returns the response set in the completion handler and ends request processing without executing any further functions. |
Examples:
// Continue the request chain
complete().setBody(myEntity).ok().next();
// End the request chain with no further processing
complete().ok().done();
modules
ObjectAn object containing instances of all available modules.
Usage:
modules.[moduleName].[moduleMethodName()];
Examples:
flex.functions.register('processPayment', function processPaymentCallback(context, complete, modules) {
const appKey = modules.backendContext.getAppKey();
});
Endpoint | HTTP Verb | Description |
---|---|---|
/_flexFunctions/:handlerName | POST | Executes the handler function |
Method | Description |
---|---|
flex.auth.register(authHandlerName, callback) | Registers a FlexAuth handler |
flex.auth.register(authHandlerName, callback)
Registers a FlexAuth handler. This includes naming the handler and defining its logic.
Name | Type | Default Value | Description |
---|---|---|---|
authHandlerName | String | - | Name for the FlexAuth handler. |
callback | Function | - | Function that defines the behavior of the handler |
const sdk = require('kinvey-flex-sdk');
const request = require('request'); // assume that the request module was added to package.json
sdk.service(function(err, flex) {
const flexAuth = flex.auth; // get the FlexAuth object from the service
function authenticate(context, complete, modules) {
// authenticate the user here
if (err) {
return complete().accessDenied(err).next();
}
return complete().setToken(token).ok().next();
}
// set the handler
flexAuth.register('myAuth', authenticate);
};
A function to be executed when a particular FlexAuth handler is called.
callback(context, complete, modules);
Argument | Type | Description |
---|---|---|
context | Object | Represents the current context of the request to Kinvey |
complete | Object | Completion handler for completing the function |
modules | Object | Contains libraries for accessing Kinvey functionality |
context
ObjectRepresents the current context of the request to Kinvey. Some of the object properties are set only at the appropriate stages of the Kinvey request pipeline.
Property | Description |
---|---|
method | The HTTP method (GET, POST, PUT, DELETE) |
headers | The HTTP request headers |
body | The request body |
body.username | Username of the user making the request |
body.password | Password of the user making the request |
body.options | Optional request parameters |
complete
ObjectCompletion handler for completing the handler. It follows a builder pattern for creating the handler's response.
complete().[setToken(<token>).addAttribute(<key>, <value>).removeAttribute(<key>).<status>.done()|next()]
Example:
complete().setToken(myToken).addAttribute('userEmail', myEmail).ok().next()
complete()
FunctionInitiates the completion process.
setToken()
FunctionSets the authentication token to be used for this user. Must be a JSON object or a Base64 encoded string. For errors, you can either pass a string as the error message or a JavaScript Error
object. Optional.
Examples:
// Set an access token as a JSON object
complete().setToken({'myAuthToken': 'ffds9afdsafdsaf89ds0fds90f8ds-='});
// Set the response to an error string to be used with error status functions
complete().setToken('Record 123 was not found');
// Sets the response to an Error object to be used with error status functions
complete().setToken(new Error('Record 123 was not found');
addAttribute()
FunctionAdds custom attributes to your FlexAuth response. Optional.
Examples:
complete().setToken({'myAuthToken': 'ffds9afdsafdsaf89ds0fds90f8ds-='}).addAttribute('email', 'test123@test.com');
removeAttribute()
FunctionRemoves a previously added custom attribute from your FlexAuth response. Optional.
Examples:
complete().setToken({'myAuthToken': 'ffds9afdsafdsaf89ds0fds90f8ds-='}).removeAttribute('email');
Sets the status code for a FlexAuth operation. Also sets the body to an OAuth-formatted error and uses the value passed into the status function as the debug property, if it is present.
Function | Status Code | Description |
---|---|---|
ok | 200 | Normal success response |
serverError | 401 | For arbitrary server errors. |
accessDenied | 401 | Thee authenticating user has been denied access |
temporarilyUnavailable | 401 | The underlying authentication source is temporarily unavailable |
notImplemented | 401 | Handler is not implemented |
Examples:
// Return that the user has been authenticated
complete().setToken(myToken).ok();
End the processing of the handler request after setting the response status. Optional.
Function | Description |
---|---|
next() | Ends processing and continues the Kinvey request pipeline |
done() | Returns the response set in the completion handler and ends request processing without executing any further functions. |
// Continue up the request chain
complete().setToken(myToken).ok().next();
// End the request chain with no further processing
complete().ok().done();
modules
ObjectAn object containing instances of all available modules.
Usage:
modules.[moduleName].[moduleMethodName()];
Examples:
flex.auth.register('myAuth', function myAuthCallback(context, complete, modules) {
const appKey = modules.backendContext.getAppKey();
});
Endpoint | HTTP Verb | Description |
---|---|---|
/_auth/:handlerName | POST | Executes the handler function |
Endpoint | HTTP Verb | Description |
---|---|---|
/_command/discover | POST | Returns a JSON object that lists all registered Flex objects on your Kinvey account. This includes FlexData service objects, FlexFunctions, and FlexAuth endpoints. |
Field name | Type | Description |
---|---|---|
dataLink | object | Represents FlexData |
dataLink.serviceObjects | array | Lists all registered FlexData service objects |
businessLogic | object | Represents FlexFunctions |
businessLogic.handlers | array | Lists all registered FlexFunctions handler functions |
auth | object | Represents FlexAuth |
auth.handlers | array | Lists all registered FlexAuth handler functions |
{
"dataLink": {
"serviceObjects": [
"musicCatalog"
]
},
"businessLogic": {
"handlers": [
"checkIfUpsert",
"updateMultipleItems",
"bulkUpload",
"deleteUsers",
"getDataWithQuery",
"printFlexContext",
"sendEmail",
"deleteOldItems"
]
},
"auth": {
"handlers": ["MyAuth"]
}
}
The Flex SDK comes with the following modules pre-installed:
Module name | Description |
---|---|
backendContext | Methods to access information about the current backend context |
dataStore | Fetch, query, and write to Kinvey collections |
Send email notifications | |
groupStore | Fetch, query, and write Kinvey groups |
Kinvey Entity | Utilities for working with Kinvey entities. |
kinveyDate | Utilities to convert dates to/from the Kinvey date format. |
push | Methods for sending push notifications to a user's device. |
Query | Create queries to be used by the dataStore module. |
requestContext | Methods to access information about the current request context. |
tempObjectStore | Key-value store for persisting temporary data between a pre- and a post-hook. |
userStore | Fetches, queries, creates, updates, deletes, suspends, and restores Kinvey users. |
roleStore | Fetches, queries, and writes Kinvey user roles. Lists role members. |
endpointRunner | Calls custom endpoints with reusable user context and authentication. |
backendContext
ModuleUsed to return data and perform functions against the current backend context.
Method | Behavior |
---|---|
getAppKey() | Returns the current backend's App Key |
getAppSecret() | Returns the current backend's App Secret |
getMasterSecret() | Returns the current backend's Master Secret |
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.
const request = require('request');
function myHandler(context, complete, modules){
const backendContext = modules.backendContext;
const appKey = backendContext.getAppKey();
const masterSecret = backendContext.getMasterSecret();
const uri = 'https://' + context.headers.host + '/appdata/' + appKey + '/myCollection/';
const authString = 'Basic ' + Buffer.from(appKey + ':' + masterSecret).toString('base64');
const requestOptions = {
uri:uri,
headers: {
'Authorization':authString
}
};
var auth = request.get(requestOptions, (error, res, body) => {
if (error){
complete.setBody(error).runtimeError.done();
} else {
complete.setBody(body).ok().next();
}
});
}
dataStore
ModuleUse the dataStore module to interact with Kinvey Data at the collection level. The dataStore module can be used to interact with both the Kinvey DataStore or with external data such as RAPID connectors or Flex Data Services.
To initialize the DataStore:
const store = modules.dataStore();
The dataStore
method also takes an optional options
argument containing store options for the current store. The options are:
Option | Description |
---|---|
useBl | For security reasons, applies only when useUserContext is false . If set to true, executes BL hooks associated with the dataStore request. If false, BL hooks do not execute. Defaults to false. |
useUserContext | Uses user context credentials to access the datastore if set to true . If false , it executes in the context of mastersecret . Defaults to false. |
useMasterSecret | DEPRECATED: use useUserContext instead Uses the mastersecret credentials to access the datastore if set to true . If set to false, will use the current user credentials. |
skipBl | DEPRECATED: use useBl instead If set to true, skips BL processing when accessing the datastore. If false or not included, it will default to executing any BL associated with the store. |
For example:
const options = {
useBl: true,
useUserContext: false
}
const store = modules.dataStore(options);
The dataStore
object contains a single method, collection
for specifying the collection to query.
const myCollection = modules.dataStore().collection('myCollection');
The collection
object contains methods for accessing data within the collection. All methods take a callback(err, results)
function and return a promise if a callback is not passed.
Method | Description |
---|---|
find(query, callback) | Finds the records contained in the query . The query is a Query object created with modules.Query . If no Query object is supplied, the find method will return all entities in the collection. |
findById(entityId, callback) | Finds a single entity by its _id . |
save(entity, callback) | Saves the provided entity to the dataStore, either as an insert or update. (NOTE: if an _id is provided and that _id already exists, the save will update the existing entity by replacing it with the entity passed into this function). |
remove(query, callback) | Removes the records contained in the query . The query is a Query object created with modules.Query . |
removeById(entityId, callback) | Removes a single entity by its _id . |
count(query, callback) | Gets a count of all records that would be returned by the query . The query is a Query object created with modules.Query . If no Query object is supplied, the count method will return a count of the number of entities in the collection. |
mastersecret
credentials and must not use business logic. If either useUserContext
or useBl
are set to true, these types of requests will fail with an error in the callback.
For example:
const store = dataStore({ useUserContext: true });
const products = store.collection('products');
products.findById(1234, (err, result) => {
if (err) {
return complete(err).runtimeError().done();
}
result.status = 'Approved';
products.save(result, (err, savedResult) => {
if (err) {
return complete().setBody(err).runtimeError().done();
}
complete().setBody(savedResult).ok().next();
});
});
});
dataStore
, locally in particular, special headers need to be added to your local tests. These headers will be added automatically by Kinvey in production use. For information on the required headers, see the section on testing locally
email
ModuleUse the email module to send email to any valid email address.
The following method takes a callback function and returns a promise if a callback is not passed:
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. The cc and bcc arguments for adding CC and BCC users are optional. |
For example, to send a text email:
const 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) {
complete().ok().next();
});
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 the from address). For example:
const 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);
Email calls are asynchronous in nature. They can be invoked without a callback, but are not guaranteed to complete before continuing to the next statement. However, once invoked they will complete the sending of the email, even if the function ends via a complete handler.
groupStore
ModuleUse the groupStore module to interact with Kinvey Groups. The groupStore module can be used to create, update, retrieve, and remove Kinvey User groups.
To initialize the groupStore:
const store = modules.groupStore();
The groupStore
method also takes an optional options
argument containing store options for the current store. The options are:
Option | Description |
---|---|
useUserContext | Uses user context credentials to access the groupStore if set to true . If false, will execute in the context of mastersecret . Defaults to false. |
For example:
const options = {
useUserContext: true
}
const store = modules.groupStore(options);
The groupStore
object contains methods for accessing Kinvey groups. All methods take a callback
function and return a promise if a callback is not passed.
err
and results
arguments.
Method | Description | |
---|---|---|
create(group, callback) | Creates a new group . The group object should be formatted according to the Group API Specification | |
update(ugroupser, callback) | Updates the provided group . Note that the group entity supplied must contain an _id . The group object should be formatted according to the Group API Specification | |
remove(groupId, callback) | Removes a single group by its _id . Note this method deletes the user from the userStore and is non-recoverable. | |
findById(groupId, callback) | Finds a user based on its ID. |
For example:
const store = groupStore({ useUserContext: true });
store.findById(1234, (err, result) => {
if (err) {
return complete().setBody(err).runtimeError().done();
}
store.update(result, (err, savedResult) => {
if (err) {
return complete(err).runtimeError().done();
}
complete().setBody(savedResult).ok().next();
});
});
groupStore
, locally in particular, special headers need to be added to your local tests. These headers will be added automatically by Kinvey in production use. For information on the required headers, see the section on testing locally.
kinveyEntity
ModuleA 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 kinveyEntity
module provides the following 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 someHandler(context, complete, modules) {
complete().setBody(modules.kinveyEntity.entity()).ok().done();
}
The response would contain an entity containing no additional attributes, except for Kinvey metadata 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 handler(context, complete, modules){
var myID = '000-22-2343';
complete().setBody(modules.kinvey.entity(myID)).ok().done();
}
{
"_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 metadata to your own JavaScript object by passing that object into the function.
function handler(context, complete, modules){
function employee() {
this.firstName = 'John';
this.lastName = 'Doe';
this.status = 'Active';
this.dob = '5/5/1985';
this.doh = '1/12/2012';
}
complete().setBody(modules.kinvey.entity(new employee())).ok().done();
}
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": {
"etc": "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 dataStore
method that takes an entity as an argument:
function handler(context, complete, modules) {
const entity = modules.kinveyEntity.entity();
entity.name = 'Sachin';
modules.dataStore().collection('People').save(entity, (err, result) =>
if (err) {
// handle error
} else {
complete().setBody(result).ok().next();
}
});
}
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 by entity()
include an _acl
namespace containing methods for accessing that entity's user, role, 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.getReaderRoles() | Return Array of String containing role IDs with read access |
_acl.getUpdateRoles() | Return Array of String containing role IDs with update access |
_acl.getDeleteRoles() | Return Array of String containing role IDs with delete 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.addReaderRole(roleId) | Grant read access to roleId , passed as String . Returns the _acl namespace for method chaining. |
_acl.addUpdateRole(roleId) | Grant update access to roleId , passed as String . Returns the _acl namespace for method chaining. |
_acl.addDeleteRole(roleId) | Grant delete access to roleId , passed as String . Returns the _acl namespace for method chaining. |
_acl.removeReader(userId) | Revoke read access from 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 from 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 read access from groupId , passed as String . Returns the _acl namespace for method chaining. |
_acl.removeWriterGroup(groupId) | Revoke write access from groupId , passed as String . Returns the _acl namespace for method chaining. |
_acl.removeReaderRole(roleId) | Revoke read access from roleId , passed as String . Returns the _acl namespace for method chaining. |
_acl.removeUpdateRole(roleId) | Revoke update access from roleId , passed as String . Returns the _acl namespace for method chaining. |
_acl.removeDeleteRole(roleId) | Revoke delete access from roleId , 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.kinveyEntity.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.
getReaders()
returns an array, no futher _acl
methods can be chained to it.
modules.kinveyEntity.entity(someObject)._acl.addReader(readUserId).addWriter(writeUserId).getReaders();
The example below uses kinveyEntity.entity()._acl
along with the Request Context module to grant write access on the requested entity to the user making the request:
function handler(context, complete, modules) {
const currentUser = modules.requestContext.getAuthenticatedUserId();
const entityId = context.entityId;
const collection = modules.dataStore().collection(collectionName);
collection.findById({entityId, (err, doc) => {
if (err){
//handle error
} else if (doc) {
const entity = modules.kinveyEntity.entity(doc)._acl.addWriter(currentUser);
//Note we directly pass the Kinvey Entity to the save method.
collection.save(entity, (err, result) => {
complete().setBody(result).ok().next();
});
} else {
// entity not found
complete().setBody(new Error 'Entity not found').runtimeError().done();
}
}
});
}
kinveyDate
ModuleA utility for converting dates.
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 a Kinvey Date string:
myDate = new Date();
kinveyDate = modules.kinveyDate.toKinveyDateString(myDate);
To convert a Kinvey Date string to a JavaScript date object:
myDate = modules.kinveyDate.fromKinveyDateString(kinveyDate, 'date');
// note: this could also be accomplished via modules.kinveyDate.fromKinveyDateString(kinveyDate);
To convert a Kinvey Date string to a moment:
myMoment = modules.kinveyDate.fromKinveyDateString(kinveyDate, 'moment');
To convert a Kinvey Date into a standard ISO-8601 date string
myDateString = modules.kinveyDate.fromKinveyDateString(kinveyDate, 'string');
push
ModuleUse the push module to send a push notification to a device registered with your app.
The module includes the following sending methods. All methods take a callback function and return a promise if a callback is not passed:
Method | Action |
---|---|
broadcastMessage(message, calback) | 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 (context.body.sendMessageToAll){
push.broadcastMessage(context.body.message, (err, result) => {
complete().ok().next();
});
}
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 dataStore
module to get a list of users.
For example:
const push = modules.push;
const userStore = modules.userStore();
const query = new modules.Query();
query.equalTo('firstName', request.body.firstName);
userStore.find(query, (err, userColl) => {
if (err) {
complete().setBody(err).runtimeError().done();
} else {
userColl.forEach((user) => {
push.sendMessage(user, 'People who are named ${user.firstName} are awesome!', (err, result) => {
//complete here
});
});
}
});
The methods sendPayload
and broadcastPayload
allow for more robust push
messages. For iOS, the payload consists of two arguments, iOSAps
and
iOSExtras
. The former 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 |
The iOSExtras
argument 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:
const iOSAps = { alert: 'You have a new message', badge: 2, sound: 'notification.wav' }
const iOSExtras = {from: 'Kinvey', subject: 'Welcome to Flex Services!'}
const androidPayload = {message: 'You have a new Message', from: 'Kinvey', subject: 'Welcome to BL' }
const push = modules.push;
push.broadcastPayload(iOSAps, iOSExtras, androidPayload, callback);
Push calls are asynchronous in nature. They can be invoked without a callback, but are not guaranteed to complete before continuing to the next statement. However, once invoked they will complete the sending of the push messages, even if the handler function is terminated via a completion handler.
query
ModuleThe Query
module allows you to build queries for use in the dataStore
module.
const query = new modules.Query();
All operator methods as exposed by the Query
module follow the same pattern: the first argument must be the field under condition, while the other arguments specify the exact condition on that field. All operators return the query itself, so it is easy to concatenate multiple conditions on one line.
For example, to select all models with a rate between 25 and 50:
const query = new modules.Query();
query.greaterThanOrEqualTo('rate', 25).lessThanOrEqualTo('rate', 50);
equalTo
matches if the field is = the supplied value.greaterThan
matches if the field is > the supplied value.greaterThanOrEqualTo
matches if the field is >= the supplied value.lessThan
matches if the field is < the supplied value.lessThanOrEqualTo
matches if the field is <= the supplied value.notEqualTo
matches if the field is != the supplied value.exists
matches if the field exists.mod
matches if the field modulo the supplied divisor (second argument) has the supplied remainder (third argument).matches
matches if the field matches the supplied regular expression.^
), 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.
contains
matches if any of the supplied values is an element in the field.containsAll
matches if the supplied values are all elements in the field.notContainedIn
matches if the supplied value is not an element in the field.size
matches if the number of elements in the field equals the supplied value.Query modifiers control how query results are presented. A distinction is made between limit, skip, and sort modifiers.
Limit and skip modifiers allow for paging of results. Set the limit to the number of results you want to show per page. The skip modifier indicates how many results are skipped from the beginning.
// Show results 20–40
const query = new modules.Query();
query.limit = 20;
query.skip = 20;
Query results are sorted either in ascending or descending order. It is possible to add multiple fields to sort on.
// Sort on last name (ascending), then on age (descending).
const query = new modules.Query();
query.ascending('last_name');
query.descending('age');
B
comes before a
, and 10
before 2
.
By default, all fields in an entity will be retrieved. You can, however, specify specific fields to retrieve. This can be useful to save bandwidth.
const query = new modules.Query();
query.fields = [ 'last_name', 'age' ];
Saving entities after retrieving them using Field Selection will result in the loss of all fields not selected. Further, these partial entities will not be available for use with Caching & Offline Saving.
You can combine filters with modifiers within a single query.
// Returns the first five users with last_name “Doe”, sorted by first_name.
const query = new modules.Query();
query.limit = 5;
query.equalTo('last_name', 'Doe');
query.ascending('first_name');
It is very easy to join multiple queries into one. In order of precedence, the three joining operators are listed below in order of precendence.
and
joins two or more queries using a logical AND operation.nor
joins two or more queries using a logical NOR operation.or
joins two or more queries using a logical OR operation.The example below demonstrates how to join two separate queries.
const query = new modules.Query();
query.equalTo('last_name', 'Doe');
const secondQuery = new modules.Query();
secondQuery.equalTo('last_name', 'Roe')
// Selects all users with last_name “Doe” or “Roe”.
query.or(secondQuery);
Alternatively, the snippet above can be shortened using the join operator inline.
// Selects all users with last_name “Doe” or “Roe”.
const query = new modules.Query();
query.equalTo('last_name', 'Doe').or().equalTo('last_name', 'Roe');
You can build arbitrary complex queries using any join operators. The rule of thumb is to take the precendence order into account when building queries to make sure the correct results are returned.
_geoloc
. The value of this field should be an array holding two elements: longitude and latitude (in that order). Kinvey indexes that attribute for optimal location querying.
The following Location Operators are supported by modules.Query
:
near
matches if the field is within the supplied radius (in miles) of the supplied coordinate.withinBox
matches if the field is within the box specified by the two supplied coordinates.withinPolygon
matches if the field is within the polygon specified by the supplied list of coordinates.For example, a query to retrieve all restaurants close (10 mile radius) to a users’ current location could look as follows:
// Get users current position
function handler(context, complete, modules) {
const coord = [context.body.longitude, context.body.latitude];
// Query for restaurants close by.
var query = new modules.Query();
query.near('_geoloc', coord, 10);
var dataStore = modules.dataStore().collection('restaurants');
var stream = dataStore.find(query, (err, result) => {
if (err) {
return complete().setBody(err).runtimeError().done():
}
complete().setBody(result).ok().next();
});
});
requestContext
ModuleUsed 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. |
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. |
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. |
setCustomReqeustProperty(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 handlerForPrefetch(context, complete, modules){
const requestContext = modules.requestContext;
const 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
complete().ok().next();
}
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 handlerForPostFetch(context, complete, modules){
const requestContext = modules.requestContext;
const officeLocation = requestContext.getCustomRequestProperty('officeLocation');
const 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
complete().ok().next();
}
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 handler(context, complete, modules){
const requestContext = modules.requestContext;
const majorVersion = requestContext.clientAppVersion.majorVersion(); //majorVersion will be 1
const minorVersion = requestContext.clientAppVersion.minorVersion(); //minorVersion will be 1
const patchVersion = requestContext.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
complete().ok().done();
}
Assuming a client app version string of "1.0.1-beta":
function handler(context, response, modules){
const requestContext = modules.requestContext;
const versionString = requestContext.clientAppVersion.stringValue(); //versionString will be "1.0.1-beta"
const majorVersion = requestContext.clientAppVersion.majorVersion(); //majorVersion will be 1
const patchVersion = requestContext.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
complete().ok().done();
}
tempObjectStore
ModuleA key-value store for persisting temporary data between a pre- and post-hook. The tempObjectStore
object 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 FlexData service and/or in the post-hook. The module 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 a handler:
function handler1(context, complete, modules) {
var tempObjectStore = modules.tempObjectStore;
tempObjectStore.set('token', context.body.token);
complete().ok().next();
}
Then, to retrieve it:
function handler2(context, response, modules) {
var tempObjectStore = modules.tempObjectStore;
var token = tempObjectStore.get('token');
complete().setBody({ message: `Object for token ${token} was saved successfully.` }).ok().done();
}
tempObjectStore
for performance reasons.
userStore
ModuleUse the userStore
module to interact with Kinvey Users. The userStore
module can be used to create, update, find, remove, suspend, and restore Kinvey users.
To initialize the userStore
:
const store = modules.userStore();
The userStore
method also takes an optional options
argument containing store options for the current store. The options are:
Option | Description |
---|---|
useBl | For security reasons, applies only when useUserContext is false . If set to true, executes BL hooks associated with the userStore request. If false, BL hooks do not execute. Note that the "create user" and "log in" operations always execute with app credentials. Defaults to false. |
useUserContext | Uses user context credentials to access the userStore if set to true . If false , it executes in the context of mastersecret . Note that regardless of the value, the "create user" and "log in" operations always execute with app credentials. Defaults to false. |
useMasterSecret | DEPRECATED: use useUserContext instead Uses the mastersecret credentials to access the userStore if set to true . If set to false, will use the current user credentials. |
skipBl | DEPRECATED: use useBl instead If set to true, skips BL processing when accessing the userStore . If false or not included, it will default to executing any BL associated with the store. |
For example:
const options = {
useBl: true,
useUserContext: true
}
const store = modules.userStore(options);
The userStore
object contains methods for accessing Kinvey users. All methods take a callback
function and return a promise if a callback is not passed.
err
and results
arguments. The remove
, suspend
, and restore
methods take only an err
argument.
Method | Description | |
---|---|---|
find(query, callback) | Finds the users contained in the query . The query is a Query object created with modules.Query . If no Query object is supplied, the find method will return all users in the system, based on the authenticated user (or mastersecret and the _acls of the user collection. | |
findById(userId, callback) | Finds a single user by its _id . | |
getCurrentUser(callback) | Gets the current user's user entity. Note, this method executes in the current user context, regardless of whether the store was set to mastersecret or not. | |
create(user, callback) | Creates the provided user . Note that regardless of whether user or mastersecret credentials are selected for the store, create always uses appsecret credentials. | |
update(user, callback) | Updates the provided user . Note that the user entity supplied must contain an _id . | |
remove(userId, callback) | Removes a single user by its _id . Note this method deletes the user from the userStore and is non-recoverable. | |
suspend(userId, callback) | Suspends a single user by its _id . | |
restore(userId, callback) | Restores a suspended user. | |
count(query, callback) | Gets a count of all users that would be returned by the query . The query is a Query object created with modules.Query . If no Query object is supplied, the count method will return a count of the total number of users. | |
assignRole(userId, roleId, callback) | Assigns a role specified using roleId to a single user specified using userId . | |
revokeRole(userId, roleId, callback) | Unassigns the role specified using roleId from the user specified using userId . | |
listRoles(userId, callback) | Lists all the roles that are currently assigned to the user specified using userId . |
userStore
(request to the useStore
when the originating Flex request was also to the userStore
) must be executed under mastersecret
credentials and must not use Business Logic. If either useUserContext
or useBl
is set to true, these types of requests will fail with an error in the callback.
For example:
const store = userStore({ useUserContext: true });
store.findById(1234, (err, result) => {
if (err) {
return complete().setBody(err).runtimeError().done();
}
result.status = 'Approved';
store.update(result, (err, savedResult) => {
if (err) {
return complete(err).runtimeError().done();
}
complete().setBody(savedResult).ok().next();
});
});
});
userStore
, locally in particular, special headers need to be added to your local tests. These headers will be added automatically by Kinvey in production use. For information on the required headers, see the section on testing locally.
roleStore
ModuleUse the roleStore module to interact with user roles in Kinvey. The roleStore module can be used to create, update, retrieve, and remove Kinvey user roles, as well as list role members. You can also assign a role to a user, unassign a role, and list all roles assigned to a user.
To initialize the roleStore:
const options = {
useUserContext: true
}
const roles = modules.roleStore(options);
The roleStore
method takes an optional options
argument containing store options for the current store. The options are:
Option | Description |
---|---|
useUserContext | Uses user context credentials to access the roleStore if set to true . If false, will execute in the context of mastersecret . Defaults to false. |
The roleStore
object contains methods for working with Kinvey roles. All methods take a callback
function with an err
argument and return a promise if a callback is not passed.
Method | Description |
---|---|
create(role, callback) | Creates a new role . The group object must be formatted according to the Roles API Specification |
update(role, callback) | Updates the provided role . Note that the role entity supplied must contain an _id . The role object must be formatted according to the Roles API Specification |
remove(roleId, callback) | Removes a single group by its ID. Deleting a role causes it to be revoked from all users who were previously its members. |
findById(roleId, callback) | Retrieves the metadata of the role specified using the ID. |
listMembers(roleId, callback) | Returns an array of objects, representing the members of the role. See the Roles API Specification for the result format. |
For example:
const roles = roleStore({ useUserContext: true });
roles.findById(1234, (err, result) => {
if (err) {
return complete().setBody(err).runtimeError().done();
}
roles.update(result, (err, savedResult) => {
if (err) {
return complete(err).runtimeError().done();
}
complete().setBody(savedResult).ok().next();
});
});
The userStore
object contains additional role-related methods for managing roles from the user perspective.
roleStore
, locally in particular, special headers need to be added to your local tests. These headers will be added automatically by Kinvey in production use. For information on the required headers, see the section on testing locally.
Use the endpointRunner
module to call custom endpoints when you need to make additional calculations or simply separate parts of the code for reuse or logically. The module allows the reuse of the existing user context and authentication.
To initialize the endpointRunner:
const options = {
useUserContext: true
}
const runner = modules.endpointRunner(options);
The endpointRunner
method takes an optional options
argument containing options for the current module. The options are:
Option | Description |
---|---|
useUserContext | Uses user context credentials to access the endpointRunner if set to true . If false, will execute in the context of mastersecret . Defaults to false. |
The endpointRunner
object contains a single method for calling existing custom Kinvey endpoints.
Method | Fluent method | Description |
---|---|---|
endpoint(endpointName) | - | Returns the internal endpoint object for the named endpoint. |
- | execute(requestBody, callback) | Executes the endpoint specified using endpoint() with an optional request body. Returns a promise if a callback function is not passed. |
For example:
const options = {
useUserContext: true
}
const verifyPhoneNumber = modules.endpointRunner(options).endpoint('verifyPhoneNumber');
const requestBody = {
phone: "555-222-333-444"
};
verifyPhoneNumber.execute(requestBody, (err, result) => {
if (err) {
return complete(err).runtimeError().done();
}
complete().setBody(result).ok().done();
});
endpointRunner
, locally in particular, special headers need to be added to your local tests. These headers will be added automatically by Kinvey in production use. For information on the required headers, see the section on testing locally.
In production use, Kinvey sends various pieces of data to the Flex service for use in certain modules. It does that using HTTP headers.
Normally, you don't need to manually set or read the headers documented in this section. When testing locally, however, you may need to pass them to simulate a production environment, otherwise some modules won't function properly.
Header | Description | Client modules |
---|---|---|
X-Kinvey-App-Metadata | A stringified JSON object containing information about the app context from which this request is being executed | backendContext , dataStore , userStore |
X-Kinvey-Original-Request-Headers | A stringified JSON object containing the request headers that belong to the request context of the server-side logic or data request | requestContext , dataStore , userStore , request argument in all handlers (if you want to access request headers) |
X-Kinvey-Username | The username of the user making the request | requestContext , dataStore , userStore |
X-Kinvey-User-Id | The user ID of the user making the request | requestContext , dataStore , userStore |
X-Auth-Key | The shared secret used for accessing this Flex service | All modules, if the SDK is initialized with a shared secret |
X-Kinvey-App-Metadata
HeaderThe object contained in the X-Kinvey-App-Metadata
contains the following properties:
Property | Description |
---|---|
_id | The environmentId |
appsecret | The app secret |
mastersecret | The master secret |
baasUrl | The base URL for the Kinvey instance you are using (ex: https://baas.kinvey.com ) |
X-Kinvey-Original-Request-Headers
HeaderThe X-Kinvey-Original-Request-Headers
object can contain any number of custom headers, but typically contains the following:
Property | Description |
---|---|
X-Kinvey-Api-Version | The API version to use (number). This header is important for the dataStore module. |
Authorization | The authorization string (either Basic or Kinvey auth) for accessing the Kinvey REST service. |
X-Kinvey-Client-App-Version | The Client App Version string |
X-Kinvey-Custom-Request-Properties | The custom request properties in stringified JSON form |