@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.
- package/.eslintrc.js +4 -0
- package/LICENSE +21 -0
- package/dist/tasenor-common-node/src/cli.d.ts +81 -0
- package/dist/tasenor-common-node/src/cli.js +242 -0
- package/dist/tasenor-common-node/src/cli.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/account.d.ts +12 -0
- package/dist/tasenor-common-node/src/commands/account.js +58 -0
- package/dist/tasenor-common-node/src/commands/account.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/balance.d.ts +11 -0
- package/dist/tasenor-common-node/src/commands/balance.js +117 -0
- package/dist/tasenor-common-node/src/commands/balance.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/db.d.ts +14 -0
- package/dist/tasenor-common-node/src/commands/db.js +69 -0
- package/dist/tasenor-common-node/src/commands/db.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/entry.d.ts +13 -0
- package/dist/tasenor-common-node/src/commands/entry.js +106 -0
- package/dist/tasenor-common-node/src/commands/entry.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/import.d.ts +17 -0
- package/dist/tasenor-common-node/src/commands/import.js +140 -0
- package/dist/tasenor-common-node/src/commands/import.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/importer.d.ts +13 -0
- package/dist/tasenor-common-node/src/commands/importer.js +71 -0
- package/dist/tasenor-common-node/src/commands/importer.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/index.d.ts +191 -0
- package/dist/tasenor-common-node/src/commands/index.js +482 -0
- package/dist/tasenor-common-node/src/commands/index.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/period.d.ts +12 -0
- package/dist/tasenor-common-node/src/commands/period.js +48 -0
- package/dist/tasenor-common-node/src/commands/period.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/plugin.d.ts +15 -0
- package/dist/tasenor-common-node/src/commands/plugin.js +78 -0
- package/dist/tasenor-common-node/src/commands/plugin.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/report.d.ts +11 -0
- package/dist/tasenor-common-node/src/commands/report.js +96 -0
- package/dist/tasenor-common-node/src/commands/report.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/settings.d.ts +10 -0
- package/dist/tasenor-common-node/src/commands/settings.js +64 -0
- package/dist/tasenor-common-node/src/commands/settings.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/stock.d.ts +8 -0
- package/dist/tasenor-common-node/src/commands/stock.js +73 -0
- package/dist/tasenor-common-node/src/commands/stock.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/tag.d.ts +13 -0
- package/dist/tasenor-common-node/src/commands/tag.js +89 -0
- package/dist/tasenor-common-node/src/commands/tag.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/tx.d.ts +12 -0
- package/dist/tasenor-common-node/src/commands/tx.js +81 -0
- package/dist/tasenor-common-node/src/commands/tx.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/user.d.ts +12 -0
- package/dist/tasenor-common-node/src/commands/user.js +52 -0
- package/dist/tasenor-common-node/src/commands/user.js.map +1 -0
- package/dist/tasenor-common-node/src/database/BookkeeperImporter.d.ts +77 -0
- package/dist/tasenor-common-node/src/database/BookkeeperImporter.js +343 -0
- package/dist/tasenor-common-node/src/database/BookkeeperImporter.js.map +1 -0
- package/dist/tasenor-common-node/src/database/DB.d.ts +51 -0
- package/dist/tasenor-common-node/src/database/DB.js +354 -0
- package/dist/tasenor-common-node/src/database/DB.js.map +1 -0
- package/dist/tasenor-common-node/src/database/index.d.ts +7 -0
- package/dist/tasenor-common-node/src/database/index.js +8 -0
- package/dist/tasenor-common-node/src/database/index.js.map +1 -0
- package/dist/tasenor-common-node/src/doccer.d.ts +29 -0
- package/dist/tasenor-common-node/src/doccer.js +30 -0
- package/dist/tasenor-common-node/src/doccer.js.map +1 -0
- package/dist/tasenor-common-node/src/error.d.ts +30 -0
- package/dist/tasenor-common-node/src/error.js +35 -0
- package/dist/tasenor-common-node/src/error.js.map +1 -0
- package/dist/tasenor-common-node/src/export/Exporter.d.ts +69 -0
- package/dist/tasenor-common-node/src/export/Exporter.js +123 -0
- package/dist/tasenor-common-node/src/export/Exporter.js.map +1 -0
- package/dist/tasenor-common-node/src/export/TasenorExporter.d.ts +55 -0
- package/dist/tasenor-common-node/src/export/TasenorExporter.js +135 -0
- package/dist/tasenor-common-node/src/export/TasenorExporter.js.map +1 -0
- package/dist/tasenor-common-node/src/export/TilitinExporter.d.ts +71 -0
- package/dist/tasenor-common-node/src/export/TilitinExporter.js +290 -0
- package/dist/tasenor-common-node/src/export/TilitinExporter.js.map +1 -0
- package/dist/tasenor-common-node/src/export/index.d.ts +8 -0
- package/dist/tasenor-common-node/src/export/index.js +9 -0
- package/dist/tasenor-common-node/src/export/index.js.map +1 -0
- package/dist/tasenor-common-node/src/import/TextFileProcessHandler.d.ts +104 -0
- package/dist/tasenor-common-node/src/import/TextFileProcessHandler.js +354 -0
- package/dist/tasenor-common-node/src/import/TextFileProcessHandler.js.map +1 -0
- package/dist/tasenor-common-node/src/import/TransactionImportConnector.d.ts +38 -0
- package/dist/tasenor-common-node/src/import/TransactionImportConnector.js +27 -0
- package/dist/tasenor-common-node/src/import/TransactionImportConnector.js.map +1 -0
- package/dist/tasenor-common-node/src/import/TransactionImportHandler.d.ts +173 -0
- package/dist/tasenor-common-node/src/import/TransactionImportHandler.js +733 -0
- package/dist/tasenor-common-node/src/import/TransactionImportHandler.js.map +1 -0
- package/dist/tasenor-common-node/src/import/TransactionRules.d.ts +238 -0
- package/dist/tasenor-common-node/src/import/TransactionRules.js +522 -0
- package/dist/tasenor-common-node/src/import/TransactionRules.js.map +1 -0
- package/dist/tasenor-common-node/src/import/TransactionUI.d.ts +181 -0
- package/dist/tasenor-common-node/src/import/TransactionUI.js +482 -0
- package/dist/tasenor-common-node/src/import/TransactionUI.js.map +1 -0
- package/dist/tasenor-common-node/src/import/TransferAnalyzer.d.ts +324 -0
- package/dist/tasenor-common-node/src/import/TransferAnalyzer.js +1379 -0
- package/dist/tasenor-common-node/src/import/TransferAnalyzer.js.map +1 -0
- package/dist/tasenor-common-node/src/import/index.d.ts +11 -0
- package/dist/tasenor-common-node/src/import/index.js +12 -0
- package/dist/tasenor-common-node/src/import/index.js.map +1 -0
- package/dist/tasenor-common-node/src/index.d.ts +12 -0
- package/dist/tasenor-common-node/src/index.js +13 -0
- package/dist/tasenor-common-node/src/index.js.map +1 -0
- package/dist/tasenor-common-node/src/net/crypto.d.ts +33 -0
- package/dist/tasenor-common-node/src/net/crypto.js +63 -0
- package/dist/tasenor-common-node/src/net/crypto.js.map +1 -0
- package/dist/tasenor-common-node/src/net/git.d.ts +49 -0
- package/dist/tasenor-common-node/src/net/git.js +137 -0
- package/dist/tasenor-common-node/src/net/git.js.map +1 -0
- package/dist/tasenor-common-node/src/net/index.d.ts +10 -0
- package/dist/tasenor-common-node/src/net/index.js +11 -0
- package/dist/tasenor-common-node/src/net/index.js.map +1 -0
- package/dist/tasenor-common-node/src/net/middleware.d.ts +61 -0
- package/dist/tasenor-common-node/src/net/middleware.js +220 -0
- package/dist/tasenor-common-node/src/net/middleware.js.map +1 -0
- package/dist/tasenor-common-node/src/net/tokens.d.ts +50 -0
- package/dist/tasenor-common-node/src/net/tokens.js +141 -0
- package/dist/tasenor-common-node/src/net/tokens.js.map +1 -0
- package/dist/tasenor-common-node/src/net/vault.d.ts +67 -0
- package/dist/tasenor-common-node/src/net/vault.js +145 -0
- package/dist/tasenor-common-node/src/net/vault.js.map +1 -0
- package/dist/tasenor-common-node/src/plugins/BackendPlugin.d.ts +91 -0
- package/dist/tasenor-common-node/src/plugins/BackendPlugin.js +165 -0
- package/dist/tasenor-common-node/src/plugins/BackendPlugin.js.map +1 -0
- package/dist/tasenor-common-node/src/plugins/DataPlugin.d.ts +13 -0
- package/dist/tasenor-common-node/src/plugins/DataPlugin.js +26 -0
- package/dist/tasenor-common-node/src/plugins/DataPlugin.js.map +1 -0
- package/dist/tasenor-common-node/src/plugins/ImportPlugin.d.ts +188 -0
- package/dist/tasenor-common-node/src/plugins/ImportPlugin.js +204 -0
- package/dist/tasenor-common-node/src/plugins/ImportPlugin.js.map +1 -0
- package/dist/tasenor-common-node/src/plugins/ReportPlugin.d.ts +132 -0
- package/dist/tasenor-common-node/src/plugins/ReportPlugin.js +393 -0
- package/dist/tasenor-common-node/src/plugins/ReportPlugin.js.map +1 -0
- package/dist/tasenor-common-node/src/plugins/SchemePlugin.d.ts +34 -0
- package/dist/tasenor-common-node/src/plugins/SchemePlugin.js +47 -0
- package/dist/tasenor-common-node/src/plugins/SchemePlugin.js.map +1 -0
- package/dist/tasenor-common-node/src/plugins/ServicePlugin.d.ts +80 -0
- package/dist/tasenor-common-node/src/plugins/ServicePlugin.js +168 -0
- package/dist/tasenor-common-node/src/plugins/ServicePlugin.js.map +1 -0
- package/dist/tasenor-common-node/src/plugins/ToolPlugin.d.ts +27 -0
- package/dist/tasenor-common-node/src/plugins/ToolPlugin.js +37 -0
- package/dist/tasenor-common-node/src/plugins/ToolPlugin.js.map +1 -0
- package/dist/tasenor-common-node/src/plugins/index.d.ts +13 -0
- package/dist/tasenor-common-node/src/plugins/index.js +14 -0
- package/dist/tasenor-common-node/src/plugins/index.js.map +1 -0
- package/dist/tasenor-common-node/src/plugins/plugins.d.ts +101 -0
- package/dist/tasenor-common-node/src/plugins/plugins.js +292 -0
- package/dist/tasenor-common-node/src/plugins/plugins.js.map +1 -0
- package/dist/tasenor-common-node/src/process/Process.d.ts +108 -0
- package/dist/tasenor-common-node/src/process/Process.js +335 -0
- package/dist/tasenor-common-node/src/process/Process.js.map +1 -0
- package/dist/tasenor-common-node/src/process/ProcessConnector.d.ts +24 -0
- package/dist/tasenor-common-node/src/process/ProcessConnector.js +28 -0
- package/dist/tasenor-common-node/src/process/ProcessConnector.js.map +1 -0
- package/dist/tasenor-common-node/src/process/ProcessFile.d.ts +69 -0
- package/dist/tasenor-common-node/src/process/ProcessFile.js +145 -0
- package/dist/tasenor-common-node/src/process/ProcessFile.js.map +1 -0
- package/dist/tasenor-common-node/src/process/ProcessHandler.d.ts +60 -0
- package/dist/tasenor-common-node/src/process/ProcessHandler.js +73 -0
- package/dist/tasenor-common-node/src/process/ProcessHandler.js.map +1 -0
- package/dist/tasenor-common-node/src/process/ProcessStep.d.ts +52 -0
- package/dist/tasenor-common-node/src/process/ProcessStep.js +78 -0
- package/dist/tasenor-common-node/src/process/ProcessStep.js.map +1 -0
- package/dist/tasenor-common-node/src/process/ProcessingSystem.d.ts +60 -0
- package/dist/tasenor-common-node/src/process/ProcessingSystem.js +182 -0
- package/dist/tasenor-common-node/src/process/ProcessingSystem.js.map +1 -0
- package/dist/tasenor-common-node/src/process/index.d.ts +11 -0
- package/dist/tasenor-common-node/src/process/index.js +12 -0
- package/dist/tasenor-common-node/src/process/index.js.map +1 -0
- package/dist/tasenor-common-node/src/reports/conversions.d.ts +8 -0
- package/dist/tasenor-common-node/src/reports/conversions.js +47 -0
- package/dist/tasenor-common-node/src/reports/conversions.js.map +1 -0
- package/dist/tasenor-common-node/src/reports/index.d.ts +6 -0
- package/dist/tasenor-common-node/src/reports/index.js +7 -0
- package/dist/tasenor-common-node/src/reports/index.js.map +1 -0
- package/dist/tasenor-common-node/src/server/ISPDemoServer.d.ts +43 -0
- package/dist/tasenor-common-node/src/server/ISPDemoServer.js +112 -0
- package/dist/tasenor-common-node/src/server/ISPDemoServer.js.map +1 -0
- package/dist/tasenor-common-node/src/server/api.d.ts +15 -0
- package/dist/tasenor-common-node/src/server/api.js +27 -0
- package/dist/tasenor-common-node/src/server/api.js.map +1 -0
- package/dist/tasenor-common-node/src/server/index.d.ts +7 -0
- package/dist/tasenor-common-node/src/server/index.js +8 -0
- package/dist/tasenor-common-node/src/server/index.js.map +1 -0
- package/dist/tasenor-common-node/src/server/router.d.ts +5 -0
- package/dist/tasenor-common-node/src/server/router.js +37 -0
- package/dist/tasenor-common-node/src/server/router.js.map +1 -0
- package/dist/tasenor-common-node/src/system.d.ts +27 -0
- package/dist/tasenor-common-node/src/system.js +95 -0
- package/dist/tasenor-common-node/src/system.js.map +1 -0
- package/dist/tasenor-common-node/src/testing/ProcessingSystemMock.d.ts +21 -0
- package/dist/tasenor-common-node/src/testing/ProcessingSystemMock.js +33 -0
- package/dist/tasenor-common-node/src/testing/ProcessingSystemMock.js.map +1 -0
- package/dist/tasenor-common-node/src/testing/UnitTestImportConnector.d.ts +24 -0
- package/dist/tasenor-common-node/src/testing/UnitTestImportConnector.js +68 -0
- package/dist/tasenor-common-node/src/testing/UnitTestImportConnector.js.map +1 -0
- package/dist/tasenor-common-node/src/testing/UnitTester.d.ts +64 -0
- package/dist/tasenor-common-node/src/testing/UnitTester.js +199 -0
- package/dist/tasenor-common-node/src/testing/UnitTester.js.map +1 -0
- package/dist/tasenor-common-node/src/testing/index.d.ts +4 -0
- package/dist/tasenor-common-node/src/testing/index.js +5 -0
- package/dist/tasenor-common-node/src/testing/index.js.map +1 -0
- package/dist/tasenor-common-node/src/testing/test-handlers.d.ts +13 -0
- package/dist/tasenor-common-node/src/testing/test-handlers.js +52 -0
- package/dist/tasenor-common-node/src/testing/test-handlers.js.map +1 -0
- package/dist/tasenor-common-node/tests/TransactionRules.spec.d.ts +1 -0
- package/dist/tasenor-common-node/tests/TransactionRules.spec.js +64 -0
- package/dist/tasenor-common-node/tests/TransactionRules.spec.js.map +1 -0
- package/dist/tasenor-common-node/tests/TransferAnalyzer-account-address.spec.d.ts +1 -0
- package/dist/tasenor-common-node/tests/TransferAnalyzer-account-address.spec.js +80 -0
- package/dist/tasenor-common-node/tests/TransferAnalyzer-account-address.spec.js.map +1 -0
- package/dist/tasenor-common-node/tests/TransferAnalyzer-buying-and-selling.spec.d.ts +1 -0
- package/dist/tasenor-common-node/tests/TransferAnalyzer-buying-and-selling.spec.js +342 -0
- package/dist/tasenor-common-node/tests/TransferAnalyzer-buying-and-selling.spec.js.map +1 -0
- package/dist/tasenor-common-node/tests/TransferAnalyzer-loans.spec.d.ts +1 -0
- package/dist/tasenor-common-node/tests/TransferAnalyzer-loans.spec.js +174 -0
- package/dist/tasenor-common-node/tests/TransferAnalyzer-loans.spec.js.map +1 -0
- package/dist/tasenor-common-node/tests/TransferAnalyzer-multiple-null-amounts.spec.d.ts +1 -0
- package/dist/tasenor-common-node/tests/TransferAnalyzer-multiple-null-amounts.spec.js +175 -0
- package/dist/tasenor-common-node/tests/TransferAnalyzer-multiple-null-amounts.spec.js.map +1 -0
- package/dist/tasenor-common-node/tests/password.spec.d.ts +1 -0
- package/dist/tasenor-common-node/tests/password.spec.js +8 -0
- package/dist/tasenor-common-node/tests/password.spec.js.map +1 -0
- package/dist/tasenor-common-node/tests/tokens.spec.d.ts +1 -0
- package/dist/tasenor-common-node/tests/tokens.spec.js +49 -0
- package/dist/tasenor-common-node/tests/tokens.spec.js.map +1 -0
- package/dist/tasenor-common-node/tests/vault.spec.d.ts +1 -0
- package/dist/tasenor-common-node/tests/vault.spec.js +19 -0
- package/dist/tasenor-common-node/tests/vault.spec.js.map +1 -0
- package/dist/tasenor-common-plugins/src/CoinbaseImport/backend/CoinbaseHandler.d.ts +11 -0
- package/dist/tasenor-common-plugins/src/CoinbaseImport/backend/CoinbaseHandler.js +30 -0
- package/dist/tasenor-common-plugins/src/CoinbaseImport/backend/CoinbaseHandler.js.map +1 -0
- package/dist/tasenor-common-plugins/src/IncomeAndExpenses/backend/index.d.ts +5 -0
- package/dist/tasenor-common-plugins/src/IncomeAndExpenses/backend/index.js +350 -0
- package/dist/tasenor-common-plugins/src/IncomeAndExpenses/backend/index.js.map +1 -0
- package/dist/tasenor-common-plugins/src/KrakenImport/backend/KrakenHandler.d.ts +23 -0
- package/dist/tasenor-common-plugins/src/KrakenImport/backend/KrakenHandler.js +83 -0
- package/dist/tasenor-common-plugins/src/KrakenImport/backend/KrakenHandler.js.map +1 -0
- package/dist/tasenor-common-plugins/src/LynxImport/backend/LynxHandler.d.ts +28 -0
- package/dist/tasenor-common-plugins/src/LynxImport/backend/LynxHandler.js +340 -0
- package/dist/tasenor-common-plugins/src/LynxImport/backend/LynxHandler.js.map +1 -0
- package/dist/tasenor-common-plugins/src/NordeaImport/backend/NordeaHandler.d.ts +11 -0
- package/dist/tasenor-common-plugins/src/NordeaImport/backend/NordeaHandler.js +39 -0
- package/dist/tasenor-common-plugins/src/NordeaImport/backend/NordeaHandler.js.map +1 -0
- package/dist/tasenor-common-plugins/src/NordnetImport/backend/NordnetHandler.d.ts +17 -0
- package/dist/tasenor-common-plugins/src/NordnetImport/backend/NordnetHandler.js +66 -0
- package/dist/tasenor-common-plugins/src/NordnetImport/backend/NordnetHandler.js.map +1 -0
- package/dist/tasenor-common-plugins/src/TITOImport/backend/TITOHandler.d.ts +13 -0
- package/dist/tasenor-common-plugins/src/TITOImport/backend/TITOHandler.js +241 -0
- package/dist/tasenor-common-plugins/src/TITOImport/backend/TITOHandler.js.map +1 -0
- package/jest.config.js +1 -0
- package/package.json +62 -0
- package/src/cli.ts +267 -0
- package/src/commands/account.ts +69 -0
- package/src/commands/balance.ts +131 -0
- package/src/commands/db.ts +84 -0
- package/src/commands/entry.ts +117 -0
- package/src/commands/import.ts +160 -0
- package/src/commands/importer.ts +84 -0
- package/src/commands/index.ts +534 -0
- package/src/commands/period.ts +59 -0
- package/src/commands/plugin.ts +95 -0
- package/src/commands/report.ts +113 -0
- package/src/commands/settings.ts +75 -0
- package/src/commands/stock.ts +80 -0
- package/src/commands/tag.ts +102 -0
- package/src/commands/tx.ts +93 -0
- package/src/commands/user.ts +65 -0
- package/src/database/BookkeeperImporter.ts +358 -0
- package/src/database/DB.ts +396 -0
- package/src/database/index.ts +7 -0
- package/src/doccer.ts +29 -0
- package/src/error.ts +32 -0
- package/src/export/Exporter.ts +136 -0
- package/src/export/TasenorExporter.ts +144 -0
- package/src/export/TilitinExporter.ts +302 -0
- package/src/export/index.ts +8 -0
- package/src/import/TextFileProcessHandler.ts +384 -0
- package/src/import/TransactionImportConnector.ts +65 -0
- package/src/import/TransactionImportHandler.ts +819 -0
- package/src/import/TransactionRules.ts +570 -0
- package/src/import/TransactionUI.ts +520 -0
- package/src/import/TransferAnalyzer.ts +1450 -0
- package/src/import/index.ts +11 -0
- package/src/index.ts +12 -0
- package/src/net/crypto.ts +69 -0
- package/src/net/git.ts +151 -0
- package/src/net/index.ts +10 -0
- package/src/net/middleware.ts +261 -0
- package/src/net/tokens.ts +140 -0
- package/src/net/vault.ts +161 -0
- package/src/plugins/BackendPlugin.ts +188 -0
- package/src/plugins/DataPlugin.ts +29 -0
- package/src/plugins/ImportPlugin.ts +211 -0
- package/src/plugins/ReportPlugin.ts +443 -0
- package/src/plugins/SchemePlugin.ts +56 -0
- package/src/plugins/ServicePlugin.ts +188 -0
- package/src/plugins/ToolPlugin.ts +44 -0
- package/src/plugins/index.ts +13 -0
- package/src/plugins/plugins.ts +345 -0
- package/src/process/Process.ts +368 -0
- package/src/process/ProcessConnector.ts +45 -0
- package/src/process/ProcessFile.ts +169 -0
- package/src/process/ProcessHandler.ts +94 -0
- package/src/process/ProcessStep.ts +100 -0
- package/src/process/ProcessingSystem.ts +202 -0
- package/src/process/index.ts +11 -0
- package/src/reports/conversions.ts +52 -0
- package/src/reports/index.ts +6 -0
- package/src/server/ISPDemoServer.ts +122 -0
- package/src/server/api.ts +37 -0
- package/src/server/index.ts +7 -0
- package/src/server/router.ts +60 -0
- package/src/system.ts +96 -0
- package/src/testing/ProcessingSystemMock.ts +45 -0
- package/src/testing/UnitTestImportConnector.ts +86 -0
- package/src/testing/UnitTester.ts +231 -0
- package/src/testing/index.ts +4 -0
- package/src/testing/test-handlers.ts +55 -0
- package/tests/TransactionRules.spec.ts +73 -0
- package/tests/TransferAnalyzer-account-address.spec.ts +87 -0
- package/tests/TransferAnalyzer-buying-and-selling.spec.ts +354 -0
- package/tests/TransferAnalyzer-loans.spec.ts +197 -0
- package/tests/TransferAnalyzer-multiple-null-amounts.spec.ts +181 -0
- package/tests/password.spec.ts +8 -0
- package/tests/tokens.spec.ts +52 -0
- package/tests/vault.spec.ts +20 -0
- package/tsconfig.json +13 -0
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
import clone from 'clone'
|
|
2
|
+
import { BadState, DatabaseError, InvalidArgument, isAskUI } from '../error'
|
|
3
|
+
import { ProcessFile } from './ProcessFile'
|
|
4
|
+
import { ProcessingSystem } from './ProcessingSystem'
|
|
5
|
+
import { ProcessStep } from './ProcessStep'
|
|
6
|
+
import { Directions, ProcessName, ProcessConfig, ProcessStatus, ID, TasenorElement, ImportAction, ImportState } from '@dataplug/tasenor-common'
|
|
7
|
+
import { KnexDatabase } from '../database'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Overall description of the process.
|
|
11
|
+
*/
|
|
12
|
+
export interface ProcessInfo {
|
|
13
|
+
name: ProcessName
|
|
14
|
+
config: ProcessConfig
|
|
15
|
+
complete: boolean
|
|
16
|
+
successful: boolean | undefined
|
|
17
|
+
currentStep: number | undefined
|
|
18
|
+
status: ProcessStatus
|
|
19
|
+
error?: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* A complete description of the process state and steps taken.
|
|
24
|
+
*/
|
|
25
|
+
export class Process {
|
|
26
|
+
|
|
27
|
+
system: ProcessingSystem
|
|
28
|
+
|
|
29
|
+
id: ID
|
|
30
|
+
name: ProcessName
|
|
31
|
+
config: ProcessConfig
|
|
32
|
+
complete: boolean
|
|
33
|
+
successful: boolean | undefined
|
|
34
|
+
currentStep: number | undefined
|
|
35
|
+
status: ProcessStatus
|
|
36
|
+
files: ProcessFile[]
|
|
37
|
+
steps: ProcessStep[]
|
|
38
|
+
error: string | undefined
|
|
39
|
+
|
|
40
|
+
constructor(system: ProcessingSystem, name: ProcessName | null, config: ProcessConfig = {}) {
|
|
41
|
+
this.system = system
|
|
42
|
+
|
|
43
|
+
this.id = null
|
|
44
|
+
this.config = config
|
|
45
|
+
this.name = name || '[no name]'
|
|
46
|
+
this.complete = false
|
|
47
|
+
this.successful = undefined
|
|
48
|
+
this.files = []
|
|
49
|
+
this.steps = []
|
|
50
|
+
this.currentStep = undefined
|
|
51
|
+
this.status = 'INCOMPLETE' as ProcessStatus
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
toString(): string {
|
|
55
|
+
return `Process #${this.id} ${this.name}`
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Get the loaded process information as JSON object.
|
|
60
|
+
* @returns
|
|
61
|
+
*/
|
|
62
|
+
toJSON(): ProcessInfo {
|
|
63
|
+
return {
|
|
64
|
+
name: this.name,
|
|
65
|
+
config: this.config,
|
|
66
|
+
complete: this.complete,
|
|
67
|
+
successful: this.successful,
|
|
68
|
+
currentStep: this.currentStep,
|
|
69
|
+
status: this.status,
|
|
70
|
+
error: this.error
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Append a file to this process and link its ID.
|
|
76
|
+
* @param file
|
|
77
|
+
*/
|
|
78
|
+
addFile(file: ProcessFile): void {
|
|
79
|
+
file.processId = this.id
|
|
80
|
+
this.files.push(file)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Append a step to this process and link its ID.
|
|
85
|
+
* @param step
|
|
86
|
+
*/
|
|
87
|
+
async addStep(step: ProcessStep): Promise<void> {
|
|
88
|
+
step.processId = this.id
|
|
89
|
+
step.process = this
|
|
90
|
+
this.steps.push(step)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Load the current step if not yet loaded and return it.
|
|
95
|
+
*/
|
|
96
|
+
async getCurrentStep(): Promise<ProcessStep> {
|
|
97
|
+
if (this.currentStep === null || this.currentStep === undefined) {
|
|
98
|
+
throw new BadState(`Process #${this.id} ${this.name} has invalid current step.`)
|
|
99
|
+
}
|
|
100
|
+
if (this.steps[this.currentStep]) {
|
|
101
|
+
return this.steps[this.currentStep]
|
|
102
|
+
}
|
|
103
|
+
return this.loadStep(this.currentStep)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Mark the current state as completed and create new additional step with the new state.
|
|
108
|
+
* @param state
|
|
109
|
+
*/
|
|
110
|
+
async proceedToState(action: ImportAction, state: ImportState): Promise<void> {
|
|
111
|
+
const current = await this.getCurrentStep()
|
|
112
|
+
const handler = this.system.getHandler(current.handler)
|
|
113
|
+
current.action = action
|
|
114
|
+
current.finished = new Date()
|
|
115
|
+
current.save()
|
|
116
|
+
const nextStep = new ProcessStep({
|
|
117
|
+
number: current.number + 1,
|
|
118
|
+
state,
|
|
119
|
+
handler: handler.name
|
|
120
|
+
})
|
|
121
|
+
this.addStep(nextStep)
|
|
122
|
+
this.currentStep = (this.currentStep || 0) + 1
|
|
123
|
+
this.system.logger.info(`Proceeding ${this} to new step ${this.currentStep}.`)
|
|
124
|
+
this.save()
|
|
125
|
+
await nextStep.save()
|
|
126
|
+
await this.system.checkFinishAndFindDirections(handler, nextStep)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Get a reference to the database.
|
|
131
|
+
*/
|
|
132
|
+
get db(): KnexDatabase {
|
|
133
|
+
return this.system.db
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Save the process info to the database.
|
|
138
|
+
*/
|
|
139
|
+
async save(): Promise<ID> {
|
|
140
|
+
if (this.id) {
|
|
141
|
+
await this.db('processes').update(this.toJSON()).where({ id: this.id })
|
|
142
|
+
return this.id
|
|
143
|
+
} else {
|
|
144
|
+
this.id = (await this.db('processes').insert(this.toJSON()).returning('id'))[0].id
|
|
145
|
+
if (this.id) return this.id
|
|
146
|
+
throw new DatabaseError(`Saving process ${JSON.stringify(this.toJSON)} failed.`)
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Load the process data and its files. Note that current step is not yet loaded here, but when using getCurrentStep().
|
|
152
|
+
* @param id
|
|
153
|
+
*/
|
|
154
|
+
async load(id: ID): Promise<void> {
|
|
155
|
+
// Load basic info.
|
|
156
|
+
const data = await this.db('processes').select('*').where({ id }).first()
|
|
157
|
+
if (!data) {
|
|
158
|
+
throw new InvalidArgument(`Cannot find process #${id}`)
|
|
159
|
+
}
|
|
160
|
+
Object.assign(this, data)
|
|
161
|
+
this.id = id
|
|
162
|
+
// Load files.
|
|
163
|
+
this.files = (await this.db('process_files').select('*').where({ processId: this.id })).map(fileData => {
|
|
164
|
+
const file = new ProcessFile(fileData)
|
|
165
|
+
file.id = fileData.id
|
|
166
|
+
return file
|
|
167
|
+
})
|
|
168
|
+
// Load current step.
|
|
169
|
+
await this.getCurrentStep()
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Load the step with the given number from the database.
|
|
174
|
+
* @param number
|
|
175
|
+
* @returns
|
|
176
|
+
*/
|
|
177
|
+
async loadStep(number: number): Promise<ProcessStep> {
|
|
178
|
+
if (!this.id) {
|
|
179
|
+
throw new BadState(`Cannot load steps, if the process have no ID ${JSON.stringify(this.toJSON())}.`)
|
|
180
|
+
}
|
|
181
|
+
if (this.currentStep === undefined) {
|
|
182
|
+
throw new BadState(`Cannot load any steps, since process have no current step ${JSON.stringify(this.toJSON())}.`)
|
|
183
|
+
}
|
|
184
|
+
const data = await this.db('process_steps').where({ processId: this.id, number }).first()
|
|
185
|
+
if (!data) {
|
|
186
|
+
throw new BadState(`Cannot find step ${this.currentStep} for process ${JSON.stringify(this.toJSON())}.`)
|
|
187
|
+
}
|
|
188
|
+
this.steps[this.currentStep] = new ProcessStep(data)
|
|
189
|
+
this.steps[this.currentStep].id = data.id
|
|
190
|
+
this.steps[this.currentStep].process = this
|
|
191
|
+
return this.steps[this.currentStep]
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Check if the process can be run.
|
|
196
|
+
*/
|
|
197
|
+
canRun(): boolean {
|
|
198
|
+
return !this.complete && (this.status === 'INCOMPLETE' || this.status === 'WAITING')
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Execute process as long as it is completed, failed or requires additional input.
|
|
203
|
+
*/
|
|
204
|
+
async run(): Promise<void> {
|
|
205
|
+
let step
|
|
206
|
+
let MAX_RUNS = 100
|
|
207
|
+
while (true) {
|
|
208
|
+
MAX_RUNS--
|
|
209
|
+
if (MAX_RUNS < 0) {
|
|
210
|
+
this.system.logger.error(`Maximum number of executions reached for the process ${this}.`)
|
|
211
|
+
break
|
|
212
|
+
}
|
|
213
|
+
step = await this.getCurrentStep()
|
|
214
|
+
if (!step.directions) {
|
|
215
|
+
this.system.logger.info(`No new directions for the process ${this}.`)
|
|
216
|
+
break
|
|
217
|
+
}
|
|
218
|
+
if (!step.directions.isImmediate()) {
|
|
219
|
+
this.system.logger.info(`Waiting for more input for the process ${this}.`)
|
|
220
|
+
await this.updateStatus()
|
|
221
|
+
break
|
|
222
|
+
}
|
|
223
|
+
const handler = this.system.getHandler(step.handler)
|
|
224
|
+
const state = clone(step.state)
|
|
225
|
+
const action = clone(step.directions.action)
|
|
226
|
+
try {
|
|
227
|
+
if (action) {
|
|
228
|
+
const nextState = await handler.action(this, action, state, this.files)
|
|
229
|
+
await this.proceedToState(action, nextState)
|
|
230
|
+
} else {
|
|
231
|
+
throw new BadState(`Process step ${step} has no action.`)
|
|
232
|
+
}
|
|
233
|
+
} catch (err) {
|
|
234
|
+
return await this.crashed(err)
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Record the error and mark the process as finished with an error.
|
|
241
|
+
* @param err
|
|
242
|
+
*/
|
|
243
|
+
async crashed(err: Error): Promise<void> {
|
|
244
|
+
if (isAskUI(err)) {
|
|
245
|
+
// Postpone the action we tried. Instead, create query for UI to add more configuration for later retry.
|
|
246
|
+
const directions = new Directions({
|
|
247
|
+
type: 'ui',
|
|
248
|
+
element: err.element as unknown as TasenorElement
|
|
249
|
+
})
|
|
250
|
+
const step = await this.getCurrentStep()
|
|
251
|
+
step.directions = directions
|
|
252
|
+
await step.save()
|
|
253
|
+
await this.updateStatus()
|
|
254
|
+
return
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
this.system.logger.error(`Processing of ${this} failed:`, err)
|
|
258
|
+
if (this.currentStep !== undefined && this.currentStep !== null) {
|
|
259
|
+
const step = await this.loadStep(this.currentStep)
|
|
260
|
+
step.finished = new Date()
|
|
261
|
+
await step.save()
|
|
262
|
+
}
|
|
263
|
+
this.error = err.stack ? err.stack : `${err.name}: ${err.message}`
|
|
264
|
+
await this.save()
|
|
265
|
+
await this.updateStatus()
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Resolve the status of the process and update it to the database.
|
|
270
|
+
*/
|
|
271
|
+
async updateStatus(): Promise<void> {
|
|
272
|
+
let status = 'INCOMPLETE'
|
|
273
|
+
if (this.error) {
|
|
274
|
+
status = 'CRASHED'
|
|
275
|
+
} else {
|
|
276
|
+
if (this.currentStep === null || this.currentStep === undefined) {
|
|
277
|
+
throw new BadState(`Cannot check status when there is no current step loaded for ${this}`)
|
|
278
|
+
}
|
|
279
|
+
const step = this.steps[this.currentStep]
|
|
280
|
+
if (step.finished) {
|
|
281
|
+
if (this.successful === true) status = 'SUCCEEDED'
|
|
282
|
+
if (this.successful === false) status = 'FAILED'
|
|
283
|
+
}
|
|
284
|
+
if (step.directions) {
|
|
285
|
+
status = step.directions.isImmediate() ? 'INCOMPLETE' : 'WAITING'
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
if (this.status !== status) {
|
|
289
|
+
this.system.logger.info(`Process ${this} is now ${status}`)
|
|
290
|
+
}
|
|
291
|
+
this.status = status as ProcessStatus
|
|
292
|
+
await this.db('processes').update({ status }).where({ id: this.id })
|
|
293
|
+
|
|
294
|
+
let directions, state
|
|
295
|
+
switch (status) {
|
|
296
|
+
case 'SUCCEEDED':
|
|
297
|
+
await this.system.connector.success(this.state)
|
|
298
|
+
break
|
|
299
|
+
case 'CRASHED':
|
|
300
|
+
await this.system.connector.fail(this.error)
|
|
301
|
+
break
|
|
302
|
+
case 'FAILED':
|
|
303
|
+
await this.system.connector.fail(this.state)
|
|
304
|
+
break
|
|
305
|
+
default:
|
|
306
|
+
directions = this.currentStep ? this.steps[this.currentStep].directions : null
|
|
307
|
+
state = this.currentStep ? this.steps[this.currentStep].state : null
|
|
308
|
+
await this.system.connector.waiting(state, directions)
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Get the state of the current step of the process.
|
|
314
|
+
*/
|
|
315
|
+
get state(): ImportState {
|
|
316
|
+
if (this.currentStep === null || this.currentStep === undefined) {
|
|
317
|
+
throw new BadState(`Cannot check state when there is no current step loaded for ${this}`)
|
|
318
|
+
}
|
|
319
|
+
const step = this.steps[this.currentStep]
|
|
320
|
+
return step.state
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Handle external input coming in.
|
|
325
|
+
* @param action
|
|
326
|
+
*/
|
|
327
|
+
async input(action: ImportAction): Promise<void> {
|
|
328
|
+
this.system.logger.info(`Handling input ${JSON.stringify(action)} on process ${this}.`)
|
|
329
|
+
const step = await this.getCurrentStep()
|
|
330
|
+
const handler = this.system.getHandler(step.handler)
|
|
331
|
+
let nextState
|
|
332
|
+
try {
|
|
333
|
+
nextState = await handler.action(this, action, clone(step.state), this.files)
|
|
334
|
+
} catch (err) {
|
|
335
|
+
return this.crashed(err)
|
|
336
|
+
}
|
|
337
|
+
await this.proceedToState(action, nextState)
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Roll back the process.
|
|
342
|
+
*/
|
|
343
|
+
async rollback(): Promise<boolean> {
|
|
344
|
+
if (this.currentStep === null || this.currentStep === undefined) {
|
|
345
|
+
throw new BadState('Cannot rollback when there is no current step.')
|
|
346
|
+
}
|
|
347
|
+
if (this.currentStep < 1) {
|
|
348
|
+
throw new BadState('Cannot rollback when there is only initial step in the process.')
|
|
349
|
+
}
|
|
350
|
+
const step = await this.getCurrentStep()
|
|
351
|
+
this.system.logger.info(`Attempt of rolling back '${step}' from '${this}'.`)
|
|
352
|
+
const handler = this.system.getHandler(step.handler)
|
|
353
|
+
await handler.rollback(this, this.state)
|
|
354
|
+
const current = await this.getCurrentStep()
|
|
355
|
+
current.action = { rollback: true }
|
|
356
|
+
current.finished = new Date()
|
|
357
|
+
current.save()
|
|
358
|
+
|
|
359
|
+
this.system.logger.info(`Proceeding ${this} to new step ${this.currentStep}.`)
|
|
360
|
+
this.save()
|
|
361
|
+
|
|
362
|
+
this.status = 'ROLLEDBACK'
|
|
363
|
+
await this.db('processes').update({ status: this.status }).where({ id: this.id })
|
|
364
|
+
this.system.logger.info(`Roll back of '${this}' successful.`)
|
|
365
|
+
|
|
366
|
+
return true
|
|
367
|
+
}
|
|
368
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
|
+
import { ID } from '@dataplug/tasenor-common'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A connector interface for querying information, applying results and running various hooks.
|
|
6
|
+
*/
|
|
7
|
+
export interface ProcessConnector {
|
|
8
|
+
initialize(server: unknown): Promise<void>
|
|
9
|
+
getTranslation(text: string, language: string): Promise<string>
|
|
10
|
+
resultExists(processId: ID, args: unknown): Promise<boolean>
|
|
11
|
+
applyResult(processId: ID, args: unknown): Promise<Record<string, unknown>>
|
|
12
|
+
rollback(processId: ID): Promise<boolean>
|
|
13
|
+
success(state: unknown): Promise<void>
|
|
14
|
+
waiting(state: unknown, directions): Promise<void>
|
|
15
|
+
fail(state: unknown): Promise<void>
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const defaultConnector = {
|
|
19
|
+
async initialize(): Promise<void> {
|
|
20
|
+
console.log(new Date(), 'Connector initialized.')
|
|
21
|
+
},
|
|
22
|
+
async resultExists(processId: ID, args: unknown): Promise<boolean> {
|
|
23
|
+
return false
|
|
24
|
+
},
|
|
25
|
+
async applyResult(): Promise<Record<string, unknown>> {
|
|
26
|
+
console.log(new Date(), 'Result received.')
|
|
27
|
+
return {}
|
|
28
|
+
},
|
|
29
|
+
async success(): Promise<void> {
|
|
30
|
+
console.log(new Date(), 'Process completed.')
|
|
31
|
+
},
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
33
|
+
async waiting(): Promise<void> {
|
|
34
|
+
},
|
|
35
|
+
async fail(): Promise<void> {
|
|
36
|
+
console.error(new Date(), 'Process failed.')
|
|
37
|
+
},
|
|
38
|
+
async getTranslation(text: string) {
|
|
39
|
+
return text
|
|
40
|
+
},
|
|
41
|
+
async rollback(processId: ID): Promise<boolean> {
|
|
42
|
+
return true
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { ID, FileEncoding } from '@dataplug/tasenor-common'
|
|
2
|
+
import chardet from 'chardet'
|
|
3
|
+
import clone from 'clone'
|
|
4
|
+
import { KnexDatabase } from '../database'
|
|
5
|
+
import { DatabaseError, InvalidFile, NotImplemented } from '../error'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A data structure containing input data for the process.
|
|
9
|
+
*/
|
|
10
|
+
export interface ProcessFileData {
|
|
11
|
+
processId?: ID
|
|
12
|
+
name: string
|
|
13
|
+
type?: string
|
|
14
|
+
encoding: FileEncoding
|
|
15
|
+
data: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* An instance of input data for processing.
|
|
20
|
+
*/
|
|
21
|
+
export class ProcessFile {
|
|
22
|
+
id: ID
|
|
23
|
+
processId: ID
|
|
24
|
+
name: string
|
|
25
|
+
type?: string
|
|
26
|
+
encoding: FileEncoding
|
|
27
|
+
data: string
|
|
28
|
+
_decoded?: string
|
|
29
|
+
|
|
30
|
+
constructor(obj: ProcessFileData) {
|
|
31
|
+
this.id = null
|
|
32
|
+
this.processId = obj.processId || null
|
|
33
|
+
this.name = obj.name
|
|
34
|
+
this.type = obj.type
|
|
35
|
+
this.encoding = obj.encoding
|
|
36
|
+
this.data = obj.data
|
|
37
|
+
this._decoded = undefined
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
toString(): string {
|
|
41
|
+
return `ProcessFile #${this.id} ${this.name}`
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get the loaded process information as JSON object.
|
|
46
|
+
* @returns
|
|
47
|
+
*/
|
|
48
|
+
toJSON(): ProcessFileData {
|
|
49
|
+
return {
|
|
50
|
+
processId: this.processId,
|
|
51
|
+
name: this.name,
|
|
52
|
+
type: this.type,
|
|
53
|
+
encoding: this.encoding,
|
|
54
|
+
data: this.data
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Save the file to the database.
|
|
60
|
+
*/
|
|
61
|
+
async save(db: KnexDatabase): Promise<ID> {
|
|
62
|
+
const out = this.toJSON()
|
|
63
|
+
if (this.encoding === 'json') {
|
|
64
|
+
out.data = JSON.stringify(out.data)
|
|
65
|
+
}
|
|
66
|
+
if (this.id) {
|
|
67
|
+
await db('process_files').update(out).where({ id: this.id })
|
|
68
|
+
return this.id
|
|
69
|
+
} else {
|
|
70
|
+
this.id = (await db('process_files').insert(out).returning('id'))[0].id
|
|
71
|
+
if (this.id) return this.id
|
|
72
|
+
throw new DatabaseError(`Saving process ${JSON.stringify(out)} failed.`)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Check if the first line of the text file matches to the regular expression.
|
|
78
|
+
* @param re
|
|
79
|
+
*/
|
|
80
|
+
firstLineMatch(re: RegExp): boolean {
|
|
81
|
+
const str = this.decode()
|
|
82
|
+
const n = str.indexOf('\n')
|
|
83
|
+
const line1 = n < 0 ? str : str.substr(0, n).trim()
|
|
84
|
+
return re.test(line1)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Check if the second line of the text file matches to the regular expression.
|
|
89
|
+
* @param re
|
|
90
|
+
*/
|
|
91
|
+
secondLineMatch(re: RegExp): boolean {
|
|
92
|
+
const lines = this.decode().split('\n')
|
|
93
|
+
return lines.length > 1 && re.test(lines[1].trim())
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Check if the third line of the text file matches to the regular expression.
|
|
98
|
+
* @param re
|
|
99
|
+
*/
|
|
100
|
+
thirdLineMatch(re: RegExp): boolean {
|
|
101
|
+
const lines = this.decode().split('\n')
|
|
102
|
+
return lines.length > 2 && re.test(lines[2].trim())
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Check if the file begins with the given string.
|
|
107
|
+
*/
|
|
108
|
+
startsWith(s: string): boolean {
|
|
109
|
+
let buffer
|
|
110
|
+
switch (this.encoding) {
|
|
111
|
+
case 'base64':
|
|
112
|
+
buffer = Buffer.from(this.data.substring(0, s.length * 2), 'base64')
|
|
113
|
+
return buffer.toString('ascii').substr(0, s.length) === s
|
|
114
|
+
default:
|
|
115
|
+
throw new NotImplemented(`Cannot handle encoding ${this.encoding} in startWith().`)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Find out if the content is binary or text.
|
|
121
|
+
*
|
|
122
|
+
* The mime type has to start with `text/`.
|
|
123
|
+
*/
|
|
124
|
+
isTextFile(): boolean {
|
|
125
|
+
return this.type?.startsWith('text/') || false
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Convert chardet encoding to the supported buffer encoding
|
|
130
|
+
* "ascii" | "utf8" | "utf-8" | "utf16le" | "ucs2" | "ucs-2" | "base64" | "latin1" | "binary" | "hex"
|
|
131
|
+
*/
|
|
132
|
+
parseEncoding(encoding: string): 'ascii' | 'utf8' | 'utf-8' | 'utf16le' | 'ucs2' | 'ucs-2' | 'base64' | 'latin1' | 'binary' | 'hex' {
|
|
133
|
+
switch (encoding.toUpperCase()) {
|
|
134
|
+
case 'UTF-8':
|
|
135
|
+
return 'utf-8'
|
|
136
|
+
case 'ISO-8859-1':
|
|
137
|
+
return 'latin1'
|
|
138
|
+
case 'UTF-16LE':
|
|
139
|
+
return 'utf16le'
|
|
140
|
+
default:
|
|
141
|
+
throw new InvalidFile(`Not able to map text encoding ${encoding}.`)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Try to recognize the file content and decode if it is a recognizable text format.
|
|
147
|
+
*/
|
|
148
|
+
decode(): string {
|
|
149
|
+
if (this._decoded) {
|
|
150
|
+
return this._decoded
|
|
151
|
+
}
|
|
152
|
+
if (this.encoding === 'base64') {
|
|
153
|
+
const buffer = Buffer.from(this.data, 'base64')
|
|
154
|
+
const encoding = chardet.detect(buffer)
|
|
155
|
+
if (!encoding) {
|
|
156
|
+
throw new InvalidFile(`Cannot determine encoding for '${this}'.`)
|
|
157
|
+
}
|
|
158
|
+
this._decoded = buffer.toString(this.parseEncoding(encoding))
|
|
159
|
+
return this._decoded
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (this.encoding === 'utf-8') {
|
|
163
|
+
this._decoded = clone(this.data)
|
|
164
|
+
return this._decoded || ''
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
throw new InvalidFile(`An encoding '${this.encoding}' is not yet supported.`)
|
|
168
|
+
}
|
|
169
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { ProcessFile } from './ProcessFile'
|
|
2
|
+
import { ProcessingSystem } from './ProcessingSystem'
|
|
3
|
+
import { Process } from './Process'
|
|
4
|
+
import { NotImplemented } from '../error'
|
|
5
|
+
import { Directions, ImportAction, ImportState, ProcessConfig } from '@dataplug/tasenor-common'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A handler taking care of moving between process states.
|
|
9
|
+
*/
|
|
10
|
+
export class ProcessHandler {
|
|
11
|
+
|
|
12
|
+
system: ProcessingSystem
|
|
13
|
+
name: string
|
|
14
|
+
|
|
15
|
+
constructor(name: string) {
|
|
16
|
+
this.name = name
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Attach this handler to the processing system during the registration.
|
|
21
|
+
* @param system
|
|
22
|
+
*/
|
|
23
|
+
connect(system: ProcessingSystem): void {
|
|
24
|
+
this.system = system
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Check if we are able to handle the given file.
|
|
29
|
+
* @param file
|
|
30
|
+
*/
|
|
31
|
+
canHandle(file: ProcessFile): boolean {
|
|
32
|
+
throw new NotImplemented(`A handler '${this.name}' cannot check file '${file.name}', since canHandle() is not implemented.`)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Check if we are able to append the given file to the process.
|
|
37
|
+
* @param file
|
|
38
|
+
*/
|
|
39
|
+
canAppend(file: ProcessFile): boolean {
|
|
40
|
+
throw new NotImplemented(`A handler '${this.name}' cannot append file '${file.name}', since canAppend() is not implemented.`)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Check if the state is either successful `true` or failed `false` or not yet complete `undefined`.
|
|
45
|
+
* @param state
|
|
46
|
+
*/
|
|
47
|
+
checkCompletion(state: ImportState): boolean | undefined {
|
|
48
|
+
throw new NotImplemented(`A handler '${this.name}' cannot check state '${JSON.stringify(state)}', since checkCompletion() is not implemented.`)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Execute an action to the state in order to produce new state. Note that state is cloned and can be modified to be new state.
|
|
53
|
+
* @param action
|
|
54
|
+
* @param state
|
|
55
|
+
* @param files
|
|
56
|
+
*/
|
|
57
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
58
|
+
async action(process: Process, action: ImportAction, state: ImportState, files: ProcessFile[]): Promise<ImportState> {
|
|
59
|
+
throw new NotImplemented(`A handler '${this.name}' for files ${files.map(f => `'${f}''`).join(', ')} does not implement action()`)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Construct intial state from the given data.
|
|
64
|
+
* @param file
|
|
65
|
+
*/
|
|
66
|
+
startingState(files: ProcessFile[]): ImportState {
|
|
67
|
+
throw new NotImplemented(`A handler '${this.name}' for file ${files.map(f => `'${f}''`).join(', ')} does not implement startingState()`)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Figure out possible directions from the given state.
|
|
72
|
+
* @param state
|
|
73
|
+
*/
|
|
74
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
75
|
+
async getDirections(state: ImportState, config: ProcessConfig): Promise<Directions> {
|
|
76
|
+
throw new NotImplemented(`A handler '${this.name}' for state '${JSON.stringify(state)}' does not implement getDirections()`)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* See if it is possible rollback a process.
|
|
81
|
+
* @param step
|
|
82
|
+
*/
|
|
83
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
84
|
+
async rollback(process: Process, state: ImportState): Promise<ImportState> {
|
|
85
|
+
throw new NotImplemented(`A handler '${this.name}' does not implement rollback()`)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* A collection of process handlers.
|
|
91
|
+
*/
|
|
92
|
+
export type ProcessHandlerMap = {
|
|
93
|
+
[key: string]: ProcessHandler
|
|
94
|
+
}
|