servant-js 0.9 → 0.9.1
raw patch · 8 files changed
+57/−22 lines, 8 filesdep +QuickCheckdep ~aesondep ~hspecdep ~servantnew-uploader
Dependencies added: QuickCheck
Dependency ranges changed: aeson, hspec, servant, servant-foreign, servant-server
Files
- CHANGELOG.md +6/−0
- servant-js.cabal +10/−8
- src/Servant/JS/Angular.hs +1/−1
- src/Servant/JS/Axios.hs +1/−1
- src/Servant/JS/Internal.hs +14/−10
- src/Servant/JS/JQuery.hs +1/−1
- src/Servant/JS/Vanilla.hs +1/−1
- test/Servant/JSSpec.hs +23/−0
CHANGELOG.md view
@@ -1,3 +1,9 @@+0.9.1+-----++* Fix javascript function name generation+* Allow servant-0.10+ 0.5 ----
servant-js.cabal view
@@ -1,16 +1,16 @@ name: servant-js-version: 0.9+version: 0.9.1 synopsis: Automatically derive javascript functions to query servant webservices. description: Automatically derive javascript functions to query servant webservices. . Supports deriving functions using vanilla javascript AJAX requests, Angulari, Axios or JQuery. .- You can find an example <https://github.com/haskell-servant/servant/blob/master/servant-js/examples/counter.hs here>+ You can find an example <https://github.com/haskell-servant/servant-js/blob/master/servant-js/examples/counter.hs here> which serves the generated javascript to a webpage that allows you to trigger webservice calls. .- <https://github.com/haskell-servant/servant/blob/master/servant-js/CHANGELOG.md CHANGELOG>+ <https://github.com/haskell-servant/servant-js/blob/master/CHANGELOG.md CHANGELOG> license: BSD3 license-file: LICENSE author: Servant Contributors@@ -20,14 +20,15 @@ build-type: Simple cabal-version: >=1.10 homepage: http://haskell-servant.readthedocs.org/-Bug-reports: http://github.com/haskell-servant/servant/issues+bug-reports: http://github.com/haskell-servant/servant-js/issues+tested-with: GHC==7.8.3, GHC==7.10.3, GHC==8.0.1 extra-source-files: include/*.h CHANGELOG.md README.md source-repository head type: git- location: http://github.com/haskell-servant/servant.git+ location: http://github.com/haskell-servant/servant-js.git flag example description: Build the example too@@ -45,8 +46,8 @@ , base-compat >= 0.9 , charset >= 0.3 , lens >= 4- , servant-foreign == 0.9.*- , servant == 0.9.*+ , servant-foreign >= 0.9 && <0.11+ , servant >= 0.9 && <0.11 , text >= 1.2 && < 1.3 hs-source-dirs: src@@ -86,11 +87,12 @@ Servant.JSSpec.CustomHeaders build-depends: base , base-compat- , hspec >= 2.1.8+ , hspec >= 2.3.0 && <2.5 , hspec-expectations , language-ecmascript >= 0.16 , lens , servant , servant-js , text+ , QuickCheck default-language: Haskell2010
src/Servant/JS/Angular.hs view
@@ -132,7 +132,7 @@ fsep = if hasService then ":" else " =" - fname = namespace <> (functionNameBuilder opts $ req ^. reqFuncName)+ fname = namespace <> (toValidFunctionName (functionNameBuilder opts $ req ^. reqFuncName)) method = req ^. reqMethod url = if url' == "'" then "'/'" else url'
src/Servant/JS/Axios.hs view
@@ -120,7 +120,7 @@ where hasNoModule = moduleName opts == "" - fname = namespace <> (functionNameBuilder opts $ req ^. reqFuncName)+ fname = namespace <> (toValidFunctionName (functionNameBuilder opts $ req ^. reqFuncName)) method = T.toLower . decodeUtf8 $ req ^. reqMethod url = if url' == "'" then "'/'" else url'
src/Servant/JS/Internal.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ViewPatterns #-} module Servant.JS.Internal ( JavaScriptGenerator@@ -116,25 +115,30 @@ setFirstChar x `T.cons` T.filter remainder xs Nothing -> "_" where- setFirstChar c = if firstChar c then c else '_'- firstChar c = prefixOK c || Set.member c firstLetterOK- remainder c = prefixOK c || Set.member c remainderOK- prefixOK c = c `elem` ['$','_']- firstLetterOK = mconcat- [ Set.lowercaseLetter+ setFirstChar c = if Set.member c firstLetterOK then c else '_'+ remainder c = Set.member c remainderOK+ firstLetterOK = (filterBmpChars $ mconcat+ [ Set.fromDistinctAscList "$_"+ , Set.lowercaseLetter , Set.uppercaseLetter , Set.titlecaseLetter , Set.modifierLetter , Set.otherLetter , Set.letterNumber- ]+ ]) remainderOK = firstLetterOK- <> mconcat+ <> (filterBmpChars $ mconcat [ Set.nonSpacingMark , Set.spacingCombiningMark , Set.decimalNumber , Set.connectorPunctuation- ]+ ])++-- Javascript identifiers can only contain codepoints in the Basic Multilingual Plane+-- that is, codepoints that can be encoded in UTF-16 without a surrogate pair (UCS-2)+-- that is, codepoints that can fit in 16-bits, up to 0xffff (65535)+filterBmpChars :: Set.CharSet -> Set.CharSet+filterBmpChars = Set.filter (< '\65536') toJSHeader :: HeaderArg f -> Text toJSHeader (HeaderArg n)
src/Servant/JS/JQuery.hs view
@@ -86,7 +86,7 @@ namespace = if (moduleName opts) == "" then "var " else (moduleName opts) <> "."- fname = namespace <> (functionNameBuilder opts $ req ^. reqFuncName)+ fname = namespace <> (toValidFunctionName (functionNameBuilder opts $ req ^. reqFuncName)) method = req ^. reqMethod url = if url' == "'" then "'/'" else url'
src/Servant/JS/Vanilla.hs view
@@ -97,7 +97,7 @@ namespace = if moduleName opts == "" then "var " else (moduleName opts) <> "."- fname = namespace <> (functionNameBuilder opts $ req ^. reqFuncName)+ fname = namespace <> (toValidFunctionName (functionNameBuilder opts $ req ^. reqFuncName)) method = req ^. reqMethod url = if url' == "'" then "'/'" else url'
test/Servant/JSSpec.hs view
@@ -15,10 +15,14 @@ import Data.Proxy import Data.Text (Text) import qualified Data.Text as T+import Language.ECMAScript3.Lexer (identifier) import Language.ECMAScript3.Parser (program, parse) import Prelude () import Prelude.Compat import Test.Hspec hiding (shouldContain, shouldNotContain)+import Test.QuickCheck (Arbitrary (..),+ choose, listOf,+ property) import Servant.API.Internal.Test.ComprehensiveAPI import Servant.API.ContentTypes@@ -97,6 +101,7 @@ angularSpec Angular axiosSpec --angularSpec AngularCustom+ internalSpec shouldContain :: Text -> Text -> Expectation a `shouldContain` b = shouldSatisfy a (T.isInfixOf b)@@ -151,6 +156,24 @@ testName = "MyService" ngOpts = NG.defAngularOptions { NG.serviceName = testName } genJS req = NG.angularService ngOpts req++newtype ASCII = ASCII {getASCII :: T.Text} deriving (Show)++instance Arbitrary ASCII where+ -- Our arbitrary instance is generating only ASCII, since the language-ecmascript's lexer+ -- is currently (October 2016) still a bit naïve+ arbitrary = fmap (ASCII . T.pack) $ listOf $ choose (minBound, '\127')+ shrink xs = (ASCII . T.pack) <$> shrink (T.unpack $ getASCII xs)++internalSpec :: Spec+internalSpec = describe "Internal" $ do+ it "should generate only valid javascript identifiers for any ASCII route" $ do+ let parseIdentifier = fmap T.pack. parse identifier ""+ property $ \x -> let valid = toValidFunctionName $ getASCII x in+ Right valid == parseIdentifier valid++ it "should generate a valid javascript identifier when supplied with hyphens, unicode whitespace, non-bmp unicode" $ do+ toValidFunctionName "a_--a\66352b\6158c\65075" `shouldBe` "a_abc\65075" generateJSSpec :: TestNames -> (AjaxReq -> Text) -> Spec generateJSSpec n gen = describe specLabel $ do