fix(multiple): three journal-triage fixes (#2316, F17, #2319)#2350
Merged
fix(multiple): three journal-triage fixes (#2316, F17, #2319)#2350
Conversation
…registered project Closes #2316. Before this PR, running `wheels stop` from any directory that isn't a registered project root (parent dir, sibling dir, deleted project dir, anywhere else) silently printed "No running server found for this directory." while the original Java/Catalina process kept listening. The user's only escape hatch was `lsof -i :<port>` + `kill`. This change adds a pre-delegation check in stop(): 1. `$findServerForProject(projectRoot)` scans `~/.wheels/servers/*/.project-path` for an entry whose stored canonical path matches the current cwd. 2. If no match is found, `$listRunningWheelsServers()` enumerates all registered LuCLI server entries with a live PID (parsing the `<pid>:<port>` server.pid format and using `java.lang.ProcessHandle` for liveness without shelling out). 3. When there are running servers but none match the cwd, print a helpful list with each server's name + port + project path, plus the explicit syntax — `wheels server stop --name <name>` and `wheels server list` — that recovers from the orphan state without leaving the wheels CLI. Verified end-to-end on macOS arm64: $ cd /tmp/parent # not a Wheels project $ wheels stop Stopping Wheels server... No registered server matches this directory. Running Wheels servers: - repapp (port 9991, project /private/tmp/parent/repapp) To stop a specific server: wheels server stop --name <name> To list all servers: wheels server list Normal in-project `wheels stop` is unaffected — the registered-server match short-circuits the orphan check and falls through to the regular LuCLI delegation. CLI suite: 457 pass, 3 fail (pre-existing DoctorSpec #2260, unrelated).
…ing-like types
Closes fresh-VM journal F17. Before this PR, `addColumnOptions` in
`vendor/wheels/databaseAdapters/Abstract.cfc` had a special case for
`type='string'` with `default=""` that omitted the DEFAULT clause:
} else if (arguments.options.type == 'string' && arguments.options.default eq "") {
arguments.sql = arguments.sql; // no DEFAULT clause
} else {
arguments.sql = arguments.sql & " DEFAULT ...";
}
…but `text` and `char` columns fell through to the else branch and
emitted `DEFAULT ''`. So a migration that declared title and body
identically:
t.string(columnNames="title", default="", allowNull=true, limit=255);
t.text(columnNames="body", default="", allowNull=true);
…produced asymmetric DDL. That asymmetry then interacted with
`validatesPresenceOf` — which checks the column's introspected
`hasDatabaseColumnDefault` and skips presence-check when a default
exists — making the user's `validatesPresenceOf` rule fire for `title`
(no DEFAULT clause emitted) but silently skip for `body` (DEFAULT ''
emitted). Tutorial chapter 7's model spec `requires a body` failed
because of this; an HTTP request that omits `post[body]` (vs sending
empty string) also slipped past validation.
Fix: extend the special case to cover all string-like types
(`string,text,char`). Empty default → no DEFAULT clause for all three;
explicit non-empty defaults still emit DEFAULT correctly.
Seven new specs in `addColumnOptionsSpec.cfc` cover:
- string/text/char with default="" all omit DEFAULT
- string/text with non-empty default still emit DEFAULT '<value>'
- integer with default="" still becomes DEFAULT NULL (regression for
the existing typed-numeric branch)
- boolean with default=true still emits DEFAULT 1
All 7 pass; framework suite: 3340 pass, 0 fail (was 3333 before).
Closes #2319. Before this PR, when `$runOnError` rendered a Wheels-typed exception (`Wheels.RouteNotFound`, `Wheels.DataSourceNotFound`, `Wheels.ViewNotFound`, etc) in HTML format, no `$header(statusCode = ...)` fired before the body was written. Lucee defaulted to HTTP 200 — misleading anything monitoring, caching, retrying, or alerting on status codes. JSON and XML branches for non-Wheels exceptions had explicit `$header(statusCode = 500)`; the Wheels-error branch and the JSON/XML Wheels-error sub-branches all skipped status assignment. This change adds a single mapping at the top of the wheelsError branch: - Any `Wheels.*NotFound` (RouteNotFound, RecordNotFound, ViewNotFound, PackageNotFound, DataSourceNotFound, …) → 404 - Everything else → 500 The status is set before the body is written so the response header commits at the right code regardless of when the servlet engine flushes. `$throwErrorOrShow404Page` already calls $header(statusCode=404) before throwing, but the onError flow can reset the response, so re-asserting in $runOnError is the durable place. Five new specs in onerrorSpec.cfc lock the mapping table — they mirror the same regex used in EventMethods so a rename there breaks the build immediately. Includes an explicit case for ActionParameterMissing (Missing != NotFound, stays 500) to guard against a too-greedy regex later. Framework suite: 3347 pass, 0 fail (was 3333 before this PR's chain; +7 from F17 specs, +7 from these new mappings). One pre-existing test that hits an unknown route and expects 404 (testClientSpec `assertNotFound() passes on 404 response`) still passes — Wheels.ViewNotFound maps to 404 under the new rule.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three independent fixes from the fresh-VM journal triage. Each is its own commit and each maps to its own issue/finding. Reviewing as one PR because they're all small and conceptually related (post-mortem of the same VM cycle), but they could land separately if reviewers prefer.
Commit 1 — fix(cli): wheels stop lists running servers when cwd doesn't match — closes #2316
Running
wheels stopfrom any directory that wasn't a registered project root (parent dir, sibling dir, deleted project dir) silently printedNo running server found for this directory.while the original Java/Catalina process kept listening.After: when no registered server matches the cwd but other Wheels servers are running, list them with name + port + project path and point users at
wheels server stop --name <name>andwheels server list. Normal in-projectwheels stopis unaffected.Commit 2 — fix(model): migrator emits symmetric DDL for empty default across string-like types — closes journal F17
addColumnOptionshad atype=='string' && default==""special case that omitted the DEFAULT clause, buttextandcharcolumns fell through and emittedDEFAULT ''. That asymmetry madevalidatesPresenceOffire inconsistently between equivalent columns — tutorial chapter 7'srequires a bodyspec failed because of it.After: extend the special case to cover `string,text,char` uniformly. 7 new specs in `addColumnOptionsSpec.cfc`.
Commit 3 — fix(view): wheels-typed error pages set HTTP status (404 / 500), not 200 — closes #2319
`$runOnError` rendered Wheels-typed exceptions in HTML format without setting a status code. Lucee defaulted to 200 — misleading anything monitoring/alerting/retrying on status codes.
After: any `Wheels.*NotFound` → 404, everything else → 500. Status set before the body so the response header commits at the right code. 5 new specs in `onerrorSpec.cfc` lock the mapping table.
Verification
Also closed during triage (no PR needed)
Deferred
🤖 Generated with Claude Code