@harperfast/harper-pro 5.0.30 → 5.1.0-beta.2

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 (942) hide show
  1. package/analytics/profile.ts +4 -0
  2. package/core/AGENTS.md +94 -6
  3. package/core/DESIGN.md +36 -0
  4. package/core/README.md +11 -10
  5. package/core/agent/agent.ts +203 -0
  6. package/core/agent/loop.ts +205 -0
  7. package/core/agent/operations.ts +148 -0
  8. package/core/agent/session.ts +187 -0
  9. package/core/agent/tools/fsTools.ts +276 -0
  10. package/core/agent/tools/httpFetchTool.ts +112 -0
  11. package/core/agent/tools/scheduleTool.ts +68 -0
  12. package/core/agent/toolset.ts +43 -0
  13. package/core/agent/types.ts +85 -0
  14. package/core/benchmarks/hnsw-search.js +157 -0
  15. package/core/benchmarks/ycsb/README.md +144 -0
  16. package/core/benchmarks/ycsb/analyze-profile.mts +120 -0
  17. package/core/benchmarks/ycsb/app/config.yaml +3 -0
  18. package/core/benchmarks/ycsb/app/schema.graphql +17 -0
  19. package/core/benchmarks/ycsb/harness.mts +328 -0
  20. package/core/benchmarks/ycsb/restClient.mts +120 -0
  21. package/core/benchmarks/ycsb/run-single-node.mts +97 -0
  22. package/core/benchmarks/ycsb/to-benchmark-json.mts +58 -0
  23. package/core/benchmarks/ycsb/workload.mts +499 -0
  24. package/core/benchmarks/ycsb/workload.test.mts +174 -0
  25. package/core/bin/{BinObjects.js → BinObjects.ts} +4 -5
  26. package/core/bin/cliCredentials.ts +133 -0
  27. package/core/bin/cliOperations.ts +339 -0
  28. package/core/bin/copyDb.ts +10 -10
  29. package/core/bin/deployRenderer.ts +196 -0
  30. package/core/bin/{harper.js → harper.ts} +48 -24
  31. package/core/bin/{install.js → install.ts} +3 -3
  32. package/core/bin/lite.ts +2 -0
  33. package/core/bin/login.ts +134 -0
  34. package/core/bin/logout.ts +11 -0
  35. package/core/bin/mcp/client.ts +407 -0
  36. package/core/bin/mcp/doctor.ts +189 -0
  37. package/core/bin/mcp/index.ts +80 -0
  38. package/core/bin/mcp/options.ts +122 -0
  39. package/core/bin/mcp/printConfig.ts +89 -0
  40. package/core/bin/multipartBuilder.ts +74 -0
  41. package/core/bin/{restart.js → restart.ts} +31 -32
  42. package/core/bin/{run.js → run.ts} +57 -46
  43. package/core/bin/sseConsumer.ts +126 -0
  44. package/core/bin/{status.js → status.ts} +10 -10
  45. package/core/bin/stop.ts +21 -0
  46. package/core/bin/upgrade.js +17 -24
  47. package/core/components/Application.ts +144 -18
  48. package/core/components/ApplicationScope.ts +2 -2
  49. package/core/components/ComponentV1.ts +2 -2
  50. package/core/components/EntryHandler.ts +159 -9
  51. package/core/components/OptionsWatcher.ts +75 -11
  52. package/core/components/Scope.ts +132 -18
  53. package/core/components/anthropic/index.ts +547 -0
  54. package/core/components/bedrock/index.ts +823 -0
  55. package/core/components/componentLoader.ts +64 -32
  56. package/core/components/deployLifecycle.ts +161 -0
  57. package/core/components/deploymentOperations.ts +173 -0
  58. package/core/components/deploymentRecorder.ts +427 -0
  59. package/core/components/deriveURLPath.ts +4 -4
  60. package/core/components/mcp/adapters/fastify.ts +87 -0
  61. package/core/components/mcp/adapters/harperHttp.ts +103 -0
  62. package/core/components/mcp/audit.ts +75 -0
  63. package/core/components/mcp/index.ts +134 -0
  64. package/core/components/mcp/jsonrpc.ts +134 -0
  65. package/core/components/mcp/lifecycle.ts +105 -0
  66. package/core/components/mcp/listChanged.ts +270 -0
  67. package/core/components/mcp/rateLimit.ts +217 -0
  68. package/core/components/mcp/resources.ts +607 -0
  69. package/core/components/mcp/session.ts +151 -0
  70. package/core/components/mcp/sessionRegistry.ts +140 -0
  71. package/core/components/mcp/toolRegistry.ts +294 -0
  72. package/core/components/mcp/tools/application.ts +761 -0
  73. package/core/components/mcp/tools/operations.ts +311 -0
  74. package/core/components/mcp/tools/schemas/derive.ts +356 -0
  75. package/core/components/mcp/tools/schemas/operationDescriptions.ts +241 -0
  76. package/core/components/mcp/tools/schemas/operations.ts +301 -0
  77. package/core/components/mcp/transport.ts +517 -0
  78. package/core/components/ollama/index.ts +316 -0
  79. package/core/components/openai/index.ts +563 -0
  80. package/core/components/operations.js +217 -60
  81. package/core/components/operationsValidation.js +12 -4
  82. package/core/components/packageComponent.ts +97 -29
  83. package/core/components/requestRestart.ts +17 -2
  84. package/core/components/status/crossThread.ts +14 -5
  85. package/core/components/status/errors.ts +1 -1
  86. package/core/config/RootConfigWatcher.ts +56 -2
  87. package/core/config/configUtils.js +29 -8
  88. package/core/config/harperConfigEnvVars.ts +1 -1
  89. package/core/dataLayer/{CreateAttributeObject.js → CreateAttributeObject.ts} +4 -3
  90. package/core/dataLayer/{CreateTableObject.js → CreateTableObject.ts} +2 -1
  91. package/core/dataLayer/{DataLayerObjects.js → DataLayerObjects.ts} +17 -9
  92. package/core/dataLayer/{DeleteBeforeObject.js → DeleteBeforeObject.ts} +2 -1
  93. package/core/dataLayer/{DeleteObject.js → DeleteObject.ts} +3 -2
  94. package/core/dataLayer/{DropAttributeObject.js → DropAttributeObject.ts} +2 -1
  95. package/core/dataLayer/{GetBackupObject.js → GetBackupObject.ts} +3 -2
  96. package/core/dataLayer/{InsertObject.js → InsertObject.ts} +3 -2
  97. package/core/dataLayer/{ReadAuditLogObject.js → ReadAuditLogObject.ts} +3 -2
  98. package/core/dataLayer/{SQLSearch.js → SQLSearch.ts} +97 -43
  99. package/core/dataLayer/{SearchByConditionsObject.js → SearchByConditionsObject.ts} +5 -6
  100. package/core/dataLayer/{SearchByHashObject.js → SearchByHashObject.ts} +2 -1
  101. package/core/dataLayer/{SearchObject.js → SearchObject.ts} +2 -1
  102. package/core/dataLayer/{SqlSearchObject.js → SqlSearchObject.ts} +2 -1
  103. package/core/dataLayer/{UpdateObject.js → UpdateObject.ts} +3 -2
  104. package/core/dataLayer/{UpsertObject.js → UpsertObject.ts} +3 -2
  105. package/core/dataLayer/{bulkLoad.js → bulkLoad.ts} +40 -49
  106. package/core/dataLayer/{delete.js → delete.ts} +21 -26
  107. package/core/dataLayer/{export.js → export.ts} +22 -26
  108. package/core/dataLayer/{getBackup.js → getBackup.ts} +7 -9
  109. package/core/dataLayer/harperBridge/BridgeMethods.ts +102 -0
  110. package/core/dataLayer/harperBridge/ResourceBridge.ts +27 -26
  111. package/core/dataLayer/harperBridge/TableSizeObject.ts +1 -0
  112. package/core/dataLayer/harperBridge/bridgeUtility/insertUpdateValidate.js +4 -4
  113. package/core/dataLayer/harperBridge/{harperBridge.js → harperBridge.ts} +3 -3
  114. package/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateAttribute.js +8 -6
  115. package/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateRecords.js +4 -4
  116. package/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateSchema.js +1 -1
  117. package/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateTable.js +6 -4
  118. package/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDeleteAuditLogsBefore.js +5 -4
  119. package/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDeleteRecords.js +4 -4
  120. package/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDropAttribute.js +6 -5
  121. package/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDropSchema.js +5 -4
  122. package/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDropTable.js +5 -5
  123. package/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbFlush.js +1 -1
  124. package/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbGetBackup.js +3 -3
  125. package/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbGetDataByHash.js +1 -1
  126. package/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbGetDataByValue.js +3 -2
  127. package/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbReadAuditLog.js +5 -5
  128. package/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbSearchByConditions.js +10 -8
  129. package/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbSearchByHash.js +1 -1
  130. package/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbSearchByValue.js +4 -3
  131. package/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbUpdateRecords.js +3 -3
  132. package/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbUpsertRecords.js +6 -5
  133. package/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBCreateAttributeObject.js +2 -1
  134. package/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/initializeHashSearch.js +3 -2
  135. package/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/initializePaths.js +2 -2
  136. package/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbCheckForNewAttributes.js +5 -4
  137. package/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbCreateTransactionsAuditEnvironment.js +6 -3
  138. package/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbGetTableSize.ts +1 -1
  139. package/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbProcessRows.js +4 -4
  140. package/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbSearch.js +5 -5
  141. package/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbWriteTransaction.js +4 -4
  142. package/core/dataLayer/{hdbInfoController.js → hdbInfoController.ts} +20 -26
  143. package/core/dataLayer/{insert.js → insert.ts} +24 -24
  144. package/core/dataLayer/{readAuditLog.js → readAuditLog.ts} +8 -10
  145. package/core/dataLayer/{schema.js → schema.ts} +32 -44
  146. package/core/dataLayer/{schemaDescribe.js → schemaDescribe.ts} +23 -26
  147. package/core/dataLayer/{search.js → search.ts} +9 -15
  148. package/core/dataLayer/{transaction.js → transaction.ts} +2 -5
  149. package/core/dataLayer/{update.js → update.ts} +19 -22
  150. package/core/index.ts +5 -0
  151. package/core/json/systemSchema.json +65 -0
  152. package/core/launchServiceScripts/utility/checkNodeVersion.js +2 -0
  153. package/core/package-lock.json +9087 -4345
  154. package/core/resources/DESIGN.md +98 -0
  155. package/core/resources/DatabaseTransaction.ts +58 -30
  156. package/core/resources/ErrorResource.ts +2 -1
  157. package/core/resources/LMDBTransaction.ts +38 -29
  158. package/core/resources/RecordEncoder.ts +41 -39
  159. package/core/resources/RequestTarget.ts +2 -0
  160. package/core/resources/Resource.ts +96 -56
  161. package/core/resources/ResourceInterface.ts +44 -21
  162. package/core/resources/Resources.ts +8 -8
  163. package/core/resources/RocksIndexStore.ts +3 -0
  164. package/core/resources/RocksTransactionLogStore.ts +13 -4
  165. package/core/resources/Table.ts +440 -223
  166. package/core/resources/analytics/metadata.ts +1 -0
  167. package/core/resources/analytics/read.ts +99 -10
  168. package/core/resources/analytics/write.ts +240 -17
  169. package/core/resources/auditStore.ts +30 -19
  170. package/core/resources/blob.ts +53 -53
  171. package/core/resources/dataLoader.ts +4 -4
  172. package/core/resources/databases.ts +208 -74
  173. package/core/resources/graphql.ts +267 -165
  174. package/core/resources/indexes/HierarchicalNavigableSmallWorld.ts +310 -65
  175. package/core/resources/indexes/vector.ts +17 -0
  176. package/core/resources/jsonSchemaTypes.ts +102 -0
  177. package/core/resources/loadEnv.ts +21 -17
  178. package/core/resources/login.ts +5 -3
  179. package/core/resources/models/Models.ts +304 -0
  180. package/core/resources/models/TestBackend.ts +83 -0
  181. package/core/resources/models/agentLoop.ts +895 -0
  182. package/core/resources/models/analyticsTable.ts +199 -0
  183. package/core/resources/models/backendHelpers.ts +116 -0
  184. package/core/resources/models/backendRegistry.ts +66 -0
  185. package/core/resources/models/bootstrap.ts +135 -0
  186. package/core/resources/models/embedHook.ts +138 -0
  187. package/core/resources/models/types.ts +296 -0
  188. package/core/resources/openApi.ts +65 -31
  189. package/core/resources/replayLogs.ts +20 -9
  190. package/core/resources/replayLogsGuards.ts +45 -0
  191. package/core/resources/roles.ts +62 -67
  192. package/core/resources/search.ts +355 -135
  193. package/core/resources/tracked.ts +18 -9
  194. package/core/resources/transaction.ts +8 -8
  195. package/core/resources/transactionBroadcast.ts +3 -3
  196. package/core/security/auth.ts +35 -26
  197. package/core/security/certificateVerification/crlVerification.ts +11 -4
  198. package/core/security/{cryptoHash.js → cryptoHash.ts} +3 -8
  199. package/core/security/data_objects/{PermissionAttributeResponseObject.js → PermissionAttributeResponseObject.ts} +4 -4
  200. package/core/security/data_objects/{PermissionResponseObject.js → PermissionResponseObject.ts} +12 -11
  201. package/core/security/data_objects/{PermissionTableResponseObject.js → PermissionTableResponseObject.ts} +6 -4
  202. package/core/security/{fastifyAuth.js → fastifyAuth.ts} +93 -20
  203. package/core/security/impersonation.ts +3 -3
  204. package/core/security/jsLoader.ts +22 -8
  205. package/core/security/{keys.js → keys.ts} +113 -121
  206. package/core/security/permissionsTranslator.js +2 -2
  207. package/core/security/{role.js → role.ts} +26 -33
  208. package/core/security/tokenAuthentication.ts +34 -7
  209. package/core/security/user.ts +26 -22
  210. package/core/server/DESIGN.md +139 -0
  211. package/core/server/DurableSubscriptionsSession.ts +67 -50
  212. package/core/server/REST.ts +120 -107
  213. package/core/server/Server.ts +31 -12
  214. package/core/server/fastifyRoutes/helpers/getCORSOptions.js +1 -1
  215. package/core/server/fastifyRoutes/helpers/getHeaderTimeoutConfig.js +1 -1
  216. package/core/server/fastifyRoutes/helpers/getServerOptions.js +1 -1
  217. package/core/server/fastifyRoutes.ts +37 -33
  218. package/core/server/graphqlQuerying.ts +6 -5
  219. package/core/server/http.ts +517 -26
  220. package/core/server/itc/serverHandlers.js +75 -14
  221. package/core/server/jobs/{JobObject.js → JobObject.ts} +13 -6
  222. package/core/server/jobs/{jobProcess.js → jobProcess.ts} +20 -16
  223. package/core/server/jobs/{jobRunner.js → jobRunner.ts} +20 -21
  224. package/core/server/jobs/{jobs.js → jobs.ts} +41 -44
  225. package/core/server/loadRootComponents.js +1 -1
  226. package/core/server/middlewareChain.ts +270 -0
  227. package/core/server/mqtt.ts +35 -26
  228. package/core/server/nodeName.ts +3 -1
  229. package/core/server/operationsServer.ts +85 -10
  230. package/core/server/serverHelpers/Headers.ts +10 -8
  231. package/core/server/serverHelpers/JSONStream.ts +15 -5
  232. package/core/server/serverHelpers/Request.ts +370 -13
  233. package/core/server/serverHelpers/contentTypes.ts +42 -11
  234. package/core/server/serverHelpers/multipartParser.ts +152 -0
  235. package/core/server/serverHelpers/progressEmitter.ts +110 -0
  236. package/core/server/serverHelpers/serverHandlers.js +43 -7
  237. package/core/server/serverHelpers/serverUtilities.ts +40 -30
  238. package/core/server/static.ts +9 -6
  239. package/core/server/status/index.ts +2 -2
  240. package/core/server/storageReclamation.ts +39 -2
  241. package/core/server/threads/itc.js +7 -4
  242. package/core/server/threads/manageThreads.js +100 -26
  243. package/core/server/threads/socketRouter.ts +12 -275
  244. package/core/server/threads/threadServer.js +345 -105
  245. package/core/server/threads/workerProcessGuard.ts +93 -0
  246. package/core/server/throttle.ts +18 -0
  247. package/core/sqlTranslator/{SelectValidator.js → SelectValidator.ts} +41 -49
  248. package/core/sqlTranslator/{alasqlFunctionImporter.js → alasqlFunctionImporter.ts} +5 -5
  249. package/core/sqlTranslator/{deleteTranslator.js → deleteTranslator.ts} +13 -18
  250. package/core/sqlTranslator/{index.js → index.ts} +30 -33
  251. package/core/sqlTranslator/{sql_statement_bucket.js → sql_statement_bucket.ts} +49 -20
  252. package/core/static/README.md +10 -9
  253. package/core/static/defaultConfig.yaml +0 -1
  254. package/core/system/000004.log +0 -0
  255. package/core/system/CURRENT +1 -0
  256. package/core/system/IDENTITY +1 -0
  257. package/core/system/LOCK +0 -0
  258. package/core/system/LOG +1351 -0
  259. package/core/system/MANIFEST-000005 +0 -0
  260. package/core/system/OPTIONS-000013 +607 -0
  261. package/core/system/OPTIONS-000015 +734 -0
  262. package/core/upgrade/{UpgradeObjects.js → UpgradeObjects.ts} +3 -6
  263. package/core/upgrade/directives/5-1-0.ts +89 -0
  264. package/core/upgrade/directives/{directivesController.js → directivesController.ts} +16 -16
  265. package/core/upgrade/{directivesManager.js → directivesManager.ts} +7 -11
  266. package/core/upgrade/{upgradePrompt.js → upgradePrompt.ts} +6 -54
  267. package/core/upgrade/{upgradeUtilities.js → upgradeUtilities.ts} +3 -7
  268. package/core/utility/{OperationFunctionCaller.js → OperationFunctionCaller.ts} +7 -7
  269. package/core/utility/{assignCmdEnvVariables.js → assignCmdEnvVariables.ts} +6 -8
  270. package/core/utility/{common_utils.js → common_utils.ts} +113 -139
  271. package/core/utility/environment/{environmentManager.js → environmentManager.ts} +34 -33
  272. package/core/utility/environment/systemInformation.ts +18 -4
  273. package/core/utility/errors/{commonErrors.js → commonErrors.ts} +9 -9
  274. package/core/utility/errors/{hdbError.js → hdbError.ts} +39 -45
  275. package/core/utility/expandEnvVar.ts +110 -0
  276. package/core/utility/functions/geo.js +2 -2
  277. package/core/utility/functions/sql/alaSQLExtension.js +1 -1
  278. package/core/utility/globalSchema.ts +30 -0
  279. package/core/utility/hdbTerms.ts +54 -1
  280. package/core/utility/install/checkJWTTokensExist.js +1 -1
  281. package/core/utility/install/{installer.js → installer.ts} +86 -62
  282. package/core/utility/installation.ts +2 -2
  283. package/core/utility/lmdb/{DBIDefinition.js → DBIDefinition.ts} +4 -1
  284. package/core/utility/lmdb/{DeleteRecordsResponseObject.js → DeleteRecordsResponseObject.ts} +2 -1
  285. package/core/utility/lmdb/{InsertRecordsResponseObject.js → InsertRecordsResponseObject.ts} +2 -1
  286. package/core/utility/lmdb/OpenDBIObject.ts +57 -0
  287. package/core/utility/lmdb/{OpenEnvironmentObject.js → OpenEnvironmentObject.ts} +19 -6
  288. package/core/utility/lmdb/{UpdateRecordsResponseObject.js → UpdateRecordsResponseObject.ts} +2 -1
  289. package/core/utility/lmdb/{UpsertRecordsResponseObject.js → UpsertRecordsResponseObject.ts} +2 -1
  290. package/core/utility/lmdb/{cleanLMDBMap.js → cleanLMDBMap.ts} +5 -5
  291. package/core/utility/lmdb/{commonUtility.js → commonUtility.ts} +13 -21
  292. package/core/utility/lmdb/{deleteUtility.js → deleteUtility.ts} +8 -12
  293. package/core/utility/lmdb/{environmentUtility.js → environmentUtility.ts} +43 -52
  294. package/core/utility/lmdb/{searchCursorFunctions.js → searchCursorFunctions.ts} +12 -26
  295. package/core/utility/lmdb/{searchUtility.js → searchUtility.ts} +75 -64
  296. package/core/utility/lmdb/{terms.js → terms.ts} +10 -23
  297. package/core/utility/lmdb/{writeUtility.js → writeUtility.ts} +37 -22
  298. package/core/utility/logging/{harper_logger.js → harper_logger.ts} +137 -90
  299. package/core/utility/logging/{logRotator.js → logRotator.ts} +15 -18
  300. package/core/utility/logging/logger.ts +1 -1
  301. package/core/utility/logging/{readLog.js → readLog.ts} +19 -19
  302. package/core/utility/logging/{transactionLog.js → transactionLog.ts} +10 -14
  303. package/core/utility/{mount_hdb.js → mount_hdb.ts} +15 -16
  304. package/core/utility/{npmUtilities.js → npmUtilities.ts} +14 -17
  305. package/core/utility/{operation_authorization.js → operation_authorization.ts} +173 -124
  306. package/core/utility/packageUtils.js +7 -16
  307. package/core/utility/password.ts +1 -1
  308. package/core/utility/processManagement/processManagement.js +2 -2
  309. package/core/utility/processManagement/servicesConfig.js +1 -1
  310. package/core/utility/{signalling.js → signalling.ts} +6 -11
  311. package/core/utility/watcherFallback.ts +74 -0
  312. package/core/validation/analyticsValidator.ts +44 -0
  313. package/core/validation/{bulkDeleteValidator.js → bulkDeleteValidator.ts} +5 -5
  314. package/core/validation/{check_permissions.js → check_permissions.ts} +3 -3
  315. package/core/validation/{common_validators.js → common_validators.ts} +12 -24
  316. package/core/validation/{configValidator.js → configValidator.ts} +114 -18
  317. package/core/validation/{deleteValidator.js → deleteValidator.ts} +5 -5
  318. package/core/validation/{fileLoadValidator.js → fileLoadValidator.ts} +12 -19
  319. package/core/validation/{insertValidator.js → insertValidator.ts} +5 -5
  320. package/core/validation/{installValidator.js → installValidator.ts} +8 -8
  321. package/core/validation/{readLogValidator.js → readLogValidator.ts} +10 -10
  322. package/core/validation/{role_validation.js → role_validation.ts} +26 -32
  323. package/core/validation/{schemaMetadataValidator.js → schemaMetadataValidator.ts} +5 -11
  324. package/core/validation/{searchValidator.js → searchValidator.ts} +12 -11
  325. package/core/validation/statusValidator.ts +1 -1
  326. package/core/validation/{transactionLogValidator.js → transactionLogValidator.ts} +4 -9
  327. package/core/validation/{user_validation.js → user_validation.ts} +4 -10
  328. package/core/validation/{validationWrapper.js → validationWrapper.ts} +3 -9
  329. package/dist/analytics/profile.js +4 -0
  330. package/dist/analytics/profile.js.map +1 -1
  331. package/dist/cloneNode/cloneNode.js +224 -12
  332. package/dist/cloneNode/cloneNode.js.map +1 -1
  333. package/dist/core/agent/agent.js +175 -0
  334. package/dist/core/agent/agent.js.map +1 -0
  335. package/dist/core/agent/loop.js +176 -0
  336. package/dist/core/agent/loop.js.map +1 -0
  337. package/dist/core/agent/operations.js +137 -0
  338. package/dist/core/agent/operations.js.map +1 -0
  339. package/dist/core/agent/session.js +182 -0
  340. package/dist/core/agent/session.js.map +1 -0
  341. package/dist/core/agent/tools/fsTools.js +286 -0
  342. package/dist/core/agent/tools/fsTools.js.map +1 -0
  343. package/dist/core/agent/tools/httpFetchTool.js +116 -0
  344. package/dist/core/agent/tools/httpFetchTool.js.map +1 -0
  345. package/dist/core/agent/tools/scheduleTool.js +54 -0
  346. package/dist/core/agent/tools/scheduleTool.js.map +1 -0
  347. package/dist/core/agent/toolset.js +33 -0
  348. package/dist/core/agent/toolset.js.map +1 -0
  349. package/dist/core/agent/types.js +10 -0
  350. package/dist/core/agent/types.js.map +1 -0
  351. package/dist/core/bin/BinObjects.js +6 -3
  352. package/dist/core/bin/BinObjects.js.map +1 -1
  353. package/dist/core/bin/cliCredentials.js +130 -0
  354. package/dist/core/bin/cliCredentials.js.map +1 -0
  355. package/dist/core/bin/cliOperations.js +254 -40
  356. package/dist/core/bin/cliOperations.js.map +1 -1
  357. package/dist/core/bin/copyDb.js +16 -16
  358. package/dist/core/bin/copyDb.js.map +1 -1
  359. package/dist/core/bin/deployRenderer.js +185 -0
  360. package/dist/core/bin/deployRenderer.js.map +1 -0
  361. package/dist/core/bin/harper.js +92 -31
  362. package/dist/core/bin/harper.js.map +1 -1
  363. package/dist/core/bin/install.js +41 -4
  364. package/dist/core/bin/install.js.map +1 -1
  365. package/dist/core/bin/lite.js +3 -4
  366. package/dist/core/bin/lite.js.map +1 -1
  367. package/dist/core/bin/login.js +123 -0
  368. package/dist/core/bin/login.js.map +1 -0
  369. package/dist/core/bin/logout.js +16 -0
  370. package/dist/core/bin/logout.js.map +1 -0
  371. package/dist/core/bin/mcp/client.js +395 -0
  372. package/dist/core/bin/mcp/client.js.map +1 -0
  373. package/dist/core/bin/mcp/doctor.js +193 -0
  374. package/dist/core/bin/mcp/doctor.js.map +1 -0
  375. package/dist/core/bin/mcp/index.js +81 -0
  376. package/dist/core/bin/mcp/index.js.map +1 -0
  377. package/dist/core/bin/mcp/options.js +113 -0
  378. package/dist/core/bin/mcp/options.js.map +1 -0
  379. package/dist/core/bin/mcp/printConfig.js +85 -0
  380. package/dist/core/bin/mcp/printConfig.js.map +1 -0
  381. package/dist/core/bin/multipartBuilder.js +55 -0
  382. package/dist/core/bin/multipartBuilder.js.map +1 -0
  383. package/dist/core/bin/restart.js +85 -48
  384. package/dist/core/bin/restart.js.map +1 -1
  385. package/dist/core/bin/run.js +123 -77
  386. package/dist/core/bin/run.js.map +1 -1
  387. package/dist/core/bin/sseConsumer.js +127 -0
  388. package/dist/core/bin/sseConsumer.js.map +1 -0
  389. package/dist/core/bin/status.js +48 -11
  390. package/dist/core/bin/status.js.map +1 -1
  391. package/dist/core/bin/stop.js +44 -7
  392. package/dist/core/bin/stop.js.map +1 -1
  393. package/dist/core/bin/upgrade.js +14 -22
  394. package/dist/core/bin/upgrade.js.map +1 -1
  395. package/dist/core/components/Application.js +134 -28
  396. package/dist/core/components/Application.js.map +1 -1
  397. package/dist/core/components/ApplicationScope.js +2 -2
  398. package/dist/core/components/ComponentV1.js +5 -5
  399. package/dist/core/components/ComponentV1.js.map +1 -1
  400. package/dist/core/components/EntryHandler.js +153 -13
  401. package/dist/core/components/EntryHandler.js.map +1 -1
  402. package/dist/core/components/OptionsWatcher.js +72 -10
  403. package/dist/core/components/OptionsWatcher.js.map +1 -1
  404. package/dist/core/components/Scope.js +112 -12
  405. package/dist/core/components/Scope.js.map +1 -1
  406. package/dist/core/components/anthropic/index.js +428 -0
  407. package/dist/core/components/anthropic/index.js.map +1 -0
  408. package/dist/core/components/bedrock/index.js +734 -0
  409. package/dist/core/components/bedrock/index.js.map +1 -0
  410. package/dist/core/components/componentLoader.js +65 -38
  411. package/dist/core/components/componentLoader.js.map +1 -1
  412. package/dist/core/components/deployLifecycle.js +156 -0
  413. package/dist/core/components/deployLifecycle.js.map +1 -0
  414. package/dist/core/components/deploymentOperations.js +185 -0
  415. package/dist/core/components/deploymentOperations.js.map +1 -0
  416. package/dist/core/components/deploymentRecorder.js +425 -0
  417. package/dist/core/components/deploymentRecorder.js.map +1 -0
  418. package/dist/core/components/deriveURLPath.js +2 -2
  419. package/dist/core/components/deriveURLPath.js.map +1 -1
  420. package/dist/core/components/mcp/adapters/fastify.js +66 -0
  421. package/dist/core/components/mcp/adapters/fastify.js.map +1 -0
  422. package/dist/core/components/mcp/adapters/harperHttp.js +78 -0
  423. package/dist/core/components/mcp/adapters/harperHttp.js.map +1 -0
  424. package/dist/core/components/mcp/audit.js +73 -0
  425. package/dist/core/components/mcp/audit.js.map +1 -0
  426. package/dist/core/components/mcp/index.js +109 -0
  427. package/dist/core/components/mcp/index.js.map +1 -0
  428. package/dist/core/components/mcp/jsonrpc.js +93 -0
  429. package/dist/core/components/mcp/jsonrpc.js.map +1 -0
  430. package/dist/core/components/mcp/lifecycle.js +79 -0
  431. package/dist/core/components/mcp/lifecycle.js.map +1 -0
  432. package/dist/core/components/mcp/listChanged.js +257 -0
  433. package/dist/core/components/mcp/listChanged.js.map +1 -0
  434. package/dist/core/components/mcp/rateLimit.js +226 -0
  435. package/dist/core/components/mcp/rateLimit.js.map +1 -0
  436. package/dist/core/components/mcp/resources.js +526 -0
  437. package/dist/core/components/mcp/resources.js.map +1 -0
  438. package/dist/core/components/mcp/session.js +170 -0
  439. package/dist/core/components/mcp/session.js.map +1 -0
  440. package/dist/core/components/mcp/sessionRegistry.js +124 -0
  441. package/dist/core/components/mcp/sessionRegistry.js.map +1 -0
  442. package/dist/core/components/mcp/toolRegistry.js +177 -0
  443. package/dist/core/components/mcp/toolRegistry.js.map +1 -0
  444. package/dist/core/components/mcp/tools/application.js +660 -0
  445. package/dist/core/components/mcp/tools/application.js.map +1 -0
  446. package/dist/core/components/mcp/tools/operations.js +331 -0
  447. package/dist/core/components/mcp/tools/operations.js.map +1 -0
  448. package/dist/core/components/mcp/tools/schemas/derive.js +291 -0
  449. package/dist/core/components/mcp/tools/schemas/derive.js.map +1 -0
  450. package/dist/core/components/mcp/tools/schemas/operationDescriptions.js +179 -0
  451. package/dist/core/components/mcp/tools/schemas/operationDescriptions.js.map +1 -0
  452. package/dist/core/components/mcp/tools/schemas/operations.js +299 -0
  453. package/dist/core/components/mcp/tools/schemas/operations.js.map +1 -0
  454. package/dist/core/components/mcp/transport.js +467 -0
  455. package/dist/core/components/mcp/transport.js.map +1 -0
  456. package/dist/core/components/ollama/index.js +239 -0
  457. package/dist/core/components/ollama/index.js.map +1 -0
  458. package/dist/core/components/openai/index.js +475 -0
  459. package/dist/core/components/openai/index.js.map +1 -0
  460. package/dist/core/components/operations.js +205 -52
  461. package/dist/core/components/operations.js.map +1 -1
  462. package/dist/core/components/operationsValidation.js +13 -4
  463. package/dist/core/components/operationsValidation.js.map +1 -1
  464. package/dist/core/components/packageComponent.js +87 -26
  465. package/dist/core/components/packageComponent.js.map +1 -1
  466. package/dist/core/components/requestRestart.js +12 -1
  467. package/dist/core/components/requestRestart.js.map +1 -1
  468. package/dist/core/components/status/crossThread.js +12 -5
  469. package/dist/core/components/status/crossThread.js.map +1 -1
  470. package/dist/core/components/status/errors.js +7 -7
  471. package/dist/core/config/RootConfigWatcher.js +52 -1
  472. package/dist/core/config/RootConfigWatcher.js.map +1 -1
  473. package/dist/core/config/configUtils.js +31 -8
  474. package/dist/core/config/configUtils.js.map +1 -1
  475. package/dist/core/config/harperConfigEnvVars.js +1 -1
  476. package/dist/core/config/harperConfigEnvVars.js.map +1 -1
  477. package/dist/core/dataLayer/CreateAttributeObject.js +4 -3
  478. package/dist/core/dataLayer/CreateAttributeObject.js.map +1 -1
  479. package/dist/core/dataLayer/CreateTableObject.js +2 -1
  480. package/dist/core/dataLayer/CreateTableObject.js.map +1 -1
  481. package/dist/core/dataLayer/DataLayerObjects.js +19 -5
  482. package/dist/core/dataLayer/DataLayerObjects.js.map +1 -1
  483. package/dist/core/dataLayer/DeleteBeforeObject.js +2 -1
  484. package/dist/core/dataLayer/DeleteBeforeObject.js.map +1 -1
  485. package/dist/core/dataLayer/DeleteObject.js +4 -3
  486. package/dist/core/dataLayer/DeleteObject.js.map +1 -1
  487. package/dist/core/dataLayer/DropAttributeObject.js +2 -1
  488. package/dist/core/dataLayer/DropAttributeObject.js.map +1 -1
  489. package/dist/core/dataLayer/GetBackupObject.js +4 -3
  490. package/dist/core/dataLayer/GetBackupObject.js.map +1 -1
  491. package/dist/core/dataLayer/InsertObject.js +4 -3
  492. package/dist/core/dataLayer/InsertObject.js.map +1 -1
  493. package/dist/core/dataLayer/ReadAuditLogObject.js +4 -3
  494. package/dist/core/dataLayer/ReadAuditLogObject.js.map +1 -1
  495. package/dist/core/dataLayer/SQLSearch.js +140 -78
  496. package/dist/core/dataLayer/SQLSearch.js.map +1 -1
  497. package/dist/core/dataLayer/SearchByConditionsObject.js +5 -7
  498. package/dist/core/dataLayer/SearchByConditionsObject.js.map +1 -1
  499. package/dist/core/dataLayer/SearchByHashObject.js +2 -1
  500. package/dist/core/dataLayer/SearchByHashObject.js.map +1 -1
  501. package/dist/core/dataLayer/SearchObject.js +2 -1
  502. package/dist/core/dataLayer/SearchObject.js.map +1 -1
  503. package/dist/core/dataLayer/SqlSearchObject.js +2 -1
  504. package/dist/core/dataLayer/SqlSearchObject.js.map +1 -1
  505. package/dist/core/dataLayer/UpdateObject.js +4 -3
  506. package/dist/core/dataLayer/UpdateObject.js.map +1 -1
  507. package/dist/core/dataLayer/UpsertObject.js +4 -3
  508. package/dist/core/dataLayer/UpsertObject.js.map +1 -1
  509. package/dist/core/dataLayer/bulkLoad.js +122 -88
  510. package/dist/core/dataLayer/bulkLoad.js.map +1 -1
  511. package/dist/core/dataLayer/delete.js +74 -39
  512. package/dist/core/dataLayer/delete.js.map +1 -1
  513. package/dist/core/dataLayer/export.js +90 -55
  514. package/dist/core/dataLayer/export.js.map +1 -1
  515. package/dist/core/dataLayer/getBackup.js +43 -11
  516. package/dist/core/dataLayer/getBackup.js.map +1 -1
  517. package/dist/core/dataLayer/harperBridge/BridgeMethods.js +41 -20
  518. package/dist/core/dataLayer/harperBridge/BridgeMethods.js.map +1 -1
  519. package/dist/core/dataLayer/harperBridge/ResourceBridge.js +26 -25
  520. package/dist/core/dataLayer/harperBridge/ResourceBridge.js.map +1 -1
  521. package/dist/core/dataLayer/harperBridge/TableSizeObject.js.map +1 -1
  522. package/dist/core/dataLayer/harperBridge/bridgeUtility/insertUpdateValidate.js +4 -4
  523. package/dist/core/dataLayer/harperBridge/harperBridge.js +38 -4
  524. package/dist/core/dataLayer/harperBridge/harperBridge.js.map +1 -1
  525. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateAttribute.js +7 -6
  526. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateAttribute.js.map +1 -1
  527. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateRecords.js +4 -4
  528. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateRecords.js.map +1 -1
  529. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateSchema.js +1 -1
  530. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateSchema.js.map +1 -1
  531. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateTable.js +5 -4
  532. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateTable.js.map +1 -1
  533. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDeleteAuditLogsBefore.js +4 -4
  534. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDeleteAuditLogsBefore.js.map +1 -1
  535. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDeleteRecords.js +4 -4
  536. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDropAttribute.js +5 -5
  537. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDropAttribute.js.map +1 -1
  538. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDropSchema.js +4 -4
  539. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDropSchema.js.map +1 -1
  540. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDropTable.js +5 -5
  541. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDropTable.js.map +1 -1
  542. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbFlush.js +1 -1
  543. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbGetBackup.js +3 -3
  544. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbGetDataByHash.js +1 -1
  545. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbGetDataByValue.js +2 -2
  546. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbGetDataByValue.js.map +1 -1
  547. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbReadAuditLog.js +5 -5
  548. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbSearchByConditions.js +8 -8
  549. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbSearchByConditions.js.map +1 -1
  550. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbSearchByHash.js +1 -1
  551. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbSearchByValue.js +3 -3
  552. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbSearchByValue.js.map +1 -1
  553. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbUpdateRecords.js +3 -3
  554. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbUpsertRecords.js +5 -5
  555. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbUpsertRecords.js.map +1 -1
  556. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBCreateAttributeObject.js +1 -1
  557. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBCreateAttributeObject.js.map +1 -1
  558. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/initializeHashSearch.js +2 -2
  559. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/initializeHashSearch.js.map +1 -1
  560. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/initializePaths.js +2 -2
  561. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbCheckForNewAttributes.js +4 -4
  562. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbCheckForNewAttributes.js.map +1 -1
  563. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbCreateTransactionsAuditEnvironment.js +5 -3
  564. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbCreateTransactionsAuditEnvironment.js.map +1 -1
  565. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbGetTableSize.js +2 -2
  566. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbProcessRows.js +4 -4
  567. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbProcessRows.js.map +1 -1
  568. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbSearch.js +5 -5
  569. package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbWriteTransaction.js +4 -4
  570. package/dist/core/dataLayer/hdbInfoController.js +66 -31
  571. package/dist/core/dataLayer/hdbInfoController.js.map +1 -1
  572. package/dist/core/dataLayer/insert.js +63 -28
  573. package/dist/core/dataLayer/insert.js.map +1 -1
  574. package/dist/core/dataLayer/readAuditLog.js +45 -13
  575. package/dist/core/dataLayer/readAuditLog.js.map +1 -1
  576. package/dist/core/dataLayer/schema.js +124 -89
  577. package/dist/core/dataLayer/schema.js.map +1 -1
  578. package/dist/core/dataLayer/schemaDescribe.js +78 -41
  579. package/dist/core/dataLayer/schemaDescribe.js.map +1 -1
  580. package/dist/core/dataLayer/search.js +12 -13
  581. package/dist/core/dataLayer/search.js.map +1 -1
  582. package/dist/core/dataLayer/transaction.js +3 -4
  583. package/dist/core/dataLayer/transaction.js.map +1 -1
  584. package/dist/core/dataLayer/update.js +53 -18
  585. package/dist/core/dataLayer/update.js.map +1 -1
  586. package/dist/core/globals.js +1 -0
  587. package/dist/core/globals.js.map +1 -1
  588. package/dist/core/index.js +4 -1
  589. package/dist/core/index.js.map +1 -1
  590. package/dist/core/json/systemSchema.json +65 -0
  591. package/dist/core/launchServiceScripts/utility/checkNodeVersion.js +3 -0
  592. package/dist/core/launchServiceScripts/utility/checkNodeVersion.js.map +1 -1
  593. package/dist/core/resources/DatabaseTransaction.js +39 -15
  594. package/dist/core/resources/DatabaseTransaction.js.map +1 -1
  595. package/dist/core/resources/ErrorResource.js +3 -1
  596. package/dist/core/resources/ErrorResource.js.map +1 -1
  597. package/dist/core/resources/LMDBTransaction.js +18 -7
  598. package/dist/core/resources/LMDBTransaction.js.map +1 -1
  599. package/dist/core/resources/RecordEncoder.js +38 -38
  600. package/dist/core/resources/RecordEncoder.js.map +1 -1
  601. package/dist/core/resources/RequestTarget.js.map +1 -1
  602. package/dist/core/resources/Resource.js +43 -10
  603. package/dist/core/resources/Resource.js.map +1 -1
  604. package/dist/core/resources/ResourceInterface.js +20 -0
  605. package/dist/core/resources/ResourceInterface.js.map +1 -1
  606. package/dist/core/resources/Resources.js +7 -6
  607. package/dist/core/resources/Resources.js.map +1 -1
  608. package/dist/core/resources/RocksIndexStore.js +3 -0
  609. package/dist/core/resources/RocksIndexStore.js.map +1 -1
  610. package/dist/core/resources/RocksTransactionLogStore.js +10 -3
  611. package/dist/core/resources/RocksTransactionLogStore.js.map +1 -1
  612. package/dist/core/resources/Table.js +306 -116
  613. package/dist/core/resources/Table.js.map +1 -1
  614. package/dist/core/resources/analytics/metadata.js +1 -0
  615. package/dist/core/resources/analytics/metadata.js.map +1 -1
  616. package/dist/core/resources/analytics/read.js +69 -8
  617. package/dist/core/resources/analytics/read.js.map +1 -1
  618. package/dist/core/resources/analytics/write.js +232 -20
  619. package/dist/core/resources/analytics/write.js.map +1 -1
  620. package/dist/core/resources/auditStore.js +16 -8
  621. package/dist/core/resources/auditStore.js.map +1 -1
  622. package/dist/core/resources/blob.js +8 -8
  623. package/dist/core/resources/blob.js.map +1 -1
  624. package/dist/core/resources/dataLoader.js +13 -13
  625. package/dist/core/resources/databases.js +175 -59
  626. package/dist/core/resources/databases.js.map +1 -1
  627. package/dist/core/resources/graphql.js +267 -173
  628. package/dist/core/resources/graphql.js.map +1 -1
  629. package/dist/core/resources/indexes/HierarchicalNavigableSmallWorld.js +327 -59
  630. package/dist/core/resources/indexes/HierarchicalNavigableSmallWorld.js.map +1 -1
  631. package/dist/core/resources/indexes/vector.js +14 -0
  632. package/dist/core/resources/indexes/vector.js.map +1 -1
  633. package/dist/core/resources/jsonSchemaTypes.js +78 -0
  634. package/dist/core/resources/jsonSchemaTypes.js.map +1 -0
  635. package/dist/core/resources/loadEnv.js +21 -18
  636. package/dist/core/resources/loadEnv.js.map +1 -1
  637. package/dist/core/resources/login.js +5 -4
  638. package/dist/core/resources/login.js.map +1 -1
  639. package/dist/core/resources/models/Models.js +265 -0
  640. package/dist/core/resources/models/Models.js.map +1 -0
  641. package/dist/core/resources/models/TestBackend.js +71 -0
  642. package/dist/core/resources/models/TestBackend.js.map +1 -0
  643. package/dist/core/resources/models/agentLoop.js +746 -0
  644. package/dist/core/resources/models/agentLoop.js.map +1 -0
  645. package/dist/core/resources/models/analyticsTable.js +166 -0
  646. package/dist/core/resources/models/analyticsTable.js.map +1 -0
  647. package/dist/core/resources/models/backendHelpers.js +109 -0
  648. package/dist/core/resources/models/backendHelpers.js.map +1 -0
  649. package/dist/core/resources/models/backendRegistry.js +54 -0
  650. package/dist/core/resources/models/backendRegistry.js.map +1 -0
  651. package/dist/core/resources/models/bootstrap.js +112 -0
  652. package/dist/core/resources/models/bootstrap.js.map +1 -0
  653. package/dist/core/resources/models/embedHook.js +127 -0
  654. package/dist/core/resources/models/embedHook.js.map +1 -0
  655. package/dist/core/resources/models/types.js +11 -0
  656. package/dist/core/resources/models/types.js.map +1 -0
  657. package/dist/core/resources/openApi.js +74 -34
  658. package/dist/core/resources/openApi.js.map +1 -1
  659. package/dist/core/resources/replayLogs.js +7 -1
  660. package/dist/core/resources/replayLogs.js.map +1 -1
  661. package/dist/core/resources/replayLogsGuards.js +47 -0
  662. package/dist/core/resources/replayLogsGuards.js.map +1 -1
  663. package/dist/core/resources/roles.js +67 -71
  664. package/dist/core/resources/roles.js.map +1 -1
  665. package/dist/core/resources/search.js +349 -140
  666. package/dist/core/resources/search.js.map +1 -1
  667. package/dist/core/resources/tracked.js +23 -15
  668. package/dist/core/resources/tracked.js.map +1 -1
  669. package/dist/core/resources/transaction.js +1 -1
  670. package/dist/core/resources/transaction.js.map +1 -1
  671. package/dist/core/resources/transactionBroadcast.js.map +1 -1
  672. package/dist/core/security/auth.js +34 -25
  673. package/dist/core/security/auth.js.map +1 -1
  674. package/dist/core/security/certificateVerification/crlVerification.js +7 -1
  675. package/dist/core/security/certificateVerification/crlVerification.js.map +1 -1
  676. package/dist/core/security/cryptoHash.js +37 -5
  677. package/dist/core/security/cryptoHash.js.map +1 -1
  678. package/dist/core/security/data_objects/PermissionAttributeResponseObject.js +4 -1
  679. package/dist/core/security/data_objects/PermissionAttributeResponseObject.js.map +1 -1
  680. package/dist/core/security/data_objects/PermissionResponseObject.js +15 -8
  681. package/dist/core/security/data_objects/PermissionResponseObject.js.map +1 -1
  682. package/dist/core/security/data_objects/PermissionTableResponseObject.js +6 -1
  683. package/dist/core/security/data_objects/PermissionTableResponseObject.js.map +1 -1
  684. package/dist/core/security/fastifyAuth.js +131 -22
  685. package/dist/core/security/fastifyAuth.js.map +1 -1
  686. package/dist/core/security/impersonation.js +15 -15
  687. package/dist/core/security/jsLoader.js +18 -5
  688. package/dist/core/security/jsLoader.js.map +1 -1
  689. package/dist/core/security/keys.js +160 -114
  690. package/dist/core/security/keys.js.map +1 -1
  691. package/dist/core/security/permissionsTranslator.js +2 -2
  692. package/dist/core/security/role.js +70 -35
  693. package/dist/core/security/role.js.map +1 -1
  694. package/dist/core/security/tokenAuthentication.js +57 -27
  695. package/dist/core/security/tokenAuthentication.js.map +1 -1
  696. package/dist/core/security/user.js +74 -38
  697. package/dist/core/security/user.js.map +1 -1
  698. package/dist/core/server/DurableSubscriptionsSession.js +71 -55
  699. package/dist/core/server/DurableSubscriptionsSession.js.map +1 -1
  700. package/dist/core/server/REST.js +17 -16
  701. package/dist/core/server/REST.js.map +1 -1
  702. package/dist/core/server/Server.js +1 -1
  703. package/dist/core/server/Server.js.map +1 -1
  704. package/dist/core/server/fastifyRoutes/helpers/getCORSOptions.js +1 -1
  705. package/dist/core/server/fastifyRoutes/helpers/getHeaderTimeoutConfig.js +1 -1
  706. package/dist/core/server/fastifyRoutes/helpers/getServerOptions.js +1 -1
  707. package/dist/core/server/fastifyRoutes.js +34 -30
  708. package/dist/core/server/fastifyRoutes.js.map +1 -1
  709. package/dist/core/server/graphqlQuerying.js +8 -7
  710. package/dist/core/server/graphqlQuerying.js.map +1 -1
  711. package/dist/core/server/http.js +523 -47
  712. package/dist/core/server/http.js.map +1 -1
  713. package/dist/core/server/itc/serverHandlers.js +66 -15
  714. package/dist/core/server/itc/serverHandlers.js.map +1 -1
  715. package/dist/core/server/jobs/JobObject.js +53 -7
  716. package/dist/core/server/jobs/JobObject.js.map +1 -1
  717. package/dist/core/server/jobs/jobProcess.js +64 -24
  718. package/dist/core/server/jobs/jobProcess.js.map +1 -1
  719. package/dist/core/server/jobs/jobRunner.js +68 -30
  720. package/dist/core/server/jobs/jobRunner.js.map +1 -1
  721. package/dist/core/server/jobs/jobs.js +93 -61
  722. package/dist/core/server/jobs/jobs.js.map +1 -1
  723. package/dist/core/server/loadRootComponents.js +1 -1
  724. package/dist/core/server/middlewareChain.js +252 -0
  725. package/dist/core/server/middlewareChain.js.map +1 -0
  726. package/dist/core/server/mqtt.js +22 -17
  727. package/dist/core/server/mqtt.js.map +1 -1
  728. package/dist/core/server/nodeName.js +46 -13
  729. package/dist/core/server/nodeName.js.map +1 -1
  730. package/dist/core/server/operationsServer.js +106 -33
  731. package/dist/core/server/operationsServer.js.map +1 -1
  732. package/dist/core/server/serverHelpers/Headers.js +2 -0
  733. package/dist/core/server/serverHelpers/Headers.js.map +1 -1
  734. package/dist/core/server/serverHelpers/JSONStream.js +12 -3
  735. package/dist/core/server/serverHelpers/JSONStream.js.map +1 -1
  736. package/dist/core/server/serverHelpers/Request.js +370 -9
  737. package/dist/core/server/serverHelpers/Request.js.map +1 -1
  738. package/dist/core/server/serverHelpers/contentTypes.js +36 -7
  739. package/dist/core/server/serverHelpers/contentTypes.js.map +1 -1
  740. package/dist/core/server/serverHelpers/multipartParser.js +142 -0
  741. package/dist/core/server/serverHelpers/multipartParser.js.map +1 -0
  742. package/dist/core/server/serverHelpers/progressEmitter.js +103 -0
  743. package/dist/core/server/serverHelpers/progressEmitter.js.map +1 -0
  744. package/dist/core/server/serverHelpers/serverHandlers.js +38 -7
  745. package/dist/core/server/serverHelpers/serverHandlers.js.map +1 -1
  746. package/dist/core/server/serverHelpers/serverUtilities.js +97 -93
  747. package/dist/core/server/serverHelpers/serverUtilities.js.map +1 -1
  748. package/dist/core/server/static.js +8 -5
  749. package/dist/core/server/static.js.map +1 -1
  750. package/dist/core/server/status/index.js +3 -3
  751. package/dist/core/server/storageReclamation.js +68 -9
  752. package/dist/core/server/storageReclamation.js.map +1 -1
  753. package/dist/core/server/threads/itc.js +7 -4
  754. package/dist/core/server/threads/itc.js.map +1 -1
  755. package/dist/core/server/threads/manageThreads.js +110 -26
  756. package/dist/core/server/threads/manageThreads.js.map +1 -1
  757. package/dist/core/server/threads/socketRouter.js +8 -271
  758. package/dist/core/server/threads/socketRouter.js.map +1 -1
  759. package/dist/core/server/threads/threadServer.js +360 -118
  760. package/dist/core/server/threads/threadServer.js.map +1 -1
  761. package/dist/core/server/threads/workerProcessGuard.js +114 -0
  762. package/dist/core/server/threads/workerProcessGuard.js.map +1 -0
  763. package/dist/core/server/throttle.js +17 -0
  764. package/dist/core/server/throttle.js.map +1 -1
  765. package/dist/core/sqlTranslator/SelectValidator.js +86 -47
  766. package/dist/core/sqlTranslator/SelectValidator.js.map +1 -1
  767. package/dist/core/sqlTranslator/alasqlFunctionImporter.js +40 -3
  768. package/dist/core/sqlTranslator/alasqlFunctionImporter.js.map +1 -1
  769. package/dist/core/sqlTranslator/deleteTranslator.js +48 -14
  770. package/dist/core/sqlTranslator/deleteTranslator.js.map +1 -1
  771. package/dist/core/sqlTranslator/index.js +69 -30
  772. package/dist/core/sqlTranslator/index.js.map +1 -1
  773. package/dist/core/sqlTranslator/sql_statement_bucket.js +55 -13
  774. package/dist/core/sqlTranslator/sql_statement_bucket.js.map +1 -1
  775. package/dist/core/upgrade/UpgradeObjects.js +37 -4
  776. package/dist/core/upgrade/UpgradeObjects.js.map +1 -1
  777. package/dist/core/upgrade/directives/5-1-0.js +114 -0
  778. package/dist/core/upgrade/directives/5-1-0.js.map +1 -0
  779. package/dist/core/upgrade/directives/directivesController.js +52 -11
  780. package/dist/core/upgrade/directives/directivesController.js.map +1 -1
  781. package/dist/core/upgrade/directivesManager.js +53 -18
  782. package/dist/core/upgrade/directivesManager.js.map +1 -1
  783. package/dist/core/upgrade/upgradePrompt.js +55 -60
  784. package/dist/core/upgrade/upgradePrompt.js.map +1 -1
  785. package/dist/core/upgrade/upgradeUtilities.js +37 -5
  786. package/dist/core/upgrade/upgradeUtilities.js.map +1 -1
  787. package/dist/core/utility/OperationFunctionCaller.js +45 -10
  788. package/dist/core/utility/OperationFunctionCaller.js.map +1 -1
  789. package/dist/core/utility/assignCmdEnvVariables.js +8 -4
  790. package/dist/core/utility/assignCmdEnvVariables.js.map +1 -1
  791. package/dist/core/utility/common_utils.js +140 -79
  792. package/dist/core/utility/common_utils.js.map +1 -1
  793. package/dist/core/utility/environment/environmentManager.js +75 -29
  794. package/dist/core/utility/environment/environmentManager.js.map +1 -1
  795. package/dist/core/utility/environment/systemInformation.js +27 -16
  796. package/dist/core/utility/environment/systemInformation.js.map +1 -1
  797. package/dist/core/utility/errors/commonErrors.js +49 -18
  798. package/dist/core/utility/errors/commonErrors.js.map +1 -1
  799. package/dist/core/utility/errors/hdbError.js +65 -26
  800. package/dist/core/utility/errors/hdbError.js.map +1 -1
  801. package/dist/core/utility/expandEnvVar.js +113 -0
  802. package/dist/core/utility/expandEnvVar.js.map +1 -0
  803. package/dist/core/utility/functions/geo.js +2 -2
  804. package/dist/core/utility/functions/sql/alaSQLExtension.js +1 -1
  805. package/dist/core/utility/globalSchema.js +14 -11
  806. package/dist/core/utility/globalSchema.js.map +1 -1
  807. package/dist/core/utility/hdbTerms.js +54 -1
  808. package/dist/core/utility/hdbTerms.js.map +1 -1
  809. package/dist/core/utility/install/checkJWTTokensExist.js +1 -1
  810. package/dist/core/utility/install/installer.js +136 -73
  811. package/dist/core/utility/install/installer.js.map +1 -1
  812. package/dist/core/utility/installation.js +3 -3
  813. package/dist/core/utility/lmdb/DBIDefinition.js +5 -1
  814. package/dist/core/utility/lmdb/DBIDefinition.js.map +1 -1
  815. package/dist/core/utility/lmdb/DeleteRecordsResponseObject.js +2 -1
  816. package/dist/core/utility/lmdb/DeleteRecordsResponseObject.js.map +1 -1
  817. package/dist/core/utility/lmdb/InsertRecordsResponseObject.js +2 -1
  818. package/dist/core/utility/lmdb/InsertRecordsResponseObject.js.map +1 -1
  819. package/dist/core/utility/lmdb/OpenDBIObject.js +68 -6
  820. package/dist/core/utility/lmdb/OpenDBIObject.js.map +1 -1
  821. package/dist/core/utility/lmdb/OpenEnvironmentObject.js +52 -4
  822. package/dist/core/utility/lmdb/OpenEnvironmentObject.js.map +1 -1
  823. package/dist/core/utility/lmdb/UpdateRecordsResponseObject.js +2 -1
  824. package/dist/core/utility/lmdb/UpdateRecordsResponseObject.js.map +1 -1
  825. package/dist/core/utility/lmdb/UpsertRecordsResponseObject.js +2 -1
  826. package/dist/core/utility/lmdb/UpsertRecordsResponseObject.js.map +1 -1
  827. package/dist/core/utility/lmdb/cleanLMDBMap.js +44 -7
  828. package/dist/core/utility/lmdb/cleanLMDBMap.js.map +1 -1
  829. package/dist/core/utility/lmdb/commonUtility.js +46 -17
  830. package/dist/core/utility/lmdb/commonUtility.js.map +1 -1
  831. package/dist/core/utility/lmdb/deleteUtility.js +51 -16
  832. package/dist/core/utility/lmdb/deleteUtility.js.map +1 -1
  833. package/dist/core/utility/lmdb/environmentUtility.js +91 -51
  834. package/dist/core/utility/lmdb/environmentUtility.js.map +1 -1
  835. package/dist/core/utility/lmdb/searchCursorFunctions.js +46 -14
  836. package/dist/core/utility/lmdb/searchCursorFunctions.js.map +1 -1
  837. package/dist/core/utility/lmdb/searchUtility.js +91 -55
  838. package/dist/core/utility/lmdb/searchUtility.js.map +1 -1
  839. package/dist/core/utility/lmdb/terms.js +12 -22
  840. package/dist/core/utility/lmdb/terms.js.map +1 -1
  841. package/dist/core/utility/lmdb/writeUtility.js +61 -28
  842. package/dist/core/utility/lmdb/writeUtility.js.map +1 -1
  843. package/dist/core/utility/logging/harper_logger.js +177 -82
  844. package/dist/core/utility/logging/harper_logger.js.map +1 -1
  845. package/dist/core/utility/logging/logRotator.js +67 -32
  846. package/dist/core/utility/logging/logRotator.js.map +1 -1
  847. package/dist/core/utility/logging/logger.js +4 -4
  848. package/dist/core/utility/logging/readLog.js +54 -17
  849. package/dist/core/utility/logging/readLog.js.map +1 -1
  850. package/dist/core/utility/logging/transactionLog.js +51 -16
  851. package/dist/core/utility/logging/transactionLog.js.map +1 -1
  852. package/dist/core/utility/mount_hdb.js +54 -17
  853. package/dist/core/utility/mount_hdb.js.map +1 -1
  854. package/dist/core/utility/npmUtilities.js +54 -19
  855. package/dist/core/utility/npmUtilities.js.map +1 -1
  856. package/dist/core/utility/operation_authorization.js +135 -86
  857. package/dist/core/utility/operation_authorization.js.map +1 -1
  858. package/dist/core/utility/packageUtils.js +7 -17
  859. package/dist/core/utility/packageUtils.js.map +1 -1
  860. package/dist/core/utility/password.js +2 -2
  861. package/dist/core/utility/processManagement/processManagement.js +2 -2
  862. package/dist/core/utility/processManagement/servicesConfig.js +1 -1
  863. package/dist/core/utility/signalling.js +51 -16
  864. package/dist/core/utility/signalling.js.map +1 -1
  865. package/dist/core/utility/watcherFallback.js +73 -0
  866. package/dist/core/utility/watcherFallback.js.map +1 -0
  867. package/dist/core/validation/analyticsValidator.js +80 -0
  868. package/dist/core/validation/analyticsValidator.js.map +1 -0
  869. package/dist/core/validation/bulkDeleteValidator.js +49 -11
  870. package/dist/core/validation/bulkDeleteValidator.js.map +1 -1
  871. package/dist/core/validation/check_permissions.js +38 -3
  872. package/dist/core/validation/check_permissions.js.map +1 -1
  873. package/dist/core/validation/common_validators.js +62 -31
  874. package/dist/core/validation/common_validators.js.map +1 -1
  875. package/dist/core/validation/configValidator.js +189 -54
  876. package/dist/core/validation/configValidator.js.map +1 -1
  877. package/dist/core/validation/deleteValidator.js +49 -11
  878. package/dist/core/validation/deleteValidator.js.map +1 -1
  879. package/dist/core/validation/fileLoadValidator.js +67 -32
  880. package/dist/core/validation/fileLoadValidator.js.map +1 -1
  881. package/dist/core/validation/insertValidator.js +48 -10
  882. package/dist/core/validation/insertValidator.js.map +1 -1
  883. package/dist/core/validation/installValidator.js +47 -10
  884. package/dist/core/validation/installValidator.js.map +1 -1
  885. package/dist/core/validation/readLogValidator.js +60 -22
  886. package/dist/core/validation/readLogValidator.js.map +1 -1
  887. package/dist/core/validation/role_validation.js +55 -19
  888. package/dist/core/validation/role_validation.js.map +1 -1
  889. package/dist/core/validation/schemaMetadataValidator.js +11 -12
  890. package/dist/core/validation/schemaMetadataValidator.js.map +1 -1
  891. package/dist/core/validation/searchValidator.js +82 -43
  892. package/dist/core/validation/searchValidator.js.map +1 -1
  893. package/dist/core/validation/transactionLogValidator.js +52 -17
  894. package/dist/core/validation/transactionLogValidator.js.map +1 -1
  895. package/dist/core/validation/user_validation.js +38 -6
  896. package/dist/core/validation/user_validation.js.map +1 -1
  897. package/dist/core/validation/validationWrapper.js +4 -5
  898. package/dist/core/validation/validationWrapper.js.map +1 -1
  899. package/dist/licensing/usageLicensing.js +30 -21
  900. package/dist/licensing/usageLicensing.js.map +1 -1
  901. package/dist/replication/knownNodes.js +171 -41
  902. package/dist/replication/knownNodes.js.map +1 -1
  903. package/dist/replication/replicationConnection.js +441 -85
  904. package/dist/replication/replicationConnection.js.map +1 -1
  905. package/dist/replication/replicator.js +56 -28
  906. package/dist/replication/replicator.js.map +1 -1
  907. package/dist/replication/setNode.js +24 -4
  908. package/dist/replication/setNode.js.map +1 -1
  909. package/dist/replication/subscriptionManager.js +195 -16
  910. package/dist/replication/subscriptionManager.js.map +1 -1
  911. package/dist/security/certificate.js +41 -6
  912. package/dist/security/certificate.js.map +1 -1
  913. package/dist/security/sshKeyOperations.js +35 -2
  914. package/dist/security/sshKeyOperations.js.map +1 -1
  915. package/licensing/usageLicensing.ts +32 -37
  916. package/npm-shrinkwrap.json +9032 -4334
  917. package/package.json +17 -12
  918. package/replication/DESIGN.md +139 -0
  919. package/replication/knownNodes.ts +165 -44
  920. package/replication/replicationConnection.ts +475 -92
  921. package/replication/replicator.ts +54 -27
  922. package/replication/setNode.ts +29 -10
  923. package/replication/subscriptionManager.ts +227 -21
  924. package/security/certificate.ts +8 -4
  925. package/security/sshKeyOperations.ts +1 -1
  926. package/static/defaultConfig.yaml +1 -0
  927. package/studio/web/assets/{index-CybLScHg.js → index-Dqr9oVhe.js} +5 -5
  928. package/studio/web/assets/index-Dqr9oVhe.js.map +1 -0
  929. package/studio/web/assets/{index.lazy-DKx5-iXF.js → index.lazy-CpKcKb7M.js} +2 -2
  930. package/studio/web/assets/{index.lazy-DKx5-iXF.js.map → index.lazy-CpKcKb7M.js.map} +1 -1
  931. package/studio/web/assets/{profile-BOjes0Wl.js → profile-C1cujdsg.js} +2 -2
  932. package/studio/web/assets/{profile-BOjes0Wl.js.map → profile-C1cujdsg.js.map} +1 -1
  933. package/studio/web/assets/{status-EWKUIrjT.js → status-CTiIIQlY.js} +2 -2
  934. package/studio/web/assets/{status-EWKUIrjT.js.map → status-CTiIIQlY.js.map} +1 -1
  935. package/studio/web/index.html +1 -1
  936. package/core/bin/cliOperations.js +0 -159
  937. package/core/bin/lite.js +0 -5
  938. package/core/bin/stop.js +0 -21
  939. package/core/dataLayer/harperBridge/BridgeMethods.js +0 -85
  940. package/core/utility/globalSchema.js +0 -35
  941. package/core/utility/lmdb/OpenDBIObject.js +0 -31
  942. package/studio/web/assets/index-CybLScHg.js.map +0 -1
@@ -37,6 +37,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.NodeReplicationConnection = exports.databaseSubscriptions = exports.tableUpdateListeners = exports.RECEIVING_STATUS_RECEIVING = exports.RECEIVING_STATUS_WAITING = exports.BACK_PRESSURE_RATIO_POSITION = exports.RECEIVING_STATUS_POSITION = exports.LATENCY_POSITION = exports.SENDING_TIME_POSITION = exports.RECEIVED_TIME_POSITION = exports.RECEIVED_VERSION_POSITION = exports.CONFIRMATION_STATUS_POSITION = exports.OPERATION_REQUEST = void 0;
40
+ exports.shouldTerminateIdlePing = shouldTerminateIdlePing;
41
+ exports.createReceiveWatchdog = createReceiveWatchdog;
40
42
  exports.createWebSocket = createWebSocket;
41
43
  exports.replicateOverWS = replicateOverWS;
42
44
  const databases_ts_1 = require("../core/resources/databases.js");
@@ -45,10 +47,11 @@ const nodeIdMapping_ts_1 = require("../core/resources/nodeIdMapping.js");
45
47
  const transactionBroadcast_ts_1 = require("../core/resources/transactionBroadcast.js");
46
48
  const replicator_ts_1 = require("./replicator.js");
47
49
  const nodeName_ts_1 = require("../core/server/nodeName.js");
