cura 0.11.0
cura: ^0.11.0 copied to clipboard
CLI tool to audit Flutter/Dart package health, dependency scores, and maintenance status.
Changelog #
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Unreleased #
0.11.0 - 2026-03-10 #
Added #
UpdateCheckerport (lib/src/domain/ports/update_checker.dart): Abstract contract for update checking;VersionCommandnow depends on the port, not the concrete service — consistent with the hexagonal architecture.- Update check on
--versionflag:cura --versionnow runs a lightweight update check and prints a notice to stderr when a newer version is available (stdout stays clean for scripts). VersionCommandunit tests: 13 tests covering--shortmode, full output, update check integration,valias, and port contract.
Fixed #
-
VersionUtilspre-release handling:1.0.0-betawas incorrectly treated as equal to1.0.0. Per semver spec, pre-release < stable for the same base — users on a pre-release are now notified when the stable version ships. -
cyan.wrapbypasseduseColorsinVersionCommand._showDetailedVersion(): the homepage URL was always coloured regardless ofuse_colorsconfig. Now uses the theme token with the standard_c()guard. -
UpdateCheckerServiceresponse parsing: no null-checks before castingresponse.data['latest']['version']. Now validates each field explicitly and throws a descriptive error if the shape is unexpected. -
Missing
sendTimeouton the update check HTTP request: onlyreceiveTimeoutwas set;sendTimeoutis now configured as well. -
AppInfo.getDetailedInfo()was dead code:VersionCommandbuilt its own output and never called this method. Removed. -
--theme <name>global flag: Override the active theme for a single run (dark/light/minimal) without editing the config file. -
ThemeManager.isValidTheme(): Returns whether a theme name is registered; used by validation points. -
CuraTheme.styleInfo()/BaseCuraTheme.styleInfo(): Completes the style-helper set alongsidestylePrimary,styleSuccess,styleWarning,styleError. -
--no-cacheglobal flag: Bypass the file cache for a single run without editing the config file (e.g.cura check --no-cache). -
Cache unit tests:
TtlStrategy,JsonFileSystemCache, andCachedAggregatorare now covered by 38 unit tests.
Fixed #
-
cura config set --globalflag: A new--global(-g) flag lets you write any key directly to the global config (~/.cura/config.yaml). Without the flag, writes still target the project config (./.cura/config.yaml). -
github_tokenalways saved to global config:cura config set github_token ghp_…now routes to~/.cura/config.yamlregardless of whether--globalis passed, because API tokens are personal credentials that must not be committed to VCS. A note is printed to remind the user when the flag was omitted. -
ConfigRepository.setValue()accepts aglobalparameter: The port andYamlConfigRepositorynow take{bool global = false}, making the write target explicit and testable. -
Theme not applied to renderers:
BarRendererandTableRendererwere using hardcoded mason_logger ANSI codes. Both now read colours fromThemeManager.currentso custom themes take full effect. -
Theme not applied to presenters:
ViewPresenterandCheckPresentercontained ~30 hardcoded colour calls (cyan.wrap,red.wrap, etc.). All replaced with theme tokens via a_c(text, color)helper that also respects_useColors. -
useColors: falsenot respected:ConsoleLogger.warn(),error(),debug(), andalert()always coloured output regardless of theuse_colorsconfig flag. -
autoDetect()was dead code:ThemeManager.autoDetect()was never called. The startup flow now calls it when no theme is explicitly set in any config file, enabling automatic dark/light detection on macOS and CI→minimal fallback. -
CI theme desync: In CI environments,
ThemeManagernow correctly mirrors the minimal logger (viaautoDetect()), preventing themed output if code paths bypass the logger. -
config set theme xyzcaused a startup crash: Writing an invalid theme name to the config file would throw an unhandledArgumentErroron the next run.ConfigSetCommandnow validates the name before persisting. -
mergeWithsilently discarded global theme: When a project config did not declaretheme:,CuraConfig.fromYamldefaulted it to'dark', overriding a globaltheme: light.themeis now nullable inCuraConfig;fromYamlreturnsnullfor absent keys andmergeWithusesother.theme ?? this.theme. -
MinimalTheme.isDarkwastrue: A no-colour theme is not a dark theme. Corrected tofalse. -
enable_cache: falsewas ignored:CachedAggregatorwas always instantiated regardless ofconfig.enableCache. The startup now conditionally wrapsMultiApiAggregatoronly when caching is enabled. -
cache_max_age_hourswas ignored: The configured TTL value was never passed toTtlStrategy. It is now forwarded asdefaultTtlso the 70–89 popularity tier honours the user setting. -
cache clearconfirmed before deleting:JsonFileSystemCache.clearAll()used fire-and-forget deletions, returning before files were actually removed. Deletions are now awaited sequentially. -
Dead code in
TtlStrategy:getPackageTtl(),getAlternativesTtl(), andgetScoresTtl()were never called. Removed. -
Dead constants in
CacheConstants: Six unused TTL/limit constants removed; the hardcoded cache path in the entry point replaced withCacheConstants.cacheSubDir.
0.10.0 - 2026-03-09 #
Added #
cura viewcommand: Full implementation with issue detection,RecommendationEngine, risk signals (--verbose), and verbose score breakdown with penalty line items.view --verbosecache and timing footer: Cache hit/miss status at top; elapsed time and API call count at bottom.view --json: Machine-readable JSON output (timestamp,package,score,github,red_flags,vulnerabilities,issues,recommendations,performance).PenaltyEvaluatorline items:calculate()returnsPenaltyResult = ({int total, List<PenaltyItem> items}). Individual deductions are now exposed for verbose rendering.JsonFileSystemCache.getEntry(): Returns({data, cachedAt})alongside the cached payload. Used byCachedAggregatorto surface cache age in the UI.PackageSuccess.cachedAt: UTC write timestamp propagated from the cache layer toPackageAuditResult.RecommendationEngineflag coverage: Added handlers forNoNullSafetyFlag(critical),NotDart3CompatibleFlag(warning), andLimitedPlatformSupportFlag(advisory).
Changed #
PackageAuditResult.recommendations: Renamed fromsuggestions. Type changed fromList<String>toList<Recommendation>so the presenter can drive icon and color rendering fromRecommendationLevel.ViewPackageDetails.execute: Switched frommapAsyncto a directswitchto capturerequestCountandcachedAtfromPackageSuccess.ViewCommand: AddedStopwatchand--jsonflag.ViewPresenter._showVerboseScoreBreakdown: Redesigned with aligned columns (label.padRight(13),ratio.padRight(6)), status icons (green✓/ yellow!/ red✗) at percentage thresholds (75% / 50%), and tree connectors (├─/└─) for penalty line items. Clamped penalty totals are annotated.ViewPresenter._showRecommendations: Now receivesList<Recommendation>and renders level-based icons:✗critical,!warning,→action,→advisory.RecommendationEnginemessages: All messages rewritten to senior tone. Declarative, no em dashes, no incises.RedFlagmessages: Allmessagegetters rewritten to senior tone.AuditIssuefactory messages: All four factory constructors rewritten to senior tone.
0.9.0 - 2026-03-08 #
Added #
PackageSuccess.requestCount: tracks exact HTTP requests per package (0 from cache).PackageAuditResult.requestCount: propagated fromPackageSuccessthroughmapAsync.check --jsonstructured output:--jsonnow emits a full JSON report withtimestamp,total_packages,overall_health,status(PASSED/WARNING/FAILED),summary,packages(withred_flagswhen present),critical_packages, andperformancemetrics.checkruntime flag overrides:--min-score,--fail-on-vulnerable, and--fail-on-discontinuednow take effect at runtime and override config-file values.checkconfig hierarchy:CheckCommandacceptsdefaultMinScore,defaultFailOnVulnerable,defaultFailOnDiscontinuedseeded from the resolved config — the fullCLI flag > config file > built-in defaulthierarchy is now enforced.checkCI auto-detection:$CIenvironment variable is detected at startup; cura automatically switches to plain-text output (no colors, no emojis) in any standard CI environment without extra configuration.CheckPackagesUsecaseunit tests: 19 tests covering success path, all failure variants, and all 4 issue-detection rules (discontinued, critical CVE, low score, stale) including boundary conditions.CheckCommandintegration tests: 20 tests covering pubspec parsing, exit-code logic for all flag combinations, config hierarchy overrides, and output mode selection.
Changed #
PackageResultExtensions.mapAsync/mapValue: mapper signature extended withint requestCount.CheckPresenter:_apiCallsnow accumulatesaudit.requestCount; label updated to"HTTP requests".ErrorFormatter: refactored around a single_renderBlockprimitive — all formatters now delegate to it, eliminating rendering duplication._verbosemade private._getSuggestionsconverted to exhaustive switch.PubDevApiClient: pub.dev requests are now sequential to avoidParallelWaitErrorswallowing typed exceptions.fetchJsoncatchesDioExceptionand maps 404 →PackageNotFoundException, 429 →RateLimitException.ViewCommand/CheckPresenter:PackageProviderErrornow routed throughErrorFormatterinstead of rawtoString().CheckCommand: aborts on firstNetworkErrorinstead of continuing to remaining packages.CheckPackagesUsecase:scoreCalculatorparameter type changed fromCalculateScoretoScoreCalculatorport — domain layer no longer depends on a concrete adapter.CheckPackagesUsecase: removed unused constructor paramsminScore,failOnVulnerable,failOnDiscontinued— acceptance criteria belong to the command layer, not the use case.PackageAuditResult.suggestions: changed fromrequiredto optional with default[]; usescore.recommendationsfor programmatic improvement guidance.
0.8.0 - 2026-03-08 #
Added #
- Strategy pattern for scoring:
CalculateScoreis now a pure orchestrator delegating toVitalityDimension,TechnicalHealthDimension,TrustDimension,MaintenanceDimension,PenaltyEvaluator,RedFlagDetector, andRecommendationEngine— each independently testable via theScoringInputDart record. RedFlagsealed class with 12 typed subtypes andRedFlagSeverity(info/warning/critical) — replacesList<String>and eliminates fragile string matching in recommendation logic.Recommendationvalue object withRecommendationLevel— replacesList<String>.Gradeenum withGrade.fromScore()and.label— replacesStringgrade field onScore.ScoreCalculatorport (domain/ports/) — enables clean mocking without touchingCalculateScore.MissingLicenseFlag(criticalseverity) — packages without an SPDX license are now flagged as a priority legal risk.ScoreWeightsmoved todomain/value_objects/(infrastructure path re-exports for compatibility).
Changed #
- Trusted publisher: removed automatic score of 100. Publishers like
dart.devnow receive a score floor of 70 — penalties and red flags still apply, ensuring stale or unlicensed official packages are surfaced. Score.gradeString→Grade,Score.redFlagsList<String>→List<RedFlag>,Score.recommendationsList<String>→List<Recommendation>.
Breaking #
Score.grade,Score.redFlags,Score.recommendationsfield types changed — callers must usescore.grade.labelfor string display.
0.7.0 - 2026-02-24 #
Added #
JsonFileSystemCache: New cache backend that persists entries as individual JSON files under~/.cura/cache/aggregated/. Each file follows a versioned envelope (schemaVersion,cachedAt,expiresAt,data). No native dependencies required — puredart:io+dart:convert.
Changed #
- Cache backend replaced:
CacheDatabase(SQLite viasqflite_common_ffi) is replaced byJsonFileSystemCache. Theaggregated/namespace maps to the formeraggregated_cachetable. TTL tiers are preserved and now stored as a pre-computedexpiresAtISO-8601 timestamp. CachedAggregatorrefactored:JsonFileSystemCacheis injected via constructor instead of accessed through theCacheDatabasesingleton. TheCachedAggregatedDatatypedef andsqflite_common_ffiimport are removed.- Atomicity: All cache writes use the write-then-rename pattern (
<key>.json.tmp→<key>.json). On POSIX this is atomic viarename(2); on Windows the target is deleted before rename (best-effort, acceptable for a cache). cleanupExpirednow also purges orphaned.json.tmpfiles older than 1 hour in addition to expired entries.- Cache commands (
clear,stats,cleanup) receiveJsonFileSystemCachevia constructor injection instead of callingCacheDatabasestatic methods.statsnow shows valid entry counts per namespace instead of SQLCOUNT(*)results. CacheConstants:databaseNameanddatabaseVersionremoved; replaced withcacheSubDirandaggregatedNamespace.- Documentation:
doc/caching.mdrewritten for the JSON file model (schema, TTL tiers, CI examples).doc/architecture.md,README.md,CLAUDE.md, and all affected dartdoc comments updated.
Removed #
CacheDatabase(lib/src/infrastructure/cache/database/cache_database.dart) — deleted.CachedEntry<T>(lib/src/infrastructure/cache/models/cached_entry.dart) — deleted; expiry is now evaluated insideJsonFileSystemCache.get.sqflite_common_ffi: ^2.3.0andsqflite_common: ^2.5.6removed frompubspec.yaml. The compiled binary no longer requires a native SQLite library on the host machine.
0.6.1 - 2026-02-24 #
Fixed #
CacheDatabasedouble-initialisation race: Two concurrentawait CacheDatabase.instancecalls arriving before the database was ready both invoked_initDatabase(), creating the SQLite connection twice. Fixed by memoising the initialisationFuture(_initFuture ??= _initDatabase()), ensuring all concurrent callers share a single in-flight operation.close()now also resets_initFutureso re-opening is safe.CachedAggregator.fetchManysilent error swallow: Errors thrown by pool tasks were not forwarded to the stream, leaving error cases silently dropped. AddedonErrorforwarding so stream consumers receive errors correctly.CachedAggregatordead import: Unusedimport 'package:cura/src/domain/ports/cache_repository.dart'removed.
Changed #
MultiApiAggregatorusesPoolManager: Replaced the inlinePoolconstruction with the sharedPoolManagerutility. The aggregator no longer owns a rawpoolimport; concurrency configuration flows throughPoolManager(maxConcurrency: ...).- Dartdoc — infrastructure cache layer: Added comprehensive API documentation to
CachedEntry,CacheDatabase,TtlStrategy(including popularity range 0–100 and per-tier TTL tables),CachedAggregator, andMultiApiAggregator.
0.6.0 - 2026-02-24 #
Added #
config init --force: New-f/--forceflag oncura config initto overwrite an existing config file with built-in defaults.- Complete
config show: Now displays all configuration fields grouped by category (Appearance, Cache, Scoring, Performance, Behaviour, Logging, API, Exclusions) with score-weights validation warning.
Fixed #
config setincomplete key support:_writeValuewas missinggithub_token,cache_max_age_hours,enable_cache,auto_update,fail_on_vulnerable,fail_on_discontinued,show_suggestions,max_suggestions_per_package,verbose_logging, andquiet— those keys were readable but silently ignored on write.config getnull display: Unknown / unset values now print(not set)instead of the string"null".ScoreWeights.fromJsontype safety: JSON fields are now cast withas int?before applying the default fallback.ConfigDefaults.defaultConfigmutability: Field changed fromstatictostatic finalto prevent accidental reassignment at runtime.
Changed #
- Centralized concurrency manager built on top of the
poolpackage. - Dartdoc: Added comprehensive API documentation to
ScoreWeights,ConfigDefaults,ConfigRepository,YamlConfigRepository, and allconfigsub-commands.
0.5.0 - 2026-02-22 #
Added #
- Visual Score Breakdown: New bar charts (█ ▓ ▒ ·) for intuitive score reading.
- Rich UI Elements: Added popularity dots (●●●) and Pub score indicators (●/◐/○).
- Color-coded Status: Visual update indicators (🟢/🟡/⚠) and severity colors for vulnerabilities.
- GitHub Metrics: Enhanced formatting for stars, forks, and last commit dates.
Changed #
- Presenter Refactor: Complete overhaul of
ViewPresenterfor better information hierarchy. - Output Styling: Standardized usage of clean separator lines (═) for better scannability.
0.4.0 - 2026-02-19 #
Added #
- Version Command: Added a dedicated
versioncommand for detailed system information (CLI version, Dart SDK, Platform). - Update Checker: Automatic check against pub.dev API to notify users when a newer version is available.
- Global Flag: Added
--version/-vas a global flag for quick version check. - Versioning Logic: Centralized
AppInfoandVersionUtilsfor robust Semantic Versioning (SemVer) comparisons. - Multi-API aggregation (pub.dev + GitHub + OSV)
- Streaming reactive package analysis
- SQLite caching (24h TTL)
- GitHub metrics integration
Changed #
- CLI Output: Customized the default help message for better UX.
- Constants: Refactored
AppConstantsto use dynamic versioning instead of hardcoded strings.