@tasenor/common-node 1.9.16

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 (326) hide show
  1. package/.eslintrc.js +4 -0
  2. package/LICENSE +21 -0
  3. package/dist/tasenor-common-node/src/cli.d.ts +81 -0
  4. package/dist/tasenor-common-node/src/cli.js +242 -0
  5. package/dist/tasenor-common-node/src/cli.js.map +1 -0
  6. package/dist/tasenor-common-node/src/commands/account.d.ts +12 -0
  7. package/dist/tasenor-common-node/src/commands/account.js +58 -0
  8. package/dist/tasenor-common-node/src/commands/account.js.map +1 -0
  9. package/dist/tasenor-common-node/src/commands/balance.d.ts +11 -0
  10. package/dist/tasenor-common-node/src/commands/balance.js +117 -0
  11. package/dist/tasenor-common-node/src/commands/balance.js.map +1 -0
  12. package/dist/tasenor-common-node/src/commands/db.d.ts +14 -0
  13. package/dist/tasenor-common-node/src/commands/db.js +69 -0
  14. package/dist/tasenor-common-node/src/commands/db.js.map +1 -0
  15. package/dist/tasenor-common-node/src/commands/entry.d.ts +13 -0
  16. package/dist/tasenor-common-node/src/commands/entry.js +106 -0
  17. package/dist/tasenor-common-node/src/commands/entry.js.map +1 -0
  18. package/dist/tasenor-common-node/src/commands/import.d.ts +17 -0
  19. package/dist/tasenor-common-node/src/commands/import.js +140 -0
  20. package/dist/tasenor-common-node/src/commands/import.js.map +1 -0
  21. package/dist/tasenor-common-node/src/commands/importer.d.ts +13 -0
  22. package/dist/tasenor-common-node/src/commands/importer.js +71 -0
  23. package/dist/tasenor-common-node/src/commands/importer.js.map +1 -0
  24. package/dist/tasenor-common-node/src/commands/index.d.ts +191 -0
  25. package/dist/tasenor-common-node/src/commands/index.js +482 -0
  26. package/dist/tasenor-common-node/src/commands/index.js.map +1 -0
  27. package/dist/tasenor-common-node/src/commands/period.d.ts +12 -0
  28. package/dist/tasenor-common-node/src/commands/period.js +48 -0
  29. package/dist/tasenor-common-node/src/commands/period.js.map +1 -0
  30. package/dist/tasenor-common-node/src/commands/plugin.d.ts +15 -0
  31. package/dist/tasenor-common-node/src/commands/plugin.js +78 -0
  32. package/dist/tasenor-common-node/src/commands/plugin.js.map +1 -0
  33. package/dist/tasenor-common-node/src/commands/report.d.ts +11 -0
  34. package/dist/tasenor-common-node/src/commands/report.js +96 -0
  35. package/dist/tasenor-common-node/src/commands/report.js.map +1 -0
  36. package/dist/tasenor-common-node/src/commands/settings.d.ts +10 -0
  37. package/dist/tasenor-common-node/src/commands/settings.js +64 -0
  38. package/dist/tasenor-common-node/src/commands/settings.js.map +1 -0
  39. package/dist/tasenor-common-node/src/commands/stock.d.ts +8 -0
  40. package/dist/tasenor-common-node/src/commands/stock.js +73 -0
  41. package/dist/tasenor-common-node/src/commands/stock.js.map +1 -0
  42. package/dist/tasenor-common-node/src/commands/tag.d.ts +13 -0
  43. package/dist/tasenor-common-node/src/commands/tag.js +89 -0
  44. package/dist/tasenor-common-node/src/commands/tag.js.map +1 -0
  45. package/dist/tasenor-common-node/src/commands/tx.d.ts +12 -0
  46. package/dist/tasenor-common-node/src/commands/tx.js +81 -0
  47. package/dist/tasenor-common-node/src/commands/tx.js.map +1 -0
  48. package/dist/tasenor-common-node/src/commands/user.d.ts +12 -0
  49. package/dist/tasenor-common-node/src/commands/user.js +52 -0
  50. package/dist/tasenor-common-node/src/commands/user.js.map +1 -0
  51. package/dist/tasenor-common-node/src/database/BookkeeperImporter.d.ts +77 -0
  52. package/dist/tasenor-common-node/src/database/BookkeeperImporter.js +343 -0
  53. package/dist/tasenor-common-node/src/database/BookkeeperImporter.js.map +1 -0
  54. package/dist/tasenor-common-node/src/database/DB.d.ts +51 -0
  55. package/dist/tasenor-common-node/src/database/DB.js +354 -0
  56. package/dist/tasenor-common-node/src/database/DB.js.map +1 -0
  57. package/dist/tasenor-common-node/src/database/index.d.ts +7 -0
  58. package/dist/tasenor-common-node/src/database/index.js +8 -0
  59. package/dist/tasenor-common-node/src/database/index.js.map +1 -0
  60. package/dist/tasenor-common-node/src/doccer.d.ts +29 -0
  61. package/dist/tasenor-common-node/src/doccer.js +30 -0
  62. package/dist/tasenor-common-node/src/doccer.js.map +1 -0
  63. package/dist/tasenor-common-node/src/error.d.ts +30 -0
  64. package/dist/tasenor-common-node/src/error.js +35 -0
  65. package/dist/tasenor-common-node/src/error.js.map +1 -0
  66. package/dist/tasenor-common-node/src/export/Exporter.d.ts +69 -0
  67. package/dist/tasenor-common-node/src/export/Exporter.js +123 -0
  68. package/dist/tasenor-common-node/src/export/Exporter.js.map +1 -0
  69. package/dist/tasenor-common-node/src/export/TasenorExporter.d.ts +55 -0
  70. package/dist/tasenor-common-node/src/export/TasenorExporter.js +135 -0
  71. package/dist/tasenor-common-node/src/export/TasenorExporter.js.map +1 -0
  72. package/dist/tasenor-common-node/src/export/TilitinExporter.d.ts +71 -0
  73. package/dist/tasenor-common-node/src/export/TilitinExporter.js +290 -0
  74. package/dist/tasenor-common-node/src/export/TilitinExporter.js.map +1 -0
  75. package/dist/tasenor-common-node/src/export/index.d.ts +8 -0
  76. package/dist/tasenor-common-node/src/export/index.js +9 -0
  77. package/dist/tasenor-common-node/src/export/index.js.map +1 -0
  78. package/dist/tasenor-common-node/src/import/TextFileProcessHandler.d.ts +104 -0
  79. package/dist/tasenor-common-node/src/import/TextFileProcessHandler.js +354 -0
  80. package/dist/tasenor-common-node/src/import/TextFileProcessHandler.js.map +1 -0
  81. package/dist/tasenor-common-node/src/import/TransactionImportConnector.d.ts +38 -0
  82. package/dist/tasenor-common-node/src/import/TransactionImportConnector.js +27 -0
  83. package/dist/tasenor-common-node/src/import/TransactionImportConnector.js.map +1 -0
  84. package/dist/tasenor-common-node/src/import/TransactionImportHandler.d.ts +173 -0
  85. package/dist/tasenor-common-node/src/import/TransactionImportHandler.js +733 -0
  86. package/dist/tasenor-common-node/src/import/TransactionImportHandler.js.map +1 -0
  87. package/dist/tasenor-common-node/src/import/TransactionRules.d.ts +238 -0
  88. package/dist/tasenor-common-node/src/import/TransactionRules.js +522 -0
  89. package/dist/tasenor-common-node/src/import/TransactionRules.js.map +1 -0
  90. package/dist/tasenor-common-node/src/import/TransactionUI.d.ts +181 -0
  91. package/dist/tasenor-common-node/src/import/TransactionUI.js +482 -0
  92. package/dist/tasenor-common-node/src/import/TransactionUI.js.map +1 -0
  93. package/dist/tasenor-common-node/src/import/TransferAnalyzer.d.ts +324 -0
  94. package/dist/tasenor-common-node/src/import/TransferAnalyzer.js +1379 -0
  95. package/dist/tasenor-common-node/src/import/TransferAnalyzer.js.map +1 -0
  96. package/dist/tasenor-common-node/src/import/index.d.ts +11 -0
  97. package/dist/tasenor-common-node/src/import/index.js +12 -0
  98. package/dist/tasenor-common-node/src/import/index.js.map +1 -0
  99. package/dist/tasenor-common-node/src/index.d.ts +12 -0
  100. package/dist/tasenor-common-node/src/index.js +13 -0
  101. package/dist/tasenor-common-node/src/index.js.map +1 -0
  102. package/dist/tasenor-common-node/src/net/crypto.d.ts +33 -0
  103. package/dist/tasenor-common-node/src/net/crypto.js +63 -0
  104. package/dist/tasenor-common-node/src/net/crypto.js.map +1 -0
  105. package/dist/tasenor-common-node/src/net/git.d.ts +49 -0
  106. package/dist/tasenor-common-node/src/net/git.js +137 -0
  107. package/dist/tasenor-common-node/src/net/git.js.map +1 -0
  108. package/dist/tasenor-common-node/src/net/index.d.ts +10 -0
  109. package/dist/tasenor-common-node/src/net/index.js +11 -0
  110. package/dist/tasenor-common-node/src/net/index.js.map +1 -0
  111. package/dist/tasenor-common-node/src/net/middleware.d.ts +61 -0
  112. package/dist/tasenor-common-node/src/net/middleware.js +220 -0
  113. package/dist/tasenor-common-node/src/net/middleware.js.map +1 -0
  114. package/dist/tasenor-common-node/src/net/tokens.d.ts +50 -0
  115. package/dist/tasenor-common-node/src/net/tokens.js +141 -0
  116. package/dist/tasenor-common-node/src/net/tokens.js.map +1 -0
  117. package/dist/tasenor-common-node/src/net/vault.d.ts +67 -0
  118. package/dist/tasenor-common-node/src/net/vault.js +145 -0
  119. package/dist/tasenor-common-node/src/net/vault.js.map +1 -0
  120. package/dist/tasenor-common-node/src/plugins/BackendPlugin.d.ts +91 -0
  121. package/dist/tasenor-common-node/src/plugins/BackendPlugin.js +165 -0
  122. package/dist/tasenor-common-node/src/plugins/BackendPlugin.js.map +1 -0
  123. package/dist/tasenor-common-node/src/plugins/DataPlugin.d.ts +13 -0
  124. package/dist/tasenor-common-node/src/plugins/DataPlugin.js +26 -0
  125. package/dist/tasenor-common-node/src/plugins/DataPlugin.js.map +1 -0
  126. package/dist/tasenor-common-node/src/plugins/ImportPlugin.d.ts +188 -0
  127. package/dist/tasenor-common-node/src/plugins/ImportPlugin.js +204 -0
  128. package/dist/tasenor-common-node/src/plugins/ImportPlugin.js.map +1 -0
  129. package/dist/tasenor-common-node/src/plugins/ReportPlugin.d.ts +132 -0
  130. package/dist/tasenor-common-node/src/plugins/ReportPlugin.js +393 -0
  131. package/dist/tasenor-common-node/src/plugins/ReportPlugin.js.map +1 -0
  132. package/dist/tasenor-common-node/src/plugins/SchemePlugin.d.ts +34 -0
  133. package/dist/tasenor-common-node/src/plugins/SchemePlugin.js +47 -0
  134. package/dist/tasenor-common-node/src/plugins/SchemePlugin.js.map +1 -0
  135. package/dist/tasenor-common-node/src/plugins/ServicePlugin.d.ts +80 -0
  136. package/dist/tasenor-common-node/src/plugins/ServicePlugin.js +168 -0
  137. package/dist/tasenor-common-node/src/plugins/ServicePlugin.js.map +1 -0
  138. package/dist/tasenor-common-node/src/plugins/ToolPlugin.d.ts +27 -0
  139. package/dist/tasenor-common-node/src/plugins/ToolPlugin.js +37 -0
  140. package/dist/tasenor-common-node/src/plugins/ToolPlugin.js.map +1 -0
  141. package/dist/tasenor-common-node/src/plugins/index.d.ts +13 -0
  142. package/dist/tasenor-common-node/src/plugins/index.js +14 -0
  143. package/dist/tasenor-common-node/src/plugins/index.js.map +1 -0
  144. package/dist/tasenor-common-node/src/plugins/plugins.d.ts +101 -0
  145. package/dist/tasenor-common-node/src/plugins/plugins.js +292 -0
  146. package/dist/tasenor-common-node/src/plugins/plugins.js.map +1 -0
  147. package/dist/tasenor-common-node/src/process/Process.d.ts +108 -0
  148. package/dist/tasenor-common-node/src/process/Process.js +335 -0
  149. package/dist/tasenor-common-node/src/process/Process.js.map +1 -0
  150. package/dist/tasenor-common-node/src/process/ProcessConnector.d.ts +24 -0
  151. package/dist/tasenor-common-node/src/process/ProcessConnector.js +28 -0
  152. package/dist/tasenor-common-node/src/process/ProcessConnector.js.map +1 -0
  153. package/dist/tasenor-common-node/src/process/ProcessFile.d.ts +69 -0
  154. package/dist/tasenor-common-node/src/process/ProcessFile.js +145 -0
  155. package/dist/tasenor-common-node/src/process/ProcessFile.js.map +1 -0
  156. package/dist/tasenor-common-node/src/process/ProcessHandler.d.ts +60 -0
  157. package/dist/tasenor-common-node/src/process/ProcessHandler.js +73 -0
  158. package/dist/tasenor-common-node/src/process/ProcessHandler.js.map +1 -0
  159. package/dist/tasenor-common-node/src/process/ProcessStep.d.ts +52 -0
  160. package/dist/tasenor-common-node/src/process/ProcessStep.js +78 -0
  161. package/dist/tasenor-common-node/src/process/ProcessStep.js.map +1 -0
  162. package/dist/tasenor-common-node/src/process/ProcessingSystem.d.ts +60 -0
  163. package/dist/tasenor-common-node/src/process/ProcessingSystem.js +182 -0
  164. package/dist/tasenor-common-node/src/process/ProcessingSystem.js.map +1 -0
  165. package/dist/tasenor-common-node/src/process/index.d.ts +11 -0
  166. package/dist/tasenor-common-node/src/process/index.js +12 -0
  167. package/dist/tasenor-common-node/src/process/index.js.map +1 -0
  168. package/dist/tasenor-common-node/src/reports/conversions.d.ts +8 -0
  169. package/dist/tasenor-common-node/src/reports/conversions.js +47 -0
  170. package/dist/tasenor-common-node/src/reports/conversions.js.map +1 -0
  171. package/dist/tasenor-common-node/src/reports/index.d.ts +6 -0
  172. package/dist/tasenor-common-node/src/reports/index.js +7 -0
  173. package/dist/tasenor-common-node/src/reports/index.js.map +1 -0
  174. package/dist/tasenor-common-node/src/server/ISPDemoServer.d.ts +43 -0
  175. package/dist/tasenor-common-node/src/server/ISPDemoServer.js +112 -0
  176. package/dist/tasenor-common-node/src/server/ISPDemoServer.js.map +1 -0
  177. package/dist/tasenor-common-node/src/server/api.d.ts +15 -0
  178. package/dist/tasenor-common-node/src/server/api.js +27 -0
  179. package/dist/tasenor-common-node/src/server/api.js.map +1 -0
  180. package/dist/tasenor-common-node/src/server/index.d.ts +7 -0
  181. package/dist/tasenor-common-node/src/server/index.js +8 -0
  182. package/dist/tasenor-common-node/src/server/index.js.map +1 -0
  183. package/dist/tasenor-common-node/src/server/router.d.ts +5 -0
  184. package/dist/tasenor-common-node/src/server/router.js +37 -0
  185. package/dist/tasenor-common-node/src/server/router.js.map +1 -0
  186. package/dist/tasenor-common-node/src/system.d.ts +27 -0
  187. package/dist/tasenor-common-node/src/system.js +95 -0
  188. package/dist/tasenor-common-node/src/system.js.map +1 -0
  189. package/dist/tasenor-common-node/src/testing/ProcessingSystemMock.d.ts +21 -0
  190. package/dist/tasenor-common-node/src/testing/ProcessingSystemMock.js +33 -0
  191. package/dist/tasenor-common-node/src/testing/ProcessingSystemMock.js.map +1 -0
  192. package/dist/tasenor-common-node/src/testing/UnitTestImportConnector.d.ts +24 -0
  193. package/dist/tasenor-common-node/src/testing/UnitTestImportConnector.js +68 -0
  194. package/dist/tasenor-common-node/src/testing/UnitTestImportConnector.js.map +1 -0
  195. package/dist/tasenor-common-node/src/testing/UnitTester.d.ts +64 -0
  196. package/dist/tasenor-common-node/src/testing/UnitTester.js +199 -0
  197. package/dist/tasenor-common-node/src/testing/UnitTester.js.map +1 -0
  198. package/dist/tasenor-common-node/src/testing/index.d.ts +4 -0
  199. package/dist/tasenor-common-node/src/testing/index.js +5 -0
  200. package/dist/tasenor-common-node/src/testing/index.js.map +1 -0
  201. package/dist/tasenor-common-node/src/testing/test-handlers.d.ts +13 -0
  202. package/dist/tasenor-common-node/src/testing/test-handlers.js +52 -0
  203. package/dist/tasenor-common-node/src/testing/test-handlers.js.map +1 -0
  204. package/dist/tasenor-common-node/tests/TransactionRules.spec.d.ts +1 -0
  205. package/dist/tasenor-common-node/tests/TransactionRules.spec.js +64 -0
  206. package/dist/tasenor-common-node/tests/TransactionRules.spec.js.map +1 -0
  207. package/dist/tasenor-common-node/tests/TransferAnalyzer-account-address.spec.d.ts +1 -0
  208. package/dist/tasenor-common-node/tests/TransferAnalyzer-account-address.spec.js +80 -0
  209. package/dist/tasenor-common-node/tests/TransferAnalyzer-account-address.spec.js.map +1 -0
  210. package/dist/tasenor-common-node/tests/TransferAnalyzer-buying-and-selling.spec.d.ts +1 -0
  211. package/dist/tasenor-common-node/tests/TransferAnalyzer-buying-and-selling.spec.js +342 -0
  212. package/dist/tasenor-common-node/tests/TransferAnalyzer-buying-and-selling.spec.js.map +1 -0
  213. package/dist/tasenor-common-node/tests/TransferAnalyzer-loans.spec.d.ts +1 -0
  214. package/dist/tasenor-common-node/tests/TransferAnalyzer-loans.spec.js +174 -0
  215. package/dist/tasenor-common-node/tests/TransferAnalyzer-loans.spec.js.map +1 -0
  216. package/dist/tasenor-common-node/tests/TransferAnalyzer-multiple-null-amounts.spec.d.ts +1 -0
  217. package/dist/tasenor-common-node/tests/TransferAnalyzer-multiple-null-amounts.spec.js +175 -0
  218. package/dist/tasenor-common-node/tests/TransferAnalyzer-multiple-null-amounts.spec.js.map +1 -0
  219. package/dist/tasenor-common-node/tests/password.spec.d.ts +1 -0
  220. package/dist/tasenor-common-node/tests/password.spec.js +8 -0
  221. package/dist/tasenor-common-node/tests/password.spec.js.map +1 -0
  222. package/dist/tasenor-common-node/tests/tokens.spec.d.ts +1 -0
  223. package/dist/tasenor-common-node/tests/tokens.spec.js +49 -0
  224. package/dist/tasenor-common-node/tests/tokens.spec.js.map +1 -0
  225. package/dist/tasenor-common-node/tests/vault.spec.d.ts +1 -0
  226. package/dist/tasenor-common-node/tests/vault.spec.js +19 -0
  227. package/dist/tasenor-common-node/tests/vault.spec.js.map +1 -0
  228. package/dist/tasenor-common-plugins/src/CoinbaseImport/backend/CoinbaseHandler.d.ts +11 -0
  229. package/dist/tasenor-common-plugins/src/CoinbaseImport/backend/CoinbaseHandler.js +30 -0
  230. package/dist/tasenor-common-plugins/src/CoinbaseImport/backend/CoinbaseHandler.js.map +1 -0
  231. package/dist/tasenor-common-plugins/src/IncomeAndExpenses/backend/index.d.ts +5 -0
  232. package/dist/tasenor-common-plugins/src/IncomeAndExpenses/backend/index.js +350 -0
  233. package/dist/tasenor-common-plugins/src/IncomeAndExpenses/backend/index.js.map +1 -0
  234. package/dist/tasenor-common-plugins/src/KrakenImport/backend/KrakenHandler.d.ts +23 -0
  235. package/dist/tasenor-common-plugins/src/KrakenImport/backend/KrakenHandler.js +83 -0
  236. package/dist/tasenor-common-plugins/src/KrakenImport/backend/KrakenHandler.js.map +1 -0
  237. package/dist/tasenor-common-plugins/src/LynxImport/backend/LynxHandler.d.ts +28 -0
  238. package/dist/tasenor-common-plugins/src/LynxImport/backend/LynxHandler.js +340 -0
  239. package/dist/tasenor-common-plugins/src/LynxImport/backend/LynxHandler.js.map +1 -0
  240. package/dist/tasenor-common-plugins/src/NordeaImport/backend/NordeaHandler.d.ts +11 -0
  241. package/dist/tasenor-common-plugins/src/NordeaImport/backend/NordeaHandler.js +39 -0
  242. package/dist/tasenor-common-plugins/src/NordeaImport/backend/NordeaHandler.js.map +1 -0
  243. package/dist/tasenor-common-plugins/src/NordnetImport/backend/NordnetHandler.d.ts +17 -0
  244. package/dist/tasenor-common-plugins/src/NordnetImport/backend/NordnetHandler.js +66 -0
  245. package/dist/tasenor-common-plugins/src/NordnetImport/backend/NordnetHandler.js.map +1 -0
  246. package/dist/tasenor-common-plugins/src/TITOImport/backend/TITOHandler.d.ts +13 -0
  247. package/dist/tasenor-common-plugins/src/TITOImport/backend/TITOHandler.js +241 -0
  248. package/dist/tasenor-common-plugins/src/TITOImport/backend/TITOHandler.js.map +1 -0
  249. package/jest.config.js +1 -0
  250. package/package.json +62 -0
  251. package/src/cli.ts +267 -0
  252. package/src/commands/account.ts +69 -0
  253. package/src/commands/balance.ts +131 -0
  254. package/src/commands/db.ts +84 -0
  255. package/src/commands/entry.ts +117 -0
  256. package/src/commands/import.ts +160 -0
  257. package/src/commands/importer.ts +84 -0
  258. package/src/commands/index.ts +534 -0
  259. package/src/commands/period.ts +59 -0
  260. package/src/commands/plugin.ts +95 -0
  261. package/src/commands/report.ts +113 -0
  262. package/src/commands/settings.ts +75 -0
  263. package/src/commands/stock.ts +80 -0
  264. package/src/commands/tag.ts +102 -0
  265. package/src/commands/tx.ts +93 -0
  266. package/src/commands/user.ts +65 -0
  267. package/src/database/BookkeeperImporter.ts +358 -0
  268. package/src/database/DB.ts +396 -0
  269. package/src/database/index.ts +7 -0
  270. package/src/doccer.ts +29 -0
  271. package/src/error.ts +32 -0
  272. package/src/export/Exporter.ts +136 -0
  273. package/src/export/TasenorExporter.ts +144 -0
  274. package/src/export/TilitinExporter.ts +302 -0
  275. package/src/export/index.ts +8 -0
  276. package/src/import/TextFileProcessHandler.ts +384 -0
  277. package/src/import/TransactionImportConnector.ts +65 -0
  278. package/src/import/TransactionImportHandler.ts +819 -0
  279. package/src/import/TransactionRules.ts +570 -0
  280. package/src/import/TransactionUI.ts +520 -0
  281. package/src/import/TransferAnalyzer.ts +1450 -0
  282. package/src/import/index.ts +11 -0
  283. package/src/index.ts +12 -0
  284. package/src/net/crypto.ts +69 -0
  285. package/src/net/git.ts +151 -0
  286. package/src/net/index.ts +10 -0
  287. package/src/net/middleware.ts +261 -0
  288. package/src/net/tokens.ts +140 -0
  289. package/src/net/vault.ts +161 -0
  290. package/src/plugins/BackendPlugin.ts +188 -0
  291. package/src/plugins/DataPlugin.ts +29 -0
  292. package/src/plugins/ImportPlugin.ts +211 -0
  293. package/src/plugins/ReportPlugin.ts +443 -0
  294. package/src/plugins/SchemePlugin.ts +56 -0
  295. package/src/plugins/ServicePlugin.ts +188 -0
  296. package/src/plugins/ToolPlugin.ts +44 -0
  297. package/src/plugins/index.ts +13 -0
  298. package/src/plugins/plugins.ts +345 -0
  299. package/src/process/Process.ts +368 -0
  300. package/src/process/ProcessConnector.ts +45 -0
  301. package/src/process/ProcessFile.ts +169 -0
  302. package/src/process/ProcessHandler.ts +94 -0
  303. package/src/process/ProcessStep.ts +100 -0
  304. package/src/process/ProcessingSystem.ts +202 -0
  305. package/src/process/index.ts +11 -0
  306. package/src/reports/conversions.ts +52 -0
  307. package/src/reports/index.ts +6 -0
  308. package/src/server/ISPDemoServer.ts +122 -0
  309. package/src/server/api.ts +37 -0
  310. package/src/server/index.ts +7 -0
  311. package/src/server/router.ts +60 -0
  312. package/src/system.ts +96 -0
  313. package/src/testing/ProcessingSystemMock.ts +45 -0
  314. package/src/testing/UnitTestImportConnector.ts +86 -0
  315. package/src/testing/UnitTester.ts +231 -0
  316. package/src/testing/index.ts +4 -0
  317. package/src/testing/test-handlers.ts +55 -0
  318. package/tests/TransactionRules.spec.ts +73 -0
  319. package/tests/TransferAnalyzer-account-address.spec.ts +87 -0
  320. package/tests/TransferAnalyzer-buying-and-selling.spec.ts +354 -0
  321. package/tests/TransferAnalyzer-loans.spec.ts +197 -0
  322. package/tests/TransferAnalyzer-multiple-null-amounts.spec.ts +181 -0
  323. package/tests/password.spec.ts +8 -0
  324. package/tests/tokens.spec.ts +52 -0
  325. package/tests/vault.spec.ts +20 -0
  326. package/tsconfig.json +13 -0
