@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.
Files changed (444) hide show
  1. package/bin/BinObjects.js +17 -0
  2. package/bin/cliOperations.js +157 -0
  3. package/bin/copyDb.ts +280 -0
  4. package/bin/harper.js +156 -0
  5. package/bin/install.js +15 -0
  6. package/bin/lite.js +5 -0
  7. package/bin/restart.js +201 -0
  8. package/bin/run.js +409 -0
  9. package/bin/status.js +65 -0
  10. package/bin/stop.js +22 -0
  11. package/bin/upgrade.js +134 -0
  12. package/components/Application.ts +646 -0
  13. package/components/ApplicationScope.ts +49 -0
  14. package/components/Component.ts +53 -0
  15. package/components/ComponentV1.ts +342 -0
  16. package/components/DEFAULT_CONFIG.ts +18 -0
  17. package/components/EntryHandler.ts +227 -0
  18. package/components/Logger.ts +14 -0
  19. package/components/OptionsWatcher.ts +354 -0
  20. package/components/PluginModule.ts +6 -0
  21. package/components/Scope.ts +329 -0
  22. package/components/componentLoader.ts +529 -0
  23. package/components/deriveCommonPatternBase.ts +31 -0
  24. package/components/deriveGlobOptions.ts +44 -0
  25. package/components/deriveURLPath.ts +57 -0
  26. package/components/operations.js +658 -0
  27. package/components/operationsValidation.js +246 -0
  28. package/components/packageComponent.ts +39 -0
  29. package/components/requestRestart.ts +26 -0
  30. package/components/resolveBaseURLPath.ts +38 -0
  31. package/components/status/ComponentStatus.ts +110 -0
  32. package/components/status/ComponentStatusRegistry.ts +251 -0
  33. package/components/status/api.ts +153 -0
  34. package/components/status/crossThread.ts +405 -0
  35. package/components/status/errors.ts +152 -0
  36. package/components/status/index.ts +44 -0
  37. package/components/status/internal.ts +65 -0
  38. package/components/status/registry.ts +12 -0
  39. package/components/status/types.ts +96 -0
  40. package/config/RootConfigWatcher.ts +59 -0
  41. package/config/configHelpers.ts +11 -0
  42. package/config/configUtils.js +967 -0
  43. package/config/harperConfigEnvVars.ts +641 -0
  44. package/dataLayer/CreateAttributeObject.js +25 -0
  45. package/dataLayer/CreateTableObject.js +11 -0
  46. package/dataLayer/DataLayerObjects.js +43 -0
  47. package/dataLayer/DeleteBeforeObject.js +22 -0
  48. package/dataLayer/DeleteObject.js +25 -0
  49. package/dataLayer/DropAttributeObject.js +11 -0
  50. package/dataLayer/GetBackupObject.js +22 -0
  51. package/dataLayer/InsertObject.js +24 -0
  52. package/dataLayer/ReadAuditLogObject.js +24 -0
  53. package/dataLayer/SQLSearch.js +1335 -0
  54. package/dataLayer/SearchByConditionsObject.js +61 -0
  55. package/dataLayer/SearchByHashObject.js +21 -0
  56. package/dataLayer/SearchObject.js +45 -0
  57. package/dataLayer/SqlSearchObject.js +14 -0
  58. package/dataLayer/UpdateObject.js +23 -0
  59. package/dataLayer/UpsertObject.js +23 -0
  60. package/dataLayer/bulkLoad.js +813 -0
  61. package/dataLayer/dataObjects/BulkLoadObjects.js +27 -0
  62. package/dataLayer/dataObjects/UpsertObject.js +23 -0
  63. package/dataLayer/delete.js +164 -0
  64. package/dataLayer/export.js +381 -0
  65. package/dataLayer/getBackup.js +40 -0
  66. package/dataLayer/harperBridge/BridgeMethods.js +81 -0
  67. package/dataLayer/harperBridge/ResourceBridge.ts +633 -0
  68. package/dataLayer/harperBridge/bridgeUtility/insertUpdateReturnObj.js +28 -0
  69. package/dataLayer/harperBridge/bridgeUtility/insertUpdateValidate.js +88 -0
  70. package/dataLayer/harperBridge/harperBridge.js +21 -0
  71. package/dataLayer/harperBridge/lmdbBridge/LMDBBridge.js +119 -0
  72. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.js +19 -0
  73. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateAttribute.js +112 -0
  74. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateRecords.js +67 -0
  75. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateSchema.js +31 -0
  76. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateTable.js +94 -0
  77. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDeleteAuditLogsBefore.js +98 -0
  78. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDeleteRecords.js +89 -0
  79. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDropAttribute.js +109 -0
  80. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDropSchema.js +107 -0
  81. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDropTable.js +137 -0
  82. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbFlush.js +35 -0
  83. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbGetBackup.js +111 -0
  84. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbGetDataByHash.js +28 -0
  85. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbGetDataByValue.js +29 -0
  86. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbReadAuditLog.js +207 -0
  87. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbSearchByConditions.js +156 -0
  88. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbSearchByHash.js +21 -0
  89. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbSearchByValue.js +30 -0
  90. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbTransaction.js +19 -0
  91. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbUpdateRecords.js +64 -0
  92. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbUpsertRecords.js +70 -0
  93. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBCreateAttributeObject.js +22 -0
  94. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBDeleteTransactionObject.js +23 -0
  95. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBInsertTransactionObject.js +22 -0
  96. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBTransactionObject.js +23 -0
  97. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBUpdateTransactionObject.js +24 -0
  98. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBUpsertTransactionObject.js +24 -0
  99. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/TableSizeObject.js +25 -0
  100. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/initializeHashSearch.js +21 -0
  101. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/initializePaths.js +157 -0
  102. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbCheckForNewAttributes.js +94 -0
  103. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbCreateTransactionsAuditEnvironment.js +39 -0
  104. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbGetTableSize.js +34 -0
  105. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbProcessRows.js +100 -0
  106. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbSearch.js +371 -0
  107. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbWriteTransaction.js +109 -0
  108. package/dataLayer/hdbInfoController.js +254 -0
  109. package/dataLayer/insert.js +266 -0
  110. package/dataLayer/readAuditLog.js +59 -0
  111. package/dataLayer/schema.js +366 -0
  112. package/dataLayer/schemaDescribe.js +289 -0
  113. package/dataLayer/search.js +60 -0
  114. package/dataLayer/transaction.js +17 -0
  115. package/dataLayer/update.js +124 -0
  116. package/dist/components/Logger.d.ts +12 -0
  117. package/dist/components/Logger.js +3 -0
  118. package/dist/components/Logger.js.map +1 -0
  119. package/dist/components/Scope.d.ts +14 -4
  120. package/dist/components/Scope.js +18 -10
  121. package/dist/components/Scope.js.map +1 -1
  122. package/dist/components/componentLoader.js +16 -9
  123. package/dist/components/componentLoader.js.map +1 -1
  124. package/dist/components/operations.js +2 -2
  125. package/dist/components/operations.js.map +1 -1
  126. package/dist/config/configUtils.d.ts +1 -1
  127. package/dist/config/configUtils.js +1 -1
  128. package/dist/config/configUtils.js.map +1 -1
  129. package/dist/dataLayer/CreateTableObject.d.ts +2 -2
  130. package/dist/dataLayer/CreateTableObject.js +2 -2
  131. package/dist/dataLayer/CreateTableObject.js.map +1 -1
  132. package/dist/dataLayer/delete.d.ts +1 -1
  133. package/dist/dataLayer/schema.js +6 -5
  134. package/dist/dataLayer/schema.js.map +1 -1
  135. package/dist/dataLayer/schemaDescribe.js +1 -1
  136. package/dist/dataLayer/schemaDescribe.js.map +1 -1
  137. package/dist/index.d.ts +1 -1
  138. package/dist/index.js +2 -0
  139. package/dist/index.js.map +1 -1
  140. package/dist/resources/DatabaseTransaction.d.ts +1 -1
  141. package/dist/resources/IterableEventQueue.d.ts +1 -1
  142. package/dist/resources/LMDBTransaction.d.ts +5 -1
  143. package/dist/resources/Resource.d.ts +1 -1
  144. package/dist/resources/RocksIndexStore.d.ts +3 -3
  145. package/dist/resources/RocksTransactionLogStore.d.ts +6 -3
  146. package/dist/resources/Table.d.ts +15 -6
  147. package/dist/resources/Table.js +4 -1
  148. package/dist/resources/Table.js.map +1 -1
  149. package/dist/resources/analytics/read.js +32 -22
  150. package/dist/resources/analytics/read.js.map +1 -1
  151. package/dist/resources/analytics/write.js +3 -6
  152. package/dist/resources/analytics/write.js.map +1 -1
  153. package/dist/resources/auditStore.d.ts +3 -3
  154. package/dist/resources/blob.d.ts +25 -2
  155. package/dist/resources/databases.d.ts +12 -2
  156. package/dist/resources/databases.js +22 -19
  157. package/dist/resources/databases.js.map +1 -1
  158. package/dist/resources/search.js +11 -5
  159. package/dist/resources/search.js.map +1 -1
  160. package/dist/resources/transaction.d.ts +2 -1
  161. package/dist/security/auth.js +1 -1
  162. package/dist/security/auth.js.map +1 -1
  163. package/dist/security/cryptoHash.d.ts +2 -2
  164. package/dist/security/jsLoader.js +243 -66
  165. package/dist/security/jsLoader.js.map +1 -1
  166. package/dist/security/keys.js +4 -5
  167. package/dist/security/keys.js.map +1 -1
  168. package/dist/security/user.js +3 -3
  169. package/dist/security/user.js.map +1 -1
  170. package/dist/server/REST.js +16 -2
  171. package/dist/server/REST.js.map +1 -1
  172. package/dist/server/Server.d.ts +2 -1
  173. package/dist/server/Server.js.map +1 -1
  174. package/dist/server/fastifyRoutes/plugins/hdbCore.d.ts +6 -1
  175. package/dist/server/fastifyRoutes.js +2 -0
  176. package/dist/server/fastifyRoutes.js.map +1 -1
  177. package/dist/server/http.js +12 -6
  178. package/dist/server/http.js.map +1 -1
  179. package/dist/server/jobs/JobObject.d.ts +3 -3
  180. package/dist/server/loadRootComponents.js +1 -0
  181. package/dist/server/loadRootComponents.js.map +1 -1
  182. package/dist/server/operationsServer.js +3 -1
  183. package/dist/server/operationsServer.js.map +1 -1
  184. package/dist/server/serverHelpers/JSONStream.d.ts +3 -3
  185. package/dist/server/serverHelpers/Request.d.ts +5 -5
  186. package/dist/server/serverHelpers/requestTimePlugin.d.ts +1 -1
  187. package/dist/server/threads/manageThreads.d.ts +2 -2
  188. package/dist/server/threads/manageThreads.js +50 -35
  189. package/dist/server/threads/manageThreads.js.map +1 -1
  190. package/dist/server/threads/socketRouter.d.ts +1 -1
  191. package/dist/sqlTranslator/deleteTranslator.d.ts +1 -1
  192. package/dist/utility/AWS/AWSConnector.d.ts +3 -2
  193. package/dist/utility/common_utils.d.ts +3 -3
  194. package/dist/utility/environment/systemInformation.d.ts +1 -0
  195. package/dist/utility/functions/date/dateFunctions.d.ts +11 -11
  196. package/dist/utility/globalSchema.d.ts +1 -1
  197. package/dist/utility/hdbTerms.d.ts +3 -0
  198. package/dist/utility/hdbTerms.js +3 -0
  199. package/dist/utility/hdbTerms.js.map +1 -1
  200. package/dist/utility/installation.d.ts +2 -4
  201. package/dist/utility/installation.js.map +1 -1
  202. package/dist/utility/lmdb/commonUtility.d.ts +1 -0
  203. package/dist/utility/lmdb/deleteUtility.d.ts +1 -0
  204. package/dist/utility/lmdb/environmentUtility.d.ts +1 -0
  205. package/dist/utility/lmdb/searchUtility.d.ts +2 -1
  206. package/dist/utility/lmdb/writeUtility.d.ts +1 -0
  207. package/dist/utility/logging/harper_logger.d.ts +6 -6
  208. package/dist/utility/processManagement/processManagement.d.ts +1 -1
  209. package/dist/utility/processManagement/servicesConfig.d.ts +12 -6
  210. package/dist/validation/common_validators.d.ts +4 -3
  211. package/dist/validation/configValidator.d.ts +3 -2
  212. package/index.d.ts +56 -0
  213. package/index.js +41 -0
  214. package/json/systemSchema.json +373 -0
  215. package/launchServiceScripts/launchHarperDB.js +3 -0
  216. package/launchServiceScripts/utility/checkNodeVersion.js +15 -0
  217. package/package.json +21 -3
  218. package/resources/DatabaseTransaction.ts +378 -0
  219. package/resources/ErrorResource.ts +57 -0
  220. package/resources/IterableEventQueue.ts +94 -0
  221. package/resources/LMDBTransaction.ts +349 -0
  222. package/resources/RecordEncoder.ts +702 -0
  223. package/resources/RequestTarget.ts +134 -0
  224. package/resources/Resource.ts +789 -0
  225. package/resources/ResourceInterface.ts +221 -0
  226. package/resources/ResourceInterfaceV2.ts +53 -0
  227. package/resources/ResourceV2.ts +67 -0
  228. package/resources/Resources.ts +162 -0
  229. package/resources/RocksIndexStore.ts +70 -0
  230. package/resources/RocksTransactionLogStore.ts +352 -0
  231. package/resources/Table.ts +4527 -0
  232. package/resources/analytics/hostnames.ts +72 -0
  233. package/resources/analytics/metadata.ts +10 -0
  234. package/resources/analytics/read.ts +252 -0
  235. package/resources/analytics/write.ts +803 -0
  236. package/resources/auditStore.ts +556 -0
  237. package/resources/blob.ts +1268 -0
  238. package/resources/crdt.ts +125 -0
  239. package/resources/dataLoader.ts +527 -0
  240. package/resources/databases.ts +1290 -0
  241. package/resources/graphql.ts +221 -0
  242. package/resources/indexes/HierarchicalNavigableSmallWorld.ts +638 -0
  243. package/resources/indexes/customIndexes.ts +7 -0
  244. package/resources/indexes/vector.ts +38 -0
  245. package/resources/jsResource.ts +86 -0
  246. package/resources/loadEnv.ts +22 -0
  247. package/resources/login.ts +18 -0
  248. package/resources/openApi.ts +409 -0
  249. package/resources/registrationDeprecated.ts +8 -0
  250. package/resources/replayLogs.ts +136 -0
  251. package/resources/roles.ts +98 -0
  252. package/resources/search.ts +1301 -0
  253. package/resources/tracked.ts +584 -0
  254. package/resources/transaction.ts +89 -0
  255. package/resources/transactionBroadcast.ts +258 -0
  256. package/security/auth.ts +376 -0
  257. package/security/certificateVerification/certificateVerificationSource.ts +84 -0
  258. package/security/certificateVerification/configValidation.ts +107 -0
  259. package/security/certificateVerification/crlVerification.ts +623 -0
  260. package/security/certificateVerification/index.ts +121 -0
  261. package/security/certificateVerification/ocspVerification.ts +148 -0
  262. package/security/certificateVerification/pkijs-ed25519-patch.ts +188 -0
  263. package/security/certificateVerification/types.ts +128 -0
  264. package/security/certificateVerification/verificationConfig.ts +138 -0
  265. package/security/certificateVerification/verificationUtils.ts +447 -0
  266. package/security/cryptoHash.js +42 -0
  267. package/security/data_objects/PermissionAttributeResponseObject.js +15 -0
  268. package/security/data_objects/PermissionResponseObject.js +115 -0
  269. package/security/data_objects/PermissionTableResponseObject.js +20 -0
  270. package/security/fastifyAuth.js +169 -0
  271. package/security/impersonation.ts +160 -0
  272. package/security/jsLoader.ts +716 -0
  273. package/security/keys.js +948 -0
  274. package/security/permissionsTranslator.js +300 -0
  275. package/security/role.js +218 -0
  276. package/security/tokenAuthentication.ts +228 -0
  277. package/security/user.ts +449 -0
  278. package/server/DurableSubscriptionsSession.ts +503 -0
  279. package/server/REST.ts +407 -0
  280. package/server/Server.ts +89 -0
  281. package/server/fastifyRoutes/helpers/getCORSOptions.js +36 -0
  282. package/server/fastifyRoutes/helpers/getHeaderTimeoutConfig.js +15 -0
  283. package/server/fastifyRoutes/helpers/getServerOptions.js +33 -0
  284. package/server/fastifyRoutes/plugins/hdbCore.js +39 -0
  285. package/server/fastifyRoutes.ts +205 -0
  286. package/server/graphqlQuerying.ts +700 -0
  287. package/server/http.ts +640 -0
  288. package/server/itc/serverHandlers.js +161 -0
  289. package/server/itc/utility/ITCEventObject.js +10 -0
  290. package/server/jobs/JobObject.js +24 -0
  291. package/server/jobs/jobProcess.js +69 -0
  292. package/server/jobs/jobRunner.js +162 -0
  293. package/server/jobs/jobs.js +304 -0
  294. package/server/loadRootComponents.js +44 -0
  295. package/server/mqtt.ts +485 -0
  296. package/server/nodeName.ts +75 -0
  297. package/server/operationsServer.ts +313 -0
  298. package/server/serverHelpers/Headers.ts +108 -0
  299. package/server/serverHelpers/JSONStream.ts +269 -0
  300. package/server/serverHelpers/OperationFunctionObject.ts +13 -0
  301. package/server/serverHelpers/Request.ts +158 -0
  302. package/server/serverHelpers/contentTypes.ts +637 -0
  303. package/server/serverHelpers/requestTimePlugin.js +57 -0
  304. package/server/serverHelpers/serverHandlers.js +148 -0
  305. package/server/serverHelpers/serverUtilities.ts +473 -0
  306. package/server/serverRegistry.ts +8 -0
  307. package/server/static.ts +187 -0
  308. package/server/status/definitions.ts +37 -0
  309. package/server/status/index.ts +125 -0
  310. package/server/storageReclamation.ts +93 -0
  311. package/server/threads/itc.js +89 -0
  312. package/server/threads/manageThreads.js +594 -0
  313. package/server/threads/socketRouter.ts +360 -0
  314. package/server/threads/threadServer.js +279 -0
  315. package/server/throttle.ts +73 -0
  316. package/sqlTranslator/SelectValidator.js +330 -0
  317. package/sqlTranslator/alasqlFunctionImporter.js +62 -0
  318. package/sqlTranslator/deleteTranslator.js +67 -0
  319. package/sqlTranslator/index.js +242 -0
  320. package/sqlTranslator/sql_statement_bucket.js +472 -0
  321. package/static/defaultConfig.yaml +3 -0
  322. package/studio/web/HDBDogOnly.svg +78 -0
  323. package/studio/web/assets/PPRadioGrotesk-Bold-DDaUYG8E.woff +0 -0
  324. package/studio/web/assets/fa-brands-400-CEJbCg16.woff +0 -0
  325. package/studio/web/assets/fa-brands-400-CSYNqBb_.ttf +0 -0
  326. package/studio/web/assets/fa-brands-400-DnkPfk3o.eot +0 -0
  327. package/studio/web/assets/fa-brands-400-UxlILjvJ.woff2 +0 -0
  328. package/studio/web/assets/fa-brands-400-cH1MgKbP.svg +3717 -0
  329. package/studio/web/assets/fa-regular-400-BhTwtT8w.eot +0 -0
  330. package/studio/web/assets/fa-regular-400-D1vz6WBx.ttf +0 -0
  331. package/studio/web/assets/fa-regular-400-DFnMcJPd.woff +0 -0
  332. package/studio/web/assets/fa-regular-400-DGzu1beS.woff2 +0 -0
  333. package/studio/web/assets/fa-regular-400-gwj8Pxq-.svg +801 -0
  334. package/studio/web/assets/fa-solid-900-B4ZZ7kfP.svg +5034 -0
  335. package/studio/web/assets/fa-solid-900-B6Axprfb.eot +0 -0
  336. package/studio/web/assets/fa-solid-900-BUswJgRo.woff2 +0 -0
  337. package/studio/web/assets/fa-solid-900-DOXgCApm.woff +0 -0
  338. package/studio/web/assets/fa-solid-900-mxuxnBEa.ttf +0 -0
  339. package/studio/web/assets/index-BTgXJX9d.js +235 -0
  340. package/studio/web/assets/index-BTgXJX9d.js.map +1 -0
  341. package/studio/web/assets/index-C-GXfcup.js +37 -0
  342. package/studio/web/assets/index-C-GXfcup.js.map +1 -0
  343. package/studio/web/assets/index-PFlNdimM.js +2 -0
  344. package/studio/web/assets/index-PFlNdimM.js.map +1 -0
  345. package/studio/web/assets/index-Y2g_iFpU.css +1 -0
  346. package/studio/web/assets/index-jiPwkrsB.css +1 -0
  347. package/studio/web/assets/index.lazy-C3TJZJ4o.js +266 -0
  348. package/studio/web/assets/index.lazy-C3TJZJ4o.js.map +1 -0
  349. package/studio/web/assets/profiler-DotzgiCJ.js +2 -0
  350. package/studio/web/assets/profiler-DotzgiCJ.js.map +1 -0
  351. package/studio/web/assets/react-redux-VxUEx_mU.js +6 -0
  352. package/studio/web/assets/react-redux-VxUEx_mU.js.map +1 -0
  353. package/studio/web/assets/startRecording-B_9J9Csd.js +3 -0
  354. package/studio/web/assets/startRecording-B_9J9Csd.js.map +1 -0
  355. package/studio/web/fabric-signup-background.webp +0 -0
  356. package/studio/web/fabric-signup-text.png +0 -0
  357. package/studio/web/favicon_purple.png +0 -0
  358. package/studio/web/github-icon.svg +15 -0
  359. package/studio/web/harper-fabric_black.png +0 -0
  360. package/studio/web/harper-fabric_white.png +0 -0
  361. package/studio/web/harper-studio_white.png +0 -0
  362. package/studio/web/index.html +16 -0
  363. package/studio/web/running.css +148 -0
  364. package/studio/web/running.html +147 -0
  365. package/studio/web/running.js +111 -0
  366. package/upgrade/UpgradeObjects.js +13 -0
  367. package/upgrade/directives/directivesController.js +90 -0
  368. package/upgrade/directivesManager.js +139 -0
  369. package/upgrade/upgradePrompt.js +124 -0
  370. package/upgrade/upgradeUtilities.js +28 -0
  371. package/utility/AWS/AWSConnector.js +29 -0
  372. package/utility/OperationFunctionCaller.js +63 -0
  373. package/utility/assignCmdEnvVariables.js +62 -0
  374. package/utility/common_utils.js +867 -0
  375. package/utility/environment/environmentManager.js +208 -0
  376. package/utility/environment/systemInformation.js +355 -0
  377. package/utility/errors/commonErrors.js +267 -0
  378. package/utility/errors/hdbError.js +146 -0
  379. package/utility/functions/date/dateFunctions.js +65 -0
  380. package/utility/functions/geo.js +355 -0
  381. package/utility/functions/sql/alaSQLExtension.js +104 -0
  382. package/utility/globalSchema.js +35 -0
  383. package/utility/hdbTerms.ts +819 -0
  384. package/utility/install/checkJWTTokensExist.js +62 -0
  385. package/utility/install/harperdb.conf +15 -0
  386. package/utility/install/harperdb.service +14 -0
  387. package/utility/install/installer.js +635 -0
  388. package/utility/installation.ts +30 -0
  389. package/utility/lmdb/DBIDefinition.js +20 -0
  390. package/utility/lmdb/DeleteRecordsResponseObject.js +25 -0
  391. package/utility/lmdb/InsertRecordsResponseObject.js +22 -0
  392. package/utility/lmdb/OpenDBIObject.js +31 -0
  393. package/utility/lmdb/OpenEnvironmentObject.js +41 -0
  394. package/utility/lmdb/UpdateRecordsResponseObject.js +25 -0
  395. package/utility/lmdb/UpsertRecordsResponseObject.js +22 -0
  396. package/utility/lmdb/cleanLMDBMap.js +65 -0
  397. package/utility/lmdb/commonUtility.js +119 -0
  398. package/utility/lmdb/deleteUtility.js +128 -0
  399. package/utility/lmdb/environmentUtility.js +477 -0
  400. package/utility/lmdb/searchCursorFunctions.js +187 -0
  401. package/utility/lmdb/searchUtility.js +918 -0
  402. package/utility/lmdb/terms.js +57 -0
  403. package/utility/lmdb/writeUtility.js +407 -0
  404. package/utility/logging/harper_logger.js +876 -0
  405. package/utility/logging/logRotator.js +157 -0
  406. package/utility/logging/logger.ts +24 -0
  407. package/utility/logging/readLog.js +355 -0
  408. package/utility/logging/transactionLog.js +57 -0
  409. package/utility/mount_hdb.js +59 -0
  410. package/utility/npmUtilities.js +102 -0
  411. package/utility/operationPermissions.ts +112 -0
  412. package/utility/operation_authorization.js +836 -0
  413. package/utility/packageUtils.js +55 -0
  414. package/utility/password.ts +99 -0
  415. package/utility/processManagement/processManagement.js +187 -0
  416. package/utility/processManagement/servicesConfig.js +56 -0
  417. package/utility/scripts/restartHdb.js +24 -0
  418. package/utility/scripts/user_data.sh +13 -0
  419. package/utility/signalling.js +36 -0
  420. package/utility/terms/certificates.js +81 -0
  421. package/utility/when.ts +20 -0
  422. package/v1.d.ts +39 -0
  423. package/v1.js +41 -0
  424. package/v2.d.ts +39 -0
  425. package/v2.js +41 -0
  426. package/validation/bulkDeleteValidator.js +24 -0
  427. package/validation/check_permissions.js +19 -0
  428. package/validation/common_validators.js +95 -0
  429. package/validation/configValidator.js +331 -0
  430. package/validation/deleteValidator.js +15 -0
  431. package/validation/fileLoadValidator.js +153 -0
  432. package/validation/insertValidator.js +40 -0
  433. package/validation/installValidator.js +37 -0
  434. package/validation/readLogValidator.js +64 -0
  435. package/validation/role_validation.js +320 -0
  436. package/validation/schemaMetadataValidator.js +42 -0
  437. package/validation/searchValidator.js +166 -0
  438. package/validation/statusValidator.ts +66 -0
  439. package/validation/transactionLogValidator.js +33 -0
  440. package/validation/user_validation.js +55 -0
  441. package/validation/validationWrapper.js +105 -0
  442. package/dist/resources/analytics/profile.d.ts +0 -2
  443. package/dist/resources/analytics/profile.js +0 -144
  444. package/dist/resources/analytics/profile.js.map +0 -1
