fasten-onprem/CONTRIBUTING.md

11 KiB

This doc is a WIP and will be expanded shortly.

In the meantime, please consider looking at the extensive docs in the Fasten Docs Repository

Tech Stack

Fasten is made up of a handful of different components. Here's a summary of the technologies & languages used in Fasten:

Frontend

  • NodeJS v18.9.0
  • Yarn 1.22.19
  • Angular v14.1.3

Backend

  • Go v1.18.3

Misc

  • Docker v20.10.17

Setup

If you're on a Mac, you can run the following commands to install the necessary software to get setup:

brew install node
npm install -g @angular/cli@14.1.3
npm install -g yarn

brew install go

brew install docker

Running Tests

Before making changes to Fasten, you'll want to run the test suites to ensure that your environment is setup correctly:

make test

# if you only want to run the frontend tests (Angular), you can run:
make test-frontend

# alternatively, if you only care about backend (Go) tests, you can run:
make test-backend

Start Development Environment

To run Fasten from source, you'll need to create 2 separate processes:

  • Angular Frontend
  • Go Backend

First we'll create a development config file (config.dev.yaml)

version: 1
web:
  listen:
    port: 9090
    host: 0.0.0.0
    basepath: ''
  src:
    frontend:
      path: ./dist
database:
  location: 'fasten.db'
cache:
  location: ''
log:
  file: '' #absolute or relative paths allowed, eg. web.log
  level: INFO

Next we'll start the processes described above:


# In terminal #1, run the following
make build-frontend-[sandbox|prod]
# eg. make build-frontend-sandbox

# In terminal #2, run the following
make serve-backend

Note: Fasten can run in 2 modes: sandbox or production (prod). In sandbox mode, it can only communicate with test servers (full of synthetic health data).

Now you can open a browser to http://localhost:9090 to see the Fasten UI.

Important URL's

The following URL's and credentials may be helpful as you're developing

Credentials

  • WebUI:
    • username: testuser
    • password: testuser

Source Code Folder Structure

The Fasten source code is organized into a handful of important folders, which we'll describe below:

Frontend

├── frontend
│   ├── src
│   │   ├── app
│   │   │   ├── app-routing.module.ts
│   │   │   ├── app.component.html
│   │   │   ├── app.component.scss
│   │   │   ├── app.component.spec.ts
│   │   │   ├── app.component.ts
│   │   │   ├── app.module.ts
│   │   │   ├── components                        # contains shared/partial components reused on multiple pages.
│   │   │   │   ├── components-sidebar
│   │   │   │   ├── footer
│   │   │   │   ├── header
│   │   │   │   ├── list-fallback-resource
│   │   │   │   ├── list-generic-resource         # A component containing a table view for every FHIR resource
│   │   │   │   ├── list-patient
│   │   │   │   ├── resource-list                 # Thin shim which populates template depending on FHIR resource type
│   │   │   │   ├── toast                         # Toast/notification component
│   │   │   │   └── utilities-sidebar
│   │   │   ├── models                            # contains classes for communicating with API's and transfering data between pages. 
│   │   │   ├── pages
│   │   │   │   ├── auth-signin                   # Login/Signin page
│   │   │   │   ├── auth-signup                   # Signup page
│   │   │   │   ├── dashboard                     # Dashboard, visible after logging in
│   │   │   │   ├── medical-sources               # Medical Provider connection page
│   │   │   │   ├── patient
│   │   │   │   ├── resource-detail               # Page displaying detailed information about FHIR resource
│   │   │   │   └── source-detail                 # 2 column page displaying FHIR counts, and table listing FHIR resources for selected type
│   │   │   ├── services
│   │   │   │   ├── auth-interceptor.service.ts   # service that looks for 401/403 API responses and triggers Logout
│   │   │   │   ├── is-authenticated-auth-guard.ts    # service that checks if user is logged in
│   │   │   │   ├── fasten-api.service.ts         # api service, used to commnunicate with Go backend (WILL BE REMOVED)
│   │   │   │   ├── fasten-db.service.ts          # db service, used to communicate with CouchDB database
│   │   │   │   ├── lighthouse.service.ts         # api service, used to communicate with auth-gateway (Lighthouse)
│   │   │   │   └── toast.service.ts              # notifications service, used to send notifications
│   │   │   └── workers
│   │   │       ├── queue.service.spec.ts
│   │   │       ├── queue.service.ts              # queue service, used to coordinate background work
│   │   │       └── source-sync.worker.ts         # background job (web-worker) that syncs all FHIR resources from healthcare provider
│   │   ├── lib                                   # root directory for libraries
│   │   │   ├── README.md
│   │   │   ├── conduit                           # Conduit Library - HealthCare provider communication layer (FHIR protocol)
│   │   │   │   ├── fhir                          # contains healthcare provider specific FHIR clients
│   │   │   ├── database                          # Database Library - PouchDB/CouchDB client, compatible with web-worker and browser env
│   │   │   │   ├── plugins
│   │   │   │   └── pouchdb_repository.ts          
│   │   │   ├── models
│   │   │   │   ├── database                      # Classes used to store data in CouchDB
│   │   │   │   ├── fasten                        
│   │   │   │   └── lighthouse                    # Classes used to communicate with Lighthouse API
│   │   │   └── utils
│   │   ├── styles.scss                           # Main sylesheet