@@ -0,0 +1,443 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ import fs from 'fs'
3
+ import { data2csv } from '..'
4
+ import dayjs from 'dayjs'
5
+ import quarterOfYear from 'dayjs/plugin/quarterOfYear'
6
+ import { ReportOptions, ReportID, ReportFlagName, ReportItem, ReportQueryParams, ReportLine, AccountNumber, ReportColumnDefinition, PeriodModel, ReportFormat, Language } from '@dataplug/tasenor-common'
7
+ import { BackendPlugin } from './BackendPlugin'
8
+
9
+ dayjs.extend(quarterOfYear)
10
+
11
+ /**
12
+ * A plugin providing one or more reports.
13
+ */
14
+ export class ReportPlugin extends BackendPlugin {
15
+
16
+ private formats: ReportID[]
17
+ // Is set, allow this report only on DBs having those accounting schemes.
18
+ protected schemes: Set<string> | undefined
19
+
20
+ constructor(...formats: ReportID[]) {
21
+ super()
22
+ this.formats = formats
23
+ this.schemes = undefined
24
+ }
25
+
26
+ /**
27
+ * Read in report struture file.
28
+ */
29
+ getReportStructure(id: ReportID, lang: Language) : ReportFormat | undefined {
30
+ const path = this.filePath(`${id}-${lang}.tsv`)
31
+ if (fs.existsSync(path)) {
32
+ return fs.readFileSync(path).toString('utf-8') as ReportFormat
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Get the list of supported languages.
38
+ */
39
+ getLanguages(): Language[] {
40
+ return []
41
+ }
42
+
43
+ /**
44
+ * Check if the given report is provided by this plugin.
45
+ * @param id
46
+ */
47
+ hasReport(id) {
48
+ return this.formats.includes(id)
49
+ }
50
+
51
+ /**
52
+ * Get the list of report IDs.
53
+ */
54
+ getFormats(scheme: string|undefined = undefined): ReportID[] {
55
+ if (this.schemes === undefined || scheme === undefined || this.schemes.has(scheme)) {
56
+ return this.formats
57
+ }
58
+ return []
59
+ }
60
+
61
+ /**
62
+ * Return UI option definitions for the given report.
63
+ * @param id
64
+ */
65
+ getReportOptions(id): ReportOptions {
66
+ return {}
67
+ }
68
+
69
+ /**
70
+ * Convert time stamp or Date to date string YYYY-MM-DD.
71
+ * @param {Number} timestamp
72
+ */
73
+ time2str(timestamp) {
74
+ if (timestamp === null) {
75
+ return null
76
+ }
77
+ if (timestamp instanceof Date) {
78
+ timestamp = timestamp.toISOString()
79
+ }
80
+ return timestamp.substr(0, 10)
81
+ }
82
+
83
+ /**
84
+ * Construct rendering information from report flags
85
+ * @param flags
86
+ * @returns
87
+ */
88
+ flags2item(flags: ReportFlagName[]) {
89
+ const item: ReportItem = {}
90
+ flags.forEach(flag => {
91
+ if (flag) {
92
+ switch (flag) {
93
+ case 'NEW_PAGE':
94
+ break
95
+ case 'BREAK':
96
+ item.break = true
97
+ break
98
+ case 'BOLD':
99
+ item.bold = true
100
+ break
101
+ case 'ITALIC':
102
+ item.italic = true
103
+ break
104
+ case 'DETAILS':
105
+ item.accountDetails = true
106
+ break
107
+ case 'HIDE_TOTAL':
108
+ item.hideTotal = true
109
+ break
110
+ case 'REQUIRED':
111
+ item.required = true
112
+ break
113
+ default:
114
+ throw new Error(`Cannot recognize report format flag '${flag}'.`)
115
+ }
116
+ }
117
+ })
118
+ return item
119
+ }
120
+
121
+ /**
122
+ * Construct column definitions for the report.
123
+ * @param id
124
+ * @param entries
125
+ * @param options
126
+ */
127
+ async getColumns(id, entries, options: ReportOptions, settings): Promise<ReportColumnDefinition[]> {
128
+ if (!options.periods) {
129
+ throw new Error(`Need periods to define columns ${JSON.stringify(options)}`)
130
+ }
131
+ const columns: ReportColumnDefinition[] = options.periods.map((period) => {
132
+ return {
133
+ type: 'numeric',
134
+ name: 'period' + period.id,
135
+ title: this.columnTitle(id, period, options)
136
+ }
137
+ })
138
+ columns.unshift({
139
+ name: 'title',
140
+ title: '',
141
+ type: 'name'
142
+ })
143
+ return columns
144
+ }
145
+
146
+ /**
147
+ * Construct a title for a column.
148
+ * @param id
149
+ * @param period
150
+ * @param options
151
+ */
152
+ columnTitle(id: ReportID, period: PeriodModel, options: ReportOptions): string {
153
+ throw new Error(`Report plugin ${this.constructor.name} does not implement columnTitle().`)
154
+ }
155
+
156
+ /**
157
+ * Force some options, if needed.
158
+ * @returns
159
+ */
160
+ forceOptions(options) {
161
+ return {
162
+ negateAssetAndProfit: false, // A flag to multiply by -1 entries from asset and profit types of accounts.
163
+ addPreviousPeriod: false // A flag to define if the previous period should be displayed for comparison.
164
+ }
165
+ }
166
+
167
+ /**
168
+ * Construct a SQL for the report query.
169
+ * @param db
170
+ * @param options
171
+ * @returns A knex query prepared.
172
+ */
173
+ async constructSqlQuery(db, options, settings) {
174
+ // Construct value negator.
175
+ let negateSql = '(CASE debit WHEN true THEN 1 ELSE -1 END)'
176
+ if (options.negateAssetAndProfit) {
177
+ negateSql += " * (CASE WHEN account.type IN ('ASSET', 'PROFIT') THEN 1 ELSE -1 END)"
178
+ }
179
+
180
+ // Find periods.
181
+ const periodIds = [options.periodId]
182
+ if (options.addPreviousPeriod) {
183
+ const recentPeriods = await db.select('*').from('period').where('id', '<=', options.periodId).orderBy('end_date', 'desc').limit(2)
184
+ if (recentPeriods.length > 1) {
185
+ periodIds.push(recentPeriods[1].id)
186
+ }
187
+ options.periods = recentPeriods // Save periods for further reference.
188
+ }
189
+
190
+ // Build a query basics.
191
+ let sqlQuery = db.select(
192
+ 'document.period_id AS periodId',
193
+ 'document.number AS documentId',
194
+ 'document.date',
195
+ 'account.name',
196
+ 'account.type',
197
+ 'account.number',
198
+ db.raw(`CAST(ROUND(${negateSql} * entry.amount * 100) AS BIGINT) AS amount`),
199
+ 'entry.description'
200
+ )
201
+ .from('entry')
202
+ .leftJoin('account', 'account.id', 'entry.account_id')
203
+ .leftJoin('document', 'document.id', 'entry.document_id')
204
+ .whereIn('document.period_id', periodIds)
205
+
206
+ // Limit by account, if given.
207
+ if (options.accountId) {
208
+ sqlQuery = sqlQuery.andWhere('account.id', '=', options.accountId)
209
+ }
210
+
211
+ // Tune ordering.
212
+ sqlQuery = (sqlQuery
213
+ .orderBy('document.date')
214
+ .orderBy('document.number')
215
+ .orderBy('document.id')
216
+ .orderBy('entry.row_number'))
217
+
218
+ return sqlQuery
219
+ }
220
+
221
+ /**
222
+ * Construct a report data for the report.
223
+ * @param db
224
+ * @param id
225
+ * @param options
226
+ *
227
+ * Resulting entries on data is an array of objects containing:
228
+ * * `tab` Zero originating indentation number.
229
+ * * `error` If true, this row has an error.
230
+ * * `required` If true, this is always shown.
231
+ * * `hideTotal` if true, do not show total.
232
+ * * `bold` if true, show in bold.
233
+ * * `italic` if true, show in italic.
234
+ * * `bigger` if true, show in bigger font.
235
+ * * `fullWidth` if set, the content in column index defined here is expanded to cover all columns.
236
+ * * `useRemainingColumns` if set, extend this column index to use all the rest columns in the row.
237
+ * * `accountDetails` if true, after this are summarized accounts under this entry.
238
+ * * `isAccount` if true, this is an account entry.
239
+ * * `needLocalization` if set, value should be localized, i.e. translated via Localization component in ui.
240
+ * * `name` Title of the entry.
241
+ * * `number` Account number if the entry is an account.
242
+ * * `amounts` An object with entry for each column mapping name of the columnt to the value to display.
243
+ */
244
+ async renderReport(db, id, options: ReportQueryParams = {}) {
245
+
246
+ // Add report forced options.
247
+ Object.assign(options, this.forceOptions(options))
248
+
249
+ // Collect settings.
250
+ const settings = (await db('settings').where('name', 'like', `${this.code}.%`).orWhere({ name: 'companyName' }).orWhere({ name: 'companyCode' })).reduce((prev, cur) => ({ ...prev, [cur.name]: cur.value }), {})
251
+
252
+ // Find tags.
253
+ const settingName = `${this.code}.tagTypes`
254
+ if (options.byTags && settings[settingName]) {
255
+ const tags = await db('tags').select('id', 'tag', 'name', 'type', 'order').from('tags').whereIn('type', settings[settingName]).orderBy('order')
256
+ settings.tags = tags
257
+ } else {
258
+ settings.tags = []
259
+ }
260
+
261
+ // Find the formatting text description, if it exist.
262
+ options.format = this.getReportStructure(id, options.lang || 'en')
263
+
264
+ // Prepare query.
265
+ const q = await this.constructSqlQuery(db, options, settings)
266
+ let entries = await q
267
+
268
+ // Process big ints.
269
+ for (const entry of entries) {
270
+ entry.amount = parseInt(entry.amount)
271
+ }
272
+
273
+ // Apply query filtering.
274
+ entries = this.doFiltering(id, entries, options, settings)
275
+
276
+ // We have now relevant entries collected. Use plugin features next.
277
+ const columns: ReportColumnDefinition[] = await this.getColumns(id, entries, options as ReportOptions, settings)
278
+ let data = this.preProcess(id, entries, options, settings, columns)
279
+ data = this.postProcess(id, data, options, settings, columns)
280
+ const report = {
281
+ format: id,
282
+ columns,
283
+ meta: {
284
+ businessName: settings.companyName,
285
+ businessId: settings.companyCode
286
+ },
287
+ data
288
+ }
289
+
290
+ // Do the final conversion, if necessary.
291
+ if (options.csv) {
292
+ return data2csv(report, options)
293
+ }
294
+
295
+ return report
296
+ }
297
+
298
+ /**
299
+ * Filter out entries not matching to the report selected parameters.
300
+ * @param id
301
+ * @param entries
302
+ * @param options
303
+ * @param settings
304
+ */
305
+ doFiltering(id, entries, options, settings) {
306
+ let filter = (entry) => true
307
+
308
+ if (options.quarter1) {
309
+ filter = (entry) => dayjs(entry.date).quarter() <= 1
310
+ } if (options.quarter2) {
311
+ filter = (entry) => dayjs(entry.date).quarter() <= 2
312
+ } if (options.quarter3) {
313
+ filter = (entry) => dayjs(entry.date).quarter() <= 3
314
+ }
315
+
316
+ return entries.filter(filter)
317
+ }
318
+
319
+ /**
320
+ * This function converts the list of relevant entries to the column report data.
321
+ * @param id
322
+ * @param entries
323
+ * @param options
324
+ * @param columns
325
+ */
326
+ preProcess(id, entries, options, settings, columns) {
327
+ throw new Error(`Report plugin ${this.constructor.name} does not implement preProcess().`)
328
+ }
329
+
330
+ /**
331
+ * Do post processing for report data before sending it.
332
+ * @param id Report type.
333
+ * @param data Calculated report data
334
+ * @param options Report options.
335
+ * @param settings System settings.
336
+ * @param columns Column definitions.
337
+ * @returns
338
+ */
339
+ postProcess(id, data, options, settings, columns) {
340
+ return data
341
+ }
342
+
343
+ /**
344
+ * A helper to combine final report from pre-processed material for reports using text description.
345
+ * @param accountNumbers A set of all account numbers found.
346
+ * @param accountNames A mapping from account numbers to their names.
347
+ * @param columnNames A list of column names.
348
+ * @param format A text description of the report.
349
+ * @param totals A mapping from account numbers their total balance.
350
+ * @returns
351
+ */
352
+ parseAndCombineReport(accountNumbers: AccountNumber[], accountNames, columns, format, totals) {
353
+ const columnNames = columns.filter((col) => col.type === 'numeric').map((col) => col.name)
354
+
355
+ // Parse report and construct format.
356
+ const allAccounts: AccountNumber[] = Array.from(accountNumbers).sort()
357
+ const ret: ReportLine[] = []
358
+ format.split('\n').forEach((line) => {
359
+ if (/^#/.test(line)) {
360
+ return
361
+ }
362
+ let [numbers, text, flags] = line.split('\t')
363
+ numbers = numbers.split(' ')
364
+ flags = flags ? new Set(flags.trim().split(/\s+/)) : new Set()
365
+ const tab = text ? text.replace(/^(_*).*/, '$1').length : 0
366
+ text = text ? text.replace(/^_+/, '') : ''
367
+
368
+ if (flags.has('NEW_PAGE')) {
369
+ ret.push({ pageBreak: true })
370
+ return
371
+ }
372
+
373
+ if (flags.has('BREAK')) {
374
+ ret.push({ paragraphBreak: true })
375
+ return
376
+ }
377
+
378
+ // Split the line and reset variables.
379
+ const amounts: Record<string, number | null> = {}
380
+ columnNames.forEach((column) => (amounts[column] = null))
381
+ let unused = true
382
+ const item: ReportItem = { tab, ...this.flags2item(flags) }
383
+
384
+ // Collect all totals inside any of the account number ranges.
385
+ for (let i = 0; i < numbers.length; i++) {
386
+ const parts = numbers[i].split('-')
387
+ const from = parts[0]
388
+ const to = parts[1]
389
+ columnNames.forEach((column) => {
390
+ allAccounts.forEach((number) => {
391
+ if (number >= from && number < to) {
392
+ unused = false
393
+ if (totals[column][number] !== undefined) {
394
+ amounts[column] += totals[column][number]
395
+ }
396
+ }
397
+ })
398
+ })
399
+ }
400
+
401
+ // If we actually show details we can skip this entry and fill details below.
402
+ if (!item.accountDetails) {
403
+ if (item.required || !unused) {
404
+ item.name = text
405
+ item.amounts = amounts
406
+ ret.push(item)
407
+ }
408
+ }
409
+
410
+ // Fill in account details for the entries wanting it.
411
+ if (item.accountDetails) {
412
+ for (let i = 0; i < numbers.length; i++) {
413
+ const parts = numbers[i].split('-')
414
+ const from = parts[0]
415
+ const to = parts[1]
416
+ allAccounts.forEach((number) => {
417
+ if (number >= from && number < to) {
418
+ const item = { tab, ...this.flags2item(flags) }
419
+ item.isAccount = true
420
+ delete item.accountDetails
421
+ item.name = accountNames[number]
422
+ item.number = number
423
+ item.amounts = {}
424
+ columnNames.forEach((column) => {
425
+ if (!item.amounts) {
426
+ item.amounts = {}
427
+ }
428
+ if (totals[column][number] === undefined) {
429
+ item.amounts[column] = null
430
+ } else {
431
+ item.amounts[column] = totals[column][number] + 0
432
+ }
433
+ })
434
+ ret.push(item)
435
+ }
436
+ })
437
+ }
438
+ }
439
+ })
440
+
441
+ return ret
442
+ }
443
+ }
@@ -0,0 +1,56 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ import { Currency, Language, SchemeName, TsvFilePath } from '@dataplug/tasenor-common'
3
+ import { BackendPlugin } from './BackendPlugin'
4
+
5
+ /**
6
+ * A plugin providing one or more accounting schemes.
7
+ */
8
+ export class SchemePlugin extends BackendPlugin {
9
+
10
+ private schemes: Set<SchemeName>
11
+
12
+ constructor(...schemes: SchemeName[]) {
13
+ super()
14
+ this.schemes = new Set(schemes)
15
+ }
16
+
17
+ /**
18
+ * Check if this plugin has the given scheme.
19
+ * @param code
20
+ * @returns
21
+ */
22
+ hasScheme(code): boolean {
23
+ return this.schemes.has(code)
24
+ }
25
+
26
+ /**
27
+ * Get the paths to the accounting scheme .tsv files by its code name.
28
+ * @param code
29
+ */
30
+ getSchemePaths(code, languae): TsvFilePath[] {
31
+ throw new Error(`A class ${this.constructor.name} does not implement getScheme().`)
32
+ }
33
+
34
+ /**
35
+ * Get the default settings for the new database.
36
+ * @param code
37
+ * @returns
38
+ */
39
+ getSchemeDefaults(code): Record<string, unknown> {
40
+ return {}
41
+ }
42
+
43
+ /**
44
+ * Supported currencies.
45
+ */
46
+ supportedCurrencies(): Currency[] {
47
+ return []
48
+ }
49
+
50
+ /**
51
+ * Supported languages.
52
+ */
53
+ supportedLanguages(): Language[] {
54
+ return []
55
+ }
56
+ }
@@ -0,0 +1,188 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ import axios from 'axios'
3
+ import { log, note, error, PluginService, PluginServiceResponse, waitPromise } from '@dataplug/tasenor-common'
4
+ import { BackendPlugin } from './BackendPlugin'
5
+ import { KnexDatabase } from '..'
6
+
7
+ export type ServicePluginRequestOptions = {
8
+ rateLimitDelay?: number
9
+ }
10
+
11
+ /**
12
+ * An API end point provider.
13
+ */
14
+ export class ServicePlugin extends BackendPlugin {
15
+
16
+ private services: PluginService[]
17
+
18
+ constructor(...services) {
19
+ super()
20
+ this.services = services
21
+ }
22
+
23
+ getServices(): PluginService[] {
24
+ return this.services
25
+ }
26
+
27
+ /**
28
+ * A query executor called by the back end for API request.
29
+ * @param best The currently best solution found.
30
+ * @param db Knex database.
31
+ * @param service Name of the service to called.
32
+ * @param query Query parameters.
33
+ * This calls the actual query function, handles errors and finally modifies `best` if found a solution.
34
+ */
35
+ async executeQuery(best: unknown, db: KnexDatabase, service: PluginService, query: Record<string, unknown>) {
36
+ const settings: Record<string, unknown> = {}
37
+ for (const setting of await db('settings').select('*').where('name', 'like', `${this.code}.%`)) {
38
+ const [, name] = setting.name.split('.')
39
+ settings[name] = setting.value
40
+ }
41
+
42
+ // First check if the current answer is adequate.
43
+ if (this.isAdequate(best)) {
44
+ return
45
+ }
46
+ // Then run the query and catch errors.
47
+ let result
48
+ try {
49
+ result = await this.query(db, settings, service, query)
50
+ } catch (err) {
51
+ error(`Exception when handling service ${service} query ${JSON.stringify(query)}: ${err}`)
52
+ result = {
53
+ status: 500,
54
+ message: `Execution of service ${service} query failed on plugin ${this.constructor.name}.`
55
+ }
56
+ }
57
+ // Combine result.
58
+ this.addResult(best, result)
59
+ }
60
+
61
+ /**
62
+ * Perform the actual query.
63
+ *
64
+ * @param db Knex database.
65
+ * @param service Name of the service to called.
66
+ * @param query Query parameters.
67
+ */
68
+ async query(db: KnexDatabase, settings: Record<string, unknown>, service: PluginService, query: unknown) {
69
+ throw new Error(`A service plugin ${this.constructor.name} does not implement query().`)
70
+ }
71
+
72
+ /**
73
+ * Combine result of the service query.
74
+ *
75
+ * @param old Currently found solution.
76
+ * @param latest The solution given by this plugin.
77
+ *
78
+ * By default, any 2xx status result will override the current result.
79
+ * Any error result will override initial 404 result.
80
+ * Otherwise the latest is ignored.
81
+ */
82
+ addResult(old, latest) {
83
+ if ((latest.status >= 200 && latest.status < 300) ||
84
+ (old.status === 404 && old.message === 'No handlers found.')) {
85
+ delete old.message
86
+ Object.assign(old, latest)
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Check if the current solution is sufficient.
92
+ * By default, any status 2xx is sufficient.
93
+ */
94
+ isAdequate(solution) {
95
+ return solution.status >= 200 && solution.status < 300
96
+ }
97
+
98
+ /**
99
+ * Execute query to the third party service,
100
+ * @param service
101
+ * @param method
102
+ * @param url
103
+ * @param params
104
+ * @returns Result body.
105
+ */
106
+ async request(service, method, url, params, headers = {}): Promise<PluginServiceResponse> {
107
+ if (method !== 'GET') {
108
+ throw new Error('Only GET method currently supported in plugin requests.')
109
+ }
110
+ note(`Service ${service} request ${method} ${url}`)
111
+ return new Promise((resolve, reject) => {
112
+ axios.request({ method, url, params, headers })
113
+ .then(response => {
114
+ log(`Request ${method} ${url}: HTTP ${response.status}`)
115
+ resolve({
116
+ status: response.status,
117
+ data: response.data
118
+ })
119
+ })
120
+ .catch(err => {
121
+ const status = err.response ? err.response.status : 500
122
+ const message = err.response && err.response.data && err.response.data.message ? err.response.data.message : `${err}`
123
+ error(`Request ${method} ${url} failed: HTTP ${status} ${message}`)
124
+ resolve({
125
+ status,
126
+ message
127
+ })
128
+ })
129
+ })
130
+ }
131
+
132
+ /**
133
+ * Pick meaningful keys unique from the headers for using as a key, whe storing result to teh cache.
134
+ * @param service
135
+ * @param header
136
+ * By default, no header is used as cache key.
137
+ */
138
+ cacheHeadersKey(service, header) {
139
+ return {}
140
+ }
141
+
142
+ /**
143
+ * Pick meaningful keys unique from the query parameters for using as a key, whe storing result to teh cache.
144
+ * @param service
145
+ * @param params
146
+ * By default, all parameters are used as cache key.
147
+ */
148
+ cacheParamsKey(service, params) {
149
+ return params
150
+ }
151
+
152
+ /**
153
+ * Execute query to the third party service,
154
+ * @param db
155
+ * @param service
156
+ * @param method
157
+ * @param url
158
+ * @param params
159
+ * @returns Result body.
160
+ */
161
+ async cachedRequest(db: KnexDatabase | null, service, method, url, params, headers = {}, options: ServicePluginRequestOptions = {}) {
162
+
163
+ // Get cache keys.
164
+ const keyParams = this.cacheParamsKey(service, params)
165
+ const keyHeaders = this.cacheHeadersKey(service, headers)
166
+
167
+ // Check if cached.
168
+ const cached = db ? await db('cached_requests').select('status', 'result').where({ method, url, query: keyParams, headers: keyHeaders }).first() : null
169
+ if (cached) {
170
+ if (cached.status >= 200 && cached.status < 300) {
171
+ log(`Using cached service ${service} result for ${method} ${url}`)
172
+ return cached.result
173
+ }
174
+ }
175
+
176
+ // Add delay if needed.
177
+ if (options.rateLimitDelay) {
178
+ await waitPromise(options.rateLimitDelay)
179
+ }
180
+
181
+ // Do the request and cache the result.
182
+ const result = await this.request(service, method, url, params, headers)
183
+ if (db) {
184
+ await db('cached_requests').insert({ method, url, query: keyParams, headers: keyHeaders, status: result.status || null, result })
185
+ }
186
+ return result
187
+ }
188
+ }