beancount 0.0.1
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 +82 -0
- package/build/src/benchmark.d.mts +1 -0
- package/build/src/benchmark.mjs +28 -0
- package/build/src/classes/Booking.d.mts +4 -0
- package/build/src/classes/Booking.mjs +7 -0
- package/build/src/classes/DateEntry.d.mts +25 -0
- package/build/src/classes/DateEntry.mjs +33 -0
- package/build/src/classes/Entry.d.mts +30 -0
- package/build/src/classes/Entry.mjs +33 -0
- package/build/src/classes/ParseResult.d.mts +9 -0
- package/build/src/classes/ParseResult.mjs +19 -0
- package/build/src/classes/Posting.d.mts +11 -0
- package/build/src/classes/Posting.mjs +37 -0
- package/build/src/classes/Transaction.d.mts +4 -0
- package/build/src/classes/Transaction.mjs +7 -0
- package/build/src/classes/Value.d.mts +12 -0
- package/build/src/classes/Value.mjs +32 -0
- package/build/src/classes/entryTypes/Balance.d.mts +13 -0
- package/build/src/classes/entryTypes/Balance.mjs +33 -0
- package/build/src/classes/entryTypes/Blankline.d.mts +8 -0
- package/build/src/classes/entryTypes/Blankline.mjs +22 -0
- package/build/src/classes/entryTypes/Close.d.mts +8 -0
- package/build/src/classes/entryTypes/Close.mjs +20 -0
- package/build/src/classes/entryTypes/Comment.d.mts +8 -0
- package/build/src/classes/entryTypes/Comment.mjs +22 -0
- package/build/src/classes/entryTypes/Commodity.d.mts +8 -0
- package/build/src/classes/entryTypes/Commodity.mjs +20 -0
- package/build/src/classes/entryTypes/Custom.d.mts +10 -0
- package/build/src/classes/entryTypes/Custom.mjs +27 -0
- package/build/src/classes/entryTypes/Document.d.mts +9 -0
- package/build/src/classes/entryTypes/Document.mjs +23 -0
- package/build/src/classes/entryTypes/Event.d.mts +10 -0
- package/build/src/classes/entryTypes/Event.mjs +23 -0
- package/build/src/classes/entryTypes/Include.d.mts +8 -0
- package/build/src/classes/entryTypes/Include.mjs +20 -0
- package/build/src/classes/entryTypes/Note.d.mts +9 -0
- package/build/src/classes/entryTypes/Note.mjs +23 -0
- package/build/src/classes/entryTypes/Open.d.mts +12 -0
- package/build/src/classes/entryTypes/Open.mjs +53 -0
- package/build/src/classes/entryTypes/Option.d.mts +10 -0
- package/build/src/classes/entryTypes/Option.mjs +21 -0
- package/build/src/classes/entryTypes/Pad.d.mts +9 -0
- package/build/src/classes/entryTypes/Pad.mjs +22 -0
- package/build/src/classes/entryTypes/Plugin.d.mts +9 -0
- package/build/src/classes/entryTypes/Plugin.mjs +25 -0
- package/build/src/classes/entryTypes/Poptag.d.mts +9 -0
- package/build/src/classes/entryTypes/Poptag.mjs +23 -0
- package/build/src/classes/entryTypes/Price.d.mts +11 -0
- package/build/src/classes/entryTypes/Price.mjs +27 -0
- package/build/src/classes/entryTypes/Pushtag.d.mts +9 -0
- package/build/src/classes/entryTypes/Pushtag.mjs +23 -0
- package/build/src/classes/entryTypes/Query.d.mts +9 -0
- package/build/src/classes/entryTypes/Query.mjs +23 -0
- package/build/src/classes/entryTypes/Transaction/Posting.d.mts +16 -0
- package/build/src/classes/entryTypes/Transaction/Posting.mjs +53 -0
- package/build/src/classes/entryTypes/Transaction/Tag.d.mts +9 -0
- package/build/src/classes/entryTypes/Transaction/Tag.mjs +11 -0
- package/build/src/classes/entryTypes/Transaction/index.d.mts +17 -0
- package/build/src/classes/entryTypes/Transaction/index.mjs +102 -0
- package/build/src/classes/entryTypes/Transaction.d.mts +12 -0
- package/build/src/classes/entryTypes/Transaction.mjs +52 -0
- package/build/src/classes/entryTypes/index.d.mts +19 -0
- package/build/src/classes/entryTypes/index.mjs +19 -0
- package/build/src/example.d.mts +1 -0
- package/build/src/example.mjs +20 -0
- package/build/src/genericParse.d.mts +24 -0
- package/build/src/genericParse.mjs +53 -0
- package/build/src/interfaces.d.mts +1 -0
- package/build/src/interfaces.mjs +1 -0
- package/build/src/parse.d.mts +29 -0
- package/build/src/parse.mjs +105 -0
- package/build/src/test.d.mts +1 -0
- package/build/src/test.mjs +7 -0
- package/build/src/utils/countChar.d.mts +1 -0
- package/build/src/utils/countChar.mjs +3 -0
- package/build/src/utils/formatPrice.d.mts +9 -0
- package/build/src/utils/formatPrice.mjs +21 -0
- package/build/src/utils/formatValue.d.mts +2 -0
- package/build/src/utils/formatValue.mjs +6 -0
- package/build/src/utils/parseMetadata.d.mts +3 -0
- package/build/src/utils/parseMetadata.mjs +16 -0
- package/build/src/utils/parseVal.d.mts +3 -0
- package/build/src/utils/parseVal.mjs +16 -0
- package/build/src/utils/simpleParseLine.d.mts +1 -0
- package/build/src/utils/simpleParseLine.mjs +1 -0
- package/build/src/utils/stringAwareParseLine.d.mts +1 -0
- package/build/src/utils/stringAwareParseLine.mjs +24 -0
- package/build/src/utils/stringAwareSplitLine.d.mts +1 -0
- package/build/src/utils/stringAwareSplitLine.mjs +32 -0
- package/build/tsconfig.build.tsbuildinfo +1 -0
- package/build/tsconfig.tsbuildinfo +1 -0
- package/package.json +37 -0
package/README.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# beancount
|
|
2
|
+
|
|
3
|
+
A parser and editor for Beancount accounting files with full type safety.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install beancount
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- **Full Beancount Support** - All directives supported: transactions, open/close, balance, pad, note, document, price, event, query, custom, commodity, include, option, plugin, pushtag/poptag
|
|
14
|
+
- **Type-Safe** - Complete TypeScript types for all entries and components
|
|
15
|
+
- **Rich Transaction Support** - Tags, links, metadata, costs, price annotations, and postings
|
|
16
|
+
- **Round-Trip Parsing** - Parse to objects and serialize back to text
|
|
17
|
+
- **Formatted Output** - Column-aligned output with `toFormattedString()` (WIP)
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { parse } from 'beancount'
|
|
23
|
+
|
|
24
|
+
const beancountContent = `
|
|
25
|
+
2024-01-01 open Assets:Checking USD
|
|
26
|
+
|
|
27
|
+
2024-01-15 * "Grocery Store" "Weekly shopping"
|
|
28
|
+
Assets:Checking -50.00 USD
|
|
29
|
+
Expenses:Food 50.00 USD
|
|
30
|
+
`
|
|
31
|
+
|
|
32
|
+
const result = parse(beancountContent)
|
|
33
|
+
|
|
34
|
+
// Access parsed entries
|
|
35
|
+
console.log(result.entries.length) // 2
|
|
36
|
+
|
|
37
|
+
// Convert back to string
|
|
38
|
+
console.log(result.toString())
|
|
39
|
+
|
|
40
|
+
// Or with formatted output (aligned columns)
|
|
41
|
+
// only partially implemented at this point
|
|
42
|
+
console.log(result.toFormattedString())
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Documentation
|
|
46
|
+
|
|
47
|
+
Full API documentation is available at https://Boelensman1.github.io/node-beancount/
|
|
48
|
+
|
|
49
|
+
You can also generate documentation locally with:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
command make docs
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Contributing
|
|
56
|
+
|
|
57
|
+
This project uses Make for task orchestration. Common commands:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# Install dependencies
|
|
61
|
+
make install
|
|
62
|
+
|
|
63
|
+
# Build the project
|
|
64
|
+
make build
|
|
65
|
+
|
|
66
|
+
# Run tests
|
|
67
|
+
make test
|
|
68
|
+
|
|
69
|
+
# Run linting (prettier, tsc, eslint, typedoc)
|
|
70
|
+
make lint
|
|
71
|
+
|
|
72
|
+
# Generate documentation
|
|
73
|
+
make docs
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Requirements
|
|
77
|
+
|
|
78
|
+
- Node.js >= 22
|
|
79
|
+
|
|
80
|
+
## License
|
|
81
|
+
|
|
82
|
+
ISC
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import { parse } from './parse.mjs';
|
|
3
|
+
const file = './test/example-full.beancount';
|
|
4
|
+
const fileBuffer = fs.readFileSync(file);
|
|
5
|
+
const fileText = fileBuffer.toString();
|
|
6
|
+
const fileSizeKB = fileBuffer.length / 1024;
|
|
7
|
+
console.log(`File size: ${fileSizeKB.toFixed(2)} KB`);
|
|
8
|
+
console.log(`String length: ${fileText.length} characters`);
|
|
9
|
+
console.log('---');
|
|
10
|
+
const iterations = 10;
|
|
11
|
+
const durations = [];
|
|
12
|
+
let lastResult = parse(fileText);
|
|
13
|
+
console.log(`Running ${iterations} iterations...`);
|
|
14
|
+
for (let i = 0; i < iterations; i++) {
|
|
15
|
+
const startTime = performance.now();
|
|
16
|
+
lastResult = parse(fileText);
|
|
17
|
+
const endTime = performance.now();
|
|
18
|
+
durations.push(endTime - startTime);
|
|
19
|
+
}
|
|
20
|
+
const avgDuration = durations.reduce((a, b) => a + b, 0) / iterations;
|
|
21
|
+
const avgDurationSeconds = avgDuration / 1000;
|
|
22
|
+
const minDuration = Math.min(...durations);
|
|
23
|
+
const maxDuration = Math.max(...durations);
|
|
24
|
+
console.log(`Average parse time: ${avgDuration.toFixed(3)} ms`);
|
|
25
|
+
console.log(`Min: ${minDuration.toFixed(3)} ms, Max: ${maxDuration.toFixed(3)} ms`);
|
|
26
|
+
console.log(`Average throughput: ${(fileSizeKB / avgDurationSeconds / 1000).toFixed(2)} MB/s`);
|
|
27
|
+
console.log('---');
|
|
28
|
+
console.log(`Parsed ${lastResult.entries.length} items`);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Temporal } from '@js-temporal/polyfill';
|
|
2
|
+
import { Entry } from './Entry.mjs';
|
|
3
|
+
import { Value } from './Value.mjs';
|
|
4
|
+
import type { EntryType } from '../parse.mjs';
|
|
5
|
+
export type DateEntryType = Exclude<EntryType, 'include' | 'option' | 'plugin'>;
|
|
6
|
+
/**
|
|
7
|
+
* Abstract base class for all Beancount entry types that have a date.
|
|
8
|
+
*
|
|
9
|
+
* Child classes must implement static `fromGenericParseResult` method
|
|
10
|
+
*/
|
|
11
|
+
export declare abstract class DateEntry extends Entry {
|
|
12
|
+
abstract type: DateEntryType;
|
|
13
|
+
date: Temporal.PlainDate;
|
|
14
|
+
metadata?: Record<string, Value>;
|
|
15
|
+
constructor(obj: {
|
|
16
|
+
date: string;
|
|
17
|
+
[key: string]: unknown;
|
|
18
|
+
});
|
|
19
|
+
/**
|
|
20
|
+
* Returns the common prefix for all DateEntry toString methods.
|
|
21
|
+
* Format: "YYYY-MM-DD <type>"
|
|
22
|
+
*/
|
|
23
|
+
protected getDateTypePrefix(): string;
|
|
24
|
+
getMetaDataString(): string;
|
|
25
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Temporal } from '@js-temporal/polyfill';
|
|
2
|
+
import { Entry } from './Entry.mjs';
|
|
3
|
+
/**
|
|
4
|
+
* Abstract base class for all Beancount entry types that have a date.
|
|
5
|
+
*
|
|
6
|
+
* Child classes must implement static `fromGenericParseResult` method
|
|
7
|
+
*/
|
|
8
|
+
export class DateEntry extends Entry {
|
|
9
|
+
constructor(obj) {
|
|
10
|
+
const { date, ...props } = obj;
|
|
11
|
+
super(props);
|
|
12
|
+
if (date) {
|
|
13
|
+
this.date = Temporal.PlainDate.from(date, { overflow: 'reject' });
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Returns the common prefix for all DateEntry toString methods.
|
|
18
|
+
* Format: "YYYY-MM-DD <type>"
|
|
19
|
+
*/
|
|
20
|
+
getDateTypePrefix() {
|
|
21
|
+
return `${this.date.toJSON()} ${this.type}`;
|
|
22
|
+
}
|
|
23
|
+
getMetaDataString() {
|
|
24
|
+
const comment = this.comment ? ` ; ${this.comment}` : '';
|
|
25
|
+
if (!this.metadata) {
|
|
26
|
+
return comment;
|
|
27
|
+
}
|
|
28
|
+
return (`${comment}\n` +
|
|
29
|
+
Object.entries(this.metadata)
|
|
30
|
+
.map(([key, val]) => ` ${key}: ${val.toString()}`)
|
|
31
|
+
.join('\n'));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { genericParse } from '../../src/genericParse.mjs';
|
|
2
|
+
import type { EntryType } from '../parse.mjs';
|
|
3
|
+
/**
|
|
4
|
+
* Type helper for Entry class constructors that enforce the static factory methods.
|
|
5
|
+
* Child classes must implement static fromGenericParseResult and fromObject methods to create instances.
|
|
6
|
+
* Note: The constructor is protected, so only the static factory methods are part of the public API.
|
|
7
|
+
*/
|
|
8
|
+
export interface EntryConstructor<T extends Entry> {
|
|
9
|
+
fromGenericParseResult(parsedStart: ReturnType<typeof genericParse>): T;
|
|
10
|
+
}
|
|
11
|
+
export interface FormatOptions {
|
|
12
|
+
currencyColumn: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Abstract base class for all Beancount entry types.
|
|
16
|
+
*
|
|
17
|
+
* Child classes must implement static `fromGenericParseResult` method
|
|
18
|
+
*/
|
|
19
|
+
export declare abstract class Entry {
|
|
20
|
+
comment?: string;
|
|
21
|
+
abstract type: EntryType | 'comment' | 'blankline';
|
|
22
|
+
constructor(obj: Record<string, unknown>);
|
|
23
|
+
static fromString<T extends Entry>(this: EntryConstructor<T>, input: string): T;
|
|
24
|
+
toFormattedString(_formatOptions: FormatOptions): string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Type assertion helper to ensure a class conforms to EntryConstructor.
|
|
28
|
+
* Usage: assertEntryConstructor(MyEntryClass)
|
|
29
|
+
*/
|
|
30
|
+
export declare function assertEntryConstructor<T extends Entry>(_ctor: EntryConstructor<T>): void;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { genericParse } from '../../src/genericParse.mjs';
|
|
2
|
+
import { stringAwareSplitLine } from '../utils/stringAwareSplitLine.mjs';
|
|
3
|
+
/**
|
|
4
|
+
* Abstract base class for all Beancount entry types.
|
|
5
|
+
*
|
|
6
|
+
* Child classes must implement static `fromGenericParseResult` method
|
|
7
|
+
*/
|
|
8
|
+
export class Entry {
|
|
9
|
+
constructor(obj) {
|
|
10
|
+
Object.assign(this, obj);
|
|
11
|
+
}
|
|
12
|
+
static fromString(input) {
|
|
13
|
+
const unparsedEntry = stringAwareSplitLine(input);
|
|
14
|
+
const genericParseResult = genericParse(unparsedEntry);
|
|
15
|
+
const result = this.fromGenericParseResult(genericParseResult);
|
|
16
|
+
if (result.type !== genericParseResult.type) {
|
|
17
|
+
console.warn('Parse result type is not equal to requested object type, make sure the correct class is initiated');
|
|
18
|
+
}
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
22
|
+
toFormattedString(_formatOptions) {
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
24
|
+
return this.toString();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Type assertion helper to ensure a class conforms to EntryConstructor.
|
|
29
|
+
* Usage: assertEntryConstructor(MyEntryClass)
|
|
30
|
+
*/
|
|
31
|
+
export function assertEntryConstructor(
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
33
|
+
_ctor) { }
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const defaultFormattingOptions = {
|
|
2
|
+
width: 100,
|
|
3
|
+
};
|
|
4
|
+
export class ParseResult {
|
|
5
|
+
constructor(entries) {
|
|
6
|
+
this.entries = entries;
|
|
7
|
+
}
|
|
8
|
+
toString() {
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
10
|
+
return this.entries.map((e) => e.toString()).join('\n');
|
|
11
|
+
}
|
|
12
|
+
toFormattedString(options = defaultFormattingOptions) {
|
|
13
|
+
// TODO: calculate currencyColumn
|
|
14
|
+
const currencyColumn = 59;
|
|
15
|
+
return this.entries
|
|
16
|
+
.map((e) => e.toFormattedString({ currencyColumn }))
|
|
17
|
+
.join('\n');
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare class Posting {
|
|
2
|
+
flag?: string;
|
|
3
|
+
account: string;
|
|
4
|
+
amount?: string;
|
|
5
|
+
currency?: string;
|
|
6
|
+
comment?: string;
|
|
7
|
+
constructor(obj: Record<string, unknown>);
|
|
8
|
+
static fromGenericParseResult(unparsedline: string): Posting;
|
|
9
|
+
get price(): string | undefined;
|
|
10
|
+
toString(): string;
|
|
11
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { formatPrice } from '../utils/formatPrice.mjs';
|
|
2
|
+
export class Posting {
|
|
3
|
+
constructor(obj) {
|
|
4
|
+
Object.assign(this, obj);
|
|
5
|
+
}
|
|
6
|
+
static fromGenericParseResult(unparsedline) {
|
|
7
|
+
// [Flag] Account Amount [{Cost}] [@ Price]
|
|
8
|
+
const matches = /^(?:([^ ]) )?([^ ]*)(?: +([^A-Z]*) +(\w+)(?: +{.*})?(?: +@ +(\d+\.?\d* (\w+)))?)?( *;.*)?$/.exec(unparsedline);
|
|
9
|
+
if (!matches) {
|
|
10
|
+
throw new Error('Could not parse posting');
|
|
11
|
+
}
|
|
12
|
+
const [, flag, account, amount, currency, cost, postingPrice, comment] = matches;
|
|
13
|
+
return new Posting({
|
|
14
|
+
flag: flag,
|
|
15
|
+
account: account?.trim(),
|
|
16
|
+
amount: amount?.trim(),
|
|
17
|
+
currency: currency?.trim(),
|
|
18
|
+
cost: cost?.trim(),
|
|
19
|
+
postingPrice: postingPrice?.trim(),
|
|
20
|
+
comment: comment?.replace(/^ *;/, '').trim(),
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
get price() {
|
|
24
|
+
return formatPrice(this.amount, this.currency);
|
|
25
|
+
}
|
|
26
|
+
toString() {
|
|
27
|
+
const parts = [];
|
|
28
|
+
if (this.flag !== undefined) {
|
|
29
|
+
parts.push(this.flag);
|
|
30
|
+
}
|
|
31
|
+
parts.push(this.account);
|
|
32
|
+
if (this.price !== undefined) {
|
|
33
|
+
parts.push(this.price);
|
|
34
|
+
}
|
|
35
|
+
return parts.join(' ');
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type ValueType = 'string' | 'date' | 'boolean' | 'amount' | 'numbers';
|
|
2
|
+
export declare const parseString: (val: string) => string;
|
|
3
|
+
export declare class Value {
|
|
4
|
+
type: ValueType;
|
|
5
|
+
value: unknown;
|
|
6
|
+
constructor(obj: {
|
|
7
|
+
type: ValueType;
|
|
8
|
+
value: unknown;
|
|
9
|
+
});
|
|
10
|
+
static fromString(input: string): Value;
|
|
11
|
+
toString(): string;
|
|
12
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export const parseString = (val) => {
|
|
2
|
+
return val.replace(/^"|"$/g, '');
|
|
3
|
+
};
|
|
4
|
+
export class Value {
|
|
5
|
+
constructor(obj) {
|
|
6
|
+
Object.assign(this, obj);
|
|
7
|
+
}
|
|
8
|
+
static fromString(input) {
|
|
9
|
+
if (input.startsWith('"') && input.endsWith('"')) {
|
|
10
|
+
// string!
|
|
11
|
+
return new Value({ type: 'string', value: parseString(input) });
|
|
12
|
+
}
|
|
13
|
+
if (input.toUpperCase() === 'TRUE') {
|
|
14
|
+
return new Value({ type: 'boolean', value: true });
|
|
15
|
+
}
|
|
16
|
+
if (input.toUpperCase() === 'FALSE') {
|
|
17
|
+
return new Value({ type: 'boolean', value: false });
|
|
18
|
+
}
|
|
19
|
+
// TODO: more parsing
|
|
20
|
+
return new Value({ type: 'amount', value: input });
|
|
21
|
+
}
|
|
22
|
+
toString() {
|
|
23
|
+
switch (this.type) {
|
|
24
|
+
case 'boolean':
|
|
25
|
+
return this.value ? 'TRUE' : 'FALSE';
|
|
26
|
+
case 'string':
|
|
27
|
+
return `"${this.value}"`;
|
|
28
|
+
default:
|
|
29
|
+
return String(this.value);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { GenericParseResultWithDate } from '../../genericParse.mjs';
|
|
2
|
+
import { FormatOptions } from '../Entry.mjs';
|
|
3
|
+
import { DateEntry } from '../DateEntry.mjs';
|
|
4
|
+
export declare class Balance extends DateEntry {
|
|
5
|
+
type: "balance";
|
|
6
|
+
account: string;
|
|
7
|
+
amount: string;
|
|
8
|
+
currency: string;
|
|
9
|
+
get price(): string | undefined;
|
|
10
|
+
static fromGenericParseResult(genericParseResult: GenericParseResultWithDate): Balance;
|
|
11
|
+
toString(): string;
|
|
12
|
+
toFormattedString(formatOptions: FormatOptions): string;
|
|
13
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { assertEntryConstructor } from '../Entry.mjs';
|
|
2
|
+
import { DateEntry } from '../DateEntry.mjs';
|
|
3
|
+
import { simpleParseLine } from '../../utils/simpleParseLine.mjs';
|
|
4
|
+
import { formatPrice } from '../../utils/formatPrice.mjs';
|
|
5
|
+
export class Balance extends DateEntry {
|
|
6
|
+
constructor() {
|
|
7
|
+
super(...arguments);
|
|
8
|
+
this.type = 'balance';
|
|
9
|
+
}
|
|
10
|
+
get price() {
|
|
11
|
+
return formatPrice(this.amount, this.currency);
|
|
12
|
+
}
|
|
13
|
+
static fromGenericParseResult(genericParseResult) {
|
|
14
|
+
const [account, amount, currency] = simpleParseLine(genericParseResult.header);
|
|
15
|
+
return new Balance({
|
|
16
|
+
...genericParseResult.props,
|
|
17
|
+
account,
|
|
18
|
+
amount,
|
|
19
|
+
currency,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
toString() {
|
|
23
|
+
return this.toFormattedString({ currencyColumn: 0 });
|
|
24
|
+
}
|
|
25
|
+
toFormattedString(formatOptions) {
|
|
26
|
+
const firstPart = `${this.getDateTypePrefix()} ${this.account}`;
|
|
27
|
+
const paddingLength = formatOptions.currencyColumn - firstPart.length - this.amount.length - 2; // not sure what this is for
|
|
28
|
+
const padding = ' '.repeat(Math.max(1, paddingLength));
|
|
29
|
+
return [firstPart, padding, this.price, this.getMetaDataString()].join('');
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// Ensure class conforms to EntryConstructor pattern
|
|
33
|
+
assertEntryConstructor(Balance);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { GenericParseResult } from '../../genericParse.mjs';
|
|
2
|
+
import { Entry, EntryConstructor } from '../Entry.mjs';
|
|
3
|
+
export declare class Blankline extends Entry {
|
|
4
|
+
type: "blankline";
|
|
5
|
+
static fromGenericParseResult(_genericParseResult: GenericParseResult): Blankline;
|
|
6
|
+
toString(): string;
|
|
7
|
+
static fromString<T extends Entry>(this: EntryConstructor<T>, _input: string): T;
|
|
8
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { assertEntryConstructor, Entry } from '../Entry.mjs';
|
|
2
|
+
export class Blankline extends Entry {
|
|
3
|
+
constructor() {
|
|
4
|
+
super(...arguments);
|
|
5
|
+
this.type = 'blankline';
|
|
6
|
+
}
|
|
7
|
+
static fromGenericParseResult(
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
9
|
+
_genericParseResult) {
|
|
10
|
+
return new Blankline({});
|
|
11
|
+
}
|
|
12
|
+
toString() {
|
|
13
|
+
return '';
|
|
14
|
+
}
|
|
15
|
+
static fromString(
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
17
|
+
_input) {
|
|
18
|
+
return this.fromGenericParseResult({});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
// Ensure class conforms to EntryConstructor pattern
|
|
22
|
+
assertEntryConstructor(Blankline);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { GenericParseResultWithDate } from '../../genericParse.mjs';
|
|
2
|
+
import { DateEntry } from '../DateEntry.mjs';
|
|
3
|
+
export declare class Close extends DateEntry {
|
|
4
|
+
type: "close";
|
|
5
|
+
account: string;
|
|
6
|
+
static fromGenericParseResult(genericParseResult: GenericParseResultWithDate): Close;
|
|
7
|
+
toString(): string;
|
|
8
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { assertEntryConstructor } from '../Entry.mjs';
|
|
2
|
+
import { DateEntry } from '../DateEntry.mjs';
|
|
3
|
+
export class Close extends DateEntry {
|
|
4
|
+
constructor() {
|
|
5
|
+
super(...arguments);
|
|
6
|
+
this.type = 'close';
|
|
7
|
+
}
|
|
8
|
+
static fromGenericParseResult(genericParseResult) {
|
|
9
|
+
const account = genericParseResult.header.trim();
|
|
10
|
+
return new Close({
|
|
11
|
+
...genericParseResult.props,
|
|
12
|
+
account,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
toString() {
|
|
16
|
+
return `${this.getDateTypePrefix()} ${this.account}${this.getMetaDataString()}`;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
// Ensure class conforms to EntryConstructor pattern
|
|
20
|
+
assertEntryConstructor(Close);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { GenericParseResult } from '../../genericParse.mjs';
|
|
2
|
+
import { Entry, EntryConstructor } from '../Entry.mjs';
|
|
3
|
+
export declare class Comment extends Entry {
|
|
4
|
+
type: "comment";
|
|
5
|
+
static fromGenericParseResult(genericParseResult: GenericParseResult): Comment;
|
|
6
|
+
toString(): string | undefined;
|
|
7
|
+
static fromString<T extends Entry>(this: EntryConstructor<T>, input: string): T;
|
|
8
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { assertEntryConstructor, Entry } from '../Entry.mjs';
|
|
2
|
+
export class Comment extends Entry {
|
|
3
|
+
constructor() {
|
|
4
|
+
super(...arguments);
|
|
5
|
+
this.type = 'comment';
|
|
6
|
+
}
|
|
7
|
+
static fromGenericParseResult(genericParseResult) {
|
|
8
|
+
return new Comment({
|
|
9
|
+
comment: genericParseResult.props.comment,
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
toString() {
|
|
13
|
+
return this.comment;
|
|
14
|
+
}
|
|
15
|
+
static fromString(input) {
|
|
16
|
+
return this.fromGenericParseResult({
|
|
17
|
+
props: { comment: input },
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
// Ensure class conforms to EntryConstructor pattern
|
|
22
|
+
assertEntryConstructor(Comment);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { GenericParseResultWithDate } from '../../genericParse.mjs';
|
|
2
|
+
import { DateEntry } from '../DateEntry.mjs';
|
|
3
|
+
export declare class Commodity extends DateEntry {
|
|
4
|
+
type: "commodity";
|
|
5
|
+
currency: string;
|
|
6
|
+
static fromGenericParseResult(genericParseResult: GenericParseResultWithDate): Commodity;
|
|
7
|
+
toString(): string;
|
|
8
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { assertEntryConstructor } from '../Entry.mjs';
|
|
2
|
+
import { DateEntry } from '../DateEntry.mjs';
|
|
3
|
+
export class Commodity extends DateEntry {
|
|
4
|
+
constructor() {
|
|
5
|
+
super(...arguments);
|
|
6
|
+
this.type = 'commodity';
|
|
7
|
+
}
|
|
8
|
+
static fromGenericParseResult(genericParseResult) {
|
|
9
|
+
const currency = genericParseResult.header.trim();
|
|
10
|
+
return new Commodity({
|
|
11
|
+
...genericParseResult.props,
|
|
12
|
+
currency,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
toString() {
|
|
16
|
+
return `${this.getDateTypePrefix()} ${this.currency}${this.getMetaDataString()}`;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
// Ensure class conforms to EntryConstructor pattern
|
|
20
|
+
assertEntryConstructor(Commodity);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { GenericParseResultWithDate } from '../../genericParse.mjs';
|
|
2
|
+
import { DateEntry } from '../DateEntry.mjs';
|
|
3
|
+
import { Value } from '../Value.mjs';
|
|
4
|
+
export declare class Custom extends DateEntry {
|
|
5
|
+
type: "custom";
|
|
6
|
+
customType: Value;
|
|
7
|
+
values?: Value[];
|
|
8
|
+
static fromGenericParseResult(genericParseResult: GenericParseResultWithDate): Custom;
|
|
9
|
+
toString(): string;
|
|
10
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { assertEntryConstructor } from '../Entry.mjs';
|
|
2
|
+
import { DateEntry } from '../DateEntry.mjs';
|
|
3
|
+
import { simpleParseLine } from '../../utils/simpleParseLine.mjs';
|
|
4
|
+
import { Value } from '../Value.mjs';
|
|
5
|
+
export class Custom extends DateEntry {
|
|
6
|
+
constructor() {
|
|
7
|
+
super(...arguments);
|
|
8
|
+
this.type = 'custom';
|
|
9
|
+
}
|
|
10
|
+
static fromGenericParseResult(genericParseResult) {
|
|
11
|
+
const [customType, ...others] = simpleParseLine(genericParseResult.header);
|
|
12
|
+
return new Custom({
|
|
13
|
+
...genericParseResult.props,
|
|
14
|
+
customType: Value.fromString(customType),
|
|
15
|
+
values: others.length > 0 ? others.map((o) => Value.fromString(o)) : undefined,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
toString() {
|
|
19
|
+
const parts = [`${this.getDateTypePrefix()} ${this.customType.toString()}`];
|
|
20
|
+
if (this.values !== undefined) {
|
|
21
|
+
parts.push(...this.values.map((v) => v.toString()));
|
|
22
|
+
}
|
|
23
|
+
return parts.join(' ') + this.getMetaDataString();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
// Ensure class conforms to EntryConstructor pattern
|
|
27
|
+
assertEntryConstructor(Custom);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { GenericParseResultWithDate } from '../../genericParse.mjs';
|
|
2
|
+
import { DateEntry } from '../DateEntry.mjs';
|
|
3
|
+
export declare class Document extends DateEntry {
|
|
4
|
+
type: "document";
|
|
5
|
+
account: string;
|
|
6
|
+
pathToDocument: string;
|
|
7
|
+
static fromGenericParseResult(genericParseResult: GenericParseResultWithDate): Document;
|
|
8
|
+
toString(): string;
|
|
9
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { assertEntryConstructor } from '../Entry.mjs';
|
|
2
|
+
import { DateEntry } from '../DateEntry.mjs';
|
|
3
|
+
import { parseString } from '../Value.mjs';
|
|
4
|
+
import { simpleParseLine } from '../../utils/simpleParseLine.mjs';
|
|
5
|
+
export class Document extends DateEntry {
|
|
6
|
+
constructor() {
|
|
7
|
+
super(...arguments);
|
|
8
|
+
this.type = 'document';
|
|
9
|
+
}
|
|
10
|
+
static fromGenericParseResult(genericParseResult) {
|
|
11
|
+
const [account, pathToDocument] = simpleParseLine(genericParseResult.header);
|
|
12
|
+
return new Document({
|
|
13
|
+
...genericParseResult.props,
|
|
14
|
+
account,
|
|
15
|
+
pathToDocument: parseString(pathToDocument),
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
toString() {
|
|
19
|
+
return `${this.getDateTypePrefix()} ${this.account} "${this.pathToDocument}"${this.getMetaDataString()}`;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
// Ensure class conforms to EntryConstructor pattern
|
|
23
|
+
assertEntryConstructor(Document);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { GenericParseResultWithDate } from '../../genericParse.mjs';
|
|
2
|
+
import { DateEntry } from '../DateEntry.mjs';
|
|
3
|
+
import { Value } from '../Value.mjs';
|
|
4
|
+
export declare class Event extends DateEntry {
|
|
5
|
+
type: "event";
|
|
6
|
+
name: string;
|
|
7
|
+
value: Value;
|
|
8
|
+
static fromGenericParseResult(genericParseResult: GenericParseResultWithDate): Event;
|
|
9
|
+
toString(): string;
|
|
10
|
+
}
|