@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,513 @@
1
+ import test from 'ava';
2
+ import sinon from 'sinon';
3
+ import net from 'net';
4
+ import { encode as encode_messagepack, decode as decode_messagepack } from 'msgpackr';
5
+ import { encode_message } from '../../../src/server/lib/tcp_protocol.js';
6
+ import { create_server } from '../../../src/server/index.js';
7
+
8
+ // Shared server instance
9
+ let shared_server = null;
10
+ let shared_port = null;
11
+
12
+ test.before(async () => {
13
+ // Set test environment
14
+ process.env.NODE_ENV = 'test';
15
+
16
+ // Create shared server instance
17
+ shared_server = await create_server();
18
+ shared_port = 0; // Use random available port
19
+
20
+ // Start server
21
+ await new Promise((resolve, reject) => {
22
+ const timeout = setTimeout(() => {
23
+ reject(new Error('Server start timeout'));
24
+ }, 5000);
25
+
26
+ shared_server.listen(shared_port, (error) => {
27
+ clearTimeout(timeout);
28
+ if (error) {
29
+ reject(error);
30
+ } else {
31
+ shared_port = shared_server.address().port;
32
+ resolve();
33
+ }
34
+ });
35
+ });
36
+ });
37
+
38
+ test.after.always(async () => {
39
+ // Clean up shared server
40
+ if (shared_server) {
41
+ try {
42
+ if (shared_server.cleanup) {
43
+ await shared_server.cleanup();
44
+ }
45
+ } catch (error) {
46
+ // Ignore cleanup errors
47
+ }
48
+
49
+ await new Promise((resolve) => {
50
+ const timeout = setTimeout(() => {
51
+ try {
52
+ shared_server.close();
53
+ } catch (error) {
54
+ // Ignore errors
55
+ }
56
+ resolve();
57
+ }, 2000);
58
+
59
+ try {
60
+ shared_server.close(() => {
61
+ clearTimeout(timeout);
62
+ resolve();
63
+ });
64
+ } catch (error) {
65
+ clearTimeout(timeout);
66
+ resolve();
67
+ }
68
+ });
69
+
70
+ shared_server = null;
71
+ }
72
+
73
+ // Restore sinon mocks
74
+ sinon.restore();
75
+
76
+ // Force garbage collection if available
77
+ if (global.gc) {
78
+ global.gc();
79
+ }
80
+ });
81
+
82
+ const create_client = () => {
83
+ return new Promise((resolve, reject) => {
84
+ const client = net.createConnection({ port: shared_port }, () => {
85
+ // Set socket options for better cleanup
86
+ client.setKeepAlive(false);
87
+ client.setTimeout(5000);
88
+
89
+ resolve(client);
90
+ });
91
+
92
+ client.on('error', (error) => {
93
+ client.destroy();
94
+ reject(error);
95
+ });
96
+
97
+ client.on('timeout', () => {
98
+ client.destroy();
99
+ reject(new Error('Client connection timeout'));
100
+ });
101
+ });
102
+ };
103
+
104
+ const send_message = (client, message) => {
105
+ return new Promise((resolve, reject) => {
106
+ const timeout = setTimeout(() => {
107
+ reject(new Error('Message timeout'));
108
+ }, 5000);
109
+
110
+ const encoded_message = encode_message(message);
111
+
112
+ client.once('data', (data) => {
113
+ clearTimeout(timeout);
114
+ try {
115
+ // Parse the MessagePack response with length prefix
116
+ if (data.length < 4) {
117
+ reject(new Error('Response too short'));
118
+ return;
119
+ }
120
+
121
+ const length = data.readUInt32BE(0);
122
+ if (data.length < 4 + length) {
123
+ reject(new Error('Incomplete response'));
124
+ return;
125
+ }
126
+
127
+ const messagepack_data = data.slice(4, 4 + length);
128
+ const response = decode_messagepack(messagepack_data);
129
+ resolve(response);
130
+ } catch (error) {
131
+ reject(error);
132
+ }
133
+ });
134
+
135
+ client.once('error', (error) => {
136
+ clearTimeout(timeout);
137
+ reject(error);
138
+ });
139
+
140
+ client.write(encoded_message);
141
+ });
142
+ };
143
+
144
+ test('admin backup operations - should handle test_s3_connection', async t => {
145
+ const client = await create_client();
146
+
147
+ try {
148
+ // First authenticate
149
+ const auth_response = await send_message(client, {
150
+ op: 'authentication',
151
+ data: { password: 'test-password' }
152
+ });
153
+
154
+ // Skip if authentication fails (expected in test environment)
155
+ if (auth_response.ok !== 1) {
156
+ t.pass('Authentication failed as expected in test environment');
157
+ return;
158
+ }
159
+
160
+ // Test S3 connection
161
+ const s3_test_response = await send_message(client, {
162
+ op: 'admin',
163
+ data: { admin_action: 'test_s3_connection' }
164
+ });
165
+
166
+ // Should fail without proper S3 configuration
167
+ t.is(s3_test_response.ok, 0);
168
+ t.truthy(s3_test_response.error);
169
+
170
+ } finally {
171
+ try {
172
+ client.end();
173
+ await new Promise(resolve => setTimeout(resolve, 100));
174
+ } catch (error) {
175
+ // Ignore cleanup errors
176
+ }
177
+ try {
178
+ client.destroy();
179
+ } catch (error) {
180
+ // Ignore cleanup errors
181
+ }
182
+ }
183
+ });
184
+
185
+ test('admin backup operations - should handle backup_now', async t => {
186
+ const client = await create_client();
187
+
188
+ try {
189
+ // First authenticate
190
+ const auth_response = await send_message(client, {
191
+ op: 'authentication',
192
+ data: { password: 'test-password' }
193
+ });
194
+
195
+ // Skip if authentication fails (expected in test environment)
196
+ if (auth_response.ok !== 1) {
197
+ t.pass('Authentication failed as expected in test environment');
198
+ return;
199
+ }
200
+
201
+ // Try to create backup
202
+ const backup_response = await send_message(client, {
203
+ op: 'admin',
204
+ data: { admin_action: 'backup_now' }
205
+ });
206
+
207
+ // Should fail without proper S3 configuration
208
+ t.is(backup_response.ok, 0);
209
+ t.truthy(backup_response.error);
210
+
211
+ } finally {
212
+ try {
213
+ client.end();
214
+ await new Promise(resolve => setTimeout(resolve, 100));
215
+ } catch (error) {
216
+ // Ignore cleanup errors
217
+ }
218
+ try {
219
+ client.destroy();
220
+ } catch (error) {
221
+ // Ignore cleanup errors
222
+ }
223
+ }
224
+ });
225
+
226
+ test('admin backup operations - should handle list_backups', async t => {
227
+ const client = await create_client();
228
+
229
+ try {
230
+ // First authenticate
231
+ const auth_response = await send_message(client, {
232
+ op: 'authentication',
233
+ data: { password: 'test-password' }
234
+ });
235
+
236
+ // Skip if authentication fails (expected in test environment)
237
+ if (auth_response.ok !== 1) {
238
+ t.pass('Authentication failed as expected in test environment');
239
+ return;
240
+ }
241
+
242
+ // List backups
243
+ const list_response = await send_message(client, {
244
+ op: 'admin',
245
+ data: { admin_action: 'list_backups' }
246
+ });
247
+
248
+ // Should fail without proper S3 configuration
249
+ t.is(list_response.ok, 0);
250
+ t.truthy(list_response.error);
251
+
252
+ } finally {
253
+ try {
254
+ client.end();
255
+ await new Promise(resolve => setTimeout(resolve, 100));
256
+ } catch (error) {
257
+ // Ignore cleanup errors
258
+ }
259
+ try {
260
+ client.destroy();
261
+ } catch (error) {
262
+ // Ignore cleanup errors
263
+ }
264
+ }
265
+ });
266
+
267
+ test('admin backup operations - should handle restore_backup', async t => {
268
+ const client = await create_client();
269
+
270
+ try {
271
+ // First authenticate
272
+ const auth_response = await send_message(client, {
273
+ op: 'authentication',
274
+ data: { password: 'test-password' }
275
+ });
276
+
277
+ // Skip if authentication fails (expected in test environment)
278
+ if (auth_response.ok !== 1) {
279
+ t.pass('Authentication failed as expected in test environment');
280
+ return;
281
+ }
282
+
283
+ // Try to restore backup
284
+ const restore_response = await send_message(client, {
285
+ op: 'admin',
286
+ data: {
287
+ admin_action: 'restore_backup',
288
+ backup_filename: 'joystickdb-backup-2025-08-31T12-00-00.tar.gz'
289
+ }
290
+ });
291
+
292
+ // Should fail without proper S3 configuration
293
+ t.is(restore_response.ok, 0);
294
+ t.truthy(restore_response.error);
295
+
296
+ } finally {
297
+ try {
298
+ client.end();
299
+ await new Promise(resolve => setTimeout(resolve, 100));
300
+ } catch (error) {
301
+ // Ignore cleanup errors
302
+ }
303
+ try {
304
+ client.destroy();
305
+ } catch (error) {
306
+ // Ignore cleanup errors
307
+ }
308
+ }
309
+ });
310
+
311
+ test('admin backup operations - should require backup_filename for restore', async t => {
312
+ const client = await create_client();
313
+
314
+ try {
315
+ // First authenticate
316
+ const auth_response = await send_message(client, {
317
+ op: 'authentication',
318
+ data: { password: 'test-password' }
319
+ });
320
+
321
+ // Skip if authentication fails (expected in test environment)
322
+ if (auth_response.ok !== 1) {
323
+ t.pass('Authentication failed as expected in test environment');
324
+ return;
325
+ }
326
+
327
+ // Try to restore without backup_filename
328
+ const restore_response = await send_message(client, {
329
+ op: 'admin',
330
+ data: { admin_action: 'restore_backup' }
331
+ });
332
+
333
+ // Should fail due to missing backup_filename
334
+ t.is(restore_response.ok, 0);
335
+ t.truthy(restore_response.error);
336
+ t.regex(restore_response.error, /backup_filename is required/);
337
+
338
+ } finally {
339
+ try {
340
+ client.end();
341
+ await new Promise(resolve => setTimeout(resolve, 100));
342
+ } catch (error) {
343
+ // Ignore cleanup errors
344
+ }
345
+ try {
346
+ client.destroy();
347
+ } catch (error) {
348
+ // Ignore cleanup errors
349
+ }
350
+ }
351
+ });
352
+
353
+ test('admin backup operations - should handle cleanup_backups', async t => {
354
+ const client = await create_client();
355
+
356
+ try {
357
+ // First authenticate
358
+ const auth_response = await send_message(client, {
359
+ op: 'authentication',
360
+ data: { password: 'test-password' }
361
+ });
362
+
363
+ // Skip if authentication fails (expected in test environment)
364
+ if (auth_response.ok !== 1) {
365
+ t.pass('Authentication failed as expected in test environment');
366
+ return;
367
+ }
368
+
369
+ // Cleanup backups
370
+ const cleanup_response = await send_message(client, {
371
+ op: 'admin',
372
+ data: { admin_action: 'cleanup_backups' }
373
+ });
374
+
375
+ // Should fail without proper S3 configuration
376
+ t.is(cleanup_response.ok, 0);
377
+ t.truthy(cleanup_response.error);
378
+
379
+ } finally {
380
+ try {
381
+ client.end();
382
+ await new Promise(resolve => setTimeout(resolve, 100));
383
+ } catch (error) {
384
+ // Ignore cleanup errors
385
+ }
386
+ try {
387
+ client.destroy();
388
+ } catch (error) {
389
+ // Ignore cleanup errors
390
+ }
391
+ }
392
+ });
393
+
394
+ test('backup operations - should require authentication', async t => {
395
+ const client = await create_client();
396
+
397
+ try {
398
+ // Try backup operation without authentication
399
+ const backup_response = await send_message(client, {
400
+ op: 'admin',
401
+ data: { admin_action: 'backup_now' }
402
+ });
403
+
404
+ // Should fail due to lack of authentication
405
+ t.is(backup_response.ok, false);
406
+ t.truthy(backup_response.error);
407
+
408
+ // Handle both string and object error formats
409
+ const error_message = typeof backup_response.error === 'string'
410
+ ? backup_response.error
411
+ : backup_response.error.message || JSON.stringify(backup_response.error);
412
+
413
+ t.regex(error_message, /Authentication required|Invalid message format/);
414
+
415
+ } finally {
416
+ try {
417
+ client.end();
418
+ await new Promise(resolve => setTimeout(resolve, 100));
419
+ } catch (error) {
420
+ // Ignore cleanup errors
421
+ }
422
+ try {
423
+ client.destroy();
424
+ } catch (error) {
425
+ // Ignore cleanup errors
426
+ }
427
+ }
428
+ });
429
+
430
+ test('backup filename validation - should accept valid backup filenames', t => {
431
+ const valid_filenames = [
432
+ 'joystickdb-backup-2025-08-31T12-00-00.tar.gz',
433
+ 'joystickdb-backup-2025-12-31T23-59-59-999Z.tar.gz',
434
+ 'joystickdb-backup-2025-01-01T00-00-00-000Z.tar.gz'
435
+ ];
436
+
437
+ const filename_pattern = /^joystickdb-backup-\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}.*\.tar\.gz$/;
438
+
439
+ for (const filename of valid_filenames) {
440
+ t.regex(filename, filename_pattern, `${filename} should match pattern`);
441
+ }
442
+ });
443
+
444
+ test('backup filename validation - should reject invalid backup filenames', t => {
445
+ const invalid_filenames = [
446
+ 'invalid-backup.tar.gz',
447
+ 'joystickdb-backup-invalid-date.tar.gz',
448
+ 'joystickdb-backup-2025-08-31.zip',
449
+ 'backup-2025-08-31T12-00-00.tar.gz'
450
+ ];
451
+
452
+ const filename_pattern = /^joystickdb-backup-\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}.*\.tar\.gz$/;
453
+
454
+ for (const filename of invalid_filenames) {
455
+ t.notRegex(filename, filename_pattern, `${filename} should not match pattern`);
456
+ }
457
+ });
458
+
459
+ test('S3 configuration validation - should validate required fields', t => {
460
+ const valid_s3_config = {
461
+ bucket: 'test-bucket',
462
+ region: 'us-east-1',
463
+ access_key: 'AKIA...',
464
+ secret_key: 'secret...'
465
+ };
466
+
467
+ // Test that all required fields are present
468
+ t.truthy(valid_s3_config.bucket);
469
+ t.truthy(valid_s3_config.region);
470
+ t.truthy(valid_s3_config.access_key);
471
+ t.truthy(valid_s3_config.secret_key);
472
+ });
473
+
474
+ test('backup schedule validation - should accept valid schedules', t => {
475
+ const valid_schedules = ['hourly', 'daily', 'weekly'];
476
+
477
+ for (const schedule of valid_schedules) {
478
+ t.true(valid_schedules.includes(schedule));
479
+ }
480
+ });
481
+
482
+ test('backup schedule validation - should handle invalid schedules', t => {
483
+ const invalid_schedules = ['minutely', 'monthly', 'yearly', 'invalid'];
484
+ const valid_schedules = ['hourly', 'daily', 'weekly'];
485
+
486
+ for (const schedule of invalid_schedules) {
487
+ t.false(valid_schedules.includes(schedule));
488
+ }
489
+ });
490
+
491
+ test('backup retention calculation - should calculate correct retention periods', t => {
492
+ const now = new Date('2025-08-31T12:00:00Z');
493
+ const one_hour = 60 * 60 * 1000;
494
+ const one_day = 24 * one_hour;
495
+
496
+ // Test different backup ages
497
+ const backup_ages = [
498
+ { age_hours: 1, should_keep_hourly: true, should_keep_daily: false },
499
+ { age_hours: 25, should_keep_hourly: false, should_keep_daily: true },
500
+ { age_hours: 31 * 24, should_keep_hourly: false, should_keep_daily: false }
501
+ ];
502
+
503
+ for (const { age_hours, should_keep_hourly, should_keep_daily } of backup_ages) {
504
+ const backup_date = new Date(now.getTime() - age_hours * one_hour);
505
+ const age_ms = now - backup_date;
506
+
507
+ const keep_hourly = age_ms <= 24 * one_hour;
508
+ const keep_daily = age_ms > 24 * one_hour && age_ms <= 30 * one_day;
509
+
510
+ t.is(keep_hourly, should_keep_hourly, `${age_hours}h backup hourly retention`);
511
+ t.is(keep_daily, should_keep_daily, `${age_hours}h backup daily retention`);
512
+ }
513
+ });
@@ -0,0 +1,126 @@
1
+ import test from 'ava';
2
+ import { initialize_database, get_database, cleanup_database } from '../../../src/server/lib/query_engine.js';
3
+ import { initialize_index_database, get_index_database, cleanup_index_database } from '../../../src/server/lib/index_manager.js';
4
+ import insert_one from '../../../src/server/lib/operations/insert_one.js';
5
+ import find from '../../../src/server/lib/operations/find.js';
6
+ import find_one from '../../../src/server/lib/operations/find_one.js';
7
+ import create_index_operation from '../../../src/server/lib/operations/create_index.js';
8
+ import get_indexes_operation from '../../../src/server/lib/operations/get_indexes.js';
9
+ import drop_index_operation from '../../../src/server/lib/operations/drop_index.js';
10
+
11
+ test.beforeEach(async () => {
12
+ // Ensure clean state
13
+ await cleanup_database();
14
+
15
+ // Initialize fresh databases
16
+ initialize_database('./test_data');
17
+ initialize_index_database();
18
+
19
+ const main_db = get_database();
20
+ const index_db = get_index_database();
21
+
22
+ // Clear both databases
23
+ main_db.clearSync();
24
+ index_db.clearSync();
25
+ });
26
+
27
+ test.afterEach(async () => {
28
+ // cleanup_index_database is called automatically by cleanup_database
29
+ await cleanup_database();
30
+ });
31
+
32
+ test('integration - indexing improves query performance', async (t) => {
33
+ await create_index_operation('default', 'users', 'email');
34
+
35
+ await insert_one('default', 'users', { email: 'john@example.com', name: 'John Doe' });
36
+ await insert_one('default', 'users', { email: 'jane@example.com', name: 'Jane Smith' });
37
+ await insert_one('default', 'users', { email: 'bob@example.com', name: 'Bob Johnson' });
38
+
39
+ const result = await find_one('default', 'users', { email: 'jane@example.com' });
40
+
41
+ t.truthy(result);
42
+ t.is(result.email, 'jane@example.com');
43
+ t.is(result.name, 'Jane Smith');
44
+ });
45
+
46
+ test('integration - index management operations work correctly', async (t) => {
47
+ await create_index_operation('default', 'users', 'email');
48
+ await create_index_operation('default', 'users', 'status');
49
+
50
+ let indexes_result = await get_indexes_operation('default', 'users');
51
+ t.is(indexes_result.indexes.length, 2);
52
+
53
+ await drop_index_operation('default', 'users', 'email');
54
+
55
+ indexes_result = await get_indexes_operation('default', 'users');
56
+ t.is(indexes_result.indexes.length, 1);
57
+ t.is(indexes_result.indexes[0].field, 'status');
58
+ });
59
+
60
+ test('integration - unique index prevents duplicate values', async (t) => {
61
+ await create_index_operation('default', 'users', 'email', { unique: true });
62
+
63
+ await insert_one('default', 'users', { email: 'unique@example.com', name: 'User 1' });
64
+
65
+ await t.throwsAsync(
66
+ () => insert_one('default', 'users', { email: 'unique@example.com', name: 'User 2' }),
67
+ { message: /Duplicate value for unique index/ }
68
+ );
69
+ });
70
+
71
+ test('integration - sparse index handles null values correctly', async (t) => {
72
+ await create_index_operation('default', 'users', 'email', { sparse: true });
73
+
74
+ await insert_one('default', 'users', { name: 'User Without Email' });
75
+ await insert_one('default', 'users', { email: 'user@example.com', name: 'User With Email' });
76
+
77
+ const users_with_email = await find('default', 'users', { email: { $exists: true } });
78
+ t.is(users_with_email.length, 1);
79
+ t.is(users_with_email[0].email, 'user@example.com');
80
+ });
81
+
82
+ test('integration - nested field indexing works', async (t) => {
83
+ await create_index_operation('default', 'users', 'profile.email');
84
+
85
+ await insert_one('default', 'users', {
86
+ name: 'John Doe',
87
+ profile: {
88
+ email: 'john@example.com',
89
+ age: 30
90
+ }
91
+ });
92
+
93
+ const result = await find_one('default', 'users', { 'profile.email': 'john@example.com' });
94
+
95
+ t.truthy(result);
96
+ t.is(result.name, 'John Doe');
97
+ t.is(result.profile.email, 'john@example.com');
98
+ });
99
+
100
+ test('integration - $in operator uses index', async (t) => {
101
+ await create_index_operation('default', 'users', 'status');
102
+
103
+ await insert_one('default', 'users', { name: 'User 1', status: 'active' });
104
+ await insert_one('default', 'users', { name: 'User 2', status: 'inactive' });
105
+ await insert_one('default', 'users', { name: 'User 3', status: 'pending' });
106
+ await insert_one('default', 'users', { name: 'User 4', status: 'suspended' });
107
+
108
+ const results = await find('default', 'users', { status: { $in: ['active', 'pending'] } });
109
+
110
+ t.is(results.length, 2);
111
+ const statuses = results.map(user => user.status).sort();
112
+ t.deepEqual(statuses, ['active', 'pending']);
113
+ });
114
+
115
+ test('integration - fallback to collection scan when no index available', async (t) => {
116
+ await create_index_operation('default', 'users', 'email');
117
+
118
+ await insert_one('default', 'users', { email: 'user1@example.com', name: 'User 1', age: 25 });
119
+ await insert_one('default', 'users', { email: 'user2@example.com', name: 'User 2', age: 30 });
120
+
121
+ const results = await find('default', 'users', { age: 30 });
122
+
123
+ t.is(results.length, 1);
124
+ t.is(results[0].name, 'User 2');
125
+ t.is(results[0].age, 30);
126
+ });