axiodb 11.9.16 → 12.10.18
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/README.md +140 -5
- package/lib/Helper/Converter.helper.d.ts +0 -25
- package/lib/Helper/Converter.helper.js +1 -26
- package/lib/Helper/Converter.helper.js.map +1 -1
- package/lib/Helper/Crypto.helper.d.ts +1 -44
- package/lib/Helper/Crypto.helper.js +1 -40
- package/lib/Helper/Crypto.helper.js.map +1 -1
- package/lib/Helper/DocumentLoader.helper.d.ts +3 -38
- package/lib/Helper/DocumentLoader.helper.js +4 -42
- package/lib/Helper/DocumentLoader.helper.js.map +1 -1
- package/lib/Helper/PathSanitizer.helper.js +6 -12
- package/lib/Helper/PathSanitizer.helper.js.map +1 -1
- package/lib/Helper/response.helper.d.ts +1 -42
- package/lib/Helper/response.helper.js +1 -43
- package/lib/Helper/response.helper.js.map +1 -1
- package/lib/Memory/memory.operation.d.ts +13 -93
- package/lib/Memory/memory.operation.js +20 -122
- package/lib/Memory/memory.operation.js.map +1 -1
- package/lib/Services/Indexation.operation.d.ts +3 -0
- package/lib/Services/Indexation.operation.js +25 -4
- package/lib/Services/Indexation.operation.js.map +1 -1
- package/lib/client/AggregationProxy.d.ts +1 -7
- package/lib/client/AggregationProxy.js +1 -7
- package/lib/client/AggregationProxy.js.map +1 -1
- package/lib/client/AxioDBCloud.client.d.ts +19 -16
- package/lib/client/AxioDBCloud.client.js +48 -31
- package/lib/client/AxioDBCloud.client.js.map +1 -1
- package/lib/client/CollectionProxy.d.ts +1 -37
- package/lib/client/CollectionProxy.js +1 -37
- package/lib/client/CollectionProxy.js.map +1 -1
- package/lib/client/DatabaseProxy.d.ts +1 -19
- package/lib/client/DatabaseProxy.js +1 -19
- package/lib/client/DatabaseProxy.js.map +1 -1
- package/lib/client/DeleteOperationProxy.d.ts +1 -10
- package/lib/client/DeleteOperationProxy.js +1 -10
- package/lib/client/DeleteOperationProxy.js.map +1 -1
- package/lib/client/PooledConnection.d.ts +7 -1
- package/lib/client/PooledConnection.js +27 -8
- package/lib/client/PooledConnection.js.map +1 -1
- package/lib/client/ReaderProxy.d.ts +1 -19
- package/lib/client/ReaderProxy.js +1 -19
- package/lib/client/ReaderProxy.js.map +1 -1
- package/lib/client/UpdateOperationProxy.d.ts +1 -10
- package/lib/client/UpdateOperationProxy.js +1 -10
- package/lib/client/UpdateOperationProxy.js.map +1 -1
- package/lib/client/types/client.types.d.ts +18 -10
- package/lib/client/types/client.types.js +0 -6
- package/lib/client/types/client.types.js.map +1 -1
- package/lib/config/DB.js +0 -3
- package/lib/config/DB.js.map +1 -1
- package/lib/config/Interfaces/Operation/Indexation.operation.interface.d.ts +6 -0
- package/lib/config/Keys/Keys.js +0 -1
- package/lib/config/Keys/Keys.js.map +1 -1
- package/lib/engine/Filesystem/FileManager.d.ts +4 -74
- package/lib/engine/Filesystem/FileManager.js +4 -76
- package/lib/engine/Filesystem/FileManager.js.map +1 -1
- package/lib/engine/Filesystem/FolderManager.d.ts +1 -31
- package/lib/engine/Filesystem/FolderManager.js +2 -47
- package/lib/engine/Filesystem/FolderManager.js.map +1 -1
- package/lib/engine/cli/worker_process.d.ts +1 -24
- package/lib/engine/cli/worker_process.js +1 -24
- package/lib/engine/cli/worker_process.js.map +1 -1
- package/lib/engine/node/WorkerForDataLoad.engine.js +3 -17
- package/lib/engine/node/WorkerForDataLoad.engine.js.map +1 -1
- package/lib/engine/node/WorkerForSearch.engine.js +2 -4
- package/lib/engine/node/WorkerForSearch.engine.js.map +1 -1
- package/lib/server/config/PortFreeChecker.d.ts +0 -26
- package/lib/server/config/PortFreeChecker.js +3 -29
- package/lib/server/config/PortFreeChecker.js.map +1 -1
- package/lib/server/config/keys.js +0 -2
- package/lib/server/config/keys.js.map +1 -1
- package/lib/server/config/server.js +13 -15
- package/lib/server/config/server.js.map +1 -1
- package/lib/server/controller/Collections/Collection.controller.d.ts +0 -48
- package/lib/server/controller/Collections/Collection.controller.js +2 -55
- package/lib/server/controller/Collections/Collection.controller.js.map +1 -1
- package/lib/server/controller/Database/Databse.controller.d.ts +2 -65
- package/lib/server/controller/Database/Databse.controller.js +3 -80
- package/lib/server/controller/Database/Databse.controller.js.map +1 -1
- package/lib/server/controller/Index/Index.controller.d.ts +3 -25
- package/lib/server/controller/Index/Index.controller.js +3 -25
- package/lib/server/controller/Index/Index.controller.js.map +1 -1
- package/lib/server/controller/Operation/CRUD.controller.d.ts +0 -167
- package/lib/server/controller/Operation/CRUD.controller.js +0 -195
- package/lib/server/controller/Operation/CRUD.controller.js.map +1 -1
- package/lib/server/controller/Stats.controller.d.ts +1 -22
- package/lib/server/controller/Stats.controller.js +2 -29
- package/lib/server/controller/Stats.controller.js.map +1 -1
- package/lib/server/helper/filesCounterInFolder.helper.d.ts +0 -15
- package/lib/server/helper/filesCounterInFolder.helper.js +0 -15
- package/lib/server/helper/filesCounterInFolder.helper.js.map +1 -1
- package/lib/server/helper/responseBuilder.helper.d.ts +0 -16
- package/lib/server/helper/responseBuilder.helper.js +0 -16
- package/lib/server/helper/responseBuilder.helper.js.map +1 -1
- package/lib/server/router/Router.d.ts +0 -6
- package/lib/server/router/Router.js +6 -22
- package/lib/server/router/Router.js.map +1 -1
- package/lib/server/router/Routers/Collection.routes.js +0 -4
- package/lib/server/router/Routers/Collection.routes.js.map +1 -1
- package/lib/server/router/Routers/DB.routes.js +1 -7
- package/lib/server/router/Routers/DB.routes.js.map +1 -1
- package/lib/server/router/Routers/Index.routes.js +0 -4
- package/lib/server/router/Routers/Index.routes.js.map +1 -1
- package/lib/server/router/Routers/Operation.routes.js +0 -9
- package/lib/server/router/Routers/Operation.routes.js.map +1 -1
- package/lib/tcp/config/keys.d.ts +15 -0
- package/lib/tcp/config/keys.js +20 -1
- package/lib/tcp/config/keys.js.map +1 -1
- package/lib/tcp/config/server.d.ts +6 -1
- package/lib/tcp/config/server.js +46 -15
- package/lib/tcp/config/server.js.map +1 -1
- package/lib/tcp/connection/ConnectionManager.d.ts +17 -1
- package/lib/tcp/connection/ConnectionManager.js +51 -3
- package/lib/tcp/connection/ConnectionManager.js.map +1 -1
- package/lib/tcp/connection/ConnectionRateLimiter.d.ts +31 -0
- package/lib/tcp/connection/ConnectionRateLimiter.js +83 -0
- package/lib/tcp/connection/ConnectionRateLimiter.js.map +1 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
- [AxioDBCloud — Connecting Remotely](#-axiodbcloud--connecting-remotely)
|
|
30
30
|
- [Simple: connect without authentication](#simple-connect-without-authentication)
|
|
31
31
|
- [Advanced: TCP authentication](#advanced-tcp-authentication)
|
|
32
|
+
- [Advanced: TLS encryption](#advanced-tls-encryption)
|
|
32
33
|
- [Troubleshooting](#-troubleshooting)
|
|
33
34
|
- [Docker Deployment](#-docker-deployment)
|
|
34
35
|
- [Simple: run the container](#simple-run-the-container)
|
|
@@ -212,7 +213,9 @@ await session.withTransaction(async (tx) => {
|
|
|
212
213
|
- **🔁 Auto-Reconnect:** exponential backoff, up to 10 retry attempts
|
|
213
214
|
- **💓 Heartbeat Monitoring:** `PING`/`PONG` every 30 seconds
|
|
214
215
|
- **🆔 Request Correlation:** UUID-based request/response matching
|
|
215
|
-
- **🧵 Connection Pooling:** client keeps a pool of `maxPoolSize` concurrent connections (default: 10, mirrors MongoDB's driver option) and
|
|
216
|
+
- **🧵 Connection Pooling:** client keeps a pool of `maxPoolSize` concurrent connections (default: 10, mirrors MongoDB's driver option) and routes each command to the least-busy connected member (fewest in-flight requests); server accepts 1,000+ concurrent connections total, capped at 100 per remote IP (see the [file descriptor limit note](#connection-refused--too-many-open-files-errors-at-high-concurrency) below if you're running near that scale)
|
|
217
|
+
- **🛡️ Connection-Level DoS Protection:** per-IP concurrent connection cap (100) plus a separate per-IP connection-*attempt* rate limiter (300 attempts / 10s → 30s cooldown), so one client can't starve the server either by holding too many sockets open or by rapidly opening and dropping them
|
|
218
|
+
- **🔒 Optional TLS Encryption:** encrypt the wire protocol with your own cert (see [Advanced: TLS](#advanced-tls-encryption) below) — off by default, so existing plaintext deployments are unaffected unless you turn it on
|
|
216
219
|
- **📐 TypeScript Support:** full type definitions included
|
|
217
220
|
|
|
218
221
|
**Use cases:** microservices sharing one AxioDB instance, Electron apps connecting to a local or remote database, teams sharing a development database, container/cloud deployments (AWS, Azure, GCP, DigitalOcean).
|
|
@@ -280,7 +283,56 @@ await client.login('admin', 'admin');
|
|
|
280
283
|
- **Accounts that still need their forced password change are rejected outright (`403`)**, not allowed through with a warning — there's no TCP command to change a password today, so log into the GUI (`http://localhost:27018`) to complete it first, or authenticate with an account that already has.
|
|
281
284
|
- If a Super Admin resets a user's password, changes their role, or deletes them via the GUI while that user has an open TCP connection, the TCP connection is immediately forced to re-authenticate on its next command.
|
|
282
285
|
|
|
283
|
-
**Known limitations:**
|
|
286
|
+
**Known limitations:** there's currently no TCP command to change a password; that must go through the GUI.
|
|
287
|
+
|
|
288
|
+
### Advanced: TLS encryption
|
|
289
|
+
|
|
290
|
+
By default, the TCP protocol is **plaintext** — anyone who can capture the network traffic between client and server (e.g. Wireshark on a shared network) can read your data and, if `TCPAuth` is on, your password. TLS fixes this. It's **off by default** — nothing below is required, and existing plaintext deployments keep working exactly as before unless you turn it on.
|
|
291
|
+
|
|
292
|
+
**You must provide your own certificate + key.** AxioDB never generates one for you — that's a security decision only you can make (a real cert from a CA, or a self-signed one for local/private use).
|
|
293
|
+
|
|
294
|
+
**Step 1 — get a cert + key.** For local/dev/private use, generate a self-signed one (one-time, takes a second):
|
|
295
|
+
```bash
|
|
296
|
+
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes -subj "/CN=localhost"
|
|
297
|
+
```
|
|
298
|
+
This creates two files, `cert.pem` and `key.pem`, in your current folder. For a real production deployment reachable from the internet, use a cert from a real CA (Let's Encrypt, your org's CA, your cloud provider's managed cert) instead — the rest of the setup below is identical either way.
|
|
299
|
+
|
|
300
|
+
**Step 2 — point the server at them:**
|
|
301
|
+
```javascript
|
|
302
|
+
const { AxioDB } = require('axiodb');
|
|
303
|
+
const db = new AxioDB({
|
|
304
|
+
TCP: true,
|
|
305
|
+
TLS: true,
|
|
306
|
+
TLSCertPath: './cert.pem', // path to the file from step 1
|
|
307
|
+
TLSKeyPath: './key.pem',
|
|
308
|
+
});
|
|
309
|
+
```
|
|
310
|
+
If `TLS: true` but either path is missing or unreadable, AxioDB throws immediately at startup — it never silently falls back to plaintext.
|
|
311
|
+
|
|
312
|
+
**Step 3 — point the client at the same cert** (only needed because it's self-signed; a real CA-issued cert wouldn't need this step, the same way your browser trusts `https://` sites without extra setup):
|
|
313
|
+
```javascript
|
|
314
|
+
const { AxioDBCloud } = require('axiodb');
|
|
315
|
+
const client = new AxioDBCloud("axiodb://localhost:27019", {
|
|
316
|
+
tls: true,
|
|
317
|
+
tlsCAPath: './cert.pem', // same cert.pem from step 1 - proves this server is the real one
|
|
318
|
+
});
|
|
319
|
+
await client.connect();
|
|
320
|
+
```
|
|
321
|
+
Without `tlsCAPath`, the client refuses to connect to a self-signed server by default (`tlsRejectUnauthorized` defaults to `true`) — this is intentional, it's the same protection that stops your browser from silently trusting a fake `https://` site. Only set `tlsRejectUnauthorized: false` for local/dev testing, never in production, since it turns that protection off entirely.
|
|
322
|
+
|
|
323
|
+
**Running this in Docker?** The cert/key files need to get *into* the container. The simplest way to think about it: your cert files live on your real machine; a Docker **bind mount** (`-v`) makes a folder from your machine visible inside the container at whatever path you choose, and you point `AXIODB_TLS_CERT_PATH`/`AXIODB_TLS_KEY_PATH` at *that in-container path*, not your real machine's path:
|
|
324
|
+
```bash
|
|
325
|
+
# cert.pem and key.pem are really at /home/you/mycerts/ on your machine.
|
|
326
|
+
# "/certs" below is just a name we're choosing for where they'll appear inside the container.
|
|
327
|
+
docker run -d --name axiodb-server \
|
|
328
|
+
-p 27018:27018 -p 27019:27019 \
|
|
329
|
+
-v /home/you/mycerts:/certs:ro \
|
|
330
|
+
-e AXIODB_TLS=true \
|
|
331
|
+
-e AXIODB_TLS_CERT_PATH=/certs/cert.pem \
|
|
332
|
+
-e AXIODB_TLS_KEY_PATH=/certs/key.pem \
|
|
333
|
+
theankansaha/axiodb
|
|
334
|
+
```
|
|
335
|
+
The rule: the `-e AXIODB_TLS_CERT_PATH=...` value must always match the *right-hand side* of the `-v` mount (`/certs/...`), never the real path on your machine (`/home/you/mycerts/...`) — the container can't see your machine's filesystem directly, only whatever you've explicitly mounted into it.
|
|
284
336
|
|
|
285
337
|
👉 **[Full AxioDBCloud Documentation](https://axiodb.in/cloud)** — setup guides, API reference, Docker examples
|
|
286
338
|
|
|
@@ -316,6 +368,27 @@ Your credentials are correct, but that account is still flagged for a forced pas
|
|
|
316
368
|
|
|
317
369
|
Five failed logins from your IP within 15 minutes trigger a 15-minute lockout, shared between TCP and the GUI. Double check the credentials you're sending, wait out the cooldown, or fix the underlying typo/config issue causing repeated failures — there's no way to clear the lockout early.
|
|
318
370
|
|
|
371
|
+
### `429` — "Too many concurrent connections from this IP address"
|
|
372
|
+
|
|
373
|
+
Unrelated to the login lockout above — this fires at connection time, before any `AUTHENTICATE`, once a single remote IP has 100 concurrent open TCP sockets to the server (`MAX_CONNECTIONS_PER_IP`), regardless of whether any of those connections are authenticated. This caps how much of the server's total 1,000-connection budget one IP can claim, so one client can't starve every other client. It's per-*connection*, not per-*request* — a single `AxioDBCloud` client at the default `maxPoolSize: 10` is nowhere near this limit; you'd only hit it by running many separate client processes behind the same IP/NAT gateway, or a runaway reconnect loop leaking sockets. If you legitimately need more than 100 concurrent connections from one IP, that's a server-side constant (`MAX_CONNECTIONS_PER_IP` in `source/tcp/config/keys.ts`) — there's no runtime option to raise it yet.
|
|
374
|
+
|
|
375
|
+
If you do set a `maxPoolSize` that pushes past this cap (or any other subset of the pool fails for another reason, e.g. a network blip), `connect()` doesn't throw as long as at least one pool member connected — it resolves with a smaller-than-requested pool and emits a `poolDegraded` event so you know about it instead of silently running under capacity:
|
|
376
|
+
|
|
377
|
+
```javascript
|
|
378
|
+
client.on('poolDegraded', ({ requested, connected, failed, errors }) => {
|
|
379
|
+
console.warn(`Pool came up smaller than requested: ${connected}/${requested} connected, ${failed} failed`);
|
|
380
|
+
console.warn(errors[0].message); // e.g. "Too many concurrent connections from this IP address"
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
await client.connect(); // resolves even if some pool members were rejected
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
(The very first connection in the pool is the exception — if *that* one fails, `connect()` rejects entirely, since it's the signal that the server is reachable and credentials are valid at all.)
|
|
387
|
+
|
|
388
|
+
### `429` — "Too many connection attempts from this IP address. Try again later."
|
|
389
|
+
|
|
390
|
+
Different from both `429`s above, and checked first: this guards against rapid connect-then-drop *churn*, which the concurrent-connection cap (`MAX_CONNECTIONS_PER_IP`) doesn't catch on its own — an attacker who never holds more than a few sockets open at once could still hammer the server with a high rate of connection attempts, each costing a TCP handshake and an accept/reject cycle, and stay under that cap the whole time. This is tracked separately, per IP, as a sliding window: once an IP crosses 300 connection attempts (successful or rejected, it doesn't matter which) within a trailing 10-second window, every new connection from that IP is rejected outright for the next 30 seconds. A normal `AxioDBCloud` client, even reconnecting a full `maxPoolSize: 10` pool repeatedly, is nowhere near this threshold — you'd only hit it via a genuine connection flood or a reconnect loop gone very wrong (e.g. retrying without backoff). There's no runtime option to raise these thresholds yet; they're constants in `source/tcp/config/keys.ts` (`CONNECTION_RATE_LIMIT_*`).
|
|
391
|
+
|
|
319
392
|
### `403` — "This is a reserved system database"
|
|
320
393
|
|
|
321
394
|
You (or a client) tried to read/write a database literally named `config` — that name is reserved for AxioDB's own RBAC storage (`users`/`roles`/`permissions`) and is blocked on both the GUI and TCP, authenticated or not. Use a different database name.
|
|
@@ -330,6 +403,37 @@ You (or a client) tried to read/write a database literally named `config` — th
|
|
|
330
403
|
|
|
331
404
|
See the [Docker Deployment](#-docker-deployment) section below, and `Docker/README.md` in the repository for a fuller Docker-specific troubleshooting guide (`docker logs`, port-conflict remapping, volume-mounting checklist).
|
|
332
405
|
|
|
406
|
+
### Connection refused / "Too many open files" errors at high concurrency
|
|
407
|
+
|
|
408
|
+
Each `AxioDBCloud` client opens `maxPoolSize` TCP sockets (default: 10), and the server holds one socket per connected client — both count against the OS's open-file-descriptor limit. Most Linux distros default `ulimit -n` to 1024 per process, which is enough for only ~100 clients at the default pool size before the server starts refusing new connections with `EMFILE`/`ENFILE`.
|
|
409
|
+
|
|
410
|
+
If you're deploying towards the 1,000+ concurrent connections the server supports, raise the limit before starting the process:
|
|
411
|
+
|
|
412
|
+
```bash
|
|
413
|
+
ulimit -n 65536 # current shell / process
|
|
414
|
+
node lib/config/DB.js
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
In Docker, set it on the container instead of the host shell:
|
|
418
|
+
|
|
419
|
+
```bash
|
|
420
|
+
docker run --ulimit nofile=65536:65536 -p 27018:27018 -p 27019:27019 theankansaha/axiodb
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
or, in Compose:
|
|
424
|
+
|
|
425
|
+
```yaml
|
|
426
|
+
services:
|
|
427
|
+
axiodb:
|
|
428
|
+
image: theankansaha/axiodb
|
|
429
|
+
ulimits:
|
|
430
|
+
nofile:
|
|
431
|
+
soft: 65536
|
|
432
|
+
hard: 65536
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
On the client side, prefer a smaller `maxPoolSize` per instance rather than raising it — the least-busy routing (see [Connection Pooling](#-axiodbcloud--connecting-remotely) above) already avoids the head-of-line blocking a bigger pool would otherwise compensate for.
|
|
436
|
+
|
|
333
437
|
---
|
|
334
438
|
|
|
335
439
|
## 🐳 Docker Deployment
|
|
@@ -362,12 +466,15 @@ Every option below has a default matching the image's previous fixed behavior
|
|
|
362
466
|
| `AXIODB_GUI` | `true` | Enable the HTTP Control Server / web GUI on port 27018 |
|
|
363
467
|
| `AXIODB_TCP` | `true` | Enable the AxioDBCloud TCP server on port 27019 |
|
|
364
468
|
| `AXIODB_TCP_AUTH` | `true` | Require username/password authentication on TCP connections (same RBAC accounts as the GUI) |
|
|
469
|
+
| `AXIODB_TLS` | `false` | Encrypt TCP connections with TLS instead of plaintext (see [Advanced: TLS encryption](#advanced-tls-encryption)) |
|
|
470
|
+
| `AXIODB_TLS_CERT_PATH` | *(none)* | Path **inside the container** to a PEM cert file - required when `AXIODB_TLS=true`. Mount the real file in with `-v` first (see the TLS section above) |
|
|
471
|
+
| `AXIODB_TLS_KEY_PATH` | *(none)* | Path **inside the container** to the matching PEM private key - required when `AXIODB_TLS=true` |
|
|
365
472
|
| `AXIODB_ROOT_NAME` | `AxioDB` | Name of the root database folder created under the data volume |
|
|
366
473
|
| `AXIODB_CUSTOM_PATH` | *(container's working directory)* | Custom path for database storage inside the container |
|
|
367
474
|
|
|
368
475
|
> Ports themselves (27018/27019) aren't configurable via environment variable — remap them at the Docker layer with `-p <host-port>:27018` / `-p <host-port>:27019`.
|
|
369
476
|
|
|
370
|
-
**Disabling TCP authentication** (only on a trusted private network — the wire is
|
|
477
|
+
**Disabling TCP authentication** (only on a trusted private network — the wire is plaintext unless you also enable `AXIODB_TLS`; see [Advanced: TLS encryption](#advanced-tls-encryption)):
|
|
371
478
|
```bash
|
|
372
479
|
docker run -d \
|
|
373
480
|
--name axiodb-server \
|
|
@@ -402,6 +509,34 @@ volumes:
|
|
|
402
509
|
axiodb-data:
|
|
403
510
|
```
|
|
404
511
|
|
|
512
|
+
**The same, with TLS enabled** — note the two different kinds of entry under `volumes:`: `./mycerts:/certs:ro` is *your real folder* on the machine running Compose (because it contains a `/`), mounted read-only at `/certs` inside the container; `axiodb-data:/app` is a Docker-managed named volume (no `/`, just a label) for the actual database files:
|
|
513
|
+
```yaml
|
|
514
|
+
version: "3.8"
|
|
515
|
+
|
|
516
|
+
services:
|
|
517
|
+
axiodb:
|
|
518
|
+
image: theankansaha/axiodb
|
|
519
|
+
container_name: axiodb-server
|
|
520
|
+
ports:
|
|
521
|
+
- "27018:27018"
|
|
522
|
+
- "27019:27019"
|
|
523
|
+
environment:
|
|
524
|
+
- AXIODB_GUI=true
|
|
525
|
+
- AXIODB_TCP=true
|
|
526
|
+
- AXIODB_TCP_AUTH=true
|
|
527
|
+
- AXIODB_TLS=true
|
|
528
|
+
- AXIODB_TLS_CERT_PATH=/certs/cert.pem
|
|
529
|
+
- AXIODB_TLS_KEY_PATH=/certs/key.pem
|
|
530
|
+
- AXIODB_ROOT_NAME=AxioDB
|
|
531
|
+
volumes:
|
|
532
|
+
- ./mycerts:/certs:ro # your real cert.pem/key.pem folder -> /certs in the container
|
|
533
|
+
- axiodb-data:/app # Docker-managed volume for database files
|
|
534
|
+
restart: unless-stopped
|
|
535
|
+
|
|
536
|
+
volumes:
|
|
537
|
+
axiodb-data:
|
|
538
|
+
```
|
|
539
|
+
|
|
405
540
|
**Building the image from source, and a fuller Docker troubleshooting guide** (container won't start, port-in-use, data-persistence checks) live in [`Docker/README.md`](Docker/README.md) — the canonical Docker doc, not duplicated here in full.
|
|
406
541
|
|
|
407
542
|
---
|
|
@@ -445,7 +580,7 @@ A Super Admin can create additional roles from the predefined permission catalog
|
|
|
445
580
|
|
|
446
581
|
**Index management:** the Control Server also exposes `GET /api/index/list`, `POST /api/index/create`, and `DELETE /api/index/delete`, gated by the same `index:view` / `index:create` / `index:delete` permissions (View role gets view-only, Admin and Super Admin get all three).
|
|
447
582
|
|
|
448
|
-
> **Security note:** RBAC protects the Control Server's HTTP API and TCP server
|
|
583
|
+
> **Security note:** RBAC protects the Control Server's HTTP API and TCP server, but the HTTP GUI itself has no TLS support - keep it on a trusted local/private network, not public internet exposure. The TCP server *can* be encrypted (see [Advanced: TLS encryption](#advanced-tls-encryption)), which is recommended if it's reachable over any untrusted network.
|
|
449
584
|
|
|
450
585
|
---
|
|
451
586
|
|
|
@@ -764,7 +899,7 @@ Yes. Full type definitions are included — no separate `@types` package needed.
|
|
|
764
899
|
No. AxioDB requires Node.js (v20+) and the filesystem — server-side and desktop only.
|
|
765
900
|
|
|
766
901
|
**Q: What is AxioDBCloud?**
|
|
767
|
-
TCP-based remote access for AxioDB. Deploy AxioDB in Docker, connect from multiple clients with the exact same API. Supports 1,000+ concurrent connections with auto-reconnect. Optional username/password authentication (`TCPAuth: true`) reuses the same RBAC accounts as the GUI — see [AxioDBCloud](#-axiodbcloud--connecting-remotely) above.
|
|
902
|
+
TCP-based remote access for AxioDB. Deploy AxioDB in Docker, connect from multiple clients with the exact same API. Supports 1,000+ concurrent connections with auto-reconnect. Optional username/password authentication (`TCPAuth: true`) reuses the same RBAC accounts as the GUI, and optional TLS encryption (`TLS: true`) protects the wire protocol on untrusted networks — see [AxioDBCloud](#-axiodbcloud--connecting-remotely) above.
|
|
768
903
|
|
|
769
904
|
---
|
|
770
905
|
|
|
@@ -1,34 +1,9 @@
|
|
|
1
1
|
export default class Converter {
|
|
2
2
|
static ToObject(): string;
|
|
3
3
|
constructor();
|
|
4
|
-
/**
|
|
5
|
-
* Converts a string to a boolean.
|
|
6
|
-
* @param value The string to convert.
|
|
7
|
-
* @returns The boolean value.
|
|
8
|
-
*/
|
|
9
4
|
ToBoolean(value: string): boolean;
|
|
10
|
-
/**
|
|
11
|
-
* Converts a string to a number.
|
|
12
|
-
* @param value The string to convert.
|
|
13
|
-
* @returns The number value.
|
|
14
|
-
*/
|
|
15
5
|
ToNumber(value: string): number;
|
|
16
|
-
/**
|
|
17
|
-
* Converts a string to a JSON object.
|
|
18
|
-
* @param value The string to convert.
|
|
19
|
-
* @returns The JSON object.
|
|
20
|
-
*/
|
|
21
6
|
ToObject(value: string): any;
|
|
22
|
-
/**
|
|
23
|
-
* Converts a JSON object to a string.
|
|
24
|
-
* @param value The JSON object to convert.
|
|
25
|
-
* @returns The string.
|
|
26
|
-
*/
|
|
27
7
|
ToString(value: object): string;
|
|
28
|
-
/**
|
|
29
|
-
* Converts a string to a string array.
|
|
30
|
-
* @param value The string to convert.
|
|
31
|
-
* @returns The string array.
|
|
32
|
-
*/
|
|
33
8
|
ToStringArray(value: string): string[];
|
|
34
9
|
}
|
|
@@ -5,44 +5,19 @@ class Converter {
|
|
|
5
5
|
static ToObject() {
|
|
6
6
|
throw new Error("Method not implemented.");
|
|
7
7
|
}
|
|
8
|
-
constructor() { }
|
|
9
|
-
/**
|
|
10
|
-
* Converts a string to a boolean.
|
|
11
|
-
* @param value The string to convert.
|
|
12
|
-
* @returns The boolean value.
|
|
13
|
-
*/
|
|
8
|
+
constructor() { }
|
|
14
9
|
ToBoolean(value) {
|
|
15
10
|
return value === "true";
|
|
16
11
|
}
|
|
17
|
-
/**
|
|
18
|
-
* Converts a string to a number.
|
|
19
|
-
* @param value The string to convert.
|
|
20
|
-
* @returns The number value.
|
|
21
|
-
*/
|
|
22
12
|
ToNumber(value) {
|
|
23
13
|
return parseInt(value);
|
|
24
14
|
}
|
|
25
|
-
/**
|
|
26
|
-
* Converts a string to a JSON object.
|
|
27
|
-
* @param value The string to convert.
|
|
28
|
-
* @returns The JSON object.
|
|
29
|
-
*/
|
|
30
15
|
ToObject(value) {
|
|
31
16
|
return JSON.parse(value);
|
|
32
17
|
}
|
|
33
|
-
/**
|
|
34
|
-
* Converts a JSON object to a string.
|
|
35
|
-
* @param value The JSON object to convert.
|
|
36
|
-
* @returns The string.
|
|
37
|
-
*/
|
|
38
18
|
ToString(value) {
|
|
39
19
|
return JSON.stringify(value);
|
|
40
20
|
}
|
|
41
|
-
/**
|
|
42
|
-
* Converts a string to a string array.
|
|
43
|
-
* @param value The string to convert.
|
|
44
|
-
* @returns The string array.
|
|
45
|
-
*/
|
|
46
21
|
ToStringArray(value) {
|
|
47
22
|
return value.split(",");
|
|
48
23
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Converter.helper.js","sourceRoot":"","sources":["../../source/Helper/Converter.helper.ts"],"names":[],"mappings":";;AAAA,uDAAuD;AACvD;IACE,MAAM,CAAC,QAAQ;QACb,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IACD,gBAAe,CAAC
|
|
1
|
+
{"version":3,"file":"Converter.helper.js","sourceRoot":"","sources":["../../source/Helper/Converter.helper.ts"],"names":[],"mappings":";;AAAA,uDAAuD;AACvD;IACE,MAAM,CAAC,QAAQ;QACb,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IACD,gBAAe,CAAC;IAET,SAAS,CAAC,KAAa;QAC5B,OAAO,KAAK,KAAK,MAAM,CAAC;IAC1B,CAAC;IAEM,QAAQ,CAAC,KAAa;QAC3B,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC;IAEM,QAAQ,CAAC,KAAa;QAC3B,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IAEM,QAAQ,CAAC,KAAa;QAC3B,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IAEM,aAAa,CAAC,KAAa;QAChC,OAAO,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;CACF"}
|
|
@@ -1,57 +1,14 @@
|
|
|
1
1
|
import { SuccessInterface } from "../config/Interfaces/Helper/response.helper.interface";
|
|
2
|
-
/**
|
|
3
|
-
* Helper class for cryptographic operations such as encryption and decryption.
|
|
4
|
-
*/
|
|
5
2
|
export declare class CryptoHelper {
|
|
6
|
-
/**
|
|
7
|
-
* The encryption key used for cryptographic operations.
|
|
8
|
-
*/
|
|
9
3
|
private encryptionKey;
|
|
10
|
-
/**
|
|
11
|
-
* Instance of ResponseHelper to handle responses.
|
|
12
|
-
*/
|
|
13
4
|
private readonly responseHelper;
|
|
14
|
-
/**
|
|
15
|
-
* Instance of Cryptography class for performing cryptographic operations.
|
|
16
|
-
*/
|
|
17
5
|
private readonly Cryptography;
|
|
18
|
-
/**
|
|
19
|
-
* Instance of Converter class for converting data formats.
|
|
20
|
-
*/
|
|
21
6
|
private readonly Converter;
|
|
22
|
-
/**
|
|
23
|
-
* Constructor to initialize the CryptoHelper class.
|
|
24
|
-
* @param encryptionKey - Optional encryption key. If not provided, a default key based on hostname and platform will be used.
|
|
25
|
-
*/
|
|
7
|
+
/** If no encryptionKey is given, falls back to a default key derived from hostname + platform. */
|
|
26
8
|
constructor(encryptionKey?: string);
|
|
27
|
-
/**
|
|
28
|
-
* Sets a new encryption key.
|
|
29
|
-
* @param encryptionKey - The new encryption key to be set.
|
|
30
|
-
* @returns A promise that resolves to a success response.
|
|
31
|
-
*/
|
|
32
9
|
setEncryptionKey(encryptionKey: string): Promise<SuccessInterface>;
|
|
33
|
-
/**
|
|
34
|
-
* Encrypts data asynchronously.
|
|
35
|
-
* @param data - The data to be encrypted.
|
|
36
|
-
* @returns A promise that resolves to the encrypted data as a string.
|
|
37
|
-
*/
|
|
38
10
|
encrypt(data: string): Promise<string>;
|
|
39
|
-
/**
|
|
40
|
-
* Decrypts data asynchronously.
|
|
41
|
-
* @param data - The data to be decrypted.
|
|
42
|
-
* @returns A promise that resolves to the decrypted data as an object.
|
|
43
|
-
*/
|
|
44
11
|
decrypt(data: string): Promise<any>;
|
|
45
|
-
/**
|
|
46
|
-
* Encrypts data synchronously.
|
|
47
|
-
* @param data - The data to be encrypted.
|
|
48
|
-
* @returns The encrypted data as a string.
|
|
49
|
-
*/
|
|
50
12
|
encryptSync(data: string): string;
|
|
51
|
-
/**
|
|
52
|
-
* Decrypts data synchronously.
|
|
53
|
-
* @param data - The data to be decrypted.
|
|
54
|
-
* @returns The decrypted data as an object.
|
|
55
|
-
*/
|
|
56
13
|
decryptSync(data: string): object;
|
|
57
14
|
}
|
|
@@ -14,78 +14,39 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.CryptoHelper = void 0;
|
|
16
16
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
17
|
-
// All Imports
|
|
18
17
|
const node_os_1 = require("node:os");
|
|
19
18
|
const response_helper_1 = __importDefault(require("./response.helper"));
|
|
20
19
|
const CryptoGraphy_helper_1 = __importDefault(require("./CryptoGraphy.helper"));
|
|
21
20
|
const Converter_helper_1 = __importDefault(require("./Converter.helper"));
|
|
22
|
-
/**
|
|
23
|
-
* Helper class for cryptographic operations such as encryption and decryption.
|
|
24
|
-
*/
|
|
25
21
|
class CryptoHelper {
|
|
26
|
-
/**
|
|
27
|
-
* Constructor to initialize the CryptoHelper class.
|
|
28
|
-
* @param encryptionKey - Optional encryption key. If not provided, a default key based on hostname and platform will be used.
|
|
29
|
-
*/
|
|
22
|
+
/** If no encryptionKey is given, falls back to a default key derived from hostname + platform. */
|
|
30
23
|
constructor(encryptionKey) {
|
|
31
|
-
/**
|
|
32
|
-
* Instance of ResponseHelper to handle responses.
|
|
33
|
-
*/
|
|
34
24
|
this.responseHelper = new response_helper_1.default();
|
|
35
|
-
/**
|
|
36
|
-
* Instance of Converter class for converting data formats.
|
|
37
|
-
*/
|
|
38
25
|
this.Converter = new Converter_helper_1.default();
|
|
39
26
|
this.encryptionKey = encryptionKey || `${(0, node_os_1.hostname)()}-${(0, node_os_1.platform)()}`;
|
|
40
27
|
this.responseHelper = new response_helper_1.default();
|
|
41
28
|
this.Cryptography = new CryptoGraphy_helper_1.default(this.encryptionKey);
|
|
42
29
|
this.Converter = new Converter_helper_1.default();
|
|
43
30
|
}
|
|
44
|
-
// methods
|
|
45
|
-
/**
|
|
46
|
-
* Sets a new encryption key.
|
|
47
|
-
* @param encryptionKey - The new encryption key to be set.
|
|
48
|
-
* @returns A promise that resolves to a success response.
|
|
49
|
-
*/
|
|
50
31
|
setEncryptionKey(encryptionKey) {
|
|
51
32
|
return __awaiter(this, void 0, void 0, function* () {
|
|
52
33
|
this.encryptionKey = encryptionKey;
|
|
53
34
|
return this.responseHelper.Success("Encryption key has been set successfully");
|
|
54
35
|
});
|
|
55
36
|
}
|
|
56
|
-
/**
|
|
57
|
-
* Encrypts data asynchronously.
|
|
58
|
-
* @param data - The data to be encrypted.
|
|
59
|
-
* @returns A promise that resolves to the encrypted data as a string.
|
|
60
|
-
*/
|
|
61
37
|
encrypt(data) {
|
|
62
38
|
return __awaiter(this, void 0, void 0, function* () {
|
|
63
39
|
return yield this.Cryptography.Encrypt(data);
|
|
64
40
|
});
|
|
65
41
|
}
|
|
66
|
-
/**
|
|
67
|
-
* Decrypts data asynchronously.
|
|
68
|
-
* @param data - The data to be decrypted.
|
|
69
|
-
* @returns A promise that resolves to the decrypted data as an object.
|
|
70
|
-
*/
|
|
71
42
|
decrypt(data) {
|
|
72
43
|
return __awaiter(this, void 0, void 0, function* () {
|
|
73
44
|
return this.Converter.ToObject(yield this.Cryptography.Decrypt(data));
|
|
74
45
|
});
|
|
75
46
|
}
|
|
76
|
-
/**
|
|
77
|
-
* Encrypts data synchronously.
|
|
78
|
-
* @param data - The data to be encrypted.
|
|
79
|
-
* @returns The encrypted data as a string.
|
|
80
|
-
*/
|
|
81
47
|
encryptSync(data) {
|
|
82
48
|
return this.Cryptography.EncryptSync(data);
|
|
83
49
|
}
|
|
84
|
-
/**
|
|
85
|
-
* Decrypts data synchronously.
|
|
86
|
-
* @param data - The data to be decrypted.
|
|
87
|
-
* @returns The decrypted data as an object.
|
|
88
|
-
*/
|
|
89
50
|
decryptSync(data) {
|
|
90
51
|
return this.Converter.ToObject(this.Cryptography.DecryptSync(data));
|
|
91
52
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Crypto.helper.js","sourceRoot":"","sources":["../../source/Helper/Crypto.helper.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,uDAAuD;AACvD,
|
|
1
|
+
{"version":3,"file":"Crypto.helper.js","sourceRoot":"","sources":["../../source/Helper/Crypto.helper.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,uDAAuD;AACvD,qCAA6C;AAC7C,wEAA+C;AAE/C,gFAAiD;AACjD,0EAA2C;AAE3C;IAME,kGAAkG;IAClG,YAAY,aAAsB;QALjB,mBAAc,GAAmB,IAAI,yBAAc,EAAE,CAAC;QAEtD,cAAS,GAAG,IAAI,0BAAS,EAAE,CAAC;QAI3C,IAAI,CAAC,aAAa,GAAG,aAAa,IAAI,GAAG,IAAA,kBAAQ,GAAE,IAAI,IAAA,kBAAQ,GAAE,EAAE,CAAC;QACpE,IAAI,CAAC,cAAc,GAAG,IAAI,yBAAc,EAAE,CAAC;QAC3C,IAAI,CAAC,YAAY,GAAG,IAAI,6BAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACzD,IAAI,CAAC,SAAS,GAAG,IAAI,0BAAS,EAAE,CAAC;IACnC,CAAC;IAEY,gBAAgB,CAC3B,aAAqB;;YAErB,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;YACnC,OAAO,IAAI,CAAC,cAAc,CAAC,OAAO,CAChC,0CAA0C,CAC3C,CAAC;QACJ,CAAC;KAAA;IAEY,OAAO,CAAC,IAAY;;YAC/B,OAAO,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/C,CAAC;KAAA;IAEY,OAAO,CAAC,IAAY;;YAC/B,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACxE,CAAC;KAAA;IAEM,WAAW,CAAC,IAAY;QAC7B,OAAO,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAC7C,CAAC;IAEM,WAAW,CAAC,IAAY;QAC7B,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;IACtE,CAAC;CACF"}
|
|
@@ -1,45 +1,10 @@
|
|
|
1
1
|
import { SuccessInterface, ErrorInterface } from '../config/Interfaces/Helper/response.helper.interface';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* replacing duplicated code in Reader, Update, Delete, and Aggregation operations.
|
|
7
|
-
*
|
|
8
|
-
* @class DocumentLoader
|
|
3
|
+
* Centralizes document-loading logic that used to be duplicated across the Reader,
|
|
4
|
+
* Update, Delete, and Aggregation operations - handles both a direct file list and
|
|
5
|
+
* full directory scanning (filtered to `.axiodb` files), loaded via worker threads.
|
|
9
6
|
*/
|
|
10
7
|
export default class DocumentLoader {
|
|
11
8
|
private static readonly ResponseHelper;
|
|
12
|
-
/**
|
|
13
|
-
* Loads all documents from a collection directory using worker threads
|
|
14
|
-
*
|
|
15
|
-
* This method consolidates the LoadAllBufferRawData logic that was previously
|
|
16
|
-
* duplicated across multiple CRUD operations. It handles both direct file
|
|
17
|
-
* specification and directory scanning with .axiodb file filtering.
|
|
18
|
-
*
|
|
19
|
-
* @param collectionPath - Full path to collection directory
|
|
20
|
-
* @param encryptionKey - Optional encryption key for encrypted documents
|
|
21
|
-
* @param isEncrypted - Whether documents are encrypted (default: false)
|
|
22
|
-
* @param documentFiles - Optional specific file names to load
|
|
23
|
-
* @param includeFileName - Whether to include fileName in result (default: false)
|
|
24
|
-
* @returns Success with document array or Error
|
|
25
|
-
*
|
|
26
|
-
* @example
|
|
27
|
-
* // Load all documents from a collection
|
|
28
|
-
* const result = await DocumentLoader.loadDocuments(
|
|
29
|
-
* '/path/to/collection',
|
|
30
|
-
* undefined,
|
|
31
|
-
* false
|
|
32
|
-
* );
|
|
33
|
-
*
|
|
34
|
-
* @example
|
|
35
|
-
* // Load specific documents with filenames included
|
|
36
|
-
* const result = await DocumentLoader.loadDocuments(
|
|
37
|
-
* '/path/to/collection',
|
|
38
|
-
* 'encryption-key',
|
|
39
|
-
* true,
|
|
40
|
-
* ['doc1.axiodb', 'doc2.axiodb'],
|
|
41
|
-
* true
|
|
42
|
-
* );
|
|
43
|
-
*/
|
|
44
9
|
static loadDocuments(collectionPath: string, encryptionKey?: string, isEncrypted?: boolean, documentFiles?: string[], includeFileName?: boolean): Promise<SuccessInterface | ErrorInterface>;
|
|
45
10
|
}
|
|
@@ -16,59 +16,21 @@ const FolderManager_1 = __importDefault(require("../engine/Filesystem/FolderMana
|
|
|
16
16
|
const BufferLoaderWithWorker_utils_1 = __importDefault(require("../utility/BufferLoaderWithWorker.utils"));
|
|
17
17
|
const response_helper_1 = __importDefault(require("./response.helper"));
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* replacing duplicated code in Reader, Update, Delete, and Aggregation operations.
|
|
23
|
-
*
|
|
24
|
-
* @class DocumentLoader
|
|
19
|
+
* Centralizes document-loading logic that used to be duplicated across the Reader,
|
|
20
|
+
* Update, Delete, and Aggregation operations - handles both a direct file list and
|
|
21
|
+
* full directory scanning (filtered to `.axiodb` files), loaded via worker threads.
|
|
25
22
|
*/
|
|
26
23
|
class DocumentLoader {
|
|
27
|
-
/**
|
|
28
|
-
* Loads all documents from a collection directory using worker threads
|
|
29
|
-
*
|
|
30
|
-
* This method consolidates the LoadAllBufferRawData logic that was previously
|
|
31
|
-
* duplicated across multiple CRUD operations. It handles both direct file
|
|
32
|
-
* specification and directory scanning with .axiodb file filtering.
|
|
33
|
-
*
|
|
34
|
-
* @param collectionPath - Full path to collection directory
|
|
35
|
-
* @param encryptionKey - Optional encryption key for encrypted documents
|
|
36
|
-
* @param isEncrypted - Whether documents are encrypted (default: false)
|
|
37
|
-
* @param documentFiles - Optional specific file names to load
|
|
38
|
-
* @param includeFileName - Whether to include fileName in result (default: false)
|
|
39
|
-
* @returns Success with document array or Error
|
|
40
|
-
*
|
|
41
|
-
* @example
|
|
42
|
-
* // Load all documents from a collection
|
|
43
|
-
* const result = await DocumentLoader.loadDocuments(
|
|
44
|
-
* '/path/to/collection',
|
|
45
|
-
* undefined,
|
|
46
|
-
* false
|
|
47
|
-
* );
|
|
48
|
-
*
|
|
49
|
-
* @example
|
|
50
|
-
* // Load specific documents with filenames included
|
|
51
|
-
* const result = await DocumentLoader.loadDocuments(
|
|
52
|
-
* '/path/to/collection',
|
|
53
|
-
* 'encryption-key',
|
|
54
|
-
* true,
|
|
55
|
-
* ['doc1.axiodb', 'doc2.axiodb'],
|
|
56
|
-
* true
|
|
57
|
-
* );
|
|
58
|
-
*/
|
|
59
24
|
static loadDocuments(collectionPath_1, encryptionKey_1) {
|
|
60
25
|
return __awaiter(this, arguments, void 0, function* (collectionPath, encryptionKey, isEncrypted = false, documentFiles, includeFileName = false) {
|
|
61
26
|
try {
|
|
62
27
|
const dataFilesList = [];
|
|
63
28
|
if (documentFiles !== undefined) {
|
|
64
|
-
// Use provided file list
|
|
65
29
|
dataFilesList.push(...documentFiles);
|
|
66
30
|
}
|
|
67
31
|
else {
|
|
68
|
-
// Scan directory for .axiodb files
|
|
69
32
|
const readResponse = yield new FolderManager_1.default().ListDirectory(collectionPath);
|
|
70
33
|
if ("data" in readResponse) {
|
|
71
|
-
// Filter for .axiodb files only
|
|
72
34
|
const axiodbFiles = readResponse.data.filter((file) => file.endsWith(".axiodb"));
|
|
73
35
|
dataFilesList.push(...axiodbFiles);
|
|
74
36
|
}
|
|
@@ -76,7 +38,7 @@ class DocumentLoader {
|
|
|
76
38
|
return this.ResponseHelper.Error("Failed to read directory");
|
|
77
39
|
}
|
|
78
40
|
}
|
|
79
|
-
//
|
|
41
|
+
// Loaded via worker threads for parallelism
|
|
80
42
|
const resultData = yield (0, BufferLoaderWithWorker_utils_1.default)(dataFilesList, encryptionKey, collectionPath, isEncrypted, includeFileName);
|
|
81
43
|
return this.ResponseHelper.Success(resultData);
|
|
82
44
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocumentLoader.helper.js","sourceRoot":"","sources":["../../source/Helper/DocumentLoader.helper.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AACA,uFAA+D;AAC/D,2GAAuE;AACvE,wEAA+C;AAE/C
|
|
1
|
+
{"version":3,"file":"DocumentLoader.helper.js","sourceRoot":"","sources":["../../source/Helper/DocumentLoader.helper.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AACA,uFAA+D;AAC/D,2GAAuE;AACvE,wEAA+C;AAE/C;;;;GAIG;AACH,MAAqB,cAAc;IAGjC,MAAM,CAAO,aAAa;6DACxB,cAAsB,EACtB,aAAsB,EACtB,WAAW,GAAY,KAAK,EAC5B,aAAwB,EACxB,eAAe,GAAY,KAAK;YAEhC,IAAI,CAAC;gBACH,MAAM,aAAa,GAAa,EAAE,CAAC;gBAEnC,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;oBAChC,aAAa,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,CAAC;gBACvC,CAAC;qBAAM,CAAC;oBACN,MAAM,YAAY,GAAG,MAAM,IAAI,uBAAa,EAAE,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;oBAE7E,IAAI,MAAM,IAAI,YAAY,EAAE,CAAC;wBAC3B,MAAM,WAAW,GAAG,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAY,EAAE,EAAE,CAC5D,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CACzB,CAAC;wBACF,aAAa,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC;oBACrC,CAAC;yBAAM,CAAC;wBACN,OAAO,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;oBAC/D,CAAC;gBACH,CAAC;gBAED,4CAA4C;gBAC5C,MAAM,UAAU,GAAG,MAAM,IAAA,sCAAgB,EACvC,aAAa,EACb,aAAa,EACb,cAAc,EACd,WAAW,EACX,eAAe,CAChB,CAAC;gBAEF,OAAO,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YACjD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;KAAA;CACF;AAzCyB,6BAAc,GAAG,IAAI,yBAAc,EAAE,CAAC"}
|
|
@@ -37,20 +37,17 @@ class PathSanitizer {
|
|
|
37
37
|
if (!userInput || typeof userInput !== 'string') {
|
|
38
38
|
throw new Error('Invalid path component: must be a non-empty string');
|
|
39
39
|
}
|
|
40
|
-
// Remove all directory traversal attempts
|
|
41
40
|
let sanitized = userInput
|
|
42
|
-
.replace(/\.\./g, '_') //
|
|
43
|
-
.replace(/\//g, '_') //
|
|
44
|
-
.replace(/\\/g, '_') //
|
|
45
|
-
.replace(/\0/g, '_'); //
|
|
46
|
-
//
|
|
47
|
-
// Note: We preserve dots for file extensions but removed '..' above
|
|
41
|
+
.replace(/\.\./g, '_') // parent directory
|
|
42
|
+
.replace(/\//g, '_') // Unix path separator
|
|
43
|
+
.replace(/\\/g, '_') // Windows path separator
|
|
44
|
+
.replace(/\0/g, '_'); // null bytes
|
|
45
|
+
// Dots are preserved (for file extensions) since '..' was already stripped above
|
|
48
46
|
sanitized = sanitized.replace(/[^a-zA-Z0-9-_.]/g, '_');
|
|
49
|
-
// Prevent empty result
|
|
50
47
|
if (sanitized.length === 0) {
|
|
51
48
|
throw new Error('Invalid path component: results in empty string after sanitization');
|
|
52
49
|
}
|
|
53
|
-
//
|
|
50
|
+
// Avoid producing a hidden file
|
|
54
51
|
if (sanitized.startsWith('.')) {
|
|
55
52
|
sanitized = '_' + sanitized.substring(1);
|
|
56
53
|
}
|
|
@@ -100,11 +97,8 @@ class PathSanitizer {
|
|
|
100
97
|
* // Throws: Security violation (after sanitization and validation)
|
|
101
98
|
*/
|
|
102
99
|
static safePath(basePath, ...components) {
|
|
103
|
-
// Sanitize each component
|
|
104
100
|
const sanitizedComponents = components.map(c => this.sanitizePathComponent(c));
|
|
105
|
-
// Join paths using Node.js path.join (handles platform differences)
|
|
106
101
|
const fullPath = path_1.default.join(basePath, ...sanitizedComponents);
|
|
107
|
-
// Validate final path is within base (defense in depth)
|
|
108
102
|
this.validatePath(basePath, fullPath);
|
|
109
103
|
return fullPath;
|
|
110
104
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PathSanitizer.helper.js","sourceRoot":"","sources":["../../source/Helper/PathSanitizer.helper.ts"],"names":[],"mappings":";;;;;AAAA,gDAAwB;AAExB;;;;;;;;;;GAUG;AACH;IACE;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,CAAC,qBAAqB,CAAC,SAAiB;QAC5C,IAAI,CAAC,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;YAChD,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;QACxE,CAAC;QAED,
|
|
1
|
+
{"version":3,"file":"PathSanitizer.helper.js","sourceRoot":"","sources":["../../source/Helper/PathSanitizer.helper.ts"],"names":[],"mappings":";;;;;AAAA,gDAAwB;AAExB;;;;;;;;;;GAUG;AACH;IACE;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,CAAC,qBAAqB,CAAC,SAAiB;QAC5C,IAAI,CAAC,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;YAChD,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;QACxE,CAAC;QAED,IAAI,SAAS,GAAG,SAAS;aACtB,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAI,mBAAmB;aAC5C,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAM,sBAAsB;aAC/C,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAM,yBAAyB;aAClD,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAK,aAAa;QAEzC,iFAAiF;QACjF,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC;QAEvD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAAC;QACxF,CAAC;QAED,gCAAgC;QAChC,IAAI,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9B,SAAS,GAAG,GAAG,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QAC3C,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,CAAC,YAAY,CAAC,QAAgB,EAAE,QAAgB;QACpD,MAAM,YAAY,GAAG,cAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC5C,MAAM,YAAY,GAAG,cAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAE5C,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YAC3C,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,CAAC,QAAQ,CAAC,QAAgB,EAAE,GAAG,UAAoB;QACvD,MAAM,mBAAmB,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/E,MAAM,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,mBAAmB,CAAC,CAAC;QAC7D,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAEtC,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF"}
|