@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,651 @@
1
+ import test from 'ava';
2
+ import sinon from 'sinon';
3
+ import net from 'net';
4
+ import { encode as encode_messagepack } from 'msgpackr';
5
+ import { parse_data, check_op_type, create_server } from '../../src/server/index.js';
6
+ import op_types from '../../src/server/lib/op_types.js';
7
+ import { load_settings, get_settings } from '../../src/server/lib/load_settings.js';
8
+ import { reset_auth_state } from '../../src/server/lib/auth_manager.js';
9
+
10
+ test.beforeEach(() => {
11
+ // Reset auth state and clean up environment variables
12
+ reset_auth_state();
13
+ delete process.env.JOYSTICK_DB_SETTINGS;
14
+ });
15
+
16
+ test.afterEach(() => {
17
+ // Clean up environment variables after each test
18
+ reset_auth_state();
19
+ delete process.env.JOYSTICK_DB_SETTINGS;
20
+ });
21
+
22
+ test('setup operation creates authentication and returns password', async (t) => {
23
+ const { setup } = await import('../../src/server/index.js');
24
+
25
+ let response_data = null;
26
+ const mock_socket = {
27
+ write: (data) => {
28
+ response_data = data;
29
+ },
30
+ end: sinon.stub()
31
+ };
32
+
33
+ await setup(mock_socket, {});
34
+
35
+ // Verify authentication environment variable was created
36
+ t.true(process.env.JOYSTICK_DB_SETTINGS !== undefined);
37
+
38
+ // Verify response was sent
39
+ t.truthy(response_data);
40
+
41
+ // Parse the response to check structure
42
+ const response_string = response_data.toString();
43
+ t.true(response_string.includes('Authentication setup completed'));
44
+ });
45
+
46
+ test('setup operation handles already configured authentication', async (t) => {
47
+ const { setup } = await import('../../src/server/index.js');
48
+ const { setup_authentication } = await import('../../src/server/lib/auth_manager.js');
49
+
50
+ // Setup authentication first
51
+ setup_authentication();
52
+
53
+ let response_data = null;
54
+ const mock_socket = {
55
+ write: (data) => {
56
+ response_data = data;
57
+ },
58
+ end: sinon.stub()
59
+ };
60
+
61
+ await setup(mock_socket, {});
62
+
63
+ // Verify error response was sent
64
+ t.truthy(response_data);
65
+
66
+ const response_string = response_data.toString();
67
+ t.true(response_string.includes('Authentication already configured'));
68
+ });
69
+
70
+ test('authentication operation requires password in data', async (t) => {
71
+ const { authentication } = await import('../../src/server/index.js');
72
+
73
+ let response_data = null;
74
+ const mock_socket = {
75
+ id: 'test-socket',
76
+ write: (data) => {
77
+ response_data = data;
78
+ },
79
+ end: sinon.stub()
80
+ };
81
+
82
+ await authentication(mock_socket, {});
83
+
84
+ // Verify error response was sent and socket was closed
85
+ t.truthy(response_data);
86
+ t.true(mock_socket.end.calledOnce);
87
+
88
+ const response_string = response_data.toString();
89
+ t.true(response_string.includes('Authentication operation requires password to be set in data'));
90
+ });
91
+
92
+ test('authentication operation succeeds with correct password', async (t) => {
93
+ const { authentication } = await import('../../src/server/index.js');
94
+ const { setup_authentication } = await import('../../src/server/lib/auth_manager.js');
95
+
96
+ // Setup authentication first
97
+ const password = setup_authentication();
98
+
99
+ let response_data = null;
100
+ const mock_socket = {
101
+ id: 'test-socket',
102
+ remoteAddress: '127.0.0.1',
103
+ write: (data) => {
104
+ response_data = data;
105
+ },
106
+ end: sinon.stub()
107
+ };
108
+
109
+ await authentication(mock_socket, { password });
110
+
111
+ // Verify success response was sent and socket was NOT closed
112
+ t.truthy(response_data);
113
+ t.false(mock_socket.end.called);
114
+
115
+ const response_string = response_data.toString();
116
+ t.true(response_string.includes('Authentication successful'));
117
+ t.true(response_string.includes('1.0.0'));
118
+ });
119
+
120
+ test('authentication operation fails with incorrect password', async (t) => {
121
+ const { authentication } = await import('../../src/server/index.js');
122
+ const { setup_authentication } = await import('../../src/server/lib/auth_manager.js');
123
+
124
+ // Setup authentication first
125
+ setup_authentication();
126
+
127
+ let response_data = null;
128
+ const mock_socket = {
129
+ id: 'test-socket',
130
+ remoteAddress: '192.168.1.100',
131
+ write: (data) => {
132
+ response_data = data;
133
+ },
134
+ end: sinon.stub()
135
+ };
136
+
137
+ await authentication(mock_socket, { password: 'wrong_password' });
138
+
139
+ // Verify error response was sent and socket was closed
140
+ t.truthy(response_data);
141
+ t.true(mock_socket.end.calledOnce);
142
+
143
+ const response_string = response_data.toString();
144
+ t.true(response_string.includes('Authentication failed'));
145
+ });
146
+
147
+ test('authentication operation handles rate limiting', async (t) => {
148
+ const { authentication } = await import('../../src/server/index.js');
149
+ const { setup_authentication } = await import('../../src/server/lib/auth_manager.js');
150
+
151
+ // Setup authentication first
152
+ setup_authentication();
153
+
154
+ let response_data = null;
155
+ const mock_socket = {
156
+ id: 'test-socket',
157
+ remoteAddress: '192.168.1.100',
158
+ write: (data) => {
159
+ response_data = data;
160
+ },
161
+ end: sinon.stub()
162
+ };
163
+
164
+ // Make 5 failed attempts to trigger rate limiting
165
+ for (let i = 0; i < 5; i++) {
166
+ await authentication(mock_socket, { password: 'wrong_password' });
167
+ }
168
+
169
+ // Reset for the rate limited attempt
170
+ response_data = null;
171
+ mock_socket.end.resetHistory();
172
+
173
+ // 6th attempt should be rate limited
174
+ await authentication(mock_socket, { password: 'wrong_password' });
175
+
176
+ // Verify rate limiting error response was sent and socket was closed
177
+ t.truthy(response_data);
178
+ t.true(mock_socket.end.calledOnce);
179
+
180
+ const response_string = response_data.toString();
181
+ t.true(response_string.includes('Too many failed attempts'));
182
+ });
183
+
184
+ test('parse_data processes valid messagepack with JSON data', (t = {}) => {
185
+ const json_data = { name: "test", value: 123 };
186
+ const json_string = JSON.stringify(json_data);
187
+ const messagepack_data = encode_messagepack(json_string);
188
+ const raw_data = Buffer.from(messagepack_data);
189
+
190
+ const result = parse_data(raw_data);
191
+
192
+ t.deepEqual(result, json_data);
193
+ });
194
+
195
+ test('check_op_type returns true for valid operation types', (t = {}) => {
196
+ op_types.forEach((op_type) => {
197
+ const result = check_op_type(op_type);
198
+ t.true(result, `Expected ${op_type} to be valid`);
199
+ });
200
+ });
201
+
202
+ test('check_op_type validates setup operation type', (t = {}) => {
203
+ const result = check_op_type('setup');
204
+ t.true(result);
205
+ });
206
+
207
+ test('check_op_type validates authentication operation type', (t = {}) => {
208
+ const result = check_op_type('authentication');
209
+ t.true(result);
210
+ });
211
+
212
+ test('check_op_type returns false for invalid operation types', (t = {}) => {
213
+ const invalid_op_types = [
214
+ "invalid_op",
215
+ "unknown",
216
+ "select",
217
+ "create",
218
+ "drop",
219
+ "alter",
220
+ "FIND_ONE",
221
+ "Authentication",
222
+ "ping_test"
223
+ ];
224
+
225
+ invalid_op_types.forEach((op_type) => {
226
+ const result = check_op_type(op_type);
227
+ t.false(result, `Expected ${op_type} to be invalid`);
228
+ });
229
+ });
230
+
231
+ test('check_op_type throws error when no op_type is provided', (t = {}) => {
232
+ const error = t.throws(() => {
233
+ check_op_type();
234
+ });
235
+
236
+ t.is(error.message, 'Must pass an op type for operation.');
237
+ });
238
+
239
+ test('check_op_type throws error when empty string is provided', (t = {}) => {
240
+ const error = t.throws(() => {
241
+ check_op_type('');
242
+ });
243
+
244
+ t.is(error.message, 'Must pass an op type for operation.');
245
+ });
246
+
247
+ test('check_op_type throws error when null is provided', (t = {}) => {
248
+ const error = t.throws(() => {
249
+ check_op_type(null);
250
+ });
251
+
252
+ t.is(error.message, 'Must pass an op type for operation.');
253
+ });
254
+
255
+ test('check_op_type throws error when undefined is provided', (t = {}) => {
256
+ const error = t.throws(() => {
257
+ check_op_type(undefined);
258
+ });
259
+
260
+ t.is(error.message, 'Must pass an op type for operation.');
261
+ });
262
+
263
+ test('check_op_type handles non-string input types', (t = {}) => {
264
+ const non_string_inputs = [
265
+ 123,
266
+ true,
267
+ {},
268
+ [],
269
+ Symbol('test')
270
+ ];
271
+
272
+ non_string_inputs.forEach((input) => {
273
+ const result = check_op_type(input);
274
+ t.false(result, `Expected ${typeof input} input to be invalid`);
275
+ });
276
+ });
277
+
278
+ test('parse_data processes messagepack with array JSON', (t = {}) => {
279
+ const json_data = [1, 2, 3, "test"];
280
+ const json_string = JSON.stringify(json_data);
281
+ const messagepack_data = encode_messagepack(json_string);
282
+ const raw_data = Buffer.from(messagepack_data);
283
+
284
+ const result = parse_data(raw_data);
285
+
286
+ t.deepEqual(result, json_data);
287
+ });
288
+
289
+ test('parse_data processes messagepack with primitive JSON values', (t = {}) => {
290
+ const test_cases = [
291
+ { input: true, expected: true },
292
+ { input: false, expected: false },
293
+ { input: null, expected: null },
294
+ { input: 42, expected: 42 },
295
+ { input: "hello", expected: "hello" }
296
+ ];
297
+
298
+ test_cases.forEach(({ input, expected }) => {
299
+ const json_string = JSON.stringify(input);
300
+ const messagepack_data = encode_messagepack(json_string);
301
+ const raw_data = Buffer.from(messagepack_data);
302
+
303
+ const result = parse_data(raw_data);
304
+
305
+ t.is(result, expected);
306
+ });
307
+ });
308
+
309
+ test('parse_data returns null for messagepack with invalid JSON', (t = {}) => {
310
+ const invalid_json = '{"name": "test", "value":}';
311
+ const messagepack_data = encode_messagepack(invalid_json);
312
+ const raw_data = Buffer.from(messagepack_data);
313
+
314
+ const result = parse_data(raw_data);
315
+
316
+ t.is(result, null);
317
+ });
318
+
319
+ test('parse_data returns null for messagepack with empty string', (t = {}) => {
320
+ const empty_string = '';
321
+ const messagepack_data = encode_messagepack(empty_string);
322
+ const raw_data = Buffer.from(messagepack_data);
323
+
324
+ const result = parse_data(raw_data);
325
+
326
+ t.is(result, null);
327
+ });
328
+
329
+ test('parse_data processes complex nested JSON objects', (t = {}) => {
330
+ const complex_data = {
331
+ user: {
332
+ id: 1,
333
+ name: "John Doe",
334
+ preferences: {
335
+ theme: "dark",
336
+ notifications: true
337
+ }
338
+ },
339
+ items: [
340
+ { id: 1, name: "Item 1" },
341
+ { id: 2, name: "Item 2" }
342
+ ]
343
+ };
344
+
345
+ const json_string = JSON.stringify(complex_data);
346
+ const messagepack_data = encode_messagepack(json_string);
347
+ const raw_data = Buffer.from(messagepack_data);
348
+
349
+ const result = parse_data(raw_data);
350
+
351
+ t.deepEqual(result, complex_data);
352
+ });
353
+
354
+ test('parse_data processes buffer input as raw_data', (t = {}) => {
355
+ const json_data = { message: "test" };
356
+ const json_string = JSON.stringify(json_data);
357
+ const messagepack_data = encode_messagepack(json_string);
358
+ const raw_data_buffer = Buffer.from(messagepack_data);
359
+
360
+ const result = parse_data(raw_data_buffer);
361
+
362
+ t.deepEqual(result, json_data);
363
+ });
364
+
365
+ test('parse_data handles messagepack with JSON containing special characters', (t = {}) => {
366
+ const json_data = {
367
+ message: "Hello \"world\" with 'quotes' and \n newlines",
368
+ unicode: "🚀 Unicode test 中文",
369
+ escaped: "Line 1\nLine 2\tTabbed"
370
+ };
371
+
372
+ const json_string = JSON.stringify(json_data);
373
+ const messagepack_data = encode_messagepack(json_string);
374
+ const raw_data = Buffer.from(messagepack_data);
375
+
376
+ const result = parse_data(raw_data);
377
+
378
+ t.deepEqual(result, json_data);
379
+ });
380
+
381
+ test('admin operation requires authentication', (t) => {
382
+ const mock_socket = {
383
+ id: 'unauthenticated-socket',
384
+ write: sinon.stub(),
385
+ end: sinon.stub()
386
+ };
387
+
388
+ const send_error_stub = sinon.stub();
389
+
390
+ const authenticated_clients = new Set();
391
+
392
+ const check_authentication = (socket) => {
393
+ return authenticated_clients.has(socket.id);
394
+ };
395
+
396
+ const is_authenticated = check_authentication(mock_socket);
397
+
398
+ t.false(is_authenticated);
399
+
400
+ if (!is_authenticated) {
401
+ send_error_stub(mock_socket, { message: 'Authentication required' });
402
+ }
403
+
404
+ t.true(send_error_stub.calledOnce);
405
+ t.true(send_error_stub.calledWith(mock_socket, { message: 'Authentication required' }));
406
+ });
407
+
408
+ test('admin operation returns server information structure', (t) => {
409
+ const mock_db = {
410
+ getStats: () => ({ pages: 100, entries: 50 }),
411
+ getRange: () => [
412
+ { key: 'users:1' },
413
+ { key: 'users:2' },
414
+ { key: 'posts:1' },
415
+ { key: 'posts:2' },
416
+ { key: 'posts:3' }
417
+ ]
418
+ };
419
+
420
+ const mock_settings = {
421
+ port: 1983,
422
+ cluster: true
423
+ };
424
+
425
+ const collections = new Map();
426
+ let total_documents = 0;
427
+
428
+ for (const { key } of mock_db.getRange()) {
429
+ if (typeof key === 'string' && key.includes(':')) {
430
+ const collection_name = key.split(':')[0];
431
+ collections.set(collection_name, (collections.get(collection_name) || 0) + 1);
432
+ total_documents++;
433
+ }
434
+ }
435
+
436
+ const admin_info = {
437
+ server: {
438
+ uptime: process.uptime(),
439
+ memory_usage: process.memoryUsage(),
440
+ node_version: process.version,
441
+ platform: process.platform,
442
+ pid: process.pid
443
+ },
444
+ database: {
445
+ total_documents,
446
+ collections: Object.fromEntries(collections),
447
+ stats: mock_db.getStats()
448
+ },
449
+ authentication: {
450
+ authenticated_clients: 0
451
+ },
452
+ settings: {
453
+ port: mock_settings.port || 1983,
454
+ cluster_enabled: !!mock_settings.cluster
455
+ }
456
+ };
457
+
458
+ t.is(typeof admin_info.server.uptime, 'number');
459
+ t.is(typeof admin_info.server.memory_usage, 'object');
460
+ t.is(typeof admin_info.server.node_version, 'string');
461
+ t.is(typeof admin_info.server.platform, 'string');
462
+ t.is(typeof admin_info.server.pid, 'number');
463
+ t.is(admin_info.database.total_documents, 5);
464
+ t.deepEqual(admin_info.database.collections, { users: 2, posts: 3 });
465
+ t.deepEqual(admin_info.database.stats, { pages: 100, entries: 50 });
466
+ t.is(admin_info.authentication.authenticated_clients, 0);
467
+ t.is(admin_info.settings.port, 1983);
468
+ t.true(admin_info.settings.cluster_enabled);
469
+ });
470
+
471
+ test('admin operation handles database without getStats method', (t) => {
472
+ const mock_db = {
473
+ getRange: () => [
474
+ { key: 'users:1' },
475
+ { key: 'posts:1' }
476
+ ]
477
+ };
478
+
479
+ const stats = mock_db.getStats ? mock_db.getStats() : {};
480
+ const collections = new Map();
481
+ let total_documents = 0;
482
+
483
+ for (const { key } of mock_db.getRange()) {
484
+ if (typeof key === 'string' && key.includes(':')) {
485
+ const collection_name = key.split(':')[0];
486
+ collections.set(collection_name, (collections.get(collection_name) || 0) + 1);
487
+ total_documents++;
488
+ }
489
+ }
490
+
491
+ t.deepEqual(stats, {});
492
+ t.is(total_documents, 2);
493
+ t.deepEqual(Object.fromEntries(collections), { users: 1, posts: 1 });
494
+ });
495
+
496
+ test('admin operation counts authenticated clients correctly', (t) => {
497
+ const authenticated_clients = new Set(['socket1', 'socket2', 'socket3']);
498
+
499
+ const admin_info = {
500
+ authentication: {
501
+ authenticated_clients: authenticated_clients.size
502
+ }
503
+ };
504
+
505
+ t.is(admin_info.authentication.authenticated_clients, 3);
506
+ });
507
+
508
+ test('reload operation requires authentication', (t) => {
509
+ const mock_socket = {
510
+ id: 'unauthenticated-socket',
511
+ write: sinon.stub(),
512
+ end: sinon.stub()
513
+ };
514
+
515
+ const send_error_stub = sinon.stub();
516
+
517
+ const authenticated_clients = new Set();
518
+
519
+ const check_authentication = (socket) => {
520
+ return authenticated_clients.has(socket.id);
521
+ };
522
+
523
+ const is_authenticated = check_authentication(mock_socket);
524
+
525
+ t.false(is_authenticated);
526
+
527
+ if (!is_authenticated) {
528
+ send_error_stub(mock_socket, { message: 'Authentication required' });
529
+ }
530
+
531
+ t.true(send_error_stub.calledOnce);
532
+ t.true(send_error_stub.calledWith(mock_socket, { message: 'Authentication required' }));
533
+ });
534
+
535
+ test('reload operation detects configuration changes', (t) => {
536
+ const old_settings = {
537
+ port: 1983,
538
+ authentication: { password_hash: 'old-hash' },
539
+ cluster: false
540
+ };
541
+
542
+ const new_settings = {
543
+ port: 2000,
544
+ authentication: { password_hash: 'new-hash' },
545
+ cluster: true
546
+ };
547
+
548
+ const reload_info = {
549
+ status: 'success',
550
+ message: 'Configuration reloaded successfully',
551
+ changes: {
552
+ port_changed: old_settings.port !== new_settings.port,
553
+ authentication_changed: old_settings.authentication?.password_hash !== new_settings.authentication?.password_hash,
554
+ cluster_changed: old_settings.cluster !== new_settings.cluster
555
+ },
556
+ timestamp: new Date().toISOString()
557
+ };
558
+
559
+ t.is(reload_info.status, 'success');
560
+ t.is(reload_info.message, 'Configuration reloaded successfully');
561
+ t.true(reload_info.changes.port_changed);
562
+ t.true(reload_info.changes.authentication_changed);
563
+ t.true(reload_info.changes.cluster_changed);
564
+ t.is(typeof reload_info.timestamp, 'string');
565
+ });
566
+
567
+ test('reload operation detects no changes when settings are identical', (t) => {
568
+ const old_settings = {
569
+ port: 1983,
570
+ authentication: { password_hash: 'same-hash' },
571
+ cluster: true
572
+ };
573
+
574
+ const new_settings = {
575
+ port: 1983,
576
+ authentication: { password_hash: 'same-hash' },
577
+ cluster: true
578
+ };
579
+
580
+ const reload_info = {
581
+ status: 'success',
582
+ message: 'Configuration reloaded successfully',
583
+ changes: {
584
+ port_changed: old_settings.port !== new_settings.port,
585
+ authentication_changed: old_settings.authentication?.password_hash !== new_settings.authentication?.password_hash,
586
+ cluster_changed: old_settings.cluster !== new_settings.cluster
587
+ },
588
+ timestamp: new Date().toISOString()
589
+ };
590
+
591
+ t.is(reload_info.status, 'success');
592
+ t.false(reload_info.changes.port_changed);
593
+ t.false(reload_info.changes.authentication_changed);
594
+ t.false(reload_info.changes.cluster_changed);
595
+ });
596
+
597
+ test('reload operation handles missing authentication in old settings', (t) => {
598
+ const old_settings = {
599
+ port: 1983,
600
+ cluster: false
601
+ };
602
+
603
+ const new_settings = {
604
+ port: 1983,
605
+ authentication: { password_hash: 'new-hash' },
606
+ cluster: false
607
+ };
608
+
609
+ const reload_info = {
610
+ status: 'success',
611
+ message: 'Configuration reloaded successfully',
612
+ changes: {
613
+ port_changed: old_settings.port !== new_settings.port,
614
+ authentication_changed: old_settings.authentication?.password_hash !== new_settings.authentication?.password_hash,
615
+ cluster_changed: old_settings.cluster !== new_settings.cluster
616
+ },
617
+ timestamp: new Date().toISOString()
618
+ };
619
+
620
+ t.false(reload_info.changes.port_changed);
621
+ t.true(reload_info.changes.authentication_changed);
622
+ t.false(reload_info.changes.cluster_changed);
623
+ });
624
+
625
+ test('reload operation handles missing authentication in new settings', (t) => {
626
+ const old_settings = {
627
+ port: 1983,
628
+ authentication: { password_hash: 'old-hash' },
629
+ cluster: false
630
+ };
631
+
632
+ const new_settings = {
633
+ port: 1983,
634
+ cluster: false
635
+ };
636
+
637
+ const reload_info = {
638
+ status: 'success',
639
+ message: 'Configuration reloaded successfully',
640
+ changes: {
641
+ port_changed: old_settings.port !== new_settings.port,
642
+ authentication_changed: old_settings.authentication?.password_hash !== new_settings.authentication?.password_hash,
643
+ cluster_changed: old_settings.cluster !== new_settings.cluster
644
+ },
645
+ timestamp: new Date().toISOString()
646
+ };
647
+
648
+ t.false(reload_info.changes.port_changed);
649
+ t.true(reload_info.changes.authentication_changed);
650
+ t.false(reload_info.changes.cluster_changed);
651
+ });