Search code examples
f#babeljsfable-f#

Using node modules from fable


I'm trying to import a node module in my fable code. Being new to fable I did expect so problems and understanding the import flow seems to be one of those. I have the below code which compiles fine but fails run time with Cannot read property 'request' of undefined on the line of the printfn statement

module Session =
    let inline f (f: 'a->'b->'c->'d) = Func<_,_,_,_> f
    [<Import("default","request")>]
    type Http = 
    abstract request : string -> System.Func<obj,obj,obj,unit> -> unit
    let http : Http = failwith "js only"
    let start () = 

       http.request "http://dr.dk" (ff (fun error response body ->
           printfn "%A" body 
       ))
    do  
        start()

Solution

  • I was able to get your example working in the Fable REPL:

    open System
    open Fable
    open Fable.Core
    open Fable.Core.JS
    open Fable.Core.JsInterop
    
    type RequestCallback = Func<obj, obj, obj, unit>
    
    type Request = Func<string, RequestCallback, unit>
    
    [<ImportDefault("request")>]
    let request : Request = jsNative
    
    let start () = 
        request.Invoke("http://dr.dk", (fun error response body ->
            console.log("error", error)
            console.log("response", response)
            console.log("body", body)
        ))
    
    start ()
    

    And here is the JavaScript that it generated:

    import request from "request";
    import { some } from "fable-library/Option.js";
    
    export function start() {
        request("http://dr.dk", (error, response, body) => {
            console.log(some("error"), error);
            console.log(some("response"), response);
            console.log(some("body"), body);
        });
    }
    
    start();
    

    Note that there are bindings for many modules already. For this particular task, I would suggest using Fable.Fetch. If you want a library that works in the browser and .NET, try Fable.SimpleHttp.