Skip to content

feat: add package system (PackageLoader) and first-party packages#1995

Merged
bpamiri merged 16 commits intodevelopfrom
peter/plugins-sentry-hotwire-basecoat
Mar 26, 2026
Merged

feat: add package system (PackageLoader) and first-party packages#1995
bpamiri merged 16 commits intodevelopfrom
peter/plugins-sentry-hotwire-basecoat

Conversation

@bpamiri
Copy link
Copy Markdown
Collaborator

@bpamiri bpamiri commented Mar 26, 2026

Summary

  • New package system: PackageLoader.cfc discovers vendor/*/package.json on startup with per-package error isolation, mixin collection, ServiceProvider/middleware support
  • Moved plugins to packages: sentry, hotwire, basecoat now live in packages/ with package.json manifests (replacing plugin.json). Activate by copying to vendor/
  • Deprecation path: plugins/ still works via existing Plugins.cfc but logs a deprecation warning
  • CI: per-package test step copies each package to vendor/, runs its specs, cleans up
  • Build: packages/ included in release artifact

Architecture

packages/           # First-party optional (NOT auto-loaded)
  sentry/           # wheels-sentry
  hotwire/          # wheels-hotwire
  basecoat/         # wheels-basecoat
vendor/             # Runtime: framework core + activated packages
  wheels/           # Framework core (excluded from package discovery)
  (sentry/, etc.)   # Activated packages appear here
plugins/            # DEPRECATED: legacy plugins still work with warning

Test plan

  • Lucee 7 + H2: 2268 pass, 0 fail, 0 error
  • Lucee 6 + H2: 2268 pass, 0 fail, 0 error
  • Package activation: copy basecoat to vendor/, app starts, core tests unaffected
  • Error isolation: broken package in vendor/ logged and skipped, app continues
  • CI matrix runs per-package tests across all engines

🤖 Generated with Claude Code

bpamiri and others added 12 commits March 26, 2026 08:28
20-task plan covering polish for SentryForWheels, finishing Hotwire's
missing helper, and building Basecoat Phases 2-5 (dialog, field,
table, tabs, dropdown, pagination, sidebar, breadcrumb).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds the Wheels 3.x plugin.json manifest to suppress deprecation warnings
and an index.cfm status/reference page for the plugin admin UI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add plugin.json manifest to suppress Wheels 3.x deprecation warning.
Fix mixin attribute: remove invalid dispatch and microsofttablehelper scopes,
leaving only controller and view.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ile handle leak, timestamp

- Change $sentryGetUser() from public to private ($ prefix = internal)
- Wrap initSentry() body in named exclusive lock to prevent double-init races
- Fix HTTP status check: Left(statuscode,3) != "200" instead of find("200",...)
- Fix file handle leak: replace fileOpen/fileReadLine/fileClose with FileRead+ListToArray in try/catch
- Add Z suffix to ISO 8601 timestamp in getTimeVars()

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove 'culprit' key from exception event payload (deprecated in SDK v7)
- Change exception type from 'exType & " Error"' to just 'exType' to avoid
  double-labeling (e.g., "Application Error Error")

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Renders JSON path configuration for Hotwire Native apps. Accepts optional
settings struct (tabs, etc.) and rules array. Falls back to sensible defaults:
all pages use default context with pull-to-refresh; /new$ and /edit$ paths
open as modals without pull-to-refresh.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…mp, user context, breadcrumbs

Covers:
- DSN parsing via public API (valid modern, valid legacy, invalid throws)
- ISO 8601 Z-suffix timestamp format
- sentrySetUser stores and overwrites request.sentryUserOverride
- addBreadcrumb appends in order and includes optional data struct
- getEnvironment/getRelease accessors return init values

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Covers all public helpers: hotwireIncludes, turboFrame/turboFrameEnd,
all 8 turbo stream actions (verifying template presence/absence on remove
and refresh), and all 4 Stimulus attribute helpers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…E.md

- Add plugin.json with correct metadata (mixins: controller,view, wheelsVersion: 3.0)
- Fix Basecoat.cfc mixin attribute: remove stale dispatch and microsofttablehelper scopes
- Replace Hotwire-content ARCHITECTURE.md with Basecoat-specific architecture doc
- Add Phase 2 dialog family (uiDialog, uiDialogFooter, uiDialogEnd) with native <dialog>, ARIA attributes, optional trigger button
- Add Phase 3 uiField with full type support: text/email/password/number/tel/url/textarea/select/checkbox/switch; error state; description; auto-generated IDs
- Add Phase 4: uiTable family, uiTabs family, uiDropdown (CSS-only details/summary), uiPagination with ellipsis/window logic
- Add Phase 5: uiBreadcrumb family, uiSidebar family

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- BasecoatSimpleSpec: Phase 1+2 — button class construction (compound variants, icon-only, anchor, turboConfirm, disabled), badge variants, alert (title/description/destructive), card family, progress, spinner, skeleton, tooltip, separator
- BasecoatComplexSpec: Phase 2-5 — dialog ARIA attributes (labelledby/describedby, ID matching, trigger/no-trigger, close button), field layout (label-above vs flex-row for checkbox/switch, error state, description, auto-IDs), table wrappers, tabs data-attributes, dropdown details/summary, pagination (disabled prev/next, window, current page), breadcrumb (aria-label, linked/current), sidebar (active state, icons, section heading)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…wheels-basecoat

Rename SentryForWheels/ folder to sentry/, rename SentryForWheels.cfc
to Sentry.cfc, update all internal component paths, plugin.json names,
box.json slugs, and documentation references.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added docs dependencies Pull requests that update a dependency file labels Mar 26, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Wheels Test Matrix

Engine MySQL PostgreSQL SQL Server H2 CockroachDB Oracle SQLite
lucee6 -- -- -- -- -- -- --
lucee7 -- -- -- -- -- -- --
adobe2023 --
adobe2025 --
boxlang -- -- -- -- -- -- --

Results for commit 31d05e9.

@github-actions
Copy link
Copy Markdown
Contributor

Wheels Test Results

    12 files   -     20   1 120 suites   - 2 240   5m 7s ⏱️ - 10m 8s
22 160 tests  - 44 344  22 068 ✅  - 43 939  92 💤  - 198  0 ❌  - 84 
22 800 runs   - 45 624  22 708 ✅  - 45 210  92 💤  - 198  0 ❌  - 93 

Results for commit 8630129. ± Comparison against base commit 5b30582.

This pull request removes 44344 tests.
boxlang/cockroachdb :: $formatSSEEvent internal method ‑ does not include empty optional fields
boxlang/cockroachdb :: $formatSSEEvent internal method ‑ formats data-only event
boxlang/cockroachdb :: $formatSSEEvent internal method ‑ formats event with all fields in correct order
boxlang/cockroachdb :: $formatSSEEvent internal method ‑ formats event with type
boxlang/cockroachdb :: $formatSSEEvent internal method ‑ handles empty data string
boxlang/cockroachdb :: $generatedKey ‑ returns lastId
boxlang/cockroachdb :: $get() tenant config override ‑ returns application value when tenant has no override for that key
boxlang/cockroachdb :: $get() tenant config override ‑ returns tenant config value when set
boxlang/cockroachdb :: $getType ‑ delegates integer to PostgreSQL parent
boxlang/cockroachdb :: $getType ‑ delegates text to PostgreSQL parent
…

@bpamiri bpamiri marked this pull request as draft March 26, 2026 20:40
bpamiri and others added 2 commits March 26, 2026 13:55
Replace the legacy plugins/ directory with a new packages/ → vendor/ activation
model. PackageLoader discovers vendor/*/package.json on startup with per-package
error isolation, collects mixins into the existing injection pipeline, and supports
ServiceProvider and middleware registration.

