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

@aurabx/jmix-js

v0.2.1

Published

TypeScript implementation of JMIX (JSON Medical Interchange) format for secure medical data exchange

Downloads

13

Readme

JMIX TypeScript Library

TypeScript implementation of the JMIX (JSON Medical Interchange) format for secure medical data exchange.

Installation

npm install
npm run build

Prerequisites

  • Node.js 20+ LTS
  • npm
  • TypeScript 5+

Quick Start

import { JmixBuilder } from 'jmix-ts';

// Create a builder
const builder = new JmixBuilder({
  outputPath: './tmp'
});

// Create or load configuration
const config = await JmixBuilder.loadConfig('./samples/sample_config.json');

// Build envelope from DICOM directory
const envelope = await builder.buildFromDicom('./samples/study_1', config);

// Save to files
await builder.saveToFiles(envelope, './output');

Demo

Run the demo to see the library in action:

npm run build
node demo-no-validation.js

This creates a complete JMIX envelope with:

  • manifest.json - Security, routing, and patient information
  • metadata.json - Clinical data and DICOM metadata
  • audit.json - Audit trail and transmission details ckaging (folder-based JMIX envelope)

Create a proper JMIX folder that includes the original DICOM files under payload/dicom and computes a deterministic SHA-256 payload hash stored at manifest.security.payload_hash.

CLI-like demo:

node demo-package.js ./samples/study_1 ./tmp

Programmatic API:

import { JmixBuilder } from './dist/index.js';

const builder = new JmixBuilder();
const config = await JmixBuilder.loadConfig('./samples/sample_config.json');
const packagePath = await builder.packageToDirectory('./samples/study_1', config, './tmp');
console.log(packagePath); // => ./tmp/<envelope_id>.JMIX

Resulting layout:

<outputRoot>/<envelope_id>.JMIX/
├── manifest.json
├── audit.json
└── payload/
    ├── metadata.json
    └── dicom/
        └── ... (original DICOM files, structure preserved)

Encryption (AES-256-GCM with X25519 + HKDF)

The library can produce an encrypted JMIX envelope. It tars the plaintext payload/ directory, encrypts it with AES-256-GCM using a key derived from X25519 ECDH and HKDF-SHA256, then writes payload.encrypted and removes the plaintext payload/.

  • Key agreement: Curve25519 (X25519)
  • KDF: HKDF-SHA256 (info = "JMIX-Payload-Encryption")
  • Cipher: AES-256-GCM
  • Manifest fields:
    • manifest.security.payload_hash — SHA-256 over the plaintext payload/ (deterministic, path+newline+bytes per file)
    • manifest.security.encryption:
      • algorithm: "AES-256-GCM"
      • ephemeral_public_key: base64
      • iv: base64 (12 bytes)
      • auth_tag: base64 (16 bytes)

Demo:

# recipientPublicKeyBase64 must be a 32-byte Curve25519 key in base64
node demo-package-encrypted.js <recipientPublicKeyBase64> ./samples/study_1 ./tmp

Programmatic API:

import { JmixBuilder } from './dist/index.js';

const builder = new JmixBuilder();
const config = await JmixBuilder.loadConfig('./samples/sample_config.json');
const packagePath = await builder.packageEncryptedToDirectory(
  './samples/study_1',
  config,
  './tmp',
  '<recipientPublicKeyBase64>'
);
console.log(packagePath);

Encrypted layout:

<outputRoot>/<envelope_id>.JMIX/
├── manifest.json               # includes security.payload_hash and security.encryption
├── audit.json
└── payload.encrypted           # AES-256-GCM encrypted TAR of plaintext payload/

Decryption

You can decrypt an encrypted JMIX envelope and restore a plaintext payload/ directory. The payload hash is verified against manifest.security.payload_hash.

Self-contained demo (encrypt + decrypt with a fresh keypair):

node demo-decrypt.js ./samples/study_1 ./tmp

Decrypt an existing folder (requires the matching Curve25519 private key in base64):

node demo-decrypt-existing.js ./tmp/<envelope_id>.JMIX <recipientPrivateKeyBase64>

Programmatic API:

import { JmixBuilder } from './dist/index.js';

const builder = new JmixBuilder();
const payloadPath = await builder.decryptEnvelope(
  './tmp/<envelope_id>.JMIX',
  '<recipientPrivateKeyBase64>'
);
console.log(payloadPath);

Verify Payload Hash

