@rustledger/wasm 0.1.0 → 0.2.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 CHANGED
@@ -1,167 +1,73 @@
1
+ <div align="center">
2
+
1
3
  # rustledger
2
4
 
3
- A pure Rust implementation of [Beancount](https://beancount.github.io/), the double-entry bookkeeping language.
5
+ **A blazing-fast Rust implementation of [Beancount](https://beancount.github.io/)**
6
+
7
+ Parse and validate your ledger faster than Python beancount.
4
8
 
5
9
  [![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
+ [![GitHub Release](https://img.shields.io/github/v/release/rustledger/rustledger)](https://github.com/rustledger/rustledger/releases)
11
+ [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](LICENSE)
12
+
13
+ </div>
10
14
 
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)
15
+ ---
16
16
 
17
17
  ## Why rustledger?
18
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
19
+ | | |
20
+ |---|---|
21
+ | **Much faster** | Parse and validate large ledgers in milliseconds ([see benchmarks](#performance)) |
22
+ | **Single binary** | No Python, no dependencies, just download and run |
23
+ | **Drop-in replacement** | Compatible `bean-*` CLI commands for easy migration |
24
+ | **Full compatibility** | Parses any valid beancount file |
25
+
26
+ ## Install
27
+
28
+ | Platform | Command |
29
+ |----------|---------|
30
+ | **Script** | `curl -sSfL rustledger.github.io/i \| sh` |
31
+ | **macOS** | `brew install rustledger/rustledger/rustledger` |
32
+ | **Ubuntu/Debian** | `sudo add-apt-repository ppa:robcohen/rustledger && sudo apt install rustledger` |
33
+ | **Fedora/RHEL** | `sudo dnf copr enable rustledger/rustledger && sudo dnf install rustledger` |
34
+ | **Arch** | `yay -S rustledger-bin` |
35
+ | **Windows** | `scoop bucket add rustledger https://github.com/rustledger/scoop-rustledger && scoop install rustledger` |
36
+ | **Cargo** | `cargo binstall rustledger` or `cargo install rustledger` |
37
+ | **Nix** | `nix run github:rustledger/rustledger` |
38
+ | **Docker** | `docker run --rm -v "$PWD:/data" ghcr.io/rustledger/rustledger /data/ledger.beancount` |
39
+ | **Binaries** | [GitHub Releases](https://github.com/rustledger/rustledger/releases) |
40
+ | **npm** | `npm install @rustledger/wasm` (WebAssembly) |
24
41
 
25
42
  ## Quick Start
26
43
 
27
44
  ```bash
28
- # Install
29
- cargo install rustledger
30
-
31
- # Validate your ledger
32
45
  rledger-check ledger.beancount
33
-
34
- # Query your data
35
46
  rledger-query ledger.beancount "SELECT account, SUM(position) GROUP BY account"
36
47
  ```
37
48
 
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
49
  ## CLI Commands
143
50
 
144
51
  | Command | Description |
145
52
  |---------|-------------|
146
53
  | `rledger-check` | Validate ledger files with detailed error messages |
147
- | `rledger-format` | Auto-format beancount files |
148
54
  | `rledger-query` | Run BQL queries (interactive shell or one-shot) |
55
+ | `rledger-format` | Auto-format beancount files |
149
56
  | `rledger-report` | Generate balance, account, and statistics reports |
150
- | `rledger-doctor` | Debugging tools: context, linked transactions, missing opens |
57
+ | `rledger-doctor` | Debugging tools for ledger issues |
151
58
  | `rledger-extract` | Import transactions from CSV/OFX bank statements |
152
59
  | `rledger-price` | Fetch commodity prices from online sources |
153
60
 
154
- ### Examples
61
+ Python beancount users can also use `bean-check`, `bean-query`, etc.
62
+
63
+ <details>
64
+ <summary><strong>CLI examples</strong></summary>
155
65
 
156
66
  ```bash
157
67
  # Validate with plugins
158
68
  rledger-check --native-plugin auto_accounts ledger.beancount
159
- rledger-check --native-plugin pedantic ledger.beancount
160
69
 
161
- # Format in place
162
- rledger-format --in-place ledger.beancount
163
-
164
- # Interactive query shell with readline and history
70
+ # Interactive query shell
165
71
  rledger-query ledger.beancount
166
72
 
167
73
  # One-shot query
@@ -169,123 +75,31 @@ rledger-query ledger.beancount "SELECT date, narration WHERE account ~ 'Expenses
169
75
 
170
76
  # Reports
171
77
  rledger-report ledger.beancount balances
172
- rledger-report ledger.beancount accounts
173
78
  rledger-report ledger.beancount stats
174
79
 
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
- }
80
+ # Format in place
81
+ rledger-format --in-place ledger.beancount
252
82
  ```
253
83
 
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
84
+ </details>
259
85
 
260
86
  ## Crates
261
87
 
262
88
  | Crate | Description |
263
89
  |-------|-------------|
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
90
+ | `rustledger` | CLI tools (rledger-check, rledger-query, etc.) |
91
+ | `rustledger-core` | Core types: Amount, Position, Inventory |
92
+ | `rustledger-parser` | Lexer and parser with error recovery |
93
+ | `rustledger-loader` | File loading and includes |
94
+ | `rustledger-booking` | Interpolation and 7 booking methods |
95
+ | `rustledger-validate` | 26 validation error codes |
96
+ | `rustledger-query` | BQL query engine |
97
+ | `rustledger-plugin` | 20 built-in plugins + Python plugin support |
98
+ | `rustledger-importer` | CSV/OFX import framework |
99
+ | `rustledger-wasm` | WebAssembly bindings for JavaScript/TypeScript |
100
+
101
+ <details>
102
+ <summary><strong>Booking methods (7)</strong></summary>
289
103
 
290
104
  | Method | Description |
291
105
  |--------|-------------|
@@ -297,123 +111,54 @@ Supports:
297
111
  | `AVERAGE` | Average cost basis |
298
112
  | `NONE` | No cost tracking |
299
113
 
300
- ### Built-in Plugins (14)
114
+ </details>
115
+
116
+ <details>
117
+ <summary><strong>Built-in plugins (20)</strong></summary>
301
118
 
302
119
  | Plugin | Description |
303
120
  |--------|-------------|
304
- | `implicit_prices` | Generate price entries from transaction costs |
305
- | `check_commodity` | Validate commodity declarations |
306
121
  | `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 |
122
+ | `auto_tag` | Automatically tag transactions |
123
+ | `check_average_cost` | Validate average cost bookings |
311
124
  | `check_closing` | Zero balance assertion on account close |
125
+ | `check_commodity` | Validate commodity declarations |
126
+ | `check_drained` | Ensure accounts are drained before close |
312
127
  | `close_tree` | Close descendant accounts |
313
128
  | `coherent_cost` | Enforce cost OR price (not both) |
314
- | `sellgains` | Cross-check capital gains against sales |
129
+ | `commodity_attr` | Validate commodity attributes |
130
+ | `currency_accounts` | Enforce currency constraints on accounts |
131
+ | `document_discovery` | Auto-discover document files |
132
+ | `implicit_prices` | Generate price entries from transaction costs |
133
+ | `leafonly` | Error on postings to non-leaf accounts |
134
+ | `noduplicates` | Hash-based duplicate transaction detection |
135
+ | `nounused` | Warn on unused accounts |
136
+ | `onecommodity` | Single commodity per account |
315
137
  | `pedantic` | Enable all strict validations |
138
+ | `sellgains` | Cross-check capital gains against sales |
139
+ | `unique_prices` | One price per day per commodity pair |
316
140
  | `unrealized` | Calculate unrealized gains |
317
- | `nounused` | Warn on unused accounts |
318
141
 
319
- ### Options (28 supported)
142
+ **Python plugins**: Run existing Python beancount plugins via CPython-WASI sandbox.
320
143
 
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
144
+ </details>
325
145
 
326
146
  ## Performance
327
147
 
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
148
+ [![Benchmark](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/rustledger/rustledger/benchmarks/.github/badges/benchmark.json)](https://github.com/rustledger/rustledger/actions/workflows/bench.yml)
356
149
 
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
- ```
150
+ <picture>
151
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/rustledger/rustledger/benchmarks/.github/badges/benchmark-chart.svg">
152
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/rustledger/rustledger/benchmarks/.github/badges/benchmark-chart.svg">
153
+ <img alt="Benchmark Chart" src="https://raw.githubusercontent.com/rustledger/rustledger/benchmarks/.github/badges/benchmark-chart.png" width="100%">
154
+ </picture>
372
155
 
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.
156
+ <sub>Benchmarks run nightly on identical 10K transaction ledgers. [View workflow →](https://github.com/rustledger/rustledger/actions/workflows/bench.yml)</sub>
409
157
 
410
158
  ## Contributing
411
159
 
412
- Contributions are welcome! Please feel free to submit a Pull Request.
160
+ See [CLAUDE.md](CLAUDE.md) for architecture and development setup.
413
161
 
414
- Before submitting:
415
- 1. Run `cargo test --all-features`
416
- 2. Run `cargo clippy --all-features`
417
- 3. Run `cargo fmt`
162
+ ## License
418
163
 
419
- See [CLAUDE.md](CLAUDE.md) for code standards and architecture overview.
164
+ [GPL-3.0](LICENSE)
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "Rustledger Contributors"
6
6
  ],
7
7
  "description": "Beancount WebAssembly bindings for JavaScript/TypeScript",
8
- "version": "0.1.0",
8
+ "version": "0.2.0",
9
9
  "license": "GPL-3.0-only",
10
10
  "repository": {
11
11
  "type": "git",
Binary file