{"id":13764452,"url":"https://github.com/SAFE-Stack/SAFE-ConfPlanner","last_synced_at":"2025-05-10T19:31:12.337Z","repository":{"id":23872331,"uuid":"100063188","full_name":"SAFE-Stack/SAFE-ConfPlanner","owner":"SAFE-Stack","description":"Working sample of a SAFE-Stack project that uses CQRS/Event-Sourcing and the Elm Architecture","archived":true,"fork":false,"pushed_at":"2024-09-06T13:28:35.000Z","size":1377,"stargazers_count":152,"open_issues_count":0,"forks_count":15,"subscribers_count":10,"default_branch":"master","last_synced_at":"2024-11-15T06:36:09.775Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"F#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SAFE-Stack.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-08-11T19:13:19.000Z","updated_at":"2024-09-14T19:30:37.000Z","dependencies_parsed_at":"2024-08-03T16:03:34.279Z","dependency_job_id":"b0462963-96bf-42b8-8029-d2760e0eb1a6","html_url":"https://github.com/SAFE-Stack/SAFE-ConfPlanner","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SAFE-Stack%2FSAFE-ConfPlanner","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SAFE-Stack%2FSAFE-ConfPlanner/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SAFE-Stack%2FSAFE-ConfPlanner/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SAFE-Stack%2FSAFE-ConfPlanner/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SAFE-Stack","download_url":"https://codeload.github.com/SAFE-Stack/SAFE-ConfPlanner/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224986024,"owners_count":17402935,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T16:00:20.805Z","updated_at":"2024-11-17T00:30:45.720Z","avatar_url":"https://github.com/SAFE-Stack.png","language":"F#","funding_links":[],"categories":["Examples"],"sub_categories":[],"readme":"# SAFE - A web stack designed for developer happiness\n\nThe following document describes a [SAFE-Stack](https://safe-stack.github.io/) sample project that brings together CQRS/Event-Sourcing on the backend and the Elm architecture on the frontend.\n\nSAFE is a technology stack that brings together several technologies into a single, coherent stack for typesafe,\nflexible end-to-end web-enabled applications that are written entirely in F#.\n\n![SAFE-Stack](public/img/safe_logo.png \"SAFE-Stack\")\n\n# SAFE-ConfPlanner\n\n[![Build Status](https://travis-ci.org/SAFE-Stack/SAFE-ConfPlanner.svg?branch=master)](https://travis-ci.org/SAFE-Stack/SAFE-ConfPlanner)\n\nThis is the sample project that is used in the talk \"Domain Driven UI\" ([Slides](http://bit.ly/DomainDrivenUi)). The title is a bit misleading as it is a bad name for \"Reusing your datatypes and behaviour from your CQRS/Event-Sourced models in your Elm-architecture application.\"\n\nGiven you use F# and Fable, you can actually build simple eventually connected systems and have the exact same model working in back and frontend.\n\nThe application showcases a couple of things:\n\n* The reuse of the complete domain model on the client and server.\n* It shows the nice fit of and similarity between CQRS/Event-Sourcing on the backend and the Elm-Architecture on the frontend.\n* It reuses projections from the backend in the update function of the elmish app. The backend is sending domain events to the frontend and the (Elm-)model is updated with the help of projections defined in the backend (on all clients that are connected via websockets).\n* It shows an easy way of implementing \"Whatif\"-Scenarios, i.e. scenarios that enable the user try out different actions. When the user is happy with the result the system sends a batch of commands to the server. When \"Whatif-Mode\" is enabled the client reuses not only the projections but also the domain behaviour defined on the server to create the events needed by the update function. The potential commands are also stored.\n* There is also an \"All or nothing\" mode for whatifs. If one command does not succeeds, none of them succeeds\n* It uses the awesome [Fulma](https://mangelmaxime.github.io/Fulma/) library for styling\n* It has BDD Style tests that show how nice the behaviour of Event-Sourced systems can be tested.\n* Websockets with Elmish/Suave\n\n## Content\nThis project consists of 6 dotnetcore subprojects\n* `Domain` - Message-based CQRS implementation of the Domain of a ConferencePlanner.\n* `Domain.Tests` - BDD-Style Tests for the `Domain`\n* `Client` - [Fable](http://fable.io/) Project that uses the Elm-Architecture (with [Fable-Elmish](https://elmish.github.io/elmish/)). It reuses the projections of the `Domain` project. Furthermore it and can also reuse the behaviour of the Domain (when switched to `WhatIf-Mode`)\n* `Server` - A Suave Webserver that allows the Client to connect via Websockets.\n* `EventSourced` - This is where all the backend infrastructure is implemented. It contains an event store with a simple in-memory storage, command and query handlers and the types that hold everything together. Most of the infrastructure is implemented asynchronously with the help of F#s awesome [Mailbox Processors](https://fsharpforfunandprofit.com/posts/concurrency-actor-model/)\n* `Support` - A simple project to fill the EventStore with some initial values.\n\n## Requirements\n\n- [dotnet core SDK 3.1.x](https://dotnet.microsoft.com/download) The .NET Core SDK\n- [node.js](https://nodejs.org/) - JavaScript runtime\n- [yarn](https://yarnpkg.com/) - Package manager for npm modules\n\n## Installation/Development mode\nThis development stack is designed to be used with minimal tooling. An instance of Visual Studio Code together with the excellent [Ionide](http://ionide.io/) plugin should be enough.\n\n- Clone the repository\n- In the cloned directory\n  - install paket: `dotnet tool restore`\n  - install dotnet packages: `dotnet paket install`\n  - install js packages: `yarn install`\n- for the tests\n  - run `dotnet test`in the root dir\n- for the client\n  - run `yarn watch` in the root dir\n- for the server\n  - open another terminal and go to `src\\Server`\n  - run `dotnet run` for the server (or `dotnet watch run` for watchmode)\n- go to `localhost:8080`\n- enjoy\n\n\n## Plans for the future\nFrom the top of my head. If anyone wants to chip in, feel welcome.\n\n### Deployment\n* make use of Azure to deploy the application\n\n### Infrastructure\n* extract the project into its own repository and make it a bit more production ready :D\n* implement at least one different event store implementation (e.g. SQLite or Azure something something)\n* implement projections that can send notifications\n\n### Server\n* switch to giraffe\n* implement a proper autohrization system\n\n### Domain\n* would build the domain a bit differently nowadays\n* build an actual Conference Planner\n\n## Known Issues\n\n### Getting rid of errors in chrome/firefox\n\n- Either comment out the lines in `App.fs`:\n\n```fsharp\n#if DEBUG\n|\u003e Program.withDebugger\n#endif\n```\n\n- Or install the [Redux DevTools](http://extension.remotedev.io/) as a Chrome/Firefox Extensions (recommended)\nOnly one error remains, when visiting the WebApp the first time.\n\n## Maintainer(s)\n\n- [@rommsen](https://github.com/rommsen)\n- [@heimeshoff](https://github.com/heimeshoff)\n- you?\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSAFE-Stack%2FSAFE-ConfPlanner","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FSAFE-Stack%2FSAFE-ConfPlanner","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSAFE-Stack%2FSAFE-ConfPlanner/lists"}