48
- const environmentManager_js_1 = __importDefault(require("../core/utility/environment/environmentManager.js"));
50
+ const env = __importStar(require("../core/utility/environment/environmentManager.js"));
49
51
  const hdbTerms_ts_1 = require("../core/utility/hdbTerms.js");
50
52
  const RecordEncoder_ts_1 = require("../core/resources/RecordEncoder.js");
51
53
  const msgpackr_1 = require("msgpackr");
54
+ const structon_1 = require("structon");
52
55
  const ws_1 = require("ws");
53
56
  const worker_threads_1 = require("worker_threads");
54
57
  const harper_logger_js_1 = __importDefault(require("../core/utility/logging/harper_logger.js"));
@@ -65,6 +68,13 @@ const blob_ts_1 = require("../core/resources/blob.js");
65
68
  const node_stream_1 = require("node:stream");
66
69
  const lmdb_1 = require("lmdb");
67
70
  const logger = forComponent('replication').conditional;
71
+ // msgpackr v2 removed the built-in `randomAccessStructure` option; that random-access
72
+ // struct support now lives in the `structon` package (the same wrapper core's
73
+ // RecordEncoder uses). Replication decoders must be structon-wrapped so they install
74
+ // the `_readStruct` hook and can decode typed-struct records — without it, struct
75
+ // marker bytes (0x20–0x3f) decode as plain integers and the decode aborts with
76
+ // "Data read, but end of buffer not reached".
77
+ const StructonPackr = (0, structon_1.createStructon)(msgpackr_1.Packr);
68
78
  // these are the codes we use for the different commands
