@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,53 @@
|
|
|
1
|
+
import { resolveBaseURLPath } from './resolveBaseURLPath';
|
|
2
|
+
import { deriveCommonPatternBase } from './deriveCommonPatternBase';
|
|
3
|
+
import { deriveGlobOptions, FastGlobOptions, FilesOption } from './deriveGlobOptions';
|
|
4
|
+
import { scan } from 'micromatch';
|
|
5
|
+
|
|
6
|
+
interface ComponentConfig {
|
|
7
|
+
files: FilesOption;
|
|
8
|
+
urlPath?: string;
|
|
9
|
+
[key: string]: unknown;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type FileAndURLPathConfig = Pick<ComponentConfig, 'files' | 'urlPath'>;
|
|
13
|
+
|
|
14
|
+
export class ComponentInvalidPatternError extends Error {
|
|
15
|
+
constructor(pattern: string) {
|
|
16
|
+
super(`Config 'files' option glob pattern must not contain '..' or start with '/'. Received: '${pattern}'`);
|
|
17
|
+
this.name = 'ComponentInvalidPatternError';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export class Component {
|
|
22
|
+
readonly globOptions: FastGlobOptions;
|
|
23
|
+
readonly baseURLPath: string;
|
|
24
|
+
readonly patternBases: string[];
|
|
25
|
+
readonly directory: string;
|
|
26
|
+
readonly name: string;
|
|
27
|
+
readonly config: ComponentConfig;
|
|
28
|
+
readonly commonPatternBase: string;
|
|
29
|
+
|
|
30
|
+
constructor(name: string, directory: string, config: ComponentConfig) {
|
|
31
|
+
this.name = name;
|
|
32
|
+
this.directory = directory;
|
|
33
|
+
this.config = config;
|
|
34
|
+
|
|
35
|
+
this.baseURLPath = resolveBaseURLPath(this.name, this.config.urlPath);
|
|
36
|
+
|
|
37
|
+
this.globOptions = deriveGlobOptions(this.config.files);
|
|
38
|
+
this.globOptions.source = this.globOptions.source.map((pattern) => {
|
|
39
|
+
if (pattern.includes('..') || pattern.startsWith('/')) {
|
|
40
|
+
throw new ComponentInvalidPatternError(pattern);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (pattern === '.' || pattern === './') {
|
|
44
|
+
return '**/*';
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return pattern;
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
this.patternBases = this.globOptions.source.map((pattern) => scan(pattern).base);
|
|
51
|
+
this.commonPatternBase = deriveCommonPatternBase(this.patternBases);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
import { isMainThread } from 'node:worker_threads';
|
|
2
|
+
import fg from 'fast-glob';
|
|
3
|
+
import { Resources } from '../resources/Resources.ts';
|
|
4
|
+
import harperLogger from '../utility/logging/harper_logger.js';
|
|
5
|
+
import { resolveBaseURLPath } from './resolveBaseURLPath.ts';
|
|
6
|
+
import { deriveGlobOptions, FastGlobOptions, FilesOption } from './deriveGlobOptions.ts';
|
|
7
|
+
import { basename, join } from 'node:path';
|
|
8
|
+
import { readFile } from 'node:fs/promises';
|
|
9
|
+
import { deriveURLPath } from './deriveURLPath.ts';
|
|
10
|
+
import { scan } from 'micromatch';
|
|
11
|
+
|
|
12
|
+
interface ComponentV1Config {
|
|
13
|
+
files: string | string[] | FilesOption;
|
|
14
|
+
/** @deprecated */ path?: string;
|
|
15
|
+
urlPath?: string;
|
|
16
|
+
/** @deprecated */ root?: string;
|
|
17
|
+
[key: string]: any;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface ComponentV1Module {
|
|
21
|
+
setupDirectory?: (urlPath: string, absolutePath: string, resources: Resources) => Promise<undefined | boolean>;
|
|
22
|
+
handleDirectory?: (urlPath: string, absolutePath: string, resources: Resources) => Promise<undefined | boolean>;
|
|
23
|
+
setupFile?: (contents: Buffer, urlPath: string, absolutePath: string, resources: Resources) => Promise<void>;
|
|
24
|
+
handleFile?: (contents: Buffer, urlPath: string, absolutePath: string, resources: Resources) => Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface ComponentV1Details {
|
|
28
|
+
config: ComponentV1Config;
|
|
29
|
+
name: string;
|
|
30
|
+
directory: string;
|
|
31
|
+
module: ComponentV1Module;
|
|
32
|
+
resources: Resources;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export class ComponentV1 {
|
|
36
|
+
readonly config: Readonly<ComponentV1Config>;
|
|
37
|
+
readonly name: string;
|
|
38
|
+
readonly directory: string;
|
|
39
|
+
readonly module: Readonly<ComponentV1Module>;
|
|
40
|
+
readonly resources: Resources;
|
|
41
|
+
readonly globOptions: FastGlobOptions;
|
|
42
|
+
readonly patternBases: string[];
|
|
43
|
+
readonly baseURLPath: string;
|
|
44
|
+
|
|
45
|
+
constructor(options: ComponentV1Details) {
|
|
46
|
+
// TO DO: Unfortunately `readonly` is a TS only thing and doesn't actually enforce that these properties can't be modified.
|
|
47
|
+
// Freeze these things so they can't be changed. likely do this at the end of the constructor
|
|
48
|
+
this.config = options.config;
|
|
49
|
+
this.name = options.name;
|
|
50
|
+
this.directory = options.directory;
|
|
51
|
+
this.module = options.module;
|
|
52
|
+
this.resources = options.resources;
|
|
53
|
+
|
|
54
|
+
// Config option basic validation
|
|
55
|
+
if (
|
|
56
|
+
!isNonEmptyString(this.config.files) &&
|
|
57
|
+
!isArrayOfNonEmptyStrings(this.config.files) &&
|
|
58
|
+
!isObject(this.config.files)
|
|
59
|
+
) {
|
|
60
|
+
throw new InvalidFilesOptionError(this);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Validating the `files` object
|
|
64
|
+
if (typeof this.config.files === 'object' && !Array.isArray(this.config.files)) {
|
|
65
|
+
if (
|
|
66
|
+
this.config.files.source === undefined ||
|
|
67
|
+
(!isArrayOfNonEmptyStrings(this.config.files.source) && !isNonEmptyString(this.config.files.source))
|
|
68
|
+
) {
|
|
69
|
+
throw new InvalidFilesSourceOptionError(this);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (
|
|
73
|
+
this.config.files.only !== undefined &&
|
|
74
|
+
(typeof this.config.files.only !== 'string' ||
|
|
75
|
+
!['all', 'files', 'directories'].includes(this.config.files.only))
|
|
76
|
+
) {
|
|
77
|
+
throw new InvalidFilesOnlyOptionError(this);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (
|
|
81
|
+
this.config.files.ignore !== undefined &&
|
|
82
|
+
!isArrayOfNonEmptyStrings(this.config.files.ignore) &&
|
|
83
|
+
!isNonEmptyString(this.config.files.ignore)
|
|
84
|
+
) {
|
|
85
|
+
throw new InvalidFileIgnoreOptionError(this);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Validate the deprecated options too
|
|
90
|
+
if (this.config.root !== undefined && !isNonEmptyString(this.config.root)) {
|
|
91
|
+
throw new InvalidRootOptionError(this);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (this.config.path !== undefined && !isNonEmptyString(this.config.path)) {
|
|
95
|
+
throw new InvalidPathOptionError(this);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Handle deprecated `path` option
|
|
99
|
+
if (this.config.path) {
|
|
100
|
+
harperLogger.warn(`Resource extension 'path' option is deprecated. Please replace with 'urlPath'.`);
|
|
101
|
+
this.config.urlPath = this.config.path;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Validate the `urlPath`
|
|
105
|
+
if (
|
|
106
|
+
this.config.urlPath !== undefined &&
|
|
107
|
+
(!isNonEmptyString(this.config.urlPath) ||
|
|
108
|
+
(typeof this.config.urlPath === 'string' && this.config.urlPath.includes('..')))
|
|
109
|
+
) {
|
|
110
|
+
throw new InvalidURLPathOptionError(this);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
this.globOptions = deriveGlobOptions(this.config.files);
|
|
114
|
+
// Validate and transform glob patterns
|
|
115
|
+
this.globOptions.source = this.globOptions.source.map((pattern) => {
|
|
116
|
+
if (pattern.includes('..')) {
|
|
117
|
+
throw new InvalidGlobPattern(this, pattern);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (pattern.startsWith('/')) {
|
|
121
|
+
harperLogger.warn(
|
|
122
|
+
`Leading '/' in 'files' glob pattern is deprecated. For backwards compatibility purposes, it is currently transformed to the relative path of the component, but in the future will result in an error. Paths are automatically derived from the root of the component directory. Please remove (e.g. '/web/*' -> 'web/*').`
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
pattern = pattern === '/' ? '.' : pattern.slice(1);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return pattern;
|
|
129
|
+
});
|
|
130
|
+
this.patternBases = this.globOptions.source.map((pattern) => scan(pattern).base);
|
|
131
|
+
this.baseURLPath = resolveBaseURLPath(this.name, this.config.urlPath);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export class ComponentV1ProcessingError extends Error {
|
|
136
|
+
constructor(message: string, component: ComponentV1Details) {
|
|
137
|
+
super(`Component ${component.name} (from ${basename(component.directory)}) ${message}`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export class InvalidFilesOptionError extends ComponentV1ProcessingError {
|
|
142
|
+
constructor(component: ComponentV1Details) {
|
|
143
|
+
super(`'files' option must be a non-empty string, an array of non-empty strings, or an object.`, component);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export class InvalidFilesSourceOptionError extends ComponentV1ProcessingError {
|
|
148
|
+
constructor(component: ComponentV1Details) {
|
|
149
|
+
super(`'files' object must have a non-empty 'source' property.`, component);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export class InvalidFilesOnlyOptionError extends ComponentV1ProcessingError {
|
|
154
|
+
constructor(component: ComponentV1Details) {
|
|
155
|
+
super(`'files.only' option must be one of 'all', 'files', or 'directories'.`, component);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export class InvalidFileIgnoreOptionError extends ComponentV1ProcessingError {
|
|
160
|
+
constructor(component: ComponentV1Details) {
|
|
161
|
+
super(`'files.ignore' option must be a non-empty string or an array of non-empty strings.`, component);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export class InvalidGlobPattern extends ComponentV1ProcessingError {
|
|
166
|
+
constructor(component: ComponentV1Details, pattern: string) {
|
|
167
|
+
super(`'files' glob pattern must not contain '..'. Received: '${pattern}'`, component);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export class InvalidRootOptionError extends ComponentV1ProcessingError {
|
|
172
|
+
constructor(component: ComponentV1Details) {
|
|
173
|
+
super(
|
|
174
|
+
`deprecated 'root' option must be a non-empty string. Consider removing and updating 'files' glob pattern instead.`,
|
|
175
|
+
component
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export class InvalidRootOptionUseError extends ComponentV1ProcessingError {
|
|
181
|
+
constructor(component: ComponentV1Details) {
|
|
182
|
+
super(
|
|
183
|
+
`the 'root' option is deprecated and only supported if 'files' is a singular, non-empty string. Please remove the 'root' option and modify the 'files' glob pattern instead.`,
|
|
184
|
+
component
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export class InvalidPathOptionError extends ComponentV1ProcessingError {
|
|
190
|
+
constructor(component: ComponentV1Details) {
|
|
191
|
+
super(`deprecated 'path' option must be a non-empty string. Consider replacing with 'urlPath'.`, component);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export class InvalidURLPathOptionError extends ComponentV1ProcessingError {
|
|
196
|
+
constructor(component: ComponentV1Details) {
|
|
197
|
+
super(`'urlPath' option must be a non-empty string that must not contain '..'.`, component);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function isNonEmptyString(value: unknown): value is string {
|
|
202
|
+
return typeof value === 'string' && value.trim() !== '';
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function isArrayOfNonEmptyStrings(value: unknown): value is string[] {
|
|
206
|
+
return Array.isArray(value) && value.length !== 0 && value.every((item) => isNonEmptyString(item));
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function isObject(value: unknown): value is Record<string, unknown> {
|
|
210
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
async function handleRoots(component: ComponentV1) {
|
|
214
|
+
if (component.config.root) {
|
|
215
|
+
harperLogger.warn(
|
|
216
|
+
`Resource extension 'root' option is deprecated. Due to backwards compatibility reasons it does not act as assumed. The glob pattern will always be evaluated from the component directory root. The option is only used for the initial root directory handling. Please remove and modify the 'files' glob pattern instead.`
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// For backwards compatibility, we need to evaluate the root path via the existing logic. This is only valid if `root` is defined, and `files` is a strings that doesn't contain `**/*`,
|
|
221
|
+
// And if that existing logic does not produce a reasonable root path to evaluate, we can consider the configure "new" and evaluate it based on a new process
|
|
222
|
+
|
|
223
|
+
let rootPaths: string[] = [];
|
|
224
|
+
|
|
225
|
+
if (component.config.root && typeof component.config.files !== 'string') {
|
|
226
|
+
throw new InvalidRootOptionUseError(component);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// This starts old root handling
|
|
230
|
+
let rootPath = component.config.root;
|
|
231
|
+
|
|
232
|
+
if (rootPath) {
|
|
233
|
+
// trim any leading slashes
|
|
234
|
+
if (rootPath.startsWith('/')) {
|
|
235
|
+
rootPath = rootPath.slice(1);
|
|
236
|
+
}
|
|
237
|
+
// add a trailing slash if it doesn't exist
|
|
238
|
+
if (!rootPath.endsWith('/')) {
|
|
239
|
+
rootPath += '/';
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const pattern = component.config.files;
|
|
244
|
+
|
|
245
|
+
// This is still old root handling logic - operate only a singular pattern
|
|
246
|
+
if (typeof pattern === 'string' && !pattern.includes('**/*')) {
|
|
247
|
+
if (pattern.indexOf('/*') > -1) {
|
|
248
|
+
rootPath = pattern.slice(0, pattern.indexOf('/*') + 1);
|
|
249
|
+
} else if (pattern.indexOf('/') > -1) {
|
|
250
|
+
rootPath = pattern.slice(0, pattern.lastIndexOf('/') + 1);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (rootPath) rootPaths.push(rootPath);
|
|
255
|
+
|
|
256
|
+
// If old handling did not result in a root path, now use the patternRoots derived from the processed glob patterns
|
|
257
|
+
if (rootPaths.length === 0) {
|
|
258
|
+
// Return early if we are only processing files
|
|
259
|
+
if (isObject(component.config.files) && component.config.files.only === 'files') {
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
rootPaths = component.patternBases;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
let hasFunctionality: boolean | undefined = false;
|
|
267
|
+
|
|
268
|
+
for (const rootPath of rootPaths) {
|
|
269
|
+
const rootPathAbsolute = join(component.directory, rootPath);
|
|
270
|
+
|
|
271
|
+
if (isMainThread && component.module.setupDirectory) {
|
|
272
|
+
hasFunctionality = await component.module.setupDirectory(
|
|
273
|
+
component.baseURLPath,
|
|
274
|
+
rootPathAbsolute,
|
|
275
|
+
component.resources
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
if (component.resources.isWorker && component.module.handleDirectory) {
|
|
279
|
+
hasFunctionality = await component.module.handleDirectory(
|
|
280
|
+
component.baseURLPath,
|
|
281
|
+
rootPathAbsolute,
|
|
282
|
+
component.resources
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
return hasFunctionality;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Process a Resource Extension component by evaluating the files glob pattern
|
|
292
|
+
* and then calling the appropriate setup/handle functions.
|
|
293
|
+
*/
|
|
294
|
+
export async function processResourceExtensionComponent(component: ComponentV1) {
|
|
295
|
+
let hasFunctionality: boolean | undefined = false;
|
|
296
|
+
|
|
297
|
+
hasFunctionality = await handleRoots(component);
|
|
298
|
+
|
|
299
|
+
// Return early if roots were functional
|
|
300
|
+
if (hasFunctionality) return hasFunctionality;
|
|
301
|
+
|
|
302
|
+
const matches = await fg(component.globOptions.source, {
|
|
303
|
+
cwd: component.directory,
|
|
304
|
+
objectMode: true,
|
|
305
|
+
onlyFiles: component.globOptions.onlyFiles,
|
|
306
|
+
onlyDirectories: component.globOptions.onlyDirectories,
|
|
307
|
+
ignore: component.globOptions.ignore,
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
for (const entry of matches) {
|
|
311
|
+
const absolutePath = join(component.directory, entry.path);
|
|
312
|
+
|
|
313
|
+
if (entry.dirent.isDirectory()) {
|
|
314
|
+
const urlPath = deriveURLPath(component, entry.path, 'directory');
|
|
315
|
+
if (isMainThread && component.module.setupDirectory) {
|
|
316
|
+
await component.module.setupDirectory(urlPath, absolutePath, component.resources);
|
|
317
|
+
hasFunctionality = true;
|
|
318
|
+
}
|
|
319
|
+
if (component.resources.isWorker && component.module.handleDirectory) {
|
|
320
|
+
await component.module.handleDirectory(urlPath, absolutePath, component.resources);
|
|
321
|
+
hasFunctionality = true;
|
|
322
|
+
}
|
|
323
|
+
} else if (entry.dirent.isFile()) {
|
|
324
|
+
const urlPath = deriveURLPath(component, entry.path, 'file');
|
|
325
|
+
const contents = await readFile(absolutePath);
|
|
326
|
+
if (isMainThread && component.module.setupFile) {
|
|
327
|
+
await component.module.setupFile(contents, urlPath, absolutePath, component.resources);
|
|
328
|
+
hasFunctionality = true;
|
|
329
|
+
} else if (component.resources.isWorker && component.module.handleFile) {
|
|
330
|
+
await component.module.handleFile(contents, urlPath, absolutePath, component.resources);
|
|
331
|
+
hasFunctionality = true;
|
|
332
|
+
}
|
|
333
|
+
} else {
|
|
334
|
+
harperLogger.error(
|
|
335
|
+
`Entry received from glob pattern match for component ${component.name} is neither a file nor a directory:`,
|
|
336
|
+
entry
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
return hasFunctionality;
|
|
342
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export const DEFAULT_CONFIG = {
|
|
2
|
+
rest: true,
|
|
3
|
+
graphqlSchema: {
|
|
4
|
+
files: '*.graphql',
|
|
5
|
+
},
|
|
6
|
+
roles: {
|
|
7
|
+
files: 'roles.yaml',
|
|
8
|
+
},
|
|
9
|
+
jsResource: {
|
|
10
|
+
files: 'resources.js',
|
|
11
|
+
},
|
|
12
|
+
fastifyRoutes: {
|
|
13
|
+
files: 'routes/*.js',
|
|
14
|
+
},
|
|
15
|
+
static: {
|
|
16
|
+
files: 'web/**',
|
|
17
|
+
},
|
|
18
|
+
};
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { type Logger } from '../utility/logging/logger.ts';
|
|
2
|
+
import { loggerWithTag } from '../utility/logging/harper_logger.js';
|
|
3
|
+
import type { Stats } from 'node:fs';
|
|
4
|
+
import { EventEmitter, once } from 'node:events';
|
|
5
|
+
import { Component, FileAndURLPathConfig } from './Component.js';
|
|
6
|
+
import chokidar, { FSWatcher, FSWatcherEventMap } from 'chokidar';
|
|
7
|
+
import { join } from 'node:path';
|
|
8
|
+
import { readFile } from 'node:fs/promises';
|
|
9
|
+
import { FilesOption } from './deriveGlobOptions.js';
|
|
10
|
+
import { deriveURLPath } from './deriveURLPath.js';
|
|
11
|
+
import { isMatch } from 'micromatch';
|
|
12
|
+
|
|
13
|
+
export interface BaseEntry {
|
|
14
|
+
stats?: Stats;
|
|
15
|
+
urlPath: string;
|
|
16
|
+
absolutePath: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface FileEntry extends BaseEntry {
|
|
20
|
+
contents: Buffer;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface EntryEvent extends BaseEntry {
|
|
24
|
+
eventType: string;
|
|
25
|
+
entryType: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface AddFileEvent extends EntryEvent, FileEntry {
|
|
29
|
+
eventType: 'add';
|
|
30
|
+
entryType: 'file';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface ChangeFileEvent extends EntryEvent, FileEntry {
|
|
34
|
+
eventType: 'change';
|
|
35
|
+
entryType: 'file';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface UnlinkFileEvent extends EntryEvent {
|
|
39
|
+
eventType: 'unlink';
|
|
40
|
+
entryType: 'file';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export type FileEntryEvent = AddFileEvent | ChangeFileEvent | UnlinkFileEvent;
|
|
44
|
+
|
|
45
|
+
export interface AddDirectoryEvent extends EntryEvent {
|
|
46
|
+
eventType: 'addDir';
|
|
47
|
+
entryType: 'directory';
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface UnlinkDirectoryEvent extends EntryEvent {
|
|
51
|
+
eventType: 'unlinkDir';
|
|
52
|
+
entryType: 'directory';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export type DirectoryEntryEvent = AddDirectoryEvent | UnlinkDirectoryEvent;
|
|
56
|
+
|
|
57
|
+
export type onEntryEventHandler = (entry: FileEntryEvent | DirectoryEntryEvent) => void | Promise<void>;
|
|
58
|
+
|
|
59
|
+
export type EntryHandlerEventMap = {
|
|
60
|
+
all: [entry: FileEntryEvent | DirectoryEntryEvent];
|
|
61
|
+
close: [];
|
|
62
|
+
error: [error: unknown];
|
|
63
|
+
ready: [];
|
|
64
|
+
initialLoadComplete: [];
|
|
65
|
+
add: [entry: AddFileEvent];
|
|
66
|
+
change: [entry: ChangeFileEvent];
|
|
67
|
+
unlink: [entry: UnlinkFileEvent];
|
|
68
|
+
addDir: [entry: AddDirectoryEvent];
|
|
69
|
+
unlinkDir: [entry: UnlinkDirectoryEvent];
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export class EntryHandler extends EventEmitter<EntryHandlerEventMap> {
|
|
73
|
+
#component: Component;
|
|
74
|
+
#watcher?: FSWatcher;
|
|
75
|
+
#logger: Logger;
|
|
76
|
+
#pendingFileReads: Set<Promise<void>>;
|
|
77
|
+
#isInitialScanComplete: boolean;
|
|
78
|
+
ready: Promise<any[]>;
|
|
79
|
+
|
|
80
|
+
constructor(name: string, directory: string, config: FilesOption | FileAndURLPathConfig, logger?: Logger) {
|
|
81
|
+
super();
|
|
82
|
+
|
|
83
|
+
this.#component = new Component(name, directory, castConfig(config));
|
|
84
|
+
this.#logger = logger || loggerWithTag(name);
|
|
85
|
+
this.#pendingFileReads = new Set();
|
|
86
|
+
this.#isInitialScanComplete = false;
|
|
87
|
+
this.ready = once(this, 'ready');
|
|
88
|
+
this.#watch();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
get name(): string {
|
|
92
|
+
return this.#component.name;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
get directory(): string {
|
|
96
|
+
return this.#component.directory;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
#handleAll(...[event, path, stats]: FSWatcherEventMap['all']): void {
|
|
100
|
+
if (path === '') path = '/';
|
|
101
|
+
|
|
102
|
+
if (!isMatch(path, this.#component.globOptions.source, { ignore: this.#component.globOptions.ignore })) return;
|
|
103
|
+
|
|
104
|
+
const absolutePath = join(this.directory, path);
|
|
105
|
+
|
|
106
|
+
switch (event) {
|
|
107
|
+
case 'add':
|
|
108
|
+
case 'change': {
|
|
109
|
+
const urlPath = deriveURLPath(this.#component, path, 'file');
|
|
110
|
+
const fileReadPromise = readFile(absolutePath)
|
|
111
|
+
.then((contents) => {
|
|
112
|
+
const entry: AddFileEvent | ChangeFileEvent = {
|
|
113
|
+
eventType: event,
|
|
114
|
+
entryType: 'file' as const,
|
|
115
|
+
contents,
|
|
116
|
+
stats,
|
|
117
|
+
absolutePath,
|
|
118
|
+
urlPath,
|
|
119
|
+
};
|
|
120
|
+
this.emit('all', entry);
|
|
121
|
+
this.emit(event, entry as any);
|
|
122
|
+
})
|
|
123
|
+
.finally(() => {
|
|
124
|
+
this.#pendingFileReads.delete(fileReadPromise);
|
|
125
|
+
this.#checkIfAllComplete();
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
this.#pendingFileReads.add(fileReadPromise);
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
case 'unlink': {
|
|
132
|
+
const urlPath = deriveURLPath(this.#component, path, 'file');
|
|
133
|
+
const entry: UnlinkFileEvent = {
|
|
134
|
+
eventType: event,
|
|
135
|
+
entryType: 'file',
|
|
136
|
+
stats,
|
|
137
|
+
absolutePath,
|
|
138
|
+
urlPath,
|
|
139
|
+
};
|
|
140
|
+
this.emit('all', entry);
|
|
141
|
+
this.emit(event, entry);
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
case 'addDir':
|
|
145
|
+
case 'unlinkDir': {
|
|
146
|
+
const urlPath = deriveURLPath(this.#component, path, 'directory');
|
|
147
|
+
const entry: DirectoryEntryEvent = {
|
|
148
|
+
eventType: event,
|
|
149
|
+
entryType: 'directory' as const,
|
|
150
|
+
stats,
|
|
151
|
+
absolutePath,
|
|
152
|
+
urlPath,
|
|
153
|
+
};
|
|
154
|
+
this.emit('all', entry);
|
|
155
|
+
this.emit(event, entry as any);
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
#handleError(error: unknown): void {
|
|
162
|
+
this.emit('error', error);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
#handleReady(): void {
|
|
166
|
+
this.#isInitialScanComplete = true;
|
|
167
|
+
if (this.#pendingFileReads.size > 0) {
|
|
168
|
+
this.#logger.debug?.(
|
|
169
|
+
`Initial scan complete, still waiting for ${this.#pendingFileReads.size} pending file reads`
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
this.#checkIfAllComplete();
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
#checkIfAllComplete(): void {
|
|
176
|
+
// Only emit 'ready' once the initial scan is complete AND all file reads are done
|
|
177
|
+
if (this.#isInitialScanComplete && this.#pendingFileReads.size === 0) {
|
|
178
|
+
this.emit('ready');
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
async #watch() {
|
|
183
|
+
await this.#watcher?.close();
|
|
184
|
+
this.#watcher = undefined;
|
|
185
|
+
|
|
186
|
+
const allowedBases = this.#component.patternBases.map((base) => join(this.#component.directory, base));
|
|
187
|
+
|
|
188
|
+
this.#watcher = chokidar
|
|
189
|
+
.watch(this.#component.commonPatternBase, {
|
|
190
|
+
cwd: this.#component.directory,
|
|
191
|
+
persistent: false,
|
|
192
|
+
ignored: (path) => {
|
|
193
|
+
const normalizedPath = path.replace(/\\/g, '/');
|
|
194
|
+
const normalizedBases = allowedBases.map((base) => base.replace(/\\/g, '/'));
|
|
195
|
+
return (
|
|
196
|
+
normalizedPath !== this.#component.directory.replace(/\\/g, '/') &&
|
|
197
|
+
normalizedBases.every((base) => !normalizedPath.startsWith(base))
|
|
198
|
+
);
|
|
199
|
+
},
|
|
200
|
+
})
|
|
201
|
+
.on('all', this.#handleAll.bind(this))
|
|
202
|
+
.on('error', this.#handleError.bind(this))
|
|
203
|
+
.on('ready', this.#handleReady.bind(this));
|
|
204
|
+
|
|
205
|
+
return this.ready;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
close(): this {
|
|
209
|
+
this.#watcher?.close();
|
|
210
|
+
this.#watcher = undefined;
|
|
211
|
+
|
|
212
|
+
this.emit('close');
|
|
213
|
+
this.removeAllListeners();
|
|
214
|
+
|
|
215
|
+
return this;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
update(config: FilesOption | FileAndURLPathConfig) {
|
|
219
|
+
this.#component = new Component(this.name, this.directory, castConfig(config));
|
|
220
|
+
|
|
221
|
+
return this.#watch();
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function castConfig(config: FilesOption | FileAndURLPathConfig): FileAndURLPathConfig {
|
|
226
|
+
return typeof config === 'string' || Array.isArray(config) || !('files' in config) ? { files: config } : config;
|
|
227
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface Logger {
|
|
2
|
+
logLevel: string;
|
|
3
|
+
|
|
4
|
+
notify?: (...args: any[]) => void;
|
|
5
|
+
fatal?: (...args: any[]) => void;
|
|
6
|
+
error?: (...args: any[]) => void;
|
|
7
|
+
warn?: (...args: any[]) => void;
|
|
8
|
+
info?: (...args: any[]) => void;
|
|
9
|
+
debug?: (...args: any[]) => void;
|
|
10
|
+
trace?: (...args: any[]) => void;
|
|
11
|
+
|
|
12
|
+
withTag: (tag: string) => Logger;
|
|
13
|
+
loggerWithTag: (tag: string) => Logger;
|
|
14
|
+
}
|