@moltendb-web/query 1.0.0-rc.1 → 1.0.0-rc.4
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 +8 -8
- package/dist/index.d.ts +7 -7
- package/dist/index.esm.js +10 -10
- package/dist/index.js +11 -11
- package/package.json +5 -3
- package/src/index.ts +11 -11
- package/dist/esm/index.js +0 -443
package/README.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# @moltendb-web/query
|
|
2
2
|
|
|
3
|
-
Type-safe, chainable query builder for [
|
|
3
|
+
Type-safe, chainable query builder for [MoltenDb](https://github.com/maximilian27/MoltenDb).
|
|
4
4
|
|
|
5
5
|
Works in vanilla JavaScript and TypeScript. Compiles as an npm module (CJS + ESM + `.d.ts`).
|
|
6
6
|
|
|
7
7
|
### 🌋 Explore the Full Functionality
|
|
8
8
|
|
|
9
|
-
The best way to experience the
|
|
9
|
+
The best way to experience the MoltenDb query builder is through our **[Interactive Demo on StackBlitz](https://stackblitz.com/~/github.com/maximilian27/moltendb-wasm-demo?file=package.json)**. It contains a complete, live environment where you can test query builder expressions, perform mutations, and see real-time events without any local setup.
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
@@ -21,15 +21,15 @@ npm install @moltendb-web/query
|
|
|
21
21
|
## Quick start
|
|
22
22
|
|
|
23
23
|
```ts
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
24
|
+
import { MoltenDb } from '@moltendb-web/core';
|
|
25
|
+
import { MoltenDbClient, WorkerTransport } from '@moltendb-web/query';
|
|
26
26
|
|
|
27
27
|
// 1. Initialize the Core Engine (boots WASM worker)
|
|
28
|
-
const db = new
|
|
28
|
+
const db = new MoltenDb('moltendb_demo');
|
|
29
29
|
await db.init();
|
|
30
30
|
|
|
31
31
|
// 2. Connect the Query Builder to the worker
|
|
32
|
-
const client = new
|
|
32
|
+
const client = new MoltenDbClient(db);
|
|
33
33
|
|
|
34
34
|
// SET — insert / upsert
|
|
35
35
|
await client.collection('laptops')
|
|
@@ -196,7 +196,7 @@ await client.collection('laptops')
|
|
|
196
196
|
Implement `MoltenTransport` to connect to any backend:
|
|
197
197
|
|
|
198
198
|
```ts
|
|
199
|
-
import { MoltenTransport,
|
|
199
|
+
import { MoltenTransport, MoltenDbClient, Document, JsonValue } from '@moltendb-web/query';
|
|
200
200
|
|
|
201
201
|
class FetchTransport implements MoltenTransport {
|
|
202
202
|
constructor(private baseUrl: string, private token: string) {}
|
|
@@ -214,7 +214,7 @@ class FetchTransport implements MoltenTransport {
|
|
|
214
214
|
}
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
-
const db = new
|
|
217
|
+
const db = new MoltenDbClient(new FetchTransport('[https://api.mydomain.com](https://api.mydomain.com)', myToken));
|
|
218
218
|
```
|
|
219
219
|
|
|
220
220
|
---
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
3
3
|
[key: string]: JsonValue;
|
|
4
4
|
};
|
|
5
|
-
/** A document stored in
|
|
5
|
+
/** A document stored in MoltenDb — any object with string keys. */
|
|
6
6
|
export type Document = {
|
|
7
7
|
[key: string]: JsonValue;
|
|
8
8
|
};
|
|
@@ -54,7 +54,7 @@ export type ExtendsMap = {
|
|
|
54
54
|
[alias: string]: string;
|
|
55
55
|
};
|
|
56
56
|
/**
|
|
57
|
-
* The transport layer used by
|
|
57
|
+
* The transport layer used by MoltenDbClient to send messages.
|
|
58
58
|
* Implement this interface to connect the query builder to any backend:
|
|
59
59
|
* - A Web Worker (WASM in-browser)
|
|
60
60
|
* - A fetch-based HTTP client
|
|
@@ -269,7 +269,7 @@ export declare class DeleteQuery {
|
|
|
269
269
|
}
|
|
270
270
|
/**
|
|
271
271
|
* A handle to a specific collection.
|
|
272
|
-
* Returned by `
|
|
272
|
+
* Returned by `MoltenDbClient.collection(name)`.
|
|
273
273
|
* Use it to start any of the four operation builders.
|
|
274
274
|
*/
|
|
275
275
|
export declare class CollectionHandle {
|
|
@@ -313,17 +313,17 @@ export declare class CollectionHandle {
|
|
|
313
313
|
delete(): DeleteQuery;
|
|
314
314
|
}
|
|
315
315
|
/**
|
|
316
|
-
* The main entry point for the
|
|
316
|
+
* The main entry point for the MoltenDb query builder.
|
|
317
317
|
*
|
|
318
318
|
* Accepts any {@link MoltenTransport} implementation — use {@link WorkerTransport}
|
|
319
|
-
* to connect to a
|
|
319
|
+
* to connect to a MoltenDb WASM Web Worker, or provide your own transport
|
|
320
320
|
* for HTTP, WebSocket, or testing.
|
|
321
321
|
*
|
|
322
322
|
* @example
|
|
323
323
|
* // Browser + WASM Web Worker
|
|
324
324
|
* const worker = new Worker('./moltendb-worker.js', { type: 'module' });
|
|
325
325
|
* const transport = new WorkerTransport(worker);
|
|
326
|
-
* const db = new
|
|
326
|
+
* const db = new MoltenDbClient(transport);
|
|
327
327
|
*
|
|
328
328
|
* const results = await db.collection('laptops')
|
|
329
329
|
* .get()
|
|
@@ -332,7 +332,7 @@ export declare class CollectionHandle {
|
|
|
332
332
|
* .count(5)
|
|
333
333
|
* .exec();
|
|
334
334
|
*/
|
|
335
|
-
export declare class
|
|
335
|
+
export declare class MoltenDbClient {
|
|
336
336
|
private transport;
|
|
337
337
|
constructor(transport: MoltenTransport);
|
|
338
338
|
/**
|
package/dist/index.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
// ───
|
|
2
|
-
// Chainable, type-safe query builder for
|
|
1
|
+
// ─── MoltenDb Query Builder ───────────────────────────────────────────────────
|
|
2
|
+
// Chainable, type-safe query builder for MoltenDb.
|
|
3
3
|
//
|
|
4
4
|
// Each operation has its own builder class that only exposes the methods
|
|
5
5
|
// that are valid for that operation — matching the server's allowed-property
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
//
|
|
14
14
|
// Usage (vanilla JS or TypeScript):
|
|
15
15
|
//
|
|
16
|
-
// const db = new
|
|
16
|
+
// const db = new MoltenDbClient(worker);
|
|
17
17
|
//
|
|
18
18
|
// // GET — chainable query
|
|
19
19
|
// const results = await db.collection('laptops')
|
|
@@ -326,7 +326,7 @@ export { DeleteQuery as DeleteQuery };
|
|
|
326
326
|
// ─── CollectionHandle ─────────────────────────────────────────────────────────
|
|
327
327
|
/**
|
|
328
328
|
* A handle to a specific collection.
|
|
329
|
-
* Returned by `
|
|
329
|
+
* Returned by `MoltenDbClient.collection(name)`.
|
|
330
330
|
* Use it to start any of the four operation builders.
|
|
331
331
|
*/
|
|
332
332
|
class CollectionHandle {
|
|
@@ -379,19 +379,19 @@ class CollectionHandle {
|
|
|
379
379
|
}
|
|
380
380
|
}
|
|
381
381
|
export { CollectionHandle as CollectionHandle };
|
|
382
|
-
// ───
|
|
382
|
+
// ─── MoltenDbClient ───────────────────────────────────────────────────────────
|
|
383
383
|
/**
|
|
384
|
-
* The main entry point for the
|
|
384
|
+
* The main entry point for the MoltenDb query builder.
|
|
385
385
|
*
|
|
386
386
|
* Accepts any {@link MoltenTransport} implementation — use {@link WorkerTransport}
|
|
387
|
-
* to connect to a
|
|
387
|
+
* to connect to a MoltenDb WASM Web Worker, or provide your own transport
|
|
388
388
|
* for HTTP, WebSocket, or testing.
|
|
389
389
|
*
|
|
390
390
|
* @example
|
|
391
391
|
* // Browser + WASM Web Worker
|
|
392
392
|
* const worker = new Worker('./moltendb-worker.js', { type: 'module' });
|
|
393
393
|
* const transport = new WorkerTransport(worker);
|
|
394
|
-
* const db = new
|
|
394
|
+
* const db = new MoltenDbClient(transport);
|
|
395
395
|
*
|
|
396
396
|
* const results = await db.collection('laptops')
|
|
397
397
|
* .get()
|
|
@@ -400,7 +400,7 @@ export { CollectionHandle as CollectionHandle };
|
|
|
400
400
|
* .count(5)
|
|
401
401
|
* .exec();
|
|
402
402
|
*/
|
|
403
|
-
class
|
|
403
|
+
class MoltenDbClient {
|
|
404
404
|
constructor(transport) {
|
|
405
405
|
this.transport = transport;
|
|
406
406
|
}
|
|
@@ -414,5 +414,5 @@ class MoltenDBClient {
|
|
|
414
414
|
return new CollectionHandle(this.transport, name);
|
|
415
415
|
}
|
|
416
416
|
}
|
|
417
|
-
export {
|
|
417
|
+
export { MoltenDbClient as MoltenDbClient };
|
|
418
418
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// ───
|
|
3
|
-
// Chainable, type-safe query builder for
|
|
2
|
+
// ─── MoltenDb Query Builder ───────────────────────────────────────────────────
|
|
3
|
+
// Chainable, type-safe query builder for MoltenDb.
|
|
4
4
|
//
|
|
5
5
|
// Each operation has its own builder class that only exposes the methods
|
|
6
6
|
// that are valid for that operation — matching the server's allowed-property
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
//
|
|
15
15
|
// Usage (vanilla JS or TypeScript):
|
|
16
16
|
//
|
|
17
|
-
// const db = new
|
|
17
|
+
// const db = new MoltenDbClient(worker);
|
|
18
18
|
//
|
|
19
19
|
// // GET — chainable query
|
|
20
20
|
// const results = await db.collection('laptops')
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
// await db.collection('laptops').delete().drop().exec();
|
|
42
42
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
43
43
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
-
exports.
|
|
44
|
+
exports.MoltenDbClient = exports.CollectionHandle = exports.DeleteQuery = exports.UpdateQuery = exports.SetQuery = exports.GetQuery = void 0;
|
|
45
45
|
// ─── GetQuery ─────────────────────────────────────────────────────────────────
|
|
46
46
|
/**
|
|
47
47
|
* Builder for GET (read/query) operations.
|
|
@@ -328,7 +328,7 @@ exports.DeleteQuery = DeleteQuery;
|
|
|
328
328
|
// ─── CollectionHandle ─────────────────────────────────────────────────────────
|
|
329
329
|
/**
|
|
330
330
|
* A handle to a specific collection.
|
|
331
|
-
* Returned by `
|
|
331
|
+
* Returned by `MoltenDbClient.collection(name)`.
|
|
332
332
|
* Use it to start any of the four operation builders.
|
|
333
333
|
*/
|
|
334
334
|
class CollectionHandle {
|
|
@@ -381,19 +381,19 @@ class CollectionHandle {
|
|
|
381
381
|
}
|
|
382
382
|
}
|
|
383
383
|
exports.CollectionHandle = CollectionHandle;
|
|
384
|
-
// ───
|
|
384
|
+
// ─── MoltenDbClient ───────────────────────────────────────────────────────────
|
|
385
385
|
/**
|
|
386
|
-
* The main entry point for the
|
|
386
|
+
* The main entry point for the MoltenDb query builder.
|
|
387
387
|
*
|
|
388
388
|
* Accepts any {@link MoltenTransport} implementation — use {@link WorkerTransport}
|
|
389
|
-
* to connect to a
|
|
389
|
+
* to connect to a MoltenDb WASM Web Worker, or provide your own transport
|
|
390
390
|
* for HTTP, WebSocket, or testing.
|
|
391
391
|
*
|
|
392
392
|
* @example
|
|
393
393
|
* // Browser + WASM Web Worker
|
|
394
394
|
* const worker = new Worker('./moltendb-worker.js', { type: 'module' });
|
|
395
395
|
* const transport = new WorkerTransport(worker);
|
|
396
|
-
* const db = new
|
|
396
|
+
* const db = new MoltenDbClient(transport);
|
|
397
397
|
*
|
|
398
398
|
* const results = await db.collection('laptops')
|
|
399
399
|
* .get()
|
|
@@ -402,7 +402,7 @@ exports.CollectionHandle = CollectionHandle;
|
|
|
402
402
|
* .count(5)
|
|
403
403
|
* .exec();
|
|
404
404
|
*/
|
|
405
|
-
class
|
|
405
|
+
class MoltenDbClient {
|
|
406
406
|
constructor(transport) {
|
|
407
407
|
this.transport = transport;
|
|
408
408
|
}
|
|
@@ -416,5 +416,5 @@ class MoltenDBClient {
|
|
|
416
416
|
return new CollectionHandle(this.transport, name);
|
|
417
417
|
}
|
|
418
418
|
}
|
|
419
|
-
exports.
|
|
419
|
+
exports.MoltenDbClient = MoltenDbClient;
|
|
420
420
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moltendb-web/query",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
4
|
-
"description": "Type-safe query builder for
|
|
3
|
+
"version": "1.0.0-rc.4",
|
|
4
|
+
"description": "Type-safe query builder for MoltenDb — chainable API for get, set, update and delete operations.",
|
|
5
|
+
"author": "Maximilian Both <maximilian.both27@outlook.com>",
|
|
5
6
|
"main": "./dist/index.js",
|
|
6
7
|
"module": "./dist/index.esm.js",
|
|
7
8
|
"types": "./dist/index.d.ts",
|
|
@@ -23,7 +24,8 @@
|
|
|
23
24
|
"scripts": {
|
|
24
25
|
"build": "tsc --project tsconfig.build.json && node scripts/build-esm.js",
|
|
25
26
|
"typecheck": "tsc --noEmit",
|
|
26
|
-
"test": "node --experimental-vm-modules node_modules/.bin/jest"
|
|
27
|
+
"test": "node --experimental-vm-modules node_modules/.bin/jest",
|
|
28
|
+
"prepublishOnly": "npm run build"
|
|
27
29
|
},
|
|
28
30
|
"keywords": ["moltendb", "database", "query-builder", "nosql", "wasm"],
|
|
29
31
|
"license": "MIT",
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
// ───
|
|
2
|
-
// Chainable, type-safe query builder for
|
|
1
|
+
// ─── MoltenDb Query Builder ───────────────────────────────────────────────────
|
|
2
|
+
// Chainable, type-safe query builder for MoltenDb.
|
|
3
3
|
//
|
|
4
4
|
// Each operation has its own builder class that only exposes the methods
|
|
5
5
|
// that are valid for that operation — matching the server's allowed-property
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
//
|
|
14
14
|
// Usage (vanilla JS or TypeScript):
|
|
15
15
|
//
|
|
16
|
-
// const db = new
|
|
16
|
+
// const db = new MoltenDbClient(worker);
|
|
17
17
|
//
|
|
18
18
|
// // GET — chainable query
|
|
19
19
|
// const results = await db.collection('laptops')
|
|
@@ -51,7 +51,7 @@ export type JsonValue =
|
|
|
51
51
|
| JsonValue[]
|
|
52
52
|
| { [key: string]: JsonValue };
|
|
53
53
|
|
|
54
|
-
/** A document stored in
|
|
54
|
+
/** A document stored in MoltenDb — any object with string keys. */
|
|
55
55
|
export type Document = { [key: string]: JsonValue };
|
|
56
56
|
|
|
57
57
|
/** A map of document key → document body used in set/update payloads. */
|
|
@@ -114,7 +114,7 @@ export type ExtendsMap = { [alias: string]: string };
|
|
|
114
114
|
// ── Transport interface ───────────────────────────────────────────────────────
|
|
115
115
|
|
|
116
116
|
/**
|
|
117
|
-
* The transport layer used by
|
|
117
|
+
* The transport layer used by MoltenDbClient to send messages.
|
|
118
118
|
* Implement this interface to connect the query builder to any backend:
|
|
119
119
|
* - A Web Worker (WASM in-browser)
|
|
120
120
|
* - A fetch-based HTTP client
|
|
@@ -447,7 +447,7 @@ export class DeleteQuery {
|
|
|
447
447
|
|
|
448
448
|
/**
|
|
449
449
|
* A handle to a specific collection.
|
|
450
|
-
* Returned by `
|
|
450
|
+
* Returned by `MoltenDbClient.collection(name)`.
|
|
451
451
|
* Use it to start any of the four operation builders.
|
|
452
452
|
*/
|
|
453
453
|
export class CollectionHandle {
|
|
@@ -507,20 +507,20 @@ export class CollectionHandle {
|
|
|
507
507
|
}
|
|
508
508
|
}
|
|
509
509
|
|
|
510
|
-
// ───
|
|
510
|
+
// ─── MoltenDbClient ───────────────────────────────────────────────────────────
|
|
511
511
|
|
|
512
512
|
/**
|
|
513
|
-
* The main entry point for the
|
|
513
|
+
* The main entry point for the MoltenDb query builder.
|
|
514
514
|
*
|
|
515
515
|
* Accepts any {@link MoltenTransport} implementation — use {@link WorkerTransport}
|
|
516
|
-
* to connect to a
|
|
516
|
+
* to connect to a MoltenDb WASM Web Worker, or provide your own transport
|
|
517
517
|
* for HTTP, WebSocket, or testing.
|
|
518
518
|
*
|
|
519
519
|
* @example
|
|
520
520
|
* // Browser + WASM Web Worker
|
|
521
521
|
* const worker = new Worker('./moltendb-worker.js', { type: 'module' });
|
|
522
522
|
* const transport = new WorkerTransport(worker);
|
|
523
|
-
* const db = new
|
|
523
|
+
* const db = new MoltenDbClient(transport);
|
|
524
524
|
*
|
|
525
525
|
* const results = await db.collection('laptops')
|
|
526
526
|
* .get()
|
|
@@ -529,7 +529,7 @@ export class CollectionHandle {
|
|
|
529
529
|
* .count(5)
|
|
530
530
|
* .exec();
|
|
531
531
|
*/
|
|
532
|
-
export class
|
|
532
|
+
export class MoltenDbClient {
|
|
533
533
|
private transport: MoltenTransport;
|
|
534
534
|
|
|
535
535
|
constructor(transport: MoltenTransport) {
|
package/dist/esm/index.js
DELETED
|
@@ -1,443 +0,0 @@
|
|
|
1
|
-
// ─── MoltenDB Query Builder ───────────────────────────────────────────────────
|
|
2
|
-
// Chainable, type-safe query builder for MoltenDB.
|
|
3
|
-
//
|
|
4
|
-
// Each operation has its own builder class that only exposes the methods
|
|
5
|
-
// that are valid for that operation — matching the server's allowed-property
|
|
6
|
-
// lists exactly:
|
|
7
|
-
//
|
|
8
|
-
// GET_ALLOWED: collection, keys, where, fields, excludedFields,
|
|
9
|
-
// joins, sort, count, offset
|
|
10
|
-
// SET_ALLOWED: collection, data, extends
|
|
11
|
-
// UPDATE_ALLOWED: collection, data
|
|
12
|
-
// DELETE_ALLOWED: collection, keys, drop
|
|
13
|
-
//
|
|
14
|
-
// Usage (vanilla JS or TypeScript):
|
|
15
|
-
//
|
|
16
|
-
// const db = new MoltenDBClient(worker);
|
|
17
|
-
//
|
|
18
|
-
// // GET — chainable query
|
|
19
|
-
// const results = await db.collection('laptops')
|
|
20
|
-
// .get()
|
|
21
|
-
// .where({ brand: 'Apple' })
|
|
22
|
-
// .fields(['brand', 'model', 'price'])
|
|
23
|
-
// .sort([{ field: 'price', order: 'asc' }])
|
|
24
|
-
// .count(10)
|
|
25
|
-
// .exec();
|
|
26
|
-
//
|
|
27
|
-
// // SET — insert/upsert
|
|
28
|
-
// await db.collection('laptops')
|
|
29
|
-
// .set({ lp1: { brand: 'Lenovo', price: 1499 } })
|
|
30
|
-
// .exec();
|
|
31
|
-
//
|
|
32
|
-
// // UPDATE — partial patch
|
|
33
|
-
// await db.collection('laptops')
|
|
34
|
-
// .update({ lp4: { price: 1749, in_stock: true } })
|
|
35
|
-
// .exec();
|
|
36
|
-
//
|
|
37
|
-
// // DELETE — single key, batch, or drop
|
|
38
|
-
// await db.collection('laptops').delete().keys('lp6').exec();
|
|
39
|
-
// await db.collection('laptops').delete().keys(['lp4', 'lp5']).exec();
|
|
40
|
-
// await db.collection('laptops').delete().drop().exec();
|
|
41
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
42
|
-
// ─── WorkerTransport ──────────────────────────────────────────────────────────
|
|
43
|
-
/**
|
|
44
|
-
* Default transport that communicates with a MoltenDB Web Worker.
|
|
45
|
-
*
|
|
46
|
-
* The worker must follow the moltendb-worker.js message protocol:
|
|
47
|
-
* postMessage({ id, action, ...payload })
|
|
48
|
-
* onmessage → { id, result } | { id, error }
|
|
49
|
-
*/
|
|
50
|
-
export class WorkerTransport {
|
|
51
|
-
constructor(worker, startId = 0) {
|
|
52
|
-
this.pending = new Map();
|
|
53
|
-
this.messageId = startId;
|
|
54
|
-
this.worker = worker;
|
|
55
|
-
this.worker.addEventListener('message', (event) => {
|
|
56
|
-
const { id, result, error } = event.data;
|
|
57
|
-
const p = this.pending.get(id);
|
|
58
|
-
if (!p)
|
|
59
|
-
return;
|
|
60
|
-
this.pending.delete(id);
|
|
61
|
-
if (error)
|
|
62
|
-
p.reject(new Error(error));
|
|
63
|
-
else
|
|
64
|
-
p.resolve(result ?? null);
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
send(action, payload) {
|
|
68
|
-
return new Promise((resolve, reject) => {
|
|
69
|
-
const id = this.messageId++;
|
|
70
|
-
this.pending.set(id, { resolve, reject });
|
|
71
|
-
this.worker.postMessage({ id, action, ...payload });
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
// ─── GetQuery ─────────────────────────────────────────────────────────────────
|
|
76
|
-
/**
|
|
77
|
-
* Builder for GET (read/query) operations.
|
|
78
|
-
*
|
|
79
|
-
* Allowed fields: collection, keys, where, fields, excludedFields,
|
|
80
|
-
* joins, sort, count, offset
|
|
81
|
-
*
|
|
82
|
-
* @example
|
|
83
|
-
* const rows = await db.collection('laptops')
|
|
84
|
-
* .get()
|
|
85
|
-
* .where({ brand: 'Apple' })
|
|
86
|
-
* .fields(['brand', 'model', 'price'])
|
|
87
|
-
* .sort([{ field: 'price', order: 'asc' }])
|
|
88
|
-
* .count(5)
|
|
89
|
-
* .exec();
|
|
90
|
-
*/
|
|
91
|
-
export class GetQuery {
|
|
92
|
-
/** @internal */
|
|
93
|
-
constructor(transport, collection) {
|
|
94
|
-
this.transport = transport;
|
|
95
|
-
this.payload = { collection };
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Fetch a single document by key, or a batch of documents by key array.
|
|
99
|
-
*
|
|
100
|
-
* @param keys - A single key string or an array of key strings.
|
|
101
|
-
*
|
|
102
|
-
* @example
|
|
103
|
-
* // Single key
|
|
104
|
-
* .keys('lp2')
|
|
105
|
-
* // Batch
|
|
106
|
-
* .keys(['lp1', 'lp3', 'lp5'])
|
|
107
|
-
*/
|
|
108
|
-
keys(keys) {
|
|
109
|
-
this.payload['keys'] = keys;
|
|
110
|
-
return this;
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Filter documents using a WHERE clause.
|
|
114
|
-
* Multiple conditions are combined with implicit AND.
|
|
115
|
-
*
|
|
116
|
-
* Supported operators: $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin, $contains
|
|
117
|
-
* Dot-notation is supported for nested fields.
|
|
118
|
-
*
|
|
119
|
-
* @example
|
|
120
|
-
* .where({ brand: 'Apple' })
|
|
121
|
-
* .where({ price: { $gt: 1000, $lt: 3000 } })
|
|
122
|
-
* .where({ 'specs.cpu.brand': 'Intel', in_stock: true })
|
|
123
|
-
*/
|
|
124
|
-
where(clause) {
|
|
125
|
-
this.payload['where'] = clause;
|
|
126
|
-
return this;
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Project the response to only the specified fields (dot-notation supported).
|
|
130
|
-
* Cannot be combined with {@link excludedFields}.
|
|
131
|
-
*
|
|
132
|
-
* @example
|
|
133
|
-
* .fields(['brand', 'model', 'specs.cpu.ghz'])
|
|
134
|
-
*/
|
|
135
|
-
fields(fields) {
|
|
136
|
-
this.payload['fields'] = fields;
|
|
137
|
-
return this;
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* Return all fields except the specified ones.
|
|
141
|
-
* Cannot be combined with {@link fields}.
|
|
142
|
-
*
|
|
143
|
-
* @example
|
|
144
|
-
* .excludedFields(['price', 'memory_id', 'display_id'])
|
|
145
|
-
*/
|
|
146
|
-
excludedFields(fields) {
|
|
147
|
-
this.payload['excludedFields'] = fields;
|
|
148
|
-
return this;
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Join related documents from other collections.
|
|
152
|
-
* Each join embeds the related document under the given alias.
|
|
153
|
-
*
|
|
154
|
-
* @example
|
|
155
|
-
* .joins([
|
|
156
|
-
* { alias: 'ram', from: 'memory', on: 'memory_id', fields: ['capacity_gb', 'type'] },
|
|
157
|
-
* { alias: 'screen', from: 'display', on: 'display_id', fields: ['refresh_hz', 'panel'] },
|
|
158
|
-
* ])
|
|
159
|
-
*/
|
|
160
|
-
joins(specs) {
|
|
161
|
-
this.payload['joins'] = specs.map(({ alias, from, on, fields }) => ({
|
|
162
|
-
[alias]: fields ? { from, on, fields } : { from, on },
|
|
163
|
-
}));
|
|
164
|
-
return this;
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* Sort the results.
|
|
168
|
-
* Multiple specs are applied in priority order (first = primary sort key).
|
|
169
|
-
*
|
|
170
|
-
* @example
|
|
171
|
-
* .sort([{ field: 'price', order: 'asc' }])
|
|
172
|
-
* .sort([{ field: 'brand', order: 'asc' }, { field: 'price', order: 'desc' }])
|
|
173
|
-
*/
|
|
174
|
-
sort(specs) {
|
|
175
|
-
this.payload['sort'] = specs;
|
|
176
|
-
return this;
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Limit the number of results returned (applied after filtering and sorting).
|
|
180
|
-
*
|
|
181
|
-
* @example
|
|
182
|
-
* .count(10)
|
|
183
|
-
*/
|
|
184
|
-
count(n) {
|
|
185
|
-
this.payload['count'] = n;
|
|
186
|
-
return this;
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* Skip the first N results (for pagination, applied after sorting).
|
|
190
|
-
*
|
|
191
|
-
* @example
|
|
192
|
-
* .offset(20).count(10) // page 3 of 10
|
|
193
|
-
*/
|
|
194
|
-
offset(n) {
|
|
195
|
-
this.payload['offset'] = n;
|
|
196
|
-
return this;
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* Build and return the raw JSON payload without sending it.
|
|
200
|
-
* Useful for debugging or passing to a custom transport.
|
|
201
|
-
*/
|
|
202
|
-
build() {
|
|
203
|
-
return { ...this.payload };
|
|
204
|
-
}
|
|
205
|
-
/**
|
|
206
|
-
* Execute the query and return the result.
|
|
207
|
-
* Returns a single document for single-key lookups, or an array for all others.
|
|
208
|
-
*/
|
|
209
|
-
exec() {
|
|
210
|
-
return this.transport.send('get', this.payload);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
// ─── SetQuery ─────────────────────────────────────────────────────────────────
|
|
214
|
-
/**
|
|
215
|
-
* Builder for SET (insert / upsert) operations.
|
|
216
|
-
*
|
|
217
|
-
* Allowed fields: collection, data, extends
|
|
218
|
-
*
|
|
219
|
-
* @example
|
|
220
|
-
* await db.collection('laptops')
|
|
221
|
-
* .set({
|
|
222
|
-
* lp1: { brand: 'Lenovo', model: 'ThinkPad X1', price: 1499 },
|
|
223
|
-
* lp2: { brand: 'Apple', model: 'MacBook Pro', price: 3499 },
|
|
224
|
-
* })
|
|
225
|
-
* .exec();
|
|
226
|
-
*/
|
|
227
|
-
export class SetQuery {
|
|
228
|
-
/** @internal */
|
|
229
|
-
constructor(transport, collection, data) {
|
|
230
|
-
this.transport = transport;
|
|
231
|
-
this.payload = { collection, data: data };
|
|
232
|
-
}
|
|
233
|
-
/**
|
|
234
|
-
* Embed data from other collections into each document at insert time.
|
|
235
|
-
* The referenced document is fetched once and stored as a snapshot.
|
|
236
|
-
*
|
|
237
|
-
* Format: `{ alias: "collection.key" }`
|
|
238
|
-
*
|
|
239
|
-
* @example
|
|
240
|
-
* .extends({ ram: 'memory.mem4', screen: 'display.dsp3' })
|
|
241
|
-
*/
|
|
242
|
-
extends(map) {
|
|
243
|
-
// The extends map is applied to every document in data.
|
|
244
|
-
// We store it at the top level; the server resolves it per-document.
|
|
245
|
-
const data = this.payload['data'];
|
|
246
|
-
if (Array.isArray(data)) {
|
|
247
|
-
// Array format — inject extends into each item
|
|
248
|
-
this.payload['data'] = data.map((doc) => ({
|
|
249
|
-
...doc,
|
|
250
|
-
extends: map,
|
|
251
|
-
}));
|
|
252
|
-
}
|
|
253
|
-
else if (data && typeof data === 'object') {
|
|
254
|
-
// Object format — inject extends into each document value
|
|
255
|
-
const updated = {};
|
|
256
|
-
for (const [key, doc] of Object.entries(data)) {
|
|
257
|
-
updated[key] = { ...doc, extends: map };
|
|
258
|
-
}
|
|
259
|
-
this.payload['data'] = updated;
|
|
260
|
-
}
|
|
261
|
-
return this;
|
|
262
|
-
}
|
|
263
|
-
/** Build and return the raw JSON payload without sending it. */
|
|
264
|
-
build() {
|
|
265
|
-
return { ...this.payload };
|
|
266
|
-
}
|
|
267
|
-
/** Execute the insert/upsert and return `{ count, status }`. */
|
|
268
|
-
exec() {
|
|
269
|
-
return this.transport.send('set', this.payload);
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
// ─── UpdateQuery ──────────────────────────────────────────────────────────────
|
|
273
|
-
/**
|
|
274
|
-
* Builder for UPDATE (partial patch / merge) operations.
|
|
275
|
-
*
|
|
276
|
-
* Allowed fields: collection, data
|
|
277
|
-
*
|
|
278
|
-
* Only the fields present in each patch object are updated —
|
|
279
|
-
* all other fields on the existing document are left unchanged.
|
|
280
|
-
*
|
|
281
|
-
* @example
|
|
282
|
-
* await db.collection('laptops')
|
|
283
|
-
* .update({ lp4: { price: 1749, in_stock: true } })
|
|
284
|
-
* .exec();
|
|
285
|
-
*/
|
|
286
|
-
export class UpdateQuery {
|
|
287
|
-
/** @internal */
|
|
288
|
-
constructor(transport, collection, data) {
|
|
289
|
-
this.transport = transport;
|
|
290
|
-
this.payload = { collection, data: data };
|
|
291
|
-
}
|
|
292
|
-
/** Build and return the raw JSON payload without sending it. */
|
|
293
|
-
build() {
|
|
294
|
-
return { ...this.payload };
|
|
295
|
-
}
|
|
296
|
-
/** Execute the patch and return `{ count, status }`. */
|
|
297
|
-
exec() {
|
|
298
|
-
return this.transport.send('update', this.payload);
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
// ─── DeleteQuery ──────────────────────────────────────────────────────────────
|
|
302
|
-
/**
|
|
303
|
-
* Builder for DELETE operations.
|
|
304
|
-
*
|
|
305
|
-
* Allowed fields: collection, keys, drop
|
|
306
|
-
*
|
|
307
|
-
* @example
|
|
308
|
-
* // Delete a single document
|
|
309
|
-
* await db.collection('laptops').delete().keys('lp6').exec();
|
|
310
|
-
*
|
|
311
|
-
* // Delete multiple documents
|
|
312
|
-
* await db.collection('laptops').delete().keys(['lp4', 'lp5']).exec();
|
|
313
|
-
*
|
|
314
|
-
* // Drop the entire collection
|
|
315
|
-
* await db.collection('laptops').delete().drop().exec();
|
|
316
|
-
*/
|
|
317
|
-
export class DeleteQuery {
|
|
318
|
-
/** @internal */
|
|
319
|
-
constructor(transport, collection) {
|
|
320
|
-
this.transport = transport;
|
|
321
|
-
this.payload = { collection };
|
|
322
|
-
}
|
|
323
|
-
/**
|
|
324
|
-
* Delete a single document by key, or multiple documents by key array.
|
|
325
|
-
*
|
|
326
|
-
* @example
|
|
327
|
-
* .keys('lp6')
|
|
328
|
-
* .keys(['lp4', 'lp5'])
|
|
329
|
-
*/
|
|
330
|
-
keys(keys) {
|
|
331
|
-
this.payload['keys'] = keys;
|
|
332
|
-
return this;
|
|
333
|
-
}
|
|
334
|
-
/**
|
|
335
|
-
* Drop the entire collection (deletes all documents).
|
|
336
|
-
* Cannot be combined with {@link keys}.
|
|
337
|
-
*
|
|
338
|
-
* @example
|
|
339
|
-
* .drop()
|
|
340
|
-
*/
|
|
341
|
-
drop() {
|
|
342
|
-
this.payload['drop'] = true;
|
|
343
|
-
return this;
|
|
344
|
-
}
|
|
345
|
-
/** Build and return the raw JSON payload without sending it. */
|
|
346
|
-
build() {
|
|
347
|
-
return { ...this.payload };
|
|
348
|
-
}
|
|
349
|
-
/** Execute the delete and return `{ count, status }`. */
|
|
350
|
-
exec() {
|
|
351
|
-
return this.transport.send('delete', this.payload);
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
// ─── CollectionHandle ─────────────────────────────────────────────────────────
|
|
355
|
-
/**
|
|
356
|
-
* A handle to a specific collection.
|
|
357
|
-
* Returned by `MoltenDBClient.collection(name)`.
|
|
358
|
-
* Use it to start any of the four operation builders.
|
|
359
|
-
*/
|
|
360
|
-
export class CollectionHandle {
|
|
361
|
-
/** @internal */
|
|
362
|
-
constructor(transport, collectionName) {
|
|
363
|
-
this.transport = transport;
|
|
364
|
-
this.collectionName = collectionName;
|
|
365
|
-
}
|
|
366
|
-
/**
|
|
367
|
-
* Start a GET (read/query) builder for this collection.
|
|
368
|
-
*
|
|
369
|
-
* @example
|
|
370
|
-
* db.collection('laptops').get().where({ brand: 'Apple' }).exec()
|
|
371
|
-
*/
|
|
372
|
-
get() {
|
|
373
|
-
return new GetQuery(this.transport, this.collectionName);
|
|
374
|
-
}
|
|
375
|
-
/**
|
|
376
|
-
* Start a SET (insert/upsert) builder for this collection.
|
|
377
|
-
*
|
|
378
|
-
* @param data - A map of `{ key: document }` pairs, or an array of documents
|
|
379
|
-
* (keys are auto-generated as UUIDv7 when using array format).
|
|
380
|
-
*
|
|
381
|
-
* @example
|
|
382
|
-
* db.collection('laptops').set({ lp1: { brand: 'Lenovo', price: 1499 } }).exec()
|
|
383
|
-
*/
|
|
384
|
-
set(data) {
|
|
385
|
-
return new SetQuery(this.transport, this.collectionName, data);
|
|
386
|
-
}
|
|
387
|
-
/**
|
|
388
|
-
* Start an UPDATE (partial patch) builder for this collection.
|
|
389
|
-
*
|
|
390
|
-
* @param data - A map of `{ key: patch }` pairs. Only the provided fields are updated.
|
|
391
|
-
*
|
|
392
|
-
* @example
|
|
393
|
-
* db.collection('laptops').update({ lp4: { price: 1749 } }).exec()
|
|
394
|
-
*/
|
|
395
|
-
update(data) {
|
|
396
|
-
return new UpdateQuery(this.transport, this.collectionName, data);
|
|
397
|
-
}
|
|
398
|
-
/**
|
|
399
|
-
* Start a DELETE builder for this collection.
|
|
400
|
-
* Chain `.keys(...)` or `.drop()` to specify what to delete.
|
|
401
|
-
*
|
|
402
|
-
* @example
|
|
403
|
-
* db.collection('laptops').delete().keys('lp6').exec()
|
|
404
|
-
*/
|
|
405
|
-
delete() {
|
|
406
|
-
return new DeleteQuery(this.transport, this.collectionName);
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
// ─── MoltenDBClient ───────────────────────────────────────────────────────────
|
|
410
|
-
/**
|
|
411
|
-
* The main entry point for the MoltenDB query builder.
|
|
412
|
-
*
|
|
413
|
-
* Accepts any {@link MoltenTransport} implementation — use {@link WorkerTransport}
|
|
414
|
-
* to connect to a MoltenDB WASM Web Worker, or provide your own transport
|
|
415
|
-
* for HTTP, WebSocket, or testing.
|
|
416
|
-
*
|
|
417
|
-
* @example
|
|
418
|
-
* // Browser + WASM Web Worker
|
|
419
|
-
* const worker = new Worker('./moltendb-worker.js', { type: 'module' });
|
|
420
|
-
* const transport = new WorkerTransport(worker);
|
|
421
|
-
* const db = new MoltenDBClient(transport);
|
|
422
|
-
*
|
|
423
|
-
* const results = await db.collection('laptops')
|
|
424
|
-
* .get()
|
|
425
|
-
* .where({ in_stock: true })
|
|
426
|
-
* .sort([{ field: 'price', order: 'asc' }])
|
|
427
|
-
* .count(5)
|
|
428
|
-
* .exec();
|
|
429
|
-
*/
|
|
430
|
-
export class MoltenDBClient {
|
|
431
|
-
constructor(transport) {
|
|
432
|
-
this.transport = transport;
|
|
433
|
-
}
|
|
434
|
-
/**
|
|
435
|
-
* Select a collection to operate on.
|
|
436
|
-
* Returns a {@link CollectionHandle} from which you can start any query builder.
|
|
437
|
-
*
|
|
438
|
-
* @param name - The collection name (e.g. `'laptops'`).
|
|
439
|
-
*/
|
|
440
|
-
collection(name) {
|
|
441
|
-
return new CollectionHandle(this.transport, name);
|
|
442
|
-
}
|
|
443
|
-
}
|