@@ -0,0 +1,360 @@
1
+ import {
2
+ startWorker,
3
+ setMonitorListener,
4
+ setMainIsWorker,
5
+ shutdownWorkers,
6
+ threadsHaveStarted,
7
+ } from './manageThreads.js';
8
+ import { createServer, Socket } from 'net';
9
+ import * as hdbTerms from '../../utility/hdbTerms.ts';
10
+ import * as harperLogger from '../../utility/logging/harper_logger.js';
11
+ import { unlinkSync, existsSync } from 'fs';
12
+ import { recordHostname, recordAction } from '../../resources/analytics/write.ts';
13
+ import { isMainThread } from 'worker_threads';
14
+ import { packageJson } from '../../utility/packageUtils.js';
15
+ import { join } from 'path';
16
+
17
+ const workers = [];
18
+ let queuedSockets = [];
19
+ const handleSocket = [];
20
+ let directThreadServer;
21
+ let currentThreadCount = 0;
22
+ const workersReady = [];
23
+
24
+ if (isMainThread) {
25
+ process.on('uncaughtException', (error) => {
26
+ // TODO: Maybe we should try to log the first of each type of error
27
+ if (error.code === 'ECONNRESET') return; // that's what network connections do
28
+ if (error.code === 'EIO') {
29
+ // that means the terminal is closed
30
+ harperLogger.disableStdio();
31
+ return;
32
+ }
33
+ console.error('uncaughtException', error);
34
+ });
35
+ }
36
+
37
+ export async function startHTTPThreads(threadCount = 2, dynamicThreads?: boolean) {
38
+ recordHostname().catch((err) => harperLogger.error?.('Error recording hostname for analytics:', err));
39
+ try {
40
+ if (dynamicThreads) {
41
+ startHTTPWorker(0, 1, true);
42
+ } else {
43
+ const { loadRootComponents } = require('../loadRootComponents.js');
44
+ if (threadCount === 0) {
45
+ setMainIsWorker(true);
46
+ await require('./threadServer.js').startServers();
47
+ return Promise.resolve([]);
48
+ }
49
+ await loadRootComponents();
50
+ }
51
+ for (let i = 0; i < threadCount; i++) {
52
+ startHTTPWorker(i, threadCount);
53
+ }
54
+ await Promise.all(workersReady);
55
+ } finally {
56
+ threadsHaveStarted();
57
+ }
58
+ }
59
+
60
+ function startHTTPWorker(index, threadCount = 1, shutdownWhenIdle?) {
61
+ currentThreadCount++;
62
+ startWorker(join(__dirname, './threadServer.js'), {
63
+ name: hdbTerms.THREAD_TYPES.HTTP,
64
+ workerIndex: index,
65
+ threadCount,
66
+ async onStarted(worker) {
67
+ // note that this can be called multiple times, once when started, and again when threads are restarted
68
+ const ready = new Promise((resolve, reject) => {
69
+ function onMessage(message) {
70
+ if (message.type === 'child_started') {
71
+ worker.removeListener('message', onMessage);
72
+ resolve(worker);
73
+ }
74
+ }
75
+
76
+ worker.on('message', onMessage);
77
+ worker.on('error', reject);
78
+ });
79
+ workersReady.push(ready);
80
+ await ready;
81
+ workers.push(worker);
82
+ worker.expectedIdle = 1;
83
+ worker.lastIdle = 0;
84
+ worker.requests = 1;
85
+ worker.on('message', (message) => {
86
+ if (message.requestId) {
87
+ const handler = requestMap.get(message.requestId);
88
+ if (handler) handler(message);
89
+ }
90
+ });
91
+ worker.on('exit', removeWorker);
92
+ worker.on('shutdown', removeWorker);
93
+ function removeWorker() {
94
+ const index = workers.indexOf(worker);
95
+ if (index > -1) workers.splice(index, 1);
96
+ }
97
+ if (queuedSockets) {
98
+ // if there are any queued sockets, we re-deliver them
99
+ const sockets = queuedSockets;
100
+ queuedSockets = [];
101
+ for (const socket of sockets) handleSocket[socket.localPort](null, socket);
102
+ }
103
+ },
104
+ });
105
+ if (shutdownWhenIdle) {
106
+ const interval = setInterval(() => {
107
+ if (recentRequest) recentRequest = false;
108
+ else {
109
+ clearInterval(interval);
110
+ console.log('shut down dynamic thread due to inactivity');
111
+ shutdownWorkers();
112
+ currentThreadCount = 0;
113
+ setTimeout(() => {
114
+ global.gc?.();
115
+ }, 5000);
116
+ }
117
+ }, 10000);
118
+ }
119
+ }
120
+ let recentRequest;
121
+ export function startSocketServer(port = 0, sessionAffinityIdentifier?) {
122
+ if (typeof port === 'string') {
123
+ // if we are using a unix domain socket, we try to delete it first, otherwise it will throw an EADDRESSINUSE
124
+ // error
125
+ try {
126
+ if (existsSync(port)) unlinkSync(port);
127
+ } catch {}
128
+ }
129
+ // at some point we may want to actually read from the https connections
130
+ let workerStrategy;
131
+ if (sessionAffinityIdentifier) {
132
+ // use remote ip address based session affinity
133
+ if (sessionAffinityIdentifier === 'ip') workerStrategy = findByRemoteAddressAffinity;
134
+ // use a header for session affinity (like Authorization or Cookie)
135
+ else workerStrategy = makeFindByHeaderAffinity(sessionAffinityIdentifier);
136
+ } else workerStrategy = findMostIdleWorker; // no session affinity, just delegate to most idle worker
137
+ const server = createServer({
138
+ allowHalfOpen: true,
139
+ pauseOnConnect: !workerStrategy.readsData,
140
+ }).listen(port);
141
+ if (server._handle) {
142
+ server._handle.onconnection = handleSocket[port] = function (err, clientHandle) {
143
+ if (!workerStrategy.readsData) {
144
+ clientHandle.reading = false;
145
+ clientHandle.readStop();
146
+ }
147
+ recentRequest = true;
148
+ workerStrategy(clientHandle, (worker, receivedData) => {
149
+ if (!worker) {
150
+ if (directThreadServer) {
151
+ const socket = clientHandle._socket || new Socket({ handle: clientHandle, writable: true, readable: true });
152
+ directThreadServer.deliverSocket(socket, port, receivedData);
153
+ socket.resume();
154
+ } else if (currentThreadCount > 0) {
155
+ // should be a thread coming on line
156
+ if (queuedSockets.length === 0) {
157
+ setTimeout(() => {
158
+ if (queuedSockets.length > 0) {
159
+ console.warn(
160
+ 'Incoming sockets/requests have been queued for workers to start, and no workers have handled them. Check to make sure an error is not preventing workers from starting'
161
+ );
162
+ }
163
+ }, 10000).unref();
164
+ }
165
+ clientHandle.localPort = port;
166
+ queuedSockets.push(clientHandle);
167
+ } else {
168
+ console.log('start up a dynamic thread to handle request');
169
+ startHTTPWorker(0);
170
+ }
171
+ recordAction(false, 'socket-routed');
172
+ return;
173
+ }
174
+ worker.requests++;
175
+ const fd = clientHandle.fd;
176
+ if (fd >= 0) worker.postMessage({ port, fd, data: receivedData });
177
+ // valid file descriptor, forward it
178
+ // Windows doesn't support passing sockets by file descriptors, so we have manually proxy the socket data
179
+ else {
180
+ const socket = clientHandle._socket || new Socket({ handle: clientHandle, writable: true, readable: true });
181
+ proxySocket(socket, worker, port);
182
+ }
183
+ recordAction(true, 'socket-routed');
184
+ });
185
+ };
186
+ harperLogger.info(`Harper ${packageJson.version} Server running on port ${port}`);
187
+ }
188
+ server.on('error', (error) => {
189
+ console.error('Error in socket server', error);
190
+ });
191
+ if (process.env._UNREF_SERVER) server.unref();
192
+ return server;
193
+ }
194
+
195
+ let secondBestAvailability = 0;
196
+
197
+ /**
198
+ * Delegate to workers based on what worker is likely to be most idle/available.
199
+ * @returns Worker
200
+ */
201
+ function findMostIdleWorker(handle, deliver) {
202
+ // fast algorithm for delegating work to workers based on last idleness check (without constantly checking idleness)
203
+ let selectedWorker;
204
+ let lastAvailability = 0;
205
+ for (const worker of workers) {
206
+ if (worker.threadId === -1) continue;
207
+ const availability = worker.expectedIdle / worker.requests;
208
+ if (availability > lastAvailability) {
209
+ selectedWorker = worker;
210
+ } else if (lastAvailability >= secondBestAvailability) {
211
+ secondBestAvailability = availability;
212
+ return deliver(selectedWorker);
213
+ }
214
+ lastAvailability = availability;
215
+ }
216
+ secondBestAvailability = 0;
217
+ deliver(selectedWorker);
218
+ }
219
+
220
+ const AFFINITY_TIMEOUT = 3600000; // an hour timeout
221
+ const sessions = new Map();
222
+
223
+ /**
224
+ * Delegate to workers using session affinity based on remote address. This will send all requests
225
+ * from the same remote address to the same worker.
226
+ * @returns Worker
227
+ */
228
+ function findByRemoteAddressAffinity(handle, deliver) {
229
+ const remoteInfo = {};
230
+ handle.getpeername(remoteInfo);
231
+ const address = remoteInfo.address;
232
+ // we might need to fallback to new Socket({handle}).remoteAddress for... bun?
233
+ const entry = sessions.get(address);
234
+ const now = Date.now();
235
+ if (entry && entry.worker.threadId !== -1) {
236
+ entry.lastUsed = now;
237
+ return deliver(entry.worker);
238
+ }
239
+ findMostIdleWorker(handle, (worker) => {
240
+ sessions.set(address, {
241
+ worker,
242
+ lastUsed: now,
243
+ });
244
+ deliver(worker);
245
+ });
246
+ }
247
+
248
+ /**
249
+ * Creates a worker strategy that uses session affinity to maintain the same thread for requests that have the
250
+ * same value of the provided header. You can use a header of "Authorization" for clients that are using
251
+ * basic authentication, or "Cookie" for clients using cookie-based authentication.
252
+ * @param header
253
+ * @returns {findByHeaderAffinity}
254
+ */
255
+ function makeFindByHeaderAffinity(header) {
256
+ // regular expression to find the specified header and group match on the value
257
+ const headerExpression = new RegExp(`${header}:\\s*(.+)`, 'i');
258
+ findByHeaderAffinity.readsData = true; // make sure we don't start with the socket being paused
259
+ return findByHeaderAffinity;
260
+ function findByHeaderAffinity(handle, deliver) {
261
+ const socket = new Socket({ handle, readable: true, writable: true });
262
+ handle._socket = socket;
263
+ socket.on('data', (data) => {
264
+ // must forcibly stop the TCP handle to ensure no more data is read and that all further data is read by
265
+ // the child worker thread (once it resumes the socket)
266
+ handle.readStop();
267
+ const headerBlock = data.toString('latin1'); // latin is standard HTTP header encoding and faster
268
+ const headerValue = headerBlock.match(headerExpression)?.[1];
269
+ const entry = sessions.get(headerValue);
270
+ const now = Date.now();
271
+ if (entry && entry.worker.threadId !== -1) {
272
+ entry.lastUsed = now;
273
+ return deliver(entry.worker);
274
+ }
275
+
276
+ findMostIdleWorker(handle, (worker) => {
277
+ sessions.set(headerValue, {
278
+ worker,
279
+ lastUsed: now,
280
+ });
281
+ deliver(worker, data);
282
+ });
283
+ });
284
+ }
285
+ }
286
+
287
+ setInterval(() => {
288
+ // clear out expired entries
289
+ const now = Date.now();
290
+ for (const [address, entry] of sessions) {
291
+ if (entry.lastUsed + AFFINITY_TIMEOUT < now) sessions.delete(address);
292
+ }
293
+ }, AFFINITY_TIMEOUT).unref();
294
+
295
+ // basically, the amount of additional idleness to expect based on previous idleness (some work will continue, some
296
+ // won't)
297
+ const EXPECTED_IDLE_DECAY = 1000;
298
+
299
+ /**
300
+ * Updates the idleness statistics for each worker
301
+ */
302
+ export function updateWorkerIdleness() {
303
+ secondBestAvailability = 0;
304
+ for (const worker of workers) {
305
+ worker.expectedIdle = worker.recentELU.idle + EXPECTED_IDLE_DECAY;
306
+ worker.requests = 1;
307
+ }
308
+ workers.sort((a, b) => (a.expectedIdle > b.expectedIdle ? -1 : 1));
309
+ }
310
+
311
+ setMonitorListener(updateWorkerIdleness);
312
+
313
+ const requestMap = new Map();
314
+ let nextId = 1;
315
+
316
+ /**
317
+ * Windows does not have file descriptors for sockets and there is no mechanism in NodeJS for sending sockets
318
+ * to workers, so we have to actually read the data from sockets and proxy the data to the threads. We may want
319
+ * to do this for some other types of connections, like cookie-based session affinity at some point, but for now
320
+ * this is just for Windows. This basically listens for the all events on a socket and forwards them to the target
321
+ * worker for it to emulate a socket with the incoming event messages (and vice versa to proxy the response).
322
+ * @param socket
323
+ * @param worker
324
+ * @param type
325
+ */
326
+ function proxySocket(socket, worker, port) {
327
+ // socket proxying for Windows
328
+ const requestId = nextId++;
329
+ worker.postMessage({ port, requestId, event: 'connection' });
330
+ socket
331
+ .on('data', (buffer) => {
332
+ const data = buffer.toString('latin1');
333
+ worker.postMessage({ port, requestId, data, event: 'data' });
334
+ })
335
+ .on('close', (hadError) => {
336
+ worker.postMessage({ port, requestId, event: 'close', hadError });
337
+ })
338
+ .on('error', (error) => {
339
+ worker.postMessage({ port, requestId, event: 'error', error });
340
+ })
341
+ .on('drain', (error) => {
342
+ worker.postMessage({ port, requestId, event: 'drain', error });
343
+ })
344
+ .on('end', () => {
345
+ worker.postMessage({ port, requestId, event: 'end' });
346
+ })
347
+ .resume();
348
+ // handle the response
349
+ requestMap.set(requestId, (message) => {
350
+ if (message.event == 'data') socket.write(Buffer.from(message.data, 'latin1'));
351
+ if (message.event == 'end') {
352
+ socket.end(message.data && Buffer.from(message.data, 'latin1'));
353
+ requestMap.delete(requestId);
354
+ }
355
+ if (message.event == 'destroy') {
356
+ socket.destroy();
357
+ requestMap.delete(requestId);
358
+ }
359
+ });
360
+ }
@@ -0,0 +1,279 @@
1
+ 'use strict';
2
+
3
+ const { isMainThread, parentPort, threadId, workerData } = require('node:worker_threads');
4
+ const { createServer: createSocketServer } = require('node:net');
5
+ const { unlinkSync, existsSync } = require('fs');
6
+ let componentsLoadedResolve;
7
+ exports.whenComponentsLoaded = new Promise((resolve) => {
8
+ componentsLoadedResolve = resolve;
9
+ });
10
+
11
+ const harperLogger = require('../../utility/logging/harper_logger.js');
12
+ const env = require('../../utility/environment/environmentManager.js');
13
+ const terms = require('../../utility/hdbTerms.ts');
14
+ const { server } = require('../Server.ts');
15
+ let { createServer: createSecureSocketServer } = require('node:tls');
16
+ const { restartNumber, getWorkerIndex } = require('./manageThreads.js');
17
+ const { createReuseportFd } = require('../serverHelpers/Request.ts');
18
+ const { createTLSSelector } = require('../../security/keys.js');
19
+ const { startupLog } = require('../../bin/run.js');
20
+ const { SERVERS, setPortServerMap, portServer } = require('../serverRegistry.ts');
21
+ const httpComponent = require('../http.ts');
22
+ const globals = require('../../globals.js');
23
+
24
+ const debugThreads = env.get(terms.CONFIG_PARAMS.THREADS_DEBUG);
25
+ const sessionAffinity = env.get(terms.CONFIG_PARAMS.HTTP_SESSIONAFFINITY);
26
+ server.socket = onSocket;
27
+
28
+ if (debugThreads) {
29
+ let port;
30
+ if (isMainThread) {
31
+ port = env.get(terms.CONFIG_PARAMS.THREADS_DEBUG_PORT) ?? 9229;
32
+ process.on(['SIGINT', 'SIGTERM', 'SIGQUIT', 'exit'], () => {
33
+ try {
34
+ require('inspector').close();
35
+ } catch (error) {
36
+ harperLogger.info('Could not close debugger', error);
37
+ }
38
+ });
39
+ } else {
40
+ const startingPort = env.get(terms.CONFIG_PARAMS.THREADS_DEBUG_STARTINGPORT);
41
+ if (startingPort && getWorkerIndex() >= 0) {
42
+ port = startingPort + getWorkerIndex();
43
+ }
44
+ }
45
+ if (port) {
46
+ const host = env.get(terms.CONFIG_PARAMS.THREADS_DEBUG_HOST);
47
+ const waitForDebugger = env.get(terms.CONFIG_PARAMS.THREADS_DEBUG_WAITFORDEBUGGER);
48
+ try {
49
+ require('inspector').open(port, host, waitForDebugger);
50
+ } catch (error) {
51
+ harperLogger.trace(`Could not start debugging on port ${port}, you may already be debugging:`, error.message);
52
+ }
53
+ }
54
+ } else if (process.env.DEV_MODE && isMainThread) {
55
+ try {
56
+ require('inspector').open(9229);
57
+ } catch (error) {
58
+ if (restartNumber <= 1)
59
+ harperLogger.trace('Could not start debugging on port 9229, you may already be debugging:', error.message);
60
+ }
61
+ }
62
+
63
+ process.on('uncaughtException', (error) => {
64
+ if (error.isHandled) return;
65
+ if (error.code === 'ECONNRESET' || error.code === 'ECONNREFUSED') return; // that's what network connections do
66
+ if (error.message === 'write EIO') return; // that means the terminal is closed
67
+ harperLogger.error('uncaughtException', error);
68
+ });
69
+ env.initSync();
70
+ exports.globals = globals;
71
+ exports.listenOnPorts = listenOnPorts;
72
+ exports.startServers = startServers;
73
+
74
+ function startServers() {
75
+ const rootPath = env.get(terms.CONFIG_PARAMS.ROOTPATH);
76
+ if (rootPath) {
77
+ try {
78
+ process.chdir(rootPath);
79
+ } catch {
80
+ // ignore any errors with this; just a best effort for now
81
+ }
82
+ }
83
+ let loaded = require('../loadRootComponents.js')
84
+ .loadRootComponents(true)
85
+ .then(() => {
86
+ parentPort
87
+ ?.on('message', (message) => {
88
+ const { port, fd, data } = message;
89
+ if (fd) {
90
+ // Create a socket from the file descriptor for the socket that was routed to us.
91
+ httpComponent.deliverSocket(fd, port, data);
92
+ } else if (message.requestId) {
93
+ // Windows doesn't support passing file descriptors, so we have to resort to manually proxying the socket
94
+ // data for each request
95
+ httpComponent.proxyRequest(message);
96
+ } else if (message.type === terms.ITC_EVENT_TYPES.SHUTDOWN) {
97
+ harperLogger.trace('received shutdown request', threadId);
98
+ // shutdown (for these threads) means stop listening for incoming requests (finish what we are working) and
99
+ // close connections as possible, then let the event loop complete
100
+ for (let port in SERVERS) {
101
+ const server = SERVERS[port];
102
+ let closeAllTimer;
103
+ if (server.closeIdleConnections) {
104
+ // Here we attempt to gracefully close all outstanding keep-alive connections,
105
+ // repeatedly closing any connections that are idle. This allows any active requests
106
+ // to finish sending their response, then we close their connections.
107
+ let symbols = Object.getOwnPropertySymbols(server);
108
+ let connectionsSymbol = symbols.find((symbol) => symbol.description.includes('connections'));
109
+ let closeAttempts = 0;
110
+ let timer = setInterval(() => {
111
+ closeAttempts++;
112
+ const forceClose = closeAttempts >= 100;
113
+ if (!server[connectionsSymbol]) {
114
+ if (forceClose) server.closeAllConnections?.();
115
+ clearInterval(timer);
116
+ return;
117
+ }
118
+ const connections = server[connectionsSymbol][forceClose ? 'all' : 'idle']?.() || [];
119
+ if (connections.length === 0) {
120
+ if (forceClose) clearInterval(timer);
121
+ return;
122
+ }
123
+ if (closeAttempts === 1) harperLogger.info(`Closing ${connections.length} idle connections`);
124
+ else if (forceClose) harperLogger.warn(`Forcefully closing ${connections.length} active connections`);
125
+ for (let i = 0, l = connections.length; i < l; i++) {
126
+ const socket = connections[i].socket;
127
+ if (socket._httpMessage && !socket._httpMessage.finished && !forceClose) {
128
+ continue;
129
+ }
130
+ if (forceClose) socket.destroySoon();
131
+ else socket.end('HTTP/1.1 408 Request Timeout\r\nConnection: close\r\n\r\n');
132
+ }
133
+ }, 25).unref();
134
+ }
135
+ // And we tell the server not to accept any more incoming connections
136
+ server.close?.(() => {
137
+ clearInterval(closeAllTimer);
138
+ // We hope for a graceful exit once all connections have been closed, and no
139
+ // more incoming connections are accepted, but if we need to, we eventually will exit
140
+ setTimeout(() => {
141
+ console.log('forced close server', port, threadId);
142
+ if (!server.cantCleanupProperly) harperLogger.warn('Had to forcefully exit the thread', threadId);
143
+ process.exit(0);
144
+ }, 5000).unref();
145
+ });
146
+ }
147
+ if (debugThreads || process.env.DEV_MODE) {
148
+ try {
149
+ require('inspector').close();
150
+ } catch (error) {
151
+ harperLogger.info('Could not close debugger', error);
152
+ }
153
+ }
154
+ }
155
+ })
156
+ .ref(); // use this to keep the thread running until we are ready to shutdown and clean up handles
157
+ let listening;
158
+ if (createReuseportFd && !sessionAffinity) {
159
+ listening = listenOnPorts();
160
+ }
161
+
162
+ // notify that we are now ready to start receiving requests
163
+ Promise.resolve(listening).then(() => {
164
+ if (getWorkerIndex() === 0) {
165
+ try {
166
+ startupLog(portServer);
167
+ } catch (err) {
168
+ console.error('Error displaying start-up log', err);
169
+ }
170
+ }
171
+ parentPort?.postMessage({ type: terms.ITC_EVENT_TYPES.CHILD_STARTED });
172
+ });
173
+ });
174
+ componentsLoadedResolve(loaded);
175
+ return loaded;
176
+ }
177
+ function listenOnPorts() {
178
+ const listening = [];
179
+ for (let port in SERVERS) {
180
+ const server = SERVERS[port];
181
+
182
+ // If server is unix domain socket
183
+ if (port.includes?.('/') && getWorkerIndex() == 0) {
184
+ if (existsSync(port)) unlinkSync(port);
185
+ listening.push(
186
+ new Promise((resolve, reject) => {
187
+ server
188
+ .listen({ path: port }, () => {
189
+ resolve({ port, name: server.name, protocol_name: server.protocol_name });
190
+ harperLogger.info('Domain socket listening on ' + port);
191
+ })
192
+ .on('error', reject);
193
+ })
194
+ );
195
+ continue;
196
+ }
197
+ let listen_on;
198
+ const threadRange = env.get(terms.CONFIG_PARAMS.HTTP_THREADRANGE);
199
+ if (threadRange) {
200
+ let threadRangeArray = typeof threadRange === 'string' ? threadRange.split('-') : threadRange;
201
+ let threadIndex = getWorkerIndex();
202
+ if (threadIndex < threadRangeArray[0] || threadIndex > threadRangeArray[1]) {
203
+ continue;
204
+ }
205
+ }
206
+
207
+ try {
208
+ const lastColon = port.lastIndexOf(':');
209
+ if (lastColon > 0)
210
+ if (createReuseportFd)
211
+ // if there is a colon, we assume it is a host:port pair, and then strip brackets as that is a common way to
212
+ // specify an IPv6 address
213
+ listen_on = {
214
+ fd: createReuseportFd(+port.slice(lastColon + 1).replace(/[[\]]/g, ''), port.slice(0, lastColon)),
215
+ };
216
+ else listen_on = { host: +port.slice(lastColon + 1).replace(/[[\]]/g, ''), port: port.slice(0, lastColon) };
217
+ else if (createReuseportFd) listen_on = { fd: createReuseportFd(+port, '::') };
218
+ else listen_on = { port };
219
+ } catch (error) {
220
+ harperLogger.error(`Unable to bind to port ${port}`, error);
221
+ continue;
222
+ }
223
+ listening.push(
224
+ new Promise((resolve, reject) => {
225
+ server
226
+ .listen(listen_on, () => {
227
+ resolve({ port, name: server.name, protocol_name: server.protocol_name });
228
+ harperLogger.trace('Listening on port ' + port, threadId);
229
+ })
230
+ .on('error', reject);
231
+ })
232
+ );
233
+ }
234
+ return Promise.all(listening);
235
+ }
236
+ if (!isMainThread && !workerData?.noServerStart) {
237
+ startServers();
238
+ }
239
+
240
+ /**
241
+ * Direct socket listener
242
+ * @param listener
243
+ * @param options
244
+ */
245
+ function onSocket(listener, options) {
246
+ let getComponentName = require('../../components/componentLoader.ts').getComponentName;
247
+ let socketServer;
248
+ if (options.securePort) {
249
+ setPortServerMap(options.securePort, { protocol_name: 'TLS', name: getComponentName() });
250
+ const SNICallback = createTLSSelector('server', options.mtls);
251
+ const tlsConfig = env.get('tls');
252
+ socketServer = createSecureSocketServer(
253
+ {
254
+ rejectUnauthorized: Boolean(options.mtls?.required),
255
+ requestCert: Boolean(options.mtls),
256
+ noDelay: true, // don't delay for Nagle's algorithm, it is a relic of the past that slows things down: https://brooker.co.za/blog/2024/05/09/nagle.html
257
+ keepAlive: true,
258
+ keepAliveInitialDelay: 600, // 10 minute keep-alive, want to be proactive about closing unused connections
259
+ // For some reason ciphers doesn't work from the secure context, despite node docs claiming it would. Lost
260
+ // count of how many node TLS bugs that makes
261
+ ciphers: tlsConfig.ciphers ?? tlsConfig[0]?.ciphers,
262
+ SNICallback,
263
+ },
264
+ listener
265
+ );
266
+ SNICallback.initialize(socketServer);
267
+ SERVERS[options.securePort] = socketServer;
268
+ }
269
+ if (options.port) {
270
+ setPortServerMap(options.port, { protocol_name: 'TCP', name: getComponentName() });
271
+ socketServer = createSocketServer(listener, {
272
+ noDelay: true,
273
+ keepAlive: true,
274
+ keepAliveInitialDelay: 600,
275
+ });
276
+ SERVERS[options.port] = socketServer;
277
+ }
278
+ return socketServer;
279
+ }