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.
Files changed (92) hide show
  1. package/README.md +82 -0
  2. package/build/src/benchmark.d.mts +1 -0
  3. package/build/src/benchmark.mjs +28 -0
  4. package/build/src/classes/Booking.d.mts +4 -0
  5. package/build/src/classes/Booking.mjs +7 -0
  6. package/build/src/classes/DateEntry.d.mts +25 -0
  7. package/build/src/classes/DateEntry.mjs +33 -0
  8. package/build/src/classes/Entry.d.mts +30 -0
  9. package/build/src/classes/Entry.mjs +33 -0
  10. package/build/src/classes/ParseResult.d.mts +9 -0
  11. package/build/src/classes/ParseResult.mjs +19 -0
  12. package/build/src/classes/Posting.d.mts +11 -0
  13. package/build/src/classes/Posting.mjs +37 -0
  14. package/build/src/classes/Transaction.d.mts +4 -0
  15. package/build/src/classes/Transaction.mjs +7 -0
  16. package/build/src/classes/Value.d.mts +12 -0
  17. package/build/src/classes/Value.mjs +32 -0
  18. package/build/src/classes/entryTypes/Balance.d.mts +13 -0
  19. package/build/src/classes/entryTypes/Balance.mjs +33 -0
  20. package/build/src/classes/entryTypes/Blankline.d.mts +8 -0
  21. package/build/src/classes/entryTypes/Blankline.mjs +22 -0
  22. package/build/src/classes/entryTypes/Close.d.mts +8 -0
  23. package/build/src/classes/entryTypes/Close.mjs +20 -0
  24. package/build/src/classes/entryTypes/Comment.d.mts +8 -0
  25. package/build/src/classes/entryTypes/Comment.mjs +22 -0
  26. package/build/src/classes/entryTypes/Commodity.d.mts +8 -0
  27. package/build/src/classes/entryTypes/Commodity.mjs +20 -0
  28. package/build/src/classes/entryTypes/Custom.d.mts +10 -0
  29. package/build/src/classes/entryTypes/Custom.mjs +27 -0
  30. package/build/src/classes/entryTypes/Document.d.mts +9 -0
  31. package/build/src/classes/entryTypes/Document.mjs +23 -0
  32. package/build/src/classes/entryTypes/Event.d.mts +10 -0
  33. package/build/src/classes/entryTypes/Event.mjs +23 -0
  34. package/build/src/classes/entryTypes/Include.d.mts +8 -0
  35. package/build/src/classes/entryTypes/Include.mjs +20 -0
  36. package/build/src/classes/entryTypes/Note.d.mts +9 -0
  37. package/build/src/classes/entryTypes/Note.mjs +23 -0
  38. package/build/src/classes/entryTypes/Open.d.mts +12 -0
  39. package/build/src/classes/entryTypes/Open.mjs +53 -0
  40. package/build/src/classes/entryTypes/Option.d.mts +10 -0
  41. package/build/src/classes/entryTypes/Option.mjs +21 -0
  42. package/build/src/classes/entryTypes/Pad.d.mts +9 -0
  43. package/build/src/classes/entryTypes/Pad.mjs +22 -0
  44. package/build/src/classes/entryTypes/Plugin.d.mts +9 -0
  45. package/build/src/classes/entryTypes/Plugin.mjs +25 -0
  46. package/build/src/classes/entryTypes/Poptag.d.mts +9 -0
  47. package/build/src/classes/entryTypes/Poptag.mjs +23 -0
  48. package/build/src/classes/entryTypes/Price.d.mts +11 -0
  49. package/build/src/classes/entryTypes/Price.mjs +27 -0
  50. package/build/src/classes/entryTypes/Pushtag.d.mts +9 -0
  51. package/build/src/classes/entryTypes/Pushtag.mjs +23 -0
  52. package/build/src/classes/entryTypes/Query.d.mts +9 -0
  53. package/build/src/classes/entryTypes/Query.mjs +23 -0
  54. package/build/src/classes/entryTypes/Transaction/Posting.d.mts +16 -0
  55. package/build/src/classes/entryTypes/Transaction/Posting.mjs +53 -0
  56. package/build/src/classes/entryTypes/Transaction/Tag.d.mts +9 -0
  57. package/build/src/classes/entryTypes/Transaction/Tag.mjs +11 -0
  58. package/build/src/classes/entryTypes/Transaction/index.d.mts +17 -0
  59. package/build/src/classes/entryTypes/Transaction/index.mjs +102 -0
  60. package/build/src/classes/entryTypes/Transaction.d.mts +12 -0
  61. package/build/src/classes/entryTypes/Transaction.mjs +52 -0
  62. package/build/src/classes/entryTypes/index.d.mts +19 -0
  63. package/build/src/classes/entryTypes/index.mjs +19 -0
  64. package/build/src/example.d.mts +1 -0
  65. package/build/src/example.mjs +20 -0
  66. package/build/src/genericParse.d.mts +24 -0
  67. package/build/src/genericParse.mjs +53 -0
  68. package/build/src/interfaces.d.mts +1 -0
  69. package/build/src/interfaces.mjs +1 -0
  70. package/build/src/parse.d.mts +29 -0
  71. package/build/src/parse.mjs +105 -0
  72. package/build/src/test.d.mts +1 -0
  73. package/build/src/test.mjs +7 -0
  74. package/build/src/utils/countChar.d.mts +1 -0
  75. package/build/src/utils/countChar.mjs +3 -0
  76. package/build/src/utils/formatPrice.d.mts +9 -0
  77. package/build/src/utils/formatPrice.mjs +21 -0
  78. package/build/src/utils/formatValue.d.mts +2 -0
  79. package/build/src/utils/formatValue.mjs +6 -0
  80. package/build/src/utils/parseMetadata.d.mts +3 -0
  81. package/build/src/utils/parseMetadata.mjs +16 -0
  82. package/build/src/utils/parseVal.d.mts +3 -0
  83. package/build/src/utils/parseVal.mjs +16 -0
  84. package/build/src/utils/simpleParseLine.d.mts +1 -0
  85. package/build/src/utils/simpleParseLine.mjs +1 -0
  86. package/build/src/utils/stringAwareParseLine.d.mts +1 -0
  87. package/build/src/utils/stringAwareParseLine.mjs +24 -0
  88. package/build/src/utils/stringAwareSplitLine.d.mts +1 -0
  89. package/build/src/utils/stringAwareSplitLine.mjs +32 -0
  90. package/build/tsconfig.build.tsbuildinfo +1 -0
  91. package/build/tsconfig.tsbuildinfo +1 -0
  92. package/package.json +37 -0
