Skip to content

thekaveh/VMx

VMx

csharp python typescript swift conformance spec-discipline examples release License: Apache 2.0

A hierarchical, lifecycle-aware MVVM viewmodel framework — one language-neutral specification, four idiomatic language flavors (C# / Python / TypeScript / Swift at total parity), 281 library conformance IDs + 5 THEME scenario IDs = 286 total verified by path-filtered CI on relevant changes (all four flavors, including the Swift notes-showcase flagship).

0. Contents

  1. Overview
  2. Architecture
  3. Flavors
  4. Getting started
  5. Repository layout
  6. Versioning and conformance
  7. Contributing
  8. License

1. Overview

VMx is a framework for building MVVM viewmodels with explicit lifecycle and reactive messaging. It targets WPF / Avalonia / MAUI on .NET, Tkinter / PyQt / NiceGUI / Textual on Python, and any DOM- or rxjs-based UI on TypeScript — but makes no assumption about the UI layer. Every flavor exposes:

  • A five-state construction lifecycle (Destructed, Constructing, Constructed, Destructing, plus terminal Disposed) with reversible construct/destruct, reconstruct(), and a synchronous depth-first dispose() cascade that can be invoked from any state.
  • A reactive message hub for PropertyChangedMessage and ConstructionStatusChangedMessage, plus collection-change events on container VMs.
  • Four hierarchy primitives — leaf ComponentVM, selectable CompositeVM, peer GroupVM, fixed-arity AggregateVM1..6 — plus forwarding decorators for instrumentation.
  • A RelayCommand with reactive canExecute triggers, plus v2.0 decorators (CompositeCommand, DecoratorCommand, ConfirmationDecoratorCommand) and a modeled-CRUD helper (ModeledCrudCommands).
  • Tree utilities (walk, find, walk_expanded) for introspection.
  • 22 opt-in capability micro-interfaces (ISelectable, IExpandable, IClosable, IFilterable, IPageable, …) and helper state classes (ExpandableState, SearchableState) for layering behaviour onto VMs additively.
  • DerivedProperty<T> for N-source computed values, FormVM<T> for snapshot/revert/validation flows, DiscriminatorVM for single-active-key coordination, PagedComposition / TokenPagedComposition for finite and cursor paging, an opt-in notification sub-package (INotificationHub), IDialogService, null-object service variants (NullMessageHub, NullDispatcher, NullNotificationHub, NullLocalizer, NullDialogService), and an ILocalizer hook for i18n.

The shape is identical across flavors; only the surface idiom changes (PascalCase in C#, snake_case in Python, camelCase in TypeScript and Swift — codified in ADR-0006).

2. Architecture

2.1 Architecture diagram

VMx architecture diagram

The diagram source is at assets/architecture.svg; a browsable HTML version with summary cards is at assets/architecture.html, and a high-resolution PNG export is at assets/architecture.png.

2.2 Class diagram

A cluster-level class map of the entire library — what every class family is, and how the families relate.

VMx class diagram

The diagram source is at assets/class-diagram.svg; a browsable HTML version with summary cards is at assets/class-diagram.html, and a high-resolution PNG export is at assets/class-diagram.png. Five bands:

  1. Lifecycle baseComponentVMBase + ConstructionStatus; every VM derives from here.
  2. VM family — five idioms: leaf, composite (homogeneous + selectable), group (homogeneous peers), aggregate (heterogeneous, fixed arity 1..6), and specialized (FormVM, DiscriminatorVM, NotificationVM, ConfirmationVM, forwarding decorators).
  3. Commands & capabilitiesRelayCommand family + DecoratorCommand chain + ModeledCrudCommands, alongside the 22 capability micro-interfaces (Selection / Expansion / Lifecycle / Query / Dialog / CRUD).
  4. Services · Messages · State · Collections — the constructor-injected runtime (MessageHub, Dispatcher, ILocalizer, IDialogService — each with its Null* sibling per ADR-0017), hub envelope types, state helpers (SearchableState, ExpandableState, DerivedProperty), observable collections, PagedComposition, TokenPagedComposition, filtered/scored composite views, fluent immutable builders, and tree utilities.
  5. Notifications sub-package (opt-in)INotificationHub, ConfirmHelper, bridged to ConfirmationDecoratorCommand in band 3 and to NotificationVM / ConfirmationVM in band 2.

Boxes are cluster-level (one box per related set of classes); the exhaustive member list lives in the linked spec chapters + ADRs.

2.3 Layers

Each flavor implements the same conceptual stack:

  • Specspec/ is the source of truth: 23 markdown chapters, 79 ADRs, 4 JSON fixtures, 286 conformance IDs, version pinned in spec/VERSION.
  • Application code — your host app instantiates VMs through builders.
  • Forwarding decorators (optional)ForwardingComponentVM and ForwardingCompositeVM wrap an inner VM for instrumentation, selective override, or composition.
  • Viewmodel hierarchyComponentVM<M>, CompositeVM<VM>, GroupVM<VM>, AggregateVM1..6.
  • CommandsRelayCommand and RelayCommand<T> with execute, canExecute, and reactive trigger observables.
  • Messages and collection eventsPropertyChangedMessage, ConstructionStatusChangedMessage, CollectionChangedEvent with BatchUpdate() and AutoConstructOnAdd options.
  • Tree utilitieswalk(root), walk_expanded(root), and find(root, predicate) over any VM hierarchy.
  • ServicesMessageHub (rx Subject-backed pub/sub) and RxDispatcher (paired foreground / background schedulers).
  • Lifecycle state machine — orchestrates every VM; transitions enforced by a fixture-backed validator (spec/fixtures/lifecycle-transitions.json).
  • Builders — immutable fluent setters that return new instances and validate required fields on build().

3. Flavors

3.1 Versions and packages

Flavor Source status Public package status Reactive primitive
C# v3.1.0 in source NuGet package not published yet System.Reactive
Python v3.1.0 in source vmx latest published: 3.1.0 reactivex
TypeScript v3.1.0 in source npm package not published yet rxjs
Swift v3.1.0 in source SwiftPM tag not published yet; no central registry Combine

main may contain an in-development source version before that version is published to package registries. Use the compatibility matrix for source-level spec parity; use each registry for installable package availability.

The Swift flavor is at total parity — all 281 library conformance IDs as of v3.1.0 plus the 5 THEME-00x scenario IDs covered by the examples/swift/notes-showcase/ flagship (ADR-0067) = 286 total, matching C#, Python, and TypeScript. See langs/swift/README.md §5 for the full ID matrix. The C# flavor multi-targets netstandard2.0 and net8.0 and ships two companion assemblies: VMx.Extensions.DependencyInjection (services.AddVMx(...)) and VMx.Notifications (opt-in INotificationHub). The Python flavor supports Python 3.10 through 3.13, is mypy --strict clean, and exposes vmx.notifications as an opt-in subpackage. The TypeScript flavor (npm package @thekaveh/vmx — renamed in v2.4.0 because the unscoped vmx name was unavailable) targets Node ≥20, emits dual ESM + CJS bundles, and exposes @thekaveh/vmx/notifications as a sub-path export.

3.2 Spec and flavor compatibility

spec csharp python typescript swift
3.1.x 3.1.0 3.1.0 3.1.0 3.1.0
2.6.x 2.6.0 2.6.1 2.6.0 2.6.0 (subset)
2.4.x 2.4.0 2.4.0 2.4.0 2.4.0 (subset)
2.3.x 2.3.0 2.3.0 2.3.0
2.2.x 2.2.0 2.2.0 2.2.0
2.1.x 2.1.0 2.1.0 2.1.0
2.0.x 2.0.0 2.0.0 2.0.0
1.0.x 1.0.0 1.0.0

See compatibility-matrix.md for the full table. Every published package declares its MinSpecVersion / __min_spec_version__ so the runtime can verify compatibility.

4. Getting started

4.1 Install

# C# (after the NuGet package is published)
dotnet add package VMx

# Python (latest public package may lag this source tree)
pip install vmx
# or
uv add vmx

# TypeScript (after the npm package is published)
npm install @thekaveh/vmx rxjs

4.2 Quickstart guides

4.3 Examples

The four flagship Notes Workspace apps — one per language flavor, one per UI framework — implement the same scenario from a single language-neutral VM API surface, exercising 19 distinct VMx features (notebooks tree, paged + filterable notes list, strict FormVM editor with validation, capability-aware action bar, notifications, async lifecycle, dialogs, AggregateVM6 root, the ThemeVM scenario contract, token-paged global search, edit/preview DiscriminatorVM, and tag autocomplete via SearchableState). See examples/notes-showcase-parity.md for the cross-flavor feature matrix and spec/proposals/2026-05-29-notes-showcase-scenario.md for the canonical scenario contract. The VM hierarchy is diagrammed at examples/assets/notes-showcase-vm-hierarchy.svg; the companion VMx component map is at examples/assets/notes-showcase-vmx-components.svg.

Smaller per-flavor demos:

5. Repository layout

.
├── spec/                  language-neutral specification (source of truth)
│   ├── 00-overview.md ... 22-discriminator-vm.md   (23 chapters)
│   ├── ADRs/              architecture decision records (0001..0079)
│   ├── fixtures/          JSON test inputs shared across flavors
│   ├── proposals/         mostly historical; scenario contracts may be normative
│   └── VERSION            spec SemVer
├── langs/
│   ├── csharp/            VMx (NuGet) + VMx.Extensions.DependencyInjection + VMx.Notifications
│   ├── python/            vmx (PyPI)
│   ├── typescript/        @thekaveh/vmx (npm)
│   └── swift/             VMx Swift Package (v3.1.0, total parity — 281 library + 5 THEME)
├── examples/              runnable example apps per flavor
├── docs/getting-started/  per-flavor quickstart tutorials
├── docs/integration/      one-page UI-framework integration recipes
├── docs/maintenance/      maintenance run ledgers and audit records
├── tools/                 cross-cutting scripts (conformance coverage)
├── assets/                architecture + class diagrams, notes-showcase assets
├── .github/               issue/PR templates + CI workflows
└── compatibility-matrix.md

5.1 Documentation map

This README is the entry point; the documents below add focused detail.

6. Versioning and conformance

6.1 SemVer policy

Each language flavor versions independently in SemVer. The spec also versions independently in SemVer. Every published package declares the spec version it implements (MinSpecVersion in C#, __min_spec_version__ in Python, __minSpecVersion__ in TypeScript, VMxVersion.minSpecVersion in Swift). A spec major bump triggers a major bump in every active flavor; a spec minor bump (like v2.1.0) is fully backwards compatible and ships in flavors as a minor bump.

6.2 Conformance catalog

spec/12-conformance.md enumerates 286 normative test scenarios keyed by ID (LIFE-001, HUB-007, COMP-013, UTIL-002, CAP-020, DPROP-012, NOTIF-010, DIA-001, FORM-001, COL-001, HIER-001, AGG-006, THEME-001, …) — 281 library IDs plus 5 THEME scenario IDs. All four flavors (C# / Python / TypeScript / Swift) implement the 281 library IDs under their registered conformance suites (langs/csharp/tests/VMx.Conformance.Tests, langs/python/tests/conformance, langs/typescript/tests/conformance, and langs/swift/Tests/VMxTests), and tools/check-conformance-coverage.py enforces 100% coverage in CI. All four flavors also cover the 5 THEME-00x scenario IDs via their respective flagship example apps — Swift via examples/swift/notes-showcase/ (ADR-0067). Every flavor is at total parity: 281 library + 5 THEME = 286.

# Verify all four flavors are at full catalog coverage
uv run --project langs/python python tools/check-conformance-coverage.py \
    --require csharp --require python --require typescript --require swift

7. Contributing

See CONTRIBUTING.md for the spec / ADR / conformance workflow and per-flavor build instructions. The repository uses pre-commit hooks (ruff, mdformat, dotnet format, eslint); install them with pre-commit install.

8. License

Apache-2.0 — see LICENSE and NOTICE.

About

Spec-driven, lifecycle-aware MVVM/ViewModel framework for C#, Python, TypeScript, and Swift. One language-neutral VMx spec, four full-parity flavors, shared reactive primitives, and 286 conformance scenarios.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

1 watching

Forks

Packages

 
 
 

Contributors