- Add vendor/wheels/PackageLoader.cfc for package discovery and loading
- Move sentry, hotwire, basecoat from plugins/ to packages/
- Replace plugin.json with package.json (adds provides.mixins/services/middleware)
- Wire $loadPackages() into onapplicationstart.cfc and EventMethods.cfc
- Add deprecation warning when plugins/ directory has loaded plugins
- Tested: Lucee 6 + Lucee 7 × H2 = 2268 pass, 0 fail, 0 error

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add "Run per-package tests" step to CI that copies each package to
  vendor/, restarts the engine, runs the package's test specs, then
  cleans up. Uses h2 for Lucee, sqlite for others. Non-blocking warnings.
- Update prepare-base.sh to include packages/ in release artifact.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added enhancement javascript Pull requests that update javascript code labels Mar 26, 2026
@bpamiri bpamiri changed the title feat: add first-party plugins — wheels-sentry, wheels-hotwire, wheels-basecoat feat: add package system (PackageLoader) and first-party packages Mar 26, 2026
bpamiri and others added 2 commits March 26, 2026 14:01
SQLite works across all engines (Lucee, Adobe, BoxLang) unlike H2 which
is Lucee-only. Standardize on sqlite as the embedded DB for package tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add PackageLoaderSpec.cfc with 10 BDD specs covering discovery, error
  isolation, manifest parsing, and mixin collection
