{"_id":"apprunner","_rev":"78-8626d94cba21b435fa24bbc8b9797365","name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","dist-tags":{"latest":"0.2.11"},"versions":{"0.0.0":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","app"],"version":"0.0.0","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.31"},"dependencies":{"haraldutil":">= 0.1.5"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage"},"readme":"# App Runner\n\nApp Runner allows to to generate and maintain many apps using shared code. Require is great, App Runner is greater!\n\nApp Runner does three things:\n* Provides loadable apis\n* Manages application errors\n* Emails anomaly reports\n\nWhy App Runner? App Runner is App Lego.\n\nIf you make many Web apps and you have several of them for example accessing Facebook or using the same type of database, App Runner enables you to architect that in a repeatable pattern. App Runner allows you to use json to configure where code comes from and its settings.\n\n# Reference\n\nApp Runner handles process exceptions and SIGINT.\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## initApp(defaults, app, cb)\n\n* defaults: options, typically loaded by haraldops\n\n  * .init.appFolder: string: the folder of initial script\n  * .init.logger: optional function(string): logging, default console.log\n  * .init.ops.sendMail: optional function(subject, body): Sends mail, default none\n  * .api: optional, indicates that Api Manager should be used\n  * .api.apiMap: api configurations\n\n* app: Web server, has .on and .get methods\n* cb(err): optional function\n\n## getApi(opts, cb)\n\nget an api implementation\n* opts: object\n* .api: string: name of api function to be loaded\n* cb(err, module)\n\nAPIs are either configured directly in opts, or in defaults provided at App Runner init\n\nIf module has module.emitter, APp Runner will listen and manage error events\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and if so configured a periodcal email.\n\n## enableAnomalyMail(flag)\n\ncontrol emailing on or off: flag: boolean, default: false\n\n## getCbCounter()\nEnsures that all callbacks has completed\n\n```js\nvar haraldutil = require('haraldutil')\nvar cbc = haraldutil.getCbCounter()\nsetTimeout(cbc.add(callback), 100)\nsetTimeout(cbc.add(callback), 100)\n\nfunction callback() {\n  if (cbc.isDone(arguments.callee))\n    console.log('All callbacks completed.')\n  else console.log('Not done yet...')\n}\n```\n```\nNot done yet...\nAll callbacks completed.\n```\nvar cbc = getCbCounter(opts)\n* opts: optional object\n* opts.emitter: optional event emitter or boolean. default: errors are thrown\n\n  * false: errors are ignored\n  * emitter: errors are emitted\n\n* opts.callback: function or array of function: add is done for each function\n\ncbc: object\n* .add(f): adds a callback for function f, return value: f\n* .isDone(f): notes one callback completed. returns true if all callbacks complete, otherwise false\n* .getStatus(): gets an object representing the current state\n\n# Examples\n\nTODO\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","_id":"apprunner@0.0.0","dist":{"shasum":"1de308269c86b01a3942d50105a8175b3ff3d01a","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.0.0.tgz","integrity":"sha512-qvX+M68sa+a1I5F1AwDB7MXS4O4TRgEdAv+qU4WRgx/P4JarkTt1mh1wKMqjEQGyiCg7TPBtdwB3Gks+Z3NJbQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCaTlfMgNi4Kt/uuxOUvPEXN/IC966tFeDDsw7acsXkJQIgGGGGq7Lf5Wqg1Pok37NL2PyqdQKhD9KV9Luv4SVp15g="}]},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.0.1":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","app"],"version":"0.0.1","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.31"},"dependencies":{"haraldutil":">= 0.1.5"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage"},"readme":"# App Runner\n\nApp Runner allows to to generate and maintain many apps using shared code. Require is great, App Runner is greater!\n\nApp Runner does three things:\n* Provides loadable apis\n* Manages application errors\n* Emails anomaly reports\n\nWhy App Runner? App Runner is App Lego.\n\nIf you make many Web apps and you have several of them for example accessing Facebook or using the same type of database, App Runner enables you to architect that in a repeatable pattern. App Runner allows you to use json to configure where code comes from and its settings.\n\n# Reference\n\nApp Runner handles process exceptions and SIGINT.\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## initApp(defaults, app, cb)\n\n* defaults: options, typically loaded by haraldops\n\n  * .init.appFolder: string: the folder of initial script\n  * .init.logger: optional function(string): logging, default console.log\n  * .init.ops.sendMail: optional function(subject, body): Sends mail, default none\n  * .api: optional, indicates that Api Manager should be used\n  * .api.apiMap: api configurations\n\n* app: Web server, has .on and .get methods\n* cb(err): optional function\n\n## getApi(opts, cb)\n\nget an api implementation\n* opts: object\n* .api: string: name of api function to be loaded\n* cb(err, module)\n\nAPIs are either configured directly in opts, or in defaults provided at App Runner init\n\nIf module has module.emitter, APp Runner will listen and manage error events\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and if so configured a periodcal email.\n\n## enableAnomalyMail(flag)\n\ncontrol emailing on or off: flag: boolean, default: false\n\n## getCbCounter()\nEnsures that all callbacks has completed\n\n```js\nvar haraldutil = require('haraldutil')\nvar cbc = haraldutil.getCbCounter()\nsetTimeout(cbc.add(callback), 100)\nsetTimeout(cbc.add(callback), 100)\n\nfunction callback() {\n  if (cbc.isDone(arguments.callee))\n    console.log('All callbacks completed.')\n  else console.log('Not done yet...')\n}\n```\n```\nNot done yet...\nAll callbacks completed.\n```\nvar cbc = getCbCounter(opts)\n* opts: optional object\n* opts.emitter: optional event emitter or boolean. default: errors are thrown\n\n  * false: errors are ignored\n  * emitter: errors are emitted\n\n* opts.callback: function or array of function: add is done for each function\n\ncbc: object\n* .add(f): adds a callback for function f, return value: f\n* .isDone(f): notes one callback completed. returns true if all callbacks complete, otherwise false\n* .getStatus(): gets an object representing the current state\n\n# Examples\n\nTODO\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","_id":"apprunner@0.0.1","dist":{"shasum":"1d46d282d2a6b42b01c59492427eff94311090f8","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.0.1.tgz","integrity":"sha512-xlvFeOWAgwWB1khMTZPZZN7sI52xixFkX09r5Xs/zhp9nyYMFhf+Zr5Cl3+gsDfNJI8eRu3LdLd++c0D+WSI7w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAv8bWiFdP5u5zqIlCokgIgruJfhJ3sZjVt/k33ua+HXAiAfmTDtJyV5kAUJVaNeIttkfEEiFL8uUn0fHwfNLAJLsw=="}]},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.0.2":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","app"],"version":"0.0.2","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.31"},"dependencies":{"haraldutil":">= 0.1.5"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage"},"readme":"# App Runner\n\nApp Runner allows to to generate and maintain many apps using shared code. Require is great, App Runner is greater!\n\nApp Runner does three things:\n* Provides loadable apis\n* Manages application errors\n* Emails anomaly reports\n\nWhy App Runner? App Runner is App Lego.\n\nIf you make many Web apps and you have several of them for example accessing Facebook or using the same type of database, App Runner enables you to architect that in a repeatable pattern. App Runner allows you to use json to configure where code comes from and its settings.\n\n## Benefits\n\n1. Load of a module now has callback and can signal load error.\n2. Each module (api) can have its location and configuration defined in json.\n3. Large volumes of errors can be emitted and properly communicated.\n4. Reported errors does not kill the app or affect its execution.\n5. Each api can register uri routes, but does not depend on a particular Web server.\n6. Unhandled exceptions are communicated similar to errors.\n7. SIGINT signal gracefully shuts down the application.\n\n# Reference\n\nApp Runner handles process exceptions and SIGINT.\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## initApp(defaults, app, cb)\n\n* defaults: options, typically loaded by haraldops\n\n  * .init.appFolder: string: the folder of initial script\n  * .init.logger: optional function(string): logging, default console.log\n  * .init.ops.sendMail: optional function(subject, body): Sends mail, default none\n  * .api: optional, indicates that Api Manager should be used\n  * .api.apiMap: api configurations\n\n* app: Web server, has .on and .get methods\n* cb(err): optional function\n\n## getApi(opts, cb)\n\nget an api implementation\n* opts: object\n* .api: string: name of api function to be loaded\n* cb(err, module)\n\nAPIs are either configured directly in opts, or in defaults provided at App Runner init\n\nIf module has module.emitter, APp Runner will listen and manage error events\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and if so configured a periodcal email.\n\n## enableAnomalyMail(flag)\n\ncontrol emailing on or off: flag: boolean, default: false\n\n## getCbCounter()\nEnsures that all callbacks has completed\n\n```js\nvar haraldutil = require('haraldutil')\nvar cbc = haraldutil.getCbCounter()\nsetTimeout(cbc.add(callback), 100)\nsetTimeout(cbc.add(callback), 100)\n\nfunction callback() {\n  if (cbc.isDone(arguments.callee))\n    console.log('All callbacks completed.')\n  else console.log('Not done yet...')\n}\n```\n```\nNot done yet...\nAll callbacks completed.\n```\nvar cbc = getCbCounter(opts)\n* opts: optional object\n* opts.emitter: optional event emitter or boolean. default: errors are thrown\n\n  * false: errors are ignored\n  * emitter: errors are emitted\n\n* opts.callback: function or array of function: add is done for each function\n\ncbc: object\n* .add(f): adds a callback for function f, return value: f\n* .isDone(f): notes one callback completed. returns true if all callbacks complete, otherwise false\n* .getStatus(): gets an object representing the current state\n\n# Examples\n\nTODO\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","_id":"apprunner@0.0.2","dist":{"shasum":"592bef4372482a3d855fa1d188254e012407a3c9","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.0.2.tgz","integrity":"sha512-VhW1iUK6EYBspZRWFft+3LVHOk0b4zLrLiIBlLhMIH/hmnBJde7oj5gbqlFW42DcCWCKzdlYKfbs7/8rgM0fpw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDuRH9o/zUMRMYrTcsfccMyR7hbEMkY7126CHk+UG7IFgIgTbHmXEdSBPXJGlRdqKgynWwXfwFB+Wh4nFBJ/zWmzIc="}]},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.0.3":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","app"],"version":"0.0.3","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.31"},"dependencies":{"haraldutil":">= 0.1.5"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage"},"readme":"# App Runner\n\nApp Runner allows to to generate and maintain many apps using shared code. Require is great, App Runner is greater!\n\nApp Runner does three things:\n* Provides loadable apis\n* Manages application errors\n* Emails anomaly reports\n\nWhy App Runner? App Runner is App Lego.\n\nIf you make many Web apps and you have several of them for example accessing Facebook or using the same type of database, App Runner enables you to architect that in a repeatable pattern. App Runner allows you to use json to configure where code comes from and its settings.\n\n## Benefits\n\n1. Load of a module now has callback and can signal load error.\n2. Each module (api) can have its location and configuration defined in json.\n3. Large volumes of errors can be emitted and properly communicated.\n4. Reported errors does not kill the app or affect its execution.\n5. Each api can register uri routes, but does not depend on a particular Web server.\n6. Unhandled exceptions are communicated similar to errors.\n7. SIGINT signal gracefully shuts down the application.\n\n# Reference\n\nApp Runner handles process exceptions and SIGINT.\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## initApp(defaults, app, cb)\n\n* defaults: options, typically loaded by haraldops\n\n  * .init.appFolder: string: the folder of initial script\n  * .init.logger: optional function(string): logging, default console.log\n  * .init.ops.sendMail: optional function(subject, body): Sends mail, default none\n  * .api: optional, indicates that Api Manager should be used\n  * .api.apiMap: api configurations\n\n* app: Web server, has .on and .get methods\n* cb(err): optional function\n\n## getApi(opts, cb)\n\nget an api implementation\n* opts: object\n* .api: string: name of api function to be loaded\n* cb(err, module)\n\nAPIs are either configured directly in opts, or in defaults provided at App Runner init\n\nIf module has module.emitter, APp Runner will listen and manage error events\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and if so configured a periodcal email.\n\n## enableAnomalyMail(flag)\n\ncontrol emailing on or off: flag: boolean, default: false\n\n## getCbCounter()\nEnsures that all callbacks has completed\n\n```js\nvar haraldutil = require('haraldutil')\nvar cbc = haraldutil.getCbCounter()\nsetTimeout(cbc.add(callback), 100)\nsetTimeout(cbc.add(callback), 100)\n\nfunction callback() {\n  if (cbc.isDone(arguments.callee))\n    console.log('All callbacks completed.')\n  else console.log('Not done yet...')\n}\n```\n```\nNot done yet...\nAll callbacks completed.\n```\nvar cbc = getCbCounter(opts)\n* opts: optional object\n* opts.emitter: optional event emitter or boolean. default: errors are thrown\n\n  * false: errors are ignored\n  * emitter: errors are emitted\n\n* opts.callback: function or array of function: add is done for each function\n\ncbc: object\n* .add(f): adds a callback for function f, return value: f\n* .isDone(f): notes one callback completed. returns true if all callbacks complete, otherwise false\n* .getStatus(): gets an object representing the current state\n\n# Examples\n\nTODO\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","_id":"apprunner@0.0.3","dist":{"shasum":"b6789619db0e592966316e8c4bde0453d0695734","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.0.3.tgz","integrity":"sha512-ya4AsP1HOimVX7vJ8tAQhF4qGlB8dqjRbyqxb7ICeOFiFy5gB9BibJIO0DudejLXu4PxG2YpiaMwTwW4pnsW3w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIENY5bEtZECSa2i1Hq+HXU37Fyj0YUFiGVGwL/iniJNCAiBSi3xhDmFY7FW4XHCWIkgtGaMSVSWJSTaP2SPM3uFKqw=="}]},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.0.4":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","app"],"version":"0.0.4","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.31"},"dependencies":{"haraldutil":">= 0.1.5"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage"},"readme":"# App Runner\n\nApp Runner allows to to generate and maintain many apps using shared code. Require is great, App Runner is greater!\n\nApp Runner does three things:\n* Provides loadable apis\n* Manages application errors\n* Emails anomaly reports\n\nWhy App Runner? App Runner is App Lego.\n\nIf you make many Web apps and you have several of them for example accessing Facebook or using the same type of database, App Runner enables you to architect that in a repeatable pattern. App Runner allows you to use json to configure where code comes from and its settings.\n\n## Benefits\n\n1. Load of a module now has callback and can signal load error.\n2. Each module (api) can have its location and configuration defined in json.\n3. Large volumes of errors can be emitted and properly communicated.\n4. Reported errors does not kill the app or affect its execution.\n5. Each api can register uri routes, but does not depend on a particular Web server.\n6. Unhandled exceptions are communicated similar to errors.\n7. SIGINT signal gracefully shuts down the application.\n\n# Reference\n\nApp Runner handles process exceptions and SIGINT.\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## initApp(defaults, app, cb)\n\n* defaults: options, typically loaded by haraldops\n\n  * .init.appFolder: string: the folder of initial script\n  * .init.logger: optional function(string): logging, default console.log\n  * .init.ops.sendMail: optional function(subject, body): Sends mail, default none\n  * .api: optional, indicates that Api Manager should be used\n  * .api.apiMap: api configurations\n\n* app: Web server, has .on and .get methods\n* cb(err): optional function\n\n## getApi(opts, cb)\n\nget an api implementation\n* opts: object\n* .api: string: name of api function to be loaded\n* cb(err, module)\n\nAPIs are either configured directly in opts, or in defaults provided at App Runner init\n\nIf module has module.emitter, APp Runner will listen and manage error events\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and if so configured a periodcal email.\n\n## enableAnomalyMail(flag)\n\ncontrol emailing on or off: flag: boolean, default: false\n\n## getCbCounter()\nEnsures that all callbacks has completed\n\n```js\nvar haraldutil = require('haraldutil')\nvar cbc = haraldutil.getCbCounter()\nsetTimeout(cbc.add(callback), 100)\nsetTimeout(cbc.add(callback), 100)\n\nfunction callback() {\n  if (cbc.isDone(arguments.callee))\n    console.log('All callbacks completed.')\n  else console.log('Not done yet...')\n}\n```\n```\nNot done yet...\nAll callbacks completed.\n```\nvar cbc = getCbCounter(opts)\n* opts: optional object\n* opts.emitter: optional event emitter or boolean. default: errors are thrown\n\n  * false: errors are ignored\n  * emitter: errors are emitted\n\n* opts.callback: function or array of function: add is done for each function\n\ncbc: object\n* .add(f): adds a callback for function f, return value: f\n* .isDone(f): notes one callback completed. returns true if all callbacks complete, otherwise false\n* .getStatus(): gets an object representing the current state\n\n# Examples\n\nTODO\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","_id":"apprunner@0.0.4","dist":{"shasum":"1e375f770ec4feb2b7ad6a01738823622871213f","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.0.4.tgz","integrity":"sha512-vULMP8SxXNfZoxVUYbwLU9kCtukK27T9+2l9qWLdbk8PurQqjgEIBoniOhYLfaiPUUl6MPGZRe4NFQL+geJJww==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFUfrecD93svl9Pq/2unxYcwGP3p9osPeyXd1j/lrflaAiEAhb9bAv9RCZR91mCFW04se9q3JJ2HDBps5EZkINs74OY="}]},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.0.5":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","app"],"version":"0.0.5","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.31"},"dependencies":{"haraldutil":">= 0.1.5"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage"},"readme":"# App Runner\n\nApp Runner allows to to generate and maintain many apps using shared code. Require is great, App Runner is greater!\n\nApp Runner does three things:\n* Provides api control in json\n* Manages application errors\n* Emails anomaly reports\n\nWhy App Runner? App Runner is App Lego.\n\nIf you make many Web apps and you have several of them for example accessing Facebook or using the same type of database, App Runner enables you to architect that in a repeatable pattern. App Runner allows you to use json to configure where code comes from and its settings.\n\n## Benefits\n\n1. Apis can be moved between project files and external modules with no code change.\n2. One or many apis per file or module.\n2. Configuration information provided to apis from code and json.\n3. Apis can emit large volumes of errors that is properly communicated.\n4. Reported errors does not kill the app or affect its execution.\n5. Each api can register uri routes, but does not depend on a particular Web server imlementation.\n6. Unhandled process exceptions are communicated similarly to errors.\n7. SIGINT signal gracefully shuts down the application.\n\n# Reference\n\nApp Runner handles process exceptions and SIGINT.\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## initApp(defaults, app, cb)\n\n* defaults: options, typically loaded by haraldops\n\n  * .init.appFolder: string: the folder of initial script\n  * .init.logger: optional function(string): logging, default console.log\n  * .init.ops.sendMail: optional function(subject, body): Sends mail, default none\n  * .api: optional, indicates that Api Manager should be used\n  * .api.apiMap: api configurations\n\n* app: Web server, has .on and .get methods\n* cb(err): optional function\n\n## getApi(opts, cb)\n\nget an api implementation\n* opts: object\n* .api: string: name of api function to be loaded\n* cb(err, module)\n\nAPIs are either configured directly in opts, or in defaults provided at App Runner init\n\nIf module has module.emitter, APp Runner will listen and manage error events\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and if so configured a periodcal email.\n\n## enableAnomalyMail(flag)\n\ncontrol emailing on or off: flag: boolean, default: false\n\n## getCbCounter()\nEnsures that all callbacks has completed\n\n```js\nvar haraldutil = require('haraldutil')\nvar cbc = haraldutil.getCbCounter()\nsetTimeout(cbc.add(callback), 100)\nsetTimeout(cbc.add(callback), 100)\n\nfunction callback() {\n  if (cbc.isDone(arguments.callee))\n    console.log('All callbacks completed.')\n  else console.log('Not done yet...')\n}\n```\n```\nNot done yet...\nAll callbacks completed.\n```\nvar cbc = getCbCounter(opts)\n* opts: optional object\n* opts.emitter: optional event emitter or boolean. default: errors are thrown\n\n  * false: errors are ignored\n  * emitter: errors are emitted\n\n* opts.callback: function or array of function: add is done for each function\n\ncbc: object\n* .add(f): adds a callback for function f, return value: f\n* .isDone(f): notes one callback completed. returns true if all callbacks complete, otherwise false\n* .getStatus(): gets an object representing the current state\n\n# Examples\n\nTODO\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","_id":"apprunner@0.0.5","dist":{"shasum":"1a514aceca813d84cc5167ae49d37b0c00565c95","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.0.5.tgz","integrity":"sha512-o7kRpzflZcHf2QSbcSwbM9UdmGngT/Y5CiU8t8XaCOAK4eKD020eE+7Ts5meolNgBUOSsNB7pJc/iyuv1NfVYg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGvozGPZPsNByRCXkm8BMsU7zZljplQtDrYCMZkgxoP/AiEA2yLpPyLIINrg9oiGJspWC1m3ET6peXwnUHhjnlL4gfI="}]},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.0.6":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","app"],"version":"0.0.6","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.31"},"dependencies":{"haraldutil":">= 0.1.5"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage"},"readme":"# App Runner\n\nApp Runner allows to to generate and maintain many apps using shared code. Require is great, App Runner is greater!\n\nApp Runner does three things:\n* Provides api control in json\n* Manages application errors\n* Emails anomaly reports\n\nWhy App Runner? App Runner is App Lego.\n\nIf you make many Web apps and you have several of them for example accessing Facebook or using the same type of database, App Runner enables you to architect that in a repeatable pattern. App Runner allows you to use json to configure where code comes from and its settings.\n\n## Benefits\n\n1. Apis can be moved between project files and external modules with no code change.\n2. One or many apis per file or module.\n2. Configuration information provided to apis from code and json.\n3. Apis can emit large volumes of errors that is properly communicated.\n4. Reported errors does not kill the app or affect its execution.\n5. Each api can register uri routes, but does not depend on a particular Web server imlementation.\n6. Unhandled process exceptions are communicated similarly to errors.\n7. SIGINT signal gracefully shuts down the application.\n\n# Reference\n\nApp Runner handles process exceptions and SIGINT.\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## initApp(defaults, app, cb)\n\n* defaults: options, typically loaded by haraldops\n\n  * .init.appFolder: string: the folder of initial script\n  * .init.logger: optional function(string): logging, default console.log\n  * .init.ops.sendMail: optional function(subject, body): Sends mail, default none\n  * .api: optional, indicates that Api Manager should be used\n  * .api.apiMap: api configurations\n\n* app: Web server, has .on and .get methods\n* cb(err): optional function\n\n## getApi(opts, cb)\n\nget an api implementation\n* opts: object\n* .api: string: name of api function to be loaded\n* cb(err, module)\n\nAPIs are either configured directly in opts, or in defaults provided at App Runner init.\n\nSettings either in json or in opts:\n* .file specifies basic require, default is './' + .api\n* if basic require begins with '.' it is resolved agains appFolder/lib or defaults.api.folder\n* .subPath is period-separated paths in the loaded module, default none\n* .apiExport is the export used to initialize\n* if function, it is invoked, and the module result is its return value\n* if value, it is used as an error emitter, return value is module.subPath\n* if false, module.subPath is returned\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and if so configured a periodcal email.\n\n## enableAnomalyMail(flag)\n\ncontrol emailing on or off: flag: boolean, default: false\n\n## getCbCounter()\nEnsures that all callbacks has completed\n\n```js\nvar haraldutil = require('haraldutil')\nvar cbc = haraldutil.getCbCounter()\nsetTimeout(cbc.add(callback), 100)\nsetTimeout(cbc.add(callback), 100)\n\nfunction callback() {\n  if (cbc.isDone(arguments.callee))\n    console.log('All callbacks completed.')\n  else console.log('Not done yet...')\n}\n```\n```\nNot done yet...\nAll callbacks completed.\n```\nvar cbc = getCbCounter(opts)\n* opts: optional object\n* opts.emitter: optional event emitter or boolean. default: errors are thrown\n\n  * false: errors are ignored\n  * emitter: errors are emitted\n\n* opts.callback: function or array of function: add is done for each function\n\ncbc: object\n* .add(f): adds a callback for function f, return value: f\n* .isDone(f): notes one callback completed. returns true if all callbacks complete, otherwise false\n* .getStatus(): gets an object representing the current state\n\n# Examples\n\nTODO\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","_id":"apprunner@0.0.6","dist":{"shasum":"1986250ceb0cfe762f3df621fad8b023ae6334c8","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.0.6.tgz","integrity":"sha512-pyuZgL9weReu9Od2vifRFyXq2a+bYUvEc0MG01jvzP7ARrIIOqiutf16qFh0c9QrFHH7/BByt2B9aF3X2G9KwA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCk+vHGXuaWkgFPx6eH5l0y7k4quyePnNH2vVq9/KOL3QIhAKNd/rJOAVPaYbLUEAozzEsySNRi5OPYluGP48bqAuD7"}]},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.0.7":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","app"],"version":"0.0.7","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.31"},"dependencies":{"haraldutil":">= 0.1.5"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage"},"readme":"# App Runner\n\nApp Runner allows to to generate and maintain many apps using shared code. Require is great, App Runner is greater!\n\nApp Runner does three things:\n* Provides module control from json\n* Manages application errors and reporting\n* Handle lifecycle of the app and its modules\n\nWhy App Runner? App Runner is App Lego.\n\nIf you make many Web apps for example accessing Facebook or the same database, App Runner enables you to architect in a repeatable pattern. App Runner allows you to use json to configure where code comes from and its settings.\n\n## Benefits\n\n1. Apis can be moved between project files and external modules with no code change.\n2. One or many apis per file or module.\n2. Configuration information provided to apis from code and json.\n3. Apis can emit large volumes of errors that is properly communicated.\n4. Reported errors does not kill the app or affect its execution.\n5. Each api can register uri routes, but does not depend on a particular Web server implementation.\n6. Unhandled process exceptions are communicated similarly to errors.\n7. SIGINT signal gracefully shuts down the application.\n8. Apis can communciate delayed readiness, and provide shutdown hooks\n\n# Reference\n\nApp Runner handles process exceptions and SIGINT.\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## initApp(defaults, app)\n\n* defaults: options, typically loaded by haraldops\n\n  * .init.appFolder: string: the folder of initial script\n  * .init.logger: optional function(string): logging, default console.log\n  * .init.ops.sendMail: optional function(subject, body): Sends mail, default none\n  * .api: optional, indicates that Api Manager should be used\n  * .api.apiMap: optional: api configurations\n\n* app: Web server, could be an event emitter and have a .get method\n\n## getApi(opts)\n\nExample of using a proprietary serverhelp api, that manages Express lifecycle as an api.\n\n```js\nrequire('apprunner')\n\t.getApi({api: 'serverhelp'})\n\t.listen({\n\t\tserver: app,\n\t\tport: defaults.PORT,\n\t\tinterface: defaults.appInterface},\n\tcbc.add(appIsUp))\n```\n\ngets an api implementation\n* opts: object\n* .api: string: name of api function to be loaded\n\nAPIs are either configured directly in the opts object, or in defaults provided at App Runner's init.\n\n## apisReady(cb)\n\nSurveys all loaded apis to see if they have concluded initializing. Each api can expose an apiReady(cb) function used fo this purpose.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and if so configured a periodcal email.\n\n## enableAnomalyMail(flag)\n\ncontrol emailing on or off: flag: boolean, default: false\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an endApi function gets this invoked prior to process.exit\n\n## getCbCounter()\nEnsures that all callbacks has completed\n\n```js\nvar apprunner = require('apprunner')\nvar cbc = haraldutil.getCbCounter()\nsetTimeout(cbc.add(callback), 100)\nsetTimeout(cbc.add(callback), 100)\n\nfunction callback() {\n  if (cbc.isDone(arguments.callee))\n    console.log('All callbacks completed.')\n  else console.log('Not done yet...')\n}\n```\n```\nNot done yet...\nAll callbacks completed.\n```\nvar cbc = getCbCounter(opts)\n* opts: optional object\n* opts.emitter: optional event emitter or boolean. default: errors are thrown\n\n  * false: errors are ignored\n  * emitter: errors are emitted\n\n* opts.callback: function or array of function: add is done for each function\n\ncbc: object\n* .add(f): adds a callback for function f, return value: f\n* .isDone(f): notes one callback completed. returns true if all callbacks complete, otherwise false\n* .getStatus(): gets an object representing the current state\n\n# Configuring and Writing an Api Module\n\nConfigurations for an api is provided either in defaults or in the opts\n\nAs a minimum, the opts object needs to contain the api property: `getApi({api: 'userstore'})`\n\nAn Api's location is determined by two properties:\n\n1. .file: the same value you would provide to require\n2. .subPath: dot-separated property access inside the module loaded by require\n\nIf file is missing some special steps are taken:\n3. If file is missing, the default filename is the api name.\n4. defaults.api.folder can provide a default folder used if file begings with '.' or is missing\n5. If no folder is provided, the lib folder in appFolder is used.\n\nThe api module itself can have four optional special exports:\n* initApi(opts): code executed on the first load of the api processing the options. May return a value that is used in place of the regular module value\n* apiReady(cb(err)) calls back when the api is ready to provide service\n* endApi(cb(err)) instructs the api to shut down, ie. close connections and clear timers\n* emitter if this is an EventEmitter, errors emitted are processed as anomalies\n\n# Examples\n\nTODO\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","_id":"apprunner@0.0.7","dist":{"shasum":"2ce9d421ce9857cf4aa74ca23406affb665a032d","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.0.7.tgz","integrity":"sha512-NLVAWtuexsLARmdPZL+0luECBTg2WFSuuX66lecttKF5H0N6Wv5KYAIGf+ZPb2LZLaw84Ol5LcZ3uhO0RG8E3w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCIPx6rDdfbPL+WDe1ndKKTBRrTeFp5C/g2KxJpMiIfyAIgD2iF0q9o6abuA2y63f+digOTT747sJNMm+bMjslXAHQ="}]},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.0.9":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","app"],"version":"0.0.9","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.31"},"dependencies":{"haraldutil":">= 0.1.5"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage"},"readme":"# App Runner\n\nApp Runner allows to to generate and maintain many apps using shared code. Require is great, App Runner is greater!\n\nApp Runner does three things:\n* Provides module control from json\n* Manages application errors and reporting\n* Handle lifecycle of the app and its modules\n\nWhy App Runner? App Runner is App Lego.\n\nIf you make many Web apps for example accessing Facebook or the same database, App Runner enables you to architect in a repeatable pattern. App Runner allows you to use json to configure where code comes from and its settings.\n\n## Benefits\n\n1. Apis can be moved between project files and external modules with no code change.\n2. One or many apis per file or module.\n2. Configuration information provided to apis from code and json.\n3. Apis can emit large volumes of errors that is properly communicated.\n4. Reported errors does not kill the app or affect its execution.\n5. Each api can register uri routes, but does not depend on a particular Web server implementation.\n6. Unhandled process exceptions are communicated similarly to errors.\n7. SIGINT signal gracefully shuts down the application.\n8. Apis can communciate delayed readiness, and provide shutdown hooks\n\n# Reference\n\nApp Runner handles process exceptions and SIGINT.\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## initApp(defaults, app)\n\n* defaults: options, typically loaded by haraldops\n\n  * .init.appFolder: string: the folder of initial script\n  * .init.logger: optional function(string): logging, default console.log\n  * .init.ops.sendMail: optional function(subject, body): Sends mail, default none\n  * .api: optional, indicates that Api Manager should be used\n  * .api.apiMap: optional: api configurations\n\n* app: Web server, could be an event emitter and have a .get method\n\n## getApi(opts)\n\nExample of using a proprietary serverhelp api, that manages Express lifecycle as an api.\n\n```js\nrequire('apprunner')\n\t.getApi({api: 'serverhelp'})\n\t.listen({\n\t\tserver: app,\n\t\tport: defaults.PORT,\n\t\tinterface: defaults.appInterface},\n\tcbc.add(appIsUp))\n```\n\ngets an api implementation\n* opts: object\n* .api: string: name of api function to be loaded\n\nAPIs are either configured directly in the opts object, or in defaults provided at App Runner's init.\n\n## apisReady(cb)\n\nSurveys all loaded apis to see if they have concluded initializing. Each api can expose an apiReady(cb) function used fo this purpose.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and if so configured a periodcal email.\n\n## enableAnomalyMail(flag)\n\ncontrol emailing on or off: flag: boolean, default: false\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an endApi function gets this invoked prior to process.exit\n\n## getCbCounter()\nEnsures that all callbacks has completed\n\n```js\nvar apprunner = require('apprunner')\nvar cbc = haraldutil.getCbCounter()\nsetTimeout(cbc.add(callback), 100)\nsetTimeout(cbc.add(callback), 100)\n\nfunction callback() {\n  if (cbc.isDone(arguments.callee))\n    console.log('All callbacks completed.')\n  else console.log('Not done yet...')\n}\n```\n```\nNot done yet...\nAll callbacks completed.\n```\nvar cbc = getCbCounter(opts)\n* opts: optional object\n* opts.emitter: optional event emitter or boolean. default: errors are thrown\n\n  * false: errors are ignored\n  * emitter: errors are emitted\n\n* opts.callback: function or array of function: add is done for each function\n\ncbc: object\n* .add(f): adds a callback for function f, return value: f\n* .isDone(f): notes one callback completed. returns true if all callbacks complete, otherwise false\n* .getStatus(): gets an object representing the current state\n\n# Configuring and Writing an Api Module\n\nConfigurations for an api is provided either in defaults or in the opts\n\n## Retrieving an api\n\nAs a minimum, the opts object needs to contain the api property: `getApi({api: 'userstore'})`\n\n## How the api is loaded\n\nAn Api's location is determined by two properties:\n\n1. .file: the same value you would provide to require\n2. .subPath: dot-separated property access inside the module loaded by require\n\nIf file is missing some special steps are taken:\n\n1. If file is missing, the default filename is the api name.\n2. defaults.api.folder can provide a default folder used if file begings with '.' or is missing\n3. If no folder is provided, the lib folder in appFolder is used.\n\n## The api module\n\nThe api module itself can have four optional special exports:\n* initApi(opts): code executed on the first load of the api processing the options. May return a value that is used in place of the regular module value\n* apiReady(cb(err)) calls back when the api is ready to provide service\n* endApi(cb(err)) instructs the api to shut down, ie. close connections and clear timers\n* emitter if this is an EventEmitter, errors emitted are processed as anomalies\n\n## Execution of initApi\n\nif your api exports initApi, ths function is invoked on each require. This is because options may change, and you need to take this in account.\n\ninitApi is provided an options object:\n\n* .config: object: the merge of options providing to getApi and options in apiMap. getApi options overrride\n* .registerHandler(string route, handler(req, res, next)): registers a route with whatever Web server is used. \n* .logger: function(string): the logging to be used\n* .apprunner: object: the apprunner module for convenience\n\nif initApi returns a value, this is used as the result of getApi().\n\n# Examples\n\nTODO\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","_id":"apprunner@0.0.9","dist":{"shasum":"b806093a5d2c2f426849f2352a0fcfb47b56ee67","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.0.9.tgz","integrity":"sha512-zQ8Njq34CI1eC+nFdTguCQJoGMjm8DPge7hTp/nAOnbSBo2KlZ1LWJVKr/dY1YW2sYRJ4aNjfZS1UPO8CZzuTQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAqVlAcriOiLRriBly87l9E3/Pcc5Ha1Yh+9c1n8iP8ZAiEAjEQIKcsnsnyLc6xHh7eDmcxo9MsZ6EelBRnh/EQcu48="}]},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.0.10":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","app"],"version":"0.0.10","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.31"},"dependencies":{"haraldutil":">= 0.1.5"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage"},"readme":"# App Runner\n\nApp Runner allows to to generate and maintain many apps using shared code. Require is great, App Runner is greater!\n\nApp Runner does three things:\n* Provides module control from json\n* Manages application errors and reporting\n* Handle lifecycle of the app and its modules\n\nWhy App Runner? App Runner is App Lego.\n\nIf you make many Web apps for example accessing Facebook or the same database, App Runner enables you to architect in a repeatable pattern. App Runner allows you to use json to configure where code comes from and its settings.\n\n## Benefits\n\n1. Apis can be moved between project files and external modules with no code change.\n2. One or many apis per file or module.\n2. Configuration information provided to apis from code and json.\n3. Apis can emit large volumes of errors that is properly communicated.\n4. Reported errors does not kill the app or affect its execution.\n5. Each api can register uri routes, but does not depend on a particular Web server implementation.\n6. Unhandled process exceptions are communicated similarly to errors.\n7. SIGINT signal gracefully shuts down the application.\n8. Apis can communciate delayed readiness, and provide shutdown hooks\n\n# Reference\n\nApp Runner handles process exceptions and SIGINT.\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## initApp(defaults, app)\n\n* defaults: options, typically loaded by haraldops\n\n  * .init.appFolder: string: the folder of initial script\n  * .init.logger: optional function(string): logging, default console.log\n  * .init.ops.sendMail: optional function(subject, body): Sends mail, default none\n  * .api: optional, indicates that Api Manager should be used\n  * .api.apiMap: optional: api configurations\n\n* app: Web server, could be an event emitter and have a .get method\n\n## getApi(opts)\n\nExample of using a proprietary serverhelp api, that manages Express lifecycle as an api.\n\n```js\nrequire('apprunner')\n\t.getApi({api: 'serverhelp'})\n\t.listen({\n\t\tserver: app,\n\t\tport: defaults.PORT,\n\t\tinterface: defaults.appInterface},\n\tcbc.add(appIsUp))\n```\n\ngets an api implementation\n* opts: object\n* .api: string: name of api function to be loaded\n\nAPIs are either configured directly in the opts object, or in defaults provided at App Runner's init.\n\n## apisReady(cb)\n\nSurveys all loaded apis to see if they have concluded initializing. Each api can expose an apiReady(cb) function used fo this purpose.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and if so configured a periodcal email.\n\n## enableAnomalyMail(flag)\n\ncontrol emailing on or off: flag: boolean, default: false\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an endApi function gets this invoked prior to process.exit\n\n## getCbCounter()\nEnsures that all callbacks has completed\n\n```js\nvar apprunner = require('apprunner')\nvar cbc = haraldutil.getCbCounter()\nsetTimeout(cbc.add(callback), 100)\nsetTimeout(cbc.add(callback), 100)\n\nfunction callback() {\n  if (cbc.isDone(arguments.callee))\n    console.log('All callbacks completed.')\n  else console.log('Not done yet...')\n}\n```\n```\nNot done yet...\nAll callbacks completed.\n```\nvar cbc = getCbCounter(opts)\n* opts: optional object\n* opts.emitter: optional event emitter or boolean. default: errors are thrown\n\n  * false: errors are ignored\n  * emitter: errors are emitted\n\n* opts.callback: function or array of function: add is done for each function\n\ncbc: object\n* .add(f): adds a callback for function f, return value: f\n* .isDone(f): notes one callback completed. returns true if all callbacks complete, otherwise false\n* .getStatus(): gets an object representing the current state\n\n# Configuring and Writing an Api Module\n\nConfigurations for an api is provided either in defaults or in the opts\n\n## Retrieving an api\n\nAs a minimum, the opts object needs to contain the api property: `getApi({api: 'userstore'})`\n\n## How the api is loaded\n\nAn Api's location is determined by two properties:\n\n1. .file: the same value you would provide to require\n2. .subPath: dot-separated property access inside the module loaded by require\n\nIf file is missing some special steps are taken:\n\n1. If file is missing, the default filename is the api name.\n2. defaults.api.folder can provide a default folder used if file begings with '.' or is missing\n3. If no folder is provided, the lib folder in appFolder is used.\n\n## The api module\n\nThe api module itself can have four optional special exports:\n* initApi(opts): code executed on the first load of the api processing the options. May return a value that is used in place of the regular module value\n* apiReady(cb(err)) calls back when the api is ready to provide service\n* endApi(cb(err)) instructs the api to shut down, ie. close connections and clear timers\n* emitter if this is an EventEmitter, errors emitted are processed as anomalies\n\n## Execution of initApi\n\nif your api exports initApi, ths function is invoked on each require. This is because options may change, and you need to take this in account.\n\ninitApi is provided an options object:\n\n* .config: object: the merge of options providing to getApi and options in apiMap. getApi options overrride\n* .registerHandler(string route, handler(req, res, next)): registers a route with whatever Web server is used. \n* .logger: function(string): the logging to be used\n* .apprunner: object: the apprunner module for convenience\n\nif initApi returns a value, this is used as the result of getApi().\n\n# Examples\n\nTODO\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","_id":"apprunner@0.0.10","dist":{"shasum":"99b62e606773a0d44d3c9f4d8a6683b94e48379d","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.0.10.tgz","integrity":"sha512-z9HjFFgWvNE+ykyZ65xHUnrgWTtmFfyzV44BgEnxYB2sAbligQSAUM11Eq8MbZJJ32RSq92Hp9QtHPOQMDJU5A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBq40soK7eXxu1C6I8JcdA72ak80diXSOaw2cGtZTiE5AiEA1aTzEpYfPza2vqIFkaphsFl3KcDXVDF/TZ+B+/dfTV8="}]},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.0.11":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","app"],"version":"0.0.11","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.31"},"dependencies":{"haraldutil":">= 0.1.5"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage"},"readme":"# App Runner\n\nApp Runner allows to to generate and maintain many apps using shared code. Require is great, App Runner is greater!\n\nApp Runner does three things:\n* Provides module control from json\n* Manages application errors and reporting\n* Handle lifecycle of the app and its modules\n\nWhy App Runner? App Runner is App Lego.\n\nIf you make many Web apps for example accessing Facebook or the same database, App Runner enables you to architect in a repeatable pattern. App Runner allows you to use json to configure where code comes from and its settings.\n\n## Benefits\n\n1. Apis can be moved between project files and external modules with no code change.\n2. One or many apis per file or module.\n2. Configuration information provided to apis from code and json.\n3. Apis can emit large volumes of errors that is properly communicated.\n4. Reported errors does not kill the app or affect its execution.\n5. Each api can register uri routes, but does not depend on a particular Web server implementation.\n6. Unhandled process exceptions are communicated similarly to errors.\n7. SIGINT signal gracefully shuts down the application.\n8. Apis can communciate delayed readiness, and provide shutdown hooks\n\n# Reference\n\nApp Runner handles process exceptions and SIGINT.\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## initApp(defaults, app)\n\n* defaults: options, typically loaded by haraldops\n\n  * .init.appFolder: string: the folder of initial script\n  * .init.logger: optional function(string): logging, default console.log\n  * .init.ops.sendMail: optional function(subject, body): Sends mail, default none\n  * .api: optional, indicates that Api Manager should be used\n  * .api.apiMap: optional: api configurations\n\n* app: Web server, could be an event emitter and have a .get method\n\n## getApi(opts)\n\nExample of using a proprietary serverhelp api, that manages Express lifecycle as an api.\n\n```js\nrequire('apprunner')\n\t.getApi({api: 'serverhelp'})\n\t.listen({\n\t\tserver: app,\n\t\tport: defaults.PORT,\n\t\tinterface: defaults.appInterface},\n\tcbc.add(appIsUp))\n```\n\ngets an api implementation\n* opts: object\n* .api: string: name of api function to be loaded\n\nAPIs are either configured directly in the opts object, or in defaults provided at App Runner's init.\n\n## apisReady(cb)\n\nSurveys all loaded apis to see if they have concluded initializing. Each api can expose an apiReady(cb) function used fo this purpose.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and if so configured a periodcal email.\n\n## enableAnomalyMail(flag)\n\ncontrol emailing on or off: flag: boolean, default: false\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an endApi function gets this invoked prior to process.exit\n\n## getCbCounter()\nEnsures that all callbacks has completed\n\n```js\nvar apprunner = require('apprunner')\nvar cbc = haraldutil.getCbCounter()\nsetTimeout(cbc.add(callback), 100)\nsetTimeout(cbc.add(callback), 100)\n\nfunction callback() {\n  if (cbc.isDone(arguments.callee))\n    console.log('All callbacks completed.')\n  else console.log('Not done yet...')\n}\n```\n```\nNot done yet...\nAll callbacks completed.\n```\nvar cbc = getCbCounter(opts)\n* opts: optional object\n* opts.emitter: optional event emitter or boolean. default: errors are thrown\n\n  * false: errors are ignored\n  * emitter: errors are emitted\n\n* opts.callback: function or array of function: add is done for each function\n\ncbc: object\n* .add(f): adds a callback for function f, return value: f\n* .isDone(f): notes one callback completed. returns true if all callbacks complete, otherwise false\n* .getStatus(): gets an object representing the current state\n\n# Configuring and Writing an Api Module\n\nConfigurations for an api is provided either in defaults or in the opts\n\n## Retrieving an api\n\nAs a minimum, the opts object needs to contain the api property: `getApi({api: 'userstore'})`\n\n## How the api is loaded\n\nAn Api's location is determined by two properties:\n\n1. .file: the same value you would provide to require\n2. .subPath: dot-separated property access inside the module loaded by require\n\nIf file is missing some special steps are taken:\n\n1. If file is missing, the default filename is the api name.\n2. defaults.api.folder can provide a default folder used if file begings with '.' or is missing\n3. If no folder is provided, the lib folder in appFolder is used.\n\n## The api module\n\nThe api module itself can have four optional special exports:\n* initApi(opts): code executed on the first load of the api processing the options. May return a value that is used in place of the regular module value\n* apiReady(cb(err)) calls back when the api is ready to provide service\n* endApi(cb(err)) instructs the api to shut down, ie. close connections and clear timers\n* emitter if this is an EventEmitter, errors emitted are processed as anomalies\n\n## Execution of initApi\n\nif your api exports initApi, ths function is invoked on each require. This is because options may change, and you need to take this in account.\n\ninitApi is provided an options object:\n\n* .config: object: the merge of options providing to getApi and options in apiMap. getApi options overrride\n* .registerHandler(string route, handler(req, res, next)): registers a route with whatever Web server is used. \n* .logger: function(string): the logging to be used\n* .apprunner: object: the apprunner module for convenience\n\nif initApi returns a value, this is used as the result of getApi().\n\n# Examples\n\nTODO\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","_id":"apprunner@0.0.11","dist":{"shasum":"67fd4cb8af58f6c58509bbed6dd9aa71f88185ab","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.0.11.tgz","integrity":"sha512-FwXslN5ncH3xnN2GlO5zy7woF2xMQEH4KO+NOq3sMFY5YZnmKIw4ICvQvN32Ie6exmDN0VA9Rj8r//OhIs9Aiw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDKkf6aXLL2C1HdWu8LdddOj8/Ba4VTFFb3g+l7Xj1XNQIgfUxlMwgTt9PVBrNkGYiHuSj8NG4RWxyslX/TaDamHrI="}]},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.0.12":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","app"],"version":"0.0.12","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.31"},"dependencies":{"haraldutil":">= 0.1.5"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage"},"readme":"# App Runner\n\nApp Runner allows to to generate and maintain many apps using shared code. Require is great, App Runner is greater!\n\nApp Runner does three things:\n* Provides module control from json\n* Manages application errors and reporting\n* Handle lifecycle of the app and its modules\n\nWhy App Runner? App Runner is App Lego.\n\nIf you make many Web apps for example accessing Facebook or the same database, App Runner enables you to architect in a repeatable pattern. App Runner allows you to use json to configure where code comes from and its settings.\n\n## Benefits\n\n1. Apis can be moved between project files and external modules with no code change.\n2. One or many apis per file or module.\n2. Configuration information provided to apis from code and json.\n3. Apis can emit large volumes of errors that is properly communicated.\n4. Reported errors does not kill the app or affect its execution.\n5. Each api can register uri routes, but does not depend on a particular Web server implementation.\n6. Unhandled process exceptions are communicated similarly to errors.\n7. SIGINT signal gracefully shuts down the application.\n8. Apis can communciate delayed readiness, and provide shutdown hooks\n\n# Reference\n\nApp Runner handles process exceptions and SIGINT.\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## initApp(defaults, app)\n\n* defaults: options, typically loaded by haraldops\n\n  * .init.appFolder: string: the folder of initial script\n  * .init.logger: optional function(string): logging, default console.log\n  * .init.ops.sendMail: optional function(subject, body): Sends mail, default none\n  * .api: optional, indicates that Api Manager should be used\n  * .api.apiMap: optional: api configurations\n\n* app: Web server, could be an event emitter and have a .get method\n\n## getApi(opts)\n\nExample of using a proprietary serverhelp api, that manages Express lifecycle as an api.\n\n```js\nrequire('apprunner')\n\t.getApi({api: 'serverhelp'})\n\t.listen({\n\t\tserver: app,\n\t\tport: defaults.PORT,\n\t\tinterface: defaults.appInterface},\n\tcbc.add(appIsUp))\n```\n\ngets an api implementation\n* opts: object\n* .api: string: name of api function to be loaded\n\nAPIs are either configured directly in the opts object, or in defaults provided at App Runner's init.\n\n## apisReady(cb)\n\nSurveys all loaded apis to see if they have concluded initializing. Each api can expose an apiReady(cb) function used fo this purpose.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and if so configured a periodcal email.\n\n## enableAnomalyMail(flag)\n\ncontrol emailing on or off: flag: boolean, default: false\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an endApi function gets this invoked prior to process.exit\n\n## getCbCounter()\nEnsures that all callbacks has completed\n\n```js\nvar apprunner = require('apprunner')\nvar cbc = haraldutil.getCbCounter()\nsetTimeout(cbc.add(callback), 100)\nsetTimeout(cbc.add(callback), 100)\n\nfunction callback() {\n  if (cbc.isDone(arguments.callee))\n    console.log('All callbacks completed.')\n  else console.log('Not done yet...')\n}\n```\n```\nNot done yet...\nAll callbacks completed.\n```\nvar cbc = getCbCounter(opts)\n* opts: optional object\n* opts.emitter: optional event emitter or boolean. default: errors are thrown\n\n  * false: errors are ignored\n  * emitter: errors are emitted\n\n* opts.callback: function or array of function: add is done for each function\n\ncbc: object\n* .add(f): adds a callback for function f, return value: f\n* .isDone(f): notes one callback completed. returns true if all callbacks complete, otherwise false\n* .getStatus(): gets an object representing the current state\n\n# Configuring and Writing an Api Module\n\nConfigurations for an api is provided either in defaults or in the opts\n\n## Retrieving an api\n\nAs a minimum, the opts object needs to contain the api property: `getApi({api: 'userstore'})`\n\n## How the api is loaded\n\nAn Api's location is determined by two properties:\n\n1. .file: the same value you would provide to require\n2. .subPath: dot-separated property access inside the module loaded by require\n\nIf file is missing some special steps are taken:\n\n1. If file is missing, the default filename is the api name.\n2. defaults.api.folder can provide a default folder used if file begings with '.' or is missing\n3. If no folder is provided, the lib folder in appFolder is used.\n\n## The api module\n\nThe api module itself can have four optional special exports:\n* initApi(opts): code executed on the first load of the api processing the options. May return a value that is used in place of the regular module value\n* apiReady(cb(err)) calls back when the api is ready to provide service\n* endApi(cb(err)) instructs the api to shut down, ie. close connections and clear timers\n* emitter if this is an EventEmitter, errors emitted are processed as anomalies\n\n## Execution of initApi\n\nif your api exports initApi, ths function is invoked on each require. This is because options may change, and you need to take this in account.\n\ninitApi is provided an options object:\n\n* .config: object: the merge of options providing to getApi and options in apiMap. getApi options overrride\n* .registerHandler(string route, handler(req, res, next)): registers a route with whatever Web server is used. \n* .logger: function(string): the logging to be used\n* .apprunner: object: the apprunner module for convenience\n\nif initApi returns a value, this is used as the result of getApi().\n\n# Examples\n\nTODO\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","_id":"apprunner@0.0.12","dist":{"shasum":"8cd34f4c4e8b919c8725b87b439805b0234a33e8","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.0.12.tgz","integrity":"sha512-1DQcj27+1rvIxU7mMbjbH+pEAUqdvR2CeiF56pErXwmHAhc7QOuKodRRQCzQTInDzmigSHPyLJaPKs27tvljBQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC7MTTuXVBhlHr7jTgoRAV3CaN4A59r+CewDQ95WUor2QIgFQJyZoEFs3ZjkeeY1xKtIqJphjERYJhU0Uic6kCm4M0="}]},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.0.13":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","app"],"version":"0.0.13","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.31"},"dependencies":{"haraldutil":">= 0.1.5"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage"},"readme":"# App Runner\n\nApp Runner allows to to generate and maintain many apps using shared code. Require is great, App Runner is greater!\n\nApp Runner does three things:\n* Provides module control from json\n* Manages application errors and reporting\n* Handle lifecycle of the app and its modules\n\nWhy App Runner? App Runner is App Lego.\n\nIf you make many Web apps for example accessing Facebook or the same database, App Runner enables you to architect in a repeatable pattern. App Runner allows you to use json to configure where code comes from and its settings.\n\n## Benefits\n\n1. Apis can be moved between project files and external modules with no code change.\n2. One or many apis per file or module.\n2. Configuration information provided to apis from code and json.\n3. Apis can emit large volumes of errors that is properly communicated.\n4. Reported errors does not kill the app or affect its execution.\n5. Each api can register uri routes, but does not depend on a particular Web server implementation.\n6. Unhandled process exceptions are communicated similarly to errors.\n7. SIGINT signal gracefully shuts down the application.\n8. Apis can communciate delayed readiness, and provide shutdown hooks\n\n# Reference\n\nApp Runner handles process exceptions and SIGINT.\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## initApp(defaults, app)\n\n* defaults: options, typically loaded by haraldops\n\n  * .init.appFolder: string: the folder of initial script\n  * .init.logger: optional function(string): logging, default console.log\n  * .init.ops.sendMail: optional function(subject, body): Sends mail, default none\n  * .api: optional, indicates that Api Manager should be used\n  * .api.apiMap: optional: api configurations\n\n* app: Web server, could be an event emitter and have a .get method\n\n## getApi(opts)\n\nExample of using a proprietary serverhelp api, that manages Express lifecycle as an api.\n\n```js\nrequire('apprunner')\n\t.getApi({api: 'serverhelp'})\n\t.listen({\n\t\tserver: app,\n\t\tport: defaults.PORT,\n\t\tinterface: defaults.appInterface},\n\tcbc.add(appIsUp))\n```\n\ngets an api implementation\n* opts: object\n* .api: string: name of api function to be loaded\n\nAPIs are either configured directly in the opts object, or in defaults provided at App Runner's init.\n\n## apisReady(cb)\n\nSurveys all loaded apis to see if they have concluded initializing. Each api can expose an apiReady(cb) function used fo this purpose.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and if so configured a periodcal email.\n\n## enableAnomalyMail(flag)\n\ncontrol emailing on or off: flag: boolean, default: false\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an endApi function gets this invoked prior to process.exit\n\n## getCbCounter()\nEnsures that all callbacks has completed\n\n```js\nvar apprunner = require('apprunner')\nvar cbc = haraldutil.getCbCounter()\nsetTimeout(cbc.add(callback), 100)\nsetTimeout(cbc.add(callback), 100)\n\nfunction callback() {\n  if (cbc.isDone(arguments.callee))\n    console.log('All callbacks completed.')\n  else console.log('Not done yet...')\n}\n```\n```\nNot done yet...\nAll callbacks completed.\n```\nvar cbc = getCbCounter(opts)\n* opts: optional object\n* opts.emitter: optional event emitter or boolean. default: errors are thrown\n\n  * false: errors are ignored\n  * emitter: errors are emitted\n\n* opts.callback: function or array of function: add is done for each function\n\ncbc: object\n* .add(f): adds a callback for function f, return value: f\n* .isDone(f): notes one callback completed. returns true if all callbacks complete, otherwise false\n* .getStatus(): gets an object representing the current state\n\n# Configuring and Writing an Api Module\n\nConfigurations for an api is provided either in defaults or in the opts\n\n## Retrieving an api\n\nAs a minimum, the opts object needs to contain the api property: `getApi({api: 'userstore'})`\n\n## How the api is loaded\n\nAn Api's location is determined by two properties:\n\n1. .file: the same value you would provide to require\n2. .subPath: dot-separated property access inside the module loaded by require\n\nIf file is missing some special steps are taken:\n\n1. If file is missing, the default filename is the api name.\n2. defaults.api.folder can provide a default folder used if file begings with '.' or is missing\n3. If no folder is provided, the lib folder in appFolder is used.\n\n## The api module\n\nThe api module itself can have four optional special exports:\n* initApi(opts): code executed on the first load of the api processing the options. May return a value that is used in place of the regular module value\n* apiReady(cb(err)) calls back when the api is ready to provide service\n* endApi(cb(err)) instructs the api to shut down, ie. close connections and clear timers\n* emitter if this is an EventEmitter, errors emitted are processed as anomalies\n\n## Execution of initApi\n\nif your api exports initApi, ths function is invoked on each require. This is because options may change, and you need to take this in account.\n\ninitApi is provided an options object:\n\n* .config: object: the merge of options providing to getApi and options in apiMap. getApi options overrride\n* .registerHandler(string route, handler(req, res, next)): registers a route with whatever Web server is used. \n* .logger: function(string): the logging to be used\n* .apprunner: object: the apprunner module for convenience\n\nif initApi returns a value, this is used as the result of getApi().\n\n# Examples\n\nTODO\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","_id":"apprunner@0.0.13","dist":{"shasum":"9249560d403441fc8f3ddf70c03993b792d42a3c","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.0.13.tgz","integrity":"sha512-2b2gsYEPZAJIiRhPVU7+wBVFHzcw9d0qC8DUlAVQWQlPjf60Scy+yRydZ9nueu2ix3ng7LsFSokSJKCpm1gy4A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD/r/qSXjQNpfwSRXkLNwnBuex61PH74CB6pnI9/3UUCAIgaurUtPKrjlPBKog9vIIf2TJ6j7S3JP4xw59zI+7/x3Y="}]},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.0.14":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","app"],"version":"0.0.14","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.31"},"dependencies":{"haraldutil":">= 0.1.5"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage"},"readme":"# App Runner\n\nApp Runner allows to to generate and maintain many apps using shared code. Require is great, App Runner is greater!\n\nApp Runner does three things:\n* Provides module control from json\n* Manages application errors and reporting\n* Handle lifecycle of the app and its modules\n\nWhy App Runner? App Runner is App Lego.\n\nIf you make many Web apps for example accessing Facebook or the same database, App Runner enables you to architect in a repeatable pattern. App Runner allows you to use json to configure where code comes from and its settings.\n\n## Benefits\n\n1. Apis can be moved between project files and external modules with no code change.\n2. One or many apis per file or module.\n2. Configuration information provided to apis from code and json.\n3. Apis can emit large volumes of errors that is properly communicated.\n4. Reported errors does not kill the app or affect its execution.\n5. Each api can register uri routes, but does not depend on a particular Web server implementation.\n6. Unhandled process exceptions are communicated similarly to errors.\n7. SIGINT signal gracefully shuts down the application.\n8. Apis can communciate delayed readiness, and provide shutdown hooks\n\n# Reference\n\nApp Runner handles process exceptions and SIGINT.\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## initApp(defaults, app)\n\n* defaults: options, typically loaded by haraldops\n\n  * .init.appFolder: string: the folder of initial script\n  * .init.logger: optional function(string): logging, default console.log\n  * .init.ops.sendMail: optional function(subject, body): Sends mail, default none\n  * .api: optional, indicates that Api Manager should be used\n  * .api.apiMap: optional: api configurations\n\n* app: Web server, could be an event emitter and have a .get method\n\n## getApi(opts)\n\nExample of using a proprietary serverhelp api, that manages Express lifecycle as an api.\n\n```js\nrequire('apprunner')\n\t.getApi({api: 'serverhelp'})\n\t.listen({\n\t\tserver: app,\n\t\tport: defaults.PORT,\n\t\tinterface: defaults.appInterface},\n\tcbc.add(appIsUp))\n```\n\ngets an api implementation\n* opts: object\n* .api: string: name of api function to be loaded\n\nAPIs are either configured directly in the opts object, or in defaults provided at App Runner's init.\n\n## apisReady(cb)\n\nSurveys all loaded apis to see if they have concluded initializing. Each api can expose an apiReady(cb) function used fo this purpose.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and if so configured a periodcal email.\n\n## enableAnomalyMail(flag)\n\ncontrol emailing on or off: flag: boolean, default: false\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an endApi function gets this invoked prior to process.exit\n\n## getCbCounter()\nEnsures that all callbacks has completed\n\n```js\nvar apprunner = require('apprunner')\nvar cbc = haraldutil.getCbCounter()\nsetTimeout(cbc.add(callback), 100)\nsetTimeout(cbc.add(callback), 100)\n\nfunction callback() {\n  if (cbc.isDone(arguments.callee))\n    console.log('All callbacks completed.')\n  else console.log('Not done yet...')\n}\n```\n```\nNot done yet...\nAll callbacks completed.\n```\nvar cbc = getCbCounter(opts)\n* opts: optional object\n* opts.emitter: optional event emitter or boolean. default: errors are thrown\n\n  * false: errors are ignored\n  * emitter: errors are emitted\n\n* opts.callback: function or array of function: add is done for each function\n\ncbc: object\n* .add(f): adds a callback for function f, return value: f\n* .isDone(f): notes one callback completed. returns true if all callbacks complete, otherwise false\n* .getStatus(): gets an object representing the current state\n\n# Configuring and Writing an Api Module\n\nConfigurations for an api is provided either in defaults or in the opts\n\n## Retrieving an api\n\nAs a minimum, the opts object needs to contain the api property: `getApi({api: 'userstore'})`\n\n## How the api is loaded\n\nAn Api's location is determined by two properties:\n\n1. .file: the same value you would provide to require\n2. .subPath: dot-separated property access inside the module loaded by require\n\nIf file is missing some special steps are taken:\n\n1. If file is missing, the default filename is the api name.\n2. defaults.api.folder can provide a default folder used if file begings with '.' or is missing\n3. If no folder is provided, the lib folder in appFolder is used.\n\n## The api module\n\nThe api module itself can have four optional special exports:\n* initApi(opts): code executed on the first load of the api processing the options. May return a value that is used in place of the regular module value\n* apiReady(cb(err)) calls back when the api is ready to provide service\n* endApi(cb(err)) instructs the api to shut down, ie. close connections and clear timers\n* emitter if this is an EventEmitter, errors emitted are processed as anomalies\n\n## Execution of initApi\n\nif your api exports initApi, ths function is invoked on each require. This is because options may change, and you need to take this in account.\n\ninitApi is provided an options object:\n\n* .config: object: the merge of options providing to getApi and options in apiMap. getApi options overrride\n* .registerHandler(string route, handler(req, res, next)): registers a route with whatever Web server is used. \n* .logger: function(string): the logging to be used\n* .apprunner: object: the apprunner module for convenience\n\nif initApi returns a value, this is used as the result of getApi().\n\n# Examples\n\nTODO\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","_id":"apprunner@0.0.14","dist":{"shasum":"d759540dc11bae1e637fee48dca652243bfc3963","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.0.14.tgz","integrity":"sha512-VrvmG2TjASTefg0LNW85UitMBZXbxvcy3diQ20rOEkdlKFeEuD30G5Zjp8D4OSjnO5zQvTXnAo8mmhEg7wbv+w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICkSAv4WmrowxLe7+51OS5et4TbU9Fig/dlCirqfpvntAiEAtjNZaUN2cWasIZ0GU4iQT0gaKGyRDbJZGePWgPG6mnk="}]},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.0.15":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","app"],"version":"0.0.15","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.31"},"dependencies":{"haraldutil":">= 0.1.5"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage"},"readme":"# App Runner\n\nApp Runner manages app execution and error reporting and provides a unified way to separate and reuse modules. Require is great, App Runner is greater!\n\n## Benefits\n\n1. Move apis between project files and external modules with no code change, or switch implementation for a given api name\n2. Implement one or many apis per file or module.\n2. Configure apis both per invocation and json at launch.\n3. Find root causes by collecting large volumes of elaborate error reports featuring multiple stack traces, variable values and any other useful information.\n4. Continue best effort execution after error reporting.\n5. Server flexibility: apis can register uri routes, but do not depend on a particular Web server implementation.\n6. Gracefully terminate after unhandled process exceptions capturing elaborate error reports.\n7. Gracefully shut down the application on demand using SIGINT signal from keyboard Ctrl-Break or another process\n8. Gracefully launch using api delayed readiness hook\n9. Gracefully exit using api shutdown hook\n9. Track performance of external interfaces using invocation timers\n\n## Features\n\n1. Provides module control from json\n2. Manages application error reports and queues\n3. Lifecycle management of the app and its modules\n5. Single-module exposure of the entire app to the launch script\n\n# Reference\n\nApp Runner handles process exceptions and SIGINT.\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## initApp(defaults, app)\n\n* defaults: options, typically loaded by haraldops\n\n  * .init.appFolder: string: the folder of initial script\n  * .init.logger: optional function(string): logging, default console.log\n  * .init.ops.sendMail: optional function(subject, body): Sends mail, default none\n  * .api: optional, indicates that Api Manager should be used\n  * .api.apiMap: optional: api configurations\n\n* app: Web server, could be an event emitter and have a .get method\n\n## getApi(opts)\n\nExample of using a proprietary serverhelp api, that manages Express lifecycle as an api.\n\n```js\nrequire('apprunner')\n\t.getApi({api: 'serverhelp'})\n\t.listen({\n\t\tserver: app,\n\t\tport: defaults.PORT,\n\t\tinterface: defaults.appInterface},\n\tcbc.add(appIsUp))\n```\n\ngets an api implementation\n* opts: object\n* .api: string: name of api function to be loaded\n\nAPIs are either configured directly in the opts object, or in defaults provided at App Runner's init.\n\n## apisReady(cb)\n\nSurveys all loaded apis to see if they have concluded initializing. Each api can expose an apiReady(cb) function used fo this purpose.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and if so configured a periodcal email.\n\n## enableAnomalyMail(flag)\n\ncontrol emailing on or off: flag: boolean, default: false\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an endApi function gets this invoked prior to process.exit\n\n## getCbCounter()\nEnsures that all callbacks has completed\n\n```js\nvar apprunner = require('apprunner')\nvar cbc = haraldutil.getCbCounter()\nsetTimeout(cbc.add(callback), 100)\nsetTimeout(cbc.add(callback), 100)\n\nfunction callback() {\n  if (cbc.isDone(arguments.callee))\n    console.log('All callbacks completed.')\n  else console.log('Not done yet...')\n}\n```\n```\nNot done yet...\nAll callbacks completed.\n```\nvar cbc = getCbCounter(opts)\n* opts: optional object\n* opts.emitter: optional event emitter or boolean. default: errors are thrown\n\n  * false: errors are ignored\n  * emitter: errors are emitted\n\n* opts.callback: function or array of function: add is done for each function\n\ncbc: object\n* .add(f): adds a callback for function f, return value: f\n* .isDone(f): notes one callback completed. returns true if all callbacks complete, otherwise false\n* .getStatus(): gets an object representing the current state\n\n# Configuring and Writing an Api Module\n\nConfigurations for an api is provided either in defaults or in the opts\n\n## Retrieving an api\n\nAs a minimum, the opts object needs to contain the api property: `getApi({api: 'userstore'})`\n\n## How the api is loaded\n\nAn Api's location is determined by two properties:\n\n1. .file: the same value you would provide to require\n2. .subPath: dot-separated property access inside the module loaded by require\n\nIf file is missing some special steps are taken:\n\n1. If file is missing, the default filename is the api name.\n2. defaults.api.folder can provide a default folder used if file begings with '.' or is missing\n3. If no folder is provided, the lib folder in appFolder is used.\n\n## The api module\n\nThe api module itself can have four optional special exports:\n* initApi(opts): code executed on the first load of the api processing the options. May return a value that is used in place of the regular module value\n* apiReady(cb(err)) calls back when the api is ready to provide service\n* endApi(cb(err)) instructs the api to shut down, ie. close connections and clear timers\n* emitter if this is an EventEmitter, errors emitted are processed as anomalies\n\n## Execution of initApi\n\nif your api exports initApi, ths function is invoked on each require. This is because options may change, and you need to take this in account.\n\ninitApi is provided an options object:\n\n* .config: object: the merge of options providing to getApi and options in apiMap. getApi options overrride\n* .registerHandler(string route, handler(req, res, next)): registers a route with whatever Web server is used. \n* .logger: function(string): the logging to be used\n* .apprunner: object: the apprunner module for convenience\n\nif initApi returns a value, this is used as the result of getApi().\n\n# Examples\n\nTODO\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","_id":"apprunner@0.0.15","dist":{"shasum":"e0ace8f80a61eff7082700dce0b88d293fcd98a5","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.0.15.tgz","integrity":"sha512-oE1zfFsut4b4LNoqQa0spr4IzF4xWByfnaWae9BFDQ32zFQoqs1Q1QkKg1nOoKlvOXZjl0yyVCEW7oQZW06DoA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIESzST3B/0ZnsOrCi6m7JBK4WAce+1nYd0PnuZRWNGyPAiBsjVWISwhjXuwhx123kCLwWcTIPxql5lq1EXLQMNkoEw=="}]},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.0.16":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","app"],"version":"0.0.16","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.31"},"dependencies":{"haraldutil":">= 0.1.5"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage"},"readme":"# App Runner\n\nApp Runner manages app execution and error reporting and provides a unified way to separate and reuse modules. Require is great, App Runner is greater!\n\n## Benefits\n\n1. Move apis between project files and external modules with no code change, or switch implementation for a given api name\n2. Implement one or many apis per file or module.\n2. Configure apis both per invocation and json at launch.\n3. Find root causes by collecting large volumes of elaborate error reports featuring multiple stack traces, variable values and any other useful information.\n4. Continue best effort execution after error reporting.\n5. Server flexibility: apis can register uri routes, but do not depend on a particular Web server implementation.\n6. Gracefully terminate after unhandled process exceptions capturing elaborate error reports.\n7. Gracefully shut down the application on demand using SIGINT signal from keyboard Ctrl-Break or another process\n8. Gracefully launch using api delayed readiness hook\n9. Gracefully exit using api shutdown hook\n9. Track performance of external interfaces using invocation timers\n\n## Features\n\n1. Provides module control from json\n2. Manages application error reports and queues\n3. Lifecycle management of the app and its modules\n5. Single-module exposure of the entire app to the launch script\n\n# Reference\n\nApp Runner handles process exceptions and SIGINT.\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## initApp(defaults, app)\n\n* defaults: options, typically loaded by haraldops\n\n  * .init.appFolder: string: the folder of initial script\n  * .init.logger: optional function(string): logging, default console.log\n  * .init.ops.sendMail: optional function(subject, body): Sends mail, default none\n  * .api: optional, indicates that Api Manager should be used\n  * .api.apiMap: optional: api configurations\n\n* app: Web server, could be an event emitter and have a .get method\n\n## getApi(opts)\n\nExample of using a proprietary serverhelp api, that manages Express lifecycle as an api.\n\n```js\nrequire('apprunner')\n\t.getApi({api: 'serverhelp'})\n\t.listen({\n\t\tserver: app,\n\t\tport: defaults.PORT,\n\t\tinterface: defaults.appInterface},\n\tcbc.add(appIsUp))\n```\n\ngets an api implementation\n* opts: object\n* .api: string: name of api function to be loaded\n\nAPIs are either configured directly in the opts object, or in defaults provided at App Runner's init.\n\n## apisReady(cb)\n\nSurveys all loaded apis to see if they have concluded initializing. Each api can expose an apiReady(cb) function used fo this purpose.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and if so configured a periodcal email.\n\n## enableAnomalyMail(flag)\n\ncontrol emailing on or off: flag: boolean, default: false\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an endApi function gets this invoked prior to process.exit\n\n## getCbCounter()\nEnsures that all callbacks has completed\n\n```js\nvar apprunner = require('apprunner')\nvar cbc = haraldutil.getCbCounter()\nsetTimeout(cbc.add(callback), 100)\nsetTimeout(cbc.add(callback), 100)\n\nfunction callback() {\n  if (cbc.isDone(arguments.callee))\n    console.log('All callbacks completed.')\n  else console.log('Not done yet...')\n}\n```\n```\nNot done yet...\nAll callbacks completed.\n```\nvar cbc = getCbCounter(opts)\n* opts: optional object\n* opts.emitter: optional event emitter or boolean. default: errors are thrown\n\n  * false: errors are ignored\n  * emitter: errors are emitted\n\n* opts.callback: function or array of function: add is done for each function\n\ncbc: object\n* .add(f): adds a callback for function f, return value: f\n* .isDone(f): notes one callback completed. returns true if all callbacks complete, otherwise false\n* .getStatus(): gets an object representing the current state\n\n# Configuring and Writing an Api Module\n\nConfigurations for an api is provided either in defaults or in the opts\n\n## Retrieving an api\n\nAs a minimum, the opts object needs to contain the api property: `getApi({api: 'userstore'})`\n\n## How the api is loaded\n\nAn Api's location is determined by two properties:\n\n1. .file: the same value you would provide to require\n2. .subPath: dot-separated property access inside the module loaded by require\n\nIf file is missing some special steps are taken:\n\n1. If file is missing, the default filename is the api name.\n2. defaults.api.folder can provide a default folder used if file begings with '.' or is missing\n3. If no folder is provided, the lib folder in appFolder is used.\n\n## The api module\n\nThe api module itself can have four optional special exports:\n* initApi(opts): code executed on the first load of the api processing the options. May return a value that is used in place of the regular module value\n* apiReady(cb(err)) calls back when the api is ready to provide service\n* endApi(cb(err)) instructs the api to shut down, ie. close connections and clear timers\n* emitter if this is an EventEmitter, errors emitted are processed as anomalies\n\n## Execution of initApi\n\nif your api exports initApi, ths function is invoked on each require. This is because options may change, and you need to take this in account.\n\ninitApi is provided an options object:\n\n* .config: object: the merge of options providing to getApi and options in apiMap. getApi options overrride\n* .registerHandler(string route, handler(req, res, next)): registers a route with whatever Web server is used. \n* .logger: function(string): the logging to be used\n* .apprunner: object: the apprunner module for convenience\n\nif initApi returns a value, this is used as the result of getApi().\n\n# Examples\n\nTODO\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","_id":"apprunner@0.0.16","dist":{"shasum":"98ebc754ef804d48bcfe73b7451ac36501c690d0","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.0.16.tgz","integrity":"sha512-t4t4AwrNmUuEYLjKPkfRM30HY0XrohdfgpJnjvKYoge+IqgQaw7/1Q8WQQ4RlNZwWXhS34KHka0brruCSxtVJA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD3fFVTyrbcilLqjVDwaqC3uC916KFFtd6IDLcVcMGbcgIgATw4qY7q/cdTuZok+q+vYXztlYFq6lNTt+GdxhUahpo="}]},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.0.17":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","app"],"version":"0.0.17","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.31"},"dependencies":{"haraldutil":">= 0.1.5"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage"},"readme":"# App Runner\n\nApp Runner manages app execution and error reporting and provides a unified way to separate and reuse modules. Require is great, App Runner is greater!\n\n## Benefits\n\n1. Move apis between project files and external modules with no code change, or switch implementation for a given api name\n2. Implement one or many apis per file or module.\n2. Configure apis both per invocation and json at launch.\n3. Find root causes by collecting large volumes of elaborate error reports featuring multiple stack traces, variable values and any other useful information.\n4. Continue best effort execution after error reporting.\n5. Server flexibility: apis can register uri routes, but do not depend on a particular Web server implementation.\n6. Gracefully terminate after unhandled process exceptions capturing elaborate error reports.\n7. Gracefully shut down the application on demand using SIGINT signal from keyboard Ctrl-Break or another process\n8. Gracefully launch using api delayed readiness hook\n9. Gracefully exit using api shutdown hook\n9. Track performance of external interfaces using invocation timers\n\n## Features\n\n1. Provides module control from json\n2. Manages application error reports and queues\n3. Lifecycle management of the app and its modules\n5. Single-module exposure of the entire app to the launch script\n\n# Reference\n\nApp Runner handles process exceptions and SIGINT.\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## initApp(defaults, app)\n\n* defaults: options, typically loaded by haraldops\n\n  * .init.appFolder: string: the folder of initial script\n  * .init.logger: optional function(string): logging, default console.log\n  * .init.ops.sendMail: optional function(subject, body): Sends mail, default none\n  * .api: optional, indicates that Api Manager should be used\n  * .api.apiMap: optional: api configurations\n\n* app: Web server, could be an event emitter and have a .get method\n\n## getApi(opts)\n\nExample of using a proprietary serverhelp api, that manages Express lifecycle as an api.\n\n```js\nrequire('apprunner')\n\t.getApi({api: 'serverhelp'})\n\t.listen({\n\t\tserver: app,\n\t\tport: defaults.PORT,\n\t\tinterface: defaults.appInterface},\n\tcbc.add(appIsUp))\n```\n\ngets an api implementation\n* opts: object\n* .api: string: name of api function to be loaded\n\nAPIs are either configured directly in the opts object, or in defaults provided at App Runner's init.\n\n## apisReady(cb)\n\nSurveys all loaded apis to see if they have concluded initializing. Each api can expose an apiReady(cb) function used fo this purpose.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and if so configured a periodcal email.\n\n## enableAnomalyMail(flag)\n\ncontrol emailing on or off: flag: boolean, default: false\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an endApi function gets this invoked prior to process.exit\n\n## getCbCounter()\nEnsures that all callbacks has completed\n\n```js\nvar apprunner = require('apprunner')\nvar cbc = haraldutil.getCbCounter()\nsetTimeout(cbc.add(callback), 100)\nsetTimeout(cbc.add(callback), 100)\n\nfunction callback() {\n  if (cbc.isDone(arguments.callee))\n    console.log('All callbacks completed.')\n  else console.log('Not done yet...')\n}\n```\n```\nNot done yet...\nAll callbacks completed.\n```\nvar cbc = getCbCounter(opts)\n* opts: optional object\n* opts.emitter: optional event emitter or boolean. default: errors are thrown\n\n  * false: errors are ignored\n  * emitter: errors are emitted\n\n* opts.callback: function or array of function: add is done for each function\n\ncbc: object\n* .add(f): adds a callback for function f, return value: f\n* .isDone(f): notes one callback completed. returns true if all callbacks complete, otherwise false\n* .getStatus(): gets an object representing the current state\n\n# Configuring and Writing an Api Module\n\nConfigurations for an api is provided either in defaults or in the opts\n\n## Retrieving an api\n\nAs a minimum, the opts object needs to contain the api property: `getApi({api: 'userstore'})`\n\n## How the api is loaded\n\nAn Api's location is determined by two properties:\n\n1. .file: the same value you would provide to require\n2. .subPath: dot-separated property access inside the module loaded by require\n\nIf file is missing some special steps are taken:\n\n1. If file is missing, the default filename is the api name.\n2. defaults.api.folder can provide a default folder used if file begings with '.' or is missing\n3. If no folder is provided, the lib folder in appFolder is used.\n\n## The api module\n\nThe api module itself can have four optional special exports:\n* initApi(opts): code executed on the first load of the api processing the options. May return a value that is used in place of the regular module value\n* apiReady(cb(err)) calls back when the api is ready to provide service\n* endApi(cb(err)) instructs the api to shut down, ie. close connections and clear timers\n* emitter if this is an EventEmitter, errors emitted are processed as anomalies\n\n## Execution of initApi\n\nif your api exports initApi, ths function is invoked on each require. This is because options may change, and you need to take this in account.\n\ninitApi is provided an options object:\n\n* .config: object: the merge of options providing to getApi and options in apiMap. getApi options overrride\n* .registerHandler(string route, handler(req, res, next)): registers a route with whatever Web server is used. \n* .logger: function(string): the logging to be used\n* .apprunner: object: the apprunner module for convenience\n\nif initApi returns a value, this is used as the result of getApi().\n\n# Examples\n\nTODO\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","_id":"apprunner@0.0.17","dist":{"shasum":"ea9f103c60e4f936b1bb5b31c0159b6db68b9f90","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.0.17.tgz","integrity":"sha512-ywyIA9vPG368m3g+Zdotvn1+ULBKwkVB9IUhO018JV4IlMfU7IBvaSlY7Mh4QlB2yK0YKxYqqaRJOgfpyp3CXg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE01rCfna8tUS224s+P050yKAIZOmN2chiQ1zrJ/Jn9lAiA+AjMSCBp+xGgkxJhTFp53B9zlt49l2OBgfzjEghwofg=="}]},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.1.0":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","app"],"version":"0.1.0","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.31"},"dependencies":{"haraldutil":">= 0.1.5"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage"},"readme":"# App Runner\n\nApp Runner manages app execution and error reporting and provides a unified way to separate and reuse modules. Require is great, App Runner is greater!\n\n## Benefits\n\n1. Move apis between project files and external modules with no code change, or switch implementation for a given api name\n2. Implement one or many apis per file or module.\n2. Configure apis both per invocation and json at launch.\n3. Find root causes by collecting large volumes of elaborate error reports featuring multiple stack traces, variable values and any other useful information.\n4. Continue best effort execution after error reporting.\n5. Server flexibility: apis can register uri routes, but do not depend on a particular Web server implementation.\n6. Gracefully terminate after unhandled process exceptions capturing elaborate error reports.\n7. Gracefully shut down the application on demand using SIGINT signal from keyboard Ctrl-Break or another process\n8. Gracefully launch using api delayed readiness hook\n9. Gracefully exit using api shutdown hook\n9. Track performance of external interfaces using invocation timers\n\n## Features\n\n1. Provides module control from json\n2. Manages application error reports and queues\n3. Lifecycle management of the app and its modules\n5. Single-module exposure of the entire app to the launch script\n\n# Reference\n\nApp Runner handles process exceptions and SIGINT.\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## initApp(defaults, app)\n\n* defaults: options, typically loaded by haraldops\n\n  * .init.appFolder: string: the folder of initial script\n  * .init.logger: optional function(string): logging, default console.log\n  * .init.ops.sendMail: optional function(subject, body): Sends mail, default none\n  * .api: optional, indicates that Api Manager should be used\n  * .api.apiMap: optional: api configurations\n\n* app: Web server, could be an event emitter and have a .get method\n\n## getApi(opts)\n\nExample of using a proprietary serverhelp api, that manages Express lifecycle as an api.\n\n```js\nrequire('apprunner')\n\t.getApi({api: 'serverhelp'})\n\t.listen({\n\t\tserver: app,\n\t\tport: defaults.PORT,\n\t\tinterface: defaults.appInterface},\n\tcbc.add(appIsUp))\n```\n\ngets an api implementation\n* opts: object\n* .api: string: name of api function to be loaded\n\nAPIs are either configured directly in the opts object, or in defaults provided at App Runner's init.\n\n## apisReady(cb)\n\nSurveys all loaded apis to see if they have concluded initializing. Each api can expose an apiReady(cb) function used fo this purpose.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and if so configured a periodcal email.\n\n## enableAnomalyMail(flag)\n\ncontrol emailing on or off: flag: boolean, default: false\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an endApi function gets this invoked prior to process.exit\n\n## getCbCounter()\nEnsures that all callbacks has completed\n\n```js\nvar apprunner = require('apprunner')\nvar cbc = haraldutil.getCbCounter()\nsetTimeout(cbc.add(callback), 100)\nsetTimeout(cbc.add(callback), 100)\n\nfunction callback() {\n  if (cbc.isDone(arguments.callee))\n    console.log('All callbacks completed.')\n  else console.log('Not done yet...')\n}\n```\n```\nNot done yet...\nAll callbacks completed.\n```\nvar cbc = getCbCounter(opts)\n* opts: optional object\n* opts.emitter: optional event emitter or boolean. default: errors are thrown\n\n  * false: errors are ignored\n  * emitter: errors are emitted\n\n* opts.callback: function or array of function: add is done for each function\n\ncbc: object\n* .add(f): adds a callback for function f, return value: f\n* .isDone(f): notes one callback completed. returns true if all callbacks complete, otherwise false\n* .getStatus(): gets an object representing the current state\n\n# Configuring and Writing an Api Module\n\nConfigurations for an api is provided either in defaults or in the opts\n\n## Retrieving an api\n\nAs a minimum, the opts object needs to contain the api property: `getApi({api: 'userstore'})`\n\n## How the api is loaded\n\nAn Api's location is determined by two properties:\n\n1. .file: the same value you would provide to require\n2. .subPath: dot-separated property access inside the module loaded by require\n\nIf file is missing some special steps are taken:\n\n1. If file is missing, the default filename is the api name.\n2. defaults.api.folder can provide a default folder used if file begings with '.' or is missing\n3. If no folder is provided, the lib folder in appFolder is used.\n\n## The api module\n\nThe api module itself can have four optional special exports:\n* initApi(opts): code executed on the first load of the api processing the options. May return a value that is used in place of the regular module value\n* apiReady(cb(err)) calls back when the api is ready to provide service\n* endApi(cb(err)) instructs the api to shut down, ie. close connections and clear timers\n* emitter if this is an EventEmitter, errors emitted are processed as anomalies\n\n## Execution of initApi\n\nif your api exports initApi, ths function is invoked on each require. This is because options may change, and you need to take this in account.\n\ninitApi is provided an options object:\n\n* .config: object: the merge of options providing to getApi and options in apiMap. getApi options overrride\n* .registerHandler(string route, handler(req, res, next)): registers a route with whatever Web server is used. \n* .logger: function(string): the logging to be used\n* .apprunner: object: the apprunner module for convenience\n\nif initApi returns a value, this is used as the result of getApi().\n\n# Examples\n\nTODO\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","_id":"apprunner@0.1.0","dist":{"shasum":"c4ae4751e6656c881b6643b76afb55d5817ea1a1","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.1.0.tgz","integrity":"sha512-Xiy4kj5Kfxa648tx6W1DyOCNw5sQyXQSgRUKLWYrh6F+hqeb+2WjqO1FftpSqfoKBf4Y+kokvirHTu6GI0oaKA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC5rhORGk9iSJaBj2HABSYIiEWEIyEsppbyfkYe6kyPwwIgNLkSbHO2cifab6bOii9XCBtIH6qGD0/9mm3DYT/zaAA="}]},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.1.1":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","app"],"version":"0.1.1","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.31"},"dependencies":{"haraldutil":">= 0.1.5"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage"},"readme":"# App Runner\n\nApp Runner manages app execution and error reporting and provides a unified way to separate and reuse modules. Require is great, App Runner is greater!\n\n## Benefits\n\n1. Move apis between project files and external modules with no code change, or switch implementation for a given api name\n2. Implement one or many apis per file or module.\n2. Configure apis both per invocation and json at launch.\n3. Find root causes by collecting large volumes of elaborate error reports featuring multiple stack traces, variable values and any other useful information.\n4. Continue best effort execution after error reporting.\n5. Server flexibility: apis can register uri routes, but do not depend on a particular Web server implementation.\n6. Gracefully terminate after unhandled process exceptions capturing elaborate error reports.\n7. Gracefully shut down the application on demand using SIGINT signal from keyboard Ctrl-Break or another process\n8. Gracefully launch using api delayed readiness hook\n9. Gracefully exit using api shutdown hook\n9. Track performance of external interfaces using invocation timers\n\n## Features\n\n1. Provides module control from json\n2. Manages application error reports and queues\n3. Lifecycle management of the app and its modules\n5. Single-module exposure of the entire app to the launch script\n\n# Reference\n\nApp Runner handles process exceptions and SIGINT.\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## initApp(defaults, app)\n\n* defaults: options, typically loaded by haraldops\n\n  * .init.appFolder: string: the folder of initial script\n  * .init.logger: optional function(string): logging, default console.log\n  * .init.ops.sendMail: optional function(subject, body): Sends mail, default none\n  * .api: optional, indicates that Api Manager should be used\n  * .api.apiMap: optional: api configurations\n\n* app: Web server, could be an event emitter and have a .get method\n\n## getApi(opts)\n\nExample of using a proprietary serverhelp api, that manages Express lifecycle as an api.\n\n```js\nrequire('apprunner')\n\t.getApi({api: 'serverhelp'})\n\t.listen({\n\t\tserver: app,\n\t\tport: defaults.PORT,\n\t\tinterface: defaults.appInterface},\n\tcbc.add(appIsUp))\n```\n\ngets an api implementation\n* opts: object\n* .api: string: name of api function to be loaded\n\nAPIs are either configured directly in the opts object, or in defaults provided at App Runner's init.\n\n## apisReady(cb)\n\nSurveys all loaded apis to see if they have concluded initializing. Each api can expose an apiReady(cb) function used fo this purpose.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and if so configured a periodcal email.\n\n## enableAnomalyMail(flag)\n\ncontrol emailing on or off: flag: boolean, default: false\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an endApi function gets this invoked prior to process.exit\n\n## getCbCounter()\nEnsures that all callbacks has completed\n\n```js\nvar apprunner = require('apprunner')\nvar cbc = haraldutil.getCbCounter()\nsetTimeout(cbc.add(callback), 100)\nsetTimeout(cbc.add(callback), 100)\n\nfunction callback() {\n  if (cbc.isDone(arguments.callee))\n    console.log('All callbacks completed.')\n  else console.log('Not done yet...')\n}\n```\n```\nNot done yet...\nAll callbacks completed.\n```\nvar cbc = getCbCounter(opts)\n* opts: optional object\n* opts.emitter: optional event emitter or boolean. default: errors are thrown\n\n  * false: errors are ignored\n  * emitter: errors are emitted\n\n* opts.callback: function or array of function: add is done for each function\n\ncbc: object\n* .add(f): adds a callback for function f, return value: f\n* .isDone(f): notes one callback completed. returns true if all callbacks complete, otherwise false\n* .getStatus(): gets an object representing the current state\n\n# Configuring and Writing an Api Module\n\nConfigurations for an api is provided either in defaults or in the opts\n\n## Retrieving an api\n\nAs a minimum, the opts object needs to contain the api property: `getApi({api: 'userstore'})`\n\n## How the api is loaded\n\nAn Api's location is determined by two properties:\n\n1. .file: the same value you would provide to require\n2. .subPath: dot-separated property access inside the module loaded by require\n\nIf file is missing some special steps are taken:\n\n1. If file is missing, the default filename is the api name.\n2. defaults.api.folder can provide a default folder used if file begings with '.' or is missing\n3. If no folder is provided, the lib folder in appFolder is used.\n\n## The api module\n\nThe api module itself can have four optional special exports:\n* initApi(opts): code executed on the first load of the api processing the options. May return a value that is used in place of the regular module value\n* apiReady(cb(err)) calls back when the api is ready to provide service\n* endApi(cb(err)) instructs the api to shut down, ie. close connections and clear timers\n* emitter if this is an EventEmitter, errors emitted are processed as anomalies\n\n## Execution of initApi\n\nif your api exports initApi, ths function is invoked on each require. This is because options may change, and you need to take this in account.\n\ninitApi is provided an options object:\n\n* .config: object: the merge of options providing to getApi and options in apiMap. getApi options overrride\n* .registerHandler(string route, handler(req, res, next)): registers a route with whatever Web server is used. \n* .logger: function(string): the logging to be used\n* .apprunner: object: the apprunner module for convenience\n\nif initApi returns a value, this is used as the result of getApi().\n\n# Examples\n\nTODO\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","_id":"apprunner@0.1.1","dist":{"shasum":"b5b55140d5b558270a7bf4215b1d08eace408934","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.1.1.tgz","integrity":"sha512-jOzi2n32Q6IY5yaKXcQA5riK09wQIXhpWX0vsfWcgTSLONZ7FF9Z3Sg/uCOyWzH8GhLzILvlsxzOqQYhiHxrvw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBn7t5my37PrpkMzmOHbdY50NFUXnUIbq7pLjUp+5/8CAiBOKTybncazLGdzCtIYCjuJUHDAbk/HPtfl7cGl6TorJg=="}]},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.1.2":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","app"],"version":"0.1.2","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.31"},"dependencies":{"haraldutil":">= 0.1.5"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage"},"readme":"# App Runner\n\nApp Runner manages app execution and error reporting and provides a unified way to separate and reuse modules. Require is great, App Runner is greater!\n\n## Benefits\n\n1. Move apis between project files and external modules with no code change, or switch implementation for a given api name\n2. Implement one or many apis per file or module.\n2. Configure apis both per invocation and json at launch.\n3. Find root causes by collecting large volumes of elaborate error reports featuring multiple stack traces, variable values and any other useful information.\n4. Continue best effort execution after error reporting.\n5. Server flexibility: apis can register uri routes, but do not depend on a particular Web server implementation.\n6. Gracefully terminate after unhandled process exceptions capturing elaborate error reports.\n7. Gracefully shut down the application on demand using SIGINT signal from keyboard Ctrl-Break or another process\n8. Gracefully launch using api delayed readiness hook\n9. Gracefully exit using api shutdown hook\n9. Track performance of external interfaces using invocation timers\n\n## Features\n\n1. Provides module control from json\n2. Manages application error reports and queues\n3. Lifecycle management of the app and its modules\n5. Single-module exposure of the entire app to the launch script\n\n# Reference\n\nApp Runner handles process exceptions and SIGINT.\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## initApp(defaults, app)\n\n* defaults: options, typically loaded by haraldops\n\n  * .init.appFolder: string: the folder of initial script\n  * .init.logger: optional function(string): logging, default console.log\n  * .init.ops.sendMail: optional function(subject, body): Sends mail, default none\n  * .api: optional, indicates that Api Manager should be used\n  * .api.apiMap: optional: api configurations\n\n* app: Web server, could be an event emitter and have a .get method\n\n## getApi(opts)\n\nExample of using a proprietary serverhelp api, that manages Express lifecycle as an api.\n\n```js\nrequire('apprunner')\n\t.getApi({api: 'serverhelp'})\n\t.listen({\n\t\tserver: app,\n\t\tport: defaults.PORT,\n\t\tinterface: defaults.appInterface},\n\tcbc.add(appIsUp))\n```\n\ngets an api implementation\n* opts: object\n* .api: string: name of api function to be loaded\n\nAPIs are either configured directly in the opts object, or in defaults provided at App Runner's init.\n\n## apisReady(cb)\n\nSurveys all loaded apis to see if they have concluded initializing. Each api can expose an apiReady(cb) function used fo this purpose.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and if so configured a periodcal email.\n\n## enableAnomalyMail(flag)\n\ncontrol emailing on or off: flag: boolean, default: false\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an endApi function gets this invoked prior to process.exit\n\n## getCbCounter()\nEnsures that all callbacks has completed\n\n```js\nvar apprunner = require('apprunner')\nvar cbc = haraldutil.getCbCounter()\nsetTimeout(cbc.add(callback), 100)\nsetTimeout(cbc.add(callback), 100)\n\nfunction callback() {\n  if (cbc.isDone(arguments.callee))\n    console.log('All callbacks completed.')\n  else console.log('Not done yet...')\n}\n```\n```\nNot done yet...\nAll callbacks completed.\n```\nvar cbc = getCbCounter(opts)\n* opts: optional object\n* opts.emitter: optional event emitter or boolean. default: errors are thrown\n\n  * false: errors are ignored\n  * emitter: errors are emitted\n\n* opts.callback: function or array of function: add is done for each function\n\ncbc: object\n* .add(f): adds a callback for function f, return value: f\n* .isDone(f): notes one callback completed. returns true if all callbacks complete, otherwise false\n* .getStatus(): gets an object representing the current state\n\n# Configuring and Writing an Api Module\n\nConfigurations for an api is provided either in defaults or in the opts\n\n## Retrieving an api\n\nAs a minimum, the opts object needs to contain the api property: `getApi({api: 'userstore'})`\n\n## How the api is loaded\n\nAn Api's location is determined by two properties:\n\n1. .file: the same value you would provide to require\n2. .subPath: dot-separated property access inside the module loaded by require\n\nIf file is missing some special steps are taken:\n\n1. If file is missing, the default filename is the api name.\n2. defaults.api.folder can provide a default folder used if file begings with '.' or is missing\n3. If no folder is provided, the lib folder in appFolder is used.\n\n## The api module\n\nThe api module itself can have four optional special exports:\n* initApi(opts): code executed on the first load of the api processing the options. May return a value that is used in place of the regular module value\n* apiReady(cb(err)) calls back when the api is ready to provide service\n* endApi(cb(err)) instructs the api to shut down, ie. close connections and clear timers\n* emitter if this is an EventEmitter, errors emitted are processed as anomalies\n\n## Execution of initApi\n\nif your api exports initApi, ths function is invoked on each require. This is because options may change, and you need to take this in account.\n\ninitApi is provided an options object:\n\n* .config: object: the merge of options providing to getApi and options in apiMap. getApi options overrride\n* .registerHandler(string route, handler(req, res, next)): registers a route with whatever Web server is used. \n* .logger: function(string): the logging to be used\n* .apprunner: object: the apprunner module for convenience\n\nif initApi returns a value, this is used as the result of getApi().\n\n# Examples\n\nTODO\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","_id":"apprunner@0.1.2","dist":{"shasum":"9a1e475e3fe3d028583e798955bb9353fa51335b","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.1.2.tgz","integrity":"sha512-bquPZdN2d8TUICJXl7MOtReHlRIflHKSVUv6j6vMV4xOmQFcwPnwQV8mocv0c3njL4DsWtioiCYIMvXCGHFDJA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEDTD4W/t+XQd6Guf7h41V8lBHZ2KNLEY/WC/vZtlV3wAiAXCkZPgXQtQVF+DfLoBWLETeSiXfgempoDv0+d0PftPQ=="}]},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.1.3":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","app"],"version":"0.1.3","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.31"},"dependencies":{"haraldutil":">= 0.1.5"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage"},"readme":"# App Runner\n\nApp Runner manages app execution and error reporting and provides a unified way to separate and reuse modules. Require is great, App Runner is greater!\n\n## Benefits\n\n1. Move apis between project files and external modules with no code change, or switch implementation for a given api name\n2. Implement one or many apis per file or module.\n2. Configure apis both per invocation and json at launch.\n3. Find root causes by collecting large volumes of elaborate error reports featuring multiple stack traces, variable values and any other useful information.\n4. Continue best effort execution after error reporting.\n5. Server flexibility: apis can register uri routes, but do not depend on a particular Web server implementation.\n6. Gracefully terminate after unhandled process exceptions capturing elaborate error reports.\n7. Gracefully shut down the application on demand using SIGINT signal from keyboard Ctrl-Break or another process\n8. Gracefully launch using api delayed readiness hook\n9. Gracefully exit using api shutdown hook\n9. Track performance of external interfaces using invocation timers\n\n## Features\n\n1. Provides module control from json\n2. Manages application error reports and queues\n3. Lifecycle management of the app and its modules\n5. Single-module exposure of the entire app to the launch script\n\n# Reference\n\nApp Runner handles process exceptions and SIGINT.\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## initApp(defaults, app)\n\n* defaults: options, typically loaded by haraldops\n\n  * .init.appFolder: string: the folder of initial script\n  * .init.logger: optional function(string): logging, default console.log\n  * .init.ops.sendMail: optional function(subject, body): Sends mail, default none\n  * .api: optional, indicates that Api Manager should be used\n  * .api.apiMap: optional: api configurations\n\n* app: Web server, could be an event emitter and have a .get method\n\n## getApi(opts)\n\nExample of using a proprietary serverhelp api, that manages Express lifecycle as an api.\n\n```js\nrequire('apprunner')\n\t.getApi({api: 'serverhelp'})\n\t.listen({\n\t\tserver: app,\n\t\tport: defaults.PORT,\n\t\tinterface: defaults.appInterface},\n\tcbc.add(appIsUp))\n```\n\ngets an api implementation\n* opts: object\n* .api: string: name of api function to be loaded\n\nAPIs are either configured directly in the opts object, or in defaults provided at App Runner's init.\n\n## apisReady(cb)\n\nSurveys all loaded apis to see if they have concluded initializing. Each api can expose an apiReady(cb) function used fo this purpose.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and if so configured a periodcal email.\n\n## enableAnomalyMail(flag)\n\ncontrol emailing on or off: flag: boolean, default: false\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an endApi function gets this invoked prior to process.exit\n\n## getCbCounter()\nEnsures that all callbacks has completed\n\n```js\nvar apprunner = require('apprunner')\nvar cbc = haraldutil.getCbCounter()\nsetTimeout(cbc.add(callback), 100)\nsetTimeout(cbc.add(callback), 100)\n\nfunction callback() {\n  if (cbc.isDone(arguments.callee))\n    console.log('All callbacks completed.')\n  else console.log('Not done yet...')\n}\n```\n```\nNot done yet...\nAll callbacks completed.\n```\nvar cbc = getCbCounter(opts)\n* opts: optional object\n* opts.emitter: optional event emitter or boolean. default: errors are thrown\n\n  * false: errors are ignored\n  * emitter: errors are emitted\n\n* opts.callback: function or array of function: add is done for each function\n\ncbc: object\n* .add(f): adds a callback for function f, return value: f\n* .isDone(f): notes one callback completed. returns true if all callbacks complete, otherwise false\n* .getStatus(): gets an object representing the current state\n\n# Configuring and Writing an Api Module\n\nConfigurations for an api is provided either in defaults or in the opts\n\n## Retrieving an api\n\nAs a minimum, the opts object needs to contain the api property: `getApi({api: 'userstore'})`\n\n## How the api is loaded\n\nAn Api's location is determined by two properties:\n\n1. .file: the same value you would provide to require\n2. .subPath: dot-separated property access inside the module loaded by require\n\nIf file is missing some special steps are taken:\n\n1. If file is missing, the default filename is the api name.\n2. defaults.api.folder can provide a default folder used if file begings with '.' or is missing\n3. If no folder is provided, the lib folder in appFolder is used.\n\n## The api module\n\nThe api module itself can have four optional special exports:\n* initApi(opts): code executed on the first load of the api processing the options. May return a value that is used in place of the regular module value\n* apiReady(cb(err)) calls back when the api is ready to provide service\n* endApi(cb(err)) instructs the api to shut down, ie. close connections and clear timers\n* emitter if this is an EventEmitter, errors emitted are processed as anomalies\n\n## Execution of initApi\n\nif your api exports initApi, ths function is invoked on each require. This is because options may change, and you need to take this in account.\n\ninitApi is provided an options object:\n\n* .config: object: the merge of options providing to getApi and options in apiMap. getApi options overrride\n* .registerHandler(string route, handler(req, res, next)): registers a route with whatever Web server is used. \n* .logger: function(string): the logging to be used\n* .apprunner: object: the apprunner module for convenience\n\nif initApi returns a value, this is used as the result of getApi().\n\n# Examples\n\nTODO\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","_id":"apprunner@0.1.3","dist":{"shasum":"fbcebfa17072afccb6aee7215fec0359318ae0d9","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.1.3.tgz","integrity":"sha512-Ub9qmKR2f/Id3bfoNbSXTP2gJVKD3Bun7kGRedorVzppoobUFjVhXkzsZ5z1TAxd31QmYsjhbeGd1eR4YqGkhQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDveD8xMvkEm1h1XcO0pfODUWkhpOO7ea2J8eHaxVCB3wIgZ8hsvMgV2ffnoIcKgo+0aZO0zUR6uiKAkN67xpPJw+0="}]},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.1.4":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","app"],"version":"0.1.4","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.31"},"dependencies":{"haraldutil":">= 0.1.5"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage"},"readme":"# App Runner\n\nApp Runner manages app execution and error reporting and provides a unified way to separate and reuse modules. Require is great, App Runner is greater!\n\n## Benefits\n\n1. Move apis between project files and external modules with no code change, or switch implementation for a given api name\n2. Implement one or many apis per file or module.\n2. Configure apis both per invocation and json at launch.\n3. Find root causes by collecting large volumes of elaborate error reports featuring multiple stack traces, variable values and any other useful information.\n4. Continue best effort execution after error reporting.\n5. Server flexibility: apis can register uri routes, but do not depend on a particular Web server implementation.\n6. Gracefully terminate after unhandled process exceptions capturing elaborate error reports.\n7. Gracefully shut down the application on demand using SIGINT signal from keyboard Ctrl-Break or another process\n8. Gracefully launch using api delayed readiness hook\n9. Gracefully exit using api shutdown hook\n9. Track performance of external interfaces using invocation timers\n\n## Features\n\n1. Provides module control from json\n2. Manages application error reports and queues\n3. Lifecycle management of the app and its modules\n5. Single-module exposure of the entire app to the launch script\n\n# Reference\n\nApp Runner handles process exceptions and SIGINT.\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## initApp(defaults, app)\n\n* defaults: options, typically loaded by haraldops\n\n  * .init.appFolder: string: the folder of initial script\n  * .init.logger: optional function(string): logging, default console.log\n  * .init.ops.sendMail: optional function(subject, body): Sends mail, default none\n  * .api: optional, indicates that Api Manager should be used\n  * .api.apiMap: optional: api configurations\n\n* app: Web server, could be an event emitter and have a .get method\n\n## getApi(opts)\n\nExample of using a proprietary serverhelp api, that manages Express lifecycle as an api.\n\n```js\nrequire('apprunner')\n\t.getApi({api: 'serverhelp'})\n\t.listen({\n\t\tserver: app,\n\t\tport: defaults.PORT,\n\t\tinterface: defaults.appInterface},\n\tcbc.add(appIsUp))\n```\n\ngets an api implementation\n* opts: object\n* .api: string: name of api function to be loaded\n\nAPIs are either configured directly in the opts object, or in defaults provided at App Runner's init.\n\n## apisReady(cb)\n\nSurveys all loaded apis to see if they have concluded initializing. Each api can expose an apiReady(cb) function used fo this purpose.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and if so configured a periodcal email.\n\n## enableAnomalyMail(flag)\n\ncontrol emailing on or off: flag: boolean, default: false\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an endApi function gets this invoked prior to process.exit\n\n## getCbCounter()\nEnsures that all callbacks has completed\n\n```js\nvar apprunner = require('apprunner')\nvar cbc = haraldutil.getCbCounter()\nsetTimeout(cbc.add(callback), 100)\nsetTimeout(cbc.add(callback), 100)\n\nfunction callback() {\n  if (cbc.isDone(arguments.callee))\n    console.log('All callbacks completed.')\n  else console.log('Not done yet...')\n}\n```\n```\nNot done yet...\nAll callbacks completed.\n```\nvar cbc = getCbCounter(opts)\n* opts: optional object\n* opts.emitter: optional event emitter or boolean. default: errors are thrown\n\n  * false: errors are ignored\n  * emitter: errors are emitted\n\n* opts.callback: function or array of function: add is done for each function\n\ncbc: object\n* .add(f): adds a callback for function f, return value: f\n* .isDone(f): notes one callback completed. returns true if all callbacks complete, otherwise false\n* .getStatus(): gets an object representing the current state\n\n# Configuring and Writing an Api Module\n\nConfigurations for an api is provided either in defaults or in the opts\n\n## Retrieving an api\n\nAs a minimum, the opts object needs to contain the api property: `getApi({api: 'userstore'})`\n\n## How the api is loaded\n\nAn Api's location is determined by two properties:\n\n1. .file: the same value you would provide to require\n2. .subPath: dot-separated property access inside the module loaded by require\n\nIf file is missing some special steps are taken:\n\n1. If file is missing, the default filename is the api name.\n2. defaults.api.folder can provide a default folder used if file begings with '.' or is missing\n3. If no folder is provided, the lib folder in appFolder is used.\n\n## The api module\n\nThe api module itself can have four optional special exports:\n* initApi(opts): code executed on the first load of the api processing the options. May return a value that is used in place of the regular module value\n* apiReady(cb(err)) calls back when the api is ready to provide service\n* endApi(cb(err)) instructs the api to shut down, ie. close connections and clear timers\n* emitter if this is an EventEmitter, errors emitted are processed as anomalies\n\n## Execution of initApi\n\nif your api exports initApi, ths function is invoked on each require. This is because options may change, and you need to take this in account.\n\ninitApi is provided an options object:\n\n* .config: object: the merge of options providing to getApi and options in apiMap. getApi options overrride\n* .registerHandler(string route, handler(req, res, next)): registers a route with whatever Web server is used. \n* .logger: function(string): the logging to be used\n* .apprunner: object: the apprunner module for convenience\n\nif initApi returns a value, this is used as the result of getApi().\n\n# Examples\n\nTODO\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","_id":"apprunner@0.1.4","dist":{"shasum":"b7e4363b9da623def36c1a119b34c9ff00684ce8","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.1.4.tgz","integrity":"sha512-XCacE7+dq2McNJDVc3uhf1vnHmRKMUoWY8F+iBwcdJHYu4OujZGZNtuy0y6nTCPrlud6PgKrrKAyhweD/bPkuQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDCCC9pMPQOlWVz3XLOXnH0yH4/TUbAKh8Qo866QbZ0tAiBfdPiyPT3JHUwKQZ0DqugRAVYAnsuXipTgnHVtUfmICw=="}]},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.1.5":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","app"],"version":"0.1.5","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.34"},"dependencies":{"haraldutil":">= 0.1.15"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage"},"readme":"# App Runner\n\nApp Runner manages app execution and error reporting and provides a unified way to separate and reuse modules. Require is great, App Runner is greater!\n\n## Benefits\n\n1. Move apis between project files and external modules with no code change, or switch implementation for a given api name\n2. Implement one or many apis per file or module.\n2. Configure apis both per invocation and json at launch.\n3. Find root causes by collecting large volumes of elaborate error reports featuring multiple stack traces, variable values and any other useful information.\n4. Continue best effort execution after error reporting.\n5. Server flexibility: apis can register uri routes, but do not depend on a particular Web server implementation.\n6. Gracefully terminate after unhandled process exceptions capturing elaborate error reports.\n7. Gracefully shut down the application on demand using SIGINT signal from keyboard Ctrl-Break or another process\n8. Gracefully launch using api delayed readiness hook\n9. Gracefully exit using api shutdown hook\n9. Track performance of external interfaces using invocation timers\n\n## Features\n\n1. Provides module control from json\n2. Manages application error reports and queues\n3. Lifecycle management of the app and its modules\n5. Single-module exposure of the entire app to the launch script\n\n# Reference\n\nApp Runner handles process exceptions and SIGINT.\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## initApp(defaults, app)\n\n* defaults: options, typically loaded by haraldops\n\n  * .init.appFolder: string: the folder of initial script\n  * .init.logger: optional function(string): logging, default console.log\n  * .init.ops.sendMail: optional function(subject, body): Sends mail, default none\n  * .api: optional, indicates that Api Manager should be used\n  * .api.apiMap: optional: api configurations\n\n* app: Web server, could be an event emitter and have a .get method\n\n## getApi(opts)\n\nExample of using a proprietary serverhelp api, that manages Express lifecycle as an api.\n\n```js\nrequire('apprunner')\n\t.getApi({api: 'serverhelp'})\n\t.listen({\n\t\tserver: app,\n\t\tport: defaults.PORT,\n\t\tinterface: defaults.appInterface},\n\tcbc.add(appIsUp))\n```\n\ngets an api implementation\n* opts: object\n* .api: string: name of api function to be loaded\n\nAPIs are either configured directly in the opts object, or in defaults provided at App Runner's init.\n\n## apisReady(cb)\n\nSurveys all loaded apis to see if they have concluded initializing. Each api can expose an apiReady(cb) function used fo this purpose.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and if so configured a periodcal email.\n\n## enableAnomalyMail(flag)\n\ncontrol emailing on or off: flag: boolean, default: false\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an endApi function gets this invoked prior to process.exit\n\n## getCbCounter()\nEnsures that all callbacks has completed\n\n```js\nvar apprunner = require('apprunner')\nvar cbc = haraldutil.getCbCounter()\nsetTimeout(cbc.add(callback), 100)\nsetTimeout(cbc.add(callback), 100)\n\nfunction callback() {\n  if (cbc.isDone(arguments.callee))\n    console.log('All callbacks completed.')\n  else console.log('Not done yet...')\n}\n```\n```\nNot done yet...\nAll callbacks completed.\n```\nvar cbc = getCbCounter(opts)\n* opts: optional object\n* opts.emitter: optional event emitter or boolean. default: errors are thrown\n\n  * false: errors are ignored\n  * emitter: errors are emitted\n\n* opts.callback: function or array of function: add is done for each function\n\ncbc: object\n* .add(f): adds a callback for function f, return value: f\n* .isDone(f): notes one callback completed. returns true if all callbacks complete, otherwise false\n* .getStatus(): gets an object representing the current state\n\n# Configuring and Writing an Api Module\n\nConfigurations for an api is provided either in defaults or in the opts\n\n## Retrieving an api\n\nAs a minimum, the opts object needs to contain the api property: `getApi({api: 'userstore'})`\n\n## How the api is loaded\n\nAn Api's location is determined by two properties:\n\n1. .file: the same value you would provide to require\n2. .subPath: dot-separated property access inside the module loaded by require\n\nIf file is missing some special steps are taken:\n\n1. If file is missing, the default filename is the api name.\n2. defaults.api.folder can provide a default folder used if file begings with '.' or is missing\n3. If no folder is provided, the lib folder in appFolder is used.\n\n## The api module\n\nThe api module itself can have four optional special exports:\n* initApi(opts): code executed on the first load of the api processing the options. May return a value that is used in place of the regular module value\n* apiReady(cb(err)) calls back when the api is ready to provide service\n* endApi(cb(err)) instructs the api to shut down, ie. close connections and clear timers\n* emitter if this is an EventEmitter, errors emitted are processed as anomalies\n\n## Execution of initApi\n\nif your api exports initApi, ths function is invoked on each require. This is because options may change, and you need to take this in account.\n\ninitApi is provided an options object:\n\n* .config: object: the merge of options providing to getApi and options in apiMap. getApi options overrride\n* .registerHandler(string route, handler(req, res, next)): registers a route with whatever Web server is used. \n* .logger: function(string): the logging to be used\n* .apprunner: object: the apprunner module for convenience\n\nif initApi returns a value, this is used as the result of getApi().\n\n# Examples\n\nTODO\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","_id":"apprunner@0.1.5","dist":{"shasum":"d319ada90d806966b272b8461c1aeb809be22505","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.1.5.tgz","integrity":"sha512-dqwXMlA3eL3uxyRzSEZW38x4k9CuYDs+Gv+oRkEqNdsr2CL4pEkEntyJk+7YxDWEwv/Qazg+bnfS45uA28NKeQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCXJanb6hBW8gJiU8s7cFzvOfugwOl6prj8g0SyVTidYwIhAIa1tp5mfg/STOY2olo2VkTGGGQq/E3w0SKrP1W2Vuzu"}]},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.1.6":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","app"],"version":"0.1.6","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.34"},"dependencies":{"haraldutil":">= 0.1.15"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage"},"readme":"# App Runner\n\nApp Runner manages app execution and error reporting and provides a unified way to separate and reuse modules. Require is great, App Runner is greater!\n\n## Benefits\n\n1. Move apis between project files and external modules with no code change, or switch implementation for a given api name\n2. Implement one or many apis per file or module.\n2. Configure apis both per invocation and json at launch.\n3. Find root causes by collecting large volumes of elaborate error reports featuring multiple stack traces, variable values and any other useful information.\n4. Continue best effort execution after error reporting.\n5. Server flexibility: apis can register uri routes, but do not depend on a particular Web server implementation.\n6. Gracefully terminate after unhandled process exceptions capturing elaborate error reports.\n7. Gracefully shut down the application on demand using SIGINT signal from keyboard Ctrl-Break or another process\n8. Gracefully launch using api delayed readiness hook\n9. Gracefully exit using api shutdown hook\n9. Track performance of external interfaces using invocation timers\n\n## Features\n\n1. Provides module control from json\n2. Manages application error reports and queues\n3. Lifecycle management of the app and its modules\n5. Single-module exposure of the entire app to the launch script\n\n# Reference\n\nApp Runner handles process exceptions and SIGINT.\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## initApp(defaults, app)\n\n* defaults: options, typically loaded by haraldops\n\n  * .init.appFolder: string: the folder of initial script\n  * .init.logger: optional function(string): logging, default console.log\n  * .init.ops.sendMail: optional function(subject, body): Sends mail, default none\n  * .api: optional, indicates that Api Manager should be used\n  * .api.apiMap: optional: api configurations\n\n* app: Web server, could be an event emitter and have a .get method\n\n## getApi(opts)\n\nExample of using a proprietary serverhelp api, that manages Express lifecycle as an api.\n\n```js\nrequire('apprunner')\n\t.getApi({api: 'serverhelp'})\n\t.listen({\n\t\tserver: app,\n\t\tport: defaults.PORT,\n\t\tinterface: defaults.appInterface},\n\tcbc.add(appIsUp))\n```\n\ngets an api implementation\n* opts: object\n* .api: string: name of api function to be loaded\n\nAPIs are either configured directly in the opts object, or in defaults provided at App Runner's init.\n\n## apisReady(cb)\n\nSurveys all loaded apis to see if they have concluded initializing. Each api can expose an apiReady(cb) function used fo this purpose.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and if so configured a periodcal email.\n\n## enableAnomalyMail(flag)\n\ncontrol emailing on or off: flag: boolean, default: false\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an endApi function gets this invoked prior to process.exit\n\n## getCbCounter()\nEnsures that all callbacks has completed\n\n```js\nvar apprunner = require('apprunner')\nvar cbc = haraldutil.getCbCounter()\nsetTimeout(cbc.add(callback), 100)\nsetTimeout(cbc.add(callback), 100)\n\nfunction callback() {\n  if (cbc.isDone(arguments.callee))\n    console.log('All callbacks completed.')\n  else console.log('Not done yet...')\n}\n```\n```\nNot done yet...\nAll callbacks completed.\n```\nvar cbc = getCbCounter(opts)\n* opts: optional object\n* opts.emitter: optional event emitter or boolean. default: errors are thrown\n\n  * false: errors are ignored\n  * emitter: errors are emitted\n\n* opts.callback: function or array of function: add is done for each function\n\ncbc: object\n* .add(f): adds a callback for function f, return value: f\n* .isDone(f): notes one callback completed. returns true if all callbacks complete, otherwise false\n* .getStatus(): gets an object representing the current state\n\n# Configuring and Writing an Api Module\n\nConfigurations for an api is provided either in defaults or in the opts\n\n## Retrieving an api\n\nAs a minimum, the opts object needs to contain the api property: `getApi({api: 'userstore'})`\n\n## How the api is loaded\n\nAn Api's location is determined by two properties:\n\n1. .file: the same value you would provide to require\n2. .subPath: dot-separated property access inside the module loaded by require\n\nIf file is missing some special steps are taken:\n\n1. If file is missing, the default filename is the api name.\n2. defaults.api.folder can provide a default folder used if file begings with '.' or is missing\n3. If no folder is provided, the lib folder in appFolder is used.\n\n## The api module\n\nThe api module itself can have four optional special exports:\n* initApi(opts): code executed on the first load of the api processing the options. May return a value that is used in place of the regular module value\n* apiReady(cb(err)) calls back when the api is ready to provide service\n* endApi(cb(err)) instructs the api to shut down, ie. close connections and clear timers\n* emitter if this is an EventEmitter, errors emitted are processed as anomalies\n\n## Execution of initApi\n\nif your api exports initApi, ths function is invoked on each require. This is because options may change, and you need to take this in account.\n\ninitApi is provided an options object:\n\n* .config: object: the merge of options providing to getApi and options in apiMap. getApi options overrride\n* .registerHandler(string route, handler(req, res, next)): registers a route with whatever Web server is used. \n* .logger: function(string): the logging to be used\n* .apprunner: object: the apprunner module for convenience\n\nif initApi returns a value, this is used as the result of getApi().\n\n# Examples\n\nTODO\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","_id":"apprunner@0.1.6","dist":{"shasum":"7f2428671a4089277f7a3001d920d6f0038a64c8","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.1.6.tgz","integrity":"sha512-zGHuSEtrH+Lf0dJdGSUbBvtyRW/xEdKp8HZdeN/zE9d6wm0vqHv73qbN07/h88Pt2nGvq9CDIEm8F/VsCdQqeQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC96dLFc3c1xTf4j/x111wB0tiztzwm4K00Eyc2biapbwIgZueGVpsR4+4BmoCD8pqgtpL2xL2ZFBY01qEtNOREY0c="}]},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.1.8":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","app"],"version":"0.1.8","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.34"},"dependencies":{"haraldutil":">= 0.1.15"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage"},"readme":"# App Runner\n\nApp Runner manages app execution and error reporting and provides a unified way to separate and reuse modules. Require is great, App Runner is greater!\n\n## Benefits\n\n1. Move apis between project files and external modules with no code change, or switch implementation for a given api name\n2. Implement one or many apis per file or module.\n2. Configure apis both per invocation and json at launch.\n3. Find root causes by collecting large volumes of elaborate error reports featuring multiple stack traces, variable values and any other useful information.\n4. Continue best effort execution after error reporting.\n5. Server flexibility: apis can register uri routes, but do not depend on a particular Web server implementation.\n6. Gracefully terminate after unhandled process exceptions capturing elaborate error reports.\n7. Gracefully shut down the application on demand using SIGINT signal from keyboard Ctrl-Break or another process\n8. Gracefully launch using api delayed readiness hook\n9. Gracefully exit using api shutdown hook\n9. Track performance of external interfaces using invocation timers\n\n## Features\n\n1. Provides module control from json\n2. Manages application error reports and queues\n3. Lifecycle management of the app and its modules\n5. Single-module exposure of the entire app to the launch script\n\n# Reference\n\nApp Runner handles process exceptions and SIGINT.\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## initApp(defaults, app)\n\n* defaults: options, typically loaded by haraldops\n\n  * .init.appFolder: string: the folder of initial script\n  * .init.logger: optional function(string): logging, default console.log\n  * .init.ops.sendMail: optional function(subject, body): Sends mail, default none\n  * .api: optional, indicates that Api Manager should be used\n  * .api.apiMap: optional: api configurations\n\n* app: Web server, could be an event emitter and have a .get method\n\n## getApi(opts)\n\nExample of using a proprietary serverhelp api, that manages Express lifecycle as an api.\n\n```js\nrequire('apprunner')\n\t.getApi({api: 'serverhelp'})\n\t.listen({\n\t\tserver: app,\n\t\tport: defaults.PORT,\n\t\tinterface: defaults.appInterface},\n\tcbc.add(appIsUp))\n```\n\ngets an api implementation\n* opts: object\n* .api: string: name of api function to be loaded\n\nAPIs are either configured directly in the opts object, or in defaults provided at App Runner's init.\n\n## apisReady(cb)\n\nSurveys all loaded apis to see if they have concluded initializing. Each api can expose an apiReady(cb) function used fo this purpose.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and if so configured a periodcal email.\n\n## enableAnomalyMail(flag)\n\ncontrol emailing on or off: flag: boolean, default: false\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an endApi function gets this invoked prior to process.exit\n\n## getCbCounter()\nEnsures that all callbacks has completed\n\n```js\nvar apprunner = require('apprunner')\nvar cbc = haraldutil.getCbCounter()\nsetTimeout(cbc.add(callback), 100)\nsetTimeout(cbc.add(callback), 100)\n\nfunction callback() {\n  if (cbc.isDone(arguments.callee))\n    console.log('All callbacks completed.')\n  else console.log('Not done yet...')\n}\n```\n```\nNot done yet...\nAll callbacks completed.\n```\nvar cbc = getCbCounter(opts)\n* opts: optional object\n* opts.emitter: optional event emitter or boolean. default: errors are thrown\n\n  * false: errors are ignored\n  * emitter: errors are emitted\n\n* opts.callback: function or array of function: add is done for each function\n\ncbc: object\n* .add(f): adds a callback for function f, return value: f\n* .isDone(f): notes one callback completed. returns true if all callbacks complete, otherwise false\n* .getStatus(): gets an object representing the current state\n\n# Configuring and Writing an Api Module\n\nConfigurations for an api is provided either in defaults or in the opts\n\n## Retrieving an api\n\nAs a minimum, the opts object needs to contain the api property: `getApi({api: 'userstore'})`\n\n## How the api is loaded\n\nAn Api's location is determined by two properties:\n\n1. .file: the same value you would provide to require\n2. .subPath: dot-separated property access inside the module loaded by require\n\nIf file is missing some special steps are taken:\n\n1. If file is missing, the default filename is the api name.\n2. defaults.api.folder can provide a default folder used if file begings with '.' or is missing\n3. If no folder is provided, the lib folder in appFolder is used.\n\n## The api module\n\nThe api module itself can have four optional special exports:\n* initApi(opts): code executed on the first load of the api processing the options. May return a value that is used in place of the regular module value\n* apiReady(cb(err)) calls back when the api is ready to provide service\n* endApi(cb(err)) instructs the api to shut down, ie. close connections and clear timers\n* emitter if this is an EventEmitter, errors emitted are processed as anomalies\n\n## Execution of initApi\n\nif your api exports initApi, ths function is invoked on each require. This is because options may change, and you need to take this in account.\n\ninitApi is provided an options object:\n\n* .config: object: the merge of options providing to getApi and options in apiMap. getApi options overrride\n* .registerHandler(string route, handler(req, res, next)): registers a route with whatever Web server is used. \n* .logger: function(string): the logging to be used\n* .apprunner: object: the apprunner module for convenience\n\nif initApi returns a value, this is used as the result of getApi().\n\n# Examples\n\nTODO\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","_id":"apprunner@0.1.8","dist":{"shasum":"50d7cdda19a527cb06f3d4169edd1c79179e9259","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.1.8.tgz","integrity":"sha512-XTBp1GPNTgCq9jHBmVveD3+fnnChMJLE46mM5+8ahJA67ZU0ZRhUm2FlWCz5KXMRpsQJ9LPP5IFFcAlEXxDmwA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDccGKaE7Bi88TJZCIxKZtrsaZzuxV0cDFUYnitzrhy0wIhAOfW1ZDtONQ6sBX5z52Du9Y7y97s9BOW8lmdSiQPk2S5"}]},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.2.0":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","app"],"version":"0.2.0","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.34"},"dependencies":{"haraldutil":">= 0.1.15"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage"},"readme":"# App Runner\n\nApp Runner manages app execution and error reporting and provides a unified way to separate and reuse modules. Require is great, App Runner is greater!\n\n## Benefits\n\n1. Move apis between project files and external modules with no code change, or switch implementation for a given api name\n2. Implement one or many apis per file or module.\n2. Configure apis both per invocation and json at launch.\n3. Find root causes by collecting large volumes of elaborate error reports featuring multiple stack traces, variable values and any other useful information.\n4. Continue best effort execution after error reporting.\n5. Server flexibility: apis can register uri routes, but do not depend on a particular Web server implementation.\n6. Gracefully terminate after unhandled process exceptions capturing elaborate error reports.\n7. Gracefully shut down the application on demand using SIGINT signal from keyboard Ctrl-Break or another process\n8. Gracefully launch using api delayed readiness hook\n9. Gracefully exit using api shutdown hook\n9. Track performance of external interfaces using invocation timers\n\n## Features\n\n1. Provides module control from json\n2. Manages application error reports and queues\n3. Lifecycle management of the app and its modules\n5. Single-module exposure of the entire app to the launch script\n\n# Reference\n\nApp Runner handles process exceptions and SIGINT.\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## initApp(defaults, app)\n\n* defaults: options, typically loaded by haraldops\n\n  * .init.appFolder: string: the folder of initial script\n  * .init.logger: optional function(string): logging, default console.log\n  * .init.ops.sendMail: optional function(subject, body): Sends mail, default none\n  * .api: optional, indicates that Api Manager should be used\n  * .api.apiMap: optional: api configurations\n\n* app: Web server, could be an event emitter and have a .get method\n\n## getApi(opts)\n\nExample of using a proprietary serverhelp api, that manages Express lifecycle as an api.\n\n```js\nrequire('apprunner')\n\t.getApi({api: 'serverhelp'})\n\t.listen({\n\t\tserver: app,\n\t\tport: defaults.PORT,\n\t\tinterface: defaults.appInterface},\n\tcbc.add(appIsUp))\n```\n\ngets an api implementation\n* opts: object\n* .api: string: name of api function to be loaded\n\nAPIs are either configured directly in the opts object, or in defaults provided at App Runner's init.\n\n## apisReady(cb)\n\nSurveys all loaded apis to see if they have concluded initializing. Each api can expose an apiReady(cb) function used fo this purpose.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and if so configured a periodcal email.\n\n## enableAnomalyMail(flag)\n\ncontrol emailing on or off: flag: boolean, default: false\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an endApi function gets this invoked prior to process.exit\n\n## getCbCounter()\nEnsures that all callbacks has completed\n\n```js\nvar apprunner = require('apprunner')\nvar cbc = haraldutil.getCbCounter()\nsetTimeout(cbc.add(callback), 100)\nsetTimeout(cbc.add(callback), 100)\n\nfunction callback() {\n  if (cbc.isDone(arguments.callee))\n    console.log('All callbacks completed.')\n  else console.log('Not done yet...')\n}\n```\n```\nNot done yet...\nAll callbacks completed.\n```\nvar cbc = getCbCounter(opts)\n* opts: optional object\n* opts.emitter: optional event emitter or boolean. default: errors are thrown\n\n  * false: errors are ignored\n  * emitter: errors are emitted\n\n* opts.callback: function or array of function: add is done for each function\n\ncbc: object\n* .add(f): adds a callback for function f, return value: f\n* .isDone(f): notes one callback completed. returns true if all callbacks complete, otherwise false\n* .getStatus(): gets an object representing the current state\n\n# Configuring and Writing an Api Module\n\nConfigurations for an api is provided either in defaults or in the opts\n\n## Retrieving an api\n\nAs a minimum, the opts object needs to contain the api property: `getApi({api: 'userstore'})`\n\n## How the api is loaded\n\nAn Api's location is determined by two properties:\n\n1. .file: the same value you would provide to require\n2. .subPath: dot-separated property access inside the module loaded by require\n\nIf file is missing some special steps are taken:\n\n1. If file is missing, the default filename is the api name.\n2. defaults.api.folder can provide a default folder used if file begings with '.' or is missing\n3. If no folder is provided, the lib folder in appFolder is used.\n\n## The api module\n\nThe api module itself can have four optional special exports:\n* initApi(opts): code executed on the first load of the api processing the options. May return a value that is used in place of the regular module value\n* apiReady(cb(err)) calls back when the api is ready to provide service\n* endApi(cb(err)) instructs the api to shut down, ie. close connections and clear timers\n* emitter if this is an EventEmitter, errors emitted are processed as anomalies\n\n## Execution of initApi\n\nif your api exports initApi, ths function is invoked on each require. This is because options may change, and you need to take this in account.\n\ninitApi is provided an options object:\n\n* .config: object: the merge of options providing to getApi and options in apiMap. getApi options overrride\n* .registerHandler(string route, handler(req, res, next)): registers a route with whatever Web server is used. \n* .logger: function(string): the logging to be used\n* .apprunner: object: the apprunner module for convenience\n\nif initApi returns a value, this is used as the result of getApi().\n\n# Examples\n\nTODO\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","readmeFilename":"readme.md","_id":"apprunner@0.2.0","dist":{"shasum":"ee3aa5fe46d695f5f808b5fb0d97dbf7519b2697","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.2.0.tgz","integrity":"sha512-4LWWDxYnP7+j5aaUE421tpj9EUtDWU1t8o9pR75h0TVPATRKvjmfyK/Mvweo/HpVjNKwR8AAW62LOtQ9SnvvKA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDhx3xTYHNOXMH2i0zsIgKGecw0hA+pthf7yJe0BpXxZAIgN+idUBJN1NPHDRfvt8Sr0J01ZU+Cpchl1nqDOGO2fCQ="}]},"_npmVersion":"1.2.0","_npmUser":{"name":"haraldrudell","email":"harald@therudells.com"},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.2.1":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","app"],"version":"0.2.1","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.34"},"dependencies":{"haraldutil":">= 0.1.15"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage"},"readme":"# App Runner\n\nApp Runner manages app execution and error reporting and provides a unified way to separate and reuse modules. Require is great, App Runner is greater!\n\n## Benefits\n\n1. Move apis between project files and external modules with no code change, or switch implementation for a given api name\n2. Implement one or many apis per file or module.\n2. Configure apis both per invocation and json at launch.\n3. Find root causes by collecting large volumes of elaborate error reports featuring multiple stack traces, variable values and any other useful information.\n4. Continue best effort execution after error reporting.\n5. Server flexibility: apis can register uri routes, but do not depend on a particular Web server implementation.\n6. Gracefully terminate after unhandled process exceptions capturing elaborate error reports.\n7. Gracefully shut down the application on demand using SIGINT signal from keyboard Ctrl-Break or another process\n8. Gracefully launch using api delayed readiness hook\n9. Gracefully exit using api shutdown hook\n9. Track performance of external interfaces using invocation timers\n\n## Features\n\n1. Provides module control from json\n2. Manages application error reports and queues\n3. Lifecycle management of the app and its modules\n5. Single-module exposure of the entire app to the launch script\n\n# Reference\n\nApp Runner handles process exceptions and SIGINT.\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## initApp(defaults, app)\n\n* defaults: options, typically loaded by haraldops\n\n  * .init.appFolder: string: the folder of initial script\n  * .init.logger: optional function(string): logging, default console.log\n  * .init.ops.sendMail: optional function(subject, body): Sends mail, default none\n  * .api: optional, indicates that Api Manager should be used\n  * .api.apiMap: optional: api configurations\n\n* app: Web server, could be an event emitter and have a .get method\n\n## getApi(opts)\n\nExample of using a proprietary serverhelp api, that manages Express lifecycle as an api.\n\n```js\nrequire('apprunner')\n\t.getApi({api: 'serverhelp'})\n\t.listen({\n\t\tserver: app,\n\t\tport: defaults.PORT,\n\t\tinterface: defaults.appInterface},\n\tcbc.add(appIsUp))\n```\n\ngets an api implementation\n* opts: object\n* .api: string: name of api function to be loaded\n\nAPIs are either configured directly in the opts object, or in defaults provided at App Runner's init.\n\n## apisReady(cb)\n\nSurveys all loaded apis to see if they have concluded initializing. Each api can expose an apiReady(cb) function used fo this purpose.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and if so configured a periodcal email.\n\n## enableAnomalyMail(flag)\n\ncontrol emailing on or off: flag: boolean, default: false\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter. Safe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an endApi function gets this invoked prior to process.exit\n\n## getCbCounter()\nEnsures that all callbacks has completed\n\n```js\nvar apprunner = require('apprunner')\nvar cbc = haraldutil.getCbCounter()\nsetTimeout(cbc.add(callback), 100)\nsetTimeout(cbc.add(callback), 100)\n\nfunction callback() {\n  if (cbc.isDone(arguments.callee))\n    console.log('All callbacks completed.')\n  else console.log('Not done yet...')\n}\n```\n```\nNot done yet...\nAll callbacks completed.\n```\nvar cbc = getCbCounter(opts)\n* opts: optional object\n* opts.emitter: optional event emitter or boolean. default: errors are thrown\n\n  * false: errors are ignored\n  * emitter: errors are emitted\n\n* opts.callback: function or array of function: add is done for each function\n\ncbc: object\n* .add(f): adds a callback for function f, return value: f\n* .isDone(f): notes one callback completed. returns true if all callbacks complete, otherwise false\n* .getStatus(): gets an object representing the current state\n\n# Configuring and Writing an Api Module\n\nConfigurations for an api is provided either in defaults or in the opts\n\n## Retrieving an api\n\nAs a minimum, the opts object needs to contain the api property: `getApi({api: 'userstore'})`\n\n## How the api is loaded\n\nAn Api's location is determined by two properties:\n\n1. .file: the same value you would provide to require\n2. .subPath: dot-separated property access inside the module loaded by require\n\nIf file is missing some special steps are taken:\n\n1. If file is missing, the default filename is the api name.\n2. defaults.api.folder can provide a default folder used if file begings with '.' or is missing\n3. If no folder is provided, the lib folder in appFolder is used.\n\n## The api module\n\nThe api module itself can have four optional special exports:\n* initApi(opts): code executed on the first load of the api processing the options. May return a value that is used in place of the regular module value\n* apiReady(cb(err)) calls back when the api is ready to provide service\n* endApi(cb(err)) instructs the api to shut down, ie. close connections and clear timers\n* emitter if this is an EventEmitter, errors emitted are processed as anomalies\n\n## Execution of initApi\n\nif your api exports initApi, ths function is invoked on each require. This is because options may change, and you need to take this in account.\n\ninitApi is provided an options object:\n\n* .config: object: the merge of options providing to getApi and options in apiMap. getApi options overrride\n* .registerHandler(string route, handler(req, res, next)): registers a route with whatever Web server is used. \n* .logger: function(string): the logging to be used\n* .apprunner: object: the apprunner module for convenience\n\nif initApi returns a value, this is used as the result of getApi().\n\n# Examples\n\nTODO\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","readmeFilename":"readme.md","_id":"apprunner@0.2.1","dist":{"shasum":"3be5744768f6e522b07dd8cb64f1fa66d9450a0c","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.2.1.tgz","integrity":"sha512-pIYi4JZTkOMfOKd3CeLmhpgrb2O3KvbNgXnni5R1SjhJqkg+lZRTxg53HI7BWZSNUAaJTqgYzHeR3v/HG/QN+A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC7b2CWDvSgGqjzVBDm20fxKbfiTUOy/rIqbCTVUCmAMAIhAJ43aFnJ/kqF45PFRILU+rwY4afNZAftopyHWMHIn1rJ"}]},"_npmVersion":"1.2.0","_npmUser":{"name":"haraldrudell","email":"harald@therudells.com"},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.2.2":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","management","lifecycle","app"],"version":"0.2.2","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.34"},"dependencies":{"haraldutil":">= 0.1.15"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage"},"readme":"# App Runner\n\nApp Runner manages app lifecycle\n\n## Benefits\n\n* Flexible module loading provide choice of implementation with no code change\n* Api lifecycle allows module spin-up/shutdown and settings from file data.\n* Easier troubleshooting with emailed anomaly reports\n* Orderly shutdown on exception and signal avoids data loss\n\n## Features\n\n1. Self-contained email forwarding and anomaly detection/reporting\n2. require replacement\n3. api module support with api names, error emiters, request timers, across-api function, settings mix-in and ready watchers\n4. Separation between web server implementation and app code\n5. Configurable handlers for SIGINT SIGURS2, uncaught exception\n\n# Function Reference\n\n## initApp(defaults)\nInitialize apprunner\n```js\nrequire('apprunner').initApp(require('haraldops').init({\n  appName: 'Node God',\n  api: {\n    apiMap: {\n      nodegodweb: {\n        onLoad: true,\n        sessionSecret: 'veryGreat',\n        PORT: 1111,\n      }\n    }\n  }\n}))\n```\n* defaults: options, typically loaded by haraldops\n\n  * .init.noInfoLog: boolean: no logging by appInit\n  * .anomaly: object for anomalysettings of false for disable\n\n## getAppData()\nRetrieve key app data\n```js\nconsole.log(require('apprunner').getAppData())\n```\n```\n{\n  appName: 'Cloud Clearing',\n  appId: 'cloudclearing',\n  launchFolder: '/home/foxyboy/Desktop/c505/node/cloudclearing',\n  sendMail: [Function: send],\n  logger: [Function],\n  registerHandler: [Function: registerHandler],\n  views: { dbview: { db: [Object] } },\n  defaultsFile: '/home/foxyboy/apps/cloudclearing.json'\n}\n```\n\n## getRequire(require, exports, opts)\n\nProvides a require with a flexible search for modules\n```\nrequire = require('apprunner').getRequire(require)\nrequire('myaliasedmodule')\n```\n\nRegisters an api with apprunner, providing emitter, rqs object and initApi wrapper\n```\nrequire = require('apprunner').getRequire(require, exports, {\n  api: 'FB Friends', initApi: initApi, endApi: endApi,\n  rqScope: true, timeoutMs: time10s, ready: false})\n```\n* options\n  * .api: optional string: unique api name eg. 'Server Helper'\n  * .emScope if emitter, this emitter will be used. id property will be updated\n  * .emScope if string: scope for emitter\n  * .initApi: optional function: the internal initApi implementation\n  * .rqScope: optional string or boolen, string slogan for request timer, true if using api name\n  * .cb(err): optional function: rqs error callback\n  * .timeoutMs: number ms: default rqs timeout if not 3 seconds\n  * .ready: positive number: timeout for ready in ms\n  * .ready false: this api does not emit ready\n  * .ready defaults: ready with timeout 3 s\n  * .saveApi: optional function\n  * .endApi: optional function\n  * .apiState: optional function\n\n1. An emitter will be created if emScope or apiName is non-zero string at require.emitter\n2. A request timer will be provided if rqScope is true or non-zero string at require.rqs\n3. The api will be managed if there is a non-zero api name. emitter and initApi are required. api name at require.emitter.id\n\n## apisReady(cb)\n\nSurveys all apis with singleton ready to see if they have concluded initializing.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and possibly via email\n```js\nrequire('apprunner').anomaly(err, {location: 'kitchen', user: 'fail'}, err2)\n```\n\n## enableAnomalyMail(flag)\ncontrol emailing of anomaly reports.\n```js\nrequire('apprunner').enableAnomalyMail('1/1/2013')\n```\n* flag either a date string or boolean flag, default: false\n\nAnomaly reports are not sent until the day after the date provided.\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter.\n\nSafe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter.\n\nSafe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an saveApi or endApi gets these functions invoked prior to process.exit\n\nApp Runner handles process exceptions and SIGINT (ie. ctrl-Break.)\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## addUriHandler(fn)\n\nProvides a function for a Web server instance that registers incoming uri and handlers\n```js\nvar apprunner = require('apprunner')\nvar express = require('express')\n\nvar app = apprunner.addErrorListener(express())\napprunner.addUriHandler(app.get.bind(app))\n```\n* fn(uri, uriHandler): function, uri: string, uriHandler: function\n\n## getRqs(errorCallback, scopeName, defaultTimeoutMs)\n\nGet a timer factory\n```js\nvar rqs = require('apprunner').getRqs(timeoutFn, 'UserStore Timers', 1000)\n\nvar timer = rqs.addRq('Getting Token')\nuserStore.getUser(fbId, saveOauthToken)\n\nfunction saveOauthToken(err, user) {\n  timer.clear()\n  ...\n}\n\nfunction timeoutFn(err) {\n  console.log('an anomaly was reported for a timed out request')\n  // maybe take alternative action\n  if (err.isTimer) {\n    if (err.param === 'Getting Token') ...\n  }\n}\n```\n* errorCallback(err): function: invoked with err for timeouts and inconsitencies\n* scopeName: optional string or object: scope name for this factory eg. 'sync Db'\n* defaultTimeoutMs: optional number: default timeout in ms, min 100,  default 3 s\n\n1. rqs.addRq(parameter, time)\n2. rqs.clearRq(parameter) : same as .clear\n3. rqs.getState()\n4. rqs.shutdown()\n\n# Apis\n\nAn api must be loaded using these two things:\n1. Being loaded using require from getRequire\n2. Provide its initApi function and api name to getRequire\n\n## What's the Difference Between an Api and a Module?\n\n1. An singleton api or api instances returned by initApi can be required to emit ready\n2. An api's initApi is provided options that is json-configured options overriden by invocation options\n3. An api can have onLoad: true\n4. An api has a sigleton emitter at require.emitter\n5. An api has a module name like all modules but also an api name at require.emitter.id\n6. An api can export the special endApi, saveApi and apiState functions\n7. An api can get a timer factory at require.rqs\n\n## Loading an Api\nSingleton\n```js\nrequire = require('apprunner').getRequire(require)\nrequire('serverhelp').listen()\nrequire('mongo').on('ready', mongoReady)\n```\nInstance\n```js\nrequire = require('apprunner').getRequire(require)\nvar fb = require('fb')\nfb.initApi({user: userId}).on('ready', fbReady)\n```\n\n## Writing an Api\nSingleton\n```js\nrequire = require('apprunner').getRequire(require, exports, {\n  api: 'MongoD', initApi: initApi, endApi: endApi,\n  rqScope: true, ready: false})\nfunction someExport(...) ...\n```\nInstance\n```\nrequire = require('apprunner').getRequire(require, exports, {\n  api: 'User Store', initApi: initApi,\n  })\nfunction initApi(opts) {\n  ...\n  var readyState\n  doSome(someCb)\n  function someCb(err, data) {\n    readyState = err || true\n    var eArgs = ['ready']\n    if (err) eArgs.push(err)\n    e.emit.apply(e, eArgs)\n  }\n  var e = new events.EventEmitter\n  e.isReady = isReady\n  return e\n  function isReady() {\n    return readyState\n}\n}\n```\n## Api settings\nApi settings are provided in the defaults object for appInit()\n```js\n{\n    \"api\": {\n    \"path\": [\n      {\n        \"folder\": \"lib\"\n      },\n      {\n        \"file\": \"applego\"\n      }\n    ],\n    \"apiMap\": {\n      \"expressapi\": {\n        \"onLoad\": true,\n        \"sessionSecret\": \"secrets\",\n        \"port\": 3003\n      },\n}\n```\n* path: optional array of locations\n* apiMap: optional object with api settings\n  * each entry can have onLoad, folder/subPath/file along with other settings\n1. A location can have folder/subPath: a string relative to the app's launch folder and a dot-separated name spacing in the loaded module\n2. A location can have  file/subpath where file is a module name and subpath is a dot-separated name spacing in the loaded module\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","readmeFilename":"readme.md","_id":"apprunner@0.2.2","dist":{"shasum":"ef03445207971a2ae57ebb92205fe74fb497638d","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.2.2.tgz","integrity":"sha512-moGUcNA8SL2oBHrNIo2TsRCgKwjFXXiFkVZ2etrQQZBJ9qiaYJG/aAPe+KeNRyfBMYQOpfGacGLZQ0ntenqn4w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDEUkOZ5MMQ3vlrO552HIyKM8AoS/1GrM1HRDXvOHBL/AiBOiWV1J/F6KSSVIK84Wz0tLvxU5g+x6m6xbVuKCsWFiQ=="}]},"_npmVersion":"1.2.0","_npmUser":{"name":"haraldrudell","email":"harald@therudells.com"},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.2.3":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","management","lifecycle","app"],"version":"0.2.3","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.34"},"dependencies":{"haraldutil":">= 0.1.15"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage","changelog":"git log --format=\"%ad %s\" --date=short >ChangeLog; ls -l ChangeLog"},"readme":"# App Runner\n\nApp Runner manages app lifecycle\n\n## Benefits\n\n* Flexible module loading provide choice of implementation with no code change\n* Api lifecycle allows module spin-up/shutdown and settings from file data.\n* Easier troubleshooting with emailed anomaly reports\n* Orderly shutdown on exception and signal avoids data loss\n\n## Features\n\n1. Self-contained email forwarding and anomaly detection/reporting\n2. require replacement\n3. api module support with api names, error emiters, request timers, across-api function, settings mix-in and ready watchers\n4. Separation between web server implementation and app code\n5. Configurable handlers for SIGINT SIGURS2, uncaught exception\n\n# Function Reference\n\n## initApp(defaults)\nInitialize apprunner\n```js\nrequire('apprunner').initApp(require('haraldops').init({\n  appName: 'Node God',\n  api: {\n    apiMap: {\n      nodegodweb: {\n        onLoad: true,\n        sessionSecret: 'veryGreat',\n        PORT: 1111,\n      }\n    }\n  }\n}))\n```\n* defaults: options, typically loaded by haraldops\n\n  * .init.noInfoLog: boolean: no logging by appInit\n  * .anomaly: object for anomalysettings of false for disable\n\n## getAppData(appInfo)\nRetrieve key app data\n```js\nconsole.log(require('apprunner').getAppData())\n```\n```\n{\n  appName: 'Cloud Clearing',\n  appId: 'cloudclearing',\n  launchFolder: '/home/foxyboy/Desktop/c505/node/cloudclearing',\n  sendMail: [Function: send],\n  logger: [Function],\n  registerHandler: [Function: registerHandler],\n  views: { dbview: { db: [Object] } },\n  defaultsFile: '/home/foxyboy/apps/cloudclearing.json'\n}\n```\n* appInfo: optional object PORT:numer, URL: string\nForwarded on signal to [Node God](https://github.com/haraldrudell/nodegod)\n\n## getRequire(require, exports, opts)\n\nProvides a require with a flexible search for modules\n```\nrequire = require('apprunner').getRequire(require)\nrequire('myaliasedmodule')\n```\n\nRegisters an api with apprunner, providing emitter, rqs object and initApi wrapper\n```\nrequire = require('apprunner').getRequire(require, exports, {\n  api: 'FB Friends', initApi: initApi, endApi: endApi,\n  rqScope: true, timeoutMs: time10s, ready: false})\n```\n* options\n  * .api: optional string: unique api name eg. 'Server Helper'\n  * .emScope if emitter, this emitter will be used. id property will be updated\n  * .emScope if string: scope for emitter\n  * .initApi: optional function: the internal initApi implementation\n  * .rqScope: optional string or boolen, string slogan for request timer, true if using api name\n  * .cb(err): optional function: rqs error callback\n  * .timeoutMs: number ms: default rqs timeout if not 3 seconds\n  * .ready: positive number: timeout for ready in ms\n  * .ready false: this api does not emit ready\n  * .ready defaults: ready with timeout 3 s\n  * .saveApi: optional function\n  * .endApi: optional function\n  * .apiState: optional function\n\n1. An emitter will be created if emScope or apiName is non-zero string at require.emitter\n2. A request timer will be provided if rqScope is true or non-zero string at require.rqs\n3. The api will be managed if there is a non-zero api name. emitter and initApi are required. api name at require.emitter.id\n\n## apisReady(cb)\n\nSurveys all apis with singleton ready to see if they have concluded initializing.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and possibly via email\n```js\nrequire('apprunner').anomaly(err, {location: 'kitchen', user: 'fail'}, err2)\n```\n\n## enableAnomalyMail(flag)\ncontrol emailing of anomaly reports.\n```js\nrequire('apprunner').enableAnomalyMail('1/1/2013')\n```\n* flag either a date string or boolean flag, default: false\n\nAnomaly reports are not sent until the day after the date provided.\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter.\n\nSafe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter.\n\nSafe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an saveApi or endApi gets these functions invoked prior to process.exit\n\nApp Runner handles process exceptions and SIGINT (ie. ctrl-Break.)\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## addUriHandler(fn)\n\nProvides a function for a Web server instance that registers incoming uri and handlers\n```js\nvar apprunner = require('apprunner')\nvar express = require('express')\n\nvar app = apprunner.addErrorListener(express())\napprunner.addUriHandler(app.get.bind(app))\n```\n* fn(uri, uriHandler): function, uri: string, uriHandler: function\n\n## getRqs(errorCallback, scopeName, defaultTimeoutMs)\n\nGet a timer factory\n```js\nvar rqs = require('apprunner').getRqs(timeoutFn, 'UserStore Timers', 1000)\n\nvar timer = rqs.addRq('Getting Token')\nuserStore.getUser(fbId, saveOauthToken)\n\nfunction saveOauthToken(err, user) {\n  timer.clear()\n  ...\n}\n\nfunction timeoutFn(err) {\n  console.log('an anomaly was reported for a timed out request')\n  // maybe take alternative action\n  if (err.isTimer) {\n    if (err.param === 'Getting Token') ...\n  }\n}\n```\n* errorCallback(err): function: invoked with err for timeouts and inconsitencies\n* scopeName: optional string or object: scope name for this factory eg. 'sync Db'\n* defaultTimeoutMs: optional number: default timeout in ms, min 100,  default 3 s\n\n1. rqs.addRq(parameter, time)\n2. rqs.clearRq(parameter) : same as .clear\n3. rqs.getState()\n4. rqs.shutdown()\n\n# Apis\n\nAn api must be loaded using these two things:\n\n1. Being loaded using require from getRequire\n2. Provide its initApi function and api name to getRequire\n\n## What's the Difference Between an Api and a Module?\n\n1. An singleton api or api instances returned by initApi can be required to emit ready\n2. An api's initApi is provided options that is json-configured options overriden by invocation options\n3. An api can have onLoad: true\n4. An api has a sigleton emitter at require.emitter\n5. An api has a module name like all modules but also an api name at require.emitter.id\n6. An api can export the special endApi, saveApi and apiState functions\n7. An api can get a timer factory at require.rqs\n\n## Loading an Api\nSingleton\n```js\nrequire = require('apprunner').getRequire(require)\nrequire('serverhelp').listen()\nrequire('mongo').once('ready', mongoReady)\n```\nInstance\n```js\nrequire = require('apprunner').getRequire(require)\nvar fb = require('fb')\nfb.initApi({user: userId}).once('ready', fbReady)\n```\n\n## Writing an Api\nSingleton\n```js\nrequire = require('apprunner').getRequire(require, exports, {\n  api: 'MongoD', initApi: initApi, endApi: endApi,\n  rqScope: true, ready: false})\nfunction someExport(...) ...\n```\nInstance\n```\nrequire = require('apprunner').getRequire(require, exports, {\n  api: 'User Store', initApi: initApi,\n  })\nfunction initApi(opts) {\n  ...\n  var readyState\n  doSome(someCb)\n  function someCb(err, data) {\n    readyState = err || true\n    var eArgs = ['ready']\n    if (err) eArgs.push(err)\n    e.emit.apply(e, eArgs)\n  }\n  var e = new events.EventEmitter\n  e.isReady = isReady\n  return e\n  function isReady() {\n    return readyState\n}\n}\n```\n## Api settings\nApi settings are provided in the defaults object for appInit()\n```js\n{\n    \"api\": {\n    \"path\": [\n      {\n        \"folder\": \"lib\"\n      },\n      {\n        \"file\": \"applego\"\n      }\n    ],\n    \"apiMap\": {\n      \"expressapi\": {\n        \"onLoad\": true,\n        \"sessionSecret\": \"secrets\",\n        \"port\": 3003\n      },\n}\n```\n* path: optional array of locations\n* apiMap: optional object with api settings\n  * each entry can have onLoad, folder/subPath/file along with other settings\n1. A location can have folder/subPath: a string relative to the app's launch folder and a dot-separated name spacing in the loaded module\n2. A location can have  file/subpath where file is a module name and subpath is a dot-separated name spacing in the loaded module\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","readmeFilename":"readme.md","_id":"apprunner@0.2.3","dist":{"shasum":"fa41df0f68e022a93e89134b5c53bc827d901412","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.2.3.tgz","integrity":"sha512-KVxzgkBzTyhc9cO9HQrV6t30n7wwibiW/lefceRcRlUv9wH7RRH1Fuv3V8oAigI9WwvF7X8r/BeACXNwXlEKQQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGp65IaSinj9RtxsX5fHQCmuH77ZrjcLKI1cJF3Ar0q/AiEAjevypM98dZWtghR/qUaDNx4lrglfSkGtPjtVvNbsdHA="}]},"_npmVersion":"1.2.0","_npmUser":{"name":"haraldrudell","email":"harald@therudells.com"},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.2.4":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","management","lifecycle","app"],"version":"0.2.4","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.34"},"dependencies":{"haraldutil":">= 0.1.15"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage","changelog":"git log --format=\"%ad %s\" --date=short >ChangeLog; ls -l ChangeLog"},"readme":"# App Runner\n\nApp Runner manages app lifecycle\n\n## Benefits\n\n* Flexible module loading provide choice of implementation with no code change\n* Api lifecycle allows module spin-up/shutdown and settings from file data.\n* Easier troubleshooting with emailed anomaly reports\n* Orderly shutdown on exception and signal avoids data loss\n\n## Features\n\n1. Self-contained email forwarding and anomaly detection/reporting\n2. require replacement\n3. api module support with api names, error emiters, request timers, across-api function, settings mix-in and ready watchers\n4. Separation between web server implementation and app code\n5. Configurable handlers for SIGINT SIGURS2, uncaught exception\n\n# Function Reference\n\n## initApp(defaults)\nInitialize apprunner\n```js\nrequire('apprunner').initApp(require('haraldops').init({\n  appName: 'Node God',\n  api: {\n    apiMap: {\n      nodegodweb: {\n        onLoad: true,\n        sessionSecret: 'veryGreat',\n        PORT: 1111,\n      }\n    }\n  }\n}))\n```\n* defaults: options, typically loaded by haraldops\n\n  * .init.noInfoLog: boolean: no logging by appInit\n  * .anomaly: object for anomalysettings of false for disable\n\n## getAppData(appInfo)\nRetrieve key app data\n```js\nconsole.log(require('apprunner').getAppData())\n```\n```\n{\n  appName: 'Cloud Clearing',\n  appId: 'cloudclearing',\n  launchFolder: '/home/foxyboy/Desktop/c505/node/cloudclearing',\n  sendMail: [Function: send],\n  logger: [Function],\n  registerHandler: [Function: registerHandler],\n  views: { dbview: { db: [Object] } },\n  defaultsFile: '/home/foxyboy/apps/cloudclearing.json'\n}\n```\n* appInfo: optional object PORT:numer, URL: string\nForwarded on signal to [Node God](https://github.com/haraldrudell/nodegod)\n\n## getRequire(require, exports, opts)\n\nProvides a require with a flexible search for modules\n```\nrequire = require('apprunner').getRequire(require)\nrequire('myaliasedmodule')\n```\n\nRegisters an api with apprunner, providing emitter, rqs object and initApi wrapper\n```\nrequire = require('apprunner').getRequire(require, exports, {\n  api: 'FB Friends', initApi: initApi, endApi: endApi,\n  rqScope: true, timeoutMs: time10s, ready: false})\n```\n* options\n  * .api: optional string: unique api name eg. 'Server Helper'\n  * .emScope if emitter, this emitter will be used. id property will be updated\n  * .emScope if string: scope for emitter\n  * .initApi: optional function: the internal initApi implementation\n  * .rqScope: optional string or boolen, string slogan for request timer, true if using api name\n  * .cb(err): optional function: rqs error callback\n  * .timeoutMs: number ms: default rqs timeout if not 3 seconds\n  * .ready: positive number: timeout for ready in ms\n  * .ready false: this api does not emit ready\n  * .ready defaults: ready with timeout 3 s\n  * .saveApi: optional function\n  * .endApi: optional function\n  * .apiState: optional function\n\n1. An emitter will be created if emScope or apiName is non-zero string at require.emitter\n2. A request timer will be provided if rqScope is true or non-zero string at require.rqs\n3. The api will be managed if there is a non-zero api name. emitter and initApi are required. api name at require.emitter.id\n\n## apisReady(cb)\n\nSurveys all apis with singleton ready to see if they have concluded initializing.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and possibly via email\n```js\nrequire('apprunner').anomaly(err, {location: 'kitchen', user: 'fail'}, err2)\n```\n\n## enableAnomalyMail(flag)\ncontrol emailing of anomaly reports.\n```js\nrequire('apprunner').enableAnomalyMail('1/1/2013')\n```\n* flag either a date string or boolean flag, default: false\n\nAnomaly reports are not sent until the day after the date provided.\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter.\n\nSafe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter.\n\nSafe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an saveApi or endApi gets these functions invoked prior to process.exit\n\nApp Runner handles process exceptions and SIGINT (ie. ctrl-Break.)\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## addUriHandler(fn)\n\nProvides a function for a Web server instance that registers incoming uri and handlers\n```js\nvar apprunner = require('apprunner')\nvar express = require('express')\n\nvar app = apprunner.addErrorListener(express())\napprunner.addUriHandler(app.get.bind(app))\n```\n* fn(uri, uriHandler): function, uri: string, uriHandler: function\n\n## getRqs(errorCallback, scopeName, defaultTimeoutMs)\n\nGet a timer factory\n```js\nvar rqs = require('apprunner').getRqs(timeoutFn, 'UserStore Timers', 1000)\n\nvar timer = rqs.addRq('Getting Token')\nuserStore.getUser(fbId, saveOauthToken)\n\nfunction saveOauthToken(err, user) {\n  timer.clear()\n  ...\n}\n\nfunction timeoutFn(err) {\n  console.log('an anomaly was reported for a timed out request')\n  // maybe take alternative action\n  if (err.isTimer) {\n    if (err.param === 'Getting Token') ...\n  }\n}\n```\n* errorCallback(err): function: invoked with err for timeouts and inconsitencies\n* scopeName: optional string or object: scope name for this factory eg. 'sync Db'\n* defaultTimeoutMs: optional number: default timeout in ms, min 100,  default 3 s\n\n1. rqs.addRq(parameter, time)\n2. rqs.clearRq(parameter) : same as .clear\n3. rqs.getState()\n4. rqs.shutdown()\n\n# Apis\n\nAn api must be loaded using these two things:\n\n1. Being loaded using require from getRequire\n2. Provide its initApi function and api name to getRequire\n\n## What's the Difference Between an Api and a Module?\n\n1. An singleton api or api instances returned by initApi can be required to emit ready\n2. An api's initApi is provided options that is json-configured options overriden by invocation options\n3. An api can have onLoad: true\n4. An api has a sigleton emitter at require.emitter\n5. An api has a module name like all modules but also an api name at require.emitter.id\n6. An api can export the special endApi, saveApi and apiState functions\n7. An api can get a timer factory at require.rqs\n\n## Loading an Api\nSingleton\n```js\nrequire = require('apprunner').getRequire(require)\nrequire('serverhelp').listen()\nrequire('mongo').once('ready', mongoReady)\n```\nInstance\n```js\nrequire = require('apprunner').getRequire(require)\nvar fb = require('fb')\nfb.initApi({user: userId}).once('ready', fbReady)\n```\n\n## Writing an Api\nSingleton\n```js\nrequire = require('apprunner').getRequire(require, exports, {\n  api: 'MongoD', initApi: initApi, endApi: endApi,\n  rqScope: true, ready: false})\nfunction someExport(...) ...\n```\nInstance\n```\nrequire = require('apprunner').getRequire(require, exports, {\n  api: 'User Store', initApi: initApi,\n  })\nfunction initApi(opts) {\n  ...\n  var readyState\n  doSome(someCb)\n  function someCb(err, data) {\n    readyState = err || true\n    var eArgs = ['ready']\n    if (err) eArgs.push(err)\n    e.emit.apply(e, eArgs)\n  }\n  var e = new events.EventEmitter\n  e.isReady = isReady\n  return e\n  function isReady() {\n    return readyState\n}\n}\n```\n## Api settings\nApi settings are provided in the defaults object for appInit()\n```js\n{\n    \"api\": {\n    \"path\": [\n      {\n        \"folder\": \"lib\"\n      },\n      {\n        \"file\": \"applego\"\n      }\n    ],\n    \"apiMap\": {\n      \"expressapi\": {\n        \"onLoad\": true,\n        \"sessionSecret\": \"secrets\",\n        \"port\": 3003\n      },\n}\n```\n* path: optional array of locations\n* apiMap: optional object with api settings\n  * each entry can have onLoad, folder/subPath/file along with other settings\n1. A location can have folder/subPath: a string relative to the app's launch folder and a dot-separated name spacing in the loaded module\n2. A location can have  file/subpath where file is a module name and subpath is a dot-separated name spacing in the loaded module\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","readmeFilename":"readme.md","_id":"apprunner@0.2.4","dist":{"shasum":"6fbf5ae232cf1e07dfbfd93d158f85623c912f24","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.2.4.tgz","integrity":"sha512-1rhfT5fOrSqQIIiz/NGUJtY2yM2YCMjOkKVfu4WQOyB6AUH/o5nC/iArpOd9BU+S0HzFWk1Y/FogSUyq+MzlxA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGlXJl0FLYsZbZEnSOkB0us6HEfCA1zhZziqQDgd2H4PAiAzV0pdCNnF9E3lmWr20pwchFAYyLhdFfXdHwc0Y5yFzQ=="}]},"_npmVersion":"1.2.0","_npmUser":{"name":"haraldrudell","email":"harald@therudells.com"},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.2.5":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","management","lifecycle","app"],"version":"0.2.5","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.34"},"dependencies":{"haraldutil":">= 0.1.17"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage","changelog":"git log --format=\"%ad %s\" --date=short >ChangeLog; ls -l ChangeLog"},"readme":"# App Runner\n\nApp Runner manages app lifecycle\n\n## Benefits\n\n* Flexible module loading provide choice of implementation with no code change\n* Api lifecycle allows module spin-up/shutdown and settings from file data.\n* Easier troubleshooting with emailed anomaly reports\n* Orderly shutdown on exception and signal avoids data loss\n\n## Features\n\n1. Self-contained email forwarding and anomaly detection/reporting\n2. require replacement\n3. api module support with api names, error emiters, request timers, across-api function, settings mix-in and ready watchers\n4. Separation between web server implementation and app code\n5. Configurable handlers for SIGINT SIGURS2, uncaught exception\n\n# Function Reference\n\n## initApp(defaults)\nInitialize apprunner\n```js\nrequire('apprunner').initApp(require('haraldops').init({\n  appName: 'Node God',\n  api: {\n    apiMap: {\n      nodegodweb: {\n        onLoad: true,\n        sessionSecret: 'veryGreat',\n        PORT: 1111,\n      }\n    }\n  }\n}))\n```\n* defaults: options, typically loaded by haraldops\n\n  * .init.noInfoLog: boolean: no logging by appInit\n  * .anomaly: object for anomalysettings of false for disable\n\n## getAppData(appInfo)\nRetrieve key app data\n```js\nconsole.log(require('apprunner').getAppData())\n```\n```\n{\n  appName: 'Cloud Clearing',\n  appId: 'cloudclearing',\n  launchFolder: '/home/foxyboy/Desktop/c505/node/cloudclearing',\n  sendMail: [Function: send],\n  logger: [Function],\n  registerHandler: [Function: registerHandler],\n  views: { dbview: { db: [Object] } },\n  defaultsFile: '/home/foxyboy/apps/cloudclearing.json'\n}\n```\n* appInfo: optional object PORT:numer, URL: string\nForwarded on signal to [Node God](https://github.com/haraldrudell/nodegod)\n\n## getRequire(require, exports, opts)\n\nProvides a require with a flexible search for modules\n```\nrequire = require('apprunner').getRequire(require)\nrequire('myaliasedmodule')\n```\n\nRegisters an api with apprunner, providing emitter, rqs object and initApi wrapper\n```\nrequire = require('apprunner').getRequire(require, exports, {\n  api: 'FB Friends', initApi: initApi, endApi: endApi,\n  rqScope: true, timeoutMs: time10s, ready: false})\n```\n* options\n  * .api: optional string: unique api name eg. 'Server Helper'\n  * .emScope if emitter, this emitter will be used. id property will be updated\n  * .emScope if string: scope for emitter\n  * .initApi: optional function: the internal initApi implementation\n  * .rqScope: optional string or boolen, string slogan for request timer, true if using api name\n  * .cb(err): optional function: rqs error callback\n  * .timeoutMs: number ms: default rqs timeout if not 3 seconds\n  * .ready: positive number: timeout for ready in ms\n  * .ready false: this api does not emit ready\n  * .ready defaults: ready with timeout 3 s\n  * .saveApi: optional function\n  * .endApi: optional function\n  * .apiState: optional function\n\n1. An emitter will be created if emScope or apiName is non-zero string at require.emitter\n2. A request timer will be provided if rqScope is true or non-zero string at require.rqs\n3. The api will be managed if there is a non-zero api name. emitter and initApi are required. api name at require.emitter.id\n\n## apisReady(cb)\n\nSurveys all apis with singleton ready to see if they have concluded initializing.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and possibly via email\n```js\nrequire('apprunner').anomaly(err, {location: 'kitchen', user: 'fail'}, err2)\n```\n\n## enableAnomalyMail(flag)\ncontrol emailing of anomaly reports.\n```js\nrequire('apprunner').enableAnomalyMail('1/1/2013')\n```\n* flag either a date string or boolean flag, default: false\n\nAnomaly reports are not sent until the day after the date provided.\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter.\n\nSafe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter.\n\nSafe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an saveApi or endApi gets these functions invoked prior to process.exit\n\nApp Runner handles process exceptions and SIGINT (ie. ctrl-Break.)\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## addUriHandler(fn)\n\nProvides a function for a Web server instance that registers incoming uri and handlers\n```js\nvar apprunner = require('apprunner')\nvar express = require('express')\n\nvar app = apprunner.addErrorListener(express())\napprunner.addUriHandler(app.get.bind(app))\n```\n* fn(uri, uriHandler): function, uri: string, uriHandler: function\n\n## getRqs(errorCallback, scopeName, defaultTimeoutMs)\n\nGet a timer factory\n```js\nvar rqs = require('apprunner').getRqs(timeoutFn, 'UserStore Timers', 1000)\n\nvar timer = rqs.addRq('Getting Token')\nuserStore.getUser(fbId, saveOauthToken)\n\nfunction saveOauthToken(err, user) {\n  timer.clear()\n  ...\n}\n\nfunction timeoutFn(err) {\n  console.log('an anomaly was reported for a timed out request')\n  // maybe take alternative action\n  if (err.isTimer) {\n    if (err.param === 'Getting Token') ...\n  }\n}\n```\n* errorCallback(err): function: invoked with err for timeouts and inconsitencies\n* scopeName: optional string or object: scope name for this factory eg. 'sync Db'\n* defaultTimeoutMs: optional number: default timeout in ms, min 100,  default 3 s\n\n1. rqs.addRq(parameter, time)\n2. rqs.clearRq(parameter) : same as .clear\n3. rqs.getState()\n4. rqs.shutdown()\n\n# Apis\n\nAn api must be loaded using these two things:\n\n1. Being loaded using require from getRequire\n2. Provide its initApi function and api name to getRequire\n\n## What's the Difference Between an Api and a Module?\n\n1. An singleton api or api instances returned by initApi can be required to emit ready\n2. An api's initApi is provided options that is json-configured options overriden by invocation options\n3. An api can have onLoad: true\n4. An api has a sigleton emitter at require.emitter\n5. An api has a module name like all modules but also an api name at require.emitter.id\n6. An api can export the special endApi, saveApi and apiState functions\n7. An api can get a timer factory at require.rqs\n\n## Loading an Api\nSingleton\n```js\nrequire = require('apprunner').getRequire(require)\nrequire('serverhelp').listen()\nrequire('mongo').once('ready', mongoReady)\n```\nInstance\n```js\nrequire = require('apprunner').getRequire(require)\nvar fb = require('fb')\nfb.initApi({user: userId}).once('ready', fbReady)\n```\n\n## Writing an Api\nSingleton\n```js\nrequire = require('apprunner').getRequire(require, exports, {\n  api: 'MongoD', initApi: initApi, endApi: endApi,\n  rqScope: true, ready: false})\nfunction someExport(...) ...\n```\nInstance\n```\nrequire = require('apprunner').getRequire(require, exports, {\n  api: 'User Store', initApi: initApi,\n  })\nfunction initApi(opts) {\n  ...\n  var readyState\n  doSome(someCb)\n  function someCb(err, data) {\n    readyState = err || true\n    var eArgs = ['ready']\n    if (err) eArgs.push(err)\n    e.emit.apply(e, eArgs)\n  }\n  var e = new events.EventEmitter\n  e.isReady = isReady\n  return e\n  function isReady() {\n    return readyState\n}\n}\n```\n## Api settings\nApi settings are provided in the defaults object for appInit()\n```js\n{\n    \"api\": {\n    \"path\": [\n      {\n        \"folder\": \"lib\"\n      },\n      {\n        \"file\": \"applego\"\n      }\n    ],\n    \"apiMap\": {\n      \"expressapi\": {\n        \"onLoad\": true,\n        \"sessionSecret\": \"secrets\",\n        \"port\": 3003\n      },\n}\n```\n* path: optional array of locations\n* apiMap: optional object with api settings\n  * each entry can have onLoad, folder/subPath/file along with other settings\n1. A location can have folder/subPath: a string relative to the app's launch folder and a dot-separated name spacing in the loaded module\n2. A location can have  file/subpath where file is a module name and subpath is a dot-separated name spacing in the loaded module\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","readmeFilename":"readme.md","_id":"apprunner@0.2.5","dist":{"shasum":"e74ac2c2ce89aaba2b0da8d2654944640e26a73a","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.2.5.tgz","integrity":"sha512-e0jXPVd3I3EcLx1y8Ad4gmMZtGe6ceI6I//WzIew+hZDB8IlPIZ44ZNN3XirOV56vQ15fxM3FRREHL1RdWsreg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCcDhzWE3UpiivzcoD4pTe8syhGcaBUpZSQ3jehdraWygIgZSlmi7NWG0uOUGsX31Rb35lRJT258qVXhDZFnN1Pl+w="}]},"_npmVersion":"1.2.0","_npmUser":{"name":"haraldrudell","email":"harald@therudells.com"},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.2.6":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","management","lifecycle","app"],"version":"0.2.6","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.34"},"dependencies":{"haraldutil":">= 0.1.17"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage","changelog":"git log --format=\"%ad %s\" --date=short >ChangeLog; ls -l ChangeLog"},"readme":"# App Runner\n\nApp Runner manages app lifecycle\n\n## Benefits\n\n* Flexible module loading provide choice of implementation with no code change\n* Api lifecycle allows module spin-up/shutdown and settings from file data.\n* Easier troubleshooting with emailed anomaly reports\n* Orderly shutdown on exception and signal avoids data loss\n\n## Features\n\n1. Self-contained email forwarding and anomaly detection/reporting\n2. require replacement\n3. api module support with api names, error emiters, request timers, across-api function, settings mix-in and ready watchers\n4. Separation between web server implementation and app code\n5. Configurable handlers for SIGINT SIGURS2, uncaught exception\n\n# Function Reference\n\n## initApp(defaults)\nInitialize apprunner\n```js\nrequire('apprunner').initApp(require('haraldops').init({\n  appName: 'Node God',\n  api: {\n    apiMap: {\n      nodegodweb: {\n        onLoad: true,\n        sessionSecret: 'veryGreat',\n        PORT: 1111,\n      }\n    }\n  }\n}))\n```\n* defaults: options, typically loaded by haraldops\n\n  * .init.noInfoLog: boolean: no logging by appInit\n  * .anomaly: object for anomalysettings of false for disable\n\n## getAppData(appInfo)\nRetrieve key app data\n```js\nconsole.log(require('apprunner').getAppData())\n```\n```\n{\n  appName: 'Cloud Clearing',\n  appId: 'cloudclearing',\n  launchFolder: '/home/foxyboy/Desktop/c505/node/cloudclearing',\n  sendMail: [Function: send],\n  logger: [Function],\n  registerHandler: [Function: registerHandler],\n  views: { dbview: { db: [Object] } },\n  defaultsFile: '/home/foxyboy/apps/cloudclearing.json'\n}\n```\n* appInfo: optional object PORT:numer, URL: string\nForwarded on signal to [Node God](https://github.com/haraldrudell/nodegod)\n\n## getRequire(require, exports, opts)\n\nProvides a require with a flexible search for modules\n```\nrequire = require('apprunner').getRequire(require)\nrequire('myaliasedmodule')\n```\n\nRegisters an api with apprunner, providing emitter, rqs object and initApi wrapper\n```\nrequire = require('apprunner').getRequire(require, exports, {\n  api: 'FB Friends', initApi: initApi, endApi: endApi,\n  rqScope: true, timeoutMs: time10s, ready: false})\n```\n* options\n  * .api: optional string: unique api name eg. 'Server Helper'\n  * .emScope if emitter, this emitter will be used. id property will be updated\n  * .emScope if string: scope for emitter\n  * .initApi: optional function: the internal initApi implementation\n  * .rqScope: optional string or boolen, string slogan for request timer, true if using api name\n  * .cb(err): optional function: rqs error callback\n  * .timeoutMs: number ms: default rqs timeout if not 3 seconds\n  * .ready: positive number: timeout for ready in ms\n  * .ready false: this api does not emit ready\n  * .ready defaults: ready with timeout 3 s\n  * .saveApi: optional function\n  * .endApi: optional function\n  * .apiState: optional function\n\n1. An emitter will be created if emScope or apiName is non-zero string at require.emitter\n2. A request timer will be provided if rqScope is true or non-zero string at require.rqs\n3. The api will be managed if there is a non-zero api name. emitter and initApi are required. api name at require.emitter.id\n\n## apisReady(cb)\n\nSurveys all apis with singleton ready to see if they have concluded initializing.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and possibly via email\n```js\nrequire('apprunner').anomaly(err, {location: 'kitchen', user: 'fail'}, err2)\n```\n\n## enableAnomalyMail(flag)\ncontrol emailing of anomaly reports.\n```js\nrequire('apprunner').enableAnomalyMail('1/1/2013')\n```\n* flag either a date string or boolean flag, default: false\n\nAnomaly reports are not sent until the day after the date provided.\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter.\n\nSafe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter.\n\nSafe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an saveApi or endApi gets these functions invoked prior to process.exit\n\nApp Runner handles process exceptions and SIGINT (ie. ctrl-Break.)\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## addUriHandler(fn)\n\nProvides a function for a Web server instance that registers incoming uri and handlers\n```js\nvar apprunner = require('apprunner')\nvar express = require('express')\n\nvar app = apprunner.addErrorListener(express())\napprunner.addUriHandler(app.get.bind(app))\n```\n* fn(uri, uriHandler): function, uri: string, uriHandler: function\n\n## getRqs(errorCallback, scopeName, defaultTimeoutMs)\n\nGet a timer factory\n```js\nvar rqs = require('apprunner').getRqs(timeoutFn, 'UserStore Timers', 1000)\n\nvar timer = rqs.addRq('Getting Token')\nuserStore.getUser(fbId, saveOauthToken)\n\nfunction saveOauthToken(err, user) {\n  timer.clear()\n  ...\n}\n\nfunction timeoutFn(err) {\n  console.log('an anomaly was reported for a timed out request')\n  // maybe take alternative action\n  if (err.isTimer) {\n    if (err.param === 'Getting Token') ...\n  }\n}\n```\n* errorCallback(err): function: invoked with err for timeouts and inconsitencies\n* scopeName: optional string or object: scope name for this factory eg. 'sync Db'\n* defaultTimeoutMs: optional number: default timeout in ms, min 100,  default 3 s\n\n1. rqs.addRq(parameter, time)\n2. rqs.clearRq(parameter) : same as .clear\n3. rqs.getState()\n4. rqs.shutdown()\n\n# Apis\n\nAn api must be loaded using these two things:\n\n1. Being loaded using require from getRequire\n2. Provide its initApi function and api name to getRequire\n\n## What's the Difference Between an Api and a Module?\n\n1. An singleton api or api instances returned by initApi can be required to emit ready\n2. An api's initApi is provided options that is json-configured options overriden by invocation options\n3. An api can have onLoad: true\n4. An api has a sigleton emitter at require.emitter\n5. An api has a module name like all modules but also an api name at require.emitter.id\n6. An api can export the special endApi, saveApi and apiState functions\n7. An api can get a timer factory at require.rqs\n\n## Loading an Api\nSingleton\n```js\nrequire = require('apprunner').getRequire(require)\nrequire('serverhelp').listen()\nrequire('mongo').once('ready', mongoReady)\n```\nInstance\n```js\nrequire = require('apprunner').getRequire(require)\nvar fb = require('fb')\nfb.initApi({user: userId}).once('ready', fbReady)\n```\n\n## Writing an Api\nSingleton\n```js\nrequire = require('apprunner').getRequire(require, exports, {\n  api: 'MongoD', initApi: initApi, endApi: endApi,\n  rqScope: true, ready: false})\nfunction someExport(...) ...\n```\nInstance\n```\nrequire = require('apprunner').getRequire(require, exports, {\n  api: 'User Store', initApi: initApi,\n  })\nfunction initApi(opts) {\n  ...\n  var readyState\n  doSome(someCb)\n  function someCb(err, data) {\n    readyState = err || true\n    var eArgs = ['ready']\n    if (err) eArgs.push(err)\n    e.emit.apply(e, eArgs)\n  }\n  var e = new events.EventEmitter\n  e.isReady = isReady\n  return e\n  function isReady() {\n    return readyState\n}\n}\n```\n## Api settings\nApi settings are provided in the defaults object for appInit()\n```js\n{\n    \"api\": {\n    \"path\": [\n      {\n        \"folder\": \"lib\"\n      },\n      {\n        \"file\": \"applego\"\n      }\n    ],\n    \"apiMap\": {\n      \"expressapi\": {\n        \"onLoad\": true,\n        \"sessionSecret\": \"secrets\",\n        \"port\": 3003\n      },\n}\n```\n* path: optional array of locations\n* apiMap: optional object with api settings\n  * each entry can have onLoad, folder/subPath/file along with other settings\n1. A location can have folder/subPath: a string relative to the app's launch folder and a dot-separated name spacing in the loaded module\n2. A location can have  file/subpath where file is a module name and subpath is a dot-separated name spacing in the loaded module\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","readmeFilename":"readme.md","_id":"apprunner@0.2.6","dist":{"shasum":"7d61204b13cd69dfb81b37d3ab9fa296ffc9e602","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.2.6.tgz","integrity":"sha512-nh6AfgvZF36ZwxyXITipPhXOEgptQbekFuntWnMjJNGhwAXsvE6migSFZBszKASxzNgETApHrXEeH3Nhsyew4w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC8wC/bHRn82r3ZWZr6UYSDQZDQN1gfp/1TxGmM+HR7hwIgeob/kRilwf26RCYm9rPcGhBIeWhOJWp3HWo4t9yHVjk="}]},"_npmVersion":"1.2.0","_npmUser":{"name":"haraldrudell","email":"harald@therudells.com"},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.2.7":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","management","lifecycle","app"],"version":"0.2.7","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.34"},"dependencies":{"haraldutil":">= 0.1.17"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage","changelog":"git log --format=\"%ad %s\" --date=short >ChangeLog; ls -l ChangeLog"},"readme":"# App Runner\n\nApp Runner manages app lifecycle\n\n## Benefits\n\n* Flexible module loading provide choice of implementation with no code change\n* Api lifecycle allows module spin-up/shutdown and settings from file data.\n* Easier troubleshooting with emailed anomaly reports\n* Orderly shutdown on exception and signal avoids data loss\n\n## Features\n\n1. Self-contained email forwarding and anomaly detection/reporting\n2. require replacement\n3. api module support with api names, error emiters, request timers, across-api function, settings mix-in and ready watchers\n4. Separation between web server implementation and app code\n5. Configurable handlers for SIGINT SIGURS2, uncaught exception\n\n# Function Reference\n\n## initApp(defaults)\nInitialize apprunner\n```js\nrequire('apprunner').initApp(require('haraldops').init({\n\tappName: 'Node God',\n\tapi: {\n\t\tapiMap: {\n\t\t\tnodegodweb: {\n\t\t\t\tonLoad: true,\n\t\t\t\tsessionSecret: 'veryGreat',\n\t\t\t\tPORT: 1111,\n\t\t\t}\n\t\t}\n\t}\n}))\n```\n* defaults: options, typically loaded by haraldops\n\n\t* .init.noInfoLog: boolean: no logging by appInit\n\t* .anomaly: object for anomalysettings of false for disable\n\n## getAppData(appInfo)\nRetrieve key app data\n```js\nconsole.log(require('apprunner').getAppData())\n```\n```\n{\n\tappName: 'Cloud Clearing',\n\tappId: 'cloudclearing',\n\tlaunchFolder: '/home/foxyboy/Desktop/c505/node/cloudclearing',\n\tsendMail: [Function: send],\n\tlogger: [Function],\n\tregisterHandler: [Function: registerHandler],\n\tviews: { dbview: { db: [Object] } },\n\tdefaultsFile: '/home/foxyboy/apps/cloudclearing.json'\n}\n```\n* appInfo: optional object PORT:numer, URL: string\nForwarded on signal to [Node God](https://github.com/haraldrudell/nodegod)\n\n## getRequire(require, exports, opts)\n\nProvides a require with a flexible search for modules\n```\nrequire = require('apprunner').getRequire(require)\nrequire('myaliasedmodule')\n```\n\nRegisters an api with apprunner, providing emitter, rqs object and initApi wrapper\n```\nrequire = require('apprunner').getRequire(require, exports, {\n\tapi: 'FB Friends', initApi: initApi, endApi: endApi,\n\trqScope: true, timeoutMs: time10s, ready: false})\n```\n* options\n\t* .api: optional string: unique api name eg. 'Server Helper'\n\t* .emScope if emitter, this emitter will be used. id property will be updated\n\t* .emScope if string: scope for emitter\n\t* .initApi: optional function: the internal initApi implementation\n\t* .rqScope: optional string or boolen, string slogan for request timer, true if using api name\n\t* .cb(err): optional function: rqs error callback\n\t* .timeoutMs: number ms: default rqs timeout if not 3 seconds\n\t* .ready: positive number: timeout for ready in ms\n\t* .ready false: this api does not emit ready\n\t* .ready defaults: ready with timeout 3 s\n\t* .saveApi: optional function\n\t* .endApi: optional function\n\t* .apiState: optional function\n\n1. An emitter will be created if emScope or apiName is non-zero string at require.emitter\n2. A request timer will be provided if rqScope is true or non-zero string at require.rqs\n3. The api will be managed if there is a non-zero api name. emitter and initApi are required. api name at require.emitter.id\n\n## apisReady(cb)\n\nSurveys all apis with singleton ready to see if they have concluded initializing.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and possibly via email\n```js\nrequire('apprunner').anomaly(err, {location: 'kitchen', user: 'fail'}, err2)\n```\n\n## enableAnomalyMail(flag)\ncontrol emailing of anomaly reports.\n```js\nrequire('apprunner').enableAnomalyMail('1/1/2013')\n```\n* flag either a date string or boolean flag, default: false\n\nAnomaly reports are not sent until the day after the date provided.\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter.\n\nSafe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter.\n\nSafe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an saveApi or endApi gets these functions invoked prior to process.exit\n\nApp Runner handles process exceptions and SIGINT (ie. ctrl-Break.)\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## addUriHandler(fn)\n\nProvides a function for a Web server instance that registers incoming uri and handlers\n```js\nvar apprunner = require('apprunner')\nvar express = require('express')\n\nvar app = apprunner.addErrorListener(express())\napprunner.addUriHandler(app.get.bind(app))\n```\n* fn(uri, uriHandler): function, uri: string, uriHandler: function\n\n## getRqs(errorCallback, scopeName, defaultTimeoutMs)\n\nGet a timer factory\n```js\nvar rqs = require('apprunner').getRqs(timeoutFn, 'UserStore Timers', 1000)\n\nvar timer = rqs.addRq('Getting Token')\nuserStore.getUser(fbId, saveOauthToken)\n\nfunction saveOauthToken(err, user) {\n\ttimer.clear()\n\t...\n}\n\nfunction timeoutFn(err) {\n\tconsole.log('an anomaly was reported for a timed out request')\n\t// maybe take alternative action\n\tif (err.isTimer) {\n\t\tif (err.param === 'Getting Token') ...\n\t}\n}\n```\n* errorCallback(err): function: invoked with err for timeouts and inconsitencies\n* scopeName: optional string or object: scope name for this factory eg. 'sync Db'\n* defaultTimeoutMs: optional number: default timeout in ms, min 100,  default 3 s\n\n1. rqs.addRq(parameter, time)\n2. rqs.clearRq(parameter) : same as .clear\n3. rqs.getState()\n4. rqs.shutdown()\n\n# Apis\n\nAn api must be loaded using these two things:\n\n1. Being loaded using require from getRequire\n2. Provide its initApi function and api name to getRequire\n\n## What's the Difference Between an Api and a Module?\n\n1. An singleton api or api instances returned by initApi can be required to emit ready\n2. An api's initApi is provided options that is json-configured options overriden by invocation options\n3. An api can have onLoad: true\n4. An api has a sigleton emitter at require.emitter\n5. An api has a module name like all modules but also an api name at require.emitter.id\n6. An api can export the special endApi, saveApi and apiState functions\n7. An api can get a timer factory at require.rqs\n\n<h2>What code should be an Api?</h2>\n<p>What source files should be designed as an api?</p>\n<ol>\n\t<li>Modules that are shared across multiple apps or apis without being an npm package.</li>\n\t<li>modules with specific needs:<ol>\n\t\t<li>Instance matching</li>\n\t\t<li>Managed lifecycle due to timers, open ports to or tcp connections</li>\n\t\t<li>Singleton ready to delay app start</li>\n\t\t<li>Configuration information like urls or passwords</li>\n\t\t<li>Diagnostic error emitting</li>\n\t\t<li>Provide ops information</li>\n\t\t<li>Start using onLoad</li>\n\t</ol>\n</ol>\n\n## Loading an Api\nSingleton\n```js\nrequire = require('apprunner').getRequire(require)\nrequire('serverhelp').listen()\nrequire('mongo').once('ready', mongoReady)\n```\nInstance\n```js\nrequire = require('apprunner').getRequire(require)\nvar fb = require('fb')\nfb.initApi({user: userId}).once('ready', fbReady)\n```\n\n## Writing an Api\nSingleton\n```js\nrequire = require('apprunner').getRequire(require, exports, {\n\tapi: 'MongoD', initApi: initApi, endApi: endApi,\n\trqScope: true, ready: false})\nfunction someExport(...) ...\n```\nInstance\n```\nrequire = require('apprunner').getRequire(require, exports, {\n\tapi: 'User Store', initApi: initApi,\n\t})\nfunction initApi(opts) {\n\t...\n\tvar readyState\n\tdoSome(someCb)\n\tfunction someCb(err, data) {\n\t\treadyState = err || true\n\t\tvar eArgs = ['ready']\n\t\tif (err) eArgs.push(err)\n\t\te.emit.apply(e, eArgs)\n\t}\n\tvar e = new events.EventEmitter\n\te.isReady = isReady\n\treturn e\n\tfunction isReady() {\n\t\treturn readyState\n}\n}\n```\n## Api settings\nApi settings are provided in the defaults object for appInit()\n```js\n{\n\t\t\"api\": {\n\t\t\"path\": [\n\t\t\t{\n\t\t\t\t\"folder\": \"lib\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"file\": \"applego\"\n\t\t\t}\n\t\t],\n\t\t\"apiMap\": {\n\t\t\t\"expressapi\": {\n\t\t\t\t\"onLoad\": true,\n\t\t\t\t\"sessionSecret\": \"secrets\",\n\t\t\t\t\"port\": 3003\n\t\t\t},\n}\n```\n* path: optional array of locations\n* apiMap: optional object with api settings\n\t* each entry can have onLoad, folder/subPath/file along with other settings\n1. A location can have folder/subPath: a string relative to the app's launch folder and a dot-separated name spacing in the loaded module\n2. A location can have  file/subpath where file is a module name and subpath is a dot-separated name spacing in the loaded module\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","readmeFilename":"readme.md","_id":"apprunner@0.2.7","dist":{"shasum":"bf6537276edfea34f67073684106fa049d731a37","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.2.7.tgz","integrity":"sha512-VbKIPQ+z4iK/4hIVHqvpiQF/CfOm0tT6pihhGcBdwURiOnT38h2GZz4t/Vy9iI8Uoi1JrQTfO2Wu4i5jumhscQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHhWPKArbMDdZc2jflhWRfpeuU7hKomtHMP7Zudid0cyAiAsLUntxAcW1/5GtJETxq4qMyDXpsgFdaKKMuGxVIq5Gg=="}]},"_npmVersion":"1.2.0","_npmUser":{"name":"haraldrudell","email":"harald@therudells.com"},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.2.8":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","management","lifecycle","app"],"version":"0.2.8","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.34","grunt":">= 0.4.0rc7"},"dependencies":{"haraldutil":">= 0.1.17"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage","changelog":"git log --format=\"%ad %s\" --date=short >ChangeLog; ls -l ChangeLog"},"readme":"# App Runner\n\nApp Runner manages app lifecycle\n\n## Benefits\n\n* Flexible module loading provide choice of implementation with no code change\n* Api lifecycle allows module spin-up/shutdown and settings from file data.\n* Easier troubleshooting with emailed anomaly reports\n* Orderly shutdown on exception and signal avoids data loss\n\n## Features\n\n1. Self-contained email forwarding and anomaly detection/reporting\n2. require replacement\n3. api module support with api names, error emiters, request timers, across-api function, settings mix-in and ready watchers\n4. Separation between web server implementation and app code\n5. Configurable handlers for SIGINT SIGURS2, uncaught exception\n\n# Function Reference\n\n## initApp(defaults)\nInitialize apprunner\n```js\nrequire('apprunner').initApp(require('haraldops').init({\n\tappName: 'Node God',\n\tapi: {\n\t\tapiMap: {\n\t\t\tnodegodweb: {\n\t\t\t\tonLoad: true,\n\t\t\t\tsessionSecret: 'veryGreat',\n\t\t\t\tPORT: 1111,\n\t\t\t}\n\t\t}\n\t}\n}))\n```\n* defaults: options, typically loaded by haraldops\n\n\t* .init.noInfoLog: boolean: no logging by appInit\n\t* .anomaly: object for anomalysettings of false for disable\n\n## getAppData(appInfo)\nRetrieve key app data\n```js\nconsole.log(require('apprunner').getAppData())\n```\n```\n{\n\tappName: 'Cloud Clearing',\n\tappId: 'cloudclearing',\n\tlaunchFolder: '/home/foxyboy/Desktop/c505/node/cloudclearing',\n\tsendMail: [Function: send],\n\tlogger: [Function],\n\tregisterHandler: [Function: registerHandler],\n\tviews: { dbview: { db: [Object] } },\n\tdefaultsFile: '/home/foxyboy/apps/cloudclearing.json'\n}\n```\n* appInfo: optional object PORT:numer, URL: string\nForwarded on signal to [Node God](https://github.com/haraldrudell/nodegod)\n\n## getRequire(require, exports, opts)\n\nProvides a require with a flexible search for modules\n```\nrequire = require('apprunner').getRequire(require)\nrequire('myaliasedmodule')\n```\n\nRegisters an api with apprunner, providing emitter, rqs object and initApi wrapper\n```\nrequire = require('apprunner').getRequire(require, exports, {\n\tapi: 'FB Friends', initApi: initApi, endApi: endApi,\n\trqScope: true, timeoutMs: time10s, ready: false})\n```\n* options\n\t* .api: optional string: unique api name eg. 'Server Helper'\n\t* .emScope if emitter, this emitter will be used. id property will be updated\n\t* .emScope if string: scope for emitter\n\t* .initApi: optional function: the internal initApi implementation\n\t* .rqScope: optional string or boolen, string slogan for request timer, true if using api name\n\t* .cb(err): optional function: rqs error callback\n\t* .timeoutMs: number ms: default rqs timeout if not 3 seconds\n\t* .ready: positive number: timeout for ready in ms\n\t* .ready false: this api does not emit ready\n\t* .ready defaults: ready with timeout 3 s\n\t* .saveApi: optional function\n\t* .endApi: optional function\n\t* .apiState: optional function\n\n1. An emitter will be created if emScope or apiName is non-zero string at require.emitter\n2. A request timer will be provided if rqScope is true or non-zero string at require.rqs\n3. The api will be managed if there is a non-zero api name. emitter and initApi are required. api name at require.emitter.id\n\n## apisReady(cb)\n\nSurveys all apis with singleton ready to see if they have concluded initializing.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and possibly via email\n```js\nrequire('apprunner').anomaly(err, {location: 'kitchen', user: 'fail'}, err2)\n```\n\n## enableAnomalyMail(flag)\ncontrol emailing of anomaly reports.\n```js\nrequire('apprunner').enableAnomalyMail('1/1/2013')\n```\n* flag either a date string or boolean flag, default: false\n\nAnomaly reports are not sent until the day after the date provided.\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter.\n\nSafe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter.\n\nSafe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an saveApi or endApi gets these functions invoked prior to process.exit\n\nApp Runner handles process exceptions and SIGINT (ie. ctrl-Break.)\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## addUriHandler(fn)\n\nProvides a function for a Web server instance that registers incoming uri and handlers\n```js\nvar apprunner = require('apprunner')\nvar express = require('express')\n\nvar app = apprunner.addErrorListener(express())\napprunner.addUriHandler(app.get.bind(app))\n```\n* fn(uri, uriHandler): function, uri: string, uriHandler: function\n\n## getRqs(errorCallback, scopeName, defaultTimeoutMs)\n\nGet a timer factory\n```js\nvar rqs = require('apprunner').getRqs(timeoutFn, 'UserStore Timers', 1000)\n\nvar timer = rqs.addRq('Getting Token')\nuserStore.getUser(fbId, saveOauthToken)\n\nfunction saveOauthToken(err, user) {\n\ttimer.clear()\n\t...\n}\n\nfunction timeoutFn(err) {\n\tconsole.log('an anomaly was reported for a timed out request')\n\t// maybe take alternative action\n\tif (err.isTimer) {\n\t\tif (err.param === 'Getting Token') ...\n\t}\n}\n```\n* errorCallback(err): function: invoked with err for timeouts and inconsitencies\n* scopeName: optional string or object: scope name for this factory eg. 'sync Db'\n* defaultTimeoutMs: optional number: default timeout in ms, min 100,  default 3 s\n\n1. rqs.addRq(parameter, time)\n2. rqs.clearRq(parameter) : same as .clear\n3. rqs.getState()\n4. rqs.shutdown()\n\n# Apis\n\nAn api must be loaded using these two things:\n\n1. Being loaded using require from getRequire\n2. Provide its initApi function and api name to getRequire\n\n## What's the Difference Between an Api and a Module?\n\n1. An singleton api or api instances returned by initApi can be required to emit ready\n2. An api's initApi is provided options that is json-configured options overriden by invocation options\n3. An api can have onLoad: true\n4. An api has a sigleton emitter at require.emitter\n5. An api has a module name like all modules but also an api name at require.emitter.id\n6. An api can export the special endApi, saveApi and apiState functions\n7. An api can get a timer factory at require.rqs\n\n<h2>What code should be an Api?</h2>\n<p>What source files should be designed as an api?</p>\n<ol>\n\t<li>Modules that are shared across multiple apps or apis without being an npm package.</li>\n\t<li>modules with specific needs:<ol>\n\t\t<li>Instance matching</li>\n\t\t<li>Managed lifecycle due to timers, open ports to or tcp connections</li>\n\t\t<li>Singleton ready to delay app start</li>\n\t\t<li>Configuration information like urls or passwords</li>\n\t\t<li>Diagnostic error emitting</li>\n\t\t<li>Provide ops information</li>\n\t\t<li>Start using onLoad</li>\n\t</ol>\n</ol>\n\n## Loading an Api\nSingleton\n```js\nrequire = require('apprunner').getRequire(require)\nrequire('serverhelp').listen()\nrequire('mongo').once('ready', mongoReady)\n```\nInstance\n```js\nrequire = require('apprunner').getRequire(require)\nvar fb = require('fb')\nfb.initApi({user: userId}).once('ready', fbReady)\n```\n\n## Writing an Api\nSingleton\n```js\nrequire = require('apprunner').getRequire(require, exports, {\n\tapi: 'MongoD', initApi: initApi, endApi: endApi,\n\trqScope: true, ready: false})\nfunction someExport(...) ...\n```\nInstance\n```\nrequire = require('apprunner').getRequire(require, exports, {\n\tapi: 'User Store', initApi: initApi,\n\t})\nfunction initApi(opts) {\n\t...\n\tvar readyState\n\tdoSome(someCb)\n\tfunction someCb(err, data) {\n\t\treadyState = err || true\n\t\tvar eArgs = ['ready']\n\t\tif (err) eArgs.push(err)\n\t\te.emit.apply(e, eArgs)\n\t}\n\tvar e = new events.EventEmitter\n\te.isReady = isReady\n\treturn e\n\tfunction isReady() {\n\t\treturn readyState\n}\n}\n```\n## Api settings\nApi settings are provided in the defaults object for appInit()\n```js\n{\n\t\t\"api\": {\n\t\t\"path\": [\n\t\t\t{\n\t\t\t\t\"folder\": \"lib\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"file\": \"applego\"\n\t\t\t}\n\t\t],\n\t\t\"apiMap\": {\n\t\t\t\"expressapi\": {\n\t\t\t\t\"onLoad\": true,\n\t\t\t\t\"sessionSecret\": \"secrets\",\n\t\t\t\t\"port\": 3003\n\t\t\t},\n}\n```\n* path: optional array of locations\n* apiMap: optional object with api settings\n\t* each entry can have onLoad, folder/subPath/file along with other settings\n1. A location can have folder/subPath: a string relative to the app's launch folder and a dot-separated name spacing in the loaded module\n2. A location can have  file/subpath where file is a module name and subpath is a dot-separated name spacing in the loaded module\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","readmeFilename":"readme.md","_id":"apprunner@0.2.8","dist":{"shasum":"805b5ff882f7f58b5ff65753d96a510db964ff3d","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.2.8.tgz","integrity":"sha512-8B/J2qQlgRr5wuWoonn25jJAJ5sMba/5CIwsyQt2nz1o2600W12ag3aYRhT3RvTvSs0Ymgu2+LrD7sZgS+M/nw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQClG9fEiytCz2+zmGzxcEuWG8VxR06kSEAyfvIHSdSHbgIhAOZ+NwNoKw2L5RIta7A0LVoVfPH0mhcwltxGrMNa4cFl"}]},"_npmVersion":"1.2.0","_npmUser":{"name":"haraldrudell","email":"harald@therudells.com"},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.2.9":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","management","lifecycle","app"],"version":"0.2.9","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"mochawrapper":">= 0.0.34","grunt":">= 0.4.0rc7"},"dependencies":{"haraldutil":">= 0.1.17"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage","changelog":"git log --format=\"%ad %s\" --date=short >ChangeLog; ls -l ChangeLog"},"readme":"# App Runner\n\nApp Runner manages app lifecycle\n\n## Benefits\n\n* Flexible module loading provide choice of implementation with no code change\n* Api lifecycle allows module spin-up/shutdown and settings from file data.\n* Easier troubleshooting with emailed anomaly reports\n* Orderly shutdown on exception and signal avoids data loss\n\n## Features\n\n1. Self-contained email forwarding and anomaly detection/reporting\n2. require replacement\n3. api module support with api names, error emiters, request timers, across-api function, settings mix-in and ready watchers\n4. Separation between web server implementation and app code\n5. Configurable handlers for SIGINT SIGURS2, uncaught exception\n\n# Function Reference\n\n## initApp(defaults)\nInitialize apprunner\n```js\nrequire('apprunner').initApp(require('haraldops').init({\n\tappName: 'Node God',\n\tapi: {\n\t\tapiMap: {\n\t\t\tnodegodweb: {\n\t\t\t\tonLoad: true,\n\t\t\t\tsessionSecret: 'veryGreat',\n\t\t\t\tPORT: 1111,\n\t\t\t}\n\t\t}\n\t}\n}))\n```\n* defaults: options, typically loaded by haraldops\n\n\t* .init.noInfoLog: boolean: no logging by appInit\n\t* .anomaly: object for anomalysettings of false for disable\n\n## getAppData(appInfo)\nRetrieve key app data\n```js\nconsole.log(require('apprunner').getAppData())\n```\n```\n{\n\tappName: 'Cloud Clearing',\n\tappId: 'cloudclearing',\n\tlaunchFolder: '/home/foxyboy/Desktop/c505/node/cloudclearing',\n\tsendMail: [Function: send],\n\tlogger: [Function],\n\tregisterHandler: [Function: registerHandler],\n\tviews: { dbview: { db: [Object] } },\n\tdefaultsFile: '/home/foxyboy/apps/cloudclearing.json'\n}\n```\n* appInfo: optional object PORT:numer, URL: string\nForwarded on signal to [Node God](https://github.com/haraldrudell/nodegod)\n\n## getRequire(require, exports, opts)\n\nProvides a require with a flexible search for modules\n```\nrequire = require('apprunner').getRequire(require)\nrequire('myaliasedmodule')\n```\n\nRegisters an api with apprunner, providing emitter, rqs object and initApi wrapper\n```\nrequire = require('apprunner').getRequire(require, exports, {\n\tapi: 'FB Friends', initApi: initApi, endApi: endApi,\n\trqScope: true, timeoutMs: time10s, ready: false})\n```\n* options\n\t* .api: optional string: unique api name eg. 'Server Helper'\n\t* .emScope if emitter, this emitter will be used. id property will be updated\n\t* .emScope if string: scope for emitter\n\t* .initApi: optional function: the internal initApi implementation\n\t* .rqScope: optional string or boolen, string slogan for request timer, true if using api name\n\t* .cb(err): optional function: rqs error callback\n\t* .timeoutMs: number ms: default rqs timeout if not 3 seconds\n\t* .ready: positive number: timeout for ready in ms\n\t* .ready false: this api does not emit ready\n\t* .ready defaults: ready with timeout 3 s\n\t* .saveApi: optional function\n\t* .endApi: optional function\n\t* .apiState: optional function\n\n1. An emitter will be created if emScope or apiName is non-zero string at require.emitter\n2. A request timer will be provided if rqScope is true or non-zero string at require.rqs\n3. The api will be managed if there is a non-zero api name. emitter and initApi are required. api name at require.emitter.id\n\n## apisReady(cb)\n\nSurveys all apis with singleton ready to see if they have concluded initializing.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and possibly via email\n```js\nrequire('apprunner').anomaly(err, {location: 'kitchen', user: 'fail'}, err2)\n```\n\n## enableAnomalyMail(flag)\ncontrol emailing of anomaly reports.\n```js\nrequire('apprunner').enableAnomalyMail('1/1/2013')\n```\n* flag either a date string or boolean flag, default: false\n\nAnomaly reports are not sent until the day after the date provided.\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter.\n\nSafe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter.\n\nSafe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an saveApi or endApi gets these functions invoked prior to process.exit\n\nApp Runner handles process exceptions and SIGINT (ie. ctrl-Break.)\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## addUriHandler(fn)\n\nProvides a function for a Web server instance that registers incoming uri and handlers\n```js\nvar apprunner = require('apprunner')\nvar express = require('express')\n\nvar app = apprunner.addErrorListener(express())\napprunner.addUriHandler(app.get.bind(app))\n```\n* fn(uri, uriHandler): function, uri: string, uriHandler: function\n\n## getRqs(errorCallback, scopeName, defaultTimeoutMs)\n\nGet a timer factory\n```js\nvar rqs = require('apprunner').getRqs(timeoutFn, 'UserStore Timers', 1000)\n\nvar timer = rqs.addRq('Getting Token')\nuserStore.getUser(fbId, saveOauthToken)\n\nfunction saveOauthToken(err, user) {\n\ttimer.clear()\n\t...\n}\n\nfunction timeoutFn(err) {\n\tconsole.log('an anomaly was reported for a timed out request')\n\t// maybe take alternative action\n\tif (err.isTimer) {\n\t\tif (err.param === 'Getting Token') ...\n\t}\n}\n```\n* errorCallback(err): function: invoked with err for timeouts and inconsitencies\n* scopeName: optional string or object: scope name for this factory eg. 'sync Db'\n* defaultTimeoutMs: optional number: default timeout in ms, min 100,  default 3 s\n\n1. rqs.addRq(parameter, time)\n2. rqs.clearRq(parameter) : same as .clear\n3. rqs.getState()\n4. rqs.shutdown()\n\n# Apis\n\nAn api must be loaded using these two things:\n\n1. Being loaded using require from getRequire\n2. Provide its initApi function and api name to getRequire\n\n## What's the Difference Between an Api and a Module?\n\n1. An singleton api or api instances returned by initApi can be required to emit ready\n2. An api's initApi is provided options that is json-configured options overriden by invocation options\n3. An api can have onLoad: true\n4. An api has a sigleton emitter at require.emitter\n5. An api has a module name like all modules but also an api name at require.emitter.id\n6. An api can export the special endApi, saveApi and apiState functions\n7. An api can get a timer factory at require.rqs\n\n<h2>What code should be an Api?</h2>\n<p>What source files should be designed as an api?</p>\n<ol>\n\t<li>Modules that are shared across multiple apps or apis without being an npm package.</li>\n\t<li>modules with specific needs:<ol>\n\t\t<li>Instance matching</li>\n\t\t<li>Managed lifecycle due to timers, open ports to or tcp connections</li>\n\t\t<li>Singleton ready to delay app start</li>\n\t\t<li>Configuration information like urls or passwords</li>\n\t\t<li>Diagnostic error emitting</li>\n\t\t<li>Provide ops information</li>\n\t\t<li>Start using onLoad</li>\n\t</ol>\n</ol>\n\n## Loading an Api\nSingleton\n```js\nrequire = require('apprunner').getRequire(require)\nrequire('serverhelp').listen()\nrequire('mongo').once('ready', mongoReady)\n```\nInstance\n```js\nrequire = require('apprunner').getRequire(require)\nvar fb = require('fb')\nfb.initApi({user: userId}).once('ready', fbReady)\n```\n\n## Writing an Api\nSingleton\n```js\nrequire = require('apprunner').getRequire(require, exports, {\n\tapi: 'MongoD', initApi: initApi, endApi: endApi,\n\trqScope: true, ready: false})\nfunction someExport(...) ...\n```\nInstance\n```\nrequire = require('apprunner').getRequire(require, exports, {\n\tapi: 'User Store', initApi: initApi,\n\t})\nfunction initApi(opts) {\n\t...\n\tvar readyState\n\tdoSome(someCb)\n\tfunction someCb(err, data) {\n\t\treadyState = err || true\n\t\tvar eArgs = ['ready']\n\t\tif (err) eArgs.push(err)\n\t\te.emit.apply(e, eArgs)\n\t}\n\tvar e = new events.EventEmitter\n\te.isReady = isReady\n\treturn e\n\tfunction isReady() {\n\t\treturn readyState\n}\n}\n```\n## Api settings\nApi settings are provided in the defaults object for appInit()\n```js\n{\n\t\t\"api\": {\n\t\t\"path\": [\n\t\t\t{\n\t\t\t\t\"folder\": \"lib\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"file\": \"applego\"\n\t\t\t}\n\t\t],\n\t\t\"apiMap\": {\n\t\t\t\"expressapi\": {\n\t\t\t\t\"onLoad\": true,\n\t\t\t\t\"sessionSecret\": \"secrets\",\n\t\t\t\t\"port\": 3003\n\t\t\t},\n}\n```\n* path: optional array of locations\n* apiMap: optional object with api settings\n\t* each entry can have onLoad, folder/subPath/file along with other settings\n1. A location can have folder/subPath: a string relative to the app's launch folder and a dot-separated name spacing in the loaded module\n2. A location can have  file/subpath where file is a module name and subpath is a dot-separated name spacing in the loaded module\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","readmeFilename":"readme.md","_id":"apprunner@0.2.9","dist":{"shasum":"f3224b9816660fd87bad698ee7d5216cd33de769","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.2.9.tgz","integrity":"sha512-WHHSRi5jLyk20hOQJa9LfNUMGypYt8j6YnwBxLV5KECg17zz1RkVnr+ZzIbEwRC8bOZDWwRmN29j1HdsE8ODjw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGfA84IiTHV/5m91CW1lH2nsEI+hK+VeJasOgUgYdIUHAiBZu8Pp2Fi0Jw92lepgQZuMz/3PVSvfBjg388ojy8XKPw=="}]},"_npmVersion":"1.2.0","_npmUser":{"name":"haraldrudell","email":"harald@therudells.com"},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.2.10":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","management","lifecycle","app"],"version":"0.2.10","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"grunt-contrib-watch":">= 0.1.4","grunts":">= 0.0.2","grunt":">= 0.4.0rc7","mochawrapper":">= 0.0.34"},"dependencies":{"haraldutil":">= 0.1.18"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage","changelog":"git log --format=\"%ad %s\" --date=short >ChangeLog; ls -l ChangeLog"},"readme":"# App Runner\n\nApp Runner manages app lifecycle\n\n## Benefits\n\n* Flexible module loading provide choice of implementation with no code change\n* Api lifecycle allows module spin-up/shutdown and settings from file data.\n* Easier troubleshooting with emailed anomaly reports\n* Orderly shutdown on exception and signal avoids data loss\n\n## Features\n\n1. Self-contained email forwarding and anomaly detection/reporting\n2. require replacement\n3. api module support with api names, error emiters, request timers, across-api function, settings mix-in and ready watchers\n4. Separation between web server implementation and app code\n5. Configurable handlers for SIGINT SIGURS2, uncaught exception\n\n# Function Reference\n\n## initApp(defaults)\nInitialize apprunner\n```js\nrequire('apprunner').initApp(require('haraldops').init({\n\tappName: 'Node God',\n\tapi: {\n\t\tapiMap: {\n\t\t\tnodegodweb: {\n\t\t\t\tonLoad: true,\n\t\t\t\tsessionSecret: 'veryGreat',\n\t\t\t\tPORT: 1111,\n\t\t\t}\n\t\t}\n\t}\n}))\n```\n* defaults: options, typically loaded by haraldops\n\n\t* .init.noInfoLog: boolean: no logging by appInit\n\t* .anomaly: object for anomalysettings of false for disable\n\n## getAppData(appInfo)\nRetrieve key app data\n```js\nconsole.log(require('apprunner').getAppData())\n```\n```\n{\n\tappName: 'Cloud Clearing',\n\tappId: 'cloudclearing',\n\tlaunchFolder: '/home/foxyboy/Desktop/c505/node/cloudclearing',\n\tsendMail: [Function: send],\n\tlogger: [Function],\n\tregisterHandler: [Function: registerHandler],\n\tviews: { dbview: { db: [Object] } },\n\tdefaultsFile: '/home/foxyboy/apps/cloudclearing.json'\n}\n```\n* appInfo: optional object PORT:numer, URL: string\nForwarded on signal to [Node God](https://github.com/haraldrudell/nodegod)\n\n## getRequire(require, exports, opts)\n\nProvides a require with a flexible search for modules\n```\nrequire = require('apprunner').getRequire(require)\nrequire('myaliasedmodule')\n```\n\nRegisters an api with apprunner, providing emitter, rqs object and initApi wrapper\n```\nrequire = require('apprunner').getRequire(require, exports, {\n\tapi: 'FB Friends', initApi: initApi, endApi: endApi,\n\trqScope: true, timeoutMs: time10s, ready: false})\n```\n* options\n\t* .api: optional string: unique api name eg. 'Server Helper'\n\t* .emScope if emitter, this emitter will be used. id property will be updated\n\t* .emScope if string: scope for emitter\n\t* .initApi: optional function: the internal initApi implementation\n\t* .rqScope: optional string or boolen, string slogan for request timer, true if using api name\n\t* .cb(err): optional function: rqs error callback\n\t* .timeoutMs: number ms: default rqs timeout if not 3 seconds\n\t* .ready: positive number: timeout for ready in ms\n\t* .ready false: this api does not emit ready\n\t* .ready defaults: ready with timeout 3 s\n\t* .saveApi: optional function\n\t* .endApi: optional function\n\t* .apiState: optional function\n\n1. An emitter will be created if emScope or apiName is non-zero string at require.emitter\n2. A request timer will be provided if rqScope is true or non-zero string at require.rqs\n3. The api will be managed if there is a non-zero api name. emitter and initApi are required. api name at require.emitter.id\n\n## apisReady(cb)\n\nSurveys all apis with singleton ready to see if they have concluded initializing.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and possibly via email\n```js\nrequire('apprunner').anomaly(err, {location: 'kitchen', user: 'fail'}, err2)\n```\n\n## enableAnomalyMail(flag)\ncontrol emailing of anomaly reports.\n```js\nrequire('apprunner').enableAnomalyMail('1/1/2013')\n```\n* flag either a date string or boolean flag, default: false\n\nAnomaly reports are not sent until the day after the date provided.\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter.\n\nSafe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter.\n\nSafe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an saveApi or endApi gets these functions invoked prior to process.exit\n\nApp Runner handles process exceptions and SIGINT (ie. ctrl-Break.)\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## addUriHandler(fn)\n\nProvides a function for a Web server instance that registers incoming uri and handlers\n```js\nvar apprunner = require('apprunner')\nvar express = require('express')\n\nvar app = apprunner.addErrorListener(express())\napprunner.addUriHandler(app.get.bind(app))\n```\n* fn(uri, uriHandler): function, uri: string, uriHandler: function\n\n## getRqs(errorCallback, scopeName, defaultTimeoutMs)\n\nGet a timer factory\n```js\nvar rqs = require('apprunner').getRqs(timeoutFn, 'UserStore Timers', 1000)\n\nvar timer = rqs.addRq('Getting Token')\nuserStore.getUser(fbId, saveOauthToken)\n\nfunction saveOauthToken(err, user) {\n\ttimer.clear()\n\t...\n}\n\nfunction timeoutFn(err) {\n\tconsole.log('an anomaly was reported for a timed out request')\n\t// maybe take alternative action\n\tif (err.isTimer) {\n\t\tif (err.param === 'Getting Token') ...\n\t}\n}\n```\n* errorCallback(err): function: invoked with err for timeouts and inconsitencies\n* scopeName: optional string or object: scope name for this factory eg. 'sync Db'\n* defaultTimeoutMs: optional number: default timeout in ms, min 100,  default 3 s\n\n1. rqs.addRq(parameter, time)\n2. rqs.clearRq(parameter) : same as .clear\n3. rqs.getState()\n4. rqs.shutdown()\n\n# Apis\n\nAn api must be loaded using these two things:\n\n1. Being loaded using require from getRequire\n2. Provide its initApi function and api name to getRequire\n\n## What's the Difference Between an Api and a Module?\n\n1. An singleton api or api instances returned by initApi can be required to emit ready\n2. An api's initApi is provided options that is json-configured options overriden by invocation options\n3. An api can have onLoad: true\n4. An api has a sigleton emitter at require.emitter\n5. An api has a module name like all modules but also an api name at require.emitter.id\n6. An api can export the special endApi, saveApi and apiState functions\n7. An api can get a timer factory at require.rqs\n\n<h2>What code should be an Api?</h2>\n<p>What source files should be designed as an api?</p>\n<ol>\n\t<li>Modules that are shared across multiple apps or apis without being an npm package.</li>\n\t<li>modules with specific needs:<ol>\n\t\t<li>Instance matching</li>\n\t\t<li>Managed lifecycle due to timers, open ports to or tcp connections</li>\n\t\t<li>Singleton ready to delay app start</li>\n\t\t<li>Configuration information like urls or passwords</li>\n\t\t<li>Diagnostic error emitting</li>\n\t\t<li>Provide ops information</li>\n\t\t<li>Start using onLoad</li>\n\t</ol>\n</ol>\n\n## Loading an Api\nSingleton\n```js\nrequire = require('apprunner').getRequire(require)\nrequire('serverhelp').listen()\nrequire('mongo').once('ready', mongoReady)\n```\nInstance\n```js\nrequire = require('apprunner').getRequire(require)\nvar fb = require('fb')\nfb.initApi({user: userId}).once('ready', fbReady)\n```\n\n## Writing an Api\nSingleton\n```js\nrequire = require('apprunner').getRequire(require, exports, {\n\tapi: 'MongoD', initApi: initApi, endApi: endApi,\n\trqScope: true, ready: false})\nfunction someExport(...) ...\n```\nInstance\n```\nrequire = require('apprunner').getRequire(require, exports, {\n\tapi: 'User Store', initApi: initApi,\n\t})\nfunction initApi(opts) {\n\t...\n\tvar readyState\n\tdoSome(someCb)\n\tfunction someCb(err, data) {\n\t\treadyState = err || true\n\t\tvar eArgs = ['ready']\n\t\tif (err) eArgs.push(err)\n\t\te.emit.apply(e, eArgs)\n\t}\n\tvar e = new events.EventEmitter\n\te.isReady = isReady\n\treturn e\n\tfunction isReady() {\n\t\treturn readyState\n}\n}\n```\n## Api settings\nApi settings are provided in the defaults object for appInit()\n```js\n{\n\t\t\"api\": {\n\t\t\"path\": [\n\t\t\t{\n\t\t\t\t\"folder\": \"lib\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"file\": \"applego\"\n\t\t\t}\n\t\t],\n\t\t\"apiMap\": {\n\t\t\t\"expressapi\": {\n\t\t\t\t\"onLoad\": true,\n\t\t\t\t\"sessionSecret\": \"secrets\",\n\t\t\t\t\"port\": 3003\n\t\t\t},\n}\n```\n* path: optional array of locations\n* apiMap: optional object with api settings\n\t* each entry can have onLoad, folder/subPath/file along with other settings\n1. A location can have folder/subPath: a string relative to the app's launch folder and a dot-separated name spacing in the loaded module\n2. A location can have  file/subpath where file is a module name and subpath is a dot-separated name spacing in the loaded module\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","readmeFilename":"readme.md","_id":"apprunner@0.2.10","dist":{"shasum":"e0757ad3ac180bcebe8efa4e0c6a2a83368293a7","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.2.10.tgz","integrity":"sha512-rtGGUX0lpSETc53JuFXdmQMLFSY2dhM65aueosWMJ7MDhaKWRMVAMsv7QX3Xh0oRPVbSwhjy0mAWiHHyqZnF6g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGKCs+PtpH1c+Ikz+Anjx8Z4ofCC/5CM+HowxM3CsAyUAiAPFfu73fdf6RtY6LnfeDFKuaabcK0N/zWvbUaq9op6TA=="}]},"_npmVersion":"1.2.0","_npmUser":{"name":"haraldrudell","email":"harald@therudells.com"},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]},"0.2.11":{"name":"apprunner","description":"Manage application errors and plugin modules by Harald Rudell","author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"keywords":["require","plugins","api","npm","errors","email","management","lifecycle","app"],"version":"0.2.11","contributors":[{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"}],"devDependencies":{"grunt-contrib-watch":">= 0.1.4","grunts":">= 0.0.2","grunt":">= 0.4.0rc7","mochawrapper":">= 0.0.34"},"dependencies":{"haraldutil":">= 0.1.18"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"main":"./lib/apprunner","scripts":{"test":"mocha --ui exports --reporter spec","monitor":"mocha --ui exports --reporter min --watch","debugtest":"mocha --debug-brk --ui exports --reporter spec","coverage":"mochacoverage","changelog":"git log --format=\"%ad %s\" --date=short >ChangeLog; ls -l ChangeLog"},"readme":"# App Runner\n\nApp Runner manages app lifecycle\n\n## Benefits\n\n* Flexible module loading provide choice of implementation with no code change\n* Api lifecycle allows module spin-up/shutdown and settings from file data.\n* Easier troubleshooting with emailed anomaly reports\n* Orderly shutdown on exception and signal avoids data loss\n\n## Features\n\n1. Self-contained email forwarding and anomaly detection/reporting\n2. require replacement\n3. api module support with api names, error emiters, request timers, across-api function, settings mix-in and ready watchers\n4. Separation between web server implementation and app code\n5. Configurable handlers for SIGINT SIGURS2, uncaught exception\n\n# Function Reference\n\n## initApp(defaults)\nInitialize apprunner\n```js\nrequire('apprunner').initApp(require('haraldops').init({\n\tappName: 'Node God',\n\tapi: {\n\t\tapiMap: {\n\t\t\tnodegodweb: {\n\t\t\t\tonLoad: true,\n\t\t\t\tsessionSecret: 'veryGreat',\n\t\t\t\tPORT: 1111,\n\t\t\t}\n\t\t}\n\t}\n}))\n```\n* defaults: options, typically loaded by haraldops\n\n\t* .init.noInfoLog: boolean: no logging by appInit\n\t* .anomaly: object for anomalysettings of false for disable\n\n## getAppData(appInfo)\nRetrieve key app data\n```js\nconsole.log(require('apprunner').getAppData())\n```\n```\n{\n\tappName: 'Cloud Clearing',\n\tappId: 'cloudclearing',\n\tlaunchFolder: '/home/foxyboy/Desktop/c505/node/cloudclearing',\n\tsendMail: [Function: send],\n\tlogger: [Function],\n\tregisterHandler: [Function: registerHandler],\n\tviews: { dbview: { db: [Object] } },\n\tdefaultsFile: '/home/foxyboy/apps/cloudclearing.json'\n}\n```\n* appInfo: optional object PORT:numer, URL: string\nForwarded on signal to [Node God](https://github.com/haraldrudell/nodegod)\n\n## getRequire(require, exports, opts)\n\nProvides a require with a flexible search for modules\n```\nrequire = require('apprunner').getRequire(require)\nrequire('myaliasedmodule')\n```\n\nRegisters an api with apprunner, providing emitter, rqs object and initApi wrapper\n```\nrequire = require('apprunner').getRequire(require, exports, {\n\tapi: 'FB Friends', initApi: initApi, endApi: endApi,\n\trqScope: true, timeoutMs: time10s, ready: false})\n```\n* options\n\t* .api: optional string: unique api name eg. 'Server Helper'\n\t* .emScope if emitter, this emitter will be used. id property will be updated\n\t* .emScope if string: scope for emitter\n\t* .initApi: optional function: the internal initApi implementation\n\t* .rqScope: optional string or boolen, string slogan for request timer, true if using api name\n\t* .cb(err): optional function: rqs error callback\n\t* .timeoutMs: number ms: default rqs timeout if not 3 seconds\n\t* .ready: positive number: timeout for ready in ms\n\t* .ready false: this api does not emit ready\n\t* .ready defaults: ready with timeout 3 s\n\t* .saveApi: optional function\n\t* .endApi: optional function\n\t* .apiState: optional function\n\n1. An emitter will be created if emScope or apiName is non-zero string at require.emitter\n2. A request timer will be provided if rqScope is true or non-zero string at require.rqs\n3. The api will be managed if there is a non-zero api name. emitter and initApi are required. api name at require.emitter.id\n\n## apisReady(cb)\n\nSurveys all apis with singleton ready to see if they have concluded initializing.\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and possibly via email\n```js\nrequire('apprunner').anomaly(err, {location: 'kitchen', user: 'fail'}, err2)\n```\n\n## enableAnomalyMail(flag)\ncontrol emailing of anomaly reports.\n```js\nrequire('apprunner').enableAnomalyMail('1/1/2013')\n```\n* flag either a date string or boolean flag, default: false\n\nAnomaly reports are not sent until the day after the date provided.\n\n## addErrorListener(emitter)\n\nAdds an error listener to the EventEmitter.\n\nSafe: can be invoked with any value, or repeatedly invoked.\n\n## removeErrorListener(emitter)\n\nRemoves an error listener to the EventEmitter.\n\nSafe: can be invoked with any value, or repeatedly invoked.\n\n## shutdown(exitCode)\n\nShuts the application down. All apis that have exposed an saveApi or endApi gets these functions invoked prior to process.exit\n\nApp Runner handles process exceptions and SIGINT (ie. ctrl-Break.)\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## addUriHandler(fn)\n\nProvides a function for a Web server instance that registers incoming uri and handlers\n```js\nvar apprunner = require('apprunner')\nvar express = require('express')\n\nvar app = apprunner.addErrorListener(express())\napprunner.addUriHandler(app.get.bind(app))\n```\n* fn(uri, uriHandler): function, uri: string, uriHandler: function\n\n## getRqs(errorCallback, scopeName, defaultTimeoutMs)\n\nGet a timer factory\n```js\nvar rqs = require('apprunner').getRqs(timeoutFn, 'UserStore Timers', 1000)\n\nvar timer = rqs.addRq('Getting Token')\nuserStore.getUser(fbId, saveOauthToken)\n\nfunction saveOauthToken(err, user) {\n\ttimer.clear()\n\t...\n}\n\nfunction timeoutFn(err) {\n\tconsole.log('an anomaly was reported for a timed out request')\n\t// maybe take alternative action\n\tif (err.isTimer) {\n\t\tif (err.param === 'Getting Token') ...\n\t}\n}\n```\n* errorCallback(err): function: invoked with err for timeouts and inconsitencies\n* scopeName: optional string or object: scope name for this factory eg. 'sync Db'\n* defaultTimeoutMs: optional number: default timeout in ms, min 100,  default 3 s\n\n1. rqs.addRq(parameter, time)\n2. rqs.clearRq(parameter) : same as .clear\n3. rqs.getState()\n4. rqs.shutdown()\n\n# Apis\n\nAn api must be loaded using these two things:\n\n1. Being loaded using require from getRequire\n2. Provide its initApi function and api name to getRequire\n\n## What's the Difference Between an Api and a Module?\n\n1. An singleton api or api instances returned by initApi can be required to emit ready\n2. An api's initApi is provided options that is json-configured options overriden by invocation options\n3. An api can have onLoad: true\n4. An api has a sigleton emitter at require.emitter\n5. An api has a module name like all modules but also an api name at require.emitter.id\n6. An api can export the special endApi, saveApi and apiState functions\n7. An api can get a timer factory at require.rqs\n\n<h2>What code should be an Api?</h2>\n<p>What source files should be designed as an api?</p>\n<ol>\n\t<li>Modules that are shared across multiple apps or apis without being an npm package.</li>\n\t<li>modules with specific needs:<ol>\n\t\t<li>Instance matching</li>\n\t\t<li>Managed lifecycle due to timers, open ports to or tcp connections</li>\n\t\t<li>Singleton ready to delay app start</li>\n\t\t<li>Configuration information like urls or passwords</li>\n\t\t<li>Diagnostic error emitting</li>\n\t\t<li>Provide ops information</li>\n\t\t<li>Start using onLoad</li>\n\t</ol>\n</ol>\n\n## Loading an Api\nSingleton\n```js\nrequire = require('apprunner').getRequire(require)\nrequire('serverhelp').listen()\nrequire('mongo').once('ready', mongoReady)\n```\nInstance\n```js\nrequire = require('apprunner').getRequire(require)\nvar fb = require('fb')\nfb.initApi({user: userId}).once('ready', fbReady)\n```\n\n## Writing an Api\nSingleton\n```js\nrequire = require('apprunner').getRequire(require, exports, {\n\tapi: 'MongoD', initApi: initApi, endApi: endApi,\n\trqScope: true, ready: false})\nfunction someExport(...) ...\n```\nInstance\n```\nrequire = require('apprunner').getRequire(require, exports, {\n\tapi: 'User Store', initApi: initApi,\n\t})\nfunction initApi(opts) {\n\t...\n\tvar readyState\n\tdoSome(someCb)\n\tfunction someCb(err, data) {\n\t\treadyState = err || true\n\t\tvar eArgs = ['ready']\n\t\tif (err) eArgs.push(err)\n\t\te.emit.apply(e, eArgs)\n\t}\n\tvar e = new events.EventEmitter\n\te.isReady = isReady\n\treturn e\n\tfunction isReady() {\n\t\treturn readyState\n}\n}\n```\n## Api settings\nApi settings are provided in the defaults object for appInit()\n```js\n{\n\t\t\"api\": {\n\t\t\"path\": [\n\t\t\t{\n\t\t\t\t\"folder\": \"lib\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"file\": \"applego\"\n\t\t\t}\n\t\t],\n\t\t\"apiMap\": {\n\t\t\t\"expressapi\": {\n\t\t\t\t\"onLoad\": true,\n\t\t\t\t\"sessionSecret\": \"secrets\",\n\t\t\t\t\"port\": 3003\n\t\t\t},\n}\n```\n* path: optional array of locations\n* apiMap: optional object with api settings\n\t* each entry can have onLoad, folder/subPath/file along with other settings\n1. A location can have folder/subPath: a string relative to the app's launch folder and a dot-separated name spacing in the loaded module\n2. A location can have  file/subpath where file is a module name and subpath is a dot-separated name spacing in the loaded module\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","readmeFilename":"readme.md","_id":"apprunner@0.2.11","dist":{"shasum":"9dbbcde45d957e9a97c6d4e72044f38ff9efc247","tarball":"https://registry.npmjs.org/apprunner/-/apprunner-0.2.11.tgz","integrity":"sha512-cNNrmpYDylkybfXQYYgktMwBvgeYEpFooaiWAJHUWPQHqJdK3Fd55J4Tbj1zOaxhNHJM1HIZ7Pt8K/KEk1/TjQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDC0iTLT/Qgw96DXHxuBbzAYq/7xK/ynNAqUEz+99jeTwIhAOKCdow9uExiNVV/fcEFqN27LyydQ7H91IBl7fB+QJ/G"}]},"_npmVersion":"1.2.0","_npmUser":{"name":"haraldrudell","email":"harald@therudells.com"},"maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}]}},"readme":"# App Runner\n\nApp Runner allows to to generate and maintain many apps using shared code. Require is great, App Runner is greater!\n\nApp Runner does three things:\n* Provides loadable apis\n* Manages application errors\n* Emails anomaly reports\n\nWhy App Runner? App Runner is App Lego.\n\nIf you make many Web apps and you have several of them for example accessing Facebook or using the same type of database, App Runner enables you to architect that in a repeatable pattern. App Runner allows you to use json to configure where code comes from and its settings.\n\n# Reference\n\nApp Runner handles process exceptions and SIGINT.\n* Exit code 0 is SIGINT\n* Exit code 2 is unhandled exception\n\n## initApp(defaults, app, cb)\n\n* defaults: options, typically loaded by haraldops\n\n  * .init.appFolder: string: the folder of initial script\n  * .init.logger: optional function(string): logging, default console.log\n  * .init.ops.sendMail: optional function(subject, body): Sends mail, default none\n  * .api: optional, indicates that Api Manager should be used\n  * .api.apiMap: api configurations\n\n* app: Web server, has .on and .get methods\n* cb(err): optional function\n\n## getApi(opts, cb)\n\nget an api implementation\n* opts: object\n* .api: string: name of api function to be loaded\n* cb(err, module)\n\nAPIs are either configured directly in opts, or in defaults provided at App Runner init\n\nIf module has module.emitter, APp Runner will listen and manage error events\n\n## anomaly(...)\n\nReport any argument as an anomaly, to the log and if so configured a periodcal email.\n\n## enableAnomalyMail(flag)\n\ncontrol emailing on or off: flag: boolean, default: false\n\n## getCbCounter()\nEnsures that all callbacks has completed\n\n```js\nvar haraldutil = require('haraldutil')\nvar cbc = haraldutil.getCbCounter()\nsetTimeout(cbc.add(callback), 100)\nsetTimeout(cbc.add(callback), 100)\n\nfunction callback() {\n  if (cbc.isDone(arguments.callee))\n    console.log('All callbacks completed.')\n  else console.log('Not done yet...')\n}\n```\n```\nNot done yet...\nAll callbacks completed.\n```\nvar cbc = getCbCounter(opts)\n* opts: optional object\n* opts.emitter: optional event emitter or boolean. default: errors are thrown\n\n  * false: errors are ignored\n  * emitter: errors are emitted\n\n* opts.callback: function or array of function: add is done for each function\n\ncbc: object\n* .add(f): adds a callback for function f, return value: f\n* .isDone(f): notes one callback completed. returns true if all callbacks complete, otherwise false\n* .getStatus(): gets an object representing the current state\n\n# Examples\n\nTODO\n\n# Notes\n\n(c) [Harald Rudell](http://www.haraldrudell.com) wrote this for node in September, 2012\n\nNo warranty expressed or implied. Use at your own risk.\n\nPlease suggest better ways, new features, and possible difficulties on [github](https://github.com/haraldrudell/apprunner)","maintainers":[{"name":"haraldrudell","email":"harald@therudells.com"}],"time":{"modified":"2022-06-13T03:19:24.921Z","created":"2012-09-10T20:17:14.498Z","0.0.0":"2012-09-10T20:17:16.058Z","0.0.1":"2012-09-10T20:53:29.722Z","0.0.2":"2012-09-10T21:19:57.685Z","0.0.3":"2012-09-10T21:26:18.497Z","0.0.4":"2012-09-10T23:18:35.688Z","0.0.5":"2012-09-11T01:12:31.288Z","0.0.6":"2012-09-11T04:32:31.547Z","0.0.7":"2012-09-12T10:10:05.323Z","0.0.9":"2012-09-12T16:26:14.925Z","0.0.10":"2012-09-12T17:04:24.772Z","0.0.11":"2012-09-12T18:34:48.645Z","0.0.12":"2012-09-15T11:21:17.693Z","0.0.13":"2012-09-18T20:01:45.094Z","0.0.14":"2012-09-20T13:35:41.778Z","0.0.15":"2012-09-28T17:10:14.540Z","0.0.16":"2012-12-22T08:04:27.352Z","0.0.17":"2012-12-22T08:55:02.005Z","0.1.0":"2012-12-25T10:52:31.885Z","0.1.1":"2012-12-25T11:28:52.185Z","0.1.2":"2012-12-26T03:24:07.818Z","0.1.3":"2012-12-30T07:43:15.500Z","0.1.4":"2012-12-31T01:11:04.063Z","0.1.5":"2013-01-09T23:27:27.944Z","0.1.6":"2013-01-10T07:38:22.487Z","0.1.8":"2013-01-12T08:44:18.969Z","0.2.0":"2013-01-13T07:02:38.450Z","0.2.1":"2013-01-13T09:52:40.602Z","0.2.2":"2013-01-15T07:24:30.247Z","0.2.3":"2013-01-16T08:30:36.619Z","0.2.4":"2013-01-18T07:41:15.842Z","0.2.5":"2013-01-21T05:58:30.798Z","0.2.6":"2013-01-21T18:15:40.485Z","0.2.7":"2013-01-24T22:20:45.381Z","0.2.8":"2013-01-27T06:33:12.398Z","0.2.9":"2013-01-27T06:35:25.264Z","0.2.10":"2013-02-02T21:57:10.303Z","0.2.11":"2013-02-02T22:22:14.605Z"},"author":{"name":"Harald Rudell","email":"harald@allgoodapps.com","url":"http://www.haraldrudell.com"},"repository":{"type":"git","url":"https://github.com/haraldrudell/apprunner"},"users":{"vteixeira":true}}