beancount 0.0.2 → 0.0.4

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 (72) hide show
  1. package/build/src/classes/DateEntry.d.mts +22 -3
  2. package/build/src/classes/DateEntry.mjs +20 -1
  3. package/build/src/classes/Entry.d.mts +61 -2
  4. package/build/src/classes/Entry.mjs +60 -0
  5. package/build/src/classes/ParseResult.d.mts +45 -3
  6. package/build/src/classes/ParseResult.mjs +56 -4
  7. package/build/src/classes/Value.d.mts +39 -0
  8. package/build/src/classes/Value.mjs +34 -0
  9. package/build/src/classes/entryTypes/Balance.d.mts +19 -0
  10. package/build/src/classes/entryTypes/Balance.mjs +16 -0
  11. package/build/src/classes/entryTypes/Blankline.d.mts +16 -0
  12. package/build/src/classes/entryTypes/Blankline.mjs +16 -0
  13. package/build/src/classes/entryTypes/Close.d.mts +12 -0
  14. package/build/src/classes/entryTypes/Close.mjs +11 -0
  15. package/build/src/classes/entryTypes/Comment.d.mts +17 -0
  16. package/build/src/classes/entryTypes/Comment.mjs +17 -0
  17. package/build/src/classes/entryTypes/Commodity.d.mts +12 -0
  18. package/build/src/classes/entryTypes/Commodity.mjs +11 -0
  19. package/build/src/classes/entryTypes/Custom.d.mts +13 -0
  20. package/build/src/classes/entryTypes/Custom.mjs +11 -0
  21. package/build/src/classes/entryTypes/Document.d.mts +13 -0
  22. package/build/src/classes/entryTypes/Document.mjs +11 -0
  23. package/build/src/classes/entryTypes/Event.d.mts +13 -0
  24. package/build/src/classes/entryTypes/Event.mjs +11 -0
  25. package/build/src/classes/entryTypes/Include.d.mts +12 -0
  26. package/build/src/classes/entryTypes/Include.mjs +11 -0
  27. package/build/src/classes/entryTypes/Note.d.mts +13 -0
  28. package/build/src/classes/entryTypes/Note.mjs +11 -0
  29. package/build/src/classes/entryTypes/Open.d.mts +15 -0
  30. package/build/src/classes/entryTypes/Open.mjs +12 -0
  31. package/build/src/classes/entryTypes/Option.d.mts +13 -0
  32. package/build/src/classes/entryTypes/Option.mjs +11 -0
  33. package/build/src/classes/entryTypes/Pad.d.mts +13 -0
  34. package/build/src/classes/entryTypes/Pad.mjs +11 -0
  35. package/build/src/classes/entryTypes/Plugin.d.mts +13 -0
  36. package/build/src/classes/entryTypes/Plugin.mjs +11 -0
  37. package/build/src/classes/entryTypes/Poptag.d.mts +12 -0
  38. package/build/src/classes/entryTypes/Poptag.mjs +11 -0
  39. package/build/src/classes/entryTypes/Price.d.mts +18 -0
  40. package/build/src/classes/entryTypes/Price.mjs +15 -0
  41. package/build/src/classes/entryTypes/Pushtag.d.mts +12 -0
  42. package/build/src/classes/entryTypes/Pushtag.mjs +11 -0
  43. package/build/src/classes/entryTypes/Query.d.mts +13 -0
  44. package/build/src/classes/entryTypes/Query.mjs +11 -0
  45. package/build/src/classes/entryTypes/Transaction/Posting.d.mts +41 -0
  46. package/build/src/classes/entryTypes/Transaction/Posting.mjs +33 -0
  47. package/build/src/classes/entryTypes/Transaction/Tag.d.mts +19 -0
  48. package/build/src/classes/entryTypes/Transaction/Tag.mjs +17 -0
  49. package/build/src/classes/entryTypes/Transaction/index.d.mts +42 -1
  50. package/build/src/classes/entryTypes/Transaction/index.mjs +69 -5
  51. package/build/src/entryTypeToClass.d.mts +59 -0
  52. package/build/src/entryTypeToClass.mjs +37 -0
  53. package/build/src/genericParse.d.mts +39 -2
  54. package/build/src/genericParse.mjs +13 -0
  55. package/build/src/main.d.mts +58 -0
  56. package/build/src/main.mjs +55 -0
  57. package/build/src/parse.d.mts +76 -23
  58. package/build/src/parse.mjs +69 -22
  59. package/build/src/utils/countChar.d.mts +7 -0
  60. package/build/src/utils/countChar.mjs +7 -0
  61. package/build/src/utils/formatPrice.d.mts +7 -2
  62. package/build/src/utils/formatPrice.mjs +7 -2
  63. package/build/src/utils/parseMetadata.d.mts +12 -0
  64. package/build/src/utils/parseMetadata.mjs +8 -0
  65. package/build/src/utils/simpleParseLine.d.mts +7 -0
  66. package/build/src/utils/simpleParseLine.mjs +7 -0
  67. package/build/src/utils/stringAwareParseLine.d.mts +7 -0
  68. package/build/src/utils/stringAwareParseLine.mjs +7 -0
  69. package/build/src/utils/stringAwareSplitLine.d.mts +9 -0
  70. package/build/src/utils/stringAwareSplitLine.mjs +9 -0
  71. package/build/tsconfig.build.tsbuildinfo +1 -1
  72. package/package.json +1 -1
@@ -1,11 +1,21 @@
1
1
  import { simpleParseLine } from '../../utils/simpleParseLine.mjs';
2
2
  import { assertEntryConstructor, Entry } from '../Entry.mjs';
3
3
  import { Tag } from './Transaction/Tag.mjs';
4
+ /**
5
+ * Represents a Poptag entry that removes a tag from the tag stack.
6
+ * Transactions after this will no longer inherit the popped tag.
7
+ */
4
8
  export class Poptag extends Entry {
5
9
  constructor() {
6
10
  super(...arguments);
11
+ /** @inheritdoc */
7
12
  this.type = 'poptag';
8
13
  }
14
+ /**
15
+ * Creates a Poptag instance from a generic parse result.
16
+ * @param genericParseResult - The parsed poptag entry data
17
+ * @returns A new Poptag instance
18
+ */
9
19
  static fromGenericParseResult(genericParseResult) {
10
20
  const [tagContent] = simpleParseLine(genericParseResult.header);
11
21
  return new Poptag({
@@ -15,6 +25,7 @@ export class Poptag extends Entry {
15
25
  }),
16
26
  });
17
27
  }
28
+ /** @inheritdoc */
18
29
  toString() {
19
30
  return `poptag #${this.tag.content}`;
20
31
  }
@@ -1,11 +1,29 @@
1
1
  import type { GenericParseResultWithDate } from '../../genericParse.mjs';
2
2
  import { DateEntry } from '../DateEntry.mjs';
3
+ /**
4
+ * Represents a Price entry that records the price of a commodity.
5
+ * Price directives establish the exchange rate between a commodity and a currency.
6
+ */
3
7
  export declare class Price extends DateEntry {
8
+ /** @inheritdoc */
4
9
  type: "price";
10
+ /** The commodity being priced */
5
11
  commodity: string;
12
+ /** The currency the price is expressed in */
6
13
  currency: string;
14
+ /** The price amount */
7
15
  amount: string;
16
+ /**
17
+ * Gets the formatted price string (amount + currency).
18
+ * @returns The formatted price string
19
+ */
8
20
  get price(): string | undefined;
21
+ /**
22
+ * Creates a Price instance from a generic parse result.
23
+ * @param genericParseResult - The parsed price entry data
24
+ * @returns A new Price instance
25
+ */
9
26
  static fromGenericParseResult(genericParseResult: GenericParseResultWithDate): Price;
27
+ /** @inheritdoc */
10
28
  toString(): string;
11
29
  }
@@ -2,14 +2,28 @@ import { assertEntryConstructor } from '../Entry.mjs';
2
2
  import { DateEntry } from '../DateEntry.mjs';
3
3
  import { simpleParseLine } from '../../utils/simpleParseLine.mjs';
4
4
  import { formatPrice } from '../../utils/formatPrice.mjs';
5
+ /**
6
+ * Represents a Price entry that records the price of a commodity.
7
+ * Price directives establish the exchange rate between a commodity and a currency.
8
+ */
5
9
  export class Price extends DateEntry {
6
10
  constructor() {
7
11
  super(...arguments);
12
+ /** @inheritdoc */
8
13
  this.type = 'price';
9
14
  }
15
+ /**
16
+ * Gets the formatted price string (amount + currency).
17
+ * @returns The formatted price string
18
+ */
10
19
  get price() {
11
20
  return formatPrice(this.amount, this.currency);
12
21
  }
22
+ /**
23
+ * Creates a Price instance from a generic parse result.
24
+ * @param genericParseResult - The parsed price entry data
25
+ * @returns A new Price instance
26
+ */
13
27
  static fromGenericParseResult(genericParseResult) {
14
28
  const [commodity, amount, currency] = simpleParseLine(genericParseResult.header);
15
29
  return new Price({
@@ -19,6 +33,7 @@ export class Price extends DateEntry {
19
33
  amount,
20
34
  });
21
35
  }
36
+ /** @inheritdoc */
22
37
  toString() {
23
38
  return `${this.getDateTypePrefix()} ${this.commodity} ${this.amount} ${this.currency}${this.getMetaDataString()}`;
24
39
  }
@@ -1,9 +1,21 @@
1
1
  import type { GenericParseResult } from '../../genericParse.mjs';
2
2
  import { Entry } from '../Entry.mjs';
3
3
  import { Tag } from './Transaction/Tag.mjs';
4
+ /**
5
+ * Represents a Pushtag entry that pushes a tag onto the tag stack.
6
+ * Subsequent transactions will automatically inherit this tag until it's popped.
7
+ */
4
8
  export declare class Pushtag extends Entry {
9
+ /** @inheritdoc */
5
10
  type: "pushtag";
11
+ /** The tag being pushed onto the stack */
6
12
  tag: Tag;
13
+ /**
14
+ * Creates a Pushtag instance from a generic parse result.
15
+ * @param genericParseResult - The parsed pushtag entry data
16
+ * @returns A new Pushtag instance
17
+ */
7
18
  static fromGenericParseResult(genericParseResult: GenericParseResult): Pushtag;
19
+ /** @inheritdoc */
8
20
  toString(): string;
9
21
  }
@@ -1,11 +1,21 @@
1
1
  import { simpleParseLine } from '../../utils/simpleParseLine.mjs';
2
2
  import { assertEntryConstructor, Entry } from '../Entry.mjs';
3
3
  import { Tag } from './Transaction/Tag.mjs';
4
+ /**
5
+ * Represents a Pushtag entry that pushes a tag onto the tag stack.
6
+ * Subsequent transactions will automatically inherit this tag until it's popped.
7
+ */
4
8
  export class Pushtag extends Entry {
5
9
  constructor() {
6
10
  super(...arguments);
11
+ /** @inheritdoc */
7
12
  this.type = 'pushtag';
8
13
  }
14
+ /**
15
+ * Creates a Pushtag instance from a generic parse result.
16
+ * @param genericParseResult - The parsed pushtag entry data
17
+ * @returns A new Pushtag instance
18
+ */
9
19
  static fromGenericParseResult(genericParseResult) {
10
20
  const [tagContent] = simpleParseLine(genericParseResult.header);
11
21
  return new Pushtag({
@@ -15,6 +25,7 @@ export class Pushtag extends Entry {
15
25
  }),
16
26
  });
17
27
  }
28
+ /** @inheritdoc */
18
29
  toString() {
19
30
  return `${this.type} #${this.tag.content}`;
20
31
  }
@@ -1,9 +1,22 @@
1
1
  import type { GenericParseResultWithDate } from '../../genericParse.mjs';
2
2
  import { DateEntry } from '../DateEntry.mjs';
3
+ /**
4
+ * Represents a Query entry that defines a named SQL query.
5
+ * Query directives allow defining reusable queries in the Beancount file.
6
+ */
3
7
  export declare class Query extends DateEntry {
8
+ /** @inheritdoc */
4
9
  type: "query";
10
+ /** The name of the query */
5
11
  name: string;
12
+ /** The SQL query contents */
6
13
  sqlContents: string;
14
+ /**
15
+ * Creates a Query instance from a generic parse result.
16
+ * @param genericParseResult - The parsed query entry data
17
+ * @returns A new Query instance
18
+ */
7
19
  static fromGenericParseResult(genericParseResult: GenericParseResultWithDate): Query;
20
+ /** @inheritdoc */
8
21
  toString(): string;
9
22
  }
@@ -2,11 +2,21 @@ import { assertEntryConstructor } from '../Entry.mjs';
2
2
  import { DateEntry } from '../DateEntry.mjs';
3
3
  import { stringAwareParseLine } from '../../utils/stringAwareParseLine.mjs';
4
4
  import { parseString } from '../Value.mjs';
5
+ /**
6
+ * Represents a Query entry that defines a named SQL query.
7
+ * Query directives allow defining reusable queries in the Beancount file.
8
+ */
5
9
  export class Query extends DateEntry {
6
10
  constructor() {
7
11
  super(...arguments);
12
+ /** @inheritdoc */
8
13
  this.type = 'query';
9
14
  }
15
+ /**
16
+ * Creates a Query instance from a generic parse result.
17
+ * @param genericParseResult - The parsed query entry data
18
+ * @returns A new Query instance
19
+ */
10
20
  static fromGenericParseResult(genericParseResult) {
11
21
  const [name, sqlContents] = stringAwareParseLine(genericParseResult.header);
12
22
  return new Query({
@@ -15,6 +25,7 @@ export class Query extends DateEntry {
15
25
  sqlContents: parseString(sqlContents).trim(),
16
26
  });
17
27
  }
28
+ /** @inheritdoc */
18
29
  toString() {
19
30
  return `${this.getDateTypePrefix()} "${this.name}" "${this.sqlContents}"${this.getMetaDataString()}`;
20
31
  }
@@ -1,16 +1,57 @@
1
1
  import { FormatOptions } from '../../Entry.mjs';
2
+ /**
3
+ * Represents a single posting (account movement) within a transaction.
4
+ * Each posting records an amount moving to/from an account.
5
+ */
2
6
  export declare class Posting {
7
+ /** Optional posting flag (e.g., '*' for cleared) */
3
8
  flag?: string;
9
+ /** The account name for this posting */
4
10
  account: string;
11
+ /** The amount as a string (may be omitted for auto-calculated postings) */
5
12
  amount?: string;
13
+ /** The currency code for the amount */
6
14
  currency?: string;
15
+ /** Optional cost specification (e.g., for currency conversions) */
7
16
  cost?: string;
17
+ /** Currency for the price annotation */
8
18
  priceCurrency?: string;
19
+ /** Amount for the price annotation */
9
20
  priceAmount?: string;
21
+ /** Optional comment for this posting */
10
22
  comment?: string;
23
+ /**
24
+ * Creates a new Posting instance.
25
+ * @param obj - Object containing posting properties
26
+ */
11
27
  constructor(obj: Record<string, unknown>);
28
+ /**
29
+ * Parses a posting line string into a Posting instance.
30
+ * Expected format: [Flag] Account [Amount Currency] [{Cost}] [@ PriceAmount PriceCurrency] [; Comment]
31
+ *
32
+ * @param unparsedline - The posting line string to parse
33
+ * @returns A new Posting instance
34
+ * @throws {Error} If the posting line cannot be parsed
35
+ */
12
36
  static fromGenericParseResult(unparsedline: string): Posting;
37
+ /**
38
+ * Gets the formatted price string combining amount, currency, cost, and price annotation.
39
+ * @returns The formatted price string, or undefined if no price components exist
40
+ */
13
41
  get price(): string | undefined;
42
+ /**
43
+ * Converts this posting to a string representation.
44
+ * Delegates to toFormattedString with zero currency column alignment.
45
+ *
46
+ * @returns The string representation of this posting
47
+ */
14
48
  toString(): string;
49
+ /**
50
+ * Converts this posting to a formatted string with aligned currency column.
51
+ * Adds padding before the price to align at the specified column.
52
+ *
53
+ * @param formatOptions - Formatting options including currency column position
54
+ * @returns The formatted string representation of this posting
55
+ */
15
56
  toFormattedString(formatOptions: FormatOptions): string;
16
57
  }
@@ -1,8 +1,24 @@
1
1
  import { formatPrice } from '../../../utils/formatPrice.mjs';
2
+ /**
3
+ * Represents a single posting (account movement) within a transaction.
4
+ * Each posting records an amount moving to/from an account.
5
+ */
2
6
  export class Posting {
7
+ /**
8
+ * Creates a new Posting instance.
9
+ * @param obj - Object containing posting properties
10
+ */
3
11
  constructor(obj) {
4
12
  Object.assign(this, obj);
5
13
  }
14
+ /**
15
+ * Parses a posting line string into a Posting instance.
16
+ * Expected format: [Flag] Account [Amount Currency] [{Cost}] [@ PriceAmount PriceCurrency] [; Comment]
17
+ *
18
+ * @param unparsedline - The posting line string to parse
19
+ * @returns A new Posting instance
20
+ * @throws {Error} If the posting line cannot be parsed
21
+ */
6
22
  static fromGenericParseResult(unparsedline) {
7
23
  // [Flag] Account Amount [{Cost}] [@ Price]
8
24
  const matches = /^(?:([^ ]) )?([^ ]*)(?: +([^A-Z]*) +(\w+)(?: +{(.*)})?(?: +@ +(?:(\d+\.?\d*) (\w+)))?)?( *;.*)?$/.exec(unparsedline);
@@ -21,12 +37,29 @@ export class Posting {
21
37
  comment: comment?.replace(/^ *;/, '').trim(),
22
38
  });
23
39
  }
40
+ /**
41
+ * Gets the formatted price string combining amount, currency, cost, and price annotation.
42
+ * @returns The formatted price string, or undefined if no price components exist
43
+ */
24
44
  get price() {
25
45
  return formatPrice(this.amount, this.currency, this.cost, this.priceAmount, this.priceCurrency);
26
46
  }
47
+ /**
48
+ * Converts this posting to a string representation.
49
+ * Delegates to toFormattedString with zero currency column alignment.
50
+ *
51
+ * @returns The string representation of this posting
52
+ */
27
53
  toString() {
28
54
  return this.toFormattedString({ currencyColumn: 0 });
29
55
  }
56
+ /**
57
+ * Converts this posting to a formatted string with aligned currency column.
58
+ * Adds padding before the price to align at the specified column.
59
+ *
60
+ * @param formatOptions - Formatting options including currency column position
61
+ * @returns The formatted string representation of this posting
62
+ */
30
63
  toFormattedString(formatOptions) {
31
64
  const parts = [];
32
65
  if (this.flag !== undefined) {
@@ -1,9 +1,28 @@
1
+ /**
2
+ * Represents a tag associated with a transaction.
3
+ * Tags can be specified inline in the transaction or inherited from a tag stack (pushtag/poptag).
4
+ */
1
5
  export declare class Tag {
6
+ /** The tag name/content (without the '#' prefix) */
2
7
  content: string;
8
+ /** Whether this tag comes from the tag stack (pushtag) or is inline */
3
9
  fromStack: boolean;
10
+ /**
11
+ * Creates a new Tag instance.
12
+ * @param obj - Object containing tag content and source information
13
+ * @param obj.content - The tag name/content
14
+ * @param obj.fromStack - Whether this tag is from the tag stack
15
+ */
4
16
  constructor(obj: {
5
17
  content: string;
6
18
  fromStack: boolean;
7
19
  });
20
+ /**
21
+ * Converts this tag to its string representation.
22
+ * Tags from the stack return an empty string (they're implicit),
23
+ * while inline tags return '#tagname' format.
24
+ *
25
+ * @returns The tag string with '#' prefix, or empty string if from stack
26
+ */
8
27
  toString(): string;
9
28
  }
@@ -1,7 +1,24 @@
1
+ /**
2
+ * Represents a tag associated with a transaction.
3
+ * Tags can be specified inline in the transaction or inherited from a tag stack (pushtag/poptag).
4
+ */
1
5
  export class Tag {
6
+ /**
7
+ * Creates a new Tag instance.
8
+ * @param obj - Object containing tag content and source information
9
+ * @param obj.content - The tag name/content
10
+ * @param obj.fromStack - Whether this tag is from the tag stack
11
+ */
2
12
  constructor(obj) {
3
13
  Object.assign(this, obj);
4
14
  }
15
+ /**
16
+ * Converts this tag to its string representation.
17
+ * Tags from the stack return an empty string (they're implicit),
18
+ * while inline tags return '#tagname' format.
19
+ *
20
+ * @returns The tag string with '#' prefix, or empty string if from stack
21
+ */
5
22
  toString() {
6
23
  if (this.fromStack) {
7
24
  return '';
@@ -3,15 +3,56 @@ import { FormatOptions } from '../../Entry.mjs';
3
3
  import { DateEntry } from '../../DateEntry.mjs';
4
4
  import { Posting } from './Posting.mjs';
5
5
  import { Tag } from './Tag.mjs';
6
+ /**
7
+ * Represents a Beancount transaction entry.
8
+ * Transactions record financial movements between accounts with postings.
9
+ */
6
10
  export declare class Transaction extends DateEntry {
11
+ /** @inheritdoc */
7
12
  type: "transaction";
13
+ /** The payee of the transaction */
8
14
  payee: string;
15
+ /** Optional narration/description of the transaction */
9
16
  narration?: string;
17
+ /** Optional transaction flag (e.g., '*' for cleared, '!' for pending) */
10
18
  flag?: string;
19
+ /** Array of postings (account movements) in this transaction */
11
20
  postings: Posting[];
12
- links: string[];
21
+ /** Set of link identifiers associated with this transaction */
22
+ links: Set<string>;
23
+ /** Array of tags associated with this transaction (from inline tags and tag stack) */
13
24
  tags: Tag[];
25
+ /**
26
+ * Creates a Transaction instance from a generic parse result.
27
+ * Parses payee, narration, links, tags, postings, and metadata.
28
+ *
29
+ * @param genericParseResult - The parsed transaction data
30
+ * @returns A new Transaction instance
31
+ */
14
32
  static fromGenericParseResult(genericParseResult: GenericParseResultTransaction): Transaction;
33
+ /** @inheritdoc */
15
34
  toString(): string;
35
+ /** @inheritdoc */
16
36
  toFormattedString(formatOptions: FormatOptions): string;
37
+ /**
38
+ * Converts this transaction to a JSON-serializable object.
39
+ * Ensures the links Set is properly serialized as an array.
40
+ *
41
+ * @returns A JSON-serializable representation of this transaction
42
+ */
43
+ toJSON(): this & {
44
+ links: string[];
45
+ };
46
+ /**
47
+ * Transforms JSON data before creating a Transaction instance.
48
+ * Deserializes transaction-specific properties including postings, tags, links, and metadata.
49
+ *
50
+ * @param json - The JSON data to transform
51
+ * @returns The transformed data with:
52
+ * - postings converted to Posting instances
53
+ * - tags converted to Tag instances
54
+ * - links converted from array to Set<string>
55
+ * - metadata values converted to Value instances
56
+ */
57
+ protected parseJSONData(json: Record<string, unknown>): Record<string, unknown>;
17
58
  }
@@ -1,13 +1,25 @@
1
1
  import { assertEntryConstructor } from '../../Entry.mjs';
2
2
  import { DateEntry } from '../../DateEntry.mjs';
3
3
  import { stringAwareParseLine } from '../../../utils/stringAwareParseLine.mjs';
4
- import { parseString } from '../../Value.mjs';
4
+ import { parseString, Value } from '../../Value.mjs';
5
5
  import { parseMetadata } from '../../../utils/parseMetadata.mjs';
6
6
  import { Posting } from './Posting.mjs';
7
7
  import { Tag } from './Tag.mjs';
8
+ /**
9
+ * Valid Beancount account type prefixes.
10
+ * @internal
11
+ */
8
12
  const AccountTypes = ['Assets', 'Liabilities', 'Equity', 'Income', 'Expenses'];
13
+ /**
14
+ * Parses a string to extract narration/payee, links, and tags.
15
+ * Links are prefixed with '^' and tags with '#'.
16
+ *
17
+ * @param input - The string to parse (may contain narration in quotes, links, and tags)
18
+ * @returns An object containing extracted links, tags, and the remaining string (narration/payee)
19
+ * @internal
20
+ */
9
21
  const getStringLinksAndTags = (input) => {
10
- let links = [];
22
+ let links = new Set();
11
23
  let tags = [];
12
24
  // default if no narration
13
25
  let strRemaining = '';
@@ -21,7 +33,7 @@ const getStringLinksAndTags = (input) => {
21
33
  }
22
34
  const linksMatch = linksAndTags.matchAll(/\^([\w-]*)/g);
23
35
  if (linksMatch) {
24
- links = linksMatch.map((m) => m[1]).toArray();
36
+ links = new Set(linksMatch.map((m) => m[1]));
25
37
  }
26
38
  const tagsMatch = linksAndTags.matchAll(/#([\w-]*)/g);
27
39
  if (tagsMatch) {
@@ -31,15 +43,27 @@ const getStringLinksAndTags = (input) => {
31
43
  }
32
44
  return { links, tags, string: strRemaining };
33
45
  };
46
+ /**
47
+ * Represents a Beancount transaction entry.
48
+ * Transactions record financial movements between accounts with postings.
49
+ */
34
50
  export class Transaction extends DateEntry {
35
51
  constructor() {
36
52
  super(...arguments);
53
+ /** @inheritdoc */
37
54
  this.type = 'transaction';
38
55
  }
56
+ /**
57
+ * Creates a Transaction instance from a generic parse result.
58
+ * Parses payee, narration, links, tags, postings, and metadata.
59
+ *
60
+ * @param genericParseResult - The parsed transaction data
61
+ * @returns A new Transaction instance
62
+ */
39
63
  static fromGenericParseResult(genericParseResult) {
40
64
  // eslint-disable-next-line prefer-const
41
65
  let [payee, ...rest] = stringAwareParseLine(genericParseResult.header);
42
- let links = [];
66
+ let links = new Set();
43
67
  let tags = [];
44
68
  let narration;
45
69
  if (rest.length === 0) {
@@ -79,9 +103,11 @@ export class Transaction extends DateEntry {
79
103
  tags,
80
104
  });
81
105
  }
106
+ /** @inheritdoc */
82
107
  toString() {
83
108
  return this.toFormattedString({ currencyColumn: 0 });
84
109
  }
110
+ /** @inheritdoc */
85
111
  toFormattedString(formatOptions) {
86
112
  const firstLine = [
87
113
  this.date.toJSON(),
@@ -91,12 +117,50 @@ export class Transaction extends DateEntry {
91
117
  if (this.narration !== undefined) {
92
118
  firstLine.push(`"${this.narration}"`);
93
119
  }
94
- firstLine.push(...this.links.map((l) => `^${l}`));
120
+ firstLine.push(...this.links.values().map((l) => `^${l}`));
95
121
  firstLine.push(...this.tags.map((t) => t.toString()));
96
122
  const lines = [firstLine.join(' ') + this.getMetaDataString()];
97
123
  lines.push(...this.postings.map((p) => ` ${p.toFormattedString(formatOptions)}`));
98
124
  return lines.join('\n');
99
125
  }
126
+ /**
127
+ * Converts this transaction to a JSON-serializable object.
128
+ * Ensures the links Set is properly serialized as an array.
129
+ *
130
+ * @returns A JSON-serializable representation of this transaction
131
+ */
132
+ toJSON() {
133
+ return {
134
+ ...this,
135
+ links: Array.from(this.links),
136
+ };
137
+ }
138
+ /**
139
+ * Transforms JSON data before creating a Transaction instance.
140
+ * Deserializes transaction-specific properties including postings, tags, links, and metadata.
141
+ *
142
+ * @param json - The JSON data to transform
143
+ * @returns The transformed data with:
144
+ * - postings converted to Posting instances
145
+ * - tags converted to Tag instances
146
+ * - links converted from array to Set<string>
147
+ * - metadata values converted to Value instances
148
+ */
149
+ parseJSONData(json) {
150
+ const { postings, tags, links, metadata, ...rest } = json;
151
+ return {
152
+ ...rest,
153
+ postings: postings?.map((p) => new Posting(p)),
154
+ tags: tags?.map((t) => new Tag(t)),
155
+ links: links ? new Set(links) : new Set(),
156
+ metadata: metadata
157
+ ? Object.fromEntries(Object.entries(metadata).map(([key, val]) => [
158
+ key,
159
+ new Value(val),
160
+ ]))
161
+ : undefined,
162
+ };
163
+ }
100
164
  }
101
165
  // Ensure class conforms to EntryConstructor pattern
102
166
  assertEntryConstructor(Transaction);
@@ -0,0 +1,59 @@
1
+ import { Transaction, Balance, Close, Comment, Commodity, Custom, Document, Event, Include, Note, Open, Option, Pad, Plugin, Poptag, Price, Pushtag, Query, Blankline } from './classes/entryTypes/index.mjs';
2
+ /**
3
+ * Union type of all valid Beancount entry type names.
4
+ * EntryTypes derived from https://beancount.github.io/docs/beancount_language_syntax.html#directives-1
5
+ * Entries can have two additional 'fake' types: 'comment' and 'blankline', see {@link EntryType}
6
+ */
7
+ export type BeancountEntryType = 'transaction' | 'balance' | 'close' | 'commodity' | 'custom' | 'document' | 'event' | 'include' | 'note' | 'open' | 'option' | 'pad' | 'plugin' | 'poptag' | 'price' | 'pushtag' | 'query';
8
+ /**
9
+ * Union type of all valid entry type names, including the 'fake' entry types of comment and blankline.
10
+ */
11
+ export type EntryType = BeancountEntryType | 'comment' | 'blankline';
12
+ /**
13
+ * Mapping of Beancount entry type names to their corresponding class constructors.
14
+ * @internal
15
+ */
16
+ export declare const beancountEntryToClass: {
17
+ transaction: typeof Transaction;
18
+ balance: typeof Balance;
19
+ close: typeof Close;
20
+ commodity: typeof Commodity;
21
+ custom: typeof Custom;
22
+ document: typeof Document;
23
+ event: typeof Event;
24
+ include: typeof Include;
25
+ note: typeof Note;
26
+ open: typeof Open;
27
+ option: typeof Option;
28
+ pad: typeof Pad;
29
+ plugin: typeof Plugin;
30
+ poptag: typeof Poptag;
31
+ price: typeof Price;
32
+ pushtag: typeof Pushtag;
33
+ query: typeof Query;
34
+ };
35
+ /**
36
+ * Mapping of all entry type names (including 'comment' and 'blankline') to their corresponding class constructors.
37
+ * @internal
38
+ */
39
+ export declare const entryTypeToClass: {
40
+ comment: typeof Comment;
41
+ blankline: typeof Blankline;
42
+ transaction: typeof Transaction;
43
+ balance: typeof Balance;
44
+ close: typeof Close;
45
+ commodity: typeof Commodity;
46
+ custom: typeof Custom;
47
+ document: typeof Document;
48
+ event: typeof Event;
49
+ include: typeof Include;
50
+ note: typeof Note;
51
+ open: typeof Open;
52
+ option: typeof Option;
53
+ pad: typeof Pad;
54
+ plugin: typeof Plugin;
55
+ poptag: typeof Poptag;
56
+ price: typeof Price;
57
+ pushtag: typeof Pushtag;
58
+ query: typeof Query;
59
+ };
@@ -0,0 +1,37 @@
1
+ import { Transaction, Balance, Close, Comment, Commodity, Custom, Document, Event, Include, Note, Open, Option, Pad, Plugin, Poptag, Price, Pushtag, Query, Blankline, } from './classes/entryTypes/index.mjs';
2
+ /**
3
+ * Mapping of Beancount entry type names to their corresponding class constructors.
4
+ * @internal
5
+ */
6
+ export const beancountEntryToClass = {
7
+ transaction: Transaction,
8
+ balance: Balance,
9
+ close: Close,
10
+ commodity: Commodity,
11
+ custom: Custom,
12
+ document: Document,
13
+ event: Event,
14
+ include: Include,
15
+ note: Note,
16
+ open: Open,
17
+ option: Option,
18
+ pad: Pad,
19
+ plugin: Plugin,
20
+ poptag: Poptag,
21
+ price: Price,
22
+ pushtag: Pushtag,
23
+ query: Query,
24
+ };
25
+ // Compile-time assertion: beancountEntryToClass must have all BeancountEntryType keys
26
+ beancountEntryToClass;
27
+ /**
28
+ * Mapping of all entry type names (including 'comment' and 'blankline') to their corresponding class constructors.
29
+ * @internal
30
+ */
31
+ export const entryTypeToClass = {
32
+ ...beancountEntryToClass,
33
+ comment: Comment,
34
+ blankline: Blankline,
35
+ };
36
+ // Compile-time assertion: entryTypeToClass must have all EntryType keys
37
+ beancountEntryToClass;