- Add test fixtures in tests/_assets/packages/ (goodpkg, brokenpkg,
  nomanifest, nomixin)
- Add componentPrefix param to PackageLoader.init() for test flexibility
- Create packages/sentry/CLAUDE.md
- Update packages/hotwire/CLAUDE.md and packages/basecoat/CLAUDE.md to
  reflect package architecture (s/Plugin/Package/)
- Add Package System section to main CLAUDE.md with activation docs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bpamiri bpamiri marked this pull request as ready for review March 26, 2026 21:07
@bpamiri bpamiri merged commit 7db5a71 into develop Mar 26, 2026
6 of 7 checks passed
@bpamiri bpamiri deleted the peter/plugins-sentry-hotwire-basecoat branch March 26, 2026 21:07
bpamiri added a commit that referenced this pull request Apr 21, 2026
…ding, glossary (#2181)

* docs(docs): phase 2c plan — ship deployment, contributing, upgrading, glossary

Closes the gap flagged in the post-merge correction on PR #2169: those four
sections shipped as placeholder stubs only, not the content the PR body
described. Plan scopes 14 pages (6 Deployment + 4 Contributing + 3 Upgrading
+ Glossary rewrite) plus sidebar wiring, scoped .ai/ audit, and completion
report.

Scope decisions recorded in the plan:
- Deployment teaches user-authored Dockerfiles + nginx/systemd (no
  wheels docker/wheels deploy commands fabricated — neither exists in v4)
- Kamal port: one sentence + link from deployment/index.mdx to the
  implementation plan, with grep-able TODO to swap to PR URL later
- Dockerfile reference is Lucee 7 canonical; others mentioned in a note
- upgrading/2x-to-3x is a ~1-screen pointer to v3.0 guides
- Glossary hand-curated from Phase 2a/2b terms, ~30-50 entries
- .ai/ audit scoped to Phase 2c topics, not a full sweep

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(docs): deployment/index — landing page for deployment & operations

Explains the two deployment models Wheels supports today (Docker, VM) and the
"what the framework gives you vs what you assemble" boundary. Notes that
wheels deploy (Kamal port) is in active development, with a grep-able TODO
to swap the placeholder for a PR/issue link once one exists.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(docs): deployment/production-config — how to configure wheels for prod

Covers config/environment.cfm + settings.cfm production overrides, env-var
resolution via application.wo.env() (framework → .env file → JVM env), the
auto-flips production applies (showErrorInformation=false, caching on,
autoMigrateDatabase=false), and a 10-item pre-boot checklist with source
anchors in the framework CFCs that enforce each item.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(docs): deployment/docker-deployment — write a production dockerfile

Teaches packaging a wheels app as a docker image. Multi-stage dockerfile
(node builder + lucee/lucee:7-tomcat10-jre21 runtime), .dockerignore,
compose with redis sidecar and required-env guards, split /health + /ready
endpoints, image-size tips, multi-arch buildx, and Adobe/BoxLang base-image
swap hints. Explicit that wheels docker/wheels deploy do not exist in 4.0 —
readers use plain docker and docker compose CLIs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(docs): deployment/vm-deployment — lucee 7 on a linux vm

Covers lucee 7 + java 21 install, /opt/myapp/{current,releases,shared}
release layout, systemd unit (User=lucee, EnvironmentFile, Restart=on-failure),
nginx reverse proxy with TLS termination, and a zero-downtime rsync → migrate
→ ln -sfn swap sequence. CommandBox fallback noted for teams that prefer
box server. No fabricated wheels commands — plain ssh, rsync, systemctl.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(docs): deployment/security-hardening — framework security primitives

Documents every header + setting in vendor/wheels/middleware/SecurityHeaders.cfc
with source line citations, the CSRF enforcement path (authenticityTokenField
→ $runCsrfProtection → $verifyAuthenticityToken), HSTS auto-default in
production, trusted proxy handling, reloadPassword rotation, and secret
management. Flags the missing HSTS off-switch as a known limitation linked
to issue #2174 rather than fabricating a non-existent parameter.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(docs): deployment/observability — requestid, sentry, health checks

Covers the RequestId middleware (X-Request-Id, UUID per request), structured
logging patterns, a minimal Health controller with /healthz + /readyz split,
Sentry package activation (cp -r packages/sentry vendor/sentry) with what it
instruments and the known job-error gap, and external APM options (Datadog,
New Relic, OpenTelemetry) since wheels ships no first-party metrics.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(docs): contributing/index — landing page for contributing & project

Explains project governance (core team via git log — no CODEOWNERS file yet),
the four ways to contribute (code, docs, packages, issue triage), and links
the existing CODE_OF_CONDUCT.md (Contributor Covenant v2.0). CardGrid to
pull-requests, coding-standards, writing-docs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(docs): contributing/pull-requests — fork, branch, test, submit

Step-by-step PR workflow. Cites commitlint.config.js directly for the valid
types + scope-enum (23 scopes spanning model, controller, view, router,
middleware, migration, cli, test, config, di, job, mailer, plugin, sse,
seed, docs, web, web/ui, web/landing, web/blog, web/guides, web/api,
web/starlight). Requires bash tools/test-local.sh before push.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(docs): contributing/coding-standards — camelcase + cross-engine compat

Covers camelCase naming, component access modifiers (public for mixin
integration, $-prefix for internal scope), and the top cross-engine gotchas
from .ai/wheels/cross-engine-compatibility.md: struct.map() collision,
Adobe CF application scope, closure this, bracket-notation function calls
in closures, array-by-value in struct literals, createDynamicProxy Lucee
7 semantics, and the private mixin function trap.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(docs): contributing/writing-docs — how to author a guide page

Walks a contributor through the docs workflow: frontmatter shapes (howto,
reference, section), Diátaxis typing, the three {test:*} directives sourced
from scripts/verify-docs/VALIDATION.md (compile, cli, tutorial), running
pnpm verify:docs + pnpm build locally, and sidebar wiring via the version
JSON file. Close with the common mdx/cfml gotchas that trip up first-time
contributors.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(docs): upgrading/index — landing with versioning policy

Framework version sourced from vendor/wheels/events/onapplicationstart.cfc
(application.\$wheels.version = 4.0.0). CHANGELOG.md header confirms
Keep-a-Changelog + SemVer. Release cadence described from actual git tag
history (no fabricated schedule). CardGrid to 3x-to-4x (critical) and
2x-to-3x (pointer).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(docs): upgrading/3x-to-4x — the critical upgrade page

Documents every 3.x → 4.0 breaking change with CHANGELOG + PR citations:
CORS deny-all (#2039), HSTS production default (#2081), CSRF key required
(#2079, #2086), allowEnvironmentSwitchViaUrl production flip (#2076),
RateLimiter trustProxy=false (#2024, #2088), CSRF SameSite cookie (#2035),
wheels snippets → wheels code (#1852), wheels.Test → wheels.WheelsTest
(#1889), tests/specs/functions/ → functional/ (#1872), wirebox → wheelsdi
(#1888). Deprecations: plugins/ (#1995), paginationLinks (#1930),
RocketUnit (#1925), HTTP MCP endpoint. Removed: RocketUnit core, Railo
shim (#1987), server.cfc (#1902). Worked example of plugin → package
port with provides.mixins explicit opt-in.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(docs): upgrading/2x-to-3x — pointer to v3 guides

Short pointer (~200 words). Directs readers to the frozen v3.0 guides for
the 2→3 hop and the sibling 3x-to-4x page for the second hop. Explains
why skipping intermediate upgrades is expensive: each major's breaking
changes assume the previous version's semantics.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(docs): glossary — 45 terms harvested from phase 2a/2b pages

Alphabetized reference with one-sentence definitions and links back to
the guide page where each concept is fully explained. Curated from
core-concepts, basics, and digging-deeper pages. Terms cut as too
generic (Controller, View, Model standalone) or lacking a conceptual
anchor in Phase 2a/2b (Mailer, WheelsTest, Strong params). Automation
deferred to a later polish pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(docs): sidebar — wire phase 2c pages into v4 nav

Populates three previously-empty sidebar groups with the new Phase 2c
pages: Deployment & Operations (5 child items), Contributing & Project
(3 child items), Upgrading (2 child items). Glossary entry unchanged —
it's already a single-link row.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(docs): .ai/ audit — delete files superseded by phase 2c

Phase 2c deployment/production-config.mdx and deployment/security-hardening.mdx
now cover the same territory with cited source anchors. Kept
.ai/wheels/security/https-detection.md (scoped to the isSecure() controller
helper, not deployment configuration) and .ai/wheels/cross-engine-compatibility.md
(contributor-facing reference used by contributing/coding-standards.mdx).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(docs): phase 2c completion report

16 commits, 14 content pages (6 deployment + 4 contributing + 3 upgrading
+ 1 glossary rewrite), sidebar wired, 2 .ai/ files retired. Final build
green at 340 pages; verify:docs green at 43/43 tagged blocks. Per-page
drift captured with source-verification wins and six carryover items
for follow-up work.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(docs): address phase 2c final review findings

Three findings from pr-review-toolkit:code-reviewer:

1. upgrading/3x-to-4x.mdx — removed fabricated SecurityHeaders(hsts=false)
   API call. vendor/wheels/middleware/SecurityHeaders.cfc has no hsts boolean;
   real parameter is strictTransportSecurity (string), and empty string
   auto-falls-back to the production default. Page now honestly notes the
   off-switch gap (#2174) with a "strip at your reverse proxy" workaround.

2. deployment/docker-deployment.mdx — fixed broken LinkCard href from
   core-concepts/middleware/ (no such page) to core-concepts/middleware-pipeline/.

3. contributing/coding-standards.mdx — replaced broken LinkCard href pointing
   at non-existent troubleshooting/cross-engine-compatibility/ with a link
   to contributing/pull-requests (sibling page).

Build + verify:docs green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(docs): vm-deployment — correct github org + branch in dockerfile link

Legacy `cfwheels/cfwheels` org and `main` branch — the repo is
`wheels-dev/wheels` and the default branch is `develop`.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file docs enhancement javascript Pull requests that update javascript code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant