@harperfast/harper 5.0.0-alpha.10 → 5.0.0-beta.3

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 (446) 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/{resources/ResourceInterfaceV2.js → components/Logger.js} +1 -1
  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 +17 -10
  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/ResourceInterface.d.ts +1 -1
  145. package/dist/resources/RocksIndexStore.d.ts +3 -3
  146. package/dist/resources/RocksTransactionLogStore.d.ts +6 -3
  147. package/dist/resources/Table.d.ts +15 -6
  148. package/dist/resources/Table.js +12 -4
  149. package/dist/resources/Table.js.map +1 -1
  150. package/dist/resources/analytics/read.js +32 -22
  151. package/dist/resources/analytics/read.js.map +1 -1
  152. package/dist/resources/analytics/write.js +3 -6
  153. package/dist/resources/analytics/write.js.map +1 -1
  154. package/dist/resources/auditStore.d.ts +3 -3
  155. package/dist/resources/blob.d.ts +25 -2
  156. package/dist/resources/databases.d.ts +12 -2
  157. package/dist/resources/databases.js +22 -19
  158. package/dist/resources/databases.js.map +1 -1
  159. package/dist/resources/search.js +11 -5
  160. package/dist/resources/search.js.map +1 -1
  161. package/dist/resources/transaction.d.ts +2 -1
  162. package/dist/security/auth.js +1 -1
  163. package/dist/security/auth.js.map +1 -1
  164. package/dist/security/cryptoHash.d.ts +2 -2
  165. package/dist/security/jsLoader.js +265 -73
  166. package/dist/security/jsLoader.js.map +1 -1
  167. package/dist/security/keys.js +11 -12
  168. package/dist/security/keys.js.map +1 -1
  169. package/dist/security/user.js +3 -3
  170. package/dist/security/user.js.map +1 -1
  171. package/dist/server/REST.js +16 -2
  172. package/dist/server/REST.js.map +1 -1
  173. package/dist/server/Server.d.ts +2 -1
  174. package/dist/server/Server.js.map +1 -1
  175. package/dist/server/fastifyRoutes/plugins/hdbCore.d.ts +6 -1
  176. package/dist/server/fastifyRoutes.js +2 -0
  177. package/dist/server/fastifyRoutes.js.map +1 -1
  178. package/dist/server/http.js +12 -6
  179. package/dist/server/http.js.map +1 -1
  180. package/dist/server/jobs/JobObject.d.ts +3 -3
  181. package/dist/server/loadRootComponents.js +1 -0
  182. package/dist/server/loadRootComponents.js.map +1 -1
  183. package/dist/server/operationsServer.js +3 -1
  184. package/dist/server/operationsServer.js.map +1 -1
  185. package/dist/server/serverHelpers/JSONStream.d.ts +3 -3
  186. package/dist/server/serverHelpers/Request.d.ts +5 -5
  187. package/dist/server/serverHelpers/requestTimePlugin.d.ts +1 -1
  188. package/dist/server/threads/manageThreads.d.ts +2 -2
  189. package/dist/server/threads/manageThreads.js +52 -35
  190. package/dist/server/threads/manageThreads.js.map +1 -1
  191. package/dist/server/threads/socketRouter.d.ts +1 -1
  192. package/dist/sqlTranslator/deleteTranslator.d.ts +1 -1
  193. package/dist/utility/AWS/AWSConnector.d.ts +3 -2
  194. package/dist/utility/common_utils.d.ts +3 -3
  195. package/dist/utility/environment/systemInformation.d.ts +1 -0
  196. package/dist/utility/functions/date/dateFunctions.d.ts +11 -11
  197. package/dist/utility/globalSchema.d.ts +1 -1
  198. package/dist/utility/hdbTerms.d.ts +3 -0
  199. package/dist/utility/hdbTerms.js +3 -0
  200. package/dist/utility/hdbTerms.js.map +1 -1
  201. package/dist/utility/installation.d.ts +2 -4
  202. package/dist/utility/installation.js.map +1 -1
  203. package/dist/utility/lmdb/commonUtility.d.ts +2 -1
  204. package/dist/utility/lmdb/commonUtility.js +20 -13
  205. package/dist/utility/lmdb/commonUtility.js.map +1 -1
  206. package/dist/utility/lmdb/deleteUtility.d.ts +1 -0
  207. package/dist/utility/lmdb/environmentUtility.d.ts +1 -0
  208. package/dist/utility/lmdb/searchUtility.d.ts +2 -1
  209. package/dist/utility/lmdb/writeUtility.d.ts +1 -0
  210. package/dist/utility/logging/harper_logger.d.ts +6 -6
  211. package/dist/utility/processManagement/processManagement.d.ts +1 -1
  212. package/dist/utility/processManagement/servicesConfig.d.ts +12 -6
  213. package/dist/validation/common_validators.d.ts +4 -3
  214. package/dist/validation/configValidator.d.ts +3 -2
  215. package/index.d.ts +56 -0
  216. package/index.js +41 -0
  217. package/json/systemSchema.json +373 -0
  218. package/launchServiceScripts/launchHarperDB.js +3 -0
  219. package/launchServiceScripts/utility/checkNodeVersion.js +15 -0
  220. package/package.json +35 -16
  221. package/resources/DatabaseTransaction.ts +378 -0
  222. package/resources/ErrorResource.ts +57 -0
  223. package/resources/IterableEventQueue.ts +94 -0
  224. package/resources/LMDBTransaction.ts +349 -0
  225. package/resources/RecordEncoder.ts +702 -0
  226. package/resources/RequestTarget.ts +134 -0
  227. package/resources/Resource.ts +789 -0
  228. package/resources/ResourceInterface.ts +221 -0
  229. package/resources/Resources.ts +162 -0
  230. package/resources/RocksIndexStore.ts +70 -0
  231. package/resources/RocksTransactionLogStore.ts +352 -0
  232. package/resources/Table.ts +4531 -0
  233. package/resources/analytics/hostnames.ts +72 -0
  234. package/resources/analytics/metadata.ts +10 -0
  235. package/resources/analytics/read.ts +252 -0
  236. package/resources/analytics/write.ts +803 -0
  237. package/resources/auditStore.ts +556 -0
  238. package/resources/blob.ts +1268 -0
  239. package/resources/crdt.ts +125 -0
  240. package/resources/dataLoader.ts +527 -0
  241. package/resources/databases.ts +1290 -0
  242. package/resources/graphql.ts +221 -0
  243. package/resources/indexes/HierarchicalNavigableSmallWorld.ts +638 -0
  244. package/resources/indexes/customIndexes.ts +7 -0
  245. package/resources/indexes/vector.ts +38 -0
  246. package/resources/jsResource.ts +86 -0
  247. package/resources/loadEnv.ts +22 -0
  248. package/resources/login.ts +18 -0
  249. package/resources/openApi.ts +409 -0
  250. package/resources/registrationDeprecated.ts +8 -0
  251. package/resources/replayLogs.ts +136 -0
  252. package/resources/roles.ts +98 -0
  253. package/resources/search.ts +1301 -0
  254. package/resources/tracked.ts +584 -0
  255. package/resources/transaction.ts +89 -0
  256. package/resources/transactionBroadcast.ts +258 -0
  257. package/security/auth.ts +376 -0
  258. package/security/certificateVerification/certificateVerificationSource.ts +84 -0
  259. package/security/certificateVerification/configValidation.ts +107 -0
  260. package/security/certificateVerification/crlVerification.ts +623 -0
  261. package/security/certificateVerification/index.ts +121 -0
  262. package/security/certificateVerification/ocspVerification.ts +148 -0
  263. package/security/certificateVerification/pkijs-ed25519-patch.ts +188 -0
  264. package/security/certificateVerification/types.ts +128 -0
  265. package/security/certificateVerification/verificationConfig.ts +138 -0
  266. package/security/certificateVerification/verificationUtils.ts +447 -0
  267. package/security/cryptoHash.js +42 -0
  268. package/security/data_objects/PermissionAttributeResponseObject.js +15 -0
  269. package/security/data_objects/PermissionResponseObject.js +115 -0
  270. package/security/data_objects/PermissionTableResponseObject.js +20 -0
  271. package/security/fastifyAuth.js +169 -0
  272. package/security/impersonation.ts +160 -0
  273. package/security/jsLoader.ts +733 -0
  274. package/security/keys.js +948 -0
  275. package/security/permissionsTranslator.js +300 -0
  276. package/security/role.js +218 -0
  277. package/security/tokenAuthentication.ts +228 -0
  278. package/security/user.ts +449 -0
  279. package/server/DurableSubscriptionsSession.ts +503 -0
  280. package/server/REST.ts +407 -0
  281. package/server/Server.ts +89 -0
  282. package/server/fastifyRoutes/helpers/getCORSOptions.js +36 -0
  283. package/server/fastifyRoutes/helpers/getHeaderTimeoutConfig.js +15 -0
  284. package/server/fastifyRoutes/helpers/getServerOptions.js +33 -0
  285. package/server/fastifyRoutes/plugins/hdbCore.js +39 -0
  286. package/server/fastifyRoutes.ts +205 -0
  287. package/server/graphqlQuerying.ts +700 -0
  288. package/server/http.ts +640 -0
  289. package/server/itc/serverHandlers.js +161 -0
  290. package/server/itc/utility/ITCEventObject.js +10 -0
  291. package/server/jobs/JobObject.js +24 -0
  292. package/server/jobs/jobProcess.js +69 -0
  293. package/server/jobs/jobRunner.js +162 -0
  294. package/server/jobs/jobs.js +304 -0
  295. package/server/loadRootComponents.js +44 -0
  296. package/server/mqtt.ts +485 -0
  297. package/server/nodeName.ts +75 -0
  298. package/server/operationsServer.ts +313 -0
  299. package/server/serverHelpers/Headers.ts +108 -0
  300. package/server/serverHelpers/JSONStream.ts +269 -0
  301. package/server/serverHelpers/OperationFunctionObject.ts +13 -0
  302. package/server/serverHelpers/Request.ts +158 -0
  303. package/server/serverHelpers/contentTypes.ts +637 -0
  304. package/server/serverHelpers/requestTimePlugin.js +57 -0
  305. package/server/serverHelpers/serverHandlers.js +148 -0
  306. package/server/serverHelpers/serverUtilities.ts +473 -0
  307. package/server/serverRegistry.ts +8 -0
  308. package/server/static.ts +187 -0
  309. package/server/status/definitions.ts +37 -0
  310. package/server/status/index.ts +125 -0
  311. package/server/storageReclamation.ts +93 -0
  312. package/server/threads/itc.js +89 -0
  313. package/server/threads/manageThreads.js +596 -0
  314. package/server/threads/socketRouter.ts +360 -0
  315. package/server/threads/threadServer.js +279 -0
  316. package/server/throttle.ts +73 -0
  317. package/sqlTranslator/SelectValidator.js +330 -0
  318. package/sqlTranslator/alasqlFunctionImporter.js +62 -0
  319. package/sqlTranslator/deleteTranslator.js +67 -0
  320. package/sqlTranslator/index.js +242 -0
  321. package/sqlTranslator/sql_statement_bucket.js +472 -0
  322. package/static/defaultConfig.yaml +3 -0
  323. package/studio/web/HDBDogOnly.svg +78 -0
  324. package/studio/web/assets/PPRadioGrotesk-Bold-DDaUYG8E.woff +0 -0
  325. package/studio/web/assets/fa-brands-400-CEJbCg16.woff +0 -0
  326. package/studio/web/assets/fa-brands-400-CSYNqBb_.ttf +0 -0
  327. package/studio/web/assets/fa-brands-400-DnkPfk3o.eot +0 -0
  328. package/studio/web/assets/fa-brands-400-UxlILjvJ.woff2 +0 -0
  329. package/studio/web/assets/fa-brands-400-cH1MgKbP.svg +3717 -0
  330. package/studio/web/assets/fa-regular-400-BhTwtT8w.eot +0 -0
  331. package/studio/web/assets/fa-regular-400-D1vz6WBx.ttf +0 -0
  332. package/studio/web/assets/fa-regular-400-DFnMcJPd.woff +0 -0
  333. package/studio/web/assets/fa-regular-400-DGzu1beS.woff2 +0 -0
  334. package/studio/web/assets/fa-regular-400-gwj8Pxq-.svg +801 -0
  335. package/studio/web/assets/fa-solid-900-B4ZZ7kfP.svg +5034 -0
  336. package/studio/web/assets/fa-solid-900-B6Axprfb.eot +0 -0
  337. package/studio/web/assets/fa-solid-900-BUswJgRo.woff2 +0 -0
  338. package/studio/web/assets/fa-solid-900-DOXgCApm.woff +0 -0
  339. package/studio/web/assets/fa-solid-900-mxuxnBEa.ttf +0 -0
  340. package/studio/web/assets/index-C1G-Jo6n.js +37 -0
  341. package/studio/web/assets/index-C1G-Jo6n.js.map +1 -0
  342. package/studio/web/assets/index-D-CahN0-.js +2 -0
  343. package/studio/web/assets/index-D-CahN0-.js.map +1 -0
  344. package/studio/web/assets/index-DxlZI0PX.js +235 -0
  345. package/studio/web/assets/index-DxlZI0PX.js.map +1 -0
  346. package/studio/web/assets/index-Y2g_iFpU.css +1 -0
  347. package/studio/web/assets/index-jiPwkrsB.css +1 -0
  348. package/studio/web/assets/index.lazy-BUXDDqq9.js +266 -0
  349. package/studio/web/assets/index.lazy-BUXDDqq9.js.map +1 -0
  350. package/studio/web/assets/profiler-CU93QiSW.js +2 -0
  351. package/studio/web/assets/profiler-CU93QiSW.js.map +1 -0
  352. package/studio/web/assets/react-redux-B8k9Ep7e.js +6 -0
  353. package/studio/web/assets/react-redux-B8k9Ep7e.js.map +1 -0
  354. package/studio/web/assets/startRecording-DFeBXGk6.js +3 -0
  355. package/studio/web/assets/startRecording-DFeBXGk6.js.map +1 -0
  356. package/studio/web/fabric-signup-background.webp +0 -0
  357. package/studio/web/fabric-signup-text.png +0 -0
  358. package/studio/web/favicon_purple.png +0 -0
  359. package/studio/web/github-icon.svg +15 -0
  360. package/studio/web/harper-fabric_black.png +0 -0
  361. package/studio/web/harper-fabric_white.png +0 -0
  362. package/studio/web/harper-studio_white.png +0 -0
  363. package/studio/web/index.html +16 -0
  364. package/studio/web/running.css +148 -0
  365. package/studio/web/running.html +147 -0
  366. package/studio/web/running.js +111 -0
  367. package/upgrade/UpgradeObjects.js +13 -0
  368. package/upgrade/directives/directivesController.js +90 -0
  369. package/upgrade/directivesManager.js +139 -0
  370. package/upgrade/upgradePrompt.js +124 -0
  371. package/upgrade/upgradeUtilities.js +28 -0
  372. package/utility/AWS/AWSConnector.js +29 -0
  373. package/utility/OperationFunctionCaller.js +63 -0
  374. package/utility/assignCmdEnvVariables.js +62 -0
  375. package/utility/common_utils.js +867 -0
  376. package/utility/environment/environmentManager.js +208 -0
  377. package/utility/environment/systemInformation.js +355 -0
  378. package/utility/errors/commonErrors.js +267 -0
  379. package/utility/errors/hdbError.js +146 -0
  380. package/utility/functions/date/dateFunctions.js +65 -0
  381. package/utility/functions/geo.js +355 -0
  382. package/utility/functions/sql/alaSQLExtension.js +104 -0
  383. package/utility/globalSchema.js +35 -0
  384. package/utility/hdbTerms.ts +819 -0
  385. package/utility/install/checkJWTTokensExist.js +62 -0
  386. package/utility/install/harperdb.conf +15 -0
  387. package/utility/install/harperdb.service +14 -0
  388. package/utility/install/installer.js +635 -0
  389. package/utility/installation.ts +30 -0
  390. package/utility/lmdb/DBIDefinition.js +20 -0
  391. package/utility/lmdb/DeleteRecordsResponseObject.js +25 -0
  392. package/utility/lmdb/InsertRecordsResponseObject.js +22 -0
  393. package/utility/lmdb/OpenDBIObject.js +31 -0
  394. package/utility/lmdb/OpenEnvironmentObject.js +41 -0
  395. package/utility/lmdb/UpdateRecordsResponseObject.js +25 -0
  396. package/utility/lmdb/UpsertRecordsResponseObject.js +22 -0
  397. package/utility/lmdb/cleanLMDBMap.js +65 -0
  398. package/utility/lmdb/commonUtility.js +130 -0
  399. package/utility/lmdb/deleteUtility.js +128 -0
  400. package/utility/lmdb/environmentUtility.js +477 -0
  401. package/utility/lmdb/searchCursorFunctions.js +187 -0
  402. package/utility/lmdb/searchUtility.js +918 -0
  403. package/utility/lmdb/terms.js +57 -0
  404. package/utility/lmdb/writeUtility.js +407 -0
  405. package/utility/logging/harper_logger.js +876 -0
  406. package/utility/logging/logRotator.js +157 -0
  407. package/utility/logging/logger.ts +24 -0
  408. package/utility/logging/readLog.js +355 -0
  409. package/utility/logging/transactionLog.js +57 -0
  410. package/utility/mount_hdb.js +59 -0
  411. package/utility/npmUtilities.js +102 -0
  412. package/utility/operationPermissions.ts +112 -0
  413. package/utility/operation_authorization.js +836 -0
  414. package/utility/packageUtils.js +55 -0
  415. package/utility/password.ts +99 -0
  416. package/utility/processManagement/processManagement.js +187 -0
  417. package/utility/processManagement/servicesConfig.js +56 -0
  418. package/utility/scripts/restartHdb.js +24 -0
  419. package/utility/scripts/user_data.sh +13 -0
  420. package/utility/signalling.js +36 -0
  421. package/utility/terms/certificates.js +81 -0
  422. package/utility/when.ts +20 -0
  423. package/validation/bulkDeleteValidator.js +24 -0
  424. package/validation/check_permissions.js +19 -0
  425. package/validation/common_validators.js +95 -0
  426. package/validation/configValidator.js +331 -0
  427. package/validation/deleteValidator.js +15 -0
  428. package/validation/fileLoadValidator.js +153 -0
  429. package/validation/insertValidator.js +40 -0
  430. package/validation/installValidator.js +37 -0
  431. package/validation/readLogValidator.js +64 -0
  432. package/validation/role_validation.js +320 -0
  433. package/validation/schemaMetadataValidator.js +42 -0
  434. package/validation/searchValidator.js +166 -0
  435. package/validation/statusValidator.ts +66 -0
  436. package/validation/transactionLogValidator.js +33 -0
  437. package/validation/user_validation.js +55 -0
  438. package/validation/validationWrapper.js +105 -0
  439. package/dist/resources/ResourceInterfaceV2.d.ts +0 -21
  440. package/dist/resources/ResourceInterfaceV2.js.map +0 -1
  441. package/dist/resources/ResourceV2.d.ts +0 -30
  442. package/dist/resources/ResourceV2.js +0 -27
  443. package/dist/resources/ResourceV2.js.map +0 -1
  444. package/dist/resources/analytics/profile.d.ts +0 -2
  445. package/dist/resources/analytics/profile.js +0 -144
  446. package/dist/resources/analytics/profile.js.map +0 -1
