@harperfast/harper 5.0.0-alpha.10 → 5.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/BinObjects.js +17 -0
- package/bin/cliOperations.js +157 -0
- package/bin/copyDb.ts +280 -0
- package/bin/harper.js +156 -0
- package/bin/install.js +15 -0
- package/bin/lite.js +5 -0
- package/bin/restart.js +201 -0
- package/bin/run.js +409 -0
- package/bin/status.js +65 -0
- package/bin/stop.js +22 -0
- package/bin/upgrade.js +134 -0
- package/components/Application.ts +646 -0
- package/components/ApplicationScope.ts +49 -0
- package/components/Component.ts +53 -0
- package/components/ComponentV1.ts +342 -0
- package/components/DEFAULT_CONFIG.ts +18 -0
- package/components/EntryHandler.ts +227 -0
- package/components/Logger.ts +14 -0
- package/components/OptionsWatcher.ts +354 -0
- package/components/PluginModule.ts +6 -0
- package/components/Scope.ts +329 -0
- package/components/componentLoader.ts +529 -0
- package/components/deriveCommonPatternBase.ts +31 -0
- package/components/deriveGlobOptions.ts +44 -0
- package/components/deriveURLPath.ts +57 -0
- package/components/operations.js +658 -0
- package/components/operationsValidation.js +246 -0
- package/components/packageComponent.ts +39 -0
- package/components/requestRestart.ts +26 -0
- package/components/resolveBaseURLPath.ts +38 -0
- package/components/status/ComponentStatus.ts +110 -0
- package/components/status/ComponentStatusRegistry.ts +251 -0
- package/components/status/api.ts +153 -0
- package/components/status/crossThread.ts +405 -0
- package/components/status/errors.ts +152 -0
- package/components/status/index.ts +44 -0
- package/components/status/internal.ts +65 -0
- package/components/status/registry.ts +12 -0
- package/components/status/types.ts +96 -0
- package/config/RootConfigWatcher.ts +59 -0
- package/config/configHelpers.ts +11 -0
- package/config/configUtils.js +967 -0
- package/config/harperConfigEnvVars.ts +641 -0
- package/dataLayer/CreateAttributeObject.js +25 -0
- package/dataLayer/CreateTableObject.js +11 -0
- package/dataLayer/DataLayerObjects.js +43 -0
- package/dataLayer/DeleteBeforeObject.js +22 -0
- package/dataLayer/DeleteObject.js +25 -0
- package/dataLayer/DropAttributeObject.js +11 -0
- package/dataLayer/GetBackupObject.js +22 -0
- package/dataLayer/InsertObject.js +24 -0
- package/dataLayer/ReadAuditLogObject.js +24 -0
- package/dataLayer/SQLSearch.js +1335 -0
- package/dataLayer/SearchByConditionsObject.js +61 -0
- package/dataLayer/SearchByHashObject.js +21 -0
- package/dataLayer/SearchObject.js +45 -0
- package/dataLayer/SqlSearchObject.js +14 -0
- package/dataLayer/UpdateObject.js +23 -0
- package/dataLayer/UpsertObject.js +23 -0
- package/dataLayer/bulkLoad.js +813 -0
- package/dataLayer/dataObjects/BulkLoadObjects.js +27 -0
- package/dataLayer/dataObjects/UpsertObject.js +23 -0
- package/dataLayer/delete.js +164 -0
- package/dataLayer/export.js +381 -0
- package/dataLayer/getBackup.js +40 -0
- package/dataLayer/harperBridge/BridgeMethods.js +81 -0
- package/dataLayer/harperBridge/ResourceBridge.ts +633 -0
- package/dataLayer/harperBridge/bridgeUtility/insertUpdateReturnObj.js +28 -0
- package/dataLayer/harperBridge/bridgeUtility/insertUpdateValidate.js +88 -0
- package/dataLayer/harperBridge/harperBridge.js +21 -0
- package/dataLayer/harperBridge/lmdbBridge/LMDBBridge.js +119 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.js +19 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateAttribute.js +112 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateRecords.js +67 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateSchema.js +31 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateTable.js +94 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDeleteAuditLogsBefore.js +98 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDeleteRecords.js +89 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDropAttribute.js +109 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDropSchema.js +107 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDropTable.js +137 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbFlush.js +35 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbGetBackup.js +111 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbGetDataByHash.js +28 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbGetDataByValue.js +29 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbReadAuditLog.js +207 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbSearchByConditions.js +156 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbSearchByHash.js +21 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbSearchByValue.js +30 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbTransaction.js +19 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbUpdateRecords.js +64 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbUpsertRecords.js +70 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBCreateAttributeObject.js +22 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBDeleteTransactionObject.js +23 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBInsertTransactionObject.js +22 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBTransactionObject.js +23 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBUpdateTransactionObject.js +24 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBUpsertTransactionObject.js +24 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/TableSizeObject.js +25 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/initializeHashSearch.js +21 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/initializePaths.js +157 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbCheckForNewAttributes.js +94 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbCreateTransactionsAuditEnvironment.js +39 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbGetTableSize.js +34 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbProcessRows.js +100 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbSearch.js +371 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbWriteTransaction.js +109 -0
- package/dataLayer/hdbInfoController.js +254 -0
- package/dataLayer/insert.js +266 -0
- package/dataLayer/readAuditLog.js +59 -0
- package/dataLayer/schema.js +366 -0
- package/dataLayer/schemaDescribe.js +289 -0
- package/dataLayer/search.js +60 -0
- package/dataLayer/transaction.js +17 -0
- package/dataLayer/update.js +124 -0
- package/dist/components/Logger.d.ts +12 -0
- package/dist/components/Logger.js +3 -0
- package/dist/components/Logger.js.map +1 -0
- package/dist/components/Scope.d.ts +14 -4
- package/dist/components/Scope.js +18 -10
- package/dist/components/Scope.js.map +1 -1
- package/dist/components/componentLoader.js +16 -9
- package/dist/components/componentLoader.js.map +1 -1
- package/dist/components/operations.js +2 -2
- package/dist/components/operations.js.map +1 -1
- package/dist/config/configUtils.d.ts +1 -1
- package/dist/config/configUtils.js +1 -1
- package/dist/config/configUtils.js.map +1 -1
- package/dist/dataLayer/CreateTableObject.d.ts +2 -2
- package/dist/dataLayer/CreateTableObject.js +2 -2
- package/dist/dataLayer/CreateTableObject.js.map +1 -1
- package/dist/dataLayer/delete.d.ts +1 -1
- package/dist/dataLayer/schema.js +6 -5
- package/dist/dataLayer/schema.js.map +1 -1
- package/dist/dataLayer/schemaDescribe.js +1 -1
- package/dist/dataLayer/schemaDescribe.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/resources/DatabaseTransaction.d.ts +1 -1
- package/dist/resources/IterableEventQueue.d.ts +1 -1
- package/dist/resources/LMDBTransaction.d.ts +5 -1
- package/dist/resources/Resource.d.ts +1 -1
- package/dist/resources/RocksIndexStore.d.ts +3 -3
- package/dist/resources/RocksTransactionLogStore.d.ts +6 -3
- package/dist/resources/Table.d.ts +15 -6
- package/dist/resources/Table.js +4 -1
- package/dist/resources/Table.js.map +1 -1
- package/dist/resources/analytics/read.js +32 -22
- package/dist/resources/analytics/read.js.map +1 -1
- package/dist/resources/analytics/write.js +3 -6
- package/dist/resources/analytics/write.js.map +1 -1
- package/dist/resources/auditStore.d.ts +3 -3
- package/dist/resources/blob.d.ts +25 -2
- package/dist/resources/databases.d.ts +12 -2
- package/dist/resources/databases.js +22 -19
- package/dist/resources/databases.js.map +1 -1
- package/dist/resources/search.js +11 -5
- package/dist/resources/search.js.map +1 -1
- package/dist/resources/transaction.d.ts +2 -1
- package/dist/security/auth.js +1 -1
- package/dist/security/auth.js.map +1 -1
- package/dist/security/cryptoHash.d.ts +2 -2
- package/dist/security/jsLoader.js +243 -66
- package/dist/security/jsLoader.js.map +1 -1
- package/dist/security/keys.js +4 -5
- package/dist/security/keys.js.map +1 -1
- package/dist/security/user.js +3 -3
- package/dist/security/user.js.map +1 -1
- package/dist/server/REST.js +16 -2
- package/dist/server/REST.js.map +1 -1
- package/dist/server/Server.d.ts +2 -1
- package/dist/server/Server.js.map +1 -1
- package/dist/server/fastifyRoutes/plugins/hdbCore.d.ts +6 -1
- package/dist/server/fastifyRoutes.js +2 -0
- package/dist/server/fastifyRoutes.js.map +1 -1
- package/dist/server/http.js +12 -6
- package/dist/server/http.js.map +1 -1
- package/dist/server/jobs/JobObject.d.ts +3 -3
- package/dist/server/loadRootComponents.js +1 -0
- package/dist/server/loadRootComponents.js.map +1 -1
- package/dist/server/operationsServer.js +3 -1
- package/dist/server/operationsServer.js.map +1 -1
- package/dist/server/serverHelpers/JSONStream.d.ts +3 -3
- package/dist/server/serverHelpers/Request.d.ts +5 -5
- package/dist/server/serverHelpers/requestTimePlugin.d.ts +1 -1
- package/dist/server/threads/manageThreads.d.ts +2 -2
- package/dist/server/threads/manageThreads.js +50 -35
- package/dist/server/threads/manageThreads.js.map +1 -1
- package/dist/server/threads/socketRouter.d.ts +1 -1
- package/dist/sqlTranslator/deleteTranslator.d.ts +1 -1
- package/dist/utility/AWS/AWSConnector.d.ts +3 -2
- package/dist/utility/common_utils.d.ts +3 -3
- package/dist/utility/environment/systemInformation.d.ts +1 -0
- package/dist/utility/functions/date/dateFunctions.d.ts +11 -11
- package/dist/utility/globalSchema.d.ts +1 -1
- package/dist/utility/hdbTerms.d.ts +3 -0
- package/dist/utility/hdbTerms.js +3 -0
- package/dist/utility/hdbTerms.js.map +1 -1
- package/dist/utility/installation.d.ts +2 -4
- package/dist/utility/installation.js.map +1 -1
- package/dist/utility/lmdb/commonUtility.d.ts +1 -0
- package/dist/utility/lmdb/deleteUtility.d.ts +1 -0
- package/dist/utility/lmdb/environmentUtility.d.ts +1 -0
- package/dist/utility/lmdb/searchUtility.d.ts +2 -1
- package/dist/utility/lmdb/writeUtility.d.ts +1 -0
- package/dist/utility/logging/harper_logger.d.ts +6 -6
- package/dist/utility/processManagement/processManagement.d.ts +1 -1
- package/dist/utility/processManagement/servicesConfig.d.ts +12 -6
- package/dist/validation/common_validators.d.ts +4 -3
- package/dist/validation/configValidator.d.ts +3 -2
- package/index.d.ts +56 -0
- package/index.js +41 -0
- package/json/systemSchema.json +373 -0
- package/launchServiceScripts/launchHarperDB.js +3 -0
- package/launchServiceScripts/utility/checkNodeVersion.js +15 -0
- package/package.json +21 -3
- package/resources/DatabaseTransaction.ts +378 -0
- package/resources/ErrorResource.ts +57 -0
- package/resources/IterableEventQueue.ts +94 -0
- package/resources/LMDBTransaction.ts +349 -0
- package/resources/RecordEncoder.ts +702 -0
- package/resources/RequestTarget.ts +134 -0
- package/resources/Resource.ts +789 -0
- package/resources/ResourceInterface.ts +221 -0
- package/resources/ResourceInterfaceV2.ts +53 -0
- package/resources/ResourceV2.ts +67 -0
- package/resources/Resources.ts +162 -0
- package/resources/RocksIndexStore.ts +70 -0
- package/resources/RocksTransactionLogStore.ts +352 -0
- package/resources/Table.ts +4527 -0
- package/resources/analytics/hostnames.ts +72 -0
- package/resources/analytics/metadata.ts +10 -0
- package/resources/analytics/read.ts +252 -0
- package/resources/analytics/write.ts +803 -0
- package/resources/auditStore.ts +556 -0
- package/resources/blob.ts +1268 -0
- package/resources/crdt.ts +125 -0
- package/resources/dataLoader.ts +527 -0
- package/resources/databases.ts +1290 -0
- package/resources/graphql.ts +221 -0
- package/resources/indexes/HierarchicalNavigableSmallWorld.ts +638 -0
- package/resources/indexes/customIndexes.ts +7 -0
- package/resources/indexes/vector.ts +38 -0
- package/resources/jsResource.ts +86 -0
- package/resources/loadEnv.ts +22 -0
- package/resources/login.ts +18 -0
- package/resources/openApi.ts +409 -0
- package/resources/registrationDeprecated.ts +8 -0
- package/resources/replayLogs.ts +136 -0
- package/resources/roles.ts +98 -0
- package/resources/search.ts +1301 -0
- package/resources/tracked.ts +584 -0
- package/resources/transaction.ts +89 -0
- package/resources/transactionBroadcast.ts +258 -0
- package/security/auth.ts +376 -0
- package/security/certificateVerification/certificateVerificationSource.ts +84 -0
- package/security/certificateVerification/configValidation.ts +107 -0
- package/security/certificateVerification/crlVerification.ts +623 -0
- package/security/certificateVerification/index.ts +121 -0
- package/security/certificateVerification/ocspVerification.ts +148 -0
- package/security/certificateVerification/pkijs-ed25519-patch.ts +188 -0
- package/security/certificateVerification/types.ts +128 -0
- package/security/certificateVerification/verificationConfig.ts +138 -0
- package/security/certificateVerification/verificationUtils.ts +447 -0
- package/security/cryptoHash.js +42 -0
- package/security/data_objects/PermissionAttributeResponseObject.js +15 -0
- package/security/data_objects/PermissionResponseObject.js +115 -0
- package/security/data_objects/PermissionTableResponseObject.js +20 -0
- package/security/fastifyAuth.js +169 -0
- package/security/impersonation.ts +160 -0
- package/security/jsLoader.ts +716 -0
- package/security/keys.js +948 -0
- package/security/permissionsTranslator.js +300 -0
- package/security/role.js +218 -0
- package/security/tokenAuthentication.ts +228 -0
- package/security/user.ts +449 -0
- package/server/DurableSubscriptionsSession.ts +503 -0
- package/server/REST.ts +407 -0
- package/server/Server.ts +89 -0
- package/server/fastifyRoutes/helpers/getCORSOptions.js +36 -0
- package/server/fastifyRoutes/helpers/getHeaderTimeoutConfig.js +15 -0
- package/server/fastifyRoutes/helpers/getServerOptions.js +33 -0
- package/server/fastifyRoutes/plugins/hdbCore.js +39 -0
- package/server/fastifyRoutes.ts +205 -0
- package/server/graphqlQuerying.ts +700 -0
- package/server/http.ts +640 -0
- package/server/itc/serverHandlers.js +161 -0
- package/server/itc/utility/ITCEventObject.js +10 -0
- package/server/jobs/JobObject.js +24 -0
- package/server/jobs/jobProcess.js +69 -0
- package/server/jobs/jobRunner.js +162 -0
- package/server/jobs/jobs.js +304 -0
- package/server/loadRootComponents.js +44 -0
- package/server/mqtt.ts +485 -0
- package/server/nodeName.ts +75 -0
- package/server/operationsServer.ts +313 -0
- package/server/serverHelpers/Headers.ts +108 -0
- package/server/serverHelpers/JSONStream.ts +269 -0
- package/server/serverHelpers/OperationFunctionObject.ts +13 -0
- package/server/serverHelpers/Request.ts +158 -0
- package/server/serverHelpers/contentTypes.ts +637 -0
- package/server/serverHelpers/requestTimePlugin.js +57 -0
- package/server/serverHelpers/serverHandlers.js +148 -0
- package/server/serverHelpers/serverUtilities.ts +473 -0
- package/server/serverRegistry.ts +8 -0
- package/server/static.ts +187 -0
- package/server/status/definitions.ts +37 -0
- package/server/status/index.ts +125 -0
- package/server/storageReclamation.ts +93 -0
- package/server/threads/itc.js +89 -0
- package/server/threads/manageThreads.js +594 -0
- package/server/threads/socketRouter.ts +360 -0
- package/server/threads/threadServer.js +279 -0
- package/server/throttle.ts +73 -0
- package/sqlTranslator/SelectValidator.js +330 -0
- package/sqlTranslator/alasqlFunctionImporter.js +62 -0
- package/sqlTranslator/deleteTranslator.js +67 -0
- package/sqlTranslator/index.js +242 -0
- package/sqlTranslator/sql_statement_bucket.js +472 -0
- package/static/defaultConfig.yaml +3 -0
- package/studio/web/HDBDogOnly.svg +78 -0
- package/studio/web/assets/PPRadioGrotesk-Bold-DDaUYG8E.woff +0 -0
- package/studio/web/assets/fa-brands-400-CEJbCg16.woff +0 -0
- package/studio/web/assets/fa-brands-400-CSYNqBb_.ttf +0 -0
- package/studio/web/assets/fa-brands-400-DnkPfk3o.eot +0 -0
- package/studio/web/assets/fa-brands-400-UxlILjvJ.woff2 +0 -0
- package/studio/web/assets/fa-brands-400-cH1MgKbP.svg +3717 -0
- package/studio/web/assets/fa-regular-400-BhTwtT8w.eot +0 -0
- package/studio/web/assets/fa-regular-400-D1vz6WBx.ttf +0 -0
- package/studio/web/assets/fa-regular-400-DFnMcJPd.woff +0 -0
- package/studio/web/assets/fa-regular-400-DGzu1beS.woff2 +0 -0
- package/studio/web/assets/fa-regular-400-gwj8Pxq-.svg +801 -0
- package/studio/web/assets/fa-solid-900-B4ZZ7kfP.svg +5034 -0
- package/studio/web/assets/fa-solid-900-B6Axprfb.eot +0 -0
- package/studio/web/assets/fa-solid-900-BUswJgRo.woff2 +0 -0
- package/studio/web/assets/fa-solid-900-DOXgCApm.woff +0 -0
- package/studio/web/assets/fa-solid-900-mxuxnBEa.ttf +0 -0
- package/studio/web/assets/index-BTgXJX9d.js +235 -0
- package/studio/web/assets/index-BTgXJX9d.js.map +1 -0
- package/studio/web/assets/index-C-GXfcup.js +37 -0
- package/studio/web/assets/index-C-GXfcup.js.map +1 -0
- package/studio/web/assets/index-PFlNdimM.js +2 -0
- package/studio/web/assets/index-PFlNdimM.js.map +1 -0
- package/studio/web/assets/index-Y2g_iFpU.css +1 -0
- package/studio/web/assets/index-jiPwkrsB.css +1 -0
- package/studio/web/assets/index.lazy-C3TJZJ4o.js +266 -0
- package/studio/web/assets/index.lazy-C3TJZJ4o.js.map +1 -0
- package/studio/web/assets/profiler-DotzgiCJ.js +2 -0
- package/studio/web/assets/profiler-DotzgiCJ.js.map +1 -0
- package/studio/web/assets/react-redux-VxUEx_mU.js +6 -0
- package/studio/web/assets/react-redux-VxUEx_mU.js.map +1 -0
- package/studio/web/assets/startRecording-B_9J9Csd.js +3 -0
- package/studio/web/assets/startRecording-B_9J9Csd.js.map +1 -0
- package/studio/web/fabric-signup-background.webp +0 -0
- package/studio/web/fabric-signup-text.png +0 -0
- package/studio/web/favicon_purple.png +0 -0
- package/studio/web/github-icon.svg +15 -0
- package/studio/web/harper-fabric_black.png +0 -0
- package/studio/web/harper-fabric_white.png +0 -0
- package/studio/web/harper-studio_white.png +0 -0
- package/studio/web/index.html +16 -0
- package/studio/web/running.css +148 -0
- package/studio/web/running.html +147 -0
- package/studio/web/running.js +111 -0
- package/upgrade/UpgradeObjects.js +13 -0
- package/upgrade/directives/directivesController.js +90 -0
- package/upgrade/directivesManager.js +139 -0
- package/upgrade/upgradePrompt.js +124 -0
- package/upgrade/upgradeUtilities.js +28 -0
- package/utility/AWS/AWSConnector.js +29 -0
- package/utility/OperationFunctionCaller.js +63 -0
- package/utility/assignCmdEnvVariables.js +62 -0
- package/utility/common_utils.js +867 -0
- package/utility/environment/environmentManager.js +208 -0
- package/utility/environment/systemInformation.js +355 -0
- package/utility/errors/commonErrors.js +267 -0
- package/utility/errors/hdbError.js +146 -0
- package/utility/functions/date/dateFunctions.js +65 -0
- package/utility/functions/geo.js +355 -0
- package/utility/functions/sql/alaSQLExtension.js +104 -0
- package/utility/globalSchema.js +35 -0
- package/utility/hdbTerms.ts +819 -0
- package/utility/install/checkJWTTokensExist.js +62 -0
- package/utility/install/harperdb.conf +15 -0
- package/utility/install/harperdb.service +14 -0
- package/utility/install/installer.js +635 -0
- package/utility/installation.ts +30 -0
- package/utility/lmdb/DBIDefinition.js +20 -0
- package/utility/lmdb/DeleteRecordsResponseObject.js +25 -0
- package/utility/lmdb/InsertRecordsResponseObject.js +22 -0
- package/utility/lmdb/OpenDBIObject.js +31 -0
- package/utility/lmdb/OpenEnvironmentObject.js +41 -0
- package/utility/lmdb/UpdateRecordsResponseObject.js +25 -0
- package/utility/lmdb/UpsertRecordsResponseObject.js +22 -0
- package/utility/lmdb/cleanLMDBMap.js +65 -0
- package/utility/lmdb/commonUtility.js +119 -0
- package/utility/lmdb/deleteUtility.js +128 -0
- package/utility/lmdb/environmentUtility.js +477 -0
- package/utility/lmdb/searchCursorFunctions.js +187 -0
- package/utility/lmdb/searchUtility.js +918 -0
- package/utility/lmdb/terms.js +57 -0
- package/utility/lmdb/writeUtility.js +407 -0
- package/utility/logging/harper_logger.js +876 -0
- package/utility/logging/logRotator.js +157 -0
- package/utility/logging/logger.ts +24 -0
- package/utility/logging/readLog.js +355 -0
- package/utility/logging/transactionLog.js +57 -0
- package/utility/mount_hdb.js +59 -0
- package/utility/npmUtilities.js +102 -0
- package/utility/operationPermissions.ts +112 -0
- package/utility/operation_authorization.js +836 -0
- package/utility/packageUtils.js +55 -0
- package/utility/password.ts +99 -0
- package/utility/processManagement/processManagement.js +187 -0
- package/utility/processManagement/servicesConfig.js +56 -0
- package/utility/scripts/restartHdb.js +24 -0
- package/utility/scripts/user_data.sh +13 -0
- package/utility/signalling.js +36 -0
- package/utility/terms/certificates.js +81 -0
- package/utility/when.ts +20 -0
- package/v1.d.ts +39 -0
- package/v1.js +41 -0
- package/v2.d.ts +39 -0
- package/v2.js +41 -0
- package/validation/bulkDeleteValidator.js +24 -0
- package/validation/check_permissions.js +19 -0
- package/validation/common_validators.js +95 -0
- package/validation/configValidator.js +331 -0
- package/validation/deleteValidator.js +15 -0
- package/validation/fileLoadValidator.js +153 -0
- package/validation/insertValidator.js +40 -0
- package/validation/installValidator.js +37 -0
- package/validation/readLogValidator.js +64 -0
- package/validation/role_validation.js +320 -0
- package/validation/schemaMetadataValidator.js +42 -0
- package/validation/searchValidator.js +166 -0
- package/validation/statusValidator.ts +66 -0
- package/validation/transactionLogValidator.js +33 -0
- package/validation/user_validation.js +55 -0
- package/validation/validationWrapper.js +105 -0
- package/dist/resources/analytics/profile.d.ts +0 -2
- package/dist/resources/analytics/profile.js +0 -144
- package/dist/resources/analytics/profile.js.map +0 -1
|
@@ -0,0 +1,813 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const insert = require('./insert.js');
|
|
4
|
+
const validator = require('../validation/fileLoadValidator.js');
|
|
5
|
+
const needle = require('needle');
|
|
6
|
+
const hdbTerms = require('../utility/hdbTerms.ts');
|
|
7
|
+
const hdbUtils = require('../utility/common_utils.js');
|
|
8
|
+
const { handleHDBError, hdbErrors } = require('../utility/errors/hdbError.js');
|
|
9
|
+
const { HTTP_STATUS_CODES, HDB_ERROR_MSGS, CHECK_LOGS_WRAPPER } = hdbErrors;
|
|
10
|
+
const logger = require('../utility/logging/harper_logger.js');
|
|
11
|
+
const papaParse = require('papaparse');
|
|
12
|
+
hdbUtils.promisifyPapaParse();
|
|
13
|
+
const fs = require('fs-extra');
|
|
14
|
+
const path = require('path');
|
|
15
|
+
const { chain } = require('stream-chain');
|
|
16
|
+
const StreamArray = require('stream-json/streamers/StreamArray');
|
|
17
|
+
const Batch = require('stream-json/utils/Batch');
|
|
18
|
+
const comp = require('stream-chain/utils/comp');
|
|
19
|
+
const { finished } = require('stream');
|
|
20
|
+
const env = require('../utility/environment/environmentManager.js');
|
|
21
|
+
const opFuncCaller = require('../utility/OperationFunctionCaller.js');
|
|
22
|
+
const AWSConnector = require('../utility/AWS/AWSConnector.js');
|
|
23
|
+
const { BulkLoadFileObject, BulkLoadDataObject } = require('./dataObjects/BulkLoadObjects.js');
|
|
24
|
+
const PermissionResponseObject = require('../security/data_objects/PermissionResponseObject.js');
|
|
25
|
+
const { verifyBulkLoadAttributePerms } = require('../utility/operation_authorization.js');
|
|
26
|
+
const { databases } = require('../resources/databases.ts');
|
|
27
|
+
const { coerceType } = require('../resources/Table.ts');
|
|
28
|
+
|
|
29
|
+
const CSV_NO_RECORDS_MSG = 'No records parsed from csv file.';
|
|
30
|
+
const TEMP_DOWNLOAD_DIR = `${env.get('HDB_ROOT')}/tmp`;
|
|
31
|
+
const { schemaRegex } = require('../validation/common_validators.js');
|
|
32
|
+
const HIGHWATERMARK = 1024 * 1024 * 2;
|
|
33
|
+
const MAX_JSON_ARRAY_SIZE = 5000;
|
|
34
|
+
|
|
35
|
+
const ACCEPTABLE_URL_CONTENT_TYPE_ENUM = {
|
|
36
|
+
'text/csv': true,
|
|
37
|
+
'application/octet-stream': true,
|
|
38
|
+
'text/plain': true,
|
|
39
|
+
'application/vnd.ms-excel': true,
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
module.exports = {
|
|
43
|
+
csvDataLoad,
|
|
44
|
+
csvURLLoad,
|
|
45
|
+
csvFileLoad,
|
|
46
|
+
importFromS3,
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Load csv values specified as a string in the message 'data' field.
|
|
51
|
+
* @param jsonMessage
|
|
52
|
+
* @returns {Promise<string>}
|
|
53
|
+
*/
|
|
54
|
+
async function csvDataLoad(jsonMessage) {
|
|
55
|
+
let validationMsg = validator.dataObject(jsonMessage);
|
|
56
|
+
if (validationMsg) {
|
|
57
|
+
throw handleHDBError(
|
|
58
|
+
validationMsg,
|
|
59
|
+
validationMsg.message,
|
|
60
|
+
HTTP_STATUS_CODES.BAD_REQUEST,
|
|
61
|
+
undefined,
|
|
62
|
+
undefined,
|
|
63
|
+
true
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
let bulkLoadResult = {};
|
|
68
|
+
try {
|
|
69
|
+
const mapOfTransforms = createTransformMap(jsonMessage.schema, jsonMessage.table);
|
|
70
|
+
let parseResults = papaParse.parse(jsonMessage.data, {
|
|
71
|
+
header: true,
|
|
72
|
+
skipEmptyLines: true,
|
|
73
|
+
transform: typeFunction.bind(null, mapOfTransforms),
|
|
74
|
+
dynamicTyping: false,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const attrsPermsErrors = new PermissionResponseObject();
|
|
78
|
+
|
|
79
|
+
if (
|
|
80
|
+
jsonMessage.hdb_user &&
|
|
81
|
+
jsonMessage.hdb_user?.role &&
|
|
82
|
+
jsonMessage.hdb_user?.role?.permission &&
|
|
83
|
+
jsonMessage.hdb_user?.role?.permission?.super_user !== true
|
|
84
|
+
) {
|
|
85
|
+
verifyBulkLoadAttributePerms(
|
|
86
|
+
jsonMessage.hdb_user?.role?.permission,
|
|
87
|
+
this.job_operation_function.name,
|
|
88
|
+
jsonMessage.action,
|
|
89
|
+
jsonMessage.schema,
|
|
90
|
+
jsonMessage.table,
|
|
91
|
+
parseResults.meta.fields,
|
|
92
|
+
attrsPermsErrors
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const attrPermsErrors = attrsPermsErrors.getPermsResponse();
|
|
97
|
+
if (attrPermsErrors) {
|
|
98
|
+
throw handleHDBError(new Error(), attrPermsErrors, HTTP_STATUS_CODES.BAD_REQUEST, undefined, undefined, true);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
let convertedMsg = new BulkLoadDataObject(
|
|
102
|
+
jsonMessage.action,
|
|
103
|
+
jsonMessage.schema,
|
|
104
|
+
jsonMessage.table,
|
|
105
|
+
parseResults.data
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
bulkLoadResult = await opFuncCaller.callOperationFunctionAsAwait(callBulkFileLoad, convertedMsg, null);
|
|
109
|
+
|
|
110
|
+
if (bulkLoadResult.message === CSV_NO_RECORDS_MSG) {
|
|
111
|
+
return CSV_NO_RECORDS_MSG;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return buildResponseMsg(bulkLoadResult.records, bulkLoadResult.number_written);
|
|
115
|
+
} catch (err) {
|
|
116
|
+
throw buildTopLevelErrMsg(err);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Orchestrates a CSV data load via a file URL. First downloads the file to a temporary folder/file, then calls fileLoad on the
|
|
122
|
+
* downloaded file. Finally deletes temporary file.
|
|
123
|
+
* @param jsonMessage
|
|
124
|
+
* @returns {Promise<string>}
|
|
125
|
+
*/
|
|
126
|
+
async function csvURLLoad(jsonMessage) {
|
|
127
|
+
let validationMsg = validator.urlObject(jsonMessage);
|
|
128
|
+
if (validationMsg) {
|
|
129
|
+
throw handleHDBError(
|
|
130
|
+
validationMsg,
|
|
131
|
+
validationMsg.message,
|
|
132
|
+
HTTP_STATUS_CODES.BAD_REQUEST,
|
|
133
|
+
undefined,
|
|
134
|
+
undefined,
|
|
135
|
+
true
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
let csvFileName = `${Date.now()}.csv`;
|
|
140
|
+
const tempFilePath = `${TEMP_DOWNLOAD_DIR}/${csvFileName}`;
|
|
141
|
+
|
|
142
|
+
try {
|
|
143
|
+
await downloadCSVFile(jsonMessage, csvFileName);
|
|
144
|
+
} catch (err) {
|
|
145
|
+
logger.error(HDB_ERROR_MSGS.DOWNLOAD_FILE_ERR(csvFileName) + ' - ' + err);
|
|
146
|
+
throw handleHDBError(err, CHECK_LOGS_WRAPPER(HDB_ERROR_MSGS.DOWNLOAD_FILE_ERR(csvFileName)));
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
try {
|
|
150
|
+
let csvFileLoadObj = new BulkLoadFileObject(
|
|
151
|
+
this.job_operation_function.name,
|
|
152
|
+
jsonMessage.action,
|
|
153
|
+
jsonMessage.schema,
|
|
154
|
+
jsonMessage.table,
|
|
155
|
+
tempFilePath,
|
|
156
|
+
hdbTerms.VALID_S3_FILE_TYPES.CSV,
|
|
157
|
+
jsonMessage.hdb_user?.role?.permission
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
let bulkLoadResult = await fileLoad(csvFileLoadObj);
|
|
161
|
+
|
|
162
|
+
// Remove the downloaded temporary CSV file and directory once fileLoad complete
|
|
163
|
+
await deleteTempFile(tempFilePath);
|
|
164
|
+
|
|
165
|
+
return bulkLoadResult;
|
|
166
|
+
} catch (err) {
|
|
167
|
+
await deleteTempFile(tempFilePath);
|
|
168
|
+
throw buildTopLevelErrMsg(err);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* This is the top-level API method to handle the local csv file load operation.
|
|
174
|
+
*
|
|
175
|
+
* @param jsonMessage
|
|
176
|
+
* @returns {Promise<string>}
|
|
177
|
+
*/
|
|
178
|
+
async function csvFileLoad(jsonMessage) {
|
|
179
|
+
let validationMsg = validator.fileObject(jsonMessage);
|
|
180
|
+
if (validationMsg) {
|
|
181
|
+
throw handleHDBError(
|
|
182
|
+
validationMsg,
|
|
183
|
+
validationMsg.message,
|
|
184
|
+
HTTP_STATUS_CODES.BAD_REQUEST,
|
|
185
|
+
undefined,
|
|
186
|
+
undefined,
|
|
187
|
+
true
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
let csvFileLoadObj = new BulkLoadFileObject(
|
|
192
|
+
this.job_operation_function.name,
|
|
193
|
+
jsonMessage.action,
|
|
194
|
+
jsonMessage.schema,
|
|
195
|
+
jsonMessage.table,
|
|
196
|
+
jsonMessage.file_path,
|
|
197
|
+
hdbTerms.VALID_S3_FILE_TYPES.CSV,
|
|
198
|
+
jsonMessage.hdb_user?.role?.permission
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
try {
|
|
202
|
+
return await fileLoad(csvFileLoadObj);
|
|
203
|
+
} catch (err) {
|
|
204
|
+
throw buildTopLevelErrMsg(err);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* This is the top-level API method that handles CSV and JSON file imports from private S3 buckets. First downloads
|
|
210
|
+
* the file to a temporary folder/file, then calls fileLoad on the downloaded file. Finally deletes temporary file.
|
|
211
|
+
*
|
|
212
|
+
* @param jsonMessage
|
|
213
|
+
* @returns {Promise<string>}
|
|
214
|
+
*/
|
|
215
|
+
async function importFromS3(jsonMessage) {
|
|
216
|
+
let validationMsg = validator.s3FileObject(jsonMessage);
|
|
217
|
+
if (validationMsg) {
|
|
218
|
+
throw handleHDBError(
|
|
219
|
+
validationMsg,
|
|
220
|
+
validationMsg.message,
|
|
221
|
+
HTTP_STATUS_CODES.BAD_REQUEST,
|
|
222
|
+
undefined,
|
|
223
|
+
undefined,
|
|
224
|
+
true
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
let tempFilePath;
|
|
229
|
+
try {
|
|
230
|
+
let s3FileType = path.extname(jsonMessage.s3.key);
|
|
231
|
+
let s3FileName = `${Date.now()}${s3FileType}`;
|
|
232
|
+
tempFilePath = `${TEMP_DOWNLOAD_DIR}/${s3FileName}`;
|
|
233
|
+
|
|
234
|
+
let s3FileLoadObj = new BulkLoadFileObject(
|
|
235
|
+
this.job_operation_function.name,
|
|
236
|
+
jsonMessage.action,
|
|
237
|
+
jsonMessage.schema,
|
|
238
|
+
jsonMessage.table,
|
|
239
|
+
tempFilePath,
|
|
240
|
+
s3FileType,
|
|
241
|
+
jsonMessage.hdb_user?.role?.permission
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
await downloadFileFromS3(s3FileName, jsonMessage);
|
|
245
|
+
|
|
246
|
+
let bulkLoadResult = await fileLoad(s3FileLoadObj);
|
|
247
|
+
|
|
248
|
+
// Remove the downloaded temporary file once fileLoad complete
|
|
249
|
+
await deleteTempFile(tempFilePath);
|
|
250
|
+
|
|
251
|
+
return bulkLoadResult;
|
|
252
|
+
} catch (err) {
|
|
253
|
+
await deleteTempFile(tempFilePath);
|
|
254
|
+
throw buildTopLevelErrMsg(err);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Gets a file via URL, then creates a temporary directory in hdb root and writes file to disk.
|
|
260
|
+
* @param req
|
|
261
|
+
* @param csvFileName
|
|
262
|
+
* @returns {Promise<void>}
|
|
263
|
+
*/
|
|
264
|
+
async function downloadCSVFile(req, csvFileName) {
|
|
265
|
+
let response;
|
|
266
|
+
try {
|
|
267
|
+
const options = req.passthrough_headers ? { headers: req.passthrough_headers } : undefined;
|
|
268
|
+
response = await needle('get', req.csv_url, options);
|
|
269
|
+
} catch (err) {
|
|
270
|
+
const errMsg = `Error downloading CSV file from ${req.csv_url}, status code: ${err.statusCode}. Check the log for more information.`;
|
|
271
|
+
throw handleHDBError(err, errMsg, err.statusCode, hdbTerms.LOG_LEVELS.ERROR, 'Error downloading CSV file - ' + err);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
validateURLResponse(response, req.csv_url);
|
|
275
|
+
|
|
276
|
+
await writeFileToTempFolder(csvFileName, response.raw);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Used to create the read stream from the S3 bucket to pipe into a local write stream.
|
|
281
|
+
* @param s3FileName - file name used to save the downloaded file locally in the tmp file
|
|
282
|
+
* @param jsonMessage
|
|
283
|
+
* @returns {Promise<void>}
|
|
284
|
+
*/
|
|
285
|
+
async function downloadFileFromS3(s3FileName, jsonMessage) {
|
|
286
|
+
try {
|
|
287
|
+
const tempDownloadLocation = `${TEMP_DOWNLOAD_DIR}/${s3FileName}`;
|
|
288
|
+
await fs.mkdirp(TEMP_DOWNLOAD_DIR);
|
|
289
|
+
await fs.writeFile(`${TEMP_DOWNLOAD_DIR}/${s3FileName}`, '', { flag: 'a+' });
|
|
290
|
+
let tempFileStream = await fs.createWriteStream(tempDownloadLocation);
|
|
291
|
+
let s3Stream = await AWSConnector.getFileStreamFromS3(jsonMessage);
|
|
292
|
+
|
|
293
|
+
await new Promise((resolve, reject) => {
|
|
294
|
+
s3Stream.on('error', function (err) {
|
|
295
|
+
reject(err);
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
s3Stream
|
|
299
|
+
.pipe(tempFileStream)
|
|
300
|
+
.on('error', function (err) {
|
|
301
|
+
reject(err);
|
|
302
|
+
})
|
|
303
|
+
.on('close', function () {
|
|
304
|
+
logger.info(`${jsonMessage.s3.key} successfully downloaded to ${tempDownloadLocation}`);
|
|
305
|
+
resolve();
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
} catch (err) {
|
|
309
|
+
logger.error(HDB_ERROR_MSGS.S3_DOWNLOAD_ERR + ' - ' + err);
|
|
310
|
+
throw handleHDBError(err, CHECK_LOGS_WRAPPER(HDB_ERROR_MSGS.S3_DOWNLOAD_ERR));
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Used to write the CSV data in the body.data from an http request to the local tmp file for processing
|
|
316
|
+
*
|
|
317
|
+
* @param fileName - file name used to save the downloaded file locally in the tmp file
|
|
318
|
+
* @param responseBody - body.data value in response from http request
|
|
319
|
+
* @returns {Promise<void>}
|
|
320
|
+
*/
|
|
321
|
+
async function writeFileToTempFolder(fileName, responseBody) {
|
|
322
|
+
try {
|
|
323
|
+
await fs.mkdirp(TEMP_DOWNLOAD_DIR);
|
|
324
|
+
await fs.writeFile(`${TEMP_DOWNLOAD_DIR}/${fileName}`, responseBody);
|
|
325
|
+
} catch (err) {
|
|
326
|
+
logger.error(HDB_ERROR_MSGS.WRITE_TEMP_FILE_ERR);
|
|
327
|
+
throw handleHDBError(err, CHECK_LOGS_WRAPPER(HDB_ERROR_MSGS.DEFAULT_BULK_LOAD_ERR));
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Deletes temp file downloaded to the tmp dir
|
|
333
|
+
*
|
|
334
|
+
* @param filePath
|
|
335
|
+
* @returns {Promise<void>}
|
|
336
|
+
*/
|
|
337
|
+
async function deleteTempFile(filePath) {
|
|
338
|
+
if (filePath) {
|
|
339
|
+
try {
|
|
340
|
+
await fs.access(filePath);
|
|
341
|
+
await fs.unlink(filePath);
|
|
342
|
+
} catch {
|
|
343
|
+
logger.warn(`could not delete temp csv file at ${filePath}, file does not exist`);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Runs multiple validations on response from HTTP client.
|
|
350
|
+
* @param response
|
|
351
|
+
* @param url
|
|
352
|
+
*/
|
|
353
|
+
function validateURLResponse(response, url) {
|
|
354
|
+
if (response.statusCode !== hdbErrors.HTTP_STATUS_CODES.OK) {
|
|
355
|
+
throw handleHDBError(
|
|
356
|
+
new Error(),
|
|
357
|
+
`CSV Load failed from URL: ${url}, status code: ${response.statusCode}, message: ${response.statusMessage}`,
|
|
358
|
+
HTTP_STATUS_CODES.BAD_REQUEST
|
|
359
|
+
);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
if (!ACCEPTABLE_URL_CONTENT_TYPE_ENUM[response.headers['content-type']]) {
|
|
363
|
+
throw handleHDBError(
|
|
364
|
+
new Error(),
|
|
365
|
+
`CSV Load failed from URL: ${url}, unsupported content type: ${response.headers['content-type']}`,
|
|
366
|
+
HTTP_STATUS_CODES.BAD_REQUEST
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if (!response.raw) {
|
|
371
|
+
throw handleHDBError(
|
|
372
|
+
new Error(),
|
|
373
|
+
`CSV Load failed from URL: ${url}, no csv found at url`,
|
|
374
|
+
HTTP_STATUS_CODES.BAD_REQUEST
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Parse and load CSV or JSON values.
|
|
381
|
+
*
|
|
382
|
+
* @param jsonMessage - An object representing the CSV file.
|
|
383
|
+
* @returns validationMsg - Contains any validation errors found
|
|
384
|
+
* @returns error - any errors found reading the csv file
|
|
385
|
+
* @return err - any errors found during the bulk load
|
|
386
|
+
*
|
|
387
|
+
*/
|
|
388
|
+
async function fileLoad(jsonMessage) {
|
|
389
|
+
try {
|
|
390
|
+
let bulkLoadResult;
|
|
391
|
+
|
|
392
|
+
switch (jsonMessage.file_type) {
|
|
393
|
+
case hdbTerms.VALID_S3_FILE_TYPES.CSV:
|
|
394
|
+
bulkLoadResult = await callPapaParse(jsonMessage);
|
|
395
|
+
break;
|
|
396
|
+
case hdbTerms.VALID_S3_FILE_TYPES.JSON:
|
|
397
|
+
bulkLoadResult = await insertJson(jsonMessage);
|
|
398
|
+
break;
|
|
399
|
+
default:
|
|
400
|
+
//we should never get here but here just incase something changes is validation and slips through
|
|
401
|
+
throw handleHDBError(
|
|
402
|
+
new Error(),
|
|
403
|
+
HDB_ERROR_MSGS.DEFAULT_BULK_LOAD_ERR,
|
|
404
|
+
HTTP_STATUS_CODES.BAD_REQUEST,
|
|
405
|
+
hdbTerms.LOG_LEVELS.ERROR,
|
|
406
|
+
HDB_ERROR_MSGS.INVALID_FILE_EXT_ERR(jsonMessage)
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
return buildResponseMsg(bulkLoadResult.records, bulkLoadResult.number_written);
|
|
411
|
+
} catch (err) {
|
|
412
|
+
throw buildTopLevelErrMsg(err);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Passed to papaparse to validate chunks of csv data from a read stream.
|
|
418
|
+
*
|
|
419
|
+
* @param jsonMessage - An object representing the CSV file.
|
|
420
|
+
* @param reject - A promise object bound to function through hdbUtils.promisifyPapaParse()
|
|
421
|
+
* @param results - An object returned by papaparse containing parsed csv data, errors and meta.
|
|
422
|
+
* @param parser - An object returned by papaparse contains abort, pause and resume.
|
|
423
|
+
* @returns if validation error found returns Promise<error>, if no error nothing is returned.
|
|
424
|
+
*/
|
|
425
|
+
async function validateChunk(jsonMessage, permsValidationResp, reject, results, parser) {
|
|
426
|
+
const resultsData = results.data ? results.data : results;
|
|
427
|
+
if (resultsData.length === 0) {
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// parser pause and resume prevent the parser from getting ahead of validation.
|
|
432
|
+
if (parser) {
|
|
433
|
+
parser.pause();
|
|
434
|
+
}
|
|
435
|
+
let writeObject = {
|
|
436
|
+
operation: jsonMessage.action,
|
|
437
|
+
schema: jsonMessage.schema,
|
|
438
|
+
table: jsonMessage.table,
|
|
439
|
+
records: resultsData,
|
|
440
|
+
};
|
|
441
|
+
|
|
442
|
+
try {
|
|
443
|
+
const { attributes } = await insert.validation(writeObject);
|
|
444
|
+
if (jsonMessage.role_perms && jsonMessage.role_perms.super_user !== true) {
|
|
445
|
+
verifyBulkLoadAttributePerms(
|
|
446
|
+
jsonMessage.role_perms,
|
|
447
|
+
jsonMessage.op,
|
|
448
|
+
jsonMessage.action,
|
|
449
|
+
jsonMessage.schema,
|
|
450
|
+
jsonMessage.table,
|
|
451
|
+
attributes,
|
|
452
|
+
permsValidationResp
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
if (parser) {
|
|
457
|
+
parser.resume();
|
|
458
|
+
}
|
|
459
|
+
} catch (err) {
|
|
460
|
+
// reject is a promise object bound to chunk function through hdbUtils.promisifyPapaParse(). In the case of an error
|
|
461
|
+
// reject will bubble up to hdbUtils.promisifyPapaParse() and return a reject promise object with given error.
|
|
462
|
+
const errResp = handleHDBError(err);
|
|
463
|
+
reject(errResp);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* Passed to papaparse to insert, update, or upsert chunks of csv data from a read stream.
|
|
469
|
+
*
|
|
470
|
+
* @param jsonMessage - An object representing the CSV file.
|
|
471
|
+
* @param insertResults - An object passed by reference used to accumulate results from insert, update, or upsert function.
|
|
472
|
+
* @param reject - A promise object bound to function through hdbUtils.promisifyPapaParse().
|
|
473
|
+
* @param results - An object returned by papaparse containing parsed csv data, errors and meta.
|
|
474
|
+
* @param parser - An object returned by papaparse contains abort, pause and resume.
|
|
475
|
+
* @returns if validation error found returns Promise<error>, if no error nothing is returned.
|
|
476
|
+
*/
|
|
477
|
+
async function insertChunk(jsonMessage, insertResults, reject, results, parser) {
|
|
478
|
+
const resultsData = results.data ? results.data : results;
|
|
479
|
+
if (resultsData.length === 0) {
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
hdbUtils.autoCastJSONDeep(resultsData);
|
|
483
|
+
// parser pause and resume prevent the parser from getting ahead of insert.
|
|
484
|
+
if (parser) {
|
|
485
|
+
parser.pause();
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
let fields = results.meta ? results.meta.fields : null;
|
|
489
|
+
|
|
490
|
+
if (fields) {
|
|
491
|
+
resultsData.forEach((record) => {
|
|
492
|
+
if (!hdbUtils.isEmpty(record) && !hdbUtils.isEmpty(record['__parsed_extra'])) {
|
|
493
|
+
delete record['__parsed_extra'];
|
|
494
|
+
}
|
|
495
|
+
});
|
|
496
|
+
} else {
|
|
497
|
+
const fieldsSet = new Set();
|
|
498
|
+
resultsData.forEach((record) => {
|
|
499
|
+
Object.keys(record).forEach((key) => fieldsSet.add(key));
|
|
500
|
+
});
|
|
501
|
+
fields = [...fieldsSet];
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
try {
|
|
505
|
+
let convertedMsg = {
|
|
506
|
+
schema: jsonMessage.schema,
|
|
507
|
+
table: jsonMessage.table,
|
|
508
|
+
action: jsonMessage.action,
|
|
509
|
+
data: resultsData,
|
|
510
|
+
};
|
|
511
|
+
let bulkLoadChunkResult = await opFuncCaller.callOperationFunctionAsAwait(callBulkFileLoad, convertedMsg, null);
|
|
512
|
+
insertResults.records += bulkLoadChunkResult.records;
|
|
513
|
+
insertResults.number_written += bulkLoadChunkResult.number_written;
|
|
514
|
+
if (parser) {
|
|
515
|
+
parser.resume();
|
|
516
|
+
}
|
|
517
|
+
} catch (err) {
|
|
518
|
+
// reject is a promise object bound to chunk function through hdbUtils.promisifyPapaParse(). In the case of an error
|
|
519
|
+
// reject will bubble up to hdbUtils.promisifyPapaParse() and return a reject promise object with given error.
|
|
520
|
+
const errResp = handleHDBError(
|
|
521
|
+
err,
|
|
522
|
+
CHECK_LOGS_WRAPPER(HDB_ERROR_MSGS.INSERT_CSV_ERR),
|
|
523
|
+
HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR,
|
|
524
|
+
hdbTerms.LOG_LEVELS.ERROR,
|
|
525
|
+
HDB_ERROR_MSGS.INSERT_CSV_ERR + ' - ' + err
|
|
526
|
+
);
|
|
527
|
+
reject(errResp);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
/**
|
|
532
|
+
* Handles two asynchronous calls to csv parser papaparse.
|
|
533
|
+
* First call validates the full read stream from csv file by calling papaparse with validateChunk function. The entire
|
|
534
|
+
* stream is consumed by validate because all rows must be validated before calling insert.
|
|
535
|
+
* Second call inserts a new csv file read stream by calling papaparse with insertChunk function.
|
|
536
|
+
*
|
|
537
|
+
* @param jsonMessage - An object representing the CSV file.
|
|
538
|
+
* @returns {Promise<{records: number, number_written: number}>}
|
|
539
|
+
*/
|
|
540
|
+
async function callPapaParse(jsonMessage) {
|
|
541
|
+
// passing insertResults object by reference to insertChunk function where it accumulate values from bulk load results.
|
|
542
|
+
let insertResults = {
|
|
543
|
+
records: 0,
|
|
544
|
+
number_written: 0,
|
|
545
|
+
};
|
|
546
|
+
const mapOfTransforms = createTransformMap(jsonMessage.schema, jsonMessage.table);
|
|
547
|
+
try {
|
|
548
|
+
const attrsPermsErrors = new PermissionResponseObject();
|
|
549
|
+
let stream = fs.createReadStream(jsonMessage.file_path, { highWaterMark: HIGHWATERMARK });
|
|
550
|
+
stream.setEncoding('utf8');
|
|
551
|
+
|
|
552
|
+
await papaParse.parsePromise(
|
|
553
|
+
stream,
|
|
554
|
+
validateChunk.bind(null, jsonMessage, attrsPermsErrors),
|
|
555
|
+
typeFunction.bind(null, mapOfTransforms)
|
|
556
|
+
);
|
|
557
|
+
|
|
558
|
+
const attrPermsErrors = attrsPermsErrors.getPermsResponse();
|
|
559
|
+
if (attrPermsErrors) {
|
|
560
|
+
throw handleHDBError(new Error(), attrPermsErrors, HTTP_STATUS_CODES.BAD_REQUEST);
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
stream = fs.createReadStream(jsonMessage.file_path, { highWaterMark: HIGHWATERMARK });
|
|
564
|
+
stream.setEncoding('utf8');
|
|
565
|
+
|
|
566
|
+
await papaParse.parsePromise(
|
|
567
|
+
stream,
|
|
568
|
+
insertChunk.bind(null, jsonMessage, insertResults),
|
|
569
|
+
typeFunction.bind(null, mapOfTransforms)
|
|
570
|
+
);
|
|
571
|
+
stream.destroy();
|
|
572
|
+
|
|
573
|
+
return insertResults;
|
|
574
|
+
} catch (err) {
|
|
575
|
+
throw handleHDBError(
|
|
576
|
+
err,
|
|
577
|
+
CHECK_LOGS_WRAPPER(HDB_ERROR_MSGS.PAPA_PARSE_ERR),
|
|
578
|
+
HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR,
|
|
579
|
+
hdbTerms.LOG_LEVELS.ERROR,
|
|
580
|
+
HDB_ERROR_MSGS.PAPA_PARSE_ERR + err
|
|
581
|
+
);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
function createTransformMap(schema, table) {
|
|
586
|
+
const attributes = databases[schema][table].attributes;
|
|
587
|
+
let mapOfTransforms = new Map(); // I don't know if this should be a Map, but this just makes a map of attributes with type coercions that we want
|
|
588
|
+
for (let attribute of attributes) {
|
|
589
|
+
if (attribute.type && !attribute.computed && !attribute.relationship)
|
|
590
|
+
mapOfTransforms.set(attribute.name, (value) => coerceType(value, attribute)); // here is
|
|
591
|
+
// the transform to use
|
|
592
|
+
}
|
|
593
|
+
return mapOfTransforms;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
function typeFunction(mapOfTransforms, value, header) {
|
|
597
|
+
let transform = mapOfTransforms.get(header);
|
|
598
|
+
if (transform) return transform(value);
|
|
599
|
+
return hdbUtils.autoCast(value);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
async function insertJson(jsonMessage) {
|
|
603
|
+
// passing insertResults object by reference to insertChunk function where it accumulate values from bulk load results.
|
|
604
|
+
let insertResults = {
|
|
605
|
+
records: 0,
|
|
606
|
+
number_written: 0,
|
|
607
|
+
};
|
|
608
|
+
|
|
609
|
+
const throwErr = (e) => {
|
|
610
|
+
throw e;
|
|
611
|
+
};
|
|
612
|
+
|
|
613
|
+
try {
|
|
614
|
+
const attrsPermsErrors = new PermissionResponseObject();
|
|
615
|
+
let jsonStreamer = chain([
|
|
616
|
+
fs.createReadStream(jsonMessage.file_path, { encoding: 'utf-8' }),
|
|
617
|
+
StreamArray.withParser(),
|
|
618
|
+
(data) => data.value,
|
|
619
|
+
new Batch({ batchSize: MAX_JSON_ARRAY_SIZE }),
|
|
620
|
+
comp(async (chunk) => {
|
|
621
|
+
await validateChunk(jsonMessage, attrsPermsErrors, throwErr, chunk);
|
|
622
|
+
}),
|
|
623
|
+
]);
|
|
624
|
+
|
|
625
|
+
await new Promise((resolve, reject) => {
|
|
626
|
+
finished(jsonStreamer, (err) => {
|
|
627
|
+
if (err) {
|
|
628
|
+
reject(err);
|
|
629
|
+
} else {
|
|
630
|
+
resolve();
|
|
631
|
+
}
|
|
632
|
+
});
|
|
633
|
+
jsonStreamer.resume();
|
|
634
|
+
});
|
|
635
|
+
|
|
636
|
+
const attrPermsErrors = attrsPermsErrors.getPermsResponse();
|
|
637
|
+
if (attrPermsErrors) {
|
|
638
|
+
throw handleHDBError(new Error(), attrPermsErrors, HTTP_STATUS_CODES.BAD_REQUEST);
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
let jsonStreamerInsert = chain([
|
|
642
|
+
fs.createReadStream(jsonMessage.file_path, { encoding: 'utf-8' }),
|
|
643
|
+
StreamArray.withParser(),
|
|
644
|
+
(data) => data.value,
|
|
645
|
+
new Batch({ batchSize: MAX_JSON_ARRAY_SIZE }),
|
|
646
|
+
comp(async (chunk) => {
|
|
647
|
+
await insertChunk(jsonMessage, insertResults, throwErr, chunk);
|
|
648
|
+
}),
|
|
649
|
+
]);
|
|
650
|
+
|
|
651
|
+
await new Promise((resolve, reject) => {
|
|
652
|
+
finished(jsonStreamerInsert, (err) => {
|
|
653
|
+
if (err) {
|
|
654
|
+
reject(err);
|
|
655
|
+
} else {
|
|
656
|
+
resolve();
|
|
657
|
+
}
|
|
658
|
+
});
|
|
659
|
+
jsonStreamerInsert.resume();
|
|
660
|
+
});
|
|
661
|
+
|
|
662
|
+
return insertResults;
|
|
663
|
+
} catch (err) {
|
|
664
|
+
throw handleHDBError(
|
|
665
|
+
err,
|
|
666
|
+
CHECK_LOGS_WRAPPER(HDB_ERROR_MSGS.INSERT_JSON_ERR),
|
|
667
|
+
HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR,
|
|
668
|
+
hdbTerms.LOG_LEVELS.ERROR,
|
|
669
|
+
HDB_ERROR_MSGS.INSERT_JSON_ERR + err
|
|
670
|
+
);
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
async function callBulkFileLoad(jsonMsg) {
|
|
675
|
+
let bulkLoadResult = {};
|
|
676
|
+
try {
|
|
677
|
+
if (jsonMsg.data && jsonMsg.data.length > 0 && validateColumnNames(jsonMsg.data[0])) {
|
|
678
|
+
bulkLoadResult = await bulkFileLoad(jsonMsg.data, jsonMsg.schema, jsonMsg.table, jsonMsg.action);
|
|
679
|
+
} else {
|
|
680
|
+
bulkLoadResult.message = 'No records parsed from csv file.';
|
|
681
|
+
logger.info(bulkLoadResult.message);
|
|
682
|
+
}
|
|
683
|
+
} catch (err) {
|
|
684
|
+
throw buildTopLevelErrMsg(err);
|
|
685
|
+
}
|
|
686
|
+
return bulkLoadResult;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
/**
|
|
690
|
+
* Validate all attribute names about to be created are valid. Returns true if valid, throws an exception
|
|
691
|
+
* if not.
|
|
692
|
+
* @param createdRecord - A single instance of a record created during csv load.
|
|
693
|
+
* @returns {boolean} - True if valid, throws exception if not.
|
|
694
|
+
*/
|
|
695
|
+
function validateColumnNames(createdRecord) {
|
|
696
|
+
let columnNames = Object.keys(createdRecord);
|
|
697
|
+
for (let key of columnNames) {
|
|
698
|
+
if (!schemaRegex.test(key)) {
|
|
699
|
+
throw new Error(`Invalid column name '${key}', cancelling load operation`);
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
return true;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
/**
|
|
706
|
+
* Performs a bulk insert, update, or upsert depending on the action passed to the function.
|
|
707
|
+
* @param records - The records to be inserted/updated/upserted
|
|
708
|
+
* @param schema - The schema containing the specified table
|
|
709
|
+
* @param table - The table to perform the insert/update/upsert
|
|
710
|
+
* @param action - Specify insert/update/upsert the specified records
|
|
711
|
+
* @returns {Promise<{records: *, new_attributes: *, number_written: number}>}
|
|
712
|
+
*/
|
|
713
|
+
async function bulkFileLoad(records, schema, table, action) {
|
|
714
|
+
if (!action) {
|
|
715
|
+
action = 'insert';
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
let targetObject = {
|
|
719
|
+
operation: action,
|
|
720
|
+
schema,
|
|
721
|
+
table,
|
|
722
|
+
records,
|
|
723
|
+
};
|
|
724
|
+
|
|
725
|
+
let writeFunction;
|
|
726
|
+
switch (action) {
|
|
727
|
+
case 'insert':
|
|
728
|
+
writeFunction = insert.insert;
|
|
729
|
+
break;
|
|
730
|
+
case 'update':
|
|
731
|
+
writeFunction = insert.update;
|
|
732
|
+
break;
|
|
733
|
+
case 'upsert':
|
|
734
|
+
writeFunction = insert.upsert;
|
|
735
|
+
break;
|
|
736
|
+
default:
|
|
737
|
+
throw handleHDBError(
|
|
738
|
+
new Error(),
|
|
739
|
+
HDB_ERROR_MSGS.INVALID_ACTION_PARAM_ERR(action),
|
|
740
|
+
HTTP_STATUS_CODES.BAD_REQUEST,
|
|
741
|
+
hdbTerms.LOG_LEVELS.ERROR,
|
|
742
|
+
HDB_ERROR_MSGS.INVALID_ACTION_PARAM_ERR(action)
|
|
743
|
+
);
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
try {
|
|
747
|
+
let writeResponse = await writeFunction(targetObject);
|
|
748
|
+
|
|
749
|
+
let modifiedHashes;
|
|
750
|
+
switch (action) {
|
|
751
|
+
case 'insert':
|
|
752
|
+
modifiedHashes = writeResponse.inserted_hashes;
|
|
753
|
+
break;
|
|
754
|
+
case 'update':
|
|
755
|
+
modifiedHashes = writeResponse.update_hashes;
|
|
756
|
+
break;
|
|
757
|
+
case 'upsert':
|
|
758
|
+
modifiedHashes = writeResponse.upserted_hashes;
|
|
759
|
+
break;
|
|
760
|
+
default:
|
|
761
|
+
//We should never get here based on the error thrown in the switch above
|
|
762
|
+
break;
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
if (Array.isArray(writeResponse.skipped_hashes) && writeResponse.skipped_hashes.length > 0) {
|
|
766
|
+
let tableInfo = global.hdb_schema[schema][table];
|
|
767
|
+
let hash_attribute = tableInfo.hash_attribute;
|
|
768
|
+
|
|
769
|
+
let x = records.length;
|
|
770
|
+
while (x--) {
|
|
771
|
+
if (writeResponse.skipped_hashes.indexOf(records[x][hash_attribute]) >= 0) {
|
|
772
|
+
records.splice(x, 1);
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
let number_written = hdbUtils.isEmptyOrZeroLength(modifiedHashes) ? 0 : modifiedHashes.length;
|
|
778
|
+
return {
|
|
779
|
+
records: records.length,
|
|
780
|
+
number_written,
|
|
781
|
+
new_attributes: writeResponse.new_attributes,
|
|
782
|
+
};
|
|
783
|
+
} catch (err) {
|
|
784
|
+
throw buildTopLevelErrMsg(err);
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
/**
|
|
789
|
+
* Builds the response message returned by bulk load operations.
|
|
790
|
+
* @param totalRecords
|
|
791
|
+
* @param number_written
|
|
792
|
+
*/
|
|
793
|
+
function buildResponseMsg(totalRecords, number_written) {
|
|
794
|
+
return `successfully loaded ${number_written} of ${totalRecords} records`;
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
/**
|
|
798
|
+
* Uses handleHDBError here to ensure the specific error that has already been created when thrown lower down
|
|
799
|
+
* the stack is used OR, if it hasn't been handled yet, will create and return the generic error message for bulk load
|
|
800
|
+
* and log the error
|
|
801
|
+
*
|
|
802
|
+
* @param err - error caught to be turned into a HDBError (if not already) or passed through via HDBError
|
|
803
|
+
* @returns {HdbError}
|
|
804
|
+
*/
|
|
805
|
+
function buildTopLevelErrMsg(err) {
|
|
806
|
+
return handleHDBError(
|
|
807
|
+
err,
|
|
808
|
+
CHECK_LOGS_WRAPPER(HDB_ERROR_MSGS.DEFAULT_BULK_LOAD_ERR),
|
|
809
|
+
HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR,
|
|
810
|
+
hdbTerms.LOG_LEVELS.ERROR,
|
|
811
|
+
HDB_ERROR_MSGS.DEFAULT_BULK_LOAD_ERR + ' - ' + err
|
|
812
|
+
);
|
|
813
|
+
}
|