@@ -0,0 +1,23 @@
1
+ import { assertEntryConstructor } from '../Entry.mjs';
2
+ import { DateEntry } from '../DateEntry.mjs';
3
+ import { parseString, Value } from '../Value.mjs';
4
+ import { stringAwareParseLine } from '../../utils/stringAwareParseLine.mjs';
5
+ export class Event extends DateEntry {
6
+ constructor() {
7
+ super(...arguments);
8
+ this.type = 'event';
9
+ }
10
+ static fromGenericParseResult(genericParseResult) {
11
+ const [name, value] = stringAwareParseLine(genericParseResult.header);
12
+ return new Event({
13
+ ...genericParseResult.props,
14
+ name: parseString(name),
15
+ value: Value.fromString(value),
16
+ });
17
+ }
18
+ toString() {
19
+ return `${this.getDateTypePrefix()} "${this.name}" ${this.value.toString()}${this.getMetaDataString()}`;
20
+ }
21
+ }
22
+ // Ensure class conforms to EntryConstructor pattern
23
+ assertEntryConstructor(Event);
@@ -0,0 +1,8 @@
1
+ import type { GenericParseResult } from '../../genericParse.mjs';
2
+ import { Entry } from '../Entry.mjs';
3
+ export declare class Include extends Entry {
4
+ type: "include";
5
+ filename: string;
6
+ static fromGenericParseResult(genericParseResult: GenericParseResult): Include;
7
+ toString(): string;
8
+ }
@@ -0,0 +1,20 @@
1
+ import { parseString } from '../Value.mjs';
2
+ import { stringAwareParseLine } from '../../utils/stringAwareParseLine.mjs';
3
+ import { assertEntryConstructor, Entry } from '../Entry.mjs';
4
+ export class Include extends Entry {
5
+ constructor() {
6
+ super(...arguments);
7
+ this.type = 'include';
8
+ }
9
+ static fromGenericParseResult(genericParseResult) {
10
+ const [filename] = stringAwareParseLine(genericParseResult.header);
11
+ return new Include({
12
+ filename: parseString(filename),
13
+ });
14
+ }
15
+ toString() {
16
+ return `${this.type} "${this.filename}"`;
17
+ }
18
+ }
19
+ // Ensure class conforms to EntryConstructor pattern
20
+ assertEntryConstructor(Include);
@@ -0,0 +1,9 @@
1
+ import type { GenericParseResultWithDate } from '../../genericParse.mjs';
2
+ import { DateEntry } from '../DateEntry.mjs';
3
+ export declare class Note extends DateEntry {
4
+ type: "note";
5
+ account: string;
6
+ description: string;
7
+ static fromGenericParseResult(genericParseResult: GenericParseResultWithDate): Note;
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 { stringAwareParseLine } from '../../utils/stringAwareParseLine.mjs';
5
+ export class Note extends DateEntry {
6
+ constructor() {
7
+ super(...arguments);
8
+ this.type = 'note';
9
+ }
10
+ static fromGenericParseResult(genericParseResult) {
11
+ const [account, description] = stringAwareParseLine(genericParseResult.header);
12
+ return new Note({
13
+ ...genericParseResult.props,
14
+ account,
15
+ description: parseString(description),
16
+ });
17
+ }
18
+ toString() {
19
+ return `${this.getDateTypePrefix()} ${this.account} "${this.description}"${this.getMetaDataString()}`;
20
+ }
21
+ }
22
+ // Ensure class conforms to EntryConstructor pattern
23
+ assertEntryConstructor(Note);
@@ -0,0 +1,12 @@
1
+ import type { GenericParseResultWithDate } from '../../genericParse.mjs';
2
+ import { FormatOptions } from '../Entry.mjs';
3
+ import { DateEntry } from '../DateEntry.mjs';
4
+ export declare class Open extends DateEntry {
5
+ type: "open";
6
+ account: string;
7
+ constraintCurrencies?: string[];
8
+ bookingMethod?: string;
9
+ static fromGenericParseResult(genericParseResult: GenericParseResultWithDate): Open;
10
+ toString(): string;
11
+ toFormattedString(formatOptions: FormatOptions): string;
12
+ }
@@ -0,0 +1,53 @@
1
+ import { assertEntryConstructor } from '../Entry.mjs';
2
+ import { DateEntry } from '../DateEntry.mjs';
3
+ import { simpleParseLine } from '../../utils/simpleParseLine.mjs';
4
+ import { parseString } from '../Value.mjs';
5
+ export class Open extends DateEntry {
6
+ constructor() {
7
+ super(...arguments);
8
+ this.type = 'open';
9
+ }
10
+ static fromGenericParseResult(genericParseResult) {
11
+ const [account, ...other] = simpleParseLine(genericParseResult.header);
12
+ let constraintCurrencies, bookingMethod;
13
+ if (other.length === 2) {
14
+ constraintCurrencies = other[0];
15
+ bookingMethod = parseString(other[1]);
16
+ }
17
+ else if (other.length === 1) {
18
+ if (other[0].startsWith('"') && other[0].endsWith('"')) {
19
+ bookingMethod = parseString(other[0]);
20
+ }
21
+ else {
22
+ constraintCurrencies = other[0];
23
+ }
24
+ }
25
+ return new Open({
26
+ ...genericParseResult.props,
27
+ account,
28
+ constraintCurrencies: constraintCurrencies?.split(','),
29
+ bookingMethod,
30
+ });
31
+ }
32
+ toString() {
33
+ return this.toFormattedString({ currencyColumn: 0 });
34
+ }
35
+ toFormattedString(formatOptions) {
36
+ const parts = [`${this.getDateTypePrefix()} ${this.account}`];
37
+ if (this.constraintCurrencies !== undefined) {
38
+ const paddingLength = formatOptions.currencyColumn -
39
+ parts.join(' ').length -
40
+ this.constraintCurrencies.join(',').length;
41
+ if (paddingLength > 0) {
42
+ parts.push(' '.repeat(paddingLength));
43
+ }
44
+ parts.push(this.constraintCurrencies.join(','));
45
+ }
46
+ if (this.bookingMethod !== undefined) {
47
+ parts.push(`"${this.bookingMethod}"`);
48
+ }
49
+ return parts.join(' ') + this.getMetaDataString();
50
+ }
51
+ }
52
+ // Ensure class conforms to EntryConstructor pattern
53
+ assertEntryConstructor(Open);
@@ -0,0 +1,10 @@
1
+ import type { GenericParseResult } from '../../genericParse.mjs';
2
+ import { Value } from '../Value.mjs';
3
+ import { Entry } from '../Entry.mjs';
4
+ export declare class Option extends Entry {
5
+ type: "option";
6
+ name: string;
7
+ value: Value;
8
+ static fromGenericParseResult(genericParseResult: GenericParseResult): Option;
9
+ toString(): string;
10
+ }
@@ -0,0 +1,21 @@
1
+ import { parseString, Value } from '../Value.mjs';
2
+ import { stringAwareParseLine } from '../../utils/stringAwareParseLine.mjs';
3
+ import { assertEntryConstructor, Entry } from '../Entry.mjs';
4
+ export class Option extends Entry {
5
+ constructor() {
6
+ super(...arguments);
7
+ this.type = 'option';
8
+ }
9
+ static fromGenericParseResult(genericParseResult) {
10
+ const [name, value] = stringAwareParseLine(genericParseResult.header);
11
+ return new Option({
12
+ name: parseString(name),
13
+ value: Value.fromString(value),
14
+ });
15
+ }
16
+ toString() {
17
+ return `${this.type} "${this.name}" ${this.value.toString()}`;
18
+ }
19
+ }
20
+ // Ensure class conforms to EntryConstructor pattern
21
+ assertEntryConstructor(Option);
@@ -0,0 +1,9 @@
1
+ import type { GenericParseResultWithDate } from '../../genericParse.mjs';
2
+ import { DateEntry } from '../DateEntry.mjs';
3
+ export declare class Pad extends DateEntry {
4
+ type: "pad";
5
+ account: string;
6
+ accountPad: string;
7
+ static fromGenericParseResult(genericParseResult: GenericParseResultWithDate): Pad;
8
+ toString(): string;
9
+ }
@@ -0,0 +1,22 @@
1
+ import { assertEntryConstructor } from '../Entry.mjs';
2
+ import { DateEntry } from '../DateEntry.mjs';
3
+ import { simpleParseLine } from '../../utils/simpleParseLine.mjs';
4
+ export class Pad extends DateEntry {
5
+ constructor() {
6
+ super(...arguments);
7
+ this.type = 'pad';
8
+ }
9
+ static fromGenericParseResult(genericParseResult) {
10
+ const [account, accountPad] = simpleParseLine(genericParseResult.header);
11
+ return new Pad({
12
+ ...genericParseResult.props,
13
+ account,
14
+ accountPad,
15
+ });
16
+ }
17
+ toString() {
18
+ return `${this.getDateTypePrefix()} ${this.account} ${this.accountPad}${this.getMetaDataString()}`;
19
+ }
20
+ }
21
+ // Ensure class conforms to EntryConstructor pattern
22
+ assertEntryConstructor(Pad);
@@ -0,0 +1,9 @@
1
+ import type { GenericParseResult } from '../../genericParse.mjs';
2
+ import { Entry } from '../Entry.mjs';
3
+ export declare class Plugin extends Entry {
4
+ type: "plugin";
5
+ moduleName: string;
6
+ config?: string;
7
+ static fromGenericParseResult(genericParseResult: GenericParseResult): Plugin;
8
+ toString(): string;
9
+ }
@@ -0,0 +1,25 @@
1
+ import { parseString } from '../Value.mjs';
2
+ import { stringAwareParseLine } from '../../utils/stringAwareParseLine.mjs';
3
+ import { assertEntryConstructor, Entry } from '../Entry.mjs';
4
+ export class Plugin extends Entry {
5
+ constructor() {
6
+ super(...arguments);
7
+ this.type = 'plugin';
8
+ }
9
+ static fromGenericParseResult(genericParseResult) {
10
+ const [moduleName, config] = stringAwareParseLine(genericParseResult.header);
11
+ return new Plugin({
12
+ moduleName: parseString(moduleName),
13
+ config: config ? parseString(config) : undefined,
14
+ });
15
+ }
16
+ toString() {
17
+ const parts = [`${this.type} "${this.moduleName}"`];
18
+ if (this.config !== undefined) {
19
+ parts.push(`"${this.config}"`);
20
+ }
21
+ return parts.join(' ');
22
+ }
23
+ }
24
+ // Ensure class conforms to EntryConstructor pattern
25
+ assertEntryConstructor(Plugin);
@@ -0,0 +1,9 @@
1
+ import type { GenericParseResult } from '../../genericParse.mjs';
2
+ import { Entry } from '../Entry.mjs';
3
+ import { Tag } from './Transaction/Tag.mjs';
4
+ export declare class Poptag extends Entry {
5
+ type: "poptag";
6
+ tag: Tag;
7
+ static fromGenericParseResult(genericParseResult: GenericParseResult): Poptag;
8
+ toString(): string;
9
+ }
@@ -0,0 +1,23 @@
1
+ import { simpleParseLine } from '../../utils/simpleParseLine.mjs';
2
+ import { assertEntryConstructor, Entry } from '../Entry.mjs';
3
+ import { Tag } from './Transaction/Tag.mjs';
4
+ export class Poptag extends Entry {
5
+ constructor() {
6
+ super(...arguments);
7
+ this.type = 'poptag';
8
+ }
9
+ static fromGenericParseResult(genericParseResult) {
10
+ const [tagContent] = simpleParseLine(genericParseResult.header);
11
+ return new Poptag({
12
+ tag: new Tag({
13
+ content: tagContent.trim().replace(/^#/, ''),
14
+ fromStack: true,
15
+ }),
16
+ });
17
+ }
18
+ toString() {
19
+ return `poptag #${this.tag.content}`;
20
+ }
21
+ }
22
+ // Ensure class conforms to EntryConstructor pattern
23
+ assertEntryConstructor(Poptag);
@@ -0,0 +1,11 @@
1
+ import type { GenericParseResultWithDate } from '../../genericParse.mjs';
2
+ import { DateEntry } from '../DateEntry.mjs';
3
+ export declare class Price extends DateEntry {
4
+ type: "price";
5
+ commodity: string;
6
+ currency: string;
7
+ amount: string;
8
+ get price(): string | undefined;
9
+ static fromGenericParseResult(genericParseResult: GenericParseResultWithDate): Price;
10
+ toString(): string;
11
+ }
@@ -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 { formatPrice } from '../../utils/formatPrice.mjs';
5
+ export class Price extends DateEntry {
6
+ constructor() {
7
+ super(...arguments);
8
+ this.type = 'price';
9
+ }
10
+ get price() {
11
+ return formatPrice(this.amount, this.currency);
12
+ }
13
+ static fromGenericParseResult(genericParseResult) {
14
+ const [commodity, amount, currency] = simpleParseLine(genericParseResult.header);
15
+ return new Price({
16
+ ...genericParseResult.props,
17
+ commodity,
18
+ currency,
19
+ amount,
20
+ });
21
+ }
22
+ toString() {
23
+ return `${this.getDateTypePrefix()} ${this.commodity} ${this.amount} ${this.currency}${this.getMetaDataString()}`;
24
+ }
25
+ }
26
+ // Ensure class conforms to EntryConstructor pattern
27
+ assertEntryConstructor(Price);
@@ -0,0 +1,9 @@
1
+ import type { GenericParseResult } from '../../genericParse.mjs';
2
+ import { Entry } from '../Entry.mjs';
3
+ import { Tag } from './Transaction/Tag.mjs';
4
+ export declare class Pushtag extends Entry {
5
+ type: "pushtag";
6
+ tag: Tag;
7
+ static fromGenericParseResult(genericParseResult: GenericParseResult): Pushtag;
8
+ toString(): string;
9
+ }
@@ -0,0 +1,23 @@
1
+ import { simpleParseLine } from '../../utils/simpleParseLine.mjs';
2
+ import { assertEntryConstructor, Entry } from '../Entry.mjs';
3
+ import { Tag } from './Transaction/Tag.mjs';
4
+ export class Pushtag extends Entry {
5
+ constructor() {
6
+ super(...arguments);
7
+ this.type = 'pushtag';
8
+ }
9
+ static fromGenericParseResult(genericParseResult) {
10
+ const [tagContent] = simpleParseLine(genericParseResult.header);
11
+ return new Pushtag({
12
+ tag: new Tag({
13
+ content: tagContent.trim().replace(/^#/, ''),
14
+ fromStack: true,
15
+ }),
16
+ });
17
+ }
18
+ toString() {
19
+ return `${this.type} #${this.tag.content}`;
20
+ }
21
+ }
22
+ // Ensure class conforms to EntryConstructor pattern
23
+ assertEntryConstructor(Pushtag);
@@ -0,0 +1,9 @@
1
+ import type { GenericParseResultWithDate } from '../../genericParse.mjs';
2
+ import { DateEntry } from '../DateEntry.mjs';
3
+ export declare class Query extends DateEntry {
4
+ type: "query";
5
+ name: string;
6
+ sqlContents: string;
7
+ static fromGenericParseResult(genericParseResult: GenericParseResultWithDate): Query;
8
+ toString(): string;
9
+ }
@@ -0,0 +1,23 @@
1
+ import { assertEntryConstructor } from '../Entry.mjs';
2
+ import { DateEntry } from '../DateEntry.mjs';
3
+ import { stringAwareParseLine } from '../../utils/stringAwareParseLine.mjs';
4
+ import { parseString } from '../Value.mjs';
5
+ export class Query extends DateEntry {
6
+ constructor() {
7
+ super(...arguments);
8
+ this.type = 'query';
9
+ }
10
+ static fromGenericParseResult(genericParseResult) {
11
+ const [name, sqlContents] = stringAwareParseLine(genericParseResult.header);
12
+ return new Query({
13
+ ...genericParseResult.props,
14
+ name: parseString(name),
15
+ sqlContents: parseString(sqlContents).trim(),
16
+ });
17
+ }
18
+ toString() {
19
+ return `${this.getDateTypePrefix()} "${this.name}" "${this.sqlContents}"${this.getMetaDataString()}`;
20
+ }
21
+ }
22
+ // Ensure class conforms to EntryConstructor pattern
23
+ assertEntryConstructor(Query);
@@ -0,0 +1,16 @@
1
+ import { FormatOptions } from '../../Entry.mjs';
2
+ export declare class Posting {
3
+ flag?: string;
4
+ account: string;
5
+ amount?: string;
6
+ currency?: string;
7
+ cost?: string;
8
+ priceCurrency?: string;
9
+ priceAmount?: string;
10
+ comment?: string;
11
+ constructor(obj: Record<string, unknown>);
12
+ static fromGenericParseResult(unparsedline: string): Posting;
13
+ get price(): string | undefined;
14
+ toString(): string;
15
+ toFormattedString(formatOptions: FormatOptions): string;
16
+ }
@@ -0,0 +1,53 @@
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, priceAmount, priceCurrency, 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
+ priceAmount: priceAmount?.trim(),
20
+ priceCurrency: priceCurrency?.trim(),
21
+ comment: comment?.replace(/^ *;/, '').trim(),
22
+ });
23
+ }
24
+ get price() {
25
+ return formatPrice(this.amount, this.currency, this.cost, this.priceAmount, this.priceCurrency);
26
+ }
27
+ toString() {
28
+ return this.toFormattedString({ currencyColumn: 0 });
29
+ }
30
+ toFormattedString(formatOptions) {
31
+ const parts = [];
32
+ if (this.flag !== undefined) {
33
+ parts.push(this.flag);
34
+ }
35
+ parts.push(this.account);
36
+ if (this.price !== undefined) {
37
+ const paddingLength = formatOptions.currencyColumn -
38
+ parts.join(' ').length -
39
+ this.amount.length -
40
+ 2 - // indent
41
+ 2 - // spacing
42
+ 2; // not sure what this is for
43
+ if (paddingLength > 0) {
44
+ parts.push(' '.repeat(paddingLength));
45
+ }
46
+ parts.push(this.price);
47
+ }
48
+ if (this.comment !== undefined) {
49
+ parts.push(';', this.comment);
50
+ }
51
+ return parts.join(' ');
52
+ }
53
+ }
@@ -0,0 +1,9 @@
1
+ export declare class Tag {
2
+ content: string;
3
+ fromStack: boolean;
4
+ constructor(obj: {
5
+ content: string;
6
+ fromStack: boolean;
7
+ });
8
+ toString(): string;
9
+ }
@@ -0,0 +1,11 @@
1
+ export class Tag {
2
+ constructor(obj) {
3
+ Object.assign(this, obj);
4
+ }
5
+ toString() {
6
+ if (this.fromStack) {
7
+ return '';
8
+ }
9
+ return `#${this.content}`;
10
+ }
11
+ }
@@ -0,0 +1,17 @@
1
+ import type { GenericParseResultTransaction } from '../../../genericParse.mjs';
2
+ import { FormatOptions } from '../../Entry.mjs';
3
+ import { DateEntry } from '../../DateEntry.mjs';
4
+ import { Posting } from './Posting.mjs';
5
+ import { Tag } from './Tag.mjs';
6
+ export declare class Transaction extends DateEntry {
7
+ type: "transaction";
8
+ payee: string;
9
+ narration?: string;
10
+ flag?: string;
11
+ postings: Posting[];
12
+ links: string[];
13
+ tags: Tag[];
14
+ static fromGenericParseResult(genericParseResult: GenericParseResultTransaction): Transaction;
15
+ toString(): string;
16
+ toFormattedString(formatOptions: FormatOptions): string;
17
+ }
@@ -0,0 +1,102 @@
1
+ import { assertEntryConstructor } from '../../Entry.mjs';
2
+ import { DateEntry } from '../../DateEntry.mjs';
3
+ import { stringAwareParseLine } from '../../../utils/stringAwareParseLine.mjs';
4
+ import { parseString } from '../../Value.mjs';
5
+ import { parseMetadata } from '../../../utils/parseMetadata.mjs';
6
+ import { Posting } from './Posting.mjs';
7
+ import { Tag } from './Tag.mjs';
8
+ const AccountTypes = ['Assets', 'Liabilities', 'Equity', 'Income', 'Expenses'];
9
+ const getStringLinksAndTags = (input) => {
10
+ let links = [];
11
+ let tags = [];
12
+ // default if no narration
13
+ let strRemaining = '';
14
+ let linksAndTags = input;
15
+ // check for narration
16
+ const match = /^(".*")(.*)/.exec(input);
17
+ if (match) {
18
+ // strRemaining = narration
19
+ strRemaining = match[1];
20
+ linksAndTags = match[2];
21
+ }
22
+ const linksMatch = linksAndTags.matchAll(/\^([\w-]*)/g);
23
+ if (linksMatch) {
24
+ links = linksMatch.map((m) => m[1]).toArray();
25
+ }
26
+ const tagsMatch = linksAndTags.matchAll(/#([\w-]*)/g);
27
+ if (tagsMatch) {
28
+ tags = tagsMatch
29
+ .map((m) => new Tag({ content: m[1], fromStack: false }))
30
+ .toArray();
31
+ }
32
+ return { links, tags, string: strRemaining };
33
+ };
34
+ export class Transaction extends DateEntry {
35
+ constructor() {
36
+ super(...arguments);
37
+ this.type = 'transaction';
38
+ }
39
+ static fromGenericParseResult(genericParseResult) {
40
+ // eslint-disable-next-line prefer-const
41
+ let [payee, ...rest] = stringAwareParseLine(genericParseResult.header);
42
+ let links = [];
43
+ let tags = [];
44
+ let narration;
45
+ if (rest.length === 0) {
46
+ // no narration
47
+ const payeeParsed = getStringLinksAndTags(payee);
48
+ payee = payeeParsed.string;
49
+ links = payeeParsed.links;
50
+ tags = payeeParsed.tags;
51
+ }
52
+ else {
53
+ const payeeParsed = getStringLinksAndTags(rest.join(' '));
54
+ narration = payeeParsed.string;
55
+ links = payeeParsed.links;
56
+ tags = payeeParsed.tags;
57
+ }
58
+ const unparsedPostings = [];
59
+ const unparsedMetadata = [];
60
+ genericParseResult.body.forEach((line) => {
61
+ // V remove flag, V get account type
62
+ const accountType = line.replace(/^[^ ] /, '').split(':')[0];
63
+ if (AccountTypes.includes(accountType)) {
64
+ unparsedPostings.push(line);
65
+ }
66
+ else {
67
+ unparsedMetadata.push(line);
68
+ }
69
+ });
70
+ const postings = unparsedPostings.map((p) => Posting.fromGenericParseResult(p));
71
+ const metadata = parseMetadata(unparsedMetadata);
72
+ return new Transaction({
73
+ ...genericParseResult.props,
74
+ payee: parseString(payee),
75
+ narration: narration ? parseString(narration) : undefined,
76
+ postings,
77
+ metadata,
78
+ links,
79
+ tags,
80
+ });
81
+ }
82
+ toString() {
83
+ return this.toFormattedString({ currencyColumn: 0 });
84
+ }
85
+ toFormattedString(formatOptions) {
86
+ const firstLine = [
87
+ this.date.toJSON(),
88
+ this.flag ?? 'txn',
89
+ `"${this.payee}"`,
90
+ ];
91
+ if (this.narration !== undefined) {
92
+ firstLine.push(`"${this.narration}"`);
93
+ }
94
+ firstLine.push(...this.links.map((l) => `^${l}`));
95
+ firstLine.push(...this.tags.map((t) => t.toString()));
96
+ const lines = [firstLine.join(' ') + this.getMetaDataString()];
97
+ lines.push(...this.postings.map((p) => ` ${p.toFormattedString(formatOptions)}`));
98
+ return lines.join('\n');
99
+ }
100
+ }
101
+ // Ensure class conforms to EntryConstructor pattern
102
+ assertEntryConstructor(Transaction);
@@ -0,0 +1,12 @@
1
+ import type { GenericParseResultTransaction } from '../../genericParse.mjs';
2
+ import { DateEntry } from '../DateEntry.mjs';
3
+ import { Posting } from '../Posting.mjs';
4
+ export declare class Transaction extends DateEntry {
5
+ type: "transaction";
6
+ payee: string;
7
+ narration?: string;
8
+ flag?: string;
9
+ postings: Posting[];
10
+ static fromGenericParseResult(genericParseResult: GenericParseResultTransaction): Transaction;
11
+ toString(): string;
12
+ }