Do not always require custom configuration files

This commit is contained in:
Jerko Steiner 2019-11-18 12:53:11 -03:00
parent 0b4aa45f95
commit 23fabb0b0c
15 changed files with 471 additions and 119 deletions

2
.gitignore vendored
View File

@ -6,6 +6,6 @@ build/
!build/.gitkeep
node_modules/
coverage/
config/local.json
config/local.yaml
lib/
tsconfig.tsbuildinfo

View File

@ -1,9 +1,18 @@
# Peer Calls
[![Build Status](https://travis-ci.org/jeremija/peer-calls.svg?branch=master)](https://travis-ci.org/jeremija/peer-calls) [![npm](https://img.shields.io/npm/v/peer-calls.svg)](https://www.npmjs.com/package/peer-calls)
[![Build Status][travis-badge]][travis]
[![NPM Package][npm-badge]][npm]
[travis-badge]: https://travis-ci.org/jeremija/peer-calls.svg?branch=master
[travis]: https://travis-ci.org/jeremija/peer-calls
[npm-badge]: https://img.shields.io/npm/v/peer-calls.svg
[npm]: https://www.npmjs.com/package/peer-calls
[peer-calls]: https://peercalls.com
[config]: https://raw.githubusercontent.com/jeremija/peer-calls/master/config/default.json
WebRTC peer to peer calls for everyone. See it live in action at
[peercalls.com](https://peercalls.com).
[peercalls.com][peer-calls].
Work in progress.
@ -14,7 +23,16 @@ Work in progress.
## From npm
create directory `./peer-calls` and copy [config/default.json](https://raw.githubusercontent.com/jeremija/peer-calls/master/config/default.json) into it.
### Local install
```bash
npm install peer-calls
mkdir config/
curl -o config/local.json https://raw.githubusercontent.com/jeremija/peer-calls/master/config/default.json
./node_modules/.bin/peer-calls
```
create directory `./peer-calls` and copy [config/default.json][config] into it.
```bash
npm install --global peer-calls

View File

@ -1,4 +0,0 @@
{
"baseUrl": "PEERCALLS_BASE_URL",
"iceServers": "PEERCALLS_ICE_SERVERS"
}

View File

@ -1,7 +0,0 @@
{
"baseUrl": "",
"iceServers": [{
"url": "stun:stun.l.google.com:19302",
"urls": "stun:stun.l.google.com:19302"
}]
}

5
config/default.yaml Normal file
View File

@ -0,0 +1,5 @@
---
baseUrl: ''
iceServers:
- url: stun:stun.l.google.com:19302
urls: stun:stun.l.google.com:19302

View File

@ -1 +0,0 @@
{}

127
package-lock.json generated
View File

@ -2368,12 +2368,6 @@
"integrity": "sha512-MNl+rT5UmZeilaPxAVs6YaPC2m6aA8rofviZbhbxpPpl61uKodfdQVsBtgJGTqGizEf02oW3tsVe7FYB8kK14A==",
"dev": true
},
"@types/config": {
"version": "0.0.36",
"resolved": "https://registry.npmjs.org/@types/config/-/config-0.0.36.tgz",
"integrity": "sha512-EoAeT1MyFWh2BJvBDEFInY714bQBbHOAucqxqqhprhbBFqr+B7fuN5T9CJqUIGDzvwubnKKRqmSo6yPo0aSpNw==",
"dev": true
},
"@types/connect": {
"version": "3.4.32",
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.32.tgz",
@ -2466,6 +2460,12 @@
"jest-diff": "^24.3.0"
}
},
"@types/js-yaml": {
"version": "3.12.1",
"resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-3.12.1.tgz",
"integrity": "sha512-SGGAhXLHDx+PK4YLNcNGa6goPf9XRWQNAUUbffkwVGGXIxmDKWyGGL4inzq2sPmExu431Ekb9aEMn9BkPqEYFA==",
"dev": true
},
"@types/json-schema": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.3.tgz",
@ -2787,7 +2787,6 @@
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
"integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
"dev": true,
"requires": {
"mime-types": "~2.1.24",
"negotiator": "0.6.2"
@ -2796,14 +2795,12 @@
"mime-db": {
"version": "1.42.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz",
"integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ==",
"dev": true
"integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ=="
},
"mime-types": {
"version": "2.1.25",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.25.tgz",
"integrity": "sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==",
"dev": true,
"requires": {
"mime-db": "1.42.0"
}
@ -2871,8 +2868,7 @@
"after": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
"integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=",
"dev": true
"integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8="
},
"ajv": {
"version": "6.10.2",
@ -3289,7 +3285,6 @@
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"dev": true,
"requires": {
"sprintf-js": "~1.0.2"
}
@ -3366,8 +3361,7 @@
"arraybuffer.slice": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz",
"integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==",
"dev": true
"integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog=="
},
"asap": {
"version": "2.0.6",
@ -3454,8 +3448,7 @@
"async-limiter": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
"integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==",
"dev": true
"integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
},
"asynckit": {
"version": "0.4.0",
@ -3847,8 +3840,7 @@
"backo2": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
"integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=",
"dev": true
"integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc="
},
"balanced-match": {
"version": "1.0.0",
@ -3926,8 +3918,7 @@
"base64-arraybuffer": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz",
"integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=",
"dev": true
"integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg="
},
"base64-js": {
"version": "1.3.0",
@ -3938,8 +3929,7 @@
"base64id": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
"integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==",
"dev": true
"integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog=="
},
"bcrypt-pbkdf": {
"version": "1.0.2",
@ -3954,7 +3944,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz",
"integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=",
"dev": true,
"requires": {
"callsite": "1.0.0"
}
@ -3968,8 +3957,7 @@
"blob": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz",
"integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==",
"dev": true
"integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig=="
},
"block-stream": {
"version": "0.0.9",
@ -4420,8 +4408,7 @@
"callsite": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz",
"integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=",
"dev": true
"integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA="
},
"callsites": {
"version": "3.1.0",
@ -4761,20 +4748,17 @@
"component-bind": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz",
"integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=",
"dev": true
"integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E="
},
"component-emitter": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
"integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
"dev": true
"integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY="
},
"component-inherit": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz",
"integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=",
"dev": true
"integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM="
},
"concat-map": {
"version": "0.0.1",
@ -4794,14 +4778,6 @@
"typedarray": "^0.0.6"
}
},
"config": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/config/-/config-3.2.4.tgz",
"integrity": "sha512-H1XIGfnU1EAkfjSLn9ZvYDRx9lOezDViuzLDgiJ/lMeqjYe3q6iQfpcLt2NInckJgpAeekbNhQkmnnbdEDs9rw==",
"requires": {
"json5": "^1.0.1"
}
},
"configstore": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz",
@ -4879,8 +4855,7 @@
"cookie": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
"integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=",
"dev": true
"integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
},
"cookie-signature": {
"version": "1.0.6",
@ -5405,7 +5380,6 @@
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.4.0.tgz",
"integrity": "sha512-XCyYVWzcHnK5cMz7G4VTu2W7zJS7SM1QkcelghyIk/FmobWBtXE7fwhBusEKvCSqc3bMh8fNFMlUkCKTFRxH2w==",
"dev": true,
"requires": {
"accepts": "~1.3.4",
"base64id": "2.0.0",
@ -5419,7 +5393,6 @@
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.0.tgz",
"integrity": "sha512-a4J5QO2k99CM2a0b12IznnyQndoEvtA4UAldhGzKqnHf42I3Qs2W5SPnDvatZRcMaNZs4IevVicBPayxYt6FwA==",
"dev": true,
"requires": {
"component-emitter": "1.2.1",
"component-inherit": "0.0.3",
@ -5438,7 +5411,6 @@
"version": "6.1.4",
"resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz",
"integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==",
"dev": true,
"requires": {
"async-limiter": "~1.0.0"
}
@ -5449,7 +5421,6 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.0.tgz",
"integrity": "sha512-6I3qD9iUxotsC5HEMuuGsKA0cXerGz+4uGcXQEkfBidgKf0amsjrrtwcbwK/nzpZBxclXlV7gGl9dgWvu4LF6w==",
"dev": true,
"requires": {
"after": "0.8.2",
"arraybuffer.slice": "~0.0.7",
@ -5916,8 +5887,7 @@
"esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
"dev": true
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
},
"esquery": {
"version": "1.0.1",
@ -7241,7 +7211,6 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz",
"integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==",
"dev": true,
"requires": {
"isarray": "2.0.1"
},
@ -7249,16 +7218,14 @@
"isarray": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
"integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=",
"dev": true
"integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4="
}
}
},
"has-cors": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
"integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=",
"dev": true
"integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk="
},
"has-flag": {
"version": "3.0.0",
@ -7558,8 +7525,7 @@
"indexof": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
"integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=",
"dev": true
"integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10="
},
"inflight": {
"version": "1.0.6",
@ -9373,7 +9339,6 @@
"version": "3.13.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
"integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
"dev": true,
"requires": {
"argparse": "^1.0.7",
"esprima": "^4.0.0"
@ -9499,14 +9464,6 @@
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
"dev": true
},
"json5": {
"version": "1.0.1",
"resolved": "http://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
"integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
"requires": {
"minimist": "^1.2.0"
}
},
"jsonify": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
@ -9901,7 +9858,8 @@
"minimist": {
"version": "1.2.0",
"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"dev": true
},
"mixin-deep": {
"version": "1.3.2",
@ -10029,8 +9987,7 @@
"negotiator": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==",
"dev": true
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
},
"neo-async": {
"version": "2.6.1",
@ -10274,8 +10231,7 @@
"object-component": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz",
"integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=",
"dev": true
"integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE="
},
"object-copy": {
"version": "0.1.0",
@ -10646,7 +10602,6 @@
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz",
"integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=",
"dev": true,
"requires": {
"better-assert": "~1.0.0"
}
@ -10655,7 +10610,6 @@
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz",
"integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=",
"dev": true,
"requires": {
"better-assert": "~1.0.0"
}
@ -12477,7 +12431,6 @@
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.3.0.tgz",
"integrity": "sha512-2A892lrj0GcgR/9Qk81EaY2gYhCBxurV0PfmmESO6p27QPrUK1J3zdns+5QPqvUYK2q657nSj0guoIil9+7eFg==",
"dev": true,
"requires": {
"debug": "~4.1.0",
"engine.io": "~3.4.0",
@ -12490,14 +12443,12 @@
"socket.io-adapter": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz",
"integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=",
"dev": true
"integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs="
},
"socket.io-client": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.3.0.tgz",
"integrity": "sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA==",
"dev": true,
"requires": {
"backo2": "1.0.2",
"base64-arraybuffer": "0.1.5",
@ -12518,14 +12469,12 @@
"isarray": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
"integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=",
"dev": true
"integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4="
},
"socket.io-parser": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz",
"integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==",
"dev": true,
"requires": {
"component-emitter": "1.2.1",
"debug": "~3.1.0",
@ -12536,7 +12485,6 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"dev": true,
"requires": {
"ms": "2.0.0"
}
@ -12549,7 +12497,6 @@
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.0.tgz",
"integrity": "sha512-/G/VOI+3DBp0+DJKW4KesGnQkQPFmUCbA/oO2QGT6CWxU7hLGWqU3tyuzeSK/dqcyeHsQg1vTe9jiZI8GU9SCQ==",
"dev": true,
"requires": {
"component-emitter": "1.2.1",
"debug": "~4.1.0",
@ -12559,8 +12506,7 @@
"isarray": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
"integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=",
"dev": true
"integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4="
}
}
},
@ -12651,8 +12597,7 @@
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
"dev": true
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
},
"sshpk": {
"version": "1.15.2",
@ -13208,8 +13153,7 @@
"to-array": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz",
"integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=",
"dev": true
"integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA="
},
"to-arraybuffer": {
"version": "1.0.1",
@ -14201,7 +14145,6 @@
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.2.0.tgz",
"integrity": "sha512-+SqNqFbwTm/0DC18KYzIsMTnEWpLwJsiasW/O17la4iDRRIO9uaHbvKiAS3AHgTiuuWerK/brj4O6MYZkei9xg==",
"dev": true,
"requires": {
"async-limiter": "^1.0.0"
}
@ -14221,8 +14164,7 @@
"xmlhttprequest-ssl": {
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz",
"integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=",
"dev": true
"integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4="
},
"xtend": {
"version": "4.0.1",
@ -14315,8 +14257,7 @@
"yeast": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
"integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=",
"dev": true
"integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk="
},
"yn": {
"version": "3.1.1",

View File

@ -49,9 +49,9 @@
"author": "Jerko Steiner",
"license": "MIT",
"dependencies": {
"config": "^3.2.4",
"debug": "^4.1.1",
"express": "^4.17.1",
"js-yaml": "^3.13.1",
"lodash": "^4.17.15",
"pug": "^2.0.4",
"socket.io": "^2.3.0",
@ -62,10 +62,10 @@
"@babel/polyfill": "^7.7.0",
"@babel/preset-env": "^7.7.1",
"@types/classnames": "^2.2.9",
"@types/config": "0.0.36",
"@types/debug": "^4.1.5",
"@types/express": "^4.17.2",
"@types/jest": "^24.0.23",
"@types/js-yaml": "^3.12.1",
"@types/lodash": "^4.14.148",
"@types/node": "^12.12.8",
"@types/react": "^16.9.11",

View File

@ -13,7 +13,7 @@ import request from 'supertest'
const io = SocketIO()
const BASE_URL: string = config.get('baseUrl')
const BASE_URL: string = config.baseUrl
describe('server/app', () => {

View File

@ -10,7 +10,7 @@ import index from './routes/index'
const debug = _debug('peercalls')
const BASE_URL: string = config.get('baseUrl')
const BASE_URL: string = config.baseUrl
const SOCKET_URL = `${BASE_URL}/ws`
debug(`WebSocket URL: ${SOCKET_URL}`)
@ -19,6 +19,7 @@ const app = express()
const server = createServer(config, app)
const io = SocketIO(server, { path: SOCKET_URL })
app.set('x-powered-by', false)
app.locals.version = require('../../package.json').version
app.locals.baseUrl = BASE_URL

View File

@ -1,4 +1,4 @@
import cfg, { IConfig } from 'config'
import { readConfig } from './readConfig'
export type ICEServer = {
url: string
@ -17,10 +17,16 @@ export type ICEServer = {
export interface Config {
baseUrl: string
iceServers: ICEServer[]
ssl: {
ssl?: {
cert: string
key: string
}
}
export const config = cfg as IConfig & Config
const cfg = readConfig()
export const config: Config = {
baseUrl: cfg.get('baseUrl', ''),
iceServers: cfg.get('iceServers'),
ssl: cfg.get('ssl', undefined),
}

View File

@ -0,0 +1 @@
export { ReadConfig, readConfig } from './readConfig'

View File

@ -0,0 +1,210 @@
import { ReadConfig, getAllConfigLocations, getAllConfigFilesInDirectory, findPackageRoot, mergeConfig, readConfig, toSnakeCase } from './readConfig'
import { existsSync, mkdirSync, rmdirSync } from 'fs'
import { join } from 'path'
describe('Config', () => {
const config = new ReadConfig({
a: 1,
b: {
c: 'test1',
d: 'test2',
},
})
describe('get', () => {
it('reads config values recursively', () => {
expect(config.get('a')).toBe(1)
expect(config.get('b')).toEqual({c: 'test1', d: 'test2'})
expect(config.get('b.c')).toBe('test1')
expect(config.get('b.d')).toBe('test2')
})
it('throws an error when key does not exist', () => {
expect(() => config.get('e')).toThrowError(/does not exist/)
expect(() => config.get('e.f')).toThrowError(/does not exist/)
})
it('returns a default value when provided', () => {
expect(config.get('b.c', 'test')).toBe('test1')
expect(config.get('e', 1)).toBe(1)
expect(config.get('e.f', 2)).toBe(2)
})
})
describe('has', () => {
it('returns true when config property exists, false otherwise', () => {
expect(config.has('a')).toBe(true)
expect(config.has('b')).toBe(true)
expect(config.has('b.c')).toBe(true)
expect(config.has('b.d')).toBe(true)
expect(config.has('e')).toBe(false)
expect(config.has('e.f')).toBe(false)
})
})
})
describe('findPackageRoot', () => {
const dir = join(__dirname, 'package.json')
beforeEach(() => {
if (existsSync(dir)) {
rmdirSync(dir)
}
mkdirSync(dir)
})
afterEach(() => {
if (existsSync(dir)) {
rmdirSync(dir)
}
})
it('finds package root folder', () => {
expect(findPackageRoot()).toEqual(jasmine.any(String))
})
it('finds package root folder', () => {
expect(findPackageRoot(__dirname)).toEqual(jasmine.any(String))
})
it('throws an error when not found', () => {
expect(() => findPackageRoot('/tmp')).toThrowError()
})
})
describe('getAllConfigFilesInDirectory', () => {
it('returns default and local files', () => {
const files = getAllConfigFilesInDirectory('/test', undefined)
expect(files).toEqual([
'/test/default.yaml',
'/test/local.yaml',
])
})
it('returns default, environment, and local files', () => {
const files = getAllConfigFilesInDirectory('/test', 'test')
expect(files).toEqual([
'/test/default.yaml',
'/test/test.yaml',
'/test/local.yaml',
])
})
})
describe('getAllConfigLocations', () => {
it('returns package and local dirs when separate', () => {
const files = getAllConfigLocations('/test1', '/test2', 'test')
expect(files).toEqual([
'/test1/default.yaml',
'/test1/test.yaml',
'/test1/local.yaml',
'/test2/default.yaml',
'/test2/test.yaml',
'/test2/local.yaml',
])
})
it('returns only package dir when local dir is same', () => {
const files = getAllConfigLocations('/test', '/test', 'test')
expect(files).toEqual([
'/test/default.yaml',
'/test/test.yaml',
'/test/local.yaml',
])
})
it('adds an extra config file', () => {
const files = getAllConfigLocations(
'/test', '/test', 'test', '/test/test-extra.yaml')
expect(files).toEqual([
'/test/default.yaml',
'/test/test.yaml',
'/test/local.yaml',
'/test/test-extra.yaml',
])
})
it('does not add extra config file when it is the same', () => {
const files = getAllConfigLocations(
'/test', '/test', 'test', '/test/test.yaml')
expect(files).toEqual([
'/test/default.yaml',
'/test/test.yaml',
'/test/local.yaml',
])
})
})
describe('toSnakeCase', () => {
it('converts uppercase, underscore-separated words to snake case', () => {
expect(toSnakeCase('TEST')).toBe('test')
expect(toSnakeCase('TEST_1')).toBe('test1')
expect(toSnakeCase('TEST_VALUE')).toBe('testValue')
expect(toSnakeCase('TEST_VALUE_TWO')).toBe('testValueTwo')
})
})
describe('mergeConfig', () => {
it('merges source config into destination', () => {
const dest = {
a: 1,
b: [2],
c: {
d: 3,
},
}
expect(mergeConfig({
a: 4,
b: {value: 5},
c: {
e: 6,
},
}, dest)).toEqual({
a: 4,
b: {value: 5},
c: {
d: 3,
e: 6,
},
})
})
})
describe('readConfig', () => {
it('reads from a number of files', () => {
const result = readConfig()
expect(result).toBeInstanceOf(ReadConfig)
})
it('reads from an extra config file', () => {
})
describe('errors', () => {
const dir = join(__dirname, 'test.dir')
beforeEach(() => {
mkdirSync(dir)
})
afterEach(() => {
rmdirSync(dir)
})
it('fails on errors different than ENOENT', () => {
expect(() => readConfig(
process.env,
undefined,
undefined,
dir,
)).toThrowError(/EISDIR/)
})
})
it('does not fail when no config files found', () => {
readConfig({}, '/tmp', '/tmp')
})
it('reads values from environment variables', () => {
const config = readConfig({
PEERCALLS__TEST_VALUE__SUB_VALUE_1: '1',
PEERCALLS__TEST_VALUE__SUB_VALUE_2: JSON.stringify({a: 2}),
}, '/tmp', '/tmp')
expect(config.value()).toEqual({
testValue: {
subValue1: 1,
subValue2: {a: 2},
},
})
})
})

View File

@ -0,0 +1,182 @@
/* eslint @typescript-eslint/no-explicit-any: 0 */
import { readFileSync, statSync } from 'fs'
import { resolve, join } from 'path'
import { safeLoad } from 'js-yaml'
import _debug from 'debug'
const debug = _debug('peercalls')
const isObject = (value: unknown) => value !== null && typeof value === 'object'
export class ReadConfig {
constructor(protected readonly config: any) {}
get(key: string, defaultValue?: any) {
let value = this.config
try {
key.split('.').forEach(k => {
if (!Object.prototype.hasOwnProperty.call(value, k)) {
throw new Error(`Property "${k}" from "${key}" does not exist`)
}
value = value[k]
})
} catch (err) {
if (arguments.length === 2) {
return defaultValue
} else {
throw err
}
}
return value
}
has(key: string) {
let c = this.config
return key.split('.').every(k => {
const has = Object.prototype.hasOwnProperty.call(c, k)
if (has) {
c = c[k]
}
return has
})
}
value() {
return this.config
}
}
function readConfigFile(filename: string): any {
return safeLoad(readFileSync(filename, 'utf8'))
}
export function mergeConfig(source: any, destination: any): any {
const stack = [{src: source, dest: destination}]
while (stack.length) {
const {src, dest} = stack.pop()!
const keys = Object.keys(src)
keys.forEach(key => {
const value = src[key]
if (isObject(value) && !Array.isArray(value)) {
if (
!Object.prototype.hasOwnProperty.call(dest, key) ||
Array.isArray(dest[key]) ||
!isObject(dest[key])
) {
dest[key] = {}
}
stack.push({src: value, dest: dest[key]})
return
}
dest[key] = value
})
}
return destination
}
export function findPackageRoot(path = __dirname): string {
path = resolve(path)
let lastPath: undefined | string
while (lastPath !== path) {
const file = join(path, 'package.json')
try {
const result = statSync(file)
if (result.isFile()) {
return path
}
} catch (err) {
// ignore error
}
lastPath = path
path = join(path, '..')
}
throw new Error('No package.json found')
}
export function getAllConfigFilesInDirectory(
dir: string,
environment: string | undefined,
): string[] {
const files: string[] = [join(dir, 'default.yaml')]
if (environment) {
files.push(join(dir, environment + '.yaml'))
}
files.push(join(dir, 'local.yaml'))
return files
}
export function getAllConfigLocations(
packageDir: string,
localDir: string,
environment: string | undefined,
extraConfigFile?: string,
): string[] {
const locations: string[] = [
...getAllConfigFilesInDirectory(packageDir, environment),
]
if (localDir !== packageDir) {
locations.push(...getAllConfigFilesInDirectory(localDir, environment))
}
if (extraConfigFile && locations.every(loc => loc !== extraConfigFile)) {
locations.push(resolve(extraConfigFile))
}
return locations
}
export function toSnakeCase(string: string) {
const value = string.split('_')
.map(item => item[0].toUpperCase() + item.slice(1).toLowerCase())
.join('')
return value[0].toLowerCase() + value.slice(1)
}
export function readConfig(
env = process.env,
packageDir = join(findPackageRoot(), 'config'),
localDir = join(process.cwd(), 'config'),
extraConfigFile?: string,
) {
const locations = getAllConfigLocations(
packageDir, localDir, env.NODE_ENV, extraConfigFile)
const readFiles = locations
.map(location => {
try {
const result = readConfigFile(location)
debug('Read config file: %s', location)
return result
} catch (err) {
if (!/ENOENT/.test(err.message)) {
throw err
}
return undefined
}
})
.filter(item => item !== undefined)
const config = readFiles
.reduce((merged, config) => mergeConfig(config, merged), {})
const envConfig: any = {}
Object.keys(env)
.filter(key => key.startsWith('PEERCALLS__'))
.forEach(key => {
const value = env[key]!
key = key.slice('PEERCALLS__'.length)
let cfg = envConfig
const keys = key.split('__').map(toSnakeCase)
const lastKey = keys[keys.length - 1]
keys
.slice(0, keys.length - 1)
.forEach(shortKey => {
cfg = cfg[shortKey] = cfg[shortKey] || {}
})
cfg[lastKey] = JSON.parse(value)
})
return new ReadConfig(mergeConfig(envConfig, config))
}

View File

@ -1,12 +1,12 @@
import { config, ICEServer } from '../config'
import { config } from '../config'
import * as turn from '../turn'
import { Router } from 'express'
import { v4 } from 'uuid'
const router = Router()
const BASE_URL: string = config.get('baseUrl')
const cfgIceServers = config.get('iceServers') as ICEServer[]
const BASE_URL: string = config.baseUrl
const cfgIceServers = config.iceServers
router.get('/', (req, res) => {
res.redirect(`${BASE_URL}/call/${v4()}`)