graphql-w-persistent 0.1.0.6 → 0.1.0.7
raw patch · 5 files changed
+156/−5 lines, 5 filesPVP: minor bump suggested
API additions: PVP suggests at least a minor version bump
API changes (from Hackage documentation)
+ GraphQL: processQueryStringWithJson :: (MonadIO m) => String -> FilePath -> m ([RootObject], [[String]])
Files
- ChangeLog.md +5/−1
- graphql-w-persistent.cabal +4/−3
- src/Components/Parsers/ServerSchemaJsonParser.hs +49/−0
- src/GraphQL.hs +90/−0
- src/Model/ServerExceptions.hs +8/−1
ChangeLog.md view
@@ -26,4 +26,8 @@ ## 0.1.0.6 -- 2018-10-24 -* Update documentation+* Update documentation + +## 0.1.0.7 -- 2018-10-26 + +* json file schema
graphql-w-persistent.cabal view
@@ -10,13 +10,13 @@ -- PVP summary: +-+------- breaking API changes -- | | +----- non-breaking API additions -- | | | +--- code changes with no API change -version: 0.1.0.6 +version: 0.1.0.7 -- A short (one-line) description of the package. synopsis: Haskell GraphQL query parser-interpreter-data processor. -- A longer description of the package. -description: This is a general purpose Haskell GraphQL query parser and interpreter. It is including data processing to return GraphQL object formats. The query parser and interpreter are universal (on available database query types which is only SQL for now). It is accepting any string query, and it is returning a list of string database-queries. The data processing unit is designed around the return values from the Yesod and Persistent interface (cast as Text data values from PersistValue). With another server that is same data representation on the returned values from the database, this entire package is applicable. To read more detailed information, you should go to the below module page. +description: This is a general purpose Haskell GraphQL query parser and interpreter middleware. It is including data processing to return GraphQL object formats. The query parser and interpreter are universal (on available database query types which is only SQL for now). It is accepting any string query, and it is returning a list of string database-queries. The data processing unit is designed around the return values from the Yesod and Persistent interface (cast as Text data values from PersistValue). With another server that is same data representation on the returned values from the database, this entire package is applicable. To read more detailed information, you should go to the below module page. -- URL for the project homepage or repository. homepage: https://github.com/jasonsychau/graphql-w-persistent @@ -66,13 +66,14 @@ Components.ObjectHandlers.ServerObjectValidator, Components.ObjectHandlers.ServerObjectTrimmer, Components.Parsers.QueryParser, + Components.Parsers.ServerSchemaJsonParser, Components.QueryComposers.SQLQueryComposer, Model.ServerObjectTypes, Model.ServerExceptions, GraphQLHelper -- LANGUAGE extensions used by modules in this package. - -- other-extensions: + --other-extensions: -- Other library packages from which modules are imported. build-depends: base >=4.11 && <4.12,
+ src/Components/Parsers/ServerSchemaJsonParser.hs view
@@ -0,0 +1,49 @@+module Components.Parsers.ServerSchemaJsonParser (fetchArguments) where + +import qualified Control.Exception as E +import Text.JSON +import Model.ServerExceptions + + +fetchArguments :: FilePath -> IO ([(String,[String])],[(String,[String])],[(String,[String])],[(String,[String])],[(String,String,[String])]) +fetchArguments fp = do + schema <- Prelude.readFile fp + let parsed = schema + return $ parseSchema parsed +parseSchema :: String -> ([(String,[String])],[(String,[String])],[(String,[String])],[(String,[String])],[(String,String,[String])]) +parseSchema str = parseHelper [] [] [] [] [] $ checkJSValueListValue (decode str :: Result [JSValue]) +checkJSValueListValue :: Result [JSValue] -> [JSValue] +checkJSValueListValue (Error str) = E.throw ImportSchemaException +checkJSValueListValue (Ok a) = a +parseHelper :: [(String,[String])] -> [(String,[String])] -> [(String,[String])] -> [(String,[String])] -> [(String,String,[String])] -> [JSValue] -> ([(String,[String])],[(String,[String])],[(String,[String])],[(String,[String])],[(String,String,[String])]) +parseHelper svrobjs sss sos sdbn sor [] = (svrobjs,sss,sos,sdbn,sor) +parseHelper svrobjs sss sos sdbn sor ((JSObject obj):t) = parseHelper ((name,pseudonyms):svrobjs) ((name,scalars):sss) ((name,nestedobjects):sos) ((name,tables):sdbn) (sor++(processRelationships relationships)) t + where + name = getServerName (valFromObj "servername" obj :: Result String) + pseudonyms = getStringList (valFromObj "pseudonyms" obj :: Result [String]) 0 + scalars = getStringList (valFromObj "scalarfields" obj :: Result [String]) 1 + nestedobjects = getStringList (valFromObj "objectfields" obj :: Result [String]) 2 + tables = getStringList (valFromObj "databasetables" obj :: Result [String]) 3 + relationships = getListStringList (valFromObj "databaserelationships" obj :: Result [[String]]) +getServerName :: Result String -> String +getServerName (Error str) = E.throw ImportSchemaServerNameException +getServerName (Ok name) = name +getStringList :: Result [String] -> Int -> [String] +getStringList (Ok rlt) _ = rlt +getStringList _ t + | t==0 = E.throw ImportSchemaPseudonymsException + | t==1 = E.throw ImportSchemaScalarFieldsException + | t==2 = E.throw ImportSchemaObjectFieldsException + | t==3 = E.throw ImportSchemaDatabaseTablesException + | otherwise = E.throw ImportSchemaException +getListStringList :: Result [[String]] -> [[String]] +getListStringList (Error str) = E.throw ImportSchemaDatabaseRelationshipsException +getListStringList (Ok rlt) = rlt +processRelationships :: [[String]] -> [(String,String,[String])] +processRelationships lst = foldr (\x y -> (getFirst x,getThird x, x):y) [] lst +getFirst :: [String] -> String +getFirst (h:t) = h +getFirst _ = E.throw ImportSchemaException +getThird :: [String] -> String +getThird (h1:h2:h3:t) = h3 +getThird _ = E.throw ImportSchemaException
src/GraphQL.hs view
@@ -57,6 +57,8 @@ import qualified Components.DataProcessors.PersistentDataProcessor as DP import Model.ServerObjectTypes import GraphQLHelper +import Components.Parsers.ServerSchemaJsonParser as JP +import Control.Monad.IO.Class as IO {- | @@ -187,6 +189,94 @@ -> [(String,String,[String])] -- ^ two database table names to list of from-to-and intermediate triplet strings as described above to identify all GraphQL relationships with database sequences. -> ([RootObject],[[String]]) -- ^ The return value is one tuple with server objects and list of grouped sql query strings. processQueryString str svrobjs sss sos sodn sor = checkObjectsToSql sss sos sodn sor $ flip checkString svrobjs $ QP.processString str + +{- | + Except being nested in a monad, this funcion is same as above. + + It is provided a convenience to use json file to configure your schema. + + The json format is a list of objects. We're allowing you to here detail your schema with a list of objects to refer to server objects... + + The every object is... + + (1) "servername" is a string to name the server object + (2) "pseudonyms" is a list of string to give all query reference + (3) "scalarfields" is a list of scalar type fields + (4) "objectfields" is a list of nested object fields + (5) "databasetables" is a list of tables in your database + (6) "databaserelationships" is a list of database relationships from this refering table to another table + + NOTE: You do not need to repeat databaserelationships in any objects. A relationship is given once, and more is redundant... + + Here is an example: + + @ + [ + { + "servername": "Person", + "pseudonyms": [ + "person", + "Person", + "owner" + ], + "scalarfields": [ + "id", + "name", + "gender" + ], + "objectfields": [ + "pet" + ], + "databasetables": [ + "person" + ], + "databaserelationships": [ + ["person","id","pet","id","pet_ownership","owner_id","animal_id"] + ] + }, + { + "servername": "Pet", + "pseudonyms": [ + "pet", + "Pet" + ], + "scalarfields": [ + "name", + "gender", + "id" + ], + "objectfields": [ + "owner" + ], + "databasetables": [ + "pet" + ], + "databaserelationships": [ + ["pet","id","person","id","pet_ownership","animal_id","owner_id"] + ] + } + ] + @ + + The exceptions thrown with this function are same as above function, but there are a few more... + + + * ImportSchemaException (when there is a problem with reading your schema) + * ImportSchemaServerNameException (when there is a problem with reading your servername argument) + * ImportSchemaPseudonymsException (when there is a problem with reading your pseudonyms list argument) + * ImportSchemaScalarFieldsException (when there is a problem with reading your scalarfields list argument) + * ImportSchemaObjectFieldsException (when there is a problem with reading your objectfields list argument) + * ImportSchemaDatabaseTablesException (when there is a problem with reading your databasetables list argument) + * ImportSchemaDatabaseRelationshipsException (when there is a problem with reading your databaserelationships list argument) +-} +processQueryStringWithJson :: (MonadIO m) + => String -- ^ This is the GraphQL query + -> FilePath -- ^ This is the filepath to your server schema json file + -> m ([RootObject],[[String]]) -- ^ Return value is same as above, but it is nested in a Monad +processQueryStringWithJson str fp = do + schema <- IO.liftIO $ JP.fetchArguments fp + let (svrobjs,sss,sos,sodn,sor) = schema + return $ checkObjectsToSql sss sos sodn sor $ flip checkString svrobjs $ QP.processString str {- | This is the function to call after casting PersistValues to Text from processQueryString.
src/Model/ServerExceptions.hs view
@@ -16,7 +16,14 @@ InvalidArgumentException | RelationshipConfigurationException | FailedObjectEqualityException | - DuplicateRootObjectsException + DuplicateRootObjectsException | + ImportSchemaException | + ImportSchemaServerNameException | + ImportSchemaPseudonymsException | + ImportSchemaScalarFieldsException | + ImportSchemaObjectFieldsException | + ImportSchemaDatabaseTablesException | + ImportSchemaDatabaseRelationshipsException deriving Show -- InvalidObjectNestedObjectFieldException |