Skip to content

Commit 88e256d

Browse files
authored
Merge branch 'Orcpub:develop' into develop
2 parents c580a94 + 400bf28 commit 88e256d

126 files changed

Lines changed: 11702 additions & 1982 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.clj-kondo/config.edn

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,47 @@
1-
{:output {:exclude-files [".*resources/public/js/compiled.*"
1+
{;; Prevent analysis of compiled CLJS output -- source copies live there
2+
;; and cause "redefined var" when IDE analyzes both src/ and compiled/.
3+
:exclude-files "resources/public/js/compiled"
4+
:output {:exclude-files [".*resources/public/js/compiled.*"
25
".*docker/scripts/.*"]}
3-
:linters {:shadowed-fn-param {:level :off}
4-
:shadowed-var {:level :off}
6+
:linters {;; Enabled at :warning so NEW accidental shadows are caught.
7+
;; :exclude covers established patterns: core vars used as param names
8+
;; (name, key, type, etc.) and domain terms used as both defs and params
9+
;; (level, ability, armor, etc.) across modifier/option/character code.
10+
:shadowed-fn-param {:level :warning
11+
:exclude [source character]}
12+
:shadowed-var {:level :warning
13+
:exclude [;; clojure.core / cljs.core vars used as parameter names
14+
name key type val num first last next ns fn comp
15+
int char chars bytes str time atom ref set class
16+
list map range min max mod count filter flatten
17+
keys vals identity ancestors comparator cond
18+
list? sequential? set?
19+
;; re-frame.core/path — used as param in route handlers
20+
path
21+
;; Domain terms used as both ns-level defs and fn params
22+
;; in modifiers.cljc, options.cljc, character.cljc, etc.
23+
level levels level-key ability abilities armor weapon weapons
24+
action alignment cls equipment size subclass-name
25+
skill-options skill-expertise tool-options weapon-proficiency-options
26+
spellcasting-template feat-selections cantrip-selections
27+
sorted-items selected-plugin-options built-template
28+
;; One-off project-var shadows — established code patterns
29+
;; where a fn/let binding intentionally shadows its ns def
30+
actual-path all-armor-inventory app-header
31+
available-selections builder-page character-summary
32+
children critical-hit-values custom-equipment entity
33+
first-class? following-usernames i instant item-adder
34+
languages levels-selection message mod-cfg mod-key
35+
name-result parties party-owner prepared-spells-by-class
36+
prepares-spells query-map search-results source speed
37+
spells-known style view]}
38+
;; 213 warnings. Many namespaces are required purely for side effects:
39+
;; re-frame event/sub registrations, modifier macros, spec loading.
40+
;; Remaining are test cleanup debt (genuinely unused test requires).
541
:unused-namespace {:level :off}
42+
;; 567 warnings. Destructured map bindings used for documentation or
43+
;; structure (e.g. {:keys [name level key]} where only some are used
44+
;; in the body). Renaming to _ would lose semantic readability.
645
:unused-binding {:level :off}
746
:missing-else-branch {:level :warning}
847
:clojure-lsp/unused-public-var
@@ -14,17 +53,17 @@
1453
orcpub.dnd.e5.options/spell-tags
1554
orcpub.dnd.e5.options/potent-spellcasting
1655
;; Live callers exist but LSP can't trace them
17-
orcpub.common/dissoc-in ; events.cljs
56+
orcpub.common/dissoc-in ; events.cljs:2976
1857
orcpub.dnd.e5.character/add-ability-namespaces ; test
1958
;; Cross-file refs: used in template.cljc but defined in spell_subs.cljs
2059
orcpub.dnd.e5.spell-subs/sunlight-sensitivity
2160
orcpub.dnd.e5.spell-subs/mask-of-the-wild-mod]
2261
;; re-frame event handlers are dispatched via keyword, not var reference.
2362
;; LSP can't connect reg-event-db registration to (dispatch [:keyword]).
2463
:exclude-when-defined-by #{re-frame.core/reg-event-db
25-
re-frame.core/reg-event-fx
26-
re-frame.core/reg-sub
27-
re-frame.core/reg-sub-raw}}
64+
re-frame.core/reg-event-fx
65+
re-frame.core/reg-sub
66+
re-frame.core/reg-sub-raw}}
2867
;; garden.selectors vars are generated by macros (defselector,
2968
;; defpseudoclass, gen-pseudo-class-defs, etc.) at compile time.
3069
;; clj-kondo can't resolve macro-generated vars statically and
@@ -34,8 +73,9 @@
3473
;; errors.cljc macros behind #?(:clj) reader conditional —
3574
;; one kondo instance can't resolve them
3675
orcpub.errors]}
37-
;; read-string is a valid cljs.core symbol that clj-kondo
38-
;; doesn't recognize in its ClojureScript analysis data.
76+
;; Macros that introduce bindings kondo can't resolve statically.
77+
;; Each (ns/macro) entry suppresses unresolved symbols inside that
78+
;; macro's body. Modifier macros use defmacro with gensym bindings.
3979
:unresolved-symbol
4080
{:exclude
4181
[read-string
@@ -66,7 +106,16 @@
66106
(orcpub.entity-spec/make-entity)
67107
(orcpub.routes-test/with-conn)
68108
(orcpub.routes.folder-test/with-conn)
109+
(orcpub.email-change-test/with-conn)
69110
(user/with-db)]}}
111+
;; native/cljs and web/cljs are separate source roots; kondo doesn't know
112+
;; about them so ns names appear to mismatch their file paths.
113+
:config-in-ns {orcpub.core {:linters {:namespace-name-mismatch {:level :off}}}
114+
orcpub.views {:linters {:namespace-name-mismatch {:level :off}}}
115+
orcpub.dnd.e5.native-views {:linters {:namespace-name-mismatch {:level :off}}}}
116+
;; with-conn macros use bare symbol bindings — handled via
117+
;; :unresolved-symbol :exclude above (macroexpand hooks can't find
118+
;; the test namespaces and produce noisy warnings).
70119
:lint-as {reagent.core/with-let clojure.core/let
71120
hiccup.def/defhtml clojure.core/defn
72121
user/with-db clojure.core/let

.devcontainer/Dockerfile

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
FROM clojure:temurin-21-lein
2+
3+
# Install useful dev tools (including unzip for Datomic Pro)
4+
RUN apt-get update \
5+
&& apt-get install -y --no-install-recommends rlwrap git curl tmux make git-lfs lsof iproute2 unzip rsync maven \
6+
libfreetype6 fontconfig fonts-dejavu-core fonts-liberation libxrender1 libxext6 libxi6 libxrandr2 \
7+
&& rm -rf /var/lib/apt/lists/*
8+
9+
# Ensure git-lfs is configured system-wide so LFS files are available in Codespaces
10+
RUN git lfs install --system || true
11+
12+
# Install Leiningen so `lein` is available for LSP and project tasks
13+
RUN curl -fsSL https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein -o /usr/local/bin/lein \
14+
&& chmod +x /usr/local/bin/lein \
15+
&& /usr/local/bin/lein --version || true
16+
17+
WORKDIR /workspace
18+
19+
# Copy project source (lib/ includes pdfbox vendor deps from host)
20+
COPY . /workspace
21+
22+
# Pre-cache Datomic Pro zip so post-create.sh skips the download.
23+
# The actual install (extract, flatten, maven-install) is done by post-create.sh
24+
# because the volume mount overwrites /workspace during container creation.
25+
ARG DATOMIC_VERSION=1.0.7482
26+
RUN curl --fail -L -o "/tmp/datomic-pro-${DATOMIC_VERSION}.zip" \
27+
"https://datomic-pro-downloads.s3.amazonaws.com/${DATOMIC_VERSION}/datomic-pro-${DATOMIC_VERSION}.zip"
28+
29+
# Default shell to bash for VS Code terminal
30+
SHELL ["/bin/bash", "-c"]

.devcontainer/devcontainer.json

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"name": "ClojureScript Lein-Figwheel Dev",
3+
"build": {
4+
"dockerfile": "Dockerfile",
5+
"context": ".."
6+
},
7+
"features": {
8+
"ghcr.io/devcontainers/features/sshd:1": {
9+
"version": "latest"
10+
}
11+
},
12+
"forwardPorts": [8890, 3449, 4334],
13+
"portsAttributes": {
14+
"8890": {
15+
"label": "Backend Server",
16+
"onAutoForward": "notify"
17+
},
18+
"3449": {
19+
"label": "Figwheel",
20+
"onAutoForward": "silent"
21+
},
22+
"4334": {
23+
"label": "Datomic",
24+
"onAutoForward": "silent"
25+
}
26+
},
27+
"postCreateCommand": [
28+
"bash",
29+
"./.devcontainer/post-create.sh"
30+
],
31+
"containerEnv": {
32+
"POST_CREATE_VERBOSE": "1",
33+
"DATOMIC_VERSION": "1.0.7482",
34+
"DATOMIC_URL": "datomic:dev://localhost:4334/orcpub"
35+
},
36+
"customizations": {
37+
"vscode": {
38+
"extensions": [
39+
"betterthantomorrow.calva",
40+
"borkdude.clj-kondo"
41+
],
42+
"settings": {}
43+
}
44+
}
45+
}

.devcontainer/post-create.sh

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Datomic Pro install script for devcontainer
4+
#
5+
# 1. Always remove lib/com/datomic/datomic-{type}/<version> if it exists
6+
# 2. Unzip the Datomic zip (from /lib or /tmp, download if missing) into target dir
7+
# 3. Flatten top-level subdir if present (some zips nest contents)
8+
# 4. Run vendor maven-install from bin/
9+
#
10+
# This script does NOT cherry-pick, rename, or check for specific files before extraction.
11+
# All contents of the zip are placed in the target directory, overwriting any previous install.
12+
#
13+
14+
set -euo pipefail
15+
16+
# Source .env from repo root if present (authoritative config)
17+
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
18+
if [ -f "$REPO_ROOT/.env" ]; then
19+
set -a
20+
# shellcheck disable=SC1090
21+
. "$REPO_ROOT/.env"
22+
set +a
23+
fi
24+
25+
# Redirect all output to persistent logs for visibility during Codespace creation
26+
LOG="/tmp/orcpub-post-create.log"
27+
WORKSPACE_LOG="$REPO_ROOT/.devcontainer/post-create.log"
28+
# Ensure workspace log exists and is writable (best-effort)
29+
mkdir -p "$(dirname "$WORKSPACE_LOG")" 2>/dev/null || true
30+
touch "$WORKSPACE_LOG" 2>/dev/null || true
31+
# Tee to both /tmp and workspace log so it's inspectable in Codespaces UI
32+
exec > >(tee -a "$LOG" "$WORKSPACE_LOG") 2>&1
33+
34+
# Optional verbose tracing: set POST_CREATE_VERBOSE=1 to enable `set -x`
35+
if [ "${POST_CREATE_VERBOSE:-0}" = "1" ]; then
36+
echo "[POST-CREATE] Verbose tracing enabled"
37+
set -x
38+
fi
39+
40+
# Timestamp helper
41+
ts() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
42+
log() { echo "$(ts) [POST-CREATE] $*"; }
43+
44+
log "Starting postCreateCommand... (logging to $LOG and $WORKSPACE_LOG)"
45+
46+
# Configuration with defaults
47+
DATOMIC_TYPE="${DATOMIC_TYPE:-pro}"
48+
RAW_DATOMIC_VERSION="${DATOMIC_VERSION:-1.0.7482}"
49+
# basename in case a path was provided (e.g., /tmp/datomic-pro-1.0.7482.zip)
50+
RAW_DATOMIC_VERSION="$(basename "$RAW_DATOMIC_VERSION")"
51+
# strip leading prefix and trailing .zip if present
52+
DATOMIC_VERSION="${RAW_DATOMIC_VERSION#datomic-${DATOMIC_TYPE}-}"
53+
DATOMIC_VERSION="${DATOMIC_VERSION%.zip}"
54+
55+
log "Using DATOMIC_TYPE=$DATOMIC_TYPE, DATOMIC_VERSION=$DATOMIC_VERSION"
56+
57+
# Paths
58+
TARGET_DIR="lib/com/datomic/datomic-${DATOMIC_TYPE}/${DATOMIC_VERSION}"
59+
ZIP_NAME="datomic-${DATOMIC_TYPE}-${DATOMIC_VERSION}.zip"
60+
DOWNLOAD_URL="https://datomic-pro-downloads.s3.amazonaws.com/${DATOMIC_VERSION}/${ZIP_NAME}"
61+
62+
# Clean and prepare target directory
63+
if [ -d "${TARGET_DIR}" ]; then
64+
log "Removing existing installation at ${TARGET_DIR}"
65+
rm -rf "${TARGET_DIR}"
66+
fi
67+
mkdir -p "${TARGET_DIR}"
68+
69+
# Find Datomic zip in /lib/ or /tmp/, download if missing
70+
ZIP_PATH="/lib/${ZIP_NAME}"
71+
if [ ! -f "$ZIP_PATH" ]; then
72+
ZIP_PATH="/tmp/${ZIP_NAME}"
73+
if [ ! -f "$ZIP_PATH" ]; then
74+
log "Downloading Datomic from $DOWNLOAD_URL"
75+
curl --fail --location --progress-bar -o "$ZIP_PATH" "$DOWNLOAD_URL"
76+
fi
77+
fi
78+
79+
# Verify zip integrity (handles corrupt/incomplete downloads)
80+
if ! unzip -t "$ZIP_PATH" >/dev/null 2>&1; then
81+
log "Corrupt or incomplete zip detected, removing and re-downloading..."
82+
rm -f "$ZIP_PATH"
83+
curl --fail --location --progress-bar -o "$ZIP_PATH" "$DOWNLOAD_URL"
84+
85+
# Verify the re-download
86+
if ! unzip -t "$ZIP_PATH" >/dev/null 2>&1; then
87+
log "ERROR: Re-downloaded zip is still corrupt. Check network connection or URL."
88+
log "URL: $DOWNLOAD_URL"
89+
exit 1
90+
fi
91+
fi
92+
93+
# Unzip Datomic distribution into target dir
94+
log "Extracting $ZIP_PATH to $TARGET_DIR"
95+
unzip -q "$ZIP_PATH" -d "${TARGET_DIR}"
96+
97+
# Flatten if needed (some zips nest contents in a subdirectory)
98+
TOP_SUBDIR=$(find "${TARGET_DIR}" -mindepth 1 -maxdepth 1 -type d -print -quit || true)
99+
if [ -n "${TOP_SUBDIR}" ] && [ -z "$(find "${TARGET_DIR}" -maxdepth 1 -type f -print -quit)" ]; then
100+
log "Flattening nested directory structure"
101+
mv "${TOP_SUBDIR}"/* "${TARGET_DIR}/"
102+
rmdir "${TOP_SUBDIR}"
103+
fi
104+
105+
# Run vendor maven-install
106+
if [ -x "${TARGET_DIR}/bin/maven-install" ]; then
107+
log "Running maven-install..."
108+
(cd "${TARGET_DIR}" && bash bin/maven-install)
109+
else
110+
log "ERROR: bin/maven-install not found or not executable in ${TARGET_DIR}/bin"
111+
exit 1
112+
fi
113+
114+
log "Datomic ${DATOMIC_TYPE} ${DATOMIC_VERSION} installed successfully to ${TARGET_DIR}"

.dockerignore

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,18 @@
33
.cache
44
.idea
55
.github
6+
7+
# Secrets — never copy into build context
8+
.env
9+
.lein-env
10+
logs/console.log
611
docker-compose*
712
test/*
813
*.md
914
data/*
1015
log/*
11-
backups/*
16+
backups/*
17+
backup/*
18+
19+
# Datomic Pro distribution (~280MB) — Docker images download their own from S3
20+
lib/com/datomic/

.env.example

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,49 @@
1111
# --- Application ---
1212
PORT=8890
1313

14+
# Image tag for docker-compose.yaml (pre-built images only, ignored by build compose)
15+
# ORCPUB_TAG=release-v2.5.0.27
16+
1417
# --- Datomic Database ---
18+
# Datomic Pro with dev storage protocol (required for Java 21 support)
1519
# ADMIN_PASSWORD secures the Datomic admin interface
1620
# DATOMIC_PASSWORD is used by the application to connect to Datomic
1721
# The password in DATOMIC_URL must match DATOMIC_PASSWORD
1822
ADMIN_PASSWORD=change-me-admin
1923
DATOMIC_PASSWORD=change-me-datomic
20-
DATOMIC_URL=datomic:free://datomic:4334/orcpub?password=change-me-datomic
24+
DATOMIC_URL=datomic:dev://datomic:4334/orcpub?password=change-me-datomic
25+
26+
# --- Transactor Tuning ---
27+
# These rarely need changing. See docker/transactor.properties.template.
28+
# ALT_HOST: peer fallback hostname (default: 127.0.0.1, set to service name for Swarm)
29+
# ENCRYPT_CHANNEL: encrypt peer-transactor communication (default: true)
30+
ALT_HOST=127.0.0.1
31+
ENCRYPT_CHANNEL=true
32+
# Password rotation — set OLD vars during rotation, remove after all peers reconnect
33+
# ADMIN_PASSWORD_OLD=
34+
# DATOMIC_PASSWORD_OLD=
2135

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

41+
# Content Security Policy (strict|permissive|none)
42+
CSP_POLICY=strict
43+
44+
# Dev mode: CSP violations are logged (Report-Only) instead of blocked,
45+
# allowing Figwheel hot-reload scripts to execute.
46+
DEV_MODE=true
47+
48+
# --- Plugins ---
49+
# URL to fetch server-hosted .orcbrew plugins on first page load.
50+
# Leave empty to disable (plugins come only from local file imports).
51+
# LOAD_HOMEBREW_URL=/homebrew.orcbrew
52+
53+
# --- Logs ---
54+
# Defaults to project logs/ if unset
55+
LOG_DIR=
56+
2657
# --- Email (SMTP) ---
2758
# Leave EMAIL_SERVER_URL empty to disable email functionality
2859
EMAIL_SERVER_URL=

.github/workflows/continuous-integration.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ jobs:
164164
165165
- name: Post PR comment with results
166166
if: github.event_name == 'pull_request' && always()
167+
continue-on-error: true # Fork PRs get read-only GITHUB_TOKEN
167168
uses: actions/github-script@v7
168169
with:
169170
script: |

0 commit comments

Comments
 (0)