Giter Club home page Giter Club logo

re-web's Introduction

ReWeb - a type-safe ergonomic ReasonML and OCaml web framework (WIP)

npm Build Status Test Status

ReWeb is a web framework based on several foundations:

  • The amazing work of the people behind Httpaf, H2, Esy, and others
  • The core idea of 'Your server as a function' by Marius Eriksen which was also the idea behind Twitter's Finagle web stack
  • Jasim Basheer's essay 'Rails on OCaml' which identifies the need for an ergonomic, Rails-like web framework that still preserves the type safety benefits of OCaml.

ReWeb's main concepts are:

  • Services: a service is a function from a request to a promise of response (i.e. an asynchronous function).
  • Filters: a filter is a function that takes a service as input and returns a service as output. It can be inserted into the 'request pipeline' and manipulate the request before the service finally handles it.
  • Server: a server is a function that takes a route (pair of HTTP method and path list) as input and returns a service as output.
  • Type-safe request pipeline: requests have a type parameter that reveals their 'context' i.e. some data that's stored inside them. Filters and services must change requests correctly and in the right order, or the compiler will present type errors.

Notice that all the main concepts here are just functions. They are all composeable using just function composition. Services can call other services. Filters can slot together by calling each other. Servers can delegate smaller scopes to other servers. See bin/Main.re for examples of all of these.

Documentation

Examples

Fullstack Reason

Check out the demo repo which shows a fullstack Reason setup with ReWeb and ReasonReact, with code sharing: https://github.com/yawaramin/fullstack-reason/

This repo can be cloned and used right away for a new project.

Bin directory

Finally, check out the example server in the bin/ directory. The Main.re file there has extensive examples of almost everything ReWeb currently supports.

Run the example server:

$ esy bin

Send some requests to it:

$ curl localhost:8080/hello
$ curl localhost:8080/auth/hello
$ curl --user 'bob:secret' localhost:8080/auth/hello

Go to http://localhost:8080/login in your browser, etc.

Try

You need Esy, you can install the beta using npm:

$ npm install --global esy@latest

Then run the esy command from this project root to install and build dependencies.

$ esy

Now you can run your editor within the environment (which also includes merlin):

$ esy $EDITOR
$ esy vim

Alternatively you can try vim-reasonml which loads esy project environments automatically.

After you make some changes to source code, you can re-run project's build again with the same simple esy command.

$ esy

Generate documentation:

$ esy doc
$ esy open '#{self.target_dir}/default/_doc/_html/index.html'

Shell into environment:

$ esy shell

Run the test suite with:

$ esy test

Warning

ReWeb is experimental and not for production use! I am still ironing out the API. But (imho) it looks promising for real-world usage.

re-web's People

Contributors

adrianmcli avatar anmonteiro avatar et7f3 avatar inchingforward avatar tatchi avatar tcoopman avatar yawaramin 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  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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar

re-web's Issues

Lwt.choose over Lwt.pick

While I was looking for the error that I had yesterday where some messages didn't arrive, I as that you use Lwt.pick here:

Lwt.pick [

I'm wondering if that shouldn't be Lwt.choose instead.

Lwt.pick wil try to cancel the other promise, so I wondering if that means that some messages might get lost.
The behavior of Lwt.choose will not cancel the promise, so I believe that you will get it on the next round.

I don't know Lwt well enough to be sure about this at all, but I'll see if I can maybe create a test case.

How to write integration tests?

First of all, great work on ReWeb! I'm coming from a JavaScript background and the ergonomics of the library just feel right.

I greatly prefer integration testing to unit testing for application development and was investigating how to do that effectively with ReWeb. I've put together a sample to show my approach and would appreciate any feedback.

Notable parts:

Issues:

  • The ReWeb abstraction requires use of internal module signatures which I understand to be breaking encapsulation.
  • I'm unable to use Filters. I think it's because the Request type used internally there is a ReWeb.Filter.Service.Request instead of a ReWeb.Request, though I'm not entirely sure.

Questions:

  • Is this an insane approach? I'm brand new to Reason/OCaml and don't know the conventions yet. It seems that "service as a function" frameworks are perfect candidates for this style of testing. I'd love to not have to stub all of the inner workings of ReWeb to test my app, I just don't want to use a real request. It's a similar approach that supertest encourages for testing express apps and react-testing-library encourages for testing React apps.
  • Is there any intention to provide a Functor for configuring ReWeb? It seems that's what other libraries (such as Rely) do. If so, would you consider allowing customisation of Reqd and ReqBody?

Thanks for your help!

Tierless web development

Since there are some big ideas like Reweb.Response.Live in the issue tracker, I wanted to throw this one out there too.

I want to be able to write a Reason module for a feature and have backend and frontend (BuckleScript) code auto-generated. It would be type-safe, and API calls would simply be function calls. Under the hood it could be some RPC mechanism, or GraphQL for an API that's available outside of this stack. Ideally, the frontend would get compiled with BuckleScript.

Some prior art would be

What do you think?

Websockets are broken

So I've tried to fix the fullstack-reason for the latest re-web (yawaramin/fullstack-reason#4) but when I run the frontend/backend I get a 500 on the websocket.

The server seems to receive the incoming request, but it never gets into the socket method.
The server also doesn't print any errors...

I've tried the same upgrade on my own code and I have the same issue.

Investigating handling databases

Hello @yawaramin

Thank you for the great work on this framework. I want to suggest adding the handling databases part to this framework, this way people can use re-web to write their json apis with databases management included. What I think is missing is something like an orm that would make handling requests to the database easy. The approach I am thinking of is to write a ppx that generates code that follows the example found here.

We will have a module that represents our Entity and the usage of the ppx can be something like:

module Entity = [%reweb.entity 
 type t = {
    id: int,
    title: string,
    completed: bool,
  }
]

and then the ppx will generate the whole module Entity found in the example.

And for the Repository module I still don't have a clear idea on how to do it because the repository needs to get the connection pool from somwhere. So maybe some combination of a functor with a ppx, the functor to inject the connection pool and the ppx to generate the remaining code ?

I would like to hear your thoughts on this.

Unable to load compilation data: No root directory found

I am using VS Code with extension reason-vscode Reason Language Server (RLS).
I cloned the re-web demo application with git clone https://github.com/yawaramin/fullstack-reason.git test01. OCaml native backend end NPM reason frontend both work very well, this is very encouraging :)

The non-critical problem: In file backend/App.re, when I navigate to open ReWeb; (see screenshot), reWeb.ml is opened. Starting from here, I can't lookup the symbols because of "No root directory found" in VS Code's error message.

The problem does not relate to ReWeb directly, sure the origin lies more in Reason Language Server's handling of native esy compiled ocaml-files, but I could find a solution yet.

If anybody have found an work-around, please let me know.
No problem if you close this issue, then it could be used for reference reasons - then perhaps it helps other people wanting get in touch ReWeb and search a way around this problem.

Following RLS issues are relating (not solved yet): 162, 177, 334

image
image

Getting "Error: Program "examples/1_hello_world/Main.bc" not found!" when running examples

Please forgive me if this is a dumb question, I'm new to this ecosystem.

While attempting to run an example from the root of the repo, I get this error:

~/Sites/projects/re-web $ esy run-example examples/1_hello_world/Main.bc                                                                
Error: Program "examples/1_hello_world/Main.bc" not found!

In contrast, when I run esy run-example examples/1_hello_world/Main.exe, it works.

I looked it up in the Dune docs (https://dune.readthedocs.io/en/latest/dune-files.html?highlight=.bc#executable), but was unable to figure out how to build a byte-code executable.

build failure with current resolutions

I'm taking the current resolutions from fullstack-reason and try to build but get this error:

(repeatable by cloning fullstack-reason and removing esy.lock and try to build)

info esy 0.6.4 (using esy.json)
info checking https://github.com/ocaml/opam-repository for updates...
info checking https://github.com/esy-ocaml/esy-opam-override for updates...
info resolving esy packages: done                         
info solving esy constraints: done         
info resolving npm packages: done                
info fetching: done                                                                                                       
info installing: done                                                                                                                
info building @opam/re-web@github:yawaramin/re-web:package.json#7767ce0@d41d8cd9
error: build failed with exit code: 1
  build log:
    # esy-build-package: building: @opam/re-web@github:yawaramin/re-web:package.json#7767ce0
    # esy-build-package: pwd: /home/thomas/.esy/source/i/opam__s__re_web__cb6b8e05
    # esy-build-package: running: 'dune' 'build' '-p' 're-web'
          ocamlc ReWeb/.ReWeb.objs/byte/reWeb__Client.{cmi,cmti} (exit 2)
    (cd /home/thomas/.esy/3/b/opam__s__re_web-96879f24/default && /home/thomas/.esy/3___________________________________________________________________/i/ocaml-4.8.1000-e74c5c0d/bin/ocamlc.opt -w -40 -w +26 -g -bin-annot -I ReWeb/.ReWeb.objs/byte -I /home/thomas/.esy/3___________________________________________________________________/i/ocaml-4.8.1000-e74c5c0d/lib/ocaml/threads -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__angstrom-opam__c__0.13.0-3f232a1b/lib/angstrom -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__base64-opam__c__3.4.0-f7a8ff68/lib/base64 -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__bigarray_compat-opam__c__1.0.0-fbe2bdce/lib/bigarray-compat -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__bigstringaf-opam__c__0.6.1-d30308a0/lib/bigstringaf -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__biniou-opam__c__1.2.1-92ec0761/lib/biniou -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__digestif-opam__c__0.8.0-1-e7d295a8/lib/digestif -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__digestif-opam__c__0.8.0-1-e7d295a8/lib/digestif/ocaml -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__easy_format-opam__c__1.3.2-15ffaf56/lib/easy-format -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__eqaf-opam__c__0.7-5b3c9cbb/lib/eqaf -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__faraday-opam__c__0.7.1-6fb74d6c/lib/faraday -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__faraday_lwt-opam__c__0.7.1-f11aed72/lib/faraday-lwt -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__faraday_lwt_unix-opam__c__0.7.1-2b3468c9/lib/faraday-lwt-unix -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__hpack-opam__c__0.2.0-cc286150/lib/hpack -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__logs-opam__c__0.7.0-00248af0/lib/logs -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__lwt-opam__c__5.3.0-cd5c1882/lib/lwt -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__lwt-opam__c__5.3.0-cd5c1882/lib/lwt/unix -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__magic_mime-opam__c__1.1.2-af438363/lib/magic-mime -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__mmap-opam__c__1.1.0-2f5f39fc/lib/mmap -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__multipart_form_data-f73eb01a/lib/multipart-form-data -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__ocamlfind-opam__c__1.8.1-c291620e/lib/bytes -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__ocplib_endian-opam__c__1.1-94505585/lib/ocplib-endian -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__ocplib_endian-opam__c__1.1-94505585/lib/ocplib-endian/bigstring -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__psq-opam__c__0.2.0-83364711/lib/psq -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__re-opam__c__1.9.0-1b0700f2/lib/re -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__re-opam__c__1.9.0-1b0700f2/lib/re/posix -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__result-opam__c__1.5-aa265883/lib/result -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__seq-opam__c__base-e549f174/lib/seq -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__stdlib_shims-opam__c__0.1.0-9fe806f1/lib/stdlib-shims -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__stringext-opam__c__1.6.0-090d22f8/lib/stringext -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__uri-opam__c__3.1.0-978f683b/lib/uri -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__websocketaf-bbc3690b/lib/websocketaf -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__websocketaf_lwt-7f7fb331/lib/websocketaf-lwt -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__websocketaf_lwt_unix-a4785e65/lib/websocketaf-lwt-unix -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__yojson-opam__c__1.7.0-af81d1af/lib/yojson -I /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__h1-1.1.1001-f0e44521/lib/httpaf -I /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__h1_lwt-1.1.1001-1f24576b/lib/httpaf-lwt -I /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__h1_lwt_unix-1.1.1002-3da3eadc/lib/httpaf-lwt-unix -I /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__h2-0.5.1001-eeefcb8f/lib/h2 -I /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__h2_lwt-0.5.1001-329a79d8/lib/h2-lwt -I /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__h2_lwt_unix-0.5.1001-305d3750/lib/h2-lwt-unix -I /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__lwt__ssl-1.1.3004-a8041646/lib/lwt_ssl -I /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__piaf-1.0.2000-237851e1/lib/piaf -I /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__ssl-0.5.9007-81270db4/lib/ssl -I ReWeb/ReWeb__Config/.ReWeb__Config.objs/byte -I ReWeb/ReWeb__Config/.ReWeb__Config.objs/native -I ReWeb/ReWeb__Header/.ReWeb__Header.objs/byte -I ReWeb/ReWeb__Header/.ReWeb__Header.objs/native -no-alias-deps -open ReWeb__ -o ReWeb/.ReWeb.objs/byte/reWeb__Client.cmi -c -intf ReWeb/Client.mli)
    File "ReWeb/Client.mli", line 6, characters 0-388:
     6 | type config = Piaf.Config.t = {
     7 |   follow_redirects : bool;
     8 |   max_redirects : int;
     9 |   allow_insecure : bool;
    10 |   max_http_version : Piaf.Versions.HTTP.t;
    ...
    16 |   max_tls_version : Piaf.Versions.TLS.t;
    17 |   tcp_nodelay : bool;
    18 |   connect_timeout : float;
    19 | }
    Error: This variant or record definition does not match that of type
             Piaf.Config.t
           The field buffer_size is only present in the original definition.
          ocamlc ReWeb/.ReWeb.objs/byte/reWeb__Server.{cmo,cmt} (exit 2)
    (cd /home/thomas/.esy/3/b/opam__s__re_web-96879f24/default && /home/thomas/.esy/3___________________________________________________________________/i/ocaml-4.8.1000-e74c5c0d/bin/ocamlc.opt -w -40 -w +26 -g -bin-annot -I ReWeb/.ReWeb.objs/byte -I /home/thomas/.esy/3___________________________________________________________________/i/ocaml-4.8.1000-e74c5c0d/lib/ocaml/threads -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__angstrom-opam__c__0.13.0-3f232a1b/lib/angstrom -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__base64-opam__c__3.4.0-f7a8ff68/lib/base64 -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__bigarray_compat-opam__c__1.0.0-fbe2bdce/lib/bigarray-compat -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__bigstringaf-opam__c__0.6.1-d30308a0/lib/bigstringaf -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__biniou-opam__c__1.2.1-92ec0761/lib/biniou -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__digestif-opam__c__0.8.0-1-e7d295a8/lib/digestif -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__digestif-opam__c__0.8.0-1-e7d295a8/lib/digestif/ocaml -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__easy_format-opam__c__1.3.2-15ffaf56/lib/easy-format -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__eqaf-opam__c__0.7-5b3c9cbb/lib/eqaf -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__faraday-opam__c__0.7.1-6fb74d6c/lib/faraday -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__faraday_lwt-opam__c__0.7.1-f11aed72/lib/faraday-lwt -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__faraday_lwt_unix-opam__c__0.7.1-2b3468c9/lib/faraday-lwt-unix -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__hpack-opam__c__0.2.0-cc286150/lib/hpack -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__logs-opam__c__0.7.0-00248af0/lib/logs -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__lwt-opam__c__5.3.0-cd5c1882/lib/lwt -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__lwt-opam__c__5.3.0-cd5c1882/lib/lwt/unix -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__magic_mime-opam__c__1.1.2-af438363/lib/magic-mime -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__mmap-opam__c__1.1.0-2f5f39fc/lib/mmap -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__multipart_form_data-f73eb01a/lib/multipart-form-data -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__ocamlfind-opam__c__1.8.1-c291620e/lib/bytes -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__ocplib_endian-opam__c__1.1-94505585/lib/ocplib-endian -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__ocplib_endian-opam__c__1.1-94505585/lib/ocplib-endian/bigstring -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__psq-opam__c__0.2.0-83364711/lib/psq -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__re-opam__c__1.9.0-1b0700f2/lib/re -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__re-opam__c__1.9.0-1b0700f2/lib/re/posix -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__result-opam__c__1.5-aa265883/lib/result -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__seq-opam__c__base-e549f174/lib/seq -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__stdlib_shims-opam__c__0.1.0-9fe806f1/lib/stdlib-shims -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__stringext-opam__c__1.6.0-090d22f8/lib/stringext -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__uri-opam__c__3.1.0-978f683b/lib/uri -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__websocketaf-bbc3690b/lib/websocketaf -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__websocketaf_lwt-7f7fb331/lib/websocketaf-lwt -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__websocketaf_lwt_unix-a4785e65/lib/websocketaf-lwt-unix -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__yojson-opam__c__1.7.0-af81d1af/lib/yojson -I /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__h1-1.1.1001-f0e44521/lib/httpaf -I /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__h1_lwt-1.1.1001-1f24576b/lib/httpaf-lwt -I /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__h1_lwt_unix-1.1.1002-3da3eadc/lib/httpaf-lwt-unix -I /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__h2-0.5.1001-eeefcb8f/lib/h2 -I /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__h2_lwt-0.5.1001-329a79d8/lib/h2-lwt -I /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__h2_lwt_unix-0.5.1001-305d3750/lib/h2-lwt-unix -I /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__lwt__ssl-1.1.3004-a8041646/lib/lwt_ssl -I /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__piaf-1.0.2000-237851e1/lib/piaf -I /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__ssl-0.5.9007-81270db4/lib/ssl -I ReWeb/ReWeb__Config/.ReWeb__Config.objs/byte -I ReWeb/ReWeb__Config/.ReWeb__Config.objs/native -I ReWeb/ReWeb__Header/.ReWeb__Header.objs/byte -I ReWeb/ReWeb__Header/.ReWeb__Header.objs/native -intf-suffix .ml -no-alias-deps -open ReWeb__ -o ReWeb/.ReWeb.objs/byte/reWeb__Server.cmo -c -impl ReWeb/Server.ml)
    File "ReWeb/Server.ml", line 1:
    Error: The files /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__h1-1.1.1001-f0e44521/lib/httpaf/httpaf.cmi
           and /home/thomas/.esy/3___________________________________________________________________/i/opam__s__websocketaf-bbc3690b/lib/websocketaf/websocketaf.cmi
           make inconsistent assumptions over interface Httpaf__
        ocamlopt ReWeb/.ReWeb.objs/native/reWeb__Server.{cmx,o} (exit 2)
    (cd /home/thomas/.esy/3/b/opam__s__re_web-96879f24/default && /home/thomas/.esy/3___________________________________________________________________/i/ocaml-4.8.1000-e74c5c0d/bin/ocamlopt.opt -w -40 -w +26 -g -I ReWeb/.ReWeb.objs/byte -I ReWeb/.ReWeb.objs/native -I /home/thomas/.esy/3___________________________________________________________________/i/ocaml-4.8.1000-e74c5c0d/lib/ocaml/threads -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__angstrom-opam__c__0.13.0-3f232a1b/lib/angstrom -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__base64-opam__c__3.4.0-f7a8ff68/lib/base64 -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__bigarray_compat-opam__c__1.0.0-fbe2bdce/lib/bigarray-compat -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__bigstringaf-opam__c__0.6.1-d30308a0/lib/bigstringaf -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__biniou-opam__c__1.2.1-92ec0761/lib/biniou -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__digestif-opam__c__0.8.0-1-e7d295a8/lib/digestif -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__digestif-opam__c__0.8.0-1-e7d295a8/lib/digestif/ocaml -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__easy_format-opam__c__1.3.2-15ffaf56/lib/easy-format -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__eqaf-opam__c__0.7-5b3c9cbb/lib/eqaf -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__faraday-opam__c__0.7.1-6fb74d6c/lib/faraday -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__faraday_lwt-opam__c__0.7.1-f11aed72/lib/faraday-lwt -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__faraday_lwt_unix-opam__c__0.7.1-2b3468c9/lib/faraday-lwt-unix -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__hpack-opam__c__0.2.0-cc286150/lib/hpack -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__logs-opam__c__0.7.0-00248af0/lib/logs -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__lwt-opam__c__5.3.0-cd5c1882/lib/lwt -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__lwt-opam__c__5.3.0-cd5c1882/lib/lwt/unix -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__magic_mime-opam__c__1.1.2-af438363/lib/magic-mime -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__mmap-opam__c__1.1.0-2f5f39fc/lib/mmap -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__multipart_form_data-f73eb01a/lib/multipart-form-data -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__ocamlfind-opam__c__1.8.1-c291620e/lib/bytes -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__ocplib_endian-opam__c__1.1-94505585/lib/ocplib-endian -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__ocplib_endian-opam__c__1.1-94505585/lib/ocplib-endian/bigstring -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__psq-opam__c__0.2.0-83364711/lib/psq -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__re-opam__c__1.9.0-1b0700f2/lib/re -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__re-opam__c__1.9.0-1b0700f2/lib/re/posix -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__result-opam__c__1.5-aa265883/lib/result -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__seq-opam__c__base-e549f174/lib/seq -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__stdlib_shims-opam__c__0.1.0-9fe806f1/lib/stdlib-shims -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__stringext-opam__c__1.6.0-090d22f8/lib/stringext -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__uri-opam__c__3.1.0-978f683b/lib/uri -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__websocketaf-bbc3690b/lib/websocketaf -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__websocketaf_lwt-7f7fb331/lib/websocketaf-lwt -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__websocketaf_lwt_unix-a4785e65/lib/websocketaf-lwt-unix -I /home/thomas/.esy/3___________________________________________________________________/i/opam__s__yojson-opam__c__1.7.0-af81d1af/lib/yojson -I /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__h1-1.1.1001-f0e44521/lib/httpaf -I /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__h1_lwt-1.1.1001-1f24576b/lib/httpaf-lwt -I /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__h1_lwt_unix-1.1.1002-3da3eadc/lib/httpaf-lwt-unix -I /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__h2-0.5.1001-eeefcb8f/lib/h2 -I /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__h2_lwt-0.5.1001-329a79d8/lib/h2-lwt -I /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__h2_lwt_unix-0.5.1001-305d3750/lib/h2-lwt-unix -I /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__lwt__ssl-1.1.3004-a8041646/lib/lwt_ssl -I /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__piaf-1.0.2000-237851e1/lib/piaf -I /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__ssl-0.5.9007-81270db4/lib/ssl -I ReWeb/ReWeb__Config/.ReWeb__Config.objs/byte -I ReWeb/ReWeb__Config/.ReWeb__Config.objs/native -I ReWeb/ReWeb__Header/.ReWeb__Header.objs/byte -I ReWeb/ReWeb__Header/.ReWeb__Header.objs/native -intf-suffix .ml -no-alias-deps -open ReWeb__ -o ReWeb/.ReWeb.objs/native/reWeb__Server.cmx -c -impl ReWeb/Server.ml)
    File "ReWeb/Server.ml", line 1:
    Error: The files /home/thomas/.esy/3___________________________________________________________________/i/reason_native_web__s__h1-1.1.1001-f0e44521/lib/httpaf/httpaf.cmi
           and /home/thomas/.esy/3___________________________________________________________________/i/opam__s__websocketaf-bbc3690b/lib/websocketaf/websocketaf.cmi
           make inconsistent assumptions over interface Httpaf__
    error: command failed: 'dune' 'build' '-p' 're-web' (exited with 1)
    esy-build-package: exiting with errors above...
    
  building @opam/re-web@github:yawaramin/re-web:package.json#7767ce0
esy: exiting due to errors above

be able to configure the port and listen to inet_addr_any

I've been playing with re-web and enjoying it so far. One of the things I was trying to do was to play with a build in docker, but found out it didn't work because the server needs to listen to inet_addr_any instead of inet_addr_loopback.

I have changed this in a branch on my fork: https://github.com/yawaramin/re-web/compare/master...tcoopman:inet_addr_any?expand=1

I can create a PR if you give me some insights in how you would want this to be configured.

You probably want to add something in the Config module?

example that uses websockets

It would be nice if there was an example that shows the usage of websockets. I'm willing to give this a try if you give me some pointers in how to do it.

adding with `opam pin`

Adding with opam pin add re-web produces the following:

❯ opam pin add re-web https://github.com/yawaramin/re-web.git
Package re-web does not exist, create as a NEW package? [Y/n] y
[re-web.~dev] synchronised (git+https://github.com/yawaramin/re-web.git)
[ERROR] In
        /Users/mando/Github/opium-realworld-example-app/_opam/.opam-switch/sources/re-web/re-web.opam:
        unsupported or missing file format version; should be 2.0
        or older [skipped]

[ERROR] Invalid opam file in re-web source from
        git+https://github.com/yawaramin/re-web.git:
    error  2: File format error: unsupported or missing file
              format version; should be 2.0 or older

might have to update something. Just an FYI.

Incorrect handling of `Connection_close` can result in an endless loop

I'm not saying this is a bug, maybe just something to put a warning in the docs.

When you receive a Connection_close on a continuously-running handler but don't return Lwt.return_unit then the handler will be stuck in an infinite loop with no way to recover from.

Depending on how you structured your code, this will also result in a cpu spike because pull will always immediately return with Empty.

Example of a wrong code with high cpu usage:

  let rec handler = (pull, push) => {
    let incoming =
      pull(timeout)
      |> Lwt.map(x => {
           switch (x) {
           | Ok(incoming) =>
             Stdlib.print_endline("incoming");
             Some(incoming);
           | Error(`Connection_close) =>
             Stdlib.print_endline("connection closed but continue");
             Some("connection close");
           | Error(`Empty) =>
             Stdlib.print_endline("empty");
             Some("empty");
           | Error(`Timeout) =>
             Stdlib.print_endline("timeout");
             Some("timeout");
           }
         });

    let%lwt incoming = incoming;

    let%lwt () =
      Option.fold(
        ~none=Lwt.return_unit,
        ~some=msg => Topic.publish(topic, ~msg),
        incoming,
      );
    handler(pull, push);
  };

So I'm not sure it's fixable by re-web but I do think the documentation should be clear about this.

Can't install using opam

Contrary to advice not to use in production systems, I'm adding a dependency on re-web to a semi-production system! I'm having trouble though because I can't use esy to manage my project, which means I don't have access to the published package. I've attempted to use opam directly by adding a pin:

pin-depends: [["re-web" "https://github.com/yawaramin/re-web.git#0.6.0"]]

Opam obviously can't parse the empty file in the root and therefore fails to create the pin. I'd be happy to create a PR to populate re-web.opam from the current contents of package.json, but I'm not sure if there's a good way to keep those files in sync.

Is there any other way I can rectify this without requiring changes in this repo? Or would a PR be accepted? Thanks for your help!

build failure

Win10, running as admin and esy V 0.6.2, using ADMIN console.

D:\CRIME\re-web>
D:\CRIME\re-web>esy
info esy 0.6.2 (using package.json)
.... fetching @opam/conf-libssl@archive:https://github.com/openssl/openssl/archive/OpenSSL_1_1_1d.tar.gz#sha1:df0e
info fetching: done
.... installing yarn-pkg-config@github:esy-ocaml/yarn-pkg-config#cca65f99674ed2d954d28788edeb8c57fada5ed0@d41d8cd9
.... installing @opam/conf-libssl@archive:https://github.com/openssl/openssl/archive/OpenSSL_1_1_1d.tar.gz#sha1:df
.... installing @opam/websocketaf-lwt-unix@github:anmonteiro/websocketaf:websocketaf-lwt-unix.opam#8318e44@51e7a4e
.... installing @opam/multipart-form-data@github:cryptosense/multipart-form-data:multipart-form-data.opam#d49fd89@
info installing: done
info building [email protected]@d41d8cd9
info building [email protected]@d41d8cd9: done
info building esy-help2man@github:esy-packages/esy-help2man#c8e6931d1dcf58a81bd801145a777fd3b115c443@d41d8cd9
info building esy-help2man@github:esy-packages/esy-help2man#c8e6931d1dcf58a81bd801145a777fd3b115c443@d41d8cd9: done
info building yarn-pkg-config@github:esy-ocaml/yarn-pkg-config#cca65f99674ed2d954d28788edeb8c57fada5ed0@d41d8cd9
info building yarn-pkg-config@github:esy-ocaml/yarn-pkg-config#cca65f99674ed2d954d28788edeb8c57fada5ed0@d41d8cd9:
done
info building @opam/jbuilder@opam:1.0+beta20.2@053ddcf2
info building @opam/jbuilder@opam:1.0+beta20.2@053ddcf2: done
info building @opam/seq@opam:base@d8d7de1d
info building @opam/seq@opam:base@d8d7de1d: done
info building @opam/cmdliner@opam:1.0.4@93208aac
info building @opam/cmdliner@opam:1.0.4@93208aac: done
info building @opam/ocamlbuild@opam:0.14.0@6ac75d03
info building @opam/ocamlbuild@opam:0.14.0@6ac75d03: done
info building @opam/ocamlfind@opam:1.8.1@ff07b0f9
info building @opam/ocamlfind@opam:1.8.1@ff07b0f9: done
info building @opam/dune@opam:2.1.3@8a848ab8
info building @opam/dune@opam:2.1.3@8a848ab8: done
info building @opam/conf-autoconf@github:esy-packages/esy-autoconf:package.json#fb93edf@d41d8cd9
info building @opam/conf-pkg-config@opam:1.1@67c69c0c
info building @opam/conf-pkg-config@opam:1.1@67c69c0c: done
info building @opam/uchar@opam:0.0.2@c8218eea
info building @opam/uchar@opam:0.0.2@c8218eea: done
info building @opam/topkg@opam:1.0.1@a42c631e
info building @opam/base-bytes@opam:base@19d0c2ff
info building @opam/base-bytes@opam:base@19d0c2ff: done
info building @opam/camomile@opam:1.0.2@51b42ad8
info building @opam/camomile@opam:1.0.2@51b42ad8: done
info building @opam/psq@opam:0.2.0@247756d4
info building @opam/psq@opam:0.2.0@247756d4: done
info building @opam/easy-format@opam:1.3.2@0484b3c4
info building @opam/easy-format@opam:1.3.2@0484b3c4: done
info building @opam/re@opam:1.9.0@d4d5e13d
info building @opam/re@opam:1.9.0@d4d5e13d: done
info building @opam/bigarray-compat@opam:1.0.0@1faefa97
info building @opam/bigarray-compat@opam:1.0.0@1faefa97: done
info building @opam/mmap@opam:1.1.0@b85334ff
info building @opam/mmap@opam:1.1.0@b85334ff: done
info building @opam/dune-private-libs@opam:2.1.3@057b6b15
info building @opam/dune-private-libs@opam:2.1.3@057b6b15: done
info building @opam/stdlib-shims@opam:0.1.0@d957c903
info building @opam/stdlib-shims@opam:0.1.0@d957c903: done
info building @opam/result@opam:1.4@dc720aef
info building @opam/result@opam:1.4@dc720aef: done
info building @opam/ppx_derivers@opam:1.2.1@ecf0aa45
info building @opam/ppx_derivers@opam:1.2.1@ecf0aa45: done
info building @opam/cppo@opam:1.6.6@f4f83858
info building @opam/cppo@opam:1.6.6@f4f83858: done
info building @opam/menhirSdk@opam:20200123@b2300eb1
info building @opam/menhirSdk@opam:20200123@b2300eb1: done
info building @opam/menhirLib@opam:20200123@aac9ddb2
info building @opam/menhirLib@opam:20200123@aac9ddb2: done
info building @opam/stringext@opam:1.6.0@104bc94b
info building @opam/stringext@opam:1.6.0@104bc94b: done
info building @opam/biniou@opam:1.2.1@d7570399
info building @opam/biniou@opam:1.2.1@d7570399: done
info building @opam/eqaf@opam:0.5@ffdce56a
info building @opam/eqaf@opam:0.5@ffdce56a: done
info building @opam/bigstringaf@opam:0.6.0@971764fa
info building @opam/bigstringaf@opam:0.6.0@971764fa: done
info building @opam/dune-configurator@opam:2.1.3@25ad9b47
info building @opam/dune-configurator@opam:2.1.3@25ad9b47: done
info building @opam/charInfo_width@opam:1.1.0@9d8d61b2
info building @opam/charInfo_width@opam:1.1.0@9d8d61b2: done
info building @opam/ocaml-migrate-parsetree@opam:1.5.0@3e319dbc
info building @opam/ocaml-migrate-parsetree@opam:1.5.0@3e319dbc: done
info building @opam/ocplib-endian@opam:1.0@aa720242
info building @opam/merlin-extend@opam:0.5@a5dd7d4b
info building @opam/merlin-extend@opam:0.5@a5dd7d4b: done
info building @opam/menhir@opam:20200123@fdbafd0c
info building @opam/menhir@opam:20200123@fdbafd0c: done
info building @opam/uri@opam:3.1.0@d38ac0ae
info building @opam/uri@opam:3.1.0@d38ac0ae: done
info building @opam/yojson@opam:1.7.0@7056d985
info building @opam/yojson@opam:1.7.0@7056d985: done
info building @opam/digestif@opam:0.8.0@ec3563c0
info building @opam/digestif@opam:0.8.0@ec3563c0: done
info building @opam/faraday@opam:0.7.0@6d4772f6
info building @opam/faraday@opam:0.7.0@6d4772f6: done
info building @opam/angstrom@opam:0.12.1@02015bad
info building @opam/angstrom@opam:0.12.1@02015bad: done
info building @opam/base64@opam:3.3.0@1a7a6d10
info building @opam/base64@opam:3.3.0@1a7a6d10: done
info building @opam/ppx_tools_versioned@opam:5.2.3@4994ec80
info building @opam/ppx_tools_versioned@opam:5.2.3@4994ec80: done
info building @esy-ocaml/[email protected]@d41d8cd9
info building @esy-ocaml/[email protected]@d41d8cd9: done
info building @opam/merlin@opam:3.3.3@d653b06a
error: build failed with exit code: 1
  build log:
    # esy-build-package: building: @opam/topkg@opam:1.0.1
    # esy-build-package: pwd: C:\Users\ysg4206\.esy\3\b\opam__s__topkg-opam__c__1.0.1-5bf1214c
    # esy-build-package: running: "ocaml" "pkg/pkg.ml" "build" "--pkg-name" "topkg" "--dev-pkg" "false"
    Cannot find file topfind.
    '"ocamlfind"' is not recognized as an internal or external command,
    operable program or batch file.
    pkg.ml: [WARNING] OCaml host-os conf:  cmd ["ocamlfind" "ocamlc" "-config"]: exited with 1
    pkg.ml: [WARNING] OCaml host-os conf: key native: undefined, stdlib dir not found for discovery
                      using false
    pkg.ml: [WARNING] OCaml host-os conf: key natdynlink: undefined, stdlib dir not found for discovery
                      using false
    pkg.ml: [WARNING] OCaml host-os conf: key ext_obj: undefined, using ".o"
    pkg.ml: [WARNING] OCaml host-os conf: key ext_lib: undefined, using ".a"
    pkg.ml: [WARNING] OCaml host-os conf: key ext_dll: undefined, using ".so"
    pkg.ml: [WARNING] OCaml host-os conf: key ext_exe: undefined and
                      no C toolchain detected, using ""
    Failure: ocamlfind not found on path, but -no-ocamlfind not used.
    pkg.ml: [ERROR] cmd ["ocamlbuild" "-use-ocamlfind" "-classic-display" "-j" "4" "-tag" "debug"
         "-build-dir" "_build" "CHANGES.md" "LICENSE.md" "README.md" "pkg/META"
         "topkg.opam" "src/topkg.cma" "src/topkg.cmi" "src/topkg.mli"]: exited with 2
    error: command failed: "ocaml" "pkg/pkg.ml" "build" "--pkg-name" "topkg" "--dev-pkg" "false" (exited with 1)
    esy-build-package: exiting with errors above...

  building @opam/topkg@opam:1.0.1
esy: exiting due to errors above

D:\CRIME\re-web>esy --version
0.6.2

Conflict with compilerlibs Config.ml

First of all thanks for the awesome lib!

I have this problem and I'm not sure if it has something to do with the configuration of https://github.com/yawaramin/fullstack-reason/. But when I try to use it with a dep that deps on compilerlibs I can't build the project because dune complains about:

$ esy b

info esy build 0.6.2 (using esy.json)
File "_none_", line 1:
Error: Files /Users/fakenickels/.esy/3_____________________________________________________________/i/ocaml-4.8.1000-426898cd/lib/ocaml/compiler-libs/ocamlcommon.cmxa
       and /Users/fakenickels/.esy/3_____________________________________________________________/i/opam__s__re_web-387ce658/lib/re-web/Z_internal_Config/Config.cmxa
       both define a module named Config
error: command failed: 'dune' 'build' '--only-packages' 'fullstack-reason' (exited with 1)
esy-build-package: exiting with errors above...
error: build failed with exit code: 1

esy: exiting due to errors above

The error can be reproduced with https://github.com/fakenickels/reweb-graphql-server/tree/feature/postgres

How does the cache work?

I'm trying to create something similar as the Topic but with other information in.
Basically Ii want to create a cache key -> t that also cleans up when there are no more users of the key. I thought that this was what Cache should be doing.

But either I'm misunderstanding something or I'm doing something wrong here, but I have some behaviour that sometimes works and sometimes it doesn't

This is a summary of the relevant code:

module Cache = Cache.Ephemeral (struct
  type t = key
  let equal (Key k1) (Key k2) = k1 = k2
  let hash = Hashtbl.seeded_hash
end)

let create cache topic_name push =
  let%lwt value = Cache.find_opt cache ~key:topic_name in
  let%lwt topic =
    match value with
    | None ->
        Stdlib.print_endline "CREATING A TOPIC" ;
        let topic = ReWeb.Topic.make () in
        let%lwt () = Cache.add cache ~key:topic_name topic in
        topic |> Lwt.return
    | Some topic ->
        Stdlib.print_endline "FOUND A TOPIC" ;
        topic |> Lwt.return

When I open 2 tabs, the first tab prints correctly CREATING A TOPIC but the second one sometimes prints FOUND A TOPIC and sometimes CREATING A TOPIC.
I have no idea why that is (the websocket connection on the first tab is still open - I can still push things to it correctly).

I'm wondering if it is because of this line. It's probably something else, and I haven't read into Ephemerals too much, but I don't understand why you are cleaning there.

Any help would be appreciated, thanks!

current version of h2 seems to fail

with this error:

info building @reason-native-web/[email protected]@d41d8cd9
error: build failed with exit code: 1
  build log:
    # esy-build-package: building: @reason-native-web/[email protected]
    # esy-build-package: pwd: /home/thomas/.esy/source/i/reason_native_web__s__h2__0.6.0__c2f59108
    # esy-build-package: running: 'dune' 'build' '--only-packages=h2' '--profile=release' '-j' '4' '--root=./ocaml-h2'
    Entering directory '/home/thomas/.esy/source/i/reason_native_web__s__h2__0.6.0__c2f59108/ocaml-h2'
    File "lib/settings.ml", line 290, characters 7-28:
    290 |        Angstrom.parse_string
                 ^^^^^^^^^^^^^^^^^^^^^
    Error: This function has type 'a Angstrom.t -> string -> ('a, string) result
           It is applied to too many arguments; maybe you forgot a `;'.
    error: command failed: 'dune' 'build' '--only-packages=h2' '--profile=release' '-j' '4' '--root=./ocaml-h2' (exited with 1)
    esy-build-package: exiting with errors above...
    
  building @reason-native-web/[email protected]

got this error when building fullstack-reason after removing esy.lock

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.