Verify the payload hash listed in manifest.security.payload_hash.

  • Plaintext payload/: compare directly
  • Encrypted payload.encrypted: requires the recipient private key to decrypt to a temp dir before verifying

CLI demo:

# Plaintext envelope
npm run demo:verify:hash -- ./tmp/<envelope_id>.JMIX

# Encrypted envelope (requires private key)
npm run demo:verify:hash -- ./tmp/<envelope_id>.JMIX <recipientPrivateKeyBase64>

Programmatic API:

import { JmixBuilder } from './dist/index.js';

const builder = new JmixBuilder();
const result = await builder.verifyPayloadHash(
  './tmp/<envelope_id>.JMIX',
  { recipientPrivateKeyBase64: '<privKey-if-encrypted>' }
);
console.log(result.ok, result.expected, result.computed);

Scripts

# Development
npm run build          # Compile TypeScript
npm run typecheck      # Type checking only
npm test               # Run all tests
npm run test:watch     # Run tests in watch mode
npm run test:coverage  # Generate coverage report

# Code Quality
npm run format         # Check code formatting
npm run format:fix     # Fix code formatting
npm run clean          # Clean build artifacts

Architecture

src/
├── JmixBuilder.ts           # Main orchestrator
├── types/index.ts           # TypeScript interfaces
├── validation/              # Ajv schema validation
├── dicom/                   # DICOM file processing
├── crypto/                  # AES-256-GCM encryption (future)
└── errors/                  # Error types

tests/                       # Jest test suite
samples/                     # Sample JSON files

Configuration

Schema Validation

** This is Alpha quality code and has not yet been fully tested **

The library uses configurable schema validation:

const builder = new JmixBuilder({
  schemaValidatorOptions: {
    schemaPath: '../jmix/schemas',  // Default: ../jmix/schemas
    strictMode: true                // Default: true
  }
});

// Or via environment variable
process.env.JMIX_SCHEMA_PATH = '/path/to/schemas';

Output Directory

Follows user rules for temp file output:

const builder = new JmixBuilder({
  outputPath: './tmp'  // Default: ./tmp (not /tmp)
});

DICOM Processing

The library automatically:

  1. Recursively scans directories for DICOM files
  2. Validates files using DICM magic number at byte offset 128
  3. Extracts metadata (patient info, study details, series information)
  4. Falls back gracefully to configuration data when DICOM parsing fails
  5. Supports empty directories for testing

Schema Validation

  • Default: Looks for schemas in ../jmix/schemas
  • Configurable: Override via constructor or environment variable
  • Graceful Degradation: Skips validation when schemas not found
  • Comprehensive: Validates manifest, metadata, and audit components

Testing

Run the comprehensive test suite:

# All tests
npm test

# Specific test files
npm test JmixBuilder.test.ts
npm test SchemaValidator.test.ts

# With coverage
npm run test:coverage

The test suite includes:

  • ✅ JmixBuilder integration tests
  • ✅ Schema validator tests
  • ✅ Type definition tests
  • ✅ DICOM processing tests
  • ✅ Configuration loading tests
  • ✅ File I/O tests

All tests use the /samples directory for realistic test data and output to ./tmp for temporary files.

Security Model

Implements the JMIX security whitepaper specifications:

  • AES-256-GCM encryption with ephemeral public keys
  • Base64 encoding for all cryptographic material (ephemeral_public_key, iv, auth_tag)
  • Forward secrecy through ephemeral key usage
  • Optional governance via Aurabox directory services

See .ai/security.md for the complete security model.

Development

The library follows TypeScript best practices:

  • ESM modules with .js imports in source
  • Strict TypeScript configuration
  • Comprehensive type definitions for all JMIX components
  • Jest testing with ts-jest for ESM support
  • Prettier formatting for consistent code style

Files Generated

A complete JMIX envelope consists of:

  • manifest.json - Routing, security classification, patient info, sender/receiver details
  • metadata.json - Clinical metadata, DICOM study information, custom metadata
  • audit.json - Audit trail, status, and events timeline
  • files.json - (Optional) File manifest with hashes and sizes

Compatibility

  • JMIX Specification: Implements JMIX v1.0 format
  • Schema Compatibility: Works with JMIX JSON Schema Draft 2020-12
  • DICOM Support: Basic DICOM file detection and metadata extraction
  • Framework Agnostic: Pure TypeScript, works with any Node.js framework

License

Matches the licensing of the JMIX specification and related implementations.


For detailed API documentation, see the TypeScript declarations in dist/ after building.