@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,340 @@
1
+ /**
2
+ * @fileoverview Find operation implementation for JoystickDB with MongoDB-like query capabilities.
3
+ * Supports complex filtering, projection, sorting, pagination, and automatic index optimization.
4
+ * Includes comprehensive query operators, field path resolution, and performance monitoring.
5
+ */
6
+
7
+ import { get_database, build_collection_key } from '../query_engine.js';
8
+ import { can_use_index, find_documents_by_index } from '../index_manager.js';
9
+ import { record_query, record_index_usage } from '../auto_index_manager.js';
10
+ import create_logger from '../logger.js';
11
+
12
+ const { create_context_logger } = create_logger('find');
13
+
14
+ /**
15
+ * Extracts field value from document using dot notation path.
16
+ * @param {Object} document - Document to extract value from
17
+ * @param {string} field_path - Dot-separated field path (e.g., 'user.profile.name')
18
+ * @returns {*} Field value or undefined if path doesn't exist
19
+ */
20
+ const get_field_value = (document, field_path) => {
21
+ const parts = field_path.split('.');
22
+ let value = document;
23
+
24
+ for (const part of parts) {
25
+ if (value === null || value === undefined) {
26
+ return undefined;
27
+ }
28
+ value = value[part];
29
+ }
30
+
31
+ return value;
32
+ };
33
+
34
+ /**
35
+ * Checks if a field exists in a document using dot notation path.
36
+ * @param {Object} document - Document to check
37
+ * @param {string} field_path - Dot-separated field path
38
+ * @returns {boolean} True if field exists, false otherwise
39
+ */
40
+ const field_exists = (document, field_path) => {
41
+ const parts = field_path.split('.');
42
+ let current = document;
43
+
44
+ for (let i = 0; i < parts.length; i++) {
45
+ if (current === null || current === undefined || typeof current !== 'object') {
46
+ return false;
47
+ }
48
+
49
+ if (i === parts.length - 1) {
50
+ return current.hasOwnProperty(parts[i]);
51
+ }
52
+
53
+ current = current[parts[i]];
54
+ }
55
+
56
+ return false;
57
+ };
58
+
59
+ /**
60
+ * Checks if a document matches the provided filter criteria.
61
+ * Supports MongoDB-like query operators including $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin, $exists, $regex.
62
+ * @param {Object} document - Document to test against filter
63
+ * @param {Object} filter - Filter criteria with field names and values/operators
64
+ * @returns {boolean} True if document matches filter, false otherwise
65
+ * @throws {Error} When unsupported query operator is used
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
+ const field_value = get_field_value(document, field);
74
+
75
+ if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
76
+ for (const [operator, operand] of Object.entries(value)) {
77
+ switch (operator) {
78
+ case '$eq':
79
+ if (field_value !== operand) return false;
80
+ break;
81
+ case '$ne':
82
+ if (field_value === operand) return false;
83
+ break;
84
+ case '$gt':
85
+ if (field_value <= operand) return false;
86
+ break;
87
+ case '$gte':
88
+ if (field_value < operand) return false;
89
+ break;
90
+ case '$lt':
91
+ if (field_value >= operand) return false;
92
+ break;
93
+ case '$lte':
94
+ if (field_value > operand) return false;
95
+ break;
96
+ case '$in':
97
+ if (!Array.isArray(operand) || !operand.includes(field_value)) return false;
98
+ break;
99
+ case '$nin':
100
+ if (!Array.isArray(operand) || operand.includes(field_value)) return false;
101
+ break;
102
+ case '$exists':
103
+ const exists = field_exists(document, field);
104
+ if (operand && !exists) return false;
105
+ if (!operand && exists) return false;
106
+ break;
107
+ case '$regex':
108
+ const regex = new RegExp(operand);
109
+ if (!regex.test(field_value)) return false;
110
+ break;
111
+ default:
112
+ throw new Error(`Unsupported query operator: ${operator}`);
113
+ }
114
+ }
115
+ } else {
116
+ if (field_value !== value) return false;
117
+ }
118
+ }
119
+
120
+ return true;
121
+ };
122
+
123
+ /**
124
+ * Applies projection to a document, including or excluding specified fields.
125
+ * Supports both inclusion and exclusion projections with MongoDB-like syntax.
126
+ * @param {Object} document - Document to project
127
+ * @param {Object} projection - Projection specification with field names and 1/0 or true/false values
128
+ * @returns {Object} Projected document with only specified fields
129
+ */
130
+ const apply_projection = (document, projection) => {
131
+ if (!projection || Object.keys(projection).length === 0) {
132
+ return document;
133
+ }
134
+
135
+ const is_inclusion = Object.values(projection).some(value => value === 1 || value === true);
136
+ const projected_document = {};
137
+
138
+ if (is_inclusion) {
139
+ projected_document._id = document._id;
140
+
141
+ for (const [field, include] of Object.entries(projection)) {
142
+ if (field === '_id' && (include === 0 || include === false)) {
143
+ delete projected_document._id;
144
+ } else if (include === 1 || include === true) {
145
+ projected_document[field] = document[field];
146
+ }
147
+ }
148
+ } else {
149
+ Object.assign(projected_document, document);
150
+
151
+ for (const [field, exclude] of Object.entries(projection)) {
152
+ if (exclude === 0 || exclude === false) {
153
+ delete projected_document[field];
154
+ }
155
+ }
156
+ }
157
+
158
+ return projected_document;
159
+ };
160
+
161
+ /**
162
+ * Sorts an array of documents based on sort specification.
163
+ * Supports multi-field sorting with ascending (1) and descending (-1) directions.
164
+ * @param {Array<Object>} documents - Array of documents to sort
165
+ * @param {Object} sort - Sort specification with field names and 1/-1 direction values
166
+ * @returns {Array<Object>} Sorted array of documents
167
+ */
168
+ const apply_sort = (documents, sort) => {
169
+ if (!sort || Object.keys(sort).length === 0) {
170
+ return documents;
171
+ }
172
+
173
+ return documents.sort((a, b) => {
174
+ for (const [field, direction] of Object.entries(sort)) {
175
+ const a_value = a[field];
176
+ const b_value = b[field];
177
+
178
+ if (a_value === b_value) continue;
179
+
180
+ if (a_value === undefined) return 1;
181
+ if (b_value === undefined) return -1;
182
+
183
+ const comparison = a_value < b_value ? -1 : a_value > b_value ? 1 : 0;
184
+
185
+ if (direction === -1) {
186
+ return -comparison;
187
+ }
188
+
189
+ return comparison;
190
+ }
191
+
192
+ return 0;
193
+ });
194
+ };
195
+
196
+ /**
197
+ * Finds documents in a collection matching the specified filter criteria.
198
+ * Supports MongoDB-like querying with automatic index optimization, projection, sorting, and pagination.
199
+ * @param {string} database_name - Name of the database
200
+ * @param {string} collection_name - Name of the collection to search
201
+ * @param {Object} [filter={}] - Filter criteria for matching documents
202
+ * @param {Object} [options={}] - Query options
203
+ * @param {Object} [options.projection] - Fields to include/exclude in results
204
+ * @param {Object} [options.sort] - Sort specification for ordering results
205
+ * @param {number} [options.limit] - Maximum number of documents to return
206
+ * @param {number} [options.skip=0] - Number of documents to skip
207
+ * @returns {Promise<Array<Object>>} Promise resolving to array of matching documents
208
+ * @throws {Error} When database or collection name is missing or query execution fails
209
+ */
210
+ const find = async (database_name, collection_name, filter = {}, options = {}) => {
211
+ const log = create_context_logger();
212
+
213
+ if (!database_name) {
214
+ throw new Error('Database name is required');
215
+ }
216
+
217
+ if (!collection_name) {
218
+ throw new Error('Collection name is required');
219
+ }
220
+
221
+ const db = get_database();
222
+ const { projection, sort, limit, skip = 0 } = options;
223
+ const start_time = Date.now();
224
+
225
+ try {
226
+ let matching_documents = [];
227
+ let used_index = false;
228
+ let indexed_field = null;
229
+
230
+ const index_info = can_use_index(database_name, collection_name, filter);
231
+
232
+ if (index_info) {
233
+ const { field, operators } = index_info;
234
+ const field_filter = filter[field];
235
+ indexed_field = field;
236
+
237
+ if (typeof field_filter === 'object' && field_filter !== null && !Array.isArray(field_filter)) {
238
+ for (const operator of operators) {
239
+ if (field_filter[operator] !== undefined) {
240
+ const document_ids = find_documents_by_index(database_name, collection_name, field, operator, field_filter[operator]);
241
+
242
+ if (document_ids) {
243
+ used_index = true;
244
+ record_index_usage(database_name, collection_name, field);
245
+
246
+ for (const document_id of document_ids) {
247
+ const collection_key = build_collection_key(database_name, collection_name, document_id);
248
+ const document_data = db.get(collection_key);
249
+
250
+ if (document_data) {
251
+ const document = JSON.parse(document_data);
252
+ if (matches_filter(document, filter)) {
253
+ matching_documents.push(document);
254
+ }
255
+ }
256
+ }
257
+ break;
258
+ }
259
+ }
260
+ }
261
+ } else if (operators.includes('eq')) {
262
+ const document_ids = find_documents_by_index(database_name, collection_name, field, 'eq', field_filter);
263
+
264
+ if (document_ids) {
265
+ used_index = true;
266
+ record_index_usage(database_name, collection_name, field);
267
+
268
+ for (const document_id of document_ids) {
269
+ const collection_key = build_collection_key(database_name, collection_name, document_id);
270
+ const document_data = db.get(collection_key);
271
+
272
+ if (document_data) {
273
+ const document = JSON.parse(document_data);
274
+ if (matches_filter(document, filter)) {
275
+ matching_documents.push(document);
276
+ }
277
+ }
278
+ }
279
+ }
280
+ }
281
+ }
282
+
283
+ if (!used_index) {
284
+ const collection_prefix = `${database_name}:${collection_name}:`;
285
+ const range = db.getRange({ start: collection_prefix, end: collection_prefix + '\xFF' });
286
+
287
+ for (const { key, value: document_data } of range) {
288
+ const document = JSON.parse(document_data);
289
+ if (matches_filter(document, filter)) {
290
+ matching_documents.push(document);
291
+ }
292
+ }
293
+ }
294
+
295
+ let sorted_documents = apply_sort(matching_documents, sort);
296
+
297
+ if (skip > 0) {
298
+ sorted_documents = sorted_documents.slice(skip);
299
+ }
300
+
301
+ if (limit && limit > 0) {
302
+ sorted_documents = sorted_documents.slice(0, limit);
303
+ }
304
+
305
+ const projected_documents = sorted_documents.map(document =>
306
+ apply_projection(document, projection)
307
+ );
308
+
309
+ const execution_time = Date.now() - start_time;
310
+
311
+ try {
312
+ record_query(collection_name, filter, execution_time, used_index, indexed_field);
313
+ } catch (auto_index_error) {
314
+ log.warn('Failed to record query for auto-indexing', {
315
+ error: auto_index_error.message
316
+ });
317
+ }
318
+
319
+ log.info('Find operation completed', {
320
+ database: database_name,
321
+ collection: collection_name,
322
+ documents_found: projected_documents.length,
323
+ total_matching: matching_documents.length,
324
+ used_index,
325
+ indexed_field,
326
+ execution_time_ms: execution_time
327
+ });
328
+
329
+ return projected_documents;
330
+ } catch (error) {
331
+ log.error('Failed to find documents', {
332
+ database: database_name,
333
+ collection: collection_name,
334
+ error: error.message
335
+ });
336
+ throw error;
337
+ }
338
+ };
339
+
340
+ export default find;
@@ -0,0 +1,319 @@
1
+ /**
2
+ * @fileoverview Find one document operation with indexing, filtering, and projection support.
3
+ *
4
+ * Provides document retrieval with MongoDB-style query operators, index optimization,
5
+ * field projection, nested field access, and comprehensive query performance tracking.
6
+ * Supports both indexed and full collection scans with automatic query recording.
7
+ */
8
+
9
+ import { get_database, build_collection_key } from '../query_engine.js';
10
+ import { can_use_index, find_documents_by_index } from '../index_manager.js';
11
+ import { record_query, record_index_usage } from '../auto_index_manager.js';
12
+ import create_logger from '../logger.js';
13
+
14
+ const { create_context_logger } = create_logger('find_one');
15
+
16
+ /**
17
+ * Gets the value of a nested field from a document using dot notation.
18
+ * @param {Object} document - Document to extract field value from
19
+ * @param {string} field_path - Dot-separated field path (e.g., 'user.name')
20
+ * @returns {any} Field value or undefined if not found
21
+ */
22
+ const get_field_value = (document, field_path) => {
23
+ const parts = field_path.split('.');
24
+ let value = document;
25
+
26
+ for (const part of parts) {
27
+ if (value === null || value === undefined) {
28
+ return undefined;
29
+ }
30
+ value = value[part];
31
+ }
32
+
33
+ return value;
34
+ };
35
+
36
+ /**
37
+ * Checks if a nested field exists in a document using dot notation.
38
+ * @param {Object} document - Document to check
39
+ * @param {string} field_path - Dot-separated field path (e.g., 'user.name')
40
+ * @returns {boolean} True if field exists
41
+ */
42
+ const field_exists = (document, field_path) => {
43
+ const parts = field_path.split('.');
44
+ let current = document;
45
+
46
+ for (let i = 0; i < parts.length; i++) {
47
+ if (current === null || current === undefined || typeof current !== 'object') {
48
+ return false;
49
+ }
50
+
51
+ if (i === parts.length - 1) {
52
+ return current.hasOwnProperty(parts[i]);
53
+ }
54
+
55
+ current = current[parts[i]];
56
+ }
57
+
58
+ return false;
59
+ };
60
+
61
+ /**
62
+ * Checks if a document matches the given filter criteria.
63
+ * @param {Object} document - Document to test
64
+ * @param {Object} filter - Filter criteria with MongoDB-style operators
65
+ * @returns {boolean} True if document matches filter
66
+ * @throws {Error} When unsupported query operator is used
67
+ */
68
+ const matches_filter = (document, filter) => {
69
+ if (!filter || Object.keys(filter).length === 0) {
70
+ return true;
71
+ }
72
+
73
+ for (const [field, value] of Object.entries(filter)) {
74
+ const field_value = get_field_value(document, field);
75
+
76
+ if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
77
+ for (const [operator, operand] of Object.entries(value)) {
78
+ switch (operator) {
79
+ case '$eq':
80
+ if (field_value !== operand) return false;
81
+ break;
82
+ case '$ne':
83
+ if (field_value === operand) return false;
84
+ break;
85
+ case '$gt':
86
+ if (field_value <= operand) return false;
87
+ break;
88
+ case '$gte':
89
+ if (field_value < operand) return false;
90
+ break;
91
+ case '$lt':
92
+ if (field_value >= operand) return false;
93
+ break;
94
+ case '$lte':
95
+ if (field_value > operand) return false;
96
+ break;
97
+ case '$in':
98
+ if (!Array.isArray(operand) || !operand.includes(field_value)) return false;
99
+ break;
100
+ case '$nin':
101
+ if (!Array.isArray(operand) || operand.includes(field_value)) return false;
102
+ break;
103
+ case '$exists':
104
+ const exists = field_exists(document, field);
105
+ if (operand && !exists) return false;
106
+ if (!operand && exists) return false;
107
+ break;
108
+ case '$regex':
109
+ const regex = new RegExp(operand);
110
+ if (!regex.test(field_value)) return false;
111
+ break;
112
+ default:
113
+ throw new Error(`Unsupported query operator: ${operator}`);
114
+ }
115
+ }
116
+ } else {
117
+ if (field_value !== value) return false;
118
+ }
119
+ }
120
+
121
+ return true;
122
+ };
123
+
124
+ /**
125
+ * Applies projection to a document, including or excluding specified fields.
126
+ * @param {Object} document - Document to project
127
+ * @param {Object} projection - Projection specification (1/true for inclusion, 0/false for exclusion)
128
+ * @returns {Object} Projected document
129
+ */
130
+ const apply_projection = (document, projection) => {
131
+ if (!projection || Object.keys(projection).length === 0) {
132
+ return document;
133
+ }
134
+
135
+ const is_inclusion = Object.values(projection).some(value => value === 1 || value === true);
136
+ const projected_document = {};
137
+
138
+ if (is_inclusion) {
139
+ projected_document._id = document._id;
140
+
141
+ for (const [field, include] of Object.entries(projection)) {
142
+ if (field === '_id' && (include === 0 || include === false)) {
143
+ delete projected_document._id;
144
+ } else if (include === 1 || include === true) {
145
+ projected_document[field] = document[field];
146
+ }
147
+ }
148
+ } else {
149
+ Object.assign(projected_document, document);
150
+
151
+ for (const [field, exclude] of Object.entries(projection)) {
152
+ if (exclude === 0 || exclude === false) {
153
+ delete projected_document[field];
154
+ }
155
+ }
156
+ }
157
+
158
+ return projected_document;
159
+ };
160
+
161
+ /**
162
+ * Finds a single document in a collection matching the filter criteria.
163
+ * @param {string} database_name - Name of the database
164
+ * @param {string} collection_name - Name of the collection
165
+ * @param {Object} [filter={}] - Filter criteria
166
+ * @param {Object} [options={}] - Query options
167
+ * @param {Object} [options.projection] - Field projection specification
168
+ * @param {Object} [options.sort] - Sort specification (currently unused)
169
+ * @returns {Promise<Object|null>} Found document or null if not found
170
+ * @throws {Error} When database or collection name is missing or query fails
171
+ */
172
+ const find_one = async (database_name, collection_name, filter = {}, options = {}) => {
173
+ const log = create_context_logger();
174
+
175
+ if (!database_name) {
176
+ throw new Error('Database name is required');
177
+ }
178
+
179
+ if (!collection_name) {
180
+ throw new Error('Collection name is required');
181
+ }
182
+
183
+ const db = get_database();
184
+ const { projection, sort } = options;
185
+ const start_time = Date.now();
186
+
187
+ try {
188
+ let found_document = null;
189
+ let used_index = false;
190
+ let indexed_field = null;
191
+
192
+ const index_info = can_use_index(database_name, collection_name, filter);
193
+
194
+ if (index_info) {
195
+ const { field, operators } = index_info;
196
+ const field_filter = filter[field];
197
+ indexed_field = field;
198
+
199
+ if (typeof field_filter === 'object' && field_filter !== null && !Array.isArray(field_filter)) {
200
+ for (const operator of operators) {
201
+ if (field_filter[operator] !== undefined) {
202
+ const document_ids = find_documents_by_index(database_name, collection_name, field, operator, field_filter[operator]);
203
+
204
+ if (document_ids && document_ids.length > 0) {
205
+ used_index = true;
206
+ record_index_usage(database_name, collection_name, field);
207
+
208
+ for (const document_id of document_ids) {
209
+ const collection_key = build_collection_key(database_name, collection_name, document_id);
210
+ const value = db.get(collection_key);
211
+
212
+ if (value) {
213
+ try {
214
+ const document = JSON.parse(value);
215
+ if (matches_filter(document, filter)) {
216
+ found_document = document;
217
+ break;
218
+ }
219
+ } catch (parse_error) {
220
+ // Skip documents that can't be parsed
221
+ continue;
222
+ }
223
+ }
224
+ }
225
+ break;
226
+ }
227
+ }
228
+ }
229
+ } else if (operators.includes('eq')) {
230
+ const document_ids = find_documents_by_index(database_name, collection_name, field, 'eq', field_filter);
231
+
232
+ if (document_ids && document_ids.length > 0) {
233
+ used_index = true;
234
+ record_index_usage(database_name, collection_name, field);
235
+
236
+ for (const document_id of document_ids) {
237
+ const collection_key = build_collection_key(database_name, collection_name, document_id);
238
+ const value = db.get(collection_key);
239
+
240
+ if (value) {
241
+ try {
242
+ const document = JSON.parse(value);
243
+ if (matches_filter(document, filter)) {
244
+ found_document = document;
245
+ break;
246
+ }
247
+ } catch (parse_error) {
248
+ // Skip documents that can't be parsed
249
+ continue;
250
+ }
251
+ }
252
+ }
253
+ }
254
+ }
255
+ }
256
+
257
+ if (!used_index) {
258
+ const collection_prefix = `${database_name}:${collection_name}:`;
259
+ const range = db.getRange({ start: collection_prefix, end: collection_prefix + '\xFF' });
260
+
261
+ for (const { key, value } of range) {
262
+ try {
263
+ const document = JSON.parse(value);
264
+ if (matches_filter(document, filter)) {
265
+ found_document = document;
266
+ break;
267
+ }
268
+ } catch (parse_error) {
269
+ // Skip documents that can't be parsed
270
+ continue;
271
+ }
272
+ }
273
+ }
274
+
275
+ const execution_time = Date.now() - start_time;
276
+
277
+ try {
278
+ record_query(collection_name, filter, execution_time, used_index, indexed_field);
279
+ } catch (auto_index_error) {
280
+ log.warn('Failed to record query for auto-indexing', {
281
+ error: auto_index_error.message
282
+ });
283
+ }
284
+
285
+ if (found_document) {
286
+ const projected_document = apply_projection(found_document, projection);
287
+
288
+ log.info('Document found', {
289
+ database: database_name,
290
+ collection: collection_name,
291
+ document_id: found_document._id,
292
+ used_index,
293
+ indexed_field,
294
+ execution_time_ms: execution_time
295
+ });
296
+
297
+ return projected_document;
298
+ }
299
+
300
+ log.info('No document found', {
301
+ database: database_name,
302
+ collection: collection_name,
303
+ used_index,
304
+ indexed_field,
305
+ execution_time_ms: execution_time
306
+ });
307
+
308
+ return null;
309
+ } catch (error) {
310
+ log.error('Failed to find document', {
311
+ database: database_name,
312
+ collection: collection_name,
313
+ error: error.message
314
+ });
315
+ throw error;
316
+ }
317
+ };
318
+
319
+ export default find_one;
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @fileoverview Get indexes operation for JoystickDB collections.
3
+ * Provides functionality to retrieve all indexes for a specified collection.
4
+ */
5
+
6
+ import { get_indexes } from '../index_manager.js';
7
+ import create_logger from '../logger.js';
8
+
9
+ const { create_context_logger } = create_logger('get_indexes');
10
+
11
+ /**
12
+ * Retrieves all indexes for a specified collection.
13
+ * @param {string} database_name - Name of the database
14
+ * @param {string} collection_name - Name of the collection to get indexes for
15
+ * @returns {Promise<Object>} Result containing acknowledged status and array of indexes
16
+ * @throws {Error} When database or collection name is missing or index retrieval fails
17
+ */
18
+ const get_indexes_operation = async (database_name, collection_name) => {
19
+ const log = create_context_logger();
20
+
21
+ if (!database_name) {
22
+ throw new Error('Database name is required');
23
+ }
24
+
25
+ if (!collection_name) {
26
+ throw new Error('Collection name is required');
27
+ }
28
+
29
+ try {
30
+ const indexes = get_indexes(database_name, collection_name);
31
+
32
+ log.info('Retrieved indexes successfully', {
33
+ database: database_name,
34
+ collection: collection_name,
35
+ count: indexes.length
36
+ });
37
+
38
+ return {
39
+ acknowledged: true,
40
+ indexes
41
+ };
42
+ } catch (error) {
43
+ log.error('Failed to get indexes', {
44
+ database: database_name,
45
+ collection: collection_name,
46
+ error: error.message
47
+ });
48
+ throw error;
49
+ }
50
+ };
51
+
52
+ export default get_indexes_operation;