├── .codeclimate.yml ├── .dockerignore ├── .gitignore ├── .npmignore ├── .travis.yml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── assets ├── digs-logo-128.png ├── digs-logo-256.png ├── digs-logo-500.png └── digs-logo.svg ├── bin └── digs.js ├── docker-compose.yml ├── grunt ├── aliases.yaml └── test-tasks.yaml ├── lib ├── debug-patcher.js ├── index.js ├── manifest-builder.js ├── plugin.js └── server.yaml ├── package.json └── scripts ├── github-labels.json └── sync-github-labels.js /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | exclude_paths: 2 | - Gruntfile.js 3 | - test/fixture.js 4 | engines: 5 | eslint: 6 | enabled: true 7 | 8 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .* 2 | test/ 3 | docs/ 4 | assets/ 5 | node_modules/ 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | *.ipr 3 | *.iws 4 | out/ 5 | .idea_modules/ 6 | atlassian-ide-plugin.xml 7 | com_crashlytics_export_strings.xml 8 | crashlytics.properties 9 | crashlytics-build.properties 10 | .DS_Store 11 | .AppleDouble 12 | .LSOverride 13 | Icon 14 | ._* 15 | .Spotlight-V100 16 | .Trashes 17 | .AppleDB 18 | .AppleDesktop 19 | Network Trash Folder 20 | Temporary Items 21 | .apdisk 22 | *.tmproj 23 | *.tmproject 24 | tmtags 25 | *.tmlanguage.cache 26 | *.tmPreferences.cache 27 | *.stTheme.cache 28 | *.sublime-workspace 29 | sftp-config.json 30 | Thumbs.db 31 | ehthumbs.db 32 | Desktop.ini 33 | $RECYCLE.BIN/ 34 | *.cab 35 | *.msi 36 | *.msm 37 | *.msp 38 | *.lnk 39 | \/.emacs.desktop 40 | /.emacs.desktop.lock 41 | *.elc 42 | auto-save-list 43 | tramp 44 | .\.org-id-locations 45 | *_archive 46 | *_flymake.* 47 | /eshell/history 48 | /eshell/lastdir 49 | /elpa/ 50 | *.rel 51 | /auto/ 52 | .cask/ 53 | logs 54 | *.log* 55 | pids 56 | *.pid 57 | *.seed 58 | lib-cov 59 | coverage 60 | .grunt 61 | .lock-wscript 62 | node_modules 63 | .directory 64 | [._]*.s[a-w][a-z] 65 | [._]s[a-w][a-z] 66 | Session.vim 67 | .netrwhist 68 | bower_components/ 69 | support/ 70 | vendor/ 71 | build/ 72 | ecosystem.json 73 | .editorconfig 74 | .eslintignore 75 | .eslintrc 76 | Gruntfile.js 77 | grunt/bump.yaml 78 | grunt/devUpdate.yaml 79 | grunt/mocha_istanbul.yaml 80 | grunt/watch.yaml 81 | grunt/digs-dev.js 82 | test/fixture.js 83 | Dockerfile 84 | test/.eslintrc 85 | 86 | .wallaby.js -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .* 2 | test/ 3 | docs/ 4 | Gruntfile.js 5 | grunt/ 6 | assets/ 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 4.2 4 | - 4.1 5 | - 4.0 6 | sudo: false 7 | env: 8 | global: 9 | - secure: CEL0O+VzeaDdAsxkmA09mzrCz1c7KNVob2H28tJO1/K7MPKad/50lBqf+rOEOpM5/JbObLGcRGDWuACzyxYLViGt8fOgSzeUdpHunSggwBxt6rteeWUWZJEWJdZUTzHR+UlZ6OvZapHm+nXqW9+QI0EleFJZgU+Q882odZnxq6QSp31Uhouu26H+AaxN7Rzd9HJS7ywkBro50euz56WgK4XzGyHWh4y6D2zETP/m1OKjoGLYqHte53TgSJXk8+jbMVkGGl3QuEb1yV8Xr8YzIwqbYOZ9WPLu7QDhTLTDVzVAMX5eRN+XIXBTDDsHKlduuu0wUhduc1a0rEyyh+Od2eo2o72Xd51o1VbiH4dF6A2C6AuN58wk4KGScGnvidv+GeNdovdfpKl+/lA59EgPiKwkESrsRru+AvObDotV+of2fdqEx+lnOrLAHyXNSsexCaWnz3Xhuj1kxu9LK6ICv3zzoVRdQTuMteH0vbQ3GZWajehmt2c5yCSUciDYkyayzUG2EyeZzovydLOuSbyJGr2K7zxOWTytCIaoKa+BX4c2vUIi4yrPpTeo9fMwG5K5dLJICIQcWlkAJliQ8465nWNqzGIL8HpUvJZCKNL8dpo+vZ5zmxRFmI+J0IbzcK6xAbjSLtDzMjk5M+7cZLcK1YAqmtAtFoZ1qNGwUUnZSfw= 10 | - secure: khB+PsskX8ZaK1yKdYLoNFwKAUgt6cCQvNR6510aMP2RTfw2iXmtzNNoPhxNeCaapJqAnkt/Ex/K7iNJH8fV5G9SFlYQa/eISzXJg3sLtdqRIMDfVTiw/drPP93xZAPD+1ylVIKD4ZoaMwlRKphidk1hkP2CU5wqmvs+JVqcn+xsWHs6dkj7e9jvi49j8M1+RiBcZaGj1xiMlidqD2koStOFw7w9yld5e1A/g96xxBxzyTZl7s3Ki49hY8bjxWrabwBbYENdn60hf5sTtn9cXwO//d+DwgZtpL6I4ddoozvjt0I1CC4JhxOZTHhfeHcIZLzSvZE7103q5Kxpe2xcMSxDmcLzi78ZU40+Hbpf/PRmk4Kj6egvt8xf/X+HpIWjlR43GkGsonLXcrzbO3FLaYPpVfuoDFtMVJEoZakeloMYyviCcoAgD/RRtWEMh9xQrePM8wC83XmUZIMH6Op895xc43ZqtvcKqwrJP1Fx2497msnIo5mS04NuGg/2WiYn3m6jQ4HimClFVCTFXnNkJROrpS4alQNK4MB+bScem2zARZPYn+hlDZsinIrtakegfW93X/6DImQ1r24Qh21q6qW420Q9MQmHi/YxnHc65ZiowANBCOrw0AeUKJvrLSUcufpF8XWPgk1OWCOGxe8rLVWCvfqyHutONTbeHFuN8nk= 11 | script: npm test 12 | after_script: 13 | - cat ./coverage/lcov.info | ./node_modules/.bin/codacy-coverage 14 | - cat ./coverage/lcov.info | ./node_modules/.bin/codeclimate-test-reporter 15 | notifications: 16 | email: false 17 | pushover: 18 | api_key: 19 | secure: uIvaG/G7QxliOFpoR+o7iaSQj8ipmGRU4emqOEW+HkuY7jUJV9HFkCFgjudS/oXpJT92zZHqk7rmLIrbc2gTVp3TQ4ca4mCXMlfhQf7JoYy7g8Iiu/qv86FeSLKYi21VtSG9MpViL7J/6aI1Q+7I2PEDCsbzz995Lee8OkCLGWk7GDpf8aKjNOyj5qAqmhnpkT+PwX8EX/X3uD/Gy3nwD6jZnsKRSwDh3PzOOjCYr3GL96CVcZb8uCGC96tVSOoX8MgXeKi12EVMXvi8am6VSyUYytXB0Zwl2ygltFv+WyaiWJWDMCXnbykNKDXEvB3Az45gACYywFy7vHoTiGHMPw+MvrdvYc6mDxvbVHweW5mC89t13SozkSOTazjQIfD7WW1UZerYAzPY+Tj6rcJ1uMQS6/8cbn/Mj8+F3aejVaU9Ppbubvc/1dx9KB7h1XGQnhsuXW1f0vYM+cIndrBrq8b7sb23IKwx0UapIKh7dIJGo3JqiDQyG1pxqTre9yxUBX5p/P7yh4ft6zxyly2nOjxaUTG2rVGzfUuj5lHYTnPVTm7RLuyIQWfkdmGi60G4YGuTcLixLsqkPXEWcHW3tRzHdhTQBygebdjFUe3BG38QKMc9cHtUIRPuOVOoTVkouY/c3gL73a/OrIm6+aEEEISqiPXX6LYIq9tnz5kXh/I= 20 | users: 21 | - 22 | secure: e/3nnPEKz0P1FGrtQlfW+b8/4D+1ZKbNRLxLSo+uUwiNJU8/QYbT+xNsi5Bh4Mye9B+t7o8mc+PuYXnUC4oVBmOevHwY8ynrp3K6RSo4viYH3Q7S0PsXR/gJ5oxOmPUnpvhdyqUqY2WR9OclWzn3ZAURhVOwcFAEAikO3FbYvATxD9EJyIpJD8aqwZdYoC+9gRkdCn6f4SS2x2cxBdnslq0TNhLMduR+wFBOm2jM4wSzYMJWB9yYlHouCOU/4OsQC0zWt1kM2RN4ACti3qqrdGPBiB+JtYNqVHZzNKlpRmFhjjHEZhMZ3uBTREALHUQPDHCXzvoNd86VU+8Z3AuWdvKwG956CHvCX6NquSOaPzNLmpYaOfSRd2wYO1aJjV3i+yl/u78aC68OVvmfgwn67zDfLnF6IERfib3ZSuKWqmjkkUxHnqluz6lZ9y+UwlidzdFbp/bfRlAReb9YmKUnPll7RE9fa9speIegXOUa4QudMwGsiz57QdHJN4syQ+p+weWbQE08aY5ZkIyD1p1UqMxCyRlvEPiEOjHUkT5C/q0llMXQE7G5xpPoCEAKEt8cVeaKQpEXP9xMGVhFdfD0GQz1eroF1trYHvzPV8QCQlEnncoMtLGo0O9mUaNXlOg922nxKjuUTCQFyUFxCmCzBT5hwB9162/CZjY2ktozyRE= 23 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to digs 2 | 3 | ## Getting Started 4 | 5 | Clone this project or (any project in the [digsjs org](https://github.com/digsjs), then execute: 6 | 7 | ```shell 8 | $ npm install 9 | ``` 10 | 11 | You may want to install multiple projects at once. If so: 12 | 13 | ### Using `npm link` 14 | 15 | I find myself usually having all of the projects open at once, and making use of `npm link` to ensure my changes to a dependency appear in its dependent(s). 16 | 17 | For example, if I want to have my modifications to **digs-common** show up in my **digs** working copy, I'd go into my **digs-common** working copy, then execute `npm link`. Then, I'd go back to my **digs** working copy, and execute `npm link digs-common`. 18 | 19 | Note that this may require superuser access, depending on your setup! 20 | 21 | ## Pull Requests 22 | 23 | Want to help? Check out the [issues labeled with `help wanted`](https://github.com/digsjs/digs/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22). 24 | 25 | ## Further Information 26 | 27 | **More resources are available in [the wiki](https://github.com/digsjs/digs/wiki).** 28 | 29 | * * * 30 | 31 | thanks for your contribution, 32 | [Chris](https://github.com/boneskull) 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Christopher Hiller (boneskull.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | digs logo 2 | 3 | # digs [![NPM](https://nodei.co/npm/digs.png?compact=true)](https://www.npmjs.com/package/digs) 4 | [![Build Status](https://travis-ci.org/digsjs/digs.svg?branch=master)](https://travis-ci.org/digsjs/digs) [![Join the chat at https://gitter.im/digsjs/digs](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/digsjs/digs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 5 | 6 | > A home automation server written in JavaScript 7 | 8 | ## Achtung! 9 | 10 | This project is under heavy development and probably won't do much of anything at any given time. 11 | 12 | The latest development release will be published under the `devel` tag. To get it: 13 | 14 | ```shell 15 | $ npm install digs@devel hapi@^8 16 | ``` 17 | 18 | In addition, the [bundle-digs](https://github.com/digsjs/bundle-digs) repo includes all other projects as submodules, if you just want to grab them all at once. 19 | 20 | ## Project Goals 21 | 22 | Hi! Could use your help (yes, you). 23 | 24 | This project has lofty goals. **digs**, ultimately: 25 | 26 | - should be first-class home automation server 27 | - should be modular 28 | - should support an assortment of interfaces, including: 29 | - RESTful HTTP and [CoAP](https://wikipedia.org/wiki/Constrained_Application_Protocol) APIs 30 | - [MQTT](http://mqtt.org) and other messaging protocols 31 | - a slick web interface which works well on mobile 32 | - a CLI 33 | - should support a wide range of: 34 | - devices 35 | - configurations 36 | - communication protocols 37 | - storage options 38 | - authenticate schemes 39 | - should "just work" 40 | - should be easily extendable for your own setup 41 | - should support serial devices 42 | - should work in real-time 43 | - should be well-documented 44 | - tutorials 45 | - full API docs 46 | - should be well-tested 47 | - 100% unit test coverage 48 | - a plethora of integration tests 49 | 50 | If this sounds good to you, I'm hoping you can lend a hand. *I am but a man.* Send a PR, create an [issue](https://github.com/digsjs/digs/issues) to discuss, or shoot me ([Christopher Hiller](https://boneskull.com)) an [email](mailto:boneskull@boneskull.com). 51 | 52 | ## Installation 53 | 54 | [Hapi](http://hapijs.com) (>= 8.0.0 < 9.0.0) is a peer depdency of this package, so: 55 | 56 | ```sh 57 | $ npm install digs hapi 58 | ``` 59 | 60 | ## Contributing 61 | 62 | See [CONTRIBUTING.md](https://github.com/digsjs/digs/blob/master/CONTRIBUTING.md). 63 | 64 | ## Project Organization 65 | 66 | **digs** is divided into multiple projects. This tends to change daily as projects are renamed, removed or created. But as of this writing: 67 | 68 | - [digs](https://www.npmjs.com/package/digs) - A Hapi plugin which makes everything work 69 | - [digs-common](https://www.npmjs.com/package/digs-common) - A moatload of common objects and functions shared by various packages 70 | - [digs-data](https://www.npmjs.com/package/digs-data) - Abstraction layer for persistent storage 71 | - [digs-serial](https://www.npmjs.com/package/digs-serial) - Serial device plugin 72 | - [digs-dev](https://www.npmjs.com/package/digs-dev) - Common development dependencies (`devDependencies`) 73 | - [digs-messenger](https://www.npmjs.com/package/digs-messenger) - Messaging protocol plugin 74 | - [digs-mqtt-broker](https://www.npmjs.com/package/digs-mqtt-broker) - Flimsy MQTT broker if you don't have a proper one 75 | - [docker-digs](https://hub.docker.com/r/digsjs/digs/) - Docker image for Digs 76 | 77 | ## Roadmap 78 | 79 | TODO 80 | 81 | ## Author 82 | 83 | [Christopher Hiller](https://boneskull.com) 84 | 85 | ## License 86 | 87 | MIT 88 | -------------------------------------------------------------------------------- /assets/digs-logo-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/digsjs/digs/e600bba1061150607742562a136d557db2bb2ff4/assets/digs-logo-128.png -------------------------------------------------------------------------------- /assets/digs-logo-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/digsjs/digs/e600bba1061150607742562a136d557db2bb2ff4/assets/digs-logo-256.png -------------------------------------------------------------------------------- /assets/digs-logo-500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/digsjs/digs/e600bba1061150607742562a136d557db2bb2ff4/assets/digs-logo-500.png -------------------------------------------------------------------------------- /assets/digs-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Digs Logoimage/svg+xmlDigs Logo08-15-2015Dick DeLeonCC BY-NC 3.0Christopher Hiller -------------------------------------------------------------------------------- /bin/digs.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /* eslint no-sync:0 */ 4 | 5 | 'use strict'; 6 | 7 | const yaml = require('yaml-js'); 8 | const yargs = require('yargs'); 9 | const common = require('digs-common'); 10 | const fs = common.fs; 11 | const Promise = common.Promise; 12 | const _ = common.utils; 13 | 14 | let debug; 15 | 16 | function parseConfig(filepath) { 17 | if (!filepath) { 18 | return Promise.resolve({}); 19 | } 20 | debug('Attempting to read config file...'); 21 | return fs.readFileAsync(filepath, 'utf8') 22 | .then((file) => { 23 | if (/\.json$/.test(filepath)) { 24 | debug('Attempting to parse config file as JSON...'); 25 | return JSON.parse(file); 26 | } 27 | debug('Attempting to parse config file as YAML...'); 28 | return yaml.load(file); 29 | }) 30 | .tap(() => { 31 | debug('Succesfully parsed config file'); 32 | }) 33 | .catch((err) => { 34 | debug(err); 35 | throw new Error(`Cannot read or parse file at "${filepath}"`); 36 | }); 37 | } 38 | 39 | const argv = yargs 40 | .option('config', { 41 | alias: 'c', 42 | describe: 'Config manifest file (JSON/YAML)', 43 | string: true 44 | }) 45 | .option('debug', { 46 | boolean: true, 47 | 'default': false, 48 | describe: 'Enable debugging output (until server instantiated)' 49 | }) 50 | .check((args) => { 51 | if (args.debug) { 52 | common.debug.enable('digs*'); 53 | debug = common.debug('digs:cli'); 54 | debug('Debug mode enabled'); 55 | } else { 56 | debug = _.noop; 57 | } 58 | if (args.config) { 59 | debug(`Using config at path ${args.config}`); 60 | } else { 61 | debug('No config file specified'); 62 | } 63 | return true; 64 | }) 65 | .argv; 66 | 67 | parseConfig(argv.config) 68 | .then((config) => { 69 | if (argv.debug) { 70 | _.set(config, 'server.app.debug', true); 71 | } 72 | return require('../lib')(config); 73 | }); 74 | 75 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | digs: 2 | build: . 3 | links: 4 | - mongo 5 | - mosquitto 6 | ports: 7 | - "9090:9090" 8 | - "5683:5683" 9 | mongo: 10 | image: mongo 11 | expose: 12 | - 3000 13 | volumes: 14 | - ./logs/:/var/log/mongodb/ 15 | - ./mongodb/db:/data/db 16 | command: --smallfiles 17 | mosquitto: 18 | image: toke/mosquitto 19 | expose: 20 | - 1883 21 | -------------------------------------------------------------------------------- /grunt/aliases.yaml: -------------------------------------------------------------------------------- 1 | test: 2 | - eslint:test 3 | - mocha_istanbul:test 4 | -------------------------------------------------------------------------------- /grunt/test-tasks.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | watch: 3 | options: 4 | reload: true 5 | files: 6 | - bin/**/*.js 7 | - lib/**/*.js 8 | - test/**/*.js 9 | - grunt/**/*.js 10 | - grunt/**/*.yaml 11 | - Gruntfile.js 12 | - index.js 13 | tasks: 14 | - test 15 | 16 | mocha_istanbul: 17 | src: test/**/*.spec.js 18 | options: 19 | coverage: false 20 | 21 | eslint: 22 | src: 23 | - <%= watch.test.files %> 24 | - 'scripts/**/*.js' 25 | - '!**/*.yaml' 26 | - '!Gruntfile.js' 27 | - '!grunt/testfile.js' 28 | - '!grunt/digs-dev.js' 29 | - '!test/fixture.js' 30 | 31 | -------------------------------------------------------------------------------- /lib/debug-patcher.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const common = require('digs-common'); 4 | const debug = common.debug('digs:debug-patcher'); 5 | const DigsObject = common.definitions.DigsObject; 6 | const _ = common.utils; 7 | const consoleError = console.error; 8 | 9 | function patch(manifest) { 10 | _.set(manifest, 'server.debug.log', _.keys(DigsObject.defaultLogColors)); 11 | 12 | console.error = function digsDebug() { 13 | const args = _(arguments) 14 | .toArray() 15 | .map(arg => { 16 | if (_.isObject(arg)) { 17 | return _.dump(arg); 18 | } 19 | return _.trim(arg); 20 | }) 21 | .value(); 22 | args.shift(); 23 | return debug.apply(null, args); 24 | }; 25 | 26 | debug('Monkeypatched Hapi debug functionality'); 27 | } 28 | 29 | function restore() { 30 | console.error = consoleError; 31 | } 32 | 33 | function registerRestore(server) { 34 | function die(err) { 35 | restore(); 36 | throw err; 37 | } 38 | 39 | process.on('uncaughtException', die); 40 | process.on('unhandledRejection', die); 41 | process.on('exit', restore); 42 | server.on('stop', restore); 43 | 44 | server.method('restoreConsoleError', restore, { 45 | callback: false 46 | }); 47 | debug('Registered method to unpatch Hapi debug functionality'); 48 | } 49 | 50 | module.exports = { 51 | patch: patch, 52 | registerRestore: registerRestore 53 | }; 54 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const common = require('digs-common'); 4 | const Promise = common.Promise; 5 | const Glue = Promise.promisifyAll(require('glue')); 6 | const path = require('path'); 7 | const _ = common.utils; 8 | const debug = common.debug('digs:server'); 9 | const debugPatcher = require('./debug-patcher'); 10 | 11 | function digs(userManifest, options, done) { 12 | const t = new Date().getTime(); 13 | const root = path.join(__dirname, '..'); 14 | debug(`Root path: ${root}`); 15 | 16 | debug(`Raw user manifest: \n${_.dump(userManifest)}`); 17 | 18 | return require('./manifest-builder')(userManifest, root) 19 | .then(manifest => { 20 | const getManifest = _.partial(_.get, manifest); 21 | let userPreConnections; 22 | 23 | function isDebugMode() { 24 | return getManifest('server.app.debug') && 25 | !getManifest('server.debug.log'); 26 | } 27 | 28 | debug('Configuring Glue options...'); 29 | options = options || {}; 30 | 31 | if (options.preConnections) { 32 | // if this is set, we'll need to execute it after our own preConnections 33 | userPreConnections = options.preConnections; 34 | } else { 35 | // otherwise just passthru. 36 | userPreConnections = (server, next) => { 37 | next(); 38 | }; 39 | } 40 | 41 | _.extend(options, { 42 | // this cannot be overridden. 43 | relativeTo: root, 44 | preConnections: (server, next) => { 45 | const coapOpts = getManifest('server.app.coap'); 46 | if (coapOpts) { 47 | debug(`Passing options to hapi-coap-listener: ${_.dump(coapOpts)}`); 48 | require('hapi-coap-listener')(server, coapOpts) 49 | .then(connectionOpts => { 50 | manifest.connections.push(connectionOpts); 51 | userPreConnections(server, next); 52 | }, () => userPreConnections(server, next)); 53 | } else { 54 | userPreConnections(server, next); 55 | } 56 | } 57 | }); 58 | 59 | if (isDebugMode) { 60 | debugPatcher.patch(manifest); 61 | } 62 | 63 | debug(`Final manifest:\n${_.dump(manifest)}`); 64 | debug(`Glue options:\n${_.dump(options)}`); 65 | 66 | return Glue.composeAsync(manifest, options) 67 | .tap(server => { 68 | server.app.debug = { 69 | manifest: manifest 70 | }; 71 | 72 | server.method('isDebugMode', isDebugMode, { 73 | callback: false 74 | }); 75 | 76 | if (isDebugMode) { 77 | debugPatcher.registerRestore(server); 78 | } 79 | }); 80 | }) 81 | .then(server => { 82 | Promise.promisifyAll(server, { 83 | context: server 84 | }); 85 | 86 | return server.startAsync() 87 | .return(server); 88 | }) 89 | .then(server => { 90 | const delta = new Date().getTime() - t; 91 | server.log('info', `Digs ready in ${delta}ms.`); 92 | return server; 93 | }) 94 | .asCallback(done); 95 | } 96 | 97 | module.exports = digs; 98 | -------------------------------------------------------------------------------- /lib/manifest-builder.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const common = require('digs-common'); 4 | const _ = common.utils; 5 | const debug = common.debug('digs:manifest-builder'); 6 | const fs = common.fs; 7 | const yaml = require('yaml-js'); 8 | const path = require('path'); 9 | 10 | module.exports = function buildManifest(manifest, root) { 11 | debug('Building manifest...'); 12 | const cwd = process.cwd(); 13 | debug(`cwd: ${cwd}`); 14 | 15 | manifest = _.defaults(manifest || {}, { 16 | server: {}, 17 | plugins: [], 18 | connections: [] 19 | }); 20 | 21 | manifest.plugins = _.map(manifest.plugins, plugin => { 22 | return _.mapKeys(plugin, (value, name) => { 23 | return require.resolve(name); 24 | }); 25 | }); 26 | 27 | const configPath = path.join(__dirname, 'server.yaml'); 28 | return fs.readFileAsync(configPath, 'utf8') 29 | .then(yaml.load) 30 | .then(serverManifest => { 31 | serverManifest.plugins = _.map(serverManifest.plugins, plugin => { 32 | return _.mapKeys(plugin, (value, name) => { 33 | if (name.charAt(0) === '.') { 34 | name = path.resolve(root, name); 35 | } 36 | return name; 37 | }); 38 | }); 39 | 40 | manifest.server = _.merge(serverManifest.server, manifest.server); 41 | 42 | manifest.connections.unshift.apply(manifest.connections, 43 | serverManifest.connections); 44 | 45 | manifest.plugins.unshift.apply(manifest.plugins, serverManifest.plugins); 46 | 47 | return manifest; 48 | }); 49 | }; 50 | -------------------------------------------------------------------------------- /lib/plugin.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const pkg = require('../package.json'); 4 | const Boom = require('boom'); 5 | 6 | function digsPlugin(digs, opts, done) { 7 | digs.route({ 8 | method: '*', 9 | path: '/{p*}', 10 | handler: (req, reply) => reply(Boom.notFound()) 11 | }); 12 | 13 | // TODO remove; replace w/ seneca 14 | digs.route({ 15 | method: 'POST', 16 | path: '/log/{tags*}', 17 | handler: (req, reply) => { 18 | digs.log(req.params.tags.split('/'), req.payload); 19 | reply({ 20 | success: true 21 | }); 22 | }, 23 | config: { 24 | tags: [ 25 | 'digs', 26 | 'log' 27 | ] 28 | } 29 | }); 30 | 31 | digs.log('debug', 'Digs plugin registered successfully'); 32 | 33 | done(); 34 | } 35 | 36 | digsPlugin.attributes = { 37 | pkg: pkg 38 | }; 39 | 40 | module.exports = digsPlugin; 41 | -------------------------------------------------------------------------------- /lib/server.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | app: 3 | namespace: digs 4 | project: home 5 | coap: 6 | port: 5683 7 | host: localhost 8 | connections: 9 | router: 10 | stripTrailingSlash: true 11 | 12 | plugins: 13 | - 14 | ./lib/plugin: {} 15 | 16 | connections: 17 | - 18 | port: 9090 19 | host: localhost 20 | labels: 21 | - http 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "digs", 3 | "version": "0.2.2-5", 4 | "dependencies": { 5 | "boom": "^3.0.0", 6 | "chalk": "^1.1.1", 7 | "coap": "^0.12.0", 8 | "digs-common": "^0.2.10", 9 | "glue": "^2.4.0", 10 | "hapi-coap-listener": "^0.4.0", 11 | "user-home": "^2.0.0", 12 | "yaml-js": "^0.1.3", 13 | "yargs": "^3.27.0" 14 | }, 15 | "bin": { 16 | "digs": "bin/digs.js" 17 | }, 18 | "keywords": [ 19 | "automation", 20 | "home", 21 | "iot", 22 | "coap", 23 | "server", 24 | "hapi", 25 | "hapi-plugin" 26 | ], 27 | "author": { 28 | "email": "boneskull@boneskull.com", 29 | "name": "Christopher Hiller", 30 | "url": "https://boneskull.com" 31 | }, 32 | "repository": { 33 | "type": "git", 34 | "url": "https://github.com/digsjs/digs.git" 35 | }, 36 | "main": "lib/index.js", 37 | "license": "MIT", 38 | "engines": { 39 | "node": ">= 4.0.0" 40 | }, 41 | "scripts": { 42 | "prepublish": "digs-dev install", 43 | "test": "grunt test", 44 | "sync-labels": "scripts/sync-github-labels" 45 | }, 46 | "devDependencies": { 47 | "bin-path": "0.0.3", 48 | "chai": "^3.4.0", 49 | "chai-as-promised": "^5.1.0", 50 | "child-process-promise": "^1.1.0", 51 | "codacy-coverage": "^1.1.3", 52 | "codeclimate-test-reporter": "^0.1.1", 53 | "digs-dev": "^0.2.17", 54 | "eslint": "^1.8.0", 55 | "github": "^0.2.4", 56 | "github-labels": "^0.5.2", 57 | "grunt": "^0.4.5", 58 | "grunt-bump": "^0.6.0", 59 | "grunt-cli": "^0.1.13", 60 | "grunt-contrib-watch": "^0.6.1", 61 | "grunt-dev-update": "^1.4.0", 62 | "grunt-eslint": "^17.3.1", 63 | "grunt-mocha-istanbul": "^3.0.1", 64 | "hapi": "^11.0.0", 65 | "istanbul": "^0.4.0", 66 | "jit-grunt": "^0.9.1", 67 | "load-grunt-config": "^0.19.0", 68 | "mocha": "^2.3.2", 69 | "pre-commit": "^1.1.2", 70 | "rewire": "github:thesavior/rewire", 71 | "sinon": "^1.17.2", 72 | "sinon-chai": "^2.8.0", 73 | "time-grunt": "^1.2.2" 74 | }, 75 | "peerDependencies": { 76 | "hapi": "^11.0.0" 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /scripts/github-labels.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "admin", 4 | "color": "5319e7" 5 | }, 6 | { 7 | "name": "bug", 8 | "color": "fc2929" 9 | }, 10 | { 11 | "name": "chore", 12 | "color": "676BFB" 13 | }, 14 | { 15 | "name": "documentation", 16 | "color": "006b75" 17 | }, 18 | { 19 | "name": "duplicate", 20 | "color": "333333" 21 | }, 22 | { 23 | "name": "enhancement", 24 | "color": "009800" 25 | }, 26 | { 27 | "name": "future", 28 | "color": "207de5" 29 | }, 30 | { 31 | "name": "help wanted", 32 | "color": "FF9324" 33 | }, 34 | { 35 | "name": "quality", 36 | "color": "fbca04" 37 | }, 38 | { 39 | "name": "wontfix", 40 | "color": "666666" 41 | } 42 | ] 43 | -------------------------------------------------------------------------------- /scripts/sync-github-labels.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | 'use strict'; 4 | 5 | const GitHubApi = require('github'); 6 | const Promise = require('digs-common').Promise; 7 | const _ = require('digs-common').utils; 8 | const childProcess = require('child-process-promise'); 9 | const binPath = Promise.promisify(require('bin-path')(require)); 10 | const path = require('path'); 11 | 12 | const github = new GitHubApi({ 13 | version: '3.0.0', 14 | protocol: 'https', 15 | host: 'api.github.com', 16 | timeout: 5000, 17 | headers: { 18 | 'user-agent': 'digsjs-label-sync-script' 19 | } 20 | }); 21 | 22 | const project = process.argv[2]; 23 | if (project) { 24 | console.log(`Updating 'digsjs/${project}`, project); 25 | } else { 26 | console.log('Querying GitHub for projects...'); 27 | } 28 | 29 | binPath('github-labels') 30 | .get('labels') 31 | .then((executable) => { 32 | function update(name) { 33 | return childProcess.spawn(executable, 34 | [ 35 | '-c', 36 | require.resolve('./github-labels.json'), 37 | '-f', 38 | `digsjs/${name}` 39 | ]) 40 | .then(() => console.log('done.')); 41 | } 42 | 43 | console.log(`Using github-labels executable "%s"`, 44 | path.relative(process.cwd(), executable)); 45 | 46 | if (project) { 47 | process.stdout.write(`${project}...`); 48 | return update(project); 49 | } 50 | 51 | return Promise.promisify(github.repos.getFromOrg)({org: 'digsjs'}) 52 | .then((data) => { 53 | const names = _.pluck(data, 'name'); 54 | console.log(`Found ${names.length} repos to sync.`); 55 | return Promise.each(names, (name) => { 56 | process.stdout.write(`${name}...`); 57 | return update(name); 58 | }); 59 | }); 60 | }) 61 | .catch(err => console.log(err)); 62 | 63 | --------------------------------------------------------------------------------