@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 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
- // Connect to a MoltenDB WASM Web Worker
23
- const worker = new Worker('./moltendb-worker.js', { type: 'module' });
24
- const db = new MoltenDBClient(new WorkerTransport(worker));
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 db.collection('laptops')
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 db.collection('laptops')
45
- .update({ lp4: { price: 1749, in_stock: true } })
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 db.collection('laptops').delete().keys('lp6').exec();
57
+ await client.collection('laptops').delete().keys('lp1').exec();
50
58
 
51
59
  // DELETE — batch
52
- await db.collection('laptops').delete().keys(['lp4', 'lp5']).exec();
60
+ await client.collection('laptops').delete().keys(['lp1', 'lp2']).exec();
53
61
 
54
62
  // DELETE — drop entire collection
55
- await db.collection('laptops').delete().drop().exec();
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 db.collection('laptops')
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 db.collection('laptops')
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
@@ -346,7 +346,7 @@ export declare class CollectionHandle {
346
346
  * .count(5)
347
347
  * .exec();
348
348
  */
349
- export declare class MoltenDBQueryBuilder {
349
+ export declare class MoltenDBClient {
350
350
  private transport;
351
351
  constructor(transport: MoltenTransport);
352
352
  /**
package/package.json CHANGED
@@ -1,10 +1,14 @@
1
1
  {
2
2
  "name": "@moltendb-web/query",
3
- "version": "0.1.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 MoltenDBQueryBuilder {
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
+