/auth0-fable-suave-scaffold

Working sample of a Suave + Fable + Elmish + Auth0 project with hot reloading

Primary LanguageF#The UnlicenseUnlicense

A sample of integrating 3d party auth provider

implementation notes.

  • Integrated Auth0 provider via auth0lock
  • Client/Auth0Lock.fs might be an example of interop with 3d party libs
  • switched token handling lib from jose-jwt to JwtSecurityToken from .Net as it supports validation via public key
  • credentials are test@example.com/test. Though using your own Auth0 profile and credentials is strongly suggested.
  • Canopy test is not adjusted to new login page and thus disabled

Readme from fable-suave-scaffold project

Requirements

  • Mono on MacOS/Linux (on Windows .NET Framework is installed by default)
  • node.js - JavaScript runtime
  • yarn - Package manager for npm modules

On OS X/macOS, make sure you have OpenSSL installed and symlinked correctly, as described here: https://www.microsoft.com/net/core#macos.

dotnet SDK 1.0.4 is required but it'll be downloaded automatically by the build script if not installed (see below). Other tools like Paket or FAKE will also be installed by the build script.

Development mode

This development stack is designed to be used with minimal tooling. An instance of Visual Studio Code together with the excellent Ionide plugin should be enough.

Start the development mode with:

> build.cmd run // on windows
$ ./build.sh run // on unix

This command will call in build.fsx the target "Run". It will start in parallel:

Previously, the build script should download all dependencies like .NET Core SDK, Fable... If you have problems with the download of the .NET Core SDK via the build.cmd or build.sh script, please install the SDK manually from here. Verify that you have at least SDK version 1.0.4 installed (dotnet --version) and then rerun the build script.

You can now edit files in src/Server or src/Client and recompile + browser refresh will be triggered automatically.

Development mode

Usually you can just keep this mode running and running. Just edit files, see the browser refreshing and commit + push with git.

Technology stack

Suave on .NET Core

The webserver backend is running as a Suave.io service on .NET Core.

In development mode the server is automatically restarted whenever a file in src/Server is saved.

React/Elmish client

The client is React single page application that uses fable-elmish to provide a scaffold for the code.

The communication to the server is done via HTTPS calls to /api/*. If a user is logged in then a JSON Web Token is sent to the server with every request.

Fable

The Fable compiler is used to compile the F# client code to JavaScript so that it can run in the browser.

Shared code between server and client

"Isomorphic F#" started a bit as a joke about Isomorphic JavaScript. The naming is really bad, but the idea to have the same code running on client and server is really interesting. If you look at src/Server/Shared/Domain.fs then you will see code that is shared between client and server. On the server it is compiled to .NET core and for the client the Fable compiler is translating it into JavaScript. This is a really convenient technique for a shared domain model.

Testing

Start the full build (incl. UI tests) with:

> build.cmd // on windows
$ ./build.sh // on unix

Expecto

Expecto is a test framework like NUnit or xUnit, but much more developer friendly. With Expecto you write tests as values in normal code. Tests can be composed, reduced, filtered, repeated and passed as values, because they are values. This gives the programmer a lot of leverage when writing tests.

If you are in development mode then you can use Expecto's focused test feature to run a selected test against the running server.

Canopy

canopy is a F# web automation and testing library, built on top of Selenium. In our expecto suite it looks like the following:

    testCase "login with test user" <| fun () ->
        url serverUrl
        waitForElement ".elmish-app"

        click "Login"

        "#username" << "test"
        "#password" << "test"

        click "Log In"

        waitForElement "Isaac Abraham"

Canopy in action

Additional tools

FAKE

FAKE is a build automation system with capabilities which are similar to make and rake. It's used to automate the build, test and deployment process. Look into build.fsx for details.

Paket

Paket is a dependency manager and allows easier management of the NuGet packages.

Deployment alternatives

Google Cloud AppEngine

The repository comes with a sample app.yaml file which is used to deploy to Google Cloud AppEngine using the custom flex environment. At the moment it seems like the application must run on port 8080 and that is set as a environment variable in the app.yaml file. When you run the deploy command it will first look for the app.yaml file and then look for the Dockerfile for what should deploy. The container that is deploy is exactly that same as the one that should have been deployed to Azure, but it is only set up to deploy from local to Google Cloud at the moment, and not from CI server to Google Cloud.

Before you can execute the deploy command you also need to build the solution with the Publish target, that is so the container image will get the compiled binaries when the container build is executed via the deploy command.

To execute the deploy you need a Google Cloud account and project configured as well as the tooling installed, https://cloud.google.com/sdk/downloads. The command you need to run is:

gcloud app deploy -q <--version=main> <--verbosity=debug>

The version and verbosity flag isn't need, but it is recommended to use the version flag so you don't up with to many versions of your application without removing previous ones. Use verbosity=debug if you are having some problems.

Deploy to the flex environment with a custom runtime like this is might take some time, but the instructions here should work.

Maintainer(s)