Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
22823da
breaking: 2026 full-stack modernization
codeGlaze Feb 17, 2026
026b031
docs: add migration documentation for 2026 stack modernization
codeGlaze Feb 17, 2026
6249565
consolidate dev tooling into user.clj, overhaul README
codeGlaze Feb 17, 2026
d163ca9
polish: UI fixes, zero-warning builds, dev-mode CSP, user tooling
codeGlaze Feb 18, 2026
c2290ca
fix: eliminate subscribe-outside-reactive-context warnings
codeGlaze Feb 18, 2026
b96b1b6
test: add CLJS test infrastructure and pure function tests
codeGlaze Feb 18, 2026
263f290
fix: replace :class-name with :class for Reagent 2.x compatibility
codeGlaze Feb 18, 2026
9cbc25a
replace prereq-fn subscribes with pure character fns
codeGlaze Feb 18, 2026
3249f88
replace multiclass/wizard prereq subscribes with pure fns in classes.…
codeGlaze Feb 18, 2026
09d7e4c
fix: eliminate remaining subscribe-outside-reactive-context warnings
codeGlaze Feb 18, 2026
6124d9f
test: add tests for compute-all-weapons-map, feat-prereqs, pdf_spec
codeGlaze Feb 18, 2026
d108134
refactor: move input debounce from component to entity/build subscrip…
codeGlaze Feb 18, 2026
f578cdb
fix: convert def+partial with subscribe to defn for reactive context
codeGlaze Feb 19, 2026
1d50782
merge: integrate develop (folders, weapons, docker) into breaking branch
codeGlaze Feb 19, 2026
f28f58f
harden: folder CRUD safety, validation, docs
codeGlaze Feb 19, 2026
bb2400d
cleanup: remove 11 orphaned subscriptions, add changelog
codeGlaze Feb 19, 2026
792fe3c
fix: resolve clj-kondo forward-reference error in on-folder-failure
codeGlaze Feb 19, 2026
29c9f28
merge: integrate lint fixes (if→when) from fix/lint-missing-else
codeGlaze Feb 19, 2026
7476f10
config: consolidate lint config, expand scope, bump clj-kondo
codeGlaze Feb 19, 2026
6bbcd9a
lint: dead code + redundant expressions in shared .cljc files
codeGlaze Feb 19, 2026
b68b917
lint: dead code + redundant expressions in frontend .cljs files
codeGlaze Feb 19, 2026
24df45b
lint: fixes in native, web, test, registration + docs
codeGlaze Feb 19, 2026
0359f32
merge: integrate error handling + import validation from feature branch
codeGlaze Feb 21, 2026
69958f5
fix: add missing kw-base and traverse-nested to common.cljc
codeGlaze Feb 21, 2026
0d8b277
fix: restore incorrectly discarded template and summary-map subscript…
codeGlaze Feb 21, 2026
f307609
fix: flyout menu flickering + dropdown duplicate React keys
codeGlaze Feb 21, 2026
79a6a54
feat: prevent and dedup duplicate selection options in homebrew
codeGlaze Feb 21, 2026
90a83d3
fix: guard combat tracker against nil-state localStorage corruption
codeGlaze Feb 21, 2026
0a9b5c7
fix: restore equipment map subs + template cache timing race
codeGlaze Feb 21, 2026
1971239
fix: subscribe-outside-reactive regression + missing content false po…
codeGlaze Feb 21, 2026
dce1863
fix: content reconciliation accuracy + subscribe warning elimination
codeGlaze Feb 21, 2026
302f603
fix: feat detection matched grandchildren instead of direct children
codeGlaze Feb 21, 2026
906ef46
refactor: replace generic tree walk with direct entity extraction
codeGlaze Feb 21, 2026
f46b956
fix: template cache subscribe guard + auth error diagnostics
codeGlaze Feb 22, 2026
22e48cc
docs: getting started guide, env var docs, dev SIGNATURE default
codeGlaze Feb 22, 2026
4133dd1
fix: party creation page crash from eager JS reload
codeGlaze Feb 22, 2026
364d971
feat: auto-generate character names + fix grappler SRD detection
codeGlaze Feb 22, 2026
7a5d04e
merge: integrate dual-stack CI from develop
codeGlaze Feb 22, 2026
39155a4
fix: resolve all lint errors and warnings
codeGlaze Feb 22, 2026
8ca47ab
fix: clean up noisy CI log output
codeGlaze Feb 22, 2026
14af98d
fix: Docker tag pin, CI fork-PR tolerance, redundant str removal
codeGlaze Feb 22, 2026
4d7284c
fix: upgrade Docker stack to Java 21 + Datomic Pro, fix healthchecks
codeGlaze Feb 22, 2026
55e9f49
fix: Alpine compatibility for Docker images
codeGlaze Feb 22, 2026
93642ad
feat: add Datomic Free→Pro migration tooling
codeGlaze Feb 22, 2026
3b06023
docs: merge migration explained doc into main runbook
codeGlaze Feb 22, 2026
5817663
docs: tighten migration docs, fix stale test counts
codeGlaze Feb 22, 2026
8f1a2ab
fix: orcpub Dockerfile — install peer jar without mvn
codeGlaze Feb 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 58 additions & 9 deletions .clj-kondo/config.edn
Original file line number Diff line number Diff line change
@@ -1,8 +1,47 @@
{:output {:exclude-files [".*resources/public/js/compiled.*"
{;; Prevent analysis of compiled CLJS output -- source copies live there
;; and cause "redefined var" when IDE analyzes both src/ and compiled/.
:exclude-files "resources/public/js/compiled"
:output {:exclude-files [".*resources/public/js/compiled.*"
".*docker/scripts/.*"]}
:linters {:shadowed-fn-param {:level :off}
:shadowed-var {:level :off}
:linters {;; Enabled at :warning so NEW accidental shadows are caught.
;; :exclude covers established patterns: core vars used as param names
;; (name, key, type, etc.) and domain terms used as both defs and params
;; (level, ability, armor, etc.) across modifier/option/character code.
:shadowed-fn-param {:level :warning
:exclude [source character]}
:shadowed-var {:level :warning
:exclude [;; clojure.core / cljs.core vars used as parameter names
name key type val num first last next ns fn comp
int char chars bytes str time atom ref set class
list map range min max mod count filter flatten
keys vals identity ancestors comparator cond
list? sequential? set?
;; re-frame.core/path — used as param in route handlers
path
;; Domain terms used as both ns-level defs and fn params
;; in modifiers.cljc, options.cljc, character.cljc, etc.
level levels level-key ability abilities armor weapon weapons
action alignment cls equipment size subclass-name
skill-options skill-expertise tool-options weapon-proficiency-options
spellcasting-template feat-selections cantrip-selections
sorted-items selected-plugin-options built-template
;; One-off project-var shadows — established code patterns
;; where a fn/let binding intentionally shadows its ns def
actual-path all-armor-inventory app-header
available-selections builder-page character-summary
children critical-hit-values custom-equipment entity
first-class? following-usernames i instant item-adder
languages levels-selection message mod-cfg mod-key
name-result parties party-owner prepared-spells-by-class
prepares-spells query-map search-results source speed
spells-known style view]}
;; 213 warnings. Many namespaces are required purely for side effects:
;; re-frame event/sub registrations, modifier macros, spec loading.
;; Remaining are test cleanup debt (genuinely unused test requires).
:unused-namespace {:level :off}
;; 567 warnings. Destructured map bindings used for documentation or
;; structure (e.g. {:keys [name level key]} where only some are used
;; in the body). Renaming to _ would lose semantic readability.
:unused-binding {:level :off}
:missing-else-branch {:level :warning}
:clojure-lsp/unused-public-var
Expand All @@ -14,17 +53,17 @@
orcpub.dnd.e5.options/spell-tags
orcpub.dnd.e5.options/potent-spellcasting
;; Live callers exist but LSP can't trace them
orcpub.common/dissoc-in ; events.cljs
orcpub.common/dissoc-in ; events.cljs:2976
orcpub.dnd.e5.character/add-ability-namespaces ; test
;; Cross-file refs: used in template.cljc but defined in spell_subs.cljs
orcpub.dnd.e5.spell-subs/sunlight-sensitivity
orcpub.dnd.e5.spell-subs/mask-of-the-wild-mod]
;; re-frame event handlers are dispatched via keyword, not var reference.
;; LSP can't connect reg-event-db registration to (dispatch [:keyword]).
:exclude-when-defined-by #{re-frame.core/reg-event-db
re-frame.core/reg-event-fx
re-frame.core/reg-sub
re-frame.core/reg-sub-raw}}
re-frame.core/reg-event-fx
re-frame.core/reg-sub
re-frame.core/reg-sub-raw}}
;; garden.selectors vars are generated by macros (defselector,
;; defpseudoclass, gen-pseudo-class-defs, etc.) at compile time.
;; clj-kondo can't resolve macro-generated vars statically and
Expand All @@ -34,8 +73,9 @@
;; errors.cljc macros behind #?(:clj) reader conditional —
;; one kondo instance can't resolve them
orcpub.errors]}
;; read-string is a valid cljs.core symbol that clj-kondo
;; doesn't recognize in its ClojureScript analysis data.
;; Macros that introduce bindings kondo can't resolve statically.
;; Each (ns/macro) entry suppresses unresolved symbols inside that
;; macro's body. Modifier macros use defmacro with gensym bindings.
:unresolved-symbol
{:exclude
[read-string
Expand Down Expand Up @@ -66,7 +106,16 @@
(orcpub.entity-spec/make-entity)
(orcpub.routes-test/with-conn)
(orcpub.routes.folder-test/with-conn)
(orcpub.email-change-test/with-conn)
(user/with-db)]}}
;; native/cljs and web/cljs are separate source roots; kondo doesn't know
;; about them so ns names appear to mismatch their file paths.
:config-in-ns {orcpub.core {:linters {:namespace-name-mismatch {:level :off}}}
orcpub.views {:linters {:namespace-name-mismatch {:level :off}}}
orcpub.dnd.e5.native-views {:linters {:namespace-name-mismatch {:level :off}}}}
;; with-conn macros use bare symbol bindings — handled via
;; :unresolved-symbol :exclude above (macroexpand hooks can't find
;; the test namespaces and produce noisy warnings).
:lint-as {reagent.core/with-let clojure.core/let
hiccup.def/defhtml clojure.core/defn
user/with-db clojure.core/let
Expand Down
30 changes: 30 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
FROM clojure:temurin-21-lein

# Install useful dev tools (including unzip for Datomic Pro)
RUN apt-get update \
&& apt-get install -y --no-install-recommends rlwrap git curl tmux make git-lfs lsof iproute2 unzip rsync maven \
libfreetype6 fontconfig fonts-dejavu-core fonts-liberation libxrender1 libxext6 libxi6 libxrandr2 \
&& rm -rf /var/lib/apt/lists/*

# Ensure git-lfs is configured system-wide so LFS files are available in Codespaces
RUN git lfs install --system || true

# Install Leiningen so `lein` is available for LSP and project tasks
RUN curl -fsSL https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein -o /usr/local/bin/lein \
&& chmod +x /usr/local/bin/lein \
&& /usr/local/bin/lein --version || true

WORKDIR /workspace

# Copy project source (lib/ includes pdfbox vendor deps from host)
COPY . /workspace

# Pre-cache Datomic Pro zip so post-create.sh skips the download.
# The actual install (extract, flatten, maven-install) is done by post-create.sh
# because the volume mount overwrites /workspace during container creation.
ARG DATOMIC_VERSION=1.0.7482
RUN curl --fail -L -o "/tmp/datomic-pro-${DATOMIC_VERSION}.zip" \
"https://datomic-pro-downloads.s3.amazonaws.com/${DATOMIC_VERSION}/datomic-pro-${DATOMIC_VERSION}.zip"

# Default shell to bash for VS Code terminal
SHELL ["/bin/bash", "-c"]
45 changes: 45 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"name": "ClojureScript Lein-Figwheel Dev",
"build": {
"dockerfile": "Dockerfile",
"context": ".."
},
"features": {
"ghcr.io/devcontainers/features/sshd:1": {
"version": "latest"
}
},
"forwardPorts": [8890, 3449, 4334],
"portsAttributes": {
"8890": {
"label": "Backend Server",
"onAutoForward": "notify"
},
"3449": {
"label": "Figwheel",
"onAutoForward": "silent"
},
"4334": {
"label": "Datomic",
"onAutoForward": "silent"
}
},
"postCreateCommand": [
"bash",
"./.devcontainer/post-create.sh"
],
"containerEnv": {
"POST_CREATE_VERBOSE": "1",
"DATOMIC_VERSION": "1.0.7482",
"DATOMIC_URL": "datomic:dev://localhost:4334/orcpub"
},
"customizations": {
"vscode": {
"extensions": [
"betterthantomorrow.calva",
"borkdude.clj-kondo"
],
"settings": {}
}
}
}
114 changes: 114 additions & 0 deletions .devcontainer/post-create.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#!/usr/bin/env bash
#
# Datomic Pro install script for devcontainer
#
# 1. Always remove lib/com/datomic/datomic-{type}/<version> if it exists
# 2. Unzip the Datomic zip (from /lib or /tmp, download if missing) into target dir
# 3. Flatten top-level subdir if present (some zips nest contents)
# 4. Run vendor maven-install from bin/
#
# This script does NOT cherry-pick, rename, or check for specific files before extraction.
# All contents of the zip are placed in the target directory, overwriting any previous install.
#

set -euo pipefail

# Source .env from repo root if present (authoritative config)
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
if [ -f "$REPO_ROOT/.env" ]; then
set -a
# shellcheck disable=SC1090
. "$REPO_ROOT/.env"
set +a
fi

# Redirect all output to persistent logs for visibility during Codespace creation
LOG="/tmp/orcpub-post-create.log"
WORKSPACE_LOG="$REPO_ROOT/.devcontainer/post-create.log"
# Ensure workspace log exists and is writable (best-effort)
mkdir -p "$(dirname "$WORKSPACE_LOG")" 2>/dev/null || true
touch "$WORKSPACE_LOG" 2>/dev/null || true
# Tee to both /tmp and workspace log so it's inspectable in Codespaces UI
exec > >(tee -a "$LOG" "$WORKSPACE_LOG") 2>&1

# Optional verbose tracing: set POST_CREATE_VERBOSE=1 to enable `set -x`
if [ "${POST_CREATE_VERBOSE:-0}" = "1" ]; then
echo "[POST-CREATE] Verbose tracing enabled"
set -x
fi

# Timestamp helper
ts() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
log() { echo "$(ts) [POST-CREATE] $*"; }

log "Starting postCreateCommand... (logging to $LOG and $WORKSPACE_LOG)"

# Configuration with defaults
DATOMIC_TYPE="${DATOMIC_TYPE:-pro}"
RAW_DATOMIC_VERSION="${DATOMIC_VERSION:-1.0.7482}"
# basename in case a path was provided (e.g., /tmp/datomic-pro-1.0.7482.zip)
RAW_DATOMIC_VERSION="$(basename "$RAW_DATOMIC_VERSION")"
# strip leading prefix and trailing .zip if present
DATOMIC_VERSION="${RAW_DATOMIC_VERSION#datomic-${DATOMIC_TYPE}-}"
DATOMIC_VERSION="${DATOMIC_VERSION%.zip}"

log "Using DATOMIC_TYPE=$DATOMIC_TYPE, DATOMIC_VERSION=$DATOMIC_VERSION"

# Paths
TARGET_DIR="lib/com/datomic/datomic-${DATOMIC_TYPE}/${DATOMIC_VERSION}"
ZIP_NAME="datomic-${DATOMIC_TYPE}-${DATOMIC_VERSION}.zip"
DOWNLOAD_URL="https://datomic-pro-downloads.s3.amazonaws.com/${DATOMIC_VERSION}/${ZIP_NAME}"

# Clean and prepare target directory
if [ -d "${TARGET_DIR}" ]; then
log "Removing existing installation at ${TARGET_DIR}"
rm -rf "${TARGET_DIR}"
fi
mkdir -p "${TARGET_DIR}"

# Find Datomic zip in /lib/ or /tmp/, download if missing
ZIP_PATH="/lib/${ZIP_NAME}"
if [ ! -f "$ZIP_PATH" ]; then
ZIP_PATH="/tmp/${ZIP_NAME}"
if [ ! -f "$ZIP_PATH" ]; then
log "Downloading Datomic from $DOWNLOAD_URL"
curl --fail --location --progress-bar -o "$ZIP_PATH" "$DOWNLOAD_URL"
fi
fi

# Verify zip integrity (handles corrupt/incomplete downloads)
if ! unzip -t "$ZIP_PATH" >/dev/null 2>&1; then
log "Corrupt or incomplete zip detected, removing and re-downloading..."
rm -f "$ZIP_PATH"
curl --fail --location --progress-bar -o "$ZIP_PATH" "$DOWNLOAD_URL"

# Verify the re-download
if ! unzip -t "$ZIP_PATH" >/dev/null 2>&1; then
log "ERROR: Re-downloaded zip is still corrupt. Check network connection or URL."
log "URL: $DOWNLOAD_URL"
exit 1
fi
fi

# Unzip Datomic distribution into target dir
log "Extracting $ZIP_PATH to $TARGET_DIR"
unzip -q "$ZIP_PATH" -d "${TARGET_DIR}"

# Flatten if needed (some zips nest contents in a subdirectory)
TOP_SUBDIR=$(find "${TARGET_DIR}" -mindepth 1 -maxdepth 1 -type d -print -quit || true)
if [ -n "${TOP_SUBDIR}" ] && [ -z "$(find "${TARGET_DIR}" -maxdepth 1 -type f -print -quit)" ]; then
log "Flattening nested directory structure"
mv "${TOP_SUBDIR}"/* "${TARGET_DIR}/"
rmdir "${TOP_SUBDIR}"
fi

# Run vendor maven-install
if [ -x "${TARGET_DIR}/bin/maven-install" ]; then
log "Running maven-install..."
(cd "${TARGET_DIR}" && bash bin/maven-install)
else
log "ERROR: bin/maven-install not found or not executable in ${TARGET_DIR}/bin"
exit 1
fi

log "Datomic ${DATOMIC_TYPE} ${DATOMIC_VERSION} installed successfully to ${TARGET_DIR}"
6 changes: 5 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@ test/*
*.md
data/*
log/*
backups/*
backups/*
backup/*

# Datomic Pro distribution (~280MB) — Docker images download their own from S3
lib/com/datomic/
17 changes: 15 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,30 @@
PORT=8890

# --- Datomic Database ---
# Datomic Pro with dev storage protocol (required for Java 21 support)
# ADMIN_PASSWORD secures the Datomic admin interface
# DATOMIC_PASSWORD is used by the application to connect to Datomic
# The password in DATOMIC_URL must match DATOMIC_PASSWORD
ADMIN_PASSWORD=change-me-admin
DATOMIC_PASSWORD=change-me-datomic
DATOMIC_URL=datomic:free://datomic:4334/orcpub?password=change-me-datomic
DATOMIC_URL=datomic:dev://datomic:4334/orcpub?password=change-me-datomic

# --- Security ---
# Secret used to sign JWT tokens (20+ characters recommended)
# REQUIRED: JWT signing secret. Authentication will fail without this.
# 20+ random characters recommended (e.g., openssl rand -hex 16)
SIGNATURE=change-me-to-something-unique-and-long

# Content Security Policy (strict|permissive|none)
CSP_POLICY=strict

# Dev mode: CSP violations are logged (Report-Only) instead of blocked,
# allowing Figwheel hot-reload scripts to execute.
DEV_MODE=true

# --- Logs ---
# Defaults to project logs/ if unset
LOG_DIR=

# --- Email (SMTP) ---
# Leave EMAIL_SERVER_URL empty to disable email functionality
EMAIL_SERVER_URL=
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ jobs:

- name: Post PR comment with results
if: github.event_name == 'pull_request' && always()
continue-on-error: true # Fork PRs get read-only GITHUB_TOKEN
uses: actions/github-script@v7
with:
script: |
Expand Down
Loading
Loading