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 🙏

© 2026 – Pkg Stats / Ryan Hefner

armanion

v9.0.0

Published

A professional-grade data system with proprietary .arm storage format

Readme

Armanion Data System

A professional-grade Node.js library with proprietary .arm storage format

Armanion is not just a file format—it's a complete Data System and State Engine designed for production use. Built with TypeScript in strict mode, it offers a minimalistic API that masks sophisticated internal architecture.

Philosophy

Armanion treats data as a living system rather than static storage:

  • Data System: Self-contained storage with its own philosophy and identity
  • State Engine: Dynamic state management with intelligent change tracking
  • Zero Compromise: Production-ready from day one with crash prevention guarantees
  • Elegant Simplicity: Complex internals, simple interface

Core Principles

  1. Deterministic: Predictable behavior across all scenarios
  2. Safe: Zero tolerance for unsafe types (no any)
  3. Atomic: All operations are transactional
  4. Encrypted: Native security without external dependencies
  5. Extensible: Plugin architecture without touching core code

Installation

npm install armanion

Quick Start

Basic Usage

import { Armanion } from 'armanion';

// Create new data system
const arm = Armanion.create({
  user: {
    name: 'John',
    age: 30
  }
});

// Read data
const name = arm.get('user.name'); // "John"

// Write data
arm.set('user.email', '[email protected]');

// Save to file
await arm.save('data.arm');

Load Existing File

import { Armanion } from 'armanion';

// Load from .arm file
const arm = await Armanion.load('data.arm');

// Access data
const user = arm.get('user');
console.log(user);

Mental Model

Think of Armanion as a smart document that:

  1. Remembers its state and tracks every change
  2. Validates operations before executing them
  3. Protects data with built-in encryption
  4. Prevents corruption through atomic transactions
  5. Extends functionality through plugins

Data Paths

Access data using dot notation paths:

// Simple path
arm.get('user.name');

// Nested path
arm.get('settings.display.theme');

// Arrays work too
arm.get('users.0.name');

Paths are:

  • Normalized automatically
  • Validated before use
  • Protected from injection

Core Features

1. Change Tracking

Every modification is tracked:

arm.set('user.name', 'Jane');
arm.set('user.age', 31);

// View all changes
const changes = arm.getChanges();
// [
//   { path: 'user.name', operation: 'set', oldValue: 'John', newValue: 'Jane' },
//   { path: 'user.age', operation: 'set', oldValue: 30, newValue: 31 }
// ]

// Check if modified
const hasChanges = arm.hasChanges(); // true

2. Transactions

Atomic operations with automatic rollback:

await arm.transaction(async (arm) => {
  arm.set('account.balance', 1000);
  arm.set('account.status', 'active');
  
  // If any error occurs, all changes rollback
  if (someCondition) {
    throw new Error('Validation failed');
  }
  
  // Changes only persist if transaction completes
});

3. Lazy Loading

Efficient memory usage for large datasets:

const arm = Armanion.create(hugData, {
  lazyThreshold: 5000 // Load chunks larger than 5KB on-demand
});

// Data loaded only when accessed
const section = arm.get('large.section');

4. Data Operations

// Set value
arm.set('user.name', 'John');

// Get value
const name = arm.get('user.name');

// Delete value
arm.delete('user.temp');

// Merge objects
arm.merge('user', { 
  email: '[email protected]',
  verified: true 
});

// Check existence
if (arm.has('user.email')) {
  console.log('Email exists');
}

5. Auto-Save

Automatic persistence on changes:

const arm = Armanion.create(data, {
  autoSave: true
});

// File is automatically saved after each change
arm.set('user.name', 'Jane');

Security & Encryption

Password-Based Encryption

// Create with encryption
const arm = Armanion.create(data, {
  encryption: {
    password: 'your-secure-password'
  }
});

// Save encrypted
await arm.save('secure.arm');

// Load encrypted
const loaded = await Armanion.load('secure.arm', {
  encryption: {
    password: 'your-secure-password'
  }
});

Key-Based Encryption

import { KeyDerivation } from 'armanion';

// Generate strong key
const key = KeyDerivation.deriveKey(
  'password',
  KeyDerivation.generateSalt(),
  32 // 256-bit key
);

const arm = Armanion.create(data, {
  encryption: { key }
});

Selective Field Encryption

Encrypt only sensitive fields:

const arm = Armanion.create(data, {
  encryption: {
    password: 'secret',
    selectiveFields: ['user.password', 'user.ssn', 'payment.cardNumber']
  }
});

// Only specified fields are encrypted
// Other fields remain in plaintext for performance

Custom Encryption Algorithms

import { EncryptionAlgorithm } from 'armanion';

class CustomAlgorithm implements EncryptionAlgorithm {
  readonly keySize = 32;
  readonly name = 'Custom-AES';
  
  encrypt(data: Buffer, key: Buffer): Buffer {
    // Your encryption logic
  }
  
