@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,789 @@
|
|
|
1
|
+
import type { User } from '../security/user.ts';
|
|
2
|
+
import type { RecordObject } from './RecordEncoder.js';
|
|
3
|
+
import {
|
|
4
|
+
ResourceInterface,
|
|
5
|
+
SubscriptionRequest,
|
|
6
|
+
Id,
|
|
7
|
+
Context,
|
|
8
|
+
Query,
|
|
9
|
+
SourceContext,
|
|
10
|
+
RequestTargetOrId,
|
|
11
|
+
} from './ResourceInterface.ts';
|
|
12
|
+
import { randomUUID } from 'crypto';
|
|
13
|
+
import { DatabaseTransaction, type Transaction } from './DatabaseTransaction.ts';
|
|
14
|
+
import { IterableEventQueue } from './IterableEventQueue.ts';
|
|
15
|
+
import { _assignPackageExport } from '../globals.js';
|
|
16
|
+
import { ClientError, AccessViolation } from '../utility/errors/hdbError.js';
|
|
17
|
+
import { transaction, contextStorage } from './transaction.ts';
|
|
18
|
+
import { parseQuery } from './search.ts';
|
|
19
|
+
import { RequestTarget } from './RequestTarget.ts';
|
|
20
|
+
import { when, promiseNormalize } from '../utility/when.ts';
|
|
21
|
+
|
|
22
|
+
const EXTENSION_TYPES = {
|
|
23
|
+
json: 'application/json',
|
|
24
|
+
cbor: 'application/cbor',
|
|
25
|
+
msgpack: 'application/x-msgpack',
|
|
26
|
+
csv: 'text/csv',
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* This is the main class that can be extended for any resource in Harper and provides the essential reusable
|
|
31
|
+
* uniform interface for interacting with data, defining the API for providing data (data sources) and for consuming
|
|
32
|
+
* data. This interface is used pervasively in Harper and is implemented by database tables and can be used to define
|
|
33
|
+
* sources for caching, real-data sources for messaging protocols, and RESTful endpoints, as well as any other types of
|
|
34
|
+
* data aggregation, processing, or monitoring.
|
|
35
|
+
*
|
|
36
|
+
* This base Resource class provides a set of static methods that are main entry points for querying and updating data
|
|
37
|
+
* in resources/tables. The static methods provide the default handling of arguments, context, and ensuring that
|
|
38
|
+
* internal actions are wrapped in a transaction. The base Resource class intended to be extended, and the instance
|
|
39
|
+
* methods can be overridden to provide specific implementations of actions like get, put, post, delete, and subscribe.
|
|
40
|
+
*/
|
|
41
|
+
export class Resource<Record extends object = any> implements ResourceInterface<Record> {
|
|
42
|
+
readonly #id: Id;
|
|
43
|
+
readonly #context: Context | SourceContext;
|
|
44
|
+
#isCollection: boolean;
|
|
45
|
+
static transactions: Transaction[] & { timestamp: number };
|
|
46
|
+
static directURLMapping = false;
|
|
47
|
+
static loadAsInstance: boolean;
|
|
48
|
+
constructor(identifier: Id, source: any) {
|
|
49
|
+
this.#id = identifier;
|
|
50
|
+
const context = source?.getContext ? (source.getContext() ?? null) : undefined;
|
|
51
|
+
this.#context = context !== undefined ? context : source || null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The get methods are for directly getting a resource, and called for HTTP GET requests.
|
|
56
|
+
*/
|
|
57
|
+
static get = transactional(
|
|
58
|
+
function (resource: Resource, query: RequestTarget, _request: Context, _data: any) {
|
|
59
|
+
const result = resource.get?.(query);
|
|
60
|
+
// for the new API we always apply select in the instance method
|
|
61
|
+
if (!resource.constructor.loadAsInstance) return result;
|
|
62
|
+
if (result?.then) return result.then(handleSelect);
|
|
63
|
+
return handleSelect(result);
|
|
64
|
+
function handleSelect(result) {
|
|
65
|
+
let select;
|
|
66
|
+
if ((select = query?.select) && result != null && !result.selectApplied) {
|
|
67
|
+
const transform = transformForSelect(select, resource.constructor);
|
|
68
|
+
if (typeof result?.map === 'function') {
|
|
69
|
+
return result.map(transform);
|
|
70
|
+
} else {
|
|
71
|
+
return transform(result);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
type: 'read',
|
|
79
|
+
// allows context to reset/remove transaction after completion so it can be used in immediate mode:
|
|
80
|
+
letItLinger: true,
|
|
81
|
+
ensureLoaded: true, // load from source by default
|
|
82
|
+
hasContent: false,
|
|
83
|
+
async: true, // use async by default
|
|
84
|
+
method: 'get',
|
|
85
|
+
}
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Store the provided record by the provided id. If no id is provided, it is auto-generated.
|
|
90
|
+
*/
|
|
91
|
+
static put = transactional(
|
|
92
|
+
function (resource: Resource, query: RequestTarget, request: Context, data: any) {
|
|
93
|
+
if (Array.isArray(data) && resource.#isCollection && resource.constructor.loadAsInstance !== false) {
|
|
94
|
+
const results = [];
|
|
95
|
+
for (const element of data) {
|
|
96
|
+
const resourceClass = resource.constructor;
|
|
97
|
+
const id = element[resourceClass.primaryKey];
|
|
98
|
+
let target = new RequestTarget();
|
|
99
|
+
target.id = id;
|
|
100
|
+
const elementResource = resourceClass.getResource(target, request, {
|
|
101
|
+
async: true,
|
|
102
|
+
});
|
|
103
|
+
if (elementResource.then) results.push(elementResource.then((resource) => resource.put(element, request)));
|
|
104
|
+
else results.push(elementResource.put(element, query));
|
|
105
|
+
}
|
|
106
|
+
return Promise.all(results);
|
|
107
|
+
}
|
|
108
|
+
return resource.put
|
|
109
|
+
? resource.constructor.loadAsInstance === false
|
|
110
|
+
? resource.put(query, data)
|
|
111
|
+
: resource.put(data, query)
|
|
112
|
+
: missingMethod(resource, 'put');
|
|
113
|
+
},
|
|
114
|
+
{ hasContent: true, type: 'update', method: 'put' }
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
static patch = transactional(
|
|
118
|
+
function (resource: Resource, query: RequestTarget, _request: Context, data: any) {
|
|
119
|
+
// TODO: Allow array like put?
|
|
120
|
+
return resource.patch
|
|
121
|
+
? resource.constructor.loadAsInstance === false
|
|
122
|
+
? resource.patch(query, data)
|
|
123
|
+
: resource.patch(data, query)
|
|
124
|
+
: missingMethod(resource, 'patch');
|
|
125
|
+
},
|
|
126
|
+
{ hasContent: true, type: 'update', method: 'patch' }
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
static delete = transactional(
|
|
130
|
+
function (resource: Resource, query: RequestTarget, _request: Context, _data: any) {
|
|
131
|
+
return resource.delete ? resource.delete(query) : missingMethod(resource, 'delete');
|
|
132
|
+
},
|
|
133
|
+
{ hasContent: false, type: 'delete', method: 'delete' }
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Generate a new primary key for a resource; by default we use UUIDs (for now).
|
|
138
|
+
*/
|
|
139
|
+
static getNewId() {
|
|
140
|
+
return randomUUID();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Create a new resource with the provided record and id. If no id is provided, it is auto-generated. Note that this
|
|
145
|
+
* facilitates creating a new resource, but does not guarantee that this is not overwriting an existing entry.
|
|
146
|
+
* @param idPrefix
|
|
147
|
+
* @param record
|
|
148
|
+
* @param context
|
|
149
|
+
*/
|
|
150
|
+
static create(idPrefix: Id, record: any, context: Context): Promise<Id>;
|
|
151
|
+
static create(record: any, context: Context): Promise<Id>;
|
|
152
|
+
static create(idPrefix: any, record: any, context?: Context): Promise<Id> {
|
|
153
|
+
let id: Id;
|
|
154
|
+
if (this.loadAsInstance === false) {
|
|
155
|
+
if (typeof idPrefix === 'object' && idPrefix && !context) {
|
|
156
|
+
// two argument form (record, context), shift the arguments
|
|
157
|
+
context = record;
|
|
158
|
+
record = idPrefix;
|
|
159
|
+
id = new RequestTarget();
|
|
160
|
+
id.isCollection = true;
|
|
161
|
+
} else id = idPrefix;
|
|
162
|
+
} else {
|
|
163
|
+
if (idPrefix == null) id = record?.[this.primaryKey] ?? this.getNewId();
|
|
164
|
+
else if (Array.isArray(idPrefix) && typeof idPrefix[0] !== 'object')
|
|
165
|
+
id = record?.[this.primaryKey] ?? [...idPrefix, this.getNewId()];
|
|
166
|
+
else if (typeof idPrefix !== 'object') id = record?.[this.primaryKey] ?? [idPrefix, this.getNewId()];
|
|
167
|
+
else {
|
|
168
|
+
// two argument form, shift the arguments
|
|
169
|
+
id = idPrefix?.[this.primaryKey] ?? this.getNewId();
|
|
170
|
+
context = record || {};
|
|
171
|
+
record = idPrefix;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if (context) {
|
|
175
|
+
if (context.getContext) context = context.getContext();
|
|
176
|
+
} else {
|
|
177
|
+
// try to get the context from the async context if possible
|
|
178
|
+
context = contextStorage.getStore() ?? {};
|
|
179
|
+
}
|
|
180
|
+
return transaction(context, async () => {
|
|
181
|
+
context.transaction.startedFrom ??= {
|
|
182
|
+
resourceName: this.name,
|
|
183
|
+
method: 'create',
|
|
184
|
+
};
|
|
185
|
+
const resource = new this(id, context);
|
|
186
|
+
const results = resource.create ? await resource.create(id, record) : missingMethod(resource, 'create');
|
|
187
|
+
context.newLocation = id ?? results?.[this.primaryKey];
|
|
188
|
+
context.createdResource = true;
|
|
189
|
+
return this.loadAsInstance === false ? results : resource;
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
static invalidate = transactional(
|
|
193
|
+
function (resource: Resource, query: RequestTarget, _request: Context, _data: any) {
|
|
194
|
+
return resource.invalidate ? resource.invalidate(query) : missingMethod(resource, 'invalidate');
|
|
195
|
+
},
|
|
196
|
+
{ hasContent: false, type: 'update', method: 'invalidate' }
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
static post = transactional(
|
|
200
|
+
function (resource: Resource, query: RequestTarget, _request: Context, data: any) {
|
|
201
|
+
if (resource.#id != null) resource.update?.(); // save any changes made during post
|
|
202
|
+
return resource.constructor.loadAsInstance === false ? resource.post(query, data) : resource.post(data, query);
|
|
203
|
+
},
|
|
204
|
+
{ hasContent: true, type: 'create', method: 'post' }
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
static update = transactional(
|
|
208
|
+
function (resource: Resource, query: RequestTarget, _request: Context, data: any) {
|
|
209
|
+
return resource.update(query, data);
|
|
210
|
+
},
|
|
211
|
+
{ type: 'update', method: 'update' }
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
static connect = transactional(
|
|
215
|
+
function (resource: Resource, query: RequestTarget, _request: Context, data: any) {
|
|
216
|
+
return resource.connect
|
|
217
|
+
? resource.constructor.loadAsInstance === false
|
|
218
|
+
? resource.connect(query, data)
|
|
219
|
+
: resource.connect(data, query)
|
|
220
|
+
: missingMethod(resource, 'connect');
|
|
221
|
+
},
|
|
222
|
+
{ hasContent: true, type: 'read', method: 'connect' }
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
static subscribe = transactional(
|
|
226
|
+
function (resource: Resource, query: RequestTarget, _request: Context, _data: any) {
|
|
227
|
+
return resource.subscribe ? resource.subscribe(query) : missingMethod(resource, 'subscribe');
|
|
228
|
+
},
|
|
229
|
+
{ type: 'read', method: 'subscribe', syncAllowed: true }
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
static publish = transactional(
|
|
233
|
+
function (resource: Resource, query: Map, _request: Context, data: any) {
|
|
234
|
+
if (resource.#id != null) resource.update?.(); // save any changes made during publish
|
|
235
|
+
return resource.publish
|
|
236
|
+
? resource.constructor.loadAsInstance === false
|
|
237
|
+
? resource.publish(query, data)
|
|
238
|
+
: resource.publish(data, query)
|
|
239
|
+
: missingMethod(resource, 'publish');
|
|
240
|
+
},
|
|
241
|
+
{ hasContent: true, type: 'create', method: 'publish' }
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
static search = transactional(
|
|
245
|
+
function (resource: Resource, query: Query, request: Context) {
|
|
246
|
+
const result = resource.search ? resource.search(query) : missingMethod(resource, 'search');
|
|
247
|
+
const select = request.select;
|
|
248
|
+
if (select && request.hasOwnProperty('select') && result != null && !result.selectApplied) {
|
|
249
|
+
const transform = transformForSelect(select, resource.constructor);
|
|
250
|
+
return result.map(transform);
|
|
251
|
+
}
|
|
252
|
+
return result;
|
|
253
|
+
},
|
|
254
|
+
{ type: 'read', method: 'search', hasContent: false, syncAllowed: true }
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
static query = transactional(
|
|
258
|
+
function (resource: Resource, query: Map, _request: Context, data: any) {
|
|
259
|
+
return resource.search
|
|
260
|
+
? resource.constructor.loadAsInstance === false
|
|
261
|
+
? resource.search(query, data)
|
|
262
|
+
: resource.search(data, query)
|
|
263
|
+
: missingMethod(resource, 'search');
|
|
264
|
+
},
|
|
265
|
+
{ hasContent: true, type: 'read', method: 'query' }
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
static copy = transactional(
|
|
269
|
+
function (resource: Resource, query: Map, _request: Context, data: any) {
|
|
270
|
+
return resource.copy
|
|
271
|
+
? resource.constructor.loadAsInstance === false
|
|
272
|
+
? resource.copy(query, data)
|
|
273
|
+
: resource.copy(data, query)
|
|
274
|
+
: missingMethod(resource, 'copy');
|
|
275
|
+
},
|
|
276
|
+
{ hasContent: true, type: 'create', method: 'copy' }
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
static move = transactional(
|
|
280
|
+
function (resource: Resource, query: Map, _request: Context, data: any) {
|
|
281
|
+
return resource.move
|
|
282
|
+
? resource.constructor.loadAsInstance === false
|
|
283
|
+
? resource.move(query, data)
|
|
284
|
+
: resource.move(data, query)
|
|
285
|
+
: missingMethod(resource, 'move');
|
|
286
|
+
},
|
|
287
|
+
{ hasContent: true, type: 'delete', method: 'move' }
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
async post(
|
|
291
|
+
target: RequestTargetOrId,
|
|
292
|
+
newRecord: Partial<Record & RecordObject>
|
|
293
|
+
): Promise<Record & Partial<RecordObject>> {
|
|
294
|
+
if (this.constructor.loadAsInstance === false) {
|
|
295
|
+
if (target.isCollection && this.create) {
|
|
296
|
+
newRecord = await this.create(target, newRecord);
|
|
297
|
+
return newRecord?.[this.constructor.primaryKey];
|
|
298
|
+
}
|
|
299
|
+
} else {
|
|
300
|
+
if (this.#isCollection) {
|
|
301
|
+
const resource = await this.constructor.create(this.#id, target, this.#context);
|
|
302
|
+
return resource.#id;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
missingMethod(this, 'post');
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
static isCollection(resource) {
|
|
309
|
+
return resource && resource.#isCollection;
|
|
310
|
+
}
|
|
311
|
+
get isCollection() {
|
|
312
|
+
return this.#isCollection;
|
|
313
|
+
}
|
|
314
|
+
static coerceId(id: string): number | string {
|
|
315
|
+
return id;
|
|
316
|
+
}
|
|
317
|
+
static parseQuery(search, query) {
|
|
318
|
+
return parseQuery(search, query);
|
|
319
|
+
}
|
|
320
|
+
static parsePath(path, context, query) {
|
|
321
|
+
const dotIndex = path.indexOf('.');
|
|
322
|
+
if (dotIndex > -1) {
|
|
323
|
+
// handle paths of the form /path/id.property
|
|
324
|
+
const property = path.slice(dotIndex + 1);
|
|
325
|
+
const requestedContentType = context?.headers && EXTENSION_TYPES[property];
|
|
326
|
+
if (requestedContentType) {
|
|
327
|
+
// handle path.json, path.cbor, etc. for requesting a specific content type using just the URL
|
|
328
|
+
context.requestedContentType = requestedContentType;
|
|
329
|
+
path = path.slice(0, dotIndex); // remove the property from the path
|
|
330
|
+
} else if (this.attributes?.find((attribute) => attribute.name === property)) {
|
|
331
|
+
// handle path.attribute for requesting a specific attribute using just the URL
|
|
332
|
+
path = path.slice(0, dotIndex); // remove the property from the path
|
|
333
|
+
if (query) query.property = property;
|
|
334
|
+
else {
|
|
335
|
+
return {
|
|
336
|
+
property,
|
|
337
|
+
id: path,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
return path;
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Gets an instance of a resource by id
|
|
346
|
+
* @param id
|
|
347
|
+
* @param request
|
|
348
|
+
* @param options
|
|
349
|
+
* @returns
|
|
350
|
+
*/
|
|
351
|
+
static getResource(
|
|
352
|
+
target: RequestTarget,
|
|
353
|
+
request: Context | SourceContext,
|
|
354
|
+
options?: any
|
|
355
|
+
): Resource | Promise<Resource> {
|
|
356
|
+
let resource;
|
|
357
|
+
const id = target.id;
|
|
358
|
+
let context = request.getContext?.();
|
|
359
|
+
let isCollection;
|
|
360
|
+
if (typeof request.isCollection === 'boolean' && request.hasOwnProperty('isCollection'))
|
|
361
|
+
isCollection = request.isCollection;
|
|
362
|
+
else isCollection = options?.isCollection;
|
|
363
|
+
// if it is a collection and we have a collection class defined, use it
|
|
364
|
+
const constructor = (isCollection && this.Collection) || this;
|
|
365
|
+
if (!context) context = context === undefined ? request : {};
|
|
366
|
+
resource = new constructor(id, context); // outside of a transaction, just create an instance
|
|
367
|
+
if (isCollection) resource.#isCollection = true;
|
|
368
|
+
return resource;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* This is called by protocols that wish to make a subscription for real-time notification/updates.
|
|
373
|
+
* This default implementation simply provides a streaming iterator that does not deliver any notifications
|
|
374
|
+
* but implementors can call send with
|
|
375
|
+
*/
|
|
376
|
+
// eslint-disable-next-line no-unused-vars
|
|
377
|
+
subscribe(request: SubscriptionRequest): AsyncIterable<Record> {
|
|
378
|
+
return new IterableEventQueue();
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
connect(target: RequestTarget, incomingMessages: IterableEventQueue<Record>): AsyncIterable<Record> {
|
|
382
|
+
// convert subscription to an (async) iterator
|
|
383
|
+
const query = this.constructor.loadAsInstance === false ? target : incomingMessages;
|
|
384
|
+
if (query?.subscribe !== false) {
|
|
385
|
+
// subscribing is the default action, but can be turned off
|
|
386
|
+
return this.subscribe?.(query);
|
|
387
|
+
}
|
|
388
|
+
return new IterableEventQueue();
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// Default permissions (super user only accesss):
|
|
392
|
+
// eslint-disable-next-line no-unused-vars
|
|
393
|
+
allowRead(user: User, target: RequestTarget, context: Context): boolean | Promise<boolean> {
|
|
394
|
+
return user?.role.permission.super_user;
|
|
395
|
+
}
|
|
396
|
+
// eslint-disable-next-line no-unused-vars
|
|
397
|
+
allowUpdate(user: User, record: Promise<Record & RecordObject>, context: Context): boolean | Promise<boolean> {
|
|
398
|
+
return user?.role.permission.super_user;
|
|
399
|
+
}
|
|
400
|
+
// eslint-disable-next-line no-unused-vars
|
|
401
|
+
allowCreate(user: User, record: Promise<Record & RecordObject>, context: Context): boolean | Promise<boolean> {
|
|
402
|
+
return user?.role.permission.super_user;
|
|
403
|
+
}
|
|
404
|
+
// eslint-disable-next-line no-unused-vars
|
|
405
|
+
allowDelete(user: User, target: RequestTarget, context: Context): boolean | Promise<boolean> {
|
|
406
|
+
return user?.role.permission.super_user;
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Get the primary key value for this resource.
|
|
410
|
+
* @returns primary key
|
|
411
|
+
*/
|
|
412
|
+
getId() {
|
|
413
|
+
return this.#id;
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Get the context for this resource
|
|
417
|
+
* @returns context object with information about the current transaction, user, and more
|
|
418
|
+
*/
|
|
419
|
+
getContext(): Context | SourceContext {
|
|
420
|
+
return this.#context;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Get the current user for the current request, based on the context.
|
|
425
|
+
* @returns user object or undefined if no user is logged in
|
|
426
|
+
*/
|
|
427
|
+
getCurrentUser(): User | undefined {
|
|
428
|
+
return (this.getContext() as Context)?.user;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
get?(
|
|
432
|
+
target?: RequestTargetOrId
|
|
433
|
+
):
|
|
434
|
+
| (Record & Partial<RecordObject>)
|
|
435
|
+
| Promise<Record & Partial<RecordObject>>
|
|
436
|
+
| AsyncIterable<Record & Partial<RecordObject>>
|
|
437
|
+
| Promise<AsyncIterable<Record & Partial<RecordObject>>>;
|
|
438
|
+
|
|
439
|
+
search?(target: RequestTargetOrId): AsyncIterable<Record & Partial<RecordObject>>;
|
|
440
|
+
|
|
441
|
+
create?(
|
|
442
|
+
newRecord: Partial<Record & RecordObject>,
|
|
443
|
+
target: RequestTargetOrId
|
|
444
|
+
): Promise<Record & Partial<RecordObject>>;
|
|
445
|
+
put?(
|
|
446
|
+
record: Record & RecordObject,
|
|
447
|
+
target: RequestTargetOrId
|
|
448
|
+
): void | (Record & Partial<RecordObject>) | Promise<void | (Record & Partial<RecordObject>)>;
|
|
449
|
+
patch?(
|
|
450
|
+
record: Partial<Record & RecordObject>,
|
|
451
|
+
target: RequestTargetOrId
|
|
452
|
+
): void | (Record & Partial<RecordObject>) | Promise<void | (Record & Partial<RecordObject>)>;
|
|
453
|
+
|
|
454
|
+
delete?(target: RequestTargetOrId): boolean | Promise<boolean>;
|
|
455
|
+
invalidate?(target: RequestTargetOrId): void | Promise<void>;
|
|
456
|
+
|
|
457
|
+
publish?(target: RequestTargetOrId, record: Record, options?: any): void;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
_assignPackageExport('Resource', Resource);
|
|
461
|
+
|
|
462
|
+
export function snakeCase(camelCase: string) {
|
|
463
|
+
return (
|
|
464
|
+
camelCase[0].toLowerCase() +
|
|
465
|
+
camelCase.slice(1).replace(/[a-z][A-Z][a-z]/g, (letters) => letters[0] + '_' + letters.slice(1))
|
|
466
|
+
);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* This is responsible for arranging arguments in the main static methods and creating the appropriate context and default transaction wrapping
|
|
471
|
+
* @param action
|
|
472
|
+
* @param options
|
|
473
|
+
* @returns
|
|
474
|
+
*/
|
|
475
|
+
function transactional(
|
|
476
|
+
action: (resource: ResourceInterface, query: RequestTarget, context: Context, data: any) => any,
|
|
477
|
+
options: {
|
|
478
|
+
hasContent: boolean;
|
|
479
|
+
type: 'read' | 'update' | 'create' | 'delete';
|
|
480
|
+
async?: boolean;
|
|
481
|
+
ensureLoaded?: boolean;
|
|
482
|
+
}
|
|
483
|
+
) {
|
|
484
|
+
applyContext.reliesOnPrototype = true;
|
|
485
|
+
const hasContent = options.hasContent;
|
|
486
|
+
return applyContext;
|
|
487
|
+
function applyContext(idOrQuery: string | Id | Query, dataOrContext?: any, context?: Context) {
|
|
488
|
+
let id, query, isCollection;
|
|
489
|
+
let data;
|
|
490
|
+
// First we do our argument normalization. There are two main types of methods, with or without content
|
|
491
|
+
if (hasContent) {
|
|
492
|
+
// for put, post, patch, publish, query
|
|
493
|
+
if (context) {
|
|
494
|
+
// if there are three arguments, it is id, data, context
|
|
495
|
+
data = dataOrContext;
|
|
496
|
+
context = context.getContext?.() || context;
|
|
497
|
+
} else if (dataOrContext) {
|
|
498
|
+
// two arguments, more possibilities:
|
|
499
|
+
if (
|
|
500
|
+
typeof idOrQuery === 'object' &&
|
|
501
|
+
idOrQuery &&
|
|
502
|
+
(!Array.isArray(idOrQuery) || typeof idOrQuery[0] === 'object')
|
|
503
|
+
) {
|
|
504
|
+
// (data, context) form
|
|
505
|
+
data = idOrQuery;
|
|
506
|
+
id = data[this.primaryKey] ?? null;
|
|
507
|
+
context = dataOrContext.getContext?.() || dataOrContext;
|
|
508
|
+
} else if (dataOrContext?.transaction instanceof DatabaseTransaction) {
|
|
509
|
+
// (id, context) form
|
|
510
|
+
context = dataOrContext;
|
|
511
|
+
} else {
|
|
512
|
+
// (id, data) form
|
|
513
|
+
data = dataOrContext;
|
|
514
|
+
}
|
|
515
|
+
} else if (idOrQuery && typeof idOrQuery === 'object') {
|
|
516
|
+
// single argument form, just data
|
|
517
|
+
data = idOrQuery;
|
|
518
|
+
idOrQuery = undefined;
|
|
519
|
+
id = data.getId?.() ?? data[this.primaryKey];
|
|
520
|
+
} else {
|
|
521
|
+
throw new ClientError(`Invalid argument for data, must be an object, but got ${idOrQuery}`);
|
|
522
|
+
}
|
|
523
|
+
if (id === null) isCollection = true;
|
|
524
|
+
// otherwise handle methods for get, delete, etc.
|
|
525
|
+
// first, check to see if it is two argument
|
|
526
|
+
} else if (dataOrContext) {
|
|
527
|
+
if (context) {
|
|
528
|
+
// (id, data, context), this a method that doesn't normally have a body/data, but with the three arguments, we have explicit data
|
|
529
|
+
data = dataOrContext;
|
|
530
|
+
context = context.getContext?.() || context;
|
|
531
|
+
} else if (hasContent === false) {
|
|
532
|
+
// (id, context), preferred form used for methods that are explicitly without a body
|
|
533
|
+
context = dataOrContext.getContext?.() || dataOrContext;
|
|
534
|
+
} else if (dataOrContext.transaction || dataOrContext.getContext) {
|
|
535
|
+
// or if it looks like a context
|
|
536
|
+
context = dataOrContext.getContext?.() || dataOrContext;
|
|
537
|
+
} else {
|
|
538
|
+
data = dataOrContext;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
if (id === undefined) {
|
|
542
|
+
if (typeof idOrQuery === 'object' && idOrQuery) {
|
|
543
|
+
// it is a query
|
|
544
|
+
query = idOrQuery;
|
|
545
|
+
if (idOrQuery instanceof URLSearchParams) {
|
|
546
|
+
// already RequestTarget (or URLSearchParams), consider it already parsed,
|
|
547
|
+
// we can just do property parsing, coerce, and assign the id
|
|
548
|
+
id = idOrQuery.id;
|
|
549
|
+
if (this.directURLMapping) {
|
|
550
|
+
id = idOrQuery.toString().slice(1); // remove the leading slash
|
|
551
|
+
query.id = id;
|
|
552
|
+
} else if (typeof id === 'string') {
|
|
553
|
+
// handle paths of the form /path/id.property
|
|
554
|
+
const parsedId = this.parsePath(id, context, query);
|
|
555
|
+
if (parsedId?.id !== undefined) {
|
|
556
|
+
query.property = parsedId.property;
|
|
557
|
+
id = parsedId.id;
|
|
558
|
+
} else {
|
|
559
|
+
id = parsedId;
|
|
560
|
+
}
|
|
561
|
+
if (id) {
|
|
562
|
+
query.id = id = this.coerceId(id);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
} else if (idOrQuery[Symbol.iterator]) {
|
|
566
|
+
// get the id part from an iterable query
|
|
567
|
+
id = [];
|
|
568
|
+
isCollection = true;
|
|
569
|
+
for (const part of idOrQuery) {
|
|
570
|
+
if (typeof part === 'object' && part) break;
|
|
571
|
+
id.push(part);
|
|
572
|
+
}
|
|
573
|
+
if (id.length === 0) id = null;
|
|
574
|
+
else {
|
|
575
|
+
if (id.length === 1) id = id[0];
|
|
576
|
+
if (query.slice) {
|
|
577
|
+
query = query.slice(id.length, query.length);
|
|
578
|
+
if (query.length === 0) {
|
|
579
|
+
query = new RequestTarget();
|
|
580
|
+
query.id = id;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
} else if (id === undefined) {
|
|
585
|
+
id = idOrQuery.id ?? null;
|
|
586
|
+
if (id == null) query.isCollection = true;
|
|
587
|
+
}
|
|
588
|
+
} else {
|
|
589
|
+
id = idOrQuery;
|
|
590
|
+
query = new RequestTarget();
|
|
591
|
+
query.id = id;
|
|
592
|
+
if (id == null) {
|
|
593
|
+
if (options.method === 'get') {
|
|
594
|
+
throw new Error(`Using an argument with a value of ${id} for ${options.method}, is not allowed`);
|
|
595
|
+
}
|
|
596
|
+
query.isCollection = true;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
if (!query) {
|
|
601
|
+
query = new RequestTarget();
|
|
602
|
+
query.id = id;
|
|
603
|
+
}
|
|
604
|
+
isCollection = query.isCollection;
|
|
605
|
+
let resourceOptions;
|
|
606
|
+
if (!context) {
|
|
607
|
+
// try to get the context from the async context if possible
|
|
608
|
+
context = contextStorage.getStore() ?? {};
|
|
609
|
+
}
|
|
610
|
+
if (query.ensureLoaded != null || query.async || isCollection) {
|
|
611
|
+
resourceOptions = { ...options };
|
|
612
|
+
if (query.ensureLoaded != null) resourceOptions.ensureLoaded = query.ensureLoaded;
|
|
613
|
+
if (query.syncAllowed) resourceOptions.syncAllowed = query.syncAllowed;
|
|
614
|
+
if (isCollection) resourceOptions.isCollection = true;
|
|
615
|
+
} else resourceOptions = options;
|
|
616
|
+
const loadAsInstance = this.loadAsInstance;
|
|
617
|
+
if (context?.transaction) {
|
|
618
|
+
// we are already in a transaction, proceed
|
|
619
|
+
const resource = this.getResource(query, context, resourceOptions);
|
|
620
|
+
return resource.then
|
|
621
|
+
? resource.then(authorizeActionOnResource)
|
|
622
|
+
: promiseNormalize(authorizeActionOnResource(resource), resourceOptions);
|
|
623
|
+
} else {
|
|
624
|
+
// start a transaction
|
|
625
|
+
return promiseNormalize(
|
|
626
|
+
transaction(context, () => {
|
|
627
|
+
// record what transaction we are starting from, so that if it times out, we can have an indication of the cause
|
|
628
|
+
context.transaction.startedFrom = {
|
|
629
|
+
resourceName: this.name,
|
|
630
|
+
method: options.method,
|
|
631
|
+
};
|
|
632
|
+
const resource = this.getResource(query, context, resourceOptions);
|
|
633
|
+
return resource.then ? resource.then(authorizeActionOnResource) : authorizeActionOnResource(resource);
|
|
634
|
+
}),
|
|
635
|
+
resourceOptions
|
|
636
|
+
);
|
|
637
|
+
}
|
|
638
|
+
function authorizeActionOnResource(resource: ResourceInterface) {
|
|
639
|
+
let checkPermission = false;
|
|
640
|
+
if (query.checkPermission) {
|
|
641
|
+
checkPermission = true;
|
|
642
|
+
// authorization has been requested, but only do it for this entry call
|
|
643
|
+
}
|
|
644
|
+
if (context.authorize) {
|
|
645
|
+
checkPermission = true;
|
|
646
|
+
// authorization has been requested, but only do it for this entry call
|
|
647
|
+
context.authorize = false;
|
|
648
|
+
query.checkPermission = true;
|
|
649
|
+
}
|
|
650
|
+
if (checkPermission) {
|
|
651
|
+
if (loadAsInstance !== false) {
|
|
652
|
+
// do permission checks, with allow methods
|
|
653
|
+
const allowed =
|
|
654
|
+
options.type === 'read'
|
|
655
|
+
? resource.allowRead(context.user, query, context)
|
|
656
|
+
: options.type === 'update'
|
|
657
|
+
? resource.doesExist?.() === false
|
|
658
|
+
? resource.allowCreate(context.user, data, context)
|
|
659
|
+
: resource.allowUpdate(context.user, data, context)
|
|
660
|
+
: options.type === 'create'
|
|
661
|
+
? resource.allowCreate(context.user, data, context)
|
|
662
|
+
: resource.allowDelete(context.user, query, context);
|
|
663
|
+
if (allowed?.then) {
|
|
664
|
+
return allowed.then((allowed) => {
|
|
665
|
+
query.checkPermission = false;
|
|
666
|
+
if (!allowed) {
|
|
667
|
+
throw new AccessViolation(context.user);
|
|
668
|
+
}
|
|
669
|
+
return when(data, (data) => {
|
|
670
|
+
return action(resource, query, context, data);
|
|
671
|
+
});
|
|
672
|
+
});
|
|
673
|
+
}
|
|
674
|
+
query.checkPermission = false;
|
|
675
|
+
if (!allowed) {
|
|
676
|
+
throw new AccessViolation(context.user);
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
return when(data, (data) => {
|
|
681
|
+
return action(resource, query, context, data);
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
function missingMethod(resource, method) {
|
|
687
|
+
const error = new ClientError(`The ${resource.constructor.name} does not have a ${method} method implemented`, 405);
|
|
688
|
+
error.allow = [];
|
|
689
|
+
error.method = method;
|
|
690
|
+
for (const method of ['get', 'put', 'post', 'delete', 'query', 'move', 'copy']) {
|
|
691
|
+
if (typeof resource[method] === 'function') error.allow.push(method);
|
|
692
|
+
}
|
|
693
|
+
throw error;
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* This is responsible for handling a select query parameter/call that selects specific
|
|
697
|
+
* properties from the returned record(s).
|
|
698
|
+
* @param object
|
|
699
|
+
* @returns
|
|
700
|
+
*/
|
|
701
|
+
function selectFromObject(object, propertyResolvers, context) {
|
|
702
|
+
// TODO: eventually we will do aggregate functions here
|
|
703
|
+
const record = object.getRecord?.();
|
|
704
|
+
if (record) {
|
|
705
|
+
const ownData = object.getChanges?.();
|
|
706
|
+
return (property) => {
|
|
707
|
+
let value, resolver;
|
|
708
|
+
if (object.hasOwnProperty(property) && typeof (value = object[property]) !== 'function') {
|
|
709
|
+
return value;
|
|
710
|
+
}
|
|
711
|
+
if (ownData && property in ownData) {
|
|
712
|
+
return ownData[property];
|
|
713
|
+
} else if ((resolver = propertyResolvers?.[property])) {
|
|
714
|
+
return resolver(object, context);
|
|
715
|
+
} else return record[property];
|
|
716
|
+
};
|
|
717
|
+
} else if (propertyResolvers) {
|
|
718
|
+
return (property) => {
|
|
719
|
+
const resolver = propertyResolvers[property];
|
|
720
|
+
return resolver ? resolver(object, context) : object[property];
|
|
721
|
+
};
|
|
722
|
+
} else return (property) => object[property];
|
|
723
|
+
}
|
|
724
|
+
export function transformForSelect(select, resource) {
|
|
725
|
+
const propertyResolvers = resource.propertyResolvers;
|
|
726
|
+
const context = resource.getContext?.();
|
|
727
|
+
let subTransforms;
|
|
728
|
+
if (typeof select === 'string')
|
|
729
|
+
// if select is a single string then return property value
|
|
730
|
+
return function transform(object) {
|
|
731
|
+
if (object.then) return object.then(transform);
|
|
732
|
+
if (Array.isArray(object)) return object.map(transform);
|
|
733
|
+
return selectFromObject(object, propertyResolvers, context)(select);
|
|
734
|
+
};
|
|
735
|
+
else if (typeof select === 'object') {
|
|
736
|
+
// if it is an array, return an array
|
|
737
|
+
if (select.asArray)
|
|
738
|
+
return function transform(object) {
|
|
739
|
+
if (object.then) return object.then(transform);
|
|
740
|
+
if (Array.isArray(object)) return object.map(transform);
|
|
741
|
+
const results = [];
|
|
742
|
+
const getProperty = handleProperty(selectFromObject(object, propertyResolvers, context));
|
|
743
|
+
for (const property of select) {
|
|
744
|
+
results.push(getProperty(property));
|
|
745
|
+
}
|
|
746
|
+
return results;
|
|
747
|
+
};
|
|
748
|
+
const forceNulls = select.forceNulls;
|
|
749
|
+
return function transform(object) {
|
|
750
|
+
if (object.then) return object.then(transform);
|
|
751
|
+
if (Array.isArray(object))
|
|
752
|
+
return object.map((value) => (value && typeof value === 'object' ? transform(value) : value));
|
|
753
|
+
// finally the case of returning objects
|
|
754
|
+
const selectedData = {};
|
|
755
|
+
const getProperty = handleProperty(selectFromObject(object, propertyResolvers, context));
|
|
756
|
+
let promises;
|
|
757
|
+
for (const property of select) {
|
|
758
|
+
let value = getProperty(property);
|
|
759
|
+
if (value === undefined && forceNulls) value = null;
|
|
760
|
+
if (value?.then) {
|
|
761
|
+
if (!promises) promises = [];
|
|
762
|
+
promises.push(value.then((value) => (selectedData[property.name || property] = value)));
|
|
763
|
+
} else selectedData[property.name || property] = value;
|
|
764
|
+
}
|
|
765
|
+
if (promises) return Promise.all(promises).then(() => selectedData);
|
|
766
|
+
return selectedData;
|
|
767
|
+
};
|
|
768
|
+
} else throw new Error('Invalid select argument type ' + typeof select);
|
|
769
|
+
function handleProperty(getProperty) {
|
|
770
|
+
return (property) => {
|
|
771
|
+
if (typeof property === 'string') {
|
|
772
|
+
return getProperty(property);
|
|
773
|
+
} else if (typeof property === 'object') {
|
|
774
|
+
// TODO: Handle aggregate functions
|
|
775
|
+
if (property.name) {
|
|
776
|
+
if (!subTransforms) subTransforms = {};
|
|
777
|
+
// TODO: Get the resource, cache this transform, and apply above
|
|
778
|
+
let transform = subTransforms[property.name];
|
|
779
|
+
if (!transform) {
|
|
780
|
+
const resource = propertyResolvers[property.name]?.definition?.tableClass;
|
|
781
|
+
transform = subTransforms[property.name] = transformForSelect(property.select || property, resource);
|
|
782
|
+
}
|
|
783
|
+
const value = getProperty(property.name);
|
|
784
|
+
return transform(value);
|
|
785
|
+
} else return getProperty(property);
|
|
786
|
+
} else return property;
|
|
787
|
+
};
|
|
788
|
+
}
|
|
789
|
+
}
|