lightstreamer-adapter
Advanced tools
Comparing version 1.0.2 to 1.3.1
@@ -1,17 +0,54 @@ | ||
## 1.0.2 (3 Feb 2014) ## | ||
## 1.3.1 (3 Nov 2014) ## | ||
### New Features ### | ||
Improved the format for publishing on npm. | ||
Introduced suitable documentation for the default behavior of the | ||
MetadataProvider object. | ||
Fixed the documentation of some cases in the MetadataResponse class, which were | ||
confused with the corresponding requests. | ||
### Lightstreamer Compatibility Notes ### | ||
Compatible with Adapter Remoting Infrastructure since 1.4.3 | ||
Compatible with Adapter Remoting Infrastructure since 1.7 | ||
## 1.0.1 (1 Oct 2013) ## | ||
## 1.3.0 (22 Aug 2014) ## | ||
### New Features ### | ||
Extended the MetadataProvider object to support the new Push Notification Service | ||
(aka MPN Module). When enabled, the new events will be issued in order to validate | ||
client requests related with the service. See the docs for details. | ||
Note that the MPN Module cannot be enabled in Moderato edition. | ||
### Lightstreamer Compatibility Notes ### | ||
Compatible with Adapter Remoting Infrastructure since 1.7 | ||
## 1.2.0 (27 Jun 2013) ## | ||
### New Features ### | ||
Added the support for Remote Adapter initialization requests introduced in | ||
ARI protocol version 1.6 and actually issued by the Proxy Adapters. | ||
Hence, a "init" event has been added to both the MetadataProvider and | ||
DataProvider objects. The events can be left unhandled, so no code changed | ||
are needed. | ||
Note that the various unit tests have been complicated somewhat, in order | ||
to account for the protocol extension. | ||
### Lightstreamer Compatibility Notes ### | ||
Compatible with Adapter Remoting Infrastructure since 1.6 | ||
## 1.1.1 (18 Jun 2013) ## | ||
### New Features ### | ||
Extended the "error" method of the DataResponse class, to make it similar to the Metadata Adapter case. | ||
@@ -21,2 +58,17 @@ In order to issue an exception of type Subscription, a second argument valued "subscription" should be passed. | ||
### Lightstreamer Compatibility Notes ### | ||
Compatible with Adapter Remoting Infrastructure since 1.5 | ||
Still compatible with 1.4.3 if "clearSnapshot" is not used. | ||
## 1.1.0 (4 Jun 2013) ## | ||
### New Features ### | ||
Added the clearSnapshot method to the DataProvider object. | ||
This leverages the extension in Lightstreamer Adapter Remoting Infrastructure 1.5. | ||
Introduced the changelog. | ||
@@ -32,6 +84,8 @@ | ||
Compatible with Adapter Remoting Infrastructure since 1.4.3 | ||
Compatible with Adapter Remoting Infrastructure since 1.5 | ||
Still compatible with 1.4.3 if "clearSnapshot" is not used. | ||
## 1.0.0 ## | ||
@@ -38,0 +92,0 @@ |
@@ -0,0 +0,0 @@ /* |
@@ -41,4 +41,30 @@ /* | ||
MODE : 'M', | ||
// MPN platform type identifier | ||
MPN_PLATFORM : 'P', | ||
// MPN subscription type identifier | ||
MPN_SUBSCRIPTION : 'P' | ||
}; | ||
// MPN subscription data subtypes. | ||
exports.mpnSubscriptionSubtypes = { | ||
// APNS type identifier | ||
APNS : "A", | ||
// APNS type identifier | ||
GCM : "G" | ||
}; | ||
// MPN platform types. | ||
exports.mpnPlatformTypes = { | ||
// APNS type identifier | ||
APNS : "A", | ||
// APNS type identifier | ||
GCM : "G", | ||
// APNS type identifier | ||
WNS : "W", | ||
// APNS type identifier | ||
MPNS : "M", | ||
// APNS type identifier | ||
BPN : "B" | ||
}; | ||
// Protocol data and metadata exceptions. | ||
@@ -48,2 +74,6 @@ exports.exceptions = { | ||
GENERIC : "E", | ||
// Metadata Exception type identifier | ||
METADATA : "EM", | ||
// Data Exception type identifier | ||
DATA : "ED", | ||
// Failure exception subtype identifier | ||
@@ -55,3 +85,3 @@ FAILURE : "EF", | ||
ACCESS : 'EA', | ||
// Credits exception subtype identifier | ||
// Credits exception subtype identifier | ||
CREDITS : 'EC', | ||
@@ -82,9 +112,9 @@ // Confliting exception subtype identifier | ||
exports.modeValues = { | ||
// Encoded mode raw value | ||
// Encoded mode raw value | ||
RAW : 'R', | ||
// Encoded mode raw value | ||
// Encoded mode raw value | ||
MERGE : 'M', | ||
// Encoded mode raw value | ||
// Encoded mode raw value | ||
DISTINCT : 'D', | ||
// Encoded mode raw value | ||
// Encoded mode raw value | ||
COMMAND : 'C' | ||
@@ -95,2 +125,4 @@ }; | ||
exports.dataMethods = { | ||
// Initialization method | ||
DATA_INIT : "DPI", | ||
// Keepalive message method | ||
@@ -106,2 +138,4 @@ KEEPALIVE : "KEEPALIVE", | ||
END_OF_SNAPSHOT : "EOS", | ||
// Clear snapshot message method | ||
CLEAR_SNAPSHOT : "CLS", | ||
// Update by indexed event message method | ||
@@ -117,2 +151,4 @@ UPDATE_BY_INDEXED_EVENT : "UD1", | ||
exports.metadataMethods = { | ||
// Initialization method | ||
METADATA_INIT : "MPI", | ||
// Get item data method | ||
@@ -139,4 +175,10 @@ GET_ITEM_DATA : "GIT", | ||
// Notify tables close method | ||
NOTIFY_TABLES_CLOSE : "NTC" | ||
NOTIFY_TABLES_CLOSE : "NTC", | ||
// Notify MPN device access | ||
NOTIFY_MPN_DEVICE_ACCESS : "MDA", | ||
// Notify MPN subscription activation | ||
NOTIFY_MPN_SUBSCRIPTION_ACTIVATION : "MSA", | ||
// Notify MPN device token change | ||
NOTIFY_MPN_DEVICE_TOKEN_CHANGE : "MDC" | ||
} | ||
@@ -26,2 +26,31 @@ /* | ||
/** | ||
* Encodes a successful initialization reply. | ||
* | ||
* @param {String} requestId the originating request id | ||
* @return {String} the encoded message | ||
* @private | ||
*/ | ||
writeInit : function(requestId) { | ||
return protocol.implodeMessage(requestId, | ||
dataMethods.DATA_INIT, types.VOID); | ||
}, | ||
/** | ||
* Encodes an unsuccessful initialization reply. | ||
* | ||
* @param {String} requestId the originating request id | ||
* @param {String} exceptionMessage the exception message | ||
* @param {String} [exceptionType] the exception type. Allowed values: data | ||
* @return {String} the encoded message | ||
* @private | ||
*/ | ||
writeInitException : function(requestId, exceptionMessage, exceptionType) { | ||
if (exceptionType === "data") { | ||
return protocol.implodeMessage(requestId, dataMethods.DATA_INIT, | ||
exceptions.DATA, protocol.encodeString(exceptionMessage)); | ||
} else { | ||
return protocol.implodeMessage(requestId, dataMethods.DATA_INIT, | ||
exceptions.GENERIC, protocol.encodeString(exceptionMessage)); | ||
} | ||
}, | ||
/** | ||
* Encodes a successful subscribe reply. | ||
@@ -107,2 +136,15 @@ * | ||
/** | ||
* Encodes a clear snapshot message for a particular item to be sent to the proxy. | ||
* | ||
* @param {String} requestId the originating request id | ||
* @param {String} itemName the item name | ||
* @return {String} the encoded message | ||
* @private | ||
*/ | ||
writeClearSnapshot : function(requestId, itemName) { | ||
return protocol.implodeMessage(protocol.timestamp(), dataMethods.CLEAR_SNAPSHOT, | ||
types.STRING, protocol.encodeString(itemName), | ||
types.STRING, requestId); | ||
}, | ||
/** | ||
* Encodes an update for a particular item to be sent to the proxy. | ||
@@ -133,19 +175,36 @@ * | ||
* @param {String} request the string message received from the remote proxy | ||
* @param {Boolean} initExpected if we are waiting for the initial "init" message | ||
* @return {Object} the decoded message | ||
* @private | ||
*/ | ||
function read(request) { | ||
function read(request, initExpected) { | ||
var message, tokens; | ||
tokens = protocol.explode(request); | ||
if (tokens.length != 4) { | ||
throw new Error('Message has an invalid number of tokens ' + request); | ||
if (tokens.length < 2) { | ||
throw new Error('Message has an invalid number of tokens: ' + request); | ||
} | ||
message = { | ||
id : tokens[0], | ||
itemName : protocol.decodeString(tokens[3]) | ||
}; | ||
if (dataMethods.SUBSCRIBE === tokens[1]) { | ||
var isInitRequest = (dataMethods.DATA_INIT === tokens[1]); | ||
if (! initExpected && isInitRequest) { | ||
throw new Error("Unexpected late " + dataMethods.DATA_INIT + " message"); | ||
} else if (initExpected && ! isInitRequest) { | ||
throw new Error("Unexpected message " + request + " while waiting for a " + dataMethods.DATA_INIT + " message"); | ||
} | ||
if (! isInitRequest && tokens.length != 4) { | ||
throw new Error('Message has an invalid number of tokens ' + request); | ||
} | ||
if (isInitRequest) { | ||
var tail = tokens.slice(2); | ||
message.verb = "init"; | ||
readInit(message, tail); | ||
} else if (dataMethods.SUBSCRIBE === tokens[1]) { | ||
message.verb = 'subscribe'; | ||
message.itemName = protocol.decodeString(tokens[3]); | ||
} else if (dataMethods.UNSUBSCRIBE === tokens[1]) { | ||
message.verb = 'unsubscribe'; | ||
message.itemName = protocol.decodeString(tokens[3]); | ||
} else { | ||
@@ -157,4 +216,20 @@ throw new Error('Message has an invalid method'); | ||
/** | ||
* Decode a init request. | ||
* | ||
* @param {Object} message the message object partially initialized with the id and the verb | ||
* @param {Array} tokens the rest of the message already tokenized | ||
* @private | ||
*/ | ||
function readInit(message, tokens) { | ||
var i; | ||
message.parameters = {}; | ||
for (i = 0; i < tokens.length; i = i + 4) { | ||
message.parameters[protocol.decodeString(tokens[i + 1])] = protocol.decodeString(tokens[i + 3]); | ||
} | ||
} | ||
exports.DataReader = function() { | ||
return new protocol.StreamReader(read); | ||
} |
@@ -29,4 +29,11 @@ /* | ||
* Data provider constructor.<br> | ||
* The created object allows you to interact with Lightstreamer Server through | ||
* the Adapter Remoting Infrastructure protocol as a Remote Data Adapter. | ||
* See the ARI Protocol documentation for details on the request and response | ||
* messages.<br> | ||
* This object extends the EventEmitter object and emits the following events: | ||
* <ul> | ||
* <li>init: function(request, response) {}<br/> | ||
* Here, the request object is an associative array with the following content: | ||
* {parameters: {<name 1>: <value 1> ... <name n>: <value n>}}</li> | ||
* <li>subscribe: function(itemName, response) {}</li> | ||
@@ -40,4 +47,4 @@ * <li>unsubscribe: function(itemName, response) {}</li> | ||
* @param {Stream} notifyStream the asynchronous stream channel to the remote LS proxy adapter | ||
* @param {Function} [isSnapshotAvailable] optional callback the receive an itemName as argument and must return | ||
* a boolean value asserting if the iteam supports snapshot. The default value is function(itemName) {return false;} | ||
* @param {Function} [isSnapshotAvailable] optional callback that receives an itemName as argument and must return | ||
* a boolean value asserting if the item supports snapshot. The default value is function(itemName) {return false;} | ||
*/ | ||
@@ -64,2 +71,5 @@ function DataProvider(reqRespStream, notifyStream, isSnapshotAvailable) { | ||
// init message expected | ||
initPending = true; | ||
// Default value for snapshot callback | ||
@@ -81,6 +91,7 @@ isSnapshotAvailable = isSnapshotAvailable || function(itemName) {return false;}; | ||
var message; | ||
reader.parse(data); | ||
reader.parse(data, initPending); | ||
initPending = false; | ||
while (!reader.isEmpty()) { | ||
message = reader.pop(); | ||
// console.log("IN MESSAGE: " + inspect(messages[i])); | ||
// console.log("IN MESSAGE: " + inspect(message)); | ||
handlers[message.verb](message); | ||
@@ -231,2 +242,24 @@ } | ||
/** | ||
* Handles an initialization request creating a DataResponse Object and | ||
* emitting the subscribe event. | ||
* If the handler is not defined, just writes an ack response. | ||
* | ||
* @param {Object} message the incoming request associative array | ||
* @private | ||
*/ | ||
'init' : function(message) { | ||
if (that.listeners(message.verb).length) { | ||
var successHandler = function(msg) { | ||
reply(proto.writeInit(msg.id)); | ||
}; | ||
var errorHandler = function(msg, exceptionMessage, exceptionType) { | ||
reply(proto.writeInitException(msg.id, exceptionMessage, exceptionType)); | ||
}; | ||
var response = new DataResponse(message, successHandler, errorHandler); | ||
that.emit("init", message, response); | ||
} else { | ||
reply(proto.writeInit(message.id)); | ||
} | ||
}, | ||
/** | ||
* Handles a subscribe request creating a DataResponse Object and | ||
@@ -291,2 +324,14 @@ * emitting the subscribe event. | ||
/** | ||
* Sends a clear snapshot message for a particular item to the remote LS proxy. | ||
* | ||
* @param {String} itemName the item name | ||
*/ | ||
function clearSnapshot(itemName) { | ||
var message, id = getIdFromItemName(itemName); | ||
message = proto.writeClearSnapshot(id, itemName); | ||
notify(message); | ||
return that; | ||
} | ||
/** | ||
* Sends a failure message to the remote LS proxy. | ||
@@ -340,2 +385,3 @@ * | ||
endOfSnapshot: endOfSnapshot, | ||
clearSnapshot: clearSnapshot, | ||
failure: failure, | ||
@@ -380,2 +426,3 @@ notifyStream: getNotifyStream, | ||
* <ul> | ||
* <li>init: "data"</li> | ||
* <li>subscribe: "subscription"</li> | ||
@@ -382,0 +429,0 @@ * <li>unsubscribe: "subscription"</li> |
@@ -21,3 +21,4 @@ /* | ||
exceptions = require('./consts').exceptions, | ||
metadataMethods = require('./consts').metadataMethods; | ||
metadataMethods = require('./consts').metadataMethods, | ||
mpnSubscriptionSubtypes = require('./consts').mpnSubscriptionSubtypes; | ||
@@ -28,2 +29,13 @@ | ||
/** | ||
* Encodes a successful initialization reply. | ||
* | ||
* @param {String} requestId the originating request id | ||
* @return {String} the encoded message | ||
* @private | ||
*/ | ||
writeInit : function(requestId) { | ||
return protocol.implodeMessage(requestId, | ||
metadataMethods.METADATA_INIT, types.VOID); | ||
}, | ||
/** | ||
* Encodes a successful get schema reply. | ||
@@ -39,3 +51,3 @@ * | ||
metadataMethods.GET_SCHEMA, | ||
protocol.implodeDataArray(fieldNames)); | ||
protocol.implodeDataArray(fieldNames)); | ||
}, | ||
@@ -53,3 +65,3 @@ /** | ||
metadataMethods.GET_ITEMS, | ||
protocol.implodeDataArray(itemNames)); | ||
protocol.implodeDataArray(itemNames)); | ||
}, | ||
@@ -114,3 +126,3 @@ /** | ||
types.DOUBLE, protocol.encodeDouble(maxBandwidth), | ||
types.BOOLEAN, protocol.encodeBoolean(notifyTables)); | ||
types.BOOLEAN, protocol.encodeBoolean(notifyTables)); | ||
}, | ||
@@ -129,3 +141,3 @@ /** | ||
types.DOUBLE, protocol.encodeDouble(maxBandwidth), | ||
types.BOOLEAN, protocol.encodeBoolean(notifyTables)); | ||
types.BOOLEAN, protocol.encodeBoolean(notifyTables)); | ||
}, | ||
@@ -141,3 +153,3 @@ /** | ||
return protocol.implodeMessage(requestId, | ||
metadataMethods.NOTIFY_USER_MESSAGE, types.VOID); | ||
metadataMethods.NOTIFY_USER_MESSAGE, types.VOID); | ||
}, | ||
@@ -153,3 +165,3 @@ /** | ||
return protocol.implodeMessage(requestId, | ||
metadataMethods.NOTIFY_NEW_SESSION, types.VOID); | ||
metadataMethods.NOTIFY_NEW_SESSION, types.VOID); | ||
}, | ||
@@ -165,3 +177,3 @@ /** | ||
return protocol.implodeMessage(requestId, | ||
metadataMethods.NOTIFY_SESSION_CLOSE, types.VOID); | ||
metadataMethods.NOTIFY_SESSION_CLOSE, types.VOID); | ||
}, | ||
@@ -177,3 +189,3 @@ /** | ||
return protocol.implodeMessage(requestId, | ||
metadataMethods.NOTIFY_NEW_TABLES, types.VOID); | ||
metadataMethods.NOTIFY_NEW_TABLES, types.VOID); | ||
}, | ||
@@ -189,5 +201,52 @@ /** | ||
return protocol.implodeMessage(requestId, | ||
metadataMethods.NOTIFY_TABLES_CLOSE, types.VOID); | ||
metadataMethods.NOTIFY_TABLES_CLOSE, types.VOID); | ||
}, | ||
/** | ||
* Encodes a successful notify MPN device access reply. | ||
* | ||
* @param {String} requestId the originating request id | ||
* @return {String} the encoded message | ||
* @private | ||
*/ | ||
writeNotifyMpnDeviceAccess : function(requestId) { | ||
return protocol.implodeMessage(requestId, | ||
metadataMethods.NOTIFY_MPN_DEVICE_ACCESS, types.VOID); | ||
}, | ||
/** | ||
* Encodes a successful notify MPN subscription activation reply. | ||
* | ||
* @param {String} requestId the originating request id | ||
* @return {String} the encoded message | ||
* @private | ||
*/ | ||
writeNotifyMpnSubscriptionActivation : function(requestId) { | ||
return protocol.implodeMessage(requestId, | ||
metadataMethods.NOTIFY_MPN_SUBSCRIPTION_ACTIVATION, types.VOID); | ||
}, | ||
/** | ||
* Encodes a successful notify MPN device token change reply. | ||
* | ||
* @param {String} requestId the originating request id | ||
* @return {String} the encoded message | ||
* @private | ||
*/ | ||
writeNotifyMpnDeviceTokenChange : function(requestId) { | ||
return protocol.implodeMessage(requestId, | ||
metadataMethods.NOTIFY_MPN_DEVICE_TOKEN_CHANGE, types.VOID); | ||
}, | ||
/** | ||
* Encodes an unsuccessful initialization reply. | ||
* | ||
* @param {String} requestId the originating request id | ||
* @param {String} exceptionMessage the exception message | ||
* @param {String} [exceptionType] the exception type. Allowed values: metadata | ||
* @return {String} the encoded message | ||
* @private | ||
*/ | ||
writeInitException : function(requestId, exceptionMessage, exceptionType) { | ||
return protocol.implodeMessage(requestId, metadataMethods.METADATA_INIT, | ||
protocol.encodeMetadataException(exceptionType), | ||
protocol.encodeString(exceptionMessage)); | ||
}, | ||
/** | ||
* Encodes an unsuccessful get schema reply. | ||
@@ -204,3 +263,3 @@ * | ||
protocol.encodeMetadataException(exceptionType), | ||
protocol.encodeString(exceptionMessage)); | ||
protocol.encodeString(exceptionMessage)); | ||
}, | ||
@@ -217,3 +276,3 @@ /** | ||
return protocol.implodeMessage(requestId, metadataMethods.GET_ITEM_DATA, | ||
exceptions.GENERIC, protocol.encodeString(exceptionMessage)); | ||
exceptions.GENERIC, protocol.encodeString(exceptionMessage)); | ||
}, | ||
@@ -230,3 +289,3 @@ /** | ||
return protocol.implodeMessage(requestId, metadataMethods.GET_USER_ITEM_DATA, | ||
exceptions.GENERIC, protocol.encodeString(exceptionMessage)); | ||
exceptions.GENERIC, protocol.encodeString(exceptionMessage)); | ||
}, | ||
@@ -245,3 +304,3 @@ /** | ||
protocol.encodeMetadataException(exceptionType), | ||
protocol.encodeString(exceptionMessage)); | ||
protocol.encodeString(exceptionMessage)); | ||
}, | ||
@@ -260,3 +319,3 @@ /** | ||
protocol.encodeMetadataException(exceptionType), | ||
protocol.encodeString(exceptionMessage)); | ||
protocol.encodeString(exceptionMessage)); | ||
}, | ||
@@ -275,3 +334,3 @@ /** | ||
protocol.encodeMetadataException(exceptionType), | ||
protocol.encodeString(exceptionMessage)); | ||
protocol.encodeString(exceptionMessage)); | ||
}, | ||
@@ -290,3 +349,3 @@ /** | ||
protocol.encodeMetadataException(exceptionType), | ||
protocol.encodeString(exceptionMessage)); | ||
protocol.encodeString(exceptionMessage)); | ||
}, | ||
@@ -305,3 +364,3 @@ /** | ||
protocol.encodeMetadataException(exceptionType), | ||
protocol.encodeString(exceptionMessage)); | ||
protocol.encodeString(exceptionMessage)); | ||
}, | ||
@@ -320,3 +379,3 @@ /** | ||
protocol.encodeMetadataException(exceptionType), | ||
protocol.encodeString(exceptionMessage)); | ||
protocol.encodeString(exceptionMessage)); | ||
}, | ||
@@ -335,3 +394,3 @@ /** | ||
protocol.encodeMetadataException(exceptionType), | ||
protocol.encodeString(exceptionMessage)); | ||
protocol.encodeString(exceptionMessage)); | ||
}, | ||
@@ -350,4 +409,46 @@ /** | ||
protocol.encodeMetadataException(exceptionType), | ||
protocol.encodeString(exceptionMessage)); | ||
protocol.encodeString(exceptionMessage)); | ||
}, | ||
/** | ||
* Encodes an unsuccessful MPN device access reply. | ||
* | ||
* @param {String} requestId the originating request id | ||
* @param {String} exceptionMessage the exception message | ||
* @param {String} [exceptionType] the exception type. Allowed values: notification, credits | ||
* @return {String} the encoded message | ||
* @private | ||
*/ | ||
writeNotifyMpnDeviceAccessException : function(requestId, exceptionMessage, exceptionType) { | ||
return protocol.implodeMessage(requestId, metadataMethods.NOTIFY_MPN_DEVICE_ACCESS, | ||
protocol.encodeMetadataException(exceptionType), | ||
protocol.encodeString(exceptionMessage)); | ||
}, | ||
/** | ||
* Encodes an unsuccessful MPN subscription activation reply. | ||
* | ||
* @param {String} requestId the originating request id | ||
* @param {String} exceptionMessage the exception message | ||
* @param {String} [exceptionType] the exception type. Allowed values: notification, credits | ||
* @return {String} the encoded message | ||
* @private | ||
*/ | ||
writeNotifyMpnSubscriptionActivationException : function(requestId, exceptionMessage, exceptionType) { | ||
return protocol.implodeMessage(requestId, metadataMethods.NOTIFY_MPN_SUBSCRIPTION_ACTIVATION, | ||
protocol.encodeMetadataException(exceptionType), | ||
protocol.encodeString(exceptionMessage)); | ||
}, | ||
/** | ||
* Encodes an unsuccessful MPN device token change reply. | ||
* | ||
* @param {String} requestId the originating request id | ||
* @param {String} exceptionMessage the exception message | ||
* @param {String} [exceptionType] the exception type. Allowed values: notification, credits | ||
* @return {String} the encoded message | ||
* @private | ||
*/ | ||
writeNotifyMpnDeviceTokenChangeException : function(requestId, exceptionMessage, exceptionType) { | ||
return protocol.implodeMessage(requestId, metadataMethods.NOTIFY_MPN_DEVICE_TOKEN_CHANGE, | ||
protocol.encodeMetadataException(exceptionType), | ||
protocol.encodeString(exceptionMessage)); | ||
}, | ||
}; | ||
@@ -361,6 +462,7 @@ | ||
* @param {String} request string message from the remote proxy (UTF8) | ||
* @param {Boolean} isStarting if we are waiting for the initial "init" message | ||
* @return {Object} the decoded message | ||
* @private | ||
*/ | ||
function read(request) { | ||
function read(request, isStarting) { | ||
var message, tokens, tail; | ||
@@ -375,3 +477,14 @@ tokens = protocol.explode((request + '').replace(/\r*\n$/, '')); | ||
tail = tokens.slice(2); | ||
if (metadataMethods.GET_ITEM_DATA === tokens[1]) { | ||
var isInitRequest = (metadataMethods.METADATA_INIT === tokens[1]); | ||
if (! isStarting && isInitRequest) { | ||
throw new Error("Unexpected late " + metadataMethods.METADATA_INIT + " message"); | ||
} else if (isStarting && ! isInitRequest) { | ||
throw new Error("Unexpected message " + request + " while waiting for a " + metadataMethods.METADATA_INIT + " message"); | ||
} | ||
if (isInitRequest) { | ||
message.verb = "init"; | ||
readInit(message, tail); | ||
} else if (metadataMethods.GET_ITEM_DATA === tokens[1]) { | ||
message.verb = "getItemData"; | ||
@@ -409,4 +522,13 @@ readGetItemData(message, tail); | ||
readNotifyTablesClose(message, tail); | ||
} else if (metadataMethods.NOTIFY_MPN_DEVICE_ACCESS === tokens[1]) { | ||
message.verb = "notifyMpnDeviceAccess"; | ||
readNotifyMpnDeviceAccess(message, tail); | ||
} else if (metadataMethods.NOTIFY_MPN_SUBSCRIPTION_ACTIVATION === tokens[1]) { | ||
message.verb = "notifyMpnSubscriptionActivation"; | ||
readNotifyMpnSubscriptionActivation(message, tail); | ||
} else if (metadataMethods.NOTIFY_MPN_DEVICE_TOKEN_CHANGE === tokens[1]) { | ||
message.verb = "notifyMpnDeviceTokenChange"; | ||
readNotifyMpnDeviceTokenChange(message, tail); | ||
} else { | ||
throw new Error('Message has an invalid method: ' + request); | ||
throw new Error('Message has an invalid method: ' + request); | ||
} | ||
@@ -417,2 +539,18 @@ return message; | ||
/** | ||
* Decode a init request. | ||
* | ||
* @param {Object} message the message object partially initialized with the id and the verb | ||
* @param {Array} tokens the rest of the message already tokenized | ||
* @private | ||
*/ | ||
function readInit(message, tokens) { | ||
var i; | ||
message.parameters = {}; | ||
for (i = 0; i < tokens.length; i = i + 4) { | ||
message.parameters[protocol.decodeString(tokens[i + 1])] = protocol.decodeString(tokens[i + 3]); | ||
} | ||
} | ||
/** | ||
* Decode an get schema request. | ||
@@ -441,3 +579,3 @@ * | ||
message.groupName = protocol.decodeString(tokens[3]); | ||
message.sessionId = protocol.decodeString(tokens[5]); | ||
message.sessionId = protocol.decodeString(tokens[5]); | ||
} | ||
@@ -523,3 +661,3 @@ | ||
message.userName = protocol.decodeString(tokens[1]); | ||
message.sessionId = protocol.decodeString(tokens[3]); | ||
message.sessionId = protocol.decodeString(tokens[3]); | ||
message.userMessage = protocol.decodeString(tokens[5]); | ||
@@ -538,3 +676,3 @@ } | ||
message.userName = protocol.decodeString(tokens[1]); | ||
message.sessionId = protocol.decodeString(tokens[3]); | ||
message.sessionId = protocol.decodeString(tokens[3]); | ||
message.contextProperties = {}; | ||
@@ -544,3 +682,3 @@ tokens = tokens.slice(4); | ||
message.contextProperties[protocol.decodeString(tokens[i + 1])] = protocol.decodeString(tokens[i + 3]); | ||
} | ||
} | ||
} | ||
@@ -556,3 +694,3 @@ | ||
function readNotifySessionClose(message, tokens) { | ||
message.sessionId = protocol.decodeString(tokens[1]); | ||
message.sessionId = protocol.decodeString(tokens[1]); | ||
} | ||
@@ -569,3 +707,3 @@ | ||
message.userName = protocol.decodeString(tokens[1]); | ||
message.sessionId = protocol.decodeString(tokens[3]); | ||
message.sessionId = protocol.decodeString(tokens[3]); | ||
readTableInfos(message, tokens.slice(4)); | ||
@@ -582,3 +720,3 @@ } | ||
function readNotifyTablesClose(message, tokens) { | ||
message.sessionId = protocol.decodeString(tokens[1]); | ||
message.sessionId = protocol.decodeString(tokens[1]); | ||
readTableInfos(message, tokens.slice(2)); | ||
@@ -588,4 +726,104 @@ } | ||
/** | ||
* Decode the tables info part pf a notify tables request. | ||
* Decode a notify MPN device access request. | ||
* | ||
* @param {Object} message the message object partially initialized with the id and the verb | ||
* @param {Array} tokens the rest of the message already tokenized | ||
* @private | ||
*/ | ||
function readNotifyMpnDeviceAccess(message, tokens) { | ||
message.userName = protocol.decodeString(tokens[1]); | ||
message.device = {}; | ||
message.device.mpnPlatformType = protocol.decodeString(tokens[3]); | ||
message.device.applicationId = protocol.decodeString(tokens[5]); | ||
message.device.deviceToken = protocol.decodeString(tokens[7]); | ||
} | ||
/** | ||
* Decode a notify MPN subscription activation request. | ||
* | ||
* @param {Object} message the message object partially initialized with the id and the verb | ||
* @param {Array} tokens the rest of the message already tokenized | ||
* @private | ||
*/ | ||
function readNotifyMpnSubscriptionActivation(message, tokens) { | ||
message.userName = protocol.decodeString(tokens[1]); | ||
message.sessionId = protocol.decodeString(tokens[3]); | ||
message.tableInfo = readTableInfo(tokens.slice(4), true); | ||
var base = 16; | ||
message.mpnSubscription = {}; | ||
message.mpnSubscription.device = {}; | ||
var mpnSubscriptionType = protocol.decodeString(tokens[base]); | ||
switch (mpnSubscriptionType.charAt(1)) { | ||
case mpnSubscriptionSubtypes.APNS: { | ||
var argumentsSize= protocol.decodeInteger(tokens[base + 1]); | ||
var customDataSize= protocol.decodeInteger(tokens[base + 2]); | ||
message.mpnSubscription.device.mpnPlatformType = protocol.decodeString(tokens[base + 4]); | ||
message.mpnSubscription.device.applicationId = protocol.decodeString(tokens[base + 6]); | ||
message.mpnSubscription.device.deviceToken = protocol.decodeString(tokens[base + 8]); | ||
message.mpnSubscription.trigger = protocol.decodeString(tokens[base + 10]); | ||
message.mpnSubscription.sound = protocol.decodeString(tokens[base + 12]); | ||
message.mpnSubscription.badge = protocol.decodeString(tokens[base + 14]); | ||
message.mpnSubscription.localizedActionKey = protocol.decodeString(tokens[base + 16]); | ||
message.mpnSubscription.launchImage = protocol.decodeString(tokens[base + 18]); | ||
message.mpnSubscription.format = protocol.decodeString(tokens[base + 20]); | ||
message.mpnSubscription.localizedFormatKey = protocol.decodeString(tokens[base + 22]); | ||
var i, arg, key, value; | ||
message.mpnSubscription.localizedFormatArguments = []; | ||
for (i = 0; i < (argumentsSize * 2); i += 2) { | ||
arg = protocol.decodeString(tokens[base + 24 + i]); | ||
message.mpnSubscription.localizedFormatArguments.push(arg); | ||
} | ||
message.mpnSubscription.customData = {}; | ||
for (i = 0; i < (customDataSize * 4); i += 4) { | ||
key = protocol.decodeString(tokens[base + 24 + (argumentsSize * 2) + i]); | ||
value = protocol.decodeString(tokens[base + 24 + (argumentsSize * 2) + i + 2]); | ||
message.mpnSubscription.customData[key] = value; | ||
} | ||
break; | ||
} | ||
case mpnSubscriptionSubtypes.GCM: { | ||
var dataSize= protocol.decodeInteger(tokens[base + 1]); | ||
message.mpnSubscription.device.mpnPlatformType = protocol.decodeString(tokens[base + 3]); | ||
message.mpnSubscription.device.applicationId = protocol.decodeString(tokens[base + 5]); | ||
message.mpnSubscription.device.deviceToken = protocol.decodeString(tokens[base + 7]); | ||
message.mpnSubscription.trigger = protocol.decodeString(tokens[base + 9]); | ||
message.mpnSubscription.collapseKey = protocol.decodeString(tokens[base + 11]); | ||
var i, key, value; | ||
message.mpnSubscription.data = {}; | ||
for (i = 0; i < (dataSize * 4); i += 4) { | ||
key = protocol.decodeString(tokens[base + 13 + i]); | ||
value = protocol.decodeString(tokens[base + 13 + i + 2]); | ||
message.mpnSubscription.data[key] = value; | ||
} | ||
message.mpnSubscription.delayWhileIdle = protocol.decodeString(tokens[base + 13 + (dataSize * 4)]); | ||
message.mpnSubscription.timeToLive = protocol.decodeString(tokens[base + 13 + (dataSize * 4) + 2]); | ||
break; | ||
} | ||
default: | ||
throw new Error('Message has unsupported MPN subscription type: ' + mpnSubscriptionType); | ||
} | ||
} | ||
/** | ||
* Decode a notify MPN device token change request. | ||
* | ||
* @param {Object} message the message object partially initialized with the id and the verb | ||
* @param {Array} tokens the rest of the message already tokenized | ||
* @private | ||
*/ | ||
function readNotifyMpnDeviceTokenChange(message, tokens) { | ||
message.userName = protocol.decodeString(tokens[1]); | ||
message.device = {}; | ||
message.device.mpnPlatformType = protocol.decodeString(tokens[3]); | ||
message.device.applicationId = protocol.decodeString(tokens[5]); | ||
message.device.deviceToken = protocol.decodeString(tokens[7]); | ||
message.newDeviceToken = protocol.decodeString(tokens[9]); | ||
} | ||
/** | ||
* Decode the tables info part of a notify tables request. | ||
* | ||
* @param {Object} message the message object partially initialized | ||
@@ -598,17 +836,31 @@ * @param {Array} tokens the table infos part of the message already tokenized | ||
message.tableInfos = []; | ||
for (i = 0; i < tokens.length; i = i + 14) { | ||
tableInfo = {}; | ||
tableInfo.winIndex = protocol.decodeInteger(tokens[i + 1]); | ||
tableInfo.pubModes = protocol.decodePubModes(tokens[i + 3]); | ||
tableInfo.groupName = protocol.decodeString(tokens[i + 5]); | ||
tableInfo.schemaName = protocol.decodeString(tokens[i + 7]); | ||
tableInfo.firstItemIndex = protocol.decodeInteger(tokens[i + 9]); | ||
tableInfo.lastItemIndex = protocol.decodeInteger(tokens[i + 11]); | ||
tableInfo.selector = protocol.decodeString(tokens[i + 13]); | ||
while (tokens.length >= 14) { | ||
tableInfo = readTableInfo(tokens); | ||
message.tableInfos.push(tableInfo); | ||
} | ||
tokens = tokens.slice(14); | ||
} | ||
} | ||
/** | ||
* Decode a table info part of a notify tables or notify MPN subscription request. | ||
* | ||
* @param {Array} tokens the table info part of the message already tokenized | ||
* @return {Object} the decoded table info | ||
* @private | ||
*/ | ||
function readTableInfo(tokens, skipSelector) { | ||
var tableInfo = {}; | ||
tableInfo.winIndex = protocol.decodeInteger(tokens[1]); | ||
tableInfo.pubModes = protocol.decodePubModes(tokens[3]); | ||
tableInfo.groupName = protocol.decodeString(tokens[5]); | ||
tableInfo.schemaName = protocol.decodeString(tokens[7]); | ||
tableInfo.firstItemIndex = protocol.decodeInteger(tokens[9]); | ||
tableInfo.lastItemIndex = protocol.decodeInteger(tokens[11]); | ||
if (!skipSelector) | ||
tableInfo.selector = protocol.decodeString(tokens[13]); | ||
return tableInfo; | ||
} | ||
exports.MetadataReader = function() { | ||
return new protocol.StreamReader(read); | ||
} |
@@ -28,4 +28,9 @@ /* | ||
* Metadata provider constructor.<br> | ||
* The created object allows you to interact with Lightstreamer Server through | ||
* the Adapter Remoting Infrastructure protocol as a Remote Metadata Adapter. | ||
* See the ARI Protocol documentation for details on the request and response | ||
* messages.<br> | ||
* This object extends the EventEmitter object and emits the following events: | ||
* <ul> | ||
* <li>init: function(request, response) {}</li> | ||
* <li>getItemData: function(request, response) {}</li> | ||
@@ -42,2 +47,5 @@ * <li>getUserItemData: function(request, response) {}</li> | ||
* <li>notifyTablesClose: function(request, response) {}</li> | ||
* <li>notifyMpnDeviceAccess: function(request, response) {}</li> | ||
* <li>notifyMpnSubscriptionActivation: function(request, response) {}</li> | ||
* <li>notifyMpnDeviceTokenChange: function(request, response) {}</li> | ||
* </ul> | ||
@@ -50,2 +58,3 @@ * The response argument is a MetadataResponse object and one of its methods, | ||
* <ul> | ||
* <li>init: {parameters: {<name 1>: <value 1> ... <name n>: <value n>}}</li> | ||
* <li>getItemData: {itemNames: [<item name 1> ... <item name n>]}</li> | ||
@@ -67,11 +76,53 @@ * <li>getUserItemData: {userName: <username>, itemNames: [<item name 1> ... <item name n>]}</li> | ||
* selector: <selector>}, ...]}</li> | ||
* <li>notifyTablesClose: {sessionId: <session id>, } | ||
* <li>notifyTablesClose: {sessionId: <session id>, | ||
* tableInfos: [{winIndex: <win index>, pubModes: <publish mode>, groupName: <group name>, | ||
* schemaName: <schema name>, firstItemIndex: <first index>, lastItemIndex: <last index>, | ||
* selector: <selector>}, ...]}</li> | ||
* <li>notifyMpnDeviceAccess: {userName: <username>, | ||
* device: {mpnPlatformType: <MPN platform type>, applicationId: <application ID>, deviceToken: <device token>}}</li> | ||
* <li>notifyMpnSubscriptionActivation: {userName: <username>, sessionId: <session id>, | ||
* tableInfo: {winIndex: <win index>, pubModes: <publish mode>, groupName: <group name>, | ||
* schemaName: <schema name>, firstItemIndex: <first index>, lastItemIndex: <last index>, selector: <selector>}, | ||
* mpnSubscription: {device: {mpnPlatformType: <MPN platform type>, applicationId: <application ID>, deviceToken: <device token>}, | ||
* trigger: <trigger expression>, <br/> | ||
* <ul> | ||
* <li>if <i>device.mpnPlatformType</i> is "A", the subscription is for <i>APNS</i> and is composed of these additional data:<br/> | ||
* sound: <sound name>, badge: <icon badge>, | ||
* localizedActionKey: <localized action key>, launchImage: <launch image name>, | ||
* format: <notification text format>, localizedFormatKey: <localized text format key>, | ||
* localizedFormatArguments: [<localized text format argument>, ...], customData: {<custom data key>: <custom data value>, ...}}}</li> | ||
* <li>if <i>device.mpnPlatformType</i> is "G", the subscription is for <i>GCM</i> and is composed of these additional data:<br/> | ||
* collapseKey: <collapse key>, data: {<data key>: <data value>, ...}, | ||
* delayWhileIdle: <delay while idle flag>, timeToLive: <time to live value>}}</li> | ||
* </ul></li> | ||
* <li>notifyMpnDeviceTokenChange: {userName: <username>, | ||
* device: {mpnPlatformType: <MPN platform type>, applicationId: <application ID>, deviceToken: <device token>}, | ||
* newDeviceToken: <new device token>}</li> | ||
* </ul> | ||
* When the handler for some event is not supplied, a default response is provided; | ||
* some default responses can be configured with the optional constructor parameters. | ||
* The getItems and getSchema events are handler in a way similar to the | ||
* LiteralBasedProvider supplied with the Java in-process Adapter SDK.<br/> | ||
* To resume the default behavior: | ||
* <ul> | ||
* <li>init: does nothing</li> | ||
* <li>getItemData: for each item returns the configured distinctSnapLen, minSourceFreq, and itemAllowedModes</li> | ||
* <li>getUserItemData: for each item returns the configured allowedBufferSize, allowedMaxItemFreq, and userAllowedModes</li> | ||
* <li>getSchema: reads the supplied schemaName as a space-separated list of field names and returns an array of such field names</li> | ||
* <li>getItems: reads the supplied groupName as a space-separated list of item names and returns an array of such item names</li> | ||
* <li>notifyUser: returns the configured maxBandwidth and notifyTables (hence accepts the user)</li> | ||
* <li>notifyUserAuth: returns the configured maxBandwidth and notifyTables (hence accepts the user)</li> | ||
* <li>notifyUserMessage: does nothing (hence accepts but ignores the message)</li> | ||
* <li>notifyNewSession: does nothing (hence accepts the session)</li> | ||
* <li>notifySessionClose: does nothing</li> | ||
* <li>notifyNewTables: does nothing (hence accepts the tables)</li> | ||
* <li>notifyTablesClose: does nothing</li> | ||
* <li>notifyMpnDeviceAccess: does nothing (hence allows the access)</li> | ||
* <li>notifyMpnSubscriptionActivation: does nothing (hence accepts the activation)</li> | ||
* <li>notifyMpnDeviceTokenChange: does nothing (hence accepts the change)</li> | ||
* </ul> | ||
* | ||
* @class | ||
* @param {Stream} stream the stream channel to the remote LS proxy adapter | ||
* @param {Object} [params] optional parameter used to by the default request handlers. By default | ||
* @param {Object} [params] optional parameters used by the default request handlers. By default | ||
* <ul> | ||
@@ -83,2 +134,3 @@ * <li>maxBandwidth: 0.0</li> | ||
* <li>itemAllowedModes: {raw: true, merge: true, distinct: true, command: true}</li> | ||
* <li>userAllowedModes: {raw: true, merge: true, distinct: true, command: true}</li> | ||
* <li>allowedMaxItemFreq: 0.0</li> | ||
@@ -94,22 +146,25 @@ * <li>allowedBufferSize: 0</li> | ||
var maxBandwidth = parseFloat(params['maxBandwidth']) || 0.0; | ||
var maxBandwidth = parseFloat(params['maxBandwidth']) || 0.0; | ||
var notifyTables = params['notifyTables'] || false; | ||
var notifyTables = params['notifyTables'] || false; | ||
var minSourceFreq = parseFloat(params['minSourceFreq']) || 0.0; | ||
var minSourceFreq = parseFloat(params['minSourceFreq']) || 0.0; | ||
var distinctSnapLen = parseInt(params['distinctSnapLen']) || 0; | ||
var distinctSnapLen = parseInt(params['distinctSnapLen']) || 0; | ||
var itemAllowedModes = params['itemAllowedModes'] || | ||
{raw: true, merge: true, distinct: true, command: true}; | ||
{raw: true, merge: true, distinct: true, command: true}; | ||
var allowedMaxItemFreq = parseFloat(params['allowedMaxItemFreq']) || 0.0; | ||
var allowedMaxItemFreq = parseFloat(params['allowedMaxItemFreq']) || 0.0; | ||
var allowedBufferSize = parseInt(params['allowedBufferSize']) || 0; | ||
var allowedBufferSize = parseInt(params['allowedBufferSize']) || 0; | ||
var userAllowedModes = params['userAllowedModes'] || | ||
{raw: true, merge: true, distinct: true, command: true}; | ||
{raw: true, merge: true, distinct: true, command: true}; | ||
var reader = new MetadataReader(); | ||
// init message expected | ||
var initPending = true; | ||
// Initialize the stream encoding and the data callback | ||
@@ -121,3 +176,3 @@ stream.setEncoding("utf8"); | ||
* Callback for the incoming data from the stream | ||
* | ||
* | ||
* @private | ||
@@ -127,6 +182,7 @@ */ | ||
var message; | ||
reader.parse(data); | ||
reader.parse(data, initPending); | ||
initPending = false; | ||
while (!reader.isEmpty()) { | ||
message = reader.pop(); | ||
// console.log("IN MESSAGE: " + inspect(messages[i])); | ||
// console.log("IN MESSAGE: " + inspect(message)); | ||
// Check if there are listeners attached to the event | ||
@@ -147,6 +203,9 @@ // otherwise falls back to the default handler | ||
* logic when necessary | ||
* | ||
* | ||
* @private | ||
*/ | ||
defHandlers = { | ||
'init' : function(message) { | ||
stream.write(proto.writeInit(message.id)); | ||
}, | ||
'getItemData' : function(message) { | ||
@@ -210,2 +269,11 @@ // Build the response using the default configuration | ||
stream.write(proto.writeNotifyTablesClose(message.id)); | ||
}, | ||
'notifyMpnDeviceAccess' : function(message) { | ||
stream.write(proto.writeNotifyMpnDeviceAccess(message.id)); | ||
}, | ||
'notifyMpnSubscriptionActivation' : function(message) { | ||
stream.write(proto.writeNotifyMpnSubscriptionActivation(message.id)); | ||
}, | ||
'notifyMpnDeviceTokenChange' : function(message) { | ||
stream.write(proto.writeNotifyMpnDeviceTokenChange(message.id)); | ||
} | ||
@@ -221,2 +289,9 @@ }; | ||
handlers = { | ||
'init' : function(message) { | ||
var response = new MetadataResponse( | ||
stream, message, | ||
proto.writeInit, | ||
proto.writeInitException); | ||
that.emit('init', message, response); | ||
}, | ||
'getItemData' : function(message) { | ||
@@ -227,3 +302,3 @@ var response = new MetadataResponse( | ||
proto.writeGetItemDataException); | ||
that.emit('getItemData', message, response); | ||
that.emit('getItemData', message, response); | ||
}, | ||
@@ -235,3 +310,3 @@ 'notifyUser' : function(message) { | ||
proto.writeNotifyUserException); | ||
that.emit('notifyUser', message, response); | ||
that.emit('notifyUser', message, response); | ||
}, | ||
@@ -243,3 +318,3 @@ 'notifyUserAuth' : function(message) { | ||
proto.writeNotifyUserAuthException); | ||
that.emit('notifyUserAuth', message, response); | ||
that.emit('notifyUserAuth', message, response); | ||
}, | ||
@@ -251,3 +326,3 @@ 'getSchema' : function(message) { | ||
proto.writeGetSchemaException); | ||
that.emit('getSchema', message, response); | ||
that.emit('getSchema', message, response); | ||
}, | ||
@@ -259,3 +334,3 @@ 'getItems' : function(message) { | ||
proto.writeGetItemsException); | ||
that.emit('getItems', message, response); | ||
that.emit('getItems', message, response); | ||
}, | ||
@@ -267,3 +342,3 @@ 'getUserItemData' : function(message) { | ||
proto.writeGetUserItemDataException); | ||
that.emit('getUserItemData', message, response); | ||
that.emit('getUserItemData', message, response); | ||
}, | ||
@@ -275,3 +350,3 @@ 'notifyUserMessage' : function(message) { | ||
proto.writeNotifyUserMessageException); | ||
that.emit('notifyUserMessage', message, response); | ||
that.emit('notifyUserMessage', message, response); | ||
}, | ||
@@ -283,3 +358,3 @@ 'notifyNewSession' : function(message) { | ||
proto.writeNotifyNewSessionException); | ||
that.emit('notifyNewSession', message, response); | ||
that.emit('notifyNewSession', message, response); | ||
}, | ||
@@ -291,3 +366,3 @@ 'notifySessionClose' : function(message) { | ||
proto.writeNotifySessionCloseException); | ||
that.emit('notifySessionClose', message, response); | ||
that.emit('notifySessionClose', message, response); | ||
}, | ||
@@ -299,3 +374,3 @@ 'notifyNewTables' : function(message) { | ||
proto.writeNotifyNewTablesException); | ||
that.emit('notifyNewTables', message, response); | ||
that.emit('notifyNewTables', message, response); | ||
}, | ||
@@ -307,4 +382,25 @@ 'notifyTablesClose' : function(message) { | ||
proto.writeNotifyTablesCloseException); | ||
that.emit('notifyTablesClose', message, response); | ||
} | ||
that.emit('notifyTablesClose', message, response); | ||
}, | ||
'notifyMpnDeviceAccess' : function(message) { | ||
var response = new MetadataResponse( | ||
stream, message, | ||
proto.writeNotifyMpnDeviceAccess, | ||
proto.writeNotifyMpnDeviceAccessException); | ||
that.emit('notifyMpnDeviceAccess', message, response); | ||
}, | ||
'notifyMpnSubscriptionActivation' : function(message) { | ||
var response = new MetadataResponse( | ||
stream, message, | ||
proto.writeNotifyMpnSubscriptionActivation, | ||
proto.writeNotifyMpnSubscriptionActivationException); | ||
that.emit('notifyMpnSubscriptionActivation', message, response); | ||
}, | ||
'notifyMpnDeviceTokenChange' : function(message) { | ||
var response = new MetadataResponse( | ||
stream, message, | ||
proto.writeNotifyMpnDeviceTokenChange, | ||
proto.writeNotifyMpnDeviceTokenChangeException); | ||
that.emit('notifyMpnDeviceTokenChange', message, response); | ||
}, | ||
}; | ||
@@ -315,3 +411,3 @@ | ||
* | ||
* @return Object the stream | ||
* @return Object the stream | ||
*/ | ||
@@ -326,3 +422,3 @@ function getStream() { | ||
}; | ||
// The object extends the standard EventEmitter | ||
@@ -356,7 +452,9 @@ that.__proto__ = EventEmitter.prototype; | ||
* <ul> | ||
* <li>init: success()</li> | ||
* <li>getItemData: success([{distinctSnapLen: <distinct snapshot length>, minSourceFreq: <min source frequency>, | ||
* allowedModes: {raw: <raw allowed>, merge: <merge allowed>, distinct: <distinct allowed>, command: <command allowed>}}, ...])</li> | ||
* <li>getUserItemData: {userName: <username>, itemNames: [<item name 1> ... <item name n>]}</li> | ||
* <li>getSchema: {userName: <username>, groupName: <group name>, schemaName: <schema name>, sessionId: <session id>}</li> | ||
* <li>getItems: {userName: <username>, groupName: <group name>, sessionId: <session id>}</li> | ||
* <li>getUserItemData: success([{allowedBufferSize: <allowed buffer size>, allowedMaxItemFreq: <allowed max item frequency>}, | ||
* allowedModes: {raw: <raw allowed for user>, merge: <merge allowed for user>, distinct: <distinct allowed for user>, command: <command allowed for user>}}, ...])</li> | ||
* <li>getSchema: success([<field 1>, <field 2>, ...])</li> | ||
* <li>getItems: success([<item 1>, <item 2>, ...])</li> | ||
* <li>notifyUser: success(<allowed max bandwidth>, <wants table notifications>)</li> | ||
@@ -369,2 +467,5 @@ * <li>notifyUserAuth: success(<allowed max bandwidth>, <wants table notifications>)</li> | ||
* <li>notifyTablesClose: success()</li> | ||
* <li>notifyMpnDeviceAccess: success()</li> | ||
* <li>notifyMpnSubscriptionActivation: success()</li> | ||
* <li>notifyMpnDeviceTokenChange: success()</li> | ||
* </ul> | ||
@@ -379,3 +480,3 @@ */ | ||
data = writeSuccess.apply(that, args); | ||
stream.write(data); | ||
stream.write(data); | ||
} | ||
@@ -387,2 +488,3 @@ | ||
* <ul> | ||
* <li>init: "metadata"</li> | ||
* <li>getItemData: none</li> | ||
@@ -397,4 +499,7 @@ * <li>getUserItemData: none</li> | ||
* <li>notifySessionClose: "notification"</li> | ||
* <li>notifyNewTables: "credits" or "notification</li> | ||
* <li>notifyNewTables: "credits" or "notification"</li> | ||
* <li>notifyTablesClose: "notification"</li> | ||
* <li>notifyMpnDeviceAccess: "credits" or "notification"</li> | ||
* <li>notifyMpnSubscriptionActivation: "credits" or "notification"</li> | ||
* <li>notifyMpnDeviceTokenChange: "credits" or "notification"</li> | ||
* </ul> | ||
@@ -409,3 +514,3 @@ * | ||
message.id, exceptionMessage, exceptionType); | ||
stream.write(data); | ||
stream.write(data); | ||
} | ||
@@ -418,3 +523,3 @@ | ||
isUsed = true; | ||
} | ||
} | ||
} | ||
@@ -421,0 +526,0 @@ |
@@ -25,3 +25,3 @@ /* | ||
/** | ||
* Concatenates the arguments in a pipe-delimited string | ||
* Concatenates the arguments in a pipe-delimited string | ||
* | ||
@@ -36,3 +36,3 @@ * @return {String} the pipe-delimited string | ||
/** | ||
* Concatenates the array in a pipe-delimited string | ||
* Concatenates the array in a pipe-delimited string | ||
* | ||
@@ -94,3 +94,3 @@ * @param {Array} tokens to be concatenated | ||
* | ||
* @param {String} message pipe-delimited string | ||
* @param {String} message pipe-delimited string | ||
* @return {Array} the fields contained in the string | ||
@@ -107,3 +107,3 @@ * @private | ||
* | ||
* @param {String} string pipe-delimited string | ||
* @param {String} string pipe-delimited string | ||
* @return {Array} publish mode flags | ||
@@ -121,9 +121,9 @@ * @private | ||
if (decStr.charAt(i) === modeValues.RAW) { | ||
mode.raw = true; | ||
mode.raw = true; | ||
} else if (decStr.charAt(i) === modeValues.MERGE) { | ||
mode.merge = true; | ||
mode.merge = true; | ||
} else if (decStr.charAt(i) === modeValues.DISTINCT) { | ||
mode.distinct = true; | ||
mode.distinct = true; | ||
} else if (decStr.charAt(i) === modeValues.COMMAND) { | ||
mode.command = true; | ||
mode.command = true; | ||
} else { | ||
@@ -143,3 +143,3 @@ throw new Error('Invalid mode "' + decStr.charAt(i) + '"'); | ||
* @param {Array} modes publish mode flags | ||
* @return {String} pipe-delimited string | ||
* @return {String} pipe-delimited string | ||
* @private | ||
@@ -169,3 +169,3 @@ */ | ||
* Encodes a string according to the ARI protocol. | ||
* | ||
* | ||
* @param {String} string input | ||
@@ -176,10 +176,11 @@ * @return {String} output | ||
function encodeString(string) { | ||
if (string) { | ||
return encodeURIComponent(string) | ||
.replace(/%20/g, "+"); | ||
} else if (string === "") { | ||
return values.EMPTY; | ||
} else { | ||
return values.NULL; | ||
} | ||
//it actually accepts any kind of object as input | ||
if (string === null) { | ||
return values.NULL; | ||
} else if (string === "") { | ||
return values.EMPTY; | ||
} else {//0 false undefined NaN will pass from here | ||
return encodeURIComponent(string) | ||
.replace(/%20/g, "+"); | ||
} | ||
} | ||
@@ -189,3 +190,3 @@ | ||
* Decodes a string according to the ARI protocol. | ||
* | ||
* | ||
* @param {String} string input | ||
@@ -197,3 +198,3 @@ * @return {String} output | ||
if (string === values.EMPTY) { | ||
return ""; | ||
return ""; | ||
} else if (string === values.NULL) { | ||
@@ -209,3 +210,3 @@ return null; | ||
* Decodes an integer according to the ARI protocol. | ||
* | ||
* | ||
* @param {String} string input | ||
@@ -225,3 +226,3 @@ * @return {Number} output | ||
* Encodes an integer according to the ARI protocol. | ||
* | ||
* | ||
* @param {Number} value input | ||
@@ -233,5 +234,5 @@ * @return {String} output | ||
if (value === null) { | ||
return values.NULL; | ||
return values.NULL; | ||
} else if (!isNaN(value) && parseInt(value)==value) { | ||
return value + ""; | ||
return value + ""; | ||
} else { | ||
@@ -244,3 +245,3 @@ throw new Error('Invalid integer value "' + value + '"'); | ||
* Encodes a float according to the ARI protocol. | ||
* | ||
* | ||
* @param {Number} value input | ||
@@ -252,5 +253,5 @@ * @return {String} output | ||
if (value === null) { | ||
return values.NULL; | ||
return values.NULL; | ||
} else if (!isNaN(value)) { | ||
return value + ""; | ||
return value + ""; | ||
} else { | ||
@@ -263,3 +264,3 @@ throw new Error('Invalid double value "' + value + '"'); | ||
* Encodes a boolean according to the ARI protocol. | ||
* | ||
* | ||
* @param {Boolean} bool input | ||
@@ -275,3 +276,3 @@ * @return {String} output | ||
* Encodes a metadata exception type. | ||
* | ||
* | ||
* @param {Boolean} type input | ||
@@ -282,3 +283,5 @@ * @return {String} output | ||
function encodeMetadataException(type) { | ||
if (type === "access") { | ||
if (type === "metadata") { | ||
return exceptions.METADATA; | ||
} else if (type === "access") { | ||
return exceptions.ACCESS; | ||
@@ -302,3 +305,3 @@ } else if (type === "credits") { | ||
* Generates a timestamp. | ||
* | ||
* | ||
* @return {String} time millis | ||
@@ -326,3 +329,3 @@ * @private | ||
*/ | ||
function parse(data) { | ||
function parse(data, initExpected) { | ||
var lines, i, last; | ||
@@ -334,3 +337,3 @@ data = tail + data; | ||
for (i = 0; i < last; i++) { | ||
messages.push(read(lines[i])); | ||
messages.push(read(lines[i], initExpected)); | ||
} | ||
@@ -346,3 +349,3 @@ tail = lines[lines.length - 1]; | ||
} | ||
/** | ||
@@ -349,0 +352,0 @@ * Return if it has no more messages |
{ | ||
"name": "lightstreamer-adapter", | ||
"version": "1.0.2", | ||
"description": "This package includes the resources needed to write Data Adapters and Metadata Adapters for Lightstreamer Server in a node environment. The adapters will run in a separate process, communicating with the Server through the Adapter Remoting Infrastructure.", | ||
"version": "1.3.1", | ||
"description": "This package includes the resources needed to write Data Adapters and Metadata Adapters for Lightstreamer Server in a Node.js environment. The adapters will run in a separate process, communicating with the Server through the Adapter Remoting Infrastructure.", | ||
"keywords": [ | ||
@@ -12,21 +12,24 @@ "lightstreamer", | ||
], | ||
"homepage": "http://www.lightstreamer.com", | ||
"repository" : { | ||
"type" : "git", | ||
"url" : "http://github.com/Weswit/Lightstreamer-lib-node-adapter.git" | ||
"repository" : { | ||
"type" : "git", | ||
"url" : "http://github.com/Weswit/Lightstreamer-lib-node-adapter.git" | ||
}, | ||
"bugs": "http://forum.lightstreamer.com", | ||
"author": { | ||
"bugs": { | ||
"url" : "http://forum.lightstreamer.com/", | ||
"email" : "support@lightstreamer.com" | ||
}, | ||
"author": { | ||
"name" : "Weswit Srl", | ||
"email" : "support@lightstreamer.com" | ||
}, | ||
"files": ["README.md","index.js","architecture.png","CHANGELOG.md","LICENSE","lib","test"], | ||
"files": ["README.md","architecture.png","index.js","CHANGELOG.md","LICENSE","lib","test"], | ||
"main": "index", | ||
"directories": { | ||
@@ -39,3 +42,3 @@ "lib": "./lib" | ||
], | ||
"dependencies": {}, | ||
@@ -45,2 +48,2 @@ "devDependencies": { | ||
} | ||
} | ||
} |
@@ -1,2 +0,2 @@ | ||
# Lightstreamer SDK for Node Adapters 1.0.2 # | ||
# Lightstreamer SDK for Node Adapters 1.3.1 # | ||
@@ -16,5 +16,4 @@ This package includes the resources needed to write Data Adapters and Metadata Adapters for [Lightstreamer](http://www.lightstreamer.com/ "Lightstreamer") Server in a [Node.js](http://nodejs.org/ "Node.js") environment. | ||
1. Download and install Lightstreamer | ||
2. Go to the "adapters" folder of your Lightstreamer Server installation. Create a new folder to deploy the remote adapters in, let's call it "NodeAdapter", and a "lib" folder inside it. | ||
3. Copy the "ls-proxy-adapters.jar" file from "Lightstreamer/DOCS-SDKs/sdk_adapter_remoting_infrastructure/lib" in the newly created "lib" folder. | ||
4. Create an "adapters.xml" file inside the "NodeAdapter" folder and use the following contents (this is an example configuration, you can modify it to your liking by following the adapter remoting infrastructure documentation): | ||
2. Go to the "adapters" folder of your Lightstreamer Server installation. Create a new folder to deploy the remote adapters in, let's call it "NodeAdapter". | ||
3. Create an "adapters.xml" file inside the "NodeAdapter" folder and use the following contents (this is an example configuration, you can modify it to your liking by following the adapter remoting infrastructure documentation): | ||
```xml | ||
@@ -24,3 +23,4 @@ <?xml version="1.0"?> | ||
<metadata_provider> | ||
<adapter_class>com.lightstreamer.adapters.remote.metadata.RobustNetworkedMetadataProvider</adapter_class> | ||
<adapter_class>ROBUST_PROXY_FOR_REMOTE_ADAPTER</adapter_class> | ||
<classloader>log-enabled</classloader> | ||
<param name="request_reply_port">8003</param> | ||
@@ -30,3 +30,4 @@ <param name="timeout">36000000</param> | ||
<data_provider> | ||
<adapter_class>com.lightstreamer.adapters.remote.data.RobustNetworkedDataProvider</adapter_class> | ||
<adapter_class>ROBUST_PROXY_FOR_REMOTE_ADAPTER</adapter_class> | ||
<classloader>log-enabled</classloader> | ||
<param name="request_reply_port">8001</param> | ||
@@ -39,5 +40,5 @@ <param name="notify_port">8002</param> | ||
5. Take note of the ports configured in the adapters.xml file as those are needed to write the remote part of the adapters. | ||
4. Take note of the ports configured in the adapters.xml file as those are needed to write the remote part of the adapters. | ||
### Write The Adapters ### | ||
### Write the Adapters ### | ||
Create a .js file, let's call it "adapters.js" | ||
@@ -91,3 +92,3 @@ | ||
### Connect A Client ### | ||
### Connect a Client ### | ||
```js | ||
@@ -98,6 +99,6 @@ var lsClient = new LightstreamerClient(LIGHTSTREAMER_SERVER_HOST,"PROXY_NODE"); | ||
note that the "PROXY_NODE" string is taken from the adapters.xml | ||
Note that the "PROXY_NODE" string is taken from the adapters.xml | ||
### API reference ### | ||
At the time of writing API docs are not deployed anywhere so you have to generate it yourself (see below how to do so). We will deploy them somewhere online at some point. | ||
### API Reference ### | ||
http://www.lightstreamer.com/docs/adapter_nodejs_api/index.html | ||
@@ -109,3 +110,3 @@ ## Develop ## | ||
We want to write code to use our package by requiring "lightstreamer-adapter" without having to specify the full path. | ||
On the other hand during development we do not want to install the package from the repo as we want in fact test it before put it on the repo for everyone else to enjoy. | ||
On the other hand, during development, we do not want to install the package from the repo as we want to, in fact, test it before putting it on the repo for everyone else to enjoy. | ||
So: | ||
@@ -125,3 +126,3 @@ | ||
NOTE: you can't globally link the package (using -g) to make it available everywhere | ||
NOTE: You can't globally link the package (using -g) to make it available everywhere | ||
@@ -134,3 +135,3 @@ ### Testing ### | ||
the -g unit will install it on the system instead of installing it locally, you may remove it if you prefer a local installation | ||
The -g unit will install it on the system instead of installing it locally; you may remove it if you prefer a local installation | ||
@@ -155,6 +156,7 @@ Go to the test folder and run the following commands | ||
## See Also ## | ||
* [Adapter Remoting Infrastructure Network Protocol Specification](http://www.lightstreamer.com/latest/Lightstreamer_Allegro-Presto-Vivace_5_1_Colosseo/Lightstreamer/DOCS-SDKs/sdk_adapter_remoting_infrastructure/doc/ARI%20Protocol.pdf "Lightstreamer ARI protocol") | ||
* [Adapter Remoting Infrastructure Network Protocol Specification](http://www.lightstreamer.com/docs/adapter_generic_base/ARI%20Protocol.pdf "Lightstreamer ARI protocol") | ||
* [Lightstreamer Chat Demo adapter for Node](https://github.com/Weswit/Lightstreamer-example-Chat-adapter-node "Lightstreamer Chat Demo adapter for Node") | ||
## Lightstreamer Compatibility Notes ## | ||
Compatible with Adapter Remoting Infrastructure since 1.4.3 | ||
Compatible with Adapter Remoting Infrastructure since 1.7 | ||
- For a version of this library compatible with Adapter Remoting Infrastructure version 1.4.3, please refer to [this tag](https://github.com/Weswit/Lightstreamer-lib-node-adapter/tree/version-1.0.2). |
@@ -21,5 +21,15 @@ /* | ||
exports.dataReads = { | ||
"Read a valid init" : function(test) { | ||
var reader = new DataReader(); | ||
reader.parse("FAKEID|DPI|S|P1|S|V1|S|P2|S|V2\r\n", true); | ||
var msg = reader.pop(); | ||
test.equal(msg.verb, "init"); | ||
test.equal(msg.id, "FAKEID"); | ||
test.equal(msg.parameters["P1"], "V1"); | ||
test.equal(msg.parameters["P2"], "V2"); | ||
test.done(); | ||
}, | ||
"Read a valid subscribe" : function(test) { | ||
var reader = new DataReader(); | ||
reader.parse("FAKEID|SUB|S|An+Item+Name\r\n"); | ||
reader.parse("FAKEID|SUB|S|An+Item+Name\r\n", false); | ||
var msg = reader.pop(); | ||
@@ -33,3 +43,3 @@ test.equal(msg.verb, "subscribe"); | ||
var reader = new DataReader(); | ||
reader.parse("FAKEID|USB|S|An+Item+Name\n"); | ||
reader.parse("FAKEID|USB|S|An+Item+Name\n", false); | ||
var msg = reader.pop(); | ||
@@ -44,3 +54,3 @@ test.equal(msg.verb, "unsubscribe"); | ||
var reader = new DataReader(); | ||
reader.parse("FAKEID|WHAT|S|An+Item+Name\n"); | ||
reader.parse("FAKEID|WHAT|S|An+Item+Name\n", false); | ||
}, Error); | ||
@@ -52,3 +62,3 @@ test.done(); | ||
var reader = new DataReader(); | ||
reader.parse("FAKEID|WHAT|An+Item+Name\r\n"); | ||
reader.parse("FAKEID|WHAT|An+Item+Name\r\n", false); | ||
}, Error); | ||
@@ -60,2 +70,17 @@ test.done(); | ||
exports.dataWrites = { | ||
"Init write" : function(test) { | ||
var msg = dataProto.writeInit("FAKEID"); | ||
test.equal(msg, "FAKEID|DPI|V\n"); | ||
test.done(); | ||
}, | ||
"Init write with exception" : function(test) { | ||
var msg = dataProto.writeInitException("FAKEID","An exception"); | ||
test.equal(msg, "FAKEID|DPI|E|An+exception\n"); | ||
test.done(); | ||
}, | ||
"Init write with data exception" : function(test) { | ||
var msg = dataProto.writeInitException("FAKEID","An exception","data"); | ||
test.equal(msg, "FAKEID|DPI|ED|An+exception\n"); | ||
test.done(); | ||
}, | ||
"Subscribe write" : function(test) { | ||
@@ -101,3 +126,9 @@ var msg = dataProto.writeSubscribe("FAKEID"); | ||
}, | ||
"Clear snapshot write" : function(test) { | ||
var msg = dataProto.writeClearSnapshot("FAKEID","AnItemId"); | ||
test.equal(msg.substring(13), "|CLS|S|AnItemId|S|FAKEID\n"); | ||
test.done(); | ||
}, | ||
"Write an update by hash" : function(test) { | ||
var fake = ""; | ||
var msg = dataProto.writeUpdate("FAKEID","AnItemName", true, | ||
@@ -109,7 +140,12 @@ { | ||
"field4" : 12.4, | ||
"field5" : true | ||
"field5" : true, | ||
"field6" : 0, | ||
"field7" : NaN, | ||
"field8" : fake.undef, //fake does not have an undef property | ||
"field9" : false | ||
}); | ||
test.equal(msg.substring(13), "|UD3|S|AnItemName|S|FAKEID|B|1|" + | ||
"S|field1|S|A+string|S|field2|S|$|S|field3|S|#|" + | ||
"S|field4|S|12.4|S|field5|S|true\n"); | ||
"S|field4|S|12.4|S|field5|S|true|S|field6|S|0|" + | ||
"S|field7|S|NaN|S|field8|S|undefined|S|field9|S|false\n"); | ||
test.done(); | ||
@@ -116,0 +152,0 @@ } |
@@ -21,3 +21,3 @@ /* | ||
exports.tests = { | ||
setUp: function (callback) { | ||
setUp: function (callback) { | ||
this.reqRespStream = new TestStream(); | ||
@@ -28,3 +28,50 @@ this.notifyStream = new TestStream(); | ||
}, | ||
"Subscribe with snapshot" : function(test) { | ||
"Initialization" : function(test) { | ||
var reqRespStream = this.reqRespStream; | ||
test.expect(3); | ||
this.dataProvider.on('init', function(message, response) { | ||
test.equal(message.parameters["P1"], "V1"); | ||
test.equal(message.parameters["P2"], "V2"); | ||
response.success(); | ||
test.equal(reqRespStream.popTestData(), "ID0|DPI|V\n"); | ||
test.done(); | ||
}); | ||
this.reqRespStream.pushTestData("ID0|DPI|S|P1|S|V1|S|P2|S|V2\r\n"); | ||
}, | ||
"Failed initialization" : function(test) { | ||
var reqRespStream = this.reqRespStream; | ||
test.expect(1); | ||
this.dataProvider.on('init', function(message, response) { | ||
response.error("An exception", "data"); | ||
test.equal(reqRespStream.popTestData(), "ID0|DPI|ED|An+exception\n"); | ||
test.done(); | ||
}); | ||
this.reqRespStream.pushTestData("ID0|DPI\r\n"); | ||
}, | ||
"Missing initialization" : function(test) { | ||
var reqRespStream = this.reqRespStream; | ||
test.expect(1); | ||
this.dataProvider.on('init', function(message, response) { | ||
response.success(); | ||
test.equal(reqRespStream.popTestData(), "ID0|DPI|V\n"); | ||
}); | ||
test.throws(function () { | ||
this.reqRespStream.pushTestData("FAKEID|SUB|S|An+Item+Name\r\n"); | ||
}, Error); | ||
test.done(); | ||
}, | ||
"Late initialization" : function(test) { | ||
var reqRespStream = this.reqRespStream; | ||
test.expect(2); | ||
this.dataProvider.on('init', function(message, response) { | ||
response.success(); | ||
test.equal(reqRespStream.popTestData(), "ID0|DPI|V\n"); | ||
}); | ||
this.reqRespStream.pushTestData("ID0|DPI\r\n"); | ||
test.throws(function () { | ||
this.reqRespStream.pushTestData("ID0|DPI\r\n"); | ||
}, Error); | ||
test.done(); | ||
}, | ||
"Subscribe with snapshot" : function(test) { | ||
this.reqRespStream = new TestStream(); | ||
@@ -35,3 +82,3 @@ // we cannot keep the old reqRespStream, because it already has a 'data' handler | ||
var reqRespStream = this.reqRespStream; | ||
test.expect(3); | ||
test.expect(4); | ||
this.dataProvider = new DataProvider( | ||
@@ -45,7 +92,9 @@ this.reqRespStream, this.notifyStream, function(itemName) { | ||
response.success(); | ||
test.equal(reqRespStream.popTestData(), "ID0|DPI|V\n"); | ||
test.equal(reqRespStream.popTestData(), "FAKEID|SUB|V\n"); | ||
test.done(); | ||
}); | ||
this.reqRespStream.pushTestData("ID0|DPI\r\n"); | ||
this.reqRespStream.pushTestData("FAKEID|SUB|S|An+Item+Name\r\n"); | ||
}, | ||
}, | ||
"Subscribe without snapshot" : function(test) { | ||
@@ -58,3 +107,3 @@ this.reqRespStream = new TestStream(); | ||
notifyStream = this.notifyStream; | ||
test.expect(2); | ||
test.expect(3); | ||
this.dataProvider = new DataProvider( | ||
@@ -65,2 +114,3 @@ this.reqRespStream, this.notifyStream, function(itemName) {return false;}); | ||
response.success(); | ||
test.equal(reqRespStream.popTestData(), "ID0|DPI|V\n"); | ||
test.equal(reqRespStream.popTestData(), "FAKEID|SUB|V\n"); | ||
@@ -72,23 +122,28 @@ var data = notifyStream.popTestData(); | ||
this.reqRespStream.pushTestData("ID0|DPI\r\n"); | ||
this.reqRespStream.pushTestData("FAKEID|SUB|S|An+Item+Name\r\n"); | ||
}, | ||
"Failed subscribe" : function(test) { | ||
"Failed subscribe" : function(test) { | ||
var reqRespStream = this.reqRespStream; | ||
test.expect(1); | ||
test.expect(2); | ||
this.dataProvider.on('subscribe', function(itemName, response) { | ||
response.error("An exception", "subscription"); | ||
test.equal(reqRespStream.popTestData(), "ID0|DPI|V\n"); | ||
test.equal(reqRespStream.popTestData(), "FAKEID|SUB|EU|An+exception\n"); | ||
test.done(); | ||
}); | ||
this.reqRespStream.pushTestData("ID0|DPI\r\n"); | ||
this.reqRespStream.pushTestData("FAKEID|SUB|S|An+Item+Name\r\n"); | ||
}, | ||
}, | ||
"Unsubscribe" : function(test) { | ||
var reqRespStream = this.reqRespStream; | ||
test.expect(2); | ||
test.expect(3); | ||
this.dataProvider.on('unsubscribe', function(itemName, response) { | ||
test.equal(itemName, "An Item Name"); | ||
response.success(); | ||
test.equal(reqRespStream.popTestData(), "ID0|DPI|V\n"); | ||
test.equal(reqRespStream.popTestData(), "FAKEID|USB|V\n"); | ||
test.done(); | ||
}); | ||
this.reqRespStream.pushTestData("ID0|DPI\r\n"); | ||
this.reqRespStream.pushTestData("FAKEID|USB|S|An+Item+Name\r\n"); | ||
@@ -101,3 +156,7 @@ }, | ||
var sub1Response; | ||
test.expect(14); | ||
test.expect(15); | ||
dataProvider.on('init', function(message, response) { | ||
response.success(); | ||
test.equal(reqRespStream.popTestData(), "ID0|DPI|V\n"); | ||
}); | ||
dataProvider.on('subscribe', function(itemName, response) { | ||
@@ -147,2 +206,3 @@ subNum++; | ||
}); | ||
this.reqRespStream.pushTestData("ID0|DPI\r\n"); | ||
this.reqRespStream.pushTestData("ID1|SUB|S|item1\n"); | ||
@@ -161,3 +221,7 @@ this.reqRespStream.pushTestData("ID2|USB|S|item1\n"); | ||
var subDelayedResp; | ||
test.expect(16); | ||
test.expect(17); | ||
dataProvider.on('init', function(message, response) { | ||
response.success(); | ||
test.equal(reqRespStream.popTestData(), "ID0|DPI|V\n"); | ||
}); | ||
dataProvider.on('subscribe', function(itemName, response) { | ||
@@ -211,2 +275,3 @@ subNum++; | ||
}); | ||
this.reqRespStream.pushTestData("ID0|DPI\r\n"); | ||
this.reqRespStream.pushTestData("ID1|SUB|S|item1\n"); | ||
@@ -239,2 +304,3 @@ this.reqRespStream.pushTestData("ID2|USB|S|item1\n"); | ||
}); | ||
reqRespStream.pushTestData("ID0|DPI\r\n"); | ||
reqRespStream.pushTestData("FAKEID|SUB|S|An+Item+Name\r\n"); | ||
@@ -250,2 +316,3 @@ }, | ||
"Update by hash" : function(test) { | ||
var fake = ""; | ||
var dataProvider = this.dataProvider, | ||
@@ -264,3 +331,7 @@ reqRespStream = this.reqRespStream, | ||
"field4" : 12.4, | ||
"field5" : true | ||
"field5" : true, | ||
"field6" : 0, | ||
"field7" : NaN, | ||
"field8" : fake.undef, //fake does not have an undef property | ||
"field9" : false | ||
}); | ||
@@ -272,6 +343,8 @@ data = notifyStream.popTestData(); | ||
"S|field1|S|A+string|S|field2|S|$|S|field3|S|#|" + | ||
"S|field4|S|12.4|S|field5|S|true\n"); | ||
"S|field4|S|12.4|S|field5|S|true|S|field6|S|0|" + | ||
"S|field7|S|NaN|S|field8|S|undefined|S|field9|S|false\n"); | ||
test.done(); | ||
}); | ||
reqRespStream.pushTestData("ID0|DPI\r\n"); | ||
reqRespStream.pushTestData("FAKEID|SUB|S|AnItemName\r\n"); | ||
@@ -286,2 +359,39 @@ }, | ||
}, | ||
"Update by hash, then clear snapshot" : function(test) { | ||
var fake = ""; | ||
var dataProvider = this.dataProvider, | ||
reqRespStream = this.reqRespStream, | ||
notifyStream = this.notifyStream; | ||
test.expect(3); | ||
dataProvider.on('subscribe', function(itemName, response) { | ||
response.success(); | ||
dataProvider.update("AnItemName", true, | ||
{ | ||
"field1" : "A string", | ||
"field2" : "", | ||
"field3" : null, | ||
"field4" : 12.4, | ||
"field5" : true, | ||
"field6" : 0, | ||
"field7" : NaN, | ||
"field8" : fake.undef, //fake does not have an undef property | ||
"field9" : false | ||
}); | ||
dataProvider.clearSnapshot("AnItemName"); | ||
data = notifyStream.popTestData(); | ||
test.equal(data.substring(13), "|EOS|S|AnItemName|S|FAKEID\n"); | ||
data = notifyStream.popTestData(); | ||
test.equal(data.substring(13), "|UD3|S|AnItemName|S|FAKEID|B|1|" + | ||
"S|field1|S|A+string|S|field2|S|$|S|field3|S|#|" + | ||
"S|field4|S|12.4|S|field5|S|true|S|field6|S|0|" + | ||
"S|field7|S|NaN|S|field8|S|undefined|S|field9|S|false\n"); | ||
data = notifyStream.popTestData(); | ||
test.equal(data.substring(13), "|CLS|S|AnItemName|S|FAKEID\n"); | ||
test.done(); | ||
}); | ||
reqRespStream.pushTestData("ID0|DPI\r\n"); | ||
reqRespStream.pushTestData("FAKEID|SUB|S|AnItemName\r\n"); | ||
}, | ||
"Subscribe with double success" : function(test) { | ||
@@ -298,2 +408,3 @@ var reqRespStream = this.reqRespStream; | ||
}); | ||
this.reqRespStream.pushTestData("ID0|DPI\r\n"); | ||
this.reqRespStream.pushTestData("FAKEID|SUB|S|An+Item+Name\r\n"); | ||
@@ -312,4 +423,5 @@ }, | ||
}); | ||
this.reqRespStream.pushTestData("ID0|DPI\r\n"); | ||
this.reqRespStream.pushTestData("FAKEID|SUB|S|An+Item+Name\r\n"); | ||
}, | ||
}; |
@@ -21,5 +21,15 @@ /* | ||
exports.metadataReads = { | ||
"Read a valid init" : function(test) { | ||
var reader = new MetadataReader(); | ||
reader.parse("FAKEID|MPI|S|P1|S|V1|S|P2|S|V2\r\n", true); | ||
var msg = reader.pop(); | ||
test.equal(msg.verb, "init"); | ||
test.equal(msg.id, "FAKEID"); | ||
test.equal(msg.parameters["P1"], "V1"); | ||
test.equal(msg.parameters["P2"], "V2"); | ||
test.done(); | ||
}, | ||
"Read a valid get item data" : function(test) { | ||
var reader = new MetadataReader(); | ||
reader.parse("FAKEID|GIT|S|An+Item+Name1|S|An+Item+Name2\r\n"); | ||
reader.parse("FAKEID|GIT|S|An+Item+Name1|S|An+Item+Name2\r\n", false); | ||
var msg = reader.pop(); | ||
@@ -35,3 +45,3 @@ test.equal(msg.verb, "getItemData"); | ||
var reader = new MetadataReader(); | ||
reader.parse("FAKEID|NUS|S|user|S|password|S|header1|S|value+1|S|header+2|S|value+2\r\n"); | ||
reader.parse("FAKEID|NUS|S|user|S|password|S|header1|S|value+1|S|header+2|S|value+2\r\n", false); | ||
var msg = reader.pop(); | ||
@@ -48,3 +58,3 @@ test.equal(msg.verb, "notifyUser"); | ||
var reader = new MetadataReader(); | ||
reader.parse("FAKEID|NUA|S|user|S|password|S|principal|S|header1|S|value+1|S|header+2|S|value+2\r\n"); | ||
reader.parse("FAKEID|NUA|S|user|S|password|S|principal|S|header1|S|value+1|S|header+2|S|value+2\r\n", false); | ||
var msg = reader.pop(); | ||
@@ -62,3 +72,3 @@ test.equal(msg.verb, "notifyUserAuth"); | ||
var reader = new MetadataReader(); | ||
reader.parse("FAKEID|GSC|S|user|S|group|S|schema|S|FAKESESSID\r\n"); | ||
reader.parse("FAKEID|GSC|S|user|S|group|S|schema|S|FAKESESSID\r\n", false); | ||
var msg = reader.pop(); | ||
@@ -75,3 +85,3 @@ test.equal(msg.verb, "getSchema"); | ||
var reader = new MetadataReader(); | ||
reader.parse("FAKEID|GIS|S|user|S|group|S|FAKESESSID\r\n"); | ||
reader.parse("FAKEID|GIS|S|user|S|group|S|FAKESESSID\r\n", false); | ||
var msg = reader.pop(); | ||
@@ -87,3 +97,3 @@ test.equal(msg.verb, "getItems"); | ||
var reader = new MetadataReader(); | ||
reader.parse("FAKEID|GUI|S|user|S|item+1|S|item+2\r\n"); | ||
reader.parse("FAKEID|GUI|S|user|S|item+1|S|item+2\r\n", false); | ||
var msg = reader.pop(); | ||
@@ -100,3 +110,3 @@ test.equal(msg.verb, "getUserItemData"); | ||
var reader = new MetadataReader(); | ||
reader.parse("FAKEID|NUM|S|user|S|FAKESESSID|S|This+is+a+message\r\n"); | ||
reader.parse("FAKEID|NUM|S|user|S|FAKESESSID|S|This+is+a+message\r\n", false); | ||
var msg = reader.pop(); | ||
@@ -112,3 +122,3 @@ test.equal(msg.verb, "notifyUserMessage"); | ||
var reader = new MetadataReader(); | ||
reader.parse("FAKEID|NNS|S|user|S|FAKESESSID|S|prop1|S|val1|S|prop2|S|val2\r\n"); | ||
reader.parse("FAKEID|NNS|S|user|S|FAKESESSID|S|prop1|S|val1|S|prop2|S|val2\r\n", false); | ||
var msg = reader.pop(); | ||
@@ -125,3 +135,3 @@ test.equal(msg.verb, "notifyNewSession"); | ||
var reader = new MetadataReader(); | ||
reader.parse("FAKEID|NSC|S|FAKESESSID\n"); | ||
reader.parse("FAKEID|NSC|S|FAKESESSID\n", false); | ||
var msg = reader.pop(); | ||
@@ -136,3 +146,3 @@ test.equal(msg.verb, "notifySessionClose"); | ||
var inMsg, msg, i; | ||
inMsg = "FAKEID|NNT|S|user|S|FAKESESSID" + | ||
@@ -144,6 +154,6 @@ "|I|1|M|M|S|group1|S|schema1|I|1|I|5|S|#" + | ||
"\n"; | ||
reader.parse(inMsg); | ||
reader.parse(inMsg, false); | ||
msg = reader.pop(); | ||
test.equal(msg.verb, "notifyNewTables"); | ||
@@ -166,3 +176,3 @@ test.equal(msg.id, "FAKEID"); | ||
test.ok(msg.tableInfos[1].pubModes["raw"]); | ||
test.ok(msg.tableInfos[2].pubModes["distinct"]); | ||
@@ -179,3 +189,3 @@ | ||
var inMsg, msg, i; | ||
inMsg = "FAKEID|NTC|S|FAKESESSID" + | ||
@@ -185,6 +195,6 @@ "|I|1|M|M|S|group1|S|schema1|I|1|I|5|S|#" + | ||
"\n"; | ||
reader.parse(inMsg); | ||
reader.parse(inMsg, false); | ||
msg = reader.pop(); | ||
test.equal(msg.verb, "notifyTablesClose"); | ||
@@ -208,2 +218,123 @@ test.equal(msg.id, "FAKEID"); | ||
test.done(); | ||
}, | ||
"Read a valid notify MPN device access" : function(test) { | ||
var reader = new MetadataReader(); | ||
var inMsg, msg, i; | ||
inMsg = "FAKEID|MDA|S|user" + | ||
"|P|A|S|appID|S|deviceToken" + | ||
"\n"; | ||
reader.parse(inMsg, false); | ||
msg = reader.pop(); | ||
test.equal(msg.verb, "notifyMpnDeviceAccess"); | ||
test.equal(msg.id, "FAKEID"); | ||
test.equal(msg.userName, "user"); | ||
test.equal(msg.device.mpnPlatformType, "A"); | ||
test.equal(msg.device.applicationId, "appID"); | ||
test.equal(msg.device.deviceToken, "deviceToken"); | ||
test.done(); | ||
}, | ||
"Read a valid notify MPN APNS subscription activation" : function(test) { | ||
var reader = new MetadataReader(); | ||
var inMsg, msg, i; | ||
inMsg = "FAKEID|MSA|S|user|S|FAKESESSID" + | ||
"|I|1|M|M|S|group1|S|schema1|I|1|I|2" + | ||
"|PA|2|2|P|A|S|appID|S|deviceToken|S|triggerExpression|S|sound|S|badge|S|locActionKey|S|launghImage" + | ||
"|S|format|S|locFormatKey|S|arg1|S|arg2|S|customKey1|S|customValue1|S|customKey2|S|customValue2" + | ||
"\n"; | ||
reader.parse(inMsg, false); | ||
msg = reader.pop(); | ||
test.equal(msg.verb, "notifyMpnSubscriptionActivation"); | ||
test.equal(msg.id, "FAKEID"); | ||
test.equal(msg.userName, "user"); | ||
test.equal(msg.sessionId, "FAKESESSID"); | ||
test.strictEqual(msg.tableInfo.winIndex, 1); | ||
test.ok(msg.tableInfo.pubModes["merge"]); | ||
test.equal(msg.tableInfo.groupName, "group1"); | ||
test.equal(msg.tableInfo.schemaName, "schema1"); | ||
test.strictEqual(msg.tableInfo.firstItemIndex, 1); | ||
test.strictEqual(msg.tableInfo.lastItemIndex, 2); | ||
test.equal(msg.mpnSubscription.device.mpnPlatformType, "A"); | ||
test.equal(msg.mpnSubscription.device.applicationId, "appID"); | ||
test.equal(msg.mpnSubscription.device.deviceToken, "deviceToken"); | ||
test.equal(msg.mpnSubscription.trigger, "triggerExpression"); | ||
test.equal(msg.mpnSubscription.sound, "sound"); | ||
test.equal(msg.mpnSubscription.badge, "badge"); | ||
test.equal(msg.mpnSubscription.localizedActionKey, "locActionKey"); | ||
test.equal(msg.mpnSubscription.launchImage, "launghImage"); | ||
test.equal(msg.mpnSubscription.format, "format"); | ||
test.equal(msg.mpnSubscription.localizedFormatKey, "locFormatKey"); | ||
test.equal(msg.mpnSubscription.localizedFormatArguments.length, 2); | ||
test.equal(msg.mpnSubscription.localizedFormatArguments[0], "arg1"); | ||
test.equal(msg.mpnSubscription.localizedFormatArguments[1], "arg2"); | ||
test.equal(msg.mpnSubscription.customData["customKey2"], "customValue2"); | ||
test.done(); | ||
}, | ||
"Read a valid notify MPN GCM subscription activation" : function(test) { | ||
var reader = new MetadataReader(); | ||
var inMsg, msg, i; | ||
inMsg = "FAKEID|MSA|S|user|S|FAKESESSID" + | ||
"|I|1|M|M|S|group1|S|schema1|I|1|I|2" + | ||
"|PG|3|P|G|S|appID|S|deviceToken|S|triggerExpression|S|collapseKey|S|key1|S|value1|S|key2|S|value2|S|key3|S|value3|S|false|S|30" + | ||
"\n"; | ||
reader.parse(inMsg, false); | ||
msg = reader.pop(); | ||
test.equal(msg.verb, "notifyMpnSubscriptionActivation"); | ||
test.equal(msg.id, "FAKEID"); | ||
test.equal(msg.userName, "user"); | ||
test.equal(msg.sessionId, "FAKESESSID"); | ||
test.strictEqual(msg.tableInfo.winIndex, 1); | ||
test.ok(msg.tableInfo.pubModes["merge"]); | ||
test.equal(msg.tableInfo.groupName, "group1"); | ||
test.equal(msg.tableInfo.schemaName, "schema1"); | ||
test.strictEqual(msg.tableInfo.firstItemIndex, 1); | ||
test.strictEqual(msg.tableInfo.lastItemIndex, 2); | ||
test.equal(msg.mpnSubscription.device.mpnPlatformType, "G"); | ||
test.equal(msg.mpnSubscription.device.applicationId, "appID"); | ||
test.equal(msg.mpnSubscription.device.deviceToken, "deviceToken"); | ||
test.equal(msg.mpnSubscription.trigger, "triggerExpression"); | ||
test.equal(msg.mpnSubscription.collapseKey, "collapseKey"); | ||
test.equal(msg.mpnSubscription.data["key1"], "value1"); | ||
test.equal(msg.mpnSubscription.data["key2"], "value2"); | ||
test.equal(msg.mpnSubscription.data["key3"], "value3"); | ||
test.equal(msg.mpnSubscription.delayWhileIdle, "false"); | ||
test.equal(msg.mpnSubscription.timeToLive, "30"); | ||
test.done(); | ||
}, | ||
"Read a valid notify MPN device token change" : function(test) { | ||
var reader = new MetadataReader(); | ||
var inMsg, msg, i; | ||
inMsg = "FAKEID|MDC|S|user|P|G|S|appID|S|deviceToken|S|deviceToken2" + | ||
"\n"; | ||
reader.parse(inMsg, false); | ||
msg = reader.pop(); | ||
test.equal(msg.verb, "notifyMpnDeviceTokenChange"); | ||
test.equal(msg.id, "FAKEID"); | ||
test.equal(msg.userName, "user"); | ||
test.equal(msg.device.mpnPlatformType, "G"); | ||
test.equal(msg.device.applicationId, "appID"); | ||
test.equal(msg.device.deviceToken, "deviceToken"); | ||
test.equal(msg.newDeviceToken, "deviceToken2"); | ||
test.done(); | ||
} | ||
@@ -213,2 +344,7 @@ }; | ||
exports.metadataWrites = { | ||
"Init write" : function(test) { | ||
var msg = metadataProto.writeInit("FAKEID"); | ||
test.equal(msg, "FAKEID|MPI|V\n"); | ||
test.done(); | ||
}, | ||
"Write a valid get schema response" : function(test) { | ||
@@ -269,2 +405,17 @@ var msg = metadataProto.writeGetSchema("FAKEID",["Field 1","Field 2"]); | ||
test.done(); | ||
}, | ||
"Write a valid notify MPN device access response" : function(test) { | ||
var msg = metadataProto.writeNotifyMpnDeviceAccess("FAKEID"); | ||
test.equal(msg, "FAKEID|MDA|V\n"); | ||
test.done(); | ||
}, | ||
"Write a valid notify MPN subscription activation response" : function(test) { | ||
var msg = metadataProto.writeNotifyMpnSubscriptionActivation("FAKEID"); | ||
test.equal(msg, "FAKEID|MSA|V\n"); | ||
test.done(); | ||
}, | ||
"Write a valid notify MPN device token change" : function(test) { | ||
var msg = metadataProto.writeNotifyMpnDeviceTokenChange("FAKEID"); | ||
test.equal(msg, "FAKEID|MDC|V\n"); | ||
test.done(); | ||
} | ||
@@ -274,2 +425,7 @@ }; | ||
exports.metadataExceptionWrites = { | ||
"Write generic exception for init" : function(test) { | ||
var msg = metadataProto.writeInitException("FAKEID","A Message"); | ||
test.equal(msg, "FAKEID|MPI|E|A+Message\n"); | ||
test.done(); | ||
}, | ||
"Write generic exception for getItemData" : function(test) { | ||
@@ -330,2 +486,22 @@ var msg = metadataProto.writeGetItemDataException("FAKEID","A Message"); | ||
}, | ||
"Write credits exception for notifyMpnDeviceAccess" : function(test) { | ||
var msg = metadataProto.writeNotifyMpnDeviceAccessException("FAKEID","A Message","credits"); | ||
test.equal(msg, "FAKEID|MDA|EC|A+Message\n"); | ||
test.done(); | ||
}, | ||
"Write credits exception for notifyMpnSubscriptionActivation" : function(test) { | ||
var msg = metadataProto.writeNotifyMpnSubscriptionActivationException("FAKEID","A Message","credits"); | ||
test.equal(msg, "FAKEID|MSA|EC|A+Message\n"); | ||
test.done(); | ||
}, | ||
"Write credits exception for notifyMpnDeviceTokenChange" : function(test) { | ||
var msg = metadataProto.writeNotifyMpnDeviceTokenChangeException("FAKEID","A Message","credits"); | ||
test.equal(msg, "FAKEID|MDC|EC|A+Message\n"); | ||
test.done(); | ||
}, | ||
"Write metadata exception for init" : function(test) { | ||
var msg = metadataProto.writeInitException("FAKEID","A Message","metadata"); | ||
test.equal(msg, "FAKEID|MPI|EM|A+Message\n"); | ||
test.done(); | ||
}, | ||
"Write access exception for notifyUser" : function(test) { | ||
@@ -332,0 +508,0 @@ var msg = metadataProto.writeNotifyUserException("FAKEID","A Message","access"); |
@@ -21,3 +21,3 @@ /* | ||
exports.tests = { | ||
setUp: function (callback) { | ||
setUp: function (callback) { | ||
this.stream = new TestStream(); | ||
@@ -27,5 +27,62 @@ this.metadataProvider = new MetadataProvider(this.stream); | ||
}, | ||
"getItemData success" : function(test) { | ||
"init success" : function(test) { | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(3); | ||
mp.on('init', function(msg, resp) { | ||
test.equal(msg.parameters["P1"], "V1"); | ||
test.equal(msg.parameters["P2"], "V2"); | ||
resp.success(); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI|S|P1|S|V1|S|P2|S|V2\r\n"); | ||
}, | ||
"init failure" : function(test) { | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(1); | ||
mp.on('init', function(msg, resp) { | ||
resp.error("An error"); | ||
test.equal(s.popTestData(), "ID0|MPI|E|An+error\n"); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
}, | ||
"init metadata failure" : function(test) { | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(1); | ||
mp.on('init', function(msg, resp) { | ||
resp.error("An error", "metadata"); | ||
test.equal(s.popTestData(), "ID0|MPI|EM|An+error\n"); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
}, | ||
"Missing initialization" : function(test) { | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(1); | ||
mp.on('init', function(msg, resp) { | ||
resp.success(); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
}); | ||
test.throws(function () { | ||
s.pushTestData("FAKEID|NUS|S|user|S|password|S|header1|S|value+1|S|header+2|S|value+2\n"); | ||
}, Error); | ||
test.done(); | ||
}, | ||
"Late initialization" : function(test) { | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(2); | ||
mp.on('init', function(msg, resp) { | ||
resp.success(); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
test.throws(function () { | ||
s.pushTestData("ID0|MPI\r\n"); | ||
}, Error); | ||
test.done(); | ||
}, | ||
"getItemData success" : function(test) { | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(3); | ||
mp.on("getItemData", function(msg, resp) { | ||
@@ -37,15 +94,19 @@ test.equal(msg.verb, "getItemData"); | ||
]); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|GIT|I|10|D|0.5|M|RM|I|5|D|0|M|D\n"); | ||
test.done(); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|GIT|S|An+Item+Name1|S|An+Item+Name2\n"); | ||
}, | ||
}, | ||
"getItemData failure" : function(test) { | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(1); | ||
test.expect(2); | ||
mp.on("getItemData", function(msg, resp) { | ||
resp.error("An error"); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|GIT|E|An+error\n"); | ||
test.done(); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|GIT|S|An+Item+Name1|S|An+Item+Name2\n"); | ||
@@ -55,9 +116,11 @@ }, | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(2); | ||
test.expect(3); | ||
mp.on("notifyUser", function(msg, resp) { | ||
test.equal(msg.verb, "notifyUser"); | ||
resp.success(12.34, true); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|NUS|D|12.34|B|1\n"); | ||
test.done(); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|NUS|S|user|S|password|S|header1|S|value+1|S|header+2|S|value+2|S|REQUEST_ID|S|FAKEREQID\n"); | ||
@@ -67,8 +130,10 @@ }, | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(1); | ||
test.expect(2); | ||
mp.on("notifyUser", function(msg, resp) { | ||
resp.error("An error"); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|NUS|E|An+error\n"); | ||
test.done(); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|NUS|S|user|S|password|S|header1|S|value+1|S|header+2|S|value+2|S|REQUEST_ID|S|FAKEREQID\n"); | ||
@@ -78,8 +143,10 @@ }, | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(1); | ||
test.expect(2); | ||
mp.on("notifyUser", function(msg, resp) { | ||
resp.error("An error", "access"); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|NUS|EA|An+error\n"); | ||
test.done(); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|NUS|S|user|S|password|S|header1|S|value+1|S|header+2|S|value+2|S|REQUEST_ID|S|FAKEREQID\n"); | ||
@@ -89,9 +156,11 @@ }, | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(2); | ||
test.expect(3); | ||
mp.on("notifyUserAuth", function(msg, resp) { | ||
test.equal(msg.verb, "notifyUserAuth"); | ||
resp.success(12.34, true); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|NUA|D|12.34|B|1\n"); | ||
test.done(); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|NUA|S|user|S|password|S|principal|S|header1|S|value+1|S|header+2|S|value+2|S|REQUEST_ID|S|FAKEREQID\n"); | ||
@@ -101,8 +170,10 @@ }, | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(1); | ||
test.expect(2); | ||
mp.on("notifyUserAuth", function(msg, resp) { | ||
resp.error("An error"); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|NUA|E|An+error\n"); | ||
test.done(); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|NUA|S|user|S|password|S|principal|S|header1|S|value+1|S|header+2|S|value+2|S|REQUEST_ID|S|FAKEREQID\n"); | ||
@@ -112,9 +183,11 @@ }, | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(2); | ||
test.expect(3); | ||
mp.on("getSchema", function(msg, resp) { | ||
test.equal(msg.verb, "getSchema"); | ||
resp.success(["Field 1","Field 2"]); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|GSC|S|Field+1|S|Field+2\n"); | ||
test.done(); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|GSC|S|user|S|group|S|schema|S|FAKESESSID\n"); | ||
@@ -124,8 +197,10 @@ }, | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(1); | ||
test.expect(2); | ||
mp.on("getSchema", function(msg, resp) { | ||
resp.error("An error"); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|GSC|E|An+error\n"); | ||
test.done(); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|GSC|S|user|S|group|S|schema|S|FAKESESSID\n"); | ||
@@ -135,9 +210,11 @@ }, | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(2); | ||
test.expect(3); | ||
mp.on("getItems", function(msg, resp) { | ||
test.equal(msg.verb, "getItems"); | ||
resp.success(["Item 1","Item 2"]); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|GIS|S|Item+1|S|Item+2\n"); | ||
test.done(); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|GIS|S|user|S|group|S|FAKESESSID\n"); | ||
@@ -147,8 +224,10 @@ }, | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(1); | ||
test.expect(2); | ||
mp.on("getItems", function(msg, resp) { | ||
resp.error("An error"); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|GIS|E|An+error\n"); | ||
test.done(); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|GIS|S|user|S|group|S|FAKESESSID\n"); | ||
@@ -158,3 +237,3 @@ }, | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(2); | ||
test.expect(3); | ||
mp.on("getUserItemData", function(msg, resp) { | ||
@@ -166,5 +245,7 @@ test.equal(msg.verb, "getUserItemData"); | ||
]); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|GUI|I|30|D|3|M|RMDC|I|40|D|2.25|M|M\n"); | ||
test.done(); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|GUI|S|user|S|item+1|S|item+2\n"); | ||
@@ -174,8 +255,10 @@ }, | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(1); | ||
test.expect(2); | ||
mp.on("getUserItemData", function(msg, resp) { | ||
resp.error("An error"); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|GUI|E|An+error\n"); | ||
test.done(); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|GUI|S|user|S|item+1|S|item+2\n"); | ||
@@ -185,9 +268,11 @@ }, | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(2); | ||
test.expect(3); | ||
mp.on("notifyUserMessage", function(msg, resp) { | ||
test.equal(msg.verb, "notifyUserMessage"); | ||
resp.success(); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|NUM|V\n"); | ||
test.done(); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|NUM|S|user|S|FAKESESSID|S|This+is+a+message\n"); | ||
@@ -197,8 +282,10 @@ }, | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(1); | ||
test.expect(2); | ||
mp.on("notifyUserMessage", function(msg, resp) { | ||
resp.error("An error"); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|NUM|E|An+error\n"); | ||
test.done(); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|NUM|S|user|S|FAKESESSID|S|This+is+a+message\n"); | ||
@@ -208,9 +295,11 @@ }, | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(2); | ||
test.expect(3); | ||
mp.on("notifyNewSession", function(msg, resp) { | ||
test.equal(msg.verb, "notifyNewSession"); | ||
resp.success(); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|NNS|V\n"); | ||
test.done(); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|NNS|S|user|S|FAKESESSID|S|prop1|S|val1|S|prop2|S|val2\n"); | ||
@@ -220,8 +309,10 @@ }, | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(1); | ||
test.expect(2); | ||
mp.on("notifyNewSession", function(msg, resp) { | ||
resp.error("An error"); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|NNS|E|An+error\n"); | ||
test.done(); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|NNS|S|user|S|FAKESESSID|S|prop1|S|val1|S|prop2|S|val2\n"); | ||
@@ -231,9 +322,11 @@ }, | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(2); | ||
test.expect(3); | ||
mp.on("notifySessionClose", function(msg, resp) { | ||
test.equal(msg.verb, "notifySessionClose"); | ||
resp.success(); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|NSC|V\n"); | ||
test.done(); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|NSC|S|FAKESESSID\n"); | ||
@@ -243,8 +336,10 @@ }, | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(1); | ||
test.expect(2); | ||
mp.on("notifySessionClose", function(msg, resp) { | ||
resp.error("An error"); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|NSC|E|An+error\n"); | ||
test.done(); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|NSC|S|FAKESESSID\n"); | ||
@@ -254,9 +349,11 @@ }, | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(2); | ||
test.expect(3); | ||
mp.on("notifyNewTables", function(msg, resp) { | ||
test.equal(msg.verb, "notifyNewTables"); | ||
resp.success(); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|NNT|V\n"); | ||
test.done(); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|NNT|S|user|S|FAKESESSID|I|1|M|M|S|group1|S|schema1|I|1|I|5|S|#\n"); | ||
@@ -266,8 +363,10 @@ }, | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(1); | ||
test.expect(2); | ||
mp.on("notifyNewTables", function(msg, resp) { | ||
resp.error("An error"); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|NNT|E|An+error\n"); | ||
test.done(); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|NNT|S|user|S|FAKESESSID|I|1|M|M|S|group1|S|schema1|I|1|I|5|S|#\n"); | ||
@@ -277,9 +376,11 @@ }, | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(2); | ||
test.expect(3); | ||
mp.on("notifyTablesClose", function(msg, resp) { | ||
test.equal(msg.verb, "notifyTablesClose"); | ||
resp.success(); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|NTC|V\n"); | ||
test.done(); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|NTC|S|FAKESESSID|I|1|M|M|S|group1|S|schema1|I|1|I|5|S|#\n"); | ||
@@ -289,8 +390,10 @@ }, | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(1); | ||
test.expect(2); | ||
mp.on("notifyTablesClose", function(msg, resp) { | ||
resp.error("An error"); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|NTC|E|An+error\n"); | ||
test.done(); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|NTC|S|FAKESESSID|I|1|M|M|S|group1|S|schema1|I|1|I|5|S|#\n"); | ||
@@ -307,4 +410,5 @@ }, | ||
}, Error); | ||
test.done(); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|NUM|S|user|S|FAKESESSID|S|This+is+a+message\n"); | ||
@@ -321,6 +425,82 @@ }, | ||
}, Error); | ||
test.done(); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|NUM|S|user|S|FAKESESSID|S|This+is+a+message\n"); | ||
}, | ||
}; | ||
"notifyMpnDeviceAccess success" : function(test) { | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(3); | ||
mp.on("notifyMpnDeviceAccess", function(msg, resp) { | ||
test.equal(msg.verb, "notifyMpnDeviceAccess"); | ||
resp.success(); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|MDA|V\n"); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|MDA|S|user|P|A|S|appID|S|deviceToken\n"); | ||
}, | ||
"notifyMpnDeviceAccess failure" : function(test) { | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(2); | ||
mp.on("notifyMpnDeviceAccess", function(msg, resp) { | ||
resp.error("An error", "credits"); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|MDA|EC|An+error\n"); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|MDA|S|user|P|A|S|appID|S|deviceToken\n"); | ||
}, | ||
"notifyMpnSubscriptionActivation success" : function(test) { | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(3); | ||
mp.on("notifyMpnSubscriptionActivation", function(msg, resp) { | ||
test.equal(msg.verb, "notifyMpnSubscriptionActivation"); | ||
resp.success(); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|MSA|V\n"); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|MSA|S|user|S|FAKESESSID|I|1|M|M|S|group1|S|schema1|I|1|I|2|PA|2|2|P|A|S|appID|S|deviceToken|S|triggerExpression|S|sound|S|badge|S|locActionKey|S|launghImage|S|format|S|locFormatKey|S|arg1|S|arg2|S|customKey1|S|customValue1|S|customKey2|S|customValue2\n"); | ||
}, | ||
"notifyMpnSubscriptionActivation failure" : function(test) { | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(2); | ||
mp.on("notifyMpnSubscriptionActivation", function(msg, resp) { | ||
resp.error("An error", "credits"); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|MSA|EC|An+error\n"); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|MSA|S|user|S|FAKESESSID|I|1|M|M|S|group1|S|schema1|I|1|I|2|PA|2|2|P|A|S|appID|S|deviceToken|S|triggerExpression|S|sound|S|badge|S|locActionKey|S|launghImage|S|format|S|locFormatKey|S|arg1|S|arg2|S|customKey1|S|customValue1|S|customKey2|S|customValue2\n"); | ||
}, | ||
"notifyMpnDeviceTokenChange success" : function(test) { | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(3); | ||
mp.on("notifyMpnDeviceTokenChange", function(msg, resp) { | ||
test.equal(msg.verb, "notifyMpnDeviceTokenChange"); | ||
resp.success(); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|MDC|V\n"); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|MDC|S|user|P|G|S|appID|S|deviceToken|S|deviceToken2\n"); | ||
}, | ||
"notifyMpnDeviceTokenChange failure" : function(test) { | ||
var d, s = this.stream, mp = this.metadataProvider; | ||
test.expect(2); | ||
mp.on("notifyMpnDeviceTokenChange", function(msg, resp) { | ||
resp.error("An error", "credits"); | ||
test.equal(s.popTestData(), "ID0|MPI|V\n"); | ||
test.equal(s.popTestData(), "FAKEID|MDC|EC|An+error\n"); | ||
test.done(); | ||
}); | ||
s.pushTestData("ID0|MPI\r\n"); | ||
s.pushTestData("FAKEID|MDC|S|user|P|G|S|appID|S|deviceToken|S|deviceToken2\n"); | ||
}, | ||
}; |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
208640
4134
0
152
19