Skip to content

Commit 7755339

Browse files
authored
Merge pull request #165 from readmeio/feat/plugin-architecture
Adding the ability to import custom targets and target clients
2 parents 13dd4fd + b7818e6 commit 7755339

File tree

4 files changed

+168
-7
lines changed

4 files changed

+168
-7
lines changed

README.md

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ snippets/
6969

7070
#### source
7171

72-
*Required*
72+
*Required*
7373
Type: `object`
7474

7575
Name of [conversion target](https://github.com/Mashape/httpsnippet/wiki/Targets)
@@ -87,7 +87,7 @@ var snippet = new HTTPSnippet({
8787

8888
#### target
8989

90-
*Required*
90+
*Required*
9191
Type: `string`
9292

9393
Name of [conversion target](https://github.com/Mashape/httpsnippet/wiki/Targets)
@@ -119,7 +119,7 @@ console.log(snippet.convert('node', {
119119

120120
#### target
121121

122-
*Required*
122+
*Required*
123123
Type: `string`
124124

125125
Name of [conversion target](https://github.com/Mashape/httpsnippet/wiki/Targets)
@@ -153,6 +153,39 @@ console.log(snippet.convert('shell', 'curl', {
153153
console.log(snippet.convert('node', 'unirest'));
154154
```
155155

156+
### addTarget(target)
157+
#### target
158+
159+
*Required*
160+
Type: `object`
161+
162+
Representation of a [conversion target](https://github.com/Kong/httpsnippet/wiki/Creating-Targets). Can use this to use targets that are not officially supported.
163+
164+
```js
165+
const customLanguageTarget = require('httpsnippet-for-my-lang');
166+
HTTPSnippet.addTarget(customLanguageTarget);
167+
```
168+
169+
### addTargetClient(target, client)
170+
### target
171+
172+
*Required*
173+
Type: `string`
174+
175+
Name of [conversion target](https://github.com/Mashape/httpsnippet/wiki/Targets)
176+
177+
### client
178+
179+
*Required*
180+
Type: `object`
181+
182+
Representation of a [conversion target client](https://github.com/Kong/httpsnippet/wiki/Creating-Targets). Can use this to use target clients that are not officially supported.
183+
184+
```js
185+
const customClient = require('httpsnippet-for-my-node-http-client');
186+
HTTPSnippet.addTargetClient('node', customClient);
187+
```
188+
156189
## Documentation
157190

158191
At the heart of this module is the [HAR Format](http://www.softwareishard.com/blog/har-12-spec/#request) as the HTTP request description format, please review some of the sample JSON HAR Request objects in [test fixtures](/test/fixtures/requests), or read the [HAR Docs](http://www.softwareishard.com/blog/har-12-spec/#request) for more details.

src/index.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,32 @@ HTTPSnippet.prototype._matchTarget = function (target, client) {
221221
// exports
222222
module.exports = HTTPSnippet
223223

224+
module.exports.addTarget = function (target) {
225+
if (!('info' in target)) {
226+
throw new Error('The supplied custom target must contain an `info` object.')
227+
} else if (!('key' in target.info) || !('title' in target.info) || !('extname' in target.info) || !('default' in target.info)) {
228+
throw new Error('The supplied custom target must have an `info` object with a `key`, `title`, `extname`, and `default` property.')
229+
} else if (targets.hasOwnProperty(target.info.key)) {
230+
throw new Error('The supplied custom target already exists.')
231+
} else if (Object.keys(target).length === 1) {
232+
throw new Error('A custom target must have a client defined on it.')
233+
}
234+
235+
targets[target.info.key] = target
236+
}
237+
238+
module.exports.addTargetClient = function (target, client) {
239+
if (!targets.hasOwnProperty(target)) {
240+
throw new Error(`Sorry, but no ${target} target exists to add clients to.`)
241+
} else if (!('info' in client)) {
242+
throw new Error('The supplied custom target client must contain an `info` object.')
243+
} else if (!('key' in client.info) || !('title' in client.info)) {
244+
throw new Error('The supplied custom target client must have an `info` object with a `key` and `title` property.')
245+
}
246+
247+
targets[target][client.info.key] = client
248+
}
249+
224250
module.exports.availableTargets = function () {
225251
return Object.keys(targets).map(function (key) {
226252
var target = Object.assign({}, targets[key].info)

test/fixtures/customTarget.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
'use strict'
2+
3+
module.exports = {
4+
info: {
5+
key: 'js-variant',
6+
title: 'JavaScript Variant',
7+
extname: '.js',
8+
default: 'request'
9+
},
10+
11+
request: require('../../src/targets/node/request')
12+
}

test/targets.js

Lines changed: 94 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* global describe, it */
1+
/* global describe, it, beforeEach */
22

33
'use strict'
44

@@ -85,15 +85,105 @@ var itShouldGenerateOutput = function (request, path, target, client) {
8585
}
8686

8787
describe('Available Targets', function () {
88-
var targets = HTTPSnippet.availableTargets()
89-
90-
targets.forEach(function (target) {
88+
HTTPSnippet.availableTargets().forEach(function (target) {
9189
it('available-targets.json should include ' + target.title, function () {
9290
fixtures['available-targets'].should.containEql(target)
9391
})
9492
})
9593
})
9694

95+
describe('Custom targets', function () {
96+
describe('Adding a custom target', function () {
97+
it('should throw if the target does has no info object', function () {
98+
(function () {
99+
HTTPSnippet.addTarget({})
100+
}).should.throw(Error)
101+
})
102+
103+
it('should throw if the target does not have a properly constructed info object', function () {
104+
(function () {
105+
HTTPSnippet.addTarget({info: {key: ''}})
106+
}).should.throw(Error)
107+
})
108+
109+
it('should throw if the target already exists', function () {
110+
(function () {
111+
HTTPSnippet.addTarget(targets.node)
112+
}).should.throw(Error)
113+
})
114+
115+
it('should throw if the target has no client', function () {
116+
(function () {
117+
HTTPSnippet.addTarget({
118+
info: targets.node.info
119+
})
120+
}).should.throw(Error)
121+
})
122+
123+
it('should add and convert for a new custom target', function () {
124+
const customTarget = require('./fixtures/customTarget')
125+
126+
HTTPSnippet.addTarget(customTarget)
127+
const target = HTTPSnippet.availableTargets().find(function (target) { return target.key === customTarget.info.key })
128+
const client = target.clients.find(function (client) { return client.key === customTarget.info.default })
129+
client.should.be.an.Object()
130+
131+
Object.keys(fixtures.requests).filter(clearInfo).forEach(function (request) {
132+
// Re-using the `request` module fixtures and framework since we copied it to create a custom client.
133+
itShouldGenerateOutput(request, 'node/request/', customTarget.info.key, customTarget.info.default)
134+
})
135+
})
136+
})
137+
138+
describe('Adding a custom client target', function () {
139+
let customClient
140+
141+
beforeEach(function () {
142+
// Re-using the existing request client instead of mocking out something completely new.
143+
customClient = {
144+
...targets.node.request,
145+
info: {
146+
key: 'axios',
147+
title: 'Axios',
148+
link: 'https://www.npmjs.com/package/axios',
149+
description: 'Promise based HTTP client for the browser and node.js'
150+
}
151+
}
152+
})
153+
154+
it("should throw if the client's target does not exist", function () {
155+
(function () {
156+
HTTPSnippet.addTargetClient('node.js', customClient)
157+
}).should.throw(Error)
158+
})
159+
160+
it('should throw if the client does has no info object', function () {
161+
(function () {
162+
HTTPSnippet.addTargetClient('node', {})
163+
}).should.throw(Error)
164+
})
165+
166+
it('should throw if the target does not have a properly constructed info object', function () {
167+
(function () {
168+
HTTPSnippet.addTargetClient('node', {info: {key: ''}})
169+
}).should.throw(Error)
170+
})
171+
172+
it('should add and convert for a new custom client target', function () {
173+
HTTPSnippet.addTargetClient('node', customClient)
174+
175+
const target = HTTPSnippet.availableTargets().find(function (target) { return target.key === 'node' })
176+
const client = target.clients.find(function (client) { return client.key === customClient.info.key })
177+
client.should.be.an.Object()
178+
179+
Object.keys(fixtures.requests).filter(clearInfo).forEach(function (request) {
180+
// Re-using the `request` module fixtures and framework since we copied it to create a custom client target.
181+
itShouldGenerateOutput(request, 'node/request/', 'node', customClient.info.key)
182+
})
183+
})
184+
})
185+
})
186+
97187
// test all the things!
98188
describe('Targets', function () {
99189
Object.keys(targets).forEach(function (target) {

0 commit comments

Comments
 (0)