@joystick.js/db-canary 0.0.0-canary.2209

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 (354) hide show
  1. package/.build/getFilesToBuild.js +26 -0
  2. package/.build/getPlatformSafeFilePath.js +6 -0
  3. package/.build/getPlatformSafePath.js +6 -0
  4. package/.build/index.js +88 -0
  5. package/.build/isWindows.js +3 -0
  6. package/API_KEY +1 -0
  7. package/README.md +1821 -0
  8. package/data/data.mdb +0 -0
  9. package/data/lock.mdb +0 -0
  10. package/dist/client/database.js +1 -0
  11. package/dist/client/index.js +1 -0
  12. package/dist/server/cluster/index.js +1 -0
  13. package/dist/server/cluster/master.js +20 -0
  14. package/dist/server/cluster/worker.js +1 -0
  15. package/dist/server/index.js +1 -0
  16. package/dist/server/lib/api_key_manager.js +9 -0
  17. package/dist/server/lib/auth_manager.js +1 -0
  18. package/dist/server/lib/auto_index_manager.js +1 -0
  19. package/dist/server/lib/backup_manager.js +1 -0
  20. package/dist/server/lib/connection_manager.js +1 -0
  21. package/dist/server/lib/disk_utils.js +2 -0
  22. package/dist/server/lib/http_server.js +405 -0
  23. package/dist/server/lib/index_manager.js +1 -0
  24. package/dist/server/lib/load_settings.js +1 -0
  25. package/dist/server/lib/logger.js +1 -0
  26. package/dist/server/lib/op_types.js +1 -0
  27. package/dist/server/lib/operation_dispatcher.js +1 -0
  28. package/dist/server/lib/operations/admin.js +1 -0
  29. package/dist/server/lib/operations/bulk_write.js +1 -0
  30. package/dist/server/lib/operations/create_index.js +1 -0
  31. package/dist/server/lib/operations/delete_one.js +1 -0
  32. package/dist/server/lib/operations/drop_index.js +1 -0
  33. package/dist/server/lib/operations/find.js +1 -0
  34. package/dist/server/lib/operations/find_one.js +1 -0
  35. package/dist/server/lib/operations/get_indexes.js +1 -0
  36. package/dist/server/lib/operations/insert_one.js +1 -0
  37. package/dist/server/lib/operations/update_one.js +1 -0
  38. package/dist/server/lib/performance_monitor.js +1 -0
  39. package/dist/server/lib/query_engine.js +1 -0
  40. package/dist/server/lib/recovery_manager.js +1 -0
  41. package/dist/server/lib/replication_manager.js +1 -0
  42. package/dist/server/lib/safe_json_parse.js +1 -0
  43. package/dist/server/lib/send_response.js +1 -0
  44. package/dist/server/lib/tcp_protocol.js +1 -0
  45. package/dist/server/lib/write_forwarder.js +1 -0
  46. package/dist/server/lib/write_queue.js +1 -0
  47. package/increment_version.js +3 -0
  48. package/logs/.013e15b54597d05db4b4b53ecc37b10c92a72927-audit.json +20 -0
  49. package/logs/.02de550a67ea0f5961faa2dfd458a4d06f59ebd1-audit.json +20 -0
  50. package/logs/.03494ba24eb3c72214b4068a77d54b8993bee651-audit.json +20 -0
  51. package/logs/.06309ec60b339be1259a7993dd09c732f8907fbc-audit.json +20 -0
  52. package/logs/.0663a04dcfa17285661e5e1b8cfa51f41523b210-audit.json +20 -0
  53. package/logs/.0f06e6c4c9b824622729e13927587479e5060391-audit.json +20 -0
  54. package/logs/.16ccf58682ecb22b3e3ec63f0da1b7fe9be56528-audit.json +20 -0
  55. package/logs/.1fa1a5d02f496474b1ab473524c65c984146a9ad-audit.json +20 -0
  56. package/logs/.2223c0ae3bea6f0d62c62b1d319cc8634856abb7-audit.json +20 -0
  57. package/logs/.23dc79ffda3e083665e6f5993f59397adcbf4a46-audit.json +20 -0
  58. package/logs/.28104f49b03906b189eefd1cd462cb46c3c0af22-audit.json +20 -0
  59. package/logs/.29cdbf13808abe6a0ce70ee2f2efdd680ce3fd8e-audit.json +20 -0
  60. package/logs/.2a9889afd071f77f41f5170d08703a0afca866b7-audit.json +20 -0
  61. package/logs/.2acec3d1940a2bbed487528b703ee5948959a599-audit.json +20 -0
  62. package/logs/.2fb60ff326338c02bfedbcd0e936444e4a216750-audit.json +20 -0
  63. package/logs/.318fc7a19530d76a345f030f7cad00dda15300e7-audit.json +20 -0
  64. package/logs/.3cf27043e19085f908cedc7701e6d013463208ee-audit.json +25 -0
  65. package/logs/.3d90d785415817fc443402843b7c95f8371adc9b-audit.json +20 -0
  66. package/logs/.4074bca620375f72966fc52dfd439577727671e5-audit.json +20 -0
  67. package/logs/.40eecf018417ea80a70ea8ec7a3cc9406bc6334b-audit.json +20 -0
  68. package/logs/.50e974f1ef7c365fca6a1251b2e2c2252914cb5e-audit.json +20 -0
  69. package/logs/.52cb7d9e4223cf26ba36006ac26b949a97c7923c-audit.json +20 -0
  70. package/logs/.54befcdb84c15aad980705a31bcc9f555c3577ab-audit.json +20 -0
  71. package/logs/.57dfb70e22eddb84db2e3c0ceeefac5c0b9baffa-audit.json +20 -0
  72. package/logs/.5f0b24705a1eaad4eca4968f2d86f91b3f9be683-audit.json +20 -0
  73. package/logs/.61ba98fdda7db58576b382fee07904e5db1169d6-audit.json +20 -0
  74. package/logs/.6235017727ef6b199d569a99d6aa8c8e80a1b475-audit.json +20 -0
  75. package/logs/.63db16193699219489d218a1ddea5dde3750cae4-audit.json +20 -0
  76. package/logs/.64fb67dfe14149c9eef728d79bf30a54da809c60-audit.json +20 -0
  77. package/logs/.669137453368987c1f311b5345342527afb54e50-audit.json +20 -0
  78. package/logs/.7a71f8c89ea28ae266d356aeff6306e876a30fbb-audit.json +20 -0
  79. package/logs/.7afbaa90fe9dc3a7d682676f9bb79f9a1b1fd9a6-audit.json +20 -0
  80. package/logs/.7ca29e322cd05327035de850099e7610864f2347-audit.json +20 -0
  81. package/logs/.83335ab3347e449dae03455a110aaf7f120d4802-audit.json +20 -0
  82. package/logs/.8c2487b5fd445d2c8e5c483c80b9fa99bbf1ca58-audit.json +20 -0
  83. package/logs/.8c8b9dc386922c9f3b4c13251af7052aac1d24c0-audit.json +20 -0
  84. package/logs/.8d6155d94640c4863301ae0fee5e4e7372a21446-audit.json +20 -0
  85. package/logs/.944a3119a243deea7c8270d5d9e582bb1d0eaa10-audit.json +20 -0
  86. package/logs/.9816a845c30fb2909f3b26a23eeb3538ebcad5db-audit.json +20 -0
  87. package/logs/.9dc08784e38b865488177c26d4af5934555e0323-audit.json +20 -0
  88. package/logs/.9dd27d2e0e454ac0a37600206d1cac5493b0d7ee-audit.json +20 -0
  89. package/logs/.a3d486feeac7654c59b547de96600e8849a06d4f-audit.json +20 -0
  90. package/logs/.a5b811f4def22250f86cc18870d7c4573625df22-audit.json +20 -0
  91. package/logs/.a61648eb5f830e0b6f508ac35e4f8f629d2ad4c7-audit.json +20 -0
  92. package/logs/.a89016d507045771b4b5a65656944a9c0f1e528b-audit.json +20 -0
  93. package/logs/.a99bee160a1c590be959af46bacc02724803f691-audit.json +20 -0
  94. package/logs/.ada7906d6243fd7da802f03d86c4ae5dd9df6236-audit.json +20 -0
  95. package/logs/.b518339ee942143b6af983af167f5bbb6983b4de-audit.json +20 -0
  96. package/logs/.b51b124b166d53c9519017856ea610d61d65fabe-audit.json +20 -0
  97. package/logs/.b7a6aee19f58e55633d5e4a3709041c47dfff975-audit.json +20 -0
  98. package/logs/.bd7a8a6ba9c55d557a4867ab53f02e3ec2e1553d-audit.json +20 -0
  99. package/logs/.c1435dafe453b169d6392b25065f3cf4ab6fbb21-audit.json +20 -0
  100. package/logs/.c17e1ce043109f77dc2f0e2aa290a9d1ed842c03-audit.json +20 -0
  101. package/logs/.ca62637ce9540e5a38a2fbedb2115febb6ad308a-audit.json +15 -0
  102. package/logs/.ccee67b9c176967f8977071409a41f5cb5cd6ad4-audit.json +20 -0
  103. package/logs/.db24043417ea79a6f14cd947476399e53930b48d-audit.json +20 -0
  104. package/logs/.e0f12acccb57829f5f33712bb2e2607ecd808147-audit.json +20 -0
  105. package/logs/.e9b6cc33d0bbd2e644c4e2bf44d177f850016557-audit.json +20 -0
  106. package/logs/.f15291d434808e3bdca7963ccd2e73893be027e6-audit.json +20 -0
  107. package/logs/.f4bdf9e21ef84f8a3fae3ffb32bbc39275991351-audit.json +15 -0
  108. package/logs/.fbac3aefac1e81b4230df5aa50667cb90d51024f-audit.json +20 -0
  109. package/logs/.fcfd495c0a9169db243f4a4f21878ee02b76413c-audit.json +20 -0
  110. package/logs/admin-2025-09-12.log +580 -0
  111. package/logs/admin-2025-09-15.log +283 -0
  112. package/logs/admin-error-2025-09-12.log +22 -0
  113. package/logs/admin-error-2025-09-15.log +10 -0
  114. package/logs/api_key_manager-2025-09-12.log +658 -0
  115. package/logs/api_key_manager-2025-09-15.log +295 -0
  116. package/logs/api_key_manager-error-2025-09-12.log +0 -0
  117. package/logs/api_key_manager-error-2025-09-15.log +0 -0
  118. package/logs/auth_manager-2025-09-12.log +4432 -0
  119. package/logs/auth_manager-2025-09-15.log +2000 -0
  120. package/logs/auth_manager-error-2025-09-12.log +11 -0
  121. package/logs/auth_manager-error-2025-09-15.log +5 -0
  122. package/logs/auto_index_manager-2025-09-12.log +84 -0
  123. package/logs/auto_index_manager-2025-09-15.log +45 -0
  124. package/logs/auto_index_manager-error-2025-09-12.log +6 -0
  125. package/logs/auto_index_manager-error-2025-09-15.log +0 -0
  126. package/logs/backup_manager-2025-09-12.log +198 -0
  127. package/logs/backup_manager-2025-09-15.log +90 -0
  128. package/logs/backup_manager-error-2025-09-12.log +198 -0
  129. package/logs/backup_manager-error-2025-09-15.log +90 -0
  130. package/logs/bulk_write-2025-09-12.log +66 -0
  131. package/logs/bulk_write-2025-09-15.log +38 -0
  132. package/logs/bulk_write-error-2025-09-12.log +0 -0
  133. package/logs/bulk_write-error-2025-09-15.log +0 -0
  134. package/logs/connection_manager-2025-09-12.log +2412 -0
  135. package/logs/connection_manager-2025-09-15.log +1132 -0
  136. package/logs/connection_manager-error-2025-09-12.log +0 -0
  137. package/logs/connection_manager-error-2025-09-15.log +0 -0
  138. package/logs/create_index-2025-09-12.log +302 -0
  139. package/logs/create_index-2025-09-15.log +158 -0
  140. package/logs/create_index-error-2025-09-12.log +30 -0
  141. package/logs/create_index-error-2025-09-15.log +13 -0
  142. package/logs/delete_one-2025-09-12.log +73 -0
  143. package/logs/delete_one-2025-09-15.log +43 -0
  144. package/logs/delete_one-error-2025-09-12.log +0 -0
  145. package/logs/delete_one-error-2025-09-15.log +0 -0
  146. package/logs/disk_utils-2025-09-12.log +4954 -0
  147. package/logs/disk_utils-2025-09-15.log +2446 -0
  148. package/logs/disk_utils-error-2025-09-12.log +0 -0
  149. package/logs/disk_utils-error-2025-09-15.log +0 -0
  150. package/logs/drop_index-2025-09-12.log +41 -0
  151. package/logs/drop_index-2025-09-15.log +23 -0
  152. package/logs/drop_index-error-2025-09-12.log +11 -0
  153. package/logs/drop_index-error-2025-09-15.log +5 -0
  154. package/logs/find-2025-09-12.log +1050 -0
  155. package/logs/find-2025-09-15.log +592 -0
  156. package/logs/find-error-2025-09-12.log +1 -0
  157. package/logs/find-error-2025-09-15.log +0 -0
  158. package/logs/find_one-2025-09-12.log +425 -0
  159. package/logs/find_one-2025-09-15.log +264 -0
  160. package/logs/find_one-error-2025-09-12.log +5 -0
  161. package/logs/find_one-error-2025-09-15.log +0 -0
  162. package/logs/get_indexes-2025-09-12.log +84 -0
  163. package/logs/get_indexes-2025-09-15.log +56 -0
  164. package/logs/get_indexes-error-2025-09-12.log +6 -0
  165. package/logs/get_indexes-error-2025-09-15.log +0 -0
  166. package/logs/http_server-2025-09-12.log +2772 -0
  167. package/logs/http_server-2025-09-15.log +1276 -0
  168. package/logs/http_server-error-2025-09-12.log +212 -0
  169. package/logs/http_server-error-2025-09-15.log +44 -0
  170. package/logs/index_manager-2025-09-12.log +5031 -0
  171. package/logs/index_manager-2025-09-15.log +2909 -0
  172. package/logs/index_manager-error-2025-09-12.log +80 -0
  173. package/logs/index_manager-error-2025-09-15.log +38 -0
  174. package/logs/insert_one-2025-09-12.log +2181 -0
  175. package/logs/insert_one-2025-09-15.log +1293 -0
  176. package/logs/insert_one-error-2025-09-12.log +0 -0
  177. package/logs/insert_one-error-2025-09-15.log +0 -0
  178. package/logs/master-2025-09-12.log +1882 -0
  179. package/logs/master-2025-09-15.log +910 -0
  180. package/logs/master-error-2025-09-12.log +80 -0
  181. package/logs/master-error-2025-09-15.log +0 -0
  182. package/logs/operation_dispatcher-2025-09-12.log +751 -0
  183. package/logs/operation_dispatcher-2025-09-15.log +359 -0
  184. package/logs/operation_dispatcher-error-2025-09-12.log +33 -0
  185. package/logs/operation_dispatcher-error-2025-09-15.log +11 -0
  186. package/logs/performance_monitor-2025-09-12.log +14889 -0
  187. package/logs/performance_monitor-2025-09-15.log +6803 -0
  188. package/logs/performance_monitor-error-2025-09-12.log +0 -0
  189. package/logs/performance_monitor-error-2025-09-15.log +0 -0
  190. package/logs/query_engine-2025-09-12.log +5310 -0
  191. package/logs/query_engine-2025-09-15.log +2639 -0
  192. package/logs/query_engine-error-2025-09-12.log +0 -0
  193. package/logs/query_engine-error-2025-09-15.log +0 -0
  194. package/logs/recovery_manager-2025-09-12.log +462 -0
  195. package/logs/recovery_manager-2025-09-15.log +210 -0
  196. package/logs/recovery_manager-error-2025-09-12.log +22 -0
  197. package/logs/recovery_manager-error-2025-09-15.log +10 -0
  198. package/logs/replication-2025-09-12.log +1923 -0
  199. package/logs/replication-2025-09-15.log +917 -0
  200. package/logs/replication-error-2025-09-12.log +33 -0
  201. package/logs/replication-error-2025-09-15.log +15 -0
  202. package/logs/server-2025-09-12.log +2601 -0
  203. package/logs/server-2025-09-15.log +1191 -0
  204. package/logs/server-error-2025-09-12.log +0 -0
  205. package/logs/server-error-2025-09-15.log +0 -0
  206. package/logs/tcp_protocol-2025-09-12.log +22 -0
  207. package/logs/tcp_protocol-2025-09-15.log +10 -0
  208. package/logs/tcp_protocol-error-2025-09-12.log +22 -0
  209. package/logs/tcp_protocol-error-2025-09-15.log +10 -0
  210. package/logs/test-2025-09-12.log +0 -0
  211. package/logs/test-2025-09-15.log +0 -0
  212. package/logs/test-error-2025-09-12.log +0 -0
  213. package/logs/test-error-2025-09-15.log +0 -0
  214. package/logs/update_one-2025-09-12.log +173 -0
  215. package/logs/update_one-2025-09-15.log +118 -0
  216. package/logs/update_one-error-2025-09-12.log +0 -0
  217. package/logs/update_one-error-2025-09-15.log +0 -0
  218. package/logs/worker-2025-09-12.log +1457 -0
  219. package/logs/worker-2025-09-15.log +695 -0
  220. package/logs/worker-error-2025-09-12.log +0 -0
  221. package/logs/worker-error-2025-09-15.log +0 -0
  222. package/logs/write_forwarder-2025-09-12.log +1956 -0
  223. package/logs/write_forwarder-2025-09-15.log +932 -0
  224. package/logs/write_forwarder-error-2025-09-12.log +66 -0
  225. package/logs/write_forwarder-error-2025-09-15.log +30 -0
  226. package/logs/write_queue-2025-09-12.log +612 -0
  227. package/logs/write_queue-2025-09-15.log +301 -0
  228. package/logs/write_queue-error-2025-09-12.log +184 -0
  229. package/logs/write_queue-error-2025-09-15.log +83 -0
  230. package/package.json +48 -0
  231. package/prompts/01-core-infrastructure.md +56 -0
  232. package/prompts/02-secondary-indexing.md +65 -0
  233. package/prompts/03-write-serialization.md +63 -0
  234. package/prompts/04-enhanced-authentication.md +75 -0
  235. package/prompts/05-comprehensive-admin-operations.md +75 -0
  236. package/prompts/06-backup-and-restore-system.md +106 -0
  237. package/prompts/07-production-safety-features.md +107 -0
  238. package/prompts/08-tcp-client-library.md +121 -0
  239. package/prompts/09-api-method-chaining.md +134 -0
  240. package/prompts/10-automatic-index-creation.md +223 -0
  241. package/prompts/11-operation-naming-consistency.md +268 -0
  242. package/prompts/12-tcp-replication-system.md +333 -0
  243. package/prompts/13-master-read-write-operations.md +57 -0
  244. package/prompts/14-index-upsert-operations.md +68 -0
  245. package/prompts/15-client-api-return-types.md +81 -0
  246. package/prompts/16-server-setup-ui.md +97 -0
  247. package/prompts/17-emergency-password-change.md +108 -0
  248. package/prompts/18-joystick-framework-integration.md +116 -0
  249. package/prompts/19-api-key-authentication-system.md +137 -0
  250. package/prompts/20-configurable-server-port.md +105 -0
  251. package/prompts/21-multi-database-support.md +161 -0
  252. package/prompts/FULL_TEXT_SEARCH.md +293 -0
  253. package/prompts/PROMPTS.md +158 -0
  254. package/prompts/README.md +221 -0
  255. package/prompts/TYPESCRIPT_GENERATION.md +179 -0
  256. package/src/client/database.js +166 -0
  257. package/src/client/index.js +752 -0
  258. package/src/server/cluster/index.js +53 -0
  259. package/src/server/cluster/master.js +774 -0
  260. package/src/server/cluster/worker.js +537 -0
  261. package/src/server/index.js +540 -0
  262. package/src/server/lib/api_key_manager.js +473 -0
  263. package/src/server/lib/auth_manager.js +375 -0
  264. package/src/server/lib/auto_index_manager.js +681 -0
  265. package/src/server/lib/backup_manager.js +650 -0
  266. package/src/server/lib/connection_manager.js +218 -0
  267. package/src/server/lib/disk_utils.js +118 -0
  268. package/src/server/lib/http_server.js +1165 -0
  269. package/src/server/lib/index_manager.js +756 -0
  270. package/src/server/lib/load_settings.js +143 -0
  271. package/src/server/lib/logger.js +135 -0
  272. package/src/server/lib/op_types.js +29 -0
  273. package/src/server/lib/operation_dispatcher.js +268 -0
  274. package/src/server/lib/operations/admin.js +808 -0
  275. package/src/server/lib/operations/bulk_write.js +367 -0
  276. package/src/server/lib/operations/create_index.js +68 -0
  277. package/src/server/lib/operations/delete_one.js +114 -0
  278. package/src/server/lib/operations/drop_index.js +58 -0
  279. package/src/server/lib/operations/find.js +340 -0
  280. package/src/server/lib/operations/find_one.js +319 -0
  281. package/src/server/lib/operations/get_indexes.js +52 -0
  282. package/src/server/lib/operations/insert_one.js +113 -0
  283. package/src/server/lib/operations/update_one.js +225 -0
  284. package/src/server/lib/performance_monitor.js +313 -0
  285. package/src/server/lib/query_engine.js +243 -0
  286. package/src/server/lib/recovery_manager.js +388 -0
  287. package/src/server/lib/replication_manager.js +727 -0
  288. package/src/server/lib/safe_json_parse.js +21 -0
  289. package/src/server/lib/send_response.js +47 -0
  290. package/src/server/lib/tcp_protocol.js +130 -0
  291. package/src/server/lib/write_forwarder.js +636 -0
  292. package/src/server/lib/write_queue.js +335 -0
  293. package/test_data/data.mdb +0 -0
  294. package/test_data/lock.mdb +0 -0
  295. package/tests/client/index.test.js +1232 -0
  296. package/tests/server/cluster/cluster.test.js +248 -0
  297. package/tests/server/cluster/master_read_write_operations.test.js +577 -0
  298. package/tests/server/index.test.js +651 -0
  299. package/tests/server/integration/authentication_integration.test.js +294 -0
  300. package/tests/server/integration/auto_indexing_integration.test.js +268 -0
  301. package/tests/server/integration/backup_integration.test.js +513 -0
  302. package/tests/server/integration/indexing_integration.test.js +126 -0
  303. package/tests/server/integration/production_safety_integration.test.js +358 -0
  304. package/tests/server/integration/replication_integration.test.js +227 -0
  305. package/tests/server/integration/write_serialization_integration.test.js +246 -0
  306. package/tests/server/lib/api_key_manager.test.js +516 -0
  307. package/tests/server/lib/auth_manager.test.js +317 -0
  308. package/tests/server/lib/auto_index_manager.test.js +275 -0
  309. package/tests/server/lib/backup_manager.test.js +238 -0
  310. package/tests/server/lib/connection_manager.test.js +221 -0
  311. package/tests/server/lib/disk_utils.test.js +63 -0
  312. package/tests/server/lib/http_server.test.js +389 -0
  313. package/tests/server/lib/index_manager.test.js +301 -0
  314. package/tests/server/lib/load_settings.test.js +107 -0
  315. package/tests/server/lib/load_settings_port_config.test.js +243 -0
  316. package/tests/server/lib/logger.test.js +282 -0
  317. package/tests/server/lib/operations/admin.test.js +638 -0
  318. package/tests/server/lib/operations/bulk_write.test.js +128 -0
  319. package/tests/server/lib/operations/create_index.test.js +138 -0
  320. package/tests/server/lib/operations/delete_one.test.js +52 -0
  321. package/tests/server/lib/operations/drop_index.test.js +72 -0
  322. package/tests/server/lib/operations/find.test.js +93 -0
  323. package/tests/server/lib/operations/find_one.test.js +91 -0
  324. package/tests/server/lib/operations/get_indexes.test.js +87 -0
  325. package/tests/server/lib/operations/insert_one.test.js +42 -0
  326. package/tests/server/lib/operations/update_one.test.js +89 -0
  327. package/tests/server/lib/performance_monitor.test.js +185 -0
  328. package/tests/server/lib/query_engine.test.js +46 -0
  329. package/tests/server/lib/recovery_manager.test.js +414 -0
  330. package/tests/server/lib/replication_manager.test.js +202 -0
  331. package/tests/server/lib/safe_json_parse.test.js +45 -0
  332. package/tests/server/lib/send_response.test.js +155 -0
  333. package/tests/server/lib/tcp_protocol.test.js +169 -0
  334. package/tests/server/lib/write_forwarder.test.js +258 -0
  335. package/tests/server/lib/write_queue.test.js +255 -0
  336. package/tsconfig.json +30 -0
  337. package/types/client/index.d.ts +447 -0
  338. package/types/server/cluster/index.d.ts +28 -0
  339. package/types/server/cluster/master.d.ts +115 -0
  340. package/types/server/cluster/worker.d.ts +1 -0
  341. package/types/server/lib/auth_manager.d.ts +13 -0
  342. package/types/server/lib/backup_manager.d.ts +43 -0
  343. package/types/server/lib/connection_manager.d.ts +15 -0
  344. package/types/server/lib/disk_utils.d.ts +3 -0
  345. package/types/server/lib/index_manager.d.ts +24 -0
  346. package/types/server/lib/load_settings.d.ts +4 -0
  347. package/types/server/lib/logger.d.ts +44 -0
  348. package/types/server/lib/op_types.d.ts +6 -0
  349. package/types/server/lib/performance_monitor.d.ts +68 -0
  350. package/types/server/lib/query_engine.d.ts +10 -0
  351. package/types/server/lib/safe_json_parse.d.ts +7 -0
  352. package/types/server/lib/send_response.d.ts +3 -0
  353. package/types/server/lib/tcp_protocol.d.ts +12 -0
  354. package/types/server/lib/write_queue.d.ts +2 -0