69
79
  const SUBSCRIPTION_REQUEST = 129;
70
80
  const NODE_NAME = 140;
@@ -81,6 +91,8 @@ const COMMITTED_UPDATE = 144;
81
91
  const DB_SCHEMA = 145;
82
92
  const BLOB_CHUNK = 146;
83
93
  const SUBSCRIPTION_UPDATE = 147;
94
+ const COPY_START = 148; // leader -> follower: a bulk table copy is starting; carries copyStartTime
95
+ const COPY_COMPLETE = 149; // leader -> follower: the bulk table copy finished; follower clears its resume cursor
84
96
  exports.CONFIRMATION_STATUS_POSITION = 0;
85
97
  exports.RECEIVED_VERSION_POSITION = 1;
86
98
  exports.RECEIVED_TIME_POSITION = 2;
@@ -90,12 +102,22 @@ exports.RECEIVING_STATUS_POSITION = 5;
90
102
  exports.BACK_PRESSURE_RATIO_POSITION = 6;
91
103
  exports.RECEIVING_STATUS_WAITING = 0;
92
104
  exports.RECEIVING_STATUS_RECEIVING = 1;
93
- const MAX_PAYLOAD = environmentManager_js_1.default.get('replication_maxPayload') ?? 100_000_000;
105
+ const MAX_PAYLOAD = env.get('replication_maxPayload') ?? 100_000_000;
94
106
  // When receiving a replication message, we apply per-record backpressure to keep a single
95
107
  // large batch from synchronously decoding thousands of records and ballooning the worker
96
108
  // heap past its limit. If the local replicator queue grows beyond this threshold we pause
97
109
  // the WS connection and wait for it to drain before continuing the decode loop.
98
- const RECEIVE_EVENT_HIGH_WATER_MARK = environmentManager_js_1.default.get('replication_receiveEventHighWaterMark') ?? 100;
110
+ const RECEIVE_EVENT_HIGH_WATER_MARK = env.get('replication_receiveEventHighWaterMark') ?? 100;
111
+ // Even when the consumer keeps up (queue below the high-water mark), a single large inbound message
112
+ // would otherwise decode thousands of records in one synchronous turn — pegging the worker, blocking
113
+ // replication ping responses, and tripping core's "JavaScript execution has taken too long" monitor
114
+ // (MAX_EVENT_DELAY_TIME = 3 s). Yield the event loop at least this often (ms) while decoding so the
115
+ // worker stays responsive during a bulk copy/clone.
116
+ const RECEIVE_YIELD_INTERVAL = env.get('replication_receiveYieldInterval') ?? 100;
117
+ // During a bulk clone copy the leader flushes a checkpoint transaction every this many records so the
118
+ // follower commits incrementally and persists a resume cursor. On reconnect the copy resumes from that
119
+ // cursor instead of restarting from zero. Larger = less overhead but coarser resume granularity.
120
+ const COPY_CHECKPOINT_RECORDS = env.get('replication_copyCheckpointRecords') ?? 1000;
99
121
  exports.tableUpdateListeners = new Map();
100
122
  // This a map of the database name to the subscription object, for the subscriptions from our tables to the replication module
101
123
  // when we receive messages from other nodes, we then forward them on to as a notification on these subscriptions
@@ -108,7 +130,91 @@ const SKIPPED_MESSAGE_SEQUENCE_UPDATE_DELAY = 300;
108
130
  // We want it be fairly quick so we can let the sending node know that we have received and committed the update.
109
131
  // (but still allow for batching so we aren't sending out a message for every update under load)
110
132
  const COMMITTED_UPDATE_DELAY = 2;
111
- const PING_INTERVAL = 30000;
133
+ const PING_INTERVAL = env.get(hdbTerms_ts_1.CONFIG_PARAMS.REPLICATION_PINGINTERVAL) ?? 30000;
134
+ // Time (ms) without any socket activity before a connection is treated as dead.
135
+ const PING_TIMEOUT = env.get(hdbTerms_ts_1.CONFIG_PARAMS.REPLICATION_PINGTIMEOUT) ?? PING_INTERVAL * 2;
136
+ // The receive-side watchdog fires after this much silence on a replication WS. Both client and
137
+ // server arm it: the client also runs an active 30s sendPing tick that should normally catch a
138
+ // silent peer first, but if that tick is missed (event-loop stall, ws.terminate() not propagating
139
+ // to 'close', etc.) this timer-based watchdog is the belt-and-suspenders that forces the
140
+ // reconnect — see harper-pro#233.
141
+ const RECEIVE_SILENCE_THRESHOLD_MS = PING_TIMEOUT;
142
+ /**
143
+ * Decide whether an idle replication connection should be terminated as dead.
144
+ *
145
+ * Liveness is measured from the last observed socket byte movement (in either direction), not from a
146
+ * single ping interval. A bulk transfer — notably the initial clone copy of a large table — makes
147
+ * slow but real progress: the sender's socket buffer drains in bursts as the peer consumes, so bytes
148
+ * keep moving within the timeout window even while it is otherwise stalled. A genuinely dead or
149
+ * unreachable peer moves no bytes at all, so it still trips the timeout. We deliberately do NOT exempt
150
+ * the sender's `isPausedForBackPressure` drain-wait here: if the peer dies after we have filled our
151
+ * socket buffer, the drain event never fires, and exempting it would hang the connection forever.
152
+ *
153
+ * The one exemption is `pauseReasons > 0`: the receiver has intentionally stopped reading to drain its
154
+ * own queue. That stall is local and self-clearing (it does not depend on the peer), so it is never a
155
+ * death signal; the caller keeps liveness fresh while paused and resumes normal detection afterward.
156
+ */
157
+ function shouldTerminateIdlePing(idleMs, pingTimeout, pauseReasons) {
158
+ return pauseReasons === 0 && idleMs >= pingTimeout;
159
+ }
160
+ /**
161
+ * Receive-side silence watchdog. Arm with `reset()` whenever incoming activity is observed
162
+ * (peer ping, pong, message). If `intervalMs` elapses with the underlying socket's `bytesRead`
163
+ * unchanged, `onSilence` is invoked exactly once.
164
+ *
165
+ * Only `bytesRead` is checked — `bytesWritten` reflects our own outbound traffic (pings, blob
166
+ * sends) and is not proof that the peer is alive. Including it would let our own keepalive
167
+ * pings suppress the watchdog in the exact missed-sendPing scenario this is meant to recover.
168
+ *
169
+ * Callers should suspend the watchdog (via `stop()`) when the underlying WS is intentionally
170
+ * paused for backpressure: `bytesRead` is frozen by design while paused and would otherwise
171
+ * cause a spurious termination of a healthy connection.
172
+ *
173
+ * Exported so the timer logic can be exercised in isolation by `unitTests/replication/
174
+ * receiveWatchdog.test.mjs` — production callers go through `replicateOverWS`.
175
+ */
176
+ function createReceiveWatchdog(opts) {
177
+ let timer;
178
+ let bytesReadAtArm = 0;
179
+ let lastResetAt = 0;
180
+ // Coalesce rapid reset() calls (e.g. message frames arriving thousands of times per second
181
+ // during a large copy) so we do not churn setTimeout/clearTimeout per frame. Granularity loss
182
+ // is small relative to intervalMs — at worst the watchdog fires this much earlier or later.
183
+ const throttleMs = Math.min(1000, Math.max(100, opts.intervalMs / 30));
184
+ function check() {
185
+ const current = opts.getBytesRead();
186
+ if (current === bytesReadAtArm) {
187
+ timer = undefined;
188
+ opts.onSilence();
189
+ return;
190
+ }
191
+ // Bytes advanced since the last arm — but the activity may have been swallowed by the
192
+ // reset() throttle, so we cannot rely on an external caller to re-arm us. Re-arm from
193
+ // the new baseline; otherwise a throttled-reset-then-silence sequence would leave the
194
+ // watchdog permanently inactive (see PR #234 review).
195
+ bytesReadAtArm = current;
196
+ lastResetAt = Date.now();
197
+ timer = setTimeout(check, opts.intervalMs).unref();
198
+ }
199
+ return {
200
+ reset() {
201
+ const now = Date.now();
202
+ if (timer && now - lastResetAt < throttleMs)
203
+ return;
204
+ lastResetAt = now;
205
+ if (timer)
206
+ clearTimeout(timer);
207
+ bytesReadAtArm = opts.getBytesRead();
208
+ timer = setTimeout(check, opts.intervalMs).unref();
209
+ },
210
+ stop() {
211
+ if (timer) {
212
+ clearTimeout(timer);
213
+ timer = undefined;
214
+ }
215
+ },
216
+ };
217
+ }
112
218
  let secureContexts;
113
219
  let replicationSecureContext;
114
220
  async function createWebSocket(url, options) {
@@ -196,6 +302,7 @@ class NodeReplicationConnection extends events_1.EventEmitter {
196
302
  databaseName;
197
303
  nodeName;
198
304
  authorization;
305
+ tentativeNode;
199
306
  constructor(url, subscription, databaseName, nodeName, authorization) {
200
307
  super();
201
308
  this.url = url;
@@ -205,6 +312,8 @@ class NodeReplicationConnection extends events_1.EventEmitter {
205
312
  this.nodeName = this.nodeName ?? (0, replicator_ts_1.urlToNodeName)(url);
206
313
  }
207
314
  async connect() {
315
+ if (this.intentionallyUnsubscribed)
316
+ return;
208
317
  if (!this.session)
209
318
  this.resetSession();
210
319
  // TODO: Need to do this specifically for each node
@@ -318,7 +427,7 @@ class NodeReplicationConnection extends events_1.EventEmitter {
318
427
  }
319
428
  unsubscribe() {
320
429
  this.intentionallyUnsubscribed = true;
321
- this.socket.close(1008, 'No longer subscribed');
430
+ this.socket?.close(1008, 'No longer subscribed');
322
431
  }
323
432
  getRecord(request) {
324
433
  return this.session.then((session) => {
@@ -366,7 +475,33 @@ function replicateOverWS(ws, options, authorization) {
366
475
  if (remoteNodeName && options.connection)
367
476
  options.connection.nodeName = remoteNodeName;
368
477
  let lastSequenceIdReceived, lastSequenceIdCommitted;
369
- let sendPingInterval, receivePingTimer, lastPingTime, skippedMessageSequenceUpdateTimer;
478
+ // Bulk-copy resume state (receiver side). While inCopyMode, each committed batch persists a cursor
479
+ // (copyStartTime + last committed table/key) so an interrupted copy can resume instead of restarting.
480
+ let inCopyMode = false;
481
+ let copyModeStartTime = 0;
482
+ let copyFromNodeId; // local id of the node we are copying from — the key for the persisted cursor
483
+ let copyCompleteReceived = false;
484
+ // Finish the copy — leave copy mode and remove the resume cursor — only once COPY_COMPLETE has been
485
+ // received AND every copied batch has committed (outstandingCommits drained, which includes the final
486
+ // end_txn that advances the resume seqId to copyStartTime). We deliberately stay in copy mode until
487
+ // then so batches still committing keep advancing the cursor (onCommit). Finishing earlier — e.g.
488
+ // synchronously when COPY_COMPLETE is decoded while batches are still queued — would freeze the cursor
489
+ // and risk a crash that loses both the cursor and the not-yet-durable rows, leaving the next start to
490
+ // resume from seqId with gaps.
491
+ function maybeFinishCopy() {
492
+ if (copyCompleteReceived && outstandingCommits === 0) {
493
+ // guard only the cursor removal on a known node id; ALWAYS exit copy mode, otherwise a
494
+ // COPY_START whose getIdOfRemoteNode returned undefined would strand the node in copy mode
495
+ // (received-version watermark suppressed) and it could never reach Available.
496
+ if (copyFromNodeId !== undefined)
497
+ tableSubscriptionToReplicator?.dbisDB?.remove([Symbol.for('copyCursor'), copyFromNodeId]);
498
+ inCopyMode = false;
499
+ copyCompleteReceived = false;
500
+ copyFromNodeId = undefined;
501
+ }
502
+ }
503
+ let sendPingInterval, lastPingTime, skippedMessageSequenceUpdateTimer;
504
+ let receiveWatchdog;
370
505
  let blobsTimer;
371
506
  const DELAY_CLOSE_TIME = 60000; // amount of time to wait before closing the connection if we haven't any activity and there are no subscriptions
372
507
  let delayedClose;
@@ -374,42 +509,77 @@ function replicateOverWS(ws, options, authorization) {
374
509
  // track bytes read and written so we can verify if a connection is really dead on pings
375
510
  let bytesRead = 0;
376
511
  let bytesWritten = 0;
377
- const blobTimeout = environmentManager_js_1.default.get(hdbTerms_ts_1.CONFIG_PARAMS.REPLICATION_BLOBTIMEOUT) ?? 120000;
512
+ // wall-clock time of the last observed socket activity (bytes moved in either direction); the
513
+ // keep-alive timeout is measured from this so a legitimately slow-but-progressing transfer stays
514
+ // alive while a truly idle/dead peer is still terminated.
515
+ let lastByteActivity = performance.now();
516
+ // Multiple independent conditions can ask to pause receive on this WS (commit backlog, consumer
517
+ // queue full, blob write backpressure). We refcount the reasons so that resuming one does not race
518
+ // ahead of another that still wants the WS paused. Declared before the ping setup below because the
519
+ // immediate sendPing() reads it.
520
+ let pauseReasons = 0;
521
+ const blobTimeout = env.get(hdbTerms_ts_1.CONFIG_PARAMS.REPLICATION_BLOBTIMEOUT) ?? 120000;
378
522
  const blobsInFlight = new Map();
379
523
  const outstandingBlobsToFinish = [];
380
524
  let outstandingBlobsBeingSent = 0;
381
525
  let blobSentCallback;
526
+ // Refresh the keep-alive liveness clock from observed socket byte movement. If the underlying
527
+ // _socket isn't observable (test mocks, pre-connect, or a change in the ws library internals),
528
+ // bytesRead/bytesWritten read as undefined; we can't measure activity, so treat the connection as
529
+ // live rather than let the keep-alive falsely terminate a healthy peer.
530
+ function noteByteActivity() {
531
+ const read = ws._socket?.bytesRead;
532
+ const written = ws._socket?.bytesWritten;
533
+ if (read === undefined || written === undefined || read !== bytesRead || written !== bytesWritten) {
534
+ lastByteActivity = performance.now();
535
+ }
536
+ }
382
537
  if (options.url) {
383
538
  const sendPing = () => {
384
- // if we have not received a message in the last ping interval, we should terminate the connection (but check to make sure we aren't just waiting for other data to flow)
385
- if (lastPingTime && bytesRead === ws._socket?.bytesRead && bytesWritten === ws._socket?.bytesWritten)
386
- ws.terminate(); // timeout
387
- else {
388
- lastPingTime = performance.now();
389
- ws.ping();
390
- bytesRead = ws._socket?.bytesRead;
391
- bytesWritten = ws._socket?.bytesWritten;
539
+ // Note any socket activity since the last interval (incoming pong/data or our send buffer
540
+ // draining as the peer consumes) either proves the peer is still alive.
541
+ noteByteActivity();
542
+ if (shouldTerminateIdlePing(performance.now() - lastByteActivity, PING_TIMEOUT, pauseReasons)) {
543
+ ws.terminate(); // no socket activity within the timeout — peer is gone
544
+ return;
392
545
  }
546
+ // While paused for receiver backpressure, keep our own liveness fresh: the stall is local and
547
+ // self-clearing (it doesn't depend on the peer), so we must not time the peer out for it.
548
+ if (pauseReasons > 0)
549
+ lastByteActivity = performance.now();
550
+ // Always send the keep-alive ping. ws.pause() only stops reads, not writes, and the accepted
551
+ // peer relies on our pings to keep its own receive timer alive even when it has no data to send
552
+ // us. Record byte counts AFTER the ping so the ping's own bytes aren't later mistaken for peer
553
+ // activity.
554
+ lastPingTime = performance.now();
555
+ ws.ping();
556
+ bytesRead = ws._socket?.bytesRead;
557
+ bytesWritten = ws._socket?.bytesWritten;
393
558
  };
394
559
  sendPingInterval = setInterval(sendPing, PING_INTERVAL).unref();
395
560
  sendPing(); // send the first ping immediately so we can measure latency
396
561
  }
397
- else {
398
- resetPingTimer();
399
- }
562
+ // Both client and server arm the receive watchdog. On the client this is independent of the
563
+ // sendPing tick above: if that tick is missed or its ws.terminate() does not propagate a
564
+ // 'close' event, the watchdog forces the reconnect path. See harper-pro#233 for the failure
565
+ // modes observed in the field.
566
+ receiveWatchdog = createReceiveWatchdog({
567
+ intervalMs: RECEIVE_SILENCE_THRESHOLD_MS,
568
+ getBytesRead: () => ws._socket?.bytesRead ?? 0,
569
+ onSilence: () => {
570
+ // Warn-level: if the active sendPing was healthy this watchdog should not have fired,
571
+ // so it is a signal that something is wrong upstream (event-loop stall, keepalive timer
572
+ // misbehaving, peer accepting bytes but not progressing the protocol). Surface it so
573
+ // operators have something to grep for.
574
+ const dbContext = databaseName ? ` (db: "${databaseName}")` : '';
575
+ const direction = options.url ? 'no activity from' : 'no ping from';
576
+ logger.warn?.(`Receive watchdog: ${direction} ${remoteNodeName}${dbContext} for ${RECEIVE_SILENCE_THRESHOLD_MS}ms — terminating connection and reconnecting`);
577
+ ws.terminate();
578
+ },
579
+ });
580
+ const resetPingTimer = receiveWatchdog.reset;
581
+ resetPingTimer();
400
582
  ws._socket?.setMaxListeners(200); // we should allow a lot of drain listeners for concurrent blob streams
401
- function resetPingTimer() {
402
- clearTimeout(receivePingTimer);
403
- bytesRead = ws._socket?.bytesRead;
404
- bytesWritten = ws._socket?.bytesWritten;
405
- receivePingTimer = setTimeout(() => {
406
- // double check to make sure we aren't just waiting for other data to flow
407
- if (bytesRead === ws._socket?.bytesRead && bytesWritten === ws._socket?.bytesWritten) {
408
- logger.warn?.(`Timeout waiting for ping from ${remoteNodeName}, terminating connection and reconnecting`);
409
- ws.terminate();
410
- }
411
- }, PING_INTERVAL * 2).unref();
412
- }
413
583
  let ratioOfBackPressureTime = 0;
414
584
  let lastBackPressureCheck = 0;
415
585
  let isPausedForBackPressure = false;
@@ -448,30 +618,37 @@ function replicateOverWS(ws, options, authorization) {
448
618
  const residencyMap = [];
449
619
  const sentResidencyLists = [];
450
620
  const receivedResidencyLists = [];
451
- const MAX_OUTSTANDING_COMMITS = environmentManager_js_1.default.get(hdbTerms_ts_1.CONFIG_PARAMS.REPLICATION_RECORDCONCURRENCY) ?? 150; // maximum before requesting that other nodes pause
452
- const MAX_OUTSTANDING_BLOBS_BEING_SENT = environmentManager_js_1.default.get(hdbTerms_ts_1.CONFIG_PARAMS.REPLICATION_BLOBCONCURRENCY) ?? 5;
621
+ const MAX_OUTSTANDING_COMMITS = env.get(hdbTerms_ts_1.CONFIG_PARAMS.REPLICATION_RECORDCONCURRENCY) ?? 150; // maximum before requesting that other nodes pause
622
+ const MAX_OUTSTANDING_BLOBS_BEING_SENT = env.get(hdbTerms_ts_1.CONFIG_PARAMS.REPLICATION_BLOBCONCURRENCY) ?? 5;
453
623
  let outstandingCommits = 0;
454
624
  let lastStructureLength = 0;
455
- // Multiple independent conditions can ask to pause receive on this WS (commit backlog,
456
- // consumer queue full, blob write backpressure). We refcount the reasons so that resuming
457
- // one does not race ahead of another that still wants the WS paused.
458
- let pauseReasons = 0;
459
625
  let commitBacklogPaused = false;
460
626
  function addPauseReason() {
461
- if (pauseReasons === 0)
627
+ if (pauseReasons === 0) {
462
628
  ws.pause();
629
+ // Suspend the receive watchdog while the socket is intentionally paused — `bytesRead`
630
+ // is frozen by `ws.pause()` so the byte check cannot tell legitimate backpressure
631
+ // from peer silence, and firing here would terminate a healthy mid-ingest connection.
632
+ receiveWatchdog?.stop();
633
+ }
463
634
  pauseReasons++;
464
635
  }
465
636
  function removePauseReason() {
466
637
  if (pauseReasons === 0)
467
638
  return;
468
639
  pauseReasons--;
469
- if (pauseReasons === 0)
640
+ if (pauseReasons === 0) {
470
641
  ws.resume();
642
+ // Restart the silence window from the resume point — we deliberately do not penalize
643
+ // the connection for the time it spent paused.
644
+ receiveWatchdog?.reset();
645
+ }
471
646
  }
472
647
  let subscriptionRequest, auditSubscription;
473
648
  let nodeSubscriptions;
474
649
  let excludedNodes; // list of nodes to exclude from this subscription
650
+ // undefined = not yet computed; null = computed, no exclusions; Set = tables to drop on receive
651
+ let receiveExcludedTables;
475
652
  let remoteShortIdToLocalId;
476
653
  let subscribedNodeIds; // map of node IDs to their subscription time ranges
477
654
  // Serialize message handling so that async backpressure inside onWSMessage doesn't allow
@@ -481,6 +658,9 @@ function replicateOverWS(ws, options, authorization) {
481
658
  let messageProcessing = Promise.resolve();
482
659
  let wsClosed = false;
483
660
  ws.on('message', (body) => {
661
+ // Reset the receive watchdog synchronously on every frame — async processing below may
662
+ // take a long time and we want a single late frame to count as proof of life immediately.
663
+ resetPingTimer();
484
664
  messageProcessing = messageProcessing.then(() => (wsClosed ? undefined : onWSMessage(body)), () => (wsClosed ? undefined : onWSMessage(body)));
485
665
  });
486
666
  let authorizationFinished = false;
@@ -683,9 +863,8 @@ function replicateOverWS(ws, options, authorization) {
683
863
  // of the table id to the decoder so we can decode the binary data for each table.
684
864
  tableDecoders[tableId] = {
685
865
  name: tableName,
686
- decoder: new msgpackr_1.Packr({
866
+ decoder: new StructonPackr({
687
867
  useBigIntExtension: true,
688
- randomAccessStructure: true,
689
868
  freezeData: true,
690
869
  typedStructs: data.typedStructs,
691
870
  structures: data.structures,
@@ -714,6 +893,20 @@ function replicateOverWS(ws, options, authorization) {
714
893
  (0, write_ts_1.recordAction)(body.length, 'bytes-received', `${remoteNodeName}.${databaseName}`, 'replication', 'committed-update');
715
894
  getSharedStatus().buffer.notify();
716
895
  break;
896
+ case COPY_START:
897
+ // the leader is (re)starting a bulk copy; track a resume cursor for it
898
+ inCopyMode = true;
899
+ copyModeStartTime = data; // copyStartTime anchor chosen by the leader
900
+ copyFromNodeId = (0, nodeIdMapping_ts_1.getIdOfRemoteNode)(remoteNodeName, auditStore);
901
+ logger.debug?.(connectionId, 'bulk copy starting from', remoteNodeName, new Date(copyModeStartTime));
902
+ break;
903
+ case COPY_COMPLETE:
904
+ // Copy signalled complete. Stay in copy mode so batches still committing keep advancing the
905
+ // cursor; maybeFinishCopy exits copy mode and clears the cursor once those commits drain.
906
+ copyCompleteReceived = true;
907
+ maybeFinishCopy();
908
+ logger.debug?.(connectionId, 'bulk copy complete from', remoteNodeName);
909
+ break;
717
910
  case SEQUENCE_ID_UPDATE:
718
911
  // we need to record the sequence number that the remote node has received
719
912
  lastSequenceIdReceived = data;
@@ -759,20 +952,38 @@ function replicateOverWS(ws, options, authorization) {
759
952
  if (stream.connectedToBlob)
760
953
  blobsInFlight.delete(fileId);
761
954
  }
955
+ else if (stream.destroyed || stream.writableEnded) {
956
+ // The stream was already torn down before this mid-blob chunk arrived —
957
+ // typically because saveBlob's pipeline failed (e.g. ENOENT on
958
+ // createWriteStream) and destroyed the PassThrough source, firing 'close'.
959
+ // We must NOT fall into the backpressure branch below: writing to a dead
960
+ // stream returns false, and pausing to wait for a 'drain'/'close' that has
961
+ // already fired strands the pause reason forever, wedging the entire
962
+ // receive loop (observed in prod: receiver goes silent, sender stuck
963
+ // reconnecting, replication never recovers). Drop the orphaned chunk and
964
+ // forget the stream instead.
965
+ blobsInFlight.delete(fileId);
966
+ }
762
967
  else if (!stream.write(blobBody)) {
763
968
  // The PassThrough's internal queue is over its HWM, meaning the downstream
764
969
  // file write (via pipeline in saveBlob) can't keep up. Pause the WS until the
765
970
  // stream drains so blob chunks don't accumulate in memory faster than they
766
- // can be flushed to disk. Also listen for 'close' so a destroyed stream
767
- // (e.g. saveBlob error) doesn't strand the pause reason.
768
- addPauseReason();
769
- const release = () => {
770
- stream.off('drain', release);
771
- stream.off('close', release);
772
- removePauseReason();
773
- };
774
- stream.on('drain', release);
775
- stream.on('close', release);
971
+ // can be flushed to disk.
972
+ if (stream.destroyed || stream.writableEnded) {
973
+ // write() itself may have torn the stream down (e.g. a late error). If so,
974
+ // 'drain'/'close' won't arrive skip pausing rather than strand the reason.
975
+ blobsInFlight.delete(fileId);
976
+ }
977
+ else {
978
+ addPauseReason();
979
+ const release = () => {
980
+ stream.off('drain', release);
981
+ stream.off('close', release);
982
+ removePauseReason();
983
+ };
984
+ stream.on('drain', release);
985
+ stream.on('close', release);
986
+ }
776
987
  }
777
988
  }
778
989
  catch (error) {
@@ -994,6 +1205,10 @@ function replicateOverWS(ws, options, authorization) {
994
1205
  let tableById;
995
1206
  let currentSequenceId = Infinity; // the last sequence number in the audit log that we have processed, set this with a finite number from the subscriptions
996
1207
  let sentSequenceId; // the last sequence number we have sent
1208
+ // Tables excluded from outgoing replication to this peer+database (from sendsTo config)
1209
+ const sendExcludedTables = authorization?.replicates && typeof authorization.replicates === 'object'
1210
+ ? (0, knownNodes_ts_1.getExcludedTablesForRouteEntries)(authorization.replicates.sendsTo, remoteNodeName, databaseName)
1211
+ : null;
997
1212
  const sendAuditRecord = (auditRecord, localTime) => {
998
1213
  if (auditRecord.type === 'end_txn') {
999
1214
  if (currentTransaction.txnTime) {
@@ -1019,6 +1234,9 @@ function replicateOverWS(ws, options, authorization) {
1019
1234
  }
1020
1235
  }
1021
1236
  const table = tableEntry.table;
1237
+ if (sendExcludedTables?.has(table.tableName)) {
1238
+ return skipAuditRecord();
1239
+ }
1022
1240
  const primaryStore = table.primaryStore;
1023
1241
  const encoder = primaryStore.encoder;
1024
1242
  // Force a reload the first time this connection touches each table:
@@ -1044,7 +1262,9 @@ function replicateOverWS(ws, options, authorization) {
1044
1262
  // in the subscribedNodeIds list, than it matches the subscription
1045
1263
  const matchesSubscription = (excludedNodes && timeRange === undefined) ||
1046
1264
  // if it is in the list, we check the timestamps to verify it matches
1047
- (timeRange && timeRange.startTime < localTime && (!timeRange.endTime || timeRange.endTime > localTime));
1265
+ (timeRange &&
1266
+ timeRange.startTime < localTime &&
1267
+ (!timeRange.endTime || timeRange.endTime > localTime));
1048
1268
  if (!matchesSubscription) {
1049
1269
  if (DEBUG_MODE)
1050
1270
  logger.trace?.(connectionId, 'skipping replication update', auditRecord.recordId, 'to:', remoteNodeName, 'from:', nodeId, 'subscribed:', subscribedNodeIds);
@@ -1232,9 +1452,13 @@ function replicateOverWS(ws, options, authorization) {
1232
1452
  subscriptionToHdbNodes?.end();
1233
1453
  });
1234
1454
  // find the earliest start time of the subscriptions
1235
- for (const { startTime } of nodeSubscriptions) {
1236
- if (startTime < currentSequenceId)
1237
- currentSequenceId = startTime;
1455
+ let copyResume;
1456
+ for (const subscription of nodeSubscriptions) {
1457
+ if (subscription.startTime < currentSequenceId)
1458
+ currentSequenceId = subscription.startTime;
1459
+ // a follower resuming an interrupted bulk copy sends back where it left off
1460
+ if (subscription.copyResume)
1461
+ copyResume = subscription.copyResume;
1238
1462
  }
1239
1463
  // wait for internal subscription, might be waiting for a table to be registered
1240
1464
  (whenSubscribedToHdbNodes || Promise.resolve())
@@ -1301,21 +1525,53 @@ function replicateOverWS(ws, options, authorization) {
1301
1525
  isFirst = false;
1302
1526
  if (currentSequenceId === 0) {
1303
1527
  logger.info?.('Replicating all tables to', remoteNodeName);
1304
- let lastSequenceId = Date.now(); // we need at least a default time point in case there are no records
1528
+ // Capture the resume point BEFORE iterating. The bulk copy walks the primary store in
1529
+ // key order (snapshot: false), but the follower resumes replication from the audit log in
1530
+ // time order. Using copyStartTime — not max(localTime) of the copied records — guarantees
1531
+ // the post-copy audit replay re-delivers every write committed during the copy, including
1532
+ // ones to keys we already passed; resuming from max(localTime) would skip those (data loss).
1533
+ // When the follower is resuming an interrupted copy, keep the original copy start time so
1534
+ // the post-copy resume point stays anchored to when the copy first began (see safety note).
1535
+ const copyStartTime = copyResume?.copyStartTime ?? Date.now();
1305
1536
  const nodeId = (0, nodeIdMapping_ts_1.getThisNodeId)(auditStore);
1537
+ // Tell the follower a bulk copy is starting and its anchor time, so it tracks a resume cursor.
1538
+ ws.send((0, msgpackr_1.encode)([COPY_START, copyStartTime]));
1539
+ let recordsSinceCheckpoint = 0;
1540
+ // If resuming, the follower already committed every table before currentTable (records commit
1541
+ // in stable iteration order), so skip to currentTable and continue after its last committed key.
1542
+ let reachedResumeTable = !copyResume;
1543
+ // currentTable must be one the loop below will actually visit (present in `tables` AND passing
1544
+ // the same replication filter); otherwise the skip loop never reaches it and would omit every
1545
+ // later table. Mirror the loop's own check so a dropped/unreplicated cursor table forces a restart.
1546
+ if (copyResume && !tableToTableEntry(tables[copyResume.currentTable])) {
1547
+ // cursor table is gone or no longer replicated — the skip loop would never reach it and
1548
+ // would omit every later table, so recopy from scratch (idempotent puts, copyStartTime reset)
1549
+ logger.warn?.('Copy-resume table missing or unreplicated, restarting full copy', copyResume.currentTable);
1550
+ copyResume = undefined;
1551
+ reachedResumeTable = true;
1552
+ }
1553
+ const resumeCurrentTable = copyResume?.currentTable;
1554
+ const resumeAfterKey = copyResume?.afterKey;
1306
1555
  for (const tableName in tables) {
1307
- if (!tableToTableEntry(tableName))
1308
- continue; // if we aren't replicating this table, skip it
1309
1556
  const table = tables[tableName];
1310
- for (const entry of table.primaryStore.getRange({
1311
- snapshot: false,
1312
- versions: true,
1313
- // values: false, // TODO: eventually, we don't want to decode, we want to use fast binary transfer
1314
- })) {
1557
+ if (!tableToTableEntry(table))
1558
+ continue; // if we aren't replicating this table, skip it
1559
+ if (!reachedResumeTable) {
1560
+ if (tableName !== resumeCurrentTable)
1561
+ continue; // already committed on the follower
1562
+ reachedResumeTable = true;
1563
+ }
1564
+ const rangeOptions = { snapshot: false, versions: true };
1565
+ // values: false, // TODO: eventually, we don't want to decode, we want to use fast binary transfer
1566
+ if (tableName === resumeCurrentTable) {
1567
+ // resume this table after the last key the follower committed
1568
+ rangeOptions.start = resumeAfterKey;
1569
+ rangeOptions.exclusiveStart = true;
1570
+ }
1571
+ for (const entry of table.primaryStore.getRange(rangeOptions)) {
1315
1572
  if (closed)
1316
1573
  return;
1317
1574
  logger.trace?.(connectionId, 'Copying record from', databaseName, tableName, entry.key, entry.localTime);
1318
- lastSequenceId = Math.max(entry.localTime ?? 1, lastSequenceId);
1319
1575
  getSharedStatus()[exports.SENDING_TIME_POSITION] = 1;
1320
1576
  const encoded = (0, auditStore_ts_1.createAuditEntry)({
1321
1577
  version: entry.version,
@@ -1348,23 +1604,43 @@ function replicateOverWS(ws, options, authorization) {
1348
1604
  extendedType: entry.metadataFlags,
1349
1605
  }, entry.localTime);
1350
1606
  logger.debug?.('sent record from table', entry.key, 'length:', encoded.length, encoded.slice(0, 10));
1607
+ // Periodically flush the accumulated records as a message so the follower commits this
1608
+ // batch and advances its resume cursor. This is a plain flush with NO sequence update:
1609
+ // emitting an end_txn here would advance the follower's received-version watermark to
1610
+ // copyStartTime mid-copy, which monitorSync could read as "caught up" and mark the clone
1611
+ // Available/cloned with rows still uncopied. (Records with differing versions already flush
1612
+ // naturally above; this also bounds same-version bulk data into committable batches.) The
1613
+ // watermark is only advanced to copyStartTime by the single end_txn after the whole copy.
1614
+ if (++recordsSinceCheckpoint >= COPY_CHECKPOINT_RECORDS && position - encodingStart > 8) {
1615
+ recordsSinceCheckpoint = 0;
1616
+ sendQueuedData();
1617
+ encodingStart = position;
1618
+ currentTransaction.txnTime = 0;
1619
+ }
1351
1620
  }
1352
1621
  logger.info?.('Finished copy table', tableName, remoteNodeName);
1353
1622
  }
1354
- currentSequenceId = lastSequenceId;
1623
+ currentSequenceId = copyStartTime;
1355
1624
  if (!currentTransaction.txnTime) {
1356
- // if we haven't sent any records, force a txn start and end so the subscribers records a timestamp
1357
- currentTransaction.txnTime = lastSequenceId;
1358
- writeFloat64(lastSequenceId);
1359
- }
1360
- if (position - encodingStart > 8) {
1361
- // if we have any queued transactions to send, send them now
1362
- sendAuditRecord({
1363
- type: 'end_txn',
1364
- }, currentSequenceId);
1625
+ // no records pending (none sent, or the last batch landed on a checkpoint flush):
1626
+ // force a txn so the end_txn below still carries the sequence update
1627
+ currentTransaction.txnTime = copyStartTime;
1628
+ encodingStart = position;
1629
+ writeFloat64(copyStartTime);
1365
1630
  }
1631
+ // ALWAYS emit the final end_txn at copyStartTime. It carries the REMOTE_SEQUENCE_UPDATE
1632
+ // that advances the follower's seqId and received-version watermark to copyStartTime —
1633
+ // the sole signal that the copy is synced (per-record watermark advance is suppressed
1634
+ // during the copy). Skipping it when the last rows landed exactly on a checkpoint flush
1635
+ // would leave the clone unable to ever reach Available.
1636
+ sendAuditRecord({
1637
+ type: 'end_txn',
1638
+ }, currentSequenceId);
1639
+ // The full copy is done — tell the follower to clear its resume cursor and fall back to
1640
+ // normal audit-log replication from the persisted seqId (which is copyStartTime).
1641
+ ws.send((0, msgpackr_1.encode)([COPY_COMPLETE]));
1366
1642
  getSharedStatus()[exports.SENDING_TIME_POSITION] = 0;
1367
- currentSequenceId = lastSequenceId;
1643
+ currentSequenceId = copyStartTime;
1368
1644
  }
1369
1645
  }
1370
1646
  const logName = subscribedNodeName === (0, nodeName_ts_1.getThisNodeName)() ? 'local' : subscribedNodeName;
@@ -1415,6 +1691,7 @@ function replicateOverWS(ws, options, authorization) {
1415
1691
  let beginTxn = true;
1416
1692
  let event; // could also get txnTime from decoder.getFloat64(0);
1417
1693
  let sequenceIdReceived;
1694
+ let lastYieldTime = performance.now();
1418
1695
  do {
1419
1696
  getSharedStatus();
1420
1697
  const eventLength = decoder.readInt();
@@ -1441,6 +1718,23 @@ function replicateOverWS(ws, options, authorization) {
1441
1718
  if (!tableDecoder) {
1442
1719
  logger.error?.(`No table found with an id of ${auditRecord.tableId}`);
1443
1720
  }
1721
+ // Lazily compute receive-side exclusions once remoteNodeName is known.
1722
+ // Prefer routeReplicates from the subscriber-side connection; fall back to
1723
+ // authorization.replicates when this is the server-side handler.
1724
+ if (receiveExcludedTables === undefined) {
1725
+ const firstNode = options.connection?.nodeSubscriptions?.[0];
1726
+ const receivesFromEntries = firstNode?.routeReplicates?.receivesFrom ??
1727
+ (authorization?.replicates && typeof authorization.replicates === 'object'
1728
+ ? authorization.replicates.receivesFrom
1729
+ : undefined);
1730
+ receiveExcludedTables =
1731
+ (0, knownNodes_ts_1.getExcludedTablesForRouteEntries)(receivesFromEntries, remoteNodeName, databaseName) ?? null;
1732
+ }
1733
+ if (tableDecoder && receiveExcludedTables?.has(tableDecoder.name)) {
1734
+ logger.trace?.(connectionId, 'dropping incoming replication for excluded table', databaseName + '.' + tableDecoder.name, 'from', remoteNodeName);
1735
+ decoder.position = start + eventLength;
1736
+ continue;
1737
+ }
1444
1738
  let residencyList;
1445
1739
  if (auditRecord.residencyId) {
1446
1740
  residencyList = receivedResidencyLists[auditRecord.residencyId];
@@ -1448,6 +1742,7 @@ function replicateOverWS(ws, options, authorization) {
1448
1742
  }
1449
1743
  const id = auditRecord.recordId;
1450
1744
  event = undefined; // reset before each decode attempt
1745
+ let receivedBlobs;
1451
1746
  try {
1452
1747
  (0, blob_ts_1.decodeBlobsWithWrites)(() => {
1453
1748
  event = {
@@ -1463,14 +1758,30 @@ function replicateOverWS(ws, options, authorization) {
1463
1758
  beginTxn,
1464
1759
  expiresAt: auditRecord.expiresAt,
1465
1760
  };
1466
- }, auditStore?.rootStore, (blob) => receiveBlobs(blob, id));
1761
+ }, auditStore?.rootStore, (blob) => {
1762
+ const localBlob = receiveBlobs(blob, id);
1763
+ (receivedBlobs ??= []).push(localBlob);
1764
+ return localBlob;
1765
+ });
1467
1766
  }
1468
1767
  catch (error) {
1469
1768
  logger.error?.('Error decoding replication message, record id: ' + id, ' typed structures for current decoder' + JSON.stringify(tableDecoder.decoder.typedStructs), ' structures for current decoder' + JSON.stringify(tableDecoder.decoder.structures), 'encoded message', auditRecord.encoded.subarray(0, 1000), auditRecord, error);
1470
1769
  }
1471
- replicationSharedStatus[exports.RECEIVED_VERSION_POSITION] = Math.max(
1472
- // ensure monotonicity
1473
- auditRecord.version, replicationSharedStatus[exports.RECEIVED_VERSION_POSITION]);
1770
+ if (!event && receivedBlobs) {
1771
+ // decode failed mid-message; the blobs that were already accepted will never be referenced. Give in-flight reads
1772
+ // a window to complete, then unlink the files. (mirrors the pattern at the relocate path above.)
1773
+ setTimeout(() => receivedBlobs.forEach(blob_ts_1.deleteBlob), 60000).unref();
1774
+ }
1775
+ // During a bulk copy, do NOT advance the received-version watermark per copied record:
1776
+ // records arrive in primary-key order carrying their original (possibly newest) versions, so a
1777
+ // single record at the leader's latest timestamp would otherwise let checkSyncStatus mark the
1778
+ // clone Available with rows still uncopied. The watermark is advanced to copyStartTime by the
1779
+ // single end_txn after the whole copy (the REMOTE_SEQUENCE_UPDATE branch above).
1780
+ if (!inCopyMode) {
1781
+ replicationSharedStatus[exports.RECEIVED_VERSION_POSITION] = Math.max(
1782
+ // ensure monotonicity
1783
+ auditRecord.version, replicationSharedStatus[exports.RECEIVED_VERSION_POSITION]);
1784
+ }
1474
1785
  replicationSharedStatus[exports.RECEIVED_TIME_POSITION] = Date.now();
1475
1786
  replicationSharedStatus[exports.RECEIVING_STATUS_POSITION] = exports.RECEIVING_STATUS_RECEIVING;
1476
1787
  if (event) {
@@ -1491,6 +1802,14 @@ function replicateOverWS(ws, options, authorization) {
1491
1802
  finally {
1492
1803
  removePauseReason();
1493
1804
  }
1805
+ lastYieldTime = performance.now();
1806
+ }
1807
+ else if (performance.now() - lastYieldTime >= RECEIVE_YIELD_INTERVAL) {
1808
+ // The high-water-mark pause only fires under heap pressure. When the consumer keeps
1809
+ // up, yield on a time budget anyway so a large message doesn't decode in one
1810
+ // synchronous turn and stall ping responses (see RECEIVE_YIELD_INTERVAL).
1811
+ await new Promise(setImmediate);
1812
+ lastYieldTime = performance.now();
1494
1813
  }
1495
1814
  }
1496
1815
  decoder.position = start + eventLength;
@@ -1504,6 +1823,9 @@ function replicateOverWS(ws, options, authorization) {
1504
1823
  addPauseReason();
1505
1824
  logger.debug?.(`Commit backlog causing replication back-pressure, requesting that ${remoteNodeName} pause replication`);
1506
1825
  }
1826
+ // Is this a bulk-copy frame? Only frames received before COPY_COMPLETE are part of the
1827
+ // primary-key copy; later audit-replay frames must not be recorded as the resume cursor.
1828
+ const isCopyFrame = inCopyMode && !copyCompleteReceived;
1507
1829
  tableSubscriptionToReplicator.send({
1508
1830
  type: 'end_txn',
1509
1831
  localTime: lastSequenceIdReceived,
@@ -1526,6 +1848,18 @@ function replicateOverWS(ws, options, authorization) {
1526
1848
  if (outstandingBlobsToFinish.length > 0)
1527
1849
  await Promise.all(outstandingBlobsToFinish);
1528
1850
  logger.trace?.('All blobs finished');
1851
+ // Persist/clear the resume cursor only AFTER this batch's blobs are durable too. The cursor
1852
+ // means "fully copied through this key"; advancing it before blob writes finish would let a
1853
+ // crash skip re-requesting an unfinished blob, leaving the record pointing at missing data.
1854
+ if (isCopyFrame && event && copyFromNodeId !== undefined) {
1855
+ tableSubscriptionToReplicator?.dbisDB?.put([Symbol.for('copyCursor'), copyFromNodeId], {
1856
+ copyStartTime: copyModeStartTime,
1857
+ currentTable: event.table,
1858
+ afterKey: event.id,
1859
+ });
1860
+ }
1861
+ // once the last copied batch (incl. its blobs) is durable, it's safe to drop the cursor
1862
+ maybeFinishCopy();
1529
1863
  if (!lastSequenceIdCommitted && sequenceIdReceived) {
1530
1864
  logger.trace?.(connectionId, 'queuing confirmation of a commit at', sequenceIdReceived);
1531
1865
  setTimeout(() => {
@@ -1546,6 +1880,7 @@ function replicateOverWS(ws, options, authorization) {
1546
1880
  }
1547
1881
  }
1548
1882
  ws.on('ping', resetPingTimer);
1883
+ ws.on('pong', resetPingTimer);
1549
1884
  ws.on('pong', () => {
1550
1885
  if (options.connection) {
1551
1886
  // every pong we can use to update our connection information (and latency)
@@ -1570,7 +1905,7 @@ function replicateOverWS(ws, options, authorization) {
1570
1905
  // cleanup
1571
1906
  wsClosed = true;
1572
1907
  clearInterval(sendPingInterval);
1573
- clearTimeout(receivePingTimer);
1908
+ receiveWatchdog?.stop();
1574
1909
  clearInterval(blobsTimer);
1575
1910
  if (auditSubscription)
1576
1911
  auditSubscription.emit('close');
@@ -1690,7 +2025,7 @@ function replicateOverWS(ws, options, authorization) {
1690
2025
  stream.recordId = id;
1691
2026
  if (remoteBlob.size === undefined && stream.expectedSize)
1692
2027
  remoteBlob.size = stream.expectedSize;
1693
- const localBlob = stream.blob ?? createBlob(stream, remoteBlob);
2028
+ const localBlob = stream.blob ?? (0, blob_ts_1.createBlob)(stream, remoteBlob);
1694
2029
  stream.blob = localBlob; // record the blob so we can reuse it if another request uses the same blob
1695
2030
  // start the save immediately. TODO: If we could add support for blobs to directly pass on a stream to the consumer
1696
2031
  // we would skip this
@@ -1798,14 +2133,16 @@ function replicateOverWS(ws, options, authorization) {
1798
2133
  const nodeSubscriptions = options.connection?.nodeSubscriptions.map((node) => {
1799
2134
  const tableSubs = [];
1800
2135
  let { replicateByDefault } = node;
2136
+ // Tables excluded by this node's receivesFrom config for this peer+database
2137
+ const receiverExcludedTables = (0, knownNodes_ts_1.getExcludedTablesForRouteEntries)(node.routeReplicates?.receivesFrom, node.name, databaseName);
1801
2138
  if (node.subscriptions) {
1802
2139
  // if the node has explicit subscriptions, we need to use that to determine subscriptions
1803
2140
  for (const subscription of node.subscriptions) {
1804
2141
  // if there is an explicit subscription listed
1805
2142
  if (subscription.subscribe && (subscription.schema || subscription.database) === databaseName) {
1806
2143
  const tableName = subscription.table;
1807
- if (tables?.[tableName]?.replicate !== false)
1808
- // if replication is enabled for this table
2144
+ if (tables?.[tableName]?.replicate !== false && !receiverExcludedTables?.has(tableName))
2145
+ // if replication is enabled for this table and not excluded
1809
2146
  tableSubs.push(tableName);
1810
2147
  }
1811
2148
  }
@@ -1814,14 +2151,22 @@ function replicateOverWS(ws, options, authorization) {
1814
2151
  else {
1815
2152
  // note that if replicateByDefault is enabled, we are listing the *excluded* tables
1816
2153
  for (const tableName in tables) {
1817
- if (replicateByDefault ? tables[tableName].replicate === false : tables[tableName].replicate) {
2154
+ if (replicateByDefault
2155
+ ? tables[tableName].replicate === false || receiverExcludedTables?.has(tableName)
2156
+ : tables[tableName].replicate && !receiverExcludedTables?.has(tableName)) {
1818
2157
  tableSubs.push(tableName);
1819
2158
  }
1820
2159
  }
1821
2160
  }
1822
2161
  const nodeId = auditStore && (0, nodeIdMapping_ts_1.getIdOfRemoteNode)(node.name, auditStore);
1823
- auditStore.ensureLogExists?.(node.name);
2162
+ auditStore?.ensureLogExists?.(node.name);
1824
2163
  const sequenceEntry = tableSubscriptionToReplicator?.dbisDB?.get([Symbol.for('seq'), nodeId]) ?? 1;
2164
+ // A persisted copy cursor means a bulk copy from this node was interrupted mid-stream. We must
2165
+ // resume that copy (not treat the persisted seqId as a normal start point — the un-copied table
2166
+ // data predates copyStartTime and would never be delivered by an audit-log resume).
2167
+ const copyCursor = nodeId === undefined
2168
+ ? undefined
2169
+ : tableSubscriptionToReplicator?.dbisDB?.get([Symbol.for('copyCursor'), nodeId]);
1825
2170
  // if we are connected directly to the node, we start from the last sequence number we received at the top level
1826
2171
  let startTime = Math.max(sequenceEntry?.seqId ?? 1, (typeof node.startTime === 'string' ? new Date(node.startTime).getTime() : node.startTime) ?? 1);
1827
2172
  logger.debug?.('Starting time recorded in db', node.name, nodeId, databaseName, sequenceEntry?.seqId, 'start time:', startTime, new Date(startTime));
@@ -1859,6 +2204,16 @@ function replicateOverWS(ws, options, authorization) {
1859
2204
  startTime = Date.now() - 60000;
1860
2205
  }
1861
2206
  }
2207
+ let copyResume;
2208
+ if (copyCursor) {
2209
+ startTime = 0; // request a copy; the cursor tells the leader where to resume
2210
+ copyResume = {
2211
+ copyStartTime: copyCursor.copyStartTime,
2212
+ currentTable: copyCursor.currentTable,
2213
+ afterKey: copyCursor.afterKey,
2214
+ };
2215
+ logger.warn?.(`Resuming interrupted copy of database ${databaseName} from ${(0, knownNodes_ts_1.getNodeURL)(node)} at table ${copyCursor.currentTable}`);
2216
+ }
1862
2217
  logger.trace?.(connectionId, 'defining subscription request', node.name, databaseName, new Date(startTime));
1863
2218
  return {
1864
2219
  name: node.name,
@@ -1867,6 +2222,7 @@ function replicateOverWS(ws, options, authorization) {
1867
2222
  startTime,
1868
2223
  isLeader: node.isLeader,
1869
2224
  endTime: node.endTime,
2225
+ copyResume, // present only when resuming an interrupted bulk copy
1870
2226
  };
1871
2227
  });
1872
2228
  let excluded;
@@ -1953,7 +2309,7 @@ function replicateOverWS(ws, options, authorization) {
1953
2309
  if (!thisNodeName)
1954
2310
  throw new Error('Node name not defined');
1955
2311
  else
1956
- throw new Error('Should not connect to self', thisNodeName);
2312
+ throw new Error('Should not connect to self: ' + thisNodeName);
1957
2313
  }
1958
2314
  sendNodeDBName(thisNodeName, databaseName);
1959
2315
  return true;