Repository navigation
Warlock.js 5.39.1
Released 2026-10-26.
All 33 packages (@warlock.js/* and create-warlock) move to 5.39.1 together;
keep every family package on the same version. No breaking changes. This is a fix
release for test-run exits, migrations, standalone builds and log channels.
1. Breaking changes
- None. 5.39.1 has no breaking changes.
2. Test runs exit promptly (core, scheduler)
- Running schedulers are stopped on shutdown. An app that calls
scheduler.start()
while its modules load (the stock template does this) kept the Vitest main process
alive after the HTTP test server stopped. Vitest then waited out its 10-second close
timeout and printedsomething prevents N Vite servers from exiting. The shutdown of
the HTTP test server,warlock startand per-worker test teardown now stop every
running@warlock.js/schedulerscheduler withinapp.shutdownTimeout. scheduler.shutdown()clears its own cap timer when the jobs finish first, so it
no longer holds the process open for up to 30 seconds.- If the message still appears, a handle the app opens itself (an interval, a socket, a
queue worker) is keeping the process alive.npx vitest run --reporter=hanging-process
names it.
3. Migrations close cleanly and never stall silently (core, cascade)
warlock migratereleases the migration lock and closes every data source before
it exits: on success, on failure, with--pending, and onCtrl+C/SIGTERM(exit
130 / 143). Shutdown has a bounded wait, so it cannot hang.- Connecting to MongoDB is bounded (30 s for server selection) and fails with a clear
message instead of hanging atConnecting to database. A stalled graceful close falls
back to a forced close after 10 s. - Long migrations report progress. A migration that runs long prints
still running "<name>", step N of M, <n>s elapsedat 30 s and then every 60 s.
Migrations are not aborted by default, so a long index build is never left half-applied. - Opt-in hard limit.
warlock migrate --timeout <seconds>(or
WARLOCK_MIGRATION_TIMEOUT_MS, in milliseconds) fails a migration that exceeds the limit,
naming it, and exits 1. - Partial failures are explained. A failed migration names the migration and, on
MongoDB, the step (step 3 of 5). It says that no ledger row was written, how many steps
were applied, and how to recover: re-running is safe because index creation is
idempotent, or--rollbackstarts over.
4. Standalone builds (core)
- Vite is no longer bundled when the app lists it under
devDependencies. Only
dependencies,optionalDependenciesandpeerDependenciescount as declared by the
app. This removes about 60 MB of bundled Vite and therolldownandlightningcss
native addons fromdist/. - Build-time tools stay out of the bundle.
vite,rolldown,lightningcss,
esbuild,oxc-parser,@vitejs/*and@babel/*(except@babel/runtime) are never
bundled or staged when framework code imports them, even when the app lists them under
dependencies. A third-party library that imports one at module level is still bundled,
so it keeps working with nonode_modules. - Aliased native packages are staged under the imported name. A package installed as
"node-pty": "npm:@lydell/node-pty"is copied todist/node_modules/node-pty, so the
import resolves fromdist/. - Only reachable native packages are staged, and the build warns about a native package
it could not copy because itsos,cpuorlibcexcludes the build machine.
5. Log channels (logger)
LogChannel.readyresolves once the channel's deferredinit()has finished. Await
it before relying on the channel being set up.- A channel disposed before its deferred
init()ran no longer creates its directory or
arms the 5-second flush interval afterwards.
6. Upgrade notes
- Update the family. Run
npx warlock update. - Read what changed. Run
npx warlock release-notes --from 5.39.0. - Remove workarounds (if added). Drop any
build.externalentries forvite,
rolldownorlightningcss, any manualscheduler.shutdown()call in test teardown,
and any raised VitestteardownTimeoutadded for slow exits. - Set a migration limit (optional). In CI, pass
warlock migrate --timeout <seconds>
if you prefer a failed run to a slow one.