@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,1232 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import { create_server } from '../../src/server/index.js';
|
|
3
|
+
import joystickdb from '../../src/client/index.js';
|
|
4
|
+
import { writeFileSync, unlinkSync, existsSync } from 'fs';
|
|
5
|
+
import { reset_auth_state } from '../../src/server/lib/auth_manager.js';
|
|
6
|
+
|
|
7
|
+
let server;
|
|
8
|
+
let client;
|
|
9
|
+
|
|
10
|
+
// NOTE: Simple port allocation using a fixed range to avoid conflicts.
|
|
11
|
+
let current_port = 2000;
|
|
12
|
+
const get_next_port = () => {
|
|
13
|
+
return ++current_port;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
test.beforeEach(async () => {
|
|
17
|
+
await reset_auth_state();
|
|
18
|
+
|
|
19
|
+
// Clean up database files to ensure test isolation
|
|
20
|
+
try {
|
|
21
|
+
if (existsSync('./data/data.mdb')) {
|
|
22
|
+
unlinkSync('./data/data.mdb');
|
|
23
|
+
}
|
|
24
|
+
if (existsSync('./data/lock.mdb')) {
|
|
25
|
+
unlinkSync('./data/lock.mdb');
|
|
26
|
+
}
|
|
27
|
+
} catch (error) {
|
|
28
|
+
// Ignore cleanup errors
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test.afterEach(async () => {
|
|
33
|
+
if (client) {
|
|
34
|
+
client.disconnect();
|
|
35
|
+
client = null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (server) {
|
|
39
|
+
await server.cleanup();
|
|
40
|
+
server.close();
|
|
41
|
+
server = null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
await reset_auth_state();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test('client can be created with custom options', (t) => {
|
|
48
|
+
client = joystickdb.client({
|
|
49
|
+
host: '127.0.0.1',
|
|
50
|
+
port: 9999,
|
|
51
|
+
timeout: 10000,
|
|
52
|
+
reconnect: false,
|
|
53
|
+
max_reconnect_attempts: 5,
|
|
54
|
+
reconnect_delay: 2000,
|
|
55
|
+
password: 'test_password',
|
|
56
|
+
auto_connect: false
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
t.is(client.host, '127.0.0.1');
|
|
60
|
+
t.is(client.port, 9999);
|
|
61
|
+
t.is(client.timeout, 10000);
|
|
62
|
+
t.is(client.reconnect, false);
|
|
63
|
+
t.is(client.max_reconnect_attempts, 5);
|
|
64
|
+
t.is(client.reconnect_delay, 2000);
|
|
65
|
+
t.is(client.password, 'test_password');
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test('client can setup authentication', async (t) => {
|
|
69
|
+
const test_port = get_next_port();
|
|
70
|
+
server = await create_server();
|
|
71
|
+
|
|
72
|
+
await new Promise((resolve) => {
|
|
73
|
+
server.listen(test_port, () => {
|
|
74
|
+
setTimeout(resolve, 100);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
client = joystickdb.client({
|
|
79
|
+
port: test_port,
|
|
80
|
+
reconnect: false
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
await new Promise((resolve) => {
|
|
84
|
+
client.on('connect', resolve);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const result = await client.setup();
|
|
88
|
+
|
|
89
|
+
t.is(result.ok, 1);
|
|
90
|
+
t.truthy(result.password);
|
|
91
|
+
t.truthy(result.message);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test('client can authenticate with valid password', async (t) => {
|
|
95
|
+
const test_port = get_next_port();
|
|
96
|
+
server = await create_server();
|
|
97
|
+
|
|
98
|
+
await new Promise((resolve) => {
|
|
99
|
+
server.listen(test_port, () => {
|
|
100
|
+
setTimeout(resolve, 100);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const setup_client = joystickdb.client({
|
|
105
|
+
port: test_port,
|
|
106
|
+
reconnect: false
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
await new Promise((resolve) => {
|
|
110
|
+
setup_client.on('connect', resolve);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
const setup_result = await setup_client.setup();
|
|
114
|
+
setup_client.disconnect();
|
|
115
|
+
|
|
116
|
+
client = joystickdb.client({
|
|
117
|
+
port: test_port,
|
|
118
|
+
reconnect: false,
|
|
119
|
+
password: setup_result.password
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
await new Promise((resolve) => {
|
|
123
|
+
client.on('authenticated', resolve);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
t.is(client.is_authenticated, true);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test('client authentication fails with invalid password', async (t) => {
|
|
130
|
+
const test_port = get_next_port();
|
|
131
|
+
server = await create_server();
|
|
132
|
+
|
|
133
|
+
await new Promise((resolve) => {
|
|
134
|
+
server.listen(test_port, () => {
|
|
135
|
+
setTimeout(resolve, 100);
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
const setup_client = joystickdb.client({
|
|
140
|
+
port: test_port,
|
|
141
|
+
reconnect: false
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
await new Promise((resolve) => {
|
|
145
|
+
setup_client.on('connect', resolve);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
await setup_client.setup();
|
|
149
|
+
setup_client.disconnect();
|
|
150
|
+
|
|
151
|
+
client = joystickdb.client({
|
|
152
|
+
port: test_port,
|
|
153
|
+
reconnect: false,
|
|
154
|
+
password: 'invalid_password'
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
const error = await new Promise((resolve) => {
|
|
158
|
+
client.on('error', resolve);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
t.truthy(error.message.includes('Authentication'));
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
test('client can perform ping operation', async (t) => {
|
|
165
|
+
const test_port = get_next_port();
|
|
166
|
+
server = await create_server();
|
|
167
|
+
|
|
168
|
+
await new Promise((resolve) => {
|
|
169
|
+
server.listen(test_port, () => {
|
|
170
|
+
setTimeout(resolve, 100);
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
client = joystickdb.client({
|
|
175
|
+
port: test_port,
|
|
176
|
+
reconnect: false
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
await new Promise((resolve) => {
|
|
180
|
+
client.on('connect', resolve);
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
const result = await client.ping();
|
|
184
|
+
|
|
185
|
+
t.is(result.ok, 1);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
test('client can perform CRUD operations', async (t) => {
|
|
189
|
+
const test_port = get_next_port();
|
|
190
|
+
server = await create_server();
|
|
191
|
+
|
|
192
|
+
await new Promise((resolve) => {
|
|
193
|
+
server.listen(test_port, () => {
|
|
194
|
+
setTimeout(resolve, 100);
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
const setup_client = joystickdb.client({
|
|
199
|
+
port: test_port,
|
|
200
|
+
reconnect: false
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
await new Promise((resolve) => {
|
|
204
|
+
setup_client.on('connect', resolve);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
const setup_result = await setup_client.setup();
|
|
208
|
+
setup_client.disconnect();
|
|
209
|
+
|
|
210
|
+
client = joystickdb.client({
|
|
211
|
+
port: test_port,
|
|
212
|
+
reconnect: false,
|
|
213
|
+
password: setup_result.password
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
await new Promise((resolve) => {
|
|
217
|
+
client.on('authenticated', resolve);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
const insert_result = await client.db('default').collection('test_collection').insert_one({
|
|
221
|
+
name: 'John Doe',
|
|
222
|
+
age: 30
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
t.is(insert_result.ok, 1);
|
|
226
|
+
t.truthy(insert_result.inserted_id);
|
|
227
|
+
|
|
228
|
+
const find_result = await client.db('default').collection('test_collection').find_one({
|
|
229
|
+
name: 'John Doe'
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
t.is(find_result.name, 'John Doe');
|
|
233
|
+
t.is(find_result.age, 30);
|
|
234
|
+
|
|
235
|
+
const update_result = await client.db('default').collection('test_collection').update_one({
|
|
236
|
+
name: 'John Doe'
|
|
237
|
+
}, {
|
|
238
|
+
$set: { age: 31 }
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
t.is(update_result.ok, 1);
|
|
242
|
+
t.is(update_result.modified_count, 1);
|
|
243
|
+
|
|
244
|
+
const updated_doc = await client.db('default').collection('test_collection').find_one({
|
|
245
|
+
name: 'John Doe'
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
t.is(updated_doc.age, 31);
|
|
249
|
+
|
|
250
|
+
const delete_result = await client.db('default').collection('test_collection').delete_one({
|
|
251
|
+
name: 'John Doe'
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
t.is(delete_result.ok, 1);
|
|
255
|
+
t.is(delete_result.deleted_count, 1);
|
|
256
|
+
|
|
257
|
+
const deleted_doc = await client.db('default').collection('test_collection').find_one({
|
|
258
|
+
name: 'John Doe'
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
t.is(deleted_doc, null);
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
test('client can perform find operation with multiple results', async (t) => {
|
|
265
|
+
const test_port = get_next_port();
|
|
266
|
+
server = await create_server();
|
|
267
|
+
|
|
268
|
+
await new Promise((resolve) => {
|
|
269
|
+
server.listen(test_port, () => {
|
|
270
|
+
setTimeout(resolve, 100);
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
const setup_client = joystickdb.client({
|
|
275
|
+
port: test_port,
|
|
276
|
+
reconnect: false
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
await new Promise((resolve) => {
|
|
280
|
+
setup_client.on('connect', resolve);
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
const setup_result = await setup_client.setup();
|
|
284
|
+
setup_client.disconnect();
|
|
285
|
+
|
|
286
|
+
client = joystickdb.client({
|
|
287
|
+
port: test_port,
|
|
288
|
+
reconnect: false,
|
|
289
|
+
password: setup_result.password
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
await new Promise((resolve) => {
|
|
293
|
+
client.on('authenticated', resolve);
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
await client.db('default').collection('test_collection').insert_one({ category: 'test', value: 1 });
|
|
297
|
+
await client.db('default').collection('test_collection').insert_one({ category: 'test', value: 2 });
|
|
298
|
+
await client.db('default').collection('test_collection').insert_one({ category: 'test', value: 3 });
|
|
299
|
+
|
|
300
|
+
const find_result = await client.db('default').collection('test_collection').find({
|
|
301
|
+
category: 'test'
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
t.truthy(find_result);
|
|
305
|
+
t.is(find_result.length, 3);
|
|
306
|
+
t.truthy(find_result.find(doc => doc.value === 1));
|
|
307
|
+
t.truthy(find_result.find(doc => doc.value === 2));
|
|
308
|
+
t.truthy(find_result.find(doc => doc.value === 3));
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
test('client can perform bulk write operations', async (t) => {
|
|
312
|
+
const test_port = get_next_port();
|
|
313
|
+
server = await create_server();
|
|
314
|
+
|
|
315
|
+
await new Promise((resolve) => {
|
|
316
|
+
server.listen(test_port, () => {
|
|
317
|
+
setTimeout(resolve, 100);
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
const setup_client = joystickdb.client({
|
|
322
|
+
port: test_port,
|
|
323
|
+
reconnect: false
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
await new Promise((resolve) => {
|
|
327
|
+
setup_client.on('connect', resolve);
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
const setup_result = await setup_client.setup();
|
|
331
|
+
setup_client.disconnect();
|
|
332
|
+
|
|
333
|
+
client = joystickdb.client({
|
|
334
|
+
port: test_port,
|
|
335
|
+
reconnect: false,
|
|
336
|
+
password: setup_result.password
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
await new Promise((resolve) => {
|
|
340
|
+
client.on('authenticated', resolve);
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
const bulk_operations = [
|
|
344
|
+
{ insert_one: { document: { name: 'Alice', age: 25 } } },
|
|
345
|
+
{ insert_one: { document: { name: 'Bob', age: 30 } } },
|
|
346
|
+
{ insert_one: { document: { name: 'Charlie', age: 35 } } }
|
|
347
|
+
];
|
|
348
|
+
|
|
349
|
+
const bulk_result = await client.db('default').collection('test_collection').bulk_write(bulk_operations);
|
|
350
|
+
|
|
351
|
+
t.is(bulk_result.ok, 1);
|
|
352
|
+
t.is(bulk_result.inserted_count, 3);
|
|
353
|
+
|
|
354
|
+
const find_result = await client.db('default').collection('test_collection').find({});
|
|
355
|
+
t.truthy(find_result);
|
|
356
|
+
t.is(find_result.length, 3);
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
test('client can perform index operations', async (t) => {
|
|
360
|
+
const test_port = get_next_port();
|
|
361
|
+
server = await create_server();
|
|
362
|
+
|
|
363
|
+
await new Promise((resolve) => {
|
|
364
|
+
server.listen(test_port, () => {
|
|
365
|
+
setTimeout(resolve, 100);
|
|
366
|
+
});
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
const setup_client = joystickdb.client({
|
|
370
|
+
port: test_port,
|
|
371
|
+
reconnect: false
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
await new Promise((resolve) => {
|
|
375
|
+
setup_client.on('connect', resolve);
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
const setup_result = await setup_client.setup();
|
|
379
|
+
setup_client.disconnect();
|
|
380
|
+
|
|
381
|
+
client = joystickdb.client({
|
|
382
|
+
port: test_port,
|
|
383
|
+
reconnect: false,
|
|
384
|
+
password: setup_result.password
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
await new Promise((resolve) => {
|
|
388
|
+
client.on('authenticated', resolve);
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
const create_index_result = await client.db('default').collection('test_collection').create_index('name');
|
|
392
|
+
|
|
393
|
+
t.is(create_index_result.ok, 1);
|
|
394
|
+
t.truthy(create_index_result.message);
|
|
395
|
+
|
|
396
|
+
const get_indexes_result = await client.db('default').collection('test_collection').get_indexes();
|
|
397
|
+
|
|
398
|
+
t.is(get_indexes_result.ok, 1);
|
|
399
|
+
t.truthy(get_indexes_result.indexes.find(index => index.field === 'name'));
|
|
400
|
+
|
|
401
|
+
const drop_index_result = await client.db('default').collection('test_collection').drop_index('name');
|
|
402
|
+
|
|
403
|
+
t.is(drop_index_result.ok, 1);
|
|
404
|
+
t.truthy(drop_index_result.message);
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
test('client can perform admin operations', async (t) => {
|
|
408
|
+
const test_port = get_next_port();
|
|
409
|
+
server = await create_server();
|
|
410
|
+
|
|
411
|
+
await new Promise((resolve) => {
|
|
412
|
+
server.listen(test_port, () => {
|
|
413
|
+
setTimeout(resolve, 100);
|
|
414
|
+
});
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
const setup_client = joystickdb.client({
|
|
418
|
+
port: test_port,
|
|
419
|
+
reconnect: false
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
await new Promise((resolve) => {
|
|
423
|
+
setup_client.on('connect', resolve);
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
const setup_result = await setup_client.setup();
|
|
427
|
+
setup_client.disconnect();
|
|
428
|
+
|
|
429
|
+
client = joystickdb.client({
|
|
430
|
+
port: test_port,
|
|
431
|
+
reconnect: false,
|
|
432
|
+
password: setup_result.password
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
await new Promise((resolve) => {
|
|
436
|
+
client.on('authenticated', resolve);
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
await client.db('default').collection('admin_test').insert_one({ test: 'data' });
|
|
440
|
+
|
|
441
|
+
const database = client.db('default');
|
|
442
|
+
|
|
443
|
+
const stats_result = await database.get_stats();
|
|
444
|
+
t.is(stats_result.ok, 1);
|
|
445
|
+
t.truthy(stats_result.database);
|
|
446
|
+
|
|
447
|
+
const collections_result = await database.list_collections();
|
|
448
|
+
t.is(collections_result.ok, 1);
|
|
449
|
+
t.truthy(collections_result.collections.some(col => col.name === 'admin_test'));
|
|
450
|
+
|
|
451
|
+
const documents_result = await database.list_documents('admin_test');
|
|
452
|
+
t.is(documents_result.ok, 1);
|
|
453
|
+
t.is(documents_result.documents.length, 1);
|
|
454
|
+
|
|
455
|
+
const document_id = documents_result.documents[0]._id;
|
|
456
|
+
const get_doc_result = await database.get_document('admin_test', document_id);
|
|
457
|
+
t.is(get_doc_result.ok, 1);
|
|
458
|
+
t.is(get_doc_result.document.test, 'data');
|
|
459
|
+
|
|
460
|
+
const query_result = await database.query_documents('admin_test', { test: 'data' });
|
|
461
|
+
t.is(query_result.ok, 1);
|
|
462
|
+
t.is(query_result.documents.length, 1);
|
|
463
|
+
|
|
464
|
+
const insert_doc_result = await database.insert_document('admin_test', { admin: 'insert' });
|
|
465
|
+
t.is(insert_doc_result.ok, 1);
|
|
466
|
+
|
|
467
|
+
const update_doc_result = await database.update_document('admin_test', document_id, { $set: { updated: true } });
|
|
468
|
+
t.is(update_doc_result.ok, 1);
|
|
469
|
+
|
|
470
|
+
const delete_doc_result = await database.delete_document('admin_test', document_id);
|
|
471
|
+
t.is(delete_doc_result.ok, 1);
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
test('client handles request timeout', async (t) => {
|
|
475
|
+
const test_port = get_next_port();
|
|
476
|
+
server = await create_server();
|
|
477
|
+
|
|
478
|
+
await new Promise((resolve) => {
|
|
479
|
+
server.listen(test_port, () => {
|
|
480
|
+
setTimeout(resolve, 100);
|
|
481
|
+
});
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
client = joystickdb.client({
|
|
485
|
+
port: test_port,
|
|
486
|
+
timeout: 100,
|
|
487
|
+
reconnect: false
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
await new Promise((resolve) => {
|
|
491
|
+
client.on('connect', resolve);
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
client.socket.write = () => {};
|
|
495
|
+
|
|
496
|
+
const error = await t.throwsAsync(async () => {
|
|
497
|
+
await client.ping();
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
t.is(error.message, 'Request timeout');
|
|
501
|
+
});
|
|
502
|
+
|
|
503
|
+
test('client queues requests when not authenticated', async (t) => {
|
|
504
|
+
const test_port = get_next_port();
|
|
505
|
+
server = await create_server();
|
|
506
|
+
|
|
507
|
+
await new Promise((resolve) => {
|
|
508
|
+
server.listen(test_port, () => {
|
|
509
|
+
setTimeout(resolve, 100);
|
|
510
|
+
});
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
const setup_client = joystickdb.client({
|
|
514
|
+
port: test_port,
|
|
515
|
+
reconnect: false
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
await new Promise((resolve) => {
|
|
519
|
+
setup_client.on('connect', resolve);
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
const setup_result = await setup_client.setup();
|
|
523
|
+
setup_client.disconnect();
|
|
524
|
+
|
|
525
|
+
client = joystickdb.client({
|
|
526
|
+
port: test_port,
|
|
527
|
+
reconnect: false,
|
|
528
|
+
password: setup_result.password
|
|
529
|
+
});
|
|
530
|
+
|
|
531
|
+
const insert_promise = client.db('default').collection('queue_test').insert_one({ queued: true });
|
|
532
|
+
|
|
533
|
+
t.is(client.request_queue.length, 1);
|
|
534
|
+
|
|
535
|
+
await new Promise((resolve) => {
|
|
536
|
+
client.on('authenticated', resolve);
|
|
537
|
+
});
|
|
538
|
+
|
|
539
|
+
const result = await insert_promise;
|
|
540
|
+
|
|
541
|
+
t.is(result.ok, 1);
|
|
542
|
+
t.is(client.request_queue.length, 0);
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
test('client handles connection errors gracefully', async (t) => {
|
|
546
|
+
client = joystickdb.client({
|
|
547
|
+
port: 9999,
|
|
548
|
+
reconnect: false,
|
|
549
|
+
timeout: 1000
|
|
550
|
+
});
|
|
551
|
+
|
|
552
|
+
const error = await new Promise((resolve) => {
|
|
553
|
+
client.on('error', resolve);
|
|
554
|
+
});
|
|
555
|
+
|
|
556
|
+
t.truthy(error);
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
test('client can reload server configuration', async (t) => {
|
|
560
|
+
const test_port = get_next_port();
|
|
561
|
+
server = await create_server();
|
|
562
|
+
|
|
563
|
+
await new Promise((resolve) => {
|
|
564
|
+
server.listen(test_port, () => {
|
|
565
|
+
setTimeout(resolve, 100);
|
|
566
|
+
});
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
const setup_client = joystickdb.client({
|
|
570
|
+
port: test_port,
|
|
571
|
+
reconnect: false
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
await new Promise((resolve) => {
|
|
575
|
+
setup_client.on('connect', resolve);
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
const setup_result = await setup_client.setup();
|
|
579
|
+
setup_client.disconnect();
|
|
580
|
+
|
|
581
|
+
client = joystickdb.client({
|
|
582
|
+
port: test_port,
|
|
583
|
+
reconnect: false,
|
|
584
|
+
password: setup_result.password
|
|
585
|
+
});
|
|
586
|
+
|
|
587
|
+
await new Promise((resolve) => {
|
|
588
|
+
client.on('authenticated', resolve);
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
const reload_result = await client.reload();
|
|
592
|
+
|
|
593
|
+
t.is(reload_result.ok, 1);
|
|
594
|
+
t.truthy(reload_result.message);
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
// NOTE: Collection chaining API tests.
|
|
598
|
+
test('client.collection() returns a collection interface', async (t) => {
|
|
599
|
+
const test_port = get_next_port();
|
|
600
|
+
server = await create_server();
|
|
601
|
+
|
|
602
|
+
await new Promise((resolve) => {
|
|
603
|
+
server.listen(test_port, () => {
|
|
604
|
+
setTimeout(resolve, 100);
|
|
605
|
+
});
|
|
606
|
+
});
|
|
607
|
+
|
|
608
|
+
const setup_client = joystickdb.client({
|
|
609
|
+
port: test_port,
|
|
610
|
+
reconnect: false
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
await new Promise((resolve) => {
|
|
614
|
+
setup_client.on('connect', resolve);
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
const setup_result = await setup_client.setup();
|
|
618
|
+
setup_client.disconnect();
|
|
619
|
+
|
|
620
|
+
client = joystickdb.client({
|
|
621
|
+
port: test_port,
|
|
622
|
+
reconnect: false,
|
|
623
|
+
password: setup_result.password
|
|
624
|
+
});
|
|
625
|
+
|
|
626
|
+
await new Promise((resolve) => {
|
|
627
|
+
client.on('authenticated', resolve);
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
const collection = client.db('default').collection('test_collection');
|
|
631
|
+
|
|
632
|
+
t.truthy(collection);
|
|
633
|
+
t.is(collection.collection_name, 'test_collection');
|
|
634
|
+
t.is(collection.client, client);
|
|
635
|
+
t.is(typeof collection.insert_one, 'function');
|
|
636
|
+
t.is(typeof collection.find_one, 'function');
|
|
637
|
+
t.is(typeof collection.find, 'function');
|
|
638
|
+
t.is(typeof collection.update_one, 'function');
|
|
639
|
+
t.is(typeof collection.delete_one, 'function');
|
|
640
|
+
t.is(typeof collection.bulk_write, 'function');
|
|
641
|
+
t.is(typeof collection.create_index, 'function');
|
|
642
|
+
t.is(typeof collection.drop_index, 'function');
|
|
643
|
+
t.is(typeof collection.get_indexes, 'function');
|
|
644
|
+
});
|
|
645
|
+
|
|
646
|
+
test('collection chaining API can perform CRUD operations', async (t) => {
|
|
647
|
+
const test_port = get_next_port();
|
|
648
|
+
server = await create_server();
|
|
649
|
+
|
|
650
|
+
await new Promise((resolve) => {
|
|
651
|
+
server.listen(test_port, () => {
|
|
652
|
+
setTimeout(resolve, 100);
|
|
653
|
+
});
|
|
654
|
+
});
|
|
655
|
+
|
|
656
|
+
const setup_client = joystickdb.client({
|
|
657
|
+
port: test_port,
|
|
658
|
+
reconnect: false
|
|
659
|
+
});
|
|
660
|
+
|
|
661
|
+
await new Promise((resolve) => {
|
|
662
|
+
setup_client.on('connect', resolve);
|
|
663
|
+
});
|
|
664
|
+
|
|
665
|
+
const setup_result = await setup_client.setup();
|
|
666
|
+
setup_client.disconnect();
|
|
667
|
+
|
|
668
|
+
client = joystickdb.client({
|
|
669
|
+
port: test_port,
|
|
670
|
+
reconnect: false,
|
|
671
|
+
password: setup_result.password
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
await new Promise((resolve) => {
|
|
675
|
+
client.on('authenticated', resolve);
|
|
676
|
+
});
|
|
677
|
+
|
|
678
|
+
const collection = client.db('default').collection('chain_test');
|
|
679
|
+
|
|
680
|
+
const insert_result = await collection.insert_one({
|
|
681
|
+
name: 'Jane Doe',
|
|
682
|
+
age: 25
|
|
683
|
+
});
|
|
684
|
+
|
|
685
|
+
t.is(insert_result.ok, 1);
|
|
686
|
+
t.truthy(insert_result.inserted_id);
|
|
687
|
+
|
|
688
|
+
const find_result = await collection.find_one({
|
|
689
|
+
name: 'Jane Doe'
|
|
690
|
+
});
|
|
691
|
+
|
|
692
|
+
t.is(find_result.name, 'Jane Doe');
|
|
693
|
+
t.is(find_result.age, 25);
|
|
694
|
+
|
|
695
|
+
const update_result = await collection.update_one({
|
|
696
|
+
name: 'Jane Doe'
|
|
697
|
+
}, {
|
|
698
|
+
$set: { age: 26 }
|
|
699
|
+
});
|
|
700
|
+
|
|
701
|
+
t.is(update_result.ok, 1);
|
|
702
|
+
t.is(update_result.modified_count, 1);
|
|
703
|
+
|
|
704
|
+
const updated_doc = await collection.find_one({
|
|
705
|
+
name: 'Jane Doe'
|
|
706
|
+
});
|
|
707
|
+
|
|
708
|
+
t.is(updated_doc.age, 26);
|
|
709
|
+
|
|
710
|
+
const delete_result = await collection.delete_one({
|
|
711
|
+
name: 'Jane Doe'
|
|
712
|
+
});
|
|
713
|
+
|
|
714
|
+
t.is(delete_result.ok, 1);
|
|
715
|
+
t.is(delete_result.deleted_count, 1);
|
|
716
|
+
|
|
717
|
+
const deleted_doc = await collection.find_one({
|
|
718
|
+
name: 'Jane Doe'
|
|
719
|
+
});
|
|
720
|
+
|
|
721
|
+
t.is(deleted_doc, null);
|
|
722
|
+
});
|
|
723
|
+
|
|
724
|
+
test('collection chaining API can perform find operation with multiple results', async (t) => {
|
|
725
|
+
const test_port = get_next_port();
|
|
726
|
+
server = await create_server();
|
|
727
|
+
|
|
728
|
+
await new Promise((resolve) => {
|
|
729
|
+
server.listen(test_port, () => {
|
|
730
|
+
setTimeout(resolve, 100);
|
|
731
|
+
});
|
|
732
|
+
});
|
|
733
|
+
|
|
734
|
+
const setup_client = joystickdb.client({
|
|
735
|
+
port: test_port,
|
|
736
|
+
reconnect: false
|
|
737
|
+
});
|
|
738
|
+
|
|
739
|
+
await new Promise((resolve) => {
|
|
740
|
+
setup_client.on('connect', resolve);
|
|
741
|
+
});
|
|
742
|
+
|
|
743
|
+
const setup_result = await setup_client.setup();
|
|
744
|
+
setup_client.disconnect();
|
|
745
|
+
|
|
746
|
+
client = joystickdb.client({
|
|
747
|
+
port: test_port,
|
|
748
|
+
reconnect: false,
|
|
749
|
+
password: setup_result.password
|
|
750
|
+
});
|
|
751
|
+
|
|
752
|
+
await new Promise((resolve) => {
|
|
753
|
+
client.on('authenticated', resolve);
|
|
754
|
+
});
|
|
755
|
+
|
|
756
|
+
const collection = client.db('default').collection('chain_find_test');
|
|
757
|
+
|
|
758
|
+
await collection.insert_one({ category: 'chain_test', value: 10 });
|
|
759
|
+
await collection.insert_one({ category: 'chain_test', value: 20 });
|
|
760
|
+
await collection.insert_one({ category: 'chain_test', value: 30 });
|
|
761
|
+
|
|
762
|
+
const find_result = await collection.find({
|
|
763
|
+
category: 'chain_test'
|
|
764
|
+
});
|
|
765
|
+
|
|
766
|
+
t.truthy(find_result);
|
|
767
|
+
t.is(find_result.length, 3);
|
|
768
|
+
t.truthy(find_result.find(doc => doc.value === 10));
|
|
769
|
+
t.truthy(find_result.find(doc => doc.value === 20));
|
|
770
|
+
t.truthy(find_result.find(doc => doc.value === 30));
|
|
771
|
+
});
|
|
772
|
+
|
|
773
|
+
test('collection chaining API can perform bulk write operations', async (t) => {
|
|
774
|
+
const test_port = get_next_port();
|
|
775
|
+
server = await create_server();
|
|
776
|
+
|
|
777
|
+
await new Promise((resolve) => {
|
|
778
|
+
server.listen(test_port, () => {
|
|
779
|
+
setTimeout(resolve, 100);
|
|
780
|
+
});
|
|
781
|
+
});
|
|
782
|
+
|
|
783
|
+
const setup_client = joystickdb.client({
|
|
784
|
+
port: test_port,
|
|
785
|
+
reconnect: false
|
|
786
|
+
});
|
|
787
|
+
|
|
788
|
+
await new Promise((resolve) => {
|
|
789
|
+
setup_client.on('connect', resolve);
|
|
790
|
+
});
|
|
791
|
+
|
|
792
|
+
const setup_result = await setup_client.setup();
|
|
793
|
+
setup_client.disconnect();
|
|
794
|
+
|
|
795
|
+
client = joystickdb.client({
|
|
796
|
+
port: test_port,
|
|
797
|
+
reconnect: false,
|
|
798
|
+
password: setup_result.password
|
|
799
|
+
});
|
|
800
|
+
|
|
801
|
+
await new Promise((resolve) => {
|
|
802
|
+
client.on('authenticated', resolve);
|
|
803
|
+
});
|
|
804
|
+
|
|
805
|
+
const collection = client.db('default').collection('chain_bulk_test');
|
|
806
|
+
|
|
807
|
+
const bulk_operations = [
|
|
808
|
+
{ insert_one: { document: { name: 'Alice', age: 25 } } },
|
|
809
|
+
{ insert_one: { document: { name: 'Bob', age: 30 } } },
|
|
810
|
+
{ insert_one: { document: { name: 'Charlie', age: 35 } } }
|
|
811
|
+
];
|
|
812
|
+
|
|
813
|
+
const bulk_result = await collection.bulk_write(bulk_operations);
|
|
814
|
+
|
|
815
|
+
t.is(bulk_result.ok, 1);
|
|
816
|
+
t.is(bulk_result.inserted_count, 3);
|
|
817
|
+
|
|
818
|
+
const find_result = await collection.find({});
|
|
819
|
+
t.truthy(find_result);
|
|
820
|
+
t.is(find_result.length, 3);
|
|
821
|
+
});
|
|
822
|
+
|
|
823
|
+
test('collection chaining API can perform index operations', async (t) => {
|
|
824
|
+
const test_port = get_next_port();
|
|
825
|
+
server = await create_server();
|
|
826
|
+
|
|
827
|
+
await new Promise((resolve) => {
|
|
828
|
+
server.listen(test_port, () => {
|
|
829
|
+
setTimeout(resolve, 100);
|
|
830
|
+
});
|
|
831
|
+
});
|
|
832
|
+
|
|
833
|
+
const setup_client = joystickdb.client({
|
|
834
|
+
port: test_port,
|
|
835
|
+
reconnect: false
|
|
836
|
+
});
|
|
837
|
+
|
|
838
|
+
await new Promise((resolve) => {
|
|
839
|
+
setup_client.on('connect', resolve);
|
|
840
|
+
});
|
|
841
|
+
|
|
842
|
+
const setup_result = await setup_client.setup();
|
|
843
|
+
setup_client.disconnect();
|
|
844
|
+
|
|
845
|
+
client = joystickdb.client({
|
|
846
|
+
port: test_port,
|
|
847
|
+
reconnect: false,
|
|
848
|
+
password: setup_result.password
|
|
849
|
+
});
|
|
850
|
+
|
|
851
|
+
await new Promise((resolve) => {
|
|
852
|
+
client.on('authenticated', resolve);
|
|
853
|
+
});
|
|
854
|
+
|
|
855
|
+
const collection = client.db('default').collection('chain_index_test');
|
|
856
|
+
|
|
857
|
+
const create_index_result = await collection.create_index('email');
|
|
858
|
+
|
|
859
|
+
t.is(create_index_result.ok, 1);
|
|
860
|
+
t.truthy(create_index_result.message);
|
|
861
|
+
|
|
862
|
+
const get_indexes_result = await collection.get_indexes();
|
|
863
|
+
|
|
864
|
+
t.is(get_indexes_result.ok, 1);
|
|
865
|
+
t.truthy(get_indexes_result.indexes.find(index => index.field === 'email'));
|
|
866
|
+
|
|
867
|
+
const drop_index_result = await collection.drop_index('email');
|
|
868
|
+
|
|
869
|
+
t.is(drop_index_result.ok, 1);
|
|
870
|
+
t.truthy(drop_index_result.message);
|
|
871
|
+
});
|
|
872
|
+
|
|
873
|
+
test('client can perform upsert_index operations', async (t) => {
|
|
874
|
+
const test_port = get_next_port();
|
|
875
|
+
server = await create_server();
|
|
876
|
+
|
|
877
|
+
await new Promise((resolve) => {
|
|
878
|
+
server.listen(test_port, () => {
|
|
879
|
+
setTimeout(resolve, 100);
|
|
880
|
+
});
|
|
881
|
+
});
|
|
882
|
+
|
|
883
|
+
const setup_client = joystickdb.client({
|
|
884
|
+
port: test_port,
|
|
885
|
+
reconnect: false
|
|
886
|
+
});
|
|
887
|
+
|
|
888
|
+
await new Promise((resolve) => {
|
|
889
|
+
setup_client.on('connect', resolve);
|
|
890
|
+
});
|
|
891
|
+
|
|
892
|
+
const setup_result = await setup_client.setup();
|
|
893
|
+
setup_client.disconnect();
|
|
894
|
+
|
|
895
|
+
client = joystickdb.client({
|
|
896
|
+
port: test_port,
|
|
897
|
+
reconnect: false,
|
|
898
|
+
password: setup_result.password
|
|
899
|
+
});
|
|
900
|
+
|
|
901
|
+
await new Promise((resolve) => {
|
|
902
|
+
client.on('authenticated', resolve);
|
|
903
|
+
});
|
|
904
|
+
|
|
905
|
+
// Test upsert creating new index
|
|
906
|
+
const create_result = await client.db('default').collection('upsert_test').upsert_index('email');
|
|
907
|
+
|
|
908
|
+
t.is(create_result.ok, 1);
|
|
909
|
+
t.is(create_result.operation_type, 'created');
|
|
910
|
+
t.truthy(create_result.message.includes('created'));
|
|
911
|
+
|
|
912
|
+
// Test upsert with same options (should be unchanged)
|
|
913
|
+
const unchanged_result = await client.db('default').collection('upsert_test').upsert_index('email');
|
|
914
|
+
|
|
915
|
+
t.is(unchanged_result.ok, 1);
|
|
916
|
+
t.is(unchanged_result.operation_type, 'unchanged');
|
|
917
|
+
t.truthy(unchanged_result.message.includes('already exists'));
|
|
918
|
+
|
|
919
|
+
// Test upsert with different options (should update)
|
|
920
|
+
const update_result = await client.db('default').collection('upsert_test').upsert_index('email', { unique: true });
|
|
921
|
+
|
|
922
|
+
t.is(update_result.ok, 1);
|
|
923
|
+
t.is(update_result.operation_type, 'updated');
|
|
924
|
+
t.truthy(update_result.message.includes('updated'));
|
|
925
|
+
|
|
926
|
+
// Verify the index was updated
|
|
927
|
+
const get_indexes_result = await client.db('default').collection('upsert_test').get_indexes();
|
|
928
|
+
|
|
929
|
+
t.is(get_indexes_result.ok, 1);
|
|
930
|
+
const email_index = get_indexes_result.indexes.find(index => index.field === 'email');
|
|
931
|
+
t.truthy(email_index);
|
|
932
|
+
t.is(email_index.unique, true);
|
|
933
|
+
});
|
|
934
|
+
|
|
935
|
+
test('collection chaining API can perform upsert_index operations', async (t) => {
|
|
936
|
+
const test_port = get_next_port();
|
|
937
|
+
server = await create_server();
|
|
938
|
+
|
|
939
|
+
await new Promise((resolve) => {
|
|
940
|
+
server.listen(test_port, () => {
|
|
941
|
+
setTimeout(resolve, 100);
|
|
942
|
+
});
|
|
943
|
+
});
|
|
944
|
+
|
|
945
|
+
const setup_client = joystickdb.client({
|
|
946
|
+
port: test_port,
|
|
947
|
+
reconnect: false
|
|
948
|
+
});
|
|
949
|
+
|
|
950
|
+
await new Promise((resolve) => {
|
|
951
|
+
setup_client.on('connect', resolve);
|
|
952
|
+
});
|
|
953
|
+
|
|
954
|
+
const setup_result = await setup_client.setup();
|
|
955
|
+
setup_client.disconnect();
|
|
956
|
+
|
|
957
|
+
client = joystickdb.client({
|
|
958
|
+
port: test_port,
|
|
959
|
+
reconnect: false,
|
|
960
|
+
password: setup_result.password
|
|
961
|
+
});
|
|
962
|
+
|
|
963
|
+
await new Promise((resolve) => {
|
|
964
|
+
client.on('authenticated', resolve);
|
|
965
|
+
});
|
|
966
|
+
|
|
967
|
+
const collection = client.db('default').collection('chain_upsert_test');
|
|
968
|
+
|
|
969
|
+
// Test upsert creating new index
|
|
970
|
+
const create_result = await collection.upsert_index('name');
|
|
971
|
+
|
|
972
|
+
t.is(create_result.ok, 1);
|
|
973
|
+
t.is(create_result.operation_type, 'created');
|
|
974
|
+
t.truthy(create_result.message.includes('created'));
|
|
975
|
+
|
|
976
|
+
// Test upsert with same options (should be unchanged)
|
|
977
|
+
const unchanged_result = await collection.upsert_index('name');
|
|
978
|
+
|
|
979
|
+
t.is(unchanged_result.ok, 1);
|
|
980
|
+
t.is(unchanged_result.operation_type, 'unchanged');
|
|
981
|
+
t.truthy(unchanged_result.message.includes('already exists'));
|
|
982
|
+
|
|
983
|
+
// Test upsert with different options (should update)
|
|
984
|
+
const update_result = await collection.upsert_index('name', { sparse: true });
|
|
985
|
+
|
|
986
|
+
t.is(update_result.ok, 1);
|
|
987
|
+
t.is(update_result.operation_type, 'updated');
|
|
988
|
+
t.truthy(update_result.message.includes('updated'));
|
|
989
|
+
|
|
990
|
+
// Verify the index was updated
|
|
991
|
+
const get_indexes_result = await collection.get_indexes();
|
|
992
|
+
|
|
993
|
+
t.is(get_indexes_result.ok, 1);
|
|
994
|
+
const name_index = get_indexes_result.indexes.find(index => index.field === 'name');
|
|
995
|
+
t.truthy(name_index);
|
|
996
|
+
t.is(name_index.sparse, true);
|
|
997
|
+
});
|
|
998
|
+
|
|
999
|
+
test('upsert_index handles unique constraint violations properly', async (t) => {
|
|
1000
|
+
const test_port = get_next_port();
|
|
1001
|
+
server = await create_server();
|
|
1002
|
+
|
|
1003
|
+
await new Promise((resolve) => {
|
|
1004
|
+
server.listen(test_port, () => {
|
|
1005
|
+
setTimeout(resolve, 100);
|
|
1006
|
+
});
|
|
1007
|
+
});
|
|
1008
|
+
|
|
1009
|
+
const setup_client = joystickdb.client({
|
|
1010
|
+
port: test_port,
|
|
1011
|
+
reconnect: false
|
|
1012
|
+
});
|
|
1013
|
+
|
|
1014
|
+
await new Promise((resolve) => {
|
|
1015
|
+
setup_client.on('connect', resolve);
|
|
1016
|
+
});
|
|
1017
|
+
|
|
1018
|
+
const setup_result = await setup_client.setup();
|
|
1019
|
+
setup_client.disconnect();
|
|
1020
|
+
|
|
1021
|
+
client = joystickdb.client({
|
|
1022
|
+
port: test_port,
|
|
1023
|
+
reconnect: false,
|
|
1024
|
+
password: setup_result.password
|
|
1025
|
+
});
|
|
1026
|
+
|
|
1027
|
+
await new Promise((resolve) => {
|
|
1028
|
+
client.on('authenticated', resolve);
|
|
1029
|
+
});
|
|
1030
|
+
|
|
1031
|
+
const collection = client.db('default').collection('unique_constraint_test');
|
|
1032
|
+
|
|
1033
|
+
// Insert documents with duplicate values
|
|
1034
|
+
await collection.insert_one({ email: 'duplicate@example.com', name: 'User 1' });
|
|
1035
|
+
await collection.insert_one({ email: 'duplicate@example.com', name: 'User 2' });
|
|
1036
|
+
|
|
1037
|
+
// Create non-unique index first
|
|
1038
|
+
const create_result = await collection.upsert_index('email', { unique: false });
|
|
1039
|
+
t.is(create_result.ok, 1);
|
|
1040
|
+
t.is(create_result.operation_type, 'created');
|
|
1041
|
+
|
|
1042
|
+
// Try to update to unique index - should fail due to duplicates
|
|
1043
|
+
const error = await t.throwsAsync(async () => {
|
|
1044
|
+
await collection.upsert_index('email', { unique: true });
|
|
1045
|
+
});
|
|
1046
|
+
|
|
1047
|
+
t.truthy(error.message.includes('Duplicate value for unique index'));
|
|
1048
|
+
});
|
|
1049
|
+
|
|
1050
|
+
test('collection chaining API works with options', async (t) => {
|
|
1051
|
+
const test_port = get_next_port();
|
|
1052
|
+
server = await create_server();
|
|
1053
|
+
|
|
1054
|
+
await new Promise((resolve) => {
|
|
1055
|
+
server.listen(test_port, () => {
|
|
1056
|
+
setTimeout(resolve, 100);
|
|
1057
|
+
});
|
|
1058
|
+
});
|
|
1059
|
+
|
|
1060
|
+
const setup_client = joystickdb.client({
|
|
1061
|
+
port: test_port,
|
|
1062
|
+
reconnect: false
|
|
1063
|
+
});
|
|
1064
|
+
|
|
1065
|
+
await new Promise((resolve) => {
|
|
1066
|
+
setup_client.on('connect', resolve);
|
|
1067
|
+
});
|
|
1068
|
+
|
|
1069
|
+
const setup_result = await setup_client.setup();
|
|
1070
|
+
setup_client.disconnect();
|
|
1071
|
+
|
|
1072
|
+
client = joystickdb.client({
|
|
1073
|
+
port: test_port,
|
|
1074
|
+
reconnect: false,
|
|
1075
|
+
password: setup_result.password
|
|
1076
|
+
});
|
|
1077
|
+
|
|
1078
|
+
await new Promise((resolve) => {
|
|
1079
|
+
client.on('authenticated', resolve);
|
|
1080
|
+
});
|
|
1081
|
+
|
|
1082
|
+
const collection = client.db('default').collection('chain_options_test');
|
|
1083
|
+
|
|
1084
|
+
const insert_result = await collection.insert_one({
|
|
1085
|
+
name: 'Test User',
|
|
1086
|
+
email: 'test@example.com'
|
|
1087
|
+
}, {
|
|
1088
|
+
validate: true
|
|
1089
|
+
});
|
|
1090
|
+
|
|
1091
|
+
t.is(insert_result.ok, 1);
|
|
1092
|
+
t.truthy(insert_result.inserted_id);
|
|
1093
|
+
|
|
1094
|
+
const find_result = await collection.find_one({
|
|
1095
|
+
name: 'Test User'
|
|
1096
|
+
}, {
|
|
1097
|
+
projection: { name: 1 }
|
|
1098
|
+
});
|
|
1099
|
+
|
|
1100
|
+
t.is(find_result.name, 'Test User');
|
|
1101
|
+
|
|
1102
|
+
const update_result = await collection.update_one({
|
|
1103
|
+
name: 'Test User'
|
|
1104
|
+
}, {
|
|
1105
|
+
$set: { updated: true }
|
|
1106
|
+
}, {
|
|
1107
|
+
upsert: false
|
|
1108
|
+
});
|
|
1109
|
+
|
|
1110
|
+
t.is(update_result.ok, 1);
|
|
1111
|
+
t.is(update_result.modified_count, 1);
|
|
1112
|
+
|
|
1113
|
+
const delete_result = await collection.delete_one({
|
|
1114
|
+
name: 'Test User'
|
|
1115
|
+
}, {
|
|
1116
|
+
limit: 1
|
|
1117
|
+
});
|
|
1118
|
+
|
|
1119
|
+
t.is(delete_result.ok, 1);
|
|
1120
|
+
t.is(delete_result.deleted_count, 1);
|
|
1121
|
+
});
|
|
1122
|
+
|
|
1123
|
+
test('both old and new API styles work simultaneously', async (t) => {
|
|
1124
|
+
const test_port = get_next_port();
|
|
1125
|
+
server = await create_server();
|
|
1126
|
+
|
|
1127
|
+
await new Promise((resolve) => {
|
|
1128
|
+
server.listen(test_port, () => {
|
|
1129
|
+
setTimeout(resolve, 100);
|
|
1130
|
+
});
|
|
1131
|
+
});
|
|
1132
|
+
|
|
1133
|
+
const setup_client = joystickdb.client({
|
|
1134
|
+
port: test_port,
|
|
1135
|
+
reconnect: false
|
|
1136
|
+
});
|
|
1137
|
+
|
|
1138
|
+
await new Promise((resolve) => {
|
|
1139
|
+
setup_client.on('connect', resolve);
|
|
1140
|
+
});
|
|
1141
|
+
|
|
1142
|
+
const setup_result = await setup_client.setup();
|
|
1143
|
+
setup_client.disconnect();
|
|
1144
|
+
|
|
1145
|
+
client = joystickdb.client({
|
|
1146
|
+
port: test_port,
|
|
1147
|
+
reconnect: false,
|
|
1148
|
+
password: setup_result.password
|
|
1149
|
+
});
|
|
1150
|
+
|
|
1151
|
+
await new Promise((resolve) => {
|
|
1152
|
+
client.on('authenticated', resolve);
|
|
1153
|
+
});
|
|
1154
|
+
|
|
1155
|
+
// Use database API style
|
|
1156
|
+
const db_insert_result = await client.db('default').collection('mixed_test').insert_one({
|
|
1157
|
+
method: 'db_api',
|
|
1158
|
+
value: 100
|
|
1159
|
+
});
|
|
1160
|
+
|
|
1161
|
+
t.is(db_insert_result.ok, 1);
|
|
1162
|
+
t.truthy(db_insert_result.inserted_id);
|
|
1163
|
+
|
|
1164
|
+
// Use collection chaining API style
|
|
1165
|
+
const collection = client.db('default').collection('mixed_test');
|
|
1166
|
+
const collection_insert_result = await collection.insert_one({
|
|
1167
|
+
method: 'collection_api',
|
|
1168
|
+
value: 200
|
|
1169
|
+
});
|
|
1170
|
+
|
|
1171
|
+
t.is(collection_insert_result.ok, 1);
|
|
1172
|
+
t.truthy(collection_insert_result.inserted_id);
|
|
1173
|
+
|
|
1174
|
+
// Verify both documents exist using database API
|
|
1175
|
+
const db_find_result = await client.db('default').collection('mixed_test').find({});
|
|
1176
|
+
t.truthy(db_find_result);
|
|
1177
|
+
t.is(db_find_result.length, 2);
|
|
1178
|
+
|
|
1179
|
+
// Verify both documents exist using collection API
|
|
1180
|
+
const collection_find_result = await collection.find({});
|
|
1181
|
+
t.truthy(collection_find_result);
|
|
1182
|
+
t.is(collection_find_result.length, 2);
|
|
1183
|
+
|
|
1184
|
+
// Check specific documents
|
|
1185
|
+
const db_doc = await client.db('default').collection('mixed_test').find_one({ method: 'db_api' });
|
|
1186
|
+
const collection_doc = await collection.find_one({ method: 'collection_api' });
|
|
1187
|
+
|
|
1188
|
+
t.is(db_doc.value, 100);
|
|
1189
|
+
t.is(collection_doc.value, 200);
|
|
1190
|
+
});
|
|
1191
|
+
|
|
1192
|
+
test('collection chaining API handles errors properly', async (t) => {
|
|
1193
|
+
const test_port = get_next_port();
|
|
1194
|
+
server = await create_server();
|
|
1195
|
+
|
|
1196
|
+
await new Promise((resolve) => {
|
|
1197
|
+
server.listen(test_port, () => {
|
|
1198
|
+
setTimeout(resolve, 100);
|
|
1199
|
+
});
|
|
1200
|
+
});
|
|
1201
|
+
|
|
1202
|
+
const setup_client = joystickdb.client({
|
|
1203
|
+
port: test_port,
|
|
1204
|
+
reconnect: false
|
|
1205
|
+
});
|
|
1206
|
+
|
|
1207
|
+
await new Promise((resolve) => {
|
|
1208
|
+
setup_client.on('connect', resolve);
|
|
1209
|
+
});
|
|
1210
|
+
|
|
1211
|
+
const setup_result = await setup_client.setup();
|
|
1212
|
+
setup_client.disconnect();
|
|
1213
|
+
|
|
1214
|
+
client = joystickdb.client({
|
|
1215
|
+
port: test_port,
|
|
1216
|
+
reconnect: false,
|
|
1217
|
+
password: setup_result.password
|
|
1218
|
+
});
|
|
1219
|
+
|
|
1220
|
+
await new Promise((resolve) => {
|
|
1221
|
+
client.on('authenticated', resolve);
|
|
1222
|
+
});
|
|
1223
|
+
|
|
1224
|
+
const collection = client.db('default').collection('error_test');
|
|
1225
|
+
|
|
1226
|
+
// Test error handling by trying to update with invalid filter
|
|
1227
|
+
const error = await t.throwsAsync(async () => {
|
|
1228
|
+
await collection.update_one(null, { $set: { test: true } });
|
|
1229
|
+
});
|
|
1230
|
+
|
|
1231
|
+
t.truthy(error);
|
|
1232
|
+
});
|