Skip to content

Commit 6cb8486

Browse files
authored
Merge pull request #82 from tggreene/add-clojure-generator
Add clojure generator
2 parents 016bdba + 63c6345 commit 6cb8486

File tree

19 files changed

+239
-0
lines changed

19 files changed

+239
-0
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"bin": "bin/httpsnippet",
1010
"keywords": [
1111
"api",
12+
"clojure",
1213
"csharp",
1314
"curl",
1415
"go",

src/targets/clojure/clj_http.js

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/**
2+
* @description
3+
* HTTP code snippet generator for Clojure using clj-http.
4+
*
5+
* @author
6+
* @tggreene
7+
*
8+
* for any questions or issues regarding the generated code snippet, please open an issue mentioning the author.
9+
*/
10+
11+
'use strict'
12+
13+
var CodeBuilder = require('../../helpers/code-builder')
14+
15+
var Keyword = function (name) {
16+
this.name = name
17+
}
18+
19+
Keyword.prototype.toString = function () {
20+
return ':' + this.name
21+
}
22+
23+
var File = function (path) {
24+
this.path = path
25+
}
26+
27+
File.prototype.toString = function () {
28+
return '(clojure.java.io/file "' + this.path + '")'
29+
}
30+
31+
var jsType = function (x) {
32+
return (typeof x !== 'undefined')
33+
? x.constructor.name.toLowerCase()
34+
: null
35+
}
36+
37+
var objEmpty = function (x) {
38+
return (jsType(x) === 'object')
39+
? Object.keys(x).length === 0
40+
: false
41+
}
42+
43+
var filterEmpty = function (m) {
44+
Object.keys(m)
45+
.filter(function (x) { return objEmpty(m[x]) })
46+
.forEach(function (x) { delete m[x] })
47+
return m
48+
}
49+
50+
var padBlock = function (x, s) {
51+
var padding = Array.apply(null, Array(x))
52+
.map(function (_) {
53+
return ' '
54+
})
55+
.join('')
56+
return s.replace(/\n/g, '\n' + padding)
57+
}
58+
59+
var jsToEdn = function (js) {
60+
switch (jsType(js)) {
61+
default: // 'number' 'boolean'
62+
return js.toString()
63+
case 'string':
64+
return '"' + js.replace(/\"/g, '\\"') + '"'
65+
case 'file':
66+
return js.toString()
67+
case 'keyword':
68+
return js.toString()
69+
case 'null':
70+
return 'nil'
71+
case 'regexp':
72+
return '#"' + js.source + '"'
73+
case 'object': // simple vertical format
74+
var obj = Object.keys(js)
75+
.reduce(function (acc, key) {
76+
var val = padBlock(key.length + 2, jsToEdn(js[key]))
77+
return acc + ':' + key + ' ' + val + '\n '
78+
}, '')
79+
.trim()
80+
return '{' + padBlock(1, obj) + '}'
81+
case 'array': // simple horizontal format
82+
var arr = js.reduce(function (acc, val) {
83+
return acc + ' ' + jsToEdn(val)
84+
}, '').trim()
85+
return '[' + padBlock(1, arr) + ']'
86+
}
87+
}
88+
89+
module.exports = function (source, options) {
90+
var code = new CodeBuilder(options)
91+
var methods = ['get', 'post', 'put', 'delete', 'patch', 'head', 'options']
92+
93+
if (methods.indexOf(source.method.toLowerCase()) === -1) {
94+
return code.push('Method not supported').join()
95+
}
96+
97+
var params = {headers: source.allHeaders,
98+
'query-params': source.queryObj}
99+
100+
switch (source.postData.mimeType) {
101+
case 'application/json':
102+
params['content-type'] = new Keyword('json')
103+
params['form-params'] = source.postData.jsonObj
104+
delete params.headers['content-type']
105+
break
106+
case 'application/x-www-form-urlencoded':
107+
params['form-params'] = source.postData.paramsObj
108+
delete params.headers['content-type']
109+
break
110+
case 'text/plain':
111+
params.body = source.postData.text
112+
delete params.headers['content-type']
113+
break
114+
case 'multipart/form-data':
115+
params.multipart = source.postData.params.map(function (x) {
116+
if (x.fileName && !x.value) {
117+
return {name: x.name,
118+
content: new File(x.fileName)}
119+
} else {
120+
return {name: x.name,
121+
content: x.value}
122+
}
123+
})
124+
delete params.headers['content-type']
125+
break
126+
}
127+
128+
switch (params.headers.accept) {
129+
case 'application/json':
130+
params.accept = new Keyword('json')
131+
delete params.headers.accept
132+
break
133+
}
134+
135+
code.push('(require \'[clj-http.client :as client])\n')
136+
137+
if (objEmpty(filterEmpty(params))) {
138+
code.push('(client/%s "%s")', source.method.toLowerCase(), source.url)
139+
} else {
140+
code.push('(client/%s "%s" %s)', source.method.toLowerCase(), source.url, padBlock(11 + source.method.length + source.url.length, jsToEdn(filterEmpty(params))))
141+
}
142+
143+
return code.join()
144+
}
145+
146+
module.exports.info = {
147+
key: 'clj_http',
148+
title: 'clj-http',
149+
link: 'https://github.com/dakrone/clj-http',
150+
description: 'An idiomatic clojure http client wrapping the apache client.'
151+
}

src/targets/clojure/index.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: 'clojure',
6+
title: 'Clojure',
7+
extname: '.clj',
8+
default: 'clj_http'
9+
},
10+
11+
clj_http: require('./clj_http')
12+
}

src/targets/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
module.exports = {
44
c: require('./c'),
5+
clojure: require('./clojure'),
56
csharp: require('./csharp'),
67
go: require('./go'),
78
java: require('./java'),

test/fixtures/available-targets.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,20 @@
221221
}
222222
]
223223
},
224+
{
225+
"key": "clojure",
226+
"title": "Clojure",
227+
"extname": ".clj",
228+
"default": "clj_http",
229+
"clients": [
230+
{
231+
"key": "clj_http",
232+
"title": "clj-http",
233+
"link": "https://github.com/dakrone/clj-http",
234+
"description": "An idiomatic clojure http client wrapping the apache client."
235+
}
236+
]
237+
},
224238
{
225239
"key": "c",
226240
"title": "C",
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
(require '[clj-http.client :as client])
2+
3+
(client/post "http://mockbin.com/har" {:form-params {:foo "bar"
4+
:hello "world"}})
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
(require '[clj-http.client :as client])
2+
3+
(client/post "http://mockbin.com/har" {:content-type :json
4+
:form-params {:number 1
5+
:string "f\"oo"
6+
:arr [1 2 3]
7+
:nested {:a "b"}
8+
:arr_mix [1 "a" {:arr_mix_nested {}}]
9+
:boolean false}})
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
(require '[clj-http.client :as client])
2+
3+
(client/post "http://mockbin.com/har" {:headers {:cookie "foo=bar; bar=baz"}})
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Method not supported
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
(require '[clj-http.client :as client])
2+
3+
(client/post "http://mockbin.com/har" {:headers {:cookie "foo=bar; bar=baz"}
4+
:query-params {:foo ["bar" "baz"]
5+
:baz "abc"
6+
:key "value"}
7+
:form-params {:foo "bar"}
8+
:accept :json})

0 commit comments

Comments
 (0)