Coder Social home page Coder Social logo

thoth-org / thoth.fetch Goto Github PK

View Code? Open in Web Editor NEW
34.0 3.0 11.0 1.57 MB

Thoth.Fetch provides an easy to use API for working with Fable.Fetch and Thoth.Json

Home Page: https://thoth-org.github.io/Thoth.Fetch/

License: MIT License

F# 99.30% Batchfile 0.04% Shell 0.06% JavaScript 0.60%
thoth fable fetch

thoth.fetch's Introduction

Thoth.Fetch Build Status

Stable Prerelease
NuGet Badge NuGet Badge

Thoth.Fetch provides an easy to use API for working with Fable.Fetch and Thoth.Json.

Click here for documentation

thoth.fetch's People

Contributors

alfonsogarciacaro avatar dependabot[bot] avatar mangelmaxime avatar scullman avatar walternative avatar zaymonfc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

thoth.fetch's Issues

Lack of compiler switch causes IDE errors?

Suppose I have a shared isomorphic library Shared.fsproj like this:

module Shared

#if FABLE_COMPILER
open Thoth.Json
#else
open Thoth.Json.Net
#endif

module Decode = 
  
  let foo = Decode.int

Then, using Thoth.Fetch with this library in Client.fsproj causes errors in the IDE (Ionide):

module Client

open Thoth.Fetch

#if FABLE_COMPILER
open Thoth.Json
#else
open Thoth.Json.Net
#endif

open Shared

let fetchFoo () = 
  Fetch.tryGet("http://localhost:5000", decoder = Decode.foo)

The type 'Thoth.Json.JsonValue' is not compatible with the type 'JsonValue'F# Compiler1

Of course, compiling with Fable is fine, because then FABLE_COMPILER is set.

I believe that the issue is here: https://github.com/thoth-org/Thoth.Fetch/blob/master/src/Fetch.fs#L6

Happy to send a PR!

Extra coders seem to be getting recognized, but their results aren't used

I have a couple coders for single-case unions:

let itemIDEnc (ItemID id) =
  Encode.string id
let itemIDDec : Decoder<ItemID> =
  Decode.map ItemID Decode.string

let extras =
  Extra.empty
    |> Extra.withCustom itemIDEnc itemIDDec
    |> Extra.withInt64

And I receive it fairly straightforwardly:

  let cmd = promise {
    return! Fetch.tryPost(Routes.query, q, extra = JsonCodecs.extras)
  }
  m, Cmd.OfPromise.perform
      (fun () -> cmd :?> JS.Promise<Result<QueryResult, FetchError>>) ()
      (fun r -> QueryResultReceived (TabID 1, r))

QueryResult has a couple int64s in there, so it'll complain if I don't have the withInt64 in there, but it still loses precision, and the other ItemID just takes on a raw string value, which causes an invalid access exception later on when I try to retrieve the value.

The same coders work fine on the encoder side.

What could be going on here?

Fetch.post = Uncaught (in promise) Error: Given an invalid JSON: Unexpected end of JSON input

Hi @MangelMaxime,

i found the solution for my CORS problem and was able to get my data from the rest service.
I implement the post after the succeeded get. And this call works in my app

let addKonto (konto:Konto) = Fetch.post ("https://smuckster.azurewebsites.net/konten", konto) |> ignore

but i see in the developer console, this error

Uncaught (in promise) Error: Given an invalid JSON: Unexpected end of JSON input

strange is, that the call is succed and the data is send correct to the rest service.

My type konto looks like this

type KontoId = int

type Konto = { Id: KontoId Name: string AppId: string DevId: string CertId: string }

and this is the value that was send

{ "Id": 0, "Name": "Test", "AppId": "A", "DevId": "B", "CertId": "C" }

The post works, but i dont know why these error appears :/

Regards

Encoder/Decoder error

Using a SAFE Stack app, I've started getting the following errors in the Console. I'm using Custom encoders/decoders as shown below.

image

