axiodb 19.1.1 → 20.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (228) hide show
  1. package/README.md +86 -9
  2. package/cli/VERSION +1 -1
  3. package/cli/cmd/auth_management.go +68 -0
  4. package/cli/cmd/document.go +33 -0
  5. package/cli/cmd/health.go +19 -0
  6. package/cli/cmd/transaction.go +191 -0
  7. package/cli/cmd/version.go +1 -1
  8. package/cli/pkg/commands/document.go +19 -0
  9. package/cli/pkg/commands/health.go +18 -0
  10. package/cli/pkg/commands/transaction.go +84 -0
  11. package/cli/pkg/httpclient/client.go +76 -0
  12. package/lib/Helper/Console.helper.js.map +1 -1
  13. package/lib/Helper/Converter.helper.d.ts +1 -1
  14. package/lib/Helper/Converter.helper.js +0 -1
  15. package/lib/Helper/Converter.helper.js.map +1 -1
  16. package/lib/Helper/DocumentLoader.helper.js +2 -1
  17. package/lib/Helper/DocumentLoader.helper.js.map +1 -1
  18. package/lib/Helper/Logger.helper.d.ts +5 -0
  19. package/lib/Helper/Logger.helper.js +45 -0
  20. package/lib/Helper/Logger.helper.js.map +1 -0
  21. package/lib/Helper/PathSanitizer.helper.js.map +1 -1
  22. package/lib/Helper/SortedIndexValues.helper.js.map +1 -1
  23. package/lib/Helper/UniqueGenerator.helper.js.map +1 -1
  24. package/lib/Helper/response.helper.d.ts +2 -2
  25. package/lib/Helper/response.helper.js +6 -3
  26. package/lib/Helper/response.helper.js.map +1 -1
  27. package/lib/Memory/memory.operation.d.ts +9 -4
  28. package/lib/Memory/memory.operation.js +3 -3
  29. package/lib/Memory/memory.operation.js.map +1 -1
  30. package/lib/Services/Aggregation/Aggregation.Operation.d.ts +1 -1
  31. package/lib/Services/Aggregation/Aggregation.Operation.js +0 -1
  32. package/lib/Services/Aggregation/Aggregation.Operation.js.map +1 -1
  33. package/lib/Services/Aggregation/OperatorRegistry.js.map +1 -1
  34. package/lib/Services/Aggregation/operators/accumulatorOperators.d.ts +12 -12
  35. package/lib/Services/Aggregation/operators/accumulatorOperators.js +2 -3
  36. package/lib/Services/Aggregation/operators/accumulatorOperators.js.map +1 -1
  37. package/lib/Services/Aggregation/operators/expressionOperators.d.ts +3 -3
  38. package/lib/Services/Aggregation/operators/expressionOperators.js +111 -108
  39. package/lib/Services/Aggregation/operators/expressionOperators.js.map +1 -1
  40. package/lib/Services/Aggregation/operators/stageOperators.d.ts +20 -37
  41. package/lib/Services/Aggregation/operators/stageOperators.js +11 -11
  42. package/lib/Services/Aggregation/operators/stageOperators.js.map +1 -1
  43. package/lib/Services/Auth/AuthEvents.service.js.map +1 -1
  44. package/lib/Services/Auth/AuthSeeder.service.js +2 -2
  45. package/lib/Services/Auth/AuthSeeder.service.js.map +1 -1
  46. package/lib/Services/Auth/AuthService.service.js +5 -8
  47. package/lib/Services/Auth/AuthService.service.js.map +1 -1
  48. package/lib/Services/Auth/ConfigDatabase.service.js.map +1 -1
  49. package/lib/Services/Auth/CookieCodec.helper.js.map +1 -1
  50. package/lib/Services/Auth/LoginRateLimiter.service.js.map +1 -1
  51. package/lib/Services/Auth/PasswordHasher.helper.js.map +1 -1
  52. package/lib/Services/Auth/PermissionChecker.helper.js.map +1 -1
  53. package/lib/Services/Auth/SessionStore.service.js.map +1 -1
  54. package/lib/Services/CRUD Operation/Create.operation.js +0 -1
  55. package/lib/Services/CRUD Operation/Create.operation.js.map +1 -1
  56. package/lib/Services/CRUD Operation/Delete.operation.d.ts +2 -2
  57. package/lib/Services/CRUD Operation/Delete.operation.js +2 -3
  58. package/lib/Services/CRUD Operation/Delete.operation.js.map +1 -1
  59. package/lib/Services/CRUD Operation/Reader.operation.d.ts +11 -3
  60. package/lib/Services/CRUD Operation/Reader.operation.js +76 -40
  61. package/lib/Services/CRUD Operation/Reader.operation.js.map +1 -1
  62. package/lib/Services/CRUD Operation/Update.operation.d.ts +4 -4
  63. package/lib/Services/CRUD Operation/Update.operation.js +2 -2
  64. package/lib/Services/CRUD Operation/Update.operation.js.map +1 -1
  65. package/lib/Services/Collection/collection.operation.d.ts +10 -3
  66. package/lib/Services/Collection/collection.operation.js +32 -7
  67. package/lib/Services/Collection/collection.operation.js.map +1 -1
  68. package/lib/Services/Database/database.operation.js +13 -9
  69. package/lib/Services/Database/database.operation.js.map +1 -1
  70. package/lib/Services/Index/Index.service.d.ts +1 -1
  71. package/lib/Services/Index/Index.service.js +1 -1
  72. package/lib/Services/Index/Index.service.js.map +1 -1
  73. package/lib/Services/Index/IndexCache.service.js +4 -5
  74. package/lib/Services/Index/IndexCache.service.js.map +1 -1
  75. package/lib/Services/Index/ReadIndex.service.d.ts +4 -4
  76. package/lib/Services/Index/ReadIndex.service.js +10 -9
  77. package/lib/Services/Index/ReadIndex.service.js.map +1 -1
  78. package/lib/Services/Indexation.operation.d.ts +1 -1
  79. package/lib/Services/Indexation.operation.js +7 -6
  80. package/lib/Services/Indexation.operation.js.map +1 -1
  81. package/lib/Services/Transaction/LockManager.service.js +3 -4
  82. package/lib/Services/Transaction/LockManager.service.js.map +1 -1
  83. package/lib/Services/Transaction/Session.service.js +9 -7
  84. package/lib/Services/Transaction/Session.service.js.map +1 -1
  85. package/lib/Services/Transaction/Transaction.service.d.ts +4 -2
  86. package/lib/Services/Transaction/Transaction.service.js +7 -2
  87. package/lib/Services/Transaction/Transaction.service.js.map +1 -1
  88. package/lib/Services/Transaction/TransactionIndexManager.service.d.ts +1 -1
  89. package/lib/Services/Transaction/TransactionIndexManager.service.js +11 -6
  90. package/lib/Services/Transaction/TransactionIndexManager.service.js.map +1 -1
  91. package/lib/Services/Transaction/TransactionRegistry.service.js.map +1 -1
  92. package/lib/Services/Transaction/WriteAheadLog.service.js +0 -1
  93. package/lib/Services/Transaction/WriteAheadLog.service.js.map +1 -1
  94. package/lib/client/AggregationProxy.js.map +1 -1
  95. package/lib/client/AxioDBCloud.client.d.ts +15 -2
  96. package/lib/client/AxioDBCloud.client.js +24 -2
  97. package/lib/client/AxioDBCloud.client.js.map +1 -1
  98. package/lib/client/CollectionProxy.d.ts +8 -0
  99. package/lib/client/CollectionProxy.js +26 -0
  100. package/lib/client/CollectionProxy.js.map +1 -1
  101. package/lib/client/DatabaseProxy.js.map +1 -1
  102. package/lib/client/DeleteOperationProxy.js.map +1 -1
  103. package/lib/client/PooledConnection.d.ts +1 -1
  104. package/lib/client/PooledConnection.js +6 -3
  105. package/lib/client/PooledConnection.js.map +1 -1
  106. package/lib/client/ReaderProxy.d.ts +3 -1
  107. package/lib/client/ReaderProxy.js +7 -0
  108. package/lib/client/ReaderProxy.js.map +1 -1
  109. package/lib/client/TransactionProxy.d.ts +37 -0
  110. package/lib/client/TransactionProxy.js +101 -0
  111. package/lib/client/TransactionProxy.js.map +1 -0
  112. package/lib/client/UpdateOperationProxy.js.map +1 -1
  113. package/lib/client/types/client.types.js.map +1 -1
  114. package/lib/config/DB.js.map +1 -1
  115. package/lib/config/Interfaces/Helper/response.helper.interface.d.ts +2 -2
  116. package/lib/config/Interfaces/Helper/response.helper.interface.js +0 -1
  117. package/lib/config/Interfaces/Helper/response.helper.interface.js.map +1 -1
  118. package/lib/config/Interfaces/Operation/aggregation.interface.d.ts +4 -4
  119. package/lib/config/Interfaces/Operation/aggregation.interface.js +0 -1
  120. package/lib/config/Interfaces/Operation/aggregation.interface.js.map +1 -1
  121. package/lib/config/Interfaces/Operation/database.operation.interface.d.ts +4 -1
  122. package/lib/config/Interfaces/Operation/database.operation.interface.js +0 -1
  123. package/lib/config/Interfaces/Operation/database.operation.interface.js.map +1 -1
  124. package/lib/config/Interfaces/Transaction/transaction.interface.d.ts +3 -3
  125. package/lib/config/Interfaces/shared.types.d.ts +36 -0
  126. package/lib/config/Interfaces/shared.types.js +7 -0
  127. package/lib/config/Interfaces/shared.types.js.map +1 -0
  128. package/lib/config/Keys/Keys.js.map +1 -1
  129. package/lib/config/Keys/Permissions.js.map +1 -1
  130. package/lib/config/Keys/StatusCode.js.map +1 -1
  131. package/lib/engine/Filesystem/FileManager.js +3 -4
  132. package/lib/engine/Filesystem/FileManager.js.map +1 -1
  133. package/lib/engine/Filesystem/FolderManager.js +11 -11
  134. package/lib/engine/Filesystem/FolderManager.js.map +1 -1
  135. package/lib/engine/cli/worker_process.js.map +1 -1
  136. package/lib/engine/node/WorkerForDataLoad.engine.js +7 -6
  137. package/lib/engine/node/WorkerForDataLoad.engine.js.map +1 -1
  138. package/lib/engine/node/WorkerForSearch.engine.js +0 -1
  139. package/lib/engine/node/WorkerForSearch.engine.js.map +1 -1
  140. package/lib/server/config/PortFreeChecker.js +0 -1
  141. package/lib/server/config/PortFreeChecker.js.map +1 -1
  142. package/lib/server/config/keys.js +0 -1
  143. package/lib/server/config/keys.js.map +1 -1
  144. package/lib/server/config/server.js +2 -2
  145. package/lib/server/config/server.js.map +1 -1
  146. package/lib/server/controller/Auth/Auth.controller.js.map +1 -1
  147. package/lib/server/controller/Auth/RoleManagement.controller.js.map +1 -1
  148. package/lib/server/controller/Auth/UserManagement.controller.js.map +1 -1
  149. package/lib/server/controller/Collections/Collection.controller.js +9 -7
  150. package/lib/server/controller/Collections/Collection.controller.js.map +1 -1
  151. package/lib/server/controller/Database/Databse.controller.js +12 -13
  152. package/lib/server/controller/Database/Databse.controller.js.map +1 -1
  153. package/lib/server/controller/Index/Index.controller.js +4 -3
  154. package/lib/server/controller/Index/Index.controller.js.map +1 -1
  155. package/lib/server/controller/Operation/CRUD.controller.d.ts +1 -0
  156. package/lib/server/controller/Operation/CRUD.controller.js +42 -18
  157. package/lib/server/controller/Operation/CRUD.controller.js.map +1 -1
  158. package/lib/server/controller/Stats.controller.js +21 -15
  159. package/lib/server/controller/Stats.controller.js.map +1 -1
  160. package/lib/server/helper/databaseImport.helper.js.map +1 -1
  161. package/lib/server/helper/documentCounterInFolder.helper.js.map +1 -1
  162. package/lib/server/helper/responseBuilder.helper.d.ts +2 -2
  163. package/lib/server/helper/responseBuilder.helper.js.map +1 -1
  164. package/lib/server/middleware/auth.middleware.js.map +1 -1
  165. package/lib/server/middleware/permission.middleware.js.map +1 -1
  166. package/lib/server/router/Router.js +8 -7
  167. package/lib/server/router/Router.js.map +1 -1
  168. package/lib/server/router/Routers/Auth.routes.js.map +1 -1
  169. package/lib/server/router/Routers/Collection.routes.js +3 -3
  170. package/lib/server/router/Routers/Collection.routes.js.map +1 -1
  171. package/lib/server/router/Routers/DB.routes.js +1 -1
  172. package/lib/server/router/Routers/DB.routes.js.map +1 -1
  173. package/lib/server/router/Routers/Index.routes.js.map +1 -1
  174. package/lib/server/router/Routers/Operation.routes.js +25 -10
  175. package/lib/server/router/Routers/Operation.routes.js.map +1 -1
  176. package/lib/server/router/Routers/RoleManagement.routes.js.map +1 -1
  177. package/lib/server/router/Routers/UserManagement.routes.js.map +1 -1
  178. package/lib/tcp/config/keys.d.ts +32 -32
  179. package/lib/tcp/config/keys.js.map +1 -1
  180. package/lib/tcp/config/permissions.d.ts +1 -4
  181. package/lib/tcp/config/permissions.js +8 -4
  182. package/lib/tcp/config/permissions.js.map +1 -1
  183. package/lib/tcp/config/protocol.d.ts +3 -3
  184. package/lib/tcp/config/protocol.js +31 -9
  185. package/lib/tcp/config/protocol.js.map +1 -1
  186. package/lib/tcp/config/server.js +17 -12
  187. package/lib/tcp/config/server.js.map +1 -1
  188. package/lib/tcp/connection/ConnectionManager.js.map +1 -1
  189. package/lib/tcp/connection/ConnectionRateLimiter.js.map +1 -1
  190. package/lib/tcp/connection/RequestContext.d.ts +2 -2
  191. package/lib/tcp/connection/RequestContext.js.map +1 -1
  192. package/lib/tcp/connection/TransactionManager.d.ts +26 -0
  193. package/lib/tcp/connection/TransactionManager.js +114 -0
  194. package/lib/tcp/connection/TransactionManager.js.map +1 -0
  195. package/lib/tcp/handler/CommandHandler.d.ts +3 -0
  196. package/lib/tcp/handler/CommandHandler.js +32 -8
  197. package/lib/tcp/handler/CommandHandler.js.map +1 -1
  198. package/lib/tcp/handler/handlers/Auth.handler.d.ts +4 -2
  199. package/lib/tcp/handler/handlers/Auth.handler.js.map +1 -1
  200. package/lib/tcp/handler/handlers/Collection.handler.d.ts +7 -5
  201. package/lib/tcp/handler/handlers/Collection.handler.js +1 -3
  202. package/lib/tcp/handler/handlers/Collection.handler.js.map +1 -1
  203. package/lib/tcp/handler/handlers/DB.handler.d.ts +6 -4
  204. package/lib/tcp/handler/handlers/DB.handler.js +1 -2
  205. package/lib/tcp/handler/handlers/DB.handler.js.map +1 -1
  206. package/lib/tcp/handler/handlers/Operation.handler.d.ts +19 -57
  207. package/lib/tcp/handler/handlers/Operation.handler.js +138 -167
  208. package/lib/tcp/handler/handlers/Operation.handler.js.map +1 -1
  209. package/lib/tcp/handler/handlers/Transaction.handler.d.ts +18 -0
  210. package/lib/tcp/handler/handlers/Transaction.handler.js +199 -0
  211. package/lib/tcp/handler/handlers/Transaction.handler.js.map +1 -0
  212. package/lib/tcp/types/command.types.d.ts +6 -1
  213. package/lib/tcp/types/command.types.js +11 -1
  214. package/lib/tcp/types/command.types.js.map +1 -1
  215. package/lib/tcp/types/protocol.types.d.ts +10 -7
  216. package/lib/tcp/types/protocol.types.js.map +1 -1
  217. package/lib/utility/BufferLoaderWithWorker.utils.js +6 -5
  218. package/lib/utility/BufferLoaderWithWorker.utils.js.map +1 -1
  219. package/lib/utility/Searcher.utils.d.ts +3 -7
  220. package/lib/utility/Searcher.utils.js +49 -49
  221. package/lib/utility/Searcher.utils.js.map +1 -1
  222. package/lib/utility/SortData.utils.d.ts +3 -2
  223. package/lib/utility/SortData.utils.js +3 -19
  224. package/lib/utility/SortData.utils.js.map +1 -1
  225. package/lib/utility/ZipUnzip.utils.d.ts +2 -2
  226. package/lib/utility/ZipUnzip.utils.js +2 -2
  227. package/lib/utility/ZipUnzip.utils.js.map +1 -1
  228. package/package.json +10 -5
package/README.md CHANGED
@@ -1,19 +1,24 @@
1
- # AxioDB: The Pure JavaScript Alternative to SQLite
1
+ # AxioDB: SQLite Alternative for JavaScript
2
2
 
3
3
  [![npm version](https://badge.fury.io/js/axiodb.svg)](https://badge.fury.io/js/axiodb)
4
+ [![npm version shields](https://img.shields.io/npm/v/axiodb?logo=npm&label=npm)](https://www.npmjs.com/package/axiodb)
4
5
  [![npm downloads total](https://img.shields.io/npm/dt/axiodb.svg)](https://www.npmjs.com/package/axiodb)
5
6
  [![npm downloads yearly](https://img.shields.io/npm/dy/axiodb.svg)](https://www.npmjs.com/package/axiodb)
6
7
  [![npm downloads weekly](https://img.shields.io/npm/dw/axiodb.svg)](https://www.npmjs.com/package/axiodb)
7
8
  [![npm downloads monthly](https://img.shields.io/npm/dm/axiodb.svg)](https://www.npmjs.com/package/axiodb)
9
+ [![install size](https://img.shields.io/npm/unpacked-size/axiodb?label=install%20size)](https://www.npmjs.com/package/axiodb)
10
+ [![jsDelivr hits](https://img.shields.io/jsdelivr/npm/hm/axiodb?label=jsDelivr)](https://www.jsdelivr.com/package/npm/axiodb)
11
+ [![npm types](https://img.shields.io/npm/types/axiodb?label=types)](https://www.npmjs.com/package/axiodb)
8
12
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
13
 
10
14
  [![Push to Registry](https://github.com/nexoral/AxioDB/actions/workflows/Push.yml/badge.svg?branch=main)](https://github.com/nexoral/AxioDB/actions/workflows/Push.yml)
11
15
  [![CodeQL](https://github.com/nexoral/AxioDB/actions/workflows/github-code-scanning/codeql/badge.svg?branch=main)](https://github.com/nexoral/AxioDB/actions/workflows/github-code-scanning/codeql)
12
16
  [![Socket Security](https://socket.dev/api/badge/npm/package/axiodb)](https://socket.dev/npm/package/axiodb)
17
+ [![GitHub Stars](https://img.shields.io/github/stars/nexoral/AxioDB?style=social)](https://github.com/nexoral/AxioDB)
13
18
 
14
19
  [![Node.js Version](https://img.shields.io/badge/node-%3E%3D20.0.0-brightgreen)](https://nodejs.org)
15
20
  [![Tested on Node.js](https://img.shields.io/badge/tested%20on-20%20%7C%2021%20%7C%2022%20%7C%2023%20%7C%2024%20%7C%2025%20%7C%2026-blue)](https://github.com/nexoral/AxioDB/actions/workflows/Push.yml)
16
- [![TypeScript](https://img.shields.io/badge/TypeScript-5.6-blue)](https://www.typescriptlang.org/)
21
+ [![TypeScript](https://img.shields.io/badge/TypeScript-6.0-blue)](https://www.typescriptlang.org/)
17
22
  [![Zero Dependencies](https://img.shields.io/badge/dependencies-0%20native-success)](https://www.npmjs.com/package/axiodb)
18
23
 
19
24
  👉 **[Official Documentation](https://axiodb.in/)**: Access full guides, examples, and API references.
@@ -156,6 +161,8 @@ const db = new AxioDB({
156
161
 
157
162
  ### Querying
158
163
  - **Chainable Query API:** `.query()`, `.Sort()`, `.Limit()`, `.Skip()`, `.setCount()`, `.setProject()`, `.exec()` / `.findOne()`
164
+ - **Index Hints:** `.hint('fieldName')` to force a specific index on any query for predictable performance
165
+ - **Batch Read:** `.findByIds(['id1', 'id2'])` to retrieve multiple documents by ID in a single call
159
166
  - **MongoDB-style Query Operators:** `$gt`, `$gte`, `$lt`, `$lte`, `$ne`, `$in`, `$nin`, `$exists`, `$regex`, `$or`, `$and`
160
167
  - **Aggregation Pipelines:** 60+ MongoDB-compatible stages (`$match`, `$group`, `$sort`, `$project`, `$limit`, `$skip`, `$unwind`, `$addFields`, `$lookup`, `$facet`, `$bucket`, `$count`, `$sample`, ...) with full expression evaluator, cross-collection `$lookup` joins, and custom operator registration via `OperatorRegistry`
161
168
  - **Bulk Operations:** high-performance `insertMany`, `UpdateMany`, `deleteMany`
@@ -170,14 +177,23 @@ const db = new AxioDB({
170
177
  ### Transactions
171
178
  - **ACID-compliant, single-collection transactions** with savepoints, rollback, and Write-Ahead Logging (WAL) for crash recovery
172
179
  - **Session Management:** scoped transactions with timeout support
180
+ - **TCP Transactions:** BEGIN/COMMIT/ROLLBACK over TCP with savepoints, connection-pinned client proxy, and auto-rollback on disconnect
173
181
 
174
182
  ```javascript
183
+ // Local transaction
175
184
  const session = collection.startSession();
176
185
  await session.withTransaction(async (tx) => {
177
186
  await tx.insert({ name: 'Alice', balance: 1000 });
178
- await tx.update({ name: 'Bob' }, { $inc: { balance: -100 } });
187
+ // Updates are flat merges; AxioDB does not implement MongoDB's $inc operator.
188
+ await tx.update({ name: 'Bob' }, { balance: 900 });
179
189
  // Auto-commits on success, auto-rolls-back on error
180
190
  });
191
+
192
+ // TCP transaction
193
+ const tx = await client.db('mydb').collection('users').beginTransaction();
194
+ await tx.insert({ name: 'Alice', balance: 1000 });
195
+ await tx.update({ name: 'Bob' }, { balance: 900 });
196
+ await tx.commit(); // or await tx.rollback();
181
197
  ```
182
198
 
183
199
  ### Caching
@@ -211,7 +227,7 @@ await session.withTransaction(async (tx) => {
211
227
  - **🔄 Zero Code Changes:** same `createDB`/`createCollection`/`insert`/`query` API as embedded AxioDB
212
228
  - **⚡ Fast Binary Protocol:** length-prefixed JSON framing, with automatic reconnection
213
229
  - **🔐 Optional Authentication:** shared RBAC with the GUI, per-IP rate limiting (see [Advanced](#advanced-tcp-authentication) below)
214
- - **📦 35+ Commands:** full CRUD, aggregation, and indexing over the wire
230
+ - **📦 32 Commands:** full CRUD, aggregation, indexing, and transactions over the wire
215
231
  - **🔁 Auto-Reconnect:** exponential backoff, up to 10 retry attempts
216
232
  - **💓 Heartbeat Monitoring:** `PING`/`PONG` every 30 seconds
217
233
  - **🆔 Request Correlation:** UUID-based request/response matching
@@ -371,12 +387,17 @@ irm https://raw.githubusercontent.com/nexoral/AxioDB/main/cli/Scripts/install.ps
371
387
 
372
388
  ### Usage
373
389
 
390
+ > **Activation notice:** Data commands (`db`/`collection`/`document`/`index`/`transaction`/`ping`/`health`/`connect`) require the server started with `TCP: true` (`AXIODB_TCP=true`, port 27019). Management commands (`user`/`role`/`user change-password`/`export`/`import`) require `GUI: true`/`HTTP: true` (`AXIODB_GUI=true`, port 27018). TCP is data-plane only — no management over TCP by design.
391
+
374
392
  **Single commands:**
375
393
  ```bash
376
394
  axiodb -c axiodb://127.0.0.1:27019 ping
377
395
  axiodb -c axiodb://127.0.0.1:27019 db list
378
396
  axiodb -c axiodb://127.0.0.1:27019 document insert '{"name":"Alice"}' --db mydb --collection users
379
397
  axiodb -c axiodb://127.0.0.1:27019 document query '{}' --db mydb --collection users
398
+ axiodb -c axiodb://127.0.0.1:27019 document query '{}' --hint email --db mydb --collection users
399
+ axiodb -c axiodb://127.0.0.1:27019 health
400
+ axiodb -c axiodb://127.0.0.1:27019 transaction begin --db mydb --collection users
380
401
  ```
381
402
 
382
403
  **Interactive REPL (MongoDB shell style):**
@@ -412,9 +433,36 @@ axiodb import ./backups/mydb.tar.gz --http-host localhost --http-port 27018 -u a
412
433
  # Tab completes .tar.gz file paths
413
434
  ```
414
435
 
436
+ **User and role administration (via HTTP API):**
437
+ ```bash
438
+ axiodb user list --http-host localhost --http-port 27018 -u admin -p secret
439
+ axiodb user create analyst analyst123 View --http-host localhost --http-port 27018 -u admin -p secret
440
+ axiodb user change-password oldPass newPass --http-host localhost --http-port 27018 -u analyst -p analyst123
441
+ axiodb role list --http-host localhost --http-port 27018 -u admin -p secret
442
+ axiodb role create Auditor document:view,document:query --http-host localhost --http-port 27018 -u admin -p secret
443
+ ```
444
+
445
+ **Transactions (via TCP, full lifecycle):**
446
+ ```bash
447
+ # File-based batch (auto-commit/rollback)
448
+ axiodb transaction run operations.json --db mydb --collection users
449
+ # Manual control
450
+ axiodb transaction begin --db mydb --collection users # → transactionId
451
+ axiodb transaction savepoint <txnId> sp1
452
+ axiodb transaction rollback-to <txnId> sp1
453
+ axiodb transaction release <txnId> sp1
454
+ axiodb transaction commit <txnId>
455
+ axiodb transaction rollback <txnId>
456
+ ```
457
+
458
+ Management commands use the authenticated HTTP API; they do not add management commands to the
459
+ TCP client protocol, which remains focused on database, collection, document, index, aggregation,
460
+ count, and transaction operations.
461
+
415
462
  ### Features
416
463
 
417
- - **All 23 commands:** database, collection, document CRUD, aggregation, indexing, export, import
464
+ - **TCP data operations:** database, collection, document CRUD, aggregation, indexing, counts, and transactions
465
+ - **CLI transactions and diagnostics:** run a transaction operation file, use query index hints, find documents by IDs, and check TCP health
418
466
  - **Interactive REPL:** MongoDB shell syntax (`use`, `show dbs`, `db.coll.find()`)
419
467
  - **Export & Import:** backup/restore databases via HTTP API, tab-completes file paths
420
468
  - **TLS support:** `--tls`, `--tls-cert`, `--tls-skip-verify`
@@ -645,7 +693,7 @@ volumes:
645
693
  ## 🤖 MCP Server — AI Agent Integration
646
694
 
647
695
  Spin up the same Docker container with `AXIODB_MCP=true` and let Claude (or any MCP-compatible
648
- AI agent) talk to your AxioDB instance directly — 32 tools covering databases, collections,
696
+ AI agent) talk to your AxioDB instance directly — 43 tools covering databases, collections,
649
697
  documents, aggregation, indexes, dashboard stats, and user/role management, all gated by the
650
698
  same RBAC as the web GUI. It runs in the same process as your existing container; nothing new
651
699
  to install, no second database instance.
@@ -804,17 +852,21 @@ const electronics = await products
804
852
 
805
853
  - `createDB(dbName: string): Promise<Database>`
806
854
  - `deleteDatabase(dbName: string): Promise<SuccessInterface | ErrorInterface>`
855
+ - `isDatabaseExists(dbName: string): Promise<boolean>`
856
+ - `getInstanceInfo(): Promise<SuccessInterface | undefined>`
807
857
 
808
858
  ### Database
809
859
 
810
860
  - `createCollection(name: string): Promise<Collection>`
811
861
  - `deleteCollection(name: string): Promise<SuccessInterface | ErrorInterface>`
862
+ - `isCollectionExists(name: string): Promise<boolean>`
812
863
  - `getCollectionInfo(): Promise<SuccessInterface>`
813
864
 
814
865
  ### Collection
815
866
 
816
867
  - `insert(document: object): Promise<SuccessInterface | ErrorInterface>`
817
- - `insertMany(documents: object[]): Promise<SuccessInterface | ErrorInterface>`
868
+ - `insertMany(documents: object | object[]): Promise<SuccessInterface | ErrorInterface>`
869
+ - `totalDocuments(): Promise<SuccessInterface | ErrorInterface>`
818
870
  - `query(query: object): Reader`
819
871
  - `update(query: object): Updater`
820
872
  - `delete(query: object): Deleter`
@@ -828,6 +880,8 @@ const electronics = await products
828
880
 
829
881
  `update(query)` and `delete(query)` on their own don't change anything — they return a chainable object. Call one of the methods below to actually apply the change:
830
882
 
883
+ Updates are flat shallow merges. AxioDB does not implement MongoDB update operators such as `$inc`, `$set`, or `$push`; keys beginning with `$` are stored as ordinary field names.
884
+
831
885
  - `updater.UpdateOne(data: object): Promise<SuccessInterface | ErrorInterface>` — applies `data` to the first document matching `query`
832
886
  - `updater.UpdateMany(data: object): Promise<SuccessInterface | ErrorInterface>` — applies `data` to every document matching `query`
833
887
  - `deleter.deleteOne(): Promise<SuccessInterface | ErrorInterface>` — deletes the first document matching `query`
@@ -860,7 +914,7 @@ await collection.delete({ status: 'inactive' }).deleteMany();
860
914
  ### Transaction (Session)
861
915
 
862
916
  - `startSession(options?: { timeout?: number }): Session`
863
- - `session.withTransaction(callback: Function): Promise<any>`
917
+ - `session.withTransaction(callback: (transaction: Transaction) => Promise<void>): Promise<SuccessInterface | ErrorInterface>`
864
918
  - `session.startTransaction(): Transaction`
865
919
  - `transaction.insert(document: object): Transaction`
866
920
  - `transaction.update(query: object, update: object): Transaction`
@@ -868,7 +922,30 @@ await collection.delete({ status: 'inactive' }).deleteMany();
868
922
  - `transaction.savepoint(name: string): Transaction`
869
923
  - `transaction.rollbackToSavepoint(name: string): Transaction`
870
924
  - `transaction.commit(): Promise<SuccessInterface>`
871
- - `transaction.rollback(): Promise<void>`
925
+ - `transaction.rollback(): Promise<SuccessInterface | ErrorInterface>`
926
+
927
+ ### MCP transactions (Docker image)
928
+
929
+ The Docker-only MCP server exposes authenticated, single-collection ACID transactions with
930
+ insert, update, delete, savepoint, commit, and rollback tools. Begin with
931
+ `axiodb_begin_transaction`, then pass its `transactionId` to the other transaction tools.
932
+
933
+ ### TCP Transaction Proxy
934
+
935
+ - `collection.beginTransaction(): Promise<TransactionProxy>`
936
+ - `transactionProxy.insert(data: object): Promise<unknown>`
937
+ - `transactionProxy.insertMany(documents: object[]): Promise<unknown>`
938
+ - `transactionProxy.query(query: object, options?): Promise<unknown>`
939
+ - `transactionProxy.findByIds(ids: string[]): Promise<unknown>`
940
+ - `transactionProxy.updateById(documentId: string, updateData: object): Promise<unknown>`
941
+ - `transactionProxy.updateByQuery(query: object, updateData: object, updateOne?: boolean): Promise<unknown>`
942
+ - `transactionProxy.deleteById(documentId: string): Promise<unknown>`
943
+ - `transactionProxy.deleteByQuery(query: object, deleteOne?: boolean): Promise<unknown>`
944
+ - `transactionProxy.savepoint(name: string): Promise<unknown>`
945
+ - `transactionProxy.rollbackToSavepoint(name: string): Promise<unknown>`
946
+ - `transactionProxy.releaseSavepoint(name: string): Promise<unknown>`
947
+ - `transactionProxy.commit(): Promise<unknown>`
948
+ - `transactionProxy.rollback(): Promise<unknown>`
872
949
 
873
950
  ---
874
951
 
package/cli/VERSION CHANGED
@@ -1 +1 @@
1
- 18.1.4
1
+ 20.3.2
@@ -0,0 +1,68 @@
1
+ package cmd
2
+
3
+ import (
4
+ "fmt"
5
+ "strings"
6
+
7
+ "github.com/nexoral/axiodb-cli/internal/config"
8
+ "github.com/nexoral/axiodb-cli/pkg/httpclient"
9
+ "github.com/spf13/cobra"
10
+ )
11
+
12
+ var userCmd = &cobra.Command{Use: "user", Short: "Manage HTTP API users"}
13
+ var roleCmd = &cobra.Command{Use: "role", Short: "Manage HTTP API roles"}
14
+
15
+ func httpClientFor(cmd *cobra.Command) (*config.Config, *httpclient.HTTPClient, error) {
16
+ cfg, err := config.FromFlags(cmd)
17
+ if err != nil { return nil, nil, err }
18
+ if cfg.Username == "" || cfg.Password == "" { return nil, nil, fmt.Errorf("--username and --password are required for HTTP administration") }
19
+ client := cfg.NewHTTPClient()
20
+ if err := client.Login(cfg.Username, cfg.Password); err != nil { return nil, nil, err }
21
+ return cfg, client, nil
22
+ }
23
+
24
+ var userListCmd = &cobra.Command{Use: "list", Short: "List users", RunE: func(cmd *cobra.Command, args []string) error {
25
+ cfg, client, err := httpClientFor(cmd); if err != nil { return err }; result, err := client.ListUsers(); if err != nil { return err }; return printOutput(cfg.Output, result)
26
+ }}
27
+
28
+ var userCreateCmd = &cobra.Command{Use: "create <username> <password> <role>", Short: "Create a user", Args: cobra.ExactArgs(3), RunE: func(cmd *cobra.Command, args []string) error {
29
+ cfg, client, err := httpClientFor(cmd); if err != nil { return err }; result, err := client.CreateUser(args[0], args[1], args[2]); if err != nil { return err }; return printOutput(cfg.Output, result)
30
+ }}
31
+
32
+ var userRoleCmd = &cobra.Command{Use: "set-role <username> <role>", Short: "Change a user's role", Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error {
33
+ cfg, client, err := httpClientFor(cmd); if err != nil { return err }; result, err := client.UpdateUserRole(args[0], args[1]); if err != nil { return err }; return printOutput(cfg.Output, result)
34
+ }}
35
+
36
+ var userResetCmd = &cobra.Command{Use: "reset-password <username> <password>", Short: "Reset a user's password", Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error {
37
+ cfg, client, err := httpClientFor(cmd); if err != nil { return err }; result, err := client.ResetUserPassword(args[0], args[1]); if err != nil { return err }; return printOutput(cfg.Output, result)
38
+ }}
39
+
40
+ var userDeleteCmd = &cobra.Command{Use: "delete <username>", Short: "Delete a user", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error {
41
+ cfg, client, err := httpClientFor(cmd); if err != nil { return err }; result, err := client.DeleteUser(args[0]); if err != nil { return err }; return printOutput(cfg.Output, result)
42
+ }}
43
+
44
+ var userChangePasswordCmd = &cobra.Command{Use: "change-password <currentPassword> <newPassword>", Short: "Change own password (self-service)", Long: "Change your own password. Requires HTTP API (port 27018) to be enabled on the server (GUI/HTTP). Uses PATCH /api/auth/change-password.", Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error {
45
+ cfg, client, err := httpClientFor(cmd); if err != nil { return err }; result, err := client.ChangeOwnPassword(args[0], args[1]); if err != nil { return err }; return printOutput(cfg.Output, result)
46
+ }}
47
+
48
+ var roleListCmd = &cobra.Command{Use: "list", Short: "List roles", RunE: func(cmd *cobra.Command, args []string) error {
49
+ cfg, client, err := httpClientFor(cmd); if err != nil { return err }; result, err := client.ListRoles(); if err != nil { return err }; return printOutput(cfg.Output, result)
50
+ }}
51
+
52
+ var roleCreateCmd = &cobra.Command{Use: "create <name> <permission,...>", Short: "Create a role", Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error {
53
+ cfg, client, err := httpClientFor(cmd); if err != nil { return err }; permissions := strings.Split(args[1], ","); result, err := client.CreateRole(args[0], permissions); if err != nil { return err }; return printOutput(cfg.Output, result)
54
+ }}
55
+
56
+ var roleDeleteCmd = &cobra.Command{Use: "delete <name>", Short: "Delete a role", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error {
57
+ cfg, client, err := httpClientFor(cmd); if err != nil { return err }; result, err := client.DeleteRole(args[0]); if err != nil { return err }; return printOutput(cfg.Output, result)
58
+ }}
59
+
60
+ var rolePermissionsCmd = &cobra.Command{Use: "permissions", Short: "List available permissions", RunE: func(cmd *cobra.Command, args []string) error {
61
+ cfg, client, err := httpClientFor(cmd); if err != nil { return err }; result, err := client.ListPermissions(); if err != nil { return err }; return printOutput(cfg.Output, result)
62
+ }}
63
+
64
+ func init() {
65
+ userCmd.AddCommand(userListCmd, userCreateCmd, userRoleCmd, userResetCmd, userDeleteCmd, userChangePasswordCmd)
66
+ roleCmd.AddCommand(roleListCmd, roleCreateCmd, roleDeleteCmd, rolePermissionsCmd)
67
+ rootCmd.AddCommand(userCmd, roleCmd)
68
+ }
@@ -101,11 +101,13 @@ var documentQueryCmd = &cobra.Command{
101
101
  skip, _ := cmd.Flags().GetInt("skip")
102
102
  sortStr, _ := cmd.Flags().GetString("sort")
103
103
  findOne, _ := cmd.Flags().GetBool("find-one")
104
+ hint, _ := cmd.Flags().GetString("hint")
104
105
 
105
106
  opts := commands.QueryOptions{
106
107
  Limit: limit,
107
108
  Skip: skip,
108
109
  FindOne: findOne,
110
+ Hint: hint,
109
111
  }
110
112
 
111
113
  if len(args) > 0 {
@@ -138,6 +140,35 @@ var documentQueryCmd = &cobra.Command{
138
140
  },
139
141
  }
140
142
 
143
+ var documentFindByIDsCmd = &cobra.Command{
144
+ Use: "find-by-ids <ids-json>",
145
+ Short: "Find multiple documents by ID",
146
+ Args: cobra.ExactArgs(1),
147
+ RunE: func(cmd *cobra.Command, args []string) error {
148
+ cfg, err := config.FromFlags(cmd)
149
+ if err != nil {
150
+ return err
151
+ }
152
+ if cfg.DB == "" || cfg.Collection == "" {
153
+ return fmt.Errorf("--db and --collection flags are required")
154
+ }
155
+ var ids []string
156
+ if err := json.Unmarshal([]byte(args[0]), &ids); err != nil || len(ids) == 0 {
157
+ return fmt.Errorf("ids must be a non-empty JSON array of strings")
158
+ }
159
+ client, err := cfg.ConnectAndAuth()
160
+ if err != nil {
161
+ return err
162
+ }
163
+ defer client.Disconnect()
164
+ resp, err := commands.FindDocumentsByIDs(client, cfg.DB, cfg.Collection, ids)
165
+ if err != nil {
166
+ return err
167
+ }
168
+ return printOutput(cfg.Output, resp)
169
+ },
170
+ }
171
+
141
172
  var documentGetCmd = &cobra.Command{
142
173
  Use: "get <id>",
143
174
  Short: "Get a document by ID",
@@ -358,6 +389,7 @@ func init() {
358
389
  documentQueryCmd.Flags().Int("skip", 0, "Skip results")
359
390
  documentQueryCmd.Flags().String("sort", "", "Sort JSON (e.g., '{\"name\":1}')")
360
391
  documentQueryCmd.Flags().Bool("find-one", false, "Find single document")
392
+ documentQueryCmd.Flags().String("hint", "", "Index field name to use")
361
393
 
362
394
  documentUpdateByQueryCmd.Flags().Bool("many", false, "Update multiple documents")
363
395
  documentDeleteByQueryCmd.Flags().Bool("many", false, "Delete multiple documents")
@@ -366,6 +398,7 @@ func init() {
366
398
  documentCmd.AddCommand(documentInsertManyCmd)
367
399
  documentCmd.AddCommand(documentQueryCmd)
368
400
  documentCmd.AddCommand(documentGetCmd)
401
+ documentCmd.AddCommand(documentFindByIDsCmd)
369
402
  documentCmd.AddCommand(documentUpdateCmd)
370
403
  documentCmd.AddCommand(documentUpdateByQueryCmd)
371
404
  documentCmd.AddCommand(documentDeleteCmd)
@@ -0,0 +1,19 @@
1
+ package cmd
2
+
3
+ import (
4
+ "github.com/nexoral/axiodb-cli/internal/config"
5
+ "github.com/nexoral/axiodb-cli/pkg/commands"
6
+ "github.com/spf13/cobra"
7
+ )
8
+
9
+ var healthCmd = &cobra.Command{
10
+ Use: "health", Short: "Check AxioDB service health",
11
+ RunE: func(cmd *cobra.Command, _ []string) error {
12
+ cfg, err := config.FromFlags(cmd); if err != nil { return err }
13
+ client, err := cfg.ConnectAndAuth(); if err != nil { return err }; defer client.Disconnect()
14
+ response, err := commands.Health(client); if err != nil { return err }
15
+ return printOutput(cfg.Output, response)
16
+ },
17
+ }
18
+
19
+ func init() { rootCmd.AddCommand(healthCmd) }
@@ -0,0 +1,191 @@
1
+ package cmd
2
+
3
+ import (
4
+ "encoding/json"
5
+ "fmt"
6
+ "os"
7
+
8
+ "github.com/nexoral/axiodb-cli/internal/config"
9
+ "github.com/nexoral/axiodb-cli/pkg/commands"
10
+ "github.com/spf13/cobra"
11
+ )
12
+
13
+ var transactionCmd = &cobra.Command{
14
+ Use: "transaction",
15
+ Short: "Run ACID transaction operations",
16
+ Long: "ACID transactions over TCP (port 27019). Requires TCP server enabled (AXIODB_TCP=true). Use 'transaction run' for file-based batch, or begin/commit/rollback/savepoint for manual control.",
17
+ }
18
+
19
+ var transactionRunCmd = &cobra.Command{
20
+ Use: "run <operations-json-file>",
21
+ Short: "Run a transaction from a JSON operation list",
22
+ Long: "Run a full transaction from a JSON file. Requires TCP (AXIODB_TCP=true) and --db/--collection. Auto-commits on success, auto-rollbacks on failure.",
23
+ Args: cobra.ExactArgs(1),
24
+ RunE: func(cmd *cobra.Command, args []string) error {
25
+ cfg, err := config.FromFlags(cmd)
26
+ if err != nil {
27
+ return err
28
+ }
29
+ if cfg.DB == "" || cfg.Collection == "" {
30
+ return fmt.Errorf("--db and --collection flags are required")
31
+ }
32
+ content, err := os.ReadFile(args[0])
33
+ if err != nil {
34
+ return fmt.Errorf("read transaction file: %w", err)
35
+ }
36
+ var steps []commands.TransactionStep
37
+ if err := json.Unmarshal(content, &steps); err != nil {
38
+ return fmt.Errorf("invalid transaction JSON: %w", err)
39
+ }
40
+ client, err := cfg.ConnectAndAuth()
41
+ if err != nil {
42
+ return err
43
+ }
44
+ defer client.Disconnect()
45
+ response, err := commands.RunTransaction(client, cfg.DB, cfg.Collection, steps)
46
+ if err != nil {
47
+ return err
48
+ }
49
+ return printOutput(cfg.Output, response)
50
+ },
51
+ }
52
+
53
+ var transactionBeginCmd = &cobra.Command{
54
+ Use: "begin",
55
+ Short: "Begin a transaction (returns transactionId)",
56
+ Long: "Begin a transaction on --db/--collection. Requires TCP. Returns transactionId for subsequent commit/rollback/savepoint calls.",
57
+ RunE: func(cmd *cobra.Command, args []string) error {
58
+ cfg, err := config.FromFlags(cmd)
59
+ if err != nil {
60
+ return err
61
+ }
62
+ if cfg.DB == "" || cfg.Collection == "" {
63
+ return fmt.Errorf("--db and --collection flags are required")
64
+ }
65
+ client, err := cfg.ConnectAndAuth()
66
+ if err != nil {
67
+ return err
68
+ }
69
+ defer client.Disconnect()
70
+ resp, err := commands.BeginTransaction(client, cfg.DB, cfg.Collection)
71
+ if err != nil {
72
+ return err
73
+ }
74
+ return printOutput(cfg.Output, resp)
75
+ },
76
+ }
77
+
78
+ var transactionCommitCmd = &cobra.Command{
79
+ Use: "commit <transactionId>",
80
+ Short: "Commit a transaction",
81
+ Args: cobra.ExactArgs(1),
82
+ RunE: func(cmd *cobra.Command, args []string) error {
83
+ cfg, err := config.FromFlags(cmd)
84
+ if err != nil {
85
+ return err
86
+ }
87
+ client, err := cfg.ConnectAndAuth()
88
+ if err != nil {
89
+ return err
90
+ }
91
+ defer client.Disconnect()
92
+ resp, err := commands.CommitTransaction(client, args[0])
93
+ if err != nil {
94
+ return err
95
+ }
96
+ return printOutput(cfg.Output, resp)
97
+ },
98
+ }
99
+
100
+ var transactionRollbackCmd = &cobra.Command{
101
+ Use: "rollback <transactionId>",
102
+ Short: "Rollback a transaction",
103
+ Args: cobra.ExactArgs(1),
104
+ RunE: func(cmd *cobra.Command, args []string) error {
105
+ cfg, err := config.FromFlags(cmd)
106
+ if err != nil {
107
+ return err
108
+ }
109
+ client, err := cfg.ConnectAndAuth()
110
+ if err != nil {
111
+ return err
112
+ }
113
+ defer client.Disconnect()
114
+ resp, err := commands.RollbackTransaction(client, args[0])
115
+ if err != nil {
116
+ return err
117
+ }
118
+ return printOutput(cfg.Output, resp)
119
+ },
120
+ }
121
+
122
+ var transactionSavepointCmd = &cobra.Command{
123
+ Use: "savepoint <transactionId> <name>",
124
+ Short: "Create a savepoint",
125
+ Args: cobra.ExactArgs(2),
126
+ RunE: func(cmd *cobra.Command, args []string) error {
127
+ cfg, err := config.FromFlags(cmd)
128
+ if err != nil {
129
+ return err
130
+ }
131
+ client, err := cfg.ConnectAndAuth()
132
+ if err != nil {
133
+ return err
134
+ }
135
+ defer client.Disconnect()
136
+ resp, err := commands.Savepoint(client, args[0], args[1])
137
+ if err != nil {
138
+ return err
139
+ }
140
+ return printOutput(cfg.Output, resp)
141
+ },
142
+ }
143
+
144
+ var transactionRollbackToCmd = &cobra.Command{
145
+ Use: "rollback-to <transactionId> <name>",
146
+ Short: "Rollback to a savepoint",
147
+ Args: cobra.ExactArgs(2),
148
+ RunE: func(cmd *cobra.Command, args []string) error {
149
+ cfg, err := config.FromFlags(cmd)
150
+ if err != nil {
151
+ return err
152
+ }
153
+ client, err := cfg.ConnectAndAuth()
154
+ if err != nil {
155
+ return err
156
+ }
157
+ defer client.Disconnect()
158
+ resp, err := commands.RollbackToSavepoint(client, args[0], args[1])
159
+ if err != nil {
160
+ return err
161
+ }
162
+ return printOutput(cfg.Output, resp)
163
+ },
164
+ }
165
+
166
+ var transactionReleaseCmd = &cobra.Command{
167
+ Use: "release <transactionId> <name>",
168
+ Short: "Release a savepoint",
169
+ Args: cobra.ExactArgs(2),
170
+ RunE: func(cmd *cobra.Command, args []string) error {
171
+ cfg, err := config.FromFlags(cmd)
172
+ if err != nil {
173
+ return err
174
+ }
175
+ client, err := cfg.ConnectAndAuth()
176
+ if err != nil {
177
+ return err
178
+ }
179
+ defer client.Disconnect()
180
+ resp, err := commands.ReleaseSavepoint(client, args[0], args[1])
181
+ if err != nil {
182
+ return err
183
+ }
184
+ return printOutput(cfg.Output, resp)
185
+ },
186
+ }
187
+
188
+ func init() {
189
+ transactionCmd.AddCommand(transactionRunCmd, transactionBeginCmd, transactionCommitCmd, transactionRollbackCmd, transactionSavepointCmd, transactionRollbackToCmd, transactionReleaseCmd)
190
+ rootCmd.AddCommand(transactionCmd)
191
+ }
@@ -6,7 +6,7 @@ import (
6
6
  "github.com/spf13/cobra"
7
7
  )
8
8
 
9
- var cliVersion = "18.1.4"
9
+ var cliVersion = "20.3.2"
10
10
 
11
11
  var versionCmd = &cobra.Command{
12
12
  Use: "version",
@@ -42,6 +42,7 @@ type QueryOptions struct {
42
42
  Skip int
43
43
  Sort interface{}
44
44
  FindOne bool
45
+ Hint string
45
46
  }
46
47
 
47
48
  func QueryDocuments(client *protocol.Client, dbName, collectionName string, opts QueryOptions) (*protocol.Response, error) {
@@ -64,6 +65,9 @@ func QueryDocuments(client *protocol.Client, dbName, collectionName string, opts
64
65
  if opts.FindOne {
65
66
  params["findOne"] = true
66
67
  }
68
+ if opts.Hint != "" {
69
+ params["hint"] = opts.Hint
70
+ }
67
71
 
68
72
  resp, err := client.Send("QUERY_DOCUMENTS", params)
69
73
  if err != nil {
@@ -90,6 +94,21 @@ func QueryByID(client *protocol.Client, dbName, collectionName, id string) (*pro
90
94
  return resp, nil
91
95
  }
92
96
 
97
+ func FindDocumentsByIDs(client *protocol.Client, dbName, collectionName string, ids interface{}) (*protocol.Response, error) {
98
+ resp, err := client.Send("FIND_BY_IDS", map[string]interface{}{
99
+ "dbName": dbName,
100
+ "collectionName": collectionName,
101
+ "ids": ids,
102
+ })
103
+ if err != nil {
104
+ return nil, fmt.Errorf("find documents by ids: %w", err)
105
+ }
106
+ if resp.StatusCode >= 400 {
107
+ return nil, fmt.Errorf("find documents by ids failed: %s", resp.Error)
108
+ }
109
+ return resp, nil
110
+ }
111
+
93
112
  func UpdateDocumentByID(client *protocol.Client, dbName, collectionName, id string, updateData interface{}) (*protocol.Response, error) {
94
113
  resp, err := client.Send("UPDATE_DOCUMENT_BY_ID", map[string]interface{}{
95
114
  "dbName": dbName,
@@ -0,0 +1,18 @@
1
+ package commands
2
+
3
+ import (
4
+ "fmt"
5
+
6
+ "github.com/nexoral/axiodb-cli/pkg/protocol"
7
+ )
8
+
9
+ func Health(client *protocol.Client) (*protocol.Response, error) {
10
+ resp, err := client.Send("HEALTH", nil)
11
+ if err != nil {
12
+ return nil, fmt.Errorf("get health: %w", err)
13
+ }
14
+ if resp.StatusCode >= 400 {
15
+ return nil, fmt.Errorf("get health failed: %s", resp.Error)
16
+ }
17
+ return resp, nil
18
+ }