@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,716 @@
1
+ import { Resource } from '../resources/Resource.ts';
2
+ import { contextStorage, transaction } from '../resources/transaction.ts';
3
+ import { RequestTarget } from '../resources/RequestTarget.ts';
4
+ import { tables, databases } from '../resources/databases.ts';
5
+ import { readFile } from 'node:fs/promises';
6
+ import { dirname, isAbsolute } from 'node:path';
7
+ import { pathToFileURL, fileURLToPath } from 'node:url';
8
+ import { SourceTextModule, SyntheticModule, createContext, runInContext } from 'node:vm';
9
+ import { ApplicationScope } from '../components/ApplicationScope.ts';
10
+ import logger from '../utility/logging/harper_logger.js';
11
+ import { createRequire } from 'node:module';
12
+ import * as env from '../utility/environment/environmentManager';
13
+ import * as child_process from 'node:child_process';
14
+ import { CONFIG_PARAMS } from '../utility/hdbTerms.ts';
15
+ import { contentTypes } from '../server/serverHelpers/contentTypes.ts';
16
+ import type { CompartmentOptions } from 'ses';
17
+ import { mkdirSync, readFileSync, writeFileSync, unlinkSync, openSync, closeSync, statSync } from 'node:fs';
18
+ import { join } from 'node:path';
19
+ import { EventEmitter } from 'node:events';
20
+
21
+ type Lockdown = 'none' | 'freeze' | 'ses';
22
+ const APPLICATIONS_LOCKDOWN: Lockdown = env.get(CONFIG_PARAMS.APPLICATIONS_LOCKDOWN);
23
+
24
+ let lockedDown = false;
25
+ /**
26
+ * This is the main entry point for loading plugin and application modules that may be executed in a
27
+ * separate top level scope. The scope indicates if we use a different top level scope or a standard import.
28
+ * @param moduleUrl
29
+ * @param scope
30
+ */
31
+ export async function scopedImport(filePath: string | URL, scope?: ApplicationScope) {
32
+ if (!lockedDown && APPLICATIONS_LOCKDOWN && APPLICATIONS_LOCKDOWN !== 'none') {
33
+ lockedDown = true;
34
+ if (APPLICATIONS_LOCKDOWN === 'ses') {
35
+ require('ses'); // load the lockdown function
36
+ lockdown({
37
+ domainTaming: 'unsafe',
38
+ consoleTaming: 'unsafe',
39
+ errorTaming: 'unsafe',
40
+ errorTrapping: 'none',
41
+ stackFiltering: 'verbose',
42
+ });
43
+ } else {
44
+ preventFunctionConstructor();
45
+ for (let name of Object.getOwnPropertyNames(Object.prototype)) {
46
+ if (name === '__proto__') continue;
47
+ overridableProperty(Object.prototype, name);
48
+ }
49
+ overridableProperty(Promise.prototype, 'then');
50
+ overridableProperty(Date, 'now');
51
+ for (let Intrinsic of [
52
+ Object,
53
+ Array,
54
+ Promise,
55
+ BigInt,
56
+ String,
57
+ Number,
58
+ Boolean,
59
+ Symbol,
60
+ RegExp,
61
+ Date,
62
+ Map,
63
+ Set,
64
+ WeakMap,
65
+ WeakSet,
66
+ Math,
67
+ JSON,
68
+ Reflect,
69
+ Atomics,
70
+ SharedArrayBuffer,
71
+ WeakRef,
72
+ FinalizationRegistry,
73
+ ]) {
74
+ Object.freeze(Intrinsic);
75
+ Object.freeze(Intrinsic.prototype);
76
+ }
77
+ Object.freeze(Function);
78
+ }
79
+ }
80
+ const moduleUrl = (filePath instanceof URL ? filePath : pathToFileURL(filePath)).toString();
81
+ try {
82
+ const containmentMode = scope?.mode;
83
+ if (scope && containmentMode !== 'none') {
84
+ if (containmentMode === 'compartment') {
85
+ // use SES Compartments
86
+ // note that we use a single compartment per scope and we load it on-demand, only
87
+ // loading if necessary (since it is actually very heavy)
88
+ const globals = getGlobalObject(scope);
89
+ if (!scope.compartment) scope.compartment = getCompartment(scope, globals);
90
+ const result = await (await scope.compartment).import(moduleUrl);
91
+ return result.namespace;
92
+ } // else use standard node:vm module to do containment
93
+ return await loadModuleWithVM(moduleUrl, scope);
94
+ } else {
95
+ // important! we need to await the import, otherwise the error will not be caught
96
+ return await import(moduleUrl);
97
+ }
98
+ } catch (err) {
99
+ try {
100
+ // the actual parse error (internally known as the "arrow message")
101
+ // is hidden behind a private symbol (arrowMessagePrivateSymbol)
102
+ // on the error object and the only way to access it is to use the
103
+ // internal util.decorateErrorStack() function
104
+ const util = await import('internal/util');
105
+ util.default.decorateErrorStack(err);
106
+ } catch {
107
+ // maybe --expose-internals was not set?
108
+ }
109
+ throw err;
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Load a module using Node's vm.Module API with (not really secure) sandboxing
115
+ */
116
+ async function loadModuleWithVM(moduleUrl: string, scope: ApplicationScope) {
117
+ const moduleCache = new Map<string, SourceTextModule | SyntheticModule>();
118
+ const linkingPromises = new Map<string, Promise<void>>();
119
+
120
+ // Create a secure context with limited globals
121
+ const contextObject = getGlobalObject(scope);
122
+ const context = createContext(contextObject);
123
+
124
+ /**
125
+ * Resolve module specifier to absolute URL
126
+ */
127
+ function resolveModule(specifier: string, referrer: string): string {
128
+ if (specifier === 'harperdb' || specifier === 'harper') return 'harper';
129
+ if (specifier.startsWith('harper/') || specifier.startsWith('harperdb/')) {
130
+ throw new Error(`Module ${specifier} is not allowed, may only access the 'harper' module`);
131
+ }
132
+ if (specifier.startsWith('file://')) {
133
+ return specifier;
134
+ }
135
+ // For relative paths, resolve to absolute file URL
136
+ if (specifier.startsWith('.')) {
137
+ const resolved = createRequire(referrer).resolve(specifier);
138
+ if (isAbsolute(resolved)) {
139
+ return pathToFileURL(resolved).toString();
140
+ }
141
+ return resolved;
142
+ }
143
+ // For package names and node: specifiers, keep as-is for proper require() handling
144
+ return specifier;
145
+ }
146
+
147
+ /**
148
+ * Load a CommonJS module in our private context
149
+ */
150
+ function loadCJS(url: string, source: string): { exports: any } {
151
+ const cjsModule = { exports: {} };
152
+ if (url.endsWith('.json')) {
153
+ cjsModule.exports = JSON.parse(source);
154
+ return cjsModule;
155
+ }
156
+ const require = createRequire(url);
157
+
158
+ const cjsRequire = (spec: string) => {
159
+ const resolvedPath = require.resolve(spec);
160
+ if (isAbsolute(resolvedPath)) {
161
+ const source = readFileSync(resolvedPath, { encoding: 'utf-8' });
162
+ return loadCJS(resolvedPath, source).exports;
163
+ } else {
164
+ return require(spec);
165
+ }
166
+ };
167
+ cjsRequire.resolve = require.resolve;
168
+
169
+ const cjsWrapper = `
170
+ (function(module, exports, require, __filename, __dirname) {
171
+ ${source}
172
+ })
173
+ `;
174
+
175
+ const wrappedFn = runInContext(cjsWrapper, contextObject, {
176
+ filename: url,
177
+ async importModuleDynamically(specifier: string, script) {
178
+ const resolvedUrl = resolveModule(specifier, script.sourceURL);
179
+ const useContainment = specifier.startsWith('.') || scope.dependencyContainment;
180
+ const dynamicModule = await loadModuleWithCache(resolvedUrl, useContainment);
181
+ return dynamicModule;
182
+ },
183
+ });
184
+ wrappedFn(
185
+ cjsModule,
186
+ cjsModule.exports,
187
+ cjsRequire,
188
+ url,
189
+ dirname(url.startsWith('file://') ? fileURLToPath(url) : url)
190
+ );
191
+
192
+ return cjsModule;
193
+ }
194
+ function loadCJSModule(url: string, source: string, usePrivateGlobal: boolean): SyntheticModule {
195
+ const cjsModule = usePrivateGlobal ? loadCJS(url, source) : { exports: require(url) };
196
+ const exportNames = Object.keys(cjsModule.exports);
197
+ const synModule = new SyntheticModule(
198
+ exportNames.length > 0 ? exportNames : ['default'],
199
+ function () {
200
+ if (exportNames.length > 0) {
201
+ for (const key of exportNames) {
202
+ this.setExport(key, cjsModule.exports[key]);
203
+ }
204
+ } else {
205
+ this.setExport('default', cjsModule.exports);
206
+ }
207
+ },
208
+ { identifier: url, context }
209
+ );
210
+ moduleCache.set(url, synModule);
211
+ return synModule;
212
+ }
213
+
214
+ /**
215
+ * Linker function for module resolution during instantiation
216
+ */
217
+ async function linker(specifier: string, referencingModule: SourceTextModule | SyntheticModule) {
218
+ const resolvedUrl = resolveModule(specifier, referencingModule.identifier);
219
+
220
+ const useContainment = specifier.startsWith('.') || scope.dependencyContainment;
221
+ // Return the module immediately (even if not yet linked) to support circular dependencies
222
+ return await getOrCreateModule(resolvedUrl, useContainment);
223
+ }
224
+
225
+ async function getOrCreateModule(
226
+ url: string,
227
+ usePrivateGlobal: boolean
228
+ ): Promise<SourceTextModule | SyntheticModule> {
229
+ // Check cache first - return cached module immediately (even if not linked yet)
230
+ if (moduleCache.has(url)) {
231
+ return moduleCache.get(url)!;
232
+ }
233
+
234
+ // Create the module and cache it immediately (before linking)
235
+ const module = await createModule(url, usePrivateGlobal);
236
+ moduleCache.set(url, module);
237
+
238
+ return module;
239
+ }
240
+
241
+ async function loadModuleWithCache(
242
+ url: string,
243
+ usePrivateGlobal: boolean
244
+ ): Promise<SourceTextModule | SyntheticModule> {
245
+ const module = await getOrCreateModule(url, usePrivateGlobal);
246
+
247
+ // Only link/evaluate once per module
248
+ if (!linkingPromises.has(url)) {
249
+ linkingPromises.set(
250
+ url,
251
+ module.link(linker).then(() => module.evaluate())
252
+ );
253
+ }
254
+
255
+ // Wait for linking to complete
256
+ await linkingPromises.get(url);
257
+
258
+ return module;
259
+ }
260
+ /**
261
+ * Create a module from URL without linking or evaluating
262
+ */
263
+ async function createModule(url: string, usePrivateGlobal: boolean): Promise<SourceTextModule | SyntheticModule> {
264
+ let module: SourceTextModule | SyntheticModule;
265
+
266
+ // Handle special built-in modules
267
+ if (url === 'harper' || url === 'harperdb') {
268
+ let harperExports = getHarperExports(scope);
269
+ module = new SyntheticModule(
270
+ Object.keys(harperExports),
271
+ function () {
272
+ for (let key in harperExports) {
273
+ this.setExport(key, harperExports[key]);
274
+ }
275
+ },
276
+ { identifier: url, context }
277
+ );
278
+ } else if (url.startsWith('file://')) {
279
+ checkAllowedModulePath(url, scope.verifyPath);
280
+ // Load source text from file
281
+ const source = await readFile(new URL(url), { encoding: 'utf-8' });
282
+
283
+ // Try to parse as ESM first
284
+ try {
285
+ module = new SourceTextModule(source, {
286
+ identifier: url,
287
+ context,
288
+ initializeImportMeta(meta) {
289
+ meta.url = url;
290
+ },
291
+ async importModuleDynamically(specifier: string) {
292
+ const resolvedUrl = resolveModule(specifier, url);
293
+ const dynamicModule = await loadModuleWithCache(resolvedUrl, true);
294
+ return dynamicModule;
295
+ },
296
+ });
297
+ } catch (err) {
298
+ // If ESM parsing fails, try to load as CommonJS
299
+ if (
300
+ err.message?.includes('require is not defined') ||
301
+ source.includes('module.exports') ||
302
+ source.includes('exports.')
303
+ ) {
304
+ module = loadCJSModule(url, source, usePrivateGlobal);
305
+ } else {
306
+ throw err;
307
+ }
308
+ }
309
+ } else {
310
+ const replacedModule = checkAllowedModulePath(url, scope.verifyPath);
311
+ // For Node.js built-in modules (node:) and npm packages
312
+ // Always try require first to properly handle CJS modules with named exports
313
+ try {
314
+ const cjsExports = replacedModule ?? require(url);
315
+ // It's a CJS module - expose all properties as named exports
316
+ const exportNames = Object.keys(cjsExports);
317
+ module = new SyntheticModule(
318
+ exportNames.length > 0 ? [...exportNames, 'default'] : ['default'],
319
+ function () {
320
+ if (exportNames.length > 0) {
321
+ for (const key of exportNames) {
322
+ this.setExport(key, cjsExports[key]);
323
+ }
324
+ }
325
+ this.setExport('default', cjsExports);
326
+ },
327
+ { identifier: url, context }
328
+ );
329
+ } catch {
330
+ // Fall back to dynamic import for ESM packages
331
+ const importedModule = await import(url);
332
+ const exportNames = Object.keys(importedModule);
333
+ module = new SyntheticModule(
334
+ exportNames,
335
+ function () {
336
+ for (const key of exportNames) {
337
+ this.setExport(key, importedModule[key]);
338
+ }
339
+ },
340
+ { identifier: url, context }
341
+ );
342
+ }
343
+ }
344
+
345
+ return module;
346
+ }
347
+
348
+ // Load the entry module
349
+ const entryModule = await loadModuleWithCache(moduleUrl, true);
350
+
351
+ // Return the module namespace (exports)
352
+ return entryModule.namespace;
353
+ }
354
+
355
+ async function getCompartment(scope: ApplicationScope, globals) {
356
+ const { StaticModuleRecord } = await import('@endo/static-module-record');
357
+ require('ses');
358
+ const compartment: CompartmentOptions = new (Compartment as typeof CompartmentOptions)(
359
+ globals,
360
+ {
361
+ //harperdb: { Resource, tables, databases }
362
+ },
363
+ {
364
+ name: 'harper-app',
365
+ resolveHook(moduleSpecifier, moduleReferrer) {
366
+ if (moduleSpecifier === 'harperdb' || moduleSpecifier === 'harper') return 'harper';
367
+ const resolved = createRequire(moduleReferrer).resolve(moduleSpecifier);
368
+ if (isAbsolute(resolved)) {
369
+ const resolvedURL = pathToFileURL(resolved).toString();
370
+ return resolvedURL;
371
+ }
372
+ return moduleSpecifier;
373
+ },
374
+ importHook: async (moduleSpecifier) => {
375
+ if (moduleSpecifier === 'harper') {
376
+ const harperExports = getHarperExports(scope);
377
+ return {
378
+ imports: [],
379
+ exports: Object.keys(harperExports),
380
+ execute(exports) {
381
+ Object.assign(exports, harperExports);
382
+ },
383
+ };
384
+ } else if (moduleSpecifier.startsWith('file:') && !moduleSpecifier.includes('node_modules')) {
385
+ const moduleText = await readFile(new URL(moduleSpecifier), { encoding: 'utf-8' });
386
+ return new StaticModuleRecord(moduleText, moduleSpecifier);
387
+ } else {
388
+ checkAllowedModulePath(moduleSpecifier, scope.verifyPath);
389
+ const moduleExports = await import(moduleSpecifier);
390
+ return {
391
+ imports: [],
392
+ exports: Object.keys(moduleExports),
393
+ execute(exports) {
394
+ for (const key of Object.keys(moduleExports)) {
395
+ exports[key] = moduleExports[key];
396
+ }
397
+ },
398
+ };
399
+ }
400
+ },
401
+ }
402
+ );
403
+ return compartment;
404
+ }
405
+
406
+ /**
407
+ * This a constrained fetch. It certainly is not guaranteed to be safe, but requiring https may
408
+ * be a good heuristic for preventing access to unsecured resources within a private network.
409
+ * @param resource
410
+ * @param options
411
+ */
412
+ function secureOnlyFetch(resource, options) {
413
+ // TODO: or maybe we should constrain by doing a DNS lookup and having disallow list of IP addresses that includes
414
+ // this server
415
+ const url = typeof resource === 'string' || resource.url;
416
+ if (new URL(url).protocol != 'https') throw new Error('Only https is allowed in fetch');
417
+ return fetch(resource, options);
418
+ }
419
+
420
+ let defaultJSGlobalNames: string[];
421
+ // get the global variable names that are intrinsically present in a VM context (so we don't override them)
422
+ function getDefaultJSGlobalNames() {
423
+ if (!defaultJSGlobalNames) {
424
+ defaultJSGlobalNames = runInContext(
425
+ 'Object.getOwnPropertyNames((function() { return this })())',
426
+ createContext({})
427
+ );
428
+ }
429
+ return defaultJSGlobalNames;
430
+ }
431
+
432
+ /**
433
+ * Get the set of global variables that should be available to modules that run in scoped compartments/contexts.
434
+ */
435
+ function getGlobalObject(scope: ApplicationScope) {
436
+ const appGlobal = {};
437
+ // create the new global object, assigning all the global variables from this global
438
+ // except those that will be natural intrinsics of the new VM
439
+ for (let name of Object.getOwnPropertyNames(global)) {
440
+ if (getDefaultJSGlobalNames().includes(name)) continue;
441
+ appGlobal[name] = global[name];
442
+ }
443
+ // now assign Harper scope-specific variables
444
+ Object.assign(appGlobal, {
445
+ server: scope.server ?? server,
446
+ logger: scope.logger ?? logger,
447
+ resources: scope.resources,
448
+ config: scope.config ?? {},
449
+ fetch: APPLICATIONS_LOCKDOWN === 'ses' ? secureOnlyFetch : fetch,
450
+ console,
451
+ global: appGlobal,
452
+ harper: getHarperExports(scope),
453
+ });
454
+ return appGlobal;
455
+ }
456
+ function getHarperExports(scope: ApplicationScope) {
457
+ return {
458
+ server: scope.server ?? server,
459
+ logger: scope.logger ?? logger,
460
+ resources: scope.resources,
461
+ config: scope.config ?? {},
462
+ Resource,
463
+ tables,
464
+ databases,
465
+ createBlob,
466
+ RequestTarget,
467
+ getContext,
468
+ transaction,
469
+ getResponse,
470
+ getUser,
471
+ authenticateUser: server.authenticateUser,
472
+ operation: server.operation,
473
+ contentTypes,
474
+ };
475
+ }
476
+ const ALLOWED_NODE_BUILTIN_MODULES = env.get(CONFIG_PARAMS.APPLICATIONS_ALLOWEDBUILTINMODULES)
477
+ ? new Set(env.get(CONFIG_PARAMS.APPLICATIONS_ALLOWEDBUILTINMODULES))
478
+ : {
479
+ // if we don't have a list of allowed modules, allow everything
480
+ has() {
481
+ return true;
482
+ },
483
+ };
484
+ const ALLOWED_COMMANDS = new Set(env.get(CONFIG_PARAMS.APPLICATIONS_ALLOWEDSPAWNCOMMANDS) ?? []);
485
+ const REPLACED_BUILTIN_MODULES = {
486
+ child_process: {
487
+ exec: createSpawn(child_process.exec),
488
+ execFile: createSpawn(child_process.execFile),
489
+ fork: createSpawn(child_process.fork, true), // this is launching node, so deemed safe
490
+ spawn: createSpawn(child_process.spawn),
491
+ },
492
+ };
493
+ /**
494
+ * Creates a ChildProcess-like object for an existing process
495
+ */
496
+ class ExistingProcessWrapper extends EventEmitter {
497
+ pid: number;
498
+ private checkInterval: NodeJS.Timeout;
499
+
500
+ constructor(pid: number) {
501
+ super();
502
+ this.pid = pid;
503
+
504
+ // Monitor process and emit exit event when it terminates
505
+ this.checkInterval = setInterval(() => {
506
+ try {
507
+ // Signal 0 checks if process exists without actually killing it
508
+ process.kill(pid, 0);
509
+ } catch {
510
+ // Process no longer exists
511
+ clearInterval(this.checkInterval);
512
+ this.emit('exit', null, null);
513
+ }
514
+ }, 1000);
515
+ }
516
+
517
+ // Kill the process
518
+ kill(signal?: NodeJS.Signals | number) {
519
+ try {
520
+ process.kill(this.pid, signal);
521
+ return true;
522
+ } catch {
523
+ return false;
524
+ }
525
+ }
526
+
527
+ // Clean up interval when wrapper is no longer needed
528
+ unref() {
529
+ clearInterval(this.checkInterval);
530
+ return this;
531
+ }
532
+ }
533
+
534
+ /**
535
+ * Checks if a process with the given PID is running
536
+ */
537
+ function isProcessRunning(pid: number): boolean {
538
+ try {
539
+ // Signal 0 checks existence without killing
540
+ process.kill(pid, 0);
541
+ return true;
542
+ } catch {
543
+ return false;
544
+ }
545
+ }
546
+
547
+ /**
548
+ * Acquires an exclusive lock using the PID file itself (synchronously with busy-wait)
549
+ * Returns 0 if lock was acquired (need to spawn new process), or the existing PID if process is running
550
+ */
551
+ function acquirePidFileLock(pidFilePath: string, maxRetries = 100, retryDelay = 5): number {
552
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
553
+ try {
554
+ // Try to open exclusively - 'wx' fails if file exists
555
+ const fd = openSync(pidFilePath, 'wx');
556
+ closeSync(fd);
557
+ return 0; // Successfully acquired lock (file created), caller should spawn process
558
+ } catch (err) {
559
+ if (err.code === 'EEXIST') {
560
+ // File exists - check if it contains a valid running process
561
+ try {
562
+ const pidContent = readFileSync(pidFilePath, 'utf-8');
563
+ const existingPid = parseInt(pidContent.trim(), 10);
564
+
565
+ if (!isNaN(existingPid) && isProcessRunning(existingPid)) {
566
+ // Valid process is running, return its PID immediately
567
+ return existingPid;
568
+ }
569
+
570
+ // Invalid/empty PID - check file age to determine if it's stale or being written
571
+ const stats = statSync(pidFilePath);
572
+ const fileAge = Date.now() - stats.mtimeMs;
573
+
574
+ // If file is very new (less than 100ms) and empty/invalid, another thread is likely still writing to it
575
+ if (fileAge < 100) {
576
+ // Just wait and retry, don't try to remove
577
+ } else {
578
+ // Stale PID file (old and invalid), try to remove it
579
+ try {
580
+ unlinkSync(pidFilePath);
581
+ } catch {
582
+ // Another thread may have removed it, retry
583
+ }
584
+ }
585
+ } catch {
586
+ // Couldn't read/stat file, another thread might be modifying it, retry
587
+ }
588
+
589
+ // Wait a bit before retrying
590
+ const start = Date.now();
591
+ while (Date.now() - start < retryDelay) {
592
+ // Busy wait
593
+ }
594
+ } else {
595
+ throw err;
596
+ }
597
+ }
598
+ }
599
+
600
+ throw new Error(`Failed to acquire PID file lock after ${maxRetries} attempts`);
601
+ }
602
+
603
+ function createSpawn(spawnFunction: (...args: any) => child_process.ChildProcess, alwaysAllow?: boolean) {
604
+ const basePath = env.getHdbBasePath();
605
+ return function (command: string, args?: any, options?: any, callback?: (...args: any[]) => void) {
606
+ if (!ALLOWED_COMMANDS.has(command.split(' ')[0]) && !alwaysAllow) {
607
+ throw new Error(`Command ${command} is not allowed`);
608
+ }
609
+ const processName = options?.name;
610
+ if (!processName)
611
+ throw new Error(
612
+ `Calling ${spawnFunction.name} in Harper must have a process "name" in the options to ensure that a single process is started and reused`
613
+ );
614
+
615
+ // Ensure PID directory exists
616
+ const pidDir = join(basePath, 'pids');
617
+ mkdirSync(pidDir, { recursive: true });
618
+
619
+ const pidFilePath = join(pidDir, `${processName}.pid`);
620
+
621
+ // Try to acquire lock - returns 0 if acquired, or existing PID
622
+ const existingPid = acquirePidFileLock(pidFilePath);
623
+
624
+ if (existingPid !== 0) {
625
+ // Existing process is running, return wrapper
626
+ return new ExistingProcessWrapper(existingPid);
627
+ }
628
+
629
+ // We acquired the lock (file was created), spawn new process
630
+ const childProcess = spawnFunction(command, args, options, callback);
631
+
632
+ // Write PID to the file we just created
633
+ try {
634
+ writeFileSync(pidFilePath, childProcess.pid.toString(), 'utf-8');
635
+ } catch (err) {
636
+ // Failed to write PID, clean up
637
+ try {
638
+ childProcess.kill();
639
+ unlinkSync(pidFilePath);
640
+ } catch {}
641
+ throw err;
642
+ }
643
+
644
+ // Clean up PID file when process exits
645
+ childProcess.on('exit', () => {
646
+ try {
647
+ unlinkSync(pidFilePath);
648
+ } catch {
649
+ // File may already be removed
650
+ }
651
+ });
652
+
653
+ return childProcess;
654
+ };
655
+ }
656
+
657
+ /**
658
+ * Validates whether a module can be loaded based on security restrictions and returns the module path or replacement.
659
+ * For file URLs, ensures the module is within the containing folder.
660
+ * For node built-in modules, checks against an allowlist and returns any replacements.
661
+ *
662
+ * @param {string} moduleUrl - The URL or identifier of the module to be loaded, which may be a file: URL, node: URL, or bare module specifier.
663
+ * @param {string} containingFolder - The absolute path of the folder that contains the application, used to validate file: URLs are within bounds.
664
+ * @return {any} Returns undefined for allowed file paths, or a replacement module identifier for allowed node built-in modules.
665
+ * @throws {Error} Throws an error if the module is outside the application folder or if the module is not in the allowed list.
666
+ */
667
+ function checkAllowedModulePath(moduleUrl: string, containingFolder?: string): boolean {
668
+ if (moduleUrl.startsWith('file:')) {
669
+ const path = moduleUrl.slice(7);
670
+ if (!containingFolder || path.startsWith(containingFolder)) {
671
+ return;
672
+ }
673
+ throw new Error(`Can not load module outside of application folder ${containingFolder}`);
674
+ }
675
+ let simpleName = moduleUrl.startsWith('node:') ? moduleUrl.slice(5) : moduleUrl;
676
+ simpleName = simpleName.split('/')[0];
677
+ if (ALLOWED_NODE_BUILTIN_MODULES.has(simpleName)) return REPLACED_BUILTIN_MODULES[simpleName];
678
+ throw new Error(`Module ${moduleUrl} is not allowed to be imported`);
679
+ }
680
+
681
+ function getContext() {
682
+ return contextStorage.getStore() ?? {};
683
+ }
684
+ function getUser() {
685
+ return contextStorage.getStore()?.user;
686
+ }
687
+ function getResponse() {
688
+ return contextStorage.getStore()?.response;
689
+ }
690
+
691
+ export function preventFunctionConstructor() {
692
+ Function.prototype.constructor = function () {}; // prevent this from being used to eval data in a parent context
693
+ }
694
+
695
+ /**
696
+ * This can redefine a property into a getter/setter that will allow derivatives of a prototype to assign
697
+ * a value to the property without incurring an error from the property being frozen and readonly.
698
+ * @param target
699
+ * @param name
700
+ * @param value
701
+ */
702
+ function overridableProperty(target, name, value = target[name]) {
703
+ Object.defineProperty(target, name, {
704
+ get() {
705
+ return value;
706
+ },
707
+ set(value) {
708
+ Object.defineProperty(this, name, {
709
+ value,
710
+ configurable: true,
711
+ enumerable: true,
712
+ writable: true,
713
+ });
714
+ },
715
+ });
716
+ }