Comparing version 0.5.0 to 1.0.0
1.0.0 / 2013-03-27 | ||
================== | ||
* pkg: update description | ||
* docs: update | ||
* feedback: [base] change default interval | ||
* agent: [all] reconnect now cancelled by .close() | ||
* docs: add resources section | ||
* docs: color scheme | ||
* docs: checkpoint - agent docs ready for proofread | ||
* agent: [base] documentation | ||
* agent: [mock/live] fix reference to stored gateway error | ||
* Merge branch 'refactor/node10' | ||
* feedback: [base/mock] convert to new lotus api | ||
* examples: [agent] fix small typos | ||
* agent: [all] upgrade to use lotus 1.0.x | ||
* codecs: [all] change exports for lotus compatibility | ||
* pkg: [lotus] update to 1.0.x | ||
* docs: add site folder | ||
* lib: documentation | ||
* grep: change to qualiancy project | ||
* Merge branch 'refactor/examples' | ||
* agent: [mock] fix scoping bug | ||
* examples: add mock examples for agent/feedback | ||
* examples: update live examples | ||
* test: [feedback] test for change of concurrency | ||
* feedback: [base] add set handle for concurrency change | ||
* deps: [facet] update and migrate to 0.4.x | ||
* message: documentation | ||
* device: add comments | ||
0.5.0 / 2013-02-28 | ||
@@ -3,0 +34,0 @@ ================== |
/*! | ||
* apnagent | ||
* Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com> | ||
* Copyright(c) 2012-2013 Jake Luer <jake@qualiancy.com> | ||
* MIT Licensed | ||
@@ -11,3 +11,3 @@ */ | ||
exports.version = '0.5.0'; | ||
exports.version = '1.0.0'; | ||
@@ -14,0 +14,0 @@ /*! |
/*! | ||
* apnagent - Agent (Base) | ||
* Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com> | ||
* Copyright(c) 2012-2013 Jake Luer <jake@qualiancy.com> | ||
* MIT Licensed | ||
@@ -55,5 +55,12 @@ */ | ||
/** | ||
* Agent (Base) | ||
* ## Agent API | ||
* | ||
* @api private | ||
* This API section covers both the `Agent` and `MockAgent` | ||
* classes. The architecture was developed to provide | ||
* feature parity for not just available methods but the | ||
* events emitted and processing methodology. Any significant | ||
* differences have already been outlined in the Agent Guide. | ||
* | ||
* @header Agent API | ||
* @see #header-agent Agent Guide | ||
*/ | ||
@@ -104,6 +111,10 @@ | ||
// decoder handles incoming apn errors | ||
decoder = lotus.createReaderStream(); | ||
decoder.use(8, codecs.getInterface('gateway response', 'reader')); | ||
decoder.on('data', function (obj) { | ||
decoder = lotus.createDecoder(); | ||
decoder.stream(8, codecs.getInterface('gateway response', 'decode')); | ||
// listen for responses | ||
decoder.stream(8).on('readable', function () { | ||
var obj = this.read(); | ||
obj.code = obj.code[0]; | ||
var message = notifErrors[obj.code] || 'None (unknown)' | ||
@@ -126,5 +137,5 @@ , err = new errors.GatewayMessageError(message, obj) | ||
// encoder handles converting msg json to buffers | ||
encoder = lotus.createWriterStream(); | ||
encoder.use(0, codecs.getInterface('gateway simple', 'writer')); | ||
encoder.use(1, codecs.getInterface('gateway enhanced', 'writer')); | ||
encoder = lotus.createEncoder(); | ||
encoder.stream(0, codecs.getInterface('gateway simple', 'encode')); | ||
encoder.stream(1, codecs.getInterface('gateway enhanced', 'encode')); | ||
@@ -149,22 +160,25 @@ // mount objects | ||
facet(Base); | ||
facet(Base.prototype); | ||
/** | ||
* .create () | ||
* ### .createMessage ([encoding]) | ||
* | ||
* Creates a message that can be further modified | ||
* through chaining. | ||
* through chaining. Do not provide arguments unless | ||
* you know what you are doing. | ||
* | ||
* @param {String} encoding (default: utf8) | ||
* @param {String} codec (simple or enhanced) | ||
* @return {Message} new message | ||
* @name create | ||
* @api public | ||
* @see #agent-messages Agent Guide - Sending Messages | ||
* @see #header-message_builder_api Message Builder API | ||
*/ | ||
Base.prototype.createMessage = function (enc, codec) { | ||
codec = codec || this.get('codec'); | ||
Base.prototype.createMessage = function (enc) { | ||
var codec = this.get('codec'); | ||
return new Message(this, codec, { enc: enc }); | ||
}; | ||
/** | ||
/*! | ||
* .nextId () | ||
@@ -195,11 +209,26 @@ * | ||
/** | ||
* .send (message) | ||
* ### .send (message[, callback]) | ||
* | ||
* If connected, convert a message to buffer and send | ||
* over the wire. If not currently connected, place | ||
* the message in a queue for later departure. | ||
* Serialize the message and catch any validation errors | ||
* that might occur. If validation passes add the message | ||
* to the send queue. Messages can also be sent by invoking | ||
* the message instance's `.send()` method. | ||
* | ||
* @param {Object} apnsagent message | ||
* ```js | ||
* var message = agent.createMessage(); | ||
* | ||
* message | ||
* .device(token) | ||
* .alert('Hello Universe'); | ||
* | ||
* agent.send(message); | ||
* ``` | ||
* | ||
* @param {Message} message to send | ||
* @param {Function} callback to invoke | ||
* @return {this} for chaining | ||
* @name send | ||
* @api public | ||
* @see #agent-messages Agent Guide - Sending Messages | ||
* @see #message_builder_api-send Message#send() | ||
*/ | ||
@@ -244,12 +273,43 @@ | ||
Base.prototype.queueIterator = function (buf, next) { | ||
Base.prototype._queueIterator = function (buf, next) { | ||
throw new Error('Queue iterator not implemented.'); | ||
}; | ||
Base.prototype.connect = function (cb) { | ||
/** | ||
* ### .connect ([ callback ]) | ||
* | ||
* Open an active gateway connection. Once the connection | ||
* is established the outgoing message queue will begin | ||
* to process items. | ||
* | ||
* @param {Function} callback | ||
* @return {this} for chaining | ||
* @name connect | ||
* @api public | ||
*/ | ||
Base.prototype.connect = function () { | ||
throw new Error('Gateway connect not implemented.'); | ||
}; | ||
/** | ||
* ### .close ([ callback ]) | ||
* | ||
* Close the active gateway connection or cancel | ||
* further reconnect attempts. If the queue is currently | ||
* processing a message it will wait for the current | ||
* message to finish before closing. | ||
* | ||
* Apple recommends that a connection always remains open | ||
* even when there are no messages to process. Production | ||
* deployments should use this sparingly. | ||
* | ||
* @param {Function} callback | ||
* @return {this} for chaining | ||
* @name close | ||
* @api public | ||
*/ | ||
Base.prototype.close = function () { | ||
throw new Error('Gateway close not implemented'); | ||
}; |
/*! | ||
* apnagent - Agent (Live) | ||
* Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com> | ||
* Copyright(c) 2012-2013 Jake Luer <jake@qualiancy.com> | ||
* MIT Licensed | ||
@@ -56,3 +56,3 @@ */ | ||
* | ||
* Begin the serer connection sequence and | ||
* Begin the server connection sequence and | ||
* establish all listeners needed for operation, | ||
@@ -90,3 +90,3 @@ * including a callback on successful connection. | ||
function reconnect () { | ||
var gwe = self.gatewayError | ||
var gwe = self.meta.gatewayError | ||
, pos = 0; | ||
@@ -142,3 +142,3 @@ | ||
self.connected = false; | ||
setTimeout(reconnect, ms(delay)); | ||
self.meta.timer = setTimeout(reconnect, ms(delay)); | ||
} else { | ||
@@ -181,3 +181,4 @@ debug('(gateway) closed - %s:%d', opts.host, opts.port); | ||
// leave if nothing needs to be done | ||
if (!this.connected) { | ||
if (!this.connected || !this.gateway) { | ||
clearTimeout(this.meta.timer); | ||
process.nextTick(cb); | ||
@@ -209,2 +210,3 @@ return this; | ||
, encoder = this.encoder | ||
, stream = encoder.stream(obj.codec) | ||
, id = obj.json.identifier | ||
@@ -214,4 +216,5 @@ , queue = this.queue; | ||
// wait for encoded message | ||
encoder.once('data', function (buf) { | ||
var gateway = self.gateway; | ||
encoder.once('readable', function () { | ||
var buf = encoder.read() | ||
, gateway = self.gateway; | ||
@@ -236,3 +239,3 @@ // requeue if not connected | ||
debug('(encoder) write: %d', id); | ||
encoder.write(obj.codec, obj.json); | ||
stream.write(obj.json); | ||
}; |
/*! | ||
* apnagent - Mock (Mock) | ||
* Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com> | ||
* apnagent - Agent (Mock) | ||
* Copyright(c) 2012-2013 Jake Luer <jake@qualiancy.com> | ||
* MIT Licensed | ||
@@ -78,3 +78,3 @@ */ | ||
function reconnect () { | ||
var gwe = self.gatewayError | ||
var gwe = self.meta.gatewayError | ||
, pos = 0; | ||
@@ -102,5 +102,5 @@ | ||
// mock gateway parses the outgoing buffers back to json | ||
gateway = lotus.createReaderStream(); | ||
gateway.use(0, codecs.getInterface('gateway simple', 'reader')); | ||
gateway.use(1, codecs.getInterface('gateway enhanced', 'reader')); | ||
gateway = lotus.createDecoder(); | ||
gateway.stream(0, codecs.getInterface('gateway simple', 'decode')); | ||
gateway.stream(1, codecs.getInterface('gateway enhanced', 'decode')); | ||
@@ -120,7 +120,11 @@ // simulate async connect | ||
// data event is emitted for each message | ||
gateway.on('data', function (json) { | ||
function emitter () { | ||
var json = this.read(); | ||
debug('(gateway) incoming message', json); | ||
self.emit('mock:message', json); | ||
}); | ||
} | ||
gateway.stream(0).on('readable', emitter); | ||
gateway.stream(1).on('readable', emitter); | ||
// an error is emitted when an incoming message is badly formatted | ||
@@ -132,4 +136,4 @@ gateway.on('error', function (err) { | ||
// end is similiar to a socket `close` event | ||
gateway.on('end', function () { | ||
// this is similiar to a socket `close` event | ||
gateway.on('close', function () { | ||
self.cache.pause(); | ||
@@ -142,3 +146,3 @@ self.queue.pause(); | ||
self.connected = false; | ||
setTimeout(reconnect, ms(delay)); | ||
self.meta.timer = setTimeout(reconnect, ms(delay)); | ||
} else { | ||
@@ -169,3 +173,4 @@ debug('(gateway) closed - mock'); | ||
// leave if nothing needs to be done | ||
if (!this.connected) { | ||
if (!this.connected || !this.gateway) { | ||
clearTimeout(this.meta.timer); | ||
process.nextTick(cb); | ||
@@ -197,2 +202,3 @@ return this; | ||
, encoder = this.encoder | ||
, stream = encoder.stream(obj.codec) | ||
, id = obj.json.identifier | ||
@@ -202,7 +208,8 @@ , queue = this.queue; | ||
// wait for encoded message | ||
encoder.once('data', function (buf) { | ||
var gateway = self.gateway; | ||
encoder.once('readable', function () { | ||
var buf = encoder.read() | ||
, gateway = self.gateway; | ||
// requeue if not connected | ||
if (!gateway || !gateway.writable || !this.connected) { | ||
if (!gateway || !gateway.writable || !self.connected) { | ||
debug('(queue) pause: not connected'); | ||
@@ -225,3 +232,3 @@ queue.pause(); | ||
debug('(encoder) write: %d', id); | ||
encoder.write(obj.codec, obj.json); | ||
stream.write(obj.json); | ||
}; |
/*! | ||
* apnagent - Cache | ||
* Copyright(c) 2013 Jake Luer <jake@alogicalparadox.com> | ||
* Copyright(c) 2013 Jake Luer <jake@qualiancy.com> | ||
* MIT Licensed | ||
@@ -5,0 +5,0 @@ */ |
/*! | ||
* apnagent - Response Codec | ||
* Copyright(c) 2013 Jake Luer <jake@alogicalparadox.com> | ||
* Copyright(c) 2013 Jake Luer <jake@qualiancy.com> | ||
* MIT Licensed | ||
@@ -14,3 +14,3 @@ */ | ||
/** | ||
* .reader | ||
* .decode | ||
* | ||
@@ -23,3 +23,3 @@ * Response Apple Push Feedback protocol. | ||
exports.reader = lotus.reader() | ||
exports.decode = lotus.decode() | ||
.u32be('timestamp') | ||
@@ -30,3 +30,3 @@ .u16be('tokenLen') | ||
/** | ||
* .writer | ||
* .encode | ||
* | ||
@@ -39,3 +39,3 @@ * Response Apple Push Feedback protocol. | ||
exports.writer = lotus.writer() | ||
exports.encode = lotus.encode() | ||
.u32be('timestamp') | ||
@@ -42,0 +42,0 @@ .u16be(function (msg) { |
/*! | ||
* apnagent - Enhanced Codec | ||
* Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com> | ||
* Copyright(c) 2012-2013 Jake Luer <jake@qualiancy.com> | ||
* MIT Licensed | ||
@@ -14,3 +14,3 @@ */ | ||
/** | ||
* .reader | ||
* .decode | ||
* | ||
@@ -23,3 +23,3 @@ * Enhanced Apple Push Notifications protocol. | ||
exports.reader = lotus.reader() | ||
exports.decode = lotus.decode() | ||
.u32be('identifier') | ||
@@ -30,6 +30,6 @@ .u32be('expiration') | ||
.u16be('payloadLen') | ||
.take('payloadLen', 'payload', 'utf8', JSON.parse); | ||
.take('payloadLen', 'payload', JSON.parse); | ||
/** | ||
* .writer | ||
* .encode | ||
* | ||
@@ -42,3 +42,3 @@ * Enhanced Apple Push Notifications protocol. | ||
exports.writer = lotus.writer() | ||
exports.encode = lotus.encode() | ||
.u32be('identifier') | ||
@@ -45,0 +45,0 @@ .u32be('expiration') |
/*! | ||
* apnagent - Response Codec | ||
* Copyright(c) 2013 Jake Luer <jake@alogicalparadox.com> | ||
* Copyright(c) 2013 Jake Luer <jake@qualiancy.com> | ||
* MIT Licensed | ||
@@ -14,3 +14,3 @@ */ | ||
/** | ||
* .reader | ||
* .decode | ||
* | ||
@@ -23,4 +23,4 @@ * Response Apple Push Notifications protocol. | ||
exports.reader = lotus.reader() | ||
exports.decode = lotus.decode() | ||
.take(1, 'code') | ||
.u32be('identifier'); |
/*! | ||
* apnagent - Simple Codec | ||
* Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com> | ||
* Copyright(c) 2012-2013 Jake Luer <jake@qualiancy.com> | ||
* MIT Licensed | ||
@@ -14,3 +14,3 @@ */ | ||
/** | ||
* .reader | ||
* .decode | ||
* | ||
@@ -23,3 +23,3 @@ * Simple Apple Push Notifications protocol. | ||
exports.reader = lotus.reader() | ||
exports.decode = lotus.decode() | ||
.u16be('tokenLen') | ||
@@ -31,3 +31,3 @@ .take('tokenLen', 'deviceToken') | ||
/** | ||
* .writer | ||
* .encode | ||
* | ||
@@ -40,3 +40,3 @@ * Enhanced Apple Push Notifications protocol. | ||
exports.writer = lotus.writer() | ||
exports.encode = lotus.encode() | ||
.u16be(function (msg) { | ||
@@ -43,0 +43,0 @@ return msg.deviceToken.length; |
/*! | ||
* apnagent - Codecs | ||
* Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com> | ||
* Copyright(c) 2012-2013 Jake Luer <jake@qualiancy.com> | ||
* MIT Licensed | ||
@@ -5,0 +5,0 @@ */ |
/*! | ||
* apnagent - Device | ||
* Copyright(c) 2013 Jake Luer <jake@alogicalparadox.com> | ||
* Copyright(c) 2013 Jake Luer <jake@qualiancy.com> | ||
* MIT Licensed | ||
@@ -14,3 +14,3 @@ */ | ||
/** | ||
* Device | ||
* ## Device API | ||
* | ||
@@ -25,7 +25,22 @@ * A small constructor to easily encapsulate a device | ||
* | ||
* @param {String|Buffer} device token | ||
* @api public | ||
* The most common usage for the `Device` constructor | ||
* is to sanitize a device token for storage in a database. | ||
* | ||
* ```js | ||
* var Device = require('apnagent').Device | ||
* , device = new Device('<a1b56d2c 08f621d8 7060da2b>'); | ||
* ``` | ||
* | ||
* @header Device API | ||
*/ | ||
function Device (token) { | ||
/*! | ||
* @param {String|Buffer|Device} device token | ||
* @api public | ||
*/ | ||
if (token instanceof Device) { | ||
token = token.toString(); | ||
} | ||
this.token = token || undefined; | ||
@@ -35,8 +50,13 @@ } | ||
/** | ||
* .toBuffer () | ||
* ### .toBuffer () | ||
* | ||
* Convert the stored device token to a buffer. | ||
* | ||
* ```js | ||
* var buf = device.toBuffer(); | ||
* ``` | ||
* | ||
* @return {Buffer} | ||
* @api public | ||
* @name toBuffer | ||
*/ | ||
@@ -49,8 +69,15 @@ | ||
/** | ||
* .toString () | ||
* ### .toString () | ||
* | ||
* Convert the stored device token to a string. | ||
* The string will be sanitized and thus not include | ||
* spaces or extra characters. | ||
* | ||
* ```js | ||
* var str = device.toString(); | ||
* ``` | ||
* | ||
* @return {String} | ||
* @api public | ||
* @name toString | ||
*/ | ||
@@ -63,12 +90,22 @@ | ||
/** | ||
* .equal (device) | ||
* ### .equal (device) | ||
* | ||
* Compare the stored device token to another | ||
* Device, string, or Buffer. Will also return false | ||
* device, string, or buffer. Will also return false | ||
* if both Devices do not have tokens associated with | ||
* them. | ||
* | ||
* ```js | ||
* // testing string | ||
* device.equal('a1b56d2c08f621d87060da2b').should.be.true; | ||
* | ||
* // testing another device | ||
* var dev2 = new Device('feedface'); | ||
* device.equal(dev2).should.be.false; | ||
* ``` | ||
* | ||
* @param {Mixed} instance of Device, String, or Buffer | ||
* @return {Boolean} device tokens equal | ||
* @api public | ||
* @name equal | ||
*/ | ||
@@ -75,0 +112,0 @@ |
/*! | ||
* apnagent - Errors | ||
* Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com> | ||
* Copyright(c) 2012-2013 Jake Luer <jake@qualiancy.com> | ||
* MIT Licensed | ||
@@ -5,0 +5,0 @@ */ |
/*! | ||
* apnagent - Feedback (Base) | ||
* Copyright(c) 2013 Jake Luer <jake@alogicalparadox.com> | ||
* Copyright(c) 2013 Jake Luer <jake@qualiancy.com> | ||
* MIT Licensed | ||
@@ -34,5 +34,8 @@ */ | ||
/** | ||
* Feedback (Base) | ||
* ## Feedback API | ||
* | ||
* @api private | ||
* This is the feedback api. | ||
* | ||
* @header Feedback API | ||
* @see #header-feedback Feedback Guide | ||
*/ | ||
@@ -43,3 +46,3 @@ | ||
this.connected = false; | ||
this.set('interval', '30s'); | ||
this.set('interval', '30m'); | ||
this.disable('sandbox'); | ||
@@ -91,9 +94,10 @@ | ||
// decoder handing incoming feedback responses | ||
decoder = lotus.createReaderStream(); | ||
decoder.use(codecs.getInterface('feedback response', 'reader')); | ||
decoder.on('data', function (obj) { | ||
queue.push({ | ||
device: new Device(obj.deviceToken) | ||
, timestamp: new Date(obj.timestamp * 1000) | ||
}, true); | ||
decoder = lotus.createDecoder(); | ||
decoder.stream(codecs.getInterface('feedback response', 'decode')); | ||
decoder.stream().on('readable', function () { | ||
var obj = this.read() | ||
, res = {}; | ||
res.device = new Device(obj.deviceToken); | ||
res.timestamp = new Date(obj.timestamp * 1000); | ||
queue.push(res, true); | ||
}); | ||
@@ -116,4 +120,19 @@ | ||
facet(Base); | ||
facet(Base.prototype, function (key, value) { | ||
key = key.toLowerCase(); | ||
// handle queue concurrency change | ||
if (key === 'concurrency') { | ||
if ('number' !== typeof value) { | ||
throw new Error('.set(\'concurrency\') fail: value must be a number'); | ||
} | ||
if (value <= 0) { | ||
throw new Error('.set(\'concurrency\') fail: value must be greater than zero'); | ||
} | ||
this.queue._concurrency = value; | ||
} | ||
}); | ||
Object.defineProperty(Base.prototype, 'length', { | ||
@@ -125,2 +144,10 @@ get: function () { | ||
/** | ||
* ### .use (fn) | ||
* | ||
* @param {Function} fn to add to stack | ||
* @name use | ||
* @api public | ||
*/ | ||
Base.prototype.use = function (fn) { | ||
@@ -133,2 +160,12 @@ this.meta.stack.push(fn); | ||
/** | ||
* ### .connect ([ callback ]) | ||
* | ||
* | ||
* @param {Function} callback | ||
* @return {this} for chaining | ||
* @name connect | ||
* @api public | ||
*/ | ||
Base.prototype.connect = function () { | ||
@@ -138,2 +175,20 @@ throw new Error('Feedback connect not implemented.'); | ||
/** | ||
* ### .close ([ callback ]) | ||
* | ||
* Close the active gateway connection or cancel | ||
* further reconnect attempts. If the queue is currently | ||
* processing a message it will wait for the current | ||
* message to finish before closing. | ||
* | ||
* Apple recommends that a connection always remains open | ||
* even when there are no messages to process. Production | ||
* deployments should use this sparingly. | ||
* | ||
* @param {Function} callback | ||
* @return {this} for chaining | ||
* @name close | ||
* @api public | ||
*/ | ||
Base.prototype.close = function () { | ||
@@ -140,0 +195,0 @@ throw new Error('Feedback close not implemented.'); |
/*! | ||
* apnagent - Feedback (Live) | ||
* Copyright(c) 2013 Jake Luer <jake@alogicalparadox.com> | ||
* Copyright(c) 2013 Jake Luer <jake@qualiancy.com> | ||
* MIT Licensed | ||
@@ -5,0 +5,0 @@ */ |
@@ -42,4 +42,4 @@ | ||
// mock feedback writes mock unsubs to decoder | ||
feedback = lotus.createWriterStream(); | ||
feedback.use(codecs.getInterface('feedback response', 'writer')); | ||
feedback = lotus.createEncoder(); | ||
feedback.stream(codecs.getInterface('feedback response', 'encode')); | ||
@@ -55,4 +55,5 @@ // simulate async connect | ||
// send simulated data | ||
process.nextTick(function () { | ||
setTimeout(function () { | ||
var outgoing = self.meta.outgoing | ||
, stream = feedback.stream() | ||
, line; | ||
@@ -64,8 +65,8 @@ | ||
debug('(mock) writing unsub - %s', line.deviceToken.toString('hex')); | ||
feedback.write(line); | ||
stream.write(line); | ||
} | ||
debug('(mock) writing complete'); | ||
feedback.end(); | ||
}); | ||
stream.end(); | ||
}, 10); | ||
}); | ||
@@ -72,0 +73,0 @@ |
/*! | ||
* apnagent - Message Builder | ||
* Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com> | ||
* Copyright(c) 2012-2013 Jake Luer <jake@qualiancy.com> | ||
* MIT Licensed | ||
@@ -29,15 +29,27 @@ */ | ||
/** | ||
* Message | ||
* ## Message Builder API | ||
* | ||
* A message encapsulates all data points that will | ||
* be encoded and sent via the wire to the APNS. If | ||
* any data is provided to a message that a codec | ||
* does not support, it will be ignored (such as | ||
* `expires` to the simple codec). | ||
* be encoded and sent through the wire to APNS. The message | ||
* builder is a chainable API that provides full feature | ||
* coverage of the Apple Push Notification specifications. | ||
* | ||
* @param {String} encoding for payload (utf8) | ||
* @api public | ||
* The preferred method of composing messages is directly | ||
* from a constructed `Agent` or `MockAgent`. | ||
* | ||
* ```js | ||
* var msg = agent.createMessage(); | ||
* ``` | ||
* | ||
* @header Message Builder API | ||
*/ | ||
function Message (agent, codec, opts) { | ||
/*! | ||
* @param {Agent} agent to use for sending | ||
* @param {String} default codec | ||
* @param {Object} payload to import | ||
* @api public | ||
*/ | ||
this._agent = agent; | ||
@@ -85,34 +97,4 @@ this.encoding = 'utf8'; | ||
/** | ||
* .set (key, value) | ||
* ### .alert (key, value) | ||
* | ||
* Set extra key values that will be incuded | ||
* as part of the payload. `aps` is reserved by | ||
* Apple and `enc` is reserved by apnagent. | ||
* | ||
* Is a key/value you pair is provided it will | ||
* be set. If an object is provided, all data points | ||
* will be merged into the current payload. | ||
* | ||
* @param {String|Object} | ||
* @param {Mixed} value | ||
* @returns {this} for chaining | ||
* @api public | ||
*/ | ||
Message.prototype.set = function (key, value) { | ||
if ('object' === typeof key) { | ||
for (var name in key) { | ||
this.set(name, key[name]); | ||
} | ||
} else { | ||
if (key === 'aps') return; | ||
this.payload[key] = value; | ||
} | ||
return this; | ||
}; | ||
/** | ||
* .alert (key, value) | ||
* | ||
* Sets variables to be included in the `alert` dictionary | ||
@@ -124,13 +106,31 @@ * for the `aps` portion of the payload. If you wish to set | ||
* | ||
* Allowed keys: | ||
* ##### Allowed keys: | ||
* | ||
* - `body` | ||
* - `action-loc-key' | ||
* - `log-key` | ||
* - `action-loc-key` | ||
* - `loc-key` | ||
* - `loc-args` | ||
* - `launch-image` | ||
* | ||
* @param {String|Object} | ||
* @param {Mixed} value | ||
* ```js | ||
* // just set body | ||
* msg.alert('Hello Universe'); | ||
* | ||
* // set multiple values | ||
* msg.set({ | ||
* body: 'Hello Universe' | ||
* , 'launch-image': 'notif.png' | ||
* }); | ||
* | ||
* // chainable | ||
* msg | ||
* .alert('Hello Universe') | ||
* .alert('launch-image', 'notif.png'); | ||
* ``` | ||
* | ||
* @param {String|Object} alert body, string key or object of alert settings | ||
* @param {Mixed} value (when first argument is a string) | ||
* @returns {this} for chaining | ||
* @api public | ||
* @name alert | ||
*/ | ||
@@ -162,12 +162,65 @@ | ||
/** | ||
* .device (token) | ||
* ### .set (key, value) | ||
* | ||
* Set extra key values that will be incuded | ||
* as part of the payload. `aps` is reserved by | ||
* Apple and `enc` is reserved by apnagent. | ||
* | ||
* Is a key/value you pair is provided it will | ||
* be set. If an object is provided, all data points | ||
* will be merged into the current payload. | ||
* | ||
* ```js | ||
* // single value | ||
* msg.set('key', 'value'); | ||
* | ||
* // multiple values | ||
* msg.set({ | ||
* key1: 'value1' | ||
* , key2: 'value2' | ||
* }); | ||
* | ||
* // or chainable | ||
* msg | ||
* .set('key1', 'value1') | ||
* .set('key2', 'value2'); | ||
* ``` | ||
* | ||
* @param {String|Object} string key or object of custom settings | ||
* @param {Mixed} value (when first argument is string) | ||
* @returns {this} for chaining | ||
* @api public | ||
* @name set | ||
*/ | ||
Message.prototype.set = function (key, value) { | ||
if ('object' === typeof key) { | ||
for (var name in key) { | ||
this.set(name, key[name]); | ||
} | ||
} else { | ||
if (key === 'aps') return; | ||
this.payload[key] = value; | ||
} | ||
return this; | ||
}; | ||
/** | ||
* ### .device (token) | ||
* | ||
* Set the device that this message is to be delivered | ||
* to. Device can be provided as a string or buffer. If | ||
* provided as a string, it expected hex compatible string, | ||
* with each 32bit (4 octet) group seperated by spaces. | ||
* provided as a string, it will be sanitized of spaces | ||
* and extra characters (such as `<` and `>`). | ||
* | ||
* @param {String|Buffer} device token | ||
* ```js | ||
* msg.device('a1b2c3'); | ||
* msg.device('<a1b2c3>'); | ||
* ``` | ||
* | ||
* @param {apnagent.Device|String|Buffer} device token | ||
* @returns {this} for chaining | ||
* @api public | ||
* @name device | ||
*/ | ||
@@ -188,8 +241,8 @@ | ||
/** | ||
* .expires (time) | ||
* ### .expires (time) | ||
* | ||
* Set the message expiration date when being used | ||
* with the enhanced codec. If you are composing a | ||
* message using the service API, you can set the | ||
* default expiration to have this automatically populated. | ||
* with the enhanced codec. The default value is `0` which | ||
* will indicate to Apple to only attempt to deliver | ||
* the message once. | ||
* | ||
@@ -199,7 +252,16 @@ * Should be provided as the number of ms until expiration | ||
* | ||
* See APNS documentation for more information. | ||
* ```js | ||
* // set to specific time in future | ||
* msg.expires('30m'); // 30 minutes | ||
* msg.expires('1d'); // 1 day | ||
* | ||
* // reset to default value | ||
* msg.expires(0); | ||
* msg.expires(true); | ||
* ``` | ||
* | ||
* @param {Number|String} time until expiration | ||
* @returns {this} for chaining | ||
* @api public | ||
* @name expires | ||
*/ | ||
@@ -226,10 +288,14 @@ | ||
/** | ||
* .badge (number) | ||
* ### .badge (number) | ||
* | ||
* Set the badge number to be displayed if the | ||
* message is delivered while the application is closed. | ||
* Set the badge number to be displayed. | ||
* | ||
* ```js | ||
* msg.badge(4); | ||
* ``` | ||
* | ||
* @param {Number} badge count | ||
* @returns {this} for chaining | ||
* @api public | ||
* @name badge | ||
*/ | ||
@@ -243,3 +309,3 @@ | ||
/** | ||
* .sound (file) | ||
* ### .sound (file) | ||
* | ||
@@ -249,3 +315,5 @@ * Set the sound file to be played when this message | ||
* | ||
* See APNS documenation for more informatino. | ||
* ```js | ||
* msg.sound('bingbong.aiff'); | ||
* ``` | ||
* | ||
@@ -255,2 +323,3 @@ * @param {String} sound file | ||
* @api public | ||
* @name sound | ||
*/ | ||
@@ -263,3 +332,3 @@ | ||
/** | ||
/*! | ||
* .serialize () | ||
@@ -355,8 +424,27 @@ * | ||
/** | ||
* .send (cb) | ||
* ### .send (cb) | ||
* | ||
* Hook to not break the chainable interface when | ||
* wanting to send a message. | ||
* Send the message through the connected agent. The `cb` | ||
* function will be invoked with an error if there is | ||
* a problem serializing the message for transport. | ||
* | ||
* If there are no serialization errors, the callback | ||
* will be invoked when the message has been flushed | ||
* through the socket. This does NOT mean the message | ||
* has be received by the device or that Apple has | ||
* accepted the message. If Apple has a problem with | ||
* the message it will be emitted on the agent's | ||
* `message:error` event. | ||
* | ||
* ```js | ||
* msg.send(function (err) { | ||
* if (err) { | ||
* // handle it | ||
* } | ||
* }); | ||
* ``` | ||
* | ||
* @param {Function} callback | ||
* @api public | ||
* @name send | ||
*/ | ||
@@ -363,0 +451,0 @@ |
/*! | ||
* apnagent - util | ||
* Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com> | ||
* Copyright(c) 2012-2013 Jake Luer <jake@qualiancy.com> | ||
* MIT Licensed | ||
@@ -5,0 +5,0 @@ */ |
{ | ||
"name": "apnagent" | ||
, "version": "0.5.0" | ||
, "description": "Node adapter for Apple Push Notification (APN) Service." | ||
, "author": "Jake Luer <jake@alogicalpardox.com> (http://alogicalparadox.com)" | ||
, "version": "1.0.0" | ||
, "description": "Node adapter for Apple Push Notification (APN) service." | ||
, "author": "Jake Luer <jake@qualiancy.com> (http://qualiancy.com)" | ||
, "license": "MIT" | ||
, "homepage": "http://apnagent.qualiancy.com" | ||
, "contributors": [ | ||
"Jake Luer <jake@alogicalparadox.com>" | ||
, "Veselin Todorov <hi@vesln.com>" | ||
"Jake Luer <jake@qualiancy.com>" | ||
] | ||
@@ -22,4 +22,7 @@ , "keywords": [ | ||
"type": "git" | ||
, "url": "git@github.com:logicalparadox/apnagent.git" | ||
, "url": "git@github.com:qualiancy/apnagent.git" | ||
} | ||
, "bugs": { | ||
"url": "https://github.com/qualiancy/apnagent/issues" | ||
} | ||
, "engines": { | ||
@@ -36,4 +39,4 @@ "node": ">= 0.8.0" | ||
, "drip": "1.1.x" | ||
, "facet": "0.3.x" | ||
, "lotus": "0.4.x" | ||
, "facet": "0.4.x" | ||
, "lotus": "1.0.x" | ||
, "tea-error": "0.1.x" | ||
@@ -40,0 +43,0 @@ , "tea-extend": "0.2.x" |
@@ -1,4 +0,4 @@ | ||
# APN Agent [![Build Status](https://travis-ci.org/logicalparadox/apnagent.png?branch=master)](https://travis-ci.org/logicalparadox/apnagent) | ||
# APN Agent [![Build Status](https://travis-ci.org/qualiancy/apnagent.png?branch=master)](https://travis-ci.org/qualiancy/apnagent) | ||
> Node adapater for Apple Push Notification (APN) Service. | ||
> Node adapater for Apple Push Notification (APN) service. | ||
@@ -12,6 +12,2 @@ #### Features | ||
#### Coming Soon | ||
- documenation website | ||
#### Related Projects | ||
@@ -31,3 +27,3 @@ | ||
Copyright (c) 2012-2013 Jake Luer <jake@alogicalparadox.com> | ||
Copyright (c) 2012-2013 Jake Luer <jake@qualiancy.com> | ||
@@ -34,0 +30,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy |
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
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
64733
2166
1
1
45
+ Addedcore-util-is@1.0.3(transitive)
+ Addedfacet@0.4.0(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedisarray@0.0.1(transitive)
+ Addedlotus@1.0.1(transitive)
+ Addedreadable-stream@1.0.34(transitive)
+ Addedstring_decoder@0.10.31(transitive)
- Removedfacet@0.3.0(transitive)
- Removedlotus@0.4.1(transitive)
Updatedfacet@0.4.x
Updatedlotus@1.0.x