@@ -0,0 +1,733 @@
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 if (SourceTextModule) {
93
+ // else use standard node:vm module to do containment (if it is available)
94
+ return await loadModuleWithVM(moduleUrl, scope);
95
+ }
96
+ }
97
+ // important! we need to await the import, otherwise the error will not be caught
98
+ return await import(moduleUrl);
99
+ } catch (err) {
100
+ try {
101
+ // the actual parse error (internally known as the "arrow message")
102
+ // is hidden behind a private symbol (arrowMessagePrivateSymbol)
103
+ // on the error object and the only way to access it is to use the
104
+ // internal util.decorateErrorStack() function
105
+ const util = await import('internal/util');
106
+ util.default.decorateErrorStack(err);
107
+ } catch {
108
+ // maybe --expose-internals was not set?
109
+ }
110
+ throw err;
111
+ }
112
+ }
113
+
114
+ let amaro: typeof import('amaro') | undefined;
115
+ /**
116
+ * Strip TypeScript types using the amaro library (what Node.js uses internally)
117
+ * Falls back to regex-based stripping if amaro is not available
118
+ */
119
+ async function stripTypeScriptTypes(source: string): Promise<string> {
120
+ // Use amaro - the library that Node.js uses internally for type stripping
121
+ amaro = await import('amaro');
122
+ return amaro.transformSync(source, { mode: 'strip-only' }).code;
123
+ }
124
+
125
+ /**
126
+ * Load a module using Node's vm.Module API with (not really secure) sandboxing
127
+ */
128
+ async function loadModuleWithVM(moduleUrl: string, scope: ApplicationScope) {
129
+ const moduleCache = new Map<string, SourceTextModule | SyntheticModule>();
130
+ const linkingPromises = new Map<string, Promise<void>>();
131
+
132
+ // Create a secure context with limited globals
133
+ const contextObject = getGlobalObject(scope);
134
+ const context = createContext(contextObject);
135
+
136
+ /**
137
+ * Resolve module specifier to absolute URL
138
+ */
139
+ function resolveModule(specifier: string, referrer: string): string {
140
+ if (specifier === 'harperdb' || specifier === 'harper') return 'harper';
141
+ if (specifier.startsWith('harper/') || specifier.startsWith('harperdb/')) {
142
+ throw new Error(`Module ${specifier} is not allowed, may only access the 'harper' module`);
143
+ }
144
+ if (specifier.startsWith('file://')) {
145
+ return specifier;
146
+ }
147
+ // For relative paths, resolve to absolute file URL
148
+ if (specifier.startsWith('.')) {
149
+ const resolved = createRequire(referrer).resolve(specifier);
150
+ if (isAbsolute(resolved)) {
151
+ return pathToFileURL(resolved).toString();
152
+ }
153
+ return resolved;
154
+ }
155
+ // For package names and node: specifiers, keep as-is for proper require() handling
156
+ return specifier;
157
+ }
158
+
159
+ /**
160
+ * Load a CommonJS module in our private context
161
+ */
162
+ function loadCJS(url: string, source: string): { exports: any } {
163
+ const cjsModule = { exports: {} };
164
+ if (url.endsWith('.json')) {
165
+ cjsModule.exports = JSON.parse(source);
166
+ return cjsModule;
167
+ }
168
+ const require = createRequire(url);
169
+
170
+ const cjsRequire = (spec: string) => {
171
+ const resolvedPath = require.resolve(spec);
172
+ if (isAbsolute(resolvedPath)) {
173
+ const source = readFileSync(resolvedPath, { encoding: 'utf-8' });
174
+ return loadCJS(resolvedPath, source).exports;
175
+ } else {
176
+ return require(spec);
177
+ }
178
+ };
179
+ cjsRequire.resolve = require.resolve;
180
+
181
+ const cjsWrapper = `
182
+ (function(module, exports, require, __filename, __dirname) {
183
+ ${source}
184
+ })
185
+ `;
186
+
187
+ const wrappedFn = runInContext(cjsWrapper, contextObject, {
188
+ filename: url,
189
+ async importModuleDynamically(specifier: string, script) {
190
+ const resolvedUrl = resolveModule(specifier, script.sourceURL);
191
+ const useContainment = specifier.startsWith('.') || scope.dependencyContainment;
192
+ const dynamicModule = await loadModuleWithCache(resolvedUrl, useContainment);
193
+ return dynamicModule;
194
+ },
195
+ });
196
+ wrappedFn(
197
+ cjsModule,
198
+ cjsModule.exports,
199
+ cjsRequire,
200
+ url,
201
+ dirname(url.startsWith('file://') ? fileURLToPath(url) : url)
202
+ );
203
+
204
+ return cjsModule;
205
+ }
206
+ function loadCJSModule(url: string, source: string, usePrivateGlobal: boolean): SyntheticModule {
207
+ const cjsModule = usePrivateGlobal ? loadCJS(url, source) : { exports: require(url) };
208
+ const exportNames = Object.keys(cjsModule.exports);
209
+ const synModule = new SyntheticModule(
210
+ exportNames.length > 0 ? exportNames : ['default'],
211
+ function () {
212
+ if (exportNames.length > 0) {
213
+ for (const key of exportNames) {
214
+ this.setExport(key, cjsModule.exports[key]);
215
+ }
216
+ } else {
217
+ this.setExport('default', cjsModule.exports);
218
+ }
219
+ },
220
+ { identifier: url, context }
221
+ );
222
+ moduleCache.set(url, synModule);
223
+ return synModule;
224
+ }
225
+
226
+ /**
227
+ * Linker function for module resolution during instantiation
228
+ */
229
+ async function linker(specifier: string, referencingModule: SourceTextModule | SyntheticModule) {
230
+ const resolvedUrl = resolveModule(specifier, referencingModule.identifier);
231
+
232
+ const useContainment = specifier.startsWith('.') || scope.dependencyContainment;
233
+ // Return the module immediately (even if not yet linked) to support circular dependencies
234
+ return await getOrCreateModule(resolvedUrl, useContainment);
235
+ }
236
+
237
+ async function getOrCreateModule(
238
+ url: string,
239
+ usePrivateGlobal: boolean
240
+ ): Promise<SourceTextModule | SyntheticModule> {
241
+ // Check cache first - return cached module immediately (even if not linked yet)
242
+ if (moduleCache.has(url)) {
243
+ return moduleCache.get(url)!;
244
+ }
245
+
246
+ // Create the module and cache it immediately (before linking)
247
+ const module = await createModule(url, usePrivateGlobal);
248
+ moduleCache.set(url, module);
249
+
250
+ return module;
251
+ }
252
+
253
+ async function loadModuleWithCache(
254
+ url: string,
255
+ usePrivateGlobal: boolean
256
+ ): Promise<SourceTextModule | SyntheticModule> {
257
+ const module = await getOrCreateModule(url, usePrivateGlobal);
258
+
259
+ // Only link/evaluate once per module
260
+ if (!linkingPromises.has(url)) {
261
+ linkingPromises.set(
262
+ url,
263
+ module.link(linker).then(() => module.evaluate())
264
+ );
265
+ }
266
+
267
+ // Wait for linking to complete
268
+ await linkingPromises.get(url);
269
+
270
+ return module;
271
+ }
272
+ /**
273
+ * Create a module from URL without linking or evaluating
274
+ */
275
+ async function createModule(url: string, usePrivateGlobal: boolean): Promise<SourceTextModule | SyntheticModule> {
276
+ let module: SourceTextModule | SyntheticModule;
277
+
278
+ // Handle special built-in modules
279
+ if (url === 'harper' || url === 'harperdb') {
280
+ let harperExports = getHarperExports(scope);
281
+ module = new SyntheticModule(
282
+ Object.keys(harperExports),
283
+ function () {
284
+ for (let key in harperExports) {
285
+ this.setExport(key, harperExports[key]);
286
+ }
287
+ },
288
+ { identifier: url, context }
289
+ );
290
+ } else if (url.startsWith('file://')) {
291
+ checkAllowedModulePath(url, scope.verifyPath);
292
+ // Load source text from file
293
+ let source = await readFile(new URL(url), { encoding: 'utf-8' });
294
+
295
+ // Strip TypeScript types if this is a .ts file
296
+ if (url.endsWith('.ts') || url.endsWith('.tsx')) {
297
+ source = await stripTypeScriptTypes(source);
298
+ }
299
+
300
+ // Try to parse as ESM first
301
+ try {
302
+ module = new SourceTextModule(source, {
303
+ identifier: url,
304
+ context,
305
+ initializeImportMeta(meta) {
306
+ meta.url = url;
307
+ },
308
+ async importModuleDynamically(specifier: string) {
309
+ const resolvedUrl = resolveModule(specifier, url);
310
+ const dynamicModule = await loadModuleWithCache(resolvedUrl, true);
311
+ return dynamicModule;
312
+ },
313
+ });
314
+ } catch (err) {
315
+ // If ESM parsing fails, try to load as CommonJS
316
+ if (
317
+ err.message?.includes('require is not defined') ||
318
+ source.includes('module.exports') ||
319
+ source.includes('exports.')
320
+ ) {
321
+ module = loadCJSModule(url, source, usePrivateGlobal);
322
+ } else {
323
+ throw err;
324
+ }
325
+ }
326
+ } else {
327
+ const replacedModule = checkAllowedModulePath(url, scope.verifyPath);
328
+ // For Node.js built-in modules (node:) and npm packages
329
+ // Always try require first to properly handle CJS modules with named exports
330
+ try {
331
+ const cjsExports = replacedModule ?? require(url);
332
+ // It's a CJS module - expose all properties as named exports
333
+ const exportNames = Object.keys(cjsExports);
334
+ module = new SyntheticModule(
335
+ exportNames.length > 0 ? [...exportNames, 'default'] : ['default'],
336
+ function () {
337
+ if (exportNames.length > 0) {
338
+ for (const key of exportNames) {
339
+ this.setExport(key, cjsExports[key]);
340
+ }
341
+ }
342
+ this.setExport('default', cjsExports);
343
+ },
344
+ { identifier: url, context }
345
+ );
346
+ } catch {
347
+ // Fall back to dynamic import for ESM packages
348
+ const importedModule = await import(url);
349
+ const exportNames = Object.keys(importedModule);
350
+ module = new SyntheticModule(
351
+ exportNames,
352
+ function () {
353
+ for (const key of exportNames) {
354
+ this.setExport(key, importedModule[key]);
355
+ }
356
+ },
357
+ { identifier: url, context }
358
+ );
359
+ }
360
+ }
361
+
362
+ return module;
363
+ }
364
+
365
+ // Load the entry module
366
+ const entryModule = await loadModuleWithCache(moduleUrl, true);
367
+
368
+ // Return the module namespace (exports)
369
+ return entryModule.namespace;
370
+ }
371
+
372
+ async function getCompartment(scope: ApplicationScope, globals) {
373
+ const { StaticModuleRecord } = await import('@endo/static-module-record');
374
+ require('ses');
375
+ const compartment: CompartmentOptions = new (Compartment as typeof CompartmentOptions)(
376
+ globals,
377
+ {
378
+ //harperdb: { Resource, tables, databases }
379
+ },
380
+ {
381
+ name: 'harper-app',
382
+ resolveHook(moduleSpecifier, moduleReferrer) {
383
+ if (moduleSpecifier === 'harperdb' || moduleSpecifier === 'harper') return 'harper';
384
+ const resolved = createRequire(moduleReferrer).resolve(moduleSpecifier);
385
+ if (isAbsolute(resolved)) {
386
+ const resolvedURL = pathToFileURL(resolved).toString();
387
+ return resolvedURL;
388
+ }
389
+ return moduleSpecifier;
390
+ },
391
+ importHook: async (moduleSpecifier) => {
392
+ if (moduleSpecifier === 'harper') {
393
+ const harperExports = getHarperExports(scope);
394
+ return {
395
+ imports: [],
396
+ exports: Object.keys(harperExports),
397
+ execute(exports) {
398
+ Object.assign(exports, harperExports);
399
+ },
400
+ };
401
+ } else if (moduleSpecifier.startsWith('file:') && !moduleSpecifier.includes('node_modules')) {
402
+ const moduleText = await readFile(new URL(moduleSpecifier), { encoding: 'utf-8' });
403
+ return new StaticModuleRecord(moduleText, moduleSpecifier);
404
+ } else {
405
+ checkAllowedModulePath(moduleSpecifier, scope.verifyPath);
406
+ const moduleExports = await import(moduleSpecifier);
407
+ return {
408
+ imports: [],
409
+ exports: Object.keys(moduleExports),
410
+ execute(exports) {
411
+ for (const key of Object.keys(moduleExports)) {
412
+ exports[key] = moduleExports[key];
413
+ }
414
+ },
415
+ };
416
+ }
417
+ },
418
+ }
419
+ );
420
+ return compartment;
421
+ }
422
+
423
+ /**
424
+ * This a constrained fetch. It certainly is not guaranteed to be safe, but requiring https may
425
+ * be a good heuristic for preventing access to unsecured resources within a private network.
426
+ * @param resource
427
+ * @param options
428
+ */
429
+ function secureOnlyFetch(resource, options) {
430
+ // TODO: or maybe we should constrain by doing a DNS lookup and having disallow list of IP addresses that includes
431
+ // this server
432
+ const url = typeof resource === 'string' || resource.url;
433
+ if (new URL(url).protocol != 'https') throw new Error('Only https is allowed in fetch');
434
+ return fetch(resource, options);
435
+ }
436
+
437
+ let defaultJSGlobalNames: string[];
438
+ // get the global variable names that are intrinsically present in a VM context (so we don't override them)
439
+ function getDefaultJSGlobalNames() {
440
+ if (!defaultJSGlobalNames) {
441
+ defaultJSGlobalNames = runInContext(
442
+ 'Object.getOwnPropertyNames((function() { return this })())',
443
+ createContext({})
444
+ );
445
+ }
446
+ return defaultJSGlobalNames;
447
+ }
448
+
449
+ /**
450
+ * Get the set of global variables that should be available to modules that run in scoped compartments/contexts.
451
+ */
452
+ function getGlobalObject(scope: ApplicationScope) {
453
+ const appGlobal = {};
454
+ // create the new global object, assigning all the global variables from this global
455
+ // except those that will be natural intrinsics of the new VM
456
+ for (let name of Object.getOwnPropertyNames(global)) {
457
+ if (getDefaultJSGlobalNames().includes(name)) continue;
458
+ appGlobal[name] = global[name];
459
+ }
460
+ // now assign Harper scope-specific variables
461
+ Object.assign(appGlobal, {
462
+ server: scope.server ?? server,
463
+ logger: scope.logger ?? logger,
464
+ resources: scope.resources,
465
+ config: scope.config ?? {},
466
+ fetch: APPLICATIONS_LOCKDOWN === 'ses' ? secureOnlyFetch : fetch,
467
+ console,
468
+ global: appGlobal,
469
+ harper: getHarperExports(scope),
470
+ });
471
+ return appGlobal;
472
+ }
473
+ function getHarperExports(scope: ApplicationScope) {
474
+ return {
475
+ server: scope.server ?? server,
476
+ logger: scope.logger ?? logger,
477
+ resources: scope.resources,
478
+ config: scope.config ?? {},
479
+ Resource,
480
+ tables,
481
+ databases,
482
+ createBlob,
483
+ RequestTarget,
484
+ getContext,
485
+ transaction,
486
+ getResponse,
487
+ getUser,
488
+ authenticateUser: server.authenticateUser,
489
+ operation: server.operation,
490
+ contentTypes,
491
+ };
492
+ }
493
+ const ALLOWED_NODE_BUILTIN_MODULES = env.get(CONFIG_PARAMS.APPLICATIONS_ALLOWEDBUILTINMODULES)
494
+ ? new Set(env.get(CONFIG_PARAMS.APPLICATIONS_ALLOWEDBUILTINMODULES))
495
+ : {
496
+ // if we don't have a list of allowed modules, allow everything
497
+ has() {
498
+ return true;
499
+ },
500
+ };
501
+ const ALLOWED_COMMANDS = new Set(env.get(CONFIG_PARAMS.APPLICATIONS_ALLOWEDSPAWNCOMMANDS) ?? []);
502
+ const REPLACED_BUILTIN_MODULES = {
503
+ child_process: {
504
+ exec: createSpawn(child_process.exec),
505
+ execFile: createSpawn(child_process.execFile),
506
+ fork: createSpawn(child_process.fork, true), // this is launching node, so deemed safe
507
+ spawn: createSpawn(child_process.spawn),
508
+ },
509
+ };
510
+ /**
511
+ * Creates a ChildProcess-like object for an existing process
512
+ */
513
+ class ExistingProcessWrapper extends EventEmitter {
514
+ pid: number;
515
+ private checkInterval: NodeJS.Timeout;
516
+
517
+ constructor(pid: number) {
518
+ super();
519
+ this.pid = pid;
520
+
521
+ // Monitor process and emit exit event when it terminates
522
+ this.checkInterval = setInterval(() => {
523
+ try {
524
+ // Signal 0 checks if process exists without actually killing it
525
+ process.kill(pid, 0);
526
+ } catch {
527
+ // Process no longer exists
528
+ clearInterval(this.checkInterval);
529
+ this.emit('exit', null, null);
530
+ }
531
+ }, 1000);
532
+ }
533
+
534
+ // Kill the process
535
+ kill(signal?: NodeJS.Signals | number) {
536
+ try {
537
+ process.kill(this.pid, signal);
538
+ return true;
539
+ } catch {
540
+ return false;
541
+ }
542
+ }
543
+
544
+ // Clean up interval when wrapper is no longer needed
545
+ unref() {
546
+ clearInterval(this.checkInterval);
547
+ return this;
548
+ }
549
+ }
550
+
551
+ /**
552
+ * Checks if a process with the given PID is running
553
+ */
554
+ function isProcessRunning(pid: number): boolean {
555
+ try {
556
+ // Signal 0 checks existence without killing
557
+ process.kill(pid, 0);
558
+ return true;
559
+ } catch {
560
+ return false;
561
+ }
562
+ }
563
+
564
+ /**
565
+ * Acquires an exclusive lock using the PID file itself (synchronously with busy-wait)
566
+ * Returns 0 if lock was acquired (need to spawn new process), or the existing PID if process is running
567
+ */
568
+ function acquirePidFileLock(pidFilePath: string, maxRetries = 100, retryDelay = 5): number {
569
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
570
+ try {
571
+ // Try to open exclusively - 'wx' fails if file exists
572
+ const fd = openSync(pidFilePath, 'wx');
573
+ closeSync(fd);
574
+ return 0; // Successfully acquired lock (file created), caller should spawn process
575
+ } catch (err) {
576
+ if (err.code === 'EEXIST') {
577
+ // File exists - check if it contains a valid running process
578
+ try {
579
+ const pidContent = readFileSync(pidFilePath, 'utf-8');
580
+ const existingPid = parseInt(pidContent.trim(), 10);
581
+
582
+ if (!isNaN(existingPid) && isProcessRunning(existingPid)) {
583
+ // Valid process is running, return its PID immediately
584
+ return existingPid;
585
+ }
586
+
587
+ // Invalid/empty PID - check file age to determine if it's stale or being written
588
+ const stats = statSync(pidFilePath);
589
+ const fileAge = Date.now() - stats.mtimeMs;
590
+
591
+ // If file is very new (less than 100ms) and empty/invalid, another thread is likely still writing to it
592
+ if (fileAge < 100) {
593
+ // Just wait and retry, don't try to remove
594
+ } else {
595
+ // Stale PID file (old and invalid), try to remove it
596
+ try {
597
+ unlinkSync(pidFilePath);
598
+ } catch {
599
+ // Another thread may have removed it, retry
600
+ }
601
+ }
602
+ } catch {
603
+ // Couldn't read/stat file, another thread might be modifying it, retry
604
+ }
605
+
606
+ // Wait a bit before retrying
607
+ const start = Date.now();
608
+ while (Date.now() - start < retryDelay) {
609
+ // Busy wait
610
+ }
611
+ } else {
612
+ throw err;
613
+ }
614
+ }
615
+ }
616
+
617
+ throw new Error(`Failed to acquire PID file lock after ${maxRetries} attempts`);
618
+ }
619
+
620
+ function createSpawn(spawnFunction: (...args: any) => child_process.ChildProcess, alwaysAllow?: boolean) {
621
+ const basePath = env.getHdbBasePath();
622
+ return function (command: string, args?: any, options?: any, callback?: (...args: any[]) => void) {
623
+ if (!ALLOWED_COMMANDS.has(command.split(' ')[0]) && !alwaysAllow) {
624
+ throw new Error(`Command ${command} is not allowed`);
625
+ }
626
+ const processName = options?.name;
627
+ if (!processName)
628
+ throw new Error(
629
+ `Calling ${spawnFunction.name} in Harper must have a process "name" in the options to ensure that a single process is started and reused`
630
+ );
631
+
632
+ // Ensure PID directory exists
633
+ const pidDir = join(basePath, 'pids');
634
+ mkdirSync(pidDir, { recursive: true });
635
+
636
+ const pidFilePath = join(pidDir, `${processName}.pid`);
637
+
638
+ // Try to acquire lock - returns 0 if acquired, or existing PID
639
+ const existingPid = acquirePidFileLock(pidFilePath);
640
+
641
+ if (existingPid !== 0) {
642
+ // Existing process is running, return wrapper
643
+ return new ExistingProcessWrapper(existingPid);
644
+ }
645
+
646
+ // We acquired the lock (file was created), spawn new process
647
+ const childProcess = spawnFunction(command, args, options, callback);
648
+
649
+ // Write PID to the file we just created
650
+ try {
651
+ writeFileSync(pidFilePath, childProcess.pid.toString(), 'utf-8');
652
+ } catch (err) {
653
+ // Failed to write PID, clean up
654
+ try {
655
+ childProcess.kill();
656
+ unlinkSync(pidFilePath);
657
+ } catch {}
658
+ throw err;
659
+ }
660
+
661
+ // Clean up PID file when process exits
662
+ childProcess.on('exit', () => {
663
+ try {
664
+ unlinkSync(pidFilePath);
665
+ } catch {
666
+ // File may already be removed
667
+ }
668
+ });
669
+
670
+ return childProcess;
671
+ };
672
+ }
673
+
674
+ /**
675
+ * Validates whether a module can be loaded based on security restrictions and returns the module path or replacement.
676
+ * For file URLs, ensures the module is within the containing folder.
677
+ * For node built-in modules, checks against an allowlist and returns any replacements.
678
+ *
679
+ * @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.
680
+ * @param {string} containingFolder - The absolute path of the folder that contains the application, used to validate file: URLs are within bounds.
681
+ * @return {any} Returns undefined for allowed file paths, or a replacement module identifier for allowed node built-in modules.
682
+ * @throws {Error} Throws an error if the module is outside the application folder or if the module is not in the allowed list.
683
+ */
684
+ function checkAllowedModulePath(moduleUrl: string, containingFolder?: string): boolean {
685
+ if (moduleUrl.startsWith('file:')) {
686
+ const path = moduleUrl.slice(7);
687
+ if (!containingFolder || path.startsWith(containingFolder)) {
688
+ return;
689
+ }
690
+ throw new Error(`Can not load module outside of application folder ${containingFolder}`);
691
+ }
692
+ let simpleName = moduleUrl.startsWith('node:') ? moduleUrl.slice(5) : moduleUrl;
693
+ simpleName = simpleName.split('/')[0];
694
+ if (ALLOWED_NODE_BUILTIN_MODULES.has(simpleName)) return REPLACED_BUILTIN_MODULES[simpleName];
695
+ throw new Error(`Module ${moduleUrl} is not allowed to be imported`);
696
+ }
697
+
698
+ function getContext() {
699
+ return contextStorage.getStore() ?? {};
700
+ }
701
+ function getUser() {
702
+ return contextStorage.getStore()?.user;
703
+ }
704
+ function getResponse() {
705
+ return contextStorage.getStore()?.response;
706
+ }
707
+
708
+ export function preventFunctionConstructor() {
709
+ Function.prototype.constructor = function () {}; // prevent this from being used to eval data in a parent context
710
+ }
711
+
712
+ /**
713
+ * This can redefine a property into a getter/setter that will allow derivatives of a prototype to assign
714
+ * a value to the property without incurring an error from the property being frozen and readonly.
715
+ * @param target
716
+ * @param name
717
+ * @param value
718
+ */
719
+ function overridableProperty(target, name, value = target[name]) {
720
+ Object.defineProperty(target, name, {
721
+ get() {
722
+ return value;
723
+ },
724
+ set(value) {
725
+ Object.defineProperty(this, name, {
726
+ value,
727
+ configurable: true,
728
+ enumerable: true,
729
+ writable: true,
730
+ });
731
+ },
732
+ });
733
+ }