Units CLI
QUDT Units CLI
The S2DM Units CLI provides integration with the QUDT (Quantities, Units, Dimensions and Types) reference model to generate standardized GraphQL unit enums. This replaces static unit definitions with a dynamic system that synchronizes directly from the authoritative QUDT repository.
How QUDT Maps to GraphQL
The sync command reads a specific released version of QUDT and maps it onto GraphQL SDL enum structures:
- Each QUDT quantity kind (e.g.
quantitykind:Velocity) becomes one GraphQL enum type (e.g.VelocityUnit). - Each QUDT unit belonging to that quantity kind (e.g.
unit:M-PER-SEC) becomes one enum value of that type (e.g.M_PER_SEC).
Elements that are marked deprecated in the QUDT release — whether the unit itself or its quantity kind — are intentionally not mapped and are ignored. They do not appear in generated enums in any form (not even as @deprecated values); only QUDT’s current, non-deprecated vocabulary is represented.
Features
- Dynamic Unit Synchronization: Fetch unit definitions from QUDT’s GitHub repository
- Version Management: Support for specific QUDT versions with automatic latest version detection
- Semantic References: Generated enums include
@referencedirectives linking to QUDT IRIs with version tags - UCUM Integration: Includes UCUM codes in descriptive comments for standardization
- SDL Validation: Generated GraphQL enums are validated for correctness
- Automatic Cleanup: Removes stale files before sync to ensure fresh state
Commands
s2dm units sync
Synchronizes unit definitions from the QUDT repository and generates GraphQL enum files in the S2DM_HOME directory (~/.s2dm/units/qudt).
Unit files are downloaded to ~/.s2dm/units/qudt to prevent users from modifying them. This is a temporary solution. In the future, QUDT unit GraphQL files will be moved to a separate repository and referenced/downloaded from there.
Syntax:
s2dm units sync [--version <version>] [--dry-run]Examples:
# Sync latest version
s2dm units sync
# Sync specific version
s2dm units sync --version v3.1.5
# Check what would be generated without creating files
s2dm units sync --dry-runOptions:
--version(optional): QUDT release tag, including the leadingv(e.g.v3.1.6). This must match a git tag in the qudt-public-repo exactly. Defaults to the latest release tag if not specified--dry-run(optional): Show how many enum files would be generated without creating them
Output:
- Creates
<QuantityKind>Unit.graphqlfiles in~/.s2dm/units/qudt(e.g.,LengthUnit.graphql) - Generates
README.mdwith version and attribution information - Generates
CHANGELOG.mdlisting quantity kinds and units that QUDT marks as deprecated in that release (and are therefore intentionally excluded from the generated enums) - Reports number of enum files generated
s2dm units check-version
Compares the local synced QUDT version with the latest available version. By default, checks the ~/.s2dm/units/qudt directory.
Syntax:
s2dm units check-versionOutput:
✓ Units are up to date.if current version matches latest⚠ There is a newer release available: X.Y.Zif update is needed
Generated Enum Format
Each generated enum follows this structure:
# Generated by S2DM from the QUDT unit vocabulary. See README.md in this directory for the QUDT version used.
# Source data: QUDT Public Repository (https://github.com/qudt/qudt-public-repo)
# © QUDT.org — Licensed under Creative Commons Attribution 4.0 International (CC BY 4.0)
# License: https://creativecommons.org/licenses/by/4.0/
# Changes: vocabulary terms transformed to GraphQL SDL enum format by S2DM (https://github.com/COVESA/s2dm)
enum LengthUnit @reference(uri: "http://qudt.org/vocab/quantitykind/Length") {
"""Meter | UCUM: m"""
M @reference(uri: "http://qudt.org/vocab/unit/M")
"""Kilometer | UCUM: km"""
KILOM @reference(uri: "http://qudt.org/vocab/unit/KiloM")
"""Centimeter | UCUM: cm"""
CENTIM @reference(uri: "http://qudt.org/vocab/unit/CentiM")
...
}The QUDT catalog version is not embedded in each enum file. It is recorded once in the directory’s README.md so that re-syncing an unchanged catalog doesn’t touch every file, keeping Git diffs focused on actual content changes.
Key Elements:
- Enum name:
<QuantityKind>Unitin PascalCase - @reference on enum: Links to QUDT quantity kind IRI
- @reference on values: Links to QUDT unit IRI
- Triple-quote docstrings: Include human-readable label and UCUM code
- Value names: Use QUDT URI segments converted to SCREAMING_SNAKE_CASE
Directory Structure
QUDT units are stored in the S2DM_HOME directory:
~/.s2dm/units/qudt/ # QUDT units (generated, read-only)
├── README.md # Version and attribution
├── CHANGELOG.md # Deprecated quantity kinds/units excluded from this release
├── LengthUnit.graphql # Length units
├── VelocityUnit.graphql # Velocity units
└── ... (500+ more unit enums)If you need custom units specific to your domain, create them in your project directory:
units/custom/ # Custom units (manual, in your project)
├── MyDomainUnit.graphql # Custom domain units
└── SpecialUnit.graphql # Special use case unitsWorkflow Example
Initial Setup: Sync units from QUDT
s2dm units sync --version v3.1.5This downloads unit enums to
~/.s2dm/units/qudt.Use Units in Schema Development: Reference generated enums
type Vehicle { speed(unit: VelocityUnit = KM_PER_HR): Float acceleration(unit: AccelerationUnit = M_PER_SEC2): Float }Check for Updates: Periodically check for new QUDT versions
s2dm units check-versionUpdate When Needed: Sync newer versions as they become available
s2dm units sync --version v3.2.0
Why URI-Based Symbols?
S2DM uses QUDT URI segments instead of labels for enum values because:
- Consistency: URI segments are standardized and don’t vary across languages
- Reliability: Labels can be inconsistent, missing, or contain formatting issues
- Semantic Accuracy: URI segments represent the canonical QUDT identifier
Technical Details
Data Source
- Repository: qudt/qudt-public-repo
- File:
src/main/rdf/vocab/unit/VOCAB_QUDT-UNITS-ALL.ttl - Format: RDF Turtle (TTL)
Deduplication
- Uses
DISTINCTin SPARQL queries to eliminate exact duplicates - Filters out units marked
qudt:deprecated trueto prevent symbol conflicts (e.g.unit:Standard, replaced byunit:STANDARD) - Filters out units whose quantity kind is itself marked
qudt:deprecated true(e.g.quantitykind:Conductivity, replaced byquantitykind:ElectricConductivity), so units aren’t grouped under a stale quantity kind label - Prefers entries with UCUM codes when duplicates remain
QUDT’s own git tags are prefixed with v (e.g. v3.5.2), not bare version numbers. Always pass --version with the v prefix, matching the tag names at qudt-public-repo/tags.
Error Handling
- Network Issues: Graceful failure with informative error messages
- Invalid Units: Units that cannot generate valid symbols are skipped
- SDL Validation: Generated GraphQL enums are validated for correctness
- Version Check: Safe handling of GitHub API rate limits