@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.
- package/.build/getFilesToBuild.js +26 -0
- package/.build/getPlatformSafeFilePath.js +6 -0
- package/.build/getPlatformSafePath.js +6 -0
- package/.build/index.js +88 -0
- package/.build/isWindows.js +3 -0
- package/API_KEY +1 -0
- package/README.md +1821 -0
- package/data/data.mdb +0 -0
- package/data/lock.mdb +0 -0
- package/dist/client/database.js +1 -0
- package/dist/client/index.js +1 -0
- package/dist/server/cluster/index.js +1 -0
- package/dist/server/cluster/master.js +20 -0
- package/dist/server/cluster/worker.js +1 -0
- package/dist/server/index.js +1 -0
- package/dist/server/lib/api_key_manager.js +9 -0
- package/dist/server/lib/auth_manager.js +1 -0
- package/dist/server/lib/auto_index_manager.js +1 -0
- package/dist/server/lib/backup_manager.js +1 -0
- package/dist/server/lib/connection_manager.js +1 -0
- package/dist/server/lib/disk_utils.js +2 -0
- package/dist/server/lib/http_server.js +405 -0
- package/dist/server/lib/index_manager.js +1 -0
- package/dist/server/lib/load_settings.js +1 -0
- package/dist/server/lib/logger.js +1 -0
- package/dist/server/lib/op_types.js +1 -0
- package/dist/server/lib/operation_dispatcher.js +1 -0
- package/dist/server/lib/operations/admin.js +1 -0
- package/dist/server/lib/operations/bulk_write.js +1 -0
- package/dist/server/lib/operations/create_index.js +1 -0
- package/dist/server/lib/operations/delete_one.js +1 -0
- package/dist/server/lib/operations/drop_index.js +1 -0
- package/dist/server/lib/operations/find.js +1 -0
- package/dist/server/lib/operations/find_one.js +1 -0
- package/dist/server/lib/operations/get_indexes.js +1 -0
- package/dist/server/lib/operations/insert_one.js +1 -0
- package/dist/server/lib/operations/update_one.js +1 -0
- package/dist/server/lib/performance_monitor.js +1 -0
- package/dist/server/lib/query_engine.js +1 -0
- package/dist/server/lib/recovery_manager.js +1 -0
- package/dist/server/lib/replication_manager.js +1 -0
- package/dist/server/lib/safe_json_parse.js +1 -0
- package/dist/server/lib/send_response.js +1 -0
- package/dist/server/lib/tcp_protocol.js +1 -0
- package/dist/server/lib/write_forwarder.js +1 -0
- package/dist/server/lib/write_queue.js +1 -0
- package/increment_version.js +3 -0
- package/logs/.013e15b54597d05db4b4b53ecc37b10c92a72927-audit.json +20 -0
- package/logs/.02de550a67ea0f5961faa2dfd458a4d06f59ebd1-audit.json +20 -0
- package/logs/.03494ba24eb3c72214b4068a77d54b8993bee651-audit.json +20 -0
- package/logs/.06309ec60b339be1259a7993dd09c732f8907fbc-audit.json +20 -0
- package/logs/.0663a04dcfa17285661e5e1b8cfa51f41523b210-audit.json +20 -0
- package/logs/.0f06e6c4c9b824622729e13927587479e5060391-audit.json +20 -0
- package/logs/.16ccf58682ecb22b3e3ec63f0da1b7fe9be56528-audit.json +20 -0
- package/logs/.1fa1a5d02f496474b1ab473524c65c984146a9ad-audit.json +20 -0
- package/logs/.2223c0ae3bea6f0d62c62b1d319cc8634856abb7-audit.json +20 -0
- package/logs/.23dc79ffda3e083665e6f5993f59397adcbf4a46-audit.json +20 -0
- package/logs/.28104f49b03906b189eefd1cd462cb46c3c0af22-audit.json +20 -0
- package/logs/.29cdbf13808abe6a0ce70ee2f2efdd680ce3fd8e-audit.json +20 -0
- package/logs/.2a9889afd071f77f41f5170d08703a0afca866b7-audit.json +20 -0
- package/logs/.2acec3d1940a2bbed487528b703ee5948959a599-audit.json +20 -0
- package/logs/.2fb60ff326338c02bfedbcd0e936444e4a216750-audit.json +20 -0
- package/logs/.318fc7a19530d76a345f030f7cad00dda15300e7-audit.json +20 -0
- package/logs/.3cf27043e19085f908cedc7701e6d013463208ee-audit.json +25 -0
- package/logs/.3d90d785415817fc443402843b7c95f8371adc9b-audit.json +20 -0
- package/logs/.4074bca620375f72966fc52dfd439577727671e5-audit.json +20 -0
- package/logs/.40eecf018417ea80a70ea8ec7a3cc9406bc6334b-audit.json +20 -0
- package/logs/.50e974f1ef7c365fca6a1251b2e2c2252914cb5e-audit.json +20 -0
- package/logs/.52cb7d9e4223cf26ba36006ac26b949a97c7923c-audit.json +20 -0
- package/logs/.54befcdb84c15aad980705a31bcc9f555c3577ab-audit.json +20 -0
- package/logs/.57dfb70e22eddb84db2e3c0ceeefac5c0b9baffa-audit.json +20 -0
- package/logs/.5f0b24705a1eaad4eca4968f2d86f91b3f9be683-audit.json +20 -0
- package/logs/.61ba98fdda7db58576b382fee07904e5db1169d6-audit.json +20 -0
- package/logs/.6235017727ef6b199d569a99d6aa8c8e80a1b475-audit.json +20 -0
- package/logs/.63db16193699219489d218a1ddea5dde3750cae4-audit.json +20 -0
- package/logs/.64fb67dfe14149c9eef728d79bf30a54da809c60-audit.json +20 -0
- package/logs/.669137453368987c1f311b5345342527afb54e50-audit.json +20 -0
- package/logs/.7a71f8c89ea28ae266d356aeff6306e876a30fbb-audit.json +20 -0
- package/logs/.7afbaa90fe9dc3a7d682676f9bb79f9a1b1fd9a6-audit.json +20 -0
- package/logs/.7ca29e322cd05327035de850099e7610864f2347-audit.json +20 -0
- package/logs/.83335ab3347e449dae03455a110aaf7f120d4802-audit.json +20 -0
- package/logs/.8c2487b5fd445d2c8e5c483c80b9fa99bbf1ca58-audit.json +20 -0
- package/logs/.8c8b9dc386922c9f3b4c13251af7052aac1d24c0-audit.json +20 -0
- package/logs/.8d6155d94640c4863301ae0fee5e4e7372a21446-audit.json +20 -0
- package/logs/.944a3119a243deea7c8270d5d9e582bb1d0eaa10-audit.json +20 -0
- package/logs/.9816a845c30fb2909f3b26a23eeb3538ebcad5db-audit.json +20 -0
- package/logs/.9dc08784e38b865488177c26d4af5934555e0323-audit.json +20 -0
- package/logs/.9dd27d2e0e454ac0a37600206d1cac5493b0d7ee-audit.json +20 -0
- package/logs/.a3d486feeac7654c59b547de96600e8849a06d4f-audit.json +20 -0
- package/logs/.a5b811f4def22250f86cc18870d7c4573625df22-audit.json +20 -0
- package/logs/.a61648eb5f830e0b6f508ac35e4f8f629d2ad4c7-audit.json +20 -0
- package/logs/.a89016d507045771b4b5a65656944a9c0f1e528b-audit.json +20 -0
- package/logs/.a99bee160a1c590be959af46bacc02724803f691-audit.json +20 -0
- package/logs/.ada7906d6243fd7da802f03d86c4ae5dd9df6236-audit.json +20 -0
- package/logs/.b518339ee942143b6af983af167f5bbb6983b4de-audit.json +20 -0
- package/logs/.b51b124b166d53c9519017856ea610d61d65fabe-audit.json +20 -0
- package/logs/.b7a6aee19f58e55633d5e4a3709041c47dfff975-audit.json +20 -0
- package/logs/.bd7a8a6ba9c55d557a4867ab53f02e3ec2e1553d-audit.json +20 -0
- package/logs/.c1435dafe453b169d6392b25065f3cf4ab6fbb21-audit.json +20 -0
- package/logs/.c17e1ce043109f77dc2f0e2aa290a9d1ed842c03-audit.json +20 -0
- package/logs/.ca62637ce9540e5a38a2fbedb2115febb6ad308a-audit.json +15 -0
- package/logs/.ccee67b9c176967f8977071409a41f5cb5cd6ad4-audit.json +20 -0
- package/logs/.db24043417ea79a6f14cd947476399e53930b48d-audit.json +20 -0
- package/logs/.e0f12acccb57829f5f33712bb2e2607ecd808147-audit.json +20 -0
- package/logs/.e9b6cc33d0bbd2e644c4e2bf44d177f850016557-audit.json +20 -0
- package/logs/.f15291d434808e3bdca7963ccd2e73893be027e6-audit.json +20 -0
- package/logs/.f4bdf9e21ef84f8a3fae3ffb32bbc39275991351-audit.json +15 -0
- package/logs/.fbac3aefac1e81b4230df5aa50667cb90d51024f-audit.json +20 -0
- package/logs/.fcfd495c0a9169db243f4a4f21878ee02b76413c-audit.json +20 -0
- package/logs/admin-2025-09-12.log +580 -0
- package/logs/admin-2025-09-15.log +283 -0
- package/logs/admin-error-2025-09-12.log +22 -0
- package/logs/admin-error-2025-09-15.log +10 -0
- package/logs/api_key_manager-2025-09-12.log +658 -0
- package/logs/api_key_manager-2025-09-15.log +295 -0
- package/logs/api_key_manager-error-2025-09-12.log +0 -0
- package/logs/api_key_manager-error-2025-09-15.log +0 -0
- package/logs/auth_manager-2025-09-12.log +4432 -0
- package/logs/auth_manager-2025-09-15.log +2000 -0
- package/logs/auth_manager-error-2025-09-12.log +11 -0
- package/logs/auth_manager-error-2025-09-15.log +5 -0
- package/logs/auto_index_manager-2025-09-12.log +84 -0
- package/logs/auto_index_manager-2025-09-15.log +45 -0
- package/logs/auto_index_manager-error-2025-09-12.log +6 -0
- package/logs/auto_index_manager-error-2025-09-15.log +0 -0
- package/logs/backup_manager-2025-09-12.log +198 -0
- package/logs/backup_manager-2025-09-15.log +90 -0
- package/logs/backup_manager-error-2025-09-12.log +198 -0
- package/logs/backup_manager-error-2025-09-15.log +90 -0
- package/logs/bulk_write-2025-09-12.log +66 -0
- package/logs/bulk_write-2025-09-15.log +38 -0
- package/logs/bulk_write-error-2025-09-12.log +0 -0
- package/logs/bulk_write-error-2025-09-15.log +0 -0
- package/logs/connection_manager-2025-09-12.log +2412 -0
- package/logs/connection_manager-2025-09-15.log +1132 -0
- package/logs/connection_manager-error-2025-09-12.log +0 -0
- package/logs/connection_manager-error-2025-09-15.log +0 -0
- package/logs/create_index-2025-09-12.log +302 -0
- package/logs/create_index-2025-09-15.log +158 -0
- package/logs/create_index-error-2025-09-12.log +30 -0
- package/logs/create_index-error-2025-09-15.log +13 -0
- package/logs/delete_one-2025-09-12.log +73 -0
- package/logs/delete_one-2025-09-15.log +43 -0
- package/logs/delete_one-error-2025-09-12.log +0 -0
- package/logs/delete_one-error-2025-09-15.log +0 -0
- package/logs/disk_utils-2025-09-12.log +4954 -0
- package/logs/disk_utils-2025-09-15.log +2446 -0
- package/logs/disk_utils-error-2025-09-12.log +0 -0
- package/logs/disk_utils-error-2025-09-15.log +0 -0
- package/logs/drop_index-2025-09-12.log +41 -0
- package/logs/drop_index-2025-09-15.log +23 -0
- package/logs/drop_index-error-2025-09-12.log +11 -0
- package/logs/drop_index-error-2025-09-15.log +5 -0
- package/logs/find-2025-09-12.log +1050 -0
- package/logs/find-2025-09-15.log +592 -0
- package/logs/find-error-2025-09-12.log +1 -0
- package/logs/find-error-2025-09-15.log +0 -0
- package/logs/find_one-2025-09-12.log +425 -0
- package/logs/find_one-2025-09-15.log +264 -0
- package/logs/find_one-error-2025-09-12.log +5 -0
- package/logs/find_one-error-2025-09-15.log +0 -0
- package/logs/get_indexes-2025-09-12.log +84 -0
- package/logs/get_indexes-2025-09-15.log +56 -0
- package/logs/get_indexes-error-2025-09-12.log +6 -0
- package/logs/get_indexes-error-2025-09-15.log +0 -0
- package/logs/http_server-2025-09-12.log +2772 -0
- package/logs/http_server-2025-09-15.log +1276 -0
- package/logs/http_server-error-2025-09-12.log +212 -0
- package/logs/http_server-error-2025-09-15.log +44 -0
- package/logs/index_manager-2025-09-12.log +5031 -0
- package/logs/index_manager-2025-09-15.log +2909 -0
- package/logs/index_manager-error-2025-09-12.log +80 -0
- package/logs/index_manager-error-2025-09-15.log +38 -0
- package/logs/insert_one-2025-09-12.log +2181 -0
- package/logs/insert_one-2025-09-15.log +1293 -0
- package/logs/insert_one-error-2025-09-12.log +0 -0
- package/logs/insert_one-error-2025-09-15.log +0 -0
- package/logs/master-2025-09-12.log +1882 -0
- package/logs/master-2025-09-15.log +910 -0
- package/logs/master-error-2025-09-12.log +80 -0
- package/logs/master-error-2025-09-15.log +0 -0
- package/logs/operation_dispatcher-2025-09-12.log +751 -0
- package/logs/operation_dispatcher-2025-09-15.log +359 -0
- package/logs/operation_dispatcher-error-2025-09-12.log +33 -0
- package/logs/operation_dispatcher-error-2025-09-15.log +11 -0
- package/logs/performance_monitor-2025-09-12.log +14889 -0
- package/logs/performance_monitor-2025-09-15.log +6803 -0
- package/logs/performance_monitor-error-2025-09-12.log +0 -0
- package/logs/performance_monitor-error-2025-09-15.log +0 -0
- package/logs/query_engine-2025-09-12.log +5310 -0
- package/logs/query_engine-2025-09-15.log +2639 -0
- package/logs/query_engine-error-2025-09-12.log +0 -0
- package/logs/query_engine-error-2025-09-15.log +0 -0
- package/logs/recovery_manager-2025-09-12.log +462 -0
- package/logs/recovery_manager-2025-09-15.log +210 -0
- package/logs/recovery_manager-error-2025-09-12.log +22 -0
- package/logs/recovery_manager-error-2025-09-15.log +10 -0
- package/logs/replication-2025-09-12.log +1923 -0
- package/logs/replication-2025-09-15.log +917 -0
- package/logs/replication-error-2025-09-12.log +33 -0
- package/logs/replication-error-2025-09-15.log +15 -0
- package/logs/server-2025-09-12.log +2601 -0
- package/logs/server-2025-09-15.log +1191 -0
- package/logs/server-error-2025-09-12.log +0 -0
- package/logs/server-error-2025-09-15.log +0 -0
- package/logs/tcp_protocol-2025-09-12.log +22 -0
- package/logs/tcp_protocol-2025-09-15.log +10 -0
- package/logs/tcp_protocol-error-2025-09-12.log +22 -0
- package/logs/tcp_protocol-error-2025-09-15.log +10 -0
- package/logs/test-2025-09-12.log +0 -0
- package/logs/test-2025-09-15.log +0 -0
- package/logs/test-error-2025-09-12.log +0 -0
- package/logs/test-error-2025-09-15.log +0 -0
- package/logs/update_one-2025-09-12.log +173 -0
- package/logs/update_one-2025-09-15.log +118 -0
- package/logs/update_one-error-2025-09-12.log +0 -0
- package/logs/update_one-error-2025-09-15.log +0 -0
- package/logs/worker-2025-09-12.log +1457 -0
- package/logs/worker-2025-09-15.log +695 -0
- package/logs/worker-error-2025-09-12.log +0 -0
- package/logs/worker-error-2025-09-15.log +0 -0
- package/logs/write_forwarder-2025-09-12.log +1956 -0
- package/logs/write_forwarder-2025-09-15.log +932 -0
- package/logs/write_forwarder-error-2025-09-12.log +66 -0
- package/logs/write_forwarder-error-2025-09-15.log +30 -0
- package/logs/write_queue-2025-09-12.log +612 -0
- package/logs/write_queue-2025-09-15.log +301 -0
- package/logs/write_queue-error-2025-09-12.log +184 -0
- package/logs/write_queue-error-2025-09-15.log +83 -0
- package/package.json +48 -0
- package/prompts/01-core-infrastructure.md +56 -0
- package/prompts/02-secondary-indexing.md +65 -0
- package/prompts/03-write-serialization.md +63 -0
- package/prompts/04-enhanced-authentication.md +75 -0
- package/prompts/05-comprehensive-admin-operations.md +75 -0
- package/prompts/06-backup-and-restore-system.md +106 -0
- package/prompts/07-production-safety-features.md +107 -0
- package/prompts/08-tcp-client-library.md +121 -0
- package/prompts/09-api-method-chaining.md +134 -0
- package/prompts/10-automatic-index-creation.md +223 -0
- package/prompts/11-operation-naming-consistency.md +268 -0
- package/prompts/12-tcp-replication-system.md +333 -0
- package/prompts/13-master-read-write-operations.md +57 -0
- package/prompts/14-index-upsert-operations.md +68 -0
- package/prompts/15-client-api-return-types.md +81 -0
- package/prompts/16-server-setup-ui.md +97 -0
- package/prompts/17-emergency-password-change.md +108 -0
- package/prompts/18-joystick-framework-integration.md +116 -0
- package/prompts/19-api-key-authentication-system.md +137 -0
- package/prompts/20-configurable-server-port.md +105 -0
- package/prompts/21-multi-database-support.md +161 -0
- package/prompts/FULL_TEXT_SEARCH.md +293 -0
- package/prompts/PROMPTS.md +158 -0
- package/prompts/README.md +221 -0
- package/prompts/TYPESCRIPT_GENERATION.md +179 -0
- package/src/client/database.js +166 -0
- package/src/client/index.js +752 -0
- package/src/server/cluster/index.js +53 -0
- package/src/server/cluster/master.js +774 -0
- package/src/server/cluster/worker.js +537 -0
- package/src/server/index.js +540 -0
- package/src/server/lib/api_key_manager.js +473 -0
- package/src/server/lib/auth_manager.js +375 -0
- package/src/server/lib/auto_index_manager.js +681 -0
- package/src/server/lib/backup_manager.js +650 -0
- package/src/server/lib/connection_manager.js +218 -0
- package/src/server/lib/disk_utils.js +118 -0
- package/src/server/lib/http_server.js +1165 -0
- package/src/server/lib/index_manager.js +756 -0
- package/src/server/lib/load_settings.js +143 -0
- package/src/server/lib/logger.js +135 -0
- package/src/server/lib/op_types.js +29 -0
- package/src/server/lib/operation_dispatcher.js +268 -0
- package/src/server/lib/operations/admin.js +808 -0
- package/src/server/lib/operations/bulk_write.js +367 -0
- package/src/server/lib/operations/create_index.js +68 -0
- package/src/server/lib/operations/delete_one.js +114 -0
- package/src/server/lib/operations/drop_index.js +58 -0
- package/src/server/lib/operations/find.js +340 -0
- package/src/server/lib/operations/find_one.js +319 -0
- package/src/server/lib/operations/get_indexes.js +52 -0
- package/src/server/lib/operations/insert_one.js +113 -0
- package/src/server/lib/operations/update_one.js +225 -0
- package/src/server/lib/performance_monitor.js +313 -0
- package/src/server/lib/query_engine.js +243 -0
- package/src/server/lib/recovery_manager.js +388 -0
- package/src/server/lib/replication_manager.js +727 -0
- package/src/server/lib/safe_json_parse.js +21 -0
- package/src/server/lib/send_response.js +47 -0
- package/src/server/lib/tcp_protocol.js +130 -0
- package/src/server/lib/write_forwarder.js +636 -0
- package/src/server/lib/write_queue.js +335 -0
- package/test_data/data.mdb +0 -0
- package/test_data/lock.mdb +0 -0
- package/tests/client/index.test.js +1232 -0
- package/tests/server/cluster/cluster.test.js +248 -0
- package/tests/server/cluster/master_read_write_operations.test.js +577 -0
- package/tests/server/index.test.js +651 -0
- package/tests/server/integration/authentication_integration.test.js +294 -0
- package/tests/server/integration/auto_indexing_integration.test.js +268 -0
- package/tests/server/integration/backup_integration.test.js +513 -0
- package/tests/server/integration/indexing_integration.test.js +126 -0
- package/tests/server/integration/production_safety_integration.test.js +358 -0
- package/tests/server/integration/replication_integration.test.js +227 -0
- package/tests/server/integration/write_serialization_integration.test.js +246 -0
- package/tests/server/lib/api_key_manager.test.js +516 -0
- package/tests/server/lib/auth_manager.test.js +317 -0
- package/tests/server/lib/auto_index_manager.test.js +275 -0
- package/tests/server/lib/backup_manager.test.js +238 -0
- package/tests/server/lib/connection_manager.test.js +221 -0
- package/tests/server/lib/disk_utils.test.js +63 -0
- package/tests/server/lib/http_server.test.js +389 -0
- package/tests/server/lib/index_manager.test.js +301 -0
- package/tests/server/lib/load_settings.test.js +107 -0
- package/tests/server/lib/load_settings_port_config.test.js +243 -0
- package/tests/server/lib/logger.test.js +282 -0
- package/tests/server/lib/operations/admin.test.js +638 -0
- package/tests/server/lib/operations/bulk_write.test.js +128 -0
- package/tests/server/lib/operations/create_index.test.js +138 -0
- package/tests/server/lib/operations/delete_one.test.js +52 -0
- package/tests/server/lib/operations/drop_index.test.js +72 -0
- package/tests/server/lib/operations/find.test.js +93 -0
- package/tests/server/lib/operations/find_one.test.js +91 -0
- package/tests/server/lib/operations/get_indexes.test.js +87 -0
- package/tests/server/lib/operations/insert_one.test.js +42 -0
- package/tests/server/lib/operations/update_one.test.js +89 -0
- package/tests/server/lib/performance_monitor.test.js +185 -0
- package/tests/server/lib/query_engine.test.js +46 -0
- package/tests/server/lib/recovery_manager.test.js +414 -0
- package/tests/server/lib/replication_manager.test.js +202 -0
- package/tests/server/lib/safe_json_parse.test.js +45 -0
- package/tests/server/lib/send_response.test.js +155 -0
- package/tests/server/lib/tcp_protocol.test.js +169 -0
- package/tests/server/lib/write_forwarder.test.js +258 -0
- package/tests/server/lib/write_queue.test.js +255 -0
- package/tsconfig.json +30 -0
- package/types/client/index.d.ts +447 -0
- package/types/server/cluster/index.d.ts +28 -0
- package/types/server/cluster/master.d.ts +115 -0
- package/types/server/cluster/worker.d.ts +1 -0
- package/types/server/lib/auth_manager.d.ts +13 -0
- package/types/server/lib/backup_manager.d.ts +43 -0
- package/types/server/lib/connection_manager.d.ts +15 -0
- package/types/server/lib/disk_utils.d.ts +3 -0
- package/types/server/lib/index_manager.d.ts +24 -0
- package/types/server/lib/load_settings.d.ts +4 -0
- package/types/server/lib/logger.d.ts +44 -0
- package/types/server/lib/op_types.d.ts +6 -0
- package/types/server/lib/performance_monitor.d.ts +68 -0
- package/types/server/lib/query_engine.d.ts +10 -0
- package/types/server/lib/safe_json_parse.d.ts +7 -0
- package/types/server/lib/send_response.d.ts +3 -0
- package/types/server/lib/tcp_protocol.d.ts +12 -0
- package/types/server/lib/write_queue.d.ts +2 -0
|
@@ -0,0 +1,540 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview JoystickDB TCP server implementation with clustering, authentication, and replication support.
|
|
3
|
+
*
|
|
4
|
+
* This is the main server entry point that handles TCP connections, message parsing, authentication,
|
|
5
|
+
* and routing operations to appropriate handlers. Supports clustering, backup/restore, replication,
|
|
6
|
+
* and comprehensive admin operations.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import net from 'net';
|
|
10
|
+
import { decode as decode_messagepack } from 'msgpackr';
|
|
11
|
+
import op_types from './lib/op_types.js';
|
|
12
|
+
import safe_json_parse from './lib/safe_json_parse.js';
|
|
13
|
+
import { load_settings, get_settings, get_port_configuration } from './lib/load_settings.js';
|
|
14
|
+
import { send_error } from './lib/send_response.js';
|
|
15
|
+
import { start_cluster } from './cluster/index.js';
|
|
16
|
+
import create_logger from './lib/logger.js';
|
|
17
|
+
import { initialize_database, cleanup_database } from './lib/query_engine.js';
|
|
18
|
+
import { create_message_parser, encode_message } from './lib/tcp_protocol.js';
|
|
19
|
+
import { create_connection_manager } from './lib/connection_manager.js';
|
|
20
|
+
import { shutdown_write_queue } from './lib/write_queue.js';
|
|
21
|
+
import {
|
|
22
|
+
setup_authentication,
|
|
23
|
+
verify_password,
|
|
24
|
+
get_client_ip,
|
|
25
|
+
is_rate_limited,
|
|
26
|
+
initialize_auth_manager,
|
|
27
|
+
reset_auth_state
|
|
28
|
+
} from './lib/auth_manager.js';
|
|
29
|
+
import {
|
|
30
|
+
initialize_api_key_manager,
|
|
31
|
+
verify_user_password,
|
|
32
|
+
check_admin_user_exists
|
|
33
|
+
} from './lib/api_key_manager.js';
|
|
34
|
+
import {
|
|
35
|
+
restore_backup,
|
|
36
|
+
start_backup_schedule,
|
|
37
|
+
stop_backup_schedule
|
|
38
|
+
} from './lib/backup_manager.js';
|
|
39
|
+
import {
|
|
40
|
+
initialize_replication_manager,
|
|
41
|
+
shutdown_replication_manager
|
|
42
|
+
} from './lib/replication_manager.js';
|
|
43
|
+
import {
|
|
44
|
+
initialize_write_forwarder,
|
|
45
|
+
shutdown_write_forwarder
|
|
46
|
+
} from './lib/write_forwarder.js';
|
|
47
|
+
import { handle_database_operation, handle_admin_operation, handle_ping_operation } from './lib/operation_dispatcher.js';
|
|
48
|
+
import { start_http_server, stop_http_server } from './lib/http_server.js';
|
|
49
|
+
import {
|
|
50
|
+
create_recovery_token,
|
|
51
|
+
initialize_recovery_manager,
|
|
52
|
+
reset_recovery_state
|
|
53
|
+
} from './lib/recovery_manager.js';
|
|
54
|
+
|
|
55
|
+
/** @type {Set<string>} Set of authenticated client socket IDs */
|
|
56
|
+
const authenticated_clients = new Set();
|
|
57
|
+
|
|
58
|
+
/** @type {Object|null} Connection manager instance */
|
|
59
|
+
let connection_manager = null;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Handles client authentication requests.
|
|
63
|
+
* @param {net.Socket} socket - Client socket connection
|
|
64
|
+
* @param {Object} [data={}] - Authentication data containing password
|
|
65
|
+
* @param {string} data.password - Client password for authentication
|
|
66
|
+
*/
|
|
67
|
+
export const authentication = async (socket, data = {}) => {
|
|
68
|
+
if (!data?.password) {
|
|
69
|
+
const response = { ok: 0, error: 'Authentication operation requires password to be set in data.' };
|
|
70
|
+
const encoded_response = encode_message(response);
|
|
71
|
+
socket.write(encoded_response);
|
|
72
|
+
socket.end();
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
const client_ip = get_client_ip(socket);
|
|
78
|
+
|
|
79
|
+
if (is_rate_limited(client_ip)) {
|
|
80
|
+
const response = { ok: 0, error: 'Too many failed attempts. Please try again later.' };
|
|
81
|
+
const encoded_response = encode_message(response);
|
|
82
|
+
socket.write(encoded_response);
|
|
83
|
+
socket.end();
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const is_valid = await verify_password(data.password, client_ip);
|
|
88
|
+
|
|
89
|
+
if (!is_valid) {
|
|
90
|
+
const response = { ok: 0, error: 'Authentication failed' };
|
|
91
|
+
const encoded_response = encode_message(response);
|
|
92
|
+
socket.write(encoded_response);
|
|
93
|
+
socket.end();
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
authenticated_clients.add(socket.id);
|
|
98
|
+
const auth_response = {
|
|
99
|
+
ok: 1,
|
|
100
|
+
version: "1.0.0",
|
|
101
|
+
message: 'Authentication successful'
|
|
102
|
+
};
|
|
103
|
+
const encoded_auth_response = encode_message(auth_response);
|
|
104
|
+
socket.write(encoded_auth_response);
|
|
105
|
+
} catch (error) {
|
|
106
|
+
const response = { ok: 0, error: `Authentication error: ${error.message}` };
|
|
107
|
+
const encoded_response = encode_message(response);
|
|
108
|
+
socket.write(encoded_response);
|
|
109
|
+
socket.end();
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Handles initial server setup, generating authentication password.
|
|
115
|
+
* @param {net.Socket} socket - Client socket connection
|
|
116
|
+
* @param {Object} [data={}] - Setup data (currently unused)
|
|
117
|
+
*/
|
|
118
|
+
export const setup = async (socket, data = {}) => {
|
|
119
|
+
try {
|
|
120
|
+
const password = setup_authentication();
|
|
121
|
+
|
|
122
|
+
// NOTE: Return response format expected by tests.
|
|
123
|
+
const response = {
|
|
124
|
+
ok: 1,
|
|
125
|
+
password,
|
|
126
|
+
message: 'Authentication setup completed successfully. Save this password - it will not be shown again.'
|
|
127
|
+
};
|
|
128
|
+
const encoded_response = encode_message(response);
|
|
129
|
+
socket.write(encoded_response);
|
|
130
|
+
} catch (error) {
|
|
131
|
+
const response = { ok: 0, error: `Setup error: ${error.message}` };
|
|
132
|
+
const encoded_response = encode_message(response);
|
|
133
|
+
socket.write(encoded_response);
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Validates if an operation type is supported.
|
|
139
|
+
* @param {string} [op_type=''] - Operation type to validate
|
|
140
|
+
* @returns {boolean} True if operation type is valid
|
|
141
|
+
* @throws {Error} When no operation type is provided
|
|
142
|
+
*/
|
|
143
|
+
export const check_op_type = (op_type = '') => {
|
|
144
|
+
if (!op_type) {
|
|
145
|
+
throw new Error('Must pass an op type for operation.');
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return op_types.includes(op_type);
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Parses raw data from various formats (string, Buffer, MessagePack) into JavaScript objects.
|
|
153
|
+
* @param {string|Buffer|Object} raw_data - Raw data to parse
|
|
154
|
+
* @returns {Object|null} Parsed data object or null if parsing fails
|
|
155
|
+
*/
|
|
156
|
+
export const parse_data = (raw_data) => {
|
|
157
|
+
try {
|
|
158
|
+
if (typeof raw_data === 'string') {
|
|
159
|
+
const data_as_json = safe_json_parse(raw_data);
|
|
160
|
+
return data_as_json;
|
|
161
|
+
} else if (Buffer.isBuffer(raw_data)) {
|
|
162
|
+
// NOTE: Decode MessagePack buffer and then parse as JSON.
|
|
163
|
+
const decoded_messagepack = decode_messagepack(raw_data);
|
|
164
|
+
if (typeof decoded_messagepack === 'string') {
|
|
165
|
+
return safe_json_parse(decoded_messagepack);
|
|
166
|
+
}
|
|
167
|
+
return decoded_messagepack;
|
|
168
|
+
} else {
|
|
169
|
+
// NOTE: raw_data is already decoded from MessagePack by the message parser.
|
|
170
|
+
return raw_data;
|
|
171
|
+
}
|
|
172
|
+
} catch (error) {
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Checks if a socket connection is authenticated.
|
|
179
|
+
* @param {net.Socket} socket - Socket connection to check
|
|
180
|
+
* @returns {boolean} True if socket is authenticated
|
|
181
|
+
*/
|
|
182
|
+
const check_authentication = (socket) => {
|
|
183
|
+
return authenticated_clients.has(socket.id);
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* @typedef {Object} ServerOptions
|
|
189
|
+
* @property {number} [worker_count] - Number of worker processes
|
|
190
|
+
* @property {number} [port=1983] - Server port
|
|
191
|
+
* @property {string} [environment] - Environment name for settings file (defaults to NODE_ENV)
|
|
192
|
+
*/
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Creates and configures the JoystickDB TCP server.
|
|
196
|
+
* @returns {Promise<net.Server>} Configured TCP server instance with cleanup method
|
|
197
|
+
*/
|
|
198
|
+
export const create_server = async () => {
|
|
199
|
+
const { create_context_logger } = create_logger('server');
|
|
200
|
+
const log = create_context_logger();
|
|
201
|
+
|
|
202
|
+
/*
|
|
203
|
+
NOTE:
|
|
204
|
+
Try to load settings, but don't fail if file doesn't exist (for tests).
|
|
205
|
+
*/
|
|
206
|
+
let settings = null;
|
|
207
|
+
try {
|
|
208
|
+
load_settings();
|
|
209
|
+
settings = get_settings();
|
|
210
|
+
} catch (error) {
|
|
211
|
+
/*
|
|
212
|
+
NOTE:
|
|
213
|
+
Settings file doesn't exist - this is OK for tests.
|
|
214
|
+
We'll handle missing settings in individual operations.
|
|
215
|
+
*/
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// NOTE: Handle startup restore if configured.
|
|
219
|
+
if (settings?.restore_from) {
|
|
220
|
+
try {
|
|
221
|
+
log.info('Startup restore requested', { backup_filename: settings.restore_from });
|
|
222
|
+
|
|
223
|
+
const restore_result = await restore_backup(settings.restore_from);
|
|
224
|
+
|
|
225
|
+
log.info('Startup restore completed', {
|
|
226
|
+
backup_filename: settings.restore_from,
|
|
227
|
+
duration_ms: restore_result.duration_ms
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// NOTE: Remove restore_from from settings after successful restore.
|
|
231
|
+
const updated_settings = { ...settings };
|
|
232
|
+
delete updated_settings.restore_from;
|
|
233
|
+
|
|
234
|
+
// NOTE: Update the environment variable with the new settings.
|
|
235
|
+
process.env.JOYSTICK_DB_SETTINGS = JSON.stringify(updated_settings);
|
|
236
|
+
|
|
237
|
+
// NOTE: Reload settings to reflect the change.
|
|
238
|
+
load_settings();
|
|
239
|
+
settings = get_settings();
|
|
240
|
+
|
|
241
|
+
log.info('Removed restore_from from settings after successful restore');
|
|
242
|
+
} catch (restore_error) {
|
|
243
|
+
log.error('Startup restore failed', {
|
|
244
|
+
backup_filename: settings.restore_from,
|
|
245
|
+
error: restore_error.message
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
// NOTE: Continue with fresh database if restore fails.
|
|
249
|
+
log.info('Continuing with fresh database after restore failure');
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
initialize_database();
|
|
254
|
+
initialize_auth_manager();
|
|
255
|
+
initialize_api_key_manager();
|
|
256
|
+
initialize_recovery_manager();
|
|
257
|
+
|
|
258
|
+
// NOTE: Initialize replication manager for primary nodes.
|
|
259
|
+
try {
|
|
260
|
+
initialize_replication_manager();
|
|
261
|
+
log.info('Replication manager initialized');
|
|
262
|
+
} catch (replication_error) {
|
|
263
|
+
log.warn('Failed to initialize replication manager', { error: replication_error.message });
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// NOTE: Initialize write forwarder for secondary nodes.
|
|
267
|
+
try {
|
|
268
|
+
initialize_write_forwarder();
|
|
269
|
+
log.info('Write forwarder initialized');
|
|
270
|
+
} catch (forwarder_error) {
|
|
271
|
+
log.warn('Failed to initialize write forwarder', { error: forwarder_error.message });
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// NOTE: Start backup scheduling if S3 is configured.
|
|
275
|
+
if (settings?.s3) {
|
|
276
|
+
try {
|
|
277
|
+
start_backup_schedule();
|
|
278
|
+
log.info('Backup scheduling started');
|
|
279
|
+
} catch (backup_schedule_error) {
|
|
280
|
+
log.warn('Failed to start backup scheduling', { error: backup_schedule_error.message });
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
connection_manager = create_connection_manager({
|
|
285
|
+
max_connections: 1000,
|
|
286
|
+
idle_timeout: 10 * 60 * 1000,
|
|
287
|
+
request_timeout: 5 * 1000
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
// NOTE: Start HTTP server for setup and recovery operations.
|
|
291
|
+
let http_server_instance = null;
|
|
292
|
+
try {
|
|
293
|
+
const { http_port } = get_port_configuration();
|
|
294
|
+
http_server_instance = await start_http_server(http_port);
|
|
295
|
+
if (http_server_instance) {
|
|
296
|
+
log.info('HTTP server started', { http_port });
|
|
297
|
+
}
|
|
298
|
+
} catch (http_error) {
|
|
299
|
+
log.warn('Failed to start HTTP server', { error: http_error.message });
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const server = net.createServer((socket = {}) => {
|
|
303
|
+
if (!connection_manager.add_connection(socket)) {
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const message_parser = create_message_parser();
|
|
308
|
+
|
|
309
|
+
socket.on('data', async (raw_data) => {
|
|
310
|
+
connection_manager.update_activity(socket.id);
|
|
311
|
+
|
|
312
|
+
try {
|
|
313
|
+
const messages = message_parser.parse_messages(raw_data);
|
|
314
|
+
|
|
315
|
+
for (const message of messages) {
|
|
316
|
+
// NOTE: Message is already decoded from MessagePack by the message parser.
|
|
317
|
+
const parsed_data = message;
|
|
318
|
+
const op_type = parsed_data?.op || null;
|
|
319
|
+
|
|
320
|
+
if (!op_type) {
|
|
321
|
+
send_error(socket, { message: 'Missing operation type' });
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
const is_valid_op_type = check_op_type(op_type);
|
|
326
|
+
|
|
327
|
+
if (!is_valid_op_type) {
|
|
328
|
+
send_error(socket, { message: 'Invalid operation type' });
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
const request_timeout = connection_manager.create_request_timeout(socket.id, op_type);
|
|
333
|
+
|
|
334
|
+
try {
|
|
335
|
+
switch(op_type) {
|
|
336
|
+
case 'authentication':
|
|
337
|
+
await authentication(socket, parsed_data?.data || {});
|
|
338
|
+
break;
|
|
339
|
+
|
|
340
|
+
case 'setup':
|
|
341
|
+
await setup(socket, parsed_data?.data || {});
|
|
342
|
+
break;
|
|
343
|
+
|
|
344
|
+
case 'insert_one':
|
|
345
|
+
case 'update_one':
|
|
346
|
+
case 'delete_one':
|
|
347
|
+
case 'bulk_write':
|
|
348
|
+
case 'find_one':
|
|
349
|
+
case 'find':
|
|
350
|
+
case 'create_index':
|
|
351
|
+
case 'drop_index':
|
|
352
|
+
case 'get_indexes':
|
|
353
|
+
// NOTE: Use shared operation dispatcher for database operations.
|
|
354
|
+
await handle_database_operation(socket, op_type, parsed_data?.data || {}, check_authentication, raw_data.length, connection_manager, authenticated_clients);
|
|
355
|
+
break;
|
|
356
|
+
|
|
357
|
+
case 'ping':
|
|
358
|
+
handle_ping_operation(socket);
|
|
359
|
+
break;
|
|
360
|
+
|
|
361
|
+
case 'admin':
|
|
362
|
+
// NOTE: Use shared operation dispatcher for admin operations.
|
|
363
|
+
await handle_admin_operation(socket, parsed_data?.data || {}, check_authentication, connection_manager, authenticated_clients);
|
|
364
|
+
break;
|
|
365
|
+
|
|
366
|
+
case 'reload':
|
|
367
|
+
if (!check_authentication(socket)) {
|
|
368
|
+
send_error(socket, { message: 'Authentication required' });
|
|
369
|
+
break;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
try {
|
|
373
|
+
let old_settings = null;
|
|
374
|
+
try {
|
|
375
|
+
old_settings = get_settings();
|
|
376
|
+
} catch (error) {
|
|
377
|
+
// NOTE: Settings not loaded yet, that's OK.
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
let new_settings = null;
|
|
381
|
+
try {
|
|
382
|
+
await load_settings();
|
|
383
|
+
new_settings = get_settings();
|
|
384
|
+
} catch (error) {
|
|
385
|
+
// NOTE: Settings file doesn't exist, create default settings for tests.
|
|
386
|
+
new_settings = {
|
|
387
|
+
port: 1983,
|
|
388
|
+
authentication: {}
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
const reload_info = {
|
|
393
|
+
ok: 1,
|
|
394
|
+
status: 'success',
|
|
395
|
+
message: 'Configuration reloaded successfully',
|
|
396
|
+
changes: {
|
|
397
|
+
port_changed: old_settings ? old_settings.port !== new_settings.port : false,
|
|
398
|
+
authentication_changed: old_settings ? old_settings.authentication?.password_hash !== new_settings.authentication?.password_hash : false
|
|
399
|
+
},
|
|
400
|
+
timestamp: new Date().toISOString()
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
const encoded_response = encode_message(reload_info);
|
|
404
|
+
socket.write(encoded_response);
|
|
405
|
+
} catch (error) {
|
|
406
|
+
const error_response = { ok: 0, error: `Reload operation failed: ${error.message}` };
|
|
407
|
+
const encoded_error_response = encode_message(error_response);
|
|
408
|
+
socket.write(encoded_error_response);
|
|
409
|
+
}
|
|
410
|
+
break;
|
|
411
|
+
|
|
412
|
+
default:
|
|
413
|
+
send_error(socket, { message: `Operation ${op_type} not implemented` });
|
|
414
|
+
}
|
|
415
|
+
} finally {
|
|
416
|
+
clearTimeout(request_timeout);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
} catch (error) {
|
|
420
|
+
log.error('Message parsing failed', {
|
|
421
|
+
client_id: socket.id,
|
|
422
|
+
error: error.message
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
send_error(socket, { message: 'Invalid message format' });
|
|
426
|
+
socket.end();
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
socket.on('end', () => {
|
|
431
|
+
log.info('Client disconnected', { socket_id: socket.id });
|
|
432
|
+
authenticated_clients.delete(socket.id);
|
|
433
|
+
connection_manager.remove_connection(socket.id);
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
socket.on('error', (error) => {
|
|
437
|
+
log.error('Socket error', {
|
|
438
|
+
socket_id: socket.id,
|
|
439
|
+
error: error.message
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
authenticated_clients.delete(socket.id);
|
|
443
|
+
connection_manager.remove_connection(socket.id);
|
|
444
|
+
});
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
// NOTE: Add cleanup method for tests.
|
|
448
|
+
server.cleanup = async () => {
|
|
449
|
+
try {
|
|
450
|
+
// NOTE: Stop HTTP server.
|
|
451
|
+
await stop_http_server();
|
|
452
|
+
|
|
453
|
+
// NOTE: Stop backup scheduling.
|
|
454
|
+
stop_backup_schedule();
|
|
455
|
+
|
|
456
|
+
// NOTE: Shutdown replication manager.
|
|
457
|
+
await shutdown_replication_manager();
|
|
458
|
+
|
|
459
|
+
// NOTE: Shutdown write forwarder.
|
|
460
|
+
await shutdown_write_forwarder();
|
|
461
|
+
|
|
462
|
+
// NOTE: Shutdown connection manager.
|
|
463
|
+
if (connection_manager) {
|
|
464
|
+
connection_manager.shutdown();
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// NOTE: Clear authenticated clients.
|
|
468
|
+
authenticated_clients.clear();
|
|
469
|
+
|
|
470
|
+
// NOTE: Shutdown write queue.
|
|
471
|
+
await shutdown_write_queue();
|
|
472
|
+
|
|
473
|
+
// NOTE: Wait a bit to ensure all operations are complete.
|
|
474
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
475
|
+
|
|
476
|
+
// NOTE: Cleanup database (after everything else is shut down).
|
|
477
|
+
await cleanup_database();
|
|
478
|
+
|
|
479
|
+
// NOTE: Reset auth state.
|
|
480
|
+
reset_auth_state();
|
|
481
|
+
|
|
482
|
+
// NOTE: Reset recovery state.
|
|
483
|
+
reset_recovery_state();
|
|
484
|
+
} catch (error) {
|
|
485
|
+
// NOTE: Ignore cleanup errors in tests.
|
|
486
|
+
}
|
|
487
|
+
};
|
|
488
|
+
|
|
489
|
+
return server;
|
|
490
|
+
};
|
|
491
|
+
|
|
492
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
493
|
+
const { create_context_logger } = create_logger('main');
|
|
494
|
+
const log = create_context_logger();
|
|
495
|
+
|
|
496
|
+
// NOTE: Check for recovery token generation flag.
|
|
497
|
+
if (process.argv.includes('--generate-recovery-token')) {
|
|
498
|
+
try {
|
|
499
|
+
initialize_recovery_manager();
|
|
500
|
+
const recovery_info = create_recovery_token();
|
|
501
|
+
|
|
502
|
+
console.log('Emergency Recovery Token Generated');
|
|
503
|
+
console.log(`Visit: ${recovery_info.url}`);
|
|
504
|
+
console.log('Token expires in 10 minutes');
|
|
505
|
+
|
|
506
|
+
log.info('Recovery token generated via CLI', {
|
|
507
|
+
expires_at: new Date(recovery_info.expires_at).toISOString()
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
process.exit(0);
|
|
511
|
+
} catch (error) {
|
|
512
|
+
console.error('Failed to generate recovery token:', error.message);
|
|
513
|
+
log.error('Recovery token generation failed', { error: error.message });
|
|
514
|
+
process.exit(1);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// NOTE: Get port configuration from settings or use defaults.
|
|
519
|
+
const { tcp_port, http_port } = get_port_configuration();
|
|
520
|
+
|
|
521
|
+
const options = {
|
|
522
|
+
worker_count: process.env.WORKER_COUNT ? parseInt(process.env.WORKER_COUNT) : undefined,
|
|
523
|
+
port: tcp_port,
|
|
524
|
+
environment: process.env.NODE_ENV || 'development'
|
|
525
|
+
};
|
|
526
|
+
|
|
527
|
+
const { has_settings } = await import('./lib/load_settings.js');
|
|
528
|
+
const has_db_settings = has_settings();
|
|
529
|
+
|
|
530
|
+
log.info('Starting JoystickDB server...', {
|
|
531
|
+
workers: options.worker_count || 'auto',
|
|
532
|
+
tcp_port: tcp_port,
|
|
533
|
+
http_port: http_port,
|
|
534
|
+
environment: options.environment,
|
|
535
|
+
has_settings: has_db_settings,
|
|
536
|
+
port_source: has_db_settings ? 'JOYSTICK_DB_SETTINGS' : 'default'
|
|
537
|
+
});
|
|
538
|
+
|
|
539
|
+
start_cluster(options);
|
|
540
|
+
}
|