dosis
v0.1.0
Published
Deterministic parser for medication dosages - like chrono for drug dosages
Maintainers
Readme
Dosis
Deterministic parser for medication dosages - like chrono for drug dosages.
Dosis is a lightweight, type-safe TypeScript library that parses dosage strings (like "20 mg", "3.5 grams", or "500 micrograms") into structured data. It handles unit normalization, conversion, and validation with comprehensive error handling.
Features
- Simple API - One function to parse any dosage string
- Type-safe - Full TypeScript support with detailed type definitions
- Unit normalization - Automatically converts between mg, g, and mcg
- Flexible parsing - Handles various formats, plurals, and whitespace
- Error handling - Optional strict mode with descriptive errors
- Validation - Customizable dosage range validation
- Zero dependencies - Lightweight and fast
- Well-tested - 62 comprehensive tests with >90% coverage
Installation
npm install dosisyarn add dosispnpm add dosisQuick Start
import { parseDosage } from 'dosis';
// Parse a simple dosage
const result = parseDosage("20 mg");
console.log(result);
// {
// original: "20 mg",
// value: 20,
// unit: "mg",
// mg: 20,
// formatted: "20 mg"
// }
// Parse with automatic conversion
const result2 = parseDosage("3.5 grams");
console.log(result2);
// {
// original: "3.5 grams",
// value: 3.5,
// unit: "g",
// mg: 3500,
// formatted: "3500 mg"
// }
// Invalid input returns null (default)
const invalid = parseDosage("not a dosage");
console.log(invalid); // nullAPI Reference
parseDosage(input: string, options?: ParseOptions): DosageParsed | null
Parses a dosage string into structured data.
Parameters
input(string): The dosage string to parse (e.g., "20 mg", "3.5 g", "500 mcg")options(ParseOptions, optional): Configuration optionsstrict(boolean, default:false): If true, throws errors instead of returning nullmaxDosageMg(number, default:1,000,000): Maximum allowed dosage in mgminDosageMg(number, default:0.000001): Minimum allowed dosage in mg
Returns
Returns a DosageParsed object on success, or null on failure (when not in strict mode).
interface DosageParsed {
original: string; // Original input string
value: number; // Numeric value extracted
unit: string; // Normalized unit (mg | g | mcg)
mg: number; // Dosage converted to mg
formatted: string; // Formatted output (e.g., "3500 mg")
}Throws (strict mode only)
InvalidFormatError: When input doesn't match expected formatInvalidValueError: When numeric value is invalid (zero, negative, NaN)InvalidUnitError: When unit is not recognizedDosageOutOfRangeError: When dosage is outside allowed bounds
Supported Formats
Units
| Unit | Variations | Conversion to mg |
|------|-----------|------------------|
| Milligrams | mg, milligram, milligrams | 1 mg = 1 mg |
| Grams | g, gram, grams | 1 g = 1000 mg |
| Micrograms | mcg, ug, microgram, micrograms | 1 mcg = 0.001 mg |
Format Examples
All of the following are valid:
parseDosage("20 mg") // With space
parseDosage("20mg") // Without space
parseDosage(" 20 mg ") // With whitespace
parseDosage("20 MG") // Case insensitive
parseDosage("20 milligrams") // Full word
parseDosage("20.5 mg") // Decimals
parseDosage("0.001 g") // Small decimals
parseDosage("500 mcg") // Micrograms
parseDosage("500 ug") // Alternative mcg notationUsage Examples
Basic Usage
import { parseDosage } from 'dosis';
// Simple parsing
const dose = parseDosage("100 mg");
console.log(dose.mg); // 100
// Unit conversion
const grams = parseDosage("2.5 g");
console.log(grams.mg); // 2500
// Micrograms
const mcg = parseDosage("250 micrograms");
console.log(mcg.mg); // 0.25Strict Mode
Use strict mode to get detailed error information instead of null:
import { parseDosage, InvalidFormatError, InvalidValueError } from 'dosis';
try {
const result = parseDosage("invalid input", { strict: true });
} catch (error) {
if (error instanceof InvalidFormatError) {
console.error("Invalid format:", error.message);
console.error("Input was:", error.input);
}
}
// Validate dosage values
try {
parseDosage("0 mg", { strict: true }); // Throws InvalidValueError
} catch (error) {
console.error("Dosage must be greater than 0");
}
try {
parseDosage("-20 mg", { strict: true }); // Throws InvalidValueError
} catch (error) {
console.error("Dosage cannot be negative");
}Custom Validation Ranges
Restrict dosages to specific ranges:
// Only allow dosages between 1mg and 1000mg
const result = parseDosage("500 mg", {
minDosageMg: 1,
maxDosageMg: 1000
});
// In strict mode, out-of-range throws error
try {
parseDosage("5000 mg", {
strict: true,
maxDosageMg: 1000
});
} catch (error) {
console.error("Dosage too high!");
}Handling Invalid Input
// Lenient mode (default) - returns null
const invalid1 = parseDosage(""); // null
const invalid2 = parseDosage("not a dose"); // null
const invalid3 = parseDosage("20 liters"); // null
const invalid4 = parseDosage("-10 mg"); // null
const invalid5 = parseDosage("0 mg"); // null
// Check result before using
const dose = parseDosage(userInput);
if (dose) {
console.log(`Parsed dosage: ${dose.formatted}`);
} else {
console.log("Invalid dosage format");
}Unit Normalization
All dosages are normalized to a standard unit:
const doses = [
parseDosage("1000 mg"),
parseDosage("1 g"),
parseDosage("1000000 mcg")
];
// All have the same mg value
doses.forEach(dose => {
console.log(dose.mg); // 1000
console.log(dose.formatted); // "1000 mg"
});Working with the Result
const dose = parseDosage("2.5 grams");
console.log(dose.original); // "2.5 grams" - original input
console.log(dose.value); // 2.5 - numeric value
console.log(dose.unit); // "g" - normalized unit
console.log(dose.mg); // 2500 - converted to mg
console.log(dose.formatted); // "2500 mg" - standard formatError Handling
Dosis provides detailed error classes for different failure scenarios:
import {
parseDosage,
DosageParseError, // Base error class
InvalidFormatError, // Invalid format
InvalidValueError, // Invalid numeric value
InvalidUnitError, // Unrecognized unit
DosageOutOfRangeError // Out of bounds
} from 'dosis';
try {
const result = parseDosage(input, { strict: true });
} catch (error) {
if (error instanceof DosageParseError) {
// All dosis errors have .input property
console.error(`Failed to parse: "${error.input}"`);
console.error(error.message);
}
}TypeScript Support
Dosis is written in TypeScript and provides full type definitions:
import type { DosageParsed, ParseOptions } from 'dosis';
function processDosage(input: string): DosageParsed | null {
return parseDosage(input);
}
const options: ParseOptions = {
strict: true,
maxDosageMg: 10000,
minDosageMg: 0.001
};Development
Setup
git clone https://github.com/yourusername/dosis.git
cd dosis
npm installScripts
npm test # Run tests in watch mode
npm run test:run # Run tests once
npm run test:coverage # Run tests with coverage report
npm run build # Build the packageTesting
Dosis has comprehensive test coverage with 62 tests covering:
- All unit variations and formats
- Case sensitivity and whitespace handling
- Number formats (integers, decimals, edge cases)
- Conversion accuracy
- Error conditions
- Validation ranges
- Edge cases
Run tests with coverage:
npm run test:coverageComparison with Alternatives
Unlike date parsing libraries like chrono that use natural language processing, Dosis uses deterministic pattern matching for reliable, predictable results. It's designed specifically for medication dosages with proper unit handling and medical-appropriate validation.
Why "Dosis"?
"Dosis" is Latin for "dose" - keeping with the medical theme while being short and memorable.
License
MIT © Jack Weatherilt
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Disclaimer: This library is for parsing dosage strings only. Always consult healthcare professionals for medical advice. Do not use this library to make medical decisions.