  decrypt(data: Buffer, key: Buffer): Buffer {
    // Your decryption logic
  }
}

const arm = Armanion.create(data, {
  encryption: {
    key: myKey,
    algorithm: new CustomAlgorithm()
  }
});

Extensibility

Hooks System

React to system events:

import { HookEvent } from 'armanion';

const arm = Armanion.create();

// Before save
arm.on(HookEvent.BEFORE_SAVE, async (context) => {
  console.log('Saving to:', context.path);
});

// After load
arm.on(HookEvent.AFTER_LOAD, async (context) => {
  console.log('Loaded:', context.data);
});

// On error
arm.on(HookEvent.ERROR, async (context) => {
  console.error('Error:', context.error);
});

Available events:

  • BEFORE_LOAD / AFTER_LOAD
  • BEFORE_SAVE / AFTER_SAVE
  • BEFORE_GET / AFTER_GET
  • BEFORE_SET / AFTER_SET
  • BEFORE_DELETE / AFTER_DELETE
  • BEFORE_COMMIT / AFTER_COMMIT
  • BEFORE_ROLLBACK / AFTER_ROLLBACK
  • ERROR

Plugins

Extend functionality without modifying core:

import { Plugin, HookEvent } from 'armanion';

class AuditPlugin implements Plugin {
  name = 'audit';
  version = '1.0.0';
  
  install(hooks) {
    hooks.on(HookEvent.AFTER_SET, async (context) => {
      console.log(`Audit: Set ${context.path} = ${context.value}`);
    });
  }
}

const arm = Armanion.create();
await arm.use(new AuditPlugin());

Built-in Plugins

Validation Plugin

import { ValidationPlugin } from 'armanion';

const validator = new ValidationPlugin();

validator.addValidator('user.age', (value) => {
  return typeof value === 'number' && value >= 0 && value <= 150;
});

validator.addValidator('user.email', (value) => {
  return typeof value === 'string' && value.includes('@');
});

await arm.use(validator);

// Now these will be validated
arm.set('user.age', 25); // ✓ OK
arm.set('user.age', -5); // ✗ Error: Validation failed

Logging Plugin

import { LoggingPlugin } from 'armanion';

await arm.use(new LoggingPlugin(console.log));

// All operations will be logged
arm.set('user.name', 'John');
// Logs: [BEFORE_SET] { path: 'user.name', value: 'John', ... }
// Logs: [AFTER_SET] { path: 'user.name', value: 'John', ... }

Error Handling

Structured Errors

All errors are deterministic and structured:

import { ArmanionError, ErrorCode } from 'armanion';

try {
  arm.get('nonexistent.path');
} catch (error) {
  if (error instanceof ArmanionError) {
    console.log(error.code); // ErrorCode.DATA_NOT_FOUND
    console.log(error.message); // "Data not found at path: nonexistent.path"
    console.log(error.recoverable); // false
    console.log(error.context); // Full error context
  }
}

Error Codes

ErrorCode.FILE_NOT_FOUND
ErrorCode.FILE_CORRUPTED
ErrorCode.INVALID_PATH
ErrorCode.DATA_NOT_FOUND
ErrorCode.VALIDATION_FAILED
ErrorCode.TRANSACTION_FAILED
ErrorCode.ENCRYPTION_FAILED
ErrorCode.DECRYPTION_FAILED
ErrorCode.OPERATION_NOT_PERMITTED
ErrorCode.INTERNAL_ERROR

Crash Prevention

Armanion guarantees your application won't crash:

// Safe execution wrapper
import { safeExecute } from 'armanion';

const result = safeExecute(
  () => riskyOperation(),
  (error) => ErrorFactory.internalError('Operation failed')
);

// Async version
const result = await safeExecuteAsync(
  async () => await riskyAsyncOperation()
);

Performance

Optimizations

  1. Lazy Loading: Large data chunks load on-demand
  2. No-Op Detection: Identical values don't trigger changes
  3. Smart Serialization: Efficient binary format
  4. Minimal I/O: Operations batched automatically
  5. Change Tracking: Only modified data is processed

Benchmarks

// Large dataset handling
const arm = Armanion.create(dataWith10MBSize);

// Fast access (O(1) for paths)
const value = arm.get('deep.nested.path'); // ~0.1ms

// Efficient saves (only changed data)
await arm.save('data.arm'); // ~50ms for 10MB

// Memory efficient (lazy loading)
console.log(process.memoryUsage()); // ~15MB for 10MB file

Best Practices

1. Use Transactions for Multiple Operations

// ✓ Good - Atomic
await arm.transaction(async (arm) => {
  arm.set('user.name', 'John');
  arm.set('user.email', '[email protected]');
  arm.delete('user.temp');
});

// ✗ Bad - Non-atomic
arm.set('user.name', 'John');
arm.set('user.email', '[email protected]');
arm.delete('user.temp');

