Comparing version 0.1.1 to 0.2.0
0.2.0 / 2013-01-15 | ||
================== | ||
* docs: update readme and package contribs | ||
* message: [send] pseudo-alias to msg._agent.send(this, cb) | ||
* Merge branch 'feature/reconnect' | ||
* test: [agent] should be able to reconnect | ||
* agent: [connect] support for reconnnect | ||
* Merge branch 'feature/events' | ||
* agent: events, custom errors, and improved codec lookup | ||
* errors: add custom errors and expose via exports.errors | ||
0.1.1 / 2013-01-12 | ||
@@ -3,0 +15,0 @@ ================== |
@@ -11,3 +11,3 @@ /*! | ||
exports.version = '0.1.1'; | ||
exports.version = '0.2.0'; | ||
@@ -19,1 +19,7 @@ /*! | ||
exports.Agent = require('./apnagent/agent'); | ||
/*! | ||
* Errors | ||
*/ | ||
exports.errors = require('./apnagent/errors'); |
@@ -24,2 +24,3 @@ /*! | ||
var codecs = require('./codecs') | ||
, errors = require('./errors') | ||
, Message = require('./message') | ||
@@ -65,4 +66,7 @@ | ||
this.connected = false; | ||
this.gatewayOpts = null; | ||
this.disable('sandbox'); | ||
this.set('codec', 'simple'); | ||
this.enable('reconnect'); | ||
this.set('reconnect delay', 3000); | ||
@@ -125,2 +129,4 @@ // queue handles writing of already packaged buffers to gateway | ||
Agent.prototype.connect = function (cb) { | ||
cb = cb || function () {}; | ||
var self = this | ||
@@ -153,7 +159,10 @@ , opts = {} | ||
// convert CA to array | ||
copy('ca'); | ||
if (opts.ca) opts.ca = [ opts.ca ]; | ||
// apply ca certificate | ||
if (this.get('ca')) { | ||
copy('ca'); | ||
opts.ca = [ opts.ca ]; | ||
} | ||
debug('initializing connection to %s:%d', opts.host, opts.port); | ||
debug('gateway initializing connection to %s:%d', opts.host, opts.port); | ||
this.gatewayOpts = opts; | ||
@@ -163,10 +172,13 @@ // connect to tls service using opts | ||
if (gateway.authorized) { | ||
debug('secure connection established to %s:%d', opts.host, opts.port); | ||
debug('gateway connection established to %s:%d', opts.host, opts.port); | ||
self.connected = true; | ||
self.queue.resume(); | ||
self.emit([ 'gateway', 'connect' ], opts.host, opts.port); | ||
cb(); | ||
} else { | ||
debug('secure connection denied to %s:%d', opts.host, opts.port); | ||
debug('gateway connection denied to %s:%d', opts.host, opts.port, gateway.authorizationError); | ||
self.gateway.destroy(); | ||
cb(new Error(gateway.authorizationError)); | ||
var err = new errors.GatewayAuthorizationError(gateway.authorizationError); | ||
self.emit([ 'gateway', 'error' ], err); | ||
cb(err); | ||
} | ||
@@ -177,12 +189,36 @@ }); | ||
gateway.on('close', function () { | ||
debug('secure connection closed to %s:%d', opts.host, opts.port); | ||
self.queue.pause(); | ||
self.gatewayOpts = null; | ||
self.gateway = null; | ||
// if user DID trigger disconnect | ||
if (!self.connected) { | ||
debug('gateway connection closed to %s:%d', opts.host, opts.port); | ||
self.emit([ 'gateway', 'close' ]); | ||
} | ||
// if user DID NOT trigger disconnect | ||
else if (self.connected && self.enabled('reconnect')) { | ||
debug('gateway connection unexpectedly closed to %s:%d', opts.host, opts.port); | ||
setTimeout(function () { | ||
debug('gateway triggering reconnect'); | ||
self.connect(function () { | ||
var host = self.gatewayOpts.host | ||
, port = self.gatewayOpts.port; | ||
debug('gateway reconnected successful to %s:%d', host, port); | ||
self.emit([ 'gateway', 'reconnect' ], host, port); | ||
}); | ||
}, self.get('reconnect delay')); | ||
} | ||
self.connected = false; | ||
self.gateway = null; | ||
}); | ||
// emit errors; | ||
gateway.on('error', function (err) { | ||
throw err; | ||
debug('gateway socket error: %s', err.message || 'Unspecified Error'); | ||
self.emit([ 'gateway', 'error' ], err); | ||
}); | ||
// mount | ||
this.gateway = gateway; | ||
@@ -218,2 +254,9 @@ }; | ||
Agent.prototype.close = function () { | ||
var host = this.enabled('sandbox') | ||
? APNS_SANDBOX | ||
: APNS_PROD; | ||
debug('closing gateway connection to %s:%d', host, APNS_PORT); | ||
this.connected = false; | ||
this.queue.pause(); | ||
this.gateway.destroy(); | ||
@@ -243,3 +286,3 @@ }; | ||
// handle error | ||
function callback (err) { | ||
function error (err) { | ||
process.nextTick(function () { | ||
@@ -252,4 +295,4 @@ debug('serialize message failed: %s', err.message); | ||
// check for codec | ||
if ('undefined' === typeof codec) { | ||
callback(new Error('Invalid codec')); | ||
if (!~[ 0, 1 ].indexOf(codec)) { | ||
error(new errors.SerializationError('Invalid codec: ' + codecStr, null, arguments.callee)); | ||
return this; | ||
@@ -262,3 +305,3 @@ } | ||
} catch (ex) { | ||
callback(ex); | ||
error(ex); | ||
return this; | ||
@@ -265,0 +308,0 @@ } |
@@ -28,5 +28,9 @@ /*! | ||
exports.getInterface = function (name, interface) { | ||
return codecs.filter(function (codec) { | ||
var codec = codecs.filter(function (codec) { | ||
return name === codec.name; | ||
})[0].mod[interface]; | ||
})[0]; | ||
return codec | ||
? codec.mod[interface] | ||
: undefined; | ||
}; | ||
@@ -48,5 +52,9 @@ | ||
exports.getId = function (name) { | ||
return codecs.filter(function (codec) { | ||
var codec = codecs.filter(function (codec) { | ||
return name === codec.name; | ||
})[0].id; | ||
})[0]; | ||
return codec | ||
? codec.id | ||
: undefined; | ||
}; | ||
@@ -53,0 +61,0 @@ |
@@ -8,3 +8,3 @@ /*! | ||
/*! | ||
* Internal module dependancies | ||
* Module dependancies | ||
*/ | ||
@@ -14,2 +14,6 @@ | ||
/*! | ||
* Internal dependencies | ||
*/ | ||
var util = require('./util'); | ||
@@ -332,1 +336,16 @@ | ||
}; | ||
/** | ||
* .send (cb) | ||
* | ||
* Hook to not break the chainable interface when | ||
* wanting to send a message. | ||
* | ||
* @param {Function} callback | ||
*/ | ||
Message.prototype.send = function (cb) { | ||
cb = cb || function () {}; | ||
if (!this._agent) return cb(new Error('Agent not associated with message.')); | ||
this._agent.send(this, cb); | ||
}; |
{ | ||
"name": "apnagent" | ||
, "version": "0.1.1" | ||
, "description": "Node adapter for Apple Push Notification Service" | ||
, "version": "0.2.0" | ||
, "description": "Node adapter for Apple Push Notification (APN) Service." | ||
, "author": "Jake Luer <jake@alogicalpardox.com> (http://alogicalparadox.com)" | ||
, "license": "MIT" | ||
, "contributors": [ | ||
"Jake Luer <jake@alogicalparadox.com>" | ||
, "Veselin Todorov <hi@vesln.com>" | ||
] | ||
, "keywords": [ | ||
@@ -33,2 +37,3 @@ "apn" | ||
, "tea-extend": "0.2.x" | ||
, "tea-error": "0.1.x" | ||
, "sherlock": "*" | ||
@@ -35,0 +40,0 @@ } |
# APN Agent | ||
> Node service adapater for Apple Push Notification (APN) Service. | ||
> Node adapater for Apple Push Notification (APN) Service. | ||
Project under heavy development. Will be release onto NPM soon. | ||
#### Features | ||
- chainable message builder | ||
- support for both simple and enhanced apple message protocol | ||
- easy sandbox mode | ||
- continuous connection and auto-reconnect on timeout | ||
#### Coming Soon | ||
- feature complete mock agent for local-only testing/development | ||
- apn feedback service integration | ||
- documenation website | ||
#### Related Projects | ||
- [apnagent-ios](https://github.com/logicalparadox/apnagent-ios): Tiny iOS application for use with the example(s). | ||
## Installation | ||
`apnagent` is available for [node.js](http://nodejs.org) on [npm](http://npmjs.org). | ||
$ npm install apnagent | ||
#### License | ||
@@ -11,3 +32,3 @@ | ||
Copyright (c) 2012 Jake Luer <jake@alogicalparadox.com> | ||
Copyright (c) 2012-2013 Jake Luer <jake@alogicalparadox.com> | ||
@@ -14,0 +35,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
23167
13
769
51
7
+ Addedtea-error@0.1.x
+ Addedtea-error@0.1.0(transitive)