@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,752 @@
1
+ import net from 'net';
2
+ import { EventEmitter } from 'events';
3
+ import { encode as encode_messagepack, decode as decode_messagepack } from 'msgpackr';
4
+ import Database from './database.js';
5
+
6
+ /**
7
+ * Encodes a message with MessagePack and prepends a 4-byte length header.
8
+ * @param {any} data - The data to encode
9
+ * @returns {Buffer} The encoded message with length header
10
+ */
11
+ const encode_message = (data) => {
12
+ // NOTE: Use compatible MessagePack options to avoid parsing issues.
13
+ const messagepack_data = encode_messagepack(data, {
14
+ useFloat32: false,
15
+ int64AsType: 'number',
16
+ mapsAsObjects: true
17
+ });
18
+ const length_buffer = Buffer.allocUnsafe(4);
19
+ length_buffer.writeUInt32BE(messagepack_data.length, 0);
20
+ return Buffer.concat([length_buffer, messagepack_data]);
21
+ };
22
+
23
+ /**
24
+ * Creates a message parser for handling TCP stream data with length-prefixed MessagePack messages.
25
+ * @returns {Object} Parser object with parse_messages and reset methods
26
+ */
27
+ const create_message_parser = () => {
28
+ let buffer = Buffer.alloc(0);
29
+ let expected_length = null;
30
+
31
+ /**
32
+ * Parses incoming data and extracts complete messages.
33
+ * @param {Buffer} data - Raw TCP data
34
+ * @returns {Array} Array of decoded messages
35
+ * @throws {Error} When message format is invalid
36
+ */
37
+ const parse_messages = (data) => {
38
+ buffer = Buffer.concat([buffer, data]);
39
+ const messages = [];
40
+
41
+ while (buffer.length > 0) {
42
+ if (expected_length === null) {
43
+ if (buffer.length < 4) {
44
+ break;
45
+ }
46
+
47
+ expected_length = buffer.readUInt32BE(0);
48
+ buffer = buffer.slice(4);
49
+ }
50
+
51
+ if (buffer.length < expected_length) {
52
+ break;
53
+ }
54
+
55
+ const message_data = buffer.slice(0, expected_length);
56
+ buffer = buffer.slice(expected_length);
57
+ expected_length = null;
58
+
59
+ try {
60
+ // NOTE: Use compatible MessagePack options to avoid parsing issues.
61
+ const decoded_message = decode_messagepack(message_data, {
62
+ useFloat32: false,
63
+ int64AsType: 'number',
64
+ mapsAsObjects: true
65
+ });
66
+ messages.push(decoded_message);
67
+ } catch (error) {
68
+ throw new Error(`Invalid message format: ${error.message}`);
69
+ }
70
+ }
71
+
72
+ return messages;
73
+ };
74
+
75
+ /**
76
+ * Resets the parser state, clearing buffers and expected length.
77
+ */
78
+ const reset = () => {
79
+ buffer = Buffer.alloc(0);
80
+ expected_length = null;
81
+ };
82
+
83
+ return {
84
+ parse_messages,
85
+ reset
86
+ };
87
+ };
88
+
89
+
90
+ /**
91
+ * @typedef {Object} ClientOptions
92
+ * @property {string} [host='localhost'] - Server hostname
93
+ * @property {number} [port=1983] - Server port
94
+ * @property {string} [password] - Authentication password (required for authenticated connections)
95
+ * @property {number} [timeout=5000] - Request timeout in milliseconds
96
+ * @property {boolean} [reconnect=true] - Enable automatic reconnection
97
+ * @property {number} [max_reconnect_attempts=10] - Maximum reconnection attempts
98
+ * @property {number} [reconnect_delay=1000] - Initial reconnection delay in milliseconds
99
+ * @property {boolean} [auto_connect=true] - Automatically connect on instantiation
100
+ */
101
+
102
+ /**
103
+ * JoystickDB TCP client for connecting to JoystickDB server.
104
+ * @extends EventEmitter
105
+ * @fires JoystickDBClient#connect
106
+ * @fires JoystickDBClient#authenticated
107
+ * @fires JoystickDBClient#error
108
+ * @fires JoystickDBClient#disconnect
109
+ * @fires JoystickDBClient#reconnecting
110
+ * @fires JoystickDBClient#response
111
+ */
112
+ class JoystickDBClient extends EventEmitter {
113
+ /**
114
+ * Creates a new JoystickDB client instance.
115
+ * @param {ClientOptions} [options={}] - Client configuration options
116
+ */
117
+ constructor(options = {}) {
118
+ super();
119
+
120
+ this.host = options.host || 'localhost';
121
+ this.port = options.port || 1983;
122
+ this.password = options.password || null;
123
+ this.timeout = options.timeout || 5000;
124
+ this.reconnect = options.reconnect !== false;
125
+ this.max_reconnect_attempts = options.max_reconnect_attempts || 10;
126
+ this.reconnect_delay = options.reconnect_delay || 1000;
127
+
128
+ this.socket = null;
129
+ this.message_parser = null;
130
+ this.is_connected = false;
131
+ this.is_authenticated = false;
132
+ this.is_connecting = false;
133
+ this.reconnect_attempts = 0;
134
+ this.reconnect_timeout = null;
135
+
136
+ this.pending_requests = new Map();
137
+ this.request_id_counter = 0;
138
+ this.request_queue = [];
139
+
140
+ if (options.auto_connect !== false) {
141
+ this.connect();
142
+ }
143
+ }
144
+
145
+ /**
146
+ * Establishes connection to the JoystickDB server.
147
+ */
148
+ connect() {
149
+ if (this.is_connecting || this.is_connected) {
150
+ return;
151
+ }
152
+
153
+ this.is_connecting = true;
154
+ this.socket = new net.Socket();
155
+ this.message_parser = create_message_parser();
156
+
157
+ const connection_timeout = setTimeout(() => {
158
+ if (this.socket && !this.is_connected) {
159
+ this.socket.destroy();
160
+ this.handle_connection_error(new Error('Connection timeout'));
161
+ }
162
+ }, this.timeout);
163
+
164
+ this.socket.connect(this.port, this.host, () => {
165
+ clearTimeout(connection_timeout);
166
+ this.is_connected = true;
167
+ this.is_connecting = false;
168
+ this.reconnect_attempts = 0;
169
+
170
+ this.emit('connect');
171
+
172
+ if (this.password) {
173
+ this.authenticate();
174
+ }
175
+ });
176
+
177
+ this.socket.on('data', (data) => {
178
+ try {
179
+ const messages = this.message_parser.parse_messages(data);
180
+
181
+ for (const message of messages) {
182
+ this.handle_message(message);
183
+ }
184
+ } catch (error) {
185
+ this.emit('error', new Error(`Message parsing failed: ${error.message}`));
186
+ }
187
+ });
188
+
189
+ this.socket.on('error', (error) => {
190
+ clearTimeout(connection_timeout);
191
+ this.handle_connection_error(error);
192
+ });
193
+
194
+ this.socket.on('close', () => {
195
+ clearTimeout(connection_timeout);
196
+ this.handle_disconnect();
197
+ });
198
+ }
199
+
200
+ /**
201
+ * Authenticates with the server using provided credentials.
202
+ */
203
+ async authenticate() {
204
+ if (!this.password) {
205
+ this.emit('error', new Error('Password required for authentication. Provide password in client options: joystickdb.client({ password: "your_password" })'));
206
+ this.disconnect();
207
+ return;
208
+ }
209
+
210
+ try {
211
+ const result = await this.send_request('authentication', {
212
+ password: this.password
213
+ });
214
+
215
+ if (result.ok === 1) {
216
+ this.is_authenticated = true;
217
+ this.emit('authenticated');
218
+ this.process_request_queue();
219
+ } else {
220
+ throw new Error('Authentication failed');
221
+ }
222
+ } catch (error) {
223
+ this.emit('error', new Error(`Authentication error: ${error.message}`));
224
+ this.disconnect();
225
+ }
226
+ }
227
+
228
+ /**
229
+ * Handles incoming messages from the server.
230
+ * @param {Object} message - Decoded message from server
231
+ */
232
+ handle_message(message) {
233
+ if (this.pending_requests.size > 0) {
234
+ const [request_id, { resolve, reject, timeout }] = this.pending_requests.entries().next().value;
235
+ clearTimeout(timeout);
236
+ this.pending_requests.delete(request_id);
237
+
238
+ if (message.ok === 1 || message.ok === true) {
239
+ resolve(message);
240
+ } else if (message.ok === 0 || message.ok === false) {
241
+ const error_message = typeof message.error === 'string' ? message.error : JSON.stringify(message.error) || 'Operation failed';
242
+ reject(new Error(error_message));
243
+ } else {
244
+ resolve(message);
245
+ }
246
+ } else {
247
+ this.emit('response', message);
248
+ }
249
+ }
250
+
251
+ /**
252
+ * Handles connection errors and manages reconnection logic.
253
+ * @param {Error} error - The connection error
254
+ */
255
+ handle_connection_error(error) {
256
+ this.is_connecting = false;
257
+ this.is_connected = false;
258
+ this.is_authenticated = false;
259
+
260
+ if (this.socket) {
261
+ this.socket.removeAllListeners();
262
+ this.socket.destroy();
263
+ this.socket = null;
264
+ }
265
+
266
+ if (this.message_parser) {
267
+ this.message_parser.reset();
268
+ }
269
+
270
+ // NOTE: Reject all pending requests.
271
+ for (const [request_id, { reject, timeout }] of this.pending_requests) {
272
+ clearTimeout(timeout);
273
+ reject(new Error('Connection lost'));
274
+ }
275
+ this.pending_requests.clear();
276
+
277
+ this.emit('error', error);
278
+
279
+ if (this.reconnect && this.reconnect_attempts < this.max_reconnect_attempts) {
280
+ this.schedule_reconnect();
281
+ } else {
282
+ this.emit('disconnect');
283
+ }
284
+ }
285
+
286
+ /**
287
+ * Handles disconnection events and manages reconnection logic.
288
+ */
289
+ handle_disconnect() {
290
+ this.is_connected = false;
291
+ this.is_authenticated = false;
292
+ this.is_connecting = false;
293
+
294
+ if (this.socket) {
295
+ this.socket.removeAllListeners();
296
+ this.socket = null;
297
+ }
298
+
299
+ if (this.message_parser) {
300
+ this.message_parser.reset();
301
+ }
302
+
303
+ // NOTE: Reject all pending requests.
304
+ for (const [request_id, { reject, timeout }] of this.pending_requests) {
305
+ clearTimeout(timeout);
306
+ reject(new Error('Connection closed'));
307
+ }
308
+ this.pending_requests.clear();
309
+
310
+ if (this.reconnect && this.reconnect_attempts < this.max_reconnect_attempts) {
311
+ this.schedule_reconnect();
312
+ } else {
313
+ this.emit('disconnect');
314
+ }
315
+ }
316
+
317
+ /**
318
+ * Schedules a reconnection attempt with exponential backoff.
319
+ */
320
+ schedule_reconnect() {
321
+ this.reconnect_attempts++;
322
+ const delay = Math.min(
323
+ this.reconnect_delay * Math.pow(2, this.reconnect_attempts - 1),
324
+ 30000
325
+ );
326
+
327
+ this.emit('reconnecting', { attempt: this.reconnect_attempts, delay });
328
+
329
+ this.reconnect_timeout = setTimeout(() => {
330
+ this.connect();
331
+ }, delay);
332
+ }
333
+
334
+ /**
335
+ * Sends a request to the server.
336
+ * @param {string} op - Operation name
337
+ * @param {Object} [data={}] - Request data
338
+ * @param {boolean} [use_queue=true] - Whether to queue request if not connected
339
+ * @returns {Promise<Object>} Server response
340
+ */
341
+ send_request(op, data = {}, use_queue = true) {
342
+ return new Promise((resolve, reject) => {
343
+ const request_id = ++this.request_id_counter;
344
+ const message = {
345
+ op,
346
+ data
347
+ };
348
+
349
+ const request = {
350
+ message,
351
+ resolve,
352
+ reject,
353
+ request_id
354
+ };
355
+
356
+ if (!this.is_connected || (op !== 'authentication' && op !== 'setup' && op !== 'ping' && !this.is_authenticated)) {
357
+ if (use_queue) {
358
+ this.request_queue.push(request);
359
+ return;
360
+ } else {
361
+ reject(new Error('Not connected or authenticated'));
362
+ return;
363
+ }
364
+ }
365
+
366
+ this.send_request_now(request);
367
+ });
368
+ }
369
+
370
+ /**
371
+ * Immediately sends a request to the server.
372
+ * @param {Object} request - Request object with message, resolve, reject, and request_id
373
+ */
374
+ send_request_now(request) {
375
+ const { message, resolve, reject, request_id } = request;
376
+
377
+ const timeout = setTimeout(() => {
378
+ this.pending_requests.delete(request_id);
379
+ reject(new Error('Request timeout'));
380
+ }, this.timeout);
381
+
382
+ this.pending_requests.set(request_id, { resolve, reject, timeout });
383
+
384
+ try {
385
+ const encoded_message = encode_message(message);
386
+ this.socket.write(encoded_message);
387
+ } catch (error) {
388
+ clearTimeout(timeout);
389
+ this.pending_requests.delete(request_id);
390
+ reject(error);
391
+ }
392
+ }
393
+
394
+ /**
395
+ * Processes queued requests after connection and authentication.
396
+ */
397
+ process_request_queue() {
398
+ while (this.request_queue.length > 0 && this.is_connected && this.is_authenticated) {
399
+ const request = this.request_queue.shift();
400
+ this.send_request_now(request);
401
+ }
402
+ }
403
+
404
+ /**
405
+ * Disconnects from the server and disables reconnection.
406
+ */
407
+ disconnect() {
408
+ this.reconnect = false;
409
+
410
+ if (this.reconnect_timeout) {
411
+ clearTimeout(this.reconnect_timeout);
412
+ this.reconnect_timeout = null;
413
+ }
414
+
415
+ if (this.socket) {
416
+ this.socket.end();
417
+ }
418
+ }
419
+
420
+
421
+
422
+ // NOTE: Backup Operations.
423
+ /**
424
+ * Triggers an immediate backup.
425
+ * @returns {Promise<Object>} Backup result
426
+ */
427
+ async backup_now() {
428
+ return this.send_request('admin', { admin_action: 'backup_now' });
429
+ }
430
+
431
+ /**
432
+ * Lists all available backups.
433
+ * @returns {Promise<Object>} Backups list
434
+ */
435
+ async list_backups() {
436
+ return this.send_request('admin', { admin_action: 'list_backups' });
437
+ }
438
+
439
+ /**
440
+ * Restores from a specific backup.
441
+ * @param {string} backup_name - Name of backup to restore
442
+ * @returns {Promise<Object>} Restore result
443
+ */
444
+ async restore_backup(backup_name) {
445
+ return this.send_request('admin', {
446
+ admin_action: 'restore_backup',
447
+ backup_name
448
+ });
449
+ }
450
+
451
+ // NOTE: Replication Operations.
452
+ /**
453
+ * Gets replication status and statistics.
454
+ * @returns {Promise<Object>} Replication status
455
+ */
456
+ async get_replication_status() {
457
+ return this.send_request('admin', { admin_action: 'get_replication_status' });
458
+ }
459
+
460
+ /**
461
+ * Adds a secondary node to replication.
462
+ * @param {Object} secondary - Secondary node configuration
463
+ * @param {string} secondary.id - Secondary node ID
464
+ * @param {string} secondary.ip - Secondary node IP address
465
+ * @param {number} secondary.port - Secondary node port
466
+ * @param {string} secondary.private_key - Base64 encoded private key
467
+ * @returns {Promise<Object>} Add secondary result
468
+ */
469
+ async add_secondary(secondary) {
470
+ return this.send_request('admin', { admin_action: 'add_secondary', ...secondary });
471
+ }
472
+
473
+ /**
474
+ * Removes a secondary node from replication.
475
+ * @param {string} secondary_id - Secondary node ID to remove
476
+ * @returns {Promise<Object>} Remove secondary result
477
+ */
478
+ async remove_secondary(secondary_id) {
479
+ return this.send_request('admin', { admin_action: 'remove_secondary', secondary_id });
480
+ }
481
+
482
+ /**
483
+ * Forces synchronization with all secondary nodes.
484
+ * @returns {Promise<Object>} Sync result
485
+ */
486
+ async sync_secondaries() {
487
+ return this.send_request('admin', { admin_action: 'sync_secondaries' });
488
+ }
489
+
490
+ /**
491
+ * Gets health status of secondary nodes.
492
+ * @returns {Promise<Object>} Secondary health status
493
+ */
494
+ async get_secondary_health() {
495
+ return this.send_request('admin', { admin_action: 'get_secondary_health' });
496
+ }
497
+
498
+ /**
499
+ * Gets write forwarder status (for secondary nodes).
500
+ * @returns {Promise<Object>} Write forwarder status
501
+ */
502
+ async get_forwarder_status() {
503
+ return this.send_request('admin', { admin_action: 'get_forwarder_status' });
504
+ }
505
+
506
+ // NOTE: Health and Utility Operations.
507
+ /**
508
+ * Pings the server to check connectivity.
509
+ * @returns {Promise<Object>} Ping result
510
+ */
511
+ async ping() {
512
+ return this.send_request('ping', {}, false);
513
+ }
514
+
515
+ /**
516
+ * Reloads server configuration.
517
+ * @returns {Promise<Object>} Reload result
518
+ */
519
+ async reload() {
520
+ return this.send_request('reload');
521
+ }
522
+
523
+ // NOTE: Auto-Indexing Operations.
524
+ /**
525
+ * Gets automatic indexing statistics.
526
+ * @returns {Promise<Object>} Auto-indexing statistics
527
+ */
528
+ async get_auto_index_stats() {
529
+ return this.send_request('admin', { admin_action: 'get_auto_index_stats' });
530
+ }
531
+
532
+
533
+ // NOTE: Setup Operation.
534
+ /**
535
+ * Performs initial server setup.
536
+ * @returns {Promise<Object>} Setup result
537
+ */
538
+ async setup() {
539
+ const result = await this.send_request('setup', {}, false);
540
+
541
+ // NOTE: Display setup instructions to user.
542
+ if (result.data && result.data.instructions) {
543
+ console.log(result.data.instructions);
544
+ }
545
+
546
+ return result;
547
+ }
548
+
549
+ // NOTE: Database Interface.
550
+ /**
551
+ * Returns a database interface for method chaining operations.
552
+ * @param {string} database_name - Database name
553
+ * @returns {Database} Database interface instance
554
+ */
555
+ db(database_name) {
556
+ return new Database(this, database_name);
557
+ }
558
+
559
+
560
+ // NOTE: Multi-Database Admin Operations.
561
+ /**
562
+ * Lists all databases on the server.
563
+ * @returns {Promise<Object>} Databases list
564
+ */
565
+ async list_databases() {
566
+ return this.send_request('admin', { admin_action: 'list_databases' });
567
+ }
568
+ }
569
+
570
+ /**
571
+ * Collection interface for method chaining operations.
572
+ * Provides a fluent API for database operations on a specific collection.
573
+ */
574
+ class Collection {
575
+ /**
576
+ * Creates a new Collection instance.
577
+ * @param {JoystickDBClient} client - The client instance
578
+ * @param {string} database_name - Name of the database
579
+ * @param {string} collection_name - Name of the collection
580
+ */
581
+ constructor(client, database_name, collection_name) {
582
+ this.client = client;
583
+ this.database_name = database_name;
584
+ this.collection_name = collection_name;
585
+ }
586
+
587
+ /**
588
+ * Inserts a single document into the collection.
589
+ * @param {Object} document - Document to insert
590
+ * @param {Object} [options={}] - Insert options
591
+ * @returns {Promise<Object>} Insert result
592
+ */
593
+ async insert_one(document, options = {}) {
594
+ return this.client.send_request('insert_one', {
595
+ database: this.database_name,
596
+ collection: this.collection_name,
597
+ document,
598
+ options
599
+ });
600
+ }
601
+
602
+ /**
603
+ * Finds a single document in the collection.
604
+ * @param {Object} [filter={}] - Query filter
605
+ * @param {Object} [options={}] - Find options
606
+ * @returns {Promise<Object|null>} Found document or null
607
+ */
608
+ async find_one(filter = {}, options = {}) {
609
+ const result = await this.client.send_request('find_one', {
610
+ database: this.database_name,
611
+ collection: this.collection_name,
612
+ filter,
613
+ options
614
+ });
615
+ return result.document;
616
+ }
617
+
618
+ /**
619
+ * Finds multiple documents in the collection.
620
+ * @param {Object} [filter={}] - Query filter
621
+ * @param {Object} [options={}] - Find options
622
+ * @returns {Promise<Array>} Array of found documents
623
+ */
624
+ async find(filter = {}, options = {}) {
625
+ const result = await this.client.send_request('find', {
626
+ database: this.database_name,
627
+ collection: this.collection_name,
628
+ filter,
629
+ options
630
+ });
631
+ return result.documents || [];
632
+ }
633
+
634
+ /**
635
+ * Updates a single document in the collection.
636
+ * @param {Object} filter - Query filter to match document
637
+ * @param {Object} update - Update operations
638
+ * @param {Object} [options={}] - Update options
639
+ * @returns {Promise<Object>} Update result
640
+ */
641
+ async update_one(filter, update, options = {}) {
642
+ return this.client.send_request('update_one', {
643
+ database: this.database_name,
644
+ collection: this.collection_name,
645
+ filter,
646
+ update,
647
+ options
648
+ });
649
+ }
650
+
651
+ /**
652
+ * Deletes a single document from the collection.
653
+ * @param {Object} filter - Query filter to match document
654
+ * @param {Object} [options={}] - Delete options
655
+ * @returns {Promise<Object>} Delete result
656
+ */
657
+ async delete_one(filter, options = {}) {
658
+ return this.client.send_request('delete_one', {
659
+ database: this.database_name,
660
+ collection: this.collection_name,
661
+ filter,
662
+ options
663
+ });
664
+ }
665
+
666
+ /**
667
+ * Performs multiple write operations in a single request.
668
+ * @param {Array<Object>} operations - Array of write operations
669
+ * @param {Object} [options={}] - Bulk write options
670
+ * @returns {Promise<Object>} Bulk write result
671
+ */
672
+ async bulk_write(operations, options = {}) {
673
+ return this.client.send_request('bulk_write', {
674
+ database: this.database_name,
675
+ collection: this.collection_name,
676
+ operations,
677
+ options
678
+ });
679
+ }
680
+
681
+ /**
682
+ * Creates an index on a collection field.
683
+ * @param {string} field - Field name to index
684
+ * @param {Object} [options={}] - Index options
685
+ * @returns {Promise<Object>} Index creation result
686
+ */
687
+ async create_index(field, options = {}) {
688
+ return this.client.send_request('create_index', {
689
+ database: this.database_name,
690
+ collection: this.collection_name,
691
+ field,
692
+ options
693
+ });
694
+ }
695
+
696
+ /**
697
+ * Creates or updates an index on a collection field (upsert operation).
698
+ * @param {string} field - Field name to index
699
+ * @param {Object} [options={}] - Index options
700
+ * @returns {Promise<Object>} Index upsert result
701
+ */
702
+ async upsert_index(field, options = {}) {
703
+ return this.client.send_request('create_index', {
704
+ database: this.database_name,
705
+ collection: this.collection_name,
706
+ field,
707
+ options: { ...options, upsert: true }
708
+ });
709
+ }
710
+
711
+ /**
712
+ * Drops an index from a collection field.
713
+ * @param {string} field - Field name of index to drop
714
+ * @returns {Promise<Object>} Index drop result
715
+ */
716
+ async drop_index(field) {
717
+ return this.client.send_request('drop_index', {
718
+ database: this.database_name,
719
+ collection: this.collection_name,
720
+ field
721
+ });
722
+ }
723
+
724
+ /**
725
+ * Gets all indexes for the collection.
726
+ * @returns {Promise<Object>} Indexes information
727
+ */
728
+ async get_indexes() {
729
+ return this.client.send_request('get_indexes', {
730
+ database: this.database_name,
731
+ collection: this.collection_name
732
+ });
733
+ }
734
+ }
735
+
736
+ // NOTE: Add Collection class as static property for Database class access.
737
+ JoystickDBClient.Collection = Collection;
738
+
739
+ /**
740
+ * JoystickDB client factory and utilities.
741
+ * @namespace
742
+ */
743
+ const joystickdb = {
744
+ /**
745
+ * Creates a new JoystickDB client instance.
746
+ * @param {ClientOptions} options - Client configuration options
747
+ * @returns {JoystickDBClient} New client instance
748
+ */
749
+ client: (options) => new JoystickDBClient(options)
750
+ };
751
+
752
+ export default joystickdb;