mirror of
https://github.com/pezkuwichain/pezkuwi-telemetry.git
synced 2026-06-14 19:41:01 +00:00
Reorganized repo using yarn and workspaces
This commit is contained in:
Generated
-466
@@ -1,466 +0,0 @@
|
||||
{
|
||||
"name": "dotstats-server",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@types/body-parser": {
|
||||
"version": "1.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.17.0.tgz",
|
||||
"integrity": "sha512-a2+YeUjPkztKJu5aIF2yArYFQQp8d51wZ7DavSHjFuY1mqVgidGyzEQ41JIVNy82fXj8yPgy2vJmfIywgESW6w==",
|
||||
"requires": {
|
||||
"@types/connect": "3.4.32",
|
||||
"@types/node": "10.3.3"
|
||||
}
|
||||
},
|
||||
"@types/connect": {
|
||||
"version": "3.4.32",
|
||||
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.32.tgz",
|
||||
"integrity": "sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg==",
|
||||
"requires": {
|
||||
"@types/node": "10.3.3"
|
||||
}
|
||||
},
|
||||
"@types/events": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz",
|
||||
"integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA=="
|
||||
},
|
||||
"@types/express": {
|
||||
"version": "4.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.16.0.tgz",
|
||||
"integrity": "sha512-TtPEYumsmSTtTetAPXlJVf3kEqb6wZK0bZojpJQrnD/djV4q1oB6QQ8aKvKqwNPACoe02GNiy5zDzcYivR5Z2w==",
|
||||
"requires": {
|
||||
"@types/body-parser": "1.17.0",
|
||||
"@types/express-serve-static-core": "4.16.0",
|
||||
"@types/serve-static": "1.13.2"
|
||||
}
|
||||
},
|
||||
"@types/express-serve-static-core": {
|
||||
"version": "4.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.16.0.tgz",
|
||||
"integrity": "sha512-lTeoCu5NxJU4OD9moCgm0ESZzweAx0YqsAcab6OB0EB3+As1OaHtKnaGJvcngQxYsi9UNv0abn4/DRavrRxt4w==",
|
||||
"requires": {
|
||||
"@types/events": "1.2.0",
|
||||
"@types/node": "10.3.3",
|
||||
"@types/range-parser": "1.2.2"
|
||||
}
|
||||
},
|
||||
"@types/mime": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.0.tgz",
|
||||
"integrity": "sha512-A2TAGbTFdBw9azHbpVd+/FkdW2T6msN1uct1O9bH3vTerEHKZhTXJUQXy+hNq1B0RagfU8U+KBdqiZpxjhOUQA=="
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "10.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.3.3.tgz",
|
||||
"integrity": "sha512-/gwCgiI2e9RzzZTKbl+am3vgNqOt7a9fJ/uxv4SqYKxenoEDNVU3KZEadlpusWhQI0A0dOrZ0T68JYKVjzmgdQ=="
|
||||
},
|
||||
"@types/range-parser": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.2.tgz",
|
||||
"integrity": "sha512-HtKGu+qG1NPvYe1z7ezLsyIaXYyi8SoAVqWDZgDQ8dLrsZvSzUNCwZyfX33uhWxL/SU0ZDQZ3nwZ0nimt507Kw=="
|
||||
},
|
||||
"@types/serve-static": {
|
||||
"version": "1.13.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.2.tgz",
|
||||
"integrity": "sha512-/BZ4QRLpH/bNYgZgwhKEh+5AsboDBcUdlBYgzoLX0fpj3Y2gp6EApyOlM3bK53wQS/OE1SrdSYBAbux2D1528Q==",
|
||||
"requires": {
|
||||
"@types/express-serve-static-core": "4.16.0",
|
||||
"@types/mime": "2.0.0"
|
||||
}
|
||||
},
|
||||
"@types/ws": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-5.1.2.tgz",
|
||||
"integrity": "sha512-NkTXUKTYdXdnPE2aUUbGOXE1XfMK527SCvU/9bj86kyFF6kZ9ZnOQ3mK5jADn98Y2vEUD/7wKDgZa7Qst2wYOg==",
|
||||
"requires": {
|
||||
"@types/events": "1.2.0",
|
||||
"@types/node": "10.3.3"
|
||||
}
|
||||
},
|
||||
"accepts": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
|
||||
"integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
|
||||
"requires": {
|
||||
"mime-types": "2.1.18",
|
||||
"negotiator": "0.6.1"
|
||||
}
|
||||
},
|
||||
"array-flatten": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
|
||||
},
|
||||
"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=="
|
||||
},
|
||||
"body-parser": {
|
||||
"version": "1.18.2",
|
||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz",
|
||||
"integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=",
|
||||
"requires": {
|
||||
"bytes": "3.0.0",
|
||||
"content-type": "1.0.4",
|
||||
"debug": "2.6.9",
|
||||
"depd": "1.1.2",
|
||||
"http-errors": "1.6.3",
|
||||
"iconv-lite": "0.4.19",
|
||||
"on-finished": "2.3.0",
|
||||
"qs": "6.5.1",
|
||||
"raw-body": "2.3.2",
|
||||
"type-is": "1.6.16"
|
||||
}
|
||||
},
|
||||
"bytes": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
|
||||
"integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg="
|
||||
},
|
||||
"content-disposition": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
|
||||
"integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ="
|
||||
},
|
||||
"content-type": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
|
||||
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
|
||||
},
|
||||
"cookie": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
|
||||
"integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
|
||||
},
|
||||
"cookie-signature": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
|
||||
},
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"depd": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
|
||||
},
|
||||
"destroy": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
|
||||
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
|
||||
},
|
||||
"ee-first": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
|
||||
},
|
||||
"encodeurl": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
|
||||
},
|
||||
"escape-html": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
|
||||
},
|
||||
"etag": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
|
||||
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
|
||||
},
|
||||
"express": {
|
||||
"version": "4.16.3",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz",
|
||||
"integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=",
|
||||
"requires": {
|
||||
"accepts": "1.3.5",
|
||||
"array-flatten": "1.1.1",
|
||||
"body-parser": "1.18.2",
|
||||
"content-disposition": "0.5.2",
|
||||
"content-type": "1.0.4",
|
||||
"cookie": "0.3.1",
|
||||
"cookie-signature": "1.0.6",
|
||||
"debug": "2.6.9",
|
||||
"depd": "1.1.2",
|
||||
"encodeurl": "1.0.2",
|
||||
"escape-html": "1.0.3",
|
||||
"etag": "1.8.1",
|
||||
"finalhandler": "1.1.1",
|
||||
"fresh": "0.5.2",
|
||||
"merge-descriptors": "1.0.1",
|
||||
"methods": "1.1.2",
|
||||
"on-finished": "2.3.0",
|
||||
"parseurl": "1.3.2",
|
||||
"path-to-regexp": "0.1.7",
|
||||
"proxy-addr": "2.0.3",
|
||||
"qs": "6.5.1",
|
||||
"range-parser": "1.2.0",
|
||||
"safe-buffer": "5.1.1",
|
||||
"send": "0.16.2",
|
||||
"serve-static": "1.13.2",
|
||||
"setprototypeof": "1.1.0",
|
||||
"statuses": "1.4.0",
|
||||
"type-is": "1.6.16",
|
||||
"utils-merge": "1.0.1",
|
||||
"vary": "1.1.2"
|
||||
}
|
||||
},
|
||||
"finalhandler": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
|
||||
"integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
|
||||
"requires": {
|
||||
"debug": "2.6.9",
|
||||
"encodeurl": "1.0.2",
|
||||
"escape-html": "1.0.3",
|
||||
"on-finished": "2.3.0",
|
||||
"parseurl": "1.3.2",
|
||||
"statuses": "1.4.0",
|
||||
"unpipe": "1.0.0"
|
||||
}
|
||||
},
|
||||
"forwarded": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
|
||||
"integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
|
||||
},
|
||||
"fresh": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
|
||||
},
|
||||
"http-errors": {
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
|
||||
"integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
|
||||
"requires": {
|
||||
"depd": "1.1.2",
|
||||
"inherits": "2.0.3",
|
||||
"setprototypeof": "1.1.0",
|
||||
"statuses": "1.4.0"
|
||||
}
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.4.19",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
|
||||
"integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ=="
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||
},
|
||||
"ipaddr.js": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz",
|
||||
"integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs="
|
||||
},
|
||||
"media-typer": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
|
||||
},
|
||||
"merge-descriptors": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
|
||||
"integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
|
||||
},
|
||||
"methods": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
|
||||
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
|
||||
},
|
||||
"mime": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
|
||||
"integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ=="
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.33.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz",
|
||||
"integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.18",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz",
|
||||
"integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==",
|
||||
"requires": {
|
||||
"mime-db": "1.33.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
},
|
||||
"negotiator": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
|
||||
"integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk="
|
||||
},
|
||||
"on-finished": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
|
||||
"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
|
||||
"requires": {
|
||||
"ee-first": "1.1.1"
|
||||
}
|
||||
},
|
||||
"parseurl": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
|
||||
"integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M="
|
||||
},
|
||||
"path-to-regexp": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
|
||||
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
|
||||
},
|
||||
"proxy-addr": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz",
|
||||
"integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==",
|
||||
"requires": {
|
||||
"forwarded": "0.1.2",
|
||||
"ipaddr.js": "1.6.0"
|
||||
}
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.5.1",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
|
||||
"integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A=="
|
||||
},
|
||||
"range-parser": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
|
||||
"integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4="
|
||||
},
|
||||
"raw-body": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz",
|
||||
"integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=",
|
||||
"requires": {
|
||||
"bytes": "3.0.0",
|
||||
"http-errors": "1.6.2",
|
||||
"iconv-lite": "0.4.19",
|
||||
"unpipe": "1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"depd": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz",
|
||||
"integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k="
|
||||
},
|
||||
"http-errors": {
|
||||
"version": "1.6.2",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz",
|
||||
"integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=",
|
||||
"requires": {
|
||||
"depd": "1.1.1",
|
||||
"inherits": "2.0.3",
|
||||
"setprototypeof": "1.0.3",
|
||||
"statuses": "1.4.0"
|
||||
}
|
||||
},
|
||||
"setprototypeof": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz",
|
||||
"integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ="
|
||||
}
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
|
||||
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
|
||||
},
|
||||
"send": {
|
||||
"version": "0.16.2",
|
||||
"resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz",
|
||||
"integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==",
|
||||
"requires": {
|
||||
"debug": "2.6.9",
|
||||
"depd": "1.1.2",
|
||||
"destroy": "1.0.4",
|
||||
"encodeurl": "1.0.2",
|
||||
"escape-html": "1.0.3",
|
||||
"etag": "1.8.1",
|
||||
"fresh": "0.5.2",
|
||||
"http-errors": "1.6.3",
|
||||
"mime": "1.4.1",
|
||||
"ms": "2.0.0",
|
||||
"on-finished": "2.3.0",
|
||||
"range-parser": "1.2.0",
|
||||
"statuses": "1.4.0"
|
||||
}
|
||||
},
|
||||
"serve-static": {
|
||||
"version": "1.13.2",
|
||||
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz",
|
||||
"integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==",
|
||||
"requires": {
|
||||
"encodeurl": "1.0.2",
|
||||
"escape-html": "1.0.3",
|
||||
"parseurl": "1.3.2",
|
||||
"send": "0.16.2"
|
||||
}
|
||||
},
|
||||
"setprototypeof": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
|
||||
"integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
|
||||
},
|
||||
"statuses": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
|
||||
"integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
|
||||
},
|
||||
"type-is": {
|
||||
"version": "1.6.16",
|
||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
|
||||
"integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==",
|
||||
"requires": {
|
||||
"media-typer": "0.3.0",
|
||||
"mime-types": "2.1.18"
|
||||
}
|
||||
},
|
||||
"typescript": {
|
||||
"version": "2.9.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz",
|
||||
"integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w=="
|
||||
},
|
||||
"unpipe": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
|
||||
},
|
||||
"utils-merge": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
|
||||
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
|
||||
},
|
||||
"vary": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
|
||||
},
|
||||
"ws": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-5.2.0.tgz",
|
||||
"integrity": "sha512-c18dMeW+PEQdDFzkhDsnBAlS4Z8KGStBQQUcQ5mf7Nf689jyGk0594L+i9RaQuf4gog6SvWLJorz2NfSaqxZ7w==",
|
||||
"requires": {
|
||||
"async-limiter": "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"name": "dotstats-backend",
|
||||
"version": "0.1.0",
|
||||
"author": "Parity Technologies Ltd. <admin@parity.io>",
|
||||
"license": "GPL-3.0",
|
||||
"description": "Polkadot Telemetry frontend",
|
||||
"main": "build/index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"start": "tsc && node build/index.js",
|
||||
"tsc": "tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/express": "^4.16.0",
|
||||
"@types/node": "^10.3.3",
|
||||
"@types/ws": "^5.1.2",
|
||||
"express": "^4.16.3",
|
||||
"typescript": "^2.9.2",
|
||||
"ws": "5.2.0"
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
import * as EventEmitter from 'events';
|
||||
import Node from './node';
|
||||
import Feed, { FeedData } from './feed';
|
||||
import { Id, IdSet } from './shared';
|
||||
|
||||
export default class Aggregator extends EventEmitter {
|
||||
private nodes: IdSet<Node> = new IdSet<Node>();
|
||||
private feeds: IdSet<Feed> = new IdSet<Feed>();
|
||||
|
||||
public height: number = 0;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
setInterval(() => this.timeoutCheck(), 10000);
|
||||
}
|
||||
|
||||
public addNode(node: Node) {
|
||||
this.nodes.add(node);
|
||||
this.broadcast(Feed.addedNode(node));
|
||||
|
||||
node.once('disconnect', () => {
|
||||
node.removeAllListeners('block');
|
||||
|
||||
this.nodes.remove(node);
|
||||
this.broadcast(Feed.removedNode(node));
|
||||
});
|
||||
|
||||
node.on('block', () => this.updateBlock(node));
|
||||
}
|
||||
|
||||
public addFeed(feed: Feed) {
|
||||
this.feeds.add(feed);
|
||||
|
||||
feed.send(Feed.bestBlock(this.height));
|
||||
|
||||
for (const node of this.nodes.entries) {
|
||||
feed.send(Feed.addedNode(node));
|
||||
}
|
||||
|
||||
feed.once('disconnect', () => {
|
||||
this.feeds.remove(feed);
|
||||
})
|
||||
}
|
||||
|
||||
public nodeList(): IterableIterator<Node> {
|
||||
return this.nodes.entries;
|
||||
}
|
||||
|
||||
private broadcast(data: FeedData) {
|
||||
for (const feed of this.feeds.entries) {
|
||||
feed.send(data);
|
||||
}
|
||||
}
|
||||
|
||||
private timeoutCheck() {
|
||||
const now = Date.now();
|
||||
|
||||
for (const node of this.nodes.entries) {
|
||||
node.timeoutCheck(now);
|
||||
}
|
||||
}
|
||||
|
||||
private updateBlock(node: Node) {
|
||||
if (node.height > this.height) {
|
||||
this.height = node.height;
|
||||
|
||||
this.broadcast(Feed.bestBlock(this.height));
|
||||
|
||||
console.log(`New block ${this.height}`);
|
||||
}
|
||||
|
||||
this.broadcast(Feed.imported(node));
|
||||
|
||||
console.log(`${node.name} imported ${node.height}, block time: ${node.blockTime / 1000}s, average: ${node.average / 1000}s | latency ${node.latency}`);
|
||||
}
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
import * as WebSocket from 'ws';
|
||||
import * as EventEmitter from 'events';
|
||||
import Node, { NodeInfo, BlockInfo } from './node';
|
||||
import { Opaque, Id, idGenerator } from './shared';
|
||||
|
||||
const nextId = idGenerator<Feed>();
|
||||
|
||||
export interface BlockInfo {
|
||||
height: number;
|
||||
blockTime: number;
|
||||
}
|
||||
|
||||
interface BestBlock {
|
||||
action: 'best';
|
||||
payload: number;
|
||||
}
|
||||
|
||||
interface AddedNode {
|
||||
action: 'added';
|
||||
payload: [Id<Node>, NodeInfo, BlockInfo];
|
||||
}
|
||||
|
||||
interface RemovedNode {
|
||||
action: 'removed';
|
||||
payload: Id<Node>;
|
||||
}
|
||||
|
||||
interface Imported {
|
||||
action: 'imported';
|
||||
payload: [Id<Node>, BlockInfo];
|
||||
}
|
||||
|
||||
type Message = BestBlock | AddedNode | RemovedNode | Imported;
|
||||
|
||||
/**
|
||||
* Opaque data type to be sent to the feed. Passing through
|
||||
* strings means we can only serialize once, no matter how
|
||||
* many feed clients are listening in.
|
||||
*/
|
||||
export type FeedData = Opaque<string, Message>;
|
||||
|
||||
function serialize(msg: Message): FeedData {
|
||||
return JSON.stringify(msg) as FeedData;
|
||||
}
|
||||
|
||||
export default class Feed extends EventEmitter {
|
||||
public id: Id<Feed>;
|
||||
|
||||
private socket: WebSocket;
|
||||
|
||||
constructor(socket: WebSocket) {
|
||||
super();
|
||||
|
||||
this.id = nextId();
|
||||
this.socket = socket;
|
||||
|
||||
socket.on('error', () => this.disconnect());
|
||||
socket.on('close', () => this.disconnect());
|
||||
}
|
||||
|
||||
public static bestBlock(height: number): FeedData {
|
||||
return serialize({
|
||||
action: 'best',
|
||||
payload: height
|
||||
});
|
||||
}
|
||||
|
||||
public static addedNode(node: Node): FeedData {
|
||||
return serialize({
|
||||
action: 'added',
|
||||
payload: [node.id, node.nodeInfo(), node.blockInfo()]
|
||||
})
|
||||
}
|
||||
|
||||
public static removedNode(node: Node): FeedData {
|
||||
return serialize({
|
||||
action: 'removed',
|
||||
payload: node.id
|
||||
});
|
||||
}
|
||||
|
||||
public static imported(node: Node): FeedData {
|
||||
return serialize({
|
||||
action: 'imported',
|
||||
payload: [node.id, node.blockInfo()]
|
||||
});
|
||||
}
|
||||
|
||||
public send(data: FeedData) {
|
||||
this.socket.send(data);
|
||||
}
|
||||
|
||||
private disconnect() {
|
||||
this.socket.removeAllListeners();
|
||||
this.socket.close();
|
||||
|
||||
this.emit('disconnect');
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
import * as WebSocket from 'ws';
|
||||
import * as express from 'express';
|
||||
import { createServer } from 'http';
|
||||
import Node from './node';
|
||||
import Feed from './feed';
|
||||
import Aggregator from './aggregator';
|
||||
import { map, join } from './shared';
|
||||
|
||||
const aggregator = new Aggregator;
|
||||
const app = express();
|
||||
const server = createServer(app);
|
||||
|
||||
// WebSocket for Nodes feeding telemetry data to the server
|
||||
const incomingTelemetry = new WebSocket.Server({ port: 1024 });
|
||||
|
||||
// WebSocket for web clients listening to the telemetry data aggregate
|
||||
const telemetryFeed = new WebSocket.Server({ server });
|
||||
|
||||
app.get('/', function (req, res) {
|
||||
function nodeInfo(node: Node) {
|
||||
return `${node.name} | ${node.height} | Block time ${node.blockTime / 1000}s`;
|
||||
}
|
||||
|
||||
res.send(
|
||||
|
||||
`<pre>
|
||||
Best block: ${aggregator.height}
|
||||
|
||||
Node list:
|
||||
${ join(map(aggregator.nodeList(), nodeInfo), '\n') }
|
||||
</pre>`
|
||||
|
||||
);
|
||||
});
|
||||
|
||||
incomingTelemetry.on('connection', async (socket: WebSocket) => {
|
||||
try {
|
||||
aggregator.addNode(await Node.fromSocket(socket));
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
|
||||
telemetryFeed.on('connection', (socket: WebSocket) => {
|
||||
aggregator.addFeed(new Feed(socket));
|
||||
});
|
||||
|
||||
server.listen(8080);
|
||||
@@ -1,78 +0,0 @@
|
||||
import { Data } from 'ws';
|
||||
import { Maybe, Opaque } from './shared';
|
||||
|
||||
export function parseMessage(data: Data): Maybe<Message> {
|
||||
try {
|
||||
const message = JSON.parse(data.toString());
|
||||
|
||||
if (message && typeof message.msg === 'string' && typeof message.ts === 'string') {
|
||||
message.ts = new Date(message.ts);
|
||||
|
||||
return message;
|
||||
}
|
||||
} catch (_) {
|
||||
console.warn('Error parsing message JSON');
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getBestBlock(message: Message): Maybe<BestBlock> {
|
||||
switch (message.msg) {
|
||||
case 'node.start':
|
||||
case 'system.interval':
|
||||
case 'block.import':
|
||||
return message;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
interface MessageBase {
|
||||
ts: Date,
|
||||
level: 'INFO' | 'WARN',
|
||||
}
|
||||
|
||||
export interface BestBlock {
|
||||
best: string,
|
||||
height: number,
|
||||
ts: Date,
|
||||
}
|
||||
|
||||
interface SystemConnected {
|
||||
msg: 'system.connected',
|
||||
name: string,
|
||||
chain: string,
|
||||
config: string,
|
||||
implementation: string,
|
||||
version: string,
|
||||
}
|
||||
|
||||
interface SystemInterval extends BestBlock {
|
||||
msg: 'system.interval',
|
||||
txcount: number,
|
||||
peers: number,
|
||||
status: 'Idle' | string, // TODO: 'Idle' | ...?
|
||||
}
|
||||
|
||||
interface NodeStart extends BestBlock {
|
||||
msg: 'node.start',
|
||||
}
|
||||
|
||||
interface BlockImport extends BestBlock {
|
||||
msg: 'block.import',
|
||||
}
|
||||
|
||||
// Union type
|
||||
export type Message = MessageBase & (
|
||||
SystemConnected |
|
||||
SystemInterval |
|
||||
NodeStart |
|
||||
BlockImport
|
||||
);
|
||||
|
||||
|
||||
// received: {"msg":"block.import","level":"INFO","ts":"2018-06-18T17:30:35.285406538+02:00","best":"3d4fdc7960078ddc9be87dddc48324a6d64afdf1f65fffe89529ce9965cd5f29","height":526}
|
||||
// received: {"msg":"node.start","level":"INFO","ts":"2018-06-18T17:30:40.038731057+02:00","best":"3d4fdc7960078ddc9be87dddc48324a6d64afdf1f65fffe89529ce9965cd5f29","height":526}
|
||||
// received: {"msg":"system.connected","level":"INFO","ts":"2018-06-18T17:30:40.038975471+02:00","chain":"dev","config":"","version":"0.2.0","implementation":"parity-polkadot","name":"Majestic Widget"}
|
||||
// received: {"msg":"system.interval","level":"INFO","ts":"2018-06-19T14:00:05.091355364+02:00","txcount":0,"best":"360c9563857308703398f637932b7ffe884e5c7b09692600ff09a4d753c9d948","height":7559,"peers":0,"status":"Idle"}
|
||||
@@ -1,179 +0,0 @@
|
||||
import * as WebSocket from 'ws';
|
||||
import * as EventEmitter from 'events';
|
||||
import { Maybe, Id, idGenerator } from './shared';
|
||||
import { parseMessage, getBestBlock, Message, BestBlock } from './message';
|
||||
|
||||
const BLOCK_TIME_HISTORY = 10;
|
||||
const TIMEOUT = 1000 * 60 * 5; // 5 seconds
|
||||
|
||||
const nextId = idGenerator<Node>();
|
||||
|
||||
export interface NodeInfo {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface BlockInfo {
|
||||
height: number;
|
||||
blockTime: number;
|
||||
}
|
||||
|
||||
export default class Node extends EventEmitter {
|
||||
public lastMessage: number;
|
||||
public id: Id<Node>;
|
||||
public name: string;
|
||||
public implementation: string;
|
||||
public version: string;
|
||||
public height: number = 0;
|
||||
public config: string;
|
||||
public latency: number = 0;
|
||||
public blockTime: number = 0;
|
||||
|
||||
private socket: WebSocket;
|
||||
private blockTimes: Array<number> = new Array(BLOCK_TIME_HISTORY);
|
||||
private lastBlockAt: Maybe<Date> = null;
|
||||
|
||||
constructor(socket: WebSocket, name: string, config: string, implentation: string, version: string) {
|
||||
super();
|
||||
|
||||
this.lastMessage = Date.now();
|
||||
this.id = nextId();
|
||||
this.socket = socket;
|
||||
this.name = name;
|
||||
this.config = config;
|
||||
this.implementation = implentation;
|
||||
this.version = version;
|
||||
|
||||
console.log(`Listening to a new node: ${name}`);
|
||||
|
||||
socket.on('message', (data) => {
|
||||
const message = parseMessage(data);
|
||||
|
||||
if (!message) return;
|
||||
|
||||
this.lastMessage = Date.now();
|
||||
this.updateLatency(message.ts);
|
||||
|
||||
const update = getBestBlock(message);
|
||||
|
||||
if (update) {
|
||||
this.updateBestBlock(update);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('close', () => {
|
||||
console.log(`${this.name} has disconnected`);
|
||||
|
||||
this.disconnect();
|
||||
});
|
||||
|
||||
socket.on('error', (error) => {
|
||||
console.error(`${this.name} has errored`, error);
|
||||
|
||||
this.disconnect();
|
||||
});
|
||||
}
|
||||
|
||||
public static fromSocket(socket: WebSocket): Promise<Node> {
|
||||
return new Promise((resolve, reject) => {
|
||||
function cleanup() {
|
||||
clearTimeout(timeout);
|
||||
socket.removeAllListeners('message');
|
||||
}
|
||||
|
||||
function handler(data: WebSocket.Data) {
|
||||
const message = parseMessage(data);
|
||||
|
||||
if (message && message.msg === "system.connected") {
|
||||
cleanup();
|
||||
|
||||
const { name, config, implementation, version } = message;
|
||||
|
||||
resolve(new Node(socket, name, config, implementation, version));
|
||||
}
|
||||
}
|
||||
|
||||
socket.on('message', handler);
|
||||
|
||||
const timeout = setTimeout(() => {
|
||||
cleanup();
|
||||
|
||||
socket.close();
|
||||
|
||||
return reject(new Error('Timeout on waiting for system.connected message'));
|
||||
}, 5000);
|
||||
});
|
||||
}
|
||||
|
||||
public timeoutCheck(now: number) {
|
||||
if (this.lastMessage + TIMEOUT < now) {
|
||||
this.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
public nodeInfo(): NodeInfo {
|
||||
return {
|
||||
name: this.name,
|
||||
};
|
||||
}
|
||||
|
||||
public blockInfo(): BlockInfo {
|
||||
return {
|
||||
height: this.height,
|
||||
blockTime: this.blockTime,
|
||||
};
|
||||
}
|
||||
|
||||
public get average(): number {
|
||||
let accounted = 0;
|
||||
let sum = 0;
|
||||
|
||||
for (const time of this.blockTimes) {
|
||||
if (time) {
|
||||
accounted += 1;
|
||||
sum += time;
|
||||
}
|
||||
}
|
||||
|
||||
if (accounted === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return sum / accounted;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private disconnect() {
|
||||
this.socket.removeAllListeners();
|
||||
this.socket.close();
|
||||
|
||||
this.emit('disconnect');
|
||||
}
|
||||
|
||||
private updateLatency(time: Date) {
|
||||
this.latency = this.lastMessage - +time;
|
||||
}
|
||||
|
||||
private updateBestBlock(update: BestBlock) {
|
||||
const { height, ts: time, best } = update;
|
||||
|
||||
if (this.height < height) {
|
||||
const blockTime = this.getBlockTime(time);
|
||||
|
||||
this.height = height;
|
||||
this.lastBlockAt = time;
|
||||
this.blockTimes[height % BLOCK_TIME_HISTORY] = blockTime;
|
||||
this.blockTime = blockTime;
|
||||
|
||||
this.emit('block');
|
||||
}
|
||||
}
|
||||
|
||||
private getBlockTime(time: Date): number {
|
||||
if (!this.lastBlockAt) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return +time - +this.lastBlockAt;
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
../../shared
|
||||
@@ -1,26 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2017",
|
||||
"module": "commonjs",
|
||||
"outDir": "build",
|
||||
"strictNullChecks": true,
|
||||
"sourceMap": true,
|
||||
"moduleResolution": "node",
|
||||
"noEmitOnError": false,
|
||||
// "noUnusedLocals": true,
|
||||
// "noUnusedParameters": true,
|
||||
"pretty": true,
|
||||
"noErrorTruncation": true,
|
||||
"noImplicitAny": true
|
||||
},
|
||||
"files": [
|
||||
"./node_modules/@types/node/index.d.ts",
|
||||
"./node_modules/@types/ws/index.d.ts"
|
||||
],
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user