2. Use Type Safety

// ✓ Good - Type safe
interface User {
  name: string;
  age: number;
}

const user = arm.get<User>('user');

// ✗ Bad - Untyped
const user = arm.get('user');

3. Validate Before Save

// ✓ Good
import { ValidationPlugin } from 'armanion';

const validator = new ValidationPlugin();
validator.addValidator('user.age', (v) => typeof v === 'number');
await arm.use(validator);

// ✗ Bad - No validation
arm.set('user.age', 'invalid'); // Could cause issues

4. Handle Errors Explicitly

// ✓ Good
try {
  await arm.save('data.arm');
} catch (error) {
  if (error instanceof ArmanionError) {
    handleArmanionError(error);
  }
}

// ✗ Bad - Silent failures
arm.save('data.arm').catch(() => {});

5. Use Encryption for Sensitive Data

// ✓ Good
const arm = Armanion.create(data, {
  encryption: {
    password: process.env.ENCRYPTION_KEY,
    selectiveFields: ['password', 'ssn', 'creditCard']
  }
});

// ✗ Bad - Plaintext sensitive data
const arm = Armanion.create(data);

ARM File Format

The .arm format is a proprietary binary format:

[Header: 12 bytes]
  - Magic: 'ARM\x01' (4 bytes)
  - Version: 1 byte
  - Flags: 1 byte (encrypted, compressed, indexed)
  - Reserved: 2 bytes
  - Checksum: 4 bytes

[Metadata Section]
  - Length: 4 bytes
  - JSON metadata

[Data Section]
  - Length: 4 bytes
  - Data (plaintext or encrypted)

[Index Section] (optional)
  - Length: 4 bytes
  - Index data

Features:

  • Corruption Detection: CRC-32 checksum
  • Version Control: Format version embedded
  • Metadata: Created/modified timestamps, encryption info
  • Compact: Binary format, minimal overhead
  • Extensible: Reserved bytes for future features

Advanced Usage

Custom Serialization

import { ARMSerializer, ARMStructure } from 'armanion';

// Create custom structure
const structure = ARMSerializer.create(
  Buffer.from(JSON.stringify(data)),
  { custom: { author: 'John' } },
  { encrypted: true }
);

// Serialize to buffer
const buffer = ARMSerializer.serialize(structure);

// Deserialize from buffer
const loaded = ARMSerializer.deserialize(buffer);

Direct Engine Access

// For advanced users who need full control
const arm = Armanion.create();
const engine = arm['engine']; // Access private engine

// Use engine directly (bypasses hooks)
engine.set('path', value);
const changes = engine.getChanges();

Custom Plugins

class CompressionPlugin implements Plugin {
  name = 'compression';
  version = '1.0.0';
  
  install(hooks) {
    // Compress before save
    hooks.on(HookEvent.BEFORE_SAVE, async (context) => {
      if (context.structure) {
        context.structure.data = compress(context.structure.data);
        context.structure.header.flags.compressed = true;
      }
    });
    
    // Decompress after load
    hooks.on(HookEvent.AFTER_LOAD, async (context) => {
      if (context.structure?.header.flags.compressed) {
        context.data = decompress(context.data);
      }
    });
  }
}

TypeScript Support

Full TypeScript support with strict typing:

import { Armanion, ArmanionConfig, HookEvent } from 'armanion';

interface AppData {
  users: User[];
  settings: Settings;
}

const config: ArmanionConfig = {
  encryption: {
    password: 'secret'
  },
  autoSave: true
};

const arm = Armanion.create<AppData>({
  users: [],
  settings: {}
}, config);

// Type-safe access
const users = arm.get<User[]>('users');

JavaScript (CommonJS) Support

Works seamlessly with CommonJS:

// CommonJS
const { Armanion } = require('armanion');

const arm = Armanion.create({ data: 'value' });
arm.save('data.arm');

API Reference

Armanion Class

Static Methods

  • create(data?, config?) - Create new instance
  • load(filePath, config?) - Load from .arm file

Instance Methods

  • get<T>(path) - Get value at path
  • set(path, value) - Set value at path
  • delete(path) - Delete value at path
  • merge(path, object) - Merge object at path
  • has(path) - Check if path exists
  • save(filePath?) - Save to .arm file
  • transaction(operation) - Execute in transaction
  • getChanges() - Get all changes
  • hasChanges() - Check if has changes
  • export() - Export all data
  • on(event, handler) - Register hook
  • use(plugin) - Install plugin
  • unuse(pluginName) - Uninstall plugin

License

MIT

Contributing

Contributions are welcome! Please ensure:

  1. All tests pass
  2. TypeScript strict mode is satisfied
  3. No any types are used
  4. Code is documented
  5. Error handling is comprehensive

Support

For issues, questions, or contributions, please open an issue on GitHub.


Armanion - Professional data management, simplified.