Fifthtry

Nix

Realm is in rust, elm, and uses python for database modelling (and migration). We have dependency on PostgreSQL libraries, do some scripting in zsh, have dependency on openssl and so on.

Setting all tools, ensuring they are of compatible versions etc is hard to do, especially if development happens across Linux and Mac.

We use nix to solve this problem.

You can install nix by running:

curl https://nixos.org/nix/install | sh

If using Catalina

Catalina doesn’t allow one to create a new folder in root partition, so you can do the following:

sudo mkdir -p /System/Volumes/Data/nix
sudo chown -R `whoami` /System/Volumes/Data/nix
echo "nix\t/System/Volumes/Data/nix" | sudo tee -a /etc/synthetic.conf
echo "export NIX_IGNORE_SYMLINK_STORE=1" >> ~/.zshrc
# reboot
curl https://nixos.org/nix/install | sh

shell.nix

The recommended way to work with nix is to have everything setup local to the project, and nothing on the system.

Nix has a “project” file, shell.nix, which instructs nix about what nix-channel to use, and what software packages to use from those channels.

shell.nix also setups environment variables etc, so system packages are not available in isolated environment, which is highly recommend.

Lets look at shell.nix for fifthtry project:

let
  moz_overlay = import (
    builtins.fetchTarball
        https://github.com/mozilla/nixpkgs-mozilla/archive/master.tar.gz
  );
  nixpkgs = import (
    builtins.fetchTarball https://github.com/NixOS/nixpkgs/archive/19.09.tar.gz
  ) {
    overlays = [ moz_overlay ];
    config = { allowUnfree = true; };
  };
  frameworks = nixpkgs.darwin.apple_sdk.frameworks;
  rustChannels = (
    nixpkgs.rustChannelOf {
      date = "2019-12-19";
      channel = "stable";
    }
  ); # UPDATE: './rust-toolchain' to reflect on heroku
in
  with nixpkgs;
  stdenv.mkDerivation {
    name = "amitu-env";
    buildInputs = [ rustChannels.rust rustChannels.rust-src rustChannels.clippy-preview ];

    nativeBuildInputs = [
      elmPackages.elm-format
      elmPackages.elm

      file
      zsh
      wget
      locale
      wrk
      vim
      less
      htop
      awscli
      sqlite
      fzf
      tree
      curl
      ripgrep
      taskwarrior
      tokei
      man
      bat
      git
      gitAndTools.diff-so-fancy
      heroku
      openssl
      pkgconfig
      perl
      nixpkgs-fmt
      cacert
      libiconv
      ngrok

      postgresql_11
      python37
      python37Packages.psycopg2
    ]
    ++ (
         stdenv.lib.optionals stdenv.isDarwin [
           frameworks.CoreServices
           frameworks.Security
           frameworks.CoreFoundation
           frameworks.Foundation
           frameworks.AppKit
         ]
    );

    RUST_BACKTRACE = 1;
    SOURCE_DATE_EPOCH = 315532800;

    shellHook = (
      if pkgs.stdenv.isDarwin then
        ''export NIX_LDFLAGS="-F${frameworks.AppKit}/Library/Frameworks -framework AppKit -F${frameworks.CoreServices}/Library/Frameworks -framework CoreServices -F${frameworks.CoreFoundation}/Library/Frameworks -framework CoreFoundation $NIX_LDFLAGS";''
      else
        ""
    )
      +
    ''
      export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib:$LD_LIBRARY_PATH;
      export ZDOTDIR=`pwd`;
      export HISTFILE=~/.zsh_history
      export CARGO_TARGET_DIR=`pwd`/target-nix
      echo "Using ${python37.name}, ${elmPackages.elm.name}, ${rustChannels.rust.name} and ${postgresql_11.name}."
      unset MACOSX_DEPLOYMENT_TARGET
    '';
  }

This will install precisely: python3-3.7.4, elm-0.19.0, rust-1.40.0-2019-12-16-73528e339 and postgresql-11.5.

There are bunch of utilities like zsh, git, curl that we may need: let me repeat, use nothing from base operating system.

nix-shell

So we have nix installed and realm-project/shell.nix file, let’s create the project environment, and understand how to enter the project environment for day to day development.

For this we are going to use nix-shell that comes with nix.

# from inside the realm-project folder
nix-shell --pure --run zsh

Every time you cd into your project directory, run this command. It expects shell.nix to be present in current directory.

--pure tells nix to create a “pure” environment, so nothing from operating system is accessible, and only things listed in shell.nix are available.

--run zsh tells nix to run zsh inside this pure nix environment. In shell.nix we have overridden ZDOTDIR environment variable, so the zsh will not read your ~/.zshrc, and will expect a .zshrc in current (or project directory). Again we want to really not have anything to do with your base operating system.

A note on target-nix: Rust/cargo usually create a folder named target in current/project directory. We setup things up so we use target-nix name instead. Rationale - If editing in say any JetBrains editor, with rust plugin (highly recommended btw), if editor/plugin is not configure to work properly with nix installed rust, it may have another version of rust installed. If we call cargo check etc using two different versions of rust, they keep overwriting each others “build cache”, which means cargo check/cargo build take longer than necessary.

So we have our stuff installed, let’s configure our shell.


PS(Note To Self): Update shell.nix to install postgres:

Table Of Content

What is Realm?

A Bit On Motivation

Routing is Hard

What does Realm do?

Backend Data And Type Safety

Tutorial

Quick Start Realm Tutorial

In Depth Tutorial (not ready)

Nix
Shell
Doit
Hello Rust
Hello Elm
Hello Static Files
Hello Server Side Rendering
Pre-Commit Hooks

Routing, Request And Response

Frontend, Data, Navigation, And APIs

How To Guides

File Upload

Backend: S3 File Upload
Authenticated File Serving
Frontend: Uploading Files From Elm

How to use storybook?

How to implement “loading..”?

Docs

Realm.In

Realm.Storybook.Story

realm::In

realm::Context

realm::Result

realm.magicSlice

realm::RequestConfig

Environment Variables

Internals - Only for Realm Developers, not Users

“Realm DATA”
iFrame Controller
Shutdown Routine
Testing Internals

Change Log

Get Realm Starter Working

Transparent Offline Feature

How to make http requests in Realm?

Development

Replay Testing

Tutorial: ToDo App

Realm Testing

Enhance Realm Starter

Double Load Issue

Deploy To Heroku Button

End failure

Realm-Starter Github Template

Proposal: Tracker And Visit

Proposal: Activity Store

Proposal: Bundling

Proposal: Retry On Network Error

Storybook: Editable JSON

Storybook: Notes

Storybook: Reference

Backlog

Readings

Change Log

How to Publish

Testing

Code Snippets

Skip rustfmt For Some Section

Close Modal Dialog When Clicked Outside

Ignoring Lints In Python

Ignoring Lints (clippy and rustc warnings) In Rust

Handle DateTime in Rust & Elm

Handle CiText value read in Rust

Transport Enum Type to and fro Rust/Elm through JSON