Skip to content

Commit 8808cb8

Browse files
authored
Merge pull request #84 from github/repo-sync
repo sync
2 parents d7fec7f + 239643b commit 8808cb8

File tree

2 files changed

+109
-0
lines changed

2 files changed

+109
-0
lines changed

lib/hydro.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
const crypto = require('crypto')
2+
const fetch = require('node-fetch')
3+
4+
module.exports = class Hydro {
5+
constructor ({ secret, endpoint }) {
6+
this.secret = secret || process.env.HYDRO_SECRET
7+
this.endpoint = endpoint || process.env.HYDRO_ENDPOINT
8+
}
9+
10+
/**
11+
* Generate a SHA256 hash of the payload using the secret
12+
* to authenticate with Hydro
13+
* @param {string} body
14+
*/
15+
generatePayloadHmac (body) {
16+
return crypto.createHmac('sha256', this.secret)
17+
.update(body)
18+
.digest('hex')
19+
}
20+
21+
/**
22+
* Publish a single event to Hydro
23+
* @param {string} schema
24+
* @param {any} value
25+
*/
26+
async publish (schema, value) {
27+
return this.publishMany([{ schema, value }])
28+
}
29+
30+
/**
31+
* Publish multiple events to Hydro
32+
* @param {[{ schema: string, value: any }]} events
33+
*/
34+
async publishMany (events) {
35+
const body = JSON.stringify({ events })
36+
const token = this.generatePayloadHmac(body)
37+
38+
return fetch(this.endpoint, {
39+
method: 'POST',
40+
body,
41+
headers: {
42+
Authorization: `Hydro ${token}`,
43+
'Content-Type': 'application/json',
44+
'X-Hydro-App': 'docs'
45+
}
46+
})
47+
}
48+
}

tests/unit/hydro.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
const nock = require('nock')
2+
const Hydro = require('../../lib/hydro')
3+
4+
describe('hydro', () => {
5+
let hydro, params
6+
7+
beforeEach(() => {
8+
hydro = new Hydro({ secret: '123', endpoint: 'https://real-hydro.com' })
9+
10+
nock(hydro.endpoint, {
11+
reqheaders: {
12+
Authorization: /^Hydro [\d\w]{64}$/,
13+
'Content-Type': 'application/json',
14+
'X-Hydro-App': 'docs'
15+
}
16+
})
17+
// Respond with a 201 and store the body we sent
18+
.post('/').reply(201, (_, body) => { params = body })
19+
})
20+
21+
describe('#publish', () => {
22+
it('publishes a single event to Hydro', async () => {
23+
await hydro.publish('event-name', { pizza: true })
24+
expect(params).toEqual({
25+
events: [{ schema: 'event-name', value: { pizza: true } }]
26+
})
27+
})
28+
})
29+
30+
describe('#publishMany', () => {
31+
it('publishes multiple events to Hydro', async () => {
32+
await hydro.publishMany([
33+
{ schema: 'event-name', value: { pizza: true } },
34+
{ schema: 'other-name', value: { salad: false } }
35+
])
36+
37+
expect(params).toEqual({
38+
events: [
39+
{ schema: 'event-name', value: { pizza: true } },
40+
{ schema: 'other-name', value: { salad: false } }
41+
]
42+
})
43+
})
44+
})
45+
46+
describe('#generatePayloadHmac', () => {
47+
it('returns a SHA256 HMAC string', () => {
48+
const body = JSON.stringify({ pizza: true })
49+
const hash = hydro.generatePayloadHmac(body)
50+
expect(hash).toEqual(expect.any(String))
51+
expect(hash).toHaveLength(64)
52+
})
53+
54+
it('generates the same string for the same payload', () => {
55+
const body = JSON.stringify({ pizza: true })
56+
const one = hydro.generatePayloadHmac(body)
57+
const two = hydro.generatePayloadHmac(body)
58+
expect(one).toBe(two)
59+
})
60+
})
61+
})

0 commit comments

Comments
 (0)