module CustomEncoders =

    let inline addDummyCoder<'b> extrasIn =
        let typeName = string typeof<'b>
        let simpleEncoder(_ : 'b) = Encode.string (sprintf "%s function" typeName)
        let simpleDecoder = Decode.fail (sprintf "Decoding is not supported for %s type" typeName)
        extrasIn |> Extra.withCustom simpleEncoder simpleDecoder
        
    let inline buildExtras<'a> extraCoders =
        let myEncoder:Encoder<'a> = Encode.Auto.generateEncoder(extra = extraCoders, caseStrategy = CaseStrategy.CamelCase)
        let myDecoder:Decoder<'a> = Decode.Auto.generateDecoder(extra = extraCoders, caseStrategy = CaseStrategy.CamelCase)
        (myEncoder, myDecoder)

let extras = Extra.empty
                |> CustomEncoders.addDummyCoder<WsSender>
                |> CustomEncoders.buildExtras<Model.Model>


#if DEBUG
open Elmish.Debug
open Elmish.HMR
#endif


Program.mkProgram Model.init Model.update ViewFeliz.render
|> Program.withSubscription subs 
#if DEBUG
|> Program.withConsoleTrace
#endif
|> Program.withReactBatched "elmish-app"
#if DEBUG
|> Program.withDebuggerCoders (fst extras) (snd extras)
#endif
|> Program.run

This was all working ok but I then started using Fetch.post for something and it was suddenly unhappy. At least, I think that's what happened.

Make an abstraction layer on top of Fetch to report good errors

As an example, this is was I used in my app at work.

type FetchResult =
    | Success of Response
    | BadStatus of Response
    | NetworkError

let fetch (url: string) (init: RequestProperties list) : JS.Promise<FetchResult> =
    GlobalFetch.fetch(RequestInfo.Url url, Fetch.requestProps init)
    |> Promise.map (fun response ->
        if response.Ok then
            Success response
        else
            if response.Status < 200 || response.Status >= 300 then
                BadStatus response
            else
                NetworkError
    )

let postRecord (url: string) (body: string) (properties: RequestProperties list) =
    let defaultProps =
      [ RequestProperties.Method HttpMethod.POST
        Fetch.requestHeaders [ ContentType "application/json" ]
        RequestProperties.Body !^(body) ]

    List.append defaultProps properties
    |> fetch url
    |> Promise.bind(fun result ->
        promise {
            match result with
            | Success response -> return response
            | BadStatus response ->
                return failwith (string response.Status + " " + response.StatusText + " for URL " + response.Url)
            | NetworkError ->
                return failwith "network error"
        }
    )

The idea is that it's important to give access to the user to Response so he doesn't lose information about what happened.

We have to provide a Result<_, _> version of the "safe" requests (tryXXXX) and one which uses exceptions for the "unsafe" requests.

Support Responses of Type unit

For example, I usually return just the response code on DELETE requests.
Fetch.delete<Data,unit> fails because there is no Auto decoder for unit.

Same for PATCH,POST and PUT. It might even make sense for GET, if the request just triggers a side effect, is used as RPC.

Proposals

  • Either adding an Auto decoder for unit in Thoth.Json
  • or handling here in Thoth.Fetch

fetchAs with RequestProperties.Mode RequestMode.Nocors is not working

Hi,

im very new to F# and web development. I started with the Safe Stack and try to access to an external API from my app.

But i had problem to get a succeded call from the browser because of CORSs.
Then i found the solution to add a RequestMode to the call

let getKonten() = Fetch.fetchAs<Konto list> ("http://safestacktest.azurewebsites.net/konten", [ RequestProperties.Mode RequestMode.Nocors ])

and i see (DevConsole F12) that the call to my API works and ive got a 200 and the data.
But then a exception is raised and i have no clue what the problem is. When i try a call over local host and return the identical data it will work and i have my deserialzed data in the app.

Fetch.fs?cbdb:353 Uncaught (in promise) Error: 0 for URL at a (Fetch.fs?cbdb:353)

Here is my SampleApp

https://github.com/TheDevKnight/SafeStackTest

it is the clean safe template and i added only a few lines to get my objects from the services.
Can someone give me a hint what im doing wrong?

Thx for any help

Regards

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.