@moltendb-web/query 0.1.0 → 0.2.0
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 +45 -22
- package/dist/index.d.ts +1 -1
- package/package.json +5 -1
- package/src/index.ts +2 -1
package/README.md
CHANGED
|
@@ -4,6 +4,10 @@ Type-safe, chainable query builder for [MoltenDB](https://github.com/maximilian2
|
|
|
4
4
|
|
|
5
5
|
Works in vanilla JavaScript and TypeScript. Compiles as an npm module (CJS + ESM + `.d.ts`).
|
|
6
6
|
|
|
7
|
+
### 🌋 Explore the Full Functionality
|
|
8
|
+
|
|
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
|
+
|
|
7
11
|
---
|
|
8
12
|
|
|
9
13
|
## Installation
|
|
@@ -17,14 +21,26 @@ npm install @moltendb-web/query
|
|
|
17
21
|
## Quick start
|
|
18
22
|
|
|
19
23
|
```ts
|
|
24
|
+
import { MoltenDB } from '@moltendb-web/core';
|
|
20
25
|
import { MoltenDBClient, WorkerTransport } from '@moltendb-web/query';
|
|
21
26
|
|
|
22
|
-
//
|
|
23
|
-
const
|
|
24
|
-
const db = new
|
|
27
|
+
// 1. Initialize the Core Engine (boots WASM worker)
|
|
28
|
+
const workerUrl = new URL('@moltendb-web/core/worker', import.meta.url).href;
|
|
29
|
+
const db = new MoltenDB('moltendb_demo', { syncEnabled: false, workerUrl });
|
|
30
|
+
await db.init();
|
|
31
|
+
|
|
32
|
+
// 2. Connect the Query Builder to the worker
|
|
33
|
+
const client = new MoltenDBClient(new WorkerTransport(db.worker, 10000));
|
|
34
|
+
// SET — insert / upsert
|
|
35
|
+
await client.collection('laptops')
|
|
36
|
+
.set({
|
|
37
|
+
lp1: { brand: 'Lenovo', model: 'ThinkPad X1', price: 1499, in_stock: true },
|
|
38
|
+
lp2: { brand: 'Apple', model: 'MacBook Pro', price: 3499, in_stock: true },
|
|
39
|
+
})
|
|
40
|
+
.exec();
|
|
25
41
|
|
|
26
42
|
// GET — query with WHERE, field projection, sort and pagination
|
|
27
|
-
const results = await
|
|
43
|
+
const results = await client.collection('laptops')
|
|
28
44
|
.get()
|
|
29
45
|
.where({ brand: 'Apple' })
|
|
30
46
|
.fields(['brand', 'model', 'price'])
|
|
@@ -32,27 +48,19 @@ const results = await db.collection('laptops')
|
|
|
32
48
|
.count(5)
|
|
33
49
|
.exec();
|
|
34
50
|
|
|
35
|
-
// SET — insert / upsert
|
|
36
|
-
await db.collection('laptops')
|
|
37
|
-
.set({
|
|
38
|
-
lp1: { brand: 'Lenovo', model: 'ThinkPad X1', price: 1499, in_stock: true },
|
|
39
|
-
lp2: { brand: 'Apple', model: 'MacBook Pro', price: 3499, in_stock: true },
|
|
40
|
-
})
|
|
41
|
-
.exec();
|
|
42
|
-
|
|
43
51
|
// UPDATE — partial patch (only listed fields are changed)
|
|
44
|
-
await
|
|
45
|
-
.update({
|
|
52
|
+
await client.collection('laptops')
|
|
53
|
+
.update({ lp1: { price: 1749, in_stock: false } })
|
|
46
54
|
.exec();
|
|
47
55
|
|
|
48
56
|
// DELETE — single key
|
|
49
|
-
await
|
|
57
|
+
await client.collection('laptops').delete().keys('lp1').exec();
|
|
50
58
|
|
|
51
59
|
// DELETE — batch
|
|
52
|
-
await
|
|
60
|
+
await client.collection('laptops').delete().keys(['lp1', 'lp2']).exec();
|
|
53
61
|
|
|
54
62
|
// DELETE — drop entire collection
|
|
55
|
-
await
|
|
63
|
+
await client.collection('laptops').delete().drop().exec();
|
|
56
64
|
```
|
|
57
65
|
|
|
58
66
|
---
|
|
@@ -67,7 +75,7 @@ combinations are caught at compile time by TypeScript.
|
|
|
67
75
|
| Method | Description |
|
|
68
76
|
|---|---|
|
|
69
77
|
| `.keys(key \| key[])` | Fetch one or more documents by key |
|
|
70
|
-
| `.where(clause)` | Filter with operators: `$eq $ne $gt $gte $lt $lte $in $nin $contains` |
|
|
78
|
+
| `.where(clause)` | Filter with operators: `$eq $ne $gt $gte $lt $lte $in $nin $contains` (and aliases) |
|
|
71
79
|
| `.fields(string[])` | Return only these fields (dot-notation supported) |
|
|
72
80
|
| `.excludedFields(string[])` | Return everything except these fields |
|
|
73
81
|
| `.joins(JoinSpec[])` | Embed related documents from other collections |
|
|
@@ -110,22 +118,29 @@ Only the fields present in each patch object are updated — all other fields ar
|
|
|
110
118
|
## WHERE operators
|
|
111
119
|
|
|
112
120
|
```ts
|
|
113
|
-
// Exact equality (implicit)
|
|
121
|
+
// Exact equality (implicit or explicit)
|
|
114
122
|
.where({ brand: 'Apple' })
|
|
123
|
+
.where({ brand: { $eq: 'Apple' } })
|
|
124
|
+
.where({ brand: { $equals: 'Apple' } }) // alias
|
|
115
125
|
|
|
116
126
|
// Comparison
|
|
117
127
|
.where({ price: { $gt: 1000, $lt: 3000 } })
|
|
128
|
+
.where({ price: { $greaterThan: 1000, $lessThan: 3000 } }) // aliases
|
|
118
129
|
.where({ 'specs.cpu.cores': { $gte: 12 } })
|
|
119
130
|
|
|
120
131
|
// Not equal
|
|
121
132
|
.where({ 'specs.cpu.brand': { $ne: 'Intel' } })
|
|
133
|
+
.where({ 'specs.cpu.brand': { $notEquals: 'Intel' } }) // alias
|
|
122
134
|
|
|
123
135
|
// In / not-in list
|
|
124
136
|
.where({ brand: { $in: ['Apple', 'Dell'] } })
|
|
137
|
+
.where({ brand: { $oneOf: ['Apple', 'Dell'] } }) // alias
|
|
125
138
|
.where({ brand: { $nin: ['Framework'] } })
|
|
139
|
+
.where({ brand: { $notIn: ['Framework'] } }) // alias
|
|
126
140
|
|
|
127
141
|
// Contains (string substring or array element)
|
|
128
142
|
.where({ model: { $contains: 'Pro' } })
|
|
143
|
+
.where({ model: { $ct: 'Pro' } }) // alias
|
|
129
144
|
.where({ tags: { $contains: 'gaming' } })
|
|
130
145
|
|
|
131
146
|
// Multiple conditions (implicit AND)
|
|
@@ -137,7 +152,7 @@ Only the fields present in each patch object are updated — all other fields ar
|
|
|
137
152
|
## Joins
|
|
138
153
|
|
|
139
154
|
```ts
|
|
140
|
-
const results = await
|
|
155
|
+
const results = await client.collection('laptops')
|
|
141
156
|
.get()
|
|
142
157
|
.fields(['brand', 'model', 'price'])
|
|
143
158
|
.joins([
|
|
@@ -153,7 +168,7 @@ const results = await db.collection('laptops')
|
|
|
153
168
|
## Extends (snapshot embedding at insert time)
|
|
154
169
|
|
|
155
170
|
```ts
|
|
156
|
-
await
|
|
171
|
+
await client.collection('laptops')
|
|
157
172
|
.set({
|
|
158
173
|
lp7: {
|
|
159
174
|
brand: 'MSI', model: 'Titan GT77', price: 3299,
|
|
@@ -165,6 +180,15 @@ await db.collection('laptops')
|
|
|
165
180
|
// lp7 is stored with the full mem4 and dsp3 documents embedded inline.
|
|
166
181
|
```
|
|
167
182
|
|
|
183
|
+
**When to use `extends` vs `joins`:**
|
|
184
|
+
|
|
185
|
+
| | `extends` | `joins` |
|
|
186
|
+
|---|---|---|
|
|
187
|
+
| Resolved at | Insert time (once) | Query time (every request) |
|
|
188
|
+
| Data freshness | Snapshot — may become stale | Always live |
|
|
189
|
+
| Read cost | O(1) — data already embedded | O(1) per join per document |
|
|
190
|
+
| Use when | Data rarely changes, fast reads matter | Data changes frequently, freshness matters |
|
|
191
|
+
|
|
168
192
|
---
|
|
169
193
|
|
|
170
194
|
## Custom transport
|
|
@@ -198,7 +222,6 @@ const db = new MoltenDBClient(new FetchTransport('https://localhost:1538', myTok
|
|
|
198
222
|
## Build
|
|
199
223
|
|
|
200
224
|
```bash
|
|
201
|
-
npm run build # emit dist/index.js (CJS), dist/index.esm.js (ESM), dist/index.d.ts
|
|
202
225
|
npm run typecheck # type-check without emitting
|
|
203
226
|
```
|
|
204
227
|
|
package/dist/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moltendb-web/query",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Type-safe query builder for MoltenDB — chainable API for get, set, update and delete operations.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.esm.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/maximilian27/moltendb-web/tree/master/packages/query"
|
|
11
|
+
},
|
|
8
12
|
"exports": {
|
|
9
13
|
".": {
|
|
10
14
|
"import": "./dist/index.esm.js",
|
package/src/index.ts
CHANGED
|
@@ -564,7 +564,7 @@ export class CollectionHandle {
|
|
|
564
564
|
* .count(5)
|
|
565
565
|
* .exec();
|
|
566
566
|
*/
|
|
567
|
-
export class
|
|
567
|
+
export class MoltenDBClient {
|
|
568
568
|
private transport: MoltenTransport;
|
|
569
569
|
|
|
570
570
|
constructor(transport: MoltenTransport) {
|
|
@@ -581,3 +581,4 @@ export class MoltenDBQueryBuilder {
|
|
|
581
581
|
return new CollectionHandle(this.transport, name);
|
|
582
582
|
}
|
|
583
583
|
}
|
|
584
|
+
|