Package

purescript-fedger

Repository
brakmic/purescript-fedger
License
MIT
Uploaded by
brakmic

purescript-fedger

This is a small collection of bindings for accessing the publicly available Fedger.io APIs. Simply register with your E-Mail to obtain a free API-Key.

To make the testing easier there's a small Demo App available.

What's the purpose of this library?

Fedger collects and provides information about companies by using machine learning. And because I'd like to learn more about ML in practice (and also have written a few articles on this subject) I thought it might be useful to have a strongly typed and side-effect-free library for ML.

Of course, it's not a secret that I'm a happy PureScript-Noob already maintaining two pet projects based on PureScript but they have nothing in common with ML.

So, Fedger.io is really perfect for me....Machine Learning and PureScript in one. 😄

Current status

All of the APIs are available as foreign imports.

The Fedger API comprises of following sub-APIs:

  • Company API
  • Discover API
  • Geo API
  • News API
  • Stats API
  • Tagged API

The Requests & Responses also have their strongly typed counterparts located in API/Fedger/Messages

Using the API

For example, here are the type definitions for getCompanySnapshot:

Query

data CompanySnapshotQuery = CompanySnapshotQuery {
  domain :: String,
  apikey :: String
}

Response

data CompanySnapshotResponse = CompanySnapshotResponse {
  "domain"        :: String,
  "name"          :: String,
  "slug"          :: String,
  "phone"         :: String,
  "dateFounded"   :: String,
  "fundingLevel"  :: String,
  "urlTwitter"    :: String,
  "urlLinkedIn"   :: String,
  "urlAngellist"  :: String,
  "urlCrunchbase" :: String
}

To call this API we use:

foreign import getCompanySnapshot :: forall e. CompanySnapshotQuery -> (CompanySnapshotResponse -> Eff e Unit) -> FedgerEff Unit

This is how a JSON-result looks like in the console:

Now we convert it to something more stable and reliable, a PureScript Type. 😄

This is the callback Function.

Because all of the API queries are asynchronous a callback must be provided by default. Currently, I'm using some jQuery.ajax() and convert the jQuery 'Deferred' into a Promise.

companySnapshotCB :: forall e. CompanySnapshotResponse -> Eff (console :: CONSOLE | e) Unit
companySnapshotCB = \(CompanySnapshotResponse r) -> do
                                                    log ("Company: "       ++ r.name          ++ "\r\n" ++
                                                         "Funding Level: " ++ r.fundingLevel  ++ "\r\n" ++
                                                         "Slug: "          ++ r.slug          ++ "\r\n" ++
                                                         "Twitter: "       ++ r.urlTwitter    ++ "\r\n" ++
                                                         "Crunchbase: "    ++ r.urlCrunchbase ++ "\r\n")

This is the main function.

We define a Query Type and fill it with data from a company we're searching for. Then we apply getCompanySnapshot to the data and callback from above.

main ::  forall e. Eff (console :: CONSOLE, fedgerM :: FedgerM | e) Unit
main = do
      let snapshotQuery = CompanySnapshotQuery { domain : "giantswarm.io", apikey : YOUR_API_KEY_HERE }
      getCompanySnapshot snapshotQuery companySnapshotCB

This is the result:

Building

Backend

npm install [initial build only]
pulp dep install [initial build only]
gulp

Frontend

gulp make-demo [initial build only]
gulp build-demo

Complete rebuild + cleanup

gulp clean && gulp && gulp build-demo

Running the Demo App

npm start

HapiJS will start to serve pages on http://localhost:8080

Issues / Important notices

Problem 1)

During my API tests I found some discrepancies between the docs and the actual response objects. For example, the docs for getFundingDetails describe the response object as

{
  "domain": "string",
  "total_fund": 0,
  "currency": "string",
  "rounds": [
    {}
  ]
}

...but the actual response object's structure is like this:

{
  "name": "",
  "domain": "",
  "amount_total": 0,
  "rounds": []
}

There's no field total_fund but amount_total instead. Also, there's no currency property at all!

Problem 2)

Accessing getFundings from the Company API yields an HTTP 500-Error.

{
  "statusCode": 500,
  "error": "Internal Server Error",
  "message": "An internal server error occurred"
}

License

MIT