@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,125 @@
1
+ export function add(record, property, action) {
2
+ const previousValue = record[property];
3
+ if (typeof previousValue === 'bigint') {
4
+ record[property] = previousValue + BigInt(action.value);
5
+ } else if (isNaN(record[property])) record[property] = action.value;
6
+ else {
7
+ record[property] = previousValue + action.value;
8
+ }
9
+ }
10
+ add.reverse = function (record, property, action) {
11
+ const previousValue = record[property];
12
+ if (typeof previousValue === 'bigint') {
13
+ record[property] = previousValue - BigInt(action.value);
14
+ } else if (!isNaN(record[property])) {
15
+ record[property] = previousValue - action.value;
16
+ }
17
+ };
18
+ const operations = {
19
+ add,
20
+ };
21
+
22
+ /**
23
+ * Rebuild a record update that has a timestamp before the provided newer update
24
+ * @param update
25
+ * @param newerUpdate
26
+ */
27
+ export function rebuildUpdateBefore(update: any, newerUpdate: any, fullUpdate?: boolean) {
28
+ let newUpdate = null;
29
+ for (const key in update) {
30
+ if (key in newerUpdate) {
31
+ const newerValue = newerUpdate[key];
32
+ if (newerValue?.__op__) {
33
+ const value = update[key];
34
+ if (value?.__op__) {
35
+ if (value.__op__ === newerValue.__op__) {
36
+ // we only have add right now
37
+ if (!newUpdate) newUpdate = {};
38
+ newUpdate[key] = value;
39
+ } else throw new Error('Can not merge updates with different operations');
40
+ } else {
41
+ if (!newUpdate) newUpdate = {};
42
+ // start with the older value
43
+ newUpdate[key] = value;
44
+ // and apply the newer update
45
+ add(newUpdate, key, newerValue);
46
+ }
47
+ } else if (fullUpdate) {
48
+ // if the newer update has a direct non-CRDT value, it overwrites the older update, but if we are using a full copy, we need to include it
49
+ if (!newUpdate) newUpdate = {};
50
+ newUpdate[key] = newerValue;
51
+ } // else we can skip for a patch
52
+ } else {
53
+ // if the newer update does not have a value for this key, we can include it
54
+ if (!newUpdate) newUpdate = {};
55
+ newUpdate[key] = update[key];
56
+ }
57
+ }
58
+ return newUpdate;
59
+ }
60
+ export function applyReverse(record, update, unknowns: Set<string>) {
61
+ for (const key in update) {
62
+ const value = update[key];
63
+ if (value?.__op__) {
64
+ const reverse = operations[value.__op__]?.reverse;
65
+ if (reverse) reverse(record, key, { value: value.value });
66
+ else throw new Error(`Unsupported operation ${value.__op__}`);
67
+ } else {
68
+ unknowns.add(key);
69
+ }
70
+ }
71
+ }
72
+
73
+ /**
74
+ * Reconstruct the record state at a given timestamp by going back through the audit history and reversing any changes
75
+ * @param currentEntry
76
+ * @param timestamp
77
+ * @param store
78
+ * @returns
79
+ */
80
+ export function getRecordAtTime(currentEntry, timestamp, store, tableId: number, recordId: any) {
81
+ const auditStore = store.rootStore.auditStore;
82
+ let record = { ...currentEntry.value };
83
+ let auditTime = currentEntry.localTime;
84
+ // Iterate in reverse through the record history, trying to reverse all changes
85
+ const unknowns = new Set<string>();
86
+ while (auditTime > timestamp) {
87
+ const auditEntry = auditStore.get(auditTime, tableId, recordId);
88
+ if (!auditEntry) break;
89
+ switch (auditEntry.type) {
90
+ case 'put':
91
+ record = auditEntry.getValue(store);
92
+ break;
93
+ case 'patch':
94
+ applyReverse(record, auditEntry.getValue(store), unknowns);
95
+ break;
96
+ case 'delete':
97
+ record = null;
98
+ }
99
+ auditTime = auditEntry.previousVersion;
100
+ }
101
+ // some patches may leave properties in an unknown state, so we need to fill in the blanks
102
+ // first we determine if there any unknown properties
103
+ // then continue to iterate back through the audit history, filling in the blanks
104
+ while (unknowns.size > 0 && auditTime > 0) {
105
+ const auditEntry = auditStore.get(auditTime, tableId, recordId);
106
+ let priorRecord: any;
107
+ switch (auditEntry.type) {
108
+ case 'put':
109
+ priorRecord = auditEntry.getValue(store);
110
+ break;
111
+ case 'patch':
112
+ priorRecord = auditEntry.getValue(store);
113
+ break;
114
+ }
115
+ for (const key in priorRecord) {
116
+ if (unknowns.has(key)) {
117
+ record[key] = priorRecord[key];
118
+ unknowns.delete(key);
119
+ }
120
+ }
121
+ auditTime = auditEntry.previousVersion;
122
+ }
123
+ // finally return the record in the state it was at the requested timestamp
124
+ return record;
125
+ }
@@ -0,0 +1,527 @@
1
+ import { basename, extname } from 'node:path';
2
+ import { createHash } from 'node:crypto';
3
+ import { parseDocument } from 'yaml';
4
+ import { Databases, databases, table, Tables, tables } from './databases.ts';
5
+ import { getWorkerIndex } from '../server/threads/manageThreads';
6
+ import { HTTP_STATUS_CODES } from '../utility/errors/commonErrors.js';
7
+ import { ClientError } from '../utility/errors/hdbError.js';
8
+ import harperLogger from '../utility/logging/harper_logger.js';
9
+ import { Attribute } from './Table.ts';
10
+ import { FileEntry } from '../components/EntryHandler.ts';
11
+
12
+ const dataLoaderLogger = harperLogger.forComponent('dataLoader');
13
+
14
+ /** System table name for storing data loader hashes */
15
+ const DATA_LOADER_HASH_TABLE = 'hdb_dataloader_hash';
16
+
17
+ /** Lazy-initialized cache for the hash tracking table */
18
+ let _hashTrackingTable: ReturnType<typeof table>;
19
+
20
+ /**
21
+ * Computes a deterministic hash of a record's content for tracking data file changes.
22
+ * The hash is computed from a stable JSON representation (sorted keys) to ensure
23
+ * the same content always produces the same hash, regardless of key order.
24
+ *
25
+ * @param record - The record object to hash
26
+ * @returns A hex string hash of the record content
27
+ */
28
+ export function computeRecordHash(record: Record<string, any>): string {
29
+ // Sort keys for deterministic hashing
30
+ const sortedKeys = Object.keys(record).sort();
31
+ const sortedRecord: Record<string, any> = {};
32
+ for (const key of sortedKeys) {
33
+ sortedRecord[key] = record[key];
34
+ }
35
+
36
+ // Compute hash of the stable JSON representation
37
+ const content = JSON.stringify(sortedRecord);
38
+ return createHash('sha256').update(content).digest('hex');
39
+ }
40
+
41
+ /**
42
+ * Gets or creates the hash tracking table in the system database.
43
+ * Lazy-initializes the table on first access.
44
+ */
45
+ function getHashTrackingTable(databasesRef: Databases) {
46
+ // Always check databasesRef first (important for testing with mocks)
47
+ if (databasesRef.system && databasesRef.system[DATA_LOADER_HASH_TABLE]) {
48
+ return databasesRef.system[DATA_LOADER_HASH_TABLE];
49
+ }
50
+
51
+ // Use cached table if available
52
+ if (_hashTrackingTable) {
53
+ return _hashTrackingTable;
54
+ }
55
+
56
+ // Create the system table for tracking hashes
57
+ _hashTrackingTable = table({
58
+ database: 'system',
59
+ table: DATA_LOADER_HASH_TABLE,
60
+ attributes: [
61
+ { name: 'id', type: 'string', isPrimaryKey: true }, // Format: "database:table:recordId"
62
+ { name: 'hash', type: 'string' },
63
+ ],
64
+ });
65
+
66
+ return _hashTrackingTable;
67
+ }
68
+
69
+ /**
70
+ * Gets the stored hash for a record from the tracking table
71
+ */
72
+ async function getStoredHash(
73
+ database: string | undefined,
74
+ tableName: string,
75
+ recordId: string,
76
+ databasesRef: Databases
77
+ ): Promise<string | null> {
78
+ try {
79
+ const trackingTable = getHashTrackingTable(databasesRef);
80
+ const hashId = database ? `${database}:${tableName}:${recordId}` : `${tableName}:${recordId}`;
81
+ const hashRecord = await trackingTable.get(hashId);
82
+ return hashRecord?.hash || null;
83
+ } catch (error) {
84
+ dataLoaderLogger.error?.(`Failed to get stored hash: ${error.message}`);
85
+ return null;
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Stores the hash for a record in the tracking table
91
+ */
92
+ async function storeHash(
93
+ database: string | undefined,
94
+ tableName: string,
95
+ recordId: string,
96
+ hash: string,
97
+ databasesRef: Databases
98
+ ): Promise<void> {
99
+ try {
100
+ const trackingTable = getHashTrackingTable(databasesRef);
101
+ const hashId = database ? `${database}:${tableName}:${recordId}` : `${tableName}:${recordId}`;
102
+ await trackingTable.put({ id: hashId, hash });
103
+ } catch (error) {
104
+ dataLoaderLogger.error?.(`Failed to store hash: ${error.message}`);
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Set up file handlers for data files and loads them into the appropriate tables
110
+ */
111
+ export function handleApplication(scope) {
112
+ // Early return if this isn't worker zero
113
+ // Currently using getWorkerIndex() over server.workerIndex to appease ts. The latter defined in manageThreads.js.
114
+ if (getWorkerIndex() !== 0) {
115
+ // debug and return
116
+ dataLoaderLogger.debug?.('Skipping data loader initialization on non-primary worker');
117
+ return;
118
+ }
119
+
120
+ // Handle all files that match the pattern in the config
121
+ // Note: Using .then() instead of async/await to avoid the performance overhead
122
+ // of additional promise wrappers created by the async/await syntax sugar
123
+ scope.handleEntry(function handleDataLoaderEntry(entry) {
124
+ // Return early if not adding or updating a file
125
+ if (entry.entryType !== 'file' || entry.eventType === 'unlink') {
126
+ return Promise.resolve();
127
+ }
128
+
129
+ return loadDataFile(entry, tables, databases).then((result) => {
130
+ dataLoaderLogger.debug?.('Data loader processed file: %s: %s', basename(entry.absolutePath), result.message);
131
+ });
132
+ });
133
+ }
134
+
135
+ /**
136
+ * This component handles data loading from YAML or JSON files into user-defined tables.
137
+ * @param { contents, absolutePath, stats } - File entry content buffer, absolute path, and stats
138
+ * @param tablesRef - Reference to tables object (local const for testing)
139
+ * @param databasesRef - Reference to databases object (local const for testing)
140
+ */
141
+
142
+ export async function loadDataFile({ contents, absolutePath }: FileEntry, tablesRef: Tables, databasesRef: Databases) {
143
+ const fileExt = extname(absolutePath) || 'unknown';
144
+ let data: DataFileFormat;
145
+
146
+ // Need to grab the file extension to determine how to parse the content
147
+ try {
148
+ if (fileExt === '.yaml' || fileExt === '.yml') {
149
+ data = parseDocument(contents.toString()).toJSON();
150
+ } else if (fileExt === '.json') {
151
+ data = JSON.parse(contents.toString());
152
+ } else {
153
+ throw new UnsupportedFileExtensionError(absolutePath, fileExt);
154
+ }
155
+ } catch (error) {
156
+ // Re-throw DataLoaderErrors
157
+ if (error instanceof DataLoaderError) {
158
+ throw error;
159
+ }
160
+
161
+ // Otherwise wrap in a FileParseError and throw
162
+ throw new FileParseError(absolutePath, error);
163
+ }
164
+
165
+ // Ensure data exists. I.E. the file is not empty
166
+ if (!data) {
167
+ throw new EmptyFileError(absolutePath);
168
+ }
169
+
170
+ const { database, table: tableName, records } = data;
171
+
172
+ // Validate the data format
173
+ if (!tableName) {
174
+ throw new MissingRequiredPropertyError(absolutePath, 'table');
175
+ }
176
+
177
+ if (!records) {
178
+ throw new MissingRequiredPropertyError(absolutePath, 'records');
179
+ }
180
+
181
+ if (!Array.isArray(records)) {
182
+ throw new InvalidPropertyTypeError(absolutePath, 'records', 'array');
183
+ }
184
+
185
+ // tableIdentifier is used for logging and error messages
186
+ const tableIdentifier = database ? `${database}.${tableName}` : tableName;
187
+
188
+ // Don't allow loading data into the system database
189
+ if (database?.toLowerCase() === 'system') {
190
+ throw new SystemDatabaseError(database, tableName);
191
+ }
192
+
193
+ try {
194
+ // Try to get the table from global tables if it exists
195
+ let tableRef;
196
+
197
+ // If a database is specified, check if the table exists in that database
198
+ if (database && databasesRef[database] && databasesRef[database][tableName]) {
199
+ dataLoaderLogger.debug?.(`Using existing table ${tableIdentifier} from database tables`);
200
+ tableRef = databasesRef[database][tableName];
201
+ }
202
+ // If no database is specified, check if the table exists in the global tables
203
+ else if (tablesRef && tablesRef[tableName]) {
204
+ dataLoaderLogger.debug?.(`Using existing table ${tableIdentifier} from global tables`);
205
+ tableRef = tablesRef[tableName];
206
+ } else {
207
+ // Table doesn't exist. Try to infer the schema from the first record
208
+ dataLoaderLogger.debug?.(`Table ${tableIdentifier} not found, creating new table`);
209
+
210
+ // Extract attributes from the first record for the ensureTable call
211
+ const attributes: Attribute[] = [];
212
+ if (records.length > 0) {
213
+ const firstRecord = records[0];
214
+ Object.keys(firstRecord)
215
+ .map((attrName) => {
216
+ const attr: Attribute = { name: attrName, type: typeof firstRecord[attrName] };
217
+ // If the attribute is 'id', mark it as primary key
218
+ if (attrName === 'id') {
219
+ attr.isPrimaryKey = true;
220
+ }
221
+ return attr;
222
+ })
223
+ .forEach((attr) => {
224
+ attributes.push(attr);
225
+ });
226
+ }
227
+
228
+ tableRef = await table({
229
+ database,
230
+ table: tableName,
231
+ attributes,
232
+ });
233
+ }
234
+
235
+ // Process records with timestamp comparison
236
+ // Count metrics
237
+ const dataFIleRecords = records.length;
238
+ let newRecords = 0;
239
+ let updatedRecords = 0;
240
+ let skippedRecords = 0;
241
+
242
+ // Process each record in a batch to avoid excessive memory usage
243
+ const batchSize = 100; // Process in batches of 100 records
244
+
245
+ for (let i = 0; i < records.length; i += batchSize) {
246
+ const batch = records.slice(i, i + batchSize);
247
+ const batchPromises: Array<() => Promise<any>> = [];
248
+
249
+ for (const newRecord of batch) {
250
+ // Wrap in an async function to handle errors individually
251
+ batchPromises.push(async () => {
252
+ try {
253
+ // Get existing record with the same ID if it exists
254
+ let existingRecord: Record<string, any> | null = null;
255
+ const recordId = newRecord.id;
256
+
257
+ if (recordId !== undefined) {
258
+ existingRecord = await tableRef.get(recordId);
259
+ }
260
+
261
+ // Compute hash of the new record from the data file
262
+ const newRecordHash = computeRecordHash(newRecord);
263
+
264
+ if (!existingRecord) {
265
+ // If the record doesn't exist yet, insert it
266
+ newRecords++;
267
+ const result = await tableRef.put(newRecord);
268
+ // Store the hash in the tracking table
269
+ await storeHash(database, tableName, recordId, newRecordHash, databasesRef);
270
+ return result;
271
+ }
272
+
273
+ // Check if there's a stored hash for this record
274
+ const existingHash = await getStoredHash(database, tableName, recordId, databasesRef);
275
+
276
+ if (!existingHash) {
277
+ // No hash means this record wasn't loaded by the data loader
278
+ // (likely created via operations API or other means)
279
+ // Don't overwrite user-created records
280
+ skippedRecords++;
281
+ return Promise.resolve({ inserted: 0, updated: 0 });
282
+ }
283
+
284
+ // Compute hash of only the fields that exist in the data file
285
+ // This allows users to add extra fields without triggering a "modified" detection
286
+ // Note: This is a simple top-level field comparison - nested object changes
287
+ // within data file fields will still be detected as modifications
288
+ const existingRecordSubset: Record<string, any> = {};
289
+ for (const key of Object.keys(newRecord)) {
290
+ if (key in existingRecord) {
291
+ existingRecordSubset[key] = existingRecord[key];
292
+ }
293
+ }
294
+ const existingRecordHash = computeRecordHash(existingRecordSubset);
295
+
296
+ if (existingRecordHash !== existingHash) {
297
+ // The existing record's data file fields don't match the stored hash,
298
+ // meaning those fields were modified externally (via operations API, etc.)
299
+ // Don't overwrite user-modified records
300
+ skippedRecords++;
301
+ return Promise.resolve({ inserted: 0, updated: 0 });
302
+ }
303
+
304
+ // Compare hashes to detect actual content changes in the data file
305
+ if (newRecordHash !== existingHash) {
306
+ // Hash differs - the data file content has changed
307
+ // Use patch to update only the fields from the data file,
308
+ // preserving any additional fields the user may have added
309
+ updatedRecords++;
310
+ await tableRef.patch(recordId, newRecord);
311
+ await storeHash(database, tableName, recordId, newRecordHash, databasesRef);
312
+ // Return a result indicating update (patch doesn't return a value)
313
+ return { updated: 1 };
314
+ } else {
315
+ // Hash matches - content hasn't changed, skip update
316
+ skippedRecords++;
317
+ return Promise.resolve({ inserted: 0, updated: 0 });
318
+ }
319
+ } catch (error) {
320
+ // For individual record errors, we log but continue processing other records
321
+ // This allows partial success in data loading
322
+ if (error instanceof DataLoaderError) {
323
+ dataLoaderLogger.error?.(`Record processing error: ${error.message}`);
324
+ } else {
325
+ const recError = new RecordProcessingError(tableIdentifier, error);
326
+ dataLoaderLogger.error?.(`Record processing error: ${recError.message}`);
327
+ }
328
+
329
+ // Don't throw, just return a failed operation result
330
+ return Promise.resolve({ inserted: 0, updated: 0, error: error.message });
331
+ }
332
+ });
333
+ }
334
+
335
+ // Execute batch promises. Currently not doing anything about errors or the put() results.
336
+ await Promise.all(batchPromises.map((fn) => fn()));
337
+ }
338
+
339
+ // Return a single result object
340
+ if (newRecords > 0 || updatedRecords > 0) {
341
+ let message = `Loaded ${newRecords} new and updated ${updatedRecords} records in ${tableIdentifier}`;
342
+ if (skippedRecords > 0) {
343
+ message += ` (${skippedRecords} records skipped)`;
344
+ }
345
+ dataLoaderLogger.info?.(message);
346
+
347
+ return new DataLoaderResult(absolutePath, database, tableName, 'success', newRecords + updatedRecords, message);
348
+ } else if (skippedRecords > 0) {
349
+ const message = `All ${skippedRecords} records in ${tableIdentifier} already up-to-date`;
350
+ dataLoaderLogger.info?.(message);
351
+
352
+ return new DataLoaderResult(absolutePath, database, tableName, 'skipped', dataFIleRecords, message);
353
+ } else {
354
+ const message = `No records to process in ${tableIdentifier}`;
355
+ dataLoaderLogger.info?.(message);
356
+
357
+ return new DataLoaderResult(absolutePath, database, tableName, 'success', 0, message);
358
+ }
359
+ } catch (error) {
360
+ // If it's already one of our custom errors, just rethrow
361
+ if (error instanceof DataLoaderError) {
362
+ throw error;
363
+ }
364
+
365
+ // Wrap and throw other errors
366
+ throw new RecordProcessingError(tableIdentifier, error);
367
+ }
368
+ }
369
+
370
+ /**
371
+ * Custom errors for the dataLoader. These are thrown during startup validation to fail early
372
+ * rather than continuing with invalid data.
373
+ */
374
+
375
+ /**
376
+ * Base class for DataLoader specific errors
377
+ */
378
+ export class DataLoaderError extends ClientError {
379
+ constructor(message: string, statusCode: number = HTTP_STATUS_CODES.BAD_REQUEST) {
380
+ super(message, statusCode);
381
+ this.name = 'DataLoaderError';
382
+ }
383
+ }
384
+
385
+ /**
386
+ * Error thrown when a file has an unsupported extension
387
+ */
388
+ export class UnsupportedFileExtensionError extends DataLoaderError {
389
+ constructor(filePath: string, extension: string) {
390
+ super(
391
+ `Unsupported file extension in ${basename(filePath)}: ${extension}. Only YAML and JSON files are supported.`,
392
+ HTTP_STATUS_CODES.BAD_REQUEST
393
+ );
394
+ this.name = 'UnsupportedFileExtensionError';
395
+ }
396
+ }
397
+
398
+ /**
399
+ * Error thrown when a file cannot be parsed
400
+ */
401
+ export class FileParseError extends DataLoaderError {
402
+ constructor(filePath: string, originalError: Error) {
403
+ super(`Failed to parse data file ${basename(filePath)}: ${originalError.message}`, HTTP_STATUS_CODES.BAD_REQUEST);
404
+ this.name = 'FileParseError';
405
+ }
406
+ }
407
+
408
+ /**
409
+ * Error thrown when a file is empty or invalid
410
+ */
411
+ export class EmptyFileError extends DataLoaderError {
412
+ constructor(filePath: string) {
413
+ super(`Data file ${basename(filePath)} is empty or invalid`, HTTP_STATUS_CODES.BAD_REQUEST);
414
+ this.name = 'EmptyFileError';
415
+ }
416
+ }
417
+
418
+ /**
419
+ * Error thrown when a data file is missing required properties
420
+ */
421
+ export class MissingRequiredPropertyError extends DataLoaderError {
422
+ constructor(filePath: string, property: string) {
423
+ super(`Data file ${basename(filePath)} is missing required "${property}" property`, HTTP_STATUS_CODES.BAD_REQUEST);
424
+ this.name = 'MissingRequiredPropertyError';
425
+ }
426
+ }
427
+
428
+ /**
429
+ * Error thrown when a property has an invalid type
430
+ */
431
+ export class InvalidPropertyTypeError extends DataLoaderError {
432
+ constructor(filePath: string, property: string, expectedType: string) {
433
+ super(
434
+ `Data file ${basename(filePath)} has invalid "${property}" property, expected ${expectedType}`,
435
+ HTTP_STATUS_CODES.BAD_REQUEST
436
+ );
437
+ this.name = 'InvalidPropertyTypeError';
438
+ }
439
+ }
440
+
441
+ /**
442
+ * Error thrown when trying to load data into the system database
443
+ */
444
+ export class SystemDatabaseError extends DataLoaderError {
445
+ constructor(database: string, table: string) {
446
+ super(`Cannot load data into system database: ${database}.${table}`, HTTP_STATUS_CODES.FORBIDDEN);
447
+ this.name = 'SystemDatabaseError';
448
+ }
449
+ }
450
+
451
+ /**
452
+ * Error thrown when record processing fails
453
+ */
454
+ export class RecordProcessingError extends DataLoaderError {
455
+ constructor(tableIdentifier: string, originalError: Error) {
456
+ super(
457
+ `Failed to process record in ${tableIdentifier}: ${originalError.message}`,
458
+ HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR
459
+ );
460
+ this.name = 'RecordProcessingError';
461
+ }
462
+ }
463
+
464
+ // Define the structure of the data file format
465
+ export interface DataFileFormat {
466
+ database?: string; // Optional database name
467
+ table: string; // Required table name
468
+ records: Record<string, any>[]; // Array of records to load
469
+ }
470
+
471
+ // Define the class for data loader results
472
+ export class DataLoaderResult {
473
+ #filePath: string; // Path to the data file
474
+ #database: string; // Database name
475
+ #table: string; // Table name
476
+ #status: string; // Status of the operation
477
+ #count: number; // Number of records processed
478
+ #message: string; // Message about the operation
479
+
480
+ constructor(
481
+ filePath: string,
482
+ database: string | null | undefined,
483
+ table: string | null,
484
+ status: string,
485
+ count: number,
486
+ message: string
487
+ ) {
488
+ this.#filePath = filePath;
489
+ this.#database = database || 'unknown';
490
+ this.#table = table || 'unknown';
491
+ this.#status = status;
492
+ this.#count = count;
493
+ this.#message = message;
494
+ }
495
+
496
+ // Getters
497
+ get filePath(): string {
498
+ return this.#filePath;
499
+ }
500
+ get database(): string {
501
+ return this.#database;
502
+ }
503
+ get table(): string {
504
+ return this.#table;
505
+ }
506
+ get status(): string {
507
+ return this.#status;
508
+ }
509
+ get count(): number {
510
+ return this.#count;
511
+ }
512
+ get message(): string {
513
+ return this.#message;
514
+ }
515
+
516
+ // Methods to convert to JSON (for serialization)
517
+ toJSON() {
518
+ return {
519
+ filePath: this.#filePath,
520
+ database: this.#database,
521
+ table: this.#table,
522
+ status: this.#status,
523
+ count: this.#count,
524
+ message: this.#message,
525
+ };
526
+ }
527
+ }