signalk-server
Version:
An implementation of a [Signal K](http://signalk.org) server for boats.
158 lines • 6.28 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveDisplayUnits = resolveDisplayUnits;
exports.validateCategoryAssignment = validateCategoryAssignment;
const loader_1 = require("./loader");
/**
* Given stored displayUnits metadata, resolve the full conversion info
*
* @param storedDisplayUnits - What's in baseDeltas.json (category, optional targetUnit)
* @param pathSiUnit - The SI unit for this path (optional)
* @param username - Username for per-user preset resolution (optional)
* @returns Full displayUnits with formula, or null if can't resolve
*/
function resolveDisplayUnits(storedDisplayUnits, pathSiUnit, username) {
if (!storedDisplayUnits?.category) {
return null;
}
const category = storedDisplayUnits.category;
// "base" category means display in SI units without conversion
if (category === 'base') {
return {
category: 'base',
targetUnit: pathSiUnit || 'base',
formula: 'value',
inverseFormula: 'value',
symbol: pathSiUnit || '',
displayFormat: undefined
};
}
// "custom" category stores explicit conversion info
if (category === 'custom') {
if (!storedDisplayUnits.targetUnit) {
return null;
}
// Identity conversion: targetUnit matches the path's SI unit
if (pathSiUnit && storedDisplayUnits.targetUnit === pathSiUnit) {
return {
category: 'custom',
targetUnit: storedDisplayUnits.targetUnit,
formula: 'value',
inverseFormula: 'value',
symbol: storedDisplayUnits.symbol || storedDisplayUnits.targetUnit,
displayFormat: storedDisplayUnits.displayFormat
};
}
// If formula is stored, use it directly
if (storedDisplayUnits.formula) {
return {
category: 'custom',
targetUnit: storedDisplayUnits.targetUnit,
formula: storedDisplayUnits.formula,
inverseFormula: storedDisplayUnits.inverseFormula || '',
symbol: storedDisplayUnits.symbol || storedDisplayUnits.targetUnit,
displayFormat: storedDisplayUnits.displayFormat
};
}
// Otherwise look up from definitions using pathSiUnit
if (pathSiUnit) {
const definitions = (0, loader_1.getMergedDefinitions)();
const conversion = definitions[pathSiUnit]?.conversions?.[storedDisplayUnits.targetUnit];
if (conversion) {
return {
category: 'custom',
targetUnit: storedDisplayUnits.targetUnit,
formula: conversion.formula,
inverseFormula: conversion.inverseFormula,
symbol: conversion.symbol || storedDisplayUnits.targetUnit,
displayFormat: storedDisplayUnits.displayFormat
};
}
}
return null;
}
const categoriesData = (0, loader_1.getCategories)();
const definitions = (0, loader_1.getMergedDefinitions)();
const preset = username ? (0, loader_1.getActivePresetForUser)(username) : (0, loader_1.getActivePreset)();
// Step 1: Get SI unit for this category
const siUnit = categoriesData.categoryToBaseUnit[category];
if (!siUnit) {
return null; // Unknown category
}
// Step 2: Determine target unit
// Priority: path override > preset default
let targetUnit;
if (storedDisplayUnits.targetUnit) {
targetUnit = storedDisplayUnits.targetUnit;
}
else if (preset?.categories?.[category]?.targetUnit) {
targetUnit = preset.categories[category].targetUnit;
}
else {
return null; // No target unit defined
}
// Step 3: Identity conversion (targetUnit === baseUnit)
if (targetUnit === siUnit) {
return {
category,
targetUnit,
formula: 'value',
inverseFormula: 'value',
symbol: siUnit,
displayFormat: storedDisplayUnits.displayFormat ||
preset?.categories?.[category]?.displayFormat
};
}
// Step 4: Get formula from definitions
const unitDef = definitions[siUnit];
if (!unitDef?.conversions) {
return null; // No conversions for this SI unit
}
const conversion = unitDef.conversions[targetUnit];
if (!conversion) {
return null; // Target unit not found in conversions
}
// Step 5: Build response
return {
category,
targetUnit,
formula: conversion.formula,
inverseFormula: conversion.inverseFormula,
symbol: conversion.symbol,
displayFormat: storedDisplayUnits.displayFormat ||
preset?.categories?.[category]?.displayFormat
};
}
/**
* Validate that a category assignment is valid for a path
*
* @param pathSiUnit - The SI unit from SignalK schema for this path (may be undefined)
* @param category - The category being assigned
* @returns Error message if invalid, null if valid
*/
function validateCategoryAssignment(pathSiUnit, category) {
// "base" category is always valid - it means use SI units
if (category === 'base') {
return null;
}
// "custom" category is always valid - user picks an explicit target unit
if (category === 'custom') {
return null;
}
const categoriesData = (0, loader_1.getCategories)();
const preset = (0, loader_1.getActivePreset)();
// Check built-in categories first, then preset categories
let categorySiUnit = categoriesData.categoryToBaseUnit[category];
if (!categorySiUnit && preset?.categories?.[category]?.baseUnit) {
categorySiUnit = preset.categories[category].baseUnit;
}
if (!categorySiUnit) {
return `Unknown category: ${category}`;
}
// If path has a defined SI unit, it must match category's SI unit
if (pathSiUnit && pathSiUnit !== categorySiUnit) {
return `Category "${category}" requires SI unit "${categorySiUnit}" but path has "${pathSiUnit}"`;
}
return null; // Valid
}
//# sourceMappingURL=resolver.js.map