Backend

The backend is incredibly simple (by design). The hope is to remove it completely if possible, allowing Fasten to be served by a CDN or minimal Nginx deployment.

├── backend
│   ├── cmd
│   └── pkg
│       ├── config
│       ├── database                  # contains CouchDB client, allowing creation of new Users (and associated databases)
│       ├── errors
│       ├── models
│       └── web
│           ├── handler               # contains code for API endpoints
│           │   ├── auth.go           # authentication endpoints (create new user)
│           │   ├── cors_proxy.go     # CORS proxy/relay for communicating with healthcare providers who do not support CORS
│           │   ├── couchdb_proxy.go  # reverse proxy for CouchDB api, allowing for database API to be exposed (with limitations)
│           │   └── metadata.go       # API endpoint returning metadata for healthcare providers

Distribution/Docker

├── docker-compose.yml                  # docker-compose file which can be used to compile and run "all-in-one" image
├── Dockerfile                          # dockerfile for "all-in-one" image, containing frontend, backend & database
├── docker
│   ├── README.md 
│   ├── couchdb                               
│   │   ├── Dockerfile                  # dockerfile for "couchdb" only image, used for development
│   │   └── local.ini
│   └── rootfs                          # filesystem configs, used in Dockerfiles to setup s6-overlay service manager
│       └── etc
│           ├── cont-init.d
│           │   ├── 01-timezone
│           │   └── 50-couchdb-init
│           └── services.d
│               ├── couchdb
│               └── fasten

FAQ

How do I run individual frontend tests?

  • ng test --include='**/base_client.spec.ts'
  • ng test --include='lib/**/*.spec.ts'

How do I change the default encryption key and admin credentials

  • FASTEN_ISSUER_JWT_KEY

Generate JWT for local use

curl -X POST http://localhost:9090/api/auth/signup -H 'Content-Type: application/json' -d '{"username":"user1","password":"user1"}'

curl -X POST http://localhost:9090/api/auth/signin -H 'Content-Type: application/json' -d '{"username":"user1","password":"user1"}'


curl -H "Authorization: Bearer ${JWT_TOKEN_HERE}" http://localhost:5984/_session

Run Component Storybook

ng run fastenhealth:storybook

Access Encrypted SQLite Database with IntelliJ

  • Download the latest sqlite-jdbc-crypt jar from https://github.com/Willena/sqlite-jdbc-crypt/releases
  • Open IntelliJ -> Data Source Properties -> Driver Tab
  • Find & Select Sqlite -> Right Click -> Duplicate
  • Rename to Sqlite (Encrypted)
  • Find Driver Files -> Select sqlite-jdbc-crypt jar that you downloaded previously
  • Remove Xerial Sqlite JDBC jar
  • Click Apply -> Click OK
  • Create New Data Source -> Select Sqlite (Encrypted) -> Change Connection Type to Url only
  • Specify the following connection url: jdbc:sqlite:fasten.db?cipher=sqlcipher&legacy=3&hmac_use=0&kdf_iter=4000&legacy_page_size=1024&key=123456789012345678901234567890
  • Replace key with the encryption key specified in your config file (database.encryption_key)
  • Click Test Connection -> Should be successful
  • Click Apply -> Click OK

Flush SQLite Write-Ahead-Log (WAL) to Database

PRAGMA wal_checkpoint(TRUNCATE);

See: https://sqlite.org/forum/info/fefd56014e2135589ea57825b0e2aa3e2df5daf53b5e41aa6a9d8f0c29d0b8e5 TODO: check if https://www.sqlite.org/pragma.html#pragma_wal_checkpoint can be used to do this automatically.