npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

dosis

v0.1.0

Published

Deterministic parser for medication dosages - like chrono for drug dosages

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 dosis
yarn add dosis
pnpm add dosis

Quick 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); // null

API 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 options
    • strict (boolean, default: false): If true, throws errors instead of returning null
    • maxDosageMg (number, default: 1,000,000): Maximum allowed dosage in mg
    • minDosageMg (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 format
  • InvalidValueError: When numeric value is invalid (zero, negative, NaN)
  • InvalidUnitError: When unit is not recognized
  • DosageOutOfRangeError: 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 notation

Usage 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.25

Strict 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 format

Error 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 install

Scripts

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 package

Testing

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:coverage

Comparison 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.