You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Semver-aware dependency resolution for plugins #1982
The current dependency system ($determineDependency()) only checks whether a named plugin is loaded — it cannot express version constraints. A plugin declaring dependency="authenticateThis" succeeds even if the loaded version is incompatible.
Current Behavior
// Plugins.cfc ~line 198-213
// Checks: does a plugin with this name exist in the loaded plugins struct?
// No version comparison whatsoever
Replace the current presence-only dependency check ($determineDependency() in Plugins.cfc:198-213) with semver-aware version constraint resolution, so plugins can declare version requirements like ">=1.0.0 <2.0.0" against their dependencies.
Merit Assessment
Recommendation: Proceed with modifications
Real problem: The current $determineDependency() only checks StructKeyExists(variables.$class.plugins, name) — it has no concept of versions. A plugin requiring authenticateThis 2.x will silently load with 0.9.x, leading to runtime errors.
Semver is the right answer: The ecosystem (box.json, npm, Cargo) has standardized on semver constraints. Plugin authors already declare versions in box.json — they just can't constrain against them.
Scope concern: Implementing a full semver parser (^, ~, range intersections) in CFML is non-trivial. Recommend starting with a subset: >=, >, <=, <, =, and exact match. Defer ^ and ~ shorthand to a follow-up or implement them as syntactic sugar that expands to range expressions.
Implementation Plan
Create vendor/wheels/utils/Semver.cfc — A lightweight utility with:
Development/testing/maintenance environments: Throw a clear error: "Plugin 'X' requires 'Y' >=1.0.0 <2.0.0 but version 0.9.2 is loaded"
Production: Log warning, add to variables.$class.dependantPlugins (existing pattern), do not throw.
Handle missing version: If a dependency plugin has no version metadata (no box.json, no plugin.json), treat as "unknown" and:
Dev: warn that version constraint cannot be verified
Production: allow (assume compatible)
Tests — Unit test Semver.cfc exhaustively (this is pure logic, easy to test): comparisons, range satisfaction, edge cases (0.x, pre-release, missing patch). Integration test with mock plugins declaring version constraints.
Estimated complexity: Medium (3-4 days — mostly the semver parser + tests).
Dependencies & Risks
Depends on Add plugin.json manifest support alongside box.json #1976 (plugin.json manifest) for the dependencies declaration format. Without plugin.json, constraints can only come from CFC metadata attributes (ugly but possible as a stopgap).
Version source reliability:$pluginMetaData() currently reads version from box.json only. Many existing plugins may not have box.json or may have stale versions. This feature is most useful once Add plugin.json manifest support alongside box.json #1976 (plugin.json) provides a canonical version source.
Semver edge cases: CFML doesn't have a semver library. The parser must handle: missing patch (1.0 → 1.0.0), leading v prefix, pre-release labels (ignore initially). Keep the initial implementation strict and well-tested.
No circular dependency detection: The current system (and this proposal) checks dependencies after all plugins load. Circular version constraints (A requires B >=2, B requires A >=2) won't cause infinite loops but should produce a clear error. Consider adding cycle detection as a follow-up.
Breaking change risk: None for existing plugins (legacy dependency attribute falls back to presence check). New behavior only activates when plugin.json declares versioned dependencies.
Automated analysis by @claude — review and adjust as needed.
Activity
bpamiri commentedon Mar 16, 2026
Analysis
Synopsis
Replace the current presence-only dependency check (
$determineDependency()inPlugins.cfc:198-213) with semver-aware version constraint resolution, so plugins can declare version requirements like">=1.0.0 <2.0.0"against their dependencies.Merit Assessment
Recommendation: Proceed with modifications
$determineDependency()only checksStructKeyExists(variables.$class.plugins, name)— it has no concept of versions. A plugin requiring authenticateThis 2.x will silently load with 0.9.x, leading to runtime errors.^,~, range intersections) in CFML is non-trivial. Recommend starting with a subset:>=,>,<=,<,=, and exact match. Defer^and~shorthand to a follow-up or implement them as syntactic sugar that expands to range expressions.Implementation Plan
Create
vendor/wheels/utils/Semver.cfc— A lightweight utility with:parse(versionString)— returns struct{major, minor, patch}(strip leadingv, ignore pre-release labels initially)satisfies(version, constraint)— evaluates a single constraint (e.g.,>=1.0.0)satisfiesAll(version, constraintString)— splits space-separated constraints and ANDs them (e.g.,">=1.0.0 <2.0.0")compare(v1, v2)— returns -1, 0, 1Replace
$determineDependency()(Plugins.cfc:198-213):plugin.jsonwithdependencies(struct of{name: constraintString}), use semver resolution.dependencyattribute (current behavior), fall back to presence-only check.variables.$class.pluginMeta[name].version(already populated frombox.jsonby$pluginMetaData()at line 184-196, and fromplugin.jsononce Add plugin.json manifest support alongside box.json #1976 lands).Error behavior:
"Plugin 'X' requires 'Y' >=1.0.0 <2.0.0 but version 0.9.2 is loaded"variables.$class.dependantPlugins(existing pattern), do not throw.Handle missing version: If a dependency plugin has no version metadata (no box.json, no plugin.json), treat as "unknown" and:
Tests — Unit test
Semver.cfcexhaustively (this is pure logic, easy to test): comparisons, range satisfaction, edge cases (0.x, pre-release, missing patch). Integration test with mock plugins declaring version constraints.Estimated complexity: Medium (3-4 days — mostly the semver parser + tests).
Dependencies & Risks
dependenciesdeclaration format. Without plugin.json, constraints can only come from CFC metadata attributes (ugly but possible as a stopgap).$pluginMetaData()currently reads version frombox.jsononly. Many existing plugins may not have box.json or may have stale versions. This feature is most useful once Add plugin.json manifest support alongside box.json #1976 (plugin.json) provides a canonical version source.1.0→1.0.0), leadingvprefix, pre-release labels (ignore initially). Keep the initial implementation strict and well-tested.dependencyattribute falls back to presence check). New behavior only activates whenplugin.jsondeclares versioned dependencies.Automated analysis by @claude — review and adjust as needed.
bpamiri commentedon Mar 25, 2026
Implemented in develop.
89dd99ffeat: semver-aware dependency resolution for plugins (wh-0cf)