@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,113 @@
1
+ /**
2
+ * @fileoverview Insert operation for adding single documents to collections with indexing and write queue support.
3
+ *
4
+ * Provides document insertion with automatic ID generation, timestamp management,
5
+ * duplicate prevention, index updates, and write queue serialization for consistency.
6
+ * Handles both internal and external insert operations with comprehensive error handling.
7
+ */
8
+
9
+ import { get_database, generate_document_id, build_collection_key } from '../query_engine.js';
10
+ import { update_indexes_on_insert } from '../index_manager.js';
11
+ import { get_write_queue } from '../write_queue.js';
12
+ import create_logger from '../logger.js';
13
+
14
+ const { create_context_logger } = create_logger('insert_one');
15
+
16
+ /**
17
+ * Internal implementation of insert_one operation without write queue serialization.
18
+ * @param {string} database_name - Name of the database
19
+ * @param {string} collection_name - Name of the collection
20
+ * @param {Object} document - Document to insert
21
+ * @param {Object} [options={}] - Insert options
22
+ * @returns {Promise<Object>} Insert result with acknowledged and inserted_id
23
+ * @throws {Error} When database/collection name is missing, document is invalid, or document already exists
24
+ */
25
+ const insert_one_internal = async (database_name, collection_name, document, options = {}) => {
26
+ const log = create_context_logger();
27
+
28
+ if (!database_name) {
29
+ throw new Error('Database name is required');
30
+ }
31
+
32
+ if (!collection_name) {
33
+ throw new Error('Collection name is required');
34
+ }
35
+
36
+ if (!document || typeof document !== 'object') {
37
+ throw new Error('Document must be a valid object');
38
+ }
39
+
40
+ const db = get_database();
41
+ const document_id = document._id || generate_document_id();
42
+ const collection_key = build_collection_key(database_name, collection_name, document_id);
43
+
44
+ const document_to_insert = {
45
+ ...document,
46
+ _id: document_id,
47
+ _created_at: new Date().toISOString(),
48
+ _updated_at: new Date().toISOString()
49
+ };
50
+
51
+ let inserted_document = null;
52
+
53
+ await db.transaction(() => {
54
+ const existing_document = db.get(collection_key);
55
+
56
+ if (existing_document) {
57
+ throw new Error(`Document with _id ${document_id} already exists`);
58
+ }
59
+
60
+ db.put(collection_key, JSON.stringify(document_to_insert));
61
+ inserted_document = document_to_insert;
62
+ });
63
+
64
+ await update_indexes_on_insert(database_name, collection_name, inserted_document);
65
+
66
+ log.info('Document inserted successfully', {
67
+ database: database_name,
68
+ collection: collection_name,
69
+ document_id: document_id
70
+ });
71
+
72
+ return {
73
+ acknowledged: true,
74
+ inserted_id: document_id
75
+ };
76
+ };
77
+
78
+ /**
79
+ * Inserts a single document into a collection with write queue serialization.
80
+ * @param {string} database_name - Name of the database
81
+ * @param {string} collection_name - Name of the collection
82
+ * @param {Object} document - Document to insert
83
+ * @param {Object} [options={}] - Insert options
84
+ * @returns {Promise<Object>} Insert result with acknowledged and inserted_id
85
+ * @throws {Error} When database/collection name is missing or document is invalid
86
+ */
87
+ const insert_one = async (database_name, collection_name, document, options = {}) => {
88
+ if (!database_name) {
89
+ throw new Error('Database name is required');
90
+ }
91
+
92
+ if (!collection_name) {
93
+ throw new Error('Collection name is required');
94
+ }
95
+
96
+ if (!document || typeof document !== 'object') {
97
+ throw new Error('Document must be a valid object');
98
+ }
99
+
100
+ const write_queue = get_write_queue();
101
+
102
+ return await write_queue.enqueue_write_operation(
103
+ () => insert_one_internal(database_name, collection_name, document, options),
104
+ {
105
+ operation: 'insert_one',
106
+ database: database_name,
107
+ collection: collection_name,
108
+ document_id: document._id || 'auto-generated'
109
+ }
110
+ );
111
+ };
112
+
113
+ export default insert_one;
@@ -0,0 +1,225 @@
1
+ import { get_database, build_collection_key, generate_document_id } from '../query_engine.js';
2
+ import { update_indexes_on_update, update_indexes_on_insert } from '../index_manager.js';
3
+ import { get_write_queue } from '../write_queue.js';
4
+ import create_logger from '../logger.js';
5
+
6
+ const { create_context_logger } = create_logger('update_one');
7
+
8
+ /**
9
+ * Applies MongoDB-style update operators to a document.
10
+ * @param {Object} document - Original document
11
+ * @param {Object} update_operations - Update operations ($set, $unset, $inc, $push, $pull)
12
+ * @returns {Object} Updated document
13
+ * @throws {Error} When unsupported update operator is used
14
+ */
15
+ const apply_update_operators = (document, update_operations) => {
16
+ const updated_document = { ...document };
17
+
18
+ for (const [operator, operations] of Object.entries(update_operations)) {
19
+ switch (operator) {
20
+ case '$set':
21
+ Object.assign(updated_document, operations);
22
+ break;
23
+
24
+ case '$unset':
25
+ for (const field of Object.keys(operations)) {
26
+ delete updated_document[field];
27
+ }
28
+ break;
29
+
30
+ case '$inc':
31
+ for (const [field, value] of Object.entries(operations)) {
32
+ updated_document[field] = (updated_document[field] || 0) + value;
33
+ }
34
+ break;
35
+
36
+ case '$push':
37
+ for (const [field, value] of Object.entries(operations)) {
38
+ if (!Array.isArray(updated_document[field])) {
39
+ updated_document[field] = [];
40
+ }
41
+ updated_document[field].push(value);
42
+ }
43
+ break;
44
+
45
+ case '$pull':
46
+ for (const [field, value] of Object.entries(operations)) {
47
+ if (Array.isArray(updated_document[field])) {
48
+ updated_document[field] = updated_document[field].filter(item => item !== value);
49
+ }
50
+ }
51
+ break;
52
+
53
+ default:
54
+ throw new Error(`Unsupported update operator: ${operator}`);
55
+ }
56
+ }
57
+
58
+ return updated_document;
59
+ };
60
+
61
+ /**
62
+ * Checks if a document matches the given filter criteria (simple equality check).
63
+ * @param {Object} document - Document to test
64
+ * @param {Object} filter - Filter criteria
65
+ * @returns {boolean} True if document matches filter
66
+ */
67
+ const matches_filter = (document, filter) => {
68
+ if (!filter || Object.keys(filter).length === 0) {
69
+ return true;
70
+ }
71
+
72
+ for (const [field, value] of Object.entries(filter)) {
73
+ if (document[field] !== value) {
74
+ return false;
75
+ }
76
+ }
77
+
78
+ return true;
79
+ };
80
+
81
+ /**
82
+ * Internal implementation of update_one operation without write queue serialization.
83
+ * @param {string} database_name - Name of the database
84
+ * @param {string} collection_name - Name of the collection
85
+ * @param {Object} filter - Filter criteria to match document
86
+ * @param {Object} update - Update operations to apply
87
+ * @param {Object} [options={}] - Update options
88
+ * @param {boolean} [options.upsert] - Create document if not found
89
+ * @returns {Promise<Object>} Update result with acknowledged, matched_count, modified_count, and optional upserted_id
90
+ * @throws {Error} When database name, collection name, filter, or update is invalid
91
+ */
92
+ const update_one_internal = async (database_name, collection_name, filter, update, options = {}) => {
93
+ const log = create_context_logger();
94
+
95
+ if (!database_name) {
96
+ throw new Error('Database name is required');
97
+ }
98
+
99
+ if (!collection_name) {
100
+ throw new Error('Collection name is required');
101
+ }
102
+
103
+ if (!filter || typeof filter !== 'object') {
104
+ throw new Error('Filter must be a valid object');
105
+ }
106
+
107
+ if (!update || typeof update !== 'object') {
108
+ throw new Error('Update must be a valid object');
109
+ }
110
+
111
+ const db = get_database();
112
+ let matched_count = 0;
113
+ let modified_count = 0;
114
+ let upserted_id = null;
115
+
116
+ let old_document = null;
117
+ let new_document = null;
118
+ let upserted_document = null;
119
+
120
+ await db.transaction(() => {
121
+ const collection_prefix = `${database_name}:${collection_name}:`;
122
+ let document_found = false;
123
+
124
+ const range = db.getRange({ start: collection_prefix, end: collection_prefix + '\xFF' });
125
+ for (const { key, value } of range) {
126
+ let document;
127
+ try {
128
+ document = JSON.parse(value);
129
+ } catch (parse_error) {
130
+ // Skip documents that can't be parsed
131
+ continue;
132
+ }
133
+
134
+ if (matches_filter(document, filter)) {
135
+ document_found = true;
136
+ matched_count = 1;
137
+
138
+ const updated_document = apply_update_operators(document, update);
139
+ updated_document._updated_at = new Date().toISOString();
140
+
141
+ if (JSON.stringify(document) !== JSON.stringify(updated_document)) {
142
+ db.put(key, JSON.stringify(updated_document));
143
+ old_document = document;
144
+ new_document = updated_document;
145
+ modified_count = 1;
146
+ }
147
+
148
+ break;
149
+ }
150
+ }
151
+
152
+ if (!document_found && options.upsert) {
153
+ const document_id = generate_document_id();
154
+ const collection_key = build_collection_key(database_name, collection_name, document_id);
155
+
156
+ const new_doc = {
157
+ ...filter,
158
+ _id: document_id,
159
+ _created_at: new Date().toISOString(),
160
+ _updated_at: new Date().toISOString()
161
+ };
162
+
163
+ upserted_document = apply_update_operators(new_doc, update);
164
+ db.put(collection_key, JSON.stringify(upserted_document));
165
+
166
+ upserted_id = document_id;
167
+ matched_count = 0;
168
+ modified_count = 0;
169
+ }
170
+ });
171
+
172
+ if (old_document && new_document) {
173
+ await update_indexes_on_update(database_name, collection_name, old_document, new_document);
174
+ }
175
+
176
+ if (upserted_document) {
177
+ await update_indexes_on_insert(database_name, collection_name, upserted_document);
178
+ }
179
+
180
+ log.info('Update operation completed', {
181
+ database: database_name,
182
+ collection: collection_name,
183
+ matched_count,
184
+ modified_count,
185
+ upserted_id
186
+ });
187
+
188
+ const result = {
189
+ acknowledged: true,
190
+ matched_count,
191
+ modified_count
192
+ };
193
+
194
+ if (upserted_id) {
195
+ result.upserted_id = upserted_id;
196
+ }
197
+
198
+ return result;
199
+ };
200
+
201
+ /**
202
+ * Updates a single document in a collection with write queue serialization.
203
+ * @param {string} database_name - Name of the database
204
+ * @param {string} collection_name - Name of the collection
205
+ * @param {Object} filter - Filter criteria to match document
206
+ * @param {Object} update - Update operations to apply
207
+ * @param {Object} [options={}] - Update options
208
+ * @param {boolean} [options.upsert] - Create document if not found
209
+ * @returns {Promise<Object>} Update result with acknowledged, matched_count, modified_count, and optional upserted_id
210
+ */
211
+ const update_one = async (database_name, collection_name, filter, update, options = {}) => {
212
+ const write_queue = get_write_queue();
213
+
214
+ return await write_queue.enqueue_write_operation(
215
+ () => update_one_internal(database_name, collection_name, filter, update, options),
216
+ {
217
+ operation: 'update_one',
218
+ database: database_name,
219
+ collection: collection_name,
220
+ filter_keys: Object.keys(filter || {})
221
+ }
222
+ );
223
+ };
224
+
225
+ export default update_one;
@@ -0,0 +1,313 @@
1
+ /**
2
+ * @fileoverview Performance monitoring system for JoystickDB server operations.
3
+ * Tracks operation metrics, response times, error rates, memory usage, database statistics,
4
+ * and system performance. Provides comprehensive monitoring and logging capabilities.
5
+ */
6
+
7
+ import create_logger from './logger.js';
8
+ import { get_database } from './query_engine.js';
9
+
10
+ const { create_context_logger } = create_logger('performance_monitor');
11
+
12
+ /**
13
+ * Performance monitoring class that tracks server operations and system metrics.
14
+ * Provides detailed statistics on operations, errors, response times, and resource usage.
15
+ */
16
+ class PerformanceMonitor {
17
+ /**
18
+ * Creates a new PerformanceMonitor instance.
19
+ * Initializes metrics tracking and logging capabilities.
20
+ */
21
+ constructor() {
22
+ this.log = create_context_logger();
23
+
24
+ /** @type {Object} Performance metrics storage */
25
+ this.metrics = {
26
+ operations: new Map(),
27
+ errors: new Map(),
28
+ response_times: [],
29
+ start_time: Date.now(),
30
+ total_requests: 0,
31
+ total_errors: 0
32
+ };
33
+
34
+ /** @type {number} Maximum number of response times to keep in memory */
35
+ this.max_response_times = 1000;
36
+ }
37
+
38
+ /**
39
+ * Tracks a database operation with timing and error information.
40
+ * @param {string} op_type - Type of operation (e.g., 'find', 'insert', 'update')
41
+ * @param {number} duration_ms - Operation duration in milliseconds
42
+ * @param {string} status - Operation status ('success' or 'error')
43
+ * @param {string|null} [error=null] - Error message if operation failed
44
+ * @param {Object} [metadata={}] - Additional metadata for logging
45
+ */
46
+ track_operation(op_type, duration_ms, status, error = null, metadata = {}) {
47
+ this.metrics.total_requests++;
48
+
49
+ // Track operation counts
50
+ if (!this.metrics.operations.has(op_type)) {
51
+ this.metrics.operations.set(op_type, { count: 0, total_time: 0, errors: 0 });
52
+ }
53
+
54
+ const op_stats = this.metrics.operations.get(op_type);
55
+ op_stats.count++;
56
+ op_stats.total_time += duration_ms;
57
+
58
+ if (status === 'error') {
59
+ this.metrics.total_errors++;
60
+ op_stats.errors++;
61
+
62
+ // Track error types
63
+ const error_key = error || 'unknown_error';
64
+ if (!this.metrics.errors.has(error_key)) {
65
+ this.metrics.errors.set(error_key, 0);
66
+ }
67
+ this.metrics.errors.set(error_key, this.metrics.errors.get(error_key) + 1);
68
+ }
69
+
70
+ // Track response times (keep only recent ones)
71
+ this.metrics.response_times.push({
72
+ timestamp: Date.now(),
73
+ duration_ms,
74
+ op_type,
75
+ status
76
+ });
77
+
78
+ if (this.metrics.response_times.length > this.max_response_times) {
79
+ this.metrics.response_times.shift();
80
+ }
81
+
82
+ // Log detailed operation info
83
+ this.log.info('Operation tracked', {
84
+ op: op_type,
85
+ duration_ms,
86
+ status,
87
+ error: error || undefined,
88
+ ...metadata
89
+ });
90
+ }
91
+
92
+ /**
93
+ * Gets comprehensive performance statistics including operation metrics and rates.
94
+ * @returns {Object} Performance statistics object
95
+ * @returns {number} returns.uptime_ms - Server uptime in milliseconds
96
+ * @returns {number} returns.uptime_seconds - Server uptime in seconds
97
+ * @returns {number} returns.total_requests - Total number of requests processed
98
+ * @returns {number} returns.total_errors - Total number of errors encountered
99
+ * @returns {number} returns.ops_per_second - Operations per second rate
100
+ * @returns {number} returns.avg_response_time_ms - Average response time in milliseconds
101
+ * @returns {number} returns.error_rate_percent - Error rate as percentage
102
+ * @returns {Object} returns.operations - Per-operation statistics breakdown
103
+ * @returns {Array} returns.top_errors - Top 10 most frequent errors
104
+ * @returns {number} returns.recent_response_times - Number of recent response times tracked
105
+ */
106
+ get_performance_stats() {
107
+ const now = Date.now();
108
+ const uptime_ms = now - this.metrics.start_time;
109
+ const uptime_seconds = uptime_ms / 1000;
110
+
111
+ // Calculate operations per second
112
+ const ops_per_second = uptime_seconds > 0 ? Math.round(this.metrics.total_requests / uptime_seconds) : 0;
113
+
114
+ // Calculate average response time
115
+ const recent_response_times = this.metrics.response_times
116
+ .filter(rt => now - rt.timestamp < 60000) // Last minute
117
+ .map(rt => rt.duration_ms);
118
+
119
+ const avg_response_time = recent_response_times.length > 0
120
+ ? Math.round(recent_response_times.reduce((sum, time) => sum + time, 0) / recent_response_times.length)
121
+ : 0;
122
+
123
+ // Calculate error rate
124
+ const error_rate = this.metrics.total_requests > 0
125
+ ? Math.round((this.metrics.total_errors / this.metrics.total_requests) * 100 * 100) / 100
126
+ : 0;
127
+
128
+ // Get operation breakdown
129
+ const operation_stats = {};
130
+ for (const [op_type, stats] of this.metrics.operations) {
131
+ operation_stats[op_type] = {
132
+ count: stats.count,
133
+ avg_duration_ms: stats.count > 0 ? Math.round(stats.total_time / stats.count) : 0,
134
+ error_count: stats.errors,
135
+ error_rate: stats.count > 0 ? Math.round((stats.errors / stats.count) * 100 * 100) / 100 : 0
136
+ };
137
+ }
138
+
139
+ // Get top errors
140
+ const top_errors = Array.from(this.metrics.errors.entries())
141
+ .sort((a, b) => b[1] - a[1])
142
+ .slice(0, 10)
143
+ .map(([error, count]) => ({ error, count }));
144
+
145
+ return {
146
+ uptime_ms,
147
+ uptime_seconds: Math.round(uptime_seconds),
148
+ total_requests: this.metrics.total_requests,
149
+ total_errors: this.metrics.total_errors,
150
+ ops_per_second,
151
+ avg_response_time_ms: avg_response_time,
152
+ error_rate_percent: error_rate,
153
+ operations: operation_stats,
154
+ top_errors,
155
+ recent_response_times: recent_response_times.length
156
+ };
157
+ }
158
+
159
+ /**
160
+ * Gets current Node.js process memory usage statistics.
161
+ * @returns {Object} Memory usage statistics
162
+ * @returns {number} returns.rss_mb - Resident Set Size in MB
163
+ * @returns {number} returns.heap_total_mb - Total heap size in MB
164
+ * @returns {number} returns.heap_used_mb - Used heap size in MB
165
+ * @returns {number} returns.heap_used_percent - Heap usage percentage
166
+ * @returns {number} returns.external_mb - External memory usage in MB
167
+ * @returns {number} returns.array_buffers_mb - ArrayBuffer memory usage in MB
168
+ */
169
+ get_memory_stats() {
170
+ const memory_usage = process.memoryUsage();
171
+
172
+ return {
173
+ rss_mb: Math.round(memory_usage.rss / 1024 / 1024),
174
+ heap_total_mb: Math.round(memory_usage.heapTotal / 1024 / 1024),
175
+ heap_used_mb: Math.round(memory_usage.heapUsed / 1024 / 1024),
176
+ heap_used_percent: Math.round((memory_usage.heapUsed / memory_usage.heapTotal) * 100),
177
+ external_mb: Math.round(memory_usage.external / 1024 / 1024),
178
+ array_buffers_mb: Math.round((memory_usage.arrayBuffers || 0) / 1024 / 1024)
179
+ };
180
+ }
181
+
182
+ /**
183
+ * Gets LMDB database statistics including storage usage and structure info.
184
+ * @returns {Object} Database statistics object
185
+ * @returns {number} returns.map_size_mb - Total database map size in MB
186
+ * @returns {number} returns.used_space_mb - Used database space in MB
187
+ * @returns {number} returns.usage_percent - Database usage percentage
188
+ * @returns {number} returns.page_size - Database page size in bytes
189
+ * @returns {number} returns.tree_depth - B-tree depth
190
+ * @returns {number} returns.entry_count - Total number of entries
191
+ * @returns {number} returns.branch_pages - Number of branch pages
192
+ * @returns {number} returns.leaf_pages - Number of leaf pages
193
+ */
194
+ get_database_stats() {
195
+ try {
196
+ const db = get_database();
197
+ const raw_stats = db.getStats ? db.getStats() : {};
198
+
199
+ const map_size_mb = Math.round((raw_stats.mapSize || 0) / 1024 / 1024);
200
+ const used_space_mb = Math.round(((raw_stats.lastPageNumber || 0) * (raw_stats.pageSize || 0)) / 1024 / 1024);
201
+ const usage_percent = map_size_mb > 0 ? Math.round((used_space_mb / map_size_mb) * 100) : 0;
202
+
203
+ return {
204
+ map_size_mb,
205
+ used_space_mb,
206
+ usage_percent,
207
+ page_size: raw_stats.pageSize || 0,
208
+ tree_depth: raw_stats.treeDepth || 0,
209
+ entry_count: raw_stats.entryCount || 0,
210
+ branch_pages: raw_stats.treeBranchPages || 0,
211
+ leaf_pages: raw_stats.treeLeafPages || 0
212
+ };
213
+ } catch (error) {
214
+ this.log.warn('Could not get database stats', { error: error.message });
215
+ return {
216
+ error: 'Database stats unavailable',
217
+ map_size_mb: 0,
218
+ used_space_mb: 0,
219
+ usage_percent: 0
220
+ };
221
+ }
222
+ }
223
+
224
+ /**
225
+ * Gets system and Node.js runtime statistics.
226
+ * @returns {Object} System statistics object
227
+ * @returns {string} returns.node_version - Node.js version
228
+ * @returns {string} returns.platform - Operating system platform
229
+ * @returns {string} returns.arch - CPU architecture
230
+ * @returns {number} returns.pid - Process ID
231
+ * @returns {number} returns.cpu_user_ms - CPU user time in milliseconds
232
+ * @returns {number} returns.cpu_system_ms - CPU system time in milliseconds
233
+ */
234
+ get_system_stats() {
235
+ const cpu_usage = process.cpuUsage();
236
+
237
+ return {
238
+ node_version: process.version,
239
+ platform: process.platform,
240
+ arch: process.arch,
241
+ pid: process.pid,
242
+ cpu_user_ms: Math.round(cpu_usage.user / 1000),
243
+ cpu_system_ms: Math.round(cpu_usage.system / 1000)
244
+ };
245
+ }
246
+
247
+ /**
248
+ * Logs a structured operation entry with detailed metrics and automatically tracks it.
249
+ * @param {string} client_id - Client identifier
250
+ * @param {string} op_type - Operation type
251
+ * @param {string|null} collection - Collection name (if applicable)
252
+ * @param {number} duration_ms - Operation duration in milliseconds
253
+ * @param {string} status - Operation status ('success' or 'error')
254
+ * @param {string|null} [error=null] - Error message if operation failed
255
+ * @param {number} [request_size=0] - Request size in bytes
256
+ * @param {number} [response_size=0] - Response size in bytes
257
+ */
258
+ log_structured_operation(client_id, op_type, collection, duration_ms, status, error = null, request_size = 0, response_size = 0) {
259
+ const log_entry = {
260
+ ts: new Date().toISOString(),
261
+ client_id,
262
+ op: op_type,
263
+ collection: collection || undefined,
264
+ duration_ms,
265
+ status,
266
+ error: error || undefined,
267
+ request_size: request_size || undefined,
268
+ response_size: response_size || undefined
269
+ };
270
+
271
+ // Remove undefined fields
272
+ Object.keys(log_entry).forEach(key => {
273
+ if (log_entry[key] === undefined) {
274
+ delete log_entry[key];
275
+ }
276
+ });
277
+
278
+ this.log.info('Structured operation log', log_entry);
279
+
280
+ // Track in performance metrics
281
+ this.track_operation(op_type, duration_ms, status, error, {
282
+ client_id,
283
+ collection,
284
+ request_size,
285
+ response_size
286
+ });
287
+ }
288
+
289
+ /**
290
+ * Resets all performance metrics to initial state.
291
+ * Preserves the start time as current time for accurate uptime calculation.
292
+ */
293
+ reset_metrics() {
294
+ this.metrics = {
295
+ operations: new Map(),
296
+ errors: new Map(),
297
+ response_times: [],
298
+ start_time: Date.now(),
299
+ total_requests: 0,
300
+ total_errors: 0
301
+ };
302
+
303
+ this.log.info('Performance metrics reset');
304
+ }
305
+ }
306
+
307
+ // Global instance
308
+ const performance_monitor = new PerformanceMonitor();
309
+
310
+ export {
311
+ performance_monitor,
312
+ PerformanceMonitor
313
+ };