rest-gen 0.14.1 → 0.14.2
raw patch · 5 files changed
+129/−49 lines, 5 filesdep ~aesonnew-uploader
Dependency ranges changed: aeson
Files
- CHANGELOG.md +10/−0
- files/Javascript/base.js +96/−42
- rest-gen.cabal +2/−2
- src/Rest/Gen/JavaScript.hs +14/−3
- src/Rest/Gen/Ruby.hs +7/−2
CHANGELOG.md view
@@ -1,10 +1,20 @@ # Changelog +### 0.14.2++* Generated JavaScript now also works as a Node module+* JavaScript constructors are now named properly instead of "constrWrapper"+* Now generates valid Ruby code again+ ### 0.14.1 * Expose modules Rest.Gen.Base.ActionInfo and Rest.Gen.Base.ApiTree again. * Make test cases compile again.++##### Revisions++* Allow `Cabal == 1.16.*` ## 0.14
files/Javascript/base.js view
@@ -1,63 +1,117 @@-$apinamespace$ =+var $apinamespace$ = function (url, secureUrl) { var postfix = '/v' + this.version + '/'; var sUrl = url + postfix; $apinamespace$.setContext(this, sUrl);- this.contextUrl = sUrl; this.secureContextUrl = (secureUrl || url.replace(/^http:/, "https:")) + postfix; };-$apinamespace$.addObject =- function (obj1, obj2)++if (typeof module === "object" && module && typeof module.exports === "object")+{+ // Export as Node module.+ module.exports = $apinamespace$;++ $apinamespace$.ajaxCall = nodeRequest;+}+else+{+ if (typeof define === "function" && define.amd)+ // Export as AMD.+ define("$apinamespace$", [], function () { return $apinamespace$; });++ else+ // Export as global.+ window.$apinamespace$ = $apinamespace$;++ $apinamespace$.ajaxCall = jQueryRequest;+}++$apinamespace$.addObject = function (obj1, obj2)+{+ for (var fld in obj2)+ obj1[fld] = obj2[fld];+};++$apinamespace$.defaultAjaxOptions = {};++function jQueryRequest (method, url, params, success, error, contentType, dataType, data, callOpts)+{+ var callData =+ { type: method+ , url: url + (params ? '?' + $dollar$.param(params) : '')+ , cache: false+ , success: success || function () {}+ , error: error || function () {}+ , contentType: contentType+ , dataType: dataType+ , xhrFields: { withCredentials: true }+ , data: data || []+ };++ $apinamespace$.addObject(callData, $apinamespace$.defaultAjaxOptions);+ $apinamespace$.addObject(callData, callOpts);++ return $dollar$.ajax(callData);+}++function nodeRequest (method, url, params, onSuccess, onError, contentType, dataType, data, callOpts)+{+ var allParams = {};+ $apinamespace$.addObject(allParams, params);++ if (method === "GET" || method === "HEAD")+ // Avoid cached API responses.+ allParams._ = Date.now();++ var headers = { "Content-type": contentType };++ if (dataType === 'json')+ headers.Accept = 'text/json';+ else if (dataType === 'xml')+ headers.Accept = 'text/xml';++ var callData =+ { url : url+ , qs : allParams+ , method : method+ , headers : headers+ };++ if (data) callData.body = data;++ $apinamespace$.addObject(callData, $apinamespace$.defaultAjaxOptions);+ $apinamespace$.addObject(callData, callOpts);++ return require("request")(callData, callback);++ function callback (error, message, response) {- for (var fld in obj2)- {- obj1[fld] = obj2[fld];- }- };-$apinamespace$.ajaxCall =- function (method, url, params, success, error, contentType, dataType, data, callOpts)+ var parsedResponse = parse(response);+ if (message.statusCode >= 200 && message.statusCode < 300)+ onSuccess && onSuccess(parsedResponse, message);+ else if (onError)+ onError(error, parsedResponse, message);+ }++ function parse (response) {- var callData =- { type: method- , url: url + (params ? '?' + $dollar$.param(params) : '')- , cache: false- , success: success || function () {}- , error: error || function () {}- , contentType: contentType- , dataType: dataType- , xhrFields: { withCredentials: true }- , data: data || []- };- $apinamespace$.addObject(callData, callOpts);- return $dollar$.ajax(callData);- };+ if (dataType === 'json')+ return JSON.parse(response);+ else return response;+ }+}+ $apinamespace$.setContext = function (obj, url) {+ obj.contextUrl = url; for (var fld in obj) { if (obj[fld] != undefined && obj[fld].apiObjectType != undefined && obj[fld].apiObjectType == 'resourceDir') { var newUrl = url + fld.replace(/([a-z0-9])([A-Z])/g, '$dollar$1-$dollar$2').toLowerCase() + '/' $apinamespace$.setContext(obj[fld], newUrl);- obj[fld].contextUrl = newUrl; } }- };-$apinamespace$.makeSilkConstructor =- function ()- {- return function constrWrapper (url)- {- if (this instanceof constrWrapper)- {- $apinamespace$.setContext(this, url);- this.contextUrl = url;- }- else- {- return constrWrapper.access(url);- }- }; };
rest-gen.cabal view
@@ -1,5 +1,5 @@ name: rest-gen-version: 0.14.1+version: 0.14.2 description: Documentation and client generation from rest definition. synopsis: Documentation and client generation from rest definition. maintainer: code@silk.co@@ -48,7 +48,7 @@ Rest.Gen.Utils build-depends: base >= 4.5 && < 4.8- , Cabal >= 1.18 && < 1.22+ , Cabal >= 1.16 && < 1.22 , HStringTemplate >= 0.6 && < 0.8 , aeson >= 0.7 && < 0.8 , blaze-html >= 0.5 && < 0.8
src/Rest/Gen/JavaScript.hs view
@@ -21,9 +21,12 @@ [ unModuleName ns ++ ".prototype.version" .=. string (show ver) , mkJsCode (unModuleName ns) priv r ]- return $ prelude ++ cod+ return $ mkJsModule (prelude ++ cod) where attrs = [("apinamespace", unModuleName ns), ("dollar", "$")] +mkJsModule :: String -> String+mkJsModule content = "(function (window) {\n\n" ++ content ++ "\n\n})(this);"+ mkJsCode :: String -> Bool -> Router m s -> Code mkJsCode ns priv = mkJs ns . sortTree . (if priv then id else noPrivate) . apiSubtrees @@ -33,7 +36,7 @@ mkRes :: String -> ApiResource -> Code mkRes ns node = mkStack $ [ if hasAccessor node- then resourceLoc ns node .=. ns ++ ".makeSilkConstructor()"+ then resourceLoc ns node .=. mkAccessorConstructor ns node else resourceLoc ns node .=. jsObject [] , resourceLoc ns node ++ ".apiObjectType" .=. string "resourceDir" , mkAccessFuncs ns node@@ -41,6 +44,14 @@ , mkPostFuncs ns node ] +mkAccessorConstructor :: String -> ApiResource -> Code+mkAccessorConstructor ns resource =+ let constrName = jsDir (cleanName (resName resource))+ in functionDecl constrName ["url"] $+ jsIf (code $ "this instanceof " ++ constrName)+ (proc (ns ++ ".setContext") (code "this, url"))+ <-> jsElse (ret $ call (constrName ++ ".access") (code "url"))+ mkPreFuncs :: String -> ApiResource -> Code mkPreFuncs ns node = let items = filter ((\i -> not $ postAction i || isAccessor i) . itemInfo) $ resItems node@@ -83,7 +94,7 @@ ++ maybe "" (\i -> "' + encodeURIComponent(" ++ i ++ ") + '/") mIdent mIdent = (if isAccessor ai then const Nothing else id) $ fmap (jsId . cleanName . description) $ ident ai in function fParams $ ret $- proc (ns ++ "." ++ "ajaxCall")+ call (ns ++ "." ++ "ajaxCall") [ string (method ai) , code $ (if (https ai) then "this.secureContextUrl" else "this.contextUrl") ++ " + '" ++ urlPart ++ "'" , code "params"
src/Rest/Gen/Ruby.hs view
@@ -3,6 +3,7 @@ import Data.Char import Data.List+import Data.List.Split (splitOn) import Data.Maybe import Code.Build@@ -17,9 +18,13 @@ mkRbApi :: H.ModuleName -> Bool -> Version -> Router m s -> IO String mkRbApi ns priv ver r =- do prelude <- readContent "Ruby/base.rb"+ do rawPrelude <- readContent "Ruby/base.rb"+ let prelude = replace "SilkApi" (unModuleName ns) rawPrelude let cod = showCode . mkRb (unModuleName ns) ver . sortTree . (if priv then id else noPrivate) . apiSubtrees $ r- return $ cod ++ prelude+ return $ cod ++ "\n" ++ prelude++replace :: String -> String -> String -> String+replace from to = intercalate to . splitOn from mkRb :: String -> Version -> ApiResource -> Code mkRb ns ver node =