Hwaro::Services::Server
Constants
Debounce interval: after detecting changes, wait this long for additional changes to settle before triggering a rebuild.
Cap on the build-failure text that reaches the terminal and the browser overlay. Crinja quotes the offending source lines in its message, so a single very long line near a syntax error (a minified vendor bundle inlined in a template, a generated data blob) produces a multi-megabyte message: the watcher repainted the console with it on every save — one broken template grew a serve log to 12 MB — and pushed the same payload over the live-reload socket. A few thousand characters is far more than the overlay can usefully show and still carries the error type, file and position, which is what the developer actually reads.
Maximum number of debounce iterations before forcing a rebuild. Prevents indefinite blocking when files are being written continuously.
prev is the previous snapshot, used only to carry data/i18n digests
forward without re-reading files whose stamps are unchanged (see
watch_digest). Passing nil — the baseline scan, or a caller without a
previous snapshot — computes them fresh.
RFC 3986 pchars besides ALPHA / DIGIT, plus the segment separator.
Polling interval for the file watcher.
Extensions whose served bytes are UTF-8 text, each with the base type to assume when the platform's MIME database has no opinion.
Registering the charset in the MIME table makes HTTP::StaticFileHandler
emit it directly, which is the only thing that works for responses past
the response output buffer (IO::DEFAULT_BUFFER_SIZE, 32 KiB) — a
post-call_next header edit is too late there, so a 40 KB
search.json used to lose its charset entirely. .html/.htm matter
most: HTML is the site's primary content type and with
--no-live-reload (or any page the injector doesn't match) it goes out
through StaticFileHandler like any other file, so a 60 KB CJK page
rendered as mojibake.
One list with one rule — deliberately NOT split on "does stdlib map
this extension?". That question has a platform-dependent answer:
Crystal seeds MIME::DEFAULT_TYPES (which already carries charsets)
and then lets the OS database override it, so macOS reads
/etc/apache2/mime.types and reports .md as nil while Linux reads
/etc/mime.types and reports text/markdown. Keying behaviour on that
split left these extensions with no charset at all on Linux — the very
bug the fallback existed to fix, invisible on macOS.
The project directories the watcher always scans, in the order the
serve receipt lists them. [assets] source_dir can add one more —
see @extra_watch_roots.
Paths matching these regexes are treated as editor byproducts
(backups, swap files, autosaves, OS metadata) and are excluded
from the watcher. Editors using rename-based atomic save or
keep-a-backup patterns (vim's default, sed -i.bak, emacs,
JetBrains, …) used to double-trigger rebuilds — once for the
real edit and once for the byproduct — and each event forced a
full rebuild (see server.cr :full strategy fallback).
Constructors
Class methods
Ensure every listed extension carries charset=utf-8 whatever the
platform's database says: append to the system's base type when it has
one, use ours when it does not. Never overrides a system type beyond
adding the charset, never double-appends, and is idempotent — a second
pass sees the charset already there and skips.
Only ever called from the dev server, so the built output and every other command keep stdlib's MIME table untouched.