Make Javascript tutorial compile.
This commit is contained in:
parent
9e71fde756
commit
7aa550aa05
3 changed files with 105 additions and 82 deletions
|
@ -154,33 +154,33 @@ javascript with just a simple function call to `jsForAPI` from
|
||||||
`Servant.JS`.
|
`Servant.JS`.
|
||||||
|
|
||||||
``` haskell
|
``` haskell
|
||||||
apiJS :: Text
|
apiJS1 :: Text
|
||||||
apiJS = jsForAPI api jquery
|
apiJS1 = jsForAPI api jquery
|
||||||
```
|
```
|
||||||
|
|
||||||
This `Text` contains 2 Javascript functions, 'getPoint' and 'getBooks':
|
This `Text` contains 2 Javascript functions, 'getPoint' and 'getBooks':
|
||||||
|
|
||||||
``` javascript
|
``` javascript
|
||||||
var getPoint = function (onSuccess, onError)
|
|
||||||
{
|
|
||||||
$.ajax(
|
|
||||||
{ url: '/point'
|
|
||||||
, success: onSuccess
|
|
||||||
, error: onError
|
|
||||||
, method: 'GET'
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
var getPoint = function(onSuccess, onError)
|
||||||
|
{
|
||||||
|
$.ajax(
|
||||||
|
{ url: '/point'
|
||||||
|
, success: onSuccess
|
||||||
|
, error: onError
|
||||||
|
, type: 'GET'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
var getBooks = function (q, onSuccess, onError)
|
var getBooks = function(q, onSuccess, onError)
|
||||||
{
|
{
|
||||||
$.ajax(
|
$.ajax(
|
||||||
{ url: '/books' + '?q=' + encodeURIComponent(q)
|
{ url: '/books' + '?q=' + encodeURIComponent(q)
|
||||||
, success: onSuccess
|
, success: onSuccess
|
||||||
, error: onError
|
, error: onError
|
||||||
, method: 'GET'
|
, type: 'GET'
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
We created a directory `static` that contains two static files: `index.html`,
|
We created a directory `static` that contains two static files: `index.html`,
|
||||||
|
@ -192,7 +192,7 @@ write the generated javascript into a file:
|
||||||
``` haskell
|
``` haskell
|
||||||
writeJSFiles :: IO ()
|
writeJSFiles :: IO ()
|
||||||
writeJSFiles = do
|
writeJSFiles = do
|
||||||
T.writeFile "static/api.js" apiJS
|
T.writeFile "static/api.js" apiJS1
|
||||||
jq <- T.readFile =<< Language.Javascript.JQuery.file
|
jq <- T.readFile =<< Language.Javascript.JQuery.file
|
||||||
T.writeFile "static/jq.js" jq
|
T.writeFile "static/jq.js" jq
|
||||||
```
|
```
|
||||||
|
@ -220,7 +220,7 @@ The `CommonGeneratorOptions` will let you define different behaviors to
|
||||||
change how functions are generated. Here is the definition of currently
|
change how functions are generated. Here is the definition of currently
|
||||||
available options:
|
available options:
|
||||||
|
|
||||||
```haskell
|
```haskell ignore
|
||||||
data CommonGeneratorOptions = CommonGeneratorOptions
|
data CommonGeneratorOptions = CommonGeneratorOptions
|
||||||
{
|
{
|
||||||
-- | function generating function names
|
-- | function generating function names
|
||||||
|
@ -249,8 +249,8 @@ Use the same code as before but simply replace the previous `apiJS` with
|
||||||
the following one:
|
the following one:
|
||||||
|
|
||||||
``` haskell
|
``` haskell
|
||||||
apiJS :: String
|
apiJS2 :: Text
|
||||||
apiJS = jsForAPI api vanillaJS
|
apiJS2 = jsForAPI api vanillaJS
|
||||||
```
|
```
|
||||||
|
|
||||||
The rest is *completely* unchanged.
|
The rest is *completely* unchanged.
|
||||||
|
@ -259,41 +259,50 @@ The output file is a bit different, but it has the same parameters,
|
||||||
|
|
||||||
``` javascript
|
``` javascript
|
||||||
|
|
||||||
var getPoint = function (onSuccess, onError)
|
|
||||||
|
var getPoint = function(onSuccess, onError)
|
||||||
{
|
{
|
||||||
var xhr = new XMLHttpRequest();
|
var xhr = new XMLHttpRequest();
|
||||||
xhr.open('GET', '/point', true);
|
xhr.open('GET', '/point', true);
|
||||||
|
xhr.setRequestHeader(\"Accept\",\"application/json\");
|
||||||
xhr.onreadystatechange = function (e) {
|
xhr.onreadystatechange = function (e) {
|
||||||
if (xhr.readyState == 4) {
|
if (xhr.readyState == 4) {
|
||||||
|
if (xhr.status == 204 || xhr.status == 205) {
|
||||||
|
onSuccess();
|
||||||
|
} else if (xhr.status >= 200 && xhr.status < 300) {
|
||||||
var value = JSON.parse(xhr.responseText);
|
var value = JSON.parse(xhr.responseText);
|
||||||
if (xhr.status == 200 || xhr.status == 201) {
|
onSuccess(value);
|
||||||
onSuccess(value);
|
} else {
|
||||||
} else {
|
var value = JSON.parse(xhr.responseText);
|
||||||
onError(value);
|
onError(value);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
xhr.send(null);
|
}
|
||||||
};
|
xhr.send(null);
|
||||||
|
}
|
||||||
|
|
||||||
var getBooks = function (q, onSuccess, onError)
|
var getBooks = function(q, onSuccess, onError)
|
||||||
{
|
{
|
||||||
var xhr = new XMLHttpRequest();
|
var xhr = new XMLHttpRequest();
|
||||||
xhr.open('GET', '/books' + '?q=' + encodeURIComponent(q), true);
|
xhr.open('GET', '/books' + '?q=' + encodeURIComponent(q), true);
|
||||||
|
xhr.setRequestHeader(\"Accept\",\"application/json\");
|
||||||
xhr.onreadystatechange = function (e) {
|
xhr.onreadystatechange = function (e) {
|
||||||
if (xhr.readyState == 4) {
|
if (xhr.readyState == 4) {
|
||||||
|
if (xhr.status == 204 || xhr.status == 205) {
|
||||||
|
onSuccess();
|
||||||
|
} else if (xhr.status >= 200 && xhr.status < 300) {
|
||||||
var value = JSON.parse(xhr.responseText);
|
var value = JSON.parse(xhr.responseText);
|
||||||
if (xhr.status == 200 || xhr.status == 201) {
|
onSuccess(value);
|
||||||
onSuccess(value);
|
} else {
|
||||||
} else {
|
var value = JSON.parse(xhr.responseText);
|
||||||
onError(value);
|
onError(value);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
xhr.send(null);
|
}
|
||||||
};
|
xhr.send(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
And that's all, your web service can of course be accessible from those
|
And 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
|
||||||
the following one:
|
the following one:
|
||||||
|
|
||||||
``` haskell
|
``` haskell
|
||||||
apiJS :: String
|
apiJS3 :: Text
|
||||||
apiJS = jsForAPI api $ axios defAxiosOptions
|
apiJS3 = jsForAPI api $ axios defAxiosOptions
|
||||||
```
|
```
|
||||||
|
|
||||||
The rest is *completely* unchanged.
|
The rest is *completely* unchanged.
|
||||||
|
@ -319,19 +328,23 @@ The output file is a bit different,
|
||||||
|
|
||||||
``` javascript
|
``` javascript
|
||||||
|
|
||||||
var getPoint = function ()
|
|
||||||
{
|
|
||||||
return axios({ url: '/point'
|
|
||||||
, method: 'get'
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var getBooks = function (q)
|
var getPoint = function()
|
||||||
{
|
{
|
||||||
return axios({ url: '/books' + '?q=' + encodeURIComponent(q)
|
return axios({ url: '/point'
|
||||||
, method: 'get'
|
, method: 'get'
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var getBooks = function(q)
|
||||||
|
{
|
||||||
|
return axios({ url: '/books' + '?q=' + encodeURIComponent(q)
|
||||||
|
, method: 'get'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Caution:** In order to support the promise style of the API, there are no onSuccess
|
**Caution:** In order to support the promise style of the API, there are no onSuccess
|
||||||
|
@ -366,8 +379,8 @@ generate top level functions.
|
||||||
The difference is that `angular` Generator always takes an argument.
|
The difference is that `angular` Generator always takes an argument.
|
||||||
|
|
||||||
``` haskell
|
``` haskell
|
||||||
apiJS :: String
|
apiJS4 :: Text
|
||||||
apiJS = jsForAPI api $ angular defAngularOptions
|
apiJS4 = jsForAPI api $ angular defAngularOptions
|
||||||
```
|
```
|
||||||
|
|
||||||
The generated code will be a bit different than previous generators. An extra
|
The generated code will be a bit different than previous generators. An extra
|
||||||
|
@ -379,21 +392,25 @@ nor onError callback functions.
|
||||||
|
|
||||||
``` javascript
|
``` javascript
|
||||||
|
|
||||||
|
|
||||||
var getPoint = function($http)
|
var getPoint = function($http)
|
||||||
{
|
{
|
||||||
return $http(
|
return $http(
|
||||||
{ url: '/counter'
|
{ url: '/point'
|
||||||
, method: 'GET'
|
, method: 'GET'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var getBooks = function($http, q)
|
var getBooks = function($http, q)
|
||||||
{
|
{
|
||||||
return $http(
|
return $http(
|
||||||
{ url: '/books' + '?q=' + encodeURIComponent(q), true);
|
{ url: '/books' + '?q=' + encodeURIComponent(q)
|
||||||
, method: 'GET'
|
, method: 'GET'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
You can then build your controllers easily
|
You can then build your controllers easily
|
||||||
|
@ -440,8 +457,8 @@ app.service('MyService', function($http) {
|
||||||
To do so, you just have to use an alternate generator.
|
To do so, you just have to use an alternate generator.
|
||||||
|
|
||||||
``` haskell
|
``` haskell
|
||||||
apiJS :: String
|
apiJS5 :: Text
|
||||||
apiJS = jsForAPI api $ angularService defAngularOptions
|
apiJS5 = jsForAPI api $ angularService defAngularOptions
|
||||||
```
|
```
|
||||||
|
|
||||||
Again, it is possible to customize some portions with the options.
|
Again, it is possible to customize some portions with the options.
|
||||||
|
@ -468,32 +485,34 @@ Servant comes with three name builders included:
|
||||||
Keeping the JQuery as an example, let's see the impact:
|
Keeping the JQuery as an example, let's see the impact:
|
||||||
|
|
||||||
``` haskell
|
``` haskell
|
||||||
apiJS :: String
|
apiJS6 :: Text
|
||||||
apiJS = jsForAPI api $ jqueryWith defCommonGeneratorOptions { functionNameBuilder= snakeCase }
|
apiJS6 = jsForAPI api $ jqueryWith defCommonGeneratorOptions { functionNameBuilder= snakeCase }
|
||||||
```
|
```
|
||||||
|
|
||||||
This `String` contains 2 Javascript functions:
|
This `Text` contains 2 Javascript functions:
|
||||||
|
|
||||||
``` javascript
|
``` javascript
|
||||||
|
|
||||||
var getPoint = function (onSuccess, onError)
|
|
||||||
|
var get_point = function(onSuccess, onError)
|
||||||
{
|
{
|
||||||
$.ajax(
|
$.ajax(
|
||||||
{ url: '/point'
|
{ url: '/point'
|
||||||
, success: onSuccess
|
, success: onSuccess
|
||||||
, error: onError
|
, error: onError
|
||||||
, method: 'GET'
|
, type: 'GET'
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
var getBooks = function (q, onSuccess, onError)
|
var get_books = function(q, onSuccess, onError)
|
||||||
{
|
{
|
||||||
$.ajax(
|
$.ajax(
|
||||||
{ url: '/books' + '?q=' + encodeURIComponent(q)
|
{ url: '/books' + '?q=' + encodeURIComponent(q)
|
||||||
, success: onSuccess
|
, success: onSuccess
|
||||||
, error: onError
|
, error: onError
|
||||||
, method: 'GET'
|
, type: 'GET'
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,10 @@ spec = do
|
||||||
describe "apiJS" $ do
|
describe "apiJS" $ do
|
||||||
it "is contained verbatim in Javascript.lhs" $ do
|
it "is contained verbatim in Javascript.lhs" $ do
|
||||||
code <- readFile "Javascript.lhs"
|
code <- readFile "Javascript.lhs"
|
||||||
cs apiJS `shouldSatisfy` (`isInfixOf` code)
|
cs apiJS1 `shouldSatisfy` (`isInfixOf` code)
|
||||||
|
cs apiJS3 `shouldSatisfy` (`isInfixOf` code)
|
||||||
|
cs apiJS4 `shouldSatisfy` (`isInfixOf` code)
|
||||||
|
cs apiJS6 `shouldSatisfy` (`isInfixOf` code)
|
||||||
|
|
||||||
describe "writeJSFiles" $ do
|
describe "writeJSFiles" $ do
|
||||||
it "[not a test] write apiJS to static/api.js" $ do
|
it "[not a test] write apiJS to static/api.js" $ do
|
||||||
|
@ -24,7 +27,7 @@ spec = do
|
||||||
describe "app" $ with (return app) $ do
|
describe "app" $ with (return app) $ do
|
||||||
context "/api.js" $ do
|
context "/api.js" $ do
|
||||||
it "delivers apiJS" $ do
|
it "delivers apiJS" $ do
|
||||||
get "/api.js" `shouldRespondWith` (fromString (cs apiJS))
|
get "/api.js" `shouldRespondWith` (fromString (cs apiJS1))
|
||||||
|
|
||||||
context "/" $ do
|
context "/" $ do
|
||||||
it "delivers something" $ do
|
it "delivers something" $ do
|
||||||
|
|
|
@ -112,6 +112,7 @@ module Servant.JS
|
||||||
, javascript
|
, javascript
|
||||||
, NoTypes
|
, NoTypes
|
||||||
, GenerateList(..)
|
, GenerateList(..)
|
||||||
|
, FunctionName(..)
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Prelude hiding (writeFile)
|
import Prelude hiding (writeFile)
|
||||||
|
|
Loading…
Reference in a new issue