@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,143 @@
1
+ /**
2
+ * @fileoverview Settings management utilities for loading and caching JoystickDB configuration.
3
+ * Provides functions to load, cache, reload, and clear settings from process.env.JOYSTICK_DB_SETTINGS.
4
+ * This allows the database server to be started as a child process with configuration passed via environment variables.
5
+ */
6
+
7
+ /** @type {Object|null} Cached settings object */
8
+ let cached_settings = null;
9
+
10
+ /**
11
+ * Validates port configuration in settings.
12
+ * @param {Object} settings - Settings object to validate
13
+ * @throws {Error} When port configuration is invalid
14
+ */
15
+ const validate_port_configuration = (settings) => {
16
+ if (settings.port !== undefined) {
17
+ if (!Number.isInteger(settings.port)) {
18
+ throw new Error('Port must be an integer');
19
+ }
20
+
21
+ if (settings.port < 1024) {
22
+ throw new Error('Port must be between 1024 and 65534 (HTTP port will be port + 1)');
23
+ }
24
+
25
+ const http_port = settings.port + 1;
26
+ if (http_port > 65535) {
27
+ throw new Error(`HTTP port (${http_port}) would exceed maximum port number (65535). Use a lower TCP port.`);
28
+ }
29
+
30
+ if (settings.port > 65534) {
31
+ throw new Error('Port must be between 1024 and 65534 (HTTP port will be port + 1)');
32
+ }
33
+ }
34
+ };
35
+
36
+ /**
37
+ * Loads JoystickDB settings from process.env.JOYSTICK_DB_SETTINGS and caches them.
38
+ * @returns {Object} Parsed JoystickDB settings object
39
+ * @throws {Error} When environment variable is missing or contains invalid JSON
40
+ */
41
+ export const load_settings = () => {
42
+ try {
43
+ const raw_settings = process.env.JOYSTICK_DB_SETTINGS;
44
+
45
+ if (!raw_settings) {
46
+ throw new Error('JOYSTICK_DB_SETTINGS environment variable is not set');
47
+ }
48
+
49
+ const parsed_settings = JSON.parse(raw_settings);
50
+
51
+ // NOTE: Validate port configuration if present.
52
+ validate_port_configuration(parsed_settings);
53
+
54
+ cached_settings = parsed_settings;
55
+
56
+ return cached_settings;
57
+ } catch (error) {
58
+ if (error instanceof SyntaxError) {
59
+ throw new Error(`Invalid JSON in JOYSTICK_DB_SETTINGS environment variable: ${error.message}`);
60
+ }
61
+
62
+ throw new Error(`Failed to load JoystickDB settings: ${error.message}`);
63
+ }
64
+ };
65
+
66
+ /**
67
+ * Gets the cached settings object.
68
+ * @returns {Object} Cached settings object
69
+ * @throws {Error} When settings haven't been loaded yet
70
+ */
71
+ export const get_settings = () => {
72
+ if (!cached_settings) {
73
+ throw new Error('Settings not loaded. Call load_settings() first.');
74
+ }
75
+
76
+ return cached_settings;
77
+ };
78
+
79
+ /**
80
+ * Reloads settings from process.env.JOYSTICK_DB_SETTINGS, clearing cache first.
81
+ * @returns {Object} Reloaded settings object
82
+ * @throws {Error} When environment variable loading fails
83
+ */
84
+ export const reload_settings = () => {
85
+ cached_settings = null;
86
+ return load_settings();
87
+ };
88
+
89
+ /**
90
+ * Clears the cached settings, forcing next load_settings call to read from environment variable.
91
+ */
92
+ export const clear_settings_cache = () => {
93
+ cached_settings = null;
94
+ };
95
+
96
+ /**
97
+ * Gets the current environment name from NODE_ENV.
98
+ * @returns {string} Current environment name
99
+ */
100
+ export const get_current_environment = () => {
101
+ return process.env.NODE_ENV || 'development';
102
+ };
103
+
104
+ /**
105
+ * Checks if JoystickDB settings are available in the environment.
106
+ * @returns {boolean} True if JOYSTICK_DB_SETTINGS environment variable is set
107
+ */
108
+ export const has_settings = () => {
109
+ return !!process.env.JOYSTICK_DB_SETTINGS;
110
+ };
111
+
112
+ /**
113
+ * Gets the configured TCP and HTTP ports from settings.
114
+ * @returns {Object} Port configuration with tcp_port and http_port
115
+ * @returns {number} returns.tcp_port - TCP server port
116
+ * @returns {number} returns.http_port - HTTP server port (tcp_port + 1)
117
+ */
118
+ export const get_port_configuration = () => {
119
+ let tcp_port = 1983; // Default TCP port
120
+
121
+ try {
122
+ // NOTE: Try to load settings if they haven't been loaded yet.
123
+ let settings;
124
+ try {
125
+ settings = get_settings();
126
+ } catch (error) {
127
+ // NOTE: Settings not loaded yet, try to load them.
128
+ load_settings();
129
+ settings = get_settings();
130
+ }
131
+
132
+ if (settings.port !== undefined) {
133
+ tcp_port = settings.port;
134
+ }
135
+ } catch (error) {
136
+ // NOTE: Settings not available or failed to load, use default port.
137
+ }
138
+
139
+ return {
140
+ tcp_port,
141
+ http_port: tcp_port + 1
142
+ };
143
+ };
@@ -0,0 +1,135 @@
1
+ import winston from 'winston';
2
+ import DailyRotateFile from 'winston-daily-rotate-file';
3
+ import path from 'path';
4
+ import { fileURLToPath } from 'url';
5
+
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = path.dirname(__filename);
8
+
9
+ const log_directory = path.join(__dirname, '../../../logs');
10
+
11
+ /**
12
+ * @typedef {Object} ContextLogger
13
+ * @property {function(string, Object): void} info - Log info message with context
14
+ * @property {function(string, Object): void} warn - Log warning message with context
15
+ * @property {function(string, Error|Object): void} error - Log error message with context or error object
16
+ * @property {function(string, Object): void} debug - Log debug message with context
17
+ * @property {function(string, number, Object): void} log_operation - Log operation completion with duration
18
+ * @property {function(string, string, Object): void} log_request - Log request with ID and operation
19
+ */
20
+
21
+ /**
22
+ * Creates a Winston logger instance with file rotation and console output.
23
+ * @param {string} [component='server'] - Component name for log identification
24
+ * @returns {Object} Object containing logger instance and context logger factory
25
+ * @returns {winston.Logger} returns.logger - Winston logger instance
26
+ * @returns {function(Object): ContextLogger} returns.create_context_logger - Factory for context loggers
27
+ */
28
+ const create_logger = (component = 'server') => {
29
+ const logger = winston.createLogger({
30
+ level: process.env.LOG_LEVEL || 'info',
31
+ format: winston.format.combine(
32
+ winston.format.timestamp({
33
+ format: 'YYYY-MM-DDTHH:mm:ss.SSSZ'
34
+ }),
35
+ winston.format.errors({ stack: true }),
36
+ winston.format.json(),
37
+ winston.format.printf((info) => {
38
+ const log_entry = {
39
+ timestamp: info.timestamp,
40
+ level: info.level,
41
+ component: component,
42
+ pid: process.pid,
43
+ message: info.message,
44
+ ...info.context && { context: info.context },
45
+ ...info.duration_ms && { duration_ms: info.duration_ms },
46
+ ...info.request_id && { request_id: info.request_id },
47
+ ...info.worker_id && { worker_id: info.worker_id },
48
+ ...info.stack && { stack: info.stack }
49
+ };
50
+
51
+ return JSON.stringify(log_entry);
52
+ })
53
+ ),
54
+ transports: [
55
+ new winston.transports.Console({
56
+ format: winston.format.printf((info) => {
57
+ const log_entry = {
58
+ level: info.level,
59
+ message: info.message,
60
+ ...info.context && { context: info.context },
61
+ ...info.duration_ms && { duration_ms: info.duration_ms },
62
+ ...info.request_id && { request_id: info.request_id },
63
+ ...info.worker_id && { worker_id: info.worker_id },
64
+ timestamp: info.timestamp
65
+ };
66
+
67
+ return JSON.stringify(log_entry);
68
+ })
69
+ }),
70
+ new DailyRotateFile({
71
+ filename: path.join(log_directory, `${component}-%DATE%.log`),
72
+ datePattern: 'YYYY-MM-DD',
73
+ zippedArchive: true,
74
+ maxSize: '20m',
75
+ maxFiles: '14d',
76
+ format: winston.format.json()
77
+ }),
78
+ new DailyRotateFile({
79
+ filename: path.join(log_directory, `${component}-error-%DATE%.log`),
80
+ datePattern: 'YYYY-MM-DD',
81
+ zippedArchive: true,
82
+ maxSize: '20m',
83
+ maxFiles: '30d',
84
+ level: 'error',
85
+ format: winston.format.json()
86
+ })
87
+ ]
88
+ });
89
+
90
+ /**
91
+ * Creates a context logger with predefined base context.
92
+ * @param {Object} [base_context={}] - Base context to include in all log messages
93
+ * @returns {ContextLogger} Context logger with info, warn, error, debug methods
94
+ */
95
+ const create_context_logger = (base_context = {}) => {
96
+ return {
97
+ info: (message, context = {}) => {
98
+ logger.info(message, { context: { ...base_context, ...context } });
99
+ },
100
+ warn: (message, context = {}) => {
101
+ logger.warn(message, { context: { ...base_context, ...context } });
102
+ },
103
+ error: (message, error_or_context = {}) => {
104
+ if (error_or_context instanceof Error) {
105
+ logger.error(message, {
106
+ context: base_context,
107
+ stack: error_or_context.stack,
108
+ error_message: error_or_context.message
109
+ });
110
+ } else {
111
+ logger.error(message, { context: { ...base_context, ...error_or_context } });
112
+ }
113
+ },
114
+ debug: (message, context = {}) => {
115
+ logger.debug(message, { context: { ...base_context, ...context } });
116
+ },
117
+ log_operation: (operation, duration_ms, context = {}) => {
118
+ logger.info(`Operation completed: ${operation}`, {
119
+ context: { ...base_context, ...context, operation },
120
+ duration_ms
121
+ });
122
+ },
123
+ log_request: (request_id, operation, context = {}) => {
124
+ logger.info(`Request: ${operation}`, {
125
+ request_id,
126
+ context: { ...base_context, ...context, operation }
127
+ });
128
+ }
129
+ };
130
+ };
131
+
132
+ return { logger, create_context_logger };
133
+ };
134
+
135
+ export default create_logger;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @fileoverview Supported operation types for JoystickDB server validation.
3
+ *
4
+ * Defines the complete list of valid operation types that the server can handle,
5
+ * used for request validation and operation routing.
6
+ */
7
+
8
+ /**
9
+ * Array of supported operation types for the JoystickDB server.
10
+ * @type {string[]}
11
+ */
12
+ const op_types = [
13
+ "authentication",
14
+ "setup",
15
+ "find_one",
16
+ "find",
17
+ "insert_one",
18
+ "update_one",
19
+ "delete_one",
20
+ "bulk_write",
21
+ "create_index",
22
+ "drop_index",
23
+ "get_indexes",
24
+ "admin",
25
+ "ping",
26
+ "reload",
27
+ ];
28
+
29
+ export default op_types;
@@ -0,0 +1,268 @@
1
+ /**
2
+ * @fileoverview Central operation dispatcher for routing and handling database and admin operations.
3
+ *
4
+ * Provides unified handling for all database operations (CRUD, indexing) and admin operations
5
+ * with authentication, performance monitoring, replication, and write forwarding support.
6
+ * Manages operation routing, error handling, and response formatting.
7
+ */
8
+
9
+ import { encode_message } from './tcp_protocol.js';
10
+ import { get_write_forwarder } from './write_forwarder.js';
11
+ import { get_replication_manager } from './replication_manager.js';
12
+ import { check_and_grow_map_size } from './query_engine.js';
13
+ import { performance_monitor } from './performance_monitor.js';
14
+ import create_logger from './logger.js';
15
+ import insert_one from './operations/insert_one.js';
16
+ import update_one from './operations/update_one.js';
17
+ import delete_one from './operations/delete_one.js';
18
+ import bulk_write from './operations/bulk_write.js';
19
+ import find_one from './operations/find_one.js';
20
+ import find from './operations/find.js';
21
+ import create_index_operation from './operations/create_index.js';
22
+ import drop_index_operation from './operations/drop_index.js';
23
+ import get_indexes_operation from './operations/get_indexes.js';
24
+ import admin_operation from './operations/admin.js';
25
+
26
+ const { create_context_logger } = create_logger('operation_dispatcher');
27
+
28
+ /**
29
+ * Validates database name according to naming rules.
30
+ * @param {string} database_name - Database name to validate
31
+ * @returns {boolean} True if valid, false otherwise
32
+ */
33
+ const validate_database_name = (database_name) => {
34
+ if (!database_name || typeof database_name !== 'string') {
35
+ return false;
36
+ }
37
+
38
+ // NOTE: Check length limit.
39
+ if (database_name.length > 64) {
40
+ return false;
41
+ }
42
+
43
+ // NOTE: Check for reserved names.
44
+ const reserved_names = ['admin', 'config', 'local'];
45
+ if (reserved_names.includes(database_name.toLowerCase())) {
46
+ return false;
47
+ }
48
+
49
+ // NOTE: Check naming convention (alphanumeric, underscores, hyphens).
50
+ const valid_name_pattern = /^[a-zA-Z0-9_-]+$/;
51
+ return valid_name_pattern.test(database_name);
52
+ };
53
+
54
+ /**
55
+ * Handles database operations (CRUD, indexing) with authentication, logging, and performance monitoring.
56
+ * @param {net.Socket} socket - Client socket connection
57
+ * @param {string} op_type - Type of database operation
58
+ * @param {Object} data - Operation data
59
+ * @param {Function} check_authentication - Function to check if socket is authenticated
60
+ * @param {number} [raw_data_size=0] - Size of raw request data for monitoring
61
+ * @param {Object} [connection_manager] - Connection manager instance (optional)
62
+ * @param {Set} [authenticated_clients] - Set of authenticated client IDs (optional)
63
+ */
64
+ export const handle_database_operation = async (socket, op_type, data, check_authentication, raw_data_size = 0, connection_manager = null, authenticated_clients = null) => {
65
+ const log = create_context_logger();
66
+ const start_time = Date.now();
67
+
68
+ if (!check_authentication(socket)) {
69
+ const response = { ok: 0, error: 'Authentication required' };
70
+ const encoded_response = encode_message(response);
71
+ socket.write(encoded_response);
72
+ performance_monitor.log_structured_operation(socket.id, op_type, null, 0, 'error', 'Authentication required', raw_data_size, 0);
73
+ return;
74
+ }
75
+
76
+ // NOTE: Extract and validate database name from request.
77
+ const database_name = data.database || 'default';
78
+
79
+ if (!validate_database_name(database_name)) {
80
+ const response = { ok: 0, error: 'Invalid database name. Database names must be alphanumeric with underscores/hyphens, max 64 characters, and cannot be reserved names (admin, config, local).' };
81
+ const encoded_response = encode_message(response);
82
+ socket.write(encoded_response);
83
+ performance_monitor.log_structured_operation(socket.id, op_type, data.collection, 0, 'error', 'Invalid database name', raw_data_size, 0);
84
+ return;
85
+ }
86
+
87
+ // NOTE: Check if this is a secondary node and should forward write operations.
88
+ const write_forwarder = get_write_forwarder();
89
+ const forwarded = await write_forwarder.forward_operation(socket, op_type, data);
90
+
91
+ if (forwarded) {
92
+ // Operation was forwarded to primary, response will be handled by forwarder
93
+ return;
94
+ }
95
+
96
+ try {
97
+ let result;
98
+
99
+ switch (op_type) {
100
+ case 'insert_one':
101
+ result = await insert_one(database_name, data.collection, data.document, data.options);
102
+ break;
103
+
104
+ case 'update_one':
105
+ result = await update_one(database_name, data.collection, data.filter, data.update, data.options);
106
+ break;
107
+
108
+ case 'delete_one':
109
+ result = await delete_one(database_name, data.collection, data.filter, data.options);
110
+ break;
111
+
112
+ case 'bulk_write':
113
+ result = await bulk_write(database_name, data.collection, data.operations, data.options);
114
+ break;
115
+
116
+ case 'find_one':
117
+ result = await find_one(database_name, data.collection, data.filter, data.options);
118
+ break;
119
+
120
+ case 'find':
121
+ result = await find(database_name, data.collection, data.filter, data.options);
122
+ break;
123
+
124
+ case 'create_index':
125
+ result = await create_index_operation(database_name, data.collection, data.field, data.options);
126
+ break;
127
+
128
+ case 'drop_index':
129
+ result = await drop_index_operation(database_name, data.collection, data.field);
130
+ break;
131
+
132
+ case 'get_indexes':
133
+ result = await get_indexes_operation(database_name, data.collection);
134
+ break;
135
+
136
+ default:
137
+ throw new Error(`Unsupported operation: ${op_type}`);
138
+ }
139
+
140
+ const duration_ms = Date.now() - start_time;
141
+
142
+ // NOTE: All operations now return structured responses for consistency.
143
+ let response;
144
+ if (op_type === 'find_one') {
145
+ response = { ok: 1, document: result };
146
+ } else if (op_type === 'find') {
147
+ response = { ok: 1, documents: result };
148
+ } else {
149
+ response = { ok: 1, ...result };
150
+ }
151
+
152
+ const encoded_response = encode_message(response);
153
+ const response_size = encoded_response.length;
154
+
155
+ socket.write(encoded_response);
156
+
157
+ // NOTE: Log structured operation with performance monitoring.
158
+ performance_monitor.log_structured_operation(
159
+ socket.id,
160
+ op_type,
161
+ data.collection,
162
+ duration_ms,
163
+ 'success',
164
+ null,
165
+ raw_data_size,
166
+ response_size
167
+ );
168
+
169
+ log.info('Database operation completed', {
170
+ client_id: socket.id,
171
+ op: op_type,
172
+ collection: data.collection,
173
+ duration_ms,
174
+ status: 'success',
175
+ request_size: raw_data_size,
176
+ response_size
177
+ });
178
+
179
+ // NOTE: Queue write operations for replication to secondary nodes.
180
+ if (op_type !== 'find' && op_type !== 'find_one' && op_type !== 'get_indexes') {
181
+ const replication_manager = get_replication_manager();
182
+ replication_manager.queue_replication(op_type, data.collection, data);
183
+
184
+ setImmediate(() => check_and_grow_map_size());
185
+ }
186
+ } catch (error) {
187
+ const duration_ms = Date.now() - start_time;
188
+
189
+ // NOTE: Log structured operation with error.
190
+ performance_monitor.log_structured_operation(
191
+ socket.id,
192
+ op_type,
193
+ data.collection,
194
+ duration_ms,
195
+ 'error',
196
+ error.message,
197
+ raw_data_size,
198
+ 0
199
+ );
200
+
201
+ log.error('Database operation failed', {
202
+ client_id: socket.id,
203
+ op: op_type,
204
+ collection: data.collection,
205
+ duration_ms,
206
+ status: 'error',
207
+ error: error.message,
208
+ request_size: raw_data_size
209
+ });
210
+
211
+ const error_response = { ok: 0, error: error.message };
212
+ const encoded_error_response = encode_message(error_response);
213
+ socket.write(encoded_error_response);
214
+ }
215
+ };
216
+
217
+ /**
218
+ * Handles admin operations with authentication and error handling.
219
+ * @param {net.Socket} socket - Client socket connection
220
+ * @param {Object} data - Admin operation data
221
+ * @param {Function} check_authentication - Function to check if socket is authenticated
222
+ * @param {Object} [connection_manager] - Connection manager instance (optional)
223
+ * @param {Set} [authenticated_clients] - Set of authenticated client IDs (optional)
224
+ */
225
+ export const handle_admin_operation = async (socket, data, check_authentication, connection_manager = null, authenticated_clients = null) => {
226
+ if (!check_authentication(socket)) {
227
+ // NOTE: Unauthenticated admin requests should return ok: false.
228
+ const response = { ok: false, error: 'Authentication required' };
229
+ const encoded_response = encode_message(response);
230
+ socket.write(encoded_response);
231
+ return;
232
+ }
233
+
234
+ try {
235
+ const admin_action = data?.admin_action;
236
+ const admin_data = data || {};
237
+
238
+ const result = await admin_operation(admin_action, admin_data, connection_manager, authenticated_clients);
239
+
240
+ // NOTE: Handle different response formats for admin operations.
241
+ if (!admin_action) {
242
+ // NOTE: Default admin operation (backward compatibility) - return result directly with ok: true.
243
+ const response = { ok: true, ...result };
244
+ const encoded_response = encode_message(response);
245
+ socket.write(encoded_response);
246
+ } else {
247
+ // NOTE: Specific admin actions - return result directly with ok: 1.
248
+ const response = { ok: 1, ...result };
249
+ const encoded_response = encode_message(response);
250
+ socket.write(encoded_response);
251
+ }
252
+ } catch (error) {
253
+ // NOTE: Admin operation errors use ok: 0.
254
+ const response = { ok: 0, error: `Admin operation failed: ${error.message}` };
255
+ const encoded_response = encode_message(response);
256
+ socket.write(encoded_response);
257
+ }
258
+ };
259
+
260
+ /**
261
+ * Handles ping operations.
262
+ * @param {net.Socket} socket - Client socket connection
263
+ */
264
+ export const handle_ping_operation = (socket) => {
265
+ const ping_response = { ok: 1 };
266
+ const encoded_ping_response = encode_message(ping_response);
267
+ socket.write(encoded_ping_response);
268
+ };