├── .npmignore
├── .gitignore
├── examples
└── echo.js
├── .babelrc
├── .eslintrc
├── webpack.config.js
├── src
├── index.js
└── browser.js
├── LICENSE
├── package.json
├── dist
├── certstream.min.js
├── certstream.js.map
├── certstream.js
└── certstream.min.js.map
└── README.md
/.npmignore:
--------------------------------------------------------------------------------
1 | src/
2 | test/
3 | .nyc_output/
4 | coverage/
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | npm-debug.log*
2 | node_modules
3 |
4 | # build artifacts
5 | **/lib/*
6 | **/.nyc_output/*
7 | **/coverage/*
8 |
9 | .idea/
--------------------------------------------------------------------------------
/examples/echo.js:
--------------------------------------------------------------------------------
1 | const CertStreamClient = require('../lib/index.js');
2 |
3 | let client = new CertStreamClient(function(message){
4 | console.log("Received -> ", message)
5 | });
6 |
7 | client.connect();
8 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015"],
3 | "plugins": ["transform-object-rest-spread", "add-module-exports"],
4 | "env": {
5 | "test": {
6 | "plugins": [
7 | "__coverage__",
8 | ]
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb",
3 | "rules": {
4 | "no-unused-expressions": 0,
5 | "space-infix-ops": 0,
6 | "default-case": 0,
7 | "no-else-return": 0,
8 | "brace-style": [2, "stroustrup"],
9 | "quote-props": [2, "consistent-as-needed"],
10 | "new-cap": 0,
11 | },
12 | "parserOptions": {
13 | "ecmaFeatures": {
14 | "experimentalObjectRestSpread": true,
15 | }
16 | },
17 | }
18 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const join = require('path').join;
2 |
3 | module.exports = {
4 | entry: './src/browser.js',
5 | output: {
6 | path: join(__dirname, 'dist'),
7 | libraryTarget: 'umd',
8 | library: 'CertStream',
9 | },
10 | devtool: 'source-map',
11 | module: {
12 | loaders: [
13 | {
14 | test: /.js$/,
15 | loader: 'babel-loader',
16 | exclude: /node_modules/,
17 | query: {
18 | presets: ['es2015'],
19 | },
20 | },
21 | ],
22 | },
23 | };
24 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | const WebSocket = require('ws');
2 |
3 | export default class CertStreamClient{
4 | constructor(callback, skipHeartbeats = false) {
5 | this.context = {};
6 | this.callback = callback;
7 | this.skipHeartbeats = skipHeartbeats;
8 | }
9 |
10 | connect(url="wss://certstream.calidog.io/"){
11 | console.log(`Connecting to ${url}...`);
12 | this.ws = new WebSocket(url);
13 |
14 | this.ws.on('open', () => {
15 | console.log("Connection established to certstream! Waiting for messages...");
16 | });
17 |
18 | this.ws.on('message', (message) => {
19 | let parsedMessage = JSON.parse(message);
20 |
21 | if (parsedMessage.message_type === "heartbeat" && this.skipHeartbeats) {
22 | return;
23 | }
24 |
25 | this.callback(parsedMessage, this.context);
26 | });
27 | }
28 | };
29 |
--------------------------------------------------------------------------------
/src/browser.js:
--------------------------------------------------------------------------------
1 | import ReconnectingWebsocket from "reconnectingwebsocket"
2 |
3 | export default class CertStreamClient{
4 | constructor(callback, skipHeartbeats = false) {
5 | this.context = {};
6 | this.callback = callback;
7 | this.skipHeartbeats = skipHeartbeats;
8 | }
9 |
10 | connect(url="wss://certstream.calidog.io/"){
11 | console.log(`Connecting to ${url}...`);
12 |
13 | this.ws = new ReconnectingWebsocket(url);
14 |
15 | console.log("Created ws -> ", this.ws);
16 |
17 | this.ws.onmessage = (message) => {
18 | console.log("onmessage called!");
19 | let parsedMessage = JSON.parse(message.data);
20 |
21 | if (parsedMessage.message_type === "heartbeat" && this.skipHeartbeats) {
22 | return
23 | }
24 |
25 | this.callback(message, this.context)
26 | };
27 |
28 | this.ws.onopen = () => {
29 | console.log("Connection established to certstream! Waiting for messages...");
30 | }
31 |
32 | this.ws.open();
33 | }
34 | };
35 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2017 fitblip (https://calidog.io)
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 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "certstream",
3 | "version": "1.1.1",
4 | "description": "certstream is a library for interacting with the CertStream network using JS.",
5 | "main": "./lib/index.js",
6 | "directories": {
7 | "test": "test"
8 | },
9 | "scripts": {
10 | "prebuild": "npm run clean",
11 | "build": "npm-run-all --parallel build:*",
12 | "build:lib": "babel src --out-dir lib",
13 | "build:umd": "webpack --output-filename certstream.js",
14 | "build:umd.min": "webpack -p --output-filename certstream.min.js",
15 | "prepublish": "in-install || npm run build",
16 | "semantic-release": "semantic-release pre && npm publish && semantic-release post",
17 | "clean": "npm-run-all --parallel clean:*",
18 | "clean:build": "rimraf dist lib",
19 | "clean:coverage": "rimraf .nyc_output coverage"
20 | },
21 | "repository": {
22 | "type": "git",
23 | "url": "https://github.com/CaliDog/certstream-js.git"
24 | },
25 | "keywords": [],
26 | "author": {
27 | "name": "fitblip",
28 | "email": "ryan@calidog.io",
29 | "website": "https://calidog.io"
30 | },
31 | "license": "MIT",
32 | "bugs": {
33 | "url": "https://github.com/CaliDog/certstream-js/issues"
34 | },
35 | "homepage": "https://github.com/CaliDog/certstream-js#readme",
36 | "devDependencies": {
37 | "babel-cli": "^6.9.0",
38 | "babel-core": "^6.9.0",
39 | "babel-loader": "^6.2.4",
40 | "babel-plugin-__coverage__": "^11.0.0",
41 | "babel-plugin-add-module-exports": "^0.2.1",
42 | "babel-plugin-transform-object-rest-spread": "^6.8.0",
43 | "babel-preset-es2015": "^6.9.0",
44 | "chai": "^3.5.0",
45 | "codecov": "^1.0.1",
46 | "commitizen": "^2.8.2",
47 | "cross-env": "^1.0.8",
48 | "cz-conventional-changelog": "^1.1.6",
49 | "eslint": "^2.12.0",
50 | "eslint-config-airbnb": "^9.0.1",
51 | "eslint-plugin-import": "^1.8.0",
52 | "eslint-plugin-jsx-a11y": "^1.2.2",
53 | "eslint-plugin-react": "^5.1.1",
54 | "ghooks": "^1.2.4",
55 | "mocha": "^3.0.0",
56 | "npm-run-all": "^2.1.2",
57 | "nyc": "^6.4.4",
58 | "rimraf": "^2.5.2",
59 | "semantic-release": "^4.3.5",
60 | "sinon": "^1.17.4",
61 | "sinon-chai": "^2.8.0",
62 | "webpack": "^1.13.1",
63 | "validate-commit-msg": "^2.6.1"
64 | },
65 | "dependencies": {
66 | "in-publish": "^2.0.0",
67 | "reconnectingwebsocket": "^1.0.0",
68 | "ws": "^3.2.0"
69 | },
70 | "nyc": {
71 | "instrument": false,
72 | "sourceMap": false
73 | },
74 | "browser": {
75 | "./index.js": "./browser.js"
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/dist/certstream.min.js:
--------------------------------------------------------------------------------
1 | !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.CertStream=t():e.CertStream=t()}(this,function(){return function(e){function t(o){if(n[o])return n[o].exports;var c=n[o]={exports:{},id:o,loaded:!1};return e[o].call(c.exports,c,c.exports,t),c.loaded=!0,c.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}function c(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(t,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n1&&void 0!==arguments[1]&&arguments[1];c(this,e),this.context={},this.callback=t,this.skipHeartbeats=n}return r(e,[{key:"connect",value:function(){var e=this;console.log("Connecting..."),this.ws=new s.default("wss://certstream.calidog.io/"),console.log("Created ws -> ",this.ws),this.ws.onmessage=function(t){console.log("onmessage called!");var n=JSON.parse(t.data);"heartbeat"===n.message_type&&e.skipHeartbeats||e.callback(t,e.context)},this.ws.onopen=function(){console.log("Connection established to certstream! Waiting for messages...")},this.ws.open()}}]),e}();t.default=a},function(e,t,n){var o,c,r;!function(n,i){c=[],o=i,r="function"==typeof o?o.apply(t,c):o,!(void 0!==r&&(e.exports=r))}(this,function(){function e(t,n,o){function c(e,t){var n=document.createEvent("CustomEvent");return n.initCustomEvent(e,!1,!1,t),n}var r={debug:!1,automaticOpen:!0,reconnectInterval:1e3,maxReconnectInterval:3e4,reconnectDecay:1.5,timeoutInterval:2e3,maxReconnectAttempts:null};o||(o={});for(var i in r)"undefined"!=typeof o[i]?this[i]=o[i]:this[i]=r[i];this.url=t,this.reconnectAttempts=0,this.readyState=WebSocket.CONNECTING,this.protocol=null;var s,a=this,u=!1,l=!1,d=document.createElement("div");d.addEventListener("open",function(e){a.onopen(e)}),d.addEventListener("close",function(e){a.onclose(e)}),d.addEventListener("connecting",function(e){a.onconnecting(e)}),d.addEventListener("message",function(e){a.onmessage(e)}),d.addEventListener("error",function(e){a.onerror(e)}),this.addEventListener=d.addEventListener.bind(d),this.removeEventListener=d.removeEventListener.bind(d),this.dispatchEvent=d.dispatchEvent.bind(d),this.open=function(t){if(s=new WebSocket(a.url,n||[]),t){if(this.maxReconnectAttempts&&this.reconnectAttempts>this.maxReconnectAttempts)return}else d.dispatchEvent(c("connecting")),this.reconnectAttempts=0;(a.debug||e.debugAll)&&console.debug("ReconnectingWebSocket","attempt-connect",a.url);var o=s,r=setTimeout(function(){(a.debug||e.debugAll)&&console.debug("ReconnectingWebSocket","connection-timeout",a.url),l=!0,o.close(),l=!1},a.timeoutInterval);s.onopen=function(n){clearTimeout(r),(a.debug||e.debugAll)&&console.debug("ReconnectingWebSocket","onopen",a.url),a.protocol=s.protocol,a.readyState=WebSocket.OPEN,a.reconnectAttempts=0;var o=c("open");o.isReconnect=t,t=!1,d.dispatchEvent(o)},s.onclose=function(n){if(clearTimeout(r),s=null,u)a.readyState=WebSocket.CLOSED,d.dispatchEvent(c("close"));else{a.readyState=WebSocket.CONNECTING;var o=c("connecting");o.code=n.code,o.reason=n.reason,o.wasClean=n.wasClean,d.dispatchEvent(o),t||l||((a.debug||e.debugAll)&&console.debug("ReconnectingWebSocket","onclose",a.url),d.dispatchEvent(c("close")));var r=a.reconnectInterval*Math.pow(a.reconnectDecay,a.reconnectAttempts);setTimeout(function(){a.reconnectAttempts++,a.open(!0)},r>a.maxReconnectInterval?a.maxReconnectInterval:r)}},s.onmessage=function(t){(a.debug||e.debugAll)&&console.debug("ReconnectingWebSocket","onmessage",a.url,t.data);var n=c("message");n.data=t.data,d.dispatchEvent(n)},s.onerror=function(t){(a.debug||e.debugAll)&&console.debug("ReconnectingWebSocket","onerror",a.url,t),d.dispatchEvent(c("error"))}},1==this.automaticOpen&&this.open(!1),this.send=function(t){if(s)return(a.debug||e.debugAll)&&console.debug("ReconnectingWebSocket","send",a.url,t),s.send(t);throw"INVALID_STATE_ERR : Pausing to reconnect websocket"},this.close=function(e,t){"undefined"==typeof e&&(e=1e3),u=!0,s&&s.close(e,t)},this.refresh=function(){s&&s.close()}}if("WebSocket"in window)return e.prototype.onopen=function(e){},e.prototype.onclose=function(e){},e.prototype.onconnecting=function(e){},e.prototype.onmessage=function(e){},e.prototype.onerror=function(e){},e.debugAll=!1,e.CONNECTING=WebSocket.CONNECTING,e.OPEN=WebSocket.OPEN,e.CLOSING=WebSocket.CLOSING,e.CLOSED=WebSocket.CLOSED,e})}])});
2 | //# sourceMappingURL=certstream.min.js.map
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
CertStream-JS
4 | See SSL certs as they're issued live.
5 |
6 |
7 | This is a library for interacting with the [certstream network](https://certstream.calidog.io/) to monitor an aggregated feed from a collection of [Certificate Transparency Logs](https://www.certificate-transparency.org/known-logs).
8 |
9 | It is built to be compatible with both node.js and a standard browser with UMD.
10 |
11 | # Installing
12 |
13 | ```
14 | npm install --save certstream
15 | ```
16 |
17 | Or if you're using this in the browser, just add `dist/certstream.min.js` to a `