@@ -0,0 +1,243 @@
1
+ /**
2
+ * @fileoverview Core database engine using LMDB for persistent storage with automatic map size management.
3
+ *
4
+ * Provides the foundational database layer for JoystickDB, handling LMDB initialization,
5
+ * document key generation, collection management, and automatic database growth.
6
+ * Integrates with index and auto-index managers for comprehensive data management.
7
+ */
8
+
9
+ import * as lmdb from 'lmdb';
10
+ import { rmSync, existsSync } from 'fs';
11
+ import create_logger from './logger.js';
12
+ import { calculate_map_size, get_disk_size, should_grow_map_size } from './disk_utils.js';
13
+ import { initialize_index_database, cleanup_index_database } from './index_manager.js';
14
+ import { initialize_auto_index_database, cleanup_auto_index_database } from './auto_index_manager.js';
15
+
16
+ const { create_context_logger } = create_logger('query_engine');
17
+
18
+ /** @type {lmdb.Database|null} Main LMDB database instance */
19
+ let db_instance = null;
20
+
21
+ /** @type {number|null} Current database map size in bytes */
22
+ let current_map_size = null;
23
+
24
+ /** @type {string|null} Path to database directory */
25
+ let database_path = null;
26
+
27
+ /**
28
+ * Initializes the LMDB database with automatic map size calculation and compression.
29
+ * Sets up the main database instance along with index and auto-index databases.
30
+ * @param {string} [db_path='./data'] - Path to database directory
31
+ * @returns {lmdb.Database} Initialized database instance
32
+ */
33
+ const initialize_database = (db_path = './data') => {
34
+ const log = create_context_logger();
35
+
36
+ if (!db_instance) {
37
+ database_path = db_path;
38
+
39
+ calculate_map_size(database_path).then((map_size) => {
40
+ current_map_size = map_size;
41
+
42
+ if (db_instance && db_instance.resize) {
43
+ db_instance.resize(current_map_size);
44
+
45
+ log.info('Database map_size updated', {
46
+ path: database_path,
47
+ map_size: current_map_size,
48
+ map_size_gb: Math.round(current_map_size / (1024 * 1024 * 1024) * 100) / 100
49
+ });
50
+ }
51
+ }).catch((error) => {
52
+ log.warn('Failed to calculate map_size, using default', {
53
+ database_path,
54
+ error: error.message
55
+ });
56
+ });
57
+
58
+ const default_map_size = 1024 * 1024 * 1024 * 10;
59
+ current_map_size = default_map_size;
60
+
61
+ db_instance = lmdb.open({
62
+ path: database_path,
63
+ compression: true,
64
+ useVersions: false,
65
+ encoding: 'msgpack',
66
+ mapSize: current_map_size
67
+ });
68
+
69
+ log.info('Database initialized', {
70
+ path: database_path,
71
+ map_size: current_map_size,
72
+ map_size_gb: Math.round(current_map_size / (1024 * 1024 * 1024) * 100) / 100
73
+ });
74
+
75
+ initialize_index_database();
76
+ initialize_auto_index_database();
77
+ }
78
+ return db_instance;
79
+ };
80
+
81
+ /**
82
+ * Checks database usage and automatically grows map size if needed.
83
+ * Monitors database statistics and disk space to determine optimal growth.
84
+ * @returns {Promise<void>}
85
+ */
86
+ const check_and_grow_map_size = async () => {
87
+ if (!db_instance || !database_path) {
88
+ return;
89
+ }
90
+
91
+ const log = create_context_logger();
92
+
93
+ try {
94
+ const stats = db_instance.getStats ? db_instance.getStats() : {};
95
+ const used_size = stats.ms_psize * stats.ms_leaf_pages || 0;
96
+
97
+ if (used_size === 0) {
98
+ return;
99
+ }
100
+
101
+ const disk_size = await get_disk_size(database_path);
102
+ const new_map_size = should_grow_map_size(current_map_size, used_size, disk_size);
103
+
104
+ if (new_map_size) {
105
+ log.info('Growing map_size', {
106
+ current_map_size,
107
+ new_map_size,
108
+ used_size,
109
+ usage_percentage: Math.round((used_size / current_map_size) * 100)
110
+ });
111
+
112
+ db_instance.resize(new_map_size);
113
+ current_map_size = new_map_size;
114
+
115
+ log.info('Map size grown successfully', {
116
+ new_map_size,
117
+ new_map_size_gb: Math.round(new_map_size / (1024 * 1024 * 1024) * 100) / 100
118
+ });
119
+ }
120
+ } catch (error) {
121
+ log.error('Failed to check/grow map_size', { error: error.message });
122
+ }
123
+ };
124
+
125
+ /**
126
+ * Gets the initialized database instance.
127
+ * @returns {lmdb.Database} Database instance
128
+ * @throws {Error} When database is not initialized
129
+ */
130
+ const get_database = () => {
131
+ if (!db_instance) {
132
+ throw new Error('Database not initialized. Call initialize_database first.');
133
+ }
134
+ return db_instance;
135
+ };
136
+
137
+ /**
138
+ * Generates a unique document ID using timestamp and random string.
139
+ * @returns {string} Unique document identifier
140
+ */
141
+ const generate_document_id = () => {
142
+ return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
143
+ };
144
+
145
+ /**
146
+ * Builds a database key for a document in a collection.
147
+ * @param {string} database_name - Name of the database
148
+ * @param {string} collection_name - Name of the collection
149
+ * @param {string} document_id - Document identifier
150
+ * @returns {string} Database key in format "database:collection:document_id"
151
+ */
152
+ const build_collection_key = (database_name, collection_name, document_id) => {
153
+ return `${database_name}:${collection_name}:${document_id}`;
154
+ };
155
+
156
+ /**
157
+ * Parses a database key to extract database name, collection name and document ID.
158
+ * @param {string} key - Database key in format "database:collection:document_id"
159
+ * @returns {Object} Parsed key components
160
+ * @returns {string} returns.database - Database name
161
+ * @returns {string} returns.collection - Collection name
162
+ * @returns {string} returns.document_id - Document identifier
163
+ */
164
+ const parse_collection_key = (key) => {
165
+ const parts = key.split(':');
166
+ return {
167
+ database: parts[0],
168
+ collection: parts[1],
169
+ document_id: parts.slice(2).join(':')
170
+ };
171
+ };
172
+
173
+ /**
174
+ * Cleanly shuts down the database and all associated resources.
175
+ * Closes index databases, auto-index databases, and the main database instance.
176
+ * @param {boolean} [remove_directory=false] - Whether to remove the database directory from disk
177
+ * @returns {Promise<void>}
178
+ */
179
+ const cleanup_database = async (remove_directory = false) => {
180
+ const log = create_context_logger();
181
+ const path_to_remove = database_path;
182
+
183
+ if (db_instance) {
184
+ try {
185
+ // Wait a bit to ensure all operations are complete
186
+ await new Promise(resolve => setTimeout(resolve, 100));
187
+
188
+ // Cleanup databases first
189
+ cleanup_auto_index_database();
190
+ cleanup_index_database();
191
+
192
+ // Close the main database
193
+ await db_instance.close();
194
+ log.info('Database closed successfully');
195
+ } catch (error) {
196
+ log.warn('Error closing database', { error: error.message });
197
+ }
198
+
199
+ // Reset all state
200
+ db_instance = null;
201
+ current_map_size = null;
202
+ database_path = null;
203
+ }
204
+
205
+ // Remove directory if requested and it's a test directory
206
+ if (remove_directory && path_to_remove && is_test_database_path(path_to_remove)) {
207
+ try {
208
+ if (existsSync(path_to_remove)) {
209
+ rmSync(path_to_remove, { recursive: true, force: true });
210
+ log.info('Test database directory removed', { path: path_to_remove });
211
+ }
212
+ } catch (error) {
213
+ log.warn('Failed to remove test database directory', {
214
+ path: path_to_remove,
215
+ error: error.message
216
+ });
217
+ }
218
+ }
219
+ };
220
+
221
+ /**
222
+ * Determines if a database path is a test database that can be safely removed.
223
+ * @param {string} path - Database path to check
224
+ * @returns {boolean} True if it's a test database path
225
+ */
226
+ const is_test_database_path = (path) => {
227
+ return path && (
228
+ path.includes('test_data') ||
229
+ path.startsWith('./test_') ||
230
+ path.startsWith('test_')
231
+ );
232
+ };
233
+
234
+ export {
235
+ initialize_database,
236
+ get_database,
237
+ generate_document_id,
238
+ build_collection_key,
239
+ parse_collection_key,
240
+ check_and_grow_map_size,
241
+ cleanup_database,
242
+ is_test_database_path
243
+ };
@@ -0,0 +1,388 @@
1
+ /**
2
+ * @fileoverview Emergency password recovery system for JoystickDB authentication.
3
+ * Provides secure token-based password recovery with rate limiting, expiration handling,
4
+ * and lockout protection. Enables emergency password changes when normal authentication
5
+ * is compromised or unavailable, with comprehensive security measures and audit logging.
6
+ */
7
+
8
+ import { readFileSync, writeFileSync, existsSync, unlinkSync } from 'fs';
9
+ import crypto from 'crypto';
10
+ import bcrypt from 'bcrypt';
11
+ import create_logger from './logger.js';
12
+
13
+ const { create_context_logger } = create_logger('recovery_manager');
14
+ const log = create_context_logger();
15
+
16
+ /** @type {string} Path to recovery token storage file */
17
+ const RECOVERY_TOKEN_FILE = './recovery_token.json';
18
+
19
+ import { load_settings as load_joystick_settings, get_settings as get_joystick_settings, has_settings } from './load_settings.js';
20
+
21
+ /** @type {number} Recovery token expiration time in minutes */
22
+ const TOKEN_EXPIRY_MINUTES = 10;
23
+
24
+ /** @type {number} Bcrypt salt rounds for password hashing */
25
+ const SALT_ROUNDS = 12;
26
+
27
+ /** @type {number} Maximum failed recovery attempts before lockout */
28
+ const MAX_RECOVERY_ATTEMPTS = 3;
29
+
30
+ /** @type {Object} Current recovery state tracking */
31
+ let recovery_state = {
32
+ token: null,
33
+ expires_at: null,
34
+ failed_attempts: 0,
35
+ locked_until: null
36
+ };
37
+
38
+ /**
39
+ * Generates a cryptographically secure recovery token.
40
+ * Uses Node.js crypto.randomUUID() for secure token generation.
41
+ * @returns {string} Secure UUID token for recovery authentication
42
+ */
43
+ const generate_recovery_token = () => {
44
+ return crypto.randomUUID();
45
+ };
46
+
47
+ /**
48
+ * Creates a new recovery token with expiration and saves it to file.
49
+ * Generates a secure token, sets expiration time, and stores recovery state
50
+ * both in memory and persistent storage with restricted file permissions.
51
+ * @returns {Object} Recovery token information
52
+ * @returns {string} returns.token - Generated recovery token
53
+ * @returns {number} returns.expires_at - Token expiration timestamp
54
+ * @returns {string} returns.url - Complete recovery URL with token
55
+ * @throws {Error} When token file cannot be saved
56
+ */
57
+ const create_recovery_token = () => {
58
+ const token = generate_recovery_token();
59
+ const expires_at = Date.now() + (TOKEN_EXPIRY_MINUTES * 60 * 1000);
60
+
61
+ recovery_state = {
62
+ token,
63
+ expires_at,
64
+ failed_attempts: 0,
65
+ locked_until: null
66
+ };
67
+
68
+ // NOTE: Store token temporarily in memory and file.
69
+ try {
70
+ writeFileSync(RECOVERY_TOKEN_FILE, JSON.stringify(recovery_state, null, 2), { mode: 0o600 });
71
+ log.info('Recovery token generated', { expires_at: new Date(expires_at).toISOString() });
72
+ } catch (error) {
73
+ log.error('Failed to save recovery token', { error: error.message });
74
+ throw new Error(`Failed to save recovery token: ${error.message}`);
75
+ }
76
+
77
+ return {
78
+ token,
79
+ expires_at,
80
+ url: `http://localhost:1984/recovery?token=${token}`
81
+ };
82
+ };
83
+
84
+ /**
85
+ * Loads recovery state from persistent storage file.
86
+ * Reads recovery token file and parses state, falling back to defaults
87
+ * if file doesn't exist or parsing fails. Handles corrupted state gracefully.
88
+ * @returns {void}
89
+ */
90
+ const load_recovery_state = () => {
91
+ try {
92
+ if (!existsSync(RECOVERY_TOKEN_FILE)) {
93
+ recovery_state = {
94
+ token: null,
95
+ expires_at: null,
96
+ failed_attempts: 0,
97
+ locked_until: null
98
+ };
99
+ return;
100
+ }
101
+
102
+ const raw_data = readFileSync(RECOVERY_TOKEN_FILE, 'utf8');
103
+ const parsed_data = JSON.parse(raw_data);
104
+
105
+ recovery_state = {
106
+ token: parsed_data.token || null,
107
+ expires_at: parsed_data.expires_at || null,
108
+ failed_attempts: parsed_data.failed_attempts || 0,
109
+ locked_until: parsed_data.locked_until || null
110
+ };
111
+
112
+ log.info('Recovery state loaded');
113
+ } catch (error) {
114
+ log.warn('Failed to load recovery state, using defaults', { error: error.message });
115
+ recovery_state = {
116
+ token: null,
117
+ expires_at: null,
118
+ failed_attempts: 0,
119
+ locked_until: null
120
+ };
121
+ }
122
+ };
123
+
124
+ /**
125
+ * Saves current recovery state to persistent storage file.
126
+ * Writes recovery state to file with restricted permissions for security.
127
+ * Logs errors but doesn't throw to avoid disrupting recovery operations.
128
+ * @returns {void}
129
+ */
130
+ const save_recovery_state = () => {
131
+ try {
132
+ writeFileSync(RECOVERY_TOKEN_FILE, JSON.stringify(recovery_state, null, 2), { mode: 0o600 });
133
+ } catch (error) {
134
+ log.error('Failed to save recovery state', { error: error.message });
135
+ }
136
+ };
137
+
138
+ /**
139
+ * Cleans up recovery token and resets state.
140
+ * Resets in-memory state and removes recovery token file from disk.
141
+ * Used after successful recovery or token expiration.
142
+ * @returns {void}
143
+ */
144
+ const cleanup_recovery_token = () => {
145
+ recovery_state = {
146
+ token: null,
147
+ expires_at: null,
148
+ failed_attempts: 0,
149
+ locked_until: null
150
+ };
151
+
152
+ try {
153
+ if (existsSync(RECOVERY_TOKEN_FILE)) {
154
+ unlinkSync(RECOVERY_TOKEN_FILE);
155
+ }
156
+ } catch (error) {
157
+ log.warn('Failed to cleanup recovery token file', { error: error.message });
158
+ }
159
+ };
160
+
161
+ /**
162
+ * Validates a provided recovery token against current state.
163
+ * Checks token existence, expiration, lockout status, and token match.
164
+ * Reloads state from file to ensure latest data and handles cleanup.
165
+ * @param {string} provided_token - Token to validate
166
+ * @returns {Object} Validation result
167
+ * @returns {boolean} returns.valid - Whether token is valid
168
+ * @returns {string} returns.reason - Reason for invalidity if applicable
169
+ */
170
+ const is_token_valid = (provided_token) => {
171
+ // NOTE: Always reload state from file to get latest data.
172
+ load_recovery_state();
173
+
174
+ const now = Date.now();
175
+
176
+ // NOTE: Check if recovery is locked due to too many failed attempts.
177
+ if (recovery_state.locked_until && now < recovery_state.locked_until) {
178
+ return { valid: false, reason: 'locked' };
179
+ }
180
+
181
+ // NOTE: Check if token exists and hasn't expired.
182
+ if (!recovery_state.token || !recovery_state.expires_at) {
183
+ return { valid: false, reason: 'no_token' };
184
+ }
185
+
186
+ if (now > recovery_state.expires_at) {
187
+ cleanup_recovery_token();
188
+ return { valid: false, reason: 'expired' };
189
+ }
190
+
191
+ if (provided_token !== recovery_state.token) {
192
+ return { valid: false, reason: 'invalid' };
193
+ }
194
+
195
+ return { valid: true };
196
+ };
197
+
198
+ /**
199
+ * Records a failed recovery attempt and applies lockout if needed.
200
+ * Increments failed attempt counter and locks recovery if maximum attempts
201
+ * are exceeded. Saves state to persistent storage and logs security events.
202
+ * @param {string} ip - IP address of failed attempt for audit logging
203
+ * @returns {void}
204
+ */
205
+ const record_failed_recovery_attempt = (ip) => {
206
+ recovery_state.failed_attempts += 1;
207
+
208
+ log.warn('Failed recovery attempt', {
209
+ ip,
210
+ attempt_count: recovery_state.failed_attempts
211
+ });
212
+
213
+ if (recovery_state.failed_attempts >= MAX_RECOVERY_ATTEMPTS) {
214
+ const lock_duration = 30 * 60 * 1000; // 30 minutes
215
+ recovery_state.locked_until = Date.now() + lock_duration;
216
+
217
+ log.warn('Recovery locked due to too many failed attempts', {
218
+ ip,
219
+ locked_until: new Date(recovery_state.locked_until).toISOString()
220
+ });
221
+ }
222
+
223
+ save_recovery_state();
224
+ };
225
+
226
+ /**
227
+ * Validates password strength requirements for recovery.
228
+ * Checks password existence, type, and minimum length requirements
229
+ * to ensure secure password policies are enforced.
230
+ * @param {string} password - Password to validate
231
+ * @returns {Object} Validation result
232
+ * @returns {boolean} returns.valid - Whether password meets requirements
233
+ * @returns {string} returns.message - Error message if validation fails
234
+ */
235
+ const validate_password_strength = (password) => {
236
+ if (!password || typeof password !== 'string') {
237
+ return { valid: false, message: 'Password is required' };
238
+ }
239
+
240
+ if (password.length < 12) {
241
+ return { valid: false, message: 'Password must be at least 12 characters long' };
242
+ }
243
+
244
+ return { valid: true };
245
+ };
246
+
247
+ /**
248
+ * Changes the database password through emergency recovery process.
249
+ * Validates password strength, hashes new password, updates settings file,
250
+ * terminates existing connections, and cleans up recovery state. Provides
251
+ * atomic updates with rollback protection and comprehensive audit logging.
252
+ * @param {string} new_password - New password to set
253
+ * @param {string} client_ip - IP address of recovery request for audit
254
+ * @param {Function|null} [connection_terminator=null] - Function to terminate active connections
255
+ * @returns {Promise<Object>} Password change result
256
+ * @returns {boolean} returns.success - Whether password change succeeded
257
+ * @returns {string} returns.timestamp - ISO timestamp of password change
258
+ * @returns {string} returns.message - Success message
259
+ * @throws {Error} When password validation fails or settings update fails
260
+ */
261
+ const change_password = async (new_password, client_ip, connection_terminator = null) => {
262
+ const validation = validate_password_strength(new_password);
263
+ if (!validation.valid) {
264
+ throw new Error(validation.message);
265
+ }
266
+
267
+ try {
268
+ // NOTE: Load current settings from environment variable.
269
+ if (!has_settings()) {
270
+ throw new Error('JOYSTICK_DB_SETTINGS environment variable not found');
271
+ }
272
+
273
+ const settings_data = load_joystick_settings();
274
+
275
+ if (!settings_data.authentication) {
276
+ throw new Error('Authentication not configured');
277
+ }
278
+
279
+ // NOTE: Hash new password.
280
+ const new_password_hash = await bcrypt.hash(new_password, SALT_ROUNDS);
281
+ const now = new Date().toISOString();
282
+
283
+ // NOTE: Update authentication section.
284
+ settings_data.authentication.password_hash = new_password_hash;
285
+ settings_data.authentication.last_updated = now;
286
+ settings_data.authentication.failed_attempts = {};
287
+ settings_data.authentication.rate_limits = {};
288
+
289
+ // NOTE: Update the environment variable with the new settings.
290
+ process.env.JOYSTICK_DB_SETTINGS = JSON.stringify(settings_data);
291
+
292
+ // NOTE: Terminate all existing connections if terminator function provided.
293
+ if (connection_terminator && typeof connection_terminator === 'function') {
294
+ try {
295
+ connection_terminator();
296
+ log.info('All existing connections terminated due to password change');
297
+ } catch (termination_error) {
298
+ log.warn('Failed to terminate some connections', { error: termination_error.message });
299
+ }
300
+ }
301
+
302
+ // NOTE: Cleanup recovery token after successful password change.
303
+ cleanup_recovery_token();
304
+
305
+ log.info('Emergency password change completed', {
306
+ client_ip,
307
+ timestamp: now
308
+ });
309
+
310
+ return {
311
+ success: true,
312
+ timestamp: now,
313
+ message: 'Password changed successfully'
314
+ };
315
+ } catch (error) {
316
+ log.error('Emergency password change failed', {
317
+ client_ip,
318
+ error: error.message
319
+ });
320
+ throw error;
321
+ }
322
+ };
323
+
324
+ /**
325
+ * Gets current recovery system status and state information.
326
+ * Returns comprehensive status including token validity, expiration,
327
+ * failed attempts, and lockout status for monitoring and debugging.
328
+ * @returns {Object} Recovery status information
329
+ * @returns {boolean} returns.token_active - Whether a valid token exists
330
+ * @returns {number|null} returns.expires_at - Token expiration timestamp
331
+ * @returns {number} returns.failed_attempts - Number of failed attempts
332
+ * @returns {number|null} returns.locked_until - Lockout expiration timestamp
333
+ * @returns {boolean} returns.is_locked - Whether recovery is currently locked
334
+ */
335
+ const get_recovery_status = () => {
336
+ const now = Date.now();
337
+
338
+ return {
339
+ token_active: !!(recovery_state.token && recovery_state.expires_at && now < recovery_state.expires_at),
340
+ expires_at: recovery_state.expires_at,
341
+ failed_attempts: recovery_state.failed_attempts,
342
+ locked_until: recovery_state.locked_until,
343
+ is_locked: !!(recovery_state.locked_until && now < recovery_state.locked_until)
344
+ };
345
+ };
346
+
347
+ /**
348
+ * Initializes the recovery manager and cleans up expired state.
349
+ * Loads recovery state from file, cleans up expired tokens and locks,
350
+ * and ensures the recovery system is in a consistent state on startup.
351
+ * @returns {void}
352
+ */
353
+ const initialize_recovery_manager = () => {
354
+ load_recovery_state();
355
+
356
+ // NOTE: Clean up expired tokens on startup.
357
+ const now = Date.now();
358
+ if (recovery_state.expires_at && now > recovery_state.expires_at) {
359
+ cleanup_recovery_token();
360
+ }
361
+
362
+ // NOTE: Clean up expired locks.
363
+ if (recovery_state.locked_until && now > recovery_state.locked_until) {
364
+ recovery_state.locked_until = null;
365
+ recovery_state.failed_attempts = 0;
366
+ save_recovery_state();
367
+ }
368
+ };
369
+
370
+ /**
371
+ * Resets all recovery state and cleans up tokens.
372
+ * Completely clears recovery state and removes token files.
373
+ * Used for administrative cleanup or system reset operations.
374
+ * @returns {void}
375
+ */
376
+ const reset_recovery_state = () => {
377
+ cleanup_recovery_token();
378
+ };
379
+
380
+ export {
381
+ create_recovery_token,
382
+ is_token_valid,
383
+ record_failed_recovery_attempt,
384
+ change_password,
385
+ get_recovery_status,
386
+ initialize_recovery_manager,
387
+ reset_recovery_state
388
+ };