bkper-js 2.12.2 → 2.12.3

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/CHANGELOG.md CHANGED
@@ -37,6 +37,7 @@ See what's new and what has changed in bkper-js
37
37
  - Deprecated `Integration.getLogo`
38
38
  - Added `Integration.getLogoUrl`
39
39
  - Added `Integration.getLogoUrlDark`
40
+ - Added `Transaction.getCreatedBy`
40
41
  - Replaced axios with native Fetch API for better compatibility with multiple environments
41
42
 
42
43
  **August 2025**
package/lib/index.d.ts CHANGED
@@ -1308,6 +1308,8 @@ export declare class Bkper {
1308
1308
  */
1309
1309
  export declare class Book extends Resource<bkper.Book> {
1310
1310
  private config?;
1311
+ private allGroupsLoaded;
1312
+ private allAccountsLoaded;
1311
1313
 
1312
1314
 
1313
1315
 
@@ -1727,11 +1729,30 @@ export declare class Book extends Resource<bkper.Book> {
1727
1729
  */
1728
1730
  updateIntegration(integration: bkper.Integration): Promise<Integration>;
1729
1731
  /**
1730
- * Gets an [[Account]] object.
1732
+ * Gets an [[Account]] object by id or name.
1733
+ *
1734
+ * Results are cached to avoid repeated server calls. Account-group relationships
1735
+ * are included if the full chart was loaded via getAccounts() or when the Book
1736
+ * was loaded with includeAccounts=true.
1731
1737
  *
1732
1738
  * @param idOrName - The id or name of the Account
1733
1739
  *
1734
1740
  * @returns The matching Account object
1741
+ *
1742
+ * @example
1743
+ * ```typescript
1744
+ * // Get individual account (basic data, cached)
1745
+ * const account = await book.getAccount('Bank Account');
1746
+ *
1747
+ * // For account-group relationships, use one of these approaches:
1748
+ * // Option 1: Load book with full data upfront
1749
+ * const bookWithAccounts = await Bkper.getBook(bookId, true);
1750
+ * const accountWithGroups = await bookWithAccounts.getAccount('Bank Account');
1751
+ *
1752
+ * // Option 2: Load full chart when needed
1753
+ * await book.getAccounts();
1754
+ * const accountWithGroups2 = await book.getAccount('Bank Account');
1755
+ * ```
1735
1756
  */
1736
1757
  getAccount(idOrName?: string): Promise<Account | undefined>;
1737
1758
 
@@ -1741,26 +1762,73 @@ export declare class Book extends Resource<bkper.Book> {
1741
1762
 
1742
1763
 
1743
1764
 
1744
-
1745
1765
  /**
1746
- * Gets a [[Group]] object.
1766
+ * Gets a [[Group]] object by id or name.
1767
+ *
1768
+ * Results are cached to avoid repeated server calls. Parent/child relationships
1769
+ * are included if all groups were loaded via getGroups() or when the Book was
1770
+ * loaded with includeGroups=true.
1747
1771
  *
1748
1772
  * @param idOrName - The id or name of the Group
1749
1773
  *
1750
1774
  * @returns The matching Group object
1775
+ *
1776
+ * @example
1777
+ * ```typescript
1778
+ * // Get individual group (basic data, cached)
1779
+ * const group = await book.getGroup('Assets');
1780
+ *
1781
+ * // For parent/child relationships, use one of these approaches:
1782
+ * // Option 1: Load book with full hierarchy upfront
1783
+ * const bookWithGroups = await Bkper.getBook(bookId, false, true);
1784
+ * const groupWithTree = await bookWithGroups.getGroup('Assets');
1785
+ *
1786
+ * // Option 2: Load full hierarchy when needed
1787
+ * await book.getGroups();
1788
+ * const groupWithTree2 = await book.getGroup('Assets');
1789
+ * console.log(groupWithTree2.getParent(), groupWithTree2.getChildren());
1790
+ * ```
1751
1791
  */
1752
1792
  getGroup(idOrName?: string): Promise<Group | undefined>;
1753
1793
  /**
1754
- * Gets all [[Groups]] of this Book.
1794
+ * Gets all [[Groups]] of this Book with complete parent/child hierarchy.
1795
+ *
1796
+ * Results are cached for performance. Group tree relationships are built
1797
+ * during loading. Consider using Bkper.getBook(id, false, true) for
1798
+ * upfront loading when you know you'll need all groups.
1755
1799
  *
1756
1800
  * @returns The retrieved [[Group]] objects
1801
+ *
1802
+ * @example
1803
+ * ```typescript
1804
+ * // Load all groups with complete hierarchy
1805
+ * const groups = await book.getGroups();
1806
+ *
1807
+ * // Alternative: Load book with groups upfront (more efficient)
1808
+ * const bookWithGroups = await Bkper.getBook(bookId, false, true);
1809
+ * const groups2 = await bookWithGroups.getGroups(); // Already cached
1810
+ * ```
1757
1811
  */
1758
1812
  getGroups(): Promise<Group[]>;
1759
1813
 
1760
1814
  /**
1761
- * Gets all [[Accounts]] of this Book.
1815
+ * Gets all [[Accounts]] of this Book with full account-group relationships.
1816
+ *
1817
+ * Results are cached for performance. Groups are automatically loaded first
1818
+ * to ensure proper linking. Consider using Bkper.getBook(id, true) for
1819
+ * upfront loading when you know you'll need all accounts.
1762
1820
  *
1763
1821
  * @returns The retrieved [[Account]] objects
1822
+ *
1823
+ * @example
1824
+ * ```typescript
1825
+ * // Load all accounts with complete relationships
1826
+ * const accounts = await book.getAccounts();
1827
+ *
1828
+ * // Alternative: Load book with accounts upfront (more efficient)
1829
+ * const bookWithAccounts = await Bkper.getBook(bookId, true);
1830
+ * const accounts2 = await bookWithAccounts.getAccounts(); // Already cached
1831
+ * ```
1764
1832
  */
1765
1833
  getAccounts(): Promise<Account[]>;
1766
1834
 
@@ -1771,6 +1839,7 @@ export declare class Book extends Resource<bkper.Book> {
1771
1839
 
1772
1840
 
1773
1841
 
1842
+
1774
1843
  /**
1775
1844
  * Lists transactions in the Book based on the provided query, limit, and cursor, for pagination.
1776
1845
  *
package/lib/model/Book.js CHANGED
@@ -44,13 +44,15 @@ import { Backlog } from "./Backlog.js";
44
44
  export class Book extends Resource {
45
45
  constructor(payload, config) {
46
46
  super(payload);
47
+ this.allGroupsLoaded = false;
48
+ this.allAccountsLoaded = false;
47
49
  this.config = config;
48
50
  if (this.payload.permission == Permission.RECORDER) {
49
51
  this.payload.groups = this.payload.groups || [];
50
52
  this.payload.accounts = this.payload.accounts || [];
51
53
  }
52
- this.mapGroups(this.payload.groups);
53
- this.mapAccounts(this.payload.accounts);
54
+ this.allGroupsLoaded = this.mapGroups(this.payload.groups);
55
+ this.allAccountsLoaded = this.mapAccounts(this.payload.accounts);
54
56
  }
55
57
  /** @internal */
56
58
  getConfig() {
@@ -721,11 +723,30 @@ export class Book extends Resource {
721
723
  });
722
724
  }
723
725
  /**
724
- * Gets an [[Account]] object.
726
+ * Gets an [[Account]] object by id or name.
727
+ *
728
+ * Results are cached to avoid repeated server calls. Account-group relationships
729
+ * are included if the full chart was loaded via getAccounts() or when the Book
730
+ * was loaded with includeAccounts=true.
725
731
  *
726
732
  * @param idOrName - The id or name of the Account
727
733
  *
728
734
  * @returns The matching Account object
735
+ *
736
+ * @example
737
+ * ```typescript
738
+ * // Get individual account (basic data, cached)
739
+ * const account = await book.getAccount('Bank Account');
740
+ *
741
+ * // For account-group relationships, use one of these approaches:
742
+ * // Option 1: Load book with full data upfront
743
+ * const bookWithAccounts = await Bkper.getBook(bookId, true);
744
+ * const accountWithGroups = await bookWithAccounts.getAccount('Bank Account');
745
+ *
746
+ * // Option 2: Load full chart when needed
747
+ * await book.getAccounts();
748
+ * const accountWithGroups2 = await book.getAccount('Bank Account');
749
+ * ```
729
750
  */
730
751
  getAccount(idOrName) {
731
752
  return __awaiter(this, void 0, void 0, function* () {
@@ -739,13 +760,14 @@ export class Book extends Resource {
739
760
  }
740
761
  // Try to get account by name
741
762
  if (!account && this.nameAccountMap) {
742
- account = this.nameAccountMap.get(idOrName);
763
+ account = this.nameAccountMap.get(Utils.normalizeName(idOrName));
743
764
  }
744
765
  // Try to fetch account from server
745
766
  if (!account) {
746
767
  const accountPayload = yield AccountService.getAccount(this.getId(), idOrName, this.getConfig());
747
768
  if (accountPayload) {
748
769
  account = new Account(this, accountPayload);
770
+ this.updateAccountCache(account);
749
771
  }
750
772
  }
751
773
  return account;
@@ -755,63 +777,42 @@ export class Book extends Resource {
755
777
  updateGroupCache(group) {
756
778
  this.updateGroupIdMap(group);
757
779
  this.updateGroupNameMap(group);
758
- if (this.idGroupMap) {
759
- group.buildGroupTree(this.idGroupMap);
760
- }
761
780
  }
762
781
  /** @internal */
763
782
  updateGroupIdMap(group) {
764
- if (this.idGroupMap) {
765
- const id = group.getId();
766
- if (id) {
767
- this.idGroupMap.set(id, group);
768
- }
783
+ this.idGroupMap = this.idGroupMap || new Map();
784
+ const id = group.getId();
785
+ if (id) {
786
+ this.idGroupMap.set(id, group);
769
787
  }
770
788
  }
771
789
  /** @internal */
772
790
  updateGroupNameMap(group) {
773
- if (this.nameGroupMap) {
774
- const normalizedName = group.getNormalizedName();
775
- if (normalizedName) {
776
- this.nameGroupMap.set(normalizedName, group);
777
- }
791
+ this.nameGroupMap = this.nameGroupMap || new Map();
792
+ const normalizedName = group.getNormalizedName();
793
+ if (normalizedName) {
794
+ this.nameGroupMap.set(normalizedName, group);
778
795
  }
779
796
  }
780
797
  /** @internal */
781
798
  updateAccountCache(account) {
782
799
  this.updateAccountIdMap(account);
783
800
  this.updateAccountNameMap(account);
784
- if (this.idAccountMap || this.nameAccountMap) {
785
- this.linkAccountsAndGroups(account);
786
- }
787
801
  }
788
802
  /** @internal */
789
803
  updateAccountIdMap(account) {
790
- if (this.idAccountMap) {
791
- const id = account.getId();
792
- if (id) {
793
- this.idAccountMap.set(id, account);
794
- }
804
+ this.idAccountMap = this.idAccountMap || new Map();
805
+ const id = account.getId();
806
+ if (id) {
807
+ this.idAccountMap.set(id, account);
795
808
  }
796
809
  }
797
810
  /** @internal */
798
811
  updateAccountNameMap(account) {
799
- if (this.nameAccountMap) {
800
- const normalizedName = account.getNormalizedName();
801
- if (normalizedName) {
802
- this.nameAccountMap.set(normalizedName, account);
803
- }
804
- }
805
- }
806
- /** @internal */
807
- linkAccountsAndGroups(account) {
808
- var _a;
809
- const groupPayloads = account.json().groups || [];
810
- for (const groupPayload of groupPayloads) {
811
- const group = (_a = this.idGroupMap) === null || _a === void 0 ? void 0 : _a.get(groupPayload.id || "");
812
- if (group != null) {
813
- group.addAccount(account);
814
- }
812
+ this.nameAccountMap = this.nameAccountMap || new Map();
813
+ const normalizedName = account.getNormalizedName();
814
+ if (normalizedName) {
815
+ this.nameAccountMap.set(normalizedName, account);
815
816
  }
816
817
  }
817
818
  /** @internal */
@@ -835,11 +836,31 @@ export class Book extends Resource {
835
836
  }
836
837
  }
837
838
  /**
838
- * Gets a [[Group]] object.
839
+ * Gets a [[Group]] object by id or name.
840
+ *
841
+ * Results are cached to avoid repeated server calls. Parent/child relationships
842
+ * are included if all groups were loaded via getGroups() or when the Book was
843
+ * loaded with includeGroups=true.
839
844
  *
840
845
  * @param idOrName - The id or name of the Group
841
846
  *
842
847
  * @returns The matching Group object
848
+ *
849
+ * @example
850
+ * ```typescript
851
+ * // Get individual group (basic data, cached)
852
+ * const group = await book.getGroup('Assets');
853
+ *
854
+ * // For parent/child relationships, use one of these approaches:
855
+ * // Option 1: Load book with full hierarchy upfront
856
+ * const bookWithGroups = await Bkper.getBook(bookId, false, true);
857
+ * const groupWithTree = await bookWithGroups.getGroup('Assets');
858
+ *
859
+ * // Option 2: Load full hierarchy when needed
860
+ * await book.getGroups();
861
+ * const groupWithTree2 = await book.getGroup('Assets');
862
+ * console.log(groupWithTree2.getParent(), groupWithTree2.getChildren());
863
+ * ```
843
864
  */
844
865
  getGroup(idOrName) {
845
866
  return __awaiter(this, void 0, void 0, function* () {
@@ -853,75 +874,123 @@ export class Book extends Resource {
853
874
  }
854
875
  // Try to get group by name
855
876
  if (!group && this.nameGroupMap) {
856
- group = this.nameGroupMap.get(idOrName);
877
+ group = this.nameGroupMap.get(Utils.normalizeName(idOrName));
857
878
  }
858
879
  // Try to fetch group from server
859
880
  if (!group) {
860
881
  const groupPayload = yield GroupService.getGroup(this.getId(), idOrName, this.getConfig());
861
882
  if (groupPayload) {
862
883
  group = new Group(this, groupPayload);
884
+ this.updateGroupCache(group);
863
885
  }
864
886
  }
865
887
  return group;
866
888
  });
867
889
  }
868
890
  /**
869
- * Gets all [[Groups]] of this Book.
891
+ * Gets all [[Groups]] of this Book with complete parent/child hierarchy.
892
+ *
893
+ * Results are cached for performance. Group tree relationships are built
894
+ * during loading. Consider using Bkper.getBook(id, false, true) for
895
+ * upfront loading when you know you'll need all groups.
870
896
  *
871
897
  * @returns The retrieved [[Group]] objects
898
+ *
899
+ * @example
900
+ * ```typescript
901
+ * // Load all groups with complete hierarchy
902
+ * const groups = await book.getGroups();
903
+ *
904
+ * // Alternative: Load book with groups upfront (more efficient)
905
+ * const bookWithGroups = await Bkper.getBook(bookId, false, true);
906
+ * const groups2 = await bookWithGroups.getGroups(); // Already cached
907
+ * ```
872
908
  */
873
909
  getGroups() {
874
910
  return __awaiter(this, void 0, void 0, function* () {
875
- if (this.idGroupMap) {
876
- return Array.from(this.idGroupMap.values());
911
+ var _a, _b;
912
+ if (this.allGroupsLoaded) {
913
+ return Array.from(((_a = this.idGroupMap) === null || _a === void 0 ? void 0 : _a.values()) || []);
877
914
  }
878
915
  let groups = yield GroupService.getGroups(this.getId(), this.getConfig());
879
- return this.mapGroups(groups);
916
+ this.allGroupsLoaded = this.mapGroups(groups);
917
+ return Array.from(((_b = this.idGroupMap) === null || _b === void 0 ? void 0 : _b.values()) || []);
880
918
  });
881
919
  }
882
920
  /** @internal */
883
921
  mapGroups(groups) {
884
922
  if (!groups) {
885
- return [];
923
+ return false;
886
924
  }
887
925
  let groupsObj = groups.map((group) => new Group(this, group));
888
926
  this.idGroupMap = new Map();
889
927
  this.nameGroupMap = new Map();
890
928
  for (const group of groupsObj) {
891
929
  this.updateGroupCache(group);
930
+ group.buildGroupTree(this.idGroupMap);
892
931
  }
893
932
  for (const group of groupsObj) {
894
933
  group.buildGroupTree(this.idGroupMap);
895
934
  }
896
- return groupsObj;
935
+ return true;
897
936
  }
898
937
  /**
899
- * Gets all [[Accounts]] of this Book.
938
+ * Gets all [[Accounts]] of this Book with full account-group relationships.
939
+ *
940
+ * Results are cached for performance. Groups are automatically loaded first
941
+ * to ensure proper linking. Consider using Bkper.getBook(id, true) for
942
+ * upfront loading when you know you'll need all accounts.
900
943
  *
901
944
  * @returns The retrieved [[Account]] objects
945
+ *
946
+ * @example
947
+ * ```typescript
948
+ * // Load all accounts with complete relationships
949
+ * const accounts = await book.getAccounts();
950
+ *
951
+ * // Alternative: Load book with accounts upfront (more efficient)
952
+ * const bookWithAccounts = await Bkper.getBook(bookId, true);
953
+ * const accounts2 = await bookWithAccounts.getAccounts(); // Already cached
954
+ * ```
902
955
  */
903
956
  getAccounts() {
904
957
  return __awaiter(this, void 0, void 0, function* () {
905
- if (this.idAccountMap) {
906
- return Array.from(this.idAccountMap.values());
958
+ var _a, _b;
959
+ if (this.allAccountsLoaded) {
960
+ return Array.from(((_a = this.idAccountMap) === null || _a === void 0 ? void 0 : _a.values()) || []);
907
961
  }
962
+ //Ensure groups are loaded
963
+ yield this.getGroups();
908
964
  let accounts = yield AccountService.getAccounts(this.getId(), this.getConfig());
909
- return this.mapAccounts(accounts);
965
+ this.allAccountsLoaded = this.mapAccounts(accounts);
966
+ return Array.from(((_b = this.idAccountMap) === null || _b === void 0 ? void 0 : _b.values()) || []);
910
967
  });
911
968
  }
912
969
  /** @internal */
913
970
  mapAccounts(accounts) {
914
971
  if (!accounts) {
915
- return [];
972
+ return false;
916
973
  }
917
974
  let accountsObj = accounts.map((account) => new Account(this, account));
918
975
  this.idAccountMap = new Map();
919
976
  this.nameAccountMap = new Map();
920
977
  for (const account of accountsObj) {
921
978
  this.updateAccountCache(account);
979
+ this.linkAccountsAndGroups(account);
922
980
  }
923
981
  this.ensureGroupsAccountMapsLoaded();
924
- return accountsObj;
982
+ return true;
983
+ }
984
+ /** @internal */
985
+ linkAccountsAndGroups(account) {
986
+ var _a;
987
+ const groupPayloads = account.json().groups || [];
988
+ for (const groupPayload of groupPayloads) {
989
+ const group = (_a = this.idGroupMap) === null || _a === void 0 ? void 0 : _a.get(groupPayload.id || "");
990
+ if (group != null) {
991
+ group.addAccount(account);
992
+ }
993
+ }
925
994
  }
926
995
  /** @internal */
927
996
  ensureGroupsAccountMapsLoaded() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bkper-js",
3
- "version": "2.12.2",
3
+ "version": "2.12.3",
4
4
  "description": "Javascript client for Bkper REST API",
5
5
  "main": "./lib/index.js",
6
6
  "module": "./lib/index.js",