@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,537 @@
1
+ /**
2
+ * @fileoverview Cluster worker process for JoystickDB server.
3
+ * Handles TCP connections, client authentication, and routes operations to master process.
4
+ * Manages socket connections, message parsing, and graceful shutdown in worker processes.
5
+ */
6
+
7
+ import net from 'net';
8
+ import op_types from '../lib/op_types.js';
9
+ import { send_success, send_error, send_message } from '../lib/send_response.js';
10
+ import { shutdown_write_queue } from '../lib/write_queue.js';
11
+ import { create_message_parser, encode_message } from '../lib/tcp_protocol.js';
12
+ import create_logger from '../lib/logger.js';
13
+ import { initialize_database, cleanup_database } from '../lib/query_engine.js';
14
+ import { handle_admin_operation, handle_ping_operation } from '../lib/operation_dispatcher.js';
15
+
16
+ /**
17
+ * Cluster worker process that handles TCP connections and routes operations to master.
18
+ * Manages client connections, authentication, and message routing in a clustered environment.
19
+ */
20
+ class ClusterWorker {
21
+ /**
22
+ * Creates a new cluster worker instance.
23
+ * Initializes connection management, authentication tracking, and sets up process event handlers.
24
+ */
25
+ constructor() {
26
+ this.server = null;
27
+ this.connections = new Map();
28
+ this.connection_count = 0;
29
+ this.settings = null;
30
+ this.port = null;
31
+ this.write_id_counter = 0;
32
+ this.pending_writes = new Map();
33
+ this.authenticated_clients = new Set();
34
+ this.heartbeat_interval = null;
35
+
36
+ const { create_context_logger } = create_logger('worker');
37
+ this.log = create_context_logger({ worker_pid: process.pid });
38
+
39
+ this.setup_worker();
40
+ }
41
+
42
+ setup_worker() {
43
+ process.on('message', (message) => {
44
+ this.handle_master_message(message);
45
+ });
46
+
47
+ process.on('SIGTERM', () => {
48
+ this.shutdown();
49
+ });
50
+
51
+ process.on('SIGINT', () => {
52
+ this.shutdown();
53
+ });
54
+
55
+ this.send_heartbeat();
56
+
57
+ this.heartbeat_interval = setInterval(() => {
58
+ this.send_heartbeat();
59
+ }, 5000);
60
+
61
+ // NOTE: Signal to master that worker is ready to receive config.
62
+ if (process.connected) {
63
+ process.send({ type: 'worker_ready' });
64
+ }
65
+ }
66
+
67
+ handle_master_message(message) {
68
+ switch (message.type) {
69
+ case 'config':
70
+ this.handle_config(message);
71
+ break;
72
+
73
+ case 'write_response':
74
+ this.handle_write_response(message);
75
+ break;
76
+
77
+ case 'auth_response':
78
+ this.handle_auth_response(message);
79
+ break;
80
+
81
+ case 'setup_response':
82
+ this.handle_setup_response(message);
83
+ break;
84
+
85
+ case 'write_notification':
86
+ this.handle_write_notification(message);
87
+ break;
88
+
89
+ case 'shutdown':
90
+ this.shutdown();
91
+ break;
92
+
93
+ default:
94
+ this.log.warn('Unknown message type received from master', {
95
+ message_type: message.type
96
+ });
97
+ }
98
+ }
99
+
100
+ handle_config(message) {
101
+ const incoming_master_id = message.data.master_id;
102
+
103
+ // NOTE: Only handle config from the first master to avoid conflicts between multiple test masters.
104
+ if (this.master_id && this.master_id !== incoming_master_id) {
105
+ this.log.info('Worker already configured by different master, ignoring config message', {
106
+ current_master_id: this.master_id,
107
+ incoming_master_id: incoming_master_id,
108
+ current_port: this.port,
109
+ new_port: message.data.port
110
+ });
111
+ return;
112
+ }
113
+
114
+ // NOTE: If already configured by the same master, ignore duplicate config.
115
+ if (this.port !== null && this.master_id === incoming_master_id) {
116
+ this.log.info('Worker already configured by same master, ignoring duplicate config message', {
117
+ master_id: incoming_master_id,
118
+ current_port: this.port,
119
+ new_port: message.data.port
120
+ });
121
+ return;
122
+ }
123
+
124
+ this.log.info('Received config message', {
125
+ port: message.data.port,
126
+ master_id: incoming_master_id
127
+ });
128
+ this.port = message.data.port;
129
+ this.settings = message.data.settings;
130
+ this.master_id = incoming_master_id;
131
+
132
+ // NOTE: Initialize database for read operations in worker process.
133
+ try {
134
+ initialize_database();
135
+ this.log.info('Database initialized in worker process');
136
+ } catch (error) {
137
+ this.log.error('Failed to initialize database in worker process', { error: error.message });
138
+ }
139
+
140
+ this.log.info('Starting server', { port: this.port });
141
+ this.start_server();
142
+ }
143
+
144
+ start_server() {
145
+ this.server = net.createServer((socket) => {
146
+ this.handle_connection(socket);
147
+ });
148
+
149
+ this.server.listen(this.port, () => {
150
+ this.log.info('Server listening', { port: this.port });
151
+ if (process.connected) {
152
+ process.send({ type: 'server_ready' });
153
+ }
154
+ });
155
+
156
+ this.server.on('error', (error) => {
157
+ this.log.error('Server error', { error: error.message });
158
+ });
159
+ }
160
+
161
+ handle_connection(socket) {
162
+ const socket_id = `${process.pid}_${Date.now()}_${Math.random()}`;
163
+ socket.id = socket_id;
164
+
165
+ // NOTE: Create message parser for this socket to handle length-prefixed MessagePack messages.
166
+ socket.message_parser = create_message_parser();
167
+
168
+ this.connections.set(socket_id, socket);
169
+ this.connection_count++;
170
+ this.update_connection_count();
171
+
172
+ socket.on('data', (raw_data) => {
173
+ this.handle_socket_data(socket, raw_data);
174
+ });
175
+
176
+ socket.on('end', () => {
177
+ this.handle_socket_end(socket);
178
+ });
179
+
180
+ socket.on('error', (error) => {
181
+ this.log.error('Socket error', { socket_id, error_message: error.message });
182
+ this.handle_socket_end(socket);
183
+ });
184
+ }
185
+
186
+ handle_socket_data(socket, raw_data) {
187
+ try {
188
+ // NOTE: Use the message parser to handle length-prefixed MessagePack messages.
189
+ const messages = socket.message_parser.parse_messages(raw_data);
190
+
191
+ for (const message of messages) {
192
+ // NOTE: Message is already decoded from MessagePack by the message parser.
193
+ const parsed_data = message;
194
+ const op_type = parsed_data?.op || null;
195
+
196
+ if (!op_type) {
197
+ send_error(socket, { message: 'Missing operation type' });
198
+ continue;
199
+ }
200
+
201
+ const is_valid_op_type = this.check_op_type(op_type);
202
+
203
+ if (!is_valid_op_type) {
204
+ send_error(socket, { message: 'Invalid operation type' });
205
+ continue;
206
+ }
207
+
208
+ this.route_operation(socket, op_type, parsed_data?.data || {});
209
+ }
210
+
211
+ } catch (error) {
212
+ this.log.error('Data parsing error', {
213
+ socket_id: socket.id,
214
+ error_message: error.message
215
+ });
216
+ send_error(socket, { message: 'Invalid data format' });
217
+ }
218
+ }
219
+
220
+ handle_socket_end(socket) {
221
+ if (socket.id) {
222
+ this.connections.delete(socket.id);
223
+ this.authenticated_clients.delete(socket.id);
224
+ this.connection_count--;
225
+ this.update_connection_count();
226
+ }
227
+ this.log.info('Client disconnected', { socket_id: socket.id });
228
+ }
229
+
230
+
231
+ check_op_type(op_type = '') {
232
+ if (!op_type) {
233
+ return false;
234
+ }
235
+ return op_types.includes(op_type);
236
+ }
237
+
238
+ route_operation(socket, op_type, data) {
239
+ switch (op_type) {
240
+ case 'authentication':
241
+ this.handle_authentication(socket, data);
242
+ break;
243
+ case 'setup':
244
+ this.handle_setup(socket, data);
245
+ break;
246
+ case 'find_one':
247
+ case 'find':
248
+ case 'get_indexes':
249
+ // NOTE: Route read operations through master for consistency.
250
+ this.handle_read_operation(socket, op_type, data);
251
+ break;
252
+ case 'create_index':
253
+ case 'drop_index':
254
+ // NOTE: Index operations are write operations, route through master.
255
+ this.handle_write_operation(socket, op_type, data);
256
+ break;
257
+ case 'insert_one':
258
+ case 'update_one':
259
+ case 'delete_one':
260
+ case 'bulk_write':
261
+ this.handle_write_operation(socket, op_type, data);
262
+ break;
263
+ case 'ping':
264
+ handle_ping_operation(socket);
265
+ break;
266
+ case 'admin':
267
+ // NOTE: Use shared operation dispatcher for admin operations.
268
+ handle_admin_operation(socket, data, this.is_authenticated.bind(this));
269
+ break;
270
+ default:
271
+ send_error(socket, { message: `Unsupported operation: ${op_type}` });
272
+ }
273
+ }
274
+
275
+ handle_authentication(socket, data) {
276
+ if (!this.is_authenticated(socket)) {
277
+ const auth_id = `${socket.id}_${Date.now()}`;
278
+
279
+ process.send({
280
+ type: 'auth_request',
281
+ data: {
282
+ auth_id,
283
+ socket_id: socket.id,
284
+ password: data.password
285
+ }
286
+ });
287
+
288
+ this.pending_writes.set(auth_id, { socket, type: 'auth' });
289
+ } else {
290
+ send_message(socket, 'Already authenticated');
291
+ }
292
+ }
293
+
294
+ handle_setup(socket, data) {
295
+ // NOTE: Forward setup request to master process.
296
+ const setup_id = `${socket.id}_${Date.now()}`;
297
+
298
+ process.send({
299
+ type: 'setup_request',
300
+ data: {
301
+ setup_id,
302
+ socket_id: socket.id
303
+ }
304
+ });
305
+
306
+ this.pending_writes.set(setup_id, { socket, type: 'setup' });
307
+ }
308
+
309
+
310
+ handle_read_operation(socket, op_type, data) {
311
+ if (!this.is_authenticated(socket)) {
312
+ send_error(socket, { message: 'Authentication required' });
313
+ return;
314
+ }
315
+
316
+ const read_id = `${socket.id}_${++this.write_id_counter}`;
317
+
318
+ process.send({
319
+ type: 'write_request',
320
+ data: {
321
+ write_id: read_id,
322
+ op_type,
323
+ data,
324
+ socket_id: socket.id
325
+ }
326
+ });
327
+
328
+ this.pending_writes.set(read_id, { socket, type: 'read' });
329
+ }
330
+
331
+ handle_write_operation(socket, op_type, data) {
332
+ if (!this.is_authenticated(socket)) {
333
+ send_error(socket, { message: 'Authentication required' });
334
+ return;
335
+ }
336
+
337
+ const write_id = `${socket.id}_${++this.write_id_counter}`;
338
+
339
+ process.send({
340
+ type: 'write_request',
341
+ data: {
342
+ write_id,
343
+ op_type,
344
+ data,
345
+ socket_id: socket.id
346
+ }
347
+ });
348
+
349
+ this.pending_writes.set(write_id, { socket, type: 'write' });
350
+ }
351
+
352
+
353
+
354
+
355
+ handle_write_response(message) {
356
+ const { write_id, success, result, error } = message.data;
357
+ const pending_write = this.pending_writes.get(write_id);
358
+
359
+ if (!pending_write) {
360
+ this.log.warn('No pending write found', { write_id });
361
+ return;
362
+ }
363
+
364
+ const { socket } = pending_write;
365
+ this.pending_writes.delete(write_id);
366
+
367
+ // NOTE: Check if socket is still connected before sending response.
368
+ if (socket.destroyed || !socket.writable) {
369
+ this.log.warn('Socket disconnected before response could be sent', { write_id });
370
+ return;
371
+ }
372
+
373
+ try {
374
+ if (success) {
375
+ // NOTE: Handle different result types properly
376
+ let response;
377
+ if (Array.isArray(result)) {
378
+ // For find operations that return arrays directly
379
+ response = { ok: 1, documents: result };
380
+ } else if (result && typeof result === 'object') {
381
+ // For operations that return objects, spread them
382
+ response = { ok: 1, ...result };
383
+ } else {
384
+ // For simple values
385
+ response = { ok: 1, result };
386
+ }
387
+ const encoded_response = encode_message(response);
388
+ socket.write(encoded_response);
389
+ } else {
390
+ const error_response = { ok: 0, error: error };
391
+ const encoded_error_response = encode_message(error_response);
392
+ socket.write(encoded_error_response);
393
+ }
394
+ } catch (write_error) {
395
+ this.log.error('Error sending response to client', {
396
+ write_id,
397
+ error: write_error.message
398
+ });
399
+ }
400
+ }
401
+
402
+ handle_auth_response(message) {
403
+ const { auth_id, success, message: auth_message } = message.data;
404
+ const pending_auth = this.pending_writes.get(auth_id);
405
+
406
+ if (!pending_auth) {
407
+ this.log.warn('No pending auth found', { auth_id });
408
+ return;
409
+ }
410
+
411
+ const { socket } = pending_auth;
412
+ this.pending_writes.delete(auth_id);
413
+
414
+ // NOTE: Check if socket is still connected before sending response.
415
+ if (socket.destroyed || !socket.writable) {
416
+ this.log.warn('Socket disconnected before auth response could be sent', { auth_id });
417
+ return;
418
+ }
419
+
420
+ try {
421
+ if (success) {
422
+ this.authenticated_clients.add(socket.id);
423
+ const auth_response = {
424
+ ok: 1,
425
+ version: "1.0.0",
426
+ message: auth_message
427
+ };
428
+ const encoded_auth_response = encode_message(auth_response);
429
+ socket.write(encoded_auth_response);
430
+ } else {
431
+ send_error(socket, { message: auth_message });
432
+ socket.end();
433
+ }
434
+ } catch (write_error) {
435
+ this.log.error('Error sending auth response to client', {
436
+ auth_id,
437
+ error: write_error.message
438
+ });
439
+ }
440
+ }
441
+
442
+ handle_setup_response(message) {
443
+ const { setup_id, success, password, message: setup_message, error } = message.data;
444
+ const pending_setup = this.pending_writes.get(setup_id);
445
+
446
+ if (!pending_setup) {
447
+ this.log.warn('No pending setup found', { setup_id });
448
+ return;
449
+ }
450
+
451
+ const { socket } = pending_setup;
452
+ this.pending_writes.delete(setup_id);
453
+
454
+ if (success) {
455
+ send_success(socket, {
456
+ password,
457
+ message: setup_message
458
+ });
459
+ } else {
460
+ send_error(socket, { message: error });
461
+ }
462
+ }
463
+
464
+ handle_write_notification(message) {
465
+ this.log.info('Received write notification', {
466
+ op_type: message.data.op_type,
467
+ timestamp: message.data.timestamp
468
+ });
469
+ }
470
+
471
+ is_authenticated(socket) {
472
+ return this.authenticated_clients.has(socket.id);
473
+ }
474
+
475
+ update_connection_count() {
476
+ if (process.connected) {
477
+ process.send({
478
+ type: 'connection_count',
479
+ data: { count: this.connection_count }
480
+ });
481
+ }
482
+ }
483
+
484
+ send_heartbeat() {
485
+ if (process.connected) {
486
+ try {
487
+ process.send({
488
+ type: 'heartbeat',
489
+ data: { timestamp: Date.now() }
490
+ });
491
+ } catch (error) {
492
+ clearInterval(this.heartbeat_interval);
493
+ }
494
+ }
495
+ }
496
+
497
+ async shutdown() {
498
+ const shutdown_start = Date.now();
499
+ this.log.info('Initiating graceful shutdown');
500
+
501
+ try {
502
+ await shutdown_write_queue();
503
+ this.log.info('Write queue shutdown complete');
504
+ } catch (error) {
505
+ this.log.error('Error shutting down write queue', { error: error.message });
506
+ }
507
+
508
+ // NOTE: Cleanup database before shutting down.
509
+ try {
510
+ await cleanup_database();
511
+ this.log.info('Database cleanup complete');
512
+ } catch (error) {
513
+ this.log.error('Error cleaning up database', { error: error.message });
514
+ }
515
+
516
+ if (this.server) {
517
+ this.server.close(() => {
518
+ this.log.info('Server closed');
519
+ });
520
+ }
521
+
522
+ for (const [_socket_id, socket] of this.connections) {
523
+ socket.end();
524
+ }
525
+
526
+ // NOTE: Use shorter timeout for tests to prevent test timeouts.
527
+ const shutdown_timeout = process.env.NODE_ENV === 'test' ? 100 : 5000;
528
+
529
+ setTimeout(() => {
530
+ const shutdown_duration = Date.now() - shutdown_start;
531
+ this.log.info('Worker shutdown complete', { shutdown_duration_ms: shutdown_duration });
532
+ process.exit(0);
533
+ }, shutdown_timeout);
534
+ }
535
+ }
536
+
537
+ const worker = new ClusterWorker();