git.iko.soy/typeable/servant
on master help sign in
Make Javascript tutorial compile.
7aa550aJulian K. Arni
doc/tutorial/Javascript.lhs+98−79
@@ -154,33 +154,33 @@ javascript with just a simple function call to `jsForAPI` from
154`Servant.JS`.
154`Servant.JS`.
155
155
156``` haskell
156``` haskell
157−apiJS :: Text
157+apiJS1 :: Text
158−apiJS = jsForAPI api jquery
158+apiJS1 = jsForAPI api jquery
159```
159```
160
160
161This `Text` contains 2 Javascript functions, 'getPoint' and 'getBooks':
161This `Text` contains 2 Javascript functions, 'getPoint' and 'getBooks':
162
162
163``` javascript
163``` javascript
164−var getPoint = function (onSuccess, onError)
165− {
166− $.ajax(
167− { url: '/point'
168− , success: onSuccess
169− , error: onError
170− , method: 'GET'
171− });
172−};
173
164
165+var getPoint = function(onSuccess, onError)
166+{
167+ $.ajax(
168+ { url: '/point'
169+ , success: onSuccess
170+ , error: onError
171+ , type: 'GET'
172+ });
173+}
174
174
175−var getBooks = function (q, onSuccess, onError)
175+var getBooks = function(q, onSuccess, onError)
176− {
176+{
177− $.ajax(
177+ $.ajax(
178− { url: '/books' + '?q=' + encodeURIComponent(q)
178+ { url: '/books' + '?q=' + encodeURIComponent(q)
179− , success: onSuccess
179+ , success: onSuccess
180− , error: onError
180+ , error: onError
181− , method: 'GET'
181+ , type: 'GET'
182− });
182+ });
183−};
183+}
184```
184```
185
185
186We created a directory `static` that contains two static files: `index.html`,
186We created a directory `static` that contains two static files: `index.html`,
@@ -192,7 +192,7 @@ write the generated javascript into a file:
192``` haskell
192``` haskell
193writeJSFiles :: IO ()
193writeJSFiles :: IO ()
194writeJSFiles = do
194writeJSFiles = do
195− T.writeFile "static/api.js" apiJS
195+ T.writeFile "static/api.js" apiJS1
196 jq <- T.readFile =<< Language.Javascript.JQuery.file
196 jq <- T.readFile =<< Language.Javascript.JQuery.file
197 T.writeFile "static/jq.js" jq
197 T.writeFile "static/jq.js" jq
198```
198```
@@ -220,7 +220,7 @@ The `CommonGeneratorOptions` will let you define different behaviors to
220change how functions are generated. Here is the definition of currently
220change how functions are generated. Here is the definition of currently
221available options:
221available options:
222
222
223−```haskell
223+```haskell ignore
224data CommonGeneratorOptions = CommonGeneratorOptions
224data CommonGeneratorOptions = CommonGeneratorOptions
225 {
225 {
226 -- | function generating function names
226 -- | function generating function names
@@ -249,8 +249,8 @@ Use the same code as before but simply replace the previous `apiJS` with
249the following one:
249the following one:
250
250
251``` haskell
251``` haskell
252−apiJS :: String
252+apiJS2 :: Text
253−apiJS = jsForAPI api vanillaJS
253+apiJS2 = jsForAPI api vanillaJS
254```
254```
255
255
256The rest is *completely* unchanged.
256The rest is *completely* unchanged.
@@ -259,41 +259,50 @@ The output file is a bit different, but it has the same parameters,
259
259
260``` javascript
260``` javascript
261
261
262−var getPoint = function (onSuccess, onError)
263−{
264− var xhr = new XMLHttpRequest();
265− xhr.open('GET', '/point', true);
266
262
263+var getPoint = function(onSuccess, onError)
264+{
265+ var xhr = new XMLHttpRequest();
266+ xhr.open('GET', '/point', true);
267+ xhr.setRequestHeader(\"Accept\",\"application/json\");
267− xhr.onreadystatechange = function (e) {
268+ xhr.onreadystatechange = function (e) {
268 if (xhr.readyState == 4) {
269 if (xhr.readyState == 4) {
270+ if (xhr.status == 204 || xhr.status == 205) {
271+ onSuccess();
272+ } else if (xhr.status >= 200 && xhr.status < 300) {
273+ var value = JSON.parse(xhr.responseText);
274+ onSuccess(value);
275+ } else {
269 var value = JSON.parse(xhr.responseText);
276 var value = JSON.parse(xhr.responseText);
270− if (xhr.status == 200 || xhr.status == 201) {
271− onSuccess(value);
272− } else {
273− onError(value);
277+ onError(value);
274− }
275− }
278+ }
276 }
279 }
280+ }
277− xhr.send(null);
281+ xhr.send(null);
278−};
282+}
279
283
280−var getBooks = function (q, onSuccess, onError)
284+var getBooks = function(q, onSuccess, onError)
281{
285{
282− var xhr = new XMLHttpRequest();
286+ var xhr = new XMLHttpRequest();
283− xhr.open('GET', '/books' + '?q=' + encodeURIComponent(q), true);
287+ xhr.open('GET', '/books' + '?q=' + encodeURIComponent(q), true);
284−
288+ xhr.setRequestHeader(\"Accept\",\"application/json\");
285− xhr.onreadystatechange = function (e) {
289+ xhr.onreadystatechange = function (e) {
286 if (xhr.readyState == 4) {
290 if (xhr.readyState == 4) {
291+ if (xhr.status == 204 || xhr.status == 205) {
292+ onSuccess();
293+ } else if (xhr.status >= 200 && xhr.status < 300) {
287 var value = JSON.parse(xhr.responseText);
294 var value = JSON.parse(xhr.responseText);
288− if (xhr.status == 200 || xhr.status == 201) {
289− onSuccess(value);
295+ onSuccess(value);
290− } else {
296+ } else {
297+ var value = JSON.parse(xhr.responseText);
291− onError(value);
298+ onError(value);
292− }
293− }
299+ }
294 }
300 }
301+ }
295− xhr.send(null);
302+ xhr.send(null);
296−};
303+}
304+
305+
297```
306```
298
307
299And that's all, your web service can of course be accessible from those
308And that's all, your web service can of course be accessible from those
@@ -309,8 +318,8 @@ Use the same code as before but simply replace the previous `apiJS` with
309the following one:
318the following one:
310
319
311``` haskell
320``` haskell
312−apiJS :: String
321+apiJS3 :: Text
313−apiJS = jsForAPI api $ axios defAxiosOptions
322+apiJS3 = jsForAPI api $ axios defAxiosOptions
314```
323```
315
324
316The rest is *completely* unchanged.
325The rest is *completely* unchanged.
@@ -319,19 +328,23 @@ The output file is a bit different,
319
328
320``` javascript
329``` javascript
321
330
331+
322−var getPoint = function ()
332+var getPoint = function()
323{
333{
324− return axios({ url: '/point'
334+ return axios({ url: '/point'
325− , method: 'get'
335+ , method: 'get'
326− });
336+ });
327−};
337+}
338+
328
339
340+
329−var getBooks = function (q)
341+var getBooks = function(q)
330{
342{
331− return axios({ url: '/books' + '?q=' + encodeURIComponent(q)
343+ return axios({ url: '/books' + '?q=' + encodeURIComponent(q)
332− , method: 'get'
344+ , method: 'get'
333− });
345+ });
334−};
346+}
347+
335```
348```
336
349
337**Caution:** In order to support the promise style of the API, there are no onSuccess
350**Caution:** In order to support the promise style of the API, there are no onSuccess
@@ -366,8 +379,8 @@ generate top level functions.
366The difference is that `angular` Generator always takes an argument.
379The difference is that `angular` Generator always takes an argument.
367
380
368``` haskell
381``` haskell
369−apiJS :: String
382+apiJS4 :: Text
370−apiJS = jsForAPI api $ angular defAngularOptions
383+apiJS4 = jsForAPI api $ angular defAngularOptions
371```
384```
372
385
373The generated code will be a bit different than previous generators. An extra
386The generated code will be a bit different than previous generators. An extra
@@ -379,21 +392,25 @@ nor onError callback functions.
379
392
380``` javascript
393``` javascript
381
394
395+
382var getPoint = function($http)
396var getPoint = function($http)
383{
397{
384 return $http(
398 return $http(
385− { url: '/counter'
399+ { url: '/point'
386− , method: 'GET'
400+ , method: 'GET'
387− });
401+ });
388}
402}
389
403
404+
405+
390var getBooks = function($http, q)
406var getBooks = function($http, q)
391{
407{
392 return $http(
408 return $http(
393− { url: '/books' + '?q=' + encodeURIComponent(q), true);
409+ { url: '/books' + '?q=' + encodeURIComponent(q)
394 , method: 'GET'
410 , method: 'GET'
395 });
411 });
396}
412}
413+
397```
414```
398
415
399You can then build your controllers easily
416You can then build your controllers easily
@@ -440,8 +457,8 @@ app.service('MyService', function($http) {
440To do so, you just have to use an alternate generator.
457To do so, you just have to use an alternate generator.
441
458
442``` haskell
459``` haskell
443−apiJS :: String
460+apiJS5 :: Text
444−apiJS = jsForAPI api $ angularService defAngularOptions
461+apiJS5 = jsForAPI api $ angularService defAngularOptions
445```
462```
446
463
447Again, it is possible to customize some portions with the options.
464Again, it is possible to customize some portions with the options.
@@ -468,32 +485,34 @@ Servant comes with three name builders included:
468Keeping the JQuery as an example, let's see the impact:
485Keeping the JQuery as an example, let's see the impact:
469
486
470``` haskell
487``` haskell
471−apiJS :: String
488+apiJS6 :: Text
472−apiJS = jsForAPI api $ jqueryWith defCommonGeneratorOptions { functionNameBuilder= snakeCase }
489+apiJS6 = jsForAPI api $ jqueryWith defCommonGeneratorOptions { functionNameBuilder= snakeCase }
473```
490```
474
491
475−This `String` contains 2 Javascript functions:
492+This `Text` contains 2 Javascript functions:
476
493
477``` javascript
494``` javascript
478
495
496+
479−var getPoint = function (onSuccess, onError)
497+var get_point = function(onSuccess, onError)
480{
498{
481 $.ajax(
499 $.ajax(
482 { url: '/point'
500 { url: '/point'
483 , success: onSuccess
501 , success: onSuccess
484 , error: onError
502 , error: onError
485− , method: 'GET'
503+ , type: 'GET'
486 });
504 });
487−};
505+}
488
506
489−var getBooks = function (q, onSuccess, onError)
507+var get_books = function(q, onSuccess, onError)
490{
508{
491 $.ajax(
509 $.ajax(
492 { url: '/books' + '?q=' + encodeURIComponent(q)
510 { url: '/books' + '?q=' + encodeURIComponent(q)
493 , success: onSuccess
511 , success: onSuccess
494 , error: onError
512 , error: onError
495− , method: 'GET'
513+ , type: 'GET'
496 });
514 });
497−};
515+}
516+
498```
517```
499
518
doc/tutorial/test/JavascriptSpec.hs+5−2
@@ -15,7 +15,10 @@ spec = do
15 describe "apiJS" $ do
15 describe "apiJS" $ do
16 it "is contained verbatim in Javascript.lhs" $ do
16 it "is contained verbatim in Javascript.lhs" $ do
17 code <- readFile "Javascript.lhs"
17 code <- readFile "Javascript.lhs"
18+ cs apiJS1 `shouldSatisfy` (`isInfixOf` code)
19+ cs apiJS3 `shouldSatisfy` (`isInfixOf` code)
20+ cs apiJS4 `shouldSatisfy` (`isInfixOf` code)
18− cs apiJS `shouldSatisfy` (`isInfixOf` code)
21+ cs apiJS6 `shouldSatisfy` (`isInfixOf` code)
19
22
20 describe "writeJSFiles" $ do
23 describe "writeJSFiles" $ do
21 it "[not a test] write apiJS to static/api.js" $ do
24 it "[not a test] write apiJS to static/api.js" $ do
@@ -24,7 +27,7 @@ spec = do
24 describe "app" $ with (return app) $ do
27 describe "app" $ with (return app) $ do
25 context "/api.js" $ do
28 context "/api.js" $ do
26 it "delivers apiJS" $ do
29 it "delivers apiJS" $ do
27− get "/api.js" `shouldRespondWith` (fromString (cs apiJS))
30+ get "/api.js" `shouldRespondWith` (fromString (cs apiJS1))
28
31
29 context "/" $ do
32 context "/" $ do
30 it "delivers something" $ do
33 it "delivers something" $ do
servant-js/src/Servant/JS.hs+1
@@ -112,6 +112,7 @@ module Servant.JS
112 , javascript
112 , javascript
113 , NoTypes
113 , NoTypes
114 , GenerateList(..)
114 , GenerateList(..)
115+ , FunctionName(..)
115 ) where
116 ) where
116
117
117import Prelude hiding (writeFile)
118import Prelude hiding (writeFile)