fragment-simulate
v0.1.0
Published
Offline double-entry ledger simulation engine for Fragment schemas
Maintainers
Readme
fragment-simulate
Offline double-entry ledger simulation engine for Fragment schemas.
Validate that your ledger schema's entry types balance correctly, satisfy pre/postconditions, and produce expected account states — all without hitting the Fragment API.
Installation
# Run directly with npx
npx fragment-simulate run -s schema.json -e entries.jsonl
# Or install globally
npm install -g fragment-simulateQuick Start
# Validate your schema
fragment-simulate validate -s fragment.json
# View chart of accounts
fragment-simulate accounts -s fragment.json
# List entry types
fragment-simulate types -s fragment.json
# Simulate entries from a file
fragment-simulate run -s fragment.json -e entries.jsonl
# Pipe entries via stdin
echo '[{"type":"payment_payout","parameters":{"psp":"stripe","seller_id":"acme","gross_amount":"10000","platform_fee":"300"}}]' | fragment-simulate run -s fragment.json
# Interactive REPL
fragment-simulate run -s fragment.json --interactiveCommands
run
Simulate ledger entries against a schema.
fragment-simulate run -s <schema> [options]
Options:
-s, --schema <path> Path to the Fragment schema file (required)
-e, --entries <path> Path to entries file (JSON, JSONL, or human-readable)
-f, --format <format> Output format: default, json, compact, quiet
-i, --interactive Start interactive REPL modeEntry sources (in priority order):
- Piped stdin
--entries <file>--interactiveREPL
Exit code: 1 if any entry is invalid, 0 otherwise.
validate
Check a schema for structural issues.
fragment-simulate validate -s <schema> [-f json]Checks:
chartOfAccountsexists with accounts and default currencyledgerEntries.typesare defined- Each entry type has lines with account paths and amounts
accounts
Display the chart of accounts tree.
fragment-simulate accounts -s <schema> [-f json]Shows each account with its type (asset/liability/income/expense), template status, and currency.
types
List all available entry types.
fragment-simulate types -s <schema> [-f json] [-t <name>]Use -t <name> to show full details (lines, parameters, conditions) for a specific type.
audit
Run entries and produce a detailed audit report with balance equation verification.
fragment-simulate audit -s <schema> -e <entries> [-f json]The audit report includes:
- Per-entry pass/fail status
- Final account balances
- Aggregate balance equation check (assets - liabilities = income - expenses)
Entry File Formats
JSON Array
[
{"type": "payment_payout", "parameters": {"psp": "stripe", "seller_id": "acme", "gross_amount": "10000", "platform_fee": "300"}},
{"type": "finalize_seller_pending", "parameters": {"seller_id": "acme", "amount": "9700"}}
]JSONL (one entry per line)
{"type": "payment_payout", "parameters": {"psp": "stripe", "seller_id": "acme", "gross_amount": "10000", "platform_fee": "300"}}
{"type": "finalize_seller_pending", "parameters": {"seller_id": "acme", "amount": "9700"}}Human-Readable
payment_payout { psp=stripe, seller_id=acme, gross_amount=10000, platform_fee=300 }
finalize_seller_pending { seller_id=acme, amount=9700 }Interactive REPL
Start with fragment-simulate run -s schema.json --interactive.
fragment> payment_payout { psp=stripe, seller_id=acme, gross_amount=10000, platform_fee=300 }
[0/1] payment_payout { psp=stripe, seller_id=acme, gross_amount=10000, platform_fee=300 }
Valid (balanced)
Balances changed:
assets/psp-settlements:stripe:USD +10000 -> 10000
liabilities/sellers:acme/pending:USD +9700 -> 9700
income/processing-fees:USD +300 -> 300
fragment> .balances
fragment> .types
fragment> .history
fragment> .help
fragment> .quitProgrammatic API
import { BalanceEngine, extractEntryTypes } from 'fragment-simulate';
import schema from './my-schema.json';
const engine = new BalanceEngine(schema);
const result = engine.simulateEntry('payment_payout', {
psp: 'stripe',
seller_id: 'acme',
gross_amount: '10000',
platform_fee: '300',
});
if (result.valid) {
console.log('Balanced!', result.balancesAfter);
} else {
console.error('Invalid:', result.reasons);
}
// Check current state
console.log(engine.getBalances());How It Works
The simulation engine:
- Parses the Fragment schema to extract account types, entry definitions, and conditions
- Fills template parameters (
{{param}}) in account paths and amount expressions - Evaluates amount expressions (integer arithmetic with
+and-) - Validates the double-entry equation:
assets - liabilities = income - expensesper currency - Checks preconditions (e.g.,
balance >= 0) against current state - Applies the entry to update internal balances
- Checks postconditions and atomically rolls back if any fail
All arithmetic uses bigint for precision — no floating-point rounding issues.
Building Standalone Binaries
./build-binaries.sh # build for current platform
./build-binaries.sh --all # build for linux, macos, windowsRequires Node.js >= 20 (uses Node SEA) or @yao-pkg/pkg as fallback.
License
MIT
