@rustledger/wasm 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,419 @@
1
+ # rustledger
2
+
3
+ A pure Rust implementation of [Beancount](https://beancount.github.io/), the double-entry bookkeeping language.
4
+
5
+ [![CI](https://github.com/rustledger/rustledger/actions/workflows/ci.yml/badge.svg)](https://github.com/rustledger/rustledger/actions/workflows/ci.yml)
6
+ [![Crates.io](https://img.shields.io/crates/v/rustledger.svg)](https://crates.io/crates/rustledger)
7
+ [![Documentation](https://docs.rs/rustledger/badge.svg)](https://docs.rs/rustledger)
8
+ [![codecov](https://codecov.io/gh/rustledger/rustledger/graph/badge.svg)](https://codecov.io/gh/rustledger/rustledger)
9
+ [![License](https://img.shields.io/crates/l/rustledger.svg)](LICENSE)
10
+
11
+ [![GitHub Release](https://img.shields.io/github/v/release/rustledger/rustledger?label=release)](https://github.com/rustledger/rustledger/releases)
12
+ [![npm](https://img.shields.io/npm/v/@rustledger/wasm?label=npm%20wasm)](https://www.npmjs.com/package/@rustledger/wasm)
13
+ [![AUR](https://img.shields.io/aur/version/rustledger?logo=arch-linux&label=AUR)](https://aur.archlinux.org/packages/rustledger)
14
+ [![Copr](https://copr.fedorainfracloud.org/coprs/robcohen/rustledger/package/rustledger/status_image/last_build.png)](https://copr.fedorainfracloud.org/coprs/robcohen/rustledger/)
15
+ [![Packaging status](https://repology.org/badge/tiny-repos/rustledger.svg)](https://repology.org/project/rustledger/versions)
16
+
17
+ ## Why rustledger?
18
+
19
+ - **10x faster** than Python beancount - parse and validate large ledgers in milliseconds
20
+ - **Pure Rust** - No Python dependencies, single binary, compiles to native and WebAssembly
21
+ - **Drop-in replacement** - Compatible `bean-*` CLI commands for easy migration
22
+ - **Formally verified** - Core algorithms verified with 19 TLA+ specifications
23
+ - **Full compatibility** - Parses any valid beancount file
24
+
25
+ ## Quick Start
26
+
27
+ ```bash
28
+ # Install
29
+ cargo install rustledger
30
+
31
+ # Validate your ledger
32
+ rledger-check ledger.beancount
33
+
34
+ # Query your data
35
+ rledger-query ledger.beancount "SELECT account, SUM(position) GROUP BY account"
36
+ ```
37
+
38
+ Example output:
39
+ ```
40
+ $ rledger-check example.beancount
41
+ Loaded 1,247 directives in 12ms
42
+ ✓ No errors found
43
+
44
+ $ rledger-query example.beancount "BALANCES WHERE account ~ 'Assets:'"
45
+ account balance
46
+ ------------------------- ----------------
47
+ Assets:Bank:Checking 2,450.00 USD
48
+ Assets:Bank:Savings 15,000.00 USD
49
+ Assets:Investments 5,230.50 USD
50
+ ```
51
+
52
+ ## Installation
53
+
54
+ ### Quick Install (Linux/macOS)
55
+
56
+ ```bash
57
+ curl -sSfL rustledger.github.io/i | sh
58
+ ```
59
+
60
+ ### Homebrew (macOS/Linux)
61
+
62
+ ```bash
63
+ brew install rustledger/rustledger/rustledger
64
+ ```
65
+
66
+ ### Scoop (Windows)
67
+
68
+ ```powershell
69
+ scoop bucket add rustledger https://github.com/rustledger/scoop-rustledger
70
+ scoop install rustledger
71
+ ```
72
+
73
+ ### Cargo
74
+
75
+ ```bash
76
+ # Pre-built binary (fast)
77
+ cargo binstall rustledger
78
+
79
+ # Build from source
80
+ cargo install rustledger
81
+ ```
82
+
83
+ ### Nix
84
+
85
+ ```bash
86
+ # Run directly
87
+ nix run github:rustledger/rustledger -- rledger-check ledger.beancount
88
+
89
+ # Install to profile
90
+ nix profile install github:rustledger/rustledger
91
+ ```
92
+
93
+ ### Arch Linux (AUR)
94
+
95
+ ```bash
96
+ # Pre-built binary (recommended)
97
+ yay -S rustledger-bin
98
+
99
+ # Or build from source
100
+ yay -S rustledger
101
+ ```
102
+
103
+ ### Docker
104
+
105
+ ```bash
106
+ # Validate a ledger file
107
+ docker run --rm -v "$PWD:/data" ghcr.io/rustledger/rustledger /data/ledger.beancount
108
+
109
+ # Run queries
110
+ docker run --rm -v "$PWD:/data" --entrypoint rledger-query ghcr.io/rustledger/rustledger \
111
+ /data/ledger.beancount "SELECT account, SUM(position) GROUP BY account"
112
+
113
+ # Use a specific version
114
+ docker run --rm -v "$PWD:/data" ghcr.io/rustledger/rustledger:1.0.0 /data/ledger.beancount
115
+ ```
116
+
117
+ ### Pre-built Binaries
118
+
119
+ Download from [GitHub Releases](https://github.com/rustledger/rustledger/releases) for:
120
+ - Linux (x86_64, ARM64, glibc and musl)
121
+ - macOS (Intel and Apple Silicon)
122
+ - Windows (x86_64, ARM64)
123
+
124
+ ### As a Library
125
+
126
+ ```bash
127
+ cargo add rustledger-core rustledger-parser rustledger-loader
128
+ ```
129
+
130
+ ### WebAssembly (npm)
131
+
132
+ ```bash
133
+ npm install @rustledger/wasm
134
+ ```
135
+
136
+ ### MCP Server
137
+
138
+ ```bash
139
+ npm install -g @rustledger/mcp-server
140
+ ```
141
+
142
+ ## CLI Commands
143
+
144
+ | Command | Description |
145
+ |---------|-------------|
146
+ | `rledger-check` | Validate ledger files with detailed error messages |
147
+ | `rledger-format` | Auto-format beancount files |
148
+ | `rledger-query` | Run BQL queries (interactive shell or one-shot) |
149
+ | `rledger-report` | Generate balance, account, and statistics reports |
150
+ | `rledger-doctor` | Debugging tools: context, linked transactions, missing opens |
151
+ | `rledger-extract` | Import transactions from CSV/OFX bank statements |
152
+ | `rledger-price` | Fetch commodity prices from online sources |
153
+
154
+ ### Examples
155
+
156
+ ```bash
157
+ # Validate with plugins
158
+ rledger-check --native-plugin auto_accounts ledger.beancount
159
+ rledger-check --native-plugin pedantic ledger.beancount
160
+
161
+ # Format in place
162
+ rledger-format --in-place ledger.beancount
163
+
164
+ # Interactive query shell with readline and history
165
+ rledger-query ledger.beancount
166
+
167
+ # One-shot query
168
+ rledger-query ledger.beancount "SELECT date, narration WHERE account ~ 'Expenses:Food'"
169
+
170
+ # Reports
171
+ rledger-report ledger.beancount balances
172
+ rledger-report ledger.beancount accounts
173
+ rledger-report ledger.beancount stats
174
+
175
+ # Debugging
176
+ rledger-doctor ledger.beancount context 42 # Show context around line 42
177
+ rledger-doctor ledger.beancount linked ^trip-2024 # Find linked transactions
178
+ rledger-doctor ledger.beancount missing # Find missing Open directives
179
+ ```
180
+
181
+ ### Python Beancount Compatibility
182
+
183
+ For users migrating from Python beancount, the `bean-*` commands are also available:
184
+
185
+ ```bash
186
+ bean-check ledger.beancount
187
+ bean-format ledger.beancount
188
+ bean-query ledger.beancount "SELECT ..."
189
+ bean-report ledger.beancount balances
190
+ bean-doctor ledger.beancount context 42
191
+ ```
192
+
193
+ ### Shell Completions
194
+
195
+ All CLI commands support generating shell completions:
196
+
197
+ ```bash
198
+ # Bash (add to ~/.bashrc)
199
+ rledger-check --generate-completions bash >> ~/.bashrc
200
+
201
+ # Zsh (add to ~/.zshrc)
202
+ rledger-check --generate-completions zsh >> ~/.zshrc
203
+
204
+ # Fish
205
+ rledger-check --generate-completions fish > ~/.config/fish/completions/rledger-check.fish
206
+
207
+ # PowerShell
208
+ rledger-check --generate-completions powershell >> $PROFILE
209
+ ```
210
+
211
+ Generate completions for each command you use (`rledger-check`, `rledger-query`, etc.).
212
+
213
+ ## Library Usage
214
+
215
+ ```rust
216
+ use rustledger_loader::load;
217
+ use std::path::Path;
218
+
219
+ fn main() -> anyhow::Result<()> {
220
+ let result = load(Path::new("ledger.beancount"))?;
221
+
222
+ println!("Loaded {} directives", result.directives.len());
223
+
224
+ for error in &result.errors {
225
+ eprintln!("{}", error);
226
+ }
227
+
228
+ Ok(())
229
+ }
230
+ ```
231
+
232
+ ## Importing Bank Statements
233
+
234
+ rustledger includes an import framework for extracting transactions from CSV and OFX files:
235
+
236
+ ```rust
237
+ use rustledger_importer::ImporterConfig;
238
+
239
+ let config = ImporterConfig::csv()
240
+ .account("Assets:Bank:Checking")
241
+ .currency("USD")
242
+ .date_column("Date")
243
+ .narration_column("Description")
244
+ .amount_column("Amount")
245
+ .date_format("%m/%d/%Y")
246
+ .build();
247
+
248
+ let result = config.extract_from_string(csv_content)?;
249
+ for directive in result.directives {
250
+ println!("{}", directive);
251
+ }
252
+ ```
253
+
254
+ Supports:
255
+ - CSV with configurable columns, delimiters, date formats
256
+ - Separate debit/credit columns
257
+ - OFX/QFX bank statement files
258
+ - Currency symbols, parentheses for negatives, thousand separators
259
+
260
+ ## Crates
261
+
262
+ | Crate | Description |
263
+ |-------|-------------|
264
+ | [`rustledger-core`](crates/rustledger-core) | Core types: Amount, Position, Inventory, Directives |
265
+ | [`rustledger-parser`](crates/rustledger-parser) | Lexer and parser with error recovery |
266
+ | [`rustledger-loader`](crates/rustledger-loader) | File loading, includes, options |
267
+ | [`rustledger-booking`](crates/rustledger-booking) | Interpolation and booking engine |
268
+ | [`rustledger-validate`](crates/rustledger-validate) | 30 validation error codes |
269
+ | [`rustledger-query`](crates/rustledger-query) | BQL query engine |
270
+ | [`rustledger-plugin`](crates/rustledger-plugin) | Native and WASM plugin system |
271
+ | [`rustledger-importer`](crates/rustledger-importer) | CSV/OFX import framework |
272
+ | [`rustledger`](crates/rustledger) | Command-line tools |
273
+ | [`rustledger-wasm`](crates/rustledger-wasm) | WebAssembly library target |
274
+
275
+ ## Features
276
+
277
+ ### Parser
278
+
279
+ - All 12 directive types (transaction, balance, open, close, commodity, pad, event, query, note, document, custom, price)
280
+ - Cost specifications: `{100 USD}`, `{{100 USD}}`, `{100 # 5 USD}`, `{*}`
281
+ - Price annotations: `@ 100 USD`, `@@ 1000 USD`
282
+ - Arithmetic expressions: `(40.00/3 + 5) USD`
283
+ - Multi-line strings with `"""..."""`
284
+ - All transaction flags: `* ! P S T C U R M`
285
+ - Metadata with 6 value types
286
+ - Error recovery (continues parsing after errors)
287
+
288
+ ### Booking Methods
289
+
290
+ | Method | Description |
291
+ |--------|-------------|
292
+ | `STRICT` | Lots must match exactly (default) |
293
+ | `STRICT_WITH_SIZE` | Exact-size matches accept oldest lot |
294
+ | `FIFO` | First in, first out |
295
+ | `LIFO` | Last in, first out |
296
+ | `HIFO` | Highest cost first |
297
+ | `AVERAGE` | Average cost basis |
298
+ | `NONE` | No cost tracking |
299
+
300
+ ### Built-in Plugins (14)
301
+
302
+ | Plugin | Description |
303
+ |--------|-------------|
304
+ | `implicit_prices` | Generate price entries from transaction costs |
305
+ | `check_commodity` | Validate commodity declarations |
306
+ | `auto_accounts` | Auto-generate Open directives |
307
+ | `leafonly` | Error on postings to non-leaf accounts |
308
+ | `noduplicates` | Hash-based duplicate transaction detection |
309
+ | `onecommodity` | Single commodity per account |
310
+ | `unique_prices` | One price per day per commodity pair |
311
+ | `check_closing` | Zero balance assertion on account close |
312
+ | `close_tree` | Close descendant accounts |
313
+ | `coherent_cost` | Enforce cost OR price (not both) |
314
+ | `sellgains` | Cross-check capital gains against sales |
315
+ | `pedantic` | Enable all strict validations |
316
+ | `unrealized` | Calculate unrealized gains |
317
+ | `nounused` | Warn on unused accounts |
318
+
319
+ ### Options (28 supported)
320
+
321
+ - Account prefixes (`name_assets`, `name_liabilities`, etc.)
322
+ - Equity accounts (`account_previous_balances`, `account_unrealized_gains`, etc.)
323
+ - Tolerance settings (`inferred_tolerance_default` with wildcards)
324
+ - Booking method, document directories, and more
325
+
326
+ ## Performance
327
+
328
+ rustledger is approximately **10x faster** than Python beancount:
329
+
330
+ | Operation | Python beancount | rustledger | Speedup |
331
+ |-----------|------------------|------------|---------|
332
+ | Parse 10K transactions | ~800ms | ~80ms | 10x |
333
+ | Full validation | ~1.2s | ~120ms | 10x |
334
+ | BQL query | ~200ms | ~20ms | 10x |
335
+
336
+ *Benchmarks on M1 MacBook Pro with a real-world 10,000 transaction ledger.*
337
+
338
+ ## Formal Verification
339
+
340
+ Core algorithms are formally specified and verified using TLA+:
341
+
342
+ - **19 TLA+ specifications** covering inventory management, booking methods, validation rules
343
+ - **Inductive invariants** prove conservation of units across all operations
344
+ - **Model checking** explores millions of states to find edge cases
345
+ - **Refinement proofs** verify Rust implementation matches specifications
346
+
347
+ ```bash
348
+ # Run all TLA+ model checks
349
+ just tla-all
350
+
351
+ # Check specific specification
352
+ just tla-check Conservation
353
+ ```
354
+
355
+ ## Development
356
+
357
+ ### With Nix (recommended)
358
+
359
+ ```bash
360
+ # Enter development shell with all tools
361
+ nix develop
362
+
363
+ # Run tests
364
+ cargo test --all-features
365
+
366
+ # Run lints
367
+ cargo clippy --all-features
368
+
369
+ # Format code
370
+ cargo fmt
371
+ ```
372
+
373
+ ### Without Nix
374
+
375
+ ```bash
376
+ # Install Rust
377
+ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
378
+
379
+ # Clone and build
380
+ git clone https://github.com/rustledger/rustledger
381
+ cd rustledger
382
+ cargo build --release
383
+ ```
384
+
385
+ ### Running Tests
386
+
387
+ ```bash
388
+ # All tests
389
+ cargo test --all-features
390
+
391
+ # Specific crate
392
+ cargo test -p rustledger-parser
393
+
394
+ # With coverage
395
+ cargo llvm-cov --all-features
396
+ ```
397
+
398
+ ## Compatibility
399
+
400
+ rustledger is fully compatible with Python beancount. It can parse and validate any valid beancount file. The `bean-*` command aliases are included by default for easy migration.
401
+
402
+ Known differences:
403
+ - Some edge cases in expression evaluation may differ slightly
404
+ - Plugin system uses native Rust or WASM (Python plugins not supported)
405
+
406
+ ## License
407
+
408
+ This project is licensed under the GNU General Public License v3.0 - see the [LICENSE](LICENSE) file for details.
409
+
410
+ ## Contributing
411
+
412
+ Contributions are welcome! Please feel free to submit a Pull Request.
413
+
414
+ Before submitting:
415
+ 1. Run `cargo test --all-features`
416
+ 2. Run `cargo clippy --all-features`
417
+ 3. Run `cargo fmt`
418
+
419
+ See [CLAUDE.md](CLAUDE.md) for code standards and architecture overview.
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@rustledger/wasm",
3
+ "type": "module",
4
+ "collaborators": [
5
+ "Rustledger Contributors"
6
+ ],
7
+ "description": "Beancount WebAssembly bindings for JavaScript/TypeScript",
8
+ "version": "0.1.0",
9
+ "license": "GPL-3.0-only",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/rustledger/rustledger"
13
+ },
14
+ "files": [
15
+ "rustledger_wasm_bg.wasm",
16
+ "rustledger_wasm.js",
17
+ "rustledger_wasm.d.ts"
18
+ ],
19
+ "main": "rustledger_wasm.js",
20
+ "homepage": "https://rustledger.github.io",
21
+ "types": "rustledger_wasm.d.ts",
22
+ "sideEffects": [
23
+ "./snippets/*"
24
+ ],
25
+ "keywords": [
26
+ "beancount",
27
+ "accounting",
28
+ "finance",
29
+ "double-entry",
30
+ "ledger"
31
+ ]
32
+ }