#!/usr/bin/env bash # # A minimal HabitGrid backend that has nothing to do with markdown, Obsidian or # Syncthing. It exists to prove the plugin's front-end talks to the *contract* # and not to one particular implementation: if this bash script works, so does # a REST client, a SQLite reader, or anything else that prints the same JSON. # # Counts live in HABITGRID_OPT_STATE_FILE, one `name=count` line per habit. # Everything it needs arrives the way the contract says it does: the verb as # argv, the options as HABITGRID_OPT_* environment variables. set -euo pipefail state_file="${HABITGRID_OPT_STATE_FILE:-}" today="${HABITGRID_TODAY:-$(date +%F)}" yesterday="$(date -d "$today -1 day" +%F)" if [[ -z "$state_file" ]]; then echo "fake-backend: HABITGRID_OPT_STATE_FILE is not set" >&2 exit 1 fi # Two habits, one with a goal and one without, so the front-end's two level # formulas both get exercised. habit_names=(coffee walk) habit_goals=(3 null) count_of() { local name="$1" [[ -f "$state_file" ]] || { echo 0; return; } local line line="$(grep -m1 "^$name=" "$state_file" || true)" echo "${line#*=}" | grep -qE '^[0-9]+$' && echo "${line#*=}" || echo 0 } set_count() { local name="$1" value="$2" rest="" [[ -f "$state_file" ]] && rest="$(grep -v "^$name=" "$state_file" || true)" { [[ -n "$rest" ]] && printf '%s\n' "$rest"; printf '%s=%s\n' "$name" "$value"; } >"$state_file" } goal_of() { local name="$1" index=0 for known in "${habit_names[@]}"; do [[ "$known" == "$name" ]] && { echo "${habit_goals[$index]}"; return; } index=$((index + 1)) done echo "null" } is_known() { local name="$1" for known in "${habit_names[@]}"; do [[ "$known" == "$name" ]] && return 0 done return 1 } # {"name":..,"goal":..,"today":..,"history":{..}} -- yesterday is always 1 so # the tests have a streak to look at. print_habit() { local name="$1" printf '{"name":"%s","goal":%s,"today":%s,"history":{"%s":%s,"%s":1}}' \ "$name" "$(goal_of "$name")" "$(count_of "$name")" \ "$today" "$(count_of "$name")" "$yesterday" } case "${1:-}" in list) printf '{"habits":[' separator="" for name in "${habit_names[@]}"; do printf '%s' "$separator" print_habit "$name" separator="," done printf ']}\n' ;; increment) name="${2:-}" if ! is_known "$name"; then echo "fake-backend: no such habit: $name" >&2 exit 1 fi set_count "$name" "$(( $(count_of "$name") + 1 ))" print_habit "$name" printf '\n' ;; *) echo "fake-backend: usage: fake-backend list|increment " >&2 exit 2 ;; esac