Haskupcake is a Haskell library to build and send requests to the PIC-SURE API.
it's name is strongly influenced by the Rcupcake library, since they both accomplish the same goal.
The use of stack is recommended.
git clone https://github.com/mikaunix/haskupcakeTo use the library in your own projects, add the path to the directory containing the cloned haskupcake repo to your stack.yaml:
packages:
- .
- /path/to/haskupcake
Instead of manually cloning the repo, you can specify the github repo with a commit in the stack.yaml file:
extra-deps:
- git: https://github.com/mikaunix/haskupcake.git
  commit: 876c2f3a2944fd3f06ff612a911d6a0d2922c748
Finally add the library as a dependency of your project in your package.yaml file:
executables:
  foo-exe:
    dependencies:
    - foo
    - haskupcake
Here are the main modules exposed by haskupcake:
import PicSure.Config
import PicSure.Resource
import PicSure.Query
import PicSure.Security
import PicSure.TypesThis is a simple YAML file, containing an object that needs to have a domain and a token attribute:
domain: https://your.domain.name
debug: false
token: yourSecretTokenIt needs to be loaded with readConfig from the PicSure.Config module, which will return a Config object to use with your queries.
The debug attribute is optional, and gives a more detailled output.
token is required (api key authentication is not supported)
The configuration file is passed around with the help of the State Monad.
Therefore you will need to initiate your calls with runStateT and lift your IO operations with liftIO.
You may use the helper withConfig function, that takes the path to the configuration file, some action in the readerT monad, and returns an IO operation.
withConfig :: FilePath -> PicSureM a -> IO a
withConfig s f = readConfig s >>=
                 genPicState  >>=
                 (fst <$>) . runStateT f
-- usage example:
-- using the config file "config.yaml", list the available resources
main = withConfig "config.yaml" $ lsPath' "/"
-- using the config file "config.yaml", query the variable "AGE" using the alias name "Age"
-- and saves the resulting table as "test.csv"
main = withConfig "config.yaml" $ simpleQuery ([("Age","AGE")]) "test.csv"Don't forget to use liftIO if you want to perform IO operations inside the Reader monad:
main = do
  l <- withConfig "config.yaml" $ do
    paths <- lsPath' ""
    liftIO $ print paths
    lsPath' $ head paths
  print lThis would print the paths directly under the root directory, and return the result of listing the first of those paths. This is not a useful thing to do, but at least it clearly shows how to insert IO.
As we saw earlier, it's possible to list the direct children of a given path quite easily. lsPath takes one more parameter than lsPath', a boolean value to return only the names of the nodes instead of the full path:
lsPath :: Bool -> String -> ReaderT Config IO [String]
lsPath relative path = do (...)
lsPath' = lsPath FalseIt's also possible to search for a path, if you know the name of what you're looking for but not the absolute path leading to it:
-- |search a specific <node>, starting at the absolute path <from>
searchPath :: String -> String -> PicSureM String
-- |search in all the available resources
searchPath' :: String -> PicSureM String
searchPath' node = searchPath node "/"This will perform a breadth-first search on all the available paths and return the first one with the same name as the one you provided, or nothing if it didn't find anything.
Use it with a bit of patience at hand, because one HTTP request has to be performed at each step, and it can take a long time to complete.
Note that you can vastly improve the speed of the search by providing a part of the path instead of just the variable name. It will also help making sure that the first occurence found by the algorithm is the one you are looking for (variable names may not be unique)
the query function takes a list of Variable, a list of Where clauses, and builds a JSON body out of them and sends it to PIC-SURE's runQuery. Thoses types are defined in the PicSure.Type module.
You'll get back a query ID, which you can use with resultStatus, resultAvailableformats, resultFetch and resultDownload.
ResultFetch returns a Either Text.Parsec.Error.ParseError [[String]]. it uses Data.CSV to parse the response.
Be careful because all the data will sit in memory after this call.
resultDownloadreads the response's body and writes it to a file, chunk by chunk. This will run in constant space, so you're only limited by your disk space, not your RAM.