#!/usr/bin/env bash
# The committed dist/ must be exactly what a fresh build of src/ produces —
# a stale dist would ship behavior the sources don't show.
set -euo pipefail
cd "$(dirname "$0")/.."
# a stale in-tree shadow cache can mask clean-clone divergence: a warm
# incremental build assigns Closure property renames from a slightly different
# pool than a cold one (dev/docs/CLJS.md)
rm -rf .shadow-cljs
npm run --silent build >/dev/null
if [ -n "$(git status --porcelain dist)" ]; then
echo "ABORT: dist/ is stale — commit the rebuilt output first:" >&2
git status --porcelain dist >&2
exit 1
fi
# macOS home-dir prefix, built from pieces: the published bytes of this
# script must never contain the pattern the idpat leak scan hunts for
LEAKPAT='/Use''rs/'
if grep -rF "$LEAKPAT" dist; then
echo "ABORT: local filesystem path embedded in dist/" >&2
exit 1
fi
# ---- THE TWO-STACK LAW (the suite's house rule 11) --------------------------
# rooms-kit is the libp2p v2 / @ipshipyard/node-datachannel 0.26 side. peer-kit
# is libp2p v3 / node-datachannel 0.33. The two load different builds of
# libdatachannel, and two copies of that native library in ONE process abort it
# (ThreadSafeCallback cancellation) — which is why the bot runs chat/board rooms
# in a forked worker. npm deps stay external imports here, so the emitted
# bundles name every stack they pull; grep them.
for bad in "ardegazu-peer-kit" '"node-datachannel"' "from\"node-datachannel\""; do
if grep -rF "$bad" dist; then
echo "ABORT: dist/ imports '$bad' — that is the OTHER WebRTC stack (rule 11)" >&2
exit 1
fi
done
# libp2p v3's family carries names the v2 stack we use does not have; any of
# them in the emitted bundles means a v3 dependency slipped in.
for bad in "@libp2p/gossipsub" "@libp2p/utils"; do
if grep -rF "$bad" dist; then
echo "ABORT: dist/ names '$bad' — a libp2p v3-era specifier (rule 11)" >&2
exit 1
fi
done
# ... and the v2 stack MUST still be the one that is named, or the greps above
# are passing for the wrong reason (e.g. an accidentally bundled dependency).
for want in "@chainsafe/libp2p-gossipsub" "@libp2p/webrtc" "@libp2p/websockets" "@orbitdb/core" "helia"; do
if ! grep -rqF "$want" dist; then
echo "ABORT: dist/ does not import '$want' — the v2 stack must stay EXTERNAL," >&2
echo " not bundled: a bundled native is exactly what rule 11 forbids." >&2
exit 1
fi
done
echo "two-stack gate: OK (v2 stack external, no peer-kit / node-datachannel / libp2p-v3 specifiers)"
# The vendored id copy is gone: ardegazu-id-kit is a real sha-pinned npm dep,
# consumed as ClojureScript source off the classpath (deps.edn). Guard the
# retirement — a hand-maintained copy under src/ is what must never come back.
if [ -e src/vendor ] || [ -e deploy/check-vendor.sh ] || [ -e deploy/vendor.sha256 ]; then
echo "ABORT: vendored id sources reappeared — consume ardegazu-id-kit, don't copy it" >&2
exit 1
fi
if ! grep -q '"ardegazu-id-kit": "git+https://git.ardegazu.ro/id-kit.git#' package.json; then
echo "ABORT: ardegazu-id-kit must be a sha-pinned git dep (never file:/local path)" >&2
exit 1
fi
if grep -rqE '"(file|link):' package.json; then
echo "ABORT: local-path dependency in package.json" >&2
exit 1
fi
# INVERTED at the pure-CLJS migration, deliberately. This used to REQUIRE
# dist/index.js to import ardegazu-id-kit, on the reasoning that Identity had to
# be the dist's class object. Our own kits are ClojureScript libraries now: they
# are compiled from source, exactly once per build, so an import of the id-kit
# PACKAGE in the emitted bundles means the hybrid crept back — a dist import
# alongside the classpath sources, i.e. two compiles of the same code in one
# graph. Foreign packages are the only thing that may appear as imports here.
if grep -rF 'ardegazu-id-kit' dist; then
echo "ABORT: dist/ imports the ardegazu-id-kit PACKAGE — id-kit is consumed as" >&2
echo " ClojureScript source off the classpath (deps.edn), so a package" >&2
echo " import means a second compiled copy in the same build" >&2
exit 1
fi
# ... and the sources must actually be reachable, or the grep above passes for
# the wrong reason (a build that quietly stopped compiling id-kit at all).
if [ ! -f node_modules/ardegazu-id-kit/src/ardegazu/id/identity.cljs ]; then
echo "ABORT: ardegazu-id-kit's CLJS sources are not installed — deps.edn puts" >&2
echo " node_modules/ardegazu-id-kit/src on the classpath" >&2
exit 1
fi
if ! grep -qF 'node_modules/ardegazu-id-kit/src' deps.edn; then
echo "ABORT: deps.edn no longer classpaths ardegazu-id-kit's src" >&2
exit 1
fi
echo "vendor-retirement gate: OK (id-kit is a sha-pinned dep, compiled from source not copied)"
echo "check-dist: OK (committed dist matches